[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Axiom-developer] Unit package proposals and questions (was Unit pac

From: William Sit
Subject: Re: [Axiom-developer] Unit package proposals and questions (was Unit package question - Part 1)
Date: Sun, 04 Sep 2005 01:22:34 -0400

Dear C.Y.:

Thanks for your comments. I have combined your two responses and rearranged the
order of your comments in the responses below to avoid as much duplication as
possible. However, to present a more or less logically ordered and
self-contained version for others not familiar (or confused) with our earlier
discussions, I have quoted some earlier email paragraphs as well.

---------- General discussion on documentation

C Y wrote:
> --- William Sit <address@hidden> wrote:
> > you have already started real work.
> That's probably too generous - I've started trying to become informed
> enough to start real work, really.  Bill is probably going to flinch
> when he sees my idea of basic pre-code (heck, it's really pure
> background) documentation :-).

Tim will love you!
> > It seems that a thorough study of dimensions and units in
> > relation to symbolic computations is not available and your
> > work/paper would be very useful.
> I hope so, although I suspect your ideas are far more useful than my
> own - I'm just asking questions and swatting user level features around
> in my head at this point.  The hard part (and interesting part) is
> expressing them in relation to Axiom's mathematical rigor.

You are welcome to ignore or include in your work/paper any ideas I presented on
this forum.

The hardest part is knowing questions to ask, and second is figuring out the
answers; the easiest (though by no means trivial) is to code the solutions.

> > After waiting a short period of further
> > discussions, a summary of the final design should be posted at
> > MathAction for others to comment on.
> Sounds good.  I apologize in advance for how basic some of my questions
> below will be - I tried to review as much as possible of earlier
> discussions, but I may have regressed some after a rather busy week at
> work.

No need to apologize (though I sometimes do myself). I too have short (if any)
memory. and tends to repeat myself -- what do you expect from an old guy :-)?

---------- Basics of the proposal: Representation of UnitSystem domains

William wrote: 

> >    Rep:=Record(value:S, dim:Dimension, unit:Unit, factor:(Float, String),
> >                absfactor:(Float, String))
> >  
> >My original proposed Rep is simpler because I was not planning for dynamic
> >changes to the unit system, so unit and factor (which would be 1 always) are
> >"hard-wired". The more general record allows more flexibility. This is 
> >slightly
> >less efficient in terms of storage, but not that bad, because no matter what,
> >somewhere, the system has to store the conversion factors. The conversion
> >factors can probably be implemented in a UnitConversion domain, which would 
> >be a
> >lookup table (maybe tables), which drives the 'setDimUnit' and 'setUnit'
> >commands. Axiom has a number of data structures with extensive tools to 
> >create
> >lookup tables (see domains of category TableAggregate in table.spad).

C Y wrote:

> That sounds good, I think - I would propose using this more general, flexible
> representation only in a single instance of a Dynamic UnitSystem - SI and CGS
> wouldn't need it, if I understand correctly.

This comment of yours is based on your breaking up UnitSystem into Static and
Dynamic Unit System. This is certainly possible, but see my comments in the
section on Static vs Dynamic user environment, which will list some pros and
cons on this break up.

> >In the new Rep, besides the unit, two factors are included: One relative to 
> >the
> >current system (to provide a relative factor to convert within this system 
> >when
> >a user changes a unit), and one relative to SI (to provide an absolute 
> >factor to
> >convert between systems: for SI derived unit system, just one factor would
> >suffice; but we should aim for uniformity to simplify the code). 

> I think the latter is a matter of convenience - converting relative to the
> current system is also doable via input unit -> SI -> output unit - if I
> understand you what you are doing is precompressing this two step process
> into one for the default "output" system?

The relative factor can either be built-in for the UnitSystem domain, or via the
SI mechanism. But we have to remember that SI is not universal (supermarket
manager example). So a relative factor setup solves the general situation and is
also more efficient. The SI approach is mainly for scientific applications AND
conversion between two drastically different systems. Believe me, in less than
30 years, symbolic computations will be used by economists, if not already.
(Mathematica has an operations research package, sold separately).

> Generality is good, but I'm afraid I'm not following - for any given Unit,
> wouldn't all you need to know be the description of that unit in terms of SI?
> Or are you proposing that all UnitSystems use this extended storage record?
> I would suggest using it only for the Dynamic UnitSystems, and then you have
> the flexibility to define new units in terms of SI which have no existing
> Static definition.

Yes, I am more in favor of every UnitSystem domain being dynamic (again, see
that section). As to shortening the Rep, yes, in principle, for "scientific"
unit systems, it only needs a conversion factor relative to SI, and yes, for
static unit systems, the relative conversion factors are not needed either.
However, SI is not everything, so the relative factors will be needed in those
cases, and SI may be replaced by another standard unit system.

C Y previously wrote:
> Is that why you're adding the extra
> arguments - to avoid Axiom needing to figure out that nm is a Length
> defined in the SI UnitSystem?  

