WeBWorK Problems

oracle function and math objects

oracle function and math objects

by Darwyn Cook -
Number of replies: 4
I have rewritten one Rochester's oracle function problems to use mathobjects, in particular to define the function. I then use the perlFunction command to pass the function to the create the cubic spline. I believe this is necessary so that we are not passing Real mathobjects to the cubic spline. Anyways, it worked fine last year, I suspect that somewhere in the upgrades to 2-4-5 something has gone awry as I now get an infinite loop error message:

Error messages

Timeout after processing this problem for 60 seconds. Check for infinite loops in problem source Died within WeBWorK::PG::Local::alarm_handler called at line 26 of [PG]/lib/Value/Real.pm from within (eval) called at line 26 of [PG]/lib/Value/Real.pm from within Value::Real::new called at line 726 of [PG]/lib/Value.pm from within Value::promote called at line 742 of [PG]/lib/Value.pm from within Value::checkOpOrderWithPromote called at line 90 of [PG]/lib/Value/Real.pm from within Value::Real::div called at line 752 of [PG]/lib/Value.pm from within Value::binOp called at line 762 of [PG]/lib/Value.pm from within Value::_div called at line 326 of [PG]/macros/PGnumericalmacros.pl from within main::create_cubic_spline called at line 71 of [TMPL]/alfredLibrary/samples/oraclefunctionexample.pg

Error details

 Problem1
ERROR caught by Translator while processing problem file:alfredLibrary/samples/oraclefunctionexample.pg
****************
Timeout after processing this problem for 60 seconds. Check for infinite loops in problem source
 Died within WeBWorK::PG::Local::alarm_handler called at line 26 of [PG]/lib/Value/Real.pm
 from within (eval) called at line 26 of [PG]/lib/Value/Real.pm
 from within Value::Real::new called at line 726 of [PG]/lib/Value.pm
 from within Value::promote called at line 742 of [PG]/lib/Value.pm
 from within Value::checkOpOrderWithPromote called at line 90 of [PG]/lib/Value/Real.pm
 from within Value::Real::div called at line 752 of [PG]/lib/Value.pm
 from within Value::binOp called at line 762 of [PG]/lib/Value.pm
 from within Value::_div called at line 326 of [PG]/macros/PGnumericalmacros.pl
 from within main::create_cubic_spline called at line 71 of [TMPL]/alfredLibrary/samples/oraclefunctionexample.pg

****************

