Component Library Properties

Kinds of Properties

The Component Library distinguishes two kinds of properties: categorical properties and scalar/cardinal properties.

Categorical properties have symbolic values that do not sensibly appear on any scale or continuum. There is no ordering to the values of categorical properties. For example, the color property is categorical. There is no natural ordering of its symbolic values: *blue, *orange, etc. Although it is possible to assign arbitrary numeric values to the symbolic constants (such as the RGB encoding of colors), it is not a feature of the colors that they are ordered. Outside of some arbitrary imposed ordering, it does not make sense to say that "blue is greater than orange", or "something green has a higher/greater color than something red".

Scalar/cardinal properties have two different kinds of values: symbolic, relative values that appear on an ordered scale and numeric values. Scalar values consist of a symbolic constant and a reference class. Cardinal values consist of a cardinal number and a unit of measurement.

Representing Properties

Properties of Entities and Events are expressed using property slots filled by instances of Property-Value. Each property slot has a range of exactly one subclass of Property-Value. Different property slots may have the same subclass of Property-Value as range. For example, length, width, height, etc. all have a range of Length-Value.

(a Device with (weight ((a Weight-Value))))

(a Substance with (temperature ((a Temperature-Value))))

(a Physical-Object with (color ((a Color-Value))))

(a Event with (duration ((a Duration-Value))))

Every property slot is filled by at most one instance of a Property-Value. So, for example, an Entity has a single Temperature-Value, though that value may be expressed in many forms (50 degrees Fahrenheit, 10 degrees Celsius, cool for a summer day, etc.).

There are two parallel and equivalent representations for individual values of properties. The Component Library copies any values from one representation to the other. The first representation uses the value slot and KM's :pair notation. The following example shows a Device that weighs 10 pounds, 4.54 kilograms and is heavy relative to Computers. The Device has a single weight (Weight-Value) but there are three representations of that weight:

(a Device with
   (weight ((a Weight-Value with
               (value ((:pair 10 *pound)
                       (:pair 4.54 *kilogram)
                       (:pair *heavy Computer)
               ))
   )))
)

The value slot is also used for categorical properties, where it is filled by a simple constant (not a :pair):

(a Physical-Object with
   (color ((a Color-Value with
              (value (*blue))
   )))
)

The second representation for values of properties avoids KM's :pair notation. It uses three different slots in place of the generic value slot: cardinal-value, scalar-value and categorical-value. These slots are filled by one or more instances of the classes Cardinal, Scalar and Categorical. Each instance is one representation of the property value. An instance of Cardinal must have exactly one filler each for the numeric-value and unit slots. An instance of Scalar must have exactly one filler for each of the scalar-constant and reference-class slots. An instance of Categorical must have exactly one filler for the categorical-constant slot.

(a Device with
   (weight ((a Weight-Value with
               (cardinal-value ((a Cardinal with
                                   (numeric-value (10))
                                   (unit (*pound))
                                )
                                (a Cardinal with
                                   (numeric-value (4.54))
                                   (unit (*kilogram))
                                )
                               )
               )
               (scalar-value   ((a Scalar with
                                   (scalar-constant (*heavy))
                                   (reference-class (Computer))
                                )
                               )
               )
   )))
)

(a Physical-Object with
   (color ((a Color-Value with
              (categorical-value ((a Categorical with
                                     (categorical-constant (*blue))
                                  )
              ))
   )))
)

Syntax and Constraints

To summarize, here is the syntax for each representation. Constraints are enforced in KM. Values encoded in each representation are copied to the other representation so either can be used for assertions and queries.

Cardinals

Syntax

(<property> ((a Property-Value with
                (value ((:pair <Number> <Unit-of-Measurement>)))
            ))
)
      
(<property> ((a Property-Value with
                (cardinal-value ((a Cardinal with
                                    (numeric-value (<Number>))
                                    (unit (<Unit-of-Measurement>))
                                 )
                ))
            ))
)
      

Constraints

<property> must be a property slot that allows cardinal values
<Number> must be an instance of Number
<Unit-of-Measurement> must be an instance of Unit-of-Measurement appropriate to <property> or a Class subsumed by the domain of <property>
multiple numeric values must be equivalent

