Opened 6 years ago

Closed 3 years ago

Last modified 14 months ago

#15605 closed defect (fixed)

(-1)^(2/3) evaluates to 1

Reported by: mmezzarobba Owned by:
Priority: major Milestone: sage-7.6
Component: symbolics Keywords:
Cc: vdelecroix Merged in:
Authors: Ralf Stephan Reviewers: Vincent Delecroix
Report Upstream: N/A Work issues:
Branch: 69f75ec (Commits) Commit:
Dependencies: Stopgaps:

Description (last modified by vdelecroix)

Likely a duplicate, but I couldn't find it elsewhere...

sage: (-1)^(2/3)
1

Of course, this is inconsistent with virtually all interpretations and conversions of symbolic expressions...

sage: CC(-1)^(2/3)
-0.500000000000000 + 0.866025403784439*I
sage: QQbar(-1)^(2/3)
-0.500000000000000? + 0.866025403784439?*I
sage: RR(-1)^(2/3)
-0.500000000000000 + 0.866025403784439*I

Also:

sage: (-1)^(-1/3)
-1
sage: 1 / ((-1)^(1/3))
-1
sage: (-1)^(1/3)*(-1)^(1/5)
1

but

sage: (-1)^(1/15)
(-1)^(1/15)

Change History (29)

comment:1 Changed 6 years ago by mmezzarobba

  • Description modified (diff)

comment:2 Changed 6 years ago by mmezzarobba

  • Description modified (diff)

comment:3 Changed 6 years ago by vbraun_spam

  • Milestone changed from sage-6.1 to sage-6.2

comment:4 Changed 6 years ago by chapoton

  • Description modified (diff)

Seems to be a problem about "even" powers:

sage: [(-1)^(i/77) for i in range(9)]
[1, (-1)^(1/77), 1, (-1)^(3/77), 1, (-1)^(5/77), 1, (-1)^(1/11), 1]

comment:5 Changed 6 years ago by vbraun_spam

  • Milestone changed from sage-6.2 to sage-6.3

comment:6 Changed 5 years ago by vbraun_spam

  • Milestone changed from sage-6.3 to sage-6.4

comment:7 in reply to: ↑ description ; follow-ups: Changed 5 years ago by tmonteil

Replying to mmezzarobba:

Likely a duplicate, but I couldn't find it elsewhere...

It is indeed a known issue since at least this ask answer, and i use this example in my presentations about Sage and the need to define objects within a reliable parent.

I did not report that on trac because this is somehow a feature of the symbolic ring : no semantics. I remember a discussion with you at sd49 (Orsay) about that precise example and the benefits (or not!) of having such kind of symbolic expressions that are able to make all kind of simplifications/derivatives/evaluations without context.

If one want to have something that both:

  • applies rules such as a^(bc) = (a^b)^c systematically,
  • takes principal branches of multi-valued complex function when evaluating,

then we should accept that kind of behaviour.

It would however be awesome to have a well-designed object to work with holomorphic functions, along the same lines that what is done with polynomials, i guess it is a very hard task, and i do not know whether there exists libraries for that.

comment:8 in reply to: ↑ 7 Changed 5 years ago by rws

Replying to tmonteil:

If one want to have something that both:

  • applies rules such as a^(bc) = (a^b)^c systematically,
  • takes principal branches of multi-valued complex function when evaluating,

then we should accept that kind of behaviour.

I think that with bc numeric (and it only makes sense to me if rational) and a negative the rule a^(bc) = (a^b)^c should not be applied simply because then a^b loses information. With symbolic exponent the user will probaby expect simplification.

comment:9 in reply to: ↑ 7 Changed 5 years ago by mmezzarobba

Replying to tmonteil:

this is somehow a feature of the symbolic ring : no semantics.

I agree in part only. Sure, general symbolic expressions have very weak semantics—essentially, I view them as straight-line programs that are just required to evaluate to what you'd expect when you assign values to free variables. Many operations on symbolic expressions, however, only make sense with stronger assumptions on the expressions. Typically, simplifications are supposed to transform these ”programs“ into ”equivalent“ ones, but of course whether two ”programs“ are equivalent depends on what the variables can represent.

