Repository: sympy/sympy
Pull request: Fixes polynomial solve with GoldenRatio and TribonacciConstant
<!-- Your title above should be a short description of what
was changed. Do not include the issue number in the title. -->
Fixes polynomial solve with GoldenRatio and TribonacciConstant
#### References to other Issues or PRs
<!-- If this pull request fixes an issue, write "Fixes #NNNN" in that exact
format, e.g. "Fixes #1234" (see
https://tinyurl.com/auto-closing for more information). Also, please
write a comment on that issue linking back to this pull request once it is
open. -->
Fixes #11553

#### Brief description of what is fixed or changed
Before fixing:
```
>>> from sympy import *
>>> x,y = symbols('x y')
>>> eq1 = x + y + 1
>>> eq2 = x + GoldenRatio
>>> solve([eq1, eq2], x, y)
Traceback (most recent call last):
   ...
sympy.polys.polyerrors.NotAlgebraic: GoldenRatio doesn't seem to be an algebraic element
```

After fixing:
```
>>> from sympy import *
>>> x,y = symbols('x y')
>>> eq1 = x + y + 1
>>> eq2 = x + GoldenRatio
>>> solve([eq1, eq2], x, y)
{x: -GoldenRatio, y: -1 + GoldenRatio}
```

#### Other comments
GoldenRatio is the number symbol treated as an algebraic expression as `(x**2 - x - 1)
`
TribonacciConstant is the number symbol treated as an algebraic expression as `(x**3 - x**2 - x - 1)
`
#### Release Notes

<!-- Write the release notes for this release below. See
https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more information
on how to write release notes. The bot will check your release notes
automatically to see if they are formatted correctly. -->

<!-- BEGIN RELEASE NOTES -->
* polys
  * Added check for expressions containing GoldenRatio and TribonacciConstant
<!-- END RELEASE NOTES -->

Problem statement:
Polynomial solve with GoldenRatio causes Traceback
Found during issue 11538 investigation. The GoldenRatio::NumberSymbol is the only NumberSymbol currently treated as an algebraic expression. However when solve is called on the GoldenRatio a Traceback occurs where GoldenRatio is not being treated algebraically. 

```
Python 2.7.12 (v2.7.12:d33e0cf91556, Jun 27 2016, 15:19:22) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sympy
>>> x,y=sympy.symbols('x y')
>>> e1=x+y+1
>>> e2=x+sympy.GoldenRatio
>>> sympy.solve([e1,e2],x,y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "sympy\solvers\solvers.py", line 1053, in solve
    solution = _solve_system(f, symbols, **flags)
  File "sympy\solvers\solvers.py", line 1660, in _solve_system
    poly = g.as_poly(*symbols, extension=True)
  File "sympy\core\basic.py", line 699, in as_poly
    poly = Poly(self, *gens, **args)
  File "sympy\polys\polytools.py", line 89, in __new__
    return cls._from_expr(rep, opt)
  File "sympy\polys\polytools.py", line 200, in _from_expr
    return cls._from_dict(rep, opt)
  File "sympy\polys\polytools.py", line 144, in _from_dict
    domain, rep = construct_domain(rep, opt=opt)
  File "sympy\polys\constructor.py", line 238, in construct_domain
    result = _construct_simple(coeffs, opt)
  File "sympy\polys\constructor.py", line 45, in _construct_simple
    domain, result = _construct_algebraic(coeffs, opt)
  File "sympy\polys\constructor.py", line 93, in _construct_algebraic
    g, span, H = primitive_element(exts, ex=True, polys=True)
  File "sympy\polys\numberfields.py", line 857, in primitive_element
    f = minpoly(ext, y)
  File "sympy\polys\numberfields.py", line 657, in minimal_polynomial
    result = _minpoly_compose(ex, x, dom)
  File "sympy\polys\numberfields.py", line 578, in _minpoly_compose
    raise NotAlgebraic("%s doesn't seem to be an algebraic element" % ex)
sympy.polys.polyerrors.NotAlgebraic: GoldenRatio doesn't seem to be an algebraic element
```

Hints from issue discussion:
It seems that `GoldenRatio` should be treated in the same way as `I` in `_minpoly_compse`. So, the following should be added:

```
    if ex is GoldenRatio:
        return x**2 - x - 1
```

I think in general it shouldn't assume that `is_algebraic` means that it can find its minimal polynomial. It should check more directly for the types of expressions it can work with, rather than blacklisting.

Commit message: added goldenratio check

Patch to review:
diff --git a/sympy/polys/numberfields.py b/sympy/polys/numberfields.py
index ff501a91e026..b0d7132f6be5 100644
--- a/sympy/polys/numberfields.py
+++ b/sympy/polys/numberfields.py
@@ -3,7 +3,7 @@
 from __future__ import print_function, division
 
 from sympy import (
-    S, Rational, AlgebraicNumber,
+    S, Rational, AlgebraicNumber, GoldenRatio,
     Add, Mul, sympify, Dummy, expand_mul, I, pi
 )
 from sympy.core.compatibility import reduce
@@ -517,6 +517,8 @@ def _minpoly_compose(ex, x, dom):
     if ex is I:
         _, factors = factor_list(x**2 + 1, x, domain=dom)
         return x**2 + 1 if len(factors) == 1 else x - I
+    if ex is GoldenRatio:
+        return x**2 - x - 1
     if hasattr(dom, 'symbols') and ex in dom.symbols:
         return x - ex
 
diff --git a/sympy/solvers/tests/test_solvers.py b/sympy/solvers/tests/test_solvers.py
index a07f2d6ddecf..2a8a3babe1b8 100644
--- a/sympy/solvers/tests/test_solvers.py
+++ b/sympy/solvers/tests/test_solvers.py
@@ -5,7 +5,7 @@
     erfcinv, exp, im, log, pi, re, sec, sin,
     sinh, solve, solve_linear, sqrt, sstr, symbols, sympify, tan, tanh,
     root, atan2, arg, Mul, SparseMatrix, ask, Tuple, nsolve, oo,
-    E, cbrt, denom, Add, Piecewise)
+    E, cbrt, denom, Add, Piecewise, GoldenRatio)
 
 from sympy.core.function import nfloat
 from sympy.solvers import solve_linear_system, solve_linear_system_LU, \
