passagemath-polyhedra 10.6.31rc3__cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-polyhedra might be problematic. Click here for more details.
- passagemath_polyhedra-10.6.31rc3.dist-info/METADATA +367 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/METADATA.bak +369 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/RECORD +206 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +6 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_polyhedra.libs/libgmp-6e109695.so.10.5.0 +0 -0
- passagemath_polyhedra.libs/libgomp-e985bcbb.so.1.0.0 +0 -0
- sage/all__sagemath_polyhedra.py +50 -0
- sage/game_theory/all.py +8 -0
- sage/game_theory/catalog.py +6 -0
- sage/game_theory/catalog_normal_form_games.py +923 -0
- sage/game_theory/cooperative_game.py +844 -0
- sage/game_theory/matching_game.py +1181 -0
- sage/game_theory/normal_form_game.py +2697 -0
- sage/game_theory/parser.py +275 -0
- sage/geometry/all__sagemath_polyhedra.py +22 -0
- sage/geometry/cone.py +6940 -0
- sage/geometry/cone_catalog.py +847 -0
- sage/geometry/cone_critical_angles.py +1027 -0
- sage/geometry/convex_set.py +1119 -0
- sage/geometry/fan.py +3743 -0
- sage/geometry/fan_isomorphism.py +389 -0
- sage/geometry/fan_morphism.py +1884 -0
- sage/geometry/hasse_diagram.py +202 -0
- sage/geometry/hyperplane_arrangement/affine_subspace.py +390 -0
- sage/geometry/hyperplane_arrangement/all.py +1 -0
- sage/geometry/hyperplane_arrangement/arrangement.py +3895 -0
- sage/geometry/hyperplane_arrangement/check_freeness.py +145 -0
- sage/geometry/hyperplane_arrangement/hyperplane.py +773 -0
- sage/geometry/hyperplane_arrangement/library.py +825 -0
- sage/geometry/hyperplane_arrangement/ordered_arrangement.py +642 -0
- sage/geometry/hyperplane_arrangement/plot.py +520 -0
- sage/geometry/integral_points.py +35 -0
- sage/geometry/integral_points_generic_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/integral_points_generic_dense.pyx +7 -0
- sage/geometry/lattice_polytope.py +5894 -0
- sage/geometry/linear_expression.py +773 -0
- sage/geometry/newton_polygon.py +767 -0
- sage/geometry/point_collection.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/point_collection.pyx +1008 -0
- sage/geometry/polyhedral_complex.py +2616 -0
- sage/geometry/polyhedron/all.py +8 -0
- sage/geometry/polyhedron/backend_cdd.py +460 -0
- sage/geometry/polyhedron/backend_cdd_rdf.py +231 -0
- sage/geometry/polyhedron/backend_field.py +347 -0
- sage/geometry/polyhedron/backend_normaliz.py +2503 -0
- sage/geometry/polyhedron/backend_number_field.py +168 -0
- sage/geometry/polyhedron/backend_polymake.py +765 -0
- sage/geometry/polyhedron/backend_ppl.py +582 -0
- sage/geometry/polyhedron/base.py +1206 -0
- sage/geometry/polyhedron/base0.py +1444 -0
- sage/geometry/polyhedron/base1.py +886 -0
- sage/geometry/polyhedron/base2.py +812 -0
- sage/geometry/polyhedron/base3.py +1845 -0
- sage/geometry/polyhedron/base4.py +1262 -0
- sage/geometry/polyhedron/base5.py +2700 -0
- sage/geometry/polyhedron/base6.py +1741 -0
- sage/geometry/polyhedron/base7.py +997 -0
- sage/geometry/polyhedron/base_QQ.py +1258 -0
- sage/geometry/polyhedron/base_RDF.py +98 -0
- sage/geometry/polyhedron/base_ZZ.py +934 -0
- sage/geometry/polyhedron/base_mutable.py +215 -0
- sage/geometry/polyhedron/base_number_field.py +122 -0
- sage/geometry/polyhedron/cdd_file_format.py +155 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/all.py +1 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +76 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +3859 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +39 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +1038 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +9 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +501 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_data_structure.pxd +207 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +102 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +2274 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +370 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +84 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +31 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +587 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +52 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +560 -0
- sage/geometry/polyhedron/constructor.py +773 -0
- sage/geometry/polyhedron/double_description.py +753 -0
- sage/geometry/polyhedron/double_description_inhomogeneous.py +564 -0
- sage/geometry/polyhedron/face.py +1060 -0
- sage/geometry/polyhedron/generating_function.py +1810 -0
- sage/geometry/polyhedron/lattice_euclidean_group_element.py +178 -0
- sage/geometry/polyhedron/library.py +3502 -0
- sage/geometry/polyhedron/misc.py +121 -0
- sage/geometry/polyhedron/modules/all.py +1 -0
- sage/geometry/polyhedron/modules/formal_polyhedra_module.py +155 -0
- sage/geometry/polyhedron/palp_database.py +447 -0
- sage/geometry/polyhedron/parent.py +1279 -0
- sage/geometry/polyhedron/plot.py +1986 -0
- sage/geometry/polyhedron/ppl_lattice_polygon.py +556 -0
- sage/geometry/polyhedron/ppl_lattice_polytope.py +1257 -0
- sage/geometry/polyhedron/representation.py +1723 -0
- sage/geometry/pseudolines.py +515 -0
- sage/geometry/relative_interior.py +445 -0
- sage/geometry/toric_plotter.py +1103 -0
- sage/geometry/triangulation/all.py +2 -0
- sage/geometry/triangulation/base.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/triangulation/base.pyx +963 -0
- sage/geometry/triangulation/data.h +147 -0
- sage/geometry/triangulation/data.pxd +4 -0
- sage/geometry/triangulation/element.py +914 -0
- sage/geometry/triangulation/functions.h +10 -0
- sage/geometry/triangulation/functions.pxd +4 -0
- sage/geometry/triangulation/point_configuration.py +2256 -0
- sage/geometry/triangulation/triangulations.h +49 -0
- sage/geometry/triangulation/triangulations.pxd +7 -0
- sage/geometry/voronoi_diagram.py +319 -0
- sage/interfaces/all__sagemath_polyhedra.py +1 -0
- sage/interfaces/polymake.py +2028 -0
- sage/numerical/all.py +13 -0
- sage/numerical/all__sagemath_polyhedra.py +11 -0
- sage/numerical/backends/all.py +1 -0
- sage/numerical/backends/all__sagemath_polyhedra.py +1 -0
- sage/numerical/backends/cvxopt_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/cvxopt_backend.pyx +1006 -0
- sage/numerical/backends/cvxopt_backend_test.py +19 -0
- sage/numerical/backends/cvxopt_sdp_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
- sage/numerical/backends/cvxpy_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/cvxpy_backend.pxd +41 -0
- sage/numerical/backends/cvxpy_backend.pyx +934 -0
- sage/numerical/backends/cvxpy_backend_test.py +13 -0
- sage/numerical/backends/generic_backend_test.py +24 -0
- sage/numerical/backends/interactivelp_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/interactivelp_backend.pxd +36 -0
- sage/numerical/backends/interactivelp_backend.pyx +1231 -0
- sage/numerical/backends/interactivelp_backend_test.py +12 -0
- sage/numerical/backends/logging_backend.py +391 -0
- sage/numerical/backends/matrix_sdp_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/matrix_sdp_backend.pxd +15 -0
- sage/numerical/backends/matrix_sdp_backend.pyx +478 -0
- sage/numerical/backends/ppl_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/ppl_backend.pyx +1126 -0
- sage/numerical/backends/ppl_backend_test.py +13 -0
- sage/numerical/backends/scip_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/scip_backend.pxd +22 -0
- sage/numerical/backends/scip_backend.pyx +1289 -0
- sage/numerical/backends/scip_backend_test.py +13 -0
- sage/numerical/interactive_simplex_method.py +5338 -0
- sage/numerical/knapsack.py +665 -0
- sage/numerical/linear_functions.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/linear_functions.pxd +31 -0
- sage/numerical/linear_functions.pyx +1648 -0
- sage/numerical/linear_tensor.py +470 -0
- sage/numerical/linear_tensor_constraints.py +448 -0
- sage/numerical/linear_tensor_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/linear_tensor_element.pxd +6 -0
- sage/numerical/linear_tensor_element.pyx +459 -0
- sage/numerical/mip.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/mip.pxd +40 -0
- sage/numerical/mip.pyx +3667 -0
- sage/numerical/sdp.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/sdp.pxd +39 -0
- sage/numerical/sdp.pyx +1433 -0
- sage/rings/all__sagemath_polyhedra.py +3 -0
- sage/rings/polynomial/all__sagemath_polyhedra.py +10 -0
- sage/rings/polynomial/omega.py +982 -0
- sage/schemes/all__sagemath_polyhedra.py +2 -0
- sage/schemes/toric/all.py +10 -0
- sage/schemes/toric/chow_group.py +1248 -0
- sage/schemes/toric/divisor.py +2082 -0
- sage/schemes/toric/divisor_class.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/schemes/toric/divisor_class.pyx +322 -0
- sage/schemes/toric/fano_variety.py +1606 -0
- sage/schemes/toric/homset.py +650 -0
- sage/schemes/toric/ideal.py +451 -0
- sage/schemes/toric/library.py +1322 -0
- sage/schemes/toric/morphism.py +1958 -0
- sage/schemes/toric/points.py +1032 -0
- sage/schemes/toric/sheaf/all.py +1 -0
- sage/schemes/toric/sheaf/constructor.py +302 -0
- sage/schemes/toric/sheaf/klyachko.py +921 -0
- sage/schemes/toric/toric_subscheme.py +905 -0
- sage/schemes/toric/variety.py +3460 -0
- sage/schemes/toric/weierstrass.py +1078 -0
- sage/schemes/toric/weierstrass_covering.py +457 -0
- sage/schemes/toric/weierstrass_higher.py +288 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.info +10 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v03 +0 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v04 +0 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v05 +1 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v06 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.info +22 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v04 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v05 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v06 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v07 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v08 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v09 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v10 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v11 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v12 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v13 +1 -0
- sage_wheels/share/reflexive_polytopes/reflexive_polytopes_2d +80 -0
- sage_wheels/share/reflexive_polytopes/reflexive_polytopes_3d +37977 -0
|
@@ -0,0 +1,886 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-polyhedra
|
|
2
|
+
r"""
|
|
3
|
+
Base class for polyhedra: Implementation of the :class:`ConvexSet_base` API
|
|
4
|
+
|
|
5
|
+
Define methods that exist for convex sets,
|
|
6
|
+
but not constructions such as dilation or product.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# ****************************************************************************
|
|
10
|
+
# Copyright (C) 2008-2012 Marshall Hampton <hamptonio@gmail.com>
|
|
11
|
+
# Copyright (C) 2011-2015 Volker Braun <vbraun.name@gmail.com>
|
|
12
|
+
# Copyright (C) 2012-2018 Frederic Chapoton
|
|
13
|
+
# Copyright (C) 2013 Andrey Novoseltsev
|
|
14
|
+
# Copyright (C) 2014-2017 Moritz Firsching
|
|
15
|
+
# Copyright (C) 2014-2019 Thierry Monteil
|
|
16
|
+
# Copyright (C) 2015 Nathann Cohen
|
|
17
|
+
# Copyright (C) 2015-2017 Jeroen Demeyer
|
|
18
|
+
# Copyright (C) 2015-2017 Vincent Delecroix
|
|
19
|
+
# Copyright (C) 2015-2018 Dima Pasechnik
|
|
20
|
+
# Copyright (C) 2015-2020 Jean-Philippe Labbe <labbe at math.huji.ac.il>
|
|
21
|
+
# Copyright (C) 2015-2021 Matthias Koeppe
|
|
22
|
+
# Copyright (C) 2016-2019 Daniel Krenn
|
|
23
|
+
# Copyright (C) 2017 Marcelo Forets
|
|
24
|
+
# Copyright (C) 2017-2018 Mark Bell
|
|
25
|
+
# Copyright (C) 2019 Julian Ritter
|
|
26
|
+
# Copyright (C) 2019-2020 Laith Rastanawi
|
|
27
|
+
# Copyright (C) 2019-2020 Sophia Elia
|
|
28
|
+
# Copyright (C) 2019-2021 Jonathan Kliem <jonathan.kliem@gmail.com>
|
|
29
|
+
#
|
|
30
|
+
# This program is free software: you can redistribute it and/or modify
|
|
31
|
+
# it under the terms of the GNU General Public License as published by
|
|
32
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
33
|
+
# (at your option) any later version.
|
|
34
|
+
# https://www.gnu.org/licenses/
|
|
35
|
+
# ****************************************************************************
|
|
36
|
+
|
|
37
|
+
from sage.structure.element import coerce_binop
|
|
38
|
+
from sage.structure.richcmp import rich_to_bool, op_NE
|
|
39
|
+
from sage.misc.abstract_method import abstract_method
|
|
40
|
+
from sage.misc.cachefunc import cached_method
|
|
41
|
+
from sage.modules.free_module_element import vector
|
|
42
|
+
from .base0 import Polyhedron_base0
|
|
43
|
+
from sage.geometry.convex_set import ConvexSet_closed
|
|
44
|
+
from sage.geometry.relative_interior import RelativeInterior
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Polyhedron_base1(Polyhedron_base0, ConvexSet_closed):
|
|
48
|
+
"""
|
|
49
|
+
Convex set methods for polyhedra,
|
|
50
|
+
but not constructions such as dilation or product.
|
|
51
|
+
|
|
52
|
+
See :class:`sage.geometry.polyhedron.base.Polyhedron_base`.
|
|
53
|
+
|
|
54
|
+
TESTS::
|
|
55
|
+
|
|
56
|
+
sage: from sage.geometry.polyhedron.base1 import Polyhedron_base1
|
|
57
|
+
sage: P = polytopes.cube()
|
|
58
|
+
sage: Q = polytopes.cube()
|
|
59
|
+
sage: Polyhedron_base1.__hash__(P) == Polyhedron_base1.__hash__(Q)
|
|
60
|
+
True
|
|
61
|
+
sage: Polyhedron_base1.__repr__(P)
|
|
62
|
+
'A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices'
|
|
63
|
+
sage: Polyhedron_base1.is_empty(P)
|
|
64
|
+
False
|
|
65
|
+
sage: Polyhedron_base1.is_universe(P)
|
|
66
|
+
False
|
|
67
|
+
sage: Polyhedron_base1.dim(P)
|
|
68
|
+
3
|
|
69
|
+
sage: Polyhedron_base1.ambient_vector_space(P)
|
|
70
|
+
Vector space of dimension 3 over Rational Field
|
|
71
|
+
sage: Polyhedron_base1.ambient_dim(P)
|
|
72
|
+
3
|
|
73
|
+
sage: Polyhedron_base1.an_affine_basis(P)
|
|
74
|
+
[A vertex at (-1, -1, -1),
|
|
75
|
+
A vertex at (1, -1, -1),
|
|
76
|
+
A vertex at (1, -1, 1),
|
|
77
|
+
A vertex at (1, 1, -1)]
|
|
78
|
+
sage: list(Polyhedron_base1._some_elements_(P))
|
|
79
|
+
[(0, 0, 0),
|
|
80
|
+
(1, -1, -1),
|
|
81
|
+
(1, 0, -1),
|
|
82
|
+
(1, 1/2, 0),
|
|
83
|
+
(1, -1/4, 1/2),
|
|
84
|
+
(0, -5/8, 3/4)]
|
|
85
|
+
sage: Polyhedron_base1.contains(P, vector([1, 1, 1]))
|
|
86
|
+
True
|
|
87
|
+
sage: Polyhedron_base1.interior_contains(P, vector([1, 1, 1]))
|
|
88
|
+
False
|
|
89
|
+
sage: Polyhedron_base1.is_relatively_open(P)
|
|
90
|
+
False
|
|
91
|
+
sage: Polyhedron_base1.relative_interior.f(P) == Polyhedron_base1.interior.f(P)
|
|
92
|
+
True
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
def __hash__(self):
|
|
96
|
+
r"""
|
|
97
|
+
TESTS::
|
|
98
|
+
|
|
99
|
+
sage: # needs sage.rings.number_field
|
|
100
|
+
sage: K.<a> = QuadraticField(2)
|
|
101
|
+
sage: p = Polyhedron(vertices=[(0, 1, a), (3, a, 5)],
|
|
102
|
+
....: rays=[(a, 2, 3), (0, 0, 1)],
|
|
103
|
+
....: base_ring=K)
|
|
104
|
+
sage: q = Polyhedron(vertices=[(3, a, 5), (0, 1, a)],
|
|
105
|
+
....: rays=[(0, 0, 1), (a, 2, 3)],
|
|
106
|
+
....: base_ring=K)
|
|
107
|
+
sage: hash(p) == hash(q)
|
|
108
|
+
True
|
|
109
|
+
"""
|
|
110
|
+
# TODO: find something better *but* fast
|
|
111
|
+
return hash((self.dim(),
|
|
112
|
+
self.ambient_dim(),
|
|
113
|
+
self.n_Hrepresentation(),
|
|
114
|
+
self.n_Vrepresentation(),
|
|
115
|
+
self.n_equations(),
|
|
116
|
+
self.n_facets(),
|
|
117
|
+
self.n_inequalities(),
|
|
118
|
+
self.n_lines(),
|
|
119
|
+
self.n_rays(),
|
|
120
|
+
self.n_vertices()))
|
|
121
|
+
|
|
122
|
+
def _repr_(self):
|
|
123
|
+
"""
|
|
124
|
+
Return a description of the polyhedron.
|
|
125
|
+
|
|
126
|
+
EXAMPLES::
|
|
127
|
+
|
|
128
|
+
sage: poly_test = Polyhedron(vertices = [[1,2,3,4],[2,1,3,4],[4,3,2,1]])
|
|
129
|
+
sage: poly_test._repr_()
|
|
130
|
+
'A 2-dimensional polyhedron in ZZ^4 defined as the convex hull of 3 vertices'
|
|
131
|
+
sage: grammar_test = Polyhedron(vertices = [[1,1,1,1,1,1]])
|
|
132
|
+
sage: grammar_test._repr_()
|
|
133
|
+
'A 0-dimensional polyhedron in ZZ^6 defined as the convex hull of 1 vertex'
|
|
134
|
+
"""
|
|
135
|
+
desc = ''
|
|
136
|
+
if self.n_vertices() == 0:
|
|
137
|
+
desc += 'The empty polyhedron'
|
|
138
|
+
else:
|
|
139
|
+
desc += 'A ' + repr(self.dim()) + '-dimensional polyhedron'
|
|
140
|
+
desc += ' in '
|
|
141
|
+
desc += self.parent()._repr_ambient_module()
|
|
142
|
+
|
|
143
|
+
if self.n_vertices() > 0:
|
|
144
|
+
desc += ' defined as the convex hull of '
|
|
145
|
+
desc += repr(self.n_vertices())
|
|
146
|
+
if self.n_vertices() == 1:
|
|
147
|
+
desc += ' vertex'
|
|
148
|
+
else:
|
|
149
|
+
desc += ' vertices'
|
|
150
|
+
|
|
151
|
+
if self.n_rays() > 0:
|
|
152
|
+
if self.n_lines() > 0:
|
|
153
|
+
desc += ", "
|
|
154
|
+
else:
|
|
155
|
+
desc += " and "
|
|
156
|
+
desc += repr(self.n_rays())
|
|
157
|
+
if self.n_rays() == 1:
|
|
158
|
+
desc += ' ray'
|
|
159
|
+
else:
|
|
160
|
+
desc += ' rays'
|
|
161
|
+
|
|
162
|
+
if self.n_lines() > 0:
|
|
163
|
+
if self.n_rays() > 0:
|
|
164
|
+
desc += ", "
|
|
165
|
+
else:
|
|
166
|
+
desc += " and "
|
|
167
|
+
desc += repr(self.n_lines())
|
|
168
|
+
if self.n_lines() == 1:
|
|
169
|
+
desc += ' line'
|
|
170
|
+
else:
|
|
171
|
+
desc += ' lines'
|
|
172
|
+
|
|
173
|
+
return desc
|
|
174
|
+
|
|
175
|
+
def _richcmp_(self, other, op):
|
|
176
|
+
"""
|
|
177
|
+
Compare ``self`` and ``other``.
|
|
178
|
+
|
|
179
|
+
INPUT:
|
|
180
|
+
|
|
181
|
+
- ``other`` -- a polyhedron
|
|
182
|
+
|
|
183
|
+
OUTPUT:
|
|
184
|
+
|
|
185
|
+
If ``other`` is a polyhedron, then the comparison
|
|
186
|
+
operator "less or equal than" means "is contained in", and
|
|
187
|
+
"less than" means "is strictly contained in".
|
|
188
|
+
|
|
189
|
+
EXAMPLES::
|
|
190
|
+
|
|
191
|
+
sage: P = Polyhedron(vertices=[(1,0), (0,1)], rays=[(1,1)])
|
|
192
|
+
sage: Q = Polyhedron(vertices=[(1,0), (0,1)])
|
|
193
|
+
sage: P >= Q
|
|
194
|
+
True
|
|
195
|
+
sage: Q <= P
|
|
196
|
+
True
|
|
197
|
+
sage: P == P
|
|
198
|
+
True
|
|
199
|
+
|
|
200
|
+
The polytope ``Q`` is strictly contained in ``P``::
|
|
201
|
+
|
|
202
|
+
sage: P > Q
|
|
203
|
+
True
|
|
204
|
+
sage: P < Q
|
|
205
|
+
False
|
|
206
|
+
sage: P == Q
|
|
207
|
+
False
|
|
208
|
+
|
|
209
|
+
Test that we have fixed a problem revealed in :issue:`31701`,
|
|
210
|
+
where neither of the two polyhedra contains the other::
|
|
211
|
+
|
|
212
|
+
sage: P = Polyhedron(vertices=[(1, 1), (0, 0), (1, 2)])
|
|
213
|
+
sage: Q = Polyhedron(vertices=[(1, 2), (0, 0), (0, 2)])
|
|
214
|
+
sage: Q < P
|
|
215
|
+
False
|
|
216
|
+
sage: P > Q
|
|
217
|
+
False
|
|
218
|
+
"""
|
|
219
|
+
if self.Vrepresentation() is None or other.Vrepresentation() is None:
|
|
220
|
+
raise RuntimeError('some V representation is missing')
|
|
221
|
+
# make sure deleted polyhedra are not used in cache
|
|
222
|
+
|
|
223
|
+
if self.ambient_dim() != other.ambient_dim():
|
|
224
|
+
return op == op_NE
|
|
225
|
+
|
|
226
|
+
c0 = self._is_subpolyhedron(other)
|
|
227
|
+
c1 = other._is_subpolyhedron(self)
|
|
228
|
+
if c0 and c1:
|
|
229
|
+
return rich_to_bool(op, 0)
|
|
230
|
+
elif c0:
|
|
231
|
+
return rich_to_bool(op, -1)
|
|
232
|
+
elif c1:
|
|
233
|
+
return rich_to_bool(op, 1)
|
|
234
|
+
else:
|
|
235
|
+
return op == op_NE
|
|
236
|
+
|
|
237
|
+
@coerce_binop
|
|
238
|
+
def _is_subpolyhedron(self, other):
|
|
239
|
+
"""
|
|
240
|
+
Test whether ``self`` is a (not necessarily strict)
|
|
241
|
+
sub-polyhedron of ``other``.
|
|
242
|
+
|
|
243
|
+
INPUT:
|
|
244
|
+
|
|
245
|
+
- ``other`` -- a :class:`Polyhedron`
|
|
246
|
+
|
|
247
|
+
OUTPUT: boolean
|
|
248
|
+
|
|
249
|
+
EXAMPLES::
|
|
250
|
+
|
|
251
|
+
sage: P = Polyhedron(vertices=[(1,0), (0,1)], rays=[(1,1)])
|
|
252
|
+
sage: Q = Polyhedron(vertices=[(1,0), (0,1)])
|
|
253
|
+
sage: P._is_subpolyhedron(Q)
|
|
254
|
+
False
|
|
255
|
+
sage: Q._is_subpolyhedron(P)
|
|
256
|
+
True
|
|
257
|
+
"""
|
|
258
|
+
return all(other_H.contains(self_V)
|
|
259
|
+
for other_H in other.Hrepresentation()
|
|
260
|
+
for self_V in self.Vrepresentation())
|
|
261
|
+
|
|
262
|
+
def is_empty(self):
|
|
263
|
+
"""
|
|
264
|
+
Test whether the polyhedron is the empty polyhedron.
|
|
265
|
+
|
|
266
|
+
OUTPUT: boolean
|
|
267
|
+
|
|
268
|
+
EXAMPLES::
|
|
269
|
+
|
|
270
|
+
sage: P = Polyhedron(vertices=[[1,0,0],[0,1,0],[0,0,1]]); P
|
|
271
|
+
A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 3 vertices
|
|
272
|
+
sage: P.is_empty(), P.is_universe()
|
|
273
|
+
(False, False)
|
|
274
|
+
|
|
275
|
+
sage: Q = Polyhedron(vertices=()); Q
|
|
276
|
+
The empty polyhedron in ZZ^0
|
|
277
|
+
sage: Q.is_empty(), Q.is_universe()
|
|
278
|
+
(True, False)
|
|
279
|
+
|
|
280
|
+
sage: R = Polyhedron(lines=[(1,0),(0,1)]); R
|
|
281
|
+
A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex and 2 lines
|
|
282
|
+
sage: R.is_empty(), R.is_universe()
|
|
283
|
+
(False, True)
|
|
284
|
+
"""
|
|
285
|
+
return self.n_Vrepresentation() == 0
|
|
286
|
+
|
|
287
|
+
def is_universe(self):
|
|
288
|
+
"""
|
|
289
|
+
Test whether the polyhedron is the whole ambient space.
|
|
290
|
+
|
|
291
|
+
OUTPUT: boolean
|
|
292
|
+
|
|
293
|
+
EXAMPLES::
|
|
294
|
+
|
|
295
|
+
sage: P = Polyhedron(vertices=[[1,0,0],[0,1,0],[0,0,1]]); P
|
|
296
|
+
A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 3 vertices
|
|
297
|
+
sage: P.is_empty(), P.is_universe()
|
|
298
|
+
(False, False)
|
|
299
|
+
|
|
300
|
+
sage: Q = Polyhedron(vertices=()); Q
|
|
301
|
+
The empty polyhedron in ZZ^0
|
|
302
|
+
sage: Q.is_empty(), Q.is_universe()
|
|
303
|
+
(True, False)
|
|
304
|
+
|
|
305
|
+
sage: R = Polyhedron(lines=[(1,0),(0,1)]); R
|
|
306
|
+
A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex and 2 lines
|
|
307
|
+
sage: R.is_empty(), R.is_universe()
|
|
308
|
+
(False, True)
|
|
309
|
+
"""
|
|
310
|
+
return self.n_Hrepresentation() == 0
|
|
311
|
+
|
|
312
|
+
def dim(self):
|
|
313
|
+
"""
|
|
314
|
+
Return the dimension of the polyhedron.
|
|
315
|
+
|
|
316
|
+
OUTPUT: -1 if the polyhedron is empty, otherwise a nonnegative integer
|
|
317
|
+
|
|
318
|
+
EXAMPLES::
|
|
319
|
+
|
|
320
|
+
sage: simplex = Polyhedron(vertices = [[1,0,0,0],[0,0,0,1],[0,1,0,0],[0,0,1,0]])
|
|
321
|
+
sage: simplex.dim()
|
|
322
|
+
3
|
|
323
|
+
sage: simplex.ambient_dim()
|
|
324
|
+
4
|
|
325
|
+
|
|
326
|
+
The empty set is a special case (:issue:`12193`)::
|
|
327
|
+
|
|
328
|
+
sage: P1=Polyhedron(vertices=[[1,0,0],[0,1,0],[0,0,1]])
|
|
329
|
+
sage: P2=Polyhedron(vertices=[[2,0,0],[0,2,0],[0,0,2]])
|
|
330
|
+
sage: P12 = P1.intersection(P2)
|
|
331
|
+
sage: P12
|
|
332
|
+
The empty polyhedron in ZZ^3
|
|
333
|
+
sage: P12.dim()
|
|
334
|
+
-1
|
|
335
|
+
"""
|
|
336
|
+
if self.n_Vrepresentation() == 0:
|
|
337
|
+
return -1 # the empty set
|
|
338
|
+
else:
|
|
339
|
+
return self.ambient_dim() - self.n_equations()
|
|
340
|
+
|
|
341
|
+
dimension = dim
|
|
342
|
+
|
|
343
|
+
def Vrepresentation_space(self):
|
|
344
|
+
r"""
|
|
345
|
+
Return the ambient free module.
|
|
346
|
+
|
|
347
|
+
OUTPUT: a free module over the base ring of dimension :meth:`ambient_dim`
|
|
348
|
+
|
|
349
|
+
EXAMPLES::
|
|
350
|
+
|
|
351
|
+
sage: poly_test = Polyhedron(vertices = [[1,0,0,0],[0,1,0,0]])
|
|
352
|
+
sage: poly_test.Vrepresentation_space()
|
|
353
|
+
Ambient free module of rank 4 over the principal ideal domain Integer Ring
|
|
354
|
+
sage: poly_test.ambient_space() is poly_test.Vrepresentation_space()
|
|
355
|
+
True
|
|
356
|
+
"""
|
|
357
|
+
return self.parent().Vrepresentation_space()
|
|
358
|
+
|
|
359
|
+
def Hrepresentation_space(self):
|
|
360
|
+
r"""
|
|
361
|
+
Return the linear space containing the H-representation vectors.
|
|
362
|
+
|
|
363
|
+
OUTPUT: a free module over the base ring of dimension :meth:`ambient_dim` + 1
|
|
364
|
+
|
|
365
|
+
EXAMPLES::
|
|
366
|
+
|
|
367
|
+
sage: poly_test = Polyhedron(vertices = [[1,0,0,0],[0,1,0,0]])
|
|
368
|
+
sage: poly_test.Hrepresentation_space()
|
|
369
|
+
Ambient free module of rank 5 over the principal ideal domain Integer Ring
|
|
370
|
+
"""
|
|
371
|
+
return self.parent().Hrepresentation_space()
|
|
372
|
+
|
|
373
|
+
ambient_space = Vrepresentation_space
|
|
374
|
+
|
|
375
|
+
def ambient_vector_space(self, base_field=None):
|
|
376
|
+
r"""
|
|
377
|
+
Return the ambient vector space.
|
|
378
|
+
|
|
379
|
+
It is the ambient free module (:meth:`Vrepresentation_space`) tensored
|
|
380
|
+
with a field.
|
|
381
|
+
|
|
382
|
+
INPUT:
|
|
383
|
+
|
|
384
|
+
- ``base_field`` -- a field (default: the fraction field of the base ring)
|
|
385
|
+
|
|
386
|
+
EXAMPLES::
|
|
387
|
+
|
|
388
|
+
sage: poly_test = Polyhedron(vertices = [[1,0,0,0],[0,1,0,0]])
|
|
389
|
+
sage: poly_test.ambient_vector_space()
|
|
390
|
+
Vector space of dimension 4 over Rational Field
|
|
391
|
+
sage: poly_test.ambient_vector_space() is poly_test.ambient()
|
|
392
|
+
True
|
|
393
|
+
|
|
394
|
+
sage: poly_test.ambient_vector_space(AA) # needs sage.rings.number_field
|
|
395
|
+
Vector space of dimension 4 over Algebraic Real Field
|
|
396
|
+
sage: poly_test.ambient_vector_space(RDF)
|
|
397
|
+
Vector space of dimension 4 over Real Double Field
|
|
398
|
+
sage: poly_test.ambient_vector_space(SR) # needs sage.symbolic
|
|
399
|
+
Vector space of dimension 4 over Symbolic Ring
|
|
400
|
+
"""
|
|
401
|
+
return self.Vrepresentation_space().vector_space(base_field=base_field)
|
|
402
|
+
|
|
403
|
+
ambient = ambient_vector_space
|
|
404
|
+
|
|
405
|
+
def ambient_dim(self):
|
|
406
|
+
r"""
|
|
407
|
+
Return the dimension of the ambient space.
|
|
408
|
+
|
|
409
|
+
EXAMPLES::
|
|
410
|
+
|
|
411
|
+
sage: poly_test = Polyhedron(vertices = [[1,0,0,0],[0,1,0,0]])
|
|
412
|
+
sage: poly_test.ambient_dim()
|
|
413
|
+
4
|
|
414
|
+
"""
|
|
415
|
+
return self.parent().ambient_dim()
|
|
416
|
+
|
|
417
|
+
def an_affine_basis(self):
|
|
418
|
+
"""
|
|
419
|
+
Return points in ``self`` that form a basis for the affine span of ``self``.
|
|
420
|
+
|
|
421
|
+
This implementation of the method :meth:`~sage.geometry.convex_set.ConvexSet_base.an_affine_basis`
|
|
422
|
+
for polytopes guarantees the following:
|
|
423
|
+
|
|
424
|
+
- All points are vertices.
|
|
425
|
+
|
|
426
|
+
- The basis is obtained by considering a maximal chain of faces
|
|
427
|
+
in the face lattice and picking for each cover relation
|
|
428
|
+
one vertex that is in the difference. Thus this method
|
|
429
|
+
is independent of the concrete realization of the polytope.
|
|
430
|
+
|
|
431
|
+
For unbounded polyhedra, the result may contain arbitrary points of ``self``,
|
|
432
|
+
not just vertices.
|
|
433
|
+
|
|
434
|
+
EXAMPLES::
|
|
435
|
+
|
|
436
|
+
sage: P = polytopes.cube()
|
|
437
|
+
sage: P.an_affine_basis()
|
|
438
|
+
[A vertex at (-1, -1, -1),
|
|
439
|
+
A vertex at (1, -1, -1),
|
|
440
|
+
A vertex at (1, -1, 1),
|
|
441
|
+
A vertex at (1, 1, -1)]
|
|
442
|
+
|
|
443
|
+
sage: P = polytopes.permutahedron(5)
|
|
444
|
+
sage: P.an_affine_basis()
|
|
445
|
+
[A vertex at (1, 2, 3, 5, 4),
|
|
446
|
+
A vertex at (2, 1, 3, 5, 4),
|
|
447
|
+
A vertex at (1, 3, 2, 5, 4),
|
|
448
|
+
A vertex at (4, 1, 3, 5, 2),
|
|
449
|
+
A vertex at (4, 2, 5, 3, 1)]
|
|
450
|
+
|
|
451
|
+
Unbounded polyhedra::
|
|
452
|
+
|
|
453
|
+
sage: p = Polyhedron(vertices=[(0, 0)], rays=[(1,0), (0,1)])
|
|
454
|
+
sage: p.an_affine_basis()
|
|
455
|
+
[A vertex at (0, 0), (1, 0), (0, 1)]
|
|
456
|
+
sage: p = Polyhedron(vertices=[(2, 1)], rays=[(1,0), (0,1)])
|
|
457
|
+
sage: p.an_affine_basis()
|
|
458
|
+
[A vertex at (2, 1), (3, 1), (2, 2)]
|
|
459
|
+
sage: p = Polyhedron(vertices=[(2, 1)], rays=[(1,0)], lines=[(0,1)])
|
|
460
|
+
sage: p.an_affine_basis()
|
|
461
|
+
[(2, 1), A vertex at (2, 0), (3, 0)]
|
|
462
|
+
"""
|
|
463
|
+
chain = self.a_maximal_chain()[1:] # we exclude the empty face
|
|
464
|
+
chain_indices = [face.ambient_V_indices() for face in chain]
|
|
465
|
+
basis_indices = []
|
|
466
|
+
|
|
467
|
+
# We use in the following that elements in ``chain_indices`` are sorted lists
|
|
468
|
+
# of V-indices.
|
|
469
|
+
# Thus for each two faces we can easily find the first Vrep that differs.
|
|
470
|
+
for dim, face in enumerate(chain_indices):
|
|
471
|
+
if dim == 0:
|
|
472
|
+
# Append the V-indices of the minimal face.
|
|
473
|
+
basis_indices.extend(face[:])
|
|
474
|
+
continue
|
|
475
|
+
|
|
476
|
+
prev_face = chain_indices[dim-1]
|
|
477
|
+
for i in range(len(prev_face)):
|
|
478
|
+
if prev_face[i] != face[i]:
|
|
479
|
+
# We found a Vrep that ``face`` has, but its facet does not.
|
|
480
|
+
basis_indices.append(face[i])
|
|
481
|
+
break
|
|
482
|
+
else: # no break
|
|
483
|
+
# ``prev_face`` contains all the same vertices as ``face`` until now.
|
|
484
|
+
# But ``face`` is guaranteed to contain one more Vrep (at least).
|
|
485
|
+
basis_indices.append(face[len(prev_face)])
|
|
486
|
+
|
|
487
|
+
Vreps = [self.Vrepresentation()[i] for i in basis_indices]
|
|
488
|
+
if all(vrep.is_vertex() for vrep in Vreps):
|
|
489
|
+
return Vreps
|
|
490
|
+
for vrep in Vreps:
|
|
491
|
+
if vrep.is_vertex():
|
|
492
|
+
vertex = vrep
|
|
493
|
+
return [vrep if vrep.is_vertex() else vertex.vector() + vrep.vector()
|
|
494
|
+
for vrep in Vreps]
|
|
495
|
+
|
|
496
|
+
@abstract_method
|
|
497
|
+
def a_maximal_chain(self):
|
|
498
|
+
r"""
|
|
499
|
+
Return a maximal chain of the face lattice in increasing order.
|
|
500
|
+
|
|
501
|
+
Subclasses must provide an implementation of this method.
|
|
502
|
+
|
|
503
|
+
EXAMPLES::
|
|
504
|
+
|
|
505
|
+
sage: from sage.geometry.polyhedron.base1 import Polyhedron_base1
|
|
506
|
+
sage: P = polytopes.cube()
|
|
507
|
+
sage: Polyhedron_base1.a_maximal_chain
|
|
508
|
+
<abstract method a_maximal_chain at ...>
|
|
509
|
+
"""
|
|
510
|
+
|
|
511
|
+
@cached_method
|
|
512
|
+
def representative_point(self):
|
|
513
|
+
"""
|
|
514
|
+
Return a "generic" point.
|
|
515
|
+
|
|
516
|
+
.. SEEALSO::
|
|
517
|
+
|
|
518
|
+
:meth:`sage.geometry.polyhedron.base.Polyhedron_base.center`.
|
|
519
|
+
|
|
520
|
+
OUTPUT:
|
|
521
|
+
|
|
522
|
+
A point as a coordinate vector. The point is chosen to be
|
|
523
|
+
interior if possible. If the polyhedron is not
|
|
524
|
+
full-dimensional, the point is in the relative interior. If
|
|
525
|
+
the polyhedron is zero-dimensional, its single point is
|
|
526
|
+
returned.
|
|
527
|
+
|
|
528
|
+
EXAMPLES::
|
|
529
|
+
|
|
530
|
+
sage: p = Polyhedron(vertices=[(3,2)], rays=[(1,-1)])
|
|
531
|
+
sage: p.representative_point()
|
|
532
|
+
(4, 1)
|
|
533
|
+
sage: p.center()
|
|
534
|
+
(3, 2)
|
|
535
|
+
|
|
536
|
+
sage: Polyhedron(vertices=[(3,2)]).representative_point()
|
|
537
|
+
(3, 2)
|
|
538
|
+
"""
|
|
539
|
+
accumulator = vector(self.base_ring(), [0]*self.ambient_dim())
|
|
540
|
+
for v in self.vertex_generator():
|
|
541
|
+
accumulator += v.vector()
|
|
542
|
+
accumulator /= self.n_vertices()
|
|
543
|
+
for r in self.ray_generator():
|
|
544
|
+
accumulator += r.vector()
|
|
545
|
+
accumulator.set_immutable()
|
|
546
|
+
return accumulator
|
|
547
|
+
|
|
548
|
+
def _some_elements_(self):
|
|
549
|
+
r"""
|
|
550
|
+
Generate some points of ``self``.
|
|
551
|
+
|
|
552
|
+
If ``self`` is empty, no points are generated; no exception will be raised.
|
|
553
|
+
|
|
554
|
+
EXAMPLES::
|
|
555
|
+
|
|
556
|
+
sage: P = polytopes.simplex()
|
|
557
|
+
sage: P.an_element() # indirect doctest
|
|
558
|
+
(1/4, 1/4, 1/4, 1/4)
|
|
559
|
+
sage: P.some_elements() # indirect doctest
|
|
560
|
+
[(1/4, 1/4, 1/4, 1/4),
|
|
561
|
+
(0, 0, 0, 1),
|
|
562
|
+
(0, 0, 1/2, 1/2),
|
|
563
|
+
(0, 1/2, 1/4, 1/4),
|
|
564
|
+
(1/2, 1/4, 1/8, 1/8)]
|
|
565
|
+
"""
|
|
566
|
+
if self.is_empty():
|
|
567
|
+
return
|
|
568
|
+
yield self.representative_point()
|
|
569
|
+
vertex_iter = iter(self.vertex_generator())
|
|
570
|
+
try:
|
|
571
|
+
p = next(vertex_iter).vector()
|
|
572
|
+
yield vector(p, immutable=True)
|
|
573
|
+
for i in range(4):
|
|
574
|
+
p = (p + next(vertex_iter).vector()) / 2
|
|
575
|
+
yield vector(p, immutable=True)
|
|
576
|
+
except StopIteration:
|
|
577
|
+
pass
|
|
578
|
+
|
|
579
|
+
def contains(self, point):
|
|
580
|
+
"""
|
|
581
|
+
Test whether the polyhedron contains the given ``point``.
|
|
582
|
+
|
|
583
|
+
.. SEEALSO::
|
|
584
|
+
|
|
585
|
+
:meth:`interior_contains`, :meth:`relative_interior_contains`.
|
|
586
|
+
|
|
587
|
+
INPUT:
|
|
588
|
+
|
|
589
|
+
- ``point`` -- coordinates of a point (an iterable)
|
|
590
|
+
|
|
591
|
+
OUTPUT: boolean
|
|
592
|
+
|
|
593
|
+
EXAMPLES::
|
|
594
|
+
|
|
595
|
+
sage: P = Polyhedron(vertices=[[1,1],[1,-1],[0,0]])
|
|
596
|
+
sage: P.contains( [1,0] )
|
|
597
|
+
True
|
|
598
|
+
sage: P.contains( P.center() ) # true for any convex set
|
|
599
|
+
True
|
|
600
|
+
|
|
601
|
+
As a shorthand, one may use the usual ``in`` operator::
|
|
602
|
+
|
|
603
|
+
sage: P.center() in P
|
|
604
|
+
True
|
|
605
|
+
sage: [-1,-1] in P
|
|
606
|
+
False
|
|
607
|
+
|
|
608
|
+
The point need not have coordinates in the same field as the
|
|
609
|
+
polyhedron::
|
|
610
|
+
|
|
611
|
+
sage: # needs sage.symbolic
|
|
612
|
+
sage: ray = Polyhedron(vertices=[(0,0)], rays=[(1,0)], base_ring=QQ)
|
|
613
|
+
sage: ray.contains([sqrt(2)/3,0]) # irrational coordinates are ok
|
|
614
|
+
True
|
|
615
|
+
sage: a = var('a')
|
|
616
|
+
sage: ray.contains([a,0]) # a might be negative!
|
|
617
|
+
False
|
|
618
|
+
sage: assume(a>0)
|
|
619
|
+
sage: ray.contains([a,0])
|
|
620
|
+
True
|
|
621
|
+
sage: ray.contains(['hello', 'kitty']) # no common ring for coordinates
|
|
622
|
+
False
|
|
623
|
+
|
|
624
|
+
The empty polyhedron needs extra care, see :issue:`10238`::
|
|
625
|
+
|
|
626
|
+
sage: empty = Polyhedron(); empty
|
|
627
|
+
The empty polyhedron in ZZ^0
|
|
628
|
+
sage: empty.contains([])
|
|
629
|
+
False
|
|
630
|
+
sage: empty.contains([0]) # not a point in QQ^0
|
|
631
|
+
False
|
|
632
|
+
sage: full = Polyhedron(vertices=[()]); full
|
|
633
|
+
A 0-dimensional polyhedron in ZZ^0 defined as the convex hull of 1 vertex
|
|
634
|
+
sage: full.contains([])
|
|
635
|
+
True
|
|
636
|
+
sage: full.contains([0])
|
|
637
|
+
False
|
|
638
|
+
|
|
639
|
+
TESTS:
|
|
640
|
+
|
|
641
|
+
Passing non-iterable objects does not cause an exception, see :issue:`32013`::
|
|
642
|
+
|
|
643
|
+
sage: None in Polyhedron(vertices=[(0,0)], rays=[(1,0)], base_ring=QQ)
|
|
644
|
+
False
|
|
645
|
+
"""
|
|
646
|
+
try:
|
|
647
|
+
p = vector(point)
|
|
648
|
+
except TypeError: # point not iterable or no common ring for elements
|
|
649
|
+
try:
|
|
650
|
+
l = len(point)
|
|
651
|
+
except TypeError:
|
|
652
|
+
return False
|
|
653
|
+
if l > 0:
|
|
654
|
+
return False
|
|
655
|
+
else:
|
|
656
|
+
p = vector(self.base_ring(), [])
|
|
657
|
+
|
|
658
|
+
if len(p) != self.ambient_dim():
|
|
659
|
+
return False
|
|
660
|
+
|
|
661
|
+
for H in self.Hrep_generator():
|
|
662
|
+
if not H.contains(p):
|
|
663
|
+
return False
|
|
664
|
+
return True
|
|
665
|
+
|
|
666
|
+
__contains__ = contains
|
|
667
|
+
|
|
668
|
+
@cached_method
|
|
669
|
+
def interior(self):
|
|
670
|
+
"""
|
|
671
|
+
The interior of ``self``.
|
|
672
|
+
|
|
673
|
+
OUTPUT:
|
|
674
|
+
|
|
675
|
+
- either an empty polyhedron or an instance of
|
|
676
|
+
:class:`~sage.geometry.relative_interior.RelativeInterior`
|
|
677
|
+
|
|
678
|
+
EXAMPLES:
|
|
679
|
+
|
|
680
|
+
If the polyhedron is full-dimensional, the result is the
|
|
681
|
+
same as that of :meth:`relative_interior`::
|
|
682
|
+
|
|
683
|
+
sage: P_full = Polyhedron(vertices=[[0,0],[1,1],[1,-1]])
|
|
684
|
+
sage: P_full.interior()
|
|
685
|
+
Relative interior of
|
|
686
|
+
a 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
|
|
687
|
+
|
|
688
|
+
If the polyhedron is of strictly smaller dimension than the
|
|
689
|
+
ambient space, its interior is empty::
|
|
690
|
+
|
|
691
|
+
sage: P_lower = Polyhedron(vertices=[[0,1], [0,-1]])
|
|
692
|
+
sage: P_lower.interior()
|
|
693
|
+
The empty polyhedron in ZZ^2
|
|
694
|
+
|
|
695
|
+
TESTS::
|
|
696
|
+
|
|
697
|
+
sage: Empty = Polyhedron(ambient_dim=2); Empty
|
|
698
|
+
The empty polyhedron in ZZ^2
|
|
699
|
+
sage: Empty.interior() is Empty
|
|
700
|
+
True
|
|
701
|
+
"""
|
|
702
|
+
if self.is_open():
|
|
703
|
+
return self
|
|
704
|
+
if not self.is_full_dimensional():
|
|
705
|
+
return self.parent().element_class(self.parent(), None, None)
|
|
706
|
+
return self.relative_interior()
|
|
707
|
+
|
|
708
|
+
def interior_contains(self, point):
|
|
709
|
+
"""
|
|
710
|
+
Test whether the interior of the polyhedron contains the
|
|
711
|
+
given ``point``.
|
|
712
|
+
|
|
713
|
+
.. SEEALSO::
|
|
714
|
+
|
|
715
|
+
:meth:`contains`, :meth:`relative_interior_contains`.
|
|
716
|
+
|
|
717
|
+
INPUT:
|
|
718
|
+
|
|
719
|
+
- ``point`` -- coordinates of a point
|
|
720
|
+
|
|
721
|
+
OUTPUT: boolean
|
|
722
|
+
|
|
723
|
+
EXAMPLES::
|
|
724
|
+
|
|
725
|
+
sage: P = Polyhedron(vertices=[[0,0],[1,1],[1,-1]])
|
|
726
|
+
sage: P.contains( [1,0] )
|
|
727
|
+
True
|
|
728
|
+
sage: P.interior_contains( [1,0] )
|
|
729
|
+
False
|
|
730
|
+
|
|
731
|
+
If the polyhedron is of strictly smaller dimension than the
|
|
732
|
+
ambient space, its interior is empty::
|
|
733
|
+
|
|
734
|
+
sage: P = Polyhedron(vertices=[[0,1],[0,-1]])
|
|
735
|
+
sage: P.contains( [0,0] )
|
|
736
|
+
True
|
|
737
|
+
sage: P.interior_contains( [0,0] )
|
|
738
|
+
False
|
|
739
|
+
|
|
740
|
+
The empty polyhedron needs extra care, see :issue:`10238`::
|
|
741
|
+
|
|
742
|
+
sage: empty = Polyhedron(); empty
|
|
743
|
+
The empty polyhedron in ZZ^0
|
|
744
|
+
sage: empty.interior_contains([])
|
|
745
|
+
False
|
|
746
|
+
"""
|
|
747
|
+
try:
|
|
748
|
+
p = vector(point)
|
|
749
|
+
except TypeError: # point not iterable or no common ring for elements
|
|
750
|
+
try:
|
|
751
|
+
l = len(point)
|
|
752
|
+
except TypeError:
|
|
753
|
+
return False
|
|
754
|
+
if l > 0:
|
|
755
|
+
return False
|
|
756
|
+
else:
|
|
757
|
+
p = vector(self.base_ring(), [])
|
|
758
|
+
|
|
759
|
+
if len(p) != self.ambient_dim():
|
|
760
|
+
return False
|
|
761
|
+
|
|
762
|
+
for H in self.Hrep_generator():
|
|
763
|
+
if not H.interior_contains(p):
|
|
764
|
+
return False
|
|
765
|
+
return True
|
|
766
|
+
|
|
767
|
+
def is_relatively_open(self):
|
|
768
|
+
r"""
|
|
769
|
+
Return whether ``self`` is relatively open.
|
|
770
|
+
|
|
771
|
+
OUTPUT: boolean
|
|
772
|
+
|
|
773
|
+
EXAMPLES::
|
|
774
|
+
|
|
775
|
+
sage: P = Polyhedron(vertices=[(1,0), (-1,0)]); P
|
|
776
|
+
A 1-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices
|
|
777
|
+
sage: P.is_relatively_open()
|
|
778
|
+
False
|
|
779
|
+
|
|
780
|
+
sage: P0 = Polyhedron(vertices=[[1, 2]]); P0
|
|
781
|
+
A 0-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex
|
|
782
|
+
sage: P0.is_relatively_open()
|
|
783
|
+
True
|
|
784
|
+
|
|
785
|
+
sage: Empty = Polyhedron(ambient_dim=2); Empty
|
|
786
|
+
The empty polyhedron in ZZ^2
|
|
787
|
+
sage: Empty.is_relatively_open()
|
|
788
|
+
True
|
|
789
|
+
|
|
790
|
+
sage: Line = Polyhedron(vertices=[(1, 1)], lines=[(1, 0)]); Line
|
|
791
|
+
A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line
|
|
792
|
+
sage: Line.is_relatively_open()
|
|
793
|
+
True
|
|
794
|
+
"""
|
|
795
|
+
return not self.inequalities()
|
|
796
|
+
|
|
797
|
+
@cached_method
|
|
798
|
+
def relative_interior(self):
|
|
799
|
+
"""
|
|
800
|
+
Return the relative interior of ``self``.
|
|
801
|
+
|
|
802
|
+
EXAMPLES::
|
|
803
|
+
|
|
804
|
+
sage: P = Polyhedron(vertices=[(1,0), (-1,0)])
|
|
805
|
+
sage: ri_P = P.relative_interior(); ri_P
|
|
806
|
+
Relative interior of
|
|
807
|
+
a 1-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices
|
|
808
|
+
sage: (0, 0) in ri_P
|
|
809
|
+
True
|
|
810
|
+
sage: (1, 0) in ri_P
|
|
811
|
+
False
|
|
812
|
+
|
|
813
|
+
sage: P0 = Polyhedron(vertices=[[1, 2]])
|
|
814
|
+
sage: P0.relative_interior() is P0
|
|
815
|
+
True
|
|
816
|
+
|
|
817
|
+
sage: Empty = Polyhedron(ambient_dim=2)
|
|
818
|
+
sage: Empty.relative_interior() is Empty
|
|
819
|
+
True
|
|
820
|
+
|
|
821
|
+
sage: Line = Polyhedron(vertices=[(1, 1)], lines=[(1, 0)])
|
|
822
|
+
sage: Line.relative_interior() is Line
|
|
823
|
+
True
|
|
824
|
+
"""
|
|
825
|
+
if self.is_relatively_open():
|
|
826
|
+
return self
|
|
827
|
+
return RelativeInterior(self)
|
|
828
|
+
|
|
829
|
+
def relative_interior_contains(self, point):
|
|
830
|
+
"""
|
|
831
|
+
Test whether the relative interior of the polyhedron
|
|
832
|
+
contains the given ``point``.
|
|
833
|
+
|
|
834
|
+
.. SEEALSO::
|
|
835
|
+
|
|
836
|
+
:meth:`contains`, :meth:`interior_contains`.
|
|
837
|
+
|
|
838
|
+
INPUT:
|
|
839
|
+
|
|
840
|
+
- ``point`` -- coordinates of a point
|
|
841
|
+
|
|
842
|
+
OUTPUT: boolean
|
|
843
|
+
|
|
844
|
+
EXAMPLES::
|
|
845
|
+
|
|
846
|
+
sage: P = Polyhedron(vertices=[(1,0), (-1,0)])
|
|
847
|
+
sage: P.contains( (0,0) )
|
|
848
|
+
True
|
|
849
|
+
sage: P.interior_contains( (0,0) )
|
|
850
|
+
False
|
|
851
|
+
sage: P.relative_interior_contains( (0,0) )
|
|
852
|
+
True
|
|
853
|
+
sage: P.relative_interior_contains( (1,0) )
|
|
854
|
+
False
|
|
855
|
+
|
|
856
|
+
The empty polyhedron needs extra care, see :issue:`10238`::
|
|
857
|
+
|
|
858
|
+
sage: empty = Polyhedron(); empty
|
|
859
|
+
The empty polyhedron in ZZ^0
|
|
860
|
+
sage: empty.relative_interior_contains([])
|
|
861
|
+
False
|
|
862
|
+
"""
|
|
863
|
+
try:
|
|
864
|
+
p = vector(point)
|
|
865
|
+
except TypeError: # point not iterable or no common ring for elements
|
|
866
|
+
try:
|
|
867
|
+
l = len(point)
|
|
868
|
+
except TypeError:
|
|
869
|
+
return False
|
|
870
|
+
if l > 0:
|
|
871
|
+
return False
|
|
872
|
+
else:
|
|
873
|
+
p = vector(self.base_ring(), [])
|
|
874
|
+
|
|
875
|
+
if len(p) != self.ambient_dim():
|
|
876
|
+
return False
|
|
877
|
+
|
|
878
|
+
for eq in self.equation_generator():
|
|
879
|
+
if not eq.contains(p):
|
|
880
|
+
return False
|
|
881
|
+
|
|
882
|
+
for ine in self.inequality_generator():
|
|
883
|
+
if not ine.interior_contains(p):
|
|
884
|
+
return False
|
|
885
|
+
|
|
886
|
+
return True
|