Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update units context to include differentiation #1177

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from

Conversation

dpvc
Copy link
Member

@dpvc dpvc commented Jan 11, 2025

The main purpose of this PR is to add the ability to differentiate formulas with units.

I also made a pass over the documentation, and corrected some errors, moved the section on removing units from a context to earlier (right after adding them), and added a section on the new differentiation features.

In the past, the D() method provided for multiple derivatives like D(2) or D(2, "x"), but only allowed one to be specified. I have extended the D() method to allow more than one numeric repeat operation, so $f->D(2, "x", 3, "y") would be $d\over dx^2 dy^3$, and is equivalent to $f->D("x", "x", "y", "y", "y") or $f->D(2, "x")->D(3, "y"). This should not affect existing problems, as it is an extension of the syntax, not a change.

While working on this, I noticed that I had handled abs() for arguments that are numbers with units, but didn't handle the |...| syntax for that. So I've added that here. That also required adding another option to the contextExtensions.pl extension mechanism to override the list classes (|...| are handled using the list delimiters infrastructure).

Finally, I fixed an error with abs() with number-with-units arguments where formula comparisons would fail (the type was not being set properly), simplified the evaluation of trig functions with angle units by removing unneeded tests that are already made in the _check() function, and added a quantity method to the Formula-with-Units class to match the one in the Number-with-Units class.

@pstaabp
Copy link
Member

pstaabp commented Jan 28, 2025

Overall, this looks great. I was testing the higher-order derivatives with the non-realistic function

Context('Units')->withUnitsFor('length','mass')->assignUnits(
        x => 'm',
        y => "ft",
    z => 'kg'
    );

$z = Compute("(3x^2 * y^4) kg");

$dz = $z->D('x',3,'y');

and the result was 6x * 24y kg/(m ft^3) as expected. I was thinking that using ->reduce would change this to 144 x * y kg/(m ft^3), but left it unchanged. Is this because the reduction rules don't automatically apply to these objects? Not a big deal, but just curious.

@Alex-Jordan
Copy link
Contributor

@pstaabp Assuming implicit multiplication has higher precedence than explicit, I think that 6x * 24y would be parsed as (6x)*(24y).

There is a relatively new reduction rule: m(nx) -> (mn)x for when m and n are numbers. There is also a reduction rule for x*n -> n*x. But neither of those apply here so I think there just is no reduction rule for this.

Note that if implicit and explicit multiplication had the same precedence, then maybe you have:
((6x)24)y
and then by x*n -> n*x:
(24(6x))y
and then by m(nx) -> (mn)x:
(144x)y

@dpvc
Copy link
Member Author

dpvc commented Feb 3, 2025

Assuming implicit multiplication has higher precedence than explicit

It doesn't. In fact, the MathQuill settings have implicit multiplication as lower precedence than explicit multiplication, if I recall correctly.

The actual result from the differentiation is [(6x)*(24y)] kg, and there is no reduction rule for (nx)*(mx) so it is not further reduced.

Also note that differentiation does a reduce automatically, so adding it afterword will never do anything.

Is this because the reduction rules don't automatically apply to these objects?

You are right, the Number-with-Units object does not have a reduce() method, and it probably should (one that reduces its formula). I will add one and make a commit for that (plus the documentation fixes that you spotted -- thanks).

@drgrice1
Copy link
Member

drgrice1 commented Feb 3, 2025

Note that MathQuill precedence is only used when parsing student answers.

@dpvc
Copy link
Member Author

dpvc commented Feb 3, 2025

Note that MathQuill precedence is only used when parsing student answers.

I seem to recall a discussion where we considered making this the precedence all the time. And one could certainly take derivatives of student answers, although I know that isn't what Peter was doing.

In any case, I was only trying to say that Alex's assumption about the precedences wasn't true, and that it is more likely to be the other way around, if anything.

@dpvc
Copy link
Member Author

dpvc commented Feb 3, 2025

You are right, the Number-with-Units object does not have a reduce() method, and it probably should

It turns out that reducing formulas that return number-with-unit objects already works fine, and that the actual NumberWithUnit object doesn't need a reduce() function after all, since it is an actual number (not a formula) with units. The formula returning a number-with-units is implemented as a formula joined to a unit via the unit "multiplication" operation, and that multiplication inherits the usual reduction method, so there is no need to do anything special for that case.

@drgrice1
Copy link
Member

drgrice1 commented Feb 3, 2025

I know, I was just pointing out that the MathQuill precedence wouldn't have had effect in @pstaabp's calls.

@dpvc
Copy link
Member Author

dpvc commented Feb 3, 2025

I've pushed the changes requested.

Copy link
Member

@drgrice1 drgrice1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good.

The new units context and the context extensions stuff in general is really awesome. So much new potential. Thanks so much for doing this.

There is one minor detail that seems to have been missed in previous pull requests. On line 171 of contextUnits.pl, C<limited => 1> should be C<< limited => 1 >>. I noticed that is not displayed correctly in the generated HTML for the POD.

@dpvc
Copy link
Member Author

dpvc commented Feb 3, 2025

The new units context and the context extensions stuff in general is really awesome. So much new potential.

Thanks! I had wanted to do a real units object since the very beginning (the old NumberWIthUnits() was a stop-gap measure that was never intended to be permanent), and it seemed like units should be able to be added to any (numeric) context, so I had to come up with a way to do that. Thus the extension framework seemed a natural thing to do.

I agree, that this opens up a lot of new possibilities.

I've made the POD change you requested. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants