[
Lists Home 
Date Index 
Thread Index
]
costello@mitre.org@INTERNET@wtgw'(Roger L. Costello):
 EXAMPLE 1

 To explain the approach I will use this example:

 <River id="Yangtze">
 <length>
 <kilometer>6340</kilometer>
 </length>
 </River>

 Recall that <kilometer> may be considered as a function:
...
 kilometer(Distance) > number
I'd say that more usually kilometre is considered a function that maps a number to
a distance. If you consider the canonical distance to be a metre, you can define:
(defun kilometre (x) (uom* 1000 (metre x)))
; where
(defun uom* (scalar uom) (list (car uom) (* scalar (cadr uom))))
(defun metre (x) (distance x))
(defun distance (x) (list 'distance x))
I don't do MathML, so you'll have to make do with lisp as it's a convenient
functional language.
I prefer that the kilometre function adds information to a number making it a
distance, instead of removing information.
<River id="Yangtze">
<length>
<kilometer>6340</kilometer>
</length>
</River>
>
(defclass River () ((id :initarg :id :accessor :id) (length :initarg :length :
accessor :length)))
(defmacro River (&rest r) (apply 'makeinstance 'River r))
(River :id Yangtze :length (kilometre 6340))
=> #<RIVER>
 Likewise, for this version:

 <River id="Yangtze">
 <length>
 <mile>3914</mile>
 </length>
 </River>

 mile is a function that maps a Distance to a number:

 mile(length(Yangtze)) > 3914

 or more generally:

 mile(Distance) > number
alternatively
(defun mile (x) (uom* 5280 (foot x)))
(defun foot (x) (uom* 12 (inch x)))
(defun inch (x) (uom* 0.0254 (metre x)))
; or in prefix notation:
; mile(number) => 5286 * foot (number) = 63360 * inch (number)
; = 1609.35 * metre (number)
so
<River id="Yangtze">
<length>
<mile>3914</mile>
</length>
</River>
>
(River :id Yangtze :length (mile 3914))
=> #<RIVER>
 "Those instances that represent equivalent Distances are
 the set of k (kilometer), m (mile) pairs such that k = m * 1.62"
Are the length properties of two rivers the same?
(setf yang0 (River :id Yangtze :length (kilometre 6299)))
(setf yang1 (River :id Yangtze :length (mile 3914)))
(:length yang0) => (kilometre 6299)
(eval (:length yang0)) => (DISTANCE 6299000)
; equivalentuomvalue tests the evaluated form of two lists
; and compares the numeric values in the second member each the
; list, using the second member of the tolerance list as a absolute
; tolerance if present. If the dimensions of the values are not
; equal it will return false.
(defun equivalentuomvalue (x y &optional &key (tolerance nil))
(let ((x (eval x)) (y (eval y)) (tolerance (eval tolerance)))
(if (and tolerance (numberp (cadr x)) (numberp (cadr y)))
(and (> (+ (cadr x) (cadr tolerance)) (cadr y) ( (cadr x) (cadr
tolerance)))
(equal (car x) (car y))
(equal (car x) (car tolerance)))
(equal x y))))
=> EQUIVALENTUOMVALUE
(equivalentuomvalue (:length yang0) (:length yang1))
=> NIL
(equivalentuomvalue (:length yang0) (:length yang1) :tolerance (metre 30))
=>T
; degrees and radians
(defun degree (x) (uom* (/ pi 180) (radian x)))
(defun radian (x) (angle x))
(defun angle (x) (list 'angle x))
(equivalentuomvalue (metre 7) (radian 7)) => NIL
Implicitly an equivalence relation defines a set.
 For example, (6340 k, 3914 m) represent equivalent Distances.
BTW
(equivalentuomvalue (mile 3914) (kilometre 6340) :tolerance (kilometre 40)) =>
NIL
wheres
(equivalentuomvalue (mile 3914) (kilometre 6299) :tolerance (foot 100)) => T
So I guess that either kilometres are subject to an import duty on entering the USA,
or your mile isn't a statue mile ;).
 I envision a document containing class definitions (e.g.,
 the Distance class). I envision an API to enable programs to
 programmatically access the class info via the API.
I've done similar to the above, but with functions that convert numbers to
distances rather than distances to numbers in a several hundred lines of Java, with
XML data files like:
<Blah
length = "2.134"
length_units = "km"
/>
The syntax of which is mainly due to XMI>Java mapping limitations.
 This API may have a method such as this:

 boolean isContainedIn((uom1_value, uom2_value), set);

 The method, isContainedIn, has two arguments. The first argument
 contains a pair of unitofmeasure values, and the second argument
 is a set definition. The result is a boolean.
What would be the truth table of this method? If the set is the set of equivalent
uom_values, then it's infinite and exposing it as the api has no more functionality
than exposing the function equivalentuomvalue.
 <Class id="Distance">
 <equivalentInstances>
 {k, m  k = m * 1.62}expressed as MathML
 {k, m  k = m * 1.62}expressed as Mathematica
 {k, m  k = m * 1.62}expressed as xPath(???)
 </equivalentInstances>
 </Class>
Do you really want to define units^2*representations functions, or wouldn't it be
better to define one function for each units (in whatever representation) that
generates a canonical form for the equivalence realtion?
 Do you have suggestions on how to represent tolerance?
 fixed, as a uomvalue, eg the example I gave above
 relative to one of the input values
 EXAMPLE 2
...
 Here is the completed Location class:

 <Class id="Location>
 <equivalentInstances>
 {c, p  c.x.kilometer = p.r.kilometer sin p.theta.radian ^
 c.y.kilometer = p.r.kilometer cos p.theta.radian}
 </equivalentInstances>
 </Class>

 Note: I am not convinced that this is the best way to express the set.
 Do you have any suggestions?
I'd call it coordianate2d or something; a general location needs 3D [+ time stamp]
[+ tolerance/confidence], a coordinate system and possibly a reference point (eg:
lat/long/alititude the reference point is implied but inertial systems
distancenorth/distanceeast/distancedown the reference point is also required)
Unfortunately, there isn't a single canonical form for equivalence:
if p0 is a cartesian point with a tolerance t0 of +/ x metres in any direction
and p1 a polar point with a tolerance t1 of +/ y degrees and +/ z range
(equivalentlocation (topolar p0) p1 t1)
<=/=>
(equivalentlocation p0 (tocartesian p1) t0)
though it should be the case, subject to rounding errors, that
(equivalentuomvalue (distancebetween (topolar p0) p1) (metre 0) :tolerance
(metre sometolerance))
<==>
(equivalentuomvalue (distancebetween p0 (tocartesian p1)) (metre 0) :
tolerance (metre sometolerance))
 API REVISITED

 Recall the API that was mentioned above:

 boolean isContainedIn((uom1_value, uom2_value), set, tolerance);

 Recall that "tolerance" is used to indicate how much slack you
 are willing to accept in deciding if a pair of values are contained
 in the set. In this Map example the tolerance is effectively a
 way of indicating "I want all values within this region". When
 you tighten the tolerance, you narrow the region. When you loosen
 the tolerance, you widen the region. I think this will be very useful.
In this case tolerance then would consist of a function to covert uom1_value and
uom2_value to a common form, a function to compute the difference in some form, and
a value that the difference value have to be less than.
For the length case, the common form is the canonical form SI metres; for the
location case different tolerances (cartesiantolerance, polartolerance,
distancetolerance) would require different common forms and difference
computations.
eg:
(equivalentlocation p0 p1 (polartolerance :theta (degrees 10) :r (kilometres
50)))
would test if p0 and p1 have bearings within ten degrees of each other and ranges
within 50km of each other from an implied origin
(equivalentlocation p0 p1 (distancetolerance (foot 10)))
would test if p0 and p1 are within 10 feet of each other
As a quickhacK:
; super class for 2d coordianate. serves no real purpose
(defclass coordianate2d () ())
; cartesian location and constructor method
(defclass cartesiancoordinate (coordianate2d) ((x :initarg :x) (y :initarg :y)))
(defun cartesiancoordinate (&key x y) (makeinstance 'cartesiancoordinate :x x :y
y))
; polar location and constructor method
(defclass polarcoordinate (coordianate2d) ((r :initarg :r) (theta :initarg :
theta)))
(defun polarcoordinate (&key theta r) (makeinstance 'polarcoordinate :theta
theta :r r))
;<Map id="M21">
; <location>
; <polarcoordinate>
; <r>
; <kilometer>141.421</kilometer>
; </r>
; <theta>
; <radian>0.7841</radian>
; </theta>
; </polarcoordinate>
; </location>
;</Map>
(defclass Map () ((location :initarg :location :accessor :location)))
(defmacro Map (&rest r) (apply 'makeinstance 'Map r))
(setf m (Map :location (polarcoordinate :r (kilometer 141.421) :theta (radian 0.
7841)))) => #<Map?>
(:location m) => (POLARCOORDINATE :R (KILOMETER 141.421) :THETA (RADIAN 0.7841))
(defmethod tocartesian ((pt cartesiancoordinate)) pt)
(defmethod tocartesian ((pt polarcoordinate))
(let
( (r (eval (:r pt)))
(theta (eval (:theta pt))))
(if (and (eql 'distance (car r)) (eql 'angle (car theta)))
(makeinstance 'cartesiancoordinate
:x (distance (* (cadr r) (cos (cadr theta))))
:y (distance (* (cadr r) (sin (cadr theta))))))))
(defmethod topolar ((pt cartesiancoordinate))
(let
( (x (eval (:x pt)))
(y (eval (:y pt))))
(if (and (eql 'distance (car x)) (eql 'distance (car y)))
(makeinstance 'polarcoordinate
:r (distance (sqrt (+ (* (cadr x) (cadr x)) (* (cadr y) (cadr y)))))
:theta (angle (atan2 (cadr x) (cadr y)))))))
(defmethod topolar ((x polarcoordinate)) x)
; haven't bothered with checking type of x and y
(defun distancebetween (p0 p1) (let ((p0 (tocartesian p0)) (p1 (tocartesian
p1)))
(let
( (dx ( (cadr (:x p0)) (cadr (:x p1))))
(dy ( (cadr (:y p0)) (cadr (:y p1)))))
(distance (sqrt (+ (* dx dx) (* dy dy)))))))
; create a comparison with based on an absolute tolerance
(defun distancetolerance (tolerance)
(lambda (p0 p1)
(equivalentuomvalue (distancebetween p0 p1) (distance 0) :tolerance
tolerance)))
; do something similar for polartolerance creates an appropriate comparitor
function
; by converting p0 and p1 to polar and taking the difference
; (defun polartolerance (&key rtolerance thetatolerance) ...
; the equivalence function for locations
(defun equivalentlocation (p1 p2 &optional &key (tolerance (distancetolerance
(metre 1))))
(funcall tolerance p1 p2))
; default tolerance is 1 metre
(setf *WARNONFLOATINGPOINTCONTAGION* nil)
; it's quite contagious
(setf p0 (polarcoordinate :theta '(degree 90) :r '(metre 1609)))
(setf p1 (cartesiancoordinate :x (mile 0) :y (mile 1)))
(equivalentlocation p0 p1) => T
(equivalentlocation p0 p1 :tolerance (distancetolerance (metre 10))) => T
(equivalentlocation p0 p1 :tolerance (distancetolerance (metre 0.01))) => NIL
(setf p2 (cartesiancoordinate :x (mile 20) :y (mile 0)))
(equivalentlocation p0 p2) => NIL
(equivalentlocation p0 p2 :tolerance (distancetolerance (kilometre 40))) => T
; but comparing two values with tolerances isn't a strict equivalence relation
; as it's not always transitive
(setf p0 (cartesiancoordinate :x (metre 1.1) :y (metre 0)))
(setf p1 (cartesiancoordinate :x (metre 2) :y (metre 0)))
(setf p2 (cartesiancoordinate :x (metre 2.9) :y (metre 0)))
(equivalentlocation p0 p1) => T
(equivalentlocation p1 p2) => T
(equivalentlocation p0 p2) => NIL
I'd guess there's similar constructs in the languages you're using.
Pete
********************************************************************
This email and any attachments are confidential to the intended
recipient and may also be privileged. If you are not the intended
recipient please delete it from your system and notify the sender.
You should not copy it or use it for any purpose nor disclose or
distribute its contents to any other person.
********************************************************************
