WeBWorK Problems

AnswerHints and Domains

AnswerHints and Domains

by D. Brian Walton -
Number of replies: 3
Suppose I am checking a problem where the domain plays a role, for the purposes here, say finding antiderivatives including a term 1/x.

I would like to have an AnswerHints inclusion that checks for ln(x) instead of ln(abs(x)) in the student answer. It would not be counted correct without including absolute value, but I'd like to point out to the student this error immediately since it is so close.

I'm having trouble distinguishing these. Suppose $f is the antiderivative of interest. Here is a snippet of the answer checking portion:

$f->{limits} = [-1,1];
$g = $f;
$g->{limits} = [0,1];
ANS( $f->cmp()->withPostFilter(AnswerHints(
$g => "Remember absolute values."
)) );

The result is that this gives the hint, but says the answer is correct. Did this somehow change the limits of $f as well?

Other ideas?

Thanks,
D. Brian Walton
James Madison University
In reply to D. Brian Walton

Re: AnswerHints and Domains

by Darwyn Cook -
I think the problem is that although you have specified the domain of the functions, you have not specified which points the functions are to be evaluated to test for correctness.
So if webwork chooses points in the interval [0,1] to test the functions, the answer will be correct and so will g, giving you a right answer and your answer hint.
To add some points in the in the interval [-1,0) you could use the command
$f->{test_at} = [[-1],[-0.5]];

-1 and -0.5 to the points already tested.
I tried this piece of code, and it worked for my test values:

DOCUMENT();

loadMacros(
 "PGstandard.pl", # Standard macros for PG language
 "MathObjects.pl",
 "answerHints.pl"
);

Context("Numeric");
$f = Formula("ln(abs(x))");
$g = Formula("ln(x)");
$f->{limits} = [-1,1];
$g->{limits} = [0,1];
$f->{test_at} = [[-1],[-0.5]];

Context()->texStrings;
BEGIN_TEXT

\{ans_rule\}
END_TEXT
Context()->normalStrings;
ANS( $f->cmp()->withPostFilter(AnswerHints(
$g => "Remember absolute values."
)) );

ENDDOCUMENT();

In reply to Darwyn Cook

Re: AnswerHints and Domains

by D. Brian Walton -
Very good, Darwyn, I also get this to work. I have discovered my issue is really that I am trying to use the FormulaUpToConstants parser. If I change your formulas to FormulaUpToConstant, I can not get your example to work.

Okay, so now I'm heading a different way. If I use a subroutine in AnswerHints, I could normally say something like

sub {
my ($correct, $student, $ans) = @_;
...
return $possibleWrongSolution == $student;
} => "Remember absolute values."

The comparison == must be overloaded in order to deal with different MathObjects to use the same comparison routines as answer checkers. So, is there a direct way to call this comparison that would allow me to send alternate hash codes/options when performing the comparison? This might allow me to send the specific points I want to test when giving an AnswerHint.

Thanks,
D. Brian Walton

In reply to D. Brian Walton

Re: AnswerHints and Domains

by Davide Cervone -
There are several reasons that your approach here failed. (Darwyn is on the right track, but I'll comment on that in a moment.)

The first problem is your line

    $g = $f;
which does not do what you think. Since a MathObject is a perl object (not a scalar value), $f is a reference to that object, so when you assign that to $g, you make $g be a reference to the same object as $f (not a copy of it), and when you change $g->{limits} that also changes $f's limits as well, which is not what you intended. The proper way to do this is to use
    $g = $f->copy;
or
    $g = $f->with(limits=>[0,1]);
both of which give you a copy (with the latter also setting limits at the same time).

The fact that your $g and $f are pointing to the same object is why you are getting a correct answer for ln(x)+C, and also why it tells you that you need to remember the absolute values as well. You are not actually distinguishing between the two functions, and the hint will be given for both ln(x)+C and ln(abs(x))+C, and both will be marked as correct.

The second problem is the one that Darwyn points out, which is that you are not guaranteed to be testing the negative values, even if you had $g properly set. (Indeed, in your case, you are guaranteed not to be testing the negative ones, since your $f has limits set to [0,1] as well). He suggests you set $f->{test_at} to force testing at negative values. I would also suggest that you force a test at a positive value as well (since there is no guarantee that the random points will get you any), so that you can make sure that ln(-x)+C is marked incorrect.

When you move to FormulaUpToConstant, you have found out that this no longer works. That is because the FormulaUpToConstant object is a bit more complicated than just a formula. If you use

    $f = FormulaUpToConstant("ln(abs(x))");
then the actual formula that is being used to compare $f with the student's answer is not $f itself, but a modified version that is stored as $f->{adapt}. This is the one whose limits and test_at values should be set. You can do that as
    $f->{adapt}{limits} = [-1,1];
    $f->{adapt}{test_at} = [[-1],[1]];
although it is not really necessary to set the limits, since they are already set to [-2,2] by default. If you do that, it should work with the rest of the code Darwyn suggested.

This issue with the internal function not getting the settings from the original should be fixed, but I haven't done that yet. For now, you might want to set the limits and test_at values for BOTH $f and $f->{adapt} so when it is fixed, your problem will still work.

Here is my version:


    loadMacros(
      "PGstandard.pl",
      "MathObjects.pl",
      "answerHints.pl",
      "parserFormulaUpToConstant.pl",
    );

    Context("Numeric");
    $f = FormulaUpToConstant("ln(abs(x))");
    $f->{test_at} = $f->{adapt}{test_at} = [[-1],[1]];

    $g = FormulaUpToConstant("ln(x)");
    $g->{limits} = $g->{adapt}{limits} = [0,1];

    Context()->texStrings;
    BEGIN_TEXT
    \($f\) is \{ans_rule\}
    END_TEXT
    Context()->normalStrings;

    ANS(
      $f->cmp->withPostFilter(AnswerHints(
        $g => "Remember absolute values."
      ))
    );

Hope that helps.

Davide