PREP 2014 Question Authoring - Archived

force anser to be number

force anser to be number

by Joel Trussell -
Number of replies: 12
I know I've seen this but I can't find it now. How do I force the student to enter a number and not a formula. I tried using
$ans = Compute($z1*$z2);
with
ANS($z3->cmp() );

but that allow the student to enter the value of z1/value of z2

I want the student to compute the quotient and enter that number.

I can disable the * operation but this gives a not very useful error message
"Can't use '*' in this context"

I read the mathObjects page again
but this didn't help.

How do I force the student's answer to be a complex number? and get the msg
"Your answer is not a number (it seems to be a formula returning a number)"
when she enters a formula?

In reply to Joel Trussell

Re: force anser to be number

by Chrissy Safranski -
I'm not entirely clear on what you're trying to do, and I've never written a problem with complex numbers, but I have an idea anyway.  (I don't let lack of knowledge stop me!)

Disabling * should work, but then your answer can't involve * either, since the students can't enter it.  I think you could calculate out what the answer would be in parts, or maybe use $a=Re(z1*z2) and $b=Im(z1*z2), and then use $ans=Compute("$a+$b i");  

And then you can change the wrong answer message that the students get when they type * to be whatever you want, using either Context error messages for most things or post answer filters if that doesn't work.  http://webwork.maa.org/wiki/ErrorMessageCustomization#.VCzB2GBX-uY

I'm sorry if this is all wrong!
In reply to Chrissy Safranski

Re: force anser to be number

by Joel Trussell -
Chrissy, 
Thanks - that will do the job - I used
Context()->operators->undefine("*");  # disallow computation in answer
Context()->{error}{msg}{"Can't use '*' in this context"} 
  = "Enter a complex number, not a formula";  

I still think there is a way to get the error message mentioned in 
http://webwork.maa.org/wiki/Introduction_to_MathObjects#.VC7htRa_7CY
"Your answer is not a number (it seems to be a formula returning a number)"

But I'm set until I find the magic method (assuming it exists) - Otherwise, what case cases the error message mentioned on the webpage. 


In reply to Joel Trussell

Re: force anser to be number

by Chrissy Safranski -
I think it's slightly different vocabulary from what you're using.  A formula is a function (and constant functions are still functions).  A number is a number, even if you write it as 3*7.  

So constants can be both, and WebWork won't tell them they've entered a formula (function) when it's a number because it is also a number.  

So I'm not sure there's a built-in way to get that message in that case.  z1*z2 is still a number if z1 and z2 are numbers.  If they entered a variable like x or z, instead of a number then they would probably get that message.  
In reply to Chrissy Safranski

Re: force anser to be number

by Joel Trussell -
so, if I ask the student to calculate $a*$b which appears as 7*3 and the student enters 7*3 instead of 21, the only option I have is disallow the '*'? 

what is a case that would result in the error message that they've entered a formula ?  this will help me understand the difference. 
Thanks
In reply to Joel Trussell

Re: force anser to be number

by Davide Cervone -
Note that there are several multiplication operators in the context, so you really need to disable "* " as well as "*".

