WeBWorK Main Forum

webwork tolerance complex numbers

webwork tolerance complex numbers

by Joel Trussell -
Number of replies: 6
I'm creating a problem for DSP filter design and using a cascade of
2nd order filters in the z-transform domain. e.g.,
H(z) = 1.31951*(z^2+0.218046*z+1)/(z^
2+1.28971*z+0.64)
I want to create test points on the unit circle, which is easy to do.
The question is how does the tolerance work for complex numbers, does
it test the real and imaginary parts for tolerance or does it test the
magnitude of the difference?

Second question, I noted that the random number generator for the
magnitude and phase of the poles and zeros is affected by the
tolerance. This seems odd, but I had a similar problem with the
tolerance affecting conditional statements. Is there anyway around
this, other than setting the tolerance small for the random generation
and higher for the answer checker?
In reply to Joel Trussell

Re: webwork tolerance complex numbers

by Davide Cervone -
The tolerances are used on the real and imaginary parts separately. That means zero-level tolerances will be used if one of them is (near) zero, so that pure real or pure imaginary numbers are more likely to be graded correctly.

In terms of your earlier question about tolerances, if you are using a MathObject Real, then any equality to inequality test uses the context's tolerance settings. The MathObejct Reals are "fuzzy" really not just in checking the student answers, but in perl code directly. That way you can use $correct == $student and similar tests within your answer checkers and they will do exactly the same checks that are done in the standard answer checking.

If you are using Perl reals, then the tolerances play no role, and you get the traditional "exact" math of Perl.

If you have a MathObject Real, $x, then $x->value will get you the underlying Perl value. So $correct->value == $student->value would test equality with the tolerances, using native perl equality.

If your random generation is using MathObjects, then the tolerances will be used in the computations. If you use native Perl reals, they won't. So use native Perl reals during the randomization and convert back to MathObejcts in the end, if you need to.
In reply to Davide Cervone

Re: webwork tolerance complex numbers

by Joel Trussell -
If I set tolerance in the context command along with other settings,

Context("Complex");
$tollim=0.5;
Context()->flags->set(
tolerance => $tollim,
tolType => "absolute",
);
and afterward use
$mag_p1 = random(0.650,0.60,0.0005);
$ang_p1 = random(-pi*9/10+0.005,9*pi/10-0.005,pi/20);
$p1 = $mag_p1*exp(i*$ang_p1);

I assume the variables $mag_p1 and $ang_p1 are Perl variables and have values unaffected by the tolerance.
With tolerance tollim = 0.5, magp1 = 0.6475, angp1 = -2.37583, p1 = -0.466752
with tolerance tollim = 0.005, magp1 = 0.6475, angp1 = -2.50827 p1 = -0.521929-0.383205i
but why the difference in angp1?
I assume the difference in p1 is because it got changes to a mathobject at some point.

Seems I'd be better off using tolerance very small for all computations and then set a wider tolerance at the answer checker
ANS($p1->cmp());

thanks


In reply to Joel Trussell

Re: webwork tolerance complex numbers

by Davide Cervone -
I assume the variables $mag_p1 and $ang_p1 are Perl variables and have values unaffected by the tolerance.

The would be an incorrect assumption. Both pi and i will generate MathObjects when MathObjects.pl has been loaded, and so you are passing MathObjects to random() in the computation of $ang_p1. Since computations with MathObjects produce other MathObjects, the computations in random() will be done with MathObjects. That also means that equality and inequality tests will be done with MathObject's fuzzy reals, and that is what is behind the difference in the values you are seeing for $ang_p1. I haven't looked at the code for random() in a long time, so I don't know what potential problems that might cause. But you can convert to Perl reals via

$ang_p1 = random((-pi*9/10+0.005)->value, (9*pi/10-0.005)->value, (pi/20)->value);
[As an aside, you might want to use ((18*pi-.01)/(18*20))->value) for the step value in order to get the range evenly divided.]

Also note that the output generated for a MathObject Complex number a + bi tests a and b to see if they are zero and leaves them out if they do. So when you use absolute tolerance of .5, that means that anything less than .5 (in absolute value) will be counted as zero. In particular, 0.383205i will be taken to be 0i and not shown. So that is probably not a tolerance value you really want to use, here.

In reply to Joel Trussell

Re: webwork tolerance complex numbers

by Nathan Wallach -
Might I suggest an extra step or two, to put in "pi" after the randomization, and using random to pick an integer "numerator". Instead of:

$ang_p1 = random(-pi*9/10+0.005,9*pi/10-0.005,pi/20);

I recommend trying something like:

$ang_pi_numerator_of_coef = non_zero_random(-17,17,1);
$ang_p1 = Compute("($ang_pi_numerator_of_coef*pi)/20");

If you really want the values shifted off nice multiples of pi/20, you can add the 0.005 at the end. If the goal is just to avoid well known angles, you could use "list_random" to select the numerator from a smaller set.