1) Within Interval context, I create

$J = Compute( "[$L,$R]" );

in order to have a closed interval for use by a custom checker. That checker will flag a non-closed interval with error message

The type of interval is incorrect

(provided by pg/lib/Value/AnswerChecker.pm)

? Given that preliminary type-checking, is it optional for my checker to do a string comparison (with "eq" instead of "==") for brackets rather than parentheses ?

2) I have vague notions about having my Solutions block include mention of a student answer. I tried replacing "my" with "our" in some parts of my checker, but that did not export student stuff to global context. If there is not a simple way to do that, then I will not pursue this low-benefit task.

3) Experiments replacing strong with weak inequalities in my custom checker had anomalous results. If c was exact solution of f(x) = y0, then [c,c] would be rejected while treatment of [c,c+0.1] or [c-0.01,c] might vary.

4) I suspect DB-tagging: Calculus : Limits and Derivatives : Continuity is appropriate given our current taxonomy. I hope various new versions of a Library Browser will soon provide fuzzy searching to identify plausible (& case-insensitive) keyword matches for

Intermediate Value Theorem

Intermediate Value property

Intermediate Value

Given that preliminary type-checking, is it optional for my checker to do a string comparison (with "eq" instead of "==") for brackets rather than parentheses ?

It turns out that the endpoint checking is done in a post-filter, so your checker will run no matter what the type of endpoints are. The post-filter will add the warning message only if the answer is marked wrong, so if you don't check this in your custom checker code (and mark it correct) your student will not receive that message.

I have vague notions about having my Solutions block include mention of a student answer. I tried replacing "my" with "our" in some parts of my checker, but that did not export student stuff to global context.

This is because the answer checkers don't run until after the problem is created (and that means after the solution is produced). So you don't have access to any variables from the checker since they haven't been created yet.

The only way to do this would be to grab the answers from the `$inputs_ref`

hash, and that is a bit of a pain. For example, you could use

$student = Parser::Formula($inputs_ref->{ANS_NUM_TO_NAME(1)});to get the student's answer from the first (unnamed) answer blank. If there is a syntax error in the student's answer,

`$student`

will be undefined, but no error will be produced. If the answer is blank, it will be a Formula object that returns a blank String object. Note that it is always a Formula object, so you could also do
$student = $student->eval if $student->isConstant;if you want to get Real, Interval, or other constants.

Experiments replacing strong with weak inequalities in my custom checker had anomalous results. If c was exact solution of f(x) = y0, then [c,c] would be rejected while treatment of [c,c+0.1] or [c-0.01,c] might vary.

The reason that `[c,c]`

doesn't work is that this type of interval is converted automatically into the set `{c}`

, so when you try to get its two endpoints and its delimiters, you end up with only one value (for `$L`

with `$R`

being undefined), and the open and close delimiters are braces. If you look closely at the "Entered" column for this answer, you will see that it shows as a set. (If you want to show the original interval there instead, add `formatStudentAnswer => "parsed"`

to the parameters passed to the `cmp()`

method.)

Custom checkers that deal with intervals have to be a bit more sophisticated, since it is possible to be passed a Set or a Union (as these are all things to which an interval can be compared without a type-match error). Here is some code that handles all the situations:

ANS($J->cmp( showEndpointHints => 0, formatStudentAnswer => "parsed", checker => sub { my ( $good , $student , $ansHash ) = @_ ; my ($L,$R,$open,$close); if ($student->class eq "Interval") { ($L,$R,$open,$close) = $student->value; } elsif ($student->class eq "Set" && $student->length == 1) { ($L) = $student->value; $R = $L; $open = "["; $close = "]" } else { return 0 if $ansHash->{isPreview}; Value->Error("Your answer should be an Interval not a Set or Union"); } my $yL = $fcn->eval(x => $L); my $yR = $fcn->eval(x => $R); ($yL,$yR) = ($yR,$yL) if $yL > $yR; return $open.$close eq "[]" && Interval("[$yL,$yR]")->contains($y0); } ));Here, we handle the Interval and Set (with one element) separately to get the correct data, and produce an error message if it is anything else (unless this is a preview, in which case we just mark it wrong).

Also note the check at the end. Here, we form a new interval and ask if the value of `$y0`

is in the interval. This makes the check a bit easier to write. Note that we swap `$yL`

and `$yR`

in the previous line, if they are in the wrong order for an interval.

As for the situation for `[c,c+.01]`

and `[c-.01,c]`

, you would need to give me some specific examples in order to test out what is really going on.

Hope that helps.

Davide

YES, it does !

1) Type of interval --- in hindsight, I should have identified my main concern was an assurance that I could omit providing a "type error" message because the system would always do it for me.

2) Your comments lead me to consider writing another problem with a non-monotonic function where the point estimate in second part is required to be in the interval answer for the first part.

3) I suspect the anomalies involved relative tolerance issues. They have not recurred after I added the following line.

Context()->flags->set( tolerance => 0.0000001 , tolType => 'absolute');

thanks,

dick