No, the extra arguments in the new Rep are for convenience of implementation and
efficiency in execution. Axiom still has to verify, on user input via the
setDimUnit commands, that the unit is a legitimate unit for the dimension
specified, even though, as you insist, we allow units outside of the current
unit system. This verification is faciliated by the UnitConversion domain.

> > I made the factor:(Float, String) [updated from Union(Float, Symbol)]

    [ added: and absfactor:(Float, String) ]

> > to allow a delay of the computation
> > when symbolic computation is more prevalent and also when S does not have
> > RetractableTo(Float).  

> >Each factor has
> >both a value (Float) and a name (String). The value of the factor is when
> >numerical output is needed, that is, when S is coerced to Float (via the 
> >"lift"
> >mechanism). The name would be used in output for symbolic computations to
> >indicate a conversion factor is needed, without spoiling the elegance of
> >symbolic computation or more importantly, going outside the domain S. It is 
> >only
> >a decoration in the output (so it can be used with even Float alone), but it
> >serves two important roles as well: it can be used as an index key to the
> >UnitConversion table(s) to look up the value of the factor, and it can also 
> >be
> >used to provide an audit trail in numerical computations: typically, if the
> >answer is simply in numeric form set to the user's unit, the user may not 
> >have
> >any idea of how what factors are used in its computation; by delaying the 
> >use of
> >numerical values for conversion factors, the user can track each conversion 
> >in
> >symbolic form for numerical inputs to verify correctness and then compute 
> >when
> >everything is ok (in case there are bugs, for example, this can be used for
> >debugging too).
> >The above setup would make the coercion to OutputForm quite straight forward 
> >and
> >uniform (which should ignore the factors if they are (1.0, "1")).

C Y wrote:

> This is definitely interesting, but I'm not sure we want such an ability to be
> the default - I would suggest hiding the conversion factors unless the user
> specifically specifies otherwise.  I like the idea of the ability to
> explicitly show them though :-).

What you meant then is to have something like:

    setSymbolicConversion(): Boolean

as default True, which will include symbolic conversion factors. Setting this
False will use numerical values. However, if you meant that when I
setDimUnit("Length", "cm",x) and x was in "m" originally that it will output
only x [cm] instead of x m2cm [cm], then I don't agree.

------------ Basics of the Proposal: UnitSystem domain specifications 

The following addresses only the user interface specifications under discussion
and is not a complete specification for the category:

William Sit wrote:

> > FIRST: Consolidate all the unitXXX and setUnitXXX functions to::
> >
> > UnitSystemCategory(S: SetCategory):Category == Exports where
> >
> >  Dimension ==> Union("Mass", "Length", ...)
> >  Unit ==> Union("kg", "m", ...)
> >  Join(RetractableTo S,...) with
> >
> >      setDimUnit: (Dimension, Unit, S) -> %

[added from earlier mail:

         setDim(Dimension, S) -> %
         setDim(dim,s) == setDimUnit(dim, unit(dim), s)

 where unit: Dimension -> Unit
 looks up the unit in a UnitConversion domain corresponding to the dimension.]

> >      setUnit: (Dimension, Unit) -> Null (?)
> >      setUnitAll: (Dimension, Unit) -> Null (?)
> >
> > where 'setDimUnit(dim, unit, s)' is a LOCAL command affecting ONLY
> > s:S, and 'setUnit(dim, unit)' would be a GLOBAL command affecting
> > ALL s:S (more on this later).  Null may be replaced with a new
> > state vector?

C Y wrote:
> I don't quite understand s:S - can you give a specific example of this
> difference?  Also, I'm not following why you would want to make any
> local vs. global distinctions here - wouldn't it be neater just to have
> the set commands work in the CurrentUnitSystem, and base things off of
> Static UnitSystems for definitions unless a totally custom conversion
> is being defined? 

In the setDimUnit, 'setDimUnit' commands, an expression s:S is involved, where S
is a domain that usually contains symbols ("RetractableTo Symbol" in Axiom
jargon) and s:S means s is such an expression. Of course S can be just Float if
no symbols are involved, in which case, expressions and variables are simply
constants.  But the user assigns a dimension and unit to an expression, which
will change the way certain variables involved in the expression are inputted or
outputted. This setting is for a specific expressions s, so has "local" scope.
The other 'setUnit' is local for a specific dimension, but has a wider scope and
affects all expressions of that dimension. Finally, the 'setUnitAll' is global
in the sense that all derived dimensions involving that specific dimension and
all expressions in all those derived dimensions will be affected. The
implementation will be assisted by the UnitConversion domain and the Rep
remembers the conversion factors both relative to the current system and to the
SI system, when possible.

> > To support the implementation for 'setUnit' (a dynamical
> > change of units), I propose to add a state vector for each unit
> > system domain: this state vector stores the current unit for each
> > dimension, which is updated by the 'setUnit' command 
    [added: and 'setUnitAll' command]. 
