Rulesbased answer tests
Rulesbased answer tests are a special kind of mathematical answer test.
Equality up to associativity and commutativity
The EqualComAss
test establishes that two expressions are equal up to commutativity and associativity of addition and multiplication, together with their inverses minus and division.
For example but This is very useful in elementary algebra, where we want the form of the answer exactly. This test seeks to establish whether two expressions are the same when the basic operations of arithmetic addition/multiplication and Boolean and/or are assumed to be nouns but are commutative and associative. Hence, but . The unary minus commutes with multiplication in a way natural to establishing the required form of equivalence.
This is a particularly useful test for checking that an answer is written in a particular form, e.g. "simplified".
Notes
 This test does not include laws of indices, so . Since we are dealing only with nouns does not simplify to . E.g. . This also means that is not considered to be equivalent to under this test. In many situations this notation is taken to mean the same thing, but internally in Maxima they are represented by different functions and are not converted to a canonical form by the test.
 By design, addition commutes with subtraction, so and multiplication commutes with division, so .
 By design since we do not have the rule . To establish this equivalence we would need a different answer test.
 This test can also be used to establish , but since the arguments of the set constructor function are commutative. Sets are not associative, so . (See Maxima's
flatten
command.)  Simplification is automatically switched off when this test is applied, otherwise it makes no sense.
Unary minus and division
In order to understand how the tests work it is essential to understand how we represent unary minus and division internally.
Without simplification, Maxima has a unary minus function: literally minus(x)
. This is transformed into UNARY_MINUS nounmul ex
The use of multiplication here allows 
to commute with other multiplication, so we can spot things like using associativity and commutativity.
Similarly, we replace division with a nounmul UNARY_RECIP(b)
. This means that UNARY_RECIP(b)
is not automatically the same as 1 nounmul UNARY_RECIP(b)
, without an additional rule.
EqualComAssRules
This is an advanced test.
This test allows question authors to create equivalence classes based on equality up to associativity and commutativity with the addition of optional rules. For example, the teacher can include the identity operations of addition and multiplication: and . This makes it much easier to establish things like is equivalent to . However, more general integer arithmetic is still not automatically included so .
This test always assumes associativity and commutativity of addition and multiplication. Essentially this test extends the EqualComAss
test by adding in additional rules. Without assumptions of commutativity and associativity we would need all sorts of additional rules, such as , since without commutativity this would not be captured by the rule zeroAdd
, i.e. . Furthermore, the way EqualComAss
deals with unary minus and division make associativity and commutativity difficult to add in their pure form.
Each rule is a named function in Maxima, and each rule has an associated predicate function to decide if the rule is applicable at the top level of an expression. E.g. zeroAddp(0+x)
would return true
and zeroAdd(0+x)
would return x
.
The teacher must supply an option consisting of a list of the following rule names.
Name  Rule 

(ALG_TRANS ) 
Always included 
assAdd 
Associativity of addition 
assMul 
Associativity of multiplication 
comAdd 
Commutativity of addition 
comMul 
Commutativity of multiplication 
(ID_TRANS ) 

zeroAdd 

zeroMul 

oneMul 

oneDiv 

onePow 

idPow 

zeroPow 
if 
zPow 
if 
(NEG_TRANS ) 

negNeg 

negDiv 
(Note, this assumes UNARY_RECIP and UNARY_MINUS ) 
negOrd 
Order summands so that the leading coefficient is not negative (see notes below). 
(DIV_TRANS ) 

recipMul 

divDiv 

Note is interpreted as in Maxima.  
divCancel 
Cancel common factors in numerator and denominator. 
(INT_ARITH ) 

intAdd 
Perform addition on integers 
intMul 
Perform multiplication on integers 
intPow 
Perform exponentiation when both arguments are integers 
Other  
intFac 
Factor integers (incompatible with intMul ) 
negDist 
Distribute only UNARY_MINUS over a sum (incompatible with negOrd ) 
sqrtRem 
Remove the sqrt function and replace with ^(1/2) 
The rule negOrd
deserves comment. Ultimately we only compare parse trees exactly, and so we need to order terms in sums and products (commutativity).
However is never ordered as . Furthermore, . We need to factor out the unary minus and ensure that the coefficient of the leading term is not negative.
Factoring out is better than distributing here, since in a produce such as it is not clear which term in the product the initial minus sign will end up in.
Since negOrd
is a factor command, it is incompatible with negDist
.
For convenience sets of rules can be specified. E.g. you can use the name ID_TRANS
in place of the list [zeroAdd,zeroMul,oneMul,oneDiv,onePow,idPow,zeroPow,zPow]
to include all of the basic identity operators.
If you want to remove tests from a list you can use code such as delete(zeroAdd, ID_TRANS)
.
The test takes the student's answer and teacher's answer and repeatedly applies the rules in turn until the expressions remain the same. The rules are designed to always shorten the expression, so the process is guaranteed to terminate. Once the expression is written in final form, the test compares the two expression trees.
Note that we do not guarantee the simplification is mathematically correct! E.g. if you are unlucky enough to try the rule zeroPow
on the expression 0^(11)
then since 11
is not equal to zero (taken literally) then the rule applies and you have failed to spot a potential 0^0
error.
If you add the rule testdebug
then you will see both expressions in the answer note. This is useful for debugging, but would clutter up things in a production setting.
Examples of use
Unique prime factorisation
Imagine we have asked students to find the prime decomposition of . This is the answer we are aiming at, but we also want to condone the answer
. We can do this with the rule [idPow]
. We might also (being generous perhaps) want to also accept . We can do this with the three rules [oneMul,idPow,zPow]
. You can try this code in the sandbox.
ATEqualComAssRules(2^0*3^1*5^0*7^2*11^1, 3^1*7^2*11^1, [oneMul,idPow,zPow]);
Note, this test always assumes commutativity so you can't (currently) enforce the order of writing the prime factors.
Developer notes
This functionality was introduced in April 2021. It is essential that the rules, and any combination of the rules, can only proceed in a single direction and that no infinite loops are created. So, intAdd
is fine because adding together two integers will make an expression simpler which in this case is shorter. For this reason we do not have expanding out (i.e. distribution) rules in the above set, and no rules of indices (which readily lead to mathematical errors). Use Maxima's simplifier if you want to include such rules.
The rules names are Maxima functions, but they assume simp:false
and that the expression has noun forms e.g. nounadd
instead of +
. You can use equals_commute_prepare(ex)
to change an expression into this noun form. The goal of this code is to create reliable equivalence classes of expressions, not perform algebraic manipulation as we traditionally know it. In particular the way unary minus is transformed into multiplication with a special tag UNARY_MINUS
is likely to cause confusion to students if an expression is manipulated using these rules and then shown to a student. The transformation is designed to go in one direction only, and we do not support displaying the resulting manipulated expressions in traditional form.
As of May 2023, these rules are not intended as an enduser simplifier and we do not currently support userdefined rules (sorry!).