(These were for use with an experimental precedence system that would allow things like sin 2x to be interpreted as sin(2x) rather than sin(2) * x. I think it had promise, but the community didn't care for it (and it did complicate the rules somewhat). I suppose it would be a good idea to remove those from the default context, but that hasn't been done because there are references to them (particular to disable them, as you are doing).
In reply to Chrissy Safranski

Re: force anser to be number

by Davide Cervone -
Disabling * should work, but then your answer can't involve * either, since the students can't enter it. I think you could calculate out what the answer would be in parts, or maybe use $a=Re(z1*z2) and $b=Im(z1*z2), and then use $ans=Compute("$a+$b i");

Note that implied multiplication will also be disabled if you disable * so the expression "$a + $b i" will generate the "Can't use '*' in this context" message due to the multiplication between $b and i.

Allowing complex numbers to be entered but not expressions involving them is more complicated than just disabling *. That is why there are contexts like "LimitedComplex" for doing this.
In reply to Joel Trussell

Re: force anser to be number

by Davide Cervone -
There are some specialized contexts for the situations where you don't want to allow expressions. These are the "Limited" contexts, like "LimitedNumeric", "LimitedComplex", "LimitedVector", "LimitedPolynomial", and so on. These handle disabling the operators, or in some cases just limiting them, and producing error messages for them.

In your case, you could use

    loadMacros("contextLimitedNumeric.pl");
    Context("LimitedNumeric");
to enable the limited context in which only numbers (not formulas) can be entered. Use
    Context("LimitedNumeric-List")
if you want to allow commas so that lists of numbers can be entered.

There is also

    Context("LimitedNumeric-Fraction");
that allows division of integers, and
    Context("LimitedNumeric-StrictFraction");
that allows fractions but not decimal numbers (though the contextFraction.pl file is probably better for doing that sort of thing -- LimitedNumeric-StrictFraction was a predecessor to the more fully featured Fraction context).

If you are using complex numbers, there are several limited complex contexts. You can require the complex number to be in polar form for example, or force it to be entered in cartesian form. See the POD documentation for contextLimitedComplex.pl for more details.

If you want to change the error message, you can do

    Context("LimitedNumeric");
    Context()->{error}{msg}{"Can't use '%s' in this context"} =
      "You must enter a number, not an expression or list";
to replace all the "Can't use ..." messages at once. Alter the message to your tastes.
In reply to Davide Cervone

Re: force anser to be number

by Joel Trussell -
OK - I understand the disallow '*' screwing up the 3j since it is implied and the answer checker will barf. So the limited context looks promising. However, when I use it with my problem - included below - there appears to be a conflict with the    ($complexJ) ? "contextComplexJ.pl"  : "",
that I use with all of our engineering problems that allows either i or j for sqrt(-1). 
2ND - WHY wouldn't I use LimitedComplex instead of LimitedNumeric? 

Finally, I'm still having problems understanding exactly when variables are declared as MathObjects. It seems $a = 2; $b = 3; $c = $a+$b; yields no mathobject but $c = Compute($a+$b) does. In the case of complex numbers, (in a complex context) what about  $a = 2+2j; $b = 3+3j; $c = $a+$b; ?  Since the variables are complex are they automatically mathobjects? 

Thanks for the help and patience. 

 DOCUMENT() ;
 loadMacros(
 "PGstandard.pl",
  "MathObjects.pl",
"PGgraphmacros.pl",
   ($complexJ) ? "contextComplexJ.pl"  : "",
#"contextLimitedNumeric.pl",
"contextLimitedComplex.pl", 
 "PGcourse.pl"
 ) ;
 #sub i ();  #make i act like the imaginary unit.
 $showPartialCorrectAnswers=1;
 TEXT(beginproblem()) ;
#Context("LimitedComplex");
Context("Complex");  # original context with i and j for sqrt(-1)
#Context("LimitedNumeric");  # attempt to disallow expressions

 $z1 =random(1,7,1) + non_zero_random(-7,7,1)*j;
 $z2 = random(-7,-1,1) + non_zero_random(-7,7,1)*j;
 
 $graph = init_graph(-8, -8, 8, 8,grid=>[16,16],axes=>[0,0]);
 $point1 = closed_circle(Re($z1), Im($z1), 'red');
 $point2 = closed_circle(Re($z2), Im($z2), 'blue');
 $graph->stamps($point1,$point2);

$z3 = Compute($z1*$z2);
# Context("LimitedComplex");  # putting here after computation still allows expression

#Context()->operators->undefine("*");  # disallow computation in answer
#Context()->{error}{msg}{"Can't use '*' in this context"} 
#  = "Enter a complex number, not a formula";  
 BEGIN_TEXT
$BBOLD Multiplication of  complex numbers. $EBOLD 
$PAR The product of two complex numbers, \(z_1 = x_1 + j y_1\) and \(z_2 = x_2 + j y_2\) is defined by
\(
z_1 z_2 =  (x_1 x_2 - y_1 y_2) +  j (x_1 y_2 + x_2 y_1)
\), where the usual rules of multiplication of numbers apply and make use of the fact that \(j^2=-1\)

 $PAR
Consider the two complex numbers \(z_1  = $z1\) and \(z_2  = $z2\) 
$PAR
Compute the product \(z_1 z_2 =\)\{ans_rule(10)\}.

$PAR

<iframe width="420" height="315" src="//www.youtube.com/embed/cWn6g8Qqvs4" frameborder="0" allowfullscreen></iframe>

$BR
If the video does not work, 
\{ htmlLink("http://youtu.be/cWn6g8Qqvs4",
"click here to go to YouTube directly.") \}
 END_TEXT
 
 ANS($z3->cmp() );


 ENDDOCUMENT() ;       
In reply to Joel Trussell

Re: force anser to be number

by Davide Cervone -
WHY wouldn't I use LimitedComplex instead of LimitedNumeric?

For complex numbers you would use LimitedComplex, not LimitedNumeric. One of your questions asked about numbers like 3*7, and in that case, you would use LimitedNumeric. Also, the title of the question is about numbers.

there appears to be a conflict with the ($complexJ) ? "contextComplexJ.pl" : ""

Are you using the newest version of contextComplexJ.pl from the develop branch, or the older one in the master branch? It has been completely rewritten. The older one only operates on the standard Complex context, not other contexts. The new one can be enabled in any context with complex numbers.

If you are using the new one, you can add

context::ComplexJ->Enable();
after setting the context in order to enable the complex-j functionality. (See example below.)

Note that, since you are using j explicitly in your problem, there is no point in conditionally loading contextComplexJ.pl, as the problem will fail without it. The new contextComplexJ.pl is set up to allow you to set your course default in PGcourse.pl without having to modify the problem files themselves, but you have to write your problems using i notation originally in order to allow PGcourse.pl to have proper control over the results.

Unfortunately, the LimitedComplex context isn't included in the ones that contextComplexJ.pl modifies automatically, so you need to do that by hand with the command above. Here is one example:


 loadMacros(
   "PGstandard.pl",
   "MathObjects.pl",
   "PGgraphmacros.pl",
   "contextComplexJ.pl",
   "contextLimitedComplex.pl", 
   "PGcourse.pl",
 ) ;

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

Context("Complex");

$z1 =random(1,7,1) + non_zero_random(-7,7,1)*j;
$z2 = random(-7,-1,1) + non_zero_random(-7,7,1)*j;
 
Context("LimitedComplex-cartesian");
context::ComplexJ->Enable();

$z3 = Compute($z1*$z2);

Context()->texStrings;
BEGIN_TEXT
$BBOLD Multiplication of  complex numbers. $EBOLD 
$PAR
The product of two complex numbers, \(z_1 = x_1 + j y_1\)
and \(z_2 = x_2 + j y_2\) is defined by
\(z_1 z_2 =  (x_1 x_2 - y_1 y_2) +  j (x_1 y_2 + x_2 y_1)\), 
where the usual rules of multiplication of numbers apply and 
make use of the fact that \(j^2=-1\). 
$PAR
Consider the two complex numbers \(z_1  = $z1\) and \(z_2  = $z2\).
$PAR
Compute the product \(z_1 z_2 =\)\{ans_rule(10)\}.
END_TEXT
Context()->normalStrings;
 
ANS($z3->cmp);

Here, $z1 and $z2 are defined in the standard Complex context, where you can do computation as normal. $z3 is created in the LimitedComplex-cartesian context (Compute() will force the value it is passed to be in the current context), where operations between complex numbers are not allowed (but operations can be used within the real and imaginary parts; use LimitedComplex-cartesian-strict if you want to allow only constants). Note that since $z1*$z2 is performed before being passed to Compute(), there is no problem performing this multiplication.

The error messages from the LimitexComplex contexts will use i rather than j (e.g., "Your answer should be if the form a+bi"), so you may want to use Context()->{error}{msg} to remap those errors to use j instead.

I also added Context()->texStrings; and Context()->normalStrings around your BEGIN_TEXT/END_TEXT block to avoid extra parentheses around the complex numbers when they are inserted into the text.

You should also note that your <if ram> is going to cause problems when students try to get a hardcopy of your homework set. It is never a good idea to insert raw HTML into a problem for that reason. Also, as you write problems, you should always test them in hardcopy to make sure nothing goes wrong (it is easy for the output to work on screen but not in hardcopy).

In reply to Davide Cervone

Re: force anser to be number

by Joel Trussell -
Are you using the newest version of contextComplexJ.pl from the develop branch, or the older one in the master branch?

How do I know? or better how do I find out? 

I copied the revised problem to a new problem, but the error message
Warning -- there may be something wrong with this question. Please inform your instructor including the warning messages below.

Warning messages

  • Constant 'j' already exists at [PG]/lib/Value/Context/Data.pm line 89
  • Constant 'j' already exists at [PG]/lib/Value/Context/Data.pm line 89
 
This may be related to your question on versions. 

We're trying to develop our Webwork problems here for use in engineering. I'm having difficulty keeping my various versions and patches consistent. For example, learning to use 
  ($complexJ) ? "contextComplexJ.pl"  : "",
then inserting the load macro in PGcourse.pl, etc. 

Given that we want the text and the students to use j but it is OK for them to use i for sqrt(-1), what is the proper macro load. 

lastly, I understand I can change contexts in the middle of a problem. I don't understand the double call

Context("LimitedComplex-cartesian");
context::ComplexJ->Enable();
This would appear to disallow the form rho *exp(j*theta) which is fine for this problem
the second line does what? I thought complexJ was a context and this looks like setting two contexts at one time. 
Thanks


In reply to Joel Trussell

Re: force anser to be number

by Davide Cervone -
It seems $a = 2; $b = 3; $c = $a+$b; yields no mathobject but $c = Compute($a+$b) does. In the case of complex numbers, (in a complex context) what about $a = 2+2j; $b = 3+3j; $c = $a+$b; ? Since the variables are complex are they automatically mathobjects?

Yes, you are correct, here. Perl has built-in support for real numbers, and so $a = 2 produces a normal Perl real number. Computations with this will also produce normal Perl reals, so $b = $a + 3 will be a Perl real, not a MathObject.

To create a MathObject real, you would do $a = Real(2). Then $a will be a MathObject real, and any computations with it will produce MathObject reals as well. That is, $b = $a + 3 will cause $b to be a MathObject real equivalent to $b = Real(5). Note that Perl reals are promoted to MathObject reals when used in expressions including MathObjects, so you don't have to do $b = $a + Real(5) for example.

Perl does not have built-in support for complex numbers, so when you use complex numbers, they are always MathObject complex numbers. The reason $a = 2+3*j produces a MathObject complex is that j is set up to produce the MathObject complex number Complex(0,1). Just like with MathObject reals, when MathObject complex numbers are used in expressions with perl reals, the perl reals are promoted to MathObjects. So the result of 2+3*j is a MathObject complex number because 3*j is a MathObject complex (since j is), and so when 2 is added to that, it produces a MathObject complex as well.

I hope that clarifies the situation.

In reply to Joel Trussell

Re: force anser to be number

by Davide Cervone -
I assume that
    I tried using 
    $ans = Compute($z1*$z2); 
    with 
    ANS($z3->cmp() );
really means
    $ans = Compute($z1*$z2);
    ANS($ans->cmp);
(with $ans rather than $z3).

In any case, note that if $z1 and $z2 are MathObject Complex objects, then there is no need for the Compute(), and you can just do

    $ans = $z1 * $z2;
    ANS($ans->cmp);