Difference between revisions of "Introduction to MathObjects"

From WeBWorK_wiki
Jump to navigation Jump to search
(Move most of the data to a separate page and link to that)
 
(13 intermediate revisions by one other user not shown)
Line 1: Line 1:
 
== What are MathObjects? ==
 
== What are MathObjects? ==
   
MathObjects are a set of formal objects that make the manipulation of mathematics within WeBWorK problems more intuitive. They make it possible to define variables as common mathematical objects, such as formulas, real number, complex numbers, intervals, vectors, points, and so on. For example:
+
MathObjects are a set of Perl objects that make the manipulation of mathematics within WeBWorK problems more intuitive. They make it possible to define variables in your problems that correspond to common mathematical objects, such as formulas, real number, complex numbers, intervals, vectors, points, and so on. For example:
   
 
$f = Formula("sin(x^2+6)");
 
$f = Formula("sin(x^2+6)");
Line 7: Line 7:
 
$z = Complex("1 + 5i");
 
$z = Complex("1 + 5i");
   
These are useful (and powerful) because MathObjects "know" information about themselves; thus, we can add formulas to get new formulas, plug real objects into formulas to get formulas evaluated at those values, calculate derivatives of formulas, add and subtract intervals to form unions and intersections, and much more.
+
These are useful (and powerful) because MathObjects "know" information about themselves; thus, you can add formulas to get new formulas, plug real objects into formulas to get formulas evaluated at those values, calculate derivatives of formulas, add and subtract intervals to form unions and intersections, and much more.
   
 
For several reasons it is usually preferable to write the MathObjects above using the <code>Compute()</code> function rather than the individual constructors for the various MathObject types.
 
For several reasons it is usually preferable to write the MathObjects above using the <code>Compute()</code> function rather than the individual constructors for the various MathObject types.
Line 16: Line 16:
   
 
The <code>Compute()</code> function determines the kind of MathObject from the Context and from the syntax of its argument, which is usually a string value that is in the form that a student could type. The <code>Compute</code> function also sets the "correct answer" to be the exact string that it was given, so that if a student were asked to enter a number that matched <code>$a</code> from above and asked to see the correct answer (after the due date), then <code>sqrt(pi/6)</code> would be displayed rather than <code>0.723601</code>. This gives you more control over the format of correct answers that are shown to students.
 
The <code>Compute()</code> function determines the kind of MathObject from the Context and from the syntax of its argument, which is usually a string value that is in the form that a student could type. The <code>Compute</code> function also sets the "correct answer" to be the exact string that it was given, so that if a student were asked to enter a number that matched <code>$a</code> from above and asked to see the correct answer (after the due date), then <code>sqrt(pi/6)</code> would be displayed rather than <code>0.723601</code>. This gives you more control over the format of correct answers that are shown to students.
  +
   
 
== Why use MathObjects? ==
 
== Why use MathObjects? ==
   
MathObjects are designed to be used in two ways. First, you can use them within your Perl code when writing problems as a means of making it easier to handle formulas and other mathematical items, and in particular to be able to produce numeric values, TeX output, and answer strings from a single formula object. This avoids having to type a function three different ways (as a Perl function, as a TeX string, and as an answer string), making it much easier to maintain a problem, or duplicate and modify it to use a different formula. Since MathObjects also included vectors, points, matrices, intervals, complex numbers, and a variety of other object types, it is easier to work with these kinds of values as well.
+
MathObjects are designed to be used in two ways. First, you can use them within your Perl code when writing problems as a means of making it easier to handle formulas and other mathematical items, and in particular to be able to produce numeric values, TeX output, and answer strings from a single formula object. This avoids having to type a function three different ways (as a Perl function, as a TeX string, and as an answer string), making it much easier to maintain a problem, or duplicate and modify it to use a different formula. Since MathObjects also includes vectors, points, matrices, intervals, complex numbers, and a variety of other object types, it is easier to work with these kinds of values as well.
   
More importantly, using MathObjects improves the processing of student input. This is accomplished through special answer checkers that are part of the MathObjects' Parser package (rather than the traditional WeBWorK answer checkers). Each of these checkers has error checking customized to the type of input expected from the student and can provide helpful feedback if the syntax of the student's entry is incorrect. Because the MathObject checkers are part of a unified library, students get consistent error messages regardless of the type of answer that is expected or that they provide. For example, if a student enters a formula in an answer blank where the correct answer is actually a number, she will receive a message indicating that what she typed was a formula but that a number was expected. Thus students are given guidance automatically about this type of semantic problem with their answers. Answer checkers for points and vectors can indicate that the number of coordinates are wrong, or can tell the student which coordinates are incorrect (at the problem-author's discretion).
+
More importantly, using MathObjects improves the processing of student input. This is accomplished through special answer checkers that are part of the MathObjects Parser package rather than the traditional WeBWorK answer checkers. Each of these checkers has error checking customized to the type of input expected from the student and can provide helpful feedback if the syntax of the student's entry is incorrect. Because the MathObject checkers are part of a unified library, students get consistent error messages regardless of the type of answer that is expected or that they provide. For example, if a student enters a formula in an answer blank where the correct answer is actually a number, she will receive a message indicating that what she typed was a formula but that a number was expected. Thus students are given guidance automatically about this type of semantic problem with their answers. Answer checkers for points and vectors can indicate that the number of coordinates are wrong, or can tell the student which coordinates are incorrect (at the problem-author's discretion).
   
