Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Example 7.16 of Elementary Algorithms (simplify-trig)

7 views
Skip to first unread message

Eduardo Cavazos

unread,
Sep 30, 2009, 6:15:35 PM9/30/09
to
Hello,

I recently wrote to Joel Cohen for clarification on a procedure
'Simplify_trig' from volume 1 of his computer algebra texts. I'm
copying y'all in case there's someone who's worked through this part
of the book and might have some advice.

The code is available at: http://github.com/dharmatech/mpl

Ed

----------------------------------------------------------------------

Joel,

Example 7.16 of Elementary Algorithms says that contract-trig should
simplify the expression to 0. Indeed, I'm able to confirm this:

(contract-trig
(alge
" sin(x) + sin(y) - 2 * sin(x/2 + y/2) * cos(x/2 - y/2) "))

;; 0

By by way, my 'alge' procedure is a simple infix-to-prefix
translator. So for example:

> (alge "a*(b+c)")
(* a (+ b c))

The example text then mentions that the expansion algorithm alone
cannot attain the full simplification to 0.

Later on, the text mentions that the Simplify_trig procedure can
perform the simplification. However, here's what I get:

(simplify-trig
(alge
" sin(x) + sin(y) - 2 * sin(x/2 + y/2) * cos(x/2 - y/2) "))

;; (+ (* -1/2 (sin (+ (* -1 x) y)))
;; (* -1/2 (sin (+ x (* -1 y)))))

Note that, if I apply simplify-trig twice, I get the simplification:

(simplify-trig
(simplify-trig
(alge
" sin(x) + sin(y) - 2 * sin(x/2 + y/2) * cos(x/2 - y/2) ")))

;; 0

My 'simplify-trig' procedure is a direct translation of the one
from your book:

(define (simplify-trig u)
(let ((w (rationalize-expression (trig-substitute u))))
(/ (contract-trig (expand-trig (numerator w)))
(contract-trig (expand-trig (denominator w))))))

For example 7.16, it really boils down to this code:

(contract-trig (expand-trig u))

If I try that out directly:

(contract-trig
(expand-trig
(alge " sin(x) + sin(y) - 2 * sin(x/2 + y/2) * cos(x/2 - y/2) ")))

;; (+ (* -1/2 (sin (+ (* -1 x) y)))
;; (* -1/2 (sin (+ x (* -1 y)))))

I get the same result as 'simplify-trig'.

Let's see what happens with (expand-trig u):

(expand-trig
(alge " sin(x) + sin(y) - 2 * sin(x/2 + y/2) * cos(x/2 - y/2) "))

;; (+ (sin x)
;; (sin y)
;; (* -2
;; (+ (* (cos (* 1/2 x)) (cos (* 1/2 y)))
;; (* (sin (* 1/2 x)) (sin (* 1/2 y))))
;; (+ (* (cos (* 1/2 y)) (sin (* 1/2 x)))
;; (* (cos (* 1/2 x)) (sin (* 1/2 y))))))

Apparently, 'contract-trig' is having trouble simplifying that
expression down to 0.

Note that if I insert a call to 'algebraic-expand' between the
'contract-trig' and 'expand-trig', the simplification works:

(contract-trig
(algebraic-expand
(expand-trig
(alge " sin(x) + sin(y) - 2 * sin(x/2 + y/2) * cos(x/2 - y/2) "))))

;; 0

So I have a few options.

1 : Modify 'expand-trig' so that it ouputs results in algebraic
expanded
form. Page 285 contains a section entitled "Appraisal of Expand_trig"
which actually mentions this as an extension. Exercise 8 is about this
extension.

2 : Modify 'simplify-trig' as above. I.e. insert a call to
'algebraic-expand'.

3 : Enhance 'contract-trig' to be able to deal with the case
above. This might involve doing expansion in that procedure.

So, it's essentially a question of where to inject the expansion.

The book claims that the default 'simpliy-trig' should arrive at 0 so
perhaps I should take another look at the code before straying from
the default algorithms.

Suggestions welcome! :-)

Ed

Daniel Lichtblau

unread,
Sep 30, 2009, 7:43:37 PM9/30/09
to

Much of this will depend on details of how one represent internals for
purposes of trig (or other) manipulation. For example, one could use
complex exponentials as "variables", in an effort to maintain
algebraic relationships between them. In this setting, an expression
that has half angles might give rise to a variable such as exp(i*x/2).
But then sin(x) will be written in terms of the square of this one.
Upshot being, expansion and/or contraction might directly give zero,
if this approach toward "canonicalizing" the expression, prior to
expansion or contraction, is taken.

Daniel Lichtblau
Wolfram Research

Richard Fateman

unread,
Oct 1, 2009, 12:43:43 PM10/1/09
to
Daniel Lichtblau wrote:
In this setting, an expression
> that has half angles might give rise to a variable such as exp(i*x/2).
> But then sin(x) will be written in terms of the square of this one.
> Upshot being, expansion and/or contraction might directly give zero,
> if this approach toward "canonicalizing" the expression, prior to
> expansion or contraction, is taken.
>
> Daniel Lichtblau
> Wolfram Research
>