> > The'setDimUnit' command can check this state vector before generating
> > the Rep (see below). Some care has to be considered: we have to
> > decide whether a 'setUnit(dim, unit)' command should affect the
> > other derived units that depends on 'dim' or not, and also those
> > the variables whose dimensions were set before this 'setUnit'
> > command and invole 'dim'. I have added 'setUnitAll' for the case
> > every current variable will be updated.
> I don't think I'm quite following - Derived Units are defined in terms
> of the Base Units for their UnitSystem - just because we are now using
> "cm" instead of "m" as our default length doesn't change the definition
> of N, or how many Newtons we have.  If we want to report a Derived Unit
> in terms of Base Units, then we would want to use cm instead of m, but
> otherwise I'm afraid I'm missing something.

My proposal allows (but the decision is still open) changing the units for a
single expression s:S -- 'setDimUnit(dim,u,s)'. It also allows changing the unit
of a single dimension, say Length, in the current (loaded) unit system without
affecting other derived dimensions that involve Length -- 'setUnit(dim,u)'.
Finally it allows changing the unit of a single dimension, say Length, and any
other derived dimension that involves Length, such as Velocity --
'setUnitAll(dim, u)'. In your example above, changing the unit of Length from
"m" to "cm" will report the unit of Force (the dimension of "N") either still as
"N", if 'setUnit(Length,"cm")' is used in SI; or as kg-cm/s^2 (by changing the
value of any expression with dimension Force by a conversion factor m2cm), if
'setUnitAll(Length,"cm")' is used in SI; in which case, the new unit of "Force"
is "kg-cm/s^2" or "kilodyne", following SI prefix convention (basically changing
SI, which is MKS based, to CGS).

---------- Scenario Example

William Sit wrote:

> > The following scenario will illustrate the potential problems and I'll put
> > in some suggestions on how to solve some of these.
> >
> > Assuming the above extended Rep:  unit is initialialised to the standard
> > one for the system, factor initialized to (1.0, "1"), absfactor initialized
> > to (absfactorvalue, absfactorname).  Let's assume the default unit system
> > is FPS (foot-pound-second, a non-scientific system still used in the US),
> > see:
> >
> >
> >
> > When a user runs the command:
> >
> > (1)   ulen: := setDim("Length", len)
> >
> > Axiom will return:
> >
> >       len [ft]
> >
> > but internally, the Rep is
> >
> >     [value = len, dim = "Length", unit = "ft", factor = (1.0,"1"),
> >      absfactor = (0.3048, "ft2m")]
> >
> > Here the absfactor says 1 ft is 0.3048 m. The name can be constructed
> > dynamically using string concatenation using the UnitConversion table.
> In general, I like this (I would prefer to simplify the 'setDim("Length", 
> len)'
> syntax as mentioned in the previous email, but I don't know if anyone else
> agrees with me as to whether my proposal there makes any sense.)

I assume you are referring to the 'setUnit(nm,N,inches)' suggestion. See section
on Updating variables and their units.

[Following quotes edited for more consistent reading]

> > In a STATIC change environment (this is, at compile time), if the user
> > prefers "in" GLOBALLY as the unit for length, the command
> >
> > (2) setUnit("Length", "in")
> >
> > will output: 

> >     len ft2in [in]
> >
> > with the internal Rep now:
> >
> >    [value = len, dim = "Length", unit = "in", factor = (12, "ft2in"),
> >     absfactor = (0.0254, "in2m")]
> >
> > where 0.0254 can be computed from 0.3048 by dividing by 12, some other
> > means. The absfactor will faciliate converting FPS to SI, and hence to
> > other system as well.

> > Here is a design question: we can let 'setUnit("Length", "in")' to modify
> > ONLY the unit of the "Length" dimension and not any derived dimension that
> > involves "Length". This would be the most flexible.
> Yes, I agree - don't update the derived dimensions.
> I'm not sure about the need for two factors, except perhaps as a matter of
> efficiency in avoiding common conversion lookups - is that the reason?

Yes, see also section below. Each expression requires one lookup at the time its
dimension and unit is set. All subsequent uses and display will avoid the lookup
again even if, in case of a variable, it is reassigned to a different value. All
necessary conversion is taken care of by the arithmetic operation in the
UnitSystem domain.

