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
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();
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
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