## WeBWorK Problems

### How to put primes in Formulas? ### How to put primes in Formulas?

by Fred Sullivan -
Number of replies: 20
I'm trying to format a DE, where the coefficients are variables, so I'd like to be able make the equation a formula and use reduce to make it pretty.

I can do this:

$a = random(6,10,1);$b = random(2,5,1);
$c = random(6,10,1);$fa = Formula("$a y")->reduce;$fb = Formula("$b y")->reduce;$fc = Formula("$c y")->reduce; ... Find the general solution for the equation $$fa'' + fb' + fc = 0$$. but it's painful, and doesn't work if I allow negative coefficients. I'd like to be able to just do$f = Formula("$a y'' +$b y' + $c y")->reduce; ... Find the general solution for the equation $$f = 0$$. But this is errormatic. Is there a way to put a prime into a Formula? In reply to Fred Sullivan ### Re: How to put primes in Formulas? by Davide Cervone - If you want them only for display (not for use in student answers), here is one approach. You need to add a a prime operator to the Context, and that requires you to make a subclass of the Parser's unary operator class. Here's code to do it:  # # Define a prime subclass of the unary operator class # package my::UOP::prime; our @ISA = ('Parser::UOP'); # # Do a typecheck on the operand # sub _check { my$self = shift;
return if $self->checkInfinite ||$self->checkString ||
$self->checkList ||$self->checkNumber;
$self->{type} = {%{$self->{op}->typeRef}};
}

#
#  A hack to prevent double-primes from inserting parentheses
#   in string and TeX output (change the precedence to hide it)
#
sub string {
my ($self,$precedence,$showparens,$position,$outerRight) = @_; my$uop = $self->{def};$precedence -= .01 if $uop->{precedence} ==$precedence;
return $self->SUPER::string($precedence,$showparens,$position,$outerRight); } sub TeX { my ($self,$precedence,$showparens,$position,$outerRight) = @_;
my $uop =$self->{def}; $precedence -= .01 if$uop->{precedence} == $precedence; return$self->SUPER::TeX($precedence,$showparens,$position,$outerRight);
}

#
#  Add prime to the given or current context
#
sub Enable {
my $self = shift; my$context = shift || main::Context();
$context->operators->add("'"=>{ precedence => 8.5, associativity => "right", type => "unary", string => "'", class => "my::UOP::prime", isCommand => 1 }); } sub Disable { my$self = shift; my $context = shift || main::Context();$context->operators->remove("'");
}



The Enable routine is the one you call to add the operator to the current context. You can put the code into a macro file (either in the same directory with the problems that use it, or in the course templates/macros directory, or somewhere else in the macros path). If you call it "parserPrime.pl", then code that uses it could look like:

    loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"parserPrime.pl"
);

my::UOP::prime->Enable;    #  add primes to it

#  create $a,$b, c here

$f = Formula("$a y'' + $b y' +$c y")->reduce;
$ans = Formula("..whatever..."); Context()->texStrings; BEGIN_TEXT Find the general solution to $$f = 0$$: \{ans_rule(30)\} END_TEXT Context()->normalStrings; my::UOP::prime->Disable; # don't allow students to enter primes ANS(Formula($ans)->cmp);


It's a little complicated, but can be done. Note that this is for display purposes only. Primes can NOT be used in the student or correct answers, as we have not implemented the eval method, which is needed for that. To do it right, we would also need to implement call and perl to handle the derivatives, though I'm not sure everything would work out for that.

Hope that helps.

Davide ### Re: How to put primes in Formulas?

by Davide Cervone -
Well, I worked out the eval, call, and perl issues (and also reduce, and D), so that I have a working prime operator that does differentiation. I have added the parserPrime.pl file to the pg/macros directory so that you can get it from there. See the documentation at the top of the file for how to use it. It is slightly different from what I have listed above.

Hope that helps.

Davide

PS, it would probably be possible to use d/dx(...) notation to do differentiation as well. Would that be a help to anyone? ### Re: How to put primes in Formulas?

