Group Abstract Group Abstract

Message Boards Message Boards

Solve and NSolve not working well with Quantity and Units?

Posted 5 years ago

I am trying to update 100k lines of Mathematica I wrote 15-20 years ago in Version 4. I am struggling with getting Quantity, Solve/NSolve and Integrate to correctly deal with units. Solve/NSolve always return the correct numerical values, but the "Units" are quite often lost. I can not figure out why. But it seems related to the Integrate function and places where variable definitions first appear in the code as arguments to the Quantity function. The Plus function may also be failing. Also of note, is how "unit-less" variable name definitions seem the direct cause of the errors produced by the Integrate function. And perhaps at the root of my programming dilemma is the way multiplying a scalar Quantity by zero wrongly preserves Units.

In V4:

   200 kg times 0 equals 0

In V12

   200 kg times 0 equals 0 kg

This bug/feature, breaks simple vector calculus computations in countless ways. See the detailed examples given far below in this thread, where V12's forcing of units on values of zero magnitude causes simple exercises in Newtonian Mechanics to "blow up".

Any help would be appreciated. See attached notebook for examples of this behavior. JPEG attached for easy demonstration of typesetting. Code is in the attached notebook.

\!\(\*OverscriptBox[\(a\), \(\[RightVector]\)]\) = {Quantity[0, (
    "Meters")/("Seconds")^2], Quantity[0, ("Meters")/("Seconds")^2]};

Solve not returning Units

NSolve working almost correctly

POSTED BY: Francis Bush
44 Replies

I have posted a new thread summarizing issues with Quantity that have been raised here. Further responses should go to that thread. This one has a considerable noise-to-signal fraction and we need to close it. We ask that responses in the new thread be kept to the point. The issues in question involve handling of units. I remark that version 4 had no built-in handling of units. Comparisons to version 4 are thus not regarded as on point.

POSTED BY: Daniel Lichtblau
POSTED BY: Francis Bush
POSTED BY: Francis Bush

Hello Dan,

In[759]:= D[Quantity[5, "Meters"], Quantity[t, "Seconds"]]

Out[759]= Quantity[0, 1/("Seconds")]

attaching a unit to t is obviously the thing to do. But in my opinion the outcome should read

Out[759]= Quantity[0, "Meters"/"Seconds"]
POSTED BY: Hans Dolhaine
POSTED BY: Daniel Lichtblau
POSTED BY: Francis Bush
POSTED BY: Francis Bush

Francis, I don't think that my solutions to your examples contain 'pages of extra code' over your presentations in your earlier posting. To me they seem about the same length or maybe even shorter. And they work. In my opinion it's not good practice to teach students to mix input values and units into their equations. If one looks into any advanced physics book or paper they just don't do it. If one plans to run them through algebraic derivations the units act like a pack of barking dogs. Units are not necessary there and they contribute nothing there.

(You talk about Mathematica as being code. Mathematica is NOT a programming language. It is a new active and dynamic medium for developing and publishing ideas that have a mathematical content. We have to learn how to use it - even the developers. If you want to be a programmer use MatLab, if you want to be a scientist/intellectual use Mathematica.)

If you are truly interested in advancing STEM education then I can show you how you can make a significant contribution if you wish to contact me by email through my profile page.

Wow, I bet your code was running on the simulators in Fort Worth.

I will never forget watching the Airforce brass show up informally on weekends, dive into a couple, interlinked, full cockpit, 360 degree simulators and dogfight away on a Saturday afternoon. In the days of "Pong" this represented the best, multi-million dollar video game on the planet!

POSTED BY: Francis Bush

On an unrelated note, in the early 80's ('81 to be exact) I worked on a Jovial compiler project. It was a subcontract from Singer I believe, and intended for use in simulators for training pilots. I have since seen one or two such simulators in a museum (maybe I also belong in a museum...)

POSTED BY: Daniel Lichtblau
POSTED BY: Francis Bush
POSTED BY: Hans Dolhaine

I appreciate everyone's time on this issue, so dear to my heart!

So, please, show me the errors of my ways, or at least the errors in my syntax.

