Nandor:
The problem here is that the perlFunction method produces a function that will throw an error when it is evaluated outside the domain of the function (i.e., when there is an error in evaluating the function) while the plotting macros expect the function to silently return an undefined value instead.
It is possible to encapsulate the perlFunction in a subroutine that does error trapping and returns the value of the formula when it evaluates without error, or undef if it does, but fortunately you don't have to do that, as PGgraphmacros.pl already contains the code for that if you use plot_functions rather than adding graphical function objects by hand. (If you want to see how it is done, look at pg/macros/PGgraphmacros.pl in the plot_functions subroutine).
There is also a subtle problem with using perlFunction to pass directly to the plotting functions, which is that the function that perlFunction produces will return MathObject Real's rather than plain old perl reals, and the overhead of that within the plotting functions will cause the plots to be produced very slowly (especially since you ask for 500 steps each). Using the plot_functions approach avoids that, as the internal routines convert back to perl reals automatically.
Here is a rewrite of your problem that takes advantage of this (and cleans up a few other items, e.g., since the the image is only 250 pixels wide, it is not necessary to use 500 steps; 250 is the largest needed, and even that is really overkill).
DOCUMENT();
loadMacros(
"PGstandard.pl",
"Parser.pl",
"PGnauGraphics.pl",
"PGgraphmacros.pl",
"PGcourse.pl",
);
TEXT(beginproblem);
#####################################################
Context('Numeric');
$a = list_random(1/3,1/2,2,3);
$b = random(-3,3,1);
$dom = 8;
@gr_lab=(-$dom+3,$dom-1);
@opts = (-$dom, -$dom, $dom, $dom, axes=>[0,0], grid=>[$dom, $dom], size=>[250,250]);
$f = Formula("$a^x + $b")->reduce;
$f->{limits} =[-$dom, $dom];
$graphf = init_graph(@opts);
(plot_functions($graphf,"$f for x in <-$dom,$dom> using color:blue"))[0]->steps(250);
$labelf = new Label(@gr_lab, 'y = f(x)', 'blue' , 'center', 'center');
$graphf->lb($labelf);
#####################################################
$graph_eval = sub{
my $h = shift;
my $ans_hash = $f->cmp->evaluate($h);
if ($h ne '') {
my $graph = init_graph(@opts);
$graph->new_color('dkgreen',0,102,0);
my ($F,$H) = plot_functions($graph,
"$f for x in <-$dom,$dom> using color:blue",
"$h for x in <-$dom,$dom> using color:dkgreen",
);
$F->steps(250); $H->steps(250);
$graph->gifName($graph->gifName()."-$orig_in");
$ans_hash->{student_ans} = Plot($graph);
}
$ans_hash;
};
#####################################################
BEGIN_TEXT
\{ Plot($graphf) \}
$PAR
Find the formula for \(f\).
$PAR
\(f(x)=\) \{ ans_rule(30) \}
$PAR
$BBOLD Hint: $EBOLD
Transform an exponential function with an integer base.
END_TEXT
#####################################################
ANS($graph_eval);
#####################################################
ENDDOCUMENT();
It's also possible to use the MathObjects answer checker directly and add a post-filter to make the graph. Here's how that might look:
DOCUMENT();
loadMacros(
"PGstandard.pl",
"Parser.pl",
"PGnauGraphics.pl",
"PGgraphmacros.pl",
"PGcourse.pl",
);
TEXT(beginproblem);
#####################################################
Context('Numeric');
$a = list_random(1/3,1/2,2,3);
$b = random(-3,3,1);
$dom = 8;
@gr_lab=(-$dom+3,$dom-1);
@opts = (-$dom, -$dom, $dom, $dom, axes=>[0,0], grid=>[$dom, $dom], size=>[250,250]);
$f = Formula("$a^x + $b")->reduce;
$f->{limits} =[-$dom, $dom];
$graphf = init_graph(@opts);
(plot_functions($graphf,"$f for x in <-$dom,$dom> using color:blue"))[0]->steps(250);
$labelf = new Label(@gr_lab, 'y = f(x)', 'blue' , 'center', 'center');
$graphf->lb($labelf);
#####################################################
BEGIN_TEXT
\{ Plot($graphf) \}
$PAR
Find the formula for \(f\).
$PAR
\(f(x)=\) \{ ans_rule(30) \}
$PAR
$BBOLD Hint: $EBOLD
Transform an exponential function with an integer base.
END_TEXT
#####################################################
ANS($f->cmp->withPostFilter(sub {
my $ans = shift;
my ($correct,$student) = ($ans->{correct_value},$ans->{student_value});
if ($student && $correct->typeMatch($student)) {
my $graph = init_graph(@opts);
$graph->new_color('dkgreen',0,102,0);
my ($c,$s) = plot_functions($graph,
"$correct for x in <-$dom,$dom> using color:blue",
"$student for x in <-$dom,$dom> using color:dkgreen",
);
$c->steps(250); $s->steps(250);
$graph->gifName($graph->gifName()."-$student");
$ans->{student_ans} = Plot($graph);
}
return $ans;
}));
#####################################################
ENDDOCUMENT();
This latter one has the advantage of reporting syntax errors in the students answers correctly (rather than giving a pink screen), and of not trying to plot things that are not of the proper form (like if the student entered a point rather than a function).
Hope these help out.
Davide