> > If the user prefers "cm" as the unit for length in an otherwise FPS system,
> > the command unitLength can be modified to produce:
> >
> > (3)   len ft2cm [cm]
> >
> > with the internal Rep now:
> >
> >    [value = len, dim = "Length", unit = "cm", factor = (30.48, "ft2cm"),
> >     absfactor = (0.01, "cm2m")]
> >
> > This is all not difficult for STATIC changes, that is, changes that are
> > effected at Axiom start time. Now consider DYNAMIC changes: suppose again
> > the default is FPS system, and the user has already set the variable ulen
> > as in (1).
> Hmm.  Need to roll around in my head some more :-/.
> > Now if the user later runs:
> >
> > (4)    setUnit("Length","cm")  [function name updated from unitLength]]
> >
> > What does this involve? You are now in a run-time environment, you cannot
> > change the code for 'setUnit' in the FPS domain, you can only change data.
> > (Code modification is in theory possible if you know enough, but I don't
> > think that is a good practice in Axiom).  To handle FUTURE assignments, we
> > can design the code for 'setUnit' to depend on a state vector for the
> > domain: this state vector stores one unit for each dimension, and is
> > updated by the 'setUnit' and 'setUnitAll' commands. The 'setUnit' (and
> > similar 'set' commands) can check this state vector before generating the 
> > Rep.
> Sounds good, in broad.
> > But what about those variables already defined, like ulen defined in (1)?
> > If ulen is used in some computation requiring ulen to be an input
> > parameter, then we can update it. For example, if the user now wants to
> > compute the area for a square with side ulen using one of the following
> > syntax:
> >
> >      uarea := ulen * ulen
> >      uarea := setDimUnit("Area", ulen, ulen) [function name updated from 
> > unitArea]
> >
> > the routine * or 'setDimUnit' can check the units of its arguments and 
> > update
> > them before computation. However, if the user simply types
> >
> >      ulen
> >
> > the interpreter can only redisplay the output (1). The interpreter has no
> > reason to call the FPS(S) domain to perform an update and change the unit
> > of ulen and display the output (3). Perhaps the domain FPS(S) should
> > provide a function 'update(ulen)'.
> Does that mean an interpreter update is needed.?
I hope not! The 'update()' function can handle that. We should not modify the
Interpreter for this project unless it is absolutely necessary, which so far, I
don't see. It is possible for the 'setDimUnit' function in the UnitSystem domain
to record all calls to the 'setDimUnit' command to create and maintain a live
list of variables or expressions, say as part of the state vector. An update can
either be applied for just one variable in the domain, or all variables in this
live list.

---------- Implementation issues: Updating variables and their units

Some updating questions are raised and solutions suggested in the Scenario
Example section above.

> As for current variables, shouldn't they be updated automatically by
> the global update?

That is the idea. That is, a 'setUnitAll(dim, u)' command will change all output
and input variables/expressions that are of dimension dim to use unit u. In the
scenario Example section, we discussed the issues and some possible actions. The
basic design question to decide is: should this global command affect only newer
variables/expressions or should this retroactively set all existing
variables/expressions? The basic implementation question is: what data
structures will support these functionalities efficiently (bear in mind some
trade offs between memory and CPU time, as usual)? It seems the proposed
state-vector can support the implementation, whatever the decisions.

> I would have thought all you needed was a single command SetUnits()
> command, which would take a minimum of one argument and a max of one
> unit per available dimension, e.g.
> SetUnits(nm,N,inches); 

[NB, Axiom convention:function names should start with lower case]

