WeBWorK Problems

How Do You Count Either of Two Answers As Correct

How Do You Count Either of Two Answers As Correct

by Fred Sullivan -
Number of replies: 9
Is there a simple way to count either of two different answers as correct?

For example, in a DE problem, I would like to count either
c1 e^t + c2 e^(-t)
or
c1 e^(-t) + c1 e^t
as correct.

Thanks.

Fred Sullivan
Wilkes University
In reply to Fred Sullivan

Re: How Do You Count Either of Two Answers As Correct

by Gavin LaRose -
Hi Fred,

One not particularly elegant solution to this is to define a custom checker that allows either of the answers you suggest:

loadMacros("MathObjects.pl");

Context("Numeric");
Context()->variables->add( t=>'Real', c1=>'Real', c2=>'Real' );
$ans1 = Compute("c1*e^t + c2*e^(-t)");
$ans2 = Compute("c2*e^t + c1*e^(-t)");
...
ANS( $ans1->cmp( checker=>sub {
my ( $correct, $student, $ansHash ) = @_;
return $student == $correct || $student == $ans2;
} ) );

This may not be terribly extensible to other general solutions, however.

Gavin
In reply to Gavin LaRose

Re: How Do You Count Either of Two Answers As Correct

by Fred Sullivan -
Gavin,

I modified your solution a bit after I realized that what I asked for was really more than I needed.

This code works:

$ans1 = Compute("c1 exp(-3t) + c2 exp(-4t)");
ANS($ans1->cmp(checker=>sub {
my ( $correct, $student, $ansHash ) = @_;
return $student == $correct ||
$student == $correct->substitute(c1=>c2,c2=>c1);
}));

But I don't understand why this code doesn't:

sub check {
my ( $correct, $student, $ansHash ) = @_;
return $student == $correct ||
$student == $correct->substitute(c1=>c2,c2=>c1);
}

$ans1 = Compute("c1 exp(-3t) + c2 exp(-4t)");
ANS($ans1->cmp(checker=>\&check));

I'm trying to abstract the checker into a separate function to make things easier, and I thought the right way to pass a reference to the function was to put \& in front of the name. I don't get any errors. When I enter the answer as in $ans1, it checks it as correct. But when I enter the answer as in $ans2, it checks it as incorrect. Obviously there's something I don't understand about Perl syntax.

Any help would be appreciated.
In reply to Fred Sullivan

Re: How Do You Count Either of Two Answers As Correct

by Davide Cervone -
One of the differences between the PG language and Perl is that PG handles \ differently (it tries to quote backslashes because they are commonly used in TeX, and the developers didn't want authors to have to double the backslashes in all their TeX code). I'm not certain I think this was a great decision, but that's what is causing you trouble. To get a "real" (i.e., non-quoted) backslash, you need to use two tildes instead:
    ANS($ans1->cmp(checker=>~~&check));
Ugly but it works. You might also consider storing the code in a variable so as to avoid having to create a function reference by hand:
    $check = sub {
      my ($correct, $student, $ansHash) = @_;
      return $student == $correct || 
          $student == $correct->substitute(c1=>c2,c2=>c1);
    }

    $ans1 = Compute("c1 exp(-3t) + c2 exp(-4t)");
    ANS($ans1->cmp(checker=>$check));

There are a couple of other small issues with your code. First, although c1=>c2works, it should really be c1=>"c2" since you are relying on Perl's automatic default to string values when nothing else makes sense, and that can be problematic.

Second, you should use the correct answer on the left and the student answer on the right of == checks, as the equality check is not entirely symmetric. For one thing, the limits for the domain are taken from the left-hand function (or from the Context if they are not set on the function itself), and the test points are determined by using the left-hand function. It is best to use the correct answer there because the limits are set properly for the correct answer, not the student answer, and you can easily get the "can't generate enough points for comparison" error if you use the student function on the left.

Hope that helps.

Davide

In reply to Davide Cervone

Re: How Do You Count Either of Two Answers As Correct

by Fred Sullivan -
Davide,

Thanks for your comments. I have been able to refine things to the following function which I have put in the PGcourse.pl file:
sub Either {
 my $ans = shift;
 return Compute($ans)->cmp(checker=>sub {
 $correct = shift;
 $student = shift;
 my $reverse = $correct->substitute(c1=>"c2",c2=>"c1");
 return $correct == $student ||
 $reverse == $student;
 })
}
and then I can just do this in the problem file:

ANS(Either("c1 exp(-$r1 t) + c2 exp(-$r2 t)"));

One thing that I don't understand (and I'm not sure that I really want to):

If I do:

return $correct == $student ||
 $correct=>substitute(c1=>"c2",c2=>"c1") == $student;
it doesn't work. If I reverse the operands to the second == it does work.

But when I store the reversed expression in a variable, it does work on the left.

I also had to use shift rather than @_ for the anonymous function because Perl didn't like @_ in that context.