by Davide Cervone -
There is an alternative approach that might be easier in this case. You could add y' and y'' to the context as variables so that they could be used in Formulas without defining the prime operator. The difficulty is that variable names can only include alphabetic and numeric characters, an the underscore. To get around that, you need to change the name patter for variables. For example,
    Context()->variables->{namePattern} = qr/[a-z][a-z0-9_]*'*/i;

would allow variable names to end in any number of primes. So you could do the following:
    Context()->variables->{namePattern} = qr/[a-z][a-z0-9_]*'*/i;
...
$f = Formula("$a y'' + $b y' +$c y")->reduce;

Ideally, this would also allow you to have students give answers that have derivatives in them, but due to the way that variables are inserted into the perl-code that underlies the formulas, that will generate illegal perl variable names. I have updated MathObjects to correctly handle these variables, but you would need to update your copy of pg/lib/Parser.pm and pg/lib/Parser/Variable.pm in order to take advantage of that. So until you update, this is for display purposes only.

Hope that helps.

Davide ### Re: How to put primes in Formulas?

by Fred Sullivan -

It would be nice to allow answers with primes, so that the first question on a word problem could be what's the differential equation. Having the ability to use d/dt would be useful, but not essential. Of course, we'd need d^2/dt^2 as well, since there's probably more work with second order equations. Higher derivatives could be handled with primes, I think.

This is excellent. I'll be writing an assignment using this stuff this weekend. ### Re: How to put primes in Formulas?