I do not quite follow. Your example has three arguments, all units of Length. I
think you are thinking of 'setUnitAll(dim, u)'? Maybe a simpler 'setAll(u)' and
let the system figure out the dimension of u? (But as explained below, this
reverse lookup from unit to dimension is not unique; in that case, we can make
'setAll(u)' return an error message with some choices (probably not all possible
choices). So you would still need the version 'setUnitAll(dim,u)' after the user
picks one of those choices.

Your line:


is, as far as I can follow, a global set. Surely, in this simple example, Axiom
can figure out that these (nm, N, inches) (aside: use "in" for "inches" -- SI
recommendations) are units for Length, but as explained, this is not possible in
general. My version 'setUnitAll(dim, u)" only does this for a particular
dimension dim and a particular unit u. I don't know why you set the Length
dimension to THREE different units. Are you imagining mixing units for the same
dimension in one session? How are you going to tell which variable/expression
will use any one of these three units? Are you saying that ALL three units
should be reported for ANY variable/expressions of dimension Length? (Note: even
if you are mixing units, the Rep will support it. I just want to know what your
line meant.)

> In the CurrentUnitSystem Dynamic UnitSystem (assuming things are in
> default mode) the "state vectors" for the dimensions corresponding to
> the units entered would be updated.  It's not clear to me why you would
> need any other arguments, unless you wanted to make sure the user knows
> the dimension of the unit they are inputing as a default.  

> Maybe I place too much emphasis on user
> convenience but I as a user would prefer not to tell Axiom things it
> already knows.

Fair enough. We can ALWAYS add defaults. The example I gave in my last message
(added above in Section on UnitSystem specification):

   setDim(dim: Dimension, s:S):% == setDimUnit: (dim, unit(dim), s)

performs a lookup for the default unit for a given dimension in the current
UnitSystem. The 'setAll(u)' above can handle cases where an automatic lookup
results in a unique dimension to set the dimension field in Rep. However we do
not want to look up repeatedly each time we use a variable, so the results are
memorized in Rep. 

And, yes, users should know the dimension of the unit they are inputting. One
danger with something like 'setAll(u)',  which left out the dimension for u, is
that a simple typo say from 'setAll(cm^2)' to 'setAll(cm^3)' would not be caught
and play havoc in subsequent computations. Forcing the user to give the intended
dimension provides a better chance that these errors will be caught.

> Maybe as a time saving alternative SetUnits could also
> accept things of the form <UnitSystem>::Unit or some such, which would
> limit the search space it would need to check?  

I don't follow the syntax of <UnitSystem>::Unit. Is :: coercion in Axiom? I have
not heard of coercing a domain into a category. Perhaps you are thinking of a
package call to a domain in UnitSystems? That would be setAll(u)$domain. But I
do not like this default setAll(u) for reasons above.

> Or even better, if
> Axiom is up to it we might also be able to build a toplevel hash table
> of all defined units in all unit systems at compile time which can
> quickly match up a unit up with a UnitSystem and Dimension.

The UnitConversion domain (perhaps category) is for this purpose. I am still
thinking about whether UnitConversion should be a category with many domains or
just one domain. The many-domain approach may provide better efficiency for more
localized conversion systems and flexibility future additions.

As we don't know all the expert areas now in existence, nor do we know what new
derived dimension or unit we may need (especially in 30 years' time), there is
no way we can have such a universal toplevel hash table. We CAN implement SI
(all the default and acceptable dimensions and units) or even more, but such a
domain will need to be revised to allow newer dimensions and units. The design
proposed will allow this of course (any design in fact), but I still subscribe
to the older Axiom philosophy that we do not modify existing libraries except
for bugs, and extend existing libraries through additional implementation. We
should allow arbitrary UnitSystems (as I also indicated in my last email,
supermarket manager will need a totally different, "non-scientific" unit system
with dimensions like "Coke", "DietCoke", etc.)

---------- Implementation Issues: Setting up Dimension and Unit domains

William Sit wrote:

> >[Comments: I have not decided whether there should be more than one category,
> >and also what to call them. Also there is a difficulty with dimensions(),
> >units() because they do not return a domain, to be used in the signatures. So
> >you may safely ignored the next paragraph for now. However, what I had in 
> >mind
> >was to allow many domains like Dimension = Union("Mass", etc) and 
> >corresponding
> >Unit = Union("slug", etc) for people (students ?) who don't need the full 
> >set,
> >as well as the ability to add new supersets later. Unfortunately, we cannot
> >have:
> > 
> >  Dimension(dims:List String) == Union(dims)
> > 
> >]
> > 
> >FIRST (alternative): On the category level:
> > 
> >There will be
> > 
> >(I) a UnitConversion category, whose details I have not investigated, but its
> >domains will contain tables for all dimensions for a particular expert field,
> >units, and conversion factors from SI. There will probably be one 
> >comprehensive
> >such domain to start the ball rolling, but we will surely miss some 
> >dimensions
> >and units in some not-so-common expert areas or new areas. The category will
> >provide guidelines to add these new areas.
> > 
> >UnitSystem(S, D, U):Category == Exports where
> >   S: SetCategory
> >   D: List String
> >   U: List String
> > 
> >   dimensions: ()->List String
> >   units: ()->List String
> >   convertFactor: String -> Float
> >
> > For example, dimensions() = ["Mass", "Length", ...] (which replaces 
> > Dimension =
> >Union("Mass", "Length", ...), making this local to a unit system rather than 
> >one
> >global list.
> >
> >(II) ??? Dimension(dims:List String) == Union(dims)

C Y wrote:

> Dimensions
> may not always map uniquely to Units, but Units DO map uniquely to
> dimensions. 

Your last remark is wrong, unless there are already standard terminology such as
in the case of Work vs Moment: standard energy-units exist as Joule, erg, eV,
etc. and moment-units exist as N-m, etc. In other cases, you may have to create
new standard names first. However, the problem still is: given some unit in
reduced basic dimensions such as (mass-length/time^2).length, say kg.m^2/s^2, we
do not know if the dimension should be Energy (either Work or Kinetic Energy or
Potential Energy) or Moment. Vectorizing some of these dimensions may help: Work
is a force vector times a length vector, and so is moment, but the two length
vectors have different directions with respect to the direction of the forces.

> Couldn't Axiom figure this out?  All it has to do is
> determine the dimension of each argument, check that all dimensions are
> unique, and set the defaults (the setunits command in Maxima works this
> way.)  We ARE back to some parser being able to check all units for a
> match to the input unit, I guess. 

What you are describing is the "forward" direction, which is easy. The problem
to map units back to dimension is the "backward" direction, which has no clean
solution (yet?). You will need a parser if the Dimensions and Units are
represented by variables taking up namespace (as in Mathematica, and I assume,
in your Maxima implementation). My proposal avoids this modification to the
Axiom Interpreter. (see also Namespace issues below).

--------- User environment for Unit systems: Static vs Dynamic

[Quotes edited to bring function names up to date]

William Sit wrote:

> > Axiom allows a user to set his preferences in a file
> > called axiom.input (which is in the directory $AXIOM/input).
> > So by putting ")set UnitSystem MYUnitSystem" in that file, Axiom
> > will use MYUNitSystem as the default unit system when the
> > functions 'setDimUnit' etc. are called.  MYUnitSystem can be SI, CGS,
> > or some modified version of the standard SI (but once modified,
> > it should be called something else).

C Y wrote:
> This isn't quite what I was thinking - I was thinking by default Axiom
> could use a unit system called CurrentUnitSystem, which would be
> somewhat different in definition from SI, CGS, etc.  Doing
> )set UnitSystem SI
> would drop the user in a strict SI output only environment without the
> possibility of local override, which I have no problem with.  (Might
> even be a good idea to have available, really - call it a STATIC
> UnitSystem definition.) 

All Axiom variables are typed. So once a user started computating using a
UnitSystem domain, say A, all his computations will be in that unit system. If
he then change to SI, he would have to coerce them to SI, which may or may not
be possible, depending on what dimensions and units are in A. (So, the domain A,
and the UnitSystems category, may have to include functions like convertIfCan: %
-> SI).

> What i would like CurrentUnitSystem to do is
> be a DYNAMIC UnitSystem, using either the system you have outlined
> below or something similar.  It would start out as an instance of the
> SI definitions by default, but allow local overrides dynamically (hence
> a Dynamic UnitSystem definition).  Also useful would be a
> SaveUnitSystem(<NewUnitSystemName>) for later use - essentially
> allowing a user to load a precustomized Dynamic UnitSystem Definition
> as the working UnitSystem.  With a Dynamic UnitSystem Definition we
> could have a MapUnitSystem(<UnitSystem name>) command to allow the user
> to restore all STATIC SI definitions (say) to the CurrentUnitSystem.
> Is that following what you had in mind?

I think you want somehow to restrict some users (say students who are learning
about units and dimensions) not to allow them to "mess" with a UnitSystem domain
like SI. I don't see the necessity because most likely, such users will only
want to do their computations in whatever unit system is the default. Even if
they were to use 'setDimUnit', 'setUnit', and 'setUnitAll' (which would be a
good experience), these only affect the interpreter session and will not modify
the SI domain at all. The state-vector does not survive an axiom reload since no
modification to the compiled code is performed. Also a user can save the history
of all inputs, including all 'set' commands (and also ')set' commands) and put
them in axiom.input or a 'myunitmod.input' and read it in anytime. There is no
need, in this dynamic design, to modify ANY compiled domain in the UnitSystem
category. When a user wants to have modification compiled into a modSI domain,
he will have to edit the SI.spad.pamphlet and change it into modSI.spad.pamphlet
and compile it. However, I don't see the necessity. Your idea of
'SaveUnitSystem(<newUnitSystemName>) is difficult (but not impossible) to
implement and involves automatically editing say SI.spad.pamphlet to
modSI.spad.pamphlet and automatically compiling it. It is trivial for a user to
read in an input file instead.

I note that each of our positions on this user environment issue has turned 180
degrees from earlier communications :-).

The ')set unitsystem <UnitSystem name>' will only need to preload <UnitSystem
name>. Tim already said that this can be added. Once loaded, it becomes what you
called CurrentUnitSystem (but without the name). The <UnitSystem name> can be
either static or dynamic, depending on whether the three 'set' commands are
implemented or not in that domain. The SI system can be restored by simply
issuing another ')set unitsystem SI' command. In fact, another way to load any
unitsystem is simply to say ')library <UnitSystem name>', just like loading any
other library, so we don't even need to add the ')set unitsystem' command,
although the ')set unitsystem' command perhaps can avoid some package calls when
the 'set' commands are used.