------Input Read
1 ##DESCRIPTION
2 #
3 # File Created:
4 # Last Modified: 5/13/2008
5 # Problem Author:
6 # WeBWorK Entry:
7 # Location:
8 #
9 ##ENDDESCRIPTION
10
11 ##KEYWORDS()
12 ##
13
14 ## DBsubject('WeBWorK')
15 ## DBchapter('WeBWorK Tutorial')
16 ## DBsection('Alfred Samples')
17 ## Date('')
18 ## Author('')
19 ## Institution('Rochester')
20 ## TitleText1('')
21 ## EditionText1('')
22 ## AuthorText1('')
23 ## Section1('')
24 ## Problem1('')
25
26
27 &DOCUMENT();
28
29 loadMacros("PG.pl",
30 "PGbasicmacros.pl",
31 "PGchoicemacros.pl",
32 "PGanswermacros.pl",
33 "PGnumericalmacros.pl",
34 "PGauxiliaryFunctions.pl",
35 "MathObjects.pl"
36 );
37
38 TEXT(beginproblem());
39
40 ## By default numbers are displayed at 6 decimal places of accuracy, this flag
41 ## displays them in their full precision.
42 Context()->{format}{number} = "";
43
44 # define function to be evaluated
45 $a= random(1,3,.1);
46 $b= random(-4,4,.1);
47 $c = random(-4,4,.1);
48 $x0=random(-2,2,0.1);
49 $function = Formula(" $a*x^2+$b*x +$c ");
50 $f = $function->perlFunction;
51 $df = $function->D('x');
52 $dfx0 = $df->eval(x=>$x0);
53
54
55 ## There are two sections of code now to create the oracle function. The first
56 ## section is to create a cubic spline approximation to the function that
57 ## can be passed to the html code that actually prints the oracle function.
58
59 ## Section 1: Creating the cubic spline approximation to f.
60
61 $llimit = -5; $rlimit = 5;
62 my $num_of_intervals = 500; # number of interpolation points
63 my $delta = ($rlimit-$llimit)/($num_of_intervals);
64 my (@x_values, @y_values);
65 foreach my $i (0..$num_of_intervals) {
66 my $x = $llimit + $delta*$i;
67 my $y = &$f($x);
68 push(@x_values, $x); push(@y_values,$y);
69 }
70
71 ($t_ref, $a_ref, $b_ref, $c_ref, $d_ref) = create_cubic_spline (~~@x_values, ~~@y_values);
72
73 $f_approx = cubic_spline(~~@x_values, ~~@y_values);
74
75 #calculate a javaScript runtime cubic spline representation of this function.
76
77 HEADER_TEXT(javaScript_cubic_spline(~~@x_values,~~@y_values, name => 'func', llimit => -3, rlimit => 3) );
78
79 ## End cubic spline creation.
80
81
82
83 # A warning that we are using javaScript
84 TEXT(M3("",
85 "\begin{rawhtml}
86 <NOSCRIPT> This problem requires that Java Script be enabled </NOSCRIPT> \end{rawhtml}
87 ",
88 "<NOSCRIPT> This problem requires that Java Script be enabled </NOSCRIPT>"
89 ));
90
91
92 BEGIN_TEXT
93 $PAR
94 The oracle function \( f(x) \) is presented below. For each \(x\) value you enter the oracle will
95 tell you the value \( f(x) \).
96 Calculate the derivative of the function at \( $x0 \) using the Newton quotient definition.
97 $PAR
98 END_TEXT
99
100
101 ## This section is the javascript to print the oracle function.
102
103 $javaScript2 = begintable(3) .
104 MODES(HTML =>q{<TR>
105 <TH>x</TH><TH></TH><TH>f(x)</TH>
106 <TR>},
107 TeX => "x & \(\rightarrow\) & f(x)\\"
108 ) .
109 row(MODES(HTML => qq{<INPUT TYPE="text" NAME="Input" Value = "$x0" Size="16">}, TeX => '\fbox{Enter \(x\)}' ),
110 MODES(HTML => qq{<INPUT TYPE="button" VALUE="---f-->"
111 OnClick="this.form.Output.value=func(this.form.Input.value);">}, TeX => '\(\rightarrow\)' ),
112 MODES(HTML => qq{<INPUT TYPE="text" NAME="Output" Size="30">}, TeX => 'result: \(f(x)\)')
113 ) .
114 row(MODES(HTML => qq{<INPUT TYPE="text" NAME="Input2" Value = "$x0" Size="16">}, TeX => '\fbox{Enter \(x\)}' ),
115 MODES(HTML => qq{<INPUT TYPE="button" VALUE="---f-->"
116 OnClick="this.form.Output2.value=func(this.form.Input2.value);">}, TeX => '\(\rightarrow\)' ),
117 MODES(HTML => qq{<INPUT TYPE="text" NAME="Output2" Size="30">}, TeX => 'result: \(f(x)\)')
118 ) .
119 row(MODES(HTML => qq{<INPUT TYPE="text" NAME="Input3" Value = "$x0" Size="16">}, TeX => '\fbox{Enter \(x\)}' ),
120 MODES(HTML => qq{<INPUT TYPE="button" VALUE="---f-->"
121 OnClick="this.form.Output3.value=func(this.form.Input3.value);">}, TeX => '\(\rightarrow\)' ),
122 MODES(HTML => qq{<INPUT TYPE="text" NAME="Output3" Size="30">}, TeX => 'result: \(f(x)\)')
123 ) . endtable();
124
125 TEXT($javaScript2);
126
127 ## End the javascript printing section.
128
129
130 BEGIN_TEXT
131 $PAR
132 Remember the technique for finding instantaneous velocities from average velocities?
133 This is the same thing.
134
135 END_TEXT
136 # The answer
137
138 Context()->flags->set(
139 tolerance => 1,
140 tolType => 'relative',
141 format => '%0.14g');
142
143 my ($ans_eval) = num_cmp( $dfx0, reltol => 1, format => '%0.14g');
144
145
146 # we'll modify the answer messages a bit to give some encouragement.
147 my $answer_evaluator = sub {
148 my $x = shift;
149 my $ans_hash = $ans_eval->evaluate($x);
150 return $ans_hash unless $x;
151 # otherwise fix the error message
152 $correct_answer = $ans_hash->{correct_ans};
153 my $error = $correct_answer - $ans_hash ->{student_ans};
154 #warn "correct answer $correct_answer and student answer", $ans_hash ->{student_ans}, "error $error";
155 my $relerror = 100* abs($error/$correct_answer) unless abs($correct_answer) <.000000001 ;
156 $relerror = .000000001 unless defined($relerror);
157 if ($relerror < 1 ) {
158 $ans_hash->{ans_message} = "Good. Your answer is off by only about $error";
159 } elsif ($relerror < 10 ) {
160 $ans_hash->{ans_message} = 'Your answer is within 10%. ';
161 } elsif($relerror < 50) {
162 $ans_hash->{ans_message} = 'Your answer is within 50%. ';
163 } else {
164 $ans_hash->{ans_message} = 'Your answer is off by more than 50%.';
165 }
166 $ans_hash;
167 };
168
169 ANS($answer_evaluator ); #We are allowing 1 percent error for the answer.
170
171
172 &ENDDOCUMENT;