by Davide Cervone -
The variable approach certainly would work for getting you the primes in student answers. The parserPrime.pl file could be used for that in a sneeky way. It would allow more flexibility in the format of answers, like (y')' would be accepted as y'', and (y+y)' would be the same as (2y)', but you might not want that flexibility.

In any case, to do this, you would need to add a "constant" that is really a formula. The constant will be shown in the correct and student answers, but the formula will be used in determining equality of the two differential equations. For example,

    loadMacros("parserPrime.pl");
parser::Prime->Enable('x');

$f = Formula("y'' + 2y' + y"); ... ANS($f->cmp);

Here, the formula given for y when it is added to the constants should be something that will have different values for different derivatives, and will not be something the student is likely to type themselves. It's a bit of a hack, but I think it should work reasonably well. In any case, using y' and y'' as variables is also a hack.

But, in order to make this work, you will need to update your copies of pg/lib/Parser/Constant.pm, pg/lib/Parser/Differentiation.pm, and pg/macros/parserPrime.pl to the most current HEAD versions. These include corrections needed for handling Formula-valued constants properly.

See if that helps.

Davide ### Re: How to put primes in Formulas?

by Darwyn Cook -
Davide,
I just updated Webwork to the rel-patches and was able to get a similar problem to work. However I wanted to use this same idea in an implicit equation, if a make a couple of changes the problem to use parserImplicitEquation I get an error I can't fix.

My code:

DOCUMENT();

# Load the macro file to create graphs.
# Load whatever macros you need for the problem
"PGbasicmacros.pl",
"PGchoicemacros.pl",
"PGauxiliaryFunctions.pl",
"MathObjects.pl",
"parserImplicitEquation.pl");
$showPartialCorrectAnswers = 1; ## Display the problem information TEXT(beginproblem()); ########################################################################## ## ## Allow variable names with primes in them ## Context("ImplicitEquation")->variables->{namePattern} = qr/[a-z][a-z0-9_]*'*/i; Context()->variables->add("y'"=>"Real","y''"=>"Real"); Context()->strings->are(linear=>{},nonlinear=>{});$linear = String(linear);
$non = String(nonlinear);$eqn1 = ImplicitEquation("y'+y=0");
Context()->texStrings;
BEGIN_TEXT
$$eqn1$$ is a \{ pop_up_list([$linear->string,$non->string]) \} differential equation.
END_TEXT
Context()->normalStrings;
ANS($linear->cmp); ENDDOCUMENT(); Which produces the following error(s): ### Error messages Global symbol "$y" requires explicit package name at line 6 of (eval 2079). Global symbol "$oldContext" requires explicit package name at (eval 2079) line 7. Global symbol "@result" requires explicit package name at (eval 2079) line 8. Global symbol "@result" requires explicit package name at (eval 2079) line 8. at line 341 of (eval 2058) Died within ImplicitEquation::getPositiveNegativeZero called at line 299 of [PG]/macros/parserImplicitEquation.pl from within ImplicitEquation::createPoints called at line 233 of [PG]/macros/parserImplicitEquation.pl from within ImplicitEquation::new called at line 2 of (eval 2077) from within main::ImplicitEquation called at line 54 of [TMPL]/alfredLibrary/diffeq/intro/order.pg  ### Error details  Problem1 ERROR caught by Translator while processing problem file:alfredLibrary/diffeq/intro/order.pg **************** Global symbol "$y" requires explicit package name at line 6 of (eval 2079).
Global symbol "$oldContext" requires explicit package name at (eval 2079) line 7. Global symbol "@result" requires explicit package name at (eval 2079) line 8. Global symbol "@result" requires explicit package name at (eval 2079) line 8. at line 341 of (eval 2058) Died within ImplicitEquation::getPositiveNegativeZero called at line 299 of [PG]/macros/parserImplicitEquation.pl from within ImplicitEquation::createPoints called at line 233 of [PG]/macros/parserImplicitEquation.pl from within ImplicitEquation::new called at line 2 of (eval 2077) from within main::ImplicitEquation called at line 54 of [TMPL]/alfredLibrary/diffeq/intro/order.pg **************** ------Input Read 1 ##DESCRIPTION 2 # 3 # File Created: 12/13/2009 4 # Last Modified: 12/13/2009 5 # Problem Author: Darwyn Cook 6 # WeBWorK Entry: 7 # Location: Alfred University 8 # 9 ##ENDDESCRIPTION 10 11 ##KEYWORDS() 12 ## 13 14 ## DBsubject('Calculus') 15 ## DBchapter('Differential Equations') 16 ## DBsection('Introduction to Differential Equations') 17 ## Date('12/13/2009') 18 ## Author('Darwyn Cook') 19 ## Institution('Alfred University') 20 ## TitleText1('Differential Equations: with Boundary Value Problems') 21 ## EditionText1('6') 22 ## AuthorText1('Zill') 23 ## Section1('') 24 ## Problem1('') 25 26 DOCUMENT(); 27 28 # Load the macro file to create graphs. 29 loadMacros("PGgraphmacros.pl"); 30 # Load whatever macros you need for the problem 31 loadMacros("PG.pl", 32 "PGbasicmacros.pl", 33 "PGchoicemacros.pl", 34 "PGanswermacros.pl", 35 "PGauxiliaryFunctions.pl", 36 "MathObjects.pl", 37 "parserImplicitEquation.pl"); 38 ## Show partial correct answers 39$showPartialCorrectAnswers = 1;
40 ## Display the problem information
41 TEXT(beginproblem());
42
43
44 ##########################################################################
45 ##
46 ## Allow variable names with primes in them
47 ##
48 Context("ImplicitEquation")->variables->{namePattern} = qr/[a-z][a-z0-9_]*'*/i;
50 Context()->strings->are(linear=>{},nonlinear=>{});
51 $linear = String(linear); 52$non = String(nonlinear);
53
54 $eqn1 = ImplicitEquation("y'+y=0"); 55 Context()->texStrings; 56 BEGIN_TEXT 57 $$eqn1$$ is a \{ pop_up_list([$linear->string,$non->string]) \} differential equation. 58 END_TEXT 59 Context()->normalStrings; 60 ANS($linear->cmp);
61 ENDDOCUMENT(); ### Re: How to put primes in Formulas?

by Davide Cervone -
Well, the problem is the one I mentioned above, which is that the approach of adding ' to the allowed variable names causes MathObjects to produce illegal perl variables when the object is turned into perl code for evaluation or comparisons. While you are not explicitly evaluating this formula, calling ImplicitEquation does cause the formula to be computed behind the scenes (as part of setting up the implicit equation object).

