# SumGrader #

`SumGrader`

is a specialized grading class used to grade the construction of summations. Students can input the limits on the sum, the variable of summation, and the summand (or some subset thereof), and will be graded correct if their construction is numerically equivalent to the instructor's construction. This method of grading allows for arbitrary variable redefinitions.

The grader numerically evaluates the student- and instructor-specified summations by evaluating the sums. Care must be taken to ensure rapid convergence with infinite summations, of which only finitely many terms can be numerically summed.

## XML Setup #

We recommend copying the following XML to set up a problem using `SumGrader`

:

```
<style>
.xmodule_display.xmodule_ProblemBlock .problem .capa_inputtype.textline input {
min-width: 0 !important;
}
.xmodule_display.xmodule_ProblemBlock div.problem section div span.MathJax {
display: inline-block !important;
}
.xmodule_display.xmodule_ProblemBlock div.problem section div span.MathJax_Preview {
display: inline-block !important;
}
</style>
<span>
<customresponse cfn="grader">
<table>
<col style="width:10%"/>
<col style="width:90%"/>
<tbody>
<tr>
<td colspan="2">
<textline size="5" correct_answer="10"/>
</td>
</tr>
<tr>
<td>
<p> \( \displaystyle \huge{ \sum }\)</p>
</td>
<td>
<br/>
<textline inline="1" size="10" correct_answer="n" math="1" preprocessorClassName="MJxPrep" preprocessorSrc="/static/MJxPrep.js"/>
</td>
</tr>
<tr>
<td colspan="2">
<p style="display: inline;">[mathjaxinline]n = [/mathjaxinline] </p><textline size="5" correct_answer="0" inline="1"/>
</td>
</tr>
</tbody>
</table>
</customresponse>
</span>
```

This sets up a summation where students can input the limits of summation and the summand (the variable of summation has been fixed to be `n`

in this case).

Further examples of formatting summations are shown in the example course.

## Specifying the Input Format #

The grader must be told which input is what, based on the order that the inputs appear in the XML. This is done through the `input_positions`

dictionary. If not specified, it is assumed that the following positions are used:

```
input_positions = {
'lower': 1,
'upper': 2,
'summand': 3,
'summation_variable': 4
}
```

This requires students to enter all four parameters in the indicated order.

If the author overrides the default `input_positions`

value, any subset of the keys ('lower', 'upper', 'summand', 'summation_variable') may be specified. Key values should be

- continuous integers starting at 1, or
- (default) None, indicating that the parameter is not entered by student

For example,

```
input_positions = {
'lower': 1,
'upper': 2,
'summand': 3
}
```

indicates that the problem has 3 input boxes which represent the lower limit, upper limit, and summand in that order. The `summation_variable`

is NOT entered by student and is instead given by the value specified by author in 'answers'.

Here is a sample grader for the above XML:

```
>>> from mitxgraders import *
>>> grader = SumGrader(
... answers={
... 'lower':'0',
... 'upper':'10',
... 'summand':'n*(n+1)',
... 'summation_variable':'n'
... },
... input_positions = {
... 'upper': 1,
... 'summand': 2,
... 'lower': 3
... }
... )
```

Note that when students specify their own variable of summation, it must not conflict with a variable already present in the problem. Note that this means that `i`

and `j`

are not available as variables of summation (as they are used to indicate the imaginary unit).

## Specifying the Answer #

The author's answer should be specified as a dictionary with the following keys:

```
answers = {
'lower': 'lower_limit',
'upper': 'upper_limit',
'summand': 'summand',
'summation_variable': 'variable_of_summation'
}
```

Note that each entry is a string value. `SumGrader`

can handle numerical, complex, vector and even matrix summands. However, it cannot handle numbered variables where the index of the numbered variable is given by the summation variable. This is due to a limitation in the way that numbered variables are sampled.

Unlike integrals, the order of the limits is unimportant.

## Infinite Sums #

`SumGrader`

