[Top][All Lists]

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

Re: [Axiom-developer] Unit package question - Reply to 1st half

From: William Sit
Subject: Re: [Axiom-developer] Unit package question - Reply to 1st half
Date: Thu, 01 Sep 2005 07:33:06 -0400

Dear C Y:

This long-winded email started more than a week ago and school started got in
the way. In addition, computer problems, mainly: network and
crashing OS without saving :-( , but also some hardware ones. 

I am glad to know that you are working on this project. I meant to form the
ideas below more thoroughly before posting them but I see you have already
started real work. So I hope these new suggestions, incomplete as they may be,
perhaps should be made known to you and we can discuss this and if I got time to
revise them (probably during labor day weekend), I'll do so. 

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 have added comments on the draft below using [comments: ...].


I think we are in general agreement regarding how to implement the UnitSystem
domains. Your provoking questions led me to propose modifications to the
original scheme (and even that, is far from a final design as I have been
changing them constantly as I write). The new scheme hopefully will solve some
of the design problems we discussed. I hope before long the new proposal will
approach a practical one. After waiting a short period of further discussions, a
summary of the final design should be posted at MathAction for others to comment

C Y wrote:
> --- William Sit <address@hidden> wrote:
> > Flexibility and generality may
> > complicate usage as well as simplify usage. We have to balance
> > the them.
> Agreed.  What about this - create such a domain as the "default"
> domain, "use" SI units for defaults, and provide tools for the user to
> make changes?  The changes would occur within the Default "working"
> unit domain, assuming any were made - otherwise, it would look just
> like the SI domain.  If one wanted to work in an environment which flat
> out disallowed such setting changes, )set UnitSystem SI (or whatever
> system desired) would take the user to the system defined SI domain
> instead of the Default environment.  Does this map to what Axiom can
> do?

I actually prefer your use of ")set UnitSystem ..." to ")set unit
...". But note ")set UnitSystem" IS setting the session default for the
user. 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 'unitMass' etc (to be grouped into a new function
'setDim', see below) are called.  MYUnitSystem can be SI, CGS,
or some modified version of the standard SI (but once modified, it should be
called something else). Of course, this needs some code or setup to modify the
interpreter, but it can be done (Tim Daly or Bill Page would no doubt know how
and can assist you when that time comes). Most likely, it is a matter of adding
one or two lines to a database.

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. 

[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

  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)

[Comments: The ideas from now on are more or less well formed. However, I have
not finished rearranging these in a more logical sequence. So read it a few
times! I might have made some obsolete claims as I reorganized my thoughts
without revising the claims.]

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) -> %
    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?

Note that the way Dimension and Unit are defined (as Union("Mass", "Length",
...) and Union("slug", "ft", ...)) is very close to making each dimension and
unit a domain of its own, except that here each domain consists of just its name
(string). You may also consult the way BasicOperators and CommonOperators are
designed, but at least for the moment, the simpler setup probably suffices.

SECOND: 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. 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.

Thus, we can replace unitLength(len) by setDim("Length", len) when the default
unit is used, where::

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

and 'unit(dim)' is a look-up function using the state-vector of the present unit

SECOND: Extend the Rep in these domains to include units and conversion factors.
   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).

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). 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")).

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.

(By the way, you can find lots of conversion factors on line: for example
Just learn a bit more! Let's just stay with English for this discussion.)

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") 

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 so that we can allow
will change the state-vector to reflect all units that involve a "Length"
dimension as component

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

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).

Now if the user later runs:
(4)    setUnitLength("cm")

What does this involve? You are now in a run-time environment, you cannot change
the code for unitLength 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 unitLength to depend on a state vector for the domain: this state vector
stores one unit for each dimension, and is updated by the setUnitLength and
similar commands. The unitLength (and similar commands) can check this state
vector before generating the Rep. 

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 := unitArea(ulen, ulen)

the routine * or unitArea can check the units of its arguments and update them
before computation. However, if the user simply types


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

