Web Conference Notes

From WeBWorK_wiki
Jump to navigation Jump to search

Prep 2011 Main Page > Web Conference 1 > Conference Notes

Notes from Web Conference 1

  • Introduction to the workshop
  • What WeBWorK problems are
  • An Introduction to problem authoring
    • WeBWorK is a Perl application, with layers on top of that. These layers are
    • PG, the problem generating language, and
    • MathObjects

Therefore we start thinking about writing problems for WeBWorK using Perl.


Basic Ideas from Perl

  1. The pound sign indicates a comment: anything in a line after a # sign is ignored by Perl.
  2. Any line of code must be ended with ;, a semicolon.

Perl Datatypes

Basic datatypes in Perl:

  • Scalar: We define a scalar variable with a $ prepending the name of the variable. Thus
$astring = "this is a string";
$anumber = 5;

define scalar variables which are, respectively, the string "this is a string" and the number 5.

  • Array: arrays are defined with a @ prepending the name of the variable. Thus
@strarray = ( "string1", "string2", "string3" );
@numarray = ( 1, 2, 2.71828, 3.1415 );

define, respectively, an array of strings and of numbers. Note that arrays may mix strings and numbers in their elements.

  • Array elements: Array elements are scalars, so we access them by using a dollar sign:

will return the value "string3" (because arrays are indexed from 0).

  • Array slices: We can also create a new array that is defined from elements of another array:
@newarray = @strarray[1..2];

will define (given the definition of @strarray above) an array which is the same as the definition

@newarray = ( "string2", "string2" );
  • Hashes: there are also associative arrays in Perl, which we don't discuss here.

Perl Mathematics

Perl supports the arithmetic operations we would expect: +, -, *, /, ** (which is exponentation), and % (which is modulo, or remainder)

Things to be careful about:

  1. ^ does not exponentiate; it's a bitwise shift, which isn't what we want.
  2. something like 5 - -3 will work, but 5--3 will invoke the decrement operator --, which is not what we (necessarily) expect.
  3. fractional exponents require some care as well: (-3)**(2/3) will not work, while ((-3)**(2))**(-1/3) will.

Perl also has named functions: sin(2) returns the sine of 2, etc: functions include

  • sin
  • sqrt
  • exp
  • log (is the natural log)
  • ln (is also)
  • logten
  • abs

Relational Operators

To test whether things are equal to each other, or greater or less than each other:

  • For numbers, we use the operators == to test equality, != to test inequality, and >, >=, <, and <= as expected. These all return 1 (for true), and 0 (for false).
  • For strings, we use the operators eq for equality and ne for inequality.

We can combine tests by using && for and and || for or: thus

(3 == (2+1)) && ("one" eq "two")

is false (0), while

(3 != (4+1)) || ("one" eq "one")

is true (1).

Flow Control

We can control how a Perl script executes by using conditional and looping statements.

Conditional Statements

The basic conditional statement is if then:

$a = 3;
if ( $a == 3 ) {
    $b = 4;

will define the variable $b to be 4. Similarly,

$a = 3;
if ( $a == 4 ) {
    $b = 3;
} else {
    $b = 2;

will define the variable $b to be 2. Finally, we can use elsif for additional conditions:

$a = 3;
if ( $a == 4 ) {
    $b = 3;
} elsif ( $a == 3 ) {
    $b = 2;
} else {
    $b = 1;

will define $b to be 2.


There are three basic ways to set up a loop: the first iterates over a variable that we define to keep track of where we are in the loop:

$n = 4;
for ( $i=1; $i<5; $i++ ) {
    $n = $n + $i;

will result in $n having the value 14.

We can also iterate over elements in an array:

@evens = ();
foreach my $i ( 0..50 ) {
    $evens[$i] = 2*$i;

will define the array @evens to be the even numbers between 0 and 100, inclusive. Two additional notes here:

  • my localizes the value of the variable to the block in which loop is defined: thus the definition of the variable $i in this loop will not change any value of $i that already existed; and
  • the notation ( 0..50 ) is the same as that we used in the array slice, and returns the values between 0 and 50 inclusive.

Finally, we can do until:

$a = 3;
do {
    $a = $a + 1;
} until ( $a == 10 );

Will loop through adding one to the variable $a

Problem Authoring

WeBWorK problems are written in the PG language. PG was developed by Mike & Arnie, and is the language that we use to write problems. It includes a number of macros that are provided "on top" of Perl

Thus, every problem file is a Perl script that uses the language that Perl provides plus a number of additional macros (functions) that allow us to create problems.

MathObjects were written by Davide Cervone to extend PG. They have the advantages that they

  • correct some Perl quirks
  • make writing problems easier
  • provide more macros
  • make answer checker feedback better for students

Thus, when we author a problem we create a PG file, which should always have a standard format. It should contain the sections:

  1. Tagging info (for indexing of the NPL)
  2. Initialization (loading macros, etc)
  3. Setup (defining parameters, etc)
  4. Main Text (what students see)
  5. Answer evaluation (checking the submitted answers)
  6. Solution (optional) and end document (mandatory)

A Sample Problem File

Sample Problem File

Notes About the Sample Problem File

  1. The Tagging section of the file defines metadata that may be used to categorize the problem if it is added to the National Problem Library.
  2. The Initialization section loads macros that are to be used, and defines the initial information about the problem.
    1. When loading macros, the default should be to load the macro files PGStandard.pl, and MathObjects.pl. There may be other macros that will be needed; this will be clear as we author other problem types.
    2. The TEXT(beginproblem()); line does a number of things, including setting the problem number on the page.
  3. The Problem Set-Up section defines what we need to know to set up the problem, including the variables that will be randomly determined for each student, and other data that are needed for the problem.
    1. Note that it is worth avoiding over-randomization. Try to make the problem generate values that you would want to work by hand.
  4. The Text section of the problem defines what the student sees when s/he views the problem.
    1. The Text section is delimited by BEGIN_TEXT and END_TEXT. Between these delimiters, we are in Text mode rather than in Pel. In this mode we can use LaTeX to display mathematics. This is discussed more below.
  5. The Answer Evaluation section defines how the student's answer is checked.
    1. Note that all MathObjects have a cmp method, which allows us to check a student's answer.
    2. We embed this comparison in the ANS macro, which then records the correctness of the student's answer in the WeBWorK database.
  6. The Solution and Enddocument section gives a full solution (if any) to the problem, and puts in the all-important ENDDOCUMENT() command.
    1. In this section, the COMMENT(); command include a comment that will be displayed in the Library Browser when a professor views the problem there.
    2. Be sure to end every PG file with the ENDDOCUMENT(); command.


A few notes about text mode. We embed mathematics in the text that is shown to the student with the notation \( \) (to embed an equation inline) or \[ \] (to put the equation in display mode).

We can also embed Perl commands in the text section by using \{ \}: this executes the code between the braces. Note that this is how we embed answer blanks in the problem.


In Perl, we can define a string:

$f = "sin(x)";

but the MathObject defined by

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

is an object that knows a lot about what the function is. Thus we can do all of the following:

$f->eval(x=>5); # plug 5 in for x
$f->D('x'); # differentiate wrt x
$g = Formula("sin(x) + -4")->reduce(); # simplifies $g to sin(x) - 4

And MathObjects can produce TeX output:

What is the derivative of \( $f->TeX() \)?

As we saw before, they can check student answers, too:

ANS( $f->cmp() );

More Perl: note that

  • $f->D() calls the method called "D" of the MathObject $f. (A method is a function associated with the object.)
  • x=>5 defines an association between x and 5; this is really an associative array definition, which we didn't discuss before.


MathObjects live in a Context, which defines the way MathObjects are interpreted. Thus we can have

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

which defines the Context in which the MathObjects that are defined to be numeric. This is the most common Context. We can modify the Context:

Find the derivative of \( $f \).
\{ ans_rule(20) \}

Note that:

  • The caret ^ works in MathObjects
  • When we changed to texStrings in the Context, we got $f->TeX() by default
  • We have to change back to normalStrings after this for the ANS() to work.

Another way to modify Contexts is to add variables:

Context("Numeric")->variables->add( y=>"Real" );
$f = Formula("x^2 + y^2");


$g = Formula("sin(t+pi)");

If we put these sequentially in the file, the second Context() call will reset the Context, and we then explicitly note that t is the only variable.

Note that:

  • By default, Context("Numeric"); sets up a Context with one variable, x.

We can also modify Contexts by disabling operators or functions:

$f = Formula("x^2"); # will return an error
$g = Formula("sin(x)"); # will return an error


  • Disabling functions or operators will mean that they are unavailable for both instructors (defining the problem) and students (providing answers).
  • We might want to do this if we are writing a problem where we want a student to enter a value rather than what a function returns, e.g., sqrt(3)/2 instead of sin(pi/3)

More Context modification: we may need to set the domain for a problem:

    x => {limits=>[2,5]}
$g = Compute("sqrt(x-1)");

This becomes important because of the way WeBWorK checks answers: it numerically evaluates the correct and student's answer at a set of points (say, 10), and requires that the values be equal at each. This, however, requires that the values picked for comparison be in the expected domain.

We note that this is a very robust way of checking formula answers.

We can also set the domain without modifying the Context:

$f = Compute("sqrt(x)");
$f->{limits} = [2,5];
$g = Compute("e^(20x)");
$g->{limits} = [-.25,.25];

Note that:

  • Compute generates a MathObject for you: it picks the most likely type of MathObject for you, and has the very desirable characteristic that it preserves the format of the answer you enter for display to the student. This is very desirable.
  • The second domain issue here is a little more subtle: something like this exponential needs to be evaluated on a small x domain if the numerical values are to be easy to evaluate