Please consider this calculation again, that requires Integrate.

r0Vec = {Quantity[0, "Meters"], Quantity[0, "Meters"]};
r1Vec = {Quantity[1, "Meters"], Quantity[0, "Meters"]};
v0Vec = AngleVector[{Quantity[2.8, ("Meters")/("Seconds")], 0 Degree}];
v1Vec = AngleVector[{Quantity[0, ("Meters")/("Seconds")], 0 Degree}];
aVec = {ax, ay}; 
m = Quantity[0.45, "Kilograms"];
g = Quantity[9.8, ("Meters")/("Seconds")^2];
Fw = m*g;
FwVec = AngleVector[{Fw, 270 Degree}];                                             
FkVec = AngleVector[{Fk, 180 Degree}];
FnVec = AngleVector[{Fw, 90 Degree}];                                              
RVec = FkVec + FnVec + FwVec;                 

This code will explode because of the way I have defined aVec. This much we can agree on. It will cause Integrate and Plus to return Quantity based errors regarding mismatched units.

aVec = {ax, ay};

So, the question now is:

How do I correct this definition?

What is the proper syntax, if you will?

As mentioned above, we could change the definition of aVec to the following:

aVec = {Quantity[ax, ("Meters")/("Seconds")^2], 
   Quantity[ay, ("Meters")/("Seconds")^2]};

And if we do so, and evaluate the following cell:

r0Vec = {Quantity[0, "Meters"], Quantity[0, "Meters"]};
r1Vec = {Quantity[1, "Meters"], Quantity[0, "Meters"]};
v0Vec = AngleVector[{Quantity[2.8, ("Meters")/("Seconds")], 0 Degree}];
v1Vec = AngleVector[{Quantity[0, ("Meters")/("Seconds")], 0 Degree}];
(*aVec={ax,ay};*) 
aVec = {Quantity[ax, ("Meters")/("Seconds")^2], 
   Quantity[ay, ("Meters")/("Seconds")^2]};
m = Quantity[0.45, "Kilograms"];
g = Quantity[9.8, ("Meters")/("Seconds")^2];
Fw = m*g;
FwVec = AngleVector[{Fw, 270 Degree}];                                             
FkVec = AngleVector[{Fk, 180 Degree}];
FnVec = AngleVector[{Fw, 90 Degree}];                                              
RVec = FkVec + FnVec + FwVec; 
NSolve[{RVec == m*aVec, 
  r1Vec == r0Vec + Integrate[v0Vec, Quantity[t, "Seconds"]] + 
    Integrate[Integrate[aVec, Quantity[t, "Seconds"]], 
     Quantity[t, "Seconds"]], 
  v1Vec == v0Vec + Integrate[aVec, Quantity[t, "Seconds"]]}, 
  {t, ax, ay, Fk}]                                  

We get, in V12, the following output:

{{t -> 0.714286, ax -> -3.92, ay -> 0., 
  Fk -> Quantity[1.764, "Newtons"]}}

Which is perfectly correct, EXCEPT there are no units for t and ax.

Why is this?

Is this the wrong syntax for the definition of aVec?

Or is this simply the best one can hope for in V12?

Thanks, - Joe

POSTED BY: Francis Bush
POSTED BY: Daniel Lichtblau
POSTED BY: Francis Bush
POSTED BY: Daniel Lichtblau
POSTED BY: Francis Bush
POSTED BY: Neil Singer
POSTED BY: Francis Bush

This is going in circles.

I have just looked at the notebooks and all the images in the posts above. Other than an example from Neil Singer, I have not seen anything that strikes me as amiss. I have seen reams of confusing code, possibly (likely, in my view) containing some degree of user error. Often in that situation code will not perform as the author expects. In such cases it is best to isolate a small number of clear examples that show the pathology. Should you do so, please post them and I'll have a look.

Earlier today I was shown a small set of examples from our Technical Services group. It may have originated with you. It contained among other things, this Integrate.

Integrate[v, Quantity[3,"Seconds"]]

