Skip to content
This repository was archived by the owner on Feb 1, 2023. It is now read-only.

Commit ed7c4a3

Browse files
author
Release Manager
committed
Trac #30605: improve cone containment tests
If `K` is a polyhedral cone, the test `x in K` only supports `x` with rational coordinates. It is desirable in many cases to perform the same test with irrational numbers as well. This will simplify the implementation in ticket #29169. URL: https://trac.sagemath.org/30605 Reported by: mjo Ticket author(s): Michael Orlitzky Reviewer(s): Jonathan Kliem
2 parents ad0f8e0 + 7ea2dd8 commit ed7c4a3

File tree

3 files changed

+110
-39
lines changed

3 files changed

+110
-39
lines changed

build/pkgs/configure/checksums.ini

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
tarball=configure-VERSION.tar.gz
2-
sha1=384646584233b2b43d67518772f298064ef46887
3-
md5=82a3a0b22d5bb54dde5eba74356e5c73
4-
cksum=462963871
2+
sha1=0844b6fc043ed89d8cc0d1ffd32ab38d3e2d355a
3+
md5=22f22483c1da51c1cef22833e3ec82ea
4+
cksum=1843480734
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
7be0559bbb823f318412c21e720bf91710ffac12
1+
e90b2d71aab2289a07c3e04c41fd536001faa1d2

src/sage/geometry/cone.py

