WeBWorK Problems

another multianswer question, different types

another multianswer question, different types

by Richard Lynch -
Number of replies: 2
Hi Everyone, I'm trying to create another T/F question using MultiAnswer. This time around, the answer is true (If B = S^{-1}AS, then det(B) = det(A)). In order to not give the answer away immediately, I want to give them three blanks in which they can enter the matrices A, B, and S and in which they can type true in any blank. I don't really care what they enter in the other two blanks as long as true is in at least one of the three.

However, whenever they enter a matrix it says "Your answer isn't a number (it looks like a matrix)," which pretty much gives the answer away. I thought checkTypes => 0 would make it not do this, but it didn't. In fact, I changed the second "correct" answer to a matrix and tried. Still no luck. 

The wiki says that setting checkTypes => 0 should make it possible to have different types in which they can enter either type in either blank? It says, 

"Lastly, checkTypes is useful if the answer blanks in the problem have different types (e.g., if the formula 1-x and the string "anything" can be entered in either order). In this case there will be trouble checking the answers, because answer checking will be stopped if the type of the student answer doesn't match that of the input answer." 

So I'm not sure why it's not working. I'd of course prefer to just have true/true/true as the three correct answers either way. Any ideas? The code I have for the MultiAnswer is:

$answer = MultiAnswer(String("true"), String("true"), String("true"))->with(
  singleResult => 0,
  checkTypes => 0,
  allowBlankAnswers => 1,
  checker => sub {
    ($correct, $student, $self) = @_;
    ($s1,$s2,$s3) = @{$student};
    $c = String("true");
    return [1,1,1] if ($s1 == $c || $s2 == $c || $s3 == $c);
    return [0,0,0];
In reply to Richard Lynch

Re: another multianswer question, different types

by Davide Cervone -
MathObject type checking doesn't look for equal types, but rather compatible types. So if you are asking for a complex number, for example, and the student enters a real number (no i), there is no type warning, because the real can be promoted to a complex at the time the check is performed.

Similarly, if the question asks for a (real) number, and the student enters a string like DNE or an infinity like -inf, there is no type warning because the question could have been asking for a limit, and DNE or -infinity could be legitimate answers for that, and even if they are not correct, you don't want to give a warning message if student enter them.

If an answer is a string, however, it is not clear what other types of answers could be reasonable (but wrong) ones. For example, if you were asking for points (x,y) where a function is undefined, the answer could be none, but the string answer checker doesn't know if points are valid answers or not, and whether they should get a type warning or not.

In order to work around this, you should provide an object of the correct type whenever you use a string answer so that the answer checker can properly determine the expected type of answer. By default it uses a real, but if you are expecting some other type of answer, then you must supply an example to be used for type checking.

This is done by providing a typeMatch option to the answer checker, as in

    ANS(String("none")->cmp(typeMatch => Point(1,2)));
which would allow the student to enter points without causing a type warning.

In your case, you would want to provide a Matrix as the typeMatch parameter. The only complication is that you are within a MultiAnswer object, and so don't have access to the individual answer checkers directly. So you can use the cmpDefaults trick again to provide them for the string answers; e.g.,

  Context()->{cmpDefaults}{String}{typeMatch} = Matrix([1,0],[0,1]);
This will allow matrix answers to be accepted without type warnings in the string answer blanks.

As for checkTypes, the Wiki reference you cite is somewhat misleading. The MultiAnswer object always does type-checking, but normally it only calls your checker if the types of the student answers are actually equal to the types of the correct answers (not just compatible, but equal). Setting checkTypes to 0 allows compatible types to be passed to your checker, but not arbitrary types. See the POD documention for parserMultiAnswer.pl for the most accurate information.

The reason checkTypes=>0 worked in the Wiki example is because strings are compatible with any answer, so the type matching never causes a warning for that. But the checker would not normally be called if the string and formula were reversed, because the types must be exact (not just compatible). Setting checkTypes=>0 loosened that requirement to be just compatible types, so the checker was called.

Anyway, hope that does what you need.


In reply to Davide Cervone

Re: another multianswer question, different types

by Richard Lynch -
Hi Davide. Once again, that did the trick. I see that checkTypes => 0 must be set in my case since otherwise the types won't equal and I need to it to take compatible answers. Now I get it! This was very informative. Thanks!!