Try using Formula() rather than ImplicitEquation() and see of that doesn't work for you (since you don't really need $eqn1 to be an actual ImplicitEquation object.) You are really only using ImplicitEquation context to get the equal sign into your formula; it would be possible to just enable the equal sign in Numeric context and avoid the implicit equation issues entirely. To do that, use  Context("Numeric")->variables->{namePattern} = qr/[a-z][a-z0-9_]*'*/i; Context()->variables->add("y"=>"Real","y'"=>"Real","y''"=>"Real"); Context()->strings->are(linear=>{},nonlinear=>{}); Parser::BOP::equality->Allow;$eqn1 = Formula("y'+y=0");

Note the addition of the variable "y" to the context as well as the equality.

I actually did fix the variable-name problem in version 1.56 of pg/lib/Parser.pm, but that hasn't made it into the patches release yet. You should be able to update just that one file (I checked and it doesn't look like any of the other changes require other files to be updated), if you prefer to go that way. I tested your problem with the current HEAD version, and it works properly there.

Hope that helps.

Davide ### Re: How to put primes in Formulas?

by Darwyn Cook -
Davide,
Thanks for the quick reply. For the purpose of the problem I am writing, which is just to display the equation, I could just TeX the formulas in the problem. An alternative I decided to use for this problem is to create a list of variables that I then give a TeX alias to.

I was trying this technique to see if I could make it work for problems where the answer will be a differential equation in prime notation. I can make that work simply enough by using formulas. by Darwyn Cook -
Davide,
After a recent update of webwork I reinstalled the head version of Parser.pm, but it caused an error: Global symbol "$main::__files__" requires explicit package name at (eval 3373) line 6. Are there some other files I need to upgrade to the head version to match? In reply to Darwyn Cook ### Re: How to put primes in Formulas? by Davide Cervone - Can you send the full error message? It gives information about about where WeBWorK was in its code when the error occurred, and it is hard to tell where this error is occurring from this single message. I do not think it is due to the updated Parser.pm. Did you run the updated WeBWork BEFORE updating Parser.pm? If so, did it work? If not, try going back to the earlier version of Parser.pm and see. The error message concerns the method WeBWorK uses to include macro files, and that is in the webwork2 directory tree, no the pg tree. It should be safe to update ALL of pg if you want to try that. But I don't think that's where the problem is. Davide PS, be sure to restart the server after making any of these changes. In reply to Davide Cervone ### Re: How to put primes in Formulas? by Darwyn Cook - Davide, I decided to start fresh, so I reload Parser.pm to the head version (1.56), and rebooted. We are getting this error: ## WeBWorK Warnings WeBWorK has encountered warnings while processing your request. If this occured when viewing a problem, it was likely caused by an error or ambiguity in that problem. Otherwise, it may indicate a problem with the WeBWorK system itself. If you are a student, report these warnings to your professor to have them corrected. If you are a professor, please consult the warning output below for more information. ### Warning messages • Variable "$C" is not imported at line 6 of (eval 8906)
•  (Did you mean &main::__files__ instead?)

From this problem:

"PGstandard.pl",
"MathObjects.pl",
"PGchoicemacros.pl",
# "parserNumberWithUnits.pl",
# "parserFormulaWithUnits.pl",
# "parserFormulaUpToConstant.pl",
# "PGcourse.pl",
);

Context("Numeric");

$showPartialCorrectAnswers = 1;$a = random(2,4,1);
$x0 = random(2,5,1);$y0 = random(10,50,5);