can handle sums over both finite and infinite ranges. A special constant `'infty'`

is recognized to cater for the infinite case (and takes on the special value `float('inf')`

).

When an infinite range is specified, the grader substitutes `infty`

for a large but finite number. This value can be set using the `inft_val`

option, which defaults to `1000`

(`1e3`

). If the grader detects the presence of the factorial function in the summand, it instead uses the value specified by the `infty_val_fact`

, which defaults to 80. Note that `(2*80)! = 160! ~ 10^284`

is just below the limit of values that can be handled numerically by double precision. This ensures that typical expressions involving factorials will not lead to overflow errors, and also leaves sufficient terms to ensure convergence.

Because infinite sums can be rewritten in a myriad of ways, it is important to ensure that after sufficiently many terms are computed, the summation has converged to within numerical precision. This often means that extra variables must be specified in a small range. E.g., if `x`

is included in the summand as `x^n`

, we recommend setting `x`

in the range `[0,0.5]`

or so. Note that `0.5^80 ~ 10^-25`

, which should be sufficiently small compared to the leading order terms.

To aid in grading infinite sums, the default tolerance on a `SumGrader`

has been set to an absolute value of `1e-12`

. This may be important when the answer provided by the instructor includes twice or half as many terms as the answer provided by the student, even though both sums are equivalent when taken to infinity.

So long as infinite summations converge sufficiently rapidly, `SumGrader`

does a good job at evaluating them. As examples, we have tested that Taylor series expansions for `exp`

, `sin`

and `cos`

converge to numerical precision for small arguments. We advise against using `SumGrader`

for slowly-converging series, such as the typical expansion for `tan^-1(1)`

.

Note that if you are using vectors or matrices in your sums, we strongly suggest that you use a small value for both `infty_val`

and `infty_val_fact`

, probably in the 15-20 range. Otherwise, you may see timeout errors from the python grader on edX.

## Even and Odd Sums #

`SumGrader`

can be told to sum only over even or odd integers through the `even_odd`

option. The default value is 0, which indicates to sum over all integers. Setting it to 1 indicates to sum over odd integers, and 2 indicates to sum over even integers. Instructors must specify this option at construction; students are unable to set this option themselves.

Here is a sample grader that implements the Taylor expansion for sine using odd integers only:

```
>>> from mitxgraders import *
>>> grader = SumGrader(
... answers={
... 'lower':'1',
... 'upper':'infty',
... 'summand':'(-1)^((n-1)/2)*x^n/fact(n)',
... 'summation_variable':'n'
... },
... input_positions={
... 'upper': 1,
... 'summand': 2,
... 'lower': 3
... },
... even_odd=1
... )
```

## Other Options #

The following options from `FormulaGrader`

are available for use in `SumGrader`

:

`user_constants`

`user_functions`

`whitelist`

`blacklist`

`tolerance`

`samples`

(default: 2)`variables`

`sample_from`

`failable_evals`

`numbered_vars`

`instructor_vars`

`forbidden_strings`

`forbidden_message`

`required_functions`

`metric_suffixes`

Unless otherwise specified, the defaults are the same as in `FormulaGrader`

.

## Option Listing #

Here is the full list of options specific to an `SumGrader`

.

```
grader = SumGrader(
input_positions=dict,
answers=dict,
even_odd=int, # default 0
infty_val=int, # default 1000
inftY_val_fact=int, # default 80
# The below options are the same as in FormulaGrader
variables=list, # default []
sample_from=dict, # default {}
samples=int, # default 1
user_functions=dict, # default {}
user_constants=dict, # default {}
failable_evals=int, # default 0
blacklist=list, # default []
whitelist=list, # default []
tolerance=(float | percentage), # default 1e-12
numbered_vars=list, # default []
instructor_vars=list, # default []
forbidden_strings=list, # default []
forbidden_message=str, # default 'Invalid Input: This particular answer is forbidden'
required_functions=list, # default []
metric_suffixes=bool, # default False
)
```