Answer checkers are available for each of the types of values that are part of the MathObjects library (numbers, complex numbers, infinities, points, vectors, intervals, sets, unions, formulas, lists of numbers, lists of points, lists of intervals, lists of formulas returning numbers, lists of formulas returning points, and so on). They are typically invoked using the notation <code>$mathObject->cmp()</code>. The <code>pg/macros</code> directory includes a number of extensions to the MathObjects library. Macro files that begin with <code>parser</code> typically define new classes of objects; e.g., <code>parserParametricLine.pl</code> defines a special class that handles parametric lines in arbitrary dimensions. These are documented in the [[Specialized parsers]] page.
 
   
 
== MathObject Contexts ==
 
== MathObject Contexts ==
   
Although a problem may include several answer blanks, the problem generally has a collection of variables that it defines, values that it uses, and so on; these form the "context" of the problem. For example, if the problem is concerned with a function of <i>x</i> and <i>y</i> and its partial derivatives, then the context of the problem includes variable <i>x</i> and <i>y</i>, and so all the answer blanks within the problem should recognize that <i>x</i> and <i>y</i> have meaning within the problem, even if the answer blank is only asking for a number. Suppose a student is asked to enter the value of a partial derivative at a particular point and, rather than giving a number, enters the formula for the derivative (not evaluated at the point). He should not be told "<i>x</i> is undefined", as would have been the case with WeBWorK's traditional answer checkers, since <i>x</i> actually <i>is</i> defined as part of the problem. Such messages serve to confuse the student rather than help him resolve the problem.
+
Although a problem may include several answer blanks, the problem generally has a collection of variables that it defines, values that it uses, and so on; these form the "context" of the problem. For example, if the problem is concerned with a function of <math>x</math> and <math>y</math> and its partial derivatives, then the context of the problem includes variables <math>x</math> and <math>y</math>, and so all the answer blanks within the problem should recognize that <code>x</code> and <code>y</code> have meaning within the problem, even if the answer blank is only asking for a number. Suppose a student is asked to enter the value of a partial derivative at a particular point and, rather than giving a number, enters the formula for the derivative (not evaluated at the point). He should not be told "x is undefined", as would have been the case with WeBWorK's traditional answer checkers, since <math>x</math> actually <i>is</i> defined as part of the problem. Such messages serve to confuse the student rather than help him resolve the problem.
   
 
MathObjects solves this issue by using a Context object to maintain the context of a problem. That way, all the answer blanks will know about all the variables and values defined within the problem, and can issue appropriate warning messages when a student uses them inappropriately. For example, in the situation described above where the student entered the unevaluated derivative where the value at a point was requested, he will get the message "Your answer is not a number (it seems to be a formula returning a number)", which should help him figure out what he has done wrong.
 
MathObjects solves this issue by using a Context object to maintain the context of a problem. That way, all the answer blanks will know about all the variables and values defined within the problem, and can issue appropriate warning messages when a student uses them inappropriately. For example, in the situation described above where the student entered the unevaluated derivative where the value at a point was requested, he will get the message "Your answer is not a number (it seems to be a formula returning a number)", which should help him figure out what he has done wrong.
Line 33: Line 33:
 
Thus one of the main purposes for the Context is to maintain the set of variables and values that are part of the problem as a whole. Another key function of the Context is to tell the answer checkers what functions and operations are available within a student answer, and what the various symbols the student can type will mean. For example, if you are asking a student to compute the value of 6 / 3, then you may want to restrict what the student can type so that she can't enter <code>/</code> in her answer, and must type an actual number (not an expression that is evaluated to a number). Or if you are asking a student to determine the value of <code>sin(pi/6)</code>, you might want to restrict his answer so that he can't include <code>sin()</code>, but you do allow arithmetic operations. Such restrictions are also part of the context of the problem, and so are maintained by MathObjects as part of the Context.
 
Thus one of the main purposes for the Context is to maintain the set of variables and values that are part of the problem as a whole. Another key function of the Context is to tell the answer checkers what functions and operations are available within a student answer, and what the various symbols the student can type will mean. For example, if you are asking a student to compute the value of 6 / 3, then you may want to restrict what the student can type so that she can't enter <code>/</code> in her answer, and must type an actual number (not an expression that is evaluated to a number). Or if you are asking a student to determine the value of <code>sin(pi/6)</code>, you might want to restrict his answer so that he can't include <code>sin()</code>, but you do allow arithmetic operations. Such restrictions are also part of the context of the problem, and so are maintained by MathObjects as part of the Context.
   