A "dynamic" unit system domain becomes static if the user does not use any of
the 'set' commands from the domain or if they are not implemented in the domain.

> Working in a Static UnitSystem no set commands are
> either possible or necessary (and thus shouldn't work) and in a Dynamic
> UnitSystem (of which there will normally be only one - the working one)
> the Static UnitSystems provide the information to use in the Dynamic
> one?

Right, see previous comments. A StaticUnitSystem domain in your sense is nothing
but a table for pairing dimensions and units. So this is included in
UnitConversion domain (basically a database). It would be just a difference in

> Since
> Static UnitSystems wouldn't be changable in a normal session anyway (at
> least without editing the source and reloading, which hopefully would
> also mandate a rebuild of the hash tree) it would be a one time expense
> and would enable considerable user convenience at many levels.  

Of course, whatever has been compiled is static, but since we are to provide
(again, as you insist -- a good thing) dynamic changes to a loaded unit system,
there is really no need to "automatically" modify library code to change a
static unit system. I remember you were oppose to this when I was defending the
old proposal that you can compile as many UnitSystem domains as you like,
modifying standard ones as little or as much as you like. Since this automation
to modify library code to generate a new compilable spad source is difficult
(remind you that this should be a documented pamphlet file, requiring expertise
in using automatic editors), and may contribute to a proliferation of domains
only for personal use, I have moved to the dynamic model to satisfy user needs.
A user can easily set up the axiom.input file to load a bunch of interpreter
code, which includes setDimUnit, setUnit, setUnitAll lines before proceeding.
The user is in total control and no system level work (like automatic editing
spad files) is required.

Requiring rebuilding the hash tree is not a good idea because a domain is
supposedly stable once built. Plus, if someone adds a new UnitSystem domain, who
would be responsible to rebuild the single hash tree? If the new domain
introduces new dimensions and units, it should create a corresponding
UnitConversion domain (hash tree) and leave the standard hash table alone.

--------------- Name space issues

