WeBWorK Problems

Bizarro Power

Bizarro Power

by Alex Jordan -
Number of replies: 2
We have made a lot of use out of the contents of the attached file. Something similar is used in LimitedRadicals context to recognize that, say, sqrt(12) is not as nice as 2*sqrt(3). The basic arithmetic operations are redefined temporarily to have bizarre meaning. In this way, answers which are numerically equivalent can be distinguished if their form is different. And all this is without looking at string-based answer checking.

We are trying to extend the idea to the ^ operator for questions like
  • simplify 12^8 * 12^5 (where we expect 12^13, and do not want to accept all of the digits that come from carrying out the exponentiation)
  • factor the integer 12 (where we'd have the answer be OneOf(Formula("2^2*3"), Formula("2*2*3")) and the bizarro arithmetic would recognize "6*2" and "4*3" as different.)
But our simple attempt to mimic what works for +, -, *, and / does not work for ^. We get the following error message:

 syntax error at (eval 7261) line 6, near "**("
although the eval number is not always the same.

If you think you may be able to offer an explanation or a fix, please download the attached .pl file and try the problem below. Everything should function well until you try submitting an answer.

# WeBWorK problem written by Chris Hughes, 2013
# Portland Community College
#
# Template:
# Simplify the following expression
# x^m * x^n
#
# We use an INTEGER value for x on the interval [2,20]
#
# This problem chooes m and n to be POSITIVE
#
# Last edited: Carl Yao 6/28/13
#
# ENDDESCRIPTION
## DBsubject('Algebra')
## DBchapter('Polynomial and Rational Functions')
## DBsection('Polynomial Functions')
## KEYWORDS('multiply','exponent','simplify')
## DBCCSS('8.EE.1')
## TitleText1('')
## EditionText1('')
## AuthorText1('')
## Section1('')
## Problem1('')
## Author('Chris Hughes')
## Institution('PCC')
##############################################
DOCUMENT();
loadMacros(
 "PGstandard.pl",
 "MathObjects.pl",
 "PGML.pl",
# "PCCmacros.pl",
 "contextLimitedPolynomial.pl",
 "answerHints.pl",
 "parserBizarroArithmeticTest.pl",
);
##############################################
Context("LimitedPolynomial-Strict");
# m and n are the exponents
$mybase=random(9,20,1);
$m=random(1,20,1);
$n=random(2,20,1);
# myvar is the variable- could be x, y, z, ..., anything in PCCmacros.pl
$myvar = "x";
# custom error message
Context()->{error}{msg}{"A variable can appear only once in each term of a polynomial"}
 = "Your answer must be fully simplified";
# quick reduction check (if $m or $n is 1)
$myvar1 = Formula("$myvar^$m")->reduce->substitute(x=>$mybase);
$myvar2 = Formula("$myvar^$n")->reduce->substitute(x=>$mybase);
$total = $m+$n;
$ans = Formula("$myvar^($total)");
Context("Numeric"); # since these problems have *numeric* bases
Context()->flags->set(formatStudentAnswer=>'parsed',reduceConstants=>0); # this line stops 9^3 being computed, and leaves it as 9^3
Context()->operators->undefine('*','/','+','-'); # forbid operators in the answer
# need to do the substitution in NUMERIC context
$myvar1 = $myvar1->substitute(x=>$mybase);
$myvar2 = $myvar2->substitute(x=>$mybase);
$ans = $ans->substitute(x=>$mybase);
$ans = Compute($ans);
Context()->operators->set(
 '^' => {class => 'my::BOP::power', isCommand => 1}, # override ^
 '**' => {class => 'my::BOP::power', isCommand => 1}, # override ** 
);
##############################################
TEXT(beginproblem());
BEGIN_PGML
Use the properties of exponents to simplify the following
 
 [`[$myvar1]\cdot[$myvar2]`]
[______]
END_PGML
$wrong=$m*$n;
ANS($ans -> cmp(checker=>sub{
my ( $correct, $student, $ansHash ) = @_;
return 0 if $ansHash->{isPreview} || $correct != $student;
$student = $ansHash->{student_formula};
$correct = $correct->{original_formula} if defined $correct->{original_formula};
$student = Formula("$student"); $correct = Formula("$correct");
return 0 unless ($correct == $student);
Context()->flags->set(bizarroPow=>1);
Value->Error("Use exponents to simplify rather than actually evaluating") unless ($correct == $student);
Context()->flags->set(bizarroPow=>0);
return 1;
}) ->
 withPostFilter(AnswerHints(
 [Compute("$mybase^($wrong)")] =>
 "When multiplying terms with the same base, you do not multiply the exponents.")));
BEGIN_PGML_SOLUTION
We _add_ the exponents as follows
 [`\begin{aligned}
 [$mybase]^{[$m]}\cdot [$mybase]^{[$n]}&=[$mybase]^{[$m]+[$n]}\\
 &=[$mybase]^{[$total]}
 \end{aligned}`]
END_PGML_SOLUTION
##############################################
ENDDOCUMENT();
 
                        
In reply to Alex Jordan

Re: Bizarro Power

by Davide Cervone -
The error comes from the result of converting the correct (and student) answers to perl form for evaluation. The isCommand value is intended to make the perl form call the objects call() method, but it turns out that exponentiation already has a perl override, so you are getting that as a command instead.

The solution is to remove the perl value when you set the isCommand, as in the following:

    Context()->operators->set(
     '^'  => {class => 'my::BOP::power', isCommand => 1, perl=>undef}, # override ^
     '**' => {class => 'my::BOP::power', isCommand => 1, perl=>undef}, # override ** 
);
This will allow the values to be checked properly.

There is another problem, however. Your formula for exponents is essentially exp(log(abs($a))**$n), so for something like 16^8 (which is what my seed produced), you get exp(log(16)**8). But log(16) is about 2.77, and log(2)**8 is around 3492. trying to take exp() of this value produces an overflow (the value "infinity"), and that makes your check ineffective.

You will need to use a bizzaro formula that produces smaller values. Perhaps using multiplication rather than exponentiation, as in exp(log(abs(b))*$n) would do?

Davide

In reply to Davide Cervone

Re: Bizarro Power

by Alex Jordan -
Thanks Davide,

Actually we've thought harder about how we want to use bizarro arithmetic in general, and it's led to some interesting realizations. I'm not sure if this is the right place to lay them out, but an overview would be that we basically want arithmetic operations that satisfy the field axioms but also interact with usual arithmetic in special ways. I can at least quickly describe one application:

For factoring problems, we are turning on bizarro + and -, but leaving * and ^ alone. Now (x+1)^2, (x+1)(1+x), (x+1)(x+1) are all equivalent, but x^2+2x+1 and x^2+x+x+1 are different from these (and to each other). Basically, regular * and bizarro + do not satisfy the distributive law, and that makes this approach to factoring (seem to) work (so far). However, we realized we still want regular * and bizarro + to obey the distributive law when the situation is "distributing a negation". Otherwise (x-1)(x-1) and (1-x)(1-x) are different.

(Side note: for factoring we still have to do a special attack for the response to (2x - 2)(x/2 - 1/2).)

Thinking more about it all, our latest proposal is that the bizarro operations be defined as:
a bizarroOp b = f^-1(f(a) regularOp f(b))
where f is an odd one-to-one function on R. If f is a simple power function, there is too much interaction between the bizarro arithmetic and regular arithmetic. As you have noted, if f involves logarithms or exponentiation, there are machine arithmetic issues. So the simplest thing we've come up with is
f(x) = x^3+x
and its inverse function that has an explicit formula found from applying the cubic formula. At all steps the numbers are kept within roughly their original value cubed.

Your observation about the numbers produced from your seed make me think we should go with f^-1(x) being x^3+x, rather than f(x). Then 16^8 will roughly translate to cube(cubeRoot(16)^cuberoot(8)), and it opens the door for slightly larger bases and exponents.

We're nearing the end of our basic algebra problem library development, and I look forward to tidying up our investigations like these and seeing if they have a place in the general distribution.