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: ...]. William -- 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 on. C Y wrote: > > --- William Sit <[EMAIL PROTECTED]> 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 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) [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 system. 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: http://medical-dictionary.thefreedictionary.com/foot-pound-second+system 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 http://www.onlineconversion.com/ 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 well. 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 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). 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). William _______________________________________________ Axiom-developer mailing list Axiom-developer@nongnu.org http://lists.nongnu.org/mailman/listinfo/axiom-developer