In a similar way, some symbols mean different things in different problems. For example in a problem dealing with intervals, <code>(4,5)</code> means the interval between 4 and 5, while in a multi-variable calculus setting, it might mean a single point in the <i>xy</i>-plane. Or in a problem on complex numbers, the value <i>i</i> means the square root of -1, while in vector calculus, it would mean the coordinate unit vector along the <i>x</i>-axis. Or in a problem on inequalities, <code>5 &lt; x</code> would use <code>&lt;</code> as the "less-than" sign, while in a vector calculus problem, <code>&lt;5,6,7&gt;</code> would mean the vector with coordinates 5, 6, and 7. The Context determines how these symbols will be interpreted by the MathObjects library.
+
In a similar way, some symbols mean different things in different problems. For example in a problem dealing with intervals, <code>(4,5)</code> means the interval between 4 and 5, while in a multi-variable calculus setting, it might mean a single point in the <math>xy</math>-plane. Or in a problem on complex numbers, the value <math>i</math> means <math>\sqrt{-1}</math>, while in vector calculus, it would mean the coordinate unit vector along the <math>x</math>-axis. Or in a problem on inequalities, <code>5 &lt; x</code> would use <code>&lt;</code> as the "less-than" sign, while in a vector calculus problem, <code>&lt;5,6,7&gt;</code> would mean the vector with coordinates 5, 6, and 7. The Context determines how these symbols will be interpreted by the MathObjects library.
   
