WeBWorK Main Forum

Using contextLimitedPolynomial.pl

Using contextLimitedPolynomial.pl

by Robin Cruz -
Number of replies: 15

I am trying to write a problem for the students to practice the distributive property.  The students must enter a polynomial -- not factors.  I would like the correct answer to show up as a polynomial.  Here is the code I have: 

loadMacros(
  "PGstandard.pl",
  "Parser.pl",
  "MathObjects.pl",
  "contextLimitedPolynomial.pl"
);

TEXT(&beginproblem);

######################################
#  Setup

$a1 = random(2,4,1);
$a2 = random(2,4,1);
$a3 = random(1,8,1);

$b1 = random(-4,-2,1);
$b2 = random(2,4,1);
$b3 = random(1,8,1);

######################################
#  Main text

BEGIN_TEXT
Use the distributive property to write the expressions without parenthesis:
$PAR

a) \( $a1($a2 x + $a3) = \) \{ ans_rule(10) \}
$PAR

b) \( $b1($b2 x + $b3) = \) \{ ans_rule(10) \}
$PAR

$BR

END_TEXT

######################################
#  Answers
Context("LimitedPolynomial")->flags->set(singlePowers=>1);

$ans_a = Formula("$a1*$a2 x + $a1*$a3")->reduce;
ANS($ans_a->cmp);

$ans_b = Formula("$b1*$b2 x + $b1 * $b3")->reduce;
ANS($ans_b->cmp);

Two problems:

1) I get an error when the leading coefficient is negative:

Error messages

You can only use '-' with monomials at line 253 of [PG]/macros/contextLimitedPolynomial.pl Died within LimitedPolynomial::UOP::_check called at line 21 of [PG]/lib/Parser/UOP.pm from within Parser::UOP::new called at line 154 of [PG]/lib/Parser/UOP.pm from within Parser::UOP::Neg called at line 61 of [PG]/lib/Parser/BOP/subtract.pm from within Parser::BOP::subtract::_reduce called at line 72 of [PG]/lib/Parser/BOP.pm from within Parser::BOP::reduce called at line 39 of [PG]/lib/Parser/BOP/add.pm from within Parser::BOP::add::_reduce called at line 72 of [PG]/lib/Parser/BOP.pm from within Parser::BOP::reduce called at line 638 of [PG]/lib/Parser.pm from within Parser::reduce called at line 75 of [TMPL]/Problems/setAlgebra_01_02_OperationsWithRealNumbers/IntAlg_22_OperationsWithReals.pg

2)  For the problem, 2(3x+5), I can enter 6x+10 and 2*3x+ 10 and the answer is evaluated as correct in both cases.  I would like only the first answer to be considered as correct.

Thanks -- rac 

In reply to Robin Cruz

Re: Using contextLimitedPolynomial.pl

by Davide Cervone -
The error message you are getting is a result of the reduce call. When both terms are negative, the reduction formulas try to factor out the common negative and form -(ax+b), which is not allowed in the LimitedPolynomial context. I have updated the contextLimitedPolynomial.pl file to disable that reduction rule.

As for the issue with 2*3x-10, I guess that there needs to be a LimitedPolynomial-Strict context in which the coefficients and powers can't include operations. That will take a little work, and I'm not sure when I'll have the time to do it. I'll let you know when I get it done.

Davide
In reply to Davide Cervone

Re: Using contextLimitedPolynomial.pl

by Robin Cruz -

Thanks for your help, Davide.  I'll update my pg folder tomorrow.

There are a couple more things I noticed while I was trying to figure it out and I'll just pass them along for what they're worth.  I'll put comments in the code for a problem to explain:

loadMacros(
  "PGstandard.pl",
  "Parser.pl",
  "MathObjects.pl",
  "contextLimitedPolynomial.pl"
);

TEXT(&beginproblem);

######################################
#  Setup

Context("Numeric");

#Note: I have to change the context to Numeric or I get an error when I define $a below. 

#Note: I thought Numeric was the default and that to change 

