WeBWorK Problems

Symbolic pi and function evaluations

Symbolic pi and function evaluations

by Ryan Hass -
Number of replies: 5
I'm new to WeBWorK and I'd like some guidance in writing a problem.  I would like to evaluate a function a particular point p.  The point p is to be expressed in terms of pi, say pi / 4, and the answer to the problem computed in terms of p.

From there, I would like to display the question as follows:

Find f(p) = [______]
or
Find sin(p) = [______]

where p is displayed as its exact value, \frac {\pi} 4, and not as a decimal

I understand how I could solve this problem if I wrote out everything explicitly, but I would like the code to be robust enough to let me define p at the beginning and have the rest of the code remain unchanged.

My current solution displays the point p as decimal and I cannot figure out how to replace sin(x) with sin(p) without computing sin(p) directly.  Can anyone offer any advice?  


###########################
#  Initialization

DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"contextFraction.pl",
"AnswerFormatHelp.pl",
"PGML.pl",
"PGcourse.pl",
);

TEXT(beginproblem());

$showPartialCorrectAnswers = 1;


###########################
#  Setup

Context("Numeric");
$f = Formula("sin(x)");
$p = PI();

$answer = $f -> eval(x => $p);
$point = $f -> substitute(x => $p);

Context()->functions->disable("Trig");

###########################
#  Main text

BEGIN_PGML
Let [` f(x) = [$f] `].  

Then
[`f([$p])`] = [_______________]{$answer->cmp()}

[`[$point]`] = [_______________]{$answer->cmp()}

END_PGML

ENDDOCUMENT();
In reply to Ryan Hass

Re: Symbolic pi and function evaluations

by Alex Jordan -
Try this. Some explanatory comments embedded.

DOCUMENT();

loadMacros(
"PGstandard.pl",
"PGML.pl",
);

Context("Numeric");
#Make it so Formula objects don't turn pi into 3.14..., nor pi/2 into 1.57...
Context()->flags->set(reduceConstants=>0);
#For good measure, make it so Formula objects don't turn sin(1) into 0.84..., nor sqrt(2) into 1.41...

Context()->flags->set(reduceConstantFunctions=>0);

$f = Formula("sin(x)");
#Define $p as a Formula, not a Real
$p = Formula("pi");
$point = $f -> substitute(x => $p);

#Since $p is a Formula and not a real, you can't evaluate $f at $p (unless you first somehow turning $p into a Real). Instead, turn $point into a Real.
$answer = $point->eval(x=>1);

Context()->functions->disable("Trig");

BEGIN_PGML

[`f([$p])`] = [_______________]{$answer}

[`[$point]`] = [_______________]{$answer}

END_PGML


ENDDOCUMENT();



In reply to Alex Jordan

Re: Symbolic pi and function evaluations

by Paul Pearson -
Hi Ryan,

You could also use that 'pi' is a pre-defined MathObject in most (all?) contexts.  Here's a sample of code that uses formatStudentAnswer=>'parsed' to prevent student answers from being displayed using decimals in the 'Entered' column of the answer feedback table.  I added some randomization to the problem and used the TeX command '\pi' to display the pi symbol in the problem text displayed to the student.

Note: Each answer blank should have a unique MathObject answer associated to it.  Using a single MathObject $answer for two different answer blanks may cause answer checkers to fail.  If you have two answer blanks that have the same answer, you should create one MathObject answer for each answer blank, as was done using $answer1 and $answer2 below.  Also, since you're using the answer comparison method with the default values, you do not need the '->cmp' in '$answer1->cmp'.

Best regards,

Paul Pearson


###########################
#  Initialization

DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGML.pl",
"PGcourse.pl",
);

TEXT(beginproblem());

$showPartialCorrectAnswers = 1;


###########################
#  Setup

Context("Numeric");
Context()->flags->set(
    formatStudentAnswer=>'parsed'
);

$f = Formula("sin(x)");

$k = random(-1,1,2) * random(2,5,1);

$answer1 = $f -> eval(x => $k * pi);
$answer2 = $f -> eval(x => $k * pi);

Context()->functions->disable("Trig");

###########################
#  Main text

BEGIN_PGML
Let [` f(x) = [$f] `].  

Then
[`f( [$k] \pi)`] = [_______________]{$answer1}

[`\sin( [$k] \pi)`] = [_______________]{$answer2}

END_PGML

ENDDOCUMENT();
In reply to Paul Pearson

Re: Symbolic pi and function evaluations

by Alex Jordan -
Paul, could you elaborate on the need to use different Math Objects for different answer blanks, or point me to a good place where this is documented? I believe it; I'd just like to understand better what the deeper issue is. This is not something I have ever heard of.
In reply to Alex Jordan

Re: Symbolic pi and function evaluations

by Paul Pearson -
Hi Alex,

I'm not sure that it is documented anywhere.  During our MAA PREP workshop on authoring problems in WebWork, Davide Cervone said that every answer blank should have a unique MathObject associated to it.  Here's my understanding of how answer blanks work and the rationale behind Davide's statement:

  1. Answer blanks are either created by \{ ans_rule() \} in a BEGIN_TEXT / END_TEXT block or by [____] in a BEGIN_PGML / END_PGML block.

  2. In html mode, every answer blank generates html source code that includes a form input box with a unique name such as AnSwEr0001 that is automatically generated (it is also possible to manually generate the name, but that's rarely done).

  3. Best PG coding practices (as established by Davide Cervone) say that every answer blank should have a MathObject associated to it.  For instance, the MathObject $answer1 = Compute("sin(x)"); can be associated with an answer blank using \{ $answer1->ans_rule() \} in a BEGIN_TEXT / END_TEXT block or by using [_____]{$answer1} in a BEGIN_PGML / END_PGML block.  Doing this assures that the student answer typed into the html form input box is associated with the MathObject $answer1 because the student answer becomes part of the "data" of the object $answer1.

  4. When the student enters their answer in the html form input box and clicks "Submit Answers", WeBWorK needs to take the student answer from the html form and route it to the proper answer checker.  In PGML, this is done entirely by the code [____]{$answer1}, so a PGML problem author does not need to do anything additional.

    In non-PGML, the problem author has to include both \{ $answer1->ans_rule() \} to create the answer blank and also ANS( $answer1->cmp() ); after the BEGIN_TEXT / END_TEXT block to do answer checking.  In non-PGML, the order in which the answer blanks are created should be the same as the order in which the answers are checked.  By using $answer1->ans_rule(), the student answer becomes part of the "data" in the object $answer1, and the answer comparison method $answer1->cmp() can easily access that "data" in the object $answer1, i.e., the method ->cmp() can easily get the student answer from the data stored in $answer1 by the method ->ans_rule().

  5. Why should every answer blank have a unique MathObject answer?  It's so that the pipeline that connects the correct answer with the student answer and the answer checker does not get broken.  I think it's intuitively clear that having a bijective correspondence between MathObjects that are the correct answers and the answer blanks is a good idea.  It's also clear that implementing this bijective correspondence in Perl should be done using a pipeline that preserves the bijective correspondence.  In short, every answer blank should have a unique MathObject associated to it.
I'm sure there's a better (more concise and clearer) technical answer that Davide Cervone could give.  If "Euler is the master of us all" in the realm of mathematics, then the same could be said of Davide in the realm of WeBWorK (and MathJax, and ...).

Best regards,

Paul Pearson
In reply to Alex Jordan

Re: Symbolic pi and function evaluations

by Ryan Hass -
I greatly appreciate the quick responses to my question.  I look forward to getting this approach up and working.