In reply to Darwyn Cook

Re: oracle function and math objects

by Darwyn Cook -
Well maybe this is not an issue with that particular problem after all, but something else. When generating a hardcopy for some problem sets I get similar errors. Is it possible these are related?
Here is one example of errors from generating hardcopy:

Hardcopy Generator

2 errors occured while generating hardcopy:

  • [edit] Errors encountered while processing problem '4' in set '1.5_Inverse_Functions' for user 'admin'. This problem has been omitted from the hardcopy. Error text:
    Timeout after processing this problem for 60 seconds. Check for infinite loops in problem source
     Died within WeBWorK::PG::Local::alarm_handler called at line 601 of [PG]/lib/Value.pm
     from within (eval) called at line 601 of [PG]/lib/Value.pm
     from within Value::inherit called at line 92 of [PG]/lib/Value/Real.pm
     from within Value::Real::div called at line 752 of [PG]/lib/Value.pm
     from within Value::binOp called at line 762 of [PG]/lib/Value.pm
     from within Value::_div called at line 359 of [PG]/lib/WWPlot.pm
     from within WWPlot::jj called at line 368 of [PG]/lib/WWPlot.pm
     from within WWPlot::lineTo called at line 310 of [PG]/lib/Fun.pm
     from within Fun::draw called at line 515 of [PG]/lib/WWPlot.pm
     from within WWPlot::draw called at line 470 of (eval 232)
     from within main::insertGraph called at line 142 of [TMPL]/Library/AlfredUniv/anton8e/chapter1/1.5/garcia1.pg
    
  • [edit] Errors encountered while processing problem '12' in set '1.5_Inverse_Functions' for user 'admin'. This problem has been omitted from the hardcopy. Error text:
    Timeout after processing this problem for 60 seconds. Check for infinite loops in problem source
     Died within WeBWorK::PG::Local::alarm_handler called at line 26 of [PG]/lib/Value/Real.pm
     from within (eval) called at line 26 of [PG]/lib/Value/Real.pm
     from within Value::Real::new called at line 726 of [PG]/lib/Value.pm
     from within Value::promote called at line 742 of [PG]/lib/Value.pm
     from within Value::checkOpOrderWithPromote called at line 90 of [PG]/lib/Value/Real.pm
     from within Value::Real::div called at line 752 of [PG]/lib/Value.pm
     from within Value::binOp called at line 762 of [PG]/lib/Value.pm
     from within Value::_div called at line 359 of [PG]/lib/WWPlot.pm
     from within WWPlot::jj called at line 368 of [PG]/lib/WWPlot.pm
     from within WWPlot::lineTo called at line 310 of [PG]/lib/Fun.pm
     from within Fun::draw called at line 515 of [PG]/lib/WWPlot.pm
     from within WWPlot::draw called at line 470 of (eval 232)
     from within main::insertGraph called at line 92 of [TMPL]/Library/Union/setFunctionInverses/ur_inv_3.pg
    