#          context, one needed to explicitly declare a new

#          context not just load the context_____.pl file.


Context()->variables->add(y=>'Real');

$a1 = random(2,6,1);
$a2 = random(3,5,1);
$a3 = non_zero_random(-9,9,1);
$a4 = random(2,9,1);
$a5 = random(1,5,1);
$a = Formula ("$a1 ($a2 y + $a3) - ($a4 y + $a5)")->reduce;

$b1 = random(2,4,1);
$b2 = random(2,4,1);
$b3 = random(2,8,1);
$b4 = random(2,7,1);
$b5 = random(1,4,1);
$b = Formula("$b1-$b2 [ $b3 -($b4 y - $b5)]");
#Note: $b is not working. The TeX is replacing the brackets with parenthesis.

######################################
#  Main text

BEGIN_TEXT
Simplify each algebraic expression:
$BR Note:  In this problem, the variable is \(y\).
$PAR
a) \( \{$a->TeX\} = \) \{ ans_rule(10) \}
$PAR
b) \( $b1-$b2 [$b3 -($b4 y - $b5)] = \) \{ ans_rule(10) \}
$BR

END_TEXT

######################################
#  Answers

Context("LimitedPolynomial")->flags->set(singlePowers=>1);
Context()->variables->add(y=>'Real');

#Note:  I have already declared y to be a variable above

#         but I get an error message that it is not defined

#         unless I declare it again before I use y below.

$ans_a = "($a1*$a2-$a4) y + ($a1*$a3-$a5)";
ANS(Formula($ans_a)->reduce->cmp);

#Note: If I use

#$ans_a = Formula("($a1*$a2-$a4) y + ($a1*$a3-$a5)")->reduce;

#ANS($ans_a->cmp);

#    I get an error about the multiplcation in the coeffiecients.

$ans_b = "($b2*$b4) y +($b1 - ($b2*$b3) - ($b2*$b5))";
ANS(Formula($ans_b)->reduce->cmp);

This note is just for your information when there is time to think about the limitedPolynomial context.  With the fix you supplied for the negative coeffecients, I can push on.

Thanks -- rac

In reply to Robin Cruz

Re: Using contextLimitedPolynomial.pl

by Davide Cervone -
Robin:

Here are some comments about our code:

    loadMacros(
      "PGstandard.pl",
      "Parser.pl",
      "MathObjects.pl",
      "contextLimitedPolynomial.pl"
    );

You don't need both Parser.pl and MathObjects.pl here. Use MathObjects.pl by itself, as Parser.pl is depricated.

    TEXT(&beginproblem);

The ampersand is not needed here (it is not an error, but is a left-over from older versions of Perl when it was needed).

    ######################################
    #  Setup

    Context("Numeric");

    #Note: I have to change the context to Numeric or I get an error when I define $a below. 
    #Note: I thought Numeric was the default and that to change 
    #          context, one needed to explicitly declare a new
    #          context not just load the context_____.pl file.

You are right, that is how it SHOULD work, but a number of the context files DO set the context. That needs to change, but I haven't done it yet. It is left over from earlier program styles and changing it will require some problems to be modified. That makes it harder to change the macro files.

    Context()->variables->add(y=>'Real');

You may want to use variables->are() rather than variables->add(). The former will mean that the only variable is y rather than both x and y.

    $a1 = random(2,6,1);
    $a2 = random(3,5,1);
    $a3 = non_zero_random(-9,9,1);
    $a4 = random(2,9,1);
    $a5 = random(1,5,1);
    $a = Formula ("$a1 ($a2 y + $a3) - ($a4 y + $a5)")->reduce;

    $b1 = random(2,4,1);
    $b2 = random(2,4,1);
    $b3 = random(2,8,1);
    $b4 = random(2,7,1);
    $b5 = random(1,4,1);
    $b = Formula("$b1-$b2 [ $b3 -($b4 y - $b5)]");

    #Note: $b is not working. The TeX is replacing the brackets with parenthesis.