Lines changed: 106 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@
209209
from sage.matrix.all import column_matrix, matrix, MatrixSpace
210210
from sage.misc.all import cached_method, flatten, latex
211211
from sage.modules.all import span, vector, VectorSpace
212-
from sage.rings.all import QQ, RR, ZZ
212+
from sage.rings.all import QQ, ZZ
213213
from sage.structure.all import SageObject, parent
214214
from sage.structure.richcmp import richcmp_method, richcmp
215215
from ppl import (C_Polyhedron, Generator_System, Constraint_System,
@@ -526,47 +526,85 @@ def _ambient_space_point(body, data):
526526
527527
OUTPUT:
528528
529-
- integral, rational or numeric point of the ambient space of ``body``
530-
if ``data`` were successfully interpreted in such a way, otherwise a
531-
``TypeError`` exception is raised
529+
An integral, rational, real algebraic, or numeric point of the
530+
ambient space of ``body`` is returned if ``data`` were
531+
successfully interpreted in such a way. A ``TypeError`` is raised
532+
otherwise.
532533
533534
TESTS::
534535
535536
sage: from sage.geometry.cone import _ambient_space_point
536537
sage: c = Cone([(1,0), (0,1)])
537538
sage: _ambient_space_point(c, [1,1])
538539
N(1, 1)
540+
sage: _ambient_space_point(c, vector(ZZ,[1,1]))
541+
N(1, 1)
539542
sage: _ambient_space_point(c, c.dual_lattice()([1,1]))
540543
Traceback (most recent call last):
541544
...
542545
TypeError: the point M(1, 1) and
543546
2-d cone in 2-d lattice N have incompatible lattices
544547
sage: _ambient_space_point(c, [1,1/3])
545548
(1, 1/3)
549+
sage: _ambient_space_point(c, vector(QQ,[1,1/3]))
550+
(1, 1/3)
546551
sage: _ambient_space_point(c, [1/2,1/sqrt(3)])
547-
(0.500000000000000, 0.577350269189626)
552+
(1/2, 0.5773502691896258?)
553+
sage: _ambient_space_point(c, vector(AA,[1/2,1/sqrt(3)]))
554+
(1/2, 0.5773502691896258?)
548555
sage: _ambient_space_point(c, [1,1,3])
549556
Traceback (most recent call last):
550557
...
551558
TypeError: [1, 1, 3] does not represent a valid point
552-
in the ambient space of 2-d cone in 2-d lattice N
559+
in the ambient space of 2-d cone in 2-d lattice N
560+
sage: _ambient_space_point(c, vector(ZZ,[1,1,3]))
561+
Traceback (most recent call last):
562+
...
563+
TypeError: (1, 1, 3) does not represent a valid point
564+
in the ambient space of 2-d cone in 2-d lattice N
565+
566+
Ensure that transcendental elements can, at the very least, be
567+
represented numerically::
568+
569+
sage: from sage.geometry.cone import _ambient_space_point
570+
sage: c = Cone([(1,0), (0,1)])
571+
sage: _ambient_space_point(c, [1, pi])
572+
(1.00000000000000, 3.14159265358979)
573+
sage: _ambient_space_point(c, vector(SR,[1, pi]))
574+
(1.00000000000000, 3.14159265358979)
575+
553576
"""
577+
from sage.rings.all import AA, RR
578+
554579
L = body.lattice()
555-
try: # to make a lattice element...
556-
return L(data)
557-
except TypeError:
558-
# Special treatment for toric lattice elements
559-
if is_ToricLattice(parent(data)):
560-
raise TypeError("the point %s and %s have incompatible "
561-
"lattices" % (data, body))
562-
try: # ... or an exact point...
563-
return L.base_extend(QQ)(data)
564-
except TypeError:
565-
pass
566-
try: # ... or at least a numeric one
567-
return L.base_extend(RR)(data)
568-
except TypeError:
569-
pass
580+
581+
def try_base_extend(ring):
582+
# Factor out the "try this ring..." code that's repeated four
583+
# times.
584+
try:
585+
return L.base_extend(ring)(data)
586+
except TypeError:
587+
pass
588+
except ValueError as ex:
589+
if str(ex).startswith("Cannot coerce"):
590+
pass
591+
592+
# Special treatment for toric lattice elements
593+
p = try_base_extend(ZZ)
594+
if p is not None:
595+
return p
596+
if is_ToricLattice(parent(data)):
597+
raise TypeError("the point %s and %s have incompatible "
598+
"lattices" % (data, body))
599+
600+
# If we don't have a lattice element, try successively
601+
# less-desirable ambient spaces until (as a last resort) we
602+
# attempt a numerical representation.
603+
for ring in [QQ, AA, RR]:
604+
p = try_base_extend(ring)
605+
if p is not None:
606+
return p
607+
570608
# Raise TypeError with our own message
571609
raise TypeError("%s does not represent a valid point in the ambient "
572610
"space of %s" % (data, body))
@@ -1546,34 +1584,67 @@ def _contains(self, point, region='whole cone'):
15461584
This function is called by :meth:`__contains__` and :meth:`contains`
15471585
to ensure the same call depth for warning messages.
15481586
1587+
By default, a point on the boundary of the cone is considered
1588+
part of the cone. If you want to test whether the
1589+
**interior** of the cone contains the point, you need to pass
1590+
the optional argument ``'interior'``. If you want to test
1591+
whether the **relative interior** of the cone contains the
1592+
point, you need to pass the optional argument
1593+
``'relative_interior'``.
1594+
1595+
.. WARNING::
1596+
1597+
The boundary of a closed convex cone is determined by a
1598+
set of inequalities. If your ``point`` has entries in an
1599+
inexact ring, it will sometimes be impossible to say (with
1600+
confidence) if that point lies on the boundary of the cone
1601+
or slightly inside it.
1602+
15491603
INPUT:
15501604
1551-
- ``point`` -- anything. An attempt will be made to convert it into a
1552-
single element of the ambient space of ``self``. If it fails,
1553-
``False`` is returned;
1605+
- ``point`` -- anything; an attempt will be made to convert it
1606+
into an element compatible with the ambient space of ``self``.
15541607
1555-
- ``region`` -- string. Can be either 'whole cone' (default),
1556-
'interior', or 'relative interior'. By default, a point on
1557-
the boundary of the cone is considered part of the cone. If
1558-
you want to test whether the **interior** of the cone
1559-
contains the point, you need to pass the optional argument
1560-
``'interior'``. If you want to test whether the **relative
1561-
interior** of the cone contains the point, you need to pass
1562-
the optional argument ``'relative_interior'``.
1608+
- ``region`` -- a string (default: 'whole cone'); can be
1609+
either 'whole cone', 'interior', or 'relative interior'.
15631610
15641611
OUTPUT:
15651612
1566-
- ``True`` if ``point`` is contained in the specified ``region`` of
1567-
``self``, ``False`` otherwise.
1613+
``True`` is returned if ``point`` is contained in the
1614+
specified ``region`` of ``self``. ``False`` is returned
1615+
otherwise, in particular when ``point`` is incompatible with
1616+
the ambient space.
15681617
1569-
Raises a ``ValueError`` if ``region`` is not one of the
1618+
A ``ValueError`` is raised if ``region`` is not one of the
15701619
three allowed values.
15711620
15721621
TESTS::
15731622
15741623
sage: c = Cone([(1,0), (0,1)])
15751624
sage: c._contains((1,1))
15761625
True
1626+
1627+
We can test vectors with irrational components::
1628+
1629+
sage: c = Cone([(1,0), (0,1)])
1630+
sage: c._contains((1,sqrt(2)))
1631+
True
1632+
sage: c._contains(vector(SR, [1,pi]))
1633+
True
1634+
1635+
Ensure that complex vectors are not contained in a real cone::
1636+
1637+
sage: c = Cone([(1,0), (0,1)])
1638+
sage: c._contains((1,I))
1639+
False
1640+
sage: c._contains(vector(QQbar,[1,I]))
1641+
False
1642+
1643+
And we refuse to coerce elements of another lattice into ours::
1644+
1645+
sage: c = Cone([(1,0), (0,1)])
1646+
sage: c._contains(c.dual().ray(0))
1647+
False
15771648
"""
15781649
try:
15791650
point = _ambient_space_point(self, point)

0 commit comments

Comments
 (0)