> (I'm still
> plotting to allow the user to gobble up all the unit names in the
> default namespace at their option, and that will DEFINITELY need
> interpreter work.

As you know, I am strongly against "gobbling up all the unit names in the
default namespace' even if it is 'at their option'.  If you are seriously
thinking about student use, you know the average students will exercise their
options without knowing or understanding what they are doing. There is no way to
consistently reserve SOME unit names in namespace, and not others. Any code to
implement this will have to know the reserved names a priori and that means ALL
the abbreviations in SI units at a minimum. You would have created a nightmare
in using the interpreter by requiring users to avoid any SI unit abbreviations
as user variables. No computer language ever has that many reserved words. Note:
Axiom function names are NOT reserved, but constructor (which may be category,
domain or package) names and their abbreviations are.

Modifying the interpreter because of a specific category or its domains is a bad
idea. Any modifications should be general purpose or fixing bugs.
> > As for tools to do the dynamic modification from standard unit
> > systems like SI, here are several changes to the previous setup
> > that will facilitate this and improve the organization of the
> > domains as well.
> Did you intend to use this setup for ALL UnitSystems or just what I've
> termed Dynamic UnitSystems?  (Sorry if I should have caught this.)

Yes. I believe this would make it easy for UnitSystem domains to inherit the
default implementations by a few simple modifications. (In the end, only the
actual coding will tell if this is possible).  I do not distinguish between
static and dynamic. Every unitsystem domain is dynamic. But if you like, you can
have them separately specified. Then a StaticUnitSystem category would not have
the three 'set' functions exported and a DynamicUnitSystem category is a
StaticUnitSystem with the three 'set' functions (and perhaps others). The
problem with this dual approach is that if after computing with a
StaticUnitSystem domain, a user suddenly decides to change the unit of one of
the dimensions, he would have to either redo the computations, or to coerce
everything from the static domain to a CORRESPONDING dynamic domain. There is no
enforcable mechanism to guarantee that every static domain has a corresponding
dynamic domain, and if this latter guarantee holds, then we are duplicating all
unit systems for something not that useful. Most users will want to have more
flexibility. I think even for student use, if they want to experiment with
changing units (at run time), why should that be forbidden? (for that matter,
Axiom being open sourced, why should ANYTHING be forbidden?)

> In the
> SetUnits usage it doesn't even need to use up toplevel namespace, and
> if a user DID want to populate the toplevel namespace it would be a big
> speedup for the interperter to be able to hash a symbol to check if it
> is a unit.

My proposal uses up NO user namespace for the dimensions or units. It uses only
strings as fake domain names. Strings are data items, not a name. The more
familiar one is the "failed" (a "domain"!) in Union(..., "failed"). This is the
built-in magic implementation of Union. A lookup requires only the case statment
and presumably implemented efficiently already.

There is perhaps one way to use variables (instead of strings) for dimensions
and units, but they will be local to the domain (using domain namespace, rather
than user namespace) and they will not be assigned any value. The advantage over
strings is that they can be used to perform arithmetic operations of
multiplication and division as symbols. Then general conversion factors can be
computed by setting up a small number of conversion rules and by solving an

Default relationship (tables) for conversion tables (which include both
dimensions and units) and the dependencies like state-vectors, can use hash

---------- Implementation Issue: Simplification of dimensions

C Y wrote:

> > > I think this is a weak spot in my understanding of dimensionality, so I
> > > apologize if I'm being dense here.  If we take C=%pi*d where C is a
> > > circumference, %pi is %pi, and d is diameter, and look at the
> > > dimensions, we have:
> > >
> > >           degree
> > > Length =  ------ Length
> > >           radian
> > >
> > > Casually, this doesn't look at all balanced.

William Sit wrote:

> > Of course not. But that is exactly the point: a dimensionless constant
> > takes on different dimensions in different conversions or equations. So
> > even thought these have the same VALUE pi, the pi in C = pi*d and the pi in
> > 180 deg = pi radians are different because their (hidden) dimensions are
> > different. In each equation, only their values are the same.

C Y recently wrote:

> OK - so how to we represent this in a  CAS?  Or more specifically, what about
> the fact that a dimensionless constant has dimension that cancels is useful
> for us to display, and how do we go about it?

We can do this:

  piInEqn1:= setDimUnit("Length/Length", "m/m", %pi)


  piInEqn1:= setDimUnit("1", "1", %pi)


  piInEqn2:= setDimUnit("Degree/Radian", "deg/rad", %pi)

Perhaps we can add a field to Rep that gives the reduced dimension as well? or
provide a function

  reduce: Dimension->Dimension

(which in any case, will be useful and necessary).
> > > Does it mean that when we
> > > define the dimensionality of the variable C we need to define it as:
> > >
> > >  degree
> > >  ------ Length
> > >  radian
> > >
> > > rather than just Length?
> >
> > No, dimension of C is length and is not dependent on any equation it is in.
> > This is a major difference between physical quantities and mathematical
> > constants.
> So we are going to have to distinguish between them somehow?  What do we want
> there?

See comments to previous question. The function reduce("Length/Length") will
return "1" so that the variable C in C:= piInEqn1 * d will give C the dimension
of "Length".
> > Perhaps we should start using the term "dimension" to mean the
> > one used in the definition, which may involve derived dimensions, and the
> > term "reduced dimension" to mean a simplified form in terms of the basic
> > dimensions. Then we can say the reduced dimensions of pi in both equations
> > are the same, namely 1 (or dimensionless), but the dimensions are
> > different. This terminology would work to say work and moment have the same
> > reduced dimensions, but their dimensions are different (when vectors are
> > used to indicate the direction of the distance with respect to the forces).
> > How vectors may be expressed in dimensions is another thing to study.
> YES!  This is an excellent suggestion, and might provide a way to address an
> issue that has been bothering me:
> Let's say we work with both work and moment, in two different equations, and
> both calculations would simplify down to length if we cancel out units.
> Presumably those lengths have the same dimension, but they sprang from two
> different equations that would not be the same dimensionally if I were to use
> proper derived dimension simplification rules, despite their both winding up
> with a length falling out.  I think being able to say work and moment have
> the same reduced dimensions would allow us to perform calculations, simply
> noting that the length is a reduced length by virtue of being calculated from
> a quantity involving ambiguous substitution.
> Hopefully that was clear enough to express my concerns.  I don't know if they
> would crop up or not in the "real world" - if this is too confusing I can try
> and construct an example (gulp).

Yes, unless given other examples, I think this is a way to get out of the
dilemma. Of course, the strong typing of Axiom already drove developers nuts,
and I'm afraid, surely, the strict setup to dimensions and units may likely do
so to scientists or economists. This is the price to pay for insisting on formal

> > >Could unit and dimension cancelation be handled
> > >on a per dimension basis?

> > May be, or may be not. It depends on the physical meanings of the
> > variables. If I have price at $5/m multiplied by 7 m, I should get $35. If
> > I have 8 N divided by 2 m^2 for pressure, and N has dimension kg-m/s^2, is
> > it ok to cancel one of the m? So a single rule of Length (m) is not
> > applicable to all cases.
> This will need to be handled, somehow.  Are there any good references that
> contain the applicable rules for us to implement?

I don't know, and I have not tried hard enough to google. This must be quite
thoroughly studied already. There is a 1941 paper on "theory of dimensions" in
Proc. Phys. Soc. by G. Brown, Vol 53, p. 418.

Don't know if it is useful. It reduces all dimensions to Length and Time, which
are related, said the author, via the speed of light. Does any one know more
about this article?

There is also a theory of dimensions for economic quantities, published in 1871!

and historically, it seems Fourier introduced the theory of dimensions in 1822
(Théorie de Chaleur, Article 160). The article below is worth reading:

Fourier's notion of homogeneity should strike a resonance.

Whether any such references will help us develop the rules to simplify
dimensions, I don't know. From what we have discussed, it seems any rule will
need some expert knowledge (in the example I gave, the expert knowledge is
simply what pressure is). So I believe the best solution may be to "leave it to
the users", and let them create their own names and simplification rules. This
means that in a UnitSystem domain, there ought to be facilities to handle rules
of simplifications, where some common defaults can be implemented. Axiom has a
RewriteRule domain that can help. RewriteRule can also be used efficiently to
perform conversion. (I once wrote a UnitConversion.nb in Mathematica for a
course using this idea: all conversion factors between the two units for the
same dimension is then a simple Solve[unit1 = x unit2, x])

> > Actually, you scenarios are not narrow but general and right! There should
> > be no difference between units as used by students and units as used by
> > researchers. The idea of units is not limited to even SI. Currency
> > conversions are conversions in monetary units. But we should be able to use
> > Axiom's unit system for grocery as well (Back to my unfinished idea on
> > different Dimension domains)! Dimension=Union("Orange", "120z-Coke", ...)
> > is as useful as Dimension=Union("Mass", "Length", ...). (Yes, a supermarket
> > manager using  Axiom, that'll be the day: not so far-fetched if you think of
> > the operation  research problems involved).
> Heh - neat :-).  But it does raise some awkward questions, which came up
> briefly earlier but escaped my notice:
> You mentioned $ interacting with meters, and in a previous email kilobits and
> kilobytes were also mentioned.  Unfortunately, neither money nor bits of
> information are covered by any combination of SI units I am aware of.  So
> perhaps our top level category should be not simply Dimensions but
> PhysicalDimensions, and we could perhaps implement some other Categories for
> Dimensions not covered by SI (like money and bits, both of which are Basic
> Units as far as I can tell).  Money might be defined in terms of other things
> in some sense, but that definition is as complex as society itself and ever
> changing.  Fascinating issues, but perhaps those should wait for later.
> Indeed, does it even make sense to include a concept like money in a system
> intending to stick to strict mathematics as much as possible?  I suppose yes
> since we can think of practical uses, but thinking about it is making my head
> hurt ;-).

"Now, you're thinking!" :-)

In my case, thinking about these things make me stare at the screen and then
fall asleep! But you got a point here, building unit systems should include, or
at least allow future inclusion, of systems outside of the usual scientific
sphere. So having an WallStreetDimensions, SupermarketDimensions,
FontsMetricDimensions systems would be fun but we don't have to implement them
right away.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]