You are right, the TeX method does not alternate parenthesis types, as the string method does. (The actual parentheses you type in are not retained within the formula.) It would require altering the MathObject code to change this behavior.

    ######################################
    #  Main text

    BEGIN_TEXT
    Simplify each algebraic expression:
    $BR Note:  In this problem, the variable is \(y\).
    $PAR
    a) \( \{$a->TeX\} = \) \{ ans_rule(10) \} 
    $PAR
    b) \( $b1-$b2 [$b3 -($b4 y - $b5)] = \) \{ ans_rule(10) \} 
    $BR

    END_TEXT

Note that the final $BR is not needed.

    ######################################
    #  Answers

    Context("LimitedPolynomial")->flags->set(singlePowers=>1);
    Context()->variables->add(y=>'Real');

    #Note:  I have already declared y to be a variable above
    #         but I get an error message that it is not defined
    #         unless I declare it again before I use y below.

Each context has its own set of variables. You added y to the Numeric context above, but that does not affect this new context. So you really DO have to add it again.

    $ans_a = "($a1*$a2-$a4) y + ($a1*$a3-$a5)";
    ANS(Formula($ans_a)->reduce->cmp);

    #Note: If I use
    #$ans_a = Formula("($a1*$a2-$a4) y + ($a1*$a3-$a5)")->reduce;
    #ANS($ans_a->cmp);
    #    I get an error about the multiplcation in the coeffiecients.

    $ans_b = "($b2*$b4) y +($b1 - ($b2*$b3) - ($b2*$b5))";
    ANS(Formula($ans_b)->reduce->cmp);

I am not able to reproduce the error you have been seeing. I also don't see how the two forms would be able to produce different results, as they should be identical (whether you use a string literal or a variable holding the string should not make any difference). Are you sure you didn't change anything else?

Davide

In reply to Robin Cruz

Re: Using contextLimitedPolynomial.pl

by Davide Cervone -
OK, I finally had time to make the new context that you needed. It is also in contextLimitedPolynomial.pl, and you get it by
      Context("LimitedPolynomial-Strict");
It does not allow operations within the coefficients of the polynomial. It also sets singlePowers automatically (and turns off reduceConstants). I think this will have the effect you want. Let me know otherwise.

You can get the new copy from the CVS repository.

Davide

In reply to Davide Cervone

Re: Using contextLimitedPolynomial.pl

by Robin Cruz -
I have a few questions:

1) I updated my pg/macros folder. However, I still seem to need the line:
included in the file to make the answer checker reject polynomials with unique degrees for each monomial. Also, even with this line, the answer checker will let an answer like "x^2+4+7" be correct -- it does not seem to work with the constant term?

2) I am trying to get a polynomial like "-3x^2-5x" to show up in the text without parenthesis about the expression or the terms. What I have works if the second term is not negative, but puts in parenthesis if it is negative. Here's what I am trying, but I do not understand how the restrictions on the "reduce" work.
--------------------CODE---------------------
$a = non_zero_random(-4,4,2);
$b = $a - non_zero_random(-2,2,1);

$na = random(6,8,1);
$nb = $na - random(1,4,1);

$term1 = Formula("$a x^$na");
$term2 = Formula("$b x^$nb");
$poly = Compute($term1+$term2)->reduce('(-x)-y'=>0,'(-x)*y'=>0);
$tpoly = $poly->TeX;
--------------END CODE SEGMENT-------------

3) Can I keep the terms in order in a polynomial like "-3x^2+5"? When I reduce it, I get "5-3x^2".

Thanks -- rac
In reply to Robin Cruz

Re: Using contextLimitedPolynomial.pl

by Davide Cervone -
I only have a second so will be very terse.

For 1), Context("LimitedPolynomial") allows operations within the coefficent, and since the constant term is the coefficient of [math]x^0[/math], that is allowed.

You need to use Context("LimitedPolynomial-Strict") to prevent operations within coefficients.

For 2) and 3) I'll have to take more time to test it, and that will have to wait until next week. Sorry!

Davide
In reply to Davide Cervone

