Below is the code. Thank you for your help.
##############################################
# Initialization
DOCUMENT();
loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGcourse.pl",
"AnswerFormatHelp.pl",
"parserFormulaUpToConstant.pl",
);
TEXT(beginproblem());
$showPartialCorrectAnswers = 0;
##############################################
# Setup
Context("Numeric");
# Integrate a*sin(b*x), a and b randomized
$a = Real(non_zero_random(-5,5,1));
$b = Real(non_zero_random(-5,5,1));
$c = Real($a*$b);
$f = FormulaUpToConstant("$a sin($b * x)")->reduce("(-x)-y"=>0,"(-x)+y"=>0);
$dfdx = $f->D; # f'(x)
##############################################
# Main text
Context()->texStrings;
BEGIN_TEXT
Compute the indefinite integral
\[ \int \{$dfdx->TeX\} dx \]
$BR
(remember: your answer should be a function of \(x\)!)
$BR
\{ ans_rule(20) \}
END_TEXT
Context()->normalStrings;
ANS( $f->cmp() );
ENDDOCUMENT();
f'(x)=(a*b)cos(bx)
inside the integral
Actually, it is f'(x) = a*(b*cos(bx))
, which is structurally different, and it is because of the structural difference that the constants are not combined. The reduce()
method would have reduced the constants in your expression, but because the two constants aren't multiplied directly in the derivative, they are not.
The reduction rules don't include anything for this situation. There are more rules that could be added that would help with this but currently there aren't any.
One way around this, however, is to take advantage of the fact that there are no parentheses displayed around the b*cos(bx)
in its string version and ask MathObject to parse the value again. Try
$dfdx = Formula($f->D->string);to force the expression to be reparsed, so that the multiplication of the two constants is performed first.
Also, I note that you have used reduce("(-x)-y"=>0,"(-x)+y"=>0)
for your formula. But it doesn't contain any sums or differences, so these rules never apply anyway, so there is no need to disable them in this case.
I see you are making $a
and $b
into Real MathObjects, that is fine, though unnecessary in this problem, since they are only used to be inserted into the formula for $f
. You also make a variable $c
that is never used, and you force it to a Real as well. Since $a
and $b
are already Real objects, there is no need to use Real()
again on the result, as it will be a Real automatically.
Re: Simplifying output of automatic differentiation
by Nicholas Nguyen -Thank you both. At this point, the problem still displays formulas like
"-(15cos(3x)),"
but at least it multiplies the coefficients now.
Davide: I ended up keeping the reduction exceptions for $f, because without them, in the solution, WeBWorK might display
"C - 5sin(3x)" instead of "-5sin(3x) + C."
Here is the updated code.
##############################################
# Initialization
DOCUMENT();
loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGcourse.pl",
"AnswerFormatHelp.pl",
"parserFormulaUpToConstant.pl",
);
TEXT(beginproblem());
$showPartialCorrectAnswers = 0;
##############################################
# Setup
Context("Numeric");
# Integrate a*sin(b*x), a and b randomized
$a = Real(non_zero_random(-5,5,1));
$b = Real(non_zero_random(-5,5,1));
$c = $a*$b; # Needed for solution display
$f = FormulaUpToConstant("$a sin($b * x)")->reduce("(-x)-y"=>0,"(-x)+y"=>0);
# Without the rules "(-x)-y"=>0,"(-x)+y"=>0, the solution might display "C - sin($ax)."
$dfdx = Formula($f->D->string);
# Reparse so $a and $b are multiplied in display
##############################################
# Main text
Context()->texStrings;
BEGIN_TEXT
Compute the indefinite integral
\[ \int $dfdx \, dx \]
$BR
(remember: your answer should be a function of \(x\)!)
$BR
\{ ans_rule(20) \}
END_TEXT
BEGIN_SOLUTION
Use subtitution with:
\[
u = $b x, \, du = $b dx \implies \frac{1}{$b}du = dx
\]
\[ \int \frac{$c}{$b} \cos(u) \, du = \int $a \cos(u) \, du \]
An antiderivative of \(\cos(u)\) is \(\sin(u)\):
\[
= $a \sin(u) + C
\]
Don't forget to substitute \(u = $b x\):
\[
= $f
\]
END_SOLUTION
Context()->normalStrings;
ANS( $f->cmp() );
ENDDOCUMENT();
Re: Simplifying output of automatic differentiation
by Nicholas Nguyen -"-15cos(3x)"
in the problem now. Here's the rewrite:
##############################################
# Initialization
DOCUMENT();
loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGcourse.pl",
"AnswerFormatHelp.pl",
"parserFormulaUpToConstant.pl",
);
TEXT(beginproblem());
$showPartialCorrectAnswers = 0;
##############################################
# Setup
Context("Numeric");
Context()->variables->add(u=>"Real");
# Integrate a*sin(u), with u=b*x a and b randomized
$a = Real(non_zero_random(-5,5,1));
$b = Real(non_zero_random(-5,5,1));
$c = $a*$b; # Needed for solution display
# Define $u = b*x as a formula of x for substitution
$u = Formula("$b x");
$f = FormulaUpToConstant("$a sin(u)")->reduce("(-x)-y"=>0,"(-x)+y"=>0);
# Without the rules "(-x)-y"=>0,"(-x)+y"=>0, the solution might display "C - sin($ax)."
$dfdu = Formula($f->D('u')); # df/du
$dfdux = $dfdu->substitute(u=>$u)->reduce; # Substitute u = $b*x into df/du
$dudx = Formula($u->D('x'))->reduce; # du/dx
$dfdx = Formula($dfdux*$dudx); # Chain rule df/du * du/dx = df/dx
$dfdxr = Formula($dfdx->reduce->string)->reduce; # Simplify
# In $dfdxr, first reduce moves coefficients outside cosine to left, but doesn't multiply
# Next, use string to multiply coefficients. This puts coefficient (with negative sign) in parentheses
# Finally, second reduce gets rid of excess parentheses around coefficient
##############################################
# Main text
Context()->texStrings;
BEGIN_TEXT
Compute the indefinite integral
\[ \int $dfdxr \, dx \]
$BR
(remember: your answer should be a function of \(x\)!)
$BR
\{ ans_rule \}
END_TEXT
BEGIN_SOLUTION
Use subtitution with:
\[
u = $b x, \, du = $b dx \implies \frac{1}{$b}du = dx
\]
\[ \int \frac{$c}{$b} \cos(u) \, du = \int $a \cos(u) \, du \]
An antiderivative of \(\cos(u)\) is \(\sin(u)\):
\[
= $a \sin(u) + C
\]
Don't forget to substitute \(u = $b x\):
\[
= $f
\]
END_SOLUTION
Context()->normalStrings;
ANS( $f->cmp() );
ENDDOCUMENT();
I have been finding this series of posts helpful for something I’ve been working on. I suspect another manifestation of this problem is illustrated by the code below.
Like Nicholas, the output I get has an extra pair of parentheses, namely:
-(sqrt(2x+3) ) +2 instead of -sqrt(2x+3) +2. The issue only seems to arise when $parent = sqrt(x). If $parent is 1/x or x^2 for example, there is no issue of extra parentheses.
~Mary
DOCUMENT();
loadMacros(
"PGstandard.pl", #
Standard macros for PG language
"MathObjects.pl",
);
TEXT(beginproblem());
Context("Numeric");
$a = -1;
#non_zero_random(-3, 3, 1);
# vertical stretch and reflection
$b = non_zero_random(-2, 2, 1); # horizontal stretch and reflection
$c = random(-4, 4, 1); # horizontal
shift
$d = random(-4, 4, 1); # vertical shift
Context() -> flags -> set ( reduceConstants => 0,
reduceConstantFunctions => 0 );
$parent = Formula("sqrt(x)");
$fx =$parent ->substitute(x => "$b * x -
$c") -> reduce ("(-x)-y" => 0, " x-(-y)" =>
0, "(-x)+y" =>0);
$fxy = Formula("$a * $fx + $d") -> reduce(
"(-x)-y" => 0, "(-x)+y" =>0, "-a" =>
0 );
Context()->texStrings;
BEGIN_TEXT
Given the function \(
f(x) = \displaystyle $fxy \) and
its parent function \( y = \displaystyle
$parent\), mid-formula is \( y = \displaystyle $fx \)
END_TEXT
ENDDOCUMENT();
-(sqrt(2x+3))+2
instead of -sqrt(2x+3)+2
.
Your issue turns out to be from a different cause. The MathObjects library adds extra parentheses in its output to try to make it painfully clear to the student what the structure of the expression is. For example, sin(x)^2 is shown as [sin(x)]^2 so it is clear that the whole expression is squared, not just the x.
Your situation is coming from that process. You can do
Context()->operators->set(fn => {parenPrecedence => 6.5})to fix this. (The
parenPrecedence
tells when extra parens are added around functions based on the precedence of the operator that surrounds them. 6.5 puts it between the precedence of unary minus and exponentiation, so that you still get [sin(x)]^2 but not -[sin(x)].)
I give you a modified version of your problem below. There are several small changes. One thing to keep in mind is that the names of the reduction formulas must be given exactly, so your " x-(-y)"
(which has an extra leading space) does nothing. In any case, I don't think you want that one since, you do want x-(-3)
to be converted to x+3
, I assume. (Your $c
can be negative in "$b * x - $c"
).
Similarly, your "-a"=>0
specification does nothing since there is no rule with the name "-a"
. Did you mean "-n"
? In any case, I would not recommend that you remove that one in this case. The parenPrecedence
is what is needed, here.
So here is the modified version:
loadMacros( "PGstandard.pl", # Standard macros for PG language "MathObjects.pl", ); TEXT(beginproblem()); Context("Numeric"); $a = -1; #non_zero_random(-3, 3, 1); # vertical stretch and reflection $b = non_zero_random(-2, 2, 1); # horizontal stretch and reflection $c = random(-4, 4, 1); # horizontal shift $d = random(-4, 4, 1); # vertical shift Context()->operators->set(fn => {parenPrecedence => 6.5}); Context()->reduction->noreduce("(-x)-y","(-x)+y"); $parent = Formula("sqrt(x)"); $fx = $parent->substitute(x => "$b * x - $c")->reduce; $fxy = Formula("$a * $fx + $d")->reduce; Context()->texStrings; BEGIN_TEXT Given the function \(f(x) = $fxy\) and its parent function \(y = $parent\), the mid-formula is \(y = $fx\) END_TEXT
Right. I forgot that you were using FormulaUpToConstant()
and that it does introduce an addition.
At this point, the problem still displays formulas like "-(15cos(3x)),"
OK, I've handled this by adjusting the reduction rules a little further. In the code below, I added
Context()->reduction->noreduce("(-x)-y","(-x)+y","(-x)*y","x*(-y)");which removes the rules that factor out negatives from sums, additions, and products (it is the latter that is causing your issues, here).
I also added reduce
to the definition of $dfdx
. Without this, you would end up with "(-15)cos(3x)".
So here is my modified version:
DOCUMENT(); loadMacros( "PGstandard.pl", "MathObjects.pl", "PGcourse.pl", "AnswerFormatHelp.pl", "parserFormulaUpToConstant.pl", ); TEXT(beginproblem()); $showPartialCorrectAnswers = 0; ############################################## # Setup Context("Numeric"); Context()->reduction->noreduce("(-x)-y","(-x)+y","(-x)*y","x*(-y)"); # Integrate a*sin(b*x), a and b randomized $a = Real(non_zero_random(-5,5,1)); $b = Real(non_zero_random(-5,5,1)); $c = $a*$b; # Needed for solution display $f = FormulaUpToConstant("$a sin($b * x)")->reduce; $dfdx = Formula($f->D->string)->reduce; # Reparse so $a and $b are multiplied in display ############################################## # Main text Context()->texStrings; BEGIN_TEXT Compute the indefinite integral \[ \int $dfdx \, dx \] (remember: your answer should be a function of \(x\)!) $BR \{ ans_rule(20) \} END_TEXT BEGIN_SOLUTION Use subtitution with: \[u = $b x, \, du = $b dx \implies \frac{1}{$b}du = dx\] \[\int \frac{$c}{$b} \cos(u) \, du = \int $a \cos(u) \, du\] An antiderivative of \(\cos(u)\) is \(\sin(u)\): \[= $a \sin(u) + C\] Don't forget to substitute \(u = $b x\): \[= $f\] END_SOLUTION Context()->normalStrings; ANS($f->cmp); ENDDOCUMENT();