@@ -2131,3 +2131,9 @@ def test_issue_17949():
     assert solve(exp(-x+x**2), x) == []
     assert solve(exp(+x-x**2), x) == []
     assert solve(exp(-x-x**2), x) == []
+
+
+def test_issue_11553():
+    eq1 = x + y + 1
+    eq2 = x + GoldenRatio
+    assert solve([eq1, eq2], x, y) == {x: -GoldenRatio, y: -1 + GoldenRatio}


Code review comments:
diff_hunk: @@ -517,6 +517,8 @@ def _minpoly_compose(ex, x, dom):
     if ex is I:
         _, factors = factor_list(x**2 + 1, x, domain=dom)
         return x**2 + 1 if len(factors) == 1 else x - I
+    if ex is GoldenRatio:
+        return x**2 - x - 1
path: sympy/polys/numberfields.py
text: @user1:
I think we need the same factorization check as above with `I` to see if phi is already included in the domain.

diff_hunk: @@ -517,6 +517,8 @@ def _minpoly_compose(ex, x, dom):
     if ex is I:
         _, factors = factor_list(x**2 + 1, x, domain=dom)
         return x**2 + 1 if len(factors) == 1 else x - I
+    if ex is GoldenRatio:
+        return x**2 - x - 1
path: sympy/polys/numberfields.py
text: @user1:
Maybe this should be handled in the same way as `I`: It `GoldenRatio` is an element of `dom`, then `x**2 - x - 1` splits into two linear factors over `dom` and the minimal polynomial is one them.