Skip to content

Commit e9b9d32

Browse files
author
Release Manager
committed
gh-38291: Implement a custom class for tropical polynomials <!-- ^ Please provide a concise and informative title. --> <!-- ^ Don't put issue numbers in the title, do this in the PR description below. --> <!-- ^ For example, instead of "Fixes #12345" use "Introduce new method to calculate 1 + 2". --> <!-- v Describe your changes below in detail. --> <!-- v Why is this change required? What problem does it solve? --> <!-- v If this PR resolves an open issue, please link to it here. For example, "Fixes #12345". --> This pull request introduces some new class for handling tropical polynomials and its related functionality. ### Summary of changes: 1. Added a new class: `TropicalPolynomialSemiring` as a parent of univariate tropical polynomials and incorporated this class into the `PolynomialRing` constructor. 2. Added a new class: `TropicalPolynomial` as an element of univariate tropical polynomials, which include methods like: - `roots`: return the list of tropical roots, counted with multiplicity - `splif_form`: return the tropical polynomial which has the same roots, but which can be reduced to its linear factors - `factor`: perform factorization - `piecewise_function`: return the tropical polynomial function - `plot`: plotting the tropical polynomial function 3. Added a new class: `TropicalMPolynomialSemiring` as a parent of multivariate tropical polynomials and incorporated this class into the `PolynomialRing` constructor. 4. Added a new class: `TropicalMPolynomial` as an element of multivariate tropical polynomials, which include methods like: - `plot3d`: return the 3d plot of tropical polynomials in two variables - `tropical_variety`: find tropical variety for any multivariate tropical polynomials 5. Added a new class: `TropicalVariety` and its subclass `TropicalCurve` and `TropicalSurface` to handle the result of `tropical_variety()` of multivariate tropical polynomials. The `TropicalVariety` include methods like: - `__init__`: calculation of tropical variety - `dimension`: return the dimension of tropical variety - `number_of_components`: return the number of components that make up this tropical variety - `components`: show all the components of this tropical variety - `_components_intersection`: return the intersection of three or more components 6. Implement the `plot` method inside the two subclasses, `TropicalCurve` and `TropicalSurface`. Fixes #37962. CC: @tscrim ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [ ] The title is concise and informative. - [ ] The description explains in detail what this PR is about. - [ ] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - #12345: short description why this is a dependency --> <!-- - #34567: ... --> URL: #38291 Reported by: Verrel Rievaldo Wijaya Reviewer(s): Travis Scrimshaw, Verrel Rievaldo Wijaya
2 parents 8ba0b84 + dceaa1e commit e9b9d32

File tree

10 files changed

+2920
-13
lines changed

10 files changed

+2920
-13
lines changed

src/doc/en/reference/polynomial_rings/index.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ Infinite Polynomial Rings
6262
sage/rings/polynomial/symmetric_ideal
6363
sage/rings/polynomial/symmetric_reduction
6464

65+
Tropical Polynomials
66+
--------------------
67+
68+
.. toctree::
69+
:maxdepth: 1
70+
71+
sage/rings/semirings/tropical_polynomial
72+
sage/rings/semirings/tropical_mpolynomial
73+
sage/rings/semirings/tropical_variety
74+
6575
Boolean Polynomials
6676
-------------------
6777

src/doc/en/reference/references/index.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,9 @@ REFERENCES:
857857
.. [BrHu2019] Petter Brändén, June Huh. *Lorentzian polynomials*.
858858
Ann. Math. (2) 192, No. 3, 821-891 (2020).
859859
:arxiv:`1902.03719`, :doi:`10.4007/annals.2020.192.3.4`.
860+
861+
.. [Bru2014] Erwan Brugalle and Kristin Shaw. *A bit of tropical geometry*.
862+
Amer. Math. Monthly, 121(7):563-589, 2014.
860863
861864
.. [BHNR2004] \S. Brlek, S. Hamel, M. Nivat, C. Reutenauer, On the
862865
Palindromic Complexity of Infinite Words,
@@ -2612,6 +2615,10 @@ REFERENCES:
26122615
Wehler K3 Surfaces over finite fields*. New Zealand Journal
26132616
of Mathematics 45 (2015), 19–31.
26142617
2618+
.. [Fil2017] Ivana Filipan, *An Invitation to Combinatorial Tropical Geometry*.
2619+
Conference: 1st Croatian Combinatorial Days. 2017.
2620+
:doi:`10.5592/CO/CCD.2016.05`.
2621+
26152622
.. [FIV2012] \H. Fournier, A. Ismail, and A. Vigneron. *Computing the Gromov
26162623
hyperbolicity of a discrete metric space*. 2012.
26172624
:arxiv:`1210.3323`.

src/sage/rings/polynomial/multi_polynomial.pyx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2665,7 +2665,7 @@ cdef class MPolynomial(CommutativePolynomial):
26652665

26662666
if gens:
26672667
# substituting all variables (in a polynomial ring with variables) with 0
2668-
d = {str(gen): 0 for gen in gens}
2668+
d = {str(gen): self.base_ring().zero() for gen in gens}
26692669
tester.assertEqual(self.subs(**d).parent(), self.parent().base_ring())
26702670

26712671
# substituting all variables (in a polynomial ring with variables)
@@ -2678,7 +2678,7 @@ cdef class MPolynomial(CommutativePolynomial):
26782678

26792679
if len(gens) > 1:
26802680
# substituting one variable (in a polynomial ring with variables) with 0
2681-
d = {str(gens[0]): 0}
2681+
d = {str(gens[0]): self.base_ring().zero()}
26822682
tester.assertEqual(self.subs(**d).parent(), self.parent())
26832683

26842684
# test error checking: partial substitution by elements

src/sage/rings/polynomial/multi_polynomial_element.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,14 @@ def __call__(self, *x, **kwds):
176176
K = x[0].parent()
177177
except AttributeError:
178178
K = self.parent().base_ring()
179-
y = K(0)
179+
try:
180+
y = K.zero()
181+
one = K.one()
182+
except (AttributeError, RuntimeError):
183+
y = K(0)
184+
one = K(1)
180185
for m, c in self.element().dict().items():
181-
y += c * prod(v ** e for v, e in zip(x, m) if e)
186+
y += c * prod((v ** e for v, e in zip(x, m) if e), one)
182187
return y
183188

184189
def _richcmp_(self, right, op):

src/sage/rings/polynomial/polydict.pyx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,9 @@ cdef class PolyDict:
800800
ring = self.__repn[E[0]].parent()
801801
pos_one = ring.one()
802802
neg_one = -pos_one
803-
except AttributeError:
803+
except (AttributeError, ArithmeticError):
804+
# AritchmeticError occurs when self.__repn[E[0]] is a tropical
805+
# semiring element
804806
# probably self.__repn[E[0]] is not a ring element
805807
pos_one = 1
806808
neg_one = -1
@@ -901,7 +903,9 @@ cdef class PolyDict:
901903
ring = self.__repn[E[0]].parent()
902904
pos_one = ring.one()
903905
neg_one = -pos_one
904-
except AttributeError:
906+
except (AttributeError, ArithmeticError):
907+
# AritchmeticError occurs when self.__repn[E[0]] is a tropical
908+
# semiring element
905909
# probably self.__repn[E[0]] is not a ring element
906910
pos_one = 1
907911
neg_one = -1

src/sage/rings/polynomial/polynomial_element.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6051,7 +6051,7 @@ cdef class Polynomial(CommutativePolynomial):
60516051
60526052
- Naqi Jaffery (2006-01-24): examples
60536053
"""
6054-
return not self.is_zero() and self[self.degree()] == 1
6054+
return not self.is_zero() and self[self.degree()] == self.base_ring().one()
60556055

60566056
def is_unit(self):
60576057
r"""

src/sage/rings/polynomial/polynomial_ring_constructor.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ def PolynomialRing(base_ring, *args, **kwds):
537537
sage: PolynomialRing(4)
538538
Traceback (most recent call last):
539539
...
540-
TypeError: base_ring 4 must be a ring
540+
TypeError: base_ring 4 must be a ring or the tropical semiring
541541
sage: PolynomialRing(QQ, -1)
542542
Traceback (most recent call last):
543543
...
@@ -622,8 +622,9 @@ def PolynomialRing(base_ring, *args, **kwds):
622622
sage: R.<x,y> = PolynomialRing(RIF,2)
623623
sage: TestSuite(R).run(skip=['_test_elements', '_test_elements_eq_transitive'])
624624
"""
625-
if base_ring not in Rings():
626-
raise TypeError("base_ring {!r} must be a ring".format(base_ring))
625+
from sage.rings.semirings.tropical_semiring import TropicalSemiring
626+
if base_ring not in Rings() and not isinstance(base_ring, TropicalSemiring):
627+
raise TypeError("base_ring {!r} must be a ring or the tropical semiring".format(base_ring))
627628

628629
n = -1 # Unknown number of variables
629630
names = None # Unknown variable names
@@ -792,7 +793,11 @@ def _single_variate(base_ring, name, sparse=None, implementation=None, order=Non
792793

793794
# Generic implementations
794795
if constructor is None:
795-
if base_ring not in _CommutativeRings:
796+
from sage.rings.semirings.tropical_semiring import TropicalSemiring
797+
if isinstance(base_ring, TropicalSemiring):
798+
from sage.rings.semirings.tropical_polynomial import TropicalPolynomialSemiring
799+
constructor = TropicalPolynomialSemiring
800+
elif base_ring not in _CommutativeRings:
796801
constructor = polynomial_ring.PolynomialRing_general
797802
elif base_ring in _CompleteDiscreteValuationRings:
798803
constructor = polynomial_ring.PolynomialRing_cdvr
@@ -804,6 +809,7 @@ def _single_variate(base_ring, name, sparse=None, implementation=None, order=Non
804809
constructor = polynomial_ring.PolynomialRing_integral_domain
805810
else:
806811
constructor = polynomial_ring.PolynomialRing_commutative
812+
807813
implementation_names = constructor._implementation_names(implementation, base_ring, sparse)
808814

809815
# Only use names which are not supported by the specialized class.
@@ -861,7 +867,11 @@ def _multi_variate(base_ring, names, sparse=None, order='degrevlex', implementat
861867

862868
if R is None and implementation == "generic":
863869
from . import multi_polynomial_ring
864-
if base_ring in _Domains:
870+
from sage.rings.semirings.tropical_semiring import TropicalSemiring
871+
if isinstance(base_ring, TropicalSemiring):
872+
from sage.rings.semirings.tropical_mpolynomial import TropicalMPolynomialSemiring
873+
constructor = TropicalMPolynomialSemiring
874+
elif base_ring in _Domains:
865875
constructor = multi_polynomial_ring.MPolynomialRing_polydict_domain
866876
else:
867877
constructor = multi_polynomial_ring.MPolynomialRing_polydict
@@ -1024,4 +1034,4 @@ def BooleanPolynomialRing_constructor(n=None, names=None, order='lex'):
10241034

10251035
############################################################################
10261036
# END (Factory function for making polynomial rings)
1027-
############################################################################
1037+
############################################################################

0 commit comments

Comments
 (0)