SampleProblem3

From WeBWorK_wiki
Jump to navigation Jump to search

A Third WeBWorK Sample Problem: Graphics

This sample problem shows how to write problems that include simple dynamically generated graphs.

Recall that a WeBWorK PG file has five sections: (1) a tagging and description section, (2) an initialization section, (3) a problem set-up section, (4) a text section, and (5) an answer and solution section. These sections are shown below, and the parts of each of each that are related to the different problem types being discussed here are indicated.

The sample file explained below is this file (need attachment).

PG problem file Explanation
# DESCRIPTION
# A simple sample problem that illustrates 
# how to include dynamically generated graphics
# in a problem.
# WeBWorK problem written by Gavin LaRose, 
# <glarose(at)umich(dot)edu>
# ENDDESCRIPTION

## DBsubject('WeBWorK')
## DBchapter('Demos')
## DBsection('Problem')
## KEYWORDS('graphs')
## TitleText1('')
## EditionText1('')
## AuthorText1('')
## Section1('')
## Problem1('')
## Author('Gavin LaRose')
## Institution('UMich')

This is the tagging and description section of the problem.

Recall that the tagging information exists to allow the problem to be easily indexed. Lists of tag values are on-line: current chapter and section names, and current keywords. The list of keywords should be comma separated and quoted (e.g., KEYWORDS('calculus','derivatives')).

DOCUMENT();
loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGgraphmacros.pl",
);

This is the initialization section of the problem. Note that we need to include PGgraphmacros.pl to use graphs in the problem.

# make sure we're in the context we want
Context("Numeric");

# we define a parabola to graph, making sure 
#    that the x and y intercepts are nice
$root1 = random(2,4,2);
$root2 = $root1 + random(2,4,2);
$func = Formula("-(1/8)(x-$root1)(x-$root2)");

# the minimum and maximum y values this 
#    reaches on the domain [-2,$root2+1] are
$ymin = $func->eval(x=>-2);
$ymax = $func->eval(x=>($root1+$root2)/2);

# the domain is
$xmin = -2;
$xmax = $root2 + 1;
# and the number of gridlines we graph
$xgrid = $xmax + 2;
$ygrid = $ymax - int($ymin) + 2;

# now initialize the graph
$graph = init_graph($xmin, int($ymin)-1, $xmax,
$ymax+1, axes=>[0,0], grid=>[$xgrid,$ygrid],
size=>[150,150]);

# and add the function to be graphed
plot_functions( $graph, "$func for x in " .
"<$xmin,$xmax> using color:blue " .
"and weight:2");

# for use below: the y-intercept is 
$yint = $func->eval(x=>0);

This is the problem set-up section of the problem.

We first define a MathObject to be the function we want. We will graph it on the domain [-1, $root2+1], and so use the MathObject to figure out what the maximum and minimum values of the function are on that domain are (we need these to define the graph).

Then we define the graph. This is first initialized; the required syntax is init_graph(xmin,ymin,xmax,ymax), which will create a graph with the default options. In this case we have chosen to specify some specific options:

  • axes=>[0,0] specifies that the axes pass through the point (0,0),
  • grid=>[$xgrid,$ygrid] specifies the number of evenly-spaced gridlines to be drawn on the graph, and
  • size=>[150,150] specifies the size of the graph (in pixels).

Another commonly used option is

  • ticks=>[number,number], which specifies the number of tick marks to put on the graph. (Obviously, this would be specified instead of grid.)

Then we add the function to the graph. The string that is used in this case always has the form indicated here: function for x in range using color:color and weight:weight. The range can be specified with standard interval notation: [0,3) will graph the function with a closed dot at the left endpoint and an open circle at the right. <0,3> omits points at the end of the function graph.

One other note here: to break the string over multiple lines, we've used Perl's concatenation operator, . (a period): in Perl, saying

$str="this and" . "that";

is the same as saying

$str="this andthat";.

TEXT(beginproblem());
Context()->texStrings;
BEGIN_TEXT
Consider the graph
$BR
$BCENTER
\{ image( insertGraph($graph), tex_size=>100,
    height=>150, width=>150,
    extra_html_tags=>'alt="graph of a ' .
    'downward opening parabola with ' .
    'x-intercepts ' . $root1 . ' and ' .
    $root2 . ', and y-intercept ' .
    $yint . '."' ) \}
$ECENTER

$PAR
What is the equation of this parabola?
$BR
\( y = \) \{ ans_rule(35) \}


END_TEXT
Context()->normalStrings;

This is the text section of the problem. Note that we've use a couple of formatting variables here: $BR to insert a line break, $PAR to insert a paragraph break, and $BCENTER and $ECENTER to begin and end a centered environment.

The graph is inserted with the image macro; if we hadn't dynamically generated the graph (that is, if it were a static image), we could have just said image(imagename). The insertGraph macro inserts the graph that we just generated. As with the init_graph call above, we could have just written image(insertGraph($graph)), but we've chosen to also include some useful options:

  • tex_size=>100 gives a scaling to use when displaying the image in the hardcopy; 100 is 10% of the usual size;
  • height=>150, width=>150 specify the height and width of the image. Because we specified these when we created the image, explicitly specifying them here means that the graph won't have to be scaled by the browser and will appear clearly without the student having to click on the graph to get a version in a separate window; and
  • extra_html_tags=>'alt="graph of..."' is a rather messy way of making sure that there is intelligible alternate text for the image when it is displayed. This may be significant for accessibility issues.
ANS( $func->cmp() );

Context()->texStrings;
SOLUTION(EV3(<<'END_SOLUTION'));
$PAR SOLUTION $PAR
Because we know that this is a parabola,
and because we know that the x-intercepts
are \(x = $root1\) and \(x = $root2\), 
we know that the equation of the function
must be 
\[ y = a (x - $root1) (x - $root2) \]
for some constant \(a\).  The y-intercept
is \(y = $yint\), which occurs when 
\(x = 0\), so we must have 
\(a($root1)($root2) = $yint\), so 
\(a = -\frac{1}{8}\), and our function is
\[ y = $func. \]
END_SOLUTION
Context()->normalStrings;

ENDDOCUMENT();

This is the answer and solution section of the problem.

Note that we use the same formatting conventions in the solution that are used in the text section of the problem.