cortex-js / compute-engine

An engine for symbolic manipulation and numeric evaluation of math formulas expressed with MathJSON
https://cortexjs.io
MIT License
356 stars 42 forks source link

parsing implicit function arguments #154

Closed dcbradley closed 5 months ago

dcbradley commented 5 months ago

The expression resulting from parsing the following latex:

\cos x \sin y

is this:

cos(x*sin(y))

rather than this:

cos(x) * sin(y)

The workaround is to use explicit grouping in the arguments:

\cos(x) \sin(y)

However, students are being taught the notation with implicit grouping but with the second interpretation rather than the first. I am wondering if there is a reasonable change that could be made to accommodate that. I'd be happy to take a crack at making a patch, but I'd like to know first if you think it's a good idea. The proposal is to make the parsing of implicit arguments stop when it hits a multiplication times a function. So if parseArguments(kind="implicit") encounters 2xy\sin..., it will return 2xy.

A less aggressive change would be to only apply this to trig functions, since we know these functions are commonly written in this way and in the cases where people do want a trig function term in the argument to another trig function, I think they are unlikely to use an implicit argument.

What do you think?

arnog commented 5 months ago

I would not have different rules for trig functions and others. ln functions also frequently have implicit arguments and I think they should behave consistently.

This is a tough one. I'm not sure exactly what the right answer is. The current behavior has the benefit of clarity: multiplications are considered part of the implicit argument. Would \cos 2f(t) be considered cos(2) x f(t) or cos(2f(t))? Or \cos 2\ln x?

Do you have some reference where the rule is explained to students?

dcbradley commented 5 months ago

Here are some examples where the notation is used:

https://www.onlinemathlearning.com/sum-identities.html https://math.libretexts.org/Bookshelves/Precalculus/Precalculus_1e_(OpenStax)/07%3A_Trigonometric_Identities_and_Equations/7.02%3A_Sum_and_Difference_Identities https://courses.lumenlearning.com/suny-osalgebratrig/chapter/sum-and-difference-identities/

In some cases, it's as if the functions are infix operators with a lower precedence than multiplication but higher than addition. The lhs becomes a multiplicative factor and the rhs becomes an argument.

dcbradley commented 5 months ago

The infix operator idea isn't exactly right, though, because explicit multiplication should also work. Clearly, the following should all be equivalent:

\cos x \sin y
\cos x * \sin y
\cos x \sin(y)
\cos x * \sin(y)
\cos x (\sin y)
\cos \frac{2x}{2} \sin y

The question is whether the above should be equivalent to the following:

\cos(x) \sin(y)
(\cos x)(\sin y)
\cos(x) * \sin(y)

And also whether it should be equivalent to the following:

\cos 1x \sin y
\cos 2x/2 \sin y

For the sake of simplicity, it's tempting to just make implicit arguments stop before multiplication. The double-angle trig formulas are therefore worth examining. In my searching, most sources use \cos(2x) rather than \cos 2x, but some do use the latter. Example:

https://www.onlinemathlearning.com/double-angle-formula.html

Also, the precalculus textbook by Larson, Hostetler, and Edwards.

In my opinion, interpreting \cos x \sin y as \cos(x \sin y) is worse than interpreting \cos 2x as (\cos 2)x.

arnog commented 5 months ago

Many people think that math notation is clear, unambiguous, logical and consistent. In practice it often relies on “you know what I mean”. Sigh.

I liked the idea of trig functions as infix operators, but you’re right it doesn’t always work.

Thanks for the examples of usage. I’ve found those two discussions:

https://www.themathdoctors.org/order-of-operations-trigonometric-functions/

https://www.quora.com/Do-you-put-parentheses-around-a-number-in-a-trig-function-i-e-sin-x-or-sin-x

(that last one is particularly good).

So, here’s what I would suggest: an implicit argument is a coefficient followed by one or more variables. A coefficient is a number or a fraction or surd that does not contain variables. so “cos sqrt(a) sin(b)” is “cos(sqrt(a)) sin(b)”. Both the coefficient and the variables are optional, but one or the other must be present.

I think this would work with logarithms as well, although now “ln ln x” would be invalid and would require parentheses.

Thoughts?

dcbradley commented 5 months ago

Yeah. Hopefully an LLM isn't required!

What about sin x^2? To me that is unambiguously sin(x^2), not (sin x)^2. One of the discussions you linked said that in the past, some people used the second interpretation. I've never seen it.

Another case is something like sin x/2. Interpreting it as sin(x/2) doesn't fit the coefficient rule, but in "ascii math" contexts this seems natural. It's certainly not a deal breaker, though, as long as \sin \frac{x}{2} works as expected. Does your rule cover that?

Seems like an implicit argument should be comprised of at least the first multiplicative term of whatever follows the function. Then ln ln x would work. The question is how much more to slurp in after the first term, no?

arnog commented 5 months ago

OK, my heuristic doesn’t quite work. It wouldn’t handle “cos a/2”.

How about this (which is getting closer to what you suggested in the first place):

when looking for an implicit argument parse all elements at the same depth, until an addition or a trig function is encountered.

This means that this would work only got trig functions and that implicit log arguments would need some other heuristic.

dcbradley commented 5 months ago

Sounds reasonable. Currently, it stops the implicit argument at any operation of lower precedence than multiplication. I assume the new rule would do the same.

Would sin cos x be allowed? Or, perhaps more realistically, something like arcsin cos x. These aren't important cases to me. I'm just trying to understand the rule.

arnog commented 5 months ago

I would be tempted to say they would not be allowed, resulting in an error. I think it’s more likely that “sin cos a” is an indication that the argument of “sin” was left out.