WeBWorK Problems

matrices in multianswers

matrices in multianswers

by Richard Lynch -
Number of replies: 4
Hello Everyone, I apologize for posting so many times today, but I am really stuck on this one. I am making another T/F question in which I want the students to enter an example if it is false. In particular, the question is "T/F: If A is a diagonal matrix, then M_{ij} is also diagonal for all i and j." I thought it would be easy enough to make two blanks, one where they can enter a matrix and another where they can enter i,j corresponding to the M_{ij} which is not diagonal. 

However, I ran into the issue of the call to Multianswer doesn't even get to my custom checker because it is checking to see if the the answer has any error messages before doing so. I am providing the 3x3 identity matrix and a List of two numbers to Multianswer and so if the student enters anything but a 3x3 matrix, it gives the "Matrix dimension is not correct" error (even if I add the showDimensionHints => 0) and does not go to my custom checker. FYI, I know this is occurring in the entry_check and perform_check subroutines of the parserMultianswer.pl macro, but I don't know how to make them look past the dimensions of the matrix. My attempts at editing the file only lead to problems. 

Any ideas how how I can do what I want? Thanks in advance! Here is the code I'm trying to use that isn't working:

###########################################################################
# initialization 
###########################################################################
DOCUMENT();
loadMacros(
  "MathObjects.pl",
  "PGstandard.pl",
  "PGmatrixmacros.pl",
  "parserMultiAnswer.pl",
);

TEXT(beginproblem());
$showPartialCorrectAnswers = 0;


###########################################################################
# setup contexts and variables 
###########################################################################
Context("Matrix");
Context()->strings->add(true=>{}, false=>{}, t=>{alias=>"true"}, f=>{alias=>"false"});

sub getCofacMat {
  my ($a, $b, $A) = @_;
  my @d = $A->dimensions;
  return if ($a < 0 || $b < 0 || $a > $d[0] || $b > $d[1]);
  my $M = new MatrixReal1($d[0]-1,$d[1]-1);
  my $m = 0; my $n = 0;
  for ($i = 0; $i < $d[0]; $i++) {
    for ($j = 0; $j < $d[1]; $j++) {
      if ($i != $a - 1 && $j != $b - 1) {
        $M->assign($m+1,$n+1,$A->element($i+1,$j+1));
        $n++;
        if ($n == $d[1] - 1) {$m++; $n = 0};   
      }
    }
  } 
  $M = Matrix($M);
  return $M;
}

$answer = MultiAnswer(Value::Matrix->I(3), List(3,1))->with(
  singleResult => 0,
  allowBlankAnswers => 1,
  showDimensionHints => 0, 
  checkTypes => 0, 
  checker => sub {
    my ($correct, $student, $self) = @_;
    my ($c1, $c2) = @{$correct};
    my ($s1, $s2) = @{$student};
    return [0,0] if (!Value::classMatch($s1, 'Matrix') || !Value::classMatch($s2, 'List'));
    return [0,0] unless $s1->isSquare;
    @a = $s1->dimensions;  

    @d = @{$s2->data};
    return [0,0] if (scalar(@d) != 2);
    return [0,0] if (!Value::classMatch($d[0], 'Real') && !Value::classMatch($d[1], 'Real'));
    return [0,0] if (floor($d[0]) != $d[0] || floor($d[1]) != $d[1]);
    return [0,0] if ($d[0] < 1 || $d[0] > $a[0] || $d[1] < 1 || $d[1] > $a[0]);

    $diag1 = 1; $diag2 = 0;
    for ($i = 0; $i < $a[0]; $i++) {
      for ($j = 0; $j < $a[0]; $j++) {
        if ($i != $j && $s1->element($i+1,$j+1) != 0) { $diag1= 0 };
      }
    }
    my $B = getCofacMat($d[0], $d[1], $s1);
    for ($i = 0; $i < $a[0]-1; $i++) {
      for ($j = 0; $j < $a[0]-1; $j++) {
        if ($i != $j && $B->element($i+1,$j+1) != 0) { $diag2 = 1 };
      }
    }
    return [1,1] if ($diag1 && $diag2);
    return [0,0];
  }
);


###########################################################################
# state the problem 
###########################################################################
Context()->texStrings;
BEGIN_TEXT
Determine if the following statement is true or false:
$PAR
$SPACE $SPACE $SPACE If \(A\) is a diagonal matrix, then \(M_{ij}\) is also diagonal for all \(i\) and \(j\).
$PAR
If the answer is true, then type ${BBOLD}true${EBOLD}. If the answer is false, give an example in the first blank of a matrix in which the condition fails and type in the second blank \(i,j\) if \(M_{ij}\) is not diagonal. For example, type 1, 2 (separate with commas) for \(M_{12}\). $PAR
Answer: \{ $answer->ans_rule(35) \} \{ $answer->ans_rule(8) \}
$PAR
${BBOLD}Help:${EBOLD} To enter a matrix use $BBOLD [[ ],[ ]] $EBOLD. For example, to enter the \(3\times 3\) matrix
$PAR\[
\left[\begin{array}{rrr}
1 & 1 & 2 \\ 2 & 3 & 5 \\ 1 & -1 & 5
\end{array}\right]
\]$PAR you would type [[1,1,2],[2,3,5],[1,-1,5]], so each inside set of [ ] represents a row.
END_TEXT
Context()->normalStrings;


###########################################################################
# check the answer  
###########################################################################
ANS($answer->cmp());
In reply to Richard Lynch

Re: matrices in multianswers

by Davide Cervone -
Adding showDimensionHints => 0 is the right idea, but including it in the MultiAnswer object won't do it, because it doesn't get passed to the individual answer checkers.

Instead, you can set the default answer-checker parameters for the Matrix class by using

    Context()->{cmpDefaults}{Matrix}{showDimensionHints} = 0;
after selecting the Matrix context. This will prevent the dimension hint, and allow the matrix to be passed to your checker.

BTW, you don't need to set checkTypes to 0 for this to work. I not recommend doing that unless you really want to process answers that are not of the correct type. Since you check for the type right off the bat, you don't seem to need to do that.

Davide

In reply to Davide Cervone

Re: matrices in multianswers

by Richard Lynch -
Once again, you saved the day. It works great. Thanks! I also removed checkTypes as suggested. I had it there in hopes that it would fix my issue, but it clearly didn't. Thanks again!

Rick