WeBWorK Problems

ijk vector formula checking

ijk vector formula checking

by Gavin LaRose -
Number of replies: 1
Hi all,

(This is essentially a recap of the discussion in http://webwork.maa.org/moodle/mod/forum/discuss.php?d=2284 that I'm re-initiating to see if any further comments come up. My conclusion here is the same as Paul's there, but it still doesn't seem very satisfying.)

I'm working with some vector formulas, and am having trouble working with student vectors input in ijk format. For example, the following is a fabricated example that illustrates the problems I'm having (I should note that this is really just an example).

             "parserMultiAnswer.pl", );
  Context()->variables->add( t=>'Real' );

  $vec = Vector( Compute("cos(t)"), Compute("cos(t)"), Formula("0") );
  $der = $vec->D('t');

  $vderChk = MultiAnswer( $vec, $der )->with(
      checker=>sub {
	  my ( $c, $s, $ans ) = @_;

	  ## the student's vector and derivative
	  my ($sVec, $sDer) = @{$s};

          if ( $sVec->D('t') == $sDer ) {
              return [ 1, 1 ];
          } else {
              return [ 1, 0 ];

  \(\vec v = \) \{ $vderChk->ans_rule(25) \}
  \(\vec v ' = \) \{ $vderChk->ans_rule(25) \}

  ANS( $vderChk->cmp() );

If a student enters the first vector with angle brackets, for example, <2t,t,1>, then the problem is marked correctly (a student answer of either <2,1,0> or 2i + j is marked correct).

However, if the student's vector is in ijk format, for example, 2t i + t j + k, we get the error message Operands for '+' must be of the same type, and the problem is marked wrong.

Similarly, if we try to work with the components of the input vectors we also run into trouble. For example, we could change the checker function in the above to the following (ignoring for the moment any question of whether this is a good way to do things).

  sub {
      my ( $c, $s, $ans ) = @_;
      my ( $sVec, $sDer ) = @{$s};

      # get the components of these vectors
      my @sVecComp = $sVec->value;
      my @sDerComp = $sDer->value;

      if ( $sVecComp[0]->D('t') == $sDerComp[0] &&
           $sVecComp[1]->D('t') == $sDerComp[1] &&
           $sVecComp[2]->D('t') == $sDerComp[2] ) {
          return [1,1];
      } else {
          return [1,0];

The evaluation behavior is the same as before. Working backwards, we find that when $sVec is in ijk format, $sVec->value returns the full input vector as the first component of the returned array, and leaves empty values for the second two components. To try and work around this, we might try getting the components with $sVec . i (and similarly with j and k), but then the derivatives fail with the error Differentiation for 'dot' is not implemented.

And so on. At the end of the day I have ended up with the hack Paul suggested in the previous post when I need these components: I check the format of the input student answer and if it is in ijk format use Perl regular expressions on the string representation of the student answer to get the i, j and k components. This doesn't strike me as particularly robust, however.

Any comments to clarify what is going wrong, and a better way to deal with it, would be welcome.


In reply to Gavin LaRose

Re: ijk vector formula checking

by Davide Cervone -

Sorry I've been off-line for so long (my work on MathJax has kept me away from WeBWorK for a while).

The real issue here is that the Operands for '+' must be of the same type that you get is a bug, and represents an error in the differentiation code. It turns out that this is due to an error in handling named constants (like i, j, and k); they were replaced by a scalar 0 rather than a zero vector, and so the differentiation formula ended up adding a vector and a scaler.

I have prepared a fix which is available in the differentiation branch of my fork of pg-dev. It modifies two files, which you can simply download and replace the current versions.

I also added differentiation rules for dot products and cross products, so not only should be able to use your original checker with these changes, but you could also use the $sVec . i approach to obtain the coordinate functions for the student's answer and differentiate them (though this is effectively the same as $sVec->D('t') . i).

I will write more about why $sVec->value doesn't do what you want later.