cortex-js / compute-engine

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

Distinguish between variable names a_b and indexing a_1 #27

Closed stefnotch closed 2 years ago

stefnotch commented 2 years ago

Sometimes, there are variables with a subscript. For example, when one has a triangle and a square and wants to calculate their areas: A_tri and A_squ. In this case, they're clearly two different variables.

However, in a different context, one has matrices. To index the first row/column (depending on convention), one would write a_1. To index the second one, it would be a_2. In that case, they're referring to the same variable.

The same thing applies to

Is there a general way of distinguishing between those two options? As in, something along the lines of ["Symbol/Variable/Function/..", ["Subscript", "a", "t"]] vs ["Subscript", "a", "1"]. The former would mean "this entire thing is the variable name" while the latter would mean "the subscript probably has a special meaning"

arnog commented 2 years ago

Great question!

The name of a symbol can include a _ underbar. So {sym: 'A_tri'} represent the variable A_tri.

If no matching symbol is found, the _ is interpreted as the Subscript operator, so a_2 would become ["Subscript", "a", 2].

In addition, it is possible to "construct" symbols, using the Symbol operator: ["Symbol", "'a'", 2] is a synonym for the symbol a_2. The Symbol operates cast all its arguments to strings (by applying the String operator on them), then concatenate them to form a symbol.

stefnotch commented 2 years ago

Oh, lovely! I guess using strings to represent variables works quite nicely in this case.

Which brings me to a more difficult one: I've seen variables with a tilde above them. And they're distinct from variables without one. Like this: f tilde

How would one represent that? Would it possible require the inclusion of a new MathJson function?

arnog commented 2 years ago

You have two options:

stefnotch commented 2 years ago

Sounds good, I'll check out both options then. Regarding the ["OverTilde", "f"] option, would using the Hold function be reasonable there? As in ["Hold", ["OverTilde", "f"]]

arnog commented 2 years ago

By default (i.e. the version that's in the Compute Engine default dictionary), the OverTilde is an "inert" function, that is it is used to "decorate" another expression, and provide some information about it. However, evaluating it does not change it, that is ce.box(["OverTilde", "f"]).evaluate().json is ["OverTilde", "f"].

The Hold function is useful to prevent an evaluation, but in this case, since the evaluation doesn't do anything, the Hold function is not necessary.