$ans0 = Formula("0 x^n");$ans1 = Formula("C x^($a)");$multipart = MultiAnswer($ans0,$ans1)->with(
singleResult => 0,
checker => sub {
my ( $correct,$student, $self ) = @_; my ($f1stu, $f2stu ) = @{$student};
my ( $f1,$f2 ) = @{$correct}; if ( ($f1 == $f1stu &&$f2 == $f2stu) || ($f1 == $f2stu &&$f2 == $f1stu) ) { return [1,1]; } else { if ($f1 == $f1stu ||$f2 == $f1stu) { return [1,0]; } elsif ($f1 == $f2stu ||$f2 == $f2stu) { return [0,1]; } else { return [0,0]; } } } ); TEXT(beginproblem()); Context()->texStrings; BEGIN_TEXT${BBOLD}(a)$EBOLD Consider the differential equation $x\frac{dy}{dx} - a y = 0.$$BR
Find a general solution to this differential equation that
has the form $$y = Cx^n$$.
$BR $$y =$$ \{ ans_rule(35) \}.$BR
Find a second solution $$y = Cx^n$$ that might not be a
general solution and which may have a different value of $$n$$
$BR $$y =$$ \{ ans_rule(35) \}.$PAR
${BBOLD}(b)$EBOLD
If the solution additionally satisfies $$y=y0$$ when $$x=x0$$,
what is the solution?
$BR $$y =$$ \{ ans_rule(35) \} END_TEXT Context()->normalStrings; # ANS($multipart->cmp() );
ANS( $ans1->cmp() ); ANS($ans0->cmp() );
ANS( Compute("$y0*(x/$x0)^($a)")->cmp() ); I am also having trouble with the questions that involve primes. Here is a simple problem I had working before: loadMacros("PG.pl", "PGbasicmacros.pl", "PGchoicemacros.pl", "PGanswermacros.pl", "PGauxiliaryFunctions.pl", "MathObjects.pl"); TEXT(beginproblem()); ######################################################### ## ## Set up the context to allow ' in variable names ## Context()->variables->{namePattern} = qr/[a-z][a-z0-9_]*'*/i; Context()->variables->are("x"=>"Real","y"=>"Real","y'"=>"Real","y''"=>"Real");$f = Formula("1+y'+y''")->reduce;

Context()->texStrings;
BEGIN_TEXT
$PAR Rewrite the differential equation in prime notation: $$y(x) =1+\frac{dy}{dx}+\frac{d^2y}{dx^2}$$ then$BR
$$y(x) =$$ \{$f->ans_rule()\} END_TEXT ANS($f->cmp);
Context()->normalStrings;

That now returns the error

### Warning messages

• String found where operator expected at line 6 of (eval 10799), near "$y') +$y'"
•  (Missing operator before ') + $y'?) • String found where operator expected at line 6 of (eval 10799), at end of line •  (Missing operator before ?) P.S. I did a webwork update rel-2-4-patches three weeks ago, and as I mentioned above just updated Parser.pm to the HEAD version. In reply to Darwyn Cook ### Re: How to put primes in Formulas? by Davide Cervone - The errors at the end of the second problem suggest that you are not using the new version of Parser.pm. Are you sure you updated it correctly? How did you go about that? Also, are you sure your web server is running the updated copy of WeBWorK? Could it be that there is more than one WeBWorK on your system and it is using an older copy, and so not using the new Parser.pm? I am not able to reproduce either error. Both problems work as expected for me. Davide In reply to Davide Cervone ### Re: How to put primes in Formulas? by Darwyn Cook - I moved Parser.pm to Parser.pm.bak (moved, not copied) then performed cvs update -A Parser.pm. Then I did cvs status Parser.pm and got the version 1.56 you mentioned above. Well I moved Parser.pm.bak back to Parser.pm and did cvs status Parser.pm again, and it also says it is version 1.56. Modulo not liking the prime notation it works just fine. There are two problems ( I know of) that are giving me issues when Parser.pm is updated to the head version, and they both use PGchoicemacros.pl, which has the following status: File: PGchoicemacros.pl Status: Up-to-date Working revision: 1.8.2.1 Repository revision: 1.8.2.1 /webwork/cvs/system/pg/macros/PGchoicemacros.pl,v Sticky Tag: rel-2-4-patches (branch: 1.8.2.1.2) Sticky Date: (none) Sticky Options: (none) In reply to Darwyn Cook ### Re: How to put primes in Formulas? by Darwyn Cook - I did a cvs update -dP in webwork/pg and webwork/webwork2 and all files were up to date.  In reply to Darwyn Cook ### Re: How to put primes in Formulas? by Davide Cervone - FYI, just moving Parser.pm.bak back to Parser.pm will not cause CVS to think it is the old version (though WeBWorK will). CVS still thinks you have 1.56 checked out (since that is the last version you DID check out) and will consider the old version to be a locally modified copy. So you can't trust the 1.56 in that case. But it doesn't really matter. You might try updating the entire PG directory to HEAD, which should not be a problem. (But then, neither should going to the current Parser.pm by itself.) When you go back to the older Parser.pm, you say it works fine except for the prime notation. Do you get the same error message for that as you do with the new Parser.pm? Davide In reply to Davide Cervone ### Re: How to put primes in Formulas? by Darwyn Cook - Well know that you say it the comment on cvs not knowing I moved a file makes perfect sense. In response to your second question, yes I am getting the same message, the long version is: ### Warning messages • String found where operator expected at line 4 of (eval 3248), near "$K',$K'" •  (Missing operator before ',$K'?)
• String found where operator expected at line 4 of (eval 3248), near "',$K'',$K'"
•  (Missing operator before ',$K'?) • String found where operator expected at line 4 of (eval 3248), near "',$K'''"
•  (Missing operator before ''?)
• String found where operator expected at line 6 of (eval 3248), at end of line
•  (Missing operator before ?)

