Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doctest: Immediate simplifications of symbolic powers #14305

Closed
zimmermann6 opened this issue Mar 19, 2013 · 58 comments
Closed

Doctest: Immediate simplifications of symbolic powers #14305

zimmermann6 opened this issue Mar 19, 2013 · 58 comments

Comments

@zimmermann6
Copy link

in Sage 5.7 we get:

sage: sqrt(x^2).simplify_radical()           
x

This is wrong (consider x=-1 for example). Even:

sage: assume(x<0)
sage: sqrt(x^2).simplify_radical()
x

Previously it was

sage: sqrt(x^2).simplify_radical()
abs(x)

Note: this invalidates a whole part of our book (in french) about Sage at
http://sagebook.gforge.inria.fr/

Depends on #23325

CC: @orlitzky @burcin @rwst

Component: calculus

Author: Ralf Stephan

Branch/Commit: e5d5ba0

Reviewer: Jeroen Demeyer

Issue created by migration from https://trac.sagemath.org/ticket/14305

@kcrisman
Copy link
Member

comment:1

Regarding these three tickets (#14305, #14306, #14308 (thanks for the pointer, Paul!)) perhaps it would be good to get that book in the standard documentation under fr/ so that it can be part of doctests? Just a brainstorm, perhaps it is not a good idea for various reasons.

@kcrisman

This comment has been minimized.

@kcrisman
Copy link
Member

comment:2

This is the problem.

(%i1) radcan(sqrt(x^2));
(%o1)                               abs(x)
(%i2) domain:complex;
(%o2)                               complex
(%i3) radcan(sqrt(x^2));
(%o3)                                  x

Except this was not exposed before, apparently - it is the case in older Sage as well. This is due to #12780.

@zimmermann6
Copy link
Author

comment:3

Karl-Dieter, I guess you mean #14308 instead of #14307?

Yes of course, in fact some chapters are already included, see tests/french_book.

Other chapters are waiting for work or reviewers: #10983, #11745. Feel free to help!

Paul

@kcrisman
Copy link
Member

comment:4

This is the problem.

(%i1) radcan(sqrt(x^2));
(%o1)                               abs(x)
(%i2) domain:complex;
(%o2)                               complex
(%i3) radcan(sqrt(x^2));
(%o3)                                  x

By the way, I should point out that Maxima folks probably won't consider this a bug, for the same reasons as discussed in the past on other tickets, and expressed best by Richard Fateman here. But if we don't want this, we'll have to figure out how to deal with this.

Except this was not exposed before, apparently - it is the case in older Sage as well. This is due to #12780.

I've also posted a comment there, hopefully mjo or someone else will respond.

@zimmermann6
Copy link
Author

comment:5

any news on this ticket?

Paul

@orlitzky
Copy link
Contributor

orlitzky commented May 7, 2013

comment:6

Jeroen asked a similar question a few months ago:

https://groups.google.com/forum/?fromgroups=#!topic/sage-support/jhCJujRtNA4/discussion

Maxima should notice that x is real (if you make the assumption), but it doesn't. The simplification of sqrt(x^2) to abs(x) relies on the "simplification domain" in Maxima being set to real -- in fact, if I remember correctly, that's the only thing the simplification domain does affect. To get the answer from sage <5.6, you'd need,

sage: maxima_lib.eval('domain: real;')
'real'
sage: sqrt(x^2).simplify()            
abs(x)

It sucks that you have to do that, and we should really add either a global method or a property of maxima_lib that lets you change it. That's one solution.

A better approach would be to notice when an expression contains only real variables, and to set the simplification domain appropriately. This could be done in either Maxima or Sage (pynac/ginac), but probably belongs in both. Symbols in sage have an associated domain, too:

sage: x = SR.symbol('x', domain='real')
sage: sqrt(x^2)
sqrt(x^2)

This never passes through Maxima, so arguably, Sage should simplify it if we can convince Maxima to do the same thing. But it's not at all easy to determine whether an expression is real; otherwise, I would have written it a long time ago! I mainly work over the reals myself and would love to have a solution that doesn't involve manually fooling with Maxima.

@zimmermann6
Copy link
Author

comment:7

before #12780, the default domain was 'real', and sqrt(x^2).simplify_radical() was correctly simplified to abs(x).

After #12780, the default domain is that of Maxima (which is 'complex' in Sage 5.9), and sqrt(x^2).simplify_radical() is incorrectly simplified to x.

I believe the authors of #12780 should fix that issue.

Paul

@orlitzky
Copy link
Contributor

orlitzky commented May 7, 2013

comment:8

Replying to @zimmermann6:

before #12780, the default domain was 'real', and sqrt(x^2).simplify_radical() was correctly simplified to abs(x).

This isn't true. Before #12780, the domain everywhere in Sage except the simplify_radical function was 'complex'. The simplify_radical function would secretly change the domain to 'real', call radcan(), and then switch the domain back to 'complex'.

There is no simplification of sqrt(x^2) that is equal to abs(x), unless you know that x is real. Everywhere else in Sage, x is complex. Before sage-5.7, you got what you want, but you want a wrong answer.

I realize there's no other nice way to get the answer you want (that sucks, I want it too, it's not my fault, etc.), but that's not a good justification for adding back wrong behavior.