I am not able to make sense of this. I will look later when time permits, but my current thinking is that it is a case of garbage-in, garbage-out that Integrate simply fails to catch. The best documentation I could find is in the Documentation Center under tutorial/SymbolicCalculationsWithUnits. It indicated that an appropriate method for obtaining what I believe is the desired integration would be this.

In[433]:= InputForm[
 iiDef = Integrate[v, {t, Quantity[0, "Seconds"], Quantity[3, "Seconds"]}]]

Out[433]//InputForm=v*Quantity[3, "Seconds"]

This can be used inside Solve without causing confusion as to units.

As a general remark, it is considered bad etiquette to claim there is a bug before it has been confirmed as such by others (whether Wolfram employees or not). Insisting these examples show serious bugs is the sort of thing that would get a question closed on Mathematica.StackExchange.com, and sometimes on Wolfram Community as well. Again, if you have a clear example of a bug, show it. It is not reasonable to expect others to go over reams of code trying to figure out what you mean.

POSTED BY: Daniel Lichtblau

All code examples are in the attached notebooks. The examples are all "three cells" in length. Practically "one-liners". I can not demonstrate these issues with less code. Because I using "built in" Mathematica typesetting, like the integral sign, there is now way to show such code on this website, short of an attached notebook.

POSTED BY: Francis Bush

The integral that I see from several messages back appears to work just fine. The message arose from an attempt to add quantities of nonconforming units.

You are making this quite difficult to even follow, let alone diagnose. I will suggest that you provide full code in the post, avoiding Subscript unless that is absolutely needed to reproduce the problematic behavior. It should be copy-pastable. I for one am not going to rekey from images because that is both laborious and error-prone.

POSTED BY: Daniel Lichtblau

It appears the "unit-less" definitions of variables, like the components of the acceleration vector (shown above and below) are causing the bulk of the problems. As the following example shows, the same unit-less definitions work fine if the Integrate function is not involved. Hence, the Quantity BUG seems related to the Integrate function.

Working example

POSTED BY: Francis Bush

No, David. I do not have a working copy of V4. Sure wish I did ;-) I know the Units package to which you refer. Many such packages are no longer "optional" and are now just built into the kernel, like it or not. The package architecture was a good one I believe. I wish Quantity was in some package, that I could delete from my laptop and return to beautiful V4 functionality. ;-) Pero, por desgracia, V4 es un idioma muerto ;-) Tenga buen dia, - Joe

POSTED BY: Francis Bush

In a last ditch effort to illustrate the shortcomings in V12 and Quantity function, I have attached a notebook below that codes a solution to a single problem in Newtonian Mechanics.

I show three implementations, two in V12 and one in V4.

Only the V4 version works in a complete and correct sense. Interestingly, the V4 version contains 1/2 the "keystrokes" to code as the V12 version. Clearly was V4 superior to V12 in this regard.

I find the Quantity function in V12 prevents a complete solution.

This seems quite ironic, since the intention of the Quantity function was to add "units" to Mathematica, but the actual implementation of the Quantity function makes it impossible to correctly use units in V12 in a complete, accurate and easy way. Instead, it merely doubles the keystrokes necessary to express a problem, up the chances of syntax errors, and prevents Solve/NSolve from correctly outputting units to some variables.

JPEGS below are shown for typesetting and additional commentary. All code is contained in the notebook, even the V4 (which of course can not be "re-evalutated" but is included, with the original V4 output, in CodeText cells).

Part 1 Part 2 Part 3 Part 4

Attachments:
POSTED BY: Francis Bush

Hi Neil, No I did attach the Wolfram Tech Support notebook called Units. It can be found in the first attachment section of this discussion. Start at the top and scroll down. In the notebook, you can see that Wolfram Tech Support was unable to produce the correct units via Solve and NSolve. You will also not how ridiculously easy such a task was in V4. See JPEGS above! How I miss V4 ;-) Regards, - Joe

POSTED BY: Francis Bush

Again, sorry for the JPEG. It is just that V4 is a "dead language" and this is my only readable options for showing how easy working with "home-rolled" units was in V4. I could easily do things in V4 that are next to impossible in V12. How could that be? Would it not be better to have Quantity as a "Package" that could be used or ignored, at the discretion of the programmer? Just a thought!