The MathObjects library comes with a collection of predefined Contexts that you can call on to set the meanings of symbols like these to be what you need for your problems. The default Context is
+
The MathObjects library comes with a collection of predefined Contexts that you can call on to set the meanings of symbols like these to be what you need for your problems. The default Context is the <code>Numeric</code> Context, which is sufficient for most first-semester calculus problems. There are Contexts for complex numbers, intervals, vectors, and so forth; see the [[Common Contexts]] list and the links at the bottom of this document for further information. The [https://github.com/openwebwork/pg/tree/master/macros pg/macros/] directory includes a number of specialized Contexts as well; the files beginning with <code>context</code> define these, and are described on the [[Specialized contexts]] page.
   
Context("Numeric");
 
  +
Use <code>$context = Context();</code> to obtain a reference to the current context. See the [[Introduction to contexts]] for information about how to use this to modify an existing context (e.g., to add variables to it, or to restrict the functions that can be used).
   
and it will be sufficient to use the default context for most first-semester calculus problems. There are Contexts for complex numbers, intervals, vectors, and so forth; see the list below and the links at the bottom of this document, for further information. The <code>pg/macros</code> directory includes a number of specialized Contexts as well; the files beginning with <code>context</code> define these, and are described on the [[Specialized contexts]] page.
 
  +
It is possible to use more than one context within the same problem. This is discussed '''(link needed)'''.
   
The main pre-defined contexts are the following:
 
  +
<div style="font-weight:bold; font-size:125%; margin-top:1em">Further Reading</div>
 
  +
* [[Introduction to Contexts]]
* <code>Numeric</code>: no points, vectors, matrices, complex numbers, or intervals are allowed.
 
  +
* [[Common Contexts]]
* <code>Complex</code>: no points, vectors, matrices, or intervals are allowed.
 
  +
* [[Specialized contexts]]
* <code>Point</code>: Nearly the same as the Vector Context below, but the angle bracket and <code>ijk</code> notation is not allowed, and vector operations on points are not defined.
 
  +
* [https://github.com/openwebwork/pg/tree/master/macros pg/macros] -- files starting with <code>context</code> define new Contexts
* <code>Vector</code>: <code>i</code>, <code>j</code>, and <code>k</code> are defined as coordinate unit vectors, and vector cross and dot produces are allowed. No complex numbers, matrices, or intervals are allowed.
 
* <code>Vector2D</code>: same as Vector above, but <code>i</code> and <code>j</code> are defined as coordinate unit vectors in <math>{\bf R}^2</math>, and <code>k</code> is not defined.
 
* <code>Matrix</code>: same as Vector above, but square brackets define matrices instead of points or intervals.
 
* <code>Interval</code>: similar to Numeric context, but <code>(a,b)</code>, <code>(a,b]</code>, <code>[a,b)</code>, and <code>[a,b]</code> create real Intervals rather than lists or errors. Finite sets of reals are created using <code>{a,b,c}</code> (with as many or as few numbers are needed).
 
* <code>Full</code>: For internal use. This context is used to seed the others.
 
** <code>pi</code> is defined
 
** <code>i</code> is square root of minus one, but <code>j</code> and <code>k</code> are unit Vectors
 
** Matrix, Vector, Point, Intervals, and Complex are all defined
 
** <code>x</code> is a variable
 
 
Use <code>$context = Context();</code> to obtain a reference to the current context. See the [[Introduction to contexts]] for information about how to use this to modify an existing context (e.g., to add variables to it, or to restrict the functions that can be used).
 
   
It is possible to use more than one context within the same problem. This is discussed '''(need a link for this)'''.
 
   
 
== How to create a MathObject ==
 
== How to create a MathObject ==
Line 76: Line 64:
 
* By combining existing MathObjects via mathematical operations (e.g., <code>$x = Formula("x"); $f = $x**2 + 2*$x + 1</code>)
 
* By combining existing MathObjects via mathematical operations (e.g., <code>$x = Formula("x"); $f = $x**2 + 2*$x + 1</code>)
   
Here are some examples:
+
Some examples:
   
 
$a = Real(3.5); or
 
$a = Real(3.5); or
Line 106: Line 94:
 
would show <code>&lt;0.866025,0.5,0.523599&gt;</code> as the correct answer.
 
would show <code>&lt;0.866025,0.5,0.523599&gt;</code> as the correct answer.
   
== The MathObject Classes ==
 
  +
In addition, <code>Compute()</code> can be used to compute the result of a formula at a given value of its inputs. For example,
  +
  +
$a = Compute("x+3",x => 2);
  +
$a = Compute("x^2+y^2",x => 1, y => 2);
  +
  +
both are equivalent to <code>$a = Real(5)</code>.
   
 
The MathObjects library defines classes for a variety of common mathematical concepts, including real numbers, complex numbers, intervals, points, vectors, matrices, and formulas. These are described in more detail in the [[:Category:MathObject_Classes| MathObject Class documentation]].
 
The MathObjects library defines classes for a variety of common mathematical concepts, including real numbers, complex numbers, intervals, points, vectors, matrices, and formulas. These are described in more detail in the [[:Category:MathObject_Classes| MathObject Class documentation]].
   
The <code>pg/macros</code> directory contains a number of extensions to MathObjects, including files that define specialized MathObject types. The ones that begin with <code>parser</code> typically define a new object class. For example, <code>parserParametricLine.pl</code> defines a constructor <code>ParametricLine()</code> for creating a special object that checks if a student's answer is a given parametric line or not, even if it is parameterized differently. These files usually contain documentation within them; see the [http://webwork.maa.org/pod/pg_TRUNK/ POD] documentation for versions that you can read on line.
+
The [https://github.com/openwebwork/pg/tree/master/macros pg/macros] directory contains a number of extensions to MathObjects, including files that define specialized MathObject types. The ones that begin with <code>parser</code> typically define a new object class. For example, <code>parserParametricLine.pl</code> defines a constructor <code>ParametricLine()</code> for creating a special object that checks if a student's answer is a given parametric line or not, even if it is parameterized differently. These files usually contain documentation within them; see the [http://webwork.maa.org/pod/pg/ POD pages] for versions that you can read on line, and [[Specialized parsers]] for a list of most of the MathObject extensions.
  +
  +
<div style="font-weight:bold; font-size:125%; margin-top:1em">Further Reading</div>
  +
* [[:Category:MathObject_Classes| MathObject Class documentation]]
  +
* [[Specialized parsers]]
  +
* [https://github.com/openwebwork/pg/tree/master/macros pg/macros] -- files starting with <code>parser</code> define new MathObejcts
  +
  +
  +
== How to display a MathObject ==
  +
  +
MathObject can be inserted into the text of your problem just as any other variable can be. When this is done, the MathObject will insert its string version (as generated by its <code>[[Common MathObject Methods#string|string()]]</code> method). Frequently, however, you want to include the MathObject within a mathematical expression, and would prefer to use its <math>\rm\TeX</math> form (as generated by its <code>[[Common MathObject Methods#TeX|TeX()]]</code> method). One way to do this is to call the <code>TeX()</code> method directly, as in
  +
  +
$f = Formula("(x+1)/(x-1)");
  +
BEGIN_TEXT
  +
\[f(x) = \{$f->TeX\}\]
  +
END_TEXT
  +
  +
but this requires <code>\{...\}</code> and the explicit use of <code>->TeX</code> to get the desired output. There is an easier way, however, that involves telling the Context to produce <math>\rm\TeX</math> format rather than string format via the <code>texStrings()</code> method of the Context object.
  +
  +
$f = Formula("(x+1)/(x-1)");
  +
Context()->texStrings;
  +
BEGIN_TEXT
  +
\[f(x) = $f\]
  +
END_TEXT
  +
Context()->normalStrings;
  +
  +
In this case, you just use <code>$f</code> within the text of the problem, which is easier to type and easier to read, especially if you have several MathObjects to insert. It is good practice to return the setting to normal using <code>normalStrings()</code>, as is done here, so that if you use MathObjects withing strings later on (e.g., <code>$g = Compute("3*$f + 1")</code>), you will not be inserting <math>\rm\TeX</math> into those strings inadvertently.
  +
   
 
== MathObject Answer Checkers ==
 
== MathObject Answer Checkers ==
Line 120: Line 113:
 
There is no need to select the right kind of answer checker, as the MathObject library handles that for you.
 
There is no need to select the right kind of answer checker, as the MathObject library handles that for you.
   
Many of the answer checkers include options that you can specify. For example, the tolerances to use, or the limits to use for the variables, or whether to provide certain kinds of hints to students as they enter incorrect answers. These are passed as name/value pairs to the <code>cmp()</code> method, as in the following example:
+
Many of the answer checkers include options that you can specify. For example, the tolerances to use, or the limits to use for the variables, or whether to provide certain kinds of hints to students as they enter incorrect answers. These are passed as <code>name=>value</code> to the <code>cmp()</code> method, separated by commas if there is more than one option to set, as in the following example:
   
 
ANS(Real(sqrt(2))->cmp(tolerance => .0001)); # requires answer with roughly four decimal places.
 
ANS(Real(sqrt(2))->cmp(tolerance => .0001)); # requires answer with roughly four decimal places.
 
ANS(Formula("sqrt(x-10)")->cmp(limits => [10,12])); # use x in the interval [10,12] so that the square root is defined.
 
ANS(Formula("sqrt(x-10)")->cmp(limits => [10,12])); # use x in the interval [10,12] so that the square root is defined.
   
See the [http://webwork.maa.org/pod/pg_TRUNK/doc/MathObjects/MathObjectsAnswerCheckers.html Answer Checker POD documentation] for details on the options you can set for the different MathObject classes.
+
See the [[Answer Checkers (MathObjects)| Answer Checkers in MathObjects]] page for details about the MathObject Answer checkers, and the [[Answer Checker Options (MathObjects)| Answer Checker Options]] page for more on the options you can set for the different MathObject classes.
  +
  +
<div style="font-weight:bold; font-size:125%; margin-top:1em">Further Reading</div>
  +
* [[Answer Checkers (MathObjects)| Answer Checkers in MathObjects]]
  +
* [[Answer Checker Options (MathObjects)| Answer Checker Options]]
  +
* [[Custom Answer Checkers]]
  +
   
 
== MathObject Methods and Properties ==
 
== MathObject Methods and Properties ==
Line 140: Line 133:
 
$mathObject->{property-name}
 
$mathObject->{property-name}
   
There are a number of methods and properties that are common to all MathObjects, which are described in the documentation for [[MathObject Methods and Properties]]. Some classes have additional methods and properties, and many of these are described in the [[:Category:MathObject_Classes|MathObject Class documentation]] under the individual class links.
+
There are a number of methods and properties that are common to all MathObjects, which are described in the documentation for [[Common MathObject Methods]] and [[Common MathObject Properties]]. Some classes have additional methods and properties, and many of these are described in the [[:Category:MathObject_Classes|MathObject Class documentation]] under the individual class links.
   
== Experimenting with MathObejcts ==
 
  +
<div style="font-weight:bold; font-size:125%; margin-top:1em">Further Reading</div>
  +
* [[Common MathObject Methods]]
  +
* [[Common MathObject Properties]]
  +
* [[:Category:MathObject_Classes|MathObject Classes]]
   
One way to experiment with MathObjects is to use the [[PGLabs| on-line PG labs]] to write example code and see what it produces. You can copy any of the examples above and paste them into the lab to check the results. This makes it easy to test code without having to write complete problem files and save them in a course. One lab lets you get the output from a line of PG code, while another lets you try out full problems to see how they work.
 
   
== Files defining MathObjects ==
 
  +
== Experimenting with MathObejcts ==
   
The MathObjects library is contained in two Perl packages: the Parser package and the Value package. The first of these implements the parser that converts student answers (or strings passed to <code>Compute()</code> or the MathObject constructor functions) into the corresponding MathObjects. The second implements the mathematical operations and functions for the various object types. The files that define the Parser package are <code>pg/lib/Parser.pm</code> and the files in the directory <code>pg/lib/Parser/</code>, while the Value package is defined in <code>pg/lib/Value.pm</code> and the directory <code>pg/lib/Value/</code>. There are also two macro files <code>pg/macro/Parser.pl</code> and <code>pg/macro/Value.pl</code> that define the object constructors and other values needed by PG problems that use MathObjects. The <code>pg/macros/MathObjects.pl</code> file is a wrapper that loads these two, and is the file that you need to include in your <code>loadMacros()</code> call in order to use MathObjects in a problem you are writing.
 
  +
One way to experiment with MathObjects is to use the [[PGLabs| on-line PG labs]] to write example code and see what it produces. You can copy any of the examples above (or elsewhere in the WIki) and paste them into the lab to check the results. This makes it easy to test code without having to write complete problem files and save them in a course. One lab lets you get the output from a line of PG code, while another lets you try out full problems to see how they work.
   
The <code>pg/lib/Value/</code> directory includes files for each of the MathObject types (e.g., <code>Real.pm</code>, <code>Complex.pm</code>, etc.). These define the various object types and how they operate. For example, these implement how operations like addition and multiplication work for each object class, how functions like <code>sin()</code> and <code>sqrt()</code> work, how to compare two objects for equality and numeric order, how to display the object in TeX and string form, how to covert the object to Perl code, and so on.
 
 
The <code>pg/lib/Parser/</code> directory contains files that make it possible to break up a string into its various tokens and map them to build the parse tree for the expression. For example, there are binary-operator and unary-operator classes that form the nodes of an expression tree. There are also function classes to handle function calls, list classes to handle points, vectors, and so on, and classes for the various values that can be produced, like numbers and strings. The Context stores information that the parser uses to create the parse tree, so the various entities like variables, constants, strings, operators, functions, parens, and so on that you can set in the Context correspond directly to the classes defined in <code>pg/lib/Parser</code>. The Parser classes are related to the ones defined in the Value package, but are not the same. The former are used to build the parse tree, while that latter are used to compute specific instances of the objects.
 
   
 
== See also ==
 
== See also ==
* [http://webwork.maa.org/pod/pg_TRUNK/doc/MathObjects/UsingMathObjects.html Using Math Objects] POD documentation
+
* [http://webwork.maa.org/pod/pg/doc/MathObjects/UsingMathObjects.html Using Math Objects] POD documentation
* [http://webwork.maa.org/pod/pg_TRUNK/doc/MathObjects/MathObjectsAnswerCheckers.html Math Objects Answer Checkers] POD documentation
+
<div style="margin-top:.75em">
  +
* [[:Category:MathObject_Classes| MathObject Classes]]
  +
* [[Common MathObject Methods]]
  +
* [[Common MathObject Properties]]
  +
</div>
  +
<div style="margin-top:.75em">
  +
* [[Answer Checkers (MathObjects)| Answer Checkers]]
  +
* [[Answer Checker Options (MathObjects)| Answer Checker Options]]
  +
* [[Custom Answer Checkers]]
  +
* [[Custom Answer Checkers for Lists]]
  +
</div>
  +
<div style="margin-top:.75em">
 
* [[Introduction to contexts]]
 
* [[Introduction to contexts]]
  +
* [[Common Contexts]]
 
* [[Context flags]]
 
* [[Context flags]]
 
* [[Specialized contexts]]
 
* [[Specialized contexts]]
  +
* [[Modifying contexts (advanced)]]
  +
</div>
  +
<div style="margin-top:.75em">
 
* [[Specialized parsers]]
 
* [[Specialized parsers]]
* [[Modifying contexts (advanced)]]
 
  +
</div>
   
 
[[Category:MathObjects]]
 
[[Category:MathObjects]]

Latest revision as of 16:14, 7 April 2021

What are MathObjects?

MathObjects are a set of Perl objects that make the manipulation of mathematics within WeBWorK problems more intuitive. They make it possible to define variables in your problems that correspond to common mathematical objects, such as formulas, real number, complex numbers, intervals, vectors, points, and so on. For example:

   $f = Formula("sin(x^2+6)");
   $a = Real("sqrt(pi/6)");
   $z = Complex("1 + 5i");

These are useful (and powerful) because MathObjects "know" information about themselves; thus, you can add formulas to get new formulas, plug real objects into formulas to get formulas evaluated at those values, calculate derivatives of formulas, add and subtract intervals to form unions and intersections, and much more.

For several reasons it is usually preferable to write the MathObjects above using the Compute() function rather than the individual constructors for the various MathObject types.

   $f = Compute("sin(x^2+6)");
   $a = Compute("sqrt(pi/6)");
   $z = Compute("1 + 5i");

The Compute() function determines the kind of MathObject from the Context and from the syntax of its argument, which is usually a string value that is in the form that a student could type. The Compute function also sets the "correct answer" to be the exact string that it was given, so that if a student were asked to enter a number that matched $a from above and asked to see the correct answer (after the due date), then sqrt(pi/6) would be displayed rather than 0.723601. This gives you more control over the format of correct answers that are shown to students.


Why use MathObjects?

MathObjects are designed to be used in two ways. First, you can use them within your Perl code when writing problems as a means of making it easier to handle formulas and other mathematical items, and in particular to be able to produce numeric values, TeX output, and answer strings from a single formula object. This avoids having to type a function three different ways (as a Perl function, as a TeX string, and as an answer string), making it much easier to maintain a problem, or duplicate and modify it to use a different formula. Since MathObjects also includes vectors, points, matrices, intervals, complex numbers, and a variety of other object types, it is easier to work with these kinds of values as well.

More importantly, using MathObjects improves the processing of student input. This is accomplished through special answer checkers that are part of the MathObjects Parser package rather than the traditional WeBWorK answer checkers. Each of these checkers has error checking customized to the type of input expected from the student and can provide helpful feedback if the syntax of the student's entry is incorrect. Because the MathObject checkers are part of a unified library, students get consistent error messages regardless of the type of answer that is expected or that they provide. For example, if a student enters a formula in an answer blank where the correct answer is actually a number, she will receive a message indicating that what she typed was a formula but that a number was expected. Thus students are given guidance automatically about this type of semantic problem with their answers. Answer checkers for points and vectors can indicate that the number of coordinates are wrong, or can tell the student which coordinates are incorrect (at the problem-author's discretion).


MathObject Contexts

Although a problem may include several answer blanks, the problem generally has a collection of variables that it defines, values that it uses, and so on; these form the "context" of the problem. For example, if the problem is concerned with a function of [math]x[/math] and [math]y[/math] and its partial derivatives, then the context of the problem includes variables [math]x[/math] and [math]y[/math], and so all the answer blanks within the problem should recognize that x and y have meaning within the problem, even if the answer blank is only asking for a number. Suppose a student is asked to enter the value of a partial derivative at a particular point and, rather than giving a number, enters the formula for the derivative (not evaluated at the point). He should not be told "x is undefined", as would have been the case with WeBWorK's traditional answer checkers, since [math]x[/math] actually is defined as part of the problem. Such messages serve to confuse the student rather than help him resolve the problem.

MathObjects solves this issue by using a Context object to maintain the context of a problem. That way, all the answer blanks will know about all the variables and values defined within the problem, and can issue appropriate warning messages when a student uses them inappropriately. For example, in the situation described above where the student entered the unevaluated derivative where the value at a point was requested, he will get the message "Your answer is not a number (it seems to be a formula returning a number)", which should help him figure out what he has done wrong.

Thus one of the main purposes for the Context is to maintain the set of variables and values that are part of the problem as a whole. Another key function of the Context is to tell the answer checkers what functions and operations are available within a student answer, and what the various symbols the student can type will mean. For example, if you are asking a student to compute the value of 6 / 3, then you may want to restrict what the student can type so that she can't enter / in her answer, and must type an actual number (not an expression that is evaluated to a number). Or if you are asking a student to determine the value of sin(pi/6), you might want to restrict his answer so that he can't include sin(), but you do allow arithmetic operations. Such restrictions are also part of the context of the problem, and so are maintained by MathObjects as part of the Context.

In a similar way, some symbols mean different things in different problems. For example in a problem dealing with intervals, (4,5) means the interval between 4 and 5, while in a multi-variable calculus setting, it might mean a single point in the [math]xy[/math]-plane. Or in a problem on complex numbers, the value [math]i[/math] means [math]\sqrt{-1}[/math], while in vector calculus, it would mean the coordinate unit vector along the [math]x[/math]-axis. Or in a problem on inequalities, 5 < x would use < as the "less-than" sign, while in a vector calculus problem, <5,6,7> would mean the vector with coordinates 5, 6, and 7. The Context determines how these symbols will be interpreted by the MathObjects library.

The MathObjects library comes with a collection of predefined Contexts that you can call on to set the meanings of symbols like these to be what you need for your problems. The default Context is the Numeric Context, which is sufficient for most first-semester calculus problems. There are Contexts for complex numbers, intervals, vectors, and so forth; see the Common Contexts list and the links at the bottom of this document for further information. The pg/macros/ directory includes a number of specialized Contexts as well; the files beginning with context define these, and are described on the Specialized contexts page.

Use $context = Context(); to obtain a reference to the current context. See the Introduction to contexts for information about how to use this to modify an existing context (e.g., to add variables to it, or to restrict the functions that can be used).

It is possible to use more than one context within the same problem. This is discussed (link needed).

Further Reading


How to create a MathObject

In order to use MathObjects in a problem you are writing, include MathObjects.pl in your loadMacros() call. For example:

   loadMacros(
     "PGstandard.pl",
     "MathObjects.pl",
     "PGcourse.pl",
   );

Once this is done, there are several ways to create MathObjects in your problem:

  • By calling a constructor function for the type of object you want (e.g., Real(3.5) or Complex("3+4i"))
  • By calling Compute() to parse a string and return the resulting object (e.g., Compute("3+4i"))
  • By calling a method of an existing MathObject that returns another object (e.g., Formula("sin(x)")->eval(x => pi/2))
  • By combining existing MathObjects via mathematical operations (e.g., $x = Formula("x"); $f = $x**2 + 2*$x + 1)

Some examples:

   $a = Real(3.5);   or
   $a = Compute(3.5);   or
   $a = Compute("3.5");
   $b = Complex(3, 4);   or
   $b = Complex("3 + 4i");   or 
   $b = Compute("3 + 4i");
   $v = Vector(4,5,8);   or
   $v = Vector([4,5,8]);   or
   $v = Vector("<4,5,8>");  or
   $v = Compute("<4,5,8>");
   $f = Formula("sin(x^2) + 6");  or
   $f = Compute("sin(x^2) + 6");

Here, $a (defined any of the three ways) represents a real number and $b (defined by any of the three) represents a complex number; $v will be a vector, and $f is a formula.

In general, the Compute() variant is preferred because you enter what you want the student to type, and Compute() generates the proper MathObject to handle that (just as it will when it processes the student answer). Another important feature of Compute() is that the input string also serves as the correct answer when a student requests answers after the due date, which lets you put the correct answer in exactly the form you want it to appear. For example if you use

   Compute("<cos(pi/6),sin(pi/6), pi/6>")->cmp

the correct answer will be presented to the student as <cos(pi/6),sin(pi/6), pi/6>, while

   Vector("<cos(pi/6),sin(pi/6), pi/6>")->cmp

would show <0.866025,0.5,0.523599> as the correct answer.

In addition, Compute() can be used to compute the result of a formula at a given value of its inputs. For example,

   $a = Compute("x+3",x => 2);
   $a = Compute("x^2+y^2",x => 1, y => 2);

both are equivalent to $a = Real(5).

The MathObjects library defines classes for a variety of common mathematical concepts, including real numbers, complex numbers, intervals, points, vectors, matrices, and formulas. These are described in more detail in the MathObject Class documentation.

The pg/macros directory contains a number of extensions to MathObjects, including files that define specialized MathObject types. The ones that begin with parser typically define a new object class. For example, parserParametricLine.pl defines a constructor ParametricLine() for creating a special object that checks if a student's answer is a given parametric line or not, even if it is parameterized differently. These files usually contain documentation within them; see the POD pages for versions that you can read on line, and Specialized parsers for a list of most of the MathObject extensions.

Further Reading


How to display a MathObject

MathObject can be inserted into the text of your problem just as any other variable can be. When this is done, the MathObject will insert its string version (as generated by its string() method). Frequently, however, you want to include the MathObject within a mathematical expression, and would prefer to use its [math]\rm\TeX[/math] form (as generated by its TeX() method). One way to do this is to call the TeX() method directly, as in

   $f = Formula("(x+1)/(x-1)");
   BEGIN_TEXT
     \[f(x) = \{$f->TeX\}\]
   END_TEXT

but this requires \{...\} and the explicit use of ->TeX to get the desired output. There is an easier way, however, that involves telling the Context to produce [math]\rm\TeX[/math] format rather than string format via the texStrings() method of the Context object.

   $f = Formula("(x+1)/(x-1)");
   Context()->texStrings;
   BEGIN_TEXT
     \[f(x) = $f\]
   END_TEXT
   Context()->normalStrings;

In this case, you just use $f within the text of the problem, which is easier to type and easier to read, especially if you have several MathObjects to insert. It is good practice to return the setting to normal using normalStrings(), as is done here, so that if you use MathObjects withing strings later on (e.g., $g = Compute("3*$f + 1")), you will not be inserting [math]\rm\TeX[/math] into those strings inadvertently.


MathObject Answer Checkers

Each MathObject type has a corresponding answer checker that can be used to process student responses. You obtain the checker by using the cmp() method of the MathObject.

   ANS($mathObject->cmp);

There is no need to select the right kind of answer checker, as the MathObject library handles that for you.

Many of the answer checkers include options that you can specify. For example, the tolerances to use, or the limits to use for the variables, or whether to provide certain kinds of hints to students as they enter incorrect answers. These are passed as name=>value to the cmp() method, separated by commas if there is more than one option to set, as in the following example:

   ANS(Real(sqrt(2))->cmp(tolerance => .0001));           # requires answer with roughly four decimal places.
   ANS(Formula("sqrt(x-10)")->cmp(limits => [10,12]));    # use x in the interval [10,12] so that the square root is defined.

See the Answer Checkers in MathObjects page for details about the MathObject Answer checkers, and the Answer Checker Options page for more on the options you can set for the different MathObject classes.

Further Reading


MathObject Methods and Properties

Since MathObjects are Perl objects, you call a method on a MathObject as you would a method for any Perl object, using the -> operator with the MathObject on the left and the method name and its arguments (if any) on the right. E.g.,

   $mathObject->method;              # when there are no arguments
   $mathObject->method($arg);        # for one argument
   $mathObject->method($arg1,$arg2); # for two arguments
   # and so on

Similarly, you access the properties of an object just as you would for a Perl hash, via the -> operator with the MathObject on the left and the property name in braces on the right. E.g.,

   $mathObject->{property-name}

There are a number of methods and properties that are common to all MathObjects, which are described in the documentation for Common MathObject Methods and Common MathObject Properties. Some classes have additional methods and properties, and many of these are described in the MathObject Class documentation under the individual class links.

Further Reading


Experimenting with MathObejcts

One way to experiment with MathObjects is to use the on-line PG labs to write example code and see what it produces. You can copy any of the examples above (or elsewhere in the WIki) and paste them into the lab to check the results. This makes it easy to test code without having to write complete problem files and save them in a course. One lab lets you get the output from a line of PG code, while another lets you try out full problems to see how they work.


See also