@nbruin
Copy link
Contributor

nbruin commented May 7, 2013

comment:9

Replying to @orlitzky:

There is no simplification of sqrt(x^2) that is equal to abs(x), unless you know that x is real. Everywhere else in Sage, x is complex. Before sage-5.7, you got what you want, but you want a wrong answer.

I'm not sure you can dispose of the problem just by declaring it invalid. We do accept assume(x<0) and with that assumption in place the answer we get back really IS wrong (since the assumption implies that x is real). I know we're not going to fix/improve maxima's assumption system any time soon, but there are cases where this bug is going to be a "won't fix" rather than an "invalid".

@orlitzky
Copy link
Contributor

orlitzky commented May 8, 2013

comment:10

We also accept assume('x is a very pretty boy'), so I'm not sure we should use that as our guide!

I'm not disagreeing that there should be an easy way to do this. Maxima should just simplify it when x is assumed real. That's probably the first bug I would target to get it fixed properly.

A second step would be to have ginac or pynac perform the same simplification on expressions of the simple form sqrt(x^2) where x is a single symbol and the domain of x is 'real'.

Finally (this is the most work), Maxima could be made to recognize when an expression y is real, and then, simplify() could turn sqrt(y^2) into abs(y). Determining whether an expression is real or not seems rather complicated, though.

@orlitzky
Copy link
Contributor

comment:11

Please take a look at #14630 which provides an easy way to get this simplification.

@kcrisman
Copy link
Member

comment:12

Thanks, that looks like a good step to take. Am I correct in saying it doesn't fix the point Nils makes about assume(x<0) (that is, when one doesn't use #14630, since the typical user would think it wasn't relevant...)?

@orlitzky
Copy link
Contributor

comment:13

Replying to @kcrisman:

Thanks, that looks like a good step to take. Am I correct in saying it doesn't fix the point Nils makes about assume(x<0) (that is, when one doesn't use #14630, since the typical user would think it wasn't relevant...)?

Correct, #14630 just provides a way to get the simplification in the description, as an alternative to setting the Maxima domain manually.

@jdemeyer jdemeyer modified the milestones: sage-5.11, sage-5.12 Aug 13, 2013
@zimmermann6
Copy link
Author

comment:15

while trying to see how we could tell Maxima that x is real after assume(x>0), I noticed that the examples with assume(x,'real') in Sage are fake:

  1. in misc/functional.py we have:
        sage: a, b, c = var("a, b, c")                                          
        sage: assume((a, 'real'), (b, 'real'), (c, 'real'))                     
        sage: z = a + b*I                                                       
        sage: bool(norm(z).simplify() == a^2 + b^2)                             
        True

but the same works without assume:

+--------------------------------------------------------------------+
| Sage Version 5.11, Release Date: 2013-08-13                        |
| Type "notebook()" for the browser-based notebook interface.        |
| Type "help()" for help.                                            |
+--------------------------------------------------------------------+
sage: a, b, c = var("a, b, c")
sage: z = a + b*I
sage: norm(z).simplify()
a^2 + b^2
  1. in symbolic/expression.pyx we have
            sage: a,b = var('a,b')
            sage: assume((a, 'real'), (b, 'real'))
            sage: f = a + b*I
            sage: f.rectform()
            a + I*b

and again it works without assume:

+--------------------------------------------------------------------+
| Sage Version 5.11, Release Date: 2013-08-13                        |
| Type "notebook()" for the browser-based notebook interface.        |
| Type "help()" for help.                                            |
+--------------------------------------------------------------------+
sage: a,b = var('a,b')
sage: f = a + b*I
sage: f.rectform()
a + I*b

Paul

@kcrisman
Copy link
Member

comment:16