I am also including the code for ur_inv_3.pg, when I try to do this problem in webwork $graph_object4 is selected by the slice, but is not produced.
## DESCRIPTION
## Algebra
## ENDDESCRIPTION

## KEYWORDS('algebra','inverse functions','graph')
## Tagged by cmd6a 8/6/06

## DBsubject('Algebra')
## DBchapter('Functions')
## DBsection('Inverse Functions')
## Date('9/9/03')
## Author('')
## Institution('Union College')
## TitleText1('')
## EditionText1('')
## AuthorText1('')
## Section1('')
## Problem1('')

DOCUMENT(); # This should be the first executable line in the problem.

loadMacros(
"PG.pl",
"PGbasicmacros.pl",
"PGchoicemacros.pl",
"PGanswermacros.pl",
"PGauxiliaryFunctions.pl",
"PGgraphmacros.pl",
"PGunion.pl", # Union College utilities
"PGcourse.pl", # Customization file for the course
);

TEXT(beginproblem());
BEGIN_PROBLEM();

##################################################

#
# The image sizes
#
$width = 180;
$texwidth = 275;

#
# Make the graphs
#
@graph_options = (axes=>[0,0], grid=>[0,0], size=>[$width,$width]);
$graph_object1 = init_graph(-10,-10,10,10,@graph_options);
$graph_object2 = init_graph(-10,-10,10,10,@graph_options);
$graph_object3 = init_graph(-10,-10,10,10,@graph_options);
$graph_object4 = init_graph(-10,-10,10,10,@graph_options);

#create a scrambled list of colors and letters
@slice = NchooseK(3,3);
@sc =("blue", "red", "green")[@slice];
@sa = ('A', 'B', 'C')[invert(@slice)];

#now we are ready to write the strings which define the function
$dom = 10;
$a = random(-8,-2,1);
$b = random(1,5,1);
$c = random(4,8,1);
$d = $c/$b;
$f1 = FEQ ("$a x for x in <-$dom, 0> using color=black and weight=2");
$f2 = FEQ ("-(1/$b) x for x in <0, $c> using color=black and weight=2");
$f3 = FEQ ("(-($c/$b)+$c)-x for x in <$c, $dom> using color=black and weight=2");
add_functions($graph_object1, $f1, $f2, $f3);
$g1 = FEQ ("-$a x for x in <-$dom, 0> using color=$sc[0] and weight=2");
$g2 = FEQ ("(1/$b) x for x in <0, $c> using color=$sc[0] and weight=2");
$g3 = FEQ ("x+(($c/$b)-$c) for x in <$c, $dom> using color=$sc[0] and weight=2");
add_functions($graph_object2, $g1, $g2, $g3);
$h1 = FEQ ("-$a x for x in <0, $dom> using color=$sc[1] and weight=2");
$h2 = FEQ ("(1/$b) x for x in <-$c, 0> using color=$sc[1] and weight=2");
$h3 = FEQ ("x-($c/$b)+$c for x in <-$dom, -$c> using color=$sc[1] and weight=2");
add_functions($graph_object3, $h1, $h2, $h3);
$i1 = FEQ ("(1/$a) x for x in <0, $dom> using color=$sc[2] and weight=2");
$i2 = FEQ ("(-$b)x for x in <-$d, 0> using color=$sc[2] and weight=2");
$i3 = FEQ ("($c-($c/$b))- x for x in <-$dom, -$d> using color=$sc[2] and weight=2");
add_functions($graph_object4, $i1, $i2, $i3);