Essentially all high-school trigonometry identities can be confirmed by
this technique, converting to exponentials and doing "rational
simplification" on the result. DanL's comment is right that one must
first recognize that r1=exp(s) and r2=exp(s/2) are not algebraically
independent; r1 must be rewritten as r2^2.

I wrote a paper on Rationally Simplifying Non-Rational Expressions,
ACM SIGSAM Bulletin, July 1972,

with such examples.


In Macsyma, use exponentialize and then radcan.

When does it fail? Some trig identities have square-roots in them,
which can result in wrong branch choices.


sqrt((sec(x)-1)/(sec(x)+1)) +(1-cos(x))/sin(x) caused some problems
in 1971, though it seems to reduce to 0 right now.

If the expression is NOT zero, then the resulting expression may not
be easy to convert back to sin, cos, tan. Just a warning, that
being able to confirm high-school identities is not necessarily what
you need to do.

RJF

clicl...@freenet.de

unread,
Oct 1, 2009, 5:09:30 PM10/1/09
to

Richard Fateman schrieb:

>
> Essentially all high-school trigonometry identities can be confirmed
> by this technique, converting to exponentials and doing "rational
> simplification" on the result. DanL's comment is right that one must
> first recognize that r1=exp(s) and r2=exp(s/2) are not algebraically
> independent; r1 must be rewritten as r2^2.
>
> I wrote a paper on Rationally Simplifying Non-Rational Expressions,
> ACM SIGSAM Bulletin, July 1972,
>
> with such examples.
>
> In Macsyma, use exponentialize and then radcan.
>
> When does it fail? Some trig identities have square-roots in them,
> which can result in wrong branch choices.
>
> sqrt((sec(x)-1)/(sec(x)+1)) +(1-cos(x))/sin(x) caused some problems
> in 1971, though it seems to reduce to 0 right now.
>
> If the expression is NOT zero, then the resulting expression may not
> be easy to convert back to sin, cos, tan. Just a warning, that
> being able to confirm high-school identities is not necessarily what
> you need to do.
>

For real x, the expression SQRT((SEC(x)-1)/(SEC(x)+1)) +
(1-COS(x))/SIN(x) is equivalent to (1 + SIGN(SIN(x))) TAN(x/2). This
equals zero only when SIN(x) < 0.

Martin.

Richard Fateman

unread,
Oct 1, 2009, 11:35:17 PM10/1/09
to
clicl...@freenet.de wrote:
...

>
> For real x, the expression SQRT((SEC(x)-1)/(SEC(x)+1)) +
> (1-COS(x))/SIN(x) is equivalent to (1 + SIGN(SIN(x))) TAN(x/2). This
> equals zero only when SIN(x) < 0.
>
> Martin.

mathematica 6.0 produces (using FullSimplify)
tan(x/2)+ sqrt(tan(x/2)2 )

which is, as you say, zero when sin(x)<0.

This is a cute result, and it may be worth thinking about how something
like it might be obtained!

clicl...@freenet.de

unread,
Oct 2, 2009, 11:11:19 AM10/2/09
to

Richard Fateman schrieb:

>
> clicl...@freenet.de wrote:
> ...
> >
> > For real x, the expression SQRT((SEC(x)-1)/(SEC(x)+1)) +
> > (1-COS(x))/SIN(x) is equivalent to (1 + SIGN(SIN(x))) TAN(x/2). This
> > equals zero only when SIN(x) < 0.
> >
>
> mathematica 6.0 produces (using FullSimplify)
> tan(x/2)+ sqrt(tan(x/2)2 )
>
> which is, as you say, zero when sin(x)<0.
>
> This is a cute result, and it may be worth thinking about how
> something like it might be obtained!

Apparently Mathematica has a route from (SEC(x)-1)/(SEC(x)+1) =
(1-COS(x))/(COS(x)+1) to SIN(x/2)^2/COS(x/2)^2 = TAN(x/2)^2.

Derive only knows to go the other way (for a suitable Trigpower
setting):

TAN(x/2)^2

[Trigonometry:=Auto, Trigpower:=Cosines]

" TAN(z/2) -> SIN(z)/(1+COS(z)) "

(SIN(x)/(COS(x)+1))^2

" SIN(z)^2 -> 1-COS(z)^2 "

(1-COS(x)^2)/(COS(x)+1)^2

" one final step "

(1-COS(x))/(COS(x)+1)

For SQRT((SEC(x)-1)/(SEC(x)+1)) with a suitable Trigonometry setting,
Derive delivers

SQRT((SEC(x)-1)/(SEC(x)+1))

[Trigonometry:=Collect, Trigpower:=Auto]

TAN(x/2)*SIGN(SIN(x)/2)

but this not stable (it also shows signs of a premature exit), with
further simplification resulting in

ABS(SIN(x))/(COS(x)+1)

Tell me if you want to see the steps.

What Maxima effectively did when simplifying SQRT((SEC(x)-1)/(SEC(x)+1))
+ (1-COS(x))/SIN(x) to zero was to take the negative root when SIN(x) >
0 and the positive root when SIN(x) < 0. With equal justification it
might have taken the positive root when SIN(x) > 0 and the negative root
when SIN(x) < 0, and thus have arrived at 2 TAN(x/2) instead of zero.

Martin.

0 new messages