Opened 2 years ago

Last modified 19 months ago

#23368 new enhancement

More immediate symbolic powers simplification

Reported by: rws Owned by:
Priority: major Milestone: sage-8.2
Component: symbolics Keywords:
Cc: charpent Merged in:
Authors: Reviewers:
Report Upstream: N/A Work issues:
Branch: Commit:
Dependencies: Stopgaps:

Description

We already do:

sage: sqrt(4/9*x)
2/3*sqrt(x)
sage: sqrt(-4*x)
2*sqrt(-x)
sage: (4*x + 12)^(-3)
1/64/(x + 3)^3
sage: (4/9*x)^(3/2)
8/27*x^(3/2)

This should be extended to rational exponents of sums:

sage: sqrt(-4*x-4)
sqrt(-4*x - 4)
sage: (4*x + 12)^(-3/2)
(4*x + 12)^(-3/2)

It's a matter of implementing the case add^rational in Pynac's power::eval

Change History (16)

comment:1 Changed 2 years ago by rws

  • Cc charpent added

comment:2 Changed 2 years ago by charpent

Thanks for Cc'ing me !

I'm not convinced that's necessarily the Right Thing (TM) to do : it might prohibit more interesting operations, such as factorization after expand().

I was thinking of adding (after 8.0) a few methods for symbolic expressions, such as x.simplify_sum() (a wrapper for x.maxima_methods().ev(simpsum=True) and possibly a collection of useful-but-not-always-pertinent transformations (such as trig (e. g. conversions to tan(x/2), rewriting products as sums and vice-versa, etc...) that might be easier to call at willwityh such "syntactic sugar" methods.

Changing Maxima's domain can be done easily enough for one evaluation of a given expression E by asking E.maxima_methods().ev(domain=real), or for the long term via maxima_calculus("domain:real").

Could we take a bit of time to think about what would be useful to implement in such methods ? This simplification is an obvious candidate, but probably not the only one, and probably not as a systematic simplification.

I'm also considering extending E.distribute() to the case of the distribution of a differentiation over a sum ; I'm not yet convinced it is useful, but I'm looking for reasons (pro or contra).

BTW, this (as well as your previous work on symbolic sums and products) and the recent distribute() should be reported back to Maxima (but the implementation is not as easy in Maxima/lisp as in Sage...).

Furthermore, let's not forget that "Syntactic sucar causes cancer of the semicolon" (A. J. Perlis, IIRC) : in other words, let's not paint ourselves in a too-difficult-to-maintain corner.

comment:3 follow-up: Changed 2 years ago by rws

Fact is, there is already such simplification with integer exponents. Please give an example where extension to rational should not be allowed. Note also there is a canonical form Pynac adheres to and that affects if this simplification is applied (leading coeff positive). Note too that the long term goal is to become more independent from Maxima, for known reasons.

comment:4 in reply to: ↑ 3 Changed 2 years ago by charpent

Replying to rws:

Fact is, there is already such simplification with integer exponents. Please give an example where extension to rational should not be allowed.

No example on hand at the moment, but ISTR to have been bitten by too-eager simplifications in integration of trig functions (undergrad-level exercises...) : "obvious" changes of variable became largely unobvious, and some factorizations were missed.

Note also there is a canonical form Pynac adheres to and that affects if this simplification is applied (leading coeff positive).

And that sometimes gives birth to strange expressions, that have to be re-massaged. A minimal example (quoted from memory, no Sage available ATM) :

var("y,z,k,theta", domain="positive")
assume(k,"noninteger")
dbeta(y,k,theta)=y^(k-1)*e^-(y/theta)/(theta^k*gamma(k)
integrate(dbeta(z,k,theta)*dbeta(y-z,k,theta),z,0,y) ## Fails (returns an unevaluated integral)
integrate((dbeta(z,k,theta)*dbeta(y-z,k,theta)).expand(),z,0,y) ## Succeeds

Note too that the long term goal is to become more independent from Maxima, for known reasons.

Agreed. But I have to confess that, to me at least, Maxima is muche easier to grasp than Pynac (my command of C++ is not up to the level of mt grasp of Lisp and Maxima...).

comment:5 Changed 2 years ago by rws

  • Branch set to u/rws/more_immediate_symbolic_powers_simplification

comment:6 Changed 2 years ago by rws

  • Commit set to b17dedb7119612ad055035e8829f235d7c33adc8

You can try it out. I added the Pynac patch in this branch, so you can see yourself which doctests fail and how they fail. Test the directories symbolic, calculus, tests, and src/doc to see the effects of this patch.


New commits:

b17dedb23368: More immediate symbolic powers simplification

comment:7 Changed 2 years ago by git

  • Commit changed from b17dedb7119612ad055035e8829f235d7c33adc8 to 3cd17f5aeafac08fbd04bf685b1ec85809201124

Branch pushed to git repo; I updated commit sha1. New commits:

3cd17f523368: new patch

comment:8 Changed 2 years ago by rws

Actually a better alternative is to draw only the rational part of the root outside. The new patch does it and "fails" only these tests:

File "src/sage/calculus/calculus.py", line 233, in sage.calculus.calculus
Failed example:
    f.derivative(x)
Expected:
    1/3/sqrt(1/9*x^2 + 1)
Got:
    1/sqrt(x^2 + 9)

File "src/sage/functions/hypergeometric.py", line 776, in sage.functions.hypergeometric.closed_form
Failed example:
    closed_form(hypergeometric([1, 1, 2], [1, 1], z))
Expected:
    (z - 1)^(-2)
Got:
    1/(z - 1)^2

Do you agree the failures are okay?

I'm still investigating the fails in src/doc.

comment:9 Changed 2 years ago by git

  • Commit changed from 3cd17f5aeafac08fbd04bf685b1ec85809201124 to ed4dece5d1690a6c4f30937041676e2027e9d7ca

Branch pushed to git repo; I updated commit sha1. New commits:

ed4dece23368: fix patch

comment:10 Changed 2 years ago by rws

  • Branch u/rws/more_immediate_symbolic_powers_simplification deleted
  • Commit ed4dece5d1690a6c4f30937041676e2027e9d7ca deleted
  • Dependencies set to pynac-0.7.10
  • Report Upstream changed from Reported upstream. No feedback yet. to Fixed upstream, in a later stable release.

After the last fix I feel justified to introduce this change in Pynac-0.7.10. I'll remove the branch now but it can still be checked out for testing. This ticket now depends on a future Pynac upgrade ticket, and it should add the bool... doctest and some more for good measure.

comment:11 Changed 23 months ago by rws

There were complications, see https://trac.sagemath.org/ticket/23325#comment:21 So a full implementation depends on improved simplifcation, probably outside Maxima.

comment:12 Changed 19 months ago by rws

  • Dependencies changed from pynac-0.7.10 to pynac-0.7.14
  • Milestone changed from sage-8.1 to sage-8.2
  • Report Upstream changed from Fixed upstream, in a later stable release. to N/A

Examples and doctests that would change:

sage: sqrt(-4*x-4)
2*sqrt(-x - 1)
sage: (4*x + 12)^(-3/2)
1/8/(x + 3)^(3/2)

Expected:
    1/4*sqrt(5) + 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4
Got:
    1/4*I*sqrt(2)*sqrt(sqrt(5) + 5) + 1/4*sqrt(5) - 1/4

Expected:
    (-1)^floor(1/2*x/pi)*sqrt(-1/2*cos(x) + 1/2)
Got:
    sqrt(1/2)*(-1)^floor(1/2*x/pi)*sqrt(-cos(x) + 1)

Expected:
    -1/2*(1/18*sqrt(23)*sqrt(3) - 1/2)^(1/3)*(I*sqrt(3) + 1) - 1/6*(-I*sqrt(3) + 1)/(1/18*sqrt(23)*sqrt(3) - 1/2)^(1/3)
Got:
    -1/2*(1/18)^(1/3)*(sqrt(23)*sqrt(3) - 9)^(1/3)*(I*sqrt(3) + 1) - 3*(1/18)^(2/3)*(-I*sqrt(3) + 1)/(sqrt(23)*sqrt(3) - 9)^(1/3)

Expected:
    -1/8*sqrt(5) + 1/4*sqrt(-3/2*sqrt(5) + 15/2) - 1/8
Got:
    1/4*sqrt(3/2)*sqrt(-sqrt(5) + 5) - 1/8*sqrt(5) - 1/8

Expected:
    1/4*sqrt(-2*sqrt(6) - 2*sqrt(2) + 8)
Got:
    1/4*sqrt(2)*sqrt(-sqrt(6) - sqrt(2) + 4)

That sqrt(23)*sqrt(3) is not combined should be addressed elsewhere.

comment:13 follow-up: Changed 19 months ago by rws

There would be 30 doctest changes in the 5 main symbolic directories alone. I'm not prepared to push this as default behaviour---but maybe as separate method.

comment:14 Changed 19 months ago by rws

The code has been archived at: https://github.com/pynac/pynac/pull/292

comment:15 in reply to: ↑ 13 Changed 19 months ago by charpent

Replying to rws:

There would be 30 doctest changes in the 5 main symbolic directories alone. I'm not prepared to push this as default behaviour

Exactly why I got cold feet with the (much smaller) distribution of a few operations over sum and product, and created distribute. Seconded.

---but maybe as separate method.

canonicalize_power(s) (parallel to canonicalize_radical) ?

Another possibility to discuss : extend canonicalize_radical : same category of operations, but this would change its definition.

comment:16 Changed 19 months ago by rws

  • Dependencies pynac-0.7.14 deleted

Yes, third possibility is to extend factor with a powers=True argument. In any case I need to think about how to implement it conditionally in Pynac.

Note: See TracTickets for help on using tickets.