@randomGraph = ($graph_object2, $graph_object3, $graph_object4)[@slice];

###############################################
#
# Make the images
#

$imageF = image(insertGraph($graph_object1),
width=>$width,height=>$width,tex_size=>$texwidth);

foreach $i (0,1,2) {
$image[$i] = image(insertGraph($randomGraph[$i]),
width=>$width,height=>$width,tex_size=>$texwidth);
}

###############################################
#
# Routines for the image tables
#

sub bold {return $BBOLD.join("",@_).$EBOLD}

sub ImageRow {
my @ops = (separation=>30);
my $images = shift; my $labels = shift;
BeginTable().
Row($images,@ops).
TableSpace(5).
AlignedRow($labels,@ops).
EndTable();
}

################################################
#
# The text of the problem
#

BEGIN_TEXT
Below is the graph of a function \(f\):
$PAR
\{ImageRow([$imageF],['The graph of \(f\)'])\}
$PAR
\{ImageRow([@image],
['Graph '.bold('A'),
'Graph '.bold('B'),
'Graph '.bold('C')])\}
$PAR
The inverse of the function \(f\) is (A, B or C): \{ans_rule(4)\}
END_TEXT

$showPartialCorrectAnswers = 0;
ANS(str_cmp($sa[2]));

################################################

END_PROBLEM();
ENDDOCUMENT(); # This should be the last executable line in the problem.

In reply to Darwyn Cook

Re: oracle function and math objects

by Darwyn Cook -
I had some more time to play with this today. It looks like the problem is in the loop that passes the array to the cubic spline function:

$function = Formula("$a*x^2+$b*x +$c");
$f = $function->perlFunction;

$llimit = -5; $rlimit = 5;
my $num_of_intervals = 100; # number of interpolation points
my $delta = ($rlimit-$llimit)/($num_of_intervals);
my (@x_values, @y_values);
foreach my $i (0..$num_of_intervals) {
my $x = $llimit + $delta*$i;
my $y = &$f($x);
push(@x_values, $x); push(@y_values,$y);
}

By decreasing the $num_intervals to 100 the problem works, but takes a long time to load. In problems that don't use a function defined by mathobjects, $num_intervals is set at 500 and are much faster to execute. Just an observation.
In reply to Darwyn Cook

Re: oracle function and math objects

by Davide Cervone -
I've only just had the opportunity to look into your problem, and the issue is the following: the result of evaluating a Formula object, either via its eval() method, or via the code returned by its perlFunction() method, will be a MathObject Real object, not a perl real. That means that any time it is used in a computation, it will produce Real objects as the result.

In your case, you make a large table of results of your function and pass them into create_cubic_spline, which does a lot of further computation with them. All those computations end up producing MathObject Reals, and that is fairly expensive.

The solution is to demote the Reals back to perl reals. To do that, use the value method of the Real object. So change

    my $y = &$f($x);
to
    my $y = &$f($x)->value;
That should improve the performance by at least an order of magnitude.

There is a similar issue with the changes that were made to PGgraphmacros.pl to have it use MathObjects for its computations. I have corrected the problem, so you should update your copy of that file.

Hope that does it for you.

Davide

In reply to Davide Cervone

Re: oracle function and math objects

by Darwyn Cook -
That did it! I will have to read up on perlfunction for a Formula object, it doesn't do what I thought!