Thanks very much to Davide and Gavin for all the help!


In reply to Fred Sullivan

Re: How Do You Count Either of Two Answers As Correct

by Davide Cervone -
Your function is good, but I would suggest a couple of improvements. First, your $correct and $student variables should be my variables so they don't go into the global namespace (minor detail).

Second, you might want to allow additional parameters that get passed to the cmp() method so that you can pass things like limits or other adjustments that might need to be included.

    sub Either {
      my $ans = shift;
      return Compute($ans)->cmp(checker=>sub {
        my $correct = shift; my $student = shift;
        my $reverse = $correct->substitute(c1=>"c2",c2=>"c1");
        return $correct == $student ||
              $reverse == $student;
      },@_);
    }
This way, any additional parameters to Either get passed on to the cmp() method, and you could do something like:
    ANS(Either("c1 sqrt(x-2) + c2",limits=>[2.1,3]));
to set the limits.

Finally, your observation about using the substitution in place of $reverseturns out to be a bug where some cached values from the first comparison ($correct == $student) where being passed on to the substituted formula. These included the test points and test values, which was what was causing the second comparison to fail. When you created $reversed before doing the first comparison, those values weren't there to pass on, so everything worked fine.

I have fixed the problem in the latest version of pg/lib/Parser.pm if you want to get an updated copy.

Davide

In reply to Davide Cervone

Re: How Do You Count Either of Two Answers As Correct

by David Gilliam -
I have been following this discussion with keen interest as I have dodged this issue for many years. We are at exactly this point in my differential equations class this semester. The ability to ask students to give the general solution of a higher order constant coefficient linear ODE would be very useful. While I never give problems with order higher than degree 4, it would be very useful to extend your discussion to include 3rd and 4th degree as well. Thus there would be parameters c1, c2, and possibly c3 and/or c4. It looks like that might be somewhat complicated but I decided to at least toss it out.

In any case the second order case is a great step - Thanks!!


David Gilliam
In reply to David Gilliam

Re: How Do You Count Either of Two Answers As Correct

by Fred Sullivan -
David,

You could modify my Either function to handle order 3 or 4 or n by checking all permutations of c1 ... cn. But that's a pain, and furthermore, it is going to mutiply the checking time by n!. I doubt that my little server would be very happy the night before a homework set is due.

What I have done in the past, and will continue to do for order >= 3, is to ask for a fundamental set, entered as a list.

E.g. ANS(Compute("exp(x),exp(-x),exp(2x),exp(-2x)")->cmp);

The students can enter the fundamental set in any order.

I then ask separately for a particular solution and the solution meeting initial conditions.

Last year I did it this way for second order, but now I'm modifying the second order problems to use Either.

The issue of general handling of arbitrary constants for DE problems is hard, I think. With linear equations, it's mostly not bad. But with general first order, it's very problematic.

I tell students to condense constants (2C => C). It would be nice to allow constants without requiring this, but I think that mathematically it's a hard problem when C can occur in various contexts, as opposed to + C in integrals.

And the problems can be even more general. For example, I gave a problem a couple of weeks ago where the solution comes out 1/sqsr(x^2+y^2) = C if you solve it as exact, but x^2+y^2 = C if you solve it as separable. One could handle situations like this using Gavin's method, or just make the students continue simplifying. Ultimately though, you can't anticipate all the possible forms of correct answers.

A checker that allows any one of several answers to be counted as correct without obfuscated code would be nice for this situation. How about something like ANS(Compute("ans1, ans2, ans3")->cmp_require_one) that gives credit when the student answer is any one of the list? I'll bet that would be easy for someone who actually understands checkers to write.
In reply to Fred Sullivan

Re: How Do You Count Either of Two Answers As Correct

by David Gilliam -
Thanks Fred

Actually what you have suggested is exactly what I do for higher order equations. I figured that extending Either to these cases might be problematic but thought it might be worth asking.

For the problem with x^2+y^2=C and 1/(x^2+y^2)=C I had exactly the same problem a while back. Bob Byerly, here at Texas Tech, modified his ConstMultChecker to handle this case but we both agreed that there are then infinitely many such formulas which are all correct. General solutions of first order nonlinear problems are very difficult. I have found methods that work for me. I fix an exact form by giving part of an answer, e.g., f(x,y)+x^2 = C, and asking for f(x,y).

In any case thank you, Gavin and Davide for the second order case. I have already converted all my problems using Either.


David Gilliam
In reply to Fred Sullivan

Re: How Do You Count Either of Two Answers As Correct

by David Gilliam -
I was hoping someone might pick up on the suggestion to write a checker that would "allows any one of several answers to be counted as correct" as suggested by Fred Sullivan. I have encountered the need for this several times.

More specifically following his suggestion

"How about something like ANS(Compute("ans1, ans2, ans3")->cmp_require_one) that gives credit when the student answer is any one of the list?"

This sounds like a wonderful idea. I do not know how to do this but would certainly appreciate such a checker.