The sensible thing to do IMO is to view all variables as complex by default, and require simplifications to be valid for arbitrary complex values of all variables (or more accurately, for a generic choice of complex values: for example, we probably do want x/x to simplify to 1). At least what's what Maple does, and Maple arguably has the best implementation of ”general symbolic expressions” over there.

We'll still get nonsense in many cases when trying to simplify expressions containing constants from finite fields or other parents that do not fit well into this model, but I don't know how to avoid that. (Something that may be worth trying would be to define new symbolic ”rings“ parametrized by a parent. For instance, in SR(QQ), all variables would be assumed to represent elements of QQ, constants would automatically be coerced into QQ, and arithmetic operations between constants would take place there. But that's not how the existing SR works.)

If one want to have something that both:

  • applies rules such as a^(bc) = (a^b)^c systematically,

I don't think we want that. IMO this rule should be applied only if either assumptions on a, b, c make it safe (e.g., c is known to be an integer) or the user explicitely asked for it. Of course, safe simplification routines are more cumbersome to use. To mitigate the issue, Maple's simplify accepts an option (symbolic) that tells it to disregard all analytical issues related to multivalued functions and just take any branch it likes. Something like that would be convenient in Sage as well.

comment:10 Changed 5 years ago by vdelecroix

  • Cc vdelecroix added

comment:11 Changed 5 years ago by vdelecroix

  • Description modified (diff)

comment:12 follow-up: Changed 5 years ago by vdelecroix

Just to give some concrete motivations, in #16222 (and #17516) we need a rather small subsets of symbolic expressions that modelize (some) algebraic numbers. Namely:

  • no variable
  • rational coefficients
  • I
  • exp(2*I*pi*a), cos(2*pi*a), sin(2*pi*a) with a rational
  • rational powers
  • taking real and imaginary parts

An example of such expression is

((cos(pi/7) + (-1)^(1/3))^(2/3)).real()

Do you think this must be out of the symbolic ring?

Vincent

comment:13 in reply to: ↑ 12 ; follow-up: Changed 5 years ago by mmezzarobba

Replying to vdelecroix:

Do you think this must be out of the symbolic ring?

I for one don't really see a problem with using the symbolic ring, but it depends if you have more use cases in mind.

comment:14 in reply to: ↑ 13 ; follow-up: Changed 5 years ago by vdelecroix

Replying to mmezzarobba:

Replying to vdelecroix:

Do you think this must be out of the symbolic ring?

I for one don't really see a problem with using the symbolic ring, but it depends if you have more use cases in mind.

Here is one problem with using the symbolic ring for constants:

sage: 0.1 * cos(pi/13)
0.100000000000000*cos(1/13*pi)

The answer should be a floating point real number!

Vincent

comment:15 in reply to: ↑ 14 ; follow-ups: Changed 5 years ago by mmezzarobba

Replying to vdelecroix:

Here is one problem with using the symbolic ring for constants:

sage: 0.1 * cos(pi/13)
0.100000000000000*cos(1/13*pi)

The answer should be a floating point real number!

Yes, perhaps, I'm not sure. Perhaps it should be a symbolic expression wrapping a FP number. Or perhaps it should just stay unevaluated. For instance, if 0.1 * cos(pi/13) evaluates to a FP number, what should 0.1 * x * cos(pi/13) do?

comment:16 in reply to: ↑ 15 Changed 5 years ago by vdelecroix

Replying to mmezzarobba:

Replying to vdelecroix:

Here is one problem with using the symbolic ring for constants:

sage: 0.1 * cos(pi/13)
0.100000000000000*cos(1/13*pi)

The answer should be a floating point real number!

Yes, perhaps, I'm not sure. Perhaps it should be a symbolic expression wrapping a FP number. Or perhaps it should just stay unevaluated. For instance, if 0.1 * cos(pi/13) evaluates to a FP number, what should 0.1 * x * cos(pi/13) do?

0.1 * x * cos(pi/13) should be an element of the symbolic ring (which might not necessarily be equal to 0.1 * cos(pi/13) * x). As soon as a variable appear, just go to the symbolic ring. I do not want to remove it, just to get off some part of it that would make something coherent.

This is why I am arguing for having a new intermediate world:

  • symbolic ring (the same as today),
  • some rings of symbolic constants, explicitely embedded in RR or CC, in which equality is known to be decidable (for example the one I mentioned above).

Having some False positive is also very annoying with respect to my perspective.

Vincent

comment:17 in reply to: ↑ 15 Changed 5 years ago by rws

Replying to mmezzarobba:

Replying to vdelecroix:

Here is one problem with using the symbolic ring for constants:

sage: 0.1 * cos(pi/13)
0.100000000000000*cos(1/13*pi)

The answer should be a floating point real number!

Yes, perhaps, I'm not sure. Perhaps it should be a symbolic expression wrapping a FP number. Or perhaps it should just stay unevaluated. For instance, if 0.1 * cos(pi/13) evaluates to a FP number, what should 0.1 * x * cos(pi/13) do?

But that would be then a different case? Anyway, the non-symbolic issue is now #18697.

comment:18 Changed 3 years ago by rws

Back to the original issue. The actual problem is in the Pynac logic for powers where usually the Python / Cython code for Rational.rational_power_parts is called and used. Apparently to speed things up this is only called if a numeric computation does not return a rational (which does not work as expected).

However, we cannot just say always use rational_power_parts because that is wrong too,

sage: from sage.rings.rational import rational_power_parts
sage: rational_power_parts(-1,1/3)
(1, -1)
sage: rational_power_parts(-1,2/3)
(1, 1)
sage: [rational_power_parts(-1, i/77) for i in range(9)]
[(1, 1), (1, -1), (1, 1), (1, -1), (1, 1), (1, -1), (1, 1), (1, -1), (1, 1)]

i.e. both wrong results in the following are from independent bugs:

sage: SR(-1)^(2/3)
1
sage: QQ(-1)^(2/3)
1

comment:19 Changed 3 years ago by rws

The symbolic issue is https://github.com/pynac/pynac/issues/221. We can then fix the Cython code in the rational ring, as well.

comment:20 Changed 3 years ago by rws

  • Branch set to u/rws/__1___2_3__evaluates_to_1

comment:21 Changed 3 years ago by git

  • Commit set to 046c9f9c4c8e465af7ed5799267b4162639f7eac

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

046c9f915605: -1 special case was badly handled

comment:22 Changed 3 years ago by rws

  • Authors set to Ralf Stephan
  • Milestone changed from sage-6.4 to sage-7.6
  • Status changed from new to needs_review

Actually fixing this in rational.pyx fixes both instances.

comment:23 Changed 3 years ago by vdelecroix

Nice!

Some more tests

sage: bool((-1)^(2/3) == -1/2 + sqrt(3)/2*I)
True
sage: all((-1)^(p/q) == cos(p*pi/q) + I * sin(p*pi/q) for p in srange(1,6) for q in srange(1,6))
True

comment:24 Changed 3 years ago by git

  • Commit changed from 046c9f9c4c8e465af7ed5799267b4162639f7eac to 69f75eccbfeb3dbd370f382f6a4129a12a86d7da

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

c1f1583Merge branch 'develop' into t/15605/__1___2_3__evaluates_to_1
69f75ecmore tests

comment:25 Changed 3 years ago by vdelecroix

  • Reviewers set to Vincent Delecroix
  • Status changed from needs_review to positive_review

good enough. Thanks for the fix!

comment:26 Changed 3 years ago by rws

Thanks for the review.

comment:27 Changed 3 years ago by vbraun

  • Branch changed from u/rws/__1___2_3__evaluates_to_1 to 69f75eccbfeb3dbd370f382f6a4129a12a86d7da
  • Resolution set to fixed
  • Status changed from positive_review to closed

comment:28 Changed 14 months ago by jdemeyer

  • Commit 69f75eccbfeb3dbd370f382f6a4129a12a86d7da deleted

I disagree with the fix here. It seems to me that we really should catch more generally (-a)^(even rational) instead of only (-1)^(even rational).

comment:29 Changed 14 months ago by jdemeyer

See #26414 for a follow-up.

Note: See TracTickets for help on using tickets.