Interesting. Maybe that is a function of having upgraded Maxima or something? I presume that this wasn't the case at some time, but presumptions can be presumptuous.

@zimmermann6
Copy link
Author

comment:17

maybe simplify and rectform secretly change the domain of variables to the real domain (as simplify_radical previously did)?

Paul

@kcrisman
Copy link
Member

comment:18

No, that is not it - simplify certainly doesn't, and rectform is just

return self.maxima_methods().rectform()

Sorry, that would have been easier to deal with. I particularly don't like the rectform example working without assuming real.

@orlitzky
Copy link
Contributor

comment:19

I remember the first example, from #12845. This is the full test:

sage: a, b, c = var("a, b, c")
sage: assume((a, 'real'), (b, 'real'), (c, 'real'))
sage: z = a + b*I
sage: bool(norm(z).simplify() == a^2 + b^2)
True
sage: norm(a + b).simplify()
a^2 + 2*a*b + b^2
sage: v = vector([a, b, c])
sage: bool(norm(v).simplify() == sqrt(a^2 + b^2 + c^2))
True
sage: forget()

The assumptions aren't needed for the first result, but they are for the last one (the norm of the vector).

The rectform() test is also mine, but the reasoning I've forgotten.

@zimmermann6
Copy link
Author

comment:20

The assumptions aren't needed for the first result, but they are for the last one (the norm of the vector).

maybe then the first test could be removed, if unrelated to assume?
Or at least the assume call moved after the first test?

Anyway the following is very annoying:

sage: (x*conjugate(x)).simplify()
x^2

Paul

@kcrisman
Copy link
Member

comment:21

Anyway the following is very annoying:

sage: (x*conjugate(x)).simplify()
x^2

Wow, agreed. Unfortunately, Maxima needs to declare this.

sage: assume(x,'complex')
sage: (x*conjugate(x)).simplify()
x*conjugate(x)

I guess a possible workaround would be to have all SR variables declared complex in Maxima when first starting Maxima, and then thereafter... but it would be very hackish and slow.

@kcrisman
Copy link
Member

comment:22

Turns out that it's possible to get all variables used so far in Maxima with values, and one could do a blanket declare on all of them. (Of course, one might not want to do this to all of them...) Fateman also has the following enigmatic response to me on the Maxima list.

I think the understanding of complex variables is at best spotty, and if you want to do "a LOT" of
things with them you better check out exactly what Maxima does, and perhaps even  make it work
with names that have no special properties.

Anyway, I really don't want to go back to assuming things in Maxima on every variable defined in Sage (or even every SR variable) but I think we might have to go that way. Maybe there is a flag we could set as an underscore attribute in the SR vars indicating whether it has been declared complex in Maxima yet, which would be dealt with appropriately for ones which aren't complex, or have been assumed real, etc. - i.e., the next time one went into Maxima, they would be in a queue that was then declared complex. Not sure how hawkish that would be, but hopefully at least not slowing down Pynac variables appreciably.

@zimmermann6
Copy link
Author

comment:23

a possible workaround would be to have all SR variables declared complex in Maxima

indeed, maybe we could declare each new variable as complex whenever var is called (without domain argument or with domain='complex').
This is by the way what the documentation of var says:

sage: var?
...
   By default, var returns a complex variable. To define real or
   positive variables we can specify the domain as:

Maybe we can add a call to assume in the function symbol of symbolic/ring.pyx?

Paul

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Sep 6, 2017

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

e5d5ba014305: fix typo

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Sep 6, 2017

Changed commit from 6125bd6 to e5d5ba0

@jdemeyer
Copy link

Reviewer: Jeroen Demeyer

@rwst
Copy link

rwst commented Oct 25, 2017

comment:39

Thanks.

@jdemeyer
Copy link

comment:40

I wonder why (x<sup>3)</sup>(1/3) is not simplified for real x though...

@zimmermann6
Copy link
Author

comment:41

try x=-1...

@rwst
Copy link

rwst commented Oct 25, 2017

comment:42
sage: var(x, domain='real')
x
sage: (x^3)^(1/3)
(x^3)^(1/3)
sage: assume(x > 0)
sage: (x^3)^(1/3)
x

@jdemeyer
Copy link

comment:43

I don't get this. Why should it matter whether x < 0 or x > 0?

Why is it valid to say that 1^(1/3) = 1 but not (-1)^(1/3) = -1 for real numbers?

@rwst
Copy link

rwst commented Oct 25, 2017

comment:44

I opened pynac/pynac#283

@zimmermann6
Copy link
Author