That is, would it not have been better for Wolfram to get a foundational concept like Units working completely, and flawlessly, before adding to that weakness new objects, entities, alphas, betas and bags of potatoes? ;-)

enter image description here

enter image description here

POSTED BY: Francis Bush
POSTED BY: Neil Singer

I understand. Thanks for your time and input.

My example notebook contained 5 simple examples, clearly sub-sectioned and each example represents a simple "freshman" Newtonian Physics problem, expressed in "vector calculus", should you find the time to explore this issue.

I heard back from Wolfram Tech Support and sadly, they could not resolve these issues with Quantity and related functions. The "Units.nb" is from Wolfram Tech Support. See attached. It does not improve on the issue and seems to confirm my complaint that Mathematica is "broken" or "limited" in this regard. Seems like a huge step backward.

Regarding a working copy of V4, no, unfortunately my laptop with a working copy of V4 died decades ago. I do have the original V4 code and the original V4 output. 100k plus lines of code that worked fine in V4 but fails miserably in V12.

The sad thing is, what was a piece of cake and pleasure in V4 is now a pain in the backside, made worse by the fact that there is no way to avoid these issues with Quantity except perform complete "unit-less" calculations.

Should there not be a "global switch" that tells the kernel to ignore anything related to Quantity, and permit "home rolled" V4 style units?

Just a thought!

POSTED BY: Francis Bush

The problem is that you are mixing scalar and unit variables. In your example, ax is a scalar but you are integrating over a Quantity[]. For example, something like this works:

bbx :=  Quantity[bxscalar, "Meters"/"Seconds"^2];
bby :=  Quantity[byscalar, "Meters"/"Seconds"^2];

bvector = {bbx, bby};
Solve[bbx ==  
  Quantity[33, "Meters"/"Seconds"]/Quantity[12, "Seconds"] , bbx]

Out[215]= {{Quantity[bxscalar, ("Meters")/("Seconds")^2] -> 
   Quantity[11/4, ("Meters")/("Seconds")^2]}}

In[216]:= Subscript[
\!\(\*OverscriptBox[\(v\), \(\[RightVector]\)]\), 0] + 
 Integrate[bvector, Quantity[t, "Seconds"]]

Out[216]= {Quantity[(2.8  + bxscalar t), ("Meters")/("Seconds")], 
 Quantity[(0.  + byscalar t), ("Meters")/("Seconds")]}

You can probably make a wrapper function to make this easier -- I'll think about it a bit.

Regards,

Neil

POSTED BY: Neil Singer

Hard to say with an image instead of the actual code, but it looks like you redefined a to be a vector comprised of two scalar components, because the subscripted elements Subscript[a,x] and Subscript[a,y] are not themselves quantities with associated units. So that would lead to a quantity incompatibility.

On a different note, you did provide a notebook showing problematic computations. But it is huge and has nothing remotely resembling a minimal example of the shortcoming(s). It is simply not something I would be prepared to wade through. I'll take a look at the example provided by @Neil Singer when time permits.

POSTED BY: Daniel Lichtblau

Do you still have Version 4 on your computer? If so you might be able to use the old MiscellaneousUnits and MiscellaneousPhysicalConstants. I thought I had saved a copy of them at the time WRI switched over but I can't find them now. I do have an extension Units2` done by Ted Ersek that substitutes for the old Units but it still requires PhysicalConstants.

The old system also allowed one to install their own units, which I don't think can be done now.

Maybe you could get those packages from Wolfram.

I don't think there are any real benefits from dragging Units through all the algebraic routines. It doesn't guarantee that the units are correct because it's possibly to use wrong units consistently. If Mathematica is going to let you use units everywhere then you are right that it should be better implemented.

As I believe the code and discussions have easily shown, Mathematica V12 and the unavoidable forced incorporation of the Quantity function has "broken" Mathematica in an important way. THIS IS A BUG!

From what I can determine, there is NO WAY to get Mathematica V12 to work flawlessly with Units from the built-in Quantity function. The best results I have been able to obtain have correct numerical values but Units are lost by functions such as Solve and NSolve. This would seem to be a MAJOR BUG in V12.

