compute-engine
compute-engine copied to clipboard
Canonical rules for fraction numerators
Hi all! I'm super interested in MathJSON, and I'm trying to set up MathLive/Compute in a personal project.
I was working on comparing linear equations with simplify/evaluate/canonical and found that I couldn't get a consistent representation for (-7/4)x+10
const answerbox="\\frac{-7x}{4}+10"
const answer = [ "Add", [ "Multiply", [ "Divide", -7, 4 ], "x" ], 10]
match(
ce.evaluate(ce.parse(answerbox)),
ce.evaluate(answer)
)
);
Is this a case where I need to use additional rewrite rules to coerce this into a unique 'canonical' form for comparison, or is this within the scope of the canonical
function?
Great question... I need to think about it a bit more for canonical
. Seems reasonable, though. However, it should definitely give the same result for simplify
@arnog Just a thought, but maybe a new canonical-no-divide
rule that behaves like canonical-subtract
and replaces a division with a non-1 numerator with multiplication? Changing -7/4
to -7 x 1/4
or -7 x 4^(-1)
I too would be in favour of adding a canonical-no-divide
rule. Preferably one that replaces every division a/b
with a * b^(-1)
QuantumSheet actually implements that, since that's what Sympy expects: https://github.com/stefnotch/quantum-sheet/blob/6b445476559ab5354b8a1c68c24a4ceb24e050e9/src/cas/pyodide-cas.ts#L101-L102
It feels a bit weird to me to not have division in the canonical form (admittedly, an earlier version of the Compute Engine did just that). That also makes some simplification rules more difficult to write since instead of detecting patterns of the form a/b
you now have to pick up a*c*d
where c
(or d
) is of the form b^-1
.
Can you tell me more about Sympy's expectations in that regard? Do you have a pointer in the documentation that discusses this and perhaps a rationale for it?
On a broader note, I intend in an upcoming revision, to have clearer lines between 'formatting' (i.e. putting into a canonical form) and 'simplifying'. Formatting will not account for any calculations (i.e. multiply by 1), but will focus on sorting arguments of commutative functions, and reducing associative, idempotent and involutory functions. Simplify on the other hand will apply more rules, including ones depending on the numerical values of the arguments, and other 'assumptions' about arguments (for example whether an argument is a positive real, or a complex number, etc...
Here is the relevant sympy documentation. Typing the following into the sympy live shell (bottom right of the documentation page) does demonstrate that behavior:
expr = x/y
srepr(expr)
Of course if that turns out to be more trouble than it's worth, that's an entirely valid reason for not including it.
Interesting... Thanks for the pointer.
Of course, since Sympy has a Rational type, \frac{7x}{4}
would be Mul(Rational(7, 4), x)
and not Mul(7, x, Pow(4, -1))
Interesting... Thanks for the pointer.
Of course, since Sympy has a Rational type,
\frac{7x}{4}
would beMul(Rational(7, 4), x)
and notMul(7, x, Pow(4, -1))
Oh yes, you're spot on! Using the Rational type whenever possible is an even better choice in Sympy. I found this out the hard way, after wondering why an automatically translated equation didn't do what I thought it would.
The Compute Engine now handles rational numbers as their own type:
console.log(ce.parse('-\\frac{7}{4}x+10').canonical.json);
//-> ["Subtract", 10, ["Multiply", ["Rational", 7, 4], "x"]]
@arnog That's great! Awesome stuff!