# Difference between revisions of "Formula (MathObject Class)"

### Formula Class

A Formula object represents an expression whose result is one of the MathObject types defined above. These act like functions in that you can evaluate them at different values of the variables that they use, or substitute other expressions for the variables (to form compositions).

### Construction

```   \$f = Formula("2x^2+3x-5");

\$a = random(2,5,1);
\$b = random(5,9,1);
\$f = Formula("x^2 + \$a x + \$b");
```

The variables used in a Formula must be declared in the Context. The Numeric Context has `x` pre-defined, but you can add more, as in the following example:

```   Context("Numeric");

\$f = Formula("x^2 + 2xy + y^2");
```

### Operations on Formulas

Formulas can be added, subtracted, multiplied, etc, to obtain new Formula objects, and functions like `sin()`, `sqrt()`, and so on will return Formula objects when their arguments are formulas:

```   \$x = Formula("x");
\$f = 3* \$x**2 - 2 * \$x + 5;    # same as Formula("3x^2 - 2x + 5");
\$g = \$x - 5;
\$h = \$f / \$g;                  # same as Formula("(3x^2 - 2x + 5) / (x - 5)");
\$g1 = sin(\$g)                  # same as Formula("sin(x-5)");
```

Formulas can produce any type of MathObject as its result, including points, vectors, intervals, etc. For example,

```   Context("Vector");
\$f1 = Formula("<2x+1,1-x,x^2>");           # a vector-valued formula

\$f2 = Formula("(1,3,-2) + t <4,-1,2>");    # a parametric line

Context("Interval");
\$f3 = Formula("(x,2x+1]");                 # an interval-valued formula
```

#### Reducing Formulas

If you substitute values as coefficients in a formula, you may end up with things like `1 x^2 + -3 x + 0`, but Formulas have a `reduce` method that can be used to remove coefficients of 1, simplify addition of negatives, remove sums or products of 0, and so forth. E.g.,

```   \$f = Formula("1 x^2 + -3 x + 0")->reduce;  # same as Formula("x^2 - 3x");
```

There are a number of reduction rules, and you can enable or disable them individually (reference needed). Note, however, that MathObjects is not a full computer algebra system, and the reduction rules are mainly geared toward improving the output, not solving equations or performing algebraic manipulations to simplify the expression.

#### Evaluating Formulas

Given a Formula, you may want to evaluate the Formula at a particular value of its variable; that can be accomplished by the `eval()` method. The arguments to `eval()` assign values to all the variables of the Formula, and it returns the value of the Formula for those inputs. For example:

```   \$f = Formula("x^2 + 2x + 1");
\$a = \$f->eval(x=>2);            # f at x=2, or Real(9)

\$g = Formula("xy + x + y");
\$b = \$g->eval(x=>2,y=>3);       # g at (x,y) = (2,3), or Real(11);
```

The `substitute()` method is similar to `eval()`, but in this case, the specified variables are replaced by the values that are given. The values need not be constants; they could be Formulas, in which case the result is the composition of the two Formulas. Note that not all the variables need to be substituted (unlike with `eval()`, where all variables must be given a value).

```   \$f = Formula("x^2 + 2x + 1");
\$g1 = \$f->substitute(x => "y");            # same as Formula("y^2 + 2y + 1");
\$g2 = \$f->substitute(x => "2x-1");         # same as Formula("(2x-1)^2 + 2(2x-1) + 1");

\$h = Formula("xy + x + y");
\$h1 = \$h->substitute(x => "y");            # same as Formula("y*y + y + y") or Formula("y^2 + 2y");
\$h2 = \$h->substitute(x => 2, y => "3x");   # same as Formula("2(3x) + 2 + 3x");
```

#### Perl Code from Formulas

If you need to evaluate a Formula multiple times (for example, to produce a graph), it is not very efficient to use `eval()`. Instead, you can use the `perlFunction` method to generate a native Perl function that you can call to evaluate the Formula. If given no arguments, `perlFunction()` returns an anonymous code reference to a subroutine that evaluates the Formula; the parameters to the subroutine are the values of the variables (in alphabetical order). If a single argument is given, it is the name to give to the subroutine; if two arguments are given, the second is an array reference that lists the order of the variables to use for the arguments to the subroutine.