Also, curiously, for a guy like me who as been out of the Wolfram universe for decades, no one on sites like this one, or StackExchange, or even Wolfram Tech Support know the answer.

Instead, the experts in the field all (1) avoid using units and Quantity at all cost, or (2) add 1000's of lines of "rewrite rules" to clean up the faulty V12 output, or (3) try unpredictable overloading of the Quantity function in a last act of desperation.

No one I have discussed this with seem to know how to use Quantity and obtain valid results.

Lastly, no where in the Wolfram docs can I find anything but the most trivial example of Units and Quantity. In simple cases it can work. In more complex cases, from my money, Quantity simply does not work.

With the addition of the Quantity functions and all the modifications to prevously existing functions, like Plus or Integrate or Solve or NSolve, (all new or "updated" in V9, I believe), Mathematica now limps down the road like a car with a flat tire.

Very sad ;-)

POSTED BY: Francis Bush

Thanks Neil. Yes, only variables assigned the output of a Quantity function have the quantity head. And you are also correct that redefining some variables can make this work (quite often). But the approach only works in simple cases. And F2, in the example above, is never assigned a Quantity head, and yet, Solve and NSolve can correctly deduce the units. Why?

For example, here are two cases where the change you suggested produces the correct output from Solve.

Example of working definitions

Also, this works:

enter image description here

However, this syntactical approach seems to still fail in the following example. For example, my original approach works (except for units output by Solve).

enter image description here

But if we attempt the same sort of thing you are suggesting here, then the total lack of Quantity definitions causes the simple functions like Integrate and Plus to "choke".

So, for this kind of calculation I am still at a loss for the correct approach.

enter image description here

POSTED BY: Francis Bush

This is not a bug. Ay is actually unitless. When you define a value as Quantity[Ay, "Unit"]. Ay is a scalar BUT the whole expression is a Quantity with units. If you solve for Ay, its always scalar. If on the other hand, you define Ay = Quantity[AyScalar,"Unit"] then Ay is a Quantity object with units and if you solve for Ay, it will have the right units.

I your example, this will work in your notebook:

Subscript[
\!\(\*OverscriptBox[\(a\), \(\[RightVector]\)]\), 
  1] = {ax, Quantity[0, ("Meters")/("Seconds")^2]};
Subscript[
\!\(\*OverscriptBox[\(a\), \(\[RightVector]\)]\), 
  2] = {Quantity[0, ("Meters")/("Seconds")^2], -ax};
POSTED BY: Neil Singer
POSTED BY: Francis Bush

Using the notation package and symbolizing expressions is generally fine but can have pattern matching issues if that is not taken into account in other code. I would suggest trying some simple examples with and without symbolized notation to see if that is the source of the problem. I could imagine (with no evidence whatsoever) that the Solve pattern matching with units could have a bug in treating those symbols. If so, tech support is very responsive and it might get it fixed fairly quickly if you can isolate the behavior.

POSTED BY: Neil Singer

It is my experience subscripts DO NOT work correctly in variable names UNLESS "Symbolized". See the attached notebook to see how this is done. You will note that my subscripted symbols are all interpreted correcly (because I used Symbolize). They cause no errors in my example notebook. It is only the UNITS that get screwed up by Solve and NSolve

Attachments:
POSTED BY: Francis Bush
Attachments:
POSTED BY: Francis Bush
POSTED BY: Neil Singer
POSTED BY: Neil Singer
POSTED BY: Francis Bush

I find that a smoother way to handle units is to avoid putting them into expressions at the beginning of a calculation but only put them in at the last steps.

Write a set of rules that give the numerical and unit values for each of your variables. Then do your algebraic calculations symbolically, using these rules at the conclusion.

I've written an application called UnitsHelper that helps with these problems, If you write to me I can send you a Dropbox link.

One of the routines, Deunitize, will remove the units from an expression in such a way to have implied input units and an implied output unit (and checks for consistency.).

UnitsHelper also has provision for defining reduced unit systems such as geometrical units or atomic units, general decibel units, and handy palettes.