I made the factor:Union(Float, Symbol) to allow a delay of the computation when
symbolic computation is more prevalent and also when S does not have
RetractableTo(Float).  This still requires S to have RetractableTo(Symbol).  The
exact meaning of factor needs some discussion: perhaps there should be two
factors! One relative to the current system (to provide a relative factor to
convert within this system when users changes a unit, and one relative to SI (to
provide an absolute factor to convert between systems).

> > > But it should be doable, readily, IMHO.  That's what computers
> > > are for - to handle the grunt work associated with such
> > > decisions.
> >
> > As long as you are willing to do the programming :-)
> Hehe - fair enough!  In fact, I think such things can be built as a
> layer on top of your system, which is undoubtedly the most robust way
> to handle things.  So I vote for doing it your way, and then if I
> really want some of what I say I want it can be implimented on top of
> the core system.
> > > There is also the case where you want to know what
> > > quantity/dimension an expression is.
> >
> > Reverse dimensional analysis, is useful for providing the user
> > with possibly different interpretation of the dimension of an
> > expression. Checking dimensional correctness is a different,
> > though related, issue.
> Ah :-). Thanks for helping clarify all of this - it's definitely
> broadened my understanding of units/dimensions/etc. :-).
> > > > Don't mix unit systems! Convert first before you start the
> > > > computations, and convert back if you really have to.
> >
> > > But that's just it - part of the reason for implementing a Unit
> > > system in a CAS in the first place is to get it to do all the
> > > converting and other annoyingly boring and error prone tasks for
> > >  you - both for input and output.
> >
> > Sure, but that does not mean one has to do it for all possible
> > conversions, only the most useful ones should be provided, with
> > functionality that allows, though not as convenient, the very
> > special user to change units.
> OK, point.  As a possible future extension to this environment though,
> I may try and code up a way to do as many such conversions (arbitrary
> unit -> current environment) as possible, since usually the unit that
> causes the biggest problem in a problem is the obscure uncommon one you
> have to go dig up the conversion factor for.  This argues for as broad
> a knowledge of units in Axiom as possible, although I admit this should
> probably be done over time and not as part of the initial effort.
> > Ignoring it in this example would mean the equation is not
> > dimensionally balanced, and worse, some may think that
> > degree = radian!
> 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. 

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.

> 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.
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.

> > OK, let me try to explain again.  A quantity is dimensionless
> > means its dimension can be reduced to 1. But sometimes, it is
> > more meaningful (physically or mathematically) to view these as a
> > quotient (this is like, but not totally, we sometimes rewrite 1 as
> > 2/2 to add fractions). Even SI recognizes this in stating that the
> > unit of a phase angle is m. m^(-1) = 1 because this IS the
> > definition (arc length spanned by the angle, divided by the radius).
> > Just because the dimensions cancel out (making it dimensionless)
> > does not mean the dimension is not there.
> OK, I think I'm getting it.  So what we need to do is examine the cases
> where it is actually useful to retain this information, and see what
> behaviors are rigorous/needed/useful.  Definitely in some cases we need
> to canel dimensions out - we don't want something described in (say)
> kg/s multiplied by seconds to wind up as kg*s/s, but if there are cases
> where m/m is useful to preserve there would seem to be a problem with
> having a general rule.  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.
> > Definitely. We can have a nanosytem domain, and other domains of
> > UnitSystem(S) as experts need them. That is the beauty of Axiom's
> > categorical approach: unifying domains with a common set of API.
> OK, cool.  So we might actually develop a situation where, for
> different kinds of work, we have different standard domains defined
> (say, as an example, if someone is working with radio telescope data
> and equations, they can do )set UnitSystem RadioTelescope having
> previously defined the desired unit conventions for such work.  I
> guess, thinking about it, my scenarios for unit use were too narrowly
> focused on the case of students, where arbitrary units will appear for
> any reason and no reason (sometimes just to make them look them up and
> do the conversion, which always annoyed me as an extra and unnecessary
> potential source of numerical errors but in retrospect was probably
> good training.)  For "real world" use, that case is not terribly
> useful, and Axiom is definitely not focused on introductory student
> problems :-).
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).


reply via email to

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