### Verifying Programs

Although EM was not designed as an assessor program, but rather for self-testing in a computer-based learning environment, reliable checking of the answers is a necessary feature to provide feedback for students. It is important to analyze what went wrong in a given answer. For instance, EM should be able to report that the dimensions of the matrices are not correct, or that a special type of matrix is expected. So, we have implemented the checking algorithm separately for each exercise as a verifying program, which is designed to report error messages relevant to that exercise. Obviously, there must be a mechanism to make a proposed answer available to the verifying program. This is accomplished by translating the current state of all objects comprising the answer template into expressions that are passed to the kernel just before the program is evaluated. The verifying program can access those expressions because EM assigns them to be values of symbols identical to the `object-tags` of the objects. Therefore, the strings given as `object-tags` in the object definitions should be different from any other symbols used in the generating and verifying programs. Each object-type has its own scheme for translating the state of the objects into expressions. For instance, consider the box of a `MatrixEntry` object with `theMatrix` as its `object-tag`. If we type

EM will pass the following expression when the checking is initiated.

Similarly, the state of a `CheckBoxes` or `RadioControls` object is presented as a list of `True/False` symbols. One possible way to structure the verifying program, which we have used throughout all the exercises on matrix algebra, is as follows.

Various conditions can be tested in turn by the `Which` operator. If one of them fails, the corresponding error message, kept as a string in `errMsgs`, is returned. If all conditions hold, "OK" is returned; this is the only string that EM will recognize as a correctly answered problem. As an example, the verifying program of the "LU Decomposition" exercise is given in Listing 2. Students are asked to compute L and U for a given square matrix A such that

where L is lower-triangular, U is upper-triangular, and P is any permutation matrix. The answer template for this exercise is comprised of two objects of type `MatrixEntry`. Since the strings `theL` and `theU` are their object tags, EM will assign the proposed answer to `theL` and `theU` symbols just before the verifying program is evaluated. The checking in this case is not trivial, since the decomposition is not unique; L and U are not the same for all possible P.

This example well justifies our choice of Mathematica as a computational engine. Even though we have generated the problem starting from the answer (first we generate `l` and `u` appropriately and then we compute `a` `=` `l`.`u`), we cannot carry out the checking by testing `SameQ[theL,l]` and `SameQ[theU,u]`. Instead, after making sure that `theL` and `theU` have the proper dimensions and that they are lower- and upper-triangular, respectively, we compute `theL`.`theU`. `Inverse[a]` and check to see if it is a permutation matrix. In this example, `MatrixQ`, `LoMatrixQ`, `UpMatrixQ`, and `PermutMatrixQ` are predicates indicating whether their argument is a general, lower-triangular, upper-triangular, or permutation matrix, respectively. They are defined in the utility package.

Listing 2. Verifying program for "LU decomposition."

Converted by Mathematica      October 5, 1999

[Prev Page][Next Page]