Re: Using contextLimitedPolynomial.pl

by Robin Cruz -

I should have been clearer.  The code in question uses "LimitedPolynomial-Strict".  Also, is there a way to prevent the answer " 5x^2 +0x-3" from being considered correct?

Whenever you have a chance -- rac

Here's the code:----------------------------------------

DOCUMENT();

loadMacros(
  "PGstandard.pl",
  "MathObjects.pl",
  "contextLimitedPolynomial.pl"
);

TEXT(beginproblem);

######################################
#  Setup

Context("LimitedPolynomial-Strict");
Context("LimitedPolynomial")->flags->set(singlePowers=>1);

($a1,$b1,$c1) = (random(4,7,1),
                 non_zero_random(-6,6,1),
                 list_random(-6,-5,-4,4,5,6));

#---The leading term is positive and the middle term is zero.
($a2,$b2,$c2) = (-$a1+random(1,3,1),
                       -$b1,
                        $c1 + non_zero_random(-3,3,1));

#----powers of the monomials
($p1,$p2) = (Formula("x^2"),Formula("x"));

$f1 = Formula("$a1 $p1 + $b1 $p2 + $c1")->reduce;
$f2 = Formula("$a2 $p1 + $b2 $p2 + $c2")->reduce;
$poly1 = $f1->TeX;
$poly2 = $f2->TeX;

######################################
#  Main text

BEGIN_TEXT
Add:  \( ( $poly1 ) + ( $poly2 ) \)
$PAR
Answer:  \{ ans_rule(40) \}
END_TEXT

######################################
#  Answer

($a3,$b3,$c3)=($a1+$a2,$b1+$b2,$c1+$c2);

$ans=Formula("$a3 $p1 + $b3 $p2 + $c3")->reduce;
ANS(Compute($ans)->cmp);

ENDDOCUMENT();

In reply to Robin Cruz

Re: Using contextLimitedPolynomial.pl

by Davide Cervone -
The code in question uses "LimitedPolynomial-Strict".

Actually, it turns out it doesn't. Your two lines

    Context("LimitedPolynomial-Strict");
    Context("LimitedPolynomial")->flags->set(singlePowers=>1);
first sets the context to LimitedPolynomial-Strict, but the second line then sets it to LimitedPolynomial (not the strict form) and adds the singlePowers flag to that. You should be able to leave the second line off entirely, since LimitedPolynomials-Strict already has singlePowers set to 1. If you need to set a flag on the current context, use
    Context()->flags->set(...)
If you pass a name to Context(), that will cause it to reset the context to that named context before setting the flags.

If the Strict context is allowing multiple terms of the same power, then something is wrong that I will need to fix.

is there a way to prevent the answer " 5x^2 +0x-3" from being considered correct?

I assume you are referring to the coefficient of 0. There is no current method, but it would not be hard to add a flag that allows that. I probably won't get to it for a few days, though, but I'll let you know when I do.

Davide

In reply to Davide Cervone

Re: Using contextLimitedPolynomial.pl

by Robin Cruz -

OK, I understand more about how to use "Context()->...".  I took out the "flags" line and moved the Context("LimitedPolynomial-Strict") line to the Answer section before  the correct answer is constructed since I don't actually need it until then. (An aside, I was wondering how the changes in context worked across BEGIN_TEXT and END_TEXT.  I had the impression at the workshop this summer that BEGIN_TEXT changed the context to strings and then END_TEXT changed it to Numeric.) 

Back to the problem at hand:  The problem is still taking answers like 2x^2+x^2+15 and 3x^2+6+9 as correct.  It correctly rejects answers like (2+1)x^2 + 15.

Thanks for looking into this, rac

In reply to Robin Cruz

Re: Using contextLimitedPolynomial.pl

by Davide Cervone -
There was a typo in the LimitedPolynomial-Strict context -- singelPowers rather than singlePowers -- so that feature was not in effect. I have fixed it in the CVS archive, so you should update the contextLimitedPolynomials.pl file. That should give you error messages for the two examples you give.

Davide
In reply to Davide Cervone

Re: Using contextLimitedPolynomial.pl

by Robin Cruz -

I updated my pg folder.  There may be another error as I am getting the following warning message on every problem template that uses contextLimitedPolynomial.pl:  (Sometimes the message is listed several times.)

Warning messages

  • Use of uninitialized value in addition (+) at line 99 of [PG]/macros/contextLimitedPolynomial.pl

Thanks for looking into this.

Also, a question (not necessarily just for limited polynomials):  Is there a way to prevent, "reduce" from changing the order of the terms (so that a positive term is first) or putting parenthesis about the negative terms? 

$a= random(-3,-1,1); 
$b= random(-3,-1,1); 
$c= random(1,5,1);

$p = Formula("$a x^3+$b x^2+$c x"); #Use this to build the polynomial


$root = non_zero_random(-3,3,1);

$d= $p->eval(x=>$root);
$f = Compute($p - $d)->reduce('(-x)-y'=>0,'(-x)*y'=>0);

If I just have "reduce", the terms are reordered.  If I put in the conditions it puts in extra parentheses on the non-leading negative terms.

Thanks for your help -- rac

In reply to Robin Cruz

Re: Using contextLimitedPolynomial.pl

by Davide Cervone -
OK, the "uninitialized value" was an error in the previous updates I made to contextLimitedPolynomial.pl. I have fixed it in the CVS repository, so the latest version should make your files work again. Sorry about that.

As for the reduction issue, the reduction algorithm still needs some work. Here's what's going on. When you use something like 3x^2+-3*x+2, that is parsed as 3x^2+(-3)*x+2. The MathObjects reduction algorithm tries to handle the +- by factoring minuses out of inner terms, so that something like (-x)*y becomes -(x*y), and then it looks for terms like x+(-y) and converts them to x-y. That means 3x^2+(-3)*x+2 first becomes 3x^2+(-(3*x))+2 and then 3x^2-3*x+2.

That works OK, but if the negative is on the first term, you get something like -3x^2+2 being parsed as (-3)x^2+2, which becomes -(3*x^2)+2, which looks bad.

When you use reduce('(-x)*y'=>0) you are telling the reduction algorithm not to do the (-x)*y to -(x*y) transformation. That fixes the -(3*x^2)+2 problem, but prevents the 3x^2+(-3)*x+2 formula from being reduced (since the factoring out of the negative is essential).

I think I have resolved the problem by having the reduction rules for (-x)*y and x*(-y) mark the resulting -(x*y) so that the parentheses will not be printed (i.e., -(x*y) will display as -x*y). That way, you can still allow the rules to factor out the negatives, but they will not cause extra parentheses to be displayed. I don't think this will cause any problems, but you should keep your eyes open for anything unusual.

To get this feature, you need to update pg/lib/Parser/BOP/multiply.pm to the one in the CVS repository, and you should not specify '(-x)*y'=>0 any longer. Also, you might want to include '(-x)+y'=>0 to prevent switching of the order of terms to get a positive one first. Note that the LimitedPolynomial contexts already have both of these turned off by default.

Hope that helps.

Davide
In reply to Davide Cervone

Re: Using contextLimitedPolynomial.pl

by Robin Cruz -

It's working great now.  Thanks for working on this.  Your modifications make it a lot easier to work with.

Thanks so much -- rac

In reply to Davide Cervone

Re: Using contextLimitedPolynomial.pl

by Bruce Yoshiwara -
Does LimitedPolynomial-Strict allow a coefficient like 1/3 (which appears to me to have an operation)?

I'm actually trying to find a way to require answers allowing only integer coefficients (so that an equation has been cleared of fractions).
In reply to Bruce Yoshiwara

Re: Using contextLimitedPolynomial.pl

by Davide Cervone -
No, the polynomial contexts require that powers be integers, since that's what is required for a polynomial. That is not restricted to the Strict context -- ALL the polynomial contexts require that.

The strict version DOES allow fractions as the coefficients, but not other operations (other than negation).

Davide