Scalars

Syntax

(<property> ((a Property-Value with
                (value ((:pair <Constant> <Class>)))
            ))
)
      
(<property> ((a Property-Value with
                (scalar-value ((a Scalar with
                                  (scalar-constant (<Constant>))
                                  (reference-class (<Class>))
                               )
                ))
            ))
)
      

Constraints

<property> must be a property slot that allows scalar values
<Constant> must be an instance of Constant appropriate to <property>
<Class> must be a Class subsumed by the domain of <property>
multiple values with the same reference <Class> must have the same <Constant>

Categoricals

Syntax

(<property> ((a Property-Value with
                (value (<Constant>))
            ))
)
      
(<property> ((a Property-Value with
                (categorical-value ((a Categorical with
                                       (categorical-constant (<Constant>))
                                    )
                ))
            ))
)
      

Constraints

<property> must be a property slot that allows categorical values
<Constant> must be an instance of Constant appropriate to <property>

Using Property Values

To use a Component Library property you must know the property's:

To create your own properties, you must specify the slots above (as appropriate) and create corresponding subclasses of Constant and Unit-of-Measurement with appropriate instances.

Here are some examples of domain, range, categorical-constant-class, scalar-constant-class and cardinal-unit-class:

KM> (the domain of width)
(Spatial-Entity)

KM> (the range of width)
(Length-Value)

KM> (the scalar-constant-class of width)
(Width-Constant)

KM> (the all-instances of (the scalar-constant-class of width))
(*narrow *wide)

KM> (the cardinal-unit-class of width)
(UoM-Length)

KM> (the all-instances of (the cardinal-unit-class of width))
(*kilometer *inch *foot *mile *yard *meter *centimeter *millimeter *micrometer *nanometer)

KM> (the domain of color)
(Spatial-Entity)

KM> (the range of color)
(Color-Value)

KM> (the categorical-constant-class of color)
(Color-Constant)

KM> (the all-instances of (the categorical-constant-class of color))
(*red *blue *yellow *green *orange *purple *pink *brown *black *white
*gray *colorless *auburn *blond *blonde *brunette *redhead *silver
*hazel *aqua *fuchsia *lime *maroon *navy *olive *teal *aliceBlue
*antiqueWhite *aquamarine *azure *beige *bisque *blanchedAlmond
*blueViolet *burlyWood *cadetBlue *chartreuse *chocolate *coral
*cornflowerBlue *cornsilk *crimson *cyan *darkBlue *darkCyan
*darkGoldenRod *darkGray *darkGreen *darkKhaki *darkMagenta
*darkOliveGreen *darkorange *darkOrchid *darkRed *darkSalmon
*darkSeaGreen *darkSlateBlue *darkSlateGray *darkTurquoise *darkViolet
*deepPink *deepSkyBlue *dimGray *dodgerBlue *feldspar *fireBrick
*floralWhite *forestGreen *gainsboro *ghostWhite *gold *goldenRod
*greenYellow *honeyDew *hotPink *indianRed *indigo *ivory *khaki
*lavender *lavenderBlush *lawnGreen *lemonChiffon *lightBlue
*lightCoral *lightCyan *lightGoldenRodYellow *lightGrey *lightGreen
*lightPink *lightSalmon *lightSeaGreen *lightSkyBlue *lightSlateBlue
*lightSlateGray *lightSteelBlue *lightYellow *limeGreen *linen
*magenta *mediumAquaMarine *mediumBlue *mediumOrchid *mediumPurple
*mediumSeaGreen *mediumSlateBlue *mediumSpringGreen *mediumTurquoise
*mediumVioletRed *midnightBlue *mintCream *mistyRose *moccasin
*mavajoWhite *oldLace *oliveDrab *orangeRed *orchid *paleGoldenRod
*paleGreen *paleTurquoise *paleVioletRed *papayaWhip *peachPuff *peru
*plum *powderBlue *rosyBrown *royalBlue *saddleBrown *salmon
*sandyBrown *seaGreen *seaShell *sienna *skyBlue *slateBlue *slateGray
*snow *springGreen *steelBlue *tan *thistle *tomato *turquoise *violet
*violetRed *wheat *whiteSmoke *yellowGreen)