comment:45

z1/n for z a complex number is defined as the principal branch, which is that having the least argument, see for example https://en.wikipedia.org/wiki/Nth_root.

Thus the square root of -1 is I, having argument pi/2, whereas -I has argument 3*pi/2.

The cube root of -1 is 1/2 + I*sqrt(3)/2, having argument pi/3.

@rwst
Copy link

rwst commented Oct 25, 2017

comment:46

Replying to @zimmermann6:

The cube root of -1 is 1/2 + I*sqrt(3)/2, having argument pi/3.

One or three cube roots of -1 exist?

@zimmermann6
Copy link
Author

comment:47

there are three complex numbers t such that t^3=z, but when you write z^(1/3), the computer algebra system must choose one of them, for example to evaluate numerically, and the usual choice is the principal branch.

I recommend reading the paper "Branch Cuts in Computer Algebra" by Adam Dingle and Richard Fateman.

@rwst
Copy link

rwst commented Oct 25, 2017

comment:48

Replying to @zimmermann6:

there are three complex numbers t such that t^3=z, but when you write z^(1/3), the computer algebra system must choose one of them, for example to evaluate numerically, and the usual choice is the principal branch.

I recommend reading the paper "Branch Cuts in Computer Algebra" by Adam Dingle and Richard Fateman.

I'm not evaluating numerically, t^3=z does not per se represent a function, just an expression. If your argument were true, I could not even solve for -1.

@rwst
Copy link

rwst commented Oct 25, 2017

comment:49

I mean why do I even argument, Jeroen is a better math, so I trust him when he objects.

@rwst
Copy link

rwst commented Oct 25, 2017

comment:50

Paul, maybe the problem is that you transfer the fact that RR is in CC to that "expressions with real variables" behave like "expressions with complex variables"?

@jdemeyer
Copy link

comment:51

Replying to @rwst:

Jeroen is a better math, so I trust him when he objects.

Not sure why you say that. I understand Paul's reasoning. It's hard to tell who is right. If only variables have a domain (as opposed to constants), then (-1)^(1/3) must indeed evaluate to a complex number because we can't guess whether the -1 represents the real or complex -1.

@rwst
Copy link

rwst commented Oct 25, 2017

comment:52

A complex function is not necessarily a complex-variable function, that's maybe the mistake I made.

@zimmermann6
Copy link
Author

comment:53

indeed we cannot know in advance whether -1 represents a real or complex number.
However, another point is that the "simplication rule" should be consistent between the real and complex numbers: when a complex number z tends to the real number -1, you want that z^(1/3) tends to (-1)^(1/3), except maybe on a line (called the branch cut) going out from 0. The principal branch gives this consistency.

@orlitzky
Copy link
Contributor

comment:54

This is messy largely because we have never decided on what sqrt or e.g. x^(1/3) is supposed to do, particularly when applied to a symbolic expression.

  • Is it a function from the real numbers to the real numbers (choose the positive root)?
  • Is it a function from the complex numbers to the complex numbers (choose the principal branch)?
  • Is the codomain of sqrt the same as a "domain" of its argument? For example, if x is a variable with domain=real, should sqrt(x) be an expression whose domain is "real"?
  • Do we want sqrt and friends to be functions at all? When solving equations, it'd be nice if we had access to both square roots.

etc.

If you ask five different people, you'll get five different answers. I'm wary of any "simplification" that might return an incorrect result to any of those people: simplification should be unambiguous and obviously correct. Any other more-powerful but less-straightforward operation should be called something else, like we've done with x.canonicalize_radical().

@rwst
Copy link

rwst commented Oct 25, 2017

comment:55

Replying to @rwst:

I mean why do I even argument, Jeroen is a better math, so I trust him when he objects.

I just reread that and yes I forgot to add "than me", opening unintended interpretations.

@kcrisman
Copy link
Member

comment:56

If you ask five different people, you'll get five different answers. I'm wary of any "simplification" that might return an incorrect result to any of those people: simplification should be unambiguous and obviously correct. Any other more-powerful but less-straightforward operation should be called something else, like we've done with x.canonicalize_radical().

Correct, this whole thread is exactly the same thing. Basically, is sqrt(x) a symbol or a function? If you want long (and undoubtedly correct in at least one interpretation) answers to this, ask Fateman :-) with whom we had long discussions about it.

@vbraun
Copy link
Member

vbraun commented Oct 29, 2017

Changed branch from u/rws/clarify_assumptions_and_domains_in_maxima to e5d5ba0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants