Difference between revisions of "Web Conference Notes"
Line 6: | Line 6: | ||
* What WeBWorK problems are |
* What WeBWorK problems are |
||
* An Introduction to problem authoring |
* An Introduction to problem authoring |
||
− | ** WeBWorK is a Perl application, with layers on top of that. |
+ | ** 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. |
|
− | + | ||
− | + | ==Perl== |
|
− | + | ===Basic Ideas from Perl=== |
|
− | + | ||
− | + | # The pound sign indicates a comment: anything in a line after a # sign is ignored by Perl. |
|
− | + | # 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: |
||
+ | $strarray[2]; |
||
+ | 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: |
||
+ | # ^ does not exponentiate; it's a bitwise shift, which isn't what we want. |
||
+ | # something like <code>5 - -3</code> will work, but <code>5--3</code> will invoke the decrement operator <code>--</code>, which is not what we (necessarily) expect. |
||
+ | # fractional exponents require some care as well: <code>(-3)**(2/3)</code> will not work, while <code>((-3)**(2))**(-1/3)</code> will. |
||
+ | |||
+ | Perl also has named functions: <code>sin(2)</code> 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 <code>==</code> to test equality, <code>!=</code> to test inequality, and <code>></code>, <code>>=</code>, <code><</code>, and <code><=</code> as expected. These all return 1 (for true), and 0 (for false). |
||
+ | * For strings, we use the operators <code>eq</code> for equality and <code>ne</code> 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 <code>if</code> <code>then</code>: |
||
+ | $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 <code>elsif</code> for additional conditions: |
||
+ | $a = 3; |
||
+ | if ( $a == 4 ) { |
||
+ | $b = 3; |
||
+ | } elsif ( $a == 3 ) { |
||
+ | $b = 2; |
||
+ | } else { |
||
+ | $b = 1; |
||
+ | } |
||
+ | will define $b to be 2. |
||
+ | |||
+ | =====Loops===== |
||
+ | |||
+ | 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: |
||
+ | * <code>my</code> 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 <code>( 0..50 )</code> is the same as that we used in the array slice, and returns the values between 0 and 50 inclusive. |
||
+ | |||
+ | Finally, we can <code>do</code> <code>until</code>: |
||
+ | $a = 3; |
||
+ | do { |
||
+ | $a = $a + 1; |
||
+ | } until ( $a == 10 ); |
||
+ | Will loop through adding one to the variable $a |
||
+ | |||
+ | ==The PG Language== |
||
+ | |||
+ | PG: is a language 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 |
||
+ | |||
+ | MathObjects: are an extension of PG, which |
||
+ | * correct some Perl quirks |
||
+ | * make writing problems easier |
||
+ | * provide more macros |
||
+ | * make answer checker feedback better for students |
||
+ | |||
+ | A PG file: is a little Perl script that uses PG macros and MathObjects. It will include the following sections: |
||
+ | # Tagging info (for indexing of the NPL) |
||
+ | # Initialization (loading macros, etc) |
||
+ | # Setup (defining parameters, etc) |
||
+ | # Main Text (what students see) |
||
+ | # Answer evaluation (checking the submitted answers) |
||
+ | # Solution (optional) and end document (mandatory) |
||
+ | |||
+ | Sample problem file |
||
+ | TEXT(beginproblem()); |
||
+ | does a number of things, including setting the problem number on the page. |
||
+ | |||
+ | Set-up: |
||
+ | Context("Numeric"); |
||
+ | $a = non_zero_random(-5,5,1); |
||
+ | $b = random(2,9,1); |
||
+ | |||
+ | Structure of a PG file: |
||
+ | # Comments on Tagging |
||
+ | # Comments on Initialization - always include PGStandard and MathObject, always use TEXT(beginproblem()); |
||
+ | # Problem setup - avoid over randomization |
||
+ | # Text section: BEGIN_TEXT/END_TEXT enters a mode that is Text, rather than Perl. In TEXT mode you can use LaTeX to display mathematics: \( \) for inline math, and \[ \] for display math. Further, we can execute Perl in the Text section with \{ \}, which executes the command in the braces. |
||
+ | # in Answer Evaluation, every MO has a cmp() method, so that Formula("$a*x/$b)->cmp() is a method, which will compare the student's answer to the correct answer and return 0 or 1; ANS() takes that result and records it to the database of student scores. |
||
+ | # COMMENT("this is a comment"); provides comments when the problem is viewed in the library browser, and |
||
+ | # ENDDOCUMENT(); must be included at the end of the document. |
||
+ | |||
+ | ==MathObjects== |
||
+ | 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: |
||
+ | BEGIN_TEXT |
||
+ | What is the derivative of \( $f->TeX() \)? |
||
+ | END_TEXT |
||
+ | As we saw before, they can check student answers, too: |
||
+ | ANS( $f->cmp() ); |
||
+ | |||
+ | More Perl: note that |
||
+ | * <code>$f->D()</code> calls the method called "D" of the MathObject $f. (A method is a function associated with the object.) |
||
+ | * <code>x=>5</code> defines an association between x and 5; this is really an associative array definition, which we didn't discuss before. |
||
+ | |||
+ | ===Contexts=== |
||
+ | |||
+ | MathObjects live in a '''Context''', which defines the way MathObjects are interpreted. Thus we can have |
||
+ | Context("Numeric"); |
||
+ | $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: |
||
+ | Context()->texStrings; |
||
+ | BEGIN_TEXT |
||
+ | Find the derivative of \( $f \). |
||
+ | $BR |
||
+ | \{ ans_rule(20) \} |
||
+ | END_TEXT |
||
+ | Context()->normalStrings(); |
||
+ | |||
+ | Note that: |
||
+ | * The caret ^ works in MathObjects |
||
+ | * When we changed to texStrings in the Context, we got <code>$f->TeX()</code> 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"); |
||
+ | or |
||
+ | Context("Nuumeric"); |
||
+ | Context()->variables->are(t=>"Real"); |
||
+ | $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, <code>Context("Numeric");</code> sets up a Context with one variable, ''x''. |
Revision as of 14:44, 26 May 2011
Prep 2011 Main Page > Web Conference 1 > Conference Notes
Contents
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.
Perl
Basic Ideas from Perl
- The pound sign indicates a comment: anything in a line after a # sign is ignored by Perl.
- 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:
$strarray[2];
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:
- ^ does not exponentiate; it's a bitwise shift, which isn't what we want.
- something like
5 - -3
will work, but5--3
will invoke the decrement operator--
, which is not what we (necessarily) expect. - 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 andne
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.
Loops
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
The PG Language
PG: is a language 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
MathObjects: are an extension of PG, which
- correct some Perl quirks
- make writing problems easier
- provide more macros
- make answer checker feedback better for students
A PG file: is a little Perl script that uses PG macros and MathObjects. It will include the following sections:
- Tagging info (for indexing of the NPL)
- Initialization (loading macros, etc)
- Setup (defining parameters, etc)
- Main Text (what students see)
- Answer evaluation (checking the submitted answers)
- Solution (optional) and end document (mandatory)
Sample problem file
TEXT(beginproblem());
does a number of things, including setting the problem number on the page.
Set-up:
Context("Numeric"); $a = non_zero_random(-5,5,1); $b = random(2,9,1);
Structure of a PG file:
- Comments on Tagging
- Comments on Initialization - always include PGStandard and MathObject, always use TEXT(beginproblem());
- Problem setup - avoid over randomization
- Text section: BEGIN_TEXT/END_TEXT enters a mode that is Text, rather than Perl. In TEXT mode you can use LaTeX to display mathematics: \( \) for inline math, and \[ \] for display math. Further, we can execute Perl in the Text section with \{ \}, which executes the command in the braces.
- in Answer Evaluation, every MO has a cmp() method, so that Formula("$a*x/$b)->cmp() is a method, which will compare the student's answer to the correct answer and return 0 or 1; ANS() takes that result and records it to the database of student scores.
- COMMENT("this is a comment"); provides comments when the problem is viewed in the library browser, and
- ENDDOCUMENT(); must be included at the end of the document.
MathObjects
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:
BEGIN_TEXT What is the derivative of \( $f->TeX() \)? END_TEXT
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.
Contexts
MathObjects live in a Context, which defines the way MathObjects are interpreted. Thus we can have
Context("Numeric"); $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:
Context()->texStrings; BEGIN_TEXT Find the derivative of \( $f \). $BR \{ ans_rule(20) \} END_TEXT Context()->normalStrings();
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");
or
Context("Nuumeric"); Context()->variables->are(t=>"Real"); $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.