KM> (the domain of slope)
(Spatial-Entity)

KM> (the range of slope)
(Unitless-Value)

KM> (the scalar-constant-class of slope)
(Slope-Constant)

KM> (the all-instances of (the scalar-constant-class of slope))
(*vertical *steep *gradual *horizontal)

KM> (the cardinal-unit-class of slope)
(UoM-Unitless)

KM> (the all-instances of (the cardinal-unit-class of slope)) 
(*unity)

KM> (the domain of distance)
(Event)

KM> (the range of distance)
(Length-Value)

KM> (the scalar-constant-class of distance)
(Distance-Constant)

KM> (the all-instances of (the scalar-constant-class of distance))
(*near *far *long)

KM> (the cardinal-unit-class of distance)
(UoM-Length)

Unit Conversion

The Component Library provides a unit converter for most Property Values and their Units of Measure. For a given instance of a subclass of Property-Value, the CLib class Unit-Conversion creates a new instance of the same Property-Value subclass with desired units. Unfortunately, the unit converter does not yet convert temperatures.

Unit-Conversion

Syntax

(the output of
     (a Unit-Conversion with
        (input (<Property-Value>))
        (target-unit (<Unit-of-Measurement>))
     )
)

Constraints

<Property-Value> must be a Property-Value that allows cardinal values
<Unit-of-Measurement> must be an instance of Unit-of-Measurement appropriate to <Property-Value>

Example

KM> (a Volume-Value with (value ((:pair 1 *liter))))
(_Volume-Value2)

KM> (the output of (a Unit-Conversion with (input (_Volume-Value2)) (target-unit (*gallon))))
(_Volume-Value4)

KM> (the value of _Volume-Value4)
((:pair 0.26417205 *gallon))

Property Value Comparison

There are two kinds of expression that could rightfully claim the description "Property Value Comparison". This unfortunate fact is the source of much confusion. To be explicit, let's give neither one that label. Here we distinguish "Asserting Property Value (In)Equality" and "Testing Property Value (In)Equality".

Asserting Property Value (In)Equality is accomplished through use of the relations greater-than (inverse less-than) and same-as. These relations allow you to assert that one Property-Value is greater than (or less than, or the same as) another Property-Value. The Property-Value instances need not have values (on the value slot). This allows the assertion of (in)equality even when the exact values are unknown.

If, however, cardinal values are given (on the value slot), assertions of (in)equality will be enforced with KM constraints:

KM> (a Length-Value) 
(_Length-Value5)

KM> (a Length-Value)
(_Length-Value6)

KM> (_Length-Value5 has (greater-than (_Length-Value6)))
(_Length-Value5)

KM> (the greater-than of _Length-Value5)
(_Length-Value6)

KM> (the less-than of _Length-Value6)
(_Length-Value5)

KM> (_Length-Value5 has (value ((:pair 2 *meter))))
(_Length-Value5)

KM> (_Length-Value6 has (value ((:pair 3 *meter))))
(_Length-Value6)

KM> (the greater-than of _Length-Value5)
ERROR! Constraint violation! Discarding value _Length-Value6
(Execution aborted)
NIL


KM> (a Temperature-Value with (value ((:pair 3 *celsius))))
(_Temperature-Value7)

KM> (a Temperature-Value)
(_Temperature-Value8)

KM> (_Temperature-Value7 has (same-as (_Temperature-Value8)))
(_Temperature-Value7)

KM> (the same-as of _Temperature-Value8)
(_Temperature-Value7)

KM> (the value of _Temperature-Value8) 
NIL

KM> (_Temperature-Value8 has (value ((:pair 3 *fahrenheit))))
(_Temperature-Value8)

KM> (the value of _Temperature-Value8)
((:pair 3 *fahrenheit))

KM> (the same-as of _Temperature-Value7)
ERROR! Constraint violation! Discarding value _Temperature-Value8
(Execution aborted)
NIL

The second kind of "Property Value Comparison" is the "Test for Property Value (In)Equality". Testing for (in)equality makes use of special infix Property-Value operators property-eq, property-gt, property-lt, property-gte and property-lte. The property comparison operators respect units of measure (with the sad exception of temperature for now). The operators also respect KM's default or user-set mathematical tolerances:

KM> (a Length-Value with (value ((:pair 36 *inch))))
(_Length-Value11)

KM> (a Lenght-Value with (value ((:pair 1 *meter))))
(_Lenght-Value9545)

KM> (a Length-Value with (value ((:pair 1 *meter))))
(_Length-Value12)

KM> (_Length-Value11 property-eq _Length-Value12)
NIL

KM> (_Length-Value11 property-lt _Length-Value12)
(T)

KM> (_Length-Value11 property-gt _Length-Value12)
NIL


KM> (a Volume-Value with (value ((:pair 1 *liter))))
(_Volume-Value13)

KM> (a Volume-Value with (value ((:pair 0.26417205 *gallon))))
(_Volume-Value14)

KM> (_Volume-Value13 property-eq _Volume-Value14)
(T)

KM> (a Volume-Value with (value ((:pair 0.264 *gallon))))
(_Volume-Value15)

KM> (_Volume-Value13 property-eq _Volume-Value15)
NIL

KM> (a Volume-Value with (value ((:pair 0.26417 *gallon))))
(_Volume-Value16)

KM> (_Volume-Value13 property-eq _Volume-Value16)
(T)

Property Value Math

The Component Library also supports some arithmetic on Property Values. The following infix operators are available: property-plus, property-minus, property-mult and property-div.

Note that Property arithmetic is only as numerically accurate as the underlying Lisp arithmetic :-b

Arithmetic Operators

Syntax

(<Property-Value-a> property-plus <Property-Value-a>)
(<Property-Value-b> property-minus <Property-Value-b>)
(<Property-Value-c> property-mult <Number>)
(<Number> property-mult <Property-Value-c>)
(<Property-Value-c> property-mult <Property-Value-c>)
(<Property-Value-d> property-div <Number>)
(<Property-Value-d> property-div <Property-Value-d>)

Constraints

<Property-Value-*> must be a Property-Value that allows cardinal values
all operators return a new instance of an appropriate subclass of Property-Value
where both operands are <Property-Value> they must be of the same type
property-mult admits two <Property-Value> operands for only a small subset of Property-Value subclasses
property-div admits any two <Property-Value> operands of the same type and returns an instance of Unitless-Value

Examples

KM> (the value of 
     ((a Mass-Value with (value ((:pair 1 *kilogram))))
      property-plus
      (a Length-Value with (value ((:pair 1000 *meter))))))
NIL

KM> (the value of 
     ((a Mass-Value with (value ((:pair 1 *kilogram))))
      property-plus
      (a Mass-Value with (value ((:pair 1.2 *kilogram))))))
((:pair 2.2 *kilogram))

KM> (the value of
     ((a Mass-Value with (value ((:pair 1 *kilogram))))
      property-minus
      (a Mass-Value with (value ((:pair 1.2 *kilogram))))))
((:pair -0.20000005 *kilogram))

KM> (the value of
     ((a Mass-Value with (value ((:pair 1.2 *kilogram))))
      property-minus
      (a Mass-Value with (value ((:pair 1 *kilogram))))))
((:pair 0.20000005 *kilogram))

KM> (the value of
     ((a Length-Value with (value ((:pair 1 *centimeter))))
      property-plus
      (a Length-Value with (value ((:pair 1 *inch))))))
((:pair 3.54 *centimeter))

KM> (the value of
     ((a Mass-Value with (value ((:pair 1.2 *kilogram))))
      property-mult
      5))
((:pair 6.0 *kilogram))

KM> (the value of
     ((a Mass-Value with (value ((:pair 1.2 *kilogram))))
      property-div
      6))
((:pair 0.20000002 *kilogram))

KM> ((a Mass-Value with (value ((:pair 1.2 *kilogram))))
     property-div
     (a Mass-Value with (value ((:pair 2 *kilogram)))))
(_Unitless-Value13)

KM> (the value of _Unitless-Value13)
((:pair 0.6 *unity))

KM> ((a Length-Value with (value ((:pair 10 *meter))))
     property-mult
     (a Length-Value with (value ((:pair 10 *meter)))))
(_Area-Value16)

KM> (the value of _Area-Value16)
((:pair 100 *square-meter))