WeBWorK Problems

Evaluating a Function at Integer Values

Evaluating a Function at Integer Values

by Danny Glin -
Number of replies: 1
This has come up in a couple of other threads, but I thought it warranted a separate discussion.
There are a few contexts where it is desirable to check functions which are only evaluated at (usually positive) integers. Some examples include sequences and series, and finding nth derivatives (as these sometimes involve factorials).
As far as I know, there is no easy way to have the default answer checkers check at just integer values, other than to specify a list of numbers to use as inputs.
How hard would it be to add a flag to specify that a variable must take on integer (or even positive integer) values? Then when functions involving this variable are checked, they are only evaluated at a random set of integer values.
In reply to Danny Glin

Re: Evaluating a Function at Integer Values

by Davide Cervone -
What you ask can already be done in several ways. The easiest is to use the little-known optional third parameter to the limits value for MathObjects. The limits are of the form
    limits => [m,M,r]
where m is the lower limit, M is the upper limit, and r is the "resolution", which is the separation between acceptable values. So to get integer values, use r = 1. (These work very much like the three parameters to the random() function.) For example:
    $f = Formula("n!/(n+1)!");
    ...
    ANS($f->cmp(limits=>[1,10,1]));
or
   $f = Formula("n!/(n+1)!")->with(limits=>[1,10,1]);
   ...
   ANS($f->cmp);
There are Context values that control the defaults for the limits. You can set the default limits directly:
    Context()->flags->set(limits=>[1,10,1]);
though if a MathObject has limits set explicitly on the object (or on the answer checker), they override these limits, including the resolution. If you want to specify the default resolution, you can do that via
    Context()->flags->set(resolution=>1);
so that all checking is done with integer values (provided the lower limit is an integer).

There is an alternative to the resolution for specifying test points. It is called the "granularity". This says how finely to chop up the range of values given in the limits, and then test points are taken from among those values. The default granularity is 1000, so limits=>[0,10] would divide the interval from 0 to 10 into 1000 pieces, and test points would be chosen from among those 1000 values. That is, in this case, you would have test points with two decimal places, but not three. If the granularity were set to 10, the values would be integers instead. (Another way to think about this is that distinct test points are separated by a distance that is at least the upper limits minus the lower limit divided by the granularity. This means that test points are not "too close together".)

If specified, resolutions takes precedence over granularity, but since resolution is not set by default, the granularity of 1000 is what usually controls the test points.

If you use integer test points, you may want to use larger intervals for your test points, as the random-point generator does not prevent the same point from being used more than once, so limits=>[1,5,1] would be likely to get repeated points. Personally, for integer test points, I think you might as well specify the points directly with

    ANS($f->with(test_points=>[[1],[2],[3],[4],[5]])->cmp);
since I don't really see the value in randomizing the selected points in this case, but if your really want to, you can achieve that result by specifying the resolution in one of the says discussed above.

Hope that does it for you.

Davide