Answer Checkers (MathObjects)
Checkers are available for each of the types of values that the parser can produce (numbers, complex numbers, infinities, points, vectors, intervals, sets, unions, formulas, lists of numbers, lists of points, lists of intervals, lists of formulas returning numbers, lists of formulas returning points, and so on).
To use one of these checkers, simply call the cmp()
method of the object that represents the correct answer. For example:
$n = Real(sqrt(2)); ANS($n->cmp);
will produce an answer checker that matches the square root of two. Similarly,
ANS(Vector(1,2,3)->cmp);
matches the vector <1,2,3>
(or any computation that produces it, e.g., <i+2j+3k>
, or <4,4,4>-<3,2,1>
), while
ANS(Interval("(-inf,3]")->cmp);
matches the given interval. Other examples include:
ANS(Infinity->cmp); ANS(String('NONE')->cmp); ANS(Union("(-inf,$a) U ($a,inf)")->cmp);
and so on.
Formulas are handled in the same way:
ANS(Formula("x+1")->cmp); $a = random(-5,5,1); $b = random(-5,5,1); $x = random(-5,5,1); $f = Formula("x^2 + $a x + $b")->reduce; ANS($f->cmp); ANS($f->eval(x=>$x)->cmp); $x = Formula('x'); ANS((1+$a*$x)->cmp); Context("Vector")->variables->are(t=>'Real'); $v = Formula("<t,t^2,t^3>"); $t = random(-5,5,1); ANS($v->cmp); ANS($v->eval(t=>$t)->cmp);
and so on.
Lists of items can be checked as easily:
ANS(List(1,-1,0)->cmp); ANS(List(Point($a,$b),Point($a,-$b))->cmp); ANS(List(Vector(1,0,0),Vector(0,1,1))->cmp); ANS(Compute("(-inf,2),(4,5)")->cmp); # easy way to get list of intervals ANS(Formula("x, x+1, x^2-1")->cmp); ANS(Formula("<x,2x>,<x,-2x>,<0,x>")->cmp); ANS(List('NONE')->cmp);
and so on. The last example may seem strange, as you could have used ANS(String('NONE')->cmp)
, but there is a reason for using this type of construction. You might be asking for one or more numbers (or points, or whatever) or the word NONE
if there are no numbers (or points). If you used String('NONE')->cmp
, the student would get an error message about a type mismatch if he entered a list of numbers, but with List('NONE')->cmp
, he will get appropriate error messages for the wrong entries in the list.
In the case of a list of points where the answer is NONE
, you should tell MathObject what the expected type of answer is, so that appropriate messages can be given. E.g.,
ANS(List('NONE')->cmp(typeMatch=>Value::Point);
would give appropriate messages for points rather than numbers (the default type).
It is often appropriate to use the list checker in this way even when the correct answer is a single value, if the student might type a list of answers.
On the other hand, using the list checker has its disadvantages. For example, if you use
ANS(Interval("(-inf,3]")->cmp);
and the student enters (-inf,3)
, she will get a message indicating that the type of interval is incorrect, while that would not be the case if
ANS(List(Interval("(-inf,3]"))->cmp);
were used. (This is because the student doesn't know how many intervals there are, so saying that the type of interval is wrong would inform her that there is only one.)
The rule of thumb is: the individual checkers can give more detailed information about what is wrong with the student's answer; the list checker allows a wider range of answers to be given without giving away how many answers there are. If the student knows there's only one, use the individual checker; if there may or may not be more than one, use the list checker.
Note that you can form lists of formulas as well. The following all produce the same answer checker:
ANS(List(Formula("x+1"),Formula("x-1"))->cmp);
ANS(Formula("x+1,x-1")->cmp); # easier
$f = Formula("x+1"); $g = Formula("x-1"); ANS(List($f,$g)->cmp);
$x = Formula('x'); ANS(List($x+1,$x-1)->cmp);
See the files in pg/doc/MathObjects/problems for more examples of using the parser's answer checkers.