From: Mike G. v. a. <we...@ma...> - 2008-06-24 23:21:43
|
Log Message: ----------- replacing .txt files with .pod files Tags: ---- rel-2-4-patches Added Files: ----------- webwork2/doc/parser/docs: ParserAnswerCheckers.pod UsingParser.pod Removed Files: ------------- webwork2/doc/parser/docs: ParserAnswerCheckers.txt UsingParser.txt Revision Data ------------- --- /dev/null +++ doc/parser/docs/UsingParser.pod @@ -0,0 +1,393 @@ +=head1 USING MATHOBJECTS + +To use MathObjects in your own problems, you need to load the +"MathObjects.pl" macro file: + + loadMacros("Parser.pl"); + +which defines the commands you need to interact with MathObjects. +Once you have done that, you can call the MathObjects functions to create +formulas for you. The main call is Formula(), which takes a string and +returns a parsed version of the string. For example: + + $f = Formula("x^2 + 3x + 1"); + +will set $f to a reference to the parsed version of the formula. + +=head2 Working With Formulas + +A formula has a number of methods that you can call. These include: + +=over + +=item $f->eval(x=>5) + +Evaluate the formula when x is 5. +If $f has more variables than that, then +you must provide additional values, as in +$f->eval(x=>3,y=>1/2); + +=item $f->reduce + +Tries to remove redundent items from your +formula. For example, Formula("1x+0") returns "x". +Reduce tries to factor out negatives and do +some other adjustments as well. (There still +needs to be more work done on this. What it does +is correct, but not always smart, and there need +to be many more situations covered.) All the +reduction rules can be individually enabled +or disabled using the Context()->reduction->set() +method, but the documentation for the various +rules is not yet ready. + +=item $f->substitute(x=>5) + +Replace x by the value 5 throughout (you may want +to reduce the result afterword, as this is not +done automatically). Note that you can replace a +variable by another formula, if you wish. To make +this easier, substitute will apply Formula() to +any string values automatically. E.g., + Formula("x-1")->substitute(x=>"y") +returns "y-1" as a formula. + +=item $f->string + +returns a string representation of the formula +(should be equivalent to the original, though not +necessarily equal to it). + +=item $f->TeX + +returns a LaTeX representation of the formula. +You can use this in BEGIN_TEXT...END_TEXT blocks +as follows: + + BEGIN_TEXT + Suppose \(f(x) = \{$f->TeX}\). ... + END_TEXT + +=item $f->perl + +returns a representation of the formula that could +be evaluated by perl's eval() function. + +=item $f->perlFunction + +returns a perl code block that can be called to +evaluate the function. For example: + + $f = Formula('x^2 + 3')->perlFunction; + $y = &$f(5); + +will assign the value 28 to $y. +You can also pass a function name to perlFunction +to get a named function to call: + + Formula('x^2 + 3')->perlFunction('f'); + $y = f(5); + +If the formula involves more than one variable, +then the paramaters should be given in +alphabetical order. + + Formula('x^2 + y')->perlFunction('f'); + $z = f(5,3); # $z is 28. + +Alternatively, you can tell the order for the +parameters: + + Formula('x^2 + y')->perlFunction('f',['y','x']); + $z = f(5,3); $ now $z is 14. + +=back + +=head2 Combining Formulas + +There is a second way to create formulas. Once you have a formula, you can +create additional formulas simply by using perls' built-in operations and +functions, which have been overloaded to handle formulas. For example, + + $x = Formula('x'); + $f = 3*x**2 + 2*$x - 1; + +makes $f be a formula, and is equivalent to having done + + $f = Formula("3x^2 + 2x - 1"); + +This can be very convenient, but also has some pitfalls. First, you +need to include '*' for multiplication, since perl doesn't do implied +multiplication, and you must remember to use '**' not '^'. (If you use '^' +on a formula, the parser will remind you to use '**'.) Second, the +precedences of the operators in perl are fixed, and so changes you make to +the precedence table for the parser are not reflected in formulas produced +in this way. (The reason '^' is not overloaded to do exponentiation is +that the precedence of '^' is wrong for that in perl, and can't be +changed.) As long as you leave the default precedences, however, things +should work as you expect. + +Note that the standard functions, like sin, cos, etc, are overloaded to +generate appropriate formulas when their values are formulas. For example, + + $x = Formula('x'); + $f = cos(3*$x + 1); + +produces the same result as $f = Formula("cos(3x+1)"); and you can then go +on to output its TeX form, etc. + +=head2 Special Syntax + +This parser has support for some things that are missing from the current +one, like absolute values. You can say |1+x| rather than abs(1+x) +(though both are allowed), and even |1 - |x|| works. + +Also, you can use sin^2(x) (or even sin^2 x) to get (sin(x))^2. + +Finally, you can use sin^-1(x) to get arcsin(x). + +There is an experimental set of operator precedences that make it possible +to write sin 2x + 3 and get sin(2x) + 3. See examples/7-precedence.pg +for some details. + +=head2 The Formula Types + +The parser understands a wide range of data types, including real and +complex numbers, points, vectors, matrices, arbitrary lists, intervals, +unions of intervals, and predefined words. Each has a syntax for use +within formulas, as described below: + + numbers the usual form: 153, 233.5, -2.456E-3, etc. + + complex a + b i where a and b are numbers: 1+i, -5i, 6-7i, etc. + + infinitites the words 'infinity' or '-infinity' (or several + equivalents). + + point (a,b,c) where a, b and c are real or complex numbers. + any number of coordinates are allowed. Eg, (1,2), + (1,0,0,0), (-1,2,-3). Points are promoted to vectors + automatically, when necessary. + + vector <a,b,c> or a i + b j + c k (when used in vector context). + As with points, vectors can have any number of + coordinates. For example, <1,0,0>, <-1,3>, <x,1-x>, etc. + + matrix [[a11,...,a1n],...[am1,...amn]], i.e., use [..] around + each row, and around the matrix itself. The elements + are separated by commas (not spaces). e.g, + [[1,2],[3,4]] (a 2x2 matrix) + [1,2] (a 1x2 matrix, really a vector) + [[1],[2]] (a 2x1 matrix, ie. column vector) + Points and vectors are promoted to matrices when + appropriate. Vectors are converted to column vectors + when needed for matrix-vector multiplication. Matrices + can be 3-dimensional or higher by repeated nesting of + matrices. (In this way, a 2-dimensional matrix is really + thought of as a vector of vectors, and n-dimensional + ones as vectors of (n-1)-dimensional ones.) + + list (a,b,c) where a,b,c are arbitrary elements. + For example, (1+i, -3, <1,2,3>, Infinity). + The empty list () is allowed, and the parentheses are + optional if there is only one list. (This makes it + possible to make list-based answer checkers that + really know where the separations occur.) + + interval (a,b), (a,b], [a,b), [a,b], or [a,a] where a and b are + numbers or appropriate forms of infinity. + For example, (-INF,3], [4,4], [2,INF), (-INF,INF). + + union represented by 'U'. For example [-1,0) U (0,1]. + + string special predefined strings like NONE and DNE. + +These forms are what are used in the strings passed to Formula(). +If you want to create versions of these in perl, there are several +ways to do it. One way is to use the Compute() command, which takes a +string parses it and then evaluates the result (it is equivalent to +Formula(...)->eval). If the formula produces a vector, the result +will be a Vector constant that you can use in perl formulas by hand. + +For example: + + $v = Compute("<1,1,0> >< <-1,4,-2>"); + +would compute the dot product of the two vectors and assign the +resulting vector object to $v. + +Another way to generate constants of the various types is to use the +following routines. If their inputs are constant, they produce a +constant of the appropriate type. If an input is a formula, they +produce corresponding formula objects. + + Real(a) create a real number with "fuzzy" + comparisons (so that 1.0000001 == Real(1) is true). + + Complex(a,b) create a complex number a + b i + + Infinity creates the +infinity object + -(Infinity) creates -infinity + + Point(x1,...xn) or Point([x1,...,xn]) produces (x1,...,xn) + + Vector(x1,...,xn) or Vector([x1,...,xn]) produces <x1,...,xn> + + Matrix([a11,...,a1m],...,[am1,...,amn]) or + Matrix([[a11,...,a1m],...,[am1,...,amn]]) produces an n x m matrix + + List(a,...,b) produces a list with the given elements + + Interval('(',a,b,']') produces (a,b], (the other endpoints work as + expected. Use 'INF' and '-INF' for infinities.) + + Union(I1,...,In) takes the union of the n intervals. (where I1 to In + are intervals.) + + String(word) Produces a string object for the given word (if it + is a known word). This is mostly to be able to + call the ->cmp and ->TeX methods. + +For example, + + $a = random(-5,5,1) + $V = Vector($a,1-$a,$a**2+1); + +produces a vector with some random coordinates. + +Objects of these types also have TeX, string and perl methods, so you can +use: + + Vector(1,2,3)->TeX + +to produce a TeX version of the vector, just as you can with formulas. + +There are several "constant" functions that generate common constant +values. These include pi, i, j, k and Infininty. you can use these +in perl expressions as though they were their actual values: + + $z = $a + $b * i; + $v = $a*i + $b*j + $c*k; + $I = Infinity; + +Note that because of a peculiarity of perl, you need to use -(pi) +or - pi (with a space) rather than -pi, and similary for the other +functions. Without this, you will get an error message about an +ambiguity being resolved. (This is not a problem if you process your +expressions through the parser itself, only if you are writing +expressions in perl directly. Note that since student answers are +processed by the parser, not perl directly, they can write -pi without +problems.) + +Another useful command is Compute(), which evaluates a formula and +returns its value. This is one way to create point or vector-valued +constants, but there is an easier way discussed below. + +=head2 Specifying the Context + +You may have noticed that "i" was used in two different ways in the +examples above. In the first example, it was treated as a complex +number and the second as a coordinate unit vector. To control which +interpretation is used, you specify a parser "context". + +The context controls what operations and functions are defined in the +parser, what variables and constants to allow, how to interpret +various paretheses, and so on. Changing the context can completely +change the way a formula is interpreted. + +There are several predefined contexts: Numeric, Complex, Vector, +Interval and Full. (You can also define your own contexts, but that +will be described elsewhere.) To select a context, use the Context() +function, e.g. + + Context("Numeric"); + +selects the numeric context, where i, j and k have no special meaning, +points and vectors can't be used, and the only predefined variable is +'x'. + +On the other hand, Context("Vector") makes i, j and k represent the +unit coordinate vectors, and defines variables 'x', 'y' and 'z'. + +Context("Interval") is like numeric context, but it also defines the +parentheses so that they will form intervals (rather than points or +lists). + +Once you have selected a context, you can modify it to suit the +particular needs of your problem. The command + + $context = Context(); + +gets you a reference to the current context object (you can also use +something like + + $context = Context("Numeric"); + +to set the context and get its reference at the same time). Once you +have this reference, you can call the Context methods to change values +in the context. These are discussed in more detail in the +documentation of the Context object [not yet written], but some of the +more common actions are described here. + +To add a variable, use, for example, + + $context->variables->add(y=>'Real'); + +To delete any existing variables and replace them with new ones, use + + $context->variables->are(t=>'Real'); + +To remove a variable, use + + $context->variables->remove('t'); + +To get the names of the defind variables, use + + @names = $context->variables->names; + + +Similarly, you can add a named constant via + + $context->constants->add(M=>1/log(10)); + +and can change, remove or list the constants via methods like those +used for variables above. The command + + $M = $constant->constants->get('M'); + +will return the value of the consant M. (See the +pg/lib/Value/Context/Data.pm file for more information on the methods +you can call for the various types of context data.) + +To add new predefined words (like 'NONE' and 'DNE'), use something +like + + $constant->strings->add(TRUE=>{},FALSE=>{}); + +Note that strings are case-sensitive, so you might want to add + + $constant->strings->add( + true => {alias=>'TRUE'}, + false => {alias=>'FALSE'}, + ); + +so that either "TRUE" or "true" will be interpreted as TRUE. + +There are a number of values stored in the context that control things +like the tolerance used when comparing numbers, and so on. You +control these via commands like: + + $context->flags->set(tolerance=>.00001); + +For example, + + $context->flags->set(ijk=>1); + +will cause the output of all vectors to be written in ijk format +rather than <...> format. + +Finally, you can add or modify the operators and functions that are +available in the parser via calls to $context->operators and +$context->functions. See the files in webwork2/docs/parser/extensions +for examples of how to do this. + --- doc/parser/docs/UsingParser.txt +++ /dev/null @@ -1,383 +0,0 @@ -USING THE PARSER: - -To use the new parser in your own problems, you need to load the -"Parser.pl" macro file: - - loadMacros("Parser.pl"); - -which defines the commands you need to interact with the parser. -Once you have done that, you can call the Parser functions to create -formulas for you. The main call is Formula(), which takes a string and -returns a parsed version of the string. For example: - - $f = Formula("x^2 + 3x + 1"); - -will set $f to a reference to the parsed version of the formula. - - -WORKING WITH FORMULAS: - -A formula has a number of methods that you can call. These include: - - $f->eval(x=>5) Evaluate the formula when x is 5. - If $f has more variables than that, then - you must provide additional values, as in - $f->eval(x=>3,y=>1/2); - - $f->reduce Tries to remove redundent items from your - formula. For example, Formula("1x+0") returns "x". - Reduce tries to factor out negatives and do - some other adjustments as well. (There still - needs to be more work done on this. What it does - is correct, but not always smart, and there need - to be many more situations covered.) All the - reduction rules can be individually enabled - or disabled using the Context()->reduction->set() - method, but the documentation for the various - rules is not yet ready. - - $f->substitute(x=>5) Replace x by the value 5 throughout (you may want - to reduce the result afterword, as this is not - done automatically). Note that you can replace a - variable by another formula, if you wish. To make - this easier, substitute will apply Formula() to - any string values automatically. E.g., - Formula("x-1")->substitute(x=>"y") - returns "y-1" as a formula. - - $f->string returns a string representation of the formula - (should be equivalent to the original, though not - necessarily equal to it). - - $f->TeX returns a LaTeX representation of the formula. - You can use this in BEGIN_TEXT...END_TEXT blocks - as follows: - - BEGIN_TEXT - Suppose \(f(x) = \{$f->TeX}\). ... - END_TEXT - - $f->perl returns a representation of the formula that could - be evaluated by perl's eval() function. - - $f->perlFunction returns a perl code block that can be called to - evaluate the function. For example: - - $f = Formula('x^2 + 3')->perlFunction; - $y = &$f(5); - - will assign the value 28 to $y. - You can also pass a function name to perlFunction - to get a named function to call: - - Formula('x^2 + 3')->perlFunction('f'); - $y = f(5); - - If the formula involves more than one variable, - then the paramaters should be given in - alphabetical order. - - Formula('x^2 + y')->perlFunction('f'); - $z = f(5,3); # $z is 28. - - Alternatively, you can tell the order for the - parameters: - - Formula('x^2 + y')->perlFunction('f',['y','x']); - $z = f(5,3); $ now $z is 14. - - -COMBINING FORMULAS: - -There is a second way to create formulas. Once you have a formula, you can -create additional formulas simply by using perls' built-in operations and -functions, which have been overloaded to handle formulas. For example, - - $x = Formula('x'); - $f = 3*x**2 + 2*$x - 1; - -makes $f be a formula, and is equivalent to having done - - $f = Formula("3x^2 + 2x - 1"); - -This can be very convenient, but also has some pitfalls. First, you -need to include '*' for multiplication, since perl doesn't do implied -multiplication, and you must remember to use '**' not '^'. (If you use '^' -on a formula, the parser will remind you to use '**'.) Second, the -precedences of the operators in perl are fixed, and so changes you make to -the precedence table for the parser are not reflected in formulas produced -in this way. (The reason '^' is not overloaded to do exponentiation is -that the precedence of '^' is wrong for that in perl, and can't be -changed.) As long as you leave the default precedences, however, things -should work as you expect. - -Note that the standard functions, like sin, cos, etc, are overloaded to -generate appropriate formulas when their values are formulas. For example, - - $x = Formula('x'); - $f = cos(3*$x + 1); - -produces the same result as $f = Formula("cos(3x+1)"); and you can then go -on to output its TeX form, etc. - - -SPECIAL SYNTAX: - -This parser has support for some things that are missing from the current -one, like absolute values. You can say |1+x| rather than abs(1+x) -(though both are allowed), and even |1 - |x|| works. - -Also, you can use sin^2(x) (or even sin^2 x) to get (sin(x))^2. - -Finally, you can use sin^-1(x) to get arcsin(x). - -There is an experimental set of operator precedences that make it possible -to write sin 2x + 3 and get sin(2x) + 3. See examples/7-precedence.pg -for some details. - - -THE FORMULA TYPES: - -The parser understands a wide range of data types, including real and -complex numbers, points, vectors, matrices, arbitrary lists, intervals, -unions of intervals, and predefined words. Each has a syntax for use -within formulas, as described below: - - numbers the usual form: 153, 233.5, -2.456E-3, etc. - - complex a + b i where a and b are numbers: 1+i, -5i, 6-7i, etc. - - infinitites the words 'infinity' or '-infinity' (or several - equivalents). - - point (a,b,c) where a, b and c are real or complex numbers. - any number of coordinates are allowed. Eg, (1,2), - (1,0,0,0), (-1,2,-3). Points are promoted to vectors - automatically, when necessary. - - vector <a,b,c> or a i + b j + c k (when used in vector context). - As with points, vectors can have any number of - coordinates. For example, <1,0,0>, <-1,3>, <x,1-x>, etc. - - matrix [[a11,...,a1n],...[am1,...amn]], i.e., use [..] around - each row, and around the matrix itself. The elements - are separated by commas (not spaces). e.g, - [[1,2],[3,4]] (a 2x2 matrix) - [1,2] (a 1x2 matrix, really a vector) - [[1],[2]] (a 2x1 matrix, ie. column vector) - Points and vectors are promoted to matrices when - appropriate. Vectors are converted to column vectors - when needed for matrix-vector multiplication. Matrices - can be 3-dimensional or higher by repeated nesting of - matrices. (In this way, a 2-dimensional matrix is really - thought of as a vector of vectors, and n-dimensional - ones as vectors of (n-1)-dimensional ones.) - - list (a,b,c) where a,b,c are arbitrary elements. - For example, (1+i, -3, <1,2,3>, Infinity). - The empty list () is allowed, and the parentheses are - optional if there is only one list. (This makes it - possible to make list-based answer checkers that - really know where the separations occur.) - - interval (a,b), (a,b], [a,b), [a,b], or [a,a] where a and b are - numbers or appropriate forms of infinity. - For example, (-INF,3], [4,4], [2,INF), (-INF,INF). - - union represented by 'U'. For example [-1,0) U (0,1]. - - string special predefined strings like NONE and DNE. - -These forms are what are used in the strings passed to Formula(). -If you want to create versions of these in perl, there are several -ways to do it. One way is to use the Compute() command, which takes a -string parses it and then evaluates the result (it is equivalent to -Formula(...)->eval). If the formula produces a vector, the result -will be a Vector constant that you can use in perl formulas by hand. - -For example: - - $v = Compute("<1,1,0> >< <-1,4,-2>"); - -would compute the dot product of the two vectors and assign the -resulting vector object to $v. - -Another way to generate constants of the various types is to use the -following routines. If their inputs are constant, they produce a -constant of the appropriate type. If an input is a formula, they -produce corresponding formula objects. - - Real(a) create a real number with "fuzzy" - comparisons (so that 1.0000001 == Real(1) is true). - - Complex(a,b) create a complex number a + b i - - Infinity creates the +infinity object - -(Infinity) creates -infinity - - Point(x1,...xn) or Point([x1,...,xn]) produces (x1,...,xn) - - Vector(x1,...,xn) or Vector([x1,...,xn]) produces <x1,...,xn> - - Matrix([a11,...,a1m],...,[am1,...,amn]) or - Matrix([[a11,...,a1m],...,[am1,...,amn]]) produces an n x m matrix - - List(a,...,b) produces a list with the given elements - - Interval('(',a,b,']') produces (a,b], (the other endpoints work as - expected. Use 'INF' and '-INF' for infinities.) - - Union(I1,...,In) takes the union of the n intervals. (where I1 to In - are intervals.) - - String(word) Produces a string object for the given word (if it - is a known word). This is mostly to be able to - call the ->cmp and ->TeX methods. - -For example, - - $a = random(-5,5,1) - $V = Vector($a,1-$a,$a**2+1); - -produces a vector with some random coordinates. - -Objects of these types also have TeX, string and perl methods, so you can -use: - - Vector(1,2,3)->TeX - -to produce a TeX version of the vector, just as you can with formulas. - -There are several "constant" functions that generate common constant -values. These include pi, i, j, k and Infininty. you can use these -in perl expressions as though they were their actual values: - - $z = $a + $b * i; - $v = $a*i + $b*j + $c*k; - $I = Infinity; - -Note that because of a peculiarity of perl, you need to use -(pi) -or - pi (with a space) rather than -pi, and similary for the other -functions. Without this, you will get an error message about an -ambiguity being resolved. (This is not a problem if you process your -expressions through the parser itself, only if you are writing -expressions in perl directly. Note that since student answers are -processed by the parser, not perl directly, they can write -pi without -problems.) - -Another useful command is Compute(), which evaluates a formula and -returns its value. This is one way to create point or vector-valued -constants, but there is an easier way discussed below. - - -SPECIFYING THE CONTEXT - -You may have noticed that "i" was used in two different ways in the -examples above. In the first example, it was treated as a complex -number and the second as a coordinate unit vector. To control which -interpretation is used, you specify a parser "context". - -The context controls what operations and functions are defined in the -parser, what variables and constants to allow, how to interpret -various paretheses, and so on. Changing the context can completely -change the way a formula is interpreted. - -There are several predefined contexts: Numeric, Complex, Vector, -Interval and Full. (You can also define your own contexts, but that -will be described elsewhere.) To select a context, use the Context() -function, e.g. - - Context("Numeric"); - -selects the numeric context, where i, j and k have no special meaning, -points and vectors can't be used, and the only predefined variable is -'x'. - -On the other hand, Context("Vector") makes i, j and k represent the -unit coordinate vectors, and defines variables 'x', 'y' and 'z'. - -Context("Interval") is like numeric context, but it also defines the -parentheses so that they will form intervals (rather than points or -lists). - -Once you have selected a context, you can modify it to suit the -particular needs of your problem. The command - - $context = Context(); - -gets you a reference to the current context object (you can also use -something like - - $context = Context("Numeric"); - -to set the context and get its reference at the same time). Once you -have this reference, you can call the Context methods to change values -in the context. These are discussed in more detail in the -documentation of the Context object [not yet written], but some of the -more common actions are described here. - -To add a variable, use, for example, - - $context->variables->add(y=>'Real'); - -To delete any existing variables and replace them with new ones, use - - $context->variables->are(t=>'Real'); - -To remove a variable, use - - $context->variables->remove('t'); - -To get the names of the defind variables, use - - @names = $context->variables->names; - - -Similarly, you can add a named constant via - - $context->constants->add(M=>1/log(10)); - -and can change, remove or list the constants via methods like those -used for variables above. The command - - $M = $constant->constants->get('M'); - -will return the value of the consant M. (See the -pg/lib/Value/Context/Data.pm file for more information on the methods -you can call for the various types of context data.) - -To add new predefined words (like 'NONE' and 'DNE'), use something -like - - $constant->strings->add(TRUE=>{},FALSE=>{}); - -Note that strings are case-sensitive, so you might want to add - - $constant->strings->add( - true => {alias=>'TRUE'}, - false => {alias=>'FALSE'}, - ); - -so that either "TRUE" or "true" will be interpreted as TRUE. - -There are a number of values stored in the context that control things -like the tolerance used when comparing numbers, and so on. You -control these via commands like: - - $context->flags->set(tolerance=>.00001); - -For example, - - $context->flags->set(ijk=>1); - -will cause the output of all vectors to be written in ijk format -rather than <...> format. - -Finally, you can add or modify the operators and functions that are -available in the parser via calls to $context->operators and -$context->functions. See the files in webwork2/docs/parser/extensions -for examples of how to do this. - - - - --- /dev/null +++ doc/parser/docs/ParserAnswerCheckers.pod @@ -0,0 +1,423 @@ +=head1 MathObjects-based Answer Checkers + +MathObjects is designed to be used in two ways. First, you can use +it within your perl code when writing problems as a means of making it +easier to handle formulas, and in particular, to genarate be able to +use a single object to produce numeric values, TeX output and answer +strings. This avoids having to type a function three different ways +(which makes maintaining a problem much harder). Since MathObjects +also included vector and complex arthimatic, it is easier to work with +these types of values as well. + +The second reason for MathObjects is to use it to process student +input. This is accomplished through special answer checkers that are +part of the Parser package (rather than the traditional WeBWorK answer +checkers). Checkers are available for all the types of values that +the parser can produce (numbers, complex numbers, infinities, points, +vectors, intervals, unions, formulas, lists of numbers, lists of +points, lists of intervals, lists of formulas returning numbers, lists +of formulas returning points, and so on). + +To use one of these checkers, simply call the ->cmp method of the +object that represents the correct answer. For example: + + $n = Real(sqrt(2)); + ANS($n->cmp); + +will produce an answer checker that matches the square root of two. +Similarly, + + ANS(Vector(1,2,3)->cmp); + +matches the vector <1,2,3> (or any computation that produces it, e.g., +i+2j+3k, or <4,4,4>-<3,2,1>), while + + ANS(Interval("(-inf,3]")->cmp); + +matches the given interval. Other examples include: + + ANS(Infinity->cmp); + ANS(String('NONE')->cmp); + ANS(Union("(-inf,$a) U ($a,inf)")->cmp); + +and so on. + +Formulas are handled in the same way: + + ANS(Formula("x+1")->cmp); + + $a = random(-5,5,1); $b = random(-5,5,1); $x = random(-5,5,1); + $f = Formula("x^2 + $a x + $b")->reduce; + ANS($f->cmp); + ANS($f->eval(x=>$x)->cmp); + + $x = Formula('x'); + ANS((1+$a*$x)->cmp); + + Context("Vector")->variables->are(t=>'Real'); + $v = Formula("<t,t^2,t^3>"); $t = random(-5,5,1); + ANS($v->cmp); + ANS($v->eval(t=>$t)->cmp); + +and so on. + +Lists of items can be checked as easily: + + ANS(List(1,-1,0)->cmp); + ANS(List(Point($a,$b),Point($a,-$b))->cmp); + ANS(List(Vector(1,0,0),Vector(0,1,1))->cmp); + ANS(Compute("(-inf,2),(4,5)")->cmp); # easy way to get list of intervals + ANS(Formula("x, x+1, x^2-1")->cmp); + ANS(Formula("<x,2x>,<x,-2x>,<0,x>")->cmp); + ANS(List('NONE')->cmp); + +and so on. The last example may seem strange, as you could have used +ANS(String('NONE')->cmp), but there is a reason for using this type +of construction. You might be asking for one or more numbers (or +points, or whatever) or the word 'NONE' of there are no numbers (or +points). If you used String('NONE')->cmp, the student would get an +error message about a type mismatch if he entered a list of numbers, +but with List('NONE')->cmp, he will get appropriate error messages for +the wrong entries in the list. + +It is often appropriate to use the list checker in this way even when +the correct answer is a single value, if the student might type a list +of answers. + +On the other hand, using the list checker has its disadvantages. For +example, if you use + + ANS(Interval("(-inf,3]")->cmp); + +and the student enters (-inf,3), she will get a message indicating +that the type of interval is incorrect, while that would not be the +case if + + ANS(List(Interval("(-inf,3]"))->cmp); + +were used. (This is because the student doesn't know how many +intervals there are, so saying that the type of interval is wrong +would inform her that there is only one.) + +The rule of thumb is: the individual checkers can give more detailed +information about what is wrong with the student's answer; the list +checker allows a wider range of answers to be given without giving +away how many answers there are. If the student knows there's only +one, use the individual checker; if there may or may not be more than +one, use the list checker. + +Note that you can form lists of formulas as well. The following all +produce the same answer checker: + + ANS(List(Formula("x+1"),Formula("x-1"))->cmp); + + ANS(Formula("x+1,x-1")->cmp); # easier + + $f = Formula("x+1"); $g = Formula("x-1"); + ANS(List($f,$g)->cmp); + + $x = Formula('x'); + ANS(List($x+1,$x-1)->cmp); + +See the files in webwork2/doc/parser/problems for more +examples of using the parser's answer checkers. + +=head2 Controlling the Details of the Answer Checkers + +The action of the answer checkers can be modified by passing flags to +the cmp() method. For example: + + ANS(Real(pi)->cmp(showTypeWarnings=>0)); + +will prevent the answer checker from reporting errors due to the +student entering in the wrong type of answer (say a vector rather than +a number). + +=head3 Flags common to all answer checkers + +There are a number of flags common to all the checkers: + +=over + +=item S<C<< showTypeWarnings=>1 or 0 >>> + +show/don't show messages about student +answers not being of the right type. +(default: 1) + +=item S<C<< showEqualErrors=>1 or 0 >>> + +show/don't show messages produced by +trying to compare the professor and +student values for equality, e.g., +conversion errors between types. +(default: 1) + +=item S<C<< ignoreStrings=>1 or 0 >>> + +show/don't show type mismatch errors +produced by strings (so that 'NONE' will +not cause a type mismatch in a checker +looking for a list of numbers, for example). +(default: 1) + +=back + +In addition to these, the individual types have their own flags: + +=head3 Flags for Real()->cmp + +=over + +=item S<C<< ignoreInfinity=>1 or 0 >>> + +Don't report type mismatches if the +student enters an infinity. +(default: 1) + +=back + +=head3 Flags for String()->cmp + +=over + +=item S<C<< typeMatch=>value >>> + +Specifies the type of object that +the student should be allowed to enter +(in addition the string). +(default: 'Value::Real') + +=back + +=head3 Flags for Point()->cmp + +=over + +=item S<C<< showDimensionHints=>1 or 0 >>> + +show/don't show messages about the +wrong number of coordinates. +(default: 1) + +=item S<C<< showCoordinateHints=>1 or 0 >>> + +show/don't show message about +which coordinates are right. +(default: 1) + +=back + +=head3 Flags for Vector()->cmp + +=over + +=item S<C<< showDimensionHints=>1 or 0 >>> + +show/don't show messages about the +wrong number of coordinates. +(default: 1) + +=item S<C<< showCoordinateHints=>1 or 0 >>> + +show/don't show message about +which coordinates are right. +(default: 1) + +=item S<C<< promotePoints=>1 or 0 >>> + +do/don't allow the student to +enter a point rather than a vector. +(default: 1) + +=item S<C<< parallel=>1 or 0 >>> + +Mark the answer as correct if it +is parallel to the professor's answer. +Note that a value of 1 forces +showCoordinateHints to be 0. +(default: 0) + +=item S<C<< sameDirection=>1 or 0 >>> + +During a parallel check, mark the +answer as correct only if it is in +the same (not the opposite) +direction as the professor's answer. +(default: 0) + +=back + +=head3 Flags for Matrix()->cmp + +=over + +=item S<C<< showDimensionHints=>1 or 0 >>> + +show/don't show messages about the +wrong number of coordinates. +(default: 1) + +=back + +The default for showEqualErrors is set to 0 for Matrices, since +these errors usually are dimension errors, and that is handled +separately (and after the equality check). + +=head3 Flags for Interval()->cmp + +=over + +=item S<C<< showEndpointHints=>1 or 0 >>> + +do/don't show messages about which +endpoints are correct. +(default: 1) + +=item S<C<< showEndTypeHints=>1 or 0 >>> + +do/don't show messages about +whether the open/closed status of +the enpoints are correct (only +shown when the endpoints themselves +are correct). +(default: 1) + +=back + +=head3 Flags for Union()->cmp and List()->cmp + +all the flags from the Real()->cmp, plus: + +=over + +=item S<C<< showHints=>1 or 0 >>> + +do/don't show messages about which +entries are incorrect. +(default: $showPartialCorrectAnswers) + +=item S<C<< showLengthHints=>1 or 0 >>> + +do/don't show messages about having the +correct number of entries (only shown +when all the student answers are +correct but there are more needed, or +all the correct answsers are among the +ones given, but some extras were given). +(default: $showPartialCorrectAnswers) + +=item S<C<< partialCredit=>1 or 0 >>> + +do/don't give partial credit for when +some answers are right, but not all. +(default: $showPartialCorrectAnswers) +(currently the default is 0 since WW +can't handle partial credit properly). + +=item S<C<< ordered=>1 or 0 >>> + +give credit only if the student answers +are in the same order as the +professor's answers. +(default: 0) + +=item S<C<< entry_type=>'a (name)' >>> + +The string to use in error messages +about type mismatches. +(default: dynamically determined from list) + +=item S<C<< list_type=>'a (name)' >>> + +The string to use in error messages +about numbers of entries in the list. +(default: dynamically determined from list) + +=item S<C<< typeMatch=>value >>> + +Specifies the type of object that +the student should be allowed to enter +in the list (determines what +constitutes a type mismatch error). +(default: dynamically determined from list) + +=item S<C<< requireParenMatch=>1 or 0 >>> + +Do/don't require the parentheses in the +student's answer to match those in the +professor's answer exactly. +(default: 1) + +=item S<C<< removeParens=>1 or 0 >>> + +Do/don't remove the parentheses from the +professor's list as part of the correct +answer string. This is so that if you +use List() to create the list (which +doesn't allow you to control the parens +directly), you can still get a list +with no parentheses. +(default: 0 for List() and 1 for Formula()) + +=back + +=head3 Flags for Formula()->cmp + +The flags for formulas are dependent on the type of the result of +the formula. If the result is a list or union, it gets the flags +for that type above, otherwise it gets that flags of the Real +type above. + +More flags need to be added in order to allow more control over the +answer checkers to give the full flexibility of the traditional +WeBWorK answer checkers. Note that some things, like whether trig +functions are allowed in the answer, are controlled through the +Context() rather than the answer checker itself. For example, + + Context()->functions->undefine('sin','cos','tan'); + +would remove those three functions from use. (One would need to remove +cot, sec, csc, arcsin, asin, etc., to do this properly; there could be +a function call to do this.) + +Similarly, which arithmetic operations are available is controlled +through Context()->operations. + +The tolerances used in comparing numbers are part of the Context as +well. You can set these via: + + Context()->flags->set( + tolerance => .0001, # the relative or absolute tolerance + tolType => 'relative', # or 'absolute' + zeroLevel => 1E-14, # when to use zeroLevelTol + zeroLevelTol => 1E-12, # smaller than this matches zero + # when one of the two is less + # than zeroLevel + limits => [-2,2], # limits for variables in formulas + num_points => 5, # the number of test points + ); + +[These need to be handled better.] + +Note that for testing formulas, you can override the limits and +num_points settings by setting these fields of the formula itself: + + $f = Formula("sqrt(x-10)"); + $f->{limits} = [10,12]; + + $f = Formula("log(xy)"); + $f->{limits} = [[.1,2],[.1,2]]; # x and y limits + +You can also specify the test points explicitly: + + $f = Formula("sqrt(x-10)"); + $f->{test_points} = [[11],[11.5],[12]]; + + $f = Formula("log(xy)"); + $f->{test_points} = [[.1,.1],[.1,.5],[.1,.75], + [.5,.1],[.5,.5],[.5,.75]]; + +[There still needs to be a means of handling the tolerances similarly, +and through the ->cmp() call itself.] + --- doc/parser/docs/ParserAnswerCheckers.txt +++ /dev/null @@ -1,348 +0,0 @@ -PARSER-BASED ANSWER CHECKERS - -The new parser is designed to be used in two ways. First, you can use -it within your perl code when writing problems as a means of making it -easier to handle formulas, and in particular, to genarate be able to -use a single object to produce numeric values, TeX output and answer -strings. This avoids having to type a function three different ways -(which makes maintaining a problem much harder). Since the parser -also included vector and complex arthimatic, it is easier to work with -these types of values as well. - -The second reason for the parser is to use it to process student -input. This is accomplished through special answer checkers that are -part of the Parser package (rather than the traditional WeBWorK answer -checkers). Checkers are available for all the types of values that -the parser can produce (numbers, complex numbers, infinities, points, -vectors, intervals, unions, formulas, lists of numbers, lists of -points, lists of intervals, lists of formulas returning numbers, lists -of formulas returning points, and so on). - -To use one of these checkers, simply call the ->cmp method of the -object that represents the correct answer. For example: - - $n = Real(sqrt(2)); - ANS($n->cmp); - -will produce an answer checker that matches the square root of two. -Similarly, - - ANS(Vector(1,2,3)->cmp); - -matches the vector <1,2,3> (or any computation that produces it, e.g., -i+2j+3k, or <4,4,4>-<3,2,1>), while - - ANS(Interval("(-inf,3]")->cmp); - -matches the given interval. Other examples include: - - ANS(Infinity->cmp); - ANS(String('NONE')->cmp); - ANS(Union("(-inf,$a) U ($a,inf)")->cmp); - -and so on. - -Formulas are handled in the same way: - - ANS(Formula("x+1")->cmp); - - $a = random(-5,5,1); $b = random(-5,5,1); $x = random(-5,5,1); - $f = Formula("x^2 + $a x + $b")->reduce; - ANS($f->cmp); - ANS($f->eval(x=>$x)->cmp); - - $x = Formula('x'); - ANS((1+$a*$x)->cmp); - - Context("Vector")->variables->are(t=>'Real'); - $v = Formula("<t,t^2,t^3>"); $t = random(-5,5,1); - ANS($v->cmp); - ANS($v->eval(t=>$t)->cmp); - -and so on. - -Lists of items can be checked as easily: - - ANS(List(1,-1,0)->cmp); - ANS(List(Point($a,$b),Point($a,-$b))->cmp); - ANS(List(Vector(1,0,0),Vector(0,1,1))->cmp); - ANS(Compute("(-inf,2),(4,5)")->cmp); # easy way to get list of intervals - ANS(Formula("x, x+1, x^2-1")->cmp); - ANS(Formula("<x,2x>,<x,-2x>,<0,x>")->cmp); - ANS(List('NONE')->cmp); - -and so on. The last example may seem strange, as you could have used -ANS(String('NONE')->cmp), but there is a reason for using this type -of construction. You might be asking for one or more numbers (or -points, or whatever) or the word 'NONE' of there are no numbers (or -points). If you used String('NONE')->cmp, the student would get an -error message about a type mismatch if he entered a list of numbers, -but with List('NONE')->cmp, he will get appropriate error messages for -the wrong entries in the list. - -It is often appropriate to use the list checker in this way even when -the correct answer is a single value, if the student might type a list -of answers. - -On the other hand, using the list checker has its disadvantages. For -example, if you use - - ANS(Interval("(-inf,3]")->cmp); - -and the student enters (-inf,3), she will get a message indicating -that the type of interval is incorrect, while that would not be the -case if - - ANS(List(Interval("(-inf,3]"))->cmp); - -were used. (This is because the student doesn't know how many -intervals there are, so saying that the type of interval is wrong -would inform her that there is only one.) - -The rule of thumb is: the individual checkers can give more detailed -information about what is wrong with the student's answer; the list -checker allows a wider range of answers to be given without giving -away how many answers there are. If the student knows there's only -one, use the individual checker; if there may or may not be more than -one, use the list checker. - -Note that you can form lists of formulas as well. The following all -produce the same answer checker: - - ANS(List(Formula("x+1"),Formula("x-1"))->cmp); - - ANS(Formula("x+1,x-1")->cmp); # easier - - $f = Formula("x+1"); $g = Formula("x-1"); - ANS(List($f,$g)->cmp); - - $x = Formula('x'); - ANS(List($x+1,$x-1)->cmp); - -See the files in webwork2/doc/parser/problems for more -examples of using the parser's answer checkers. - - -CONTROLLING THE DETAILS OF THE ANSWER CHECKERS: - -The action of the answer checkers can be modified by passing flags to -the cmp() method. For example: - - ANS(Real(pi)->cmp(showTypeWarnings=>0)); - -will prevent the answer checker from reporting errors due to the -student entering in the wrong type of answer (say a vector rather than -a number). - -There are a number of flags common to all the checkers: - - showTypeWarnings=>1 or 0 show/don't show messages about student - answers not being of the right type. - (default: 1) - - showEqualErrors=>1 or 0 show/don't show messages produced by - trying to compare the professor and - student values for equality, e.g., - conversion errors between types. - (default: 1) - - ignoreStrings=>1 or 0 show/don't show type mismatch errors - produced by strings (so that 'NONE' will - not cause a type mismatch in a checker - looking for a list of numbers, for example). - (default: 1) - -In addition to these, the individual types have their own flags: - - Real()->cmp: - - ignoreInfinity=>1 or 0 Don't report type mismatches if the - student enters an infinity. - (default: 1) - - String()->cmp: - - typeMatch=>value Specifies the type of object that - the student should be allowed to enter - (in addition the string). - (default: 'Value::Real') - - - Point()->cmp: - - showDimensionHints=>1 or 0 show/don't show messages about the - wrong number of coordinates. - (default: 1) - - showCoordinateHints=>1 or 0 show/don't show message about - which coordinates are right. - (default: 1) - - - Vector()->cmp: - - showDimensionHints=>1 or 0 show/don't show messages about the - wrong number of coordinates. - (default: 1) - - showCoordinateHints=>1 or 0 show/don't show message about - which coordinates are right. - (default: 1) - - promotePoints=>1 or 0 do/don't allow the student to - enter a point rather than a vector. - (default: 1) - - parallel=>1 or 0 Mark the answer as correct if it - is parallel to the professor's answer. - Note that a value of 1 forces - showCoordinateHints to be 0. - (default: 0) - - sameDirection=>1 or 0 During a parallel check, mark the - answer as correct only if it is in - the same (not the opposite) - direction as the professor's answer. - (default: 0) - - Matrix()->cmp: - - showDimensionHints=>1 or 0 show/don't show messages about the - wrong number of coordinates. - (default: 1) - - The default for showEqualErrors is set to 0 for Matrices, since - these errors usually are dimension errors, and that is handled - separately (and after the equality check). - - - Interval()->cmp: - - showEndpointHints=>1 or 0 do/don't show messages about which - endpoints are correct. - (default: 1) - - showEndTypeHints=>1 or 0 do/don't show messages about - whether the open/closed status of - the enpoints are correct (only - shown when the endpoints themselves - are correct). - (default: 1) - - - Union()->cmp and - List()->cmp: - - all the flags from the Real()->cmp, plus: - - showHints=>1 or 0 do/don't show messages about which - entries are incorrect. - (default: $showPartialCorrectAnswers) - - showLengthHints=>1 or 0 do/don't show messages about having the - correct number of entries (only shown - when all the student answers are - correct but there are more needed, or - all the correct answsers are among the - ones given, but some extras were given). - (default: $showPartialCorrectAnswers) - - partialCredit=>1 or 0 do/don't give partial credit for when - some answers are right, but not all. - (default: $showPartialCorrectAnswers) - (currently the default is 0 since WW - can't handle partial credit properly). - - ordered=>1 or 0 give credit only if the student answers - are in the same order as the - professor's answers. - (default: 0) - - entry_type=>'a (name)' The string to use in error messages - about type mismatches. - (default: dynamically determined from list) - - list_type=>'a (name)' The string to use in error messages - about numbers of entries in the list. - (default: dynamically determined from list) - - typeMatch=>value Specifies the type of object that - the student should be allowed to enter - in the list (determines what - constitutes a type mismatch error). - (default: dynamically determined from list) - - requireParenMatch=>1 or 0 - Do/don't require the parentheses in the - student's answer to match those in the - professor's answer exactly. - (default: 1) - - removeParens=>1 or 0 Do/don't remove the parentheses from the - professor's list as part of the correct - answer string. This is so that if you - use List() to create the list (which - doesn't allow you to control the parens - directly), you can still get a list - with no parentheses. - (default: 0 for List() and 1 for Formula()) - - Formula()->cmp: - - The flags for formulas are dependent on the type of the result of - the formula. If the result is a list or union, it gets the flags - for that type above, otherwise it gets that flags of the Real - type above. - - -More flags need to be added in order to allow more control over the -answer checkers to give the full flexibility of the traditional -WeBWorK answer checkers. Note that some things, like whether trig -functions are allowed in the answer, are controlled through the -Context() rather than the answer checker itself. For example, - - Context()->functions->undefine('sin','cos','tan'); - -would remove those three functions from use. (One would need to remove -cot, sec, csc, arcsin, asin, etc., to do this properly; there could be -a function call to do this.) - -Similarly, which arithmetic operations are available is controlled -through Context()->operations. - -The tolerances used in comparing numbers are part of the Context as -well. You can set these via: - - Context()->flags->set( - tolerance => .0001, # the relative or absolute tolerance - tolType => 'relative', # or 'absolute' - zeroLevel => 1E-14, # when to use zeroLevelTol - zeroLevelTol => 1E-12, # smaller than this matches zero - # when one of the two is less - # than zeroLevel - limits => [-2,2], # limits for variables in formulas - num_points => 5, # the number of test points - ); - -[These need to be handled better.] - -Note that for testing formulas, you can override the limits and -num_points settings by setting these fields of the formula itself: - - $f = Formula("sqrt(x-10)"); - $f->{limits} = [10,12]; - - $f = Formula("log(xy)"); - $f->{limits} = [[.1,2],[.1,2]]; # x and y limits - -You can also specify the test points explicitly: - - $f = Formula("sqrt(x-10)"); - $f->{test_points} = [[11],[11.5],[12]]; - - $f = Formula("log(xy)"); - $f->{test_points} = [[.1,.1],[.1,.5],[.1,.75], - [.5,.1],[.5,.5],[.5,.75]]; - -[There still needs to be a means of handling the tolerances similarly, -and through the ->cmp() call itself.] |