I am having trouble with a problem I created in WeBWorK 2.9 that does not work properly in the current version of WeBWorK on the U of R server.
It uses bizarro arithmetic to try to be sure students simplify entries in a multianswer construct.
For some reason, even when all answers are correct, I get back the error "" on the multianswer components of the problem every time.
Here is the code for the problem:
## DESCRIPTION
## Differential equation solved using Variation of Parameters
## ENDDESCRIPTION
## DBsubject(Differential equations)
## DBchapter(Higher order differential equations)
## DBsection(Variation of parameters)
## Date(3/12/2015)
## Institution(Monroe Community College)
## Author(Paul Seeburger)
## Level(2)
## KEYWORDS('differential equation','second order','linear','nonhomogeneous','variation of parameters')
## adapted from: IndianaDiffEq/setDiffEQ10Linear2ndOrderNonhom/ur_de_10_16.pg
DOCUMENT() ;
loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGmatrixmacros.pl",
"parserPopUp.pl",
"parserMultiAnswer.pl",
"weightedGrader.pl",
"bizarroArithmetic.pl",
"PGunion.pl",
"PGcourse.pl",
#"PGdiffeqmacros.pl"
) ;
############
TEXT(beginproblem()) ;
Context("Numeric");
Context()->variables->are(
't'=>["Real", limits=>[-2,2]], 'y'=>["Real", limits=>[-2,2]]);
#, 'a'=>'Parameter','b'=>'Parameter');
#Context()->variables->remove('x');
Context()->functions->set( atan => {TeX => '\arctan'} );
# root of the characteristic equation
$r = Real(non_zero_random(-5,5,1));
$a = -2*$r;
$b = $r**2;
$c = Real(non_zero_random(-20,20,.5));
$ch = Real("-1*$c/2");
# $e = exp(1);
# $ans = Compute("($c/2)*(($e)**($r*t))");
$showPartialCorrectAnswers = 1 ;
$yp = Compute("e^($r t)($ch ln(t^2 + 1) + $c t arctan(t))")->reduce;
Context("Numeric");
Context()->variables->are(
't'=>["Real", limits=>[-2,2]], 'y'=>["Real", limits=>[-2,2]]);
#Context()->variables->remove('x');
Context()->functions->set( atan => {TeX => '\arctan'} );
#Context()->flags->set( checkUndefinedPoints=>1);
$a11 = Formula("e^($r t)");
#$a11->{test_at} = [[-2],[-1],[0],[1],[2]];
$a12 = Formula("t e^($r t)");
$a21 = Formula("$r e^($r t)");
$a22 = Formula("e^($r t)(1 + $r t)");
$n = Real("2*$r");
$wronskian = Formula("e^($n t)"); #Compute
$b11 = Real("0"); #Formula("0t");
$b12 = Formula("t e^($r t)");
$b21 = Formula("$c e^($r t)/(t^2+1)");
$b22 = Formula("e^($r t)(1 + $r t)");
$n2 = Real("-1*$c");
$w1 = Formula("$n2 t e^($n t)/(t^2+1)"); #Compute
$c11 = Formula("e^($r t)");
$c12 = Real("0"); #Formula("0t");
$c21 = Formula("$r e^($r t)");
$c22 = Formula("$c e^($r t)/(t^2+1)");
$w2 = Formula("$c e^($n t)/(t^2+1)"); #Compute
$u1p = Formula("$n2 t/(t^2+1)"); #Compute
$u2p = Formula("$c/(t^2+1)"); #Compute
$u1 = Formula("$n2/2 * ln(t^2 + 1)")->reduce; #Compute
$u2 = Formula("$c arctan(t)"); #Compute
#$yp = Compute("$ch e^($r t)ln(t^2 + 1) + $c t arctan(t)")->reduce;
$multians1 = MultiAnswer($a11, $a12, $a21, $a22, $wronskian, $b11, $b12, $b21, $b22, $w1, $c11, $c12, $c21, $c22, $w2, $u1p, $u2p, $u1, $u2)->with(
singleResult => 0, # I cannot get this problem to work well with a single result since it would not show students which parts are correct and which are incorrect. Maybe change in the future, once this process is easier.
allowBlankAnswers => 1,
checkTypes => 0,
# The formatting has not been expanded to include the second and third determinants
# This is not important on this problem since we cannot display the problem this way anyway.
format => "<table border='0' cellspacing='20'>
<tr><td> %s </td><td> %s </td> </tr>
<tr><td> %s </td><td> %s </td> </tr>
<tr><td> = %s </td></tr>
</table>",
tex_format => "\left\lbrack\begin{array}{rr} %s & %s \\ %s & %s \end{array}\right\rbrack = %s",
checker => sub {
my ( $correct, $student, $self, $ans) = @_;
my @c = @{$correct};
my @s = @{$student};
my @score = ();
Context()->operators->set(
'/' => {class => 'bizarro::BOP::divide', isCommand => 1},
'/ ' => {class => 'bizarro::BOP::divide', isCommand => 1},
' /' => {class => 'bizarro::BOP::divide', isCommand => 1},
'//' => {class => 'bizarro::BOP::divide', isCommand => 1},
'-' => {class => 'bizarro::BOP::subtract', isCommand => 1},
'- ' => {class => 'bizarro::BOP::subtract', isCommand => 1},
' -' => {class => 'bizarro::BOP::subtract', isCommand => 1},
'*' => {class => 'bizarro::BOP::multiply', isCommand => 1},
'* ' => {class => 'bizarro::BOP::multiply', isCommand => 1},
' *' => {class => 'bizarro::BOP::multiply', isCommand => 1});
$flag = 1;
if ($c[0] == $s[1]) {
$flag = -1;
foreach my $j (0..1) {
$score[$j] = 0;
if ($c[$j]->typeMatch($s[1-$j]) && $c[$j] == $s[1-$j]) { $score[$j] = 1; }
$score[$j+2] = 0;
if ($c[$j+2]->typeMatch($s[1-$j+2]) && $c[$j+2] == $s[1-$j+2]) { $score[$j+2] = 1; }
}
}
else {
foreach my $j (0..3) {
$score[$j] = 0;
if ($c[$j]->typeMatch($s[$j]) && $c[$j] == $s[$j]) { $score[$j] = 1; }
}
}
$student = Formula("$s[4]"); $correct = Formula("$flag*$c[4]")->reduce;
if ($correct != $student) {
$score[4] = 0;
}
else {
Context()->flags->set(bizarroDiv=>1,bizarroSub=>1,bizarroMul=>1);
delete $correct->{test_values}, $student->{test_values};
# Context()->flags->set(limits=>[0.25,0.4]);
if (($correct != $student) || ($student != $correct)) {
$self->setMessage(5, "Your Wronskian answer is correct, but please simplify it further");
$score[4] = 0;
}
# Value->Error("Your Wronskian answer is correct, but please simplify it further") unless (($correct == $student) or ($student == $correct));
else {
$score[4] = 1;
}
Context()->flags->set(bizarroDiv=>0,bizarroSub=>0,bizarroMul=>0);
}
###### Check W1 Determinant contingent on the choices made by student in W above.
$i = 5; # offset
## Check first column is 0, f(x)
$score[$i] = ($c[$i]->typeMatch($s[$i]) && $c[$i] == $s[$i]);
$score[$i+2] = ($c[$i+2]->typeMatch($s[$i+2]) && $c[$i+2] == $s[$i+2]);
## Check second column contingent on student choices made in W above.
$score[$i+1] = ($c[$i+1]->typeMatch($s[$i+1]) && $s[1] == $s[$i+1]);
$score[$i+3] = ($c[$i+3]->typeMatch($s[$i+3]) && $s[3] == $s[$i+3]);
## Check determinant W1
$off = 0;
if ($flag==-1) { $off = 5;}
$student = Formula("$s[$i+4]"); $correct = Formula("$flag*$c[$i+4+$off]")->reduce;
if ($correct != $student) {
$score[$i+4] = 0;
}
else {
Context()->flags->set(bizarroDiv=>1,bizarroMul=>1);
delete $correct->{test_values}, $student->{test_values};
# Context()->flags->set(limits=>[0.25,0.4]);
if (($correct != $student) || ($student != $correct)) {
$self->setMessage($i+5, "Your W1 answer is correct, but please simplify the final determinant expression further");
$score[$i+4] = 0;
}
# Value->Error("Your Wronskian answer is correct, but please simplify it further") unless (($correct == $student) or ($student == $correct));
else {
$score[$i+4] = 1;
}
Context()->flags->set(bizarroDiv=>0,bizarroMul=>0);
}
###### Check W2 Determinant contingent on the choices made by student in W above.
$i = 10; # offset
## Check second column is 0, f(x)
$score[$i+1] = ($c[$i+1]->typeMatch($s[$i+1]) && $c[$i+1] == $s[$i+1]);
$score[$i+3] = ($c[$i+2]->typeMatch($s[$i+2]) && $c[$i+3] == $s[$i+3]);
## Check first column contingent on student choices made in W above.
$score[$i] = ($c[$i]->typeMatch($s[$i]) && $s[0] == $s[$i]);
$score[$i+2] = ($c[$i+2]->typeMatch($s[$i+2]) && $s[2] == $s[$i+2]);
## Check determinant W2
$student = Formula("$s[$i+4]"); $correct = Formula("$flag*$c[$i+4-$off]")->reduce;
if ($correct != $student) {
$score[$i+4] = 0;
}
else {
Context()->flags->set(bizarroDiv=>1,bizarroMul=>1);
delete $correct->{test_values}, $student->{test_values};
## Context()->flags->set(limits=>[0.25,0.4]);
if (($correct != $student) || ($student != $correct)) {
$self->setMessage($i+5, "Your W2 answer is correct, but please simplify the final determinant expression further");
$score[$i+4] = 0;
}
# Value->Error("Your Wronskian answer is correct, but please simplify it further") unless (($correct == $student) or ($student == $correct));
else {
$score[$i+4] = 1;
}
Context()->flags->set(bizarroDiv=>0,bizarroMul=>0);
}
#### Check for u1 prime
$student = Formula("$s[15]");
if ($flag == -1) {
$correct2 = Formula("$c[15]")->reduce;
$correct = Formula("$c[16]")->reduce;
}
else {
$correct2 = Formula("$c[16]")->reduce;
$correct = Formula("$c[15]")->reduce;
}
if ($correct != $student) {
$score[15] = 0;
}
else {
Context()->flags->set(bizarroDiv=>1,bizarroMul=>1);
delete $correct->{test_values}, $student->{test_values};
## Context()->flags->set(limits=>[0.25,0.4]);
if (($correct != $student) || ($student != $correct)) {
$self->setMessage(16, "Your u1' is correct, but please simplify the final expression further");
$score[15] = 0;
}
# Value->Error("Your Wronskian answer is correct, but please simplify it further") unless (($correct == $student) or ($student == $correct));
else {
$score[15] = 1;
}
Context()->flags->set(bizarroDiv=>0,bizarroMul=>0);
}
#### Check for u2 prime
$student = Formula("$s[16]");
if ($correct2 != $student) {
$score[16] = 0;
}
else {
Context()->flags->set(bizarroDiv=>1,bizarroMul=>1);
delete $correct2->{test_values}, $student->{test_values};
## Context()->flags->set(limits=>[0.25,0.4]);
if (($correct2 != $student) || ($student != $correct2)) {
$self->setMessage(17, "Your u2' is correct, but please simplify the final expression further");
$score[16] = 0;
}
else {
$score[16] = 1;
}
Context()->flags->set(bizarroDiv=>0,bizarroMul=>0);
}
#### Check for u1
$student = Formula("$s[17]");
if ($flag == -1) {
$correct2 = Formula("$c[17]")->reduce;
$correct = Formula("$c[18]")->reduce;
}
else {
$correct2 = Formula("$c[18]")->reduce;
$correct = Formula("$c[17]")->reduce;
}
$score[17] = ($student == $correct || $correct == $student);
#### Check for u2
$student = Formula("$s[18]");
$score[18] = ($student == $correct2 || $correct2 == $student);
return [ @score ];
}
);
##################################
# reset the context and get rid of adaptive parameters
Context("Numeric");
Context()->variables->add(
'y' =>'Real','t' =>'Real',
'c1'=>'Real',
'c2'=>'Real',
);
Context()->variables->remove('x');
Context()->variables->set(
'c1'=>{limits=>[2,4]},
'c2'=>{limits=>[2,4]},
'y'=>{limits=>[-2,2]},
't'=>{limits=>[-2,2]}
);
$yhomogeneous = Compute("c1 e^($r t) + c2 t e^($r t)");
Context()->texStrings;
BEGIN_TEXT
Use variation of parameters to find a particular solution to:
\(\quad \displaystyle {y'' + $a y' + $b y = \frac{$c e^{$r t}}{t^2+1}} \).
\{ BeginList('OL',type=>'a') \}
$ITEM Find the most general solution to the
associated homogeneous differential equation.
Use \( c_1 \) and \( c_2 \) in your answer to denote arbitrary constants. $BR
Enter \( c_1 \) as ${BTT}c1${ETT} and \( c_2 \) as ${BTT}c2${ETT}.
$BR
$BR
\( y_c = \)
\{ ans_rule(60) \}
$ITEMSEP
$ITEM Use the two independent solutions of the homogeneous form of the DE to enter the Wronskian determinant, \(W\):
$PAR
$BCENTER
\{
mbox(
"\(W = \mathrm{det} \)",
display_matrix([
[$multians1->ans_rule(20),$multians1->ans_rule(20)],
[$multians1->ans_rule(20),$multians1->ans_rule(20)]], align=>'cc'),
" = ".$SPACE.$multians1->ans_rule(30)
);
\}
$ECENTER
$ITEMSEP
$ITEM Now enter the determinants, \(W_1\) and \(W_2\):
$PAR
$BCENTER
\{
mbox(
"\(W_1 = \mathrm{det} \)",
display_matrix([
[$multians1->ans_rule(20),$multians1->ans_rule(20)],
[$multians1->ans_rule(20),$multians1->ans_rule(20)]], align=>'cc'),
" = ".$SPACE.$multians1->ans_rule(30)
);
\}
$ECENTER
$PAR
$BCENTER
\{
mbox(
"\(W_2 = \mathrm{det} \)",
display_matrix([
[$multians1->ans_rule(20),$multians1->ans_rule(20)],
[$multians1->ans_rule(20),$multians1->ans_rule(20)]], align=>'cc'),
" = ".$SPACE.$multians1->ans_rule(30)
);
\}
$ECENTER
$ITEMSEP
$ITEM Use these results to determine \(u_1^{\prime}\) and \(u_2^\prime\). (Please simplify them. This will make it easier to integrate in the next step.)
$PAR
\(u_1^\prime = \frac{W_1}{W} =\) \{$multians1->ans_rule(30) \}
$PAR
\(u_2^\prime = \frac{W_2}{W} =\) \{$multians1->ans_rule(30) \}
$ITEMSEP
$ITEM Now integrate \(u_1^{\prime}\) to determine \(u_1\),
$PAR
\(u_1 = \int{u_1^\prime\,dt} =\) \{$multians1->ans_rule(30) \} \( + \quad C_1\)
$PAR
and integrate \(u_2^{\prime}\) to determine \(u_2\).
$PAR
\(u_2 = \int{u_2^\prime\,dt} =\) \{$multians1->ans_rule(30) \} \( + \quad C_2\)
$ITEMSEP
$ITEM Finally, enter the simplest form of the particular solution you obtained (not including any terms that are part of the complementary solution to the homogeneous form of this DE).
$PAR
\(y_{p} = \) \{ans_rule(60)\}
\{ EndList('OL') \}
END_TEXT
Context()->normalStrings;
ANS( $yhomogeneous->cmp(
checker => sub {
my ( $correct, $student, $answerHash ) = @_;
my $stu = Formula($student);
################################
# Check for arbitrary constants
#
Value->Error("Is your answer the most general solution?")
if (
Formula($stu->D('c1'))==Formula(0) ||
Formula($stu->D('c2'))==Formula(0)
);
############################################
# Check for linear independence (Wronskian)
#
my $t = Real(1.24);
my $a11 = $stu->eval('c1'=>1,'c2'=>0,t=>$t,y=>0);
my $a12 = $stu->eval('c1'=>0,'c2'=>1,t=>$t,y=>0);
my $a21 = $stu->D('t')->eval('c1'=>1,'c2'=>0,t=>$t,y=>0);
my $a22 = $stu->D('t')->eval('c1'=>0,'c2'=>1,t=>$t,y=>0);
# my $wronskian = $a11*$a22 - $a21*$a12;
# Value->Error("Your functions are not linearly independent or your answer is not complete")
# if ($wronskian==Real(0));
Value->Error("Your functions are not linearly independent or your answer is not complete")
if ($a11 * $a22 == $a21 * $a12);
########################################################
# Check that the student answer is a solution to the DE
#
my $stu1 = Formula($stu->D('t'));
my $stu2 = Formula($stu->D('t','t'));
return (($stu2 + $a*$stu1) == (-1 * $b * $stu));
}));
ANS( $multians1->cmp());
ANS( $yp->cmp() );
ENDDOCUMENT() ;
Please let me know if you have any ideas about where my issue may be.
Thanks!
Paul