You made the point earlier that this shouldn't happen if webwork was finding the updated Parser.pm. I think that tomorrow morning, when I am pretty well guaranteed that no students will be on, I will take a more radical approach by reinstalling pg. If that doesn't work then I will follow it up by reinstalling webwork (with the appropriate backups of course).

It is clear from your comments that this is peculiar to our system, so maybe that will clear it up?

P.S. I took your comment about having a second webwork on our server to heart. I compared the directories on our production server with a fresh install on a virtual server and didn't see anything.
Oh yeah, I learned my lesson from before, I reboot frequently :) ### Re: How to put primes in Formulas?

by Darwyn Cook -
I should have said above that the virtual version of webwork I have on my laptop is not fully functional yet, just up to the point where I need to install the admin course. Otherwise I would have tested this out on there before bugging you.

At any rate, no luck for me. Here is what I did in order:
1) Updated pg to the head version using cvs update -A. Reboot, get both of the error messages from above when the head version of Parser.pm is installed.
2) Moved webwork2 to webwork2_save, deleted webwork2 and reinstalled from cvs. Didn't help.
3) Moved pg to pg_save, deleted pg, reinstalled pg from cvs to the rel-2-4-patches. Updated Parser.pm to the head version. Didn't work.

Since the production version of our webwork is on a virtual server I reverted back to the snapshot I took just before starting this.

The next step for me is to get the virtual webwork I have on my laptop working. If I can get the primes working on it then it will become production :) Time to go to bed. ### Re: How to put primes in Formulas?

by Darwyn Cook -
OK, I got the virtual machine on my laptop up and running. Updating Parser.pm to the head version did not work for me, but updating pg to the head version did.

After I got webwork up and running I deleted Parser.pm and performed a cvs update -A Parser.pm, then rebooted. I got a missing string error, which I wasn't clever enough to copy. Updated the pg directory by cvs update -A, rebooted, and it works fine.

Time to figure out what is up the production server now I guess. ### Re: How to put primes in Formulas?

by Darwyn Cook -
I don't if anyone is still following this saga, but here is the conclusion finally. After getting Parser.pm to work on my laptop I decided to give the virtual server one more try.

So I updated the entire pg directory to the head version again, rebooted, still didn't work. Then just for the heck of it I deleted Parser.pm and a backup I had made some time ago, Parser.pm.bak, and rebooted again. Then did the cvs to the head, rebooted again, and voila it works. Apparently the system needed to be rebooted in between deleting the files and updating from cvs.

I have to believe that the Parser.pm.bak was causing me trouble, although how that could be possible after I completely removed the pg directory last and did a "fresh install" of pg night is a mystery*. I will say that after removing the directory last night I did not reboot before reinstalling pg, which apparently was my mistake.

Oh yeah, the version of webwork on my laptop is clearly newer than the one on our production server, although they should be identical, the browser interface has clearly changed. So whatever is happening, updates don't seem to be.

*If you're wondering how a copy of Parser.pm.bak ended up in a directory that I completely removed - after my lack of success I reverted to a previous snapshot that still had that file.

Anyways, thanks again for the help Davide. 