```   \$f = Formula("x^2+y");

\$F = \$f->perlFunction;            # anonymous subroutine reference
\$a = &{\$F}(2,3);                  # value of \$f for x=2 and y=3, i.e., Real(7)
```
```   \$f->perlFunction("F");            # subroutine named F
\$a = F(2,3);                      # again, Real(y)
```
```   \$f->perlFunciton("G",["y","x"]);  # change order of variables in arguments to G
\$a = \$G(2,3);                     # value of \$f for y=2 and x=3, i.e.,  Real(11);
```

#### Derivatives of Formulas

You can obtain the derivative of a Formula using the `D()` method. If the Formula has more than one variable, then you need to indicate which one to differentiate by; you do this by giving the variable name as an argument to the method. You can get second or third derivatives (or higher) either by using `D()` a second time or third time, or by including more variable names in the call to `D()`. For example:

```   \$f = Formula("3x^2-5x+2");
\$df = \$f->D('x');                    # same as Formula("3*(2x)-5");
\$df_4 = \$df->eval(x=>4);             # f'(4), i.e., Real(19);
\$ddf = \$df->D('x');                  # same as Formula("6");
\$ddf = \$f->D('x','x');               # same as above

\$f = Formula("x^2 + 4xy^2 + y^3");
\$fx = \$f->D('x');                    # same as Formula("2x+4y^2");
\$fxy = \$fx->D('y');                  # same as Formula("4*(2y)");
\$fxy = \$f->D('x','y');               # same as above
```

As with all MathObjects, you obtain an answer checker for a Formula object via the `cmp()` method:

```   ANS(Compute("x^2+2x+1")->cmp);
```

The options for the Formula answer checker is dependent on the type of the result of the Formula. They include all the options for the class of the result, and the following additional options:

Option Description Default
`upToConstant => 1` or `0` For Real-valued formulas, this controls whether the student's answer only needs to match the correct answer up to addition of a constant. `0`
`showDomainErrors => 1` or `0` If the test points for the function comparison reveals that the student answer is defined on a different domain from the correct answer (e.g., the student's answer is not defined at one of the test points), then this value determines whether or not a message is issued alerting the student to that fact. `1`

### Methods

The Formula class supports the Common MathObject Methods, and the following additional methods:

Method Description
`\$f->eval(x => value,...)` Returns the value of `\$f` evaluated at the given values of its variables. All variables used in the Formula must be given a value (use `substitute` if you want to set only some of the variables). See the Evaluating Formulas above for examples.
`\$f->substitute(x => value,...)` Returns a copy of `\$f` with the given values replaced by their given values. The values can be any appropriate MathObject, including other Formula objects. If the value is a perl string, it will be parsed to form a MathObject. See the Evaluating Formulas above for examples.
`\$f->reduce`
`\$f->reduce(rule => 0 or 1,...)`
Returns a copy of `\$f` where the MathObject reduction rules have been applied. You can turn on or off individual rules or collections of rules by giving the name of the rule and setting it to `0` (don't apply) or 1 (apply). See Reducing Formulas above for examples. See the Reduction rules for MathObject Formulas for a list of the reduction rules.
`\$f->perlFunction`
`\$f->perlFunction("name")`
`\$f->perlFunction("name",["x",...])`
Turns `\$f` into executable Perl code that can be called to evaluate the Formula efficiently. The first form returns an anonymous code reference, the second makes a names Perl subroutine, and the third specifies the order of the variables in the subroutine's argument list (the default is alphabetical). See Perl Code from Formulas above for examples.
`\$f->isConstant` Returns `true` if `\$f` contains no variables (i.e., is constant-valued), and `undef` otherwise.
`\$f->usesOneOf("x",...)` Returns `1` if any of the variables listed appear in `\$f`, and `0` otherwise.
`\$f->copy` Returns a copy of `\$f`. Note that setting `\$g = \$f` does not copy `\$f`; instead, both `\$g` and `\$f` both point to the same Formula object, so changes to one will change the other. Use `\$g = \$f->copy` to obtain a separate copy for `\$g`.

There are additional methods for a Formula that are for internal use during the parsing of the formula. These are in the `pg/lib/Parser.pm` file, and are not documented here.

### Properties

The Formula class supports the Common MathObject Properties, and the following additional ones:

Property Description Default
`\$f->{test_points}` A reference to an array of values to use for the variables in `\$f` when comparing `\$f` to another Formula. The value in the array are themselves references to arrays whose values are the values for the variables in `\$f` listed in alphabetical order. For example,
`\$f = Formula("ln(|x|)")->with(test_points => [[-3],[-2],[-1],,,]);`

sets `\$f` so that both positive and negative values are used; this means `\$f` will not match `Formula("ln(x)")`, for instance.

If not set, it will be created automatically from random points when `\$f` is first compared to another Formula. If set, no random points will be used.

`undef`
`\$f->{test_at}` A reference to an array of values to use for test points for `\$f` in addition to the randomly chosen ones. The format is the same as for `test_points` above. E.g.,
`\$f = Formula("ln(|x|)")->with(test_at => [[-1],]);`

will cause `\$f` to use [math]x=-1[/math] and [math]x=1[/math] along with the usual random points when it is compared to another Formula.

`undef`
`\$f->{test_values}` A reference to an array of values produced by `\$f` at the `\$f->{test_points}`. You should not set this yourself; it is generated automatically when `\$f` is compared to another Formula. produced from `\$f`
`\$f->{test_adapt}` When `\$f` includes adaptive parameters, this is a reference to the array of values produced by the adapted formula at the test points (where the adaptive parameters have their adapted values). You should not set this yourself; it is generated automatically when `\$f` is compared to another Formula. produced from `\$f`
`\$f->{parameters}` When `\$f` includes adaptive parameters, this is a reference to the array of the adapted values for those parameters (in alphabetical order). You should not set this yourself; it is generated automatically when `\$f` is compared to another Formula. produced automatically
`\$f->{variables}` A reference to a hash whose keys are the names of the variables used in `\$f` (and whose values are 1). You should not set this yourself; it is maintained automatically. produced automatically
`\$f->{values}` A reference to a hash whose keys are the names of variables whose values are being set during an `eval()` or `substitute()` call, and whose values are the values to which each variable is being set. You should not set this yourself; it is maintained automatically by the `eval()` and `substitute()` methods, but if you implement your own parser objects, you may need to read these values to perform the requires substitutions. produced automatically
`\$f->{f}` An anonymous code reference used to evaluate `\$f` during comparisons to other Formulas. You should not set this value yourself; it is generated automatically when `\$f` is compared to another Formula. `\$f->perlFunction`
`\$f->{domainMismatch}` When `\$f` is compared to another Formula, this is set to `1` if the other Formula can't be computed at all the test points for `\$f`, and `0` if it can be. You should not set this value yourself; it is generated automatically when `\$f` is compared to another Formula. produced automatically
`\$f->{tree}` This is a reference to the root node of the parse tree for the Formula. The tree is made up of nodes that represent things like binary operators, function calls, variable references, and so on. The various types of nodes are implemented by the files in the pg/lib/Parser directory, with `pg/lib/Parser/Item.pm` being the base class from which others are subclassed. produced automatically
`\$f->{string}` The original string from which the Formula was generated, when it was created by parsing a string (e.g., via `Compute()` or `Formula()`). `undef`
`\$f->{tokens}` A reference to the array of "tokens" produced by parsing the string for `\$f`. These are themselves references to arrays of four or five elements: the first is a string indicating the type of token (e.g., `"var"`, `"num"`, `"fn"`, etc.), the second is a string representing the instance of that type for this token (e.g., `"x"`, `3.14`, `"sin"`, etc.), and the next two are the starting and ending positions of the token in the original string (used for syntax error highlighting); if present, the fifth is `true` when there are spaces preceding the given token in the string (used for experimental non-standard operator precedences). produced automatically