WeBWorK Problems

Forcing the limited fraction context in matrices

Forcing the limited fraction context in matrices

by Rick Lynch -
Number of replies: 1

I am in need of enforcing reduced fractions with limited use of operators inside matrices. I have tried to follow Davide's advice by adding 

Context()->parens->set("[" => {formMatrix => 1});

to the "LimitedFraction" context. The full code is attached.

It seems to force the entries to be reduced fractions and disallow operators, but only when all answer blanks are not filled. However, it doesn't actually work when checking the entire matrix. That is, when a student enters all entries, it gives a weird 'Can't locate object method "weaken" via package "main"' error:

Another issue seems to be location of the errors. For unreduced fractions, it will actually say the entry that the fraction isn't reduced, but if it's an operator error, it doesn't (and in fact doesn't even give an error message):

Lastly, assuming I can get all of that above working somehow, is there a way to change all error messages for "Can't use 'op' in this context" to something more understandable by the students? I am aware I can change individual error message by doing something like:

@badops = ('+','-','*',' *','* ','^','**');
foreach $bad (@badops) {
    Context()->{error}{msg}{"Can't use '$bad' in this context"} = "Each entry must be a fully computed and reduced number";

but is there a way to cover all operators other than just adding everything to the @badops array? 

Thanks so much in advance!

In reply to Rick Lynch

Re: Forcing the limited fraction context in matrices

by Davide Cervone -

The first issue (the one that is causing the error about weaken not being found) is easily fixed. In the Fraction context, the [ delimiter is defined, but just doesn't produce matrices, so

Context()->parens->set("[" => {formMatrix => 1});

is sufficient to allow it to do that. But in the LimitedFraction context, the [ has been removed, so you need a little more information in order to enable it again. This will do it:

Context()->parens->set("[" => {close => ']', type => 'Matrix', formMatrix => 1});

There are also a couple of simplifications that you can use.:

  • To modify the error messages about invalid operations, you only need to modify one message (which is the template for the one that has the individual operator names inserted into it):

    Context()->{error}{msg}{"Can't use '%s' in this context"} = "Each entry must be a fully computed and reduced number";
  • To turn the entries in the transpose into fractions, you can use the map keyword as follows:

    $At = Matrix(map {[map {Fraction($_, $d)} @{$_}]} $At->value);
  • To get the answer array, you can use

    a. [`\dfrac{1}{[$d]} A^T = `] [____]*{$At}

    and avoid the need for the [@ ... @] and following ANS() call. This works unless you need to add answer filters or hints, in which case your original notation will work for that.

The second issue, the one about missing error messages, is a bug. The error messages are actually being generated, but are then being overwritten later in the answer checker process. This can be resolved by using

package my::Matrix;
our @ISA = ('Value::Matrix');

sub cmp_Error {
  my $self = shift; my $ans = shift; my $message = shift;
  $self->SUPER::cmp_Error($ans, $message || $ans->{error_message}, @_);

package main;

Context()->{value}{Matrix} = 'my::Matrix';

before creating the matrix in the LimitedFraction context.

I think that should take care of your issues.