PGfunctionevaluators.pl - Macros that generate function answer evaluators.
ANS(fun_cmp($answer_or_answer_array_ref, %options));
ANS(function_cmp($correctEqn, $var, $llimit, $ulimit, $relTol, $numPoints, $zeroLevel,
$zeroLevelTol));
ANS(function_cmp_up_to_constant($correctEqn, $var, $llimit, $ulimit, $relpercentTol,
$numOfPoints, $maxConstantOfIntegration, $zeroLevel,
$zeroLevelTol));
ANS(function_cmp_abs($correctFunction, $var, $llimit, $ulimit, $absTol, $numOfPoints));
ANS(function_cmp_up_to_constant_abs($correctFunction, $var, $llimit, $ulimit,
$absTol, $numOfPoints, $maxConstantOfIntegration));
Function answer evaluators take in a function, compare it numerically to a correct function, and return a score. They can require an exactly equivalent function, or one that is equal up to a constant. They can accept or reject an answer based on specified tolerances for numerical deviation.
The general function answer evaluator is fun_cmp(). It takes a hash of named options as parameters. There are also several specific function_cmp_*() answer evaluators for use in common situations which feature a simplified syntax.
The MathObjects system provides a Formula->cmp() method that produce answer evaluators for function comparisons. fun_cmp() has been rewritten to use Formula->cmp() to produce the answer evaluator. It is recommended that you use the Formula object's cmp() method directly if possible.
ANS(fun_cmp($answer_or_answer_array_ref, %options));
Compares a function or a list of functions, using a named hash of options to set parameters. This can make for more readable code than using the function_cmp() style, but some people find one or the other easier to remember.
$answer_or_answer_array_ref can either be a string scalar representing the correct formula or a reference to an array of string scalars. If multiple formulas are provided, fun_cmp() will return a list of answer evaluators, one for each answer specified. The answer can contain functions, pi, e, and arithmetic operations. However, the correct answer string follows a slightly stricter syntax than student answers; specifically, there is no implicit multiplication. So the correct answer must be "3*x" rather than "3 x". Students can still enter "3 x".
%options is a hash containing options that affect the way the comparison is performed. All hash items are optional. Allowed options are:
This determines the evaluation mode. The recognized modes are:
Function must match exactly.
Function must match up to a constant.
An absolute tolerance value. When the student and correct functions are evaluated, the result for each evaluation point must be within a fixed distance from the correct answer to qualify. For example, an absolute tolerance of 5 means that any result which is +-5 of the correct answer qualifies as correct. abstol is accepted as a synonym for tol.
A relative tolerance. Relative tolerances are given in percentages. A relative tolerance of 1 indicates that when the student's function are evaluated, the result of evaluation at each point must be within within 1% of the correct answer to qualify as correct. In other words, a student answer is correct when
abs(studentAnswer - correctAnswer) <= abs(.01*relTol*correctAnswer)
tol and relTol are mutually exclusive. reltol is also accpeted as a synonym for relTol.
zeroLevel and zeroLevelTol specify a alternative absolute tolerance to use when the correct answer is very close to zero.
If the correct answer has an absolute value less than or equal to zeroLevel, then the student answer must be, in absolute terms, within zeroLevelTol of correctAnswer, i.e.,
abs(studentAnswer - correctAnswer) <= zeroLevelTol
In other words, if the correct answer is very near zero, an absolute tolerance will be used. One must do this to handle floating point answers very near zero, because of the inaccuracy of floating point arithmetic. However, the default values are almost always adequate.
The var parameter can contain a number, a string, or a reference to an array of variable names. If it contains a number, the variables are named automatically as follows:
var | variables used
-----+--------------------
1 | x
2 | x, y
3 | x, y, z
4+ | x_1, x_2, x_3, ...
If the var parameter contains a reference to an array of variable names, then the number of variables is determined by the number of items in the array. For example:
var=>['r','s','t']
If the var parameter contains a string, the string is used as the name of a single variable. Hence, the following are equivalent:
var=>['t']
var=>'t'
vars is recognied as a synonym for var. The default is a single variable, x.
Limits are specified with the limits parameter. If you specify limits for one variable, you must specify them for all variables. The limit parameter must be a reference to an array of arrays of the form [$lower_limit. $upper_limit]
, each array corresponding to the lower and upper endpoints of the (half-open) domain of one variable. For example,
vars=>2, limits=>[[0,2], [-3,8]]
would cause x to be evaluated in [0,2) and y to be evaluated in [-3,8). If only one variable is being used, you can write either:
limits => [[0,3]]
limits => [0,3]
domain is recognized as a synonym for limits.
In some cases, the problem writer may want to specify the points used to check a particular function. For example, if you want to use only integer values, they can be specified. With one variable, either of these two forms work:
test_points=>[1,4,5,6]
test_points=>[[1,4,5,6]]
With more variables, specify the list for the first variable, then the second, and so on:
vars=>['x','y'], test_points=>[[1,4,5],[7,14,29]]".
If the problem writer wants random values which need to meet some special restrictions (such as being integers), they can be generated in the problem:
test_points=>[random(1,50), random(1,50), random(1,50), random(1,50)]
Note that test_points should not be used for function checks which involve parameters (either explicitly given by "params", or as antiderivatives).
The number of sample points to use when evaluating the function.
Maximum size for the constant of integration (in antider mode).
A reference to an array of "free" parameters which can be used to adapt the correct answer to the submitted answer. (e.g. ['c'] for a constant of integration in the answer x^3/3+c.
If set to one, extra debugging information will be output.
# standard compare, variable is x
fun_cmp("3*x");
# standard compare, defaults used for all three functions
fun_cmp(["3*x", "4*x+3", "3*x**2"]);
# standard compare, variable is t
fun_cmp("3*t", var=>'t');
# x, y and z are the variables
fun_cmp("5*x*y*z", var=>3);
# student answer must match up to constant (i.e., 5x+C)
fun_cmp("5*x", mode=>'antider');
# x is evaluated in [0,2), y in [5,7)
fun_cmp(["3*x*y", "4*x*y"], limits=>[[0,2], [5,7]]);
There are four single-variable function answer evaluators: "normal," absolute tolerance, antiderivative, and antiderivative with absolute tolerance. All parameters (other than the correct equation) are optional.
ANS(function_cmp($correctEqn, $var, $llimit, $ulimit, $relTol, $numPoints,
$zeroLevel, $zeroLevelTol));
function_cmp() uses standard comparison and relative tolerance. It takes a string representing a single-variable function and compares the student answer to that function numerically. $var, $relTol, $numPoints, $zeroLevel, and $zeroLevelTol are equivalent to the identically-named options to fun_cmp(), above. $llimit and $ulimit are combined to form the value of limits above.
ANS(function_cmp_up_to_constant($correctEqn, $var, $llimit, $ulimit,
$relpercentTol, $numOfPoints,
$maxConstantOfIntegration, $zeroLevel,
$zeroLevelTol));
function_cmp_up_to_constant() uses antiderivative compare and relative tolerance. All but the first argument are optional. All options work exactly like function_cmp(), except of course $maxConstantOfIntegration. It will accept as correct any function which differs from $correctEqn by at most a constant; that is, if
$studentEqn = $correctEqn + C, where C <= $maxConstantOfIntegration
the answer is correct.
ANS(function_cmp_abs($correctFunction, $var, $llimit, $ulimit, $absTol, $numOfPoints));
function_cmp_abs() uses standard compare and absolute tolerance. All but the first argument are optional. $absTol defines the absolute tolerance value. See the corresponding option to fun_cmp(), above. All other options work exactly as for function_cmp().
ANS(function_cmp_up_to_constant_abs($correctFunction, $var, $llimit,
$ulimit, $absTol, $numOfPoints,
$maxConstantOfIntegration));
function_cmp_up_to_constant_abs() uses antiderivative compare and absolute tolerance. All but the first argument are optional. $absTol defines the absolute tolerance value. See the corresponding option to fun_cmp(), above. All other options work exactly as with function_cmp_up_to_constant().
FIXME undocumented.
ANS(multivar_function_cmp($correctFunction, $var, $limits, $relTol, $numPoints, $zeroLevel, $zeroLevelTol));
This function is deprecated. Use fun_cmp instead:
ANS(fun_cmp($correctFunction, var=>$var, limits=>$limits, ...));