-
Notifications
You must be signed in to change notification settings - Fork 3
Constraints
The ES-DOC meta-programming ontology schema formalism (as applied to CIM v1 & CIM v2) supports the notion of constraints. A constraint applies to a named property with in a class definition. Each declared constraint mutates either the class interface, the instance constructor, and / or instance validation.
A class property value can be constrained using a regular expression. Downstream applications should enforce the constraint on instances.
'constraint':[
('regex', 'property-name', 'a-regular-expression')
]
For example
'property': [
('latitude', 'int', '1.1', "Integer latitude")
]
could be constrained like this:
'constraint' : [
('regex','latitude','[0-8]?[0-9]')
]
By default a class property value linked to an enumeration has an open enumeration:
'properties':[
('property-name', 'enumeration', '1.1', 'some enumerated property')
]
To constrain the the enumeration to be closed the following constraint can be defined:
'constraints':[
('enum-extensibilty', 'property-name', False)
]
(NB: An alternative formalism exploiting a modification of the cardinality was discussed - see the section on cardinality on the Properties page, it might be that version will be preferred.)
The cardinality of a class property is defined as part of the property definition:
'properties':[
('property-name', 'some_type', '0.N', 'some interesting property')
]
Sub-classes can constrain the cardinality definition in order to 'remove' the property:
'constraints':[
('cardinality','property-name', '0.0')
]
Sub-classes can constrain the cardinality definition in order to mark the property as required:
'constraints':[
('cardinality', 'property-name', '1.N')
]
In some cases a sub-class can constrain a super-class by imposing a value on the property. This is most likely to happen in an extension vocabulary (which will generally use a different, more compact, syntax), so we don't expect to see this often (if at all) in the main schema. However, the logic needs to be supported since in principle any extension vocabulary could be written using the main schema formalism, so it is defined here.
Consider a property with, for example, a name which we want to constrain in the sub-class
'properties':[
('name','str','0.1','the name of something, e.g. a scientific process')
]
It could be constrained in the sub-class as follows:
'constraints':[
('constant', 'name', 'Cloud Physics')
]
When the parent property can have multiple values as in this case:
'properties':[
('processes','science.process','0.N','The set of simulated processes')
]
the situation is more complicated, since we might either want to fix the list of possible values, or we might still want it to be extensible. These two options are supported with the following alternate constraint declarations:
'constraints':[
('constant', 'process', ['cmip6.clouds','cmip6.radiation'])
]
(the default is that these are extensible), but if not
'constraints':[
('constant', 'process', ['cmip6.clouds','cmip6.radiation'], 'extensibility', False)
]
(NB: In this example cmip6.clouds
and cmip6.radiation
would have to be cmip6
extension subclasses of science.process
declared and defined elsewhere.)
These last two examples could be dealt with by additional constraints on cardinality, but that seems clumsy!
Where there are multiple properties defined, but only one should be selected, then we use the mutually-exclusive
syntax, which is best shown with an example:
def initialisation_requirement():
""" A requirement on how a particular simulation should be initialised """
return {
'type': 'class',
'base': 'designing.numerical_requirement',
'is_abstract': False,
'properties': [
('initialise_from_experiment', 'designing.numerical_experiment', '0.1',
'This experiment should be initialised from the output of this experiment'),
('initialise_from_data', 'data.dataset','0.1',
'Initialisation should use this primary dataset'),
('branch_time_in_initialisation_source', 'time.datetime', '0.1',
'If appropriate, the time in the initialisation_source (whether observed or simulated)')
],
'constraints': [
('mutually-exclusive', ('initialise_from_experiment', 'initialise_from_data'), '1.1')
]
}
This indicates that only one of the two properties initialise_from_experiment
or initialise_from_data
can
be selected, but one must be selected. If the 1.1
in the constraint tuple had been a 0.1
we would have
been indicating that only one of them can be selected, but none could be selected. Any valid cardinality
can appear in this situation.