Representation of basic objects

Basic parts of the configuration design problem structure are: All these parts can be implemented as objects in COOL (the object part of CLIPS). Each part is represented by one or several classes and instances of these classes stand for particular parameters, components, and constraints of the problem being solved. All these classes are defined as subclasses of the parent class USER which represents the root of user defined class hierarchy.

Parameters which form the solution can be implemented by the class parameter:

(defclass parameter
(is-a USER)
(role concrete)
(pattern-match reactive)
(slot param-name
(access initialize-only)
(create-accessor read-write))
(slot active
(allowed-values yes no)
(default yes)
(access read-write)
(create-accessor read-write))
(slot priority
(access read-write)
(create-accessor read-write))
(slot param-type
(allowed-values dependent independent)
(default independent)
(access initialize-only)
(create-accessor read-write))
(slot param-value
(access read-write)
(create-accessor read-write))
(multislot param-domain
(access initialize-only)
(create-accessor read-write))
)
Some slots have defined default values. It is not compulsory, but it makes the parameter definition of a particular application easier.

From the point of view of access, there are two types of slots. The first type provides only the possibility of reading the values assigned to the slots. The second type enables to change the values of these slots. For read-only slots it is enough to set their values only once when instances are created. It is possible to do using CLIPS features - setting the initialize-only access (which contains reading too) to the slot. If the value of a slot can be changed the access to this slot has to be read-write.

The slot param-domain has the form (param-domain <domain type> <domain>). It defines the type of the domain and the values which can be assigned to the parameter (in the room allocation problem only enumerative type is allowed). <domain> represents one or several values depending on the type of the domain.

The class component is dedicated to the representation of components which can form the artefact. But a particular application can use a large number of different components. That is why the class component does not represent a particular component (it cannot create instances - it is an abstract class), but serves as the parent class for the definition of all possible components. This parent class contains only information which concerns all components (and they can inherit it from the parent class component).

(defclass component
(is-a USER)
(role abstract)
(slot comp-name
(access initialize-only)
(create-accessor read-write))
(slot comp-number
(default 1)
(access initialize-only)
(create-accessor read-write))
)
Information which is common to all components is only the name of the component and the number of components of the same name.

Different component types can be defined by subclasses of the parent class component. These subclasses have the following general form:

(defclass component-<component type>
(is-a component)
(role concrete)
(pattern-match reactive)
...
)
Every component type is represented by exactly one subclass. In this way the number of these subclasses is equal to the number of different component types which are available. The number and the definition of slots are different for different component types and depend on a particular application.

Since components are predefined (and their features are not changed during the search for the solution), their slots are available only for reading. Every slot (concerning a component) has the form

(slot <slot name>
... - information on one feature
(access initialize-only)
(create-accessor read-write))
Constraints can be defined as instances of the class constraint which has the following form:
(defclass constraint
(is-a USER)
(role concrete)
(pattern-match reactive)
(slot cons-name
(access initialize-only)
(create-accessor read-write))
(slot priority
(access read-write)
(create-accessor read-write))
(multislot cons-param
(access initialize-only)
(create-accessor read-write))
(slot cons-violation
(allowed-values yes no)
(default no)
(access read-write)
(create-accessor read-write))
(multislot viol-param
(default (create$ ))
(access read-write)
(create-accessor read-write))
(slot active
(allowed-values yes no)
(default yes)
(access read-write)
(create-accessor read-write))
)
The slots which are used only to read information and for which there is no need to change their values are defined as initialize-only. Since the priority of a constraint can vary during the search for the solution depending on the state of other constraints, the slot priority enables to change its value.

The slot cons-param contains the list of all parameters which are relevant to the constraint. If some of them violate the constraint, the value of the slot cons-violation is set to yes and this parameter is registered in the viol-param slot. If there is no parameter to violate some constraint, the slot viol-param of this constraint is empty.

Since the management of the slots viol-param is not trivial (modification of a part of the slot content always occurs), it is not possible to use default accessors. New accessors have the form

(defmessage-handler constraint del-viol-param primary (?param)
(bind ?position (member$ ?param ?self:viol-param))
(bind ?self:viol-param (delete$ ?self:viol-param ?position ?position))
)
(defmessage-handler constraint add-viol-param primary (?param)
(bind ?self:viol-param (insert$ ?self:viol-param 1 ?param))
)