passagemath-polyhedra 10.6.31rc3__cp314-cp314-musllinux_1_2_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 +208 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +5 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_polyhedra.libs/libgcc_s-0cd532bd.so.1 +0 -0
- passagemath_polyhedra.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_polyhedra.libs/libgomp-8949ffbe.so.1.0.0 +0 -0
- passagemath_polyhedra.libs/libstdc++-5d72f927.so.6.0.33 +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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.so +0 -0
- sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
- sage/numerical/backends/cvxpy_backend.cpython-314-x86_64-linux-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.so +0 -0
- sage/numerical/mip.pxd +40 -0
- sage/numerical/mip.pyx +3667 -0
- sage/numerical/sdp.cpython-314-x86_64-linux-musl.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-musl.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,914 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-polyhedra
|
|
2
|
+
"""
|
|
3
|
+
A triangulation
|
|
4
|
+
|
|
5
|
+
In Sage, the
|
|
6
|
+
:class:`~sage.geometry.triangulation.point_configuration.PointConfiguration`
|
|
7
|
+
and :class:`Triangulation` satisfy a parent/element relationship. In
|
|
8
|
+
particular, each triangulation refers back to its point
|
|
9
|
+
configuration. If you want to triangulate a point configuration, you
|
|
10
|
+
should construct a point configuration first and then use one of its
|
|
11
|
+
methods to triangulate it according to your requirements. You should
|
|
12
|
+
never have to construct a :class:`Triangulation` object directly.
|
|
13
|
+
|
|
14
|
+
EXAMPLES:
|
|
15
|
+
|
|
16
|
+
First, we select the internal implementation for enumerating
|
|
17
|
+
triangulations::
|
|
18
|
+
|
|
19
|
+
sage: PointConfiguration.set_engine('internal') # to make doctests independent of TOPCOM
|
|
20
|
+
|
|
21
|
+
Here is a simple example of how to triangulate a point configuration::
|
|
22
|
+
|
|
23
|
+
sage: p = [[0,-1,-1],[0,0,1],[0,1,0], [1,-1,-1],[1,0,1],[1,1,0]]
|
|
24
|
+
sage: points = PointConfiguration(p)
|
|
25
|
+
sage: triang = points.triangulate(); triang
|
|
26
|
+
(<0,1,2,5>, <0,1,3,5>, <1,3,4,5>)
|
|
27
|
+
sage: triang.plot(axes=False) # needs sage.plot
|
|
28
|
+
Graphics3d Object
|
|
29
|
+
|
|
30
|
+
See :mod:`sage.geometry.triangulation.point_configuration` for more details.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
#*****************************************************************************
|
|
34
|
+
# Copyright (C) 2010 Volker Braun <vbraun.name@gmail.com>
|
|
35
|
+
#
|
|
36
|
+
# This program is free software: you can redistribute it and/or modify
|
|
37
|
+
# it under the terms of the GNU General Public License as published by
|
|
38
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
39
|
+
# (at your option) any later version.
|
|
40
|
+
# https://www.gnu.org/licenses/
|
|
41
|
+
#*****************************************************************************
|
|
42
|
+
|
|
43
|
+
from sage.structure.richcmp import richcmp
|
|
44
|
+
from sage.structure.element import Element
|
|
45
|
+
from sage.rings.integer_ring import ZZ
|
|
46
|
+
from sage.rings.rational_field import QQ
|
|
47
|
+
from sage.modules.free_module_element import vector
|
|
48
|
+
from sage.misc.cachefunc import cached_method
|
|
49
|
+
from sage.sets.set import Set
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
########################################################################
|
|
53
|
+
def triangulation_render_2d(triangulation, **kwds):
|
|
54
|
+
r"""
|
|
55
|
+
Return a graphical representation of a 2-d triangulation.
|
|
56
|
+
|
|
57
|
+
INPUT:
|
|
58
|
+
|
|
59
|
+
- ``triangulation`` -- a :class:`Triangulation`
|
|
60
|
+
|
|
61
|
+
- ``**kwds`` -- keywords that are passed on to the graphics primitives
|
|
62
|
+
|
|
63
|
+
OUTPUT: a 2-d graphics object
|
|
64
|
+
|
|
65
|
+
EXAMPLES::
|
|
66
|
+
|
|
67
|
+
sage: points = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
|
|
68
|
+
sage: triang = points.triangulate()
|
|
69
|
+
sage: triang.plot(axes=False, aspect_ratio=1) # indirect doctest # needs sage.plot
|
|
70
|
+
Graphics object consisting of 12 graphics primitives
|
|
71
|
+
"""
|
|
72
|
+
from sage.plot.all import point2d, line2d, polygon2d
|
|
73
|
+
points = [point.reduced_affine() for point in triangulation.point_configuration()]
|
|
74
|
+
coord = [ [p[0], p[1]] for p in points ]
|
|
75
|
+
plot_points = sum([ point2d(p,
|
|
76
|
+
zorder=2, pointsize=10, **kwds)
|
|
77
|
+
for p in coord ])
|
|
78
|
+
|
|
79
|
+
tmp_lines = []
|
|
80
|
+
for t in triangulation:
|
|
81
|
+
if len(t) >= 2:
|
|
82
|
+
tmp_lines.append([t[0], t[1]])
|
|
83
|
+
if len(t) >= 3:
|
|
84
|
+
tmp_lines.append([t[0], t[2]])
|
|
85
|
+
tmp_lines.append([t[1], t[2]])
|
|
86
|
+
all_lines = []
|
|
87
|
+
interior_lines = []
|
|
88
|
+
for l in tmp_lines:
|
|
89
|
+
if l not in all_lines:
|
|
90
|
+
all_lines.append(l)
|
|
91
|
+
else:
|
|
92
|
+
interior_lines.append(l)
|
|
93
|
+
exterior_lines = [l for l in all_lines if l not in interior_lines]
|
|
94
|
+
|
|
95
|
+
plot_interior_lines = sum([ line2d([ coord[l[0]], coord[l[1]] ],
|
|
96
|
+
zorder=1, rgbcolor=(0,1,0), **kwds)
|
|
97
|
+
for l in interior_lines ])
|
|
98
|
+
plot_exterior_lines = sum([ line2d([ coord[l[0]], coord[l[1]] ],
|
|
99
|
+
zorder=1, rgbcolor=(0,0,1), **kwds)
|
|
100
|
+
for l in exterior_lines ])
|
|
101
|
+
|
|
102
|
+
plot_triangs = sum([ polygon2d([coord[t[0]], coord[t[1]], coord[t[2]]],
|
|
103
|
+
zorder=0, rgbcolor=(0.8, 1, 0.8), **kwds)
|
|
104
|
+
for t in triangulation if len(t) >= 3 ])
|
|
105
|
+
|
|
106
|
+
return \
|
|
107
|
+
plot_points + \
|
|
108
|
+
plot_interior_lines + plot_exterior_lines + \
|
|
109
|
+
plot_triangs
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def triangulation_render_3d(triangulation, **kwds):
|
|
113
|
+
r"""
|
|
114
|
+
Return a graphical representation of a 3-d triangulation.
|
|
115
|
+
|
|
116
|
+
INPUT:
|
|
117
|
+
|
|
118
|
+
- ``triangulation`` -- a :class:`Triangulation`
|
|
119
|
+
|
|
120
|
+
- ``**kwds`` -- keywords that are passed on to the graphics primitives
|
|
121
|
+
|
|
122
|
+
OUTPUT: a 3-d graphics object
|
|
123
|
+
|
|
124
|
+
EXAMPLES::
|
|
125
|
+
|
|
126
|
+
sage: p = [[0,-1,-1],[0,0,1],[0,1,0], [1,-1,-1],[1,0,1],[1,1,0]]
|
|
127
|
+
sage: points = PointConfiguration(p)
|
|
128
|
+
sage: triang = points.triangulate()
|
|
129
|
+
sage: triang.plot(axes=False) # indirect doctest # needs sage.plot
|
|
130
|
+
Graphics3d Object
|
|
131
|
+
"""
|
|
132
|
+
from sage.plot.plot3d.all import point3d, line3d, polygon3d
|
|
133
|
+
points = [ point.reduced_affine() for point in triangulation.point_configuration() ]
|
|
134
|
+
coord = [ [p[0], p[1], p[2] ] for p in points ]
|
|
135
|
+
plot_points = sum([ point3d(p, size=15,
|
|
136
|
+
**kwds)
|
|
137
|
+
for p in coord ])
|
|
138
|
+
|
|
139
|
+
tmp_lines = []
|
|
140
|
+
for t in triangulation:
|
|
141
|
+
if len(t) >= 2:
|
|
142
|
+
tmp_lines.append([t[0], t[1]])
|
|
143
|
+
if len(t) >= 3:
|
|
144
|
+
tmp_lines.append([t[0], t[2]])
|
|
145
|
+
tmp_lines.append([t[1], t[2]])
|
|
146
|
+
if len(t) >= 4:
|
|
147
|
+
tmp_lines.append([t[0], t[3]])
|
|
148
|
+
tmp_lines.append([t[1], t[3]])
|
|
149
|
+
tmp_lines.append([t[2], t[3]])
|
|
150
|
+
all_lines = []
|
|
151
|
+
interior_lines = []
|
|
152
|
+
for l in tmp_lines:
|
|
153
|
+
if l not in all_lines:
|
|
154
|
+
all_lines.append(l)
|
|
155
|
+
else:
|
|
156
|
+
interior_lines.append(l)
|
|
157
|
+
exterior_lines = [l for l in all_lines if l not in interior_lines]
|
|
158
|
+
|
|
159
|
+
from sage.plot.plot3d.texture import Texture
|
|
160
|
+
line_int = Texture(color='darkblue', ambient=1, diffuse=0)
|
|
161
|
+
line_ext = Texture(color='green', ambient=1, diffuse=0)
|
|
162
|
+
triang_int = Texture(opacity=0.3, specular=0, shininess=0, diffuse=0, ambient=1, color='yellow')
|
|
163
|
+
triang_ext = Texture(opacity=0.6, specular=0, shininess=0, diffuse=0, ambient=1, color='green')
|
|
164
|
+
|
|
165
|
+
plot_interior_lines = sum([ line3d([ coord[l[0]], coord[l[1]] ],
|
|
166
|
+
thickness=2, texture=line_int, **kwds)
|
|
167
|
+
for l in interior_lines ])
|
|
168
|
+
plot_exterior_lines = sum([ line3d([ coord[l[0]], coord[l[1]] ],
|
|
169
|
+
thickness=3, texture=line_ext, **kwds)
|
|
170
|
+
for l in exterior_lines ])
|
|
171
|
+
|
|
172
|
+
tmp_triangs = []
|
|
173
|
+
for t in triangulation:
|
|
174
|
+
if len(t) >= 3:
|
|
175
|
+
tmp_triangs.append([t[0], t[1], t[2]])
|
|
176
|
+
if len(t) >= 4:
|
|
177
|
+
tmp_triangs.append([t[0], t[1], t[3]])
|
|
178
|
+
tmp_triangs.append([t[0], t[2], t[3]])
|
|
179
|
+
tmp_triangs.append([t[1], t[2], t[3]])
|
|
180
|
+
all_triangs = []
|
|
181
|
+
interior_triangs = []
|
|
182
|
+
for l in tmp_triangs:
|
|
183
|
+
if l not in all_triangs:
|
|
184
|
+
all_triangs.append(l)
|
|
185
|
+
else:
|
|
186
|
+
interior_triangs.append(l)
|
|
187
|
+
exterior_triangs = [l for l in all_triangs if l not in interior_triangs]
|
|
188
|
+
|
|
189
|
+
plot_interior_triangs = \
|
|
190
|
+
sum([polygon3d([coord[t[0]], coord[t[1]], coord[t[2]]],
|
|
191
|
+
texture=triang_int, **kwds)
|
|
192
|
+
for t in interior_triangs])
|
|
193
|
+
plot_exterior_triangs = \
|
|
194
|
+
sum([polygon3d([coord[t[0]], coord[t[1]], coord[t[2]]],
|
|
195
|
+
texture=triang_ext, **kwds)
|
|
196
|
+
for t in exterior_triangs])
|
|
197
|
+
|
|
198
|
+
return plot_points + \
|
|
199
|
+
plot_interior_lines + plot_exterior_lines + \
|
|
200
|
+
plot_interior_triangs + plot_exterior_triangs
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
########################################################################
|
|
204
|
+
class Triangulation(Element):
|
|
205
|
+
"""
|
|
206
|
+
A triangulation of a
|
|
207
|
+
:class:`~sage.geometry.triangulation.point_configuration.PointConfiguration`.
|
|
208
|
+
|
|
209
|
+
.. WARNING::
|
|
210
|
+
|
|
211
|
+
You should never create :class:`Triangulation` objects
|
|
212
|
+
manually. See
|
|
213
|
+
:meth:`~sage.geometry.triangulation.point_configuration.PointConfiguration.triangulate`
|
|
214
|
+
and
|
|
215
|
+
:meth:`~sage.geometry.triangulation.point_configuration.PointConfiguration.triangulations`
|
|
216
|
+
to triangulate point configurations.
|
|
217
|
+
"""
|
|
218
|
+
def __init__(self, triangulation, parent, check=True):
|
|
219
|
+
"""
|
|
220
|
+
The constructor of a ``Triangulation`` object.
|
|
221
|
+
|
|
222
|
+
Note that an internal reference to the underlying ``PointConfiguration`` is
|
|
223
|
+
kept.
|
|
224
|
+
|
|
225
|
+
INPUT:
|
|
226
|
+
|
|
227
|
+
- ``parent`` -- a
|
|
228
|
+
:class:`~sage.geometry.triangulation.point_configuration.PointConfiguration`
|
|
229
|
+
|
|
230
|
+
- ``triangulation`` -- an iterable of integers or an iterable of
|
|
231
|
+
iterables (e.g. a list of lists), specifying the maximal simplices
|
|
232
|
+
of the triangulation. In the first case, each integer specifies a simplex
|
|
233
|
+
by the correspondence :meth:`PointConfiguration.simplex_to_int`. In the second
|
|
234
|
+
case, a simplex is specified by listing the indices of the included points.
|
|
235
|
+
|
|
236
|
+
- ``check`` -- boolean; whether to perform checks that the
|
|
237
|
+
triangulation is, indeed, a triangulation of the point
|
|
238
|
+
configuration
|
|
239
|
+
|
|
240
|
+
NOTE:
|
|
241
|
+
|
|
242
|
+
Passing ``check=False`` allows you to create triangulations of
|
|
243
|
+
subsets of the points of the configuration, see
|
|
244
|
+
:meth:`~sage.geometry.triangulation.point_configuration.PointConfiguration.bistellar_flips`.
|
|
245
|
+
|
|
246
|
+
EXAMPLES::
|
|
247
|
+
|
|
248
|
+
sage: p = [[0,1],[0,0],[1,0]]
|
|
249
|
+
sage: points = PointConfiguration(p)
|
|
250
|
+
sage: from sage.geometry.triangulation.point_configuration import Triangulation
|
|
251
|
+
sage: Triangulation([(0,1,2)], points)
|
|
252
|
+
(<0,1,2>)
|
|
253
|
+
sage: Triangulation([1], points)
|
|
254
|
+
(<0,1,2>)
|
|
255
|
+
"""
|
|
256
|
+
Element.__init__(self, parent=parent)
|
|
257
|
+
self._point_configuration = parent
|
|
258
|
+
|
|
259
|
+
try:
|
|
260
|
+
triangulation = tuple(sorted( tuple(sorted(t)) for t in triangulation))
|
|
261
|
+
except TypeError:
|
|
262
|
+
triangulation = tuple( self.point_configuration().int_to_simplex(i)
|
|
263
|
+
for i in triangulation )
|
|
264
|
+
assert not check or all( len(t) == self.point_configuration().dim()+1
|
|
265
|
+
for t in triangulation)
|
|
266
|
+
self._triangulation = triangulation
|
|
267
|
+
|
|
268
|
+
def point_configuration(self):
|
|
269
|
+
"""
|
|
270
|
+
Return the point configuration underlying the triangulation.
|
|
271
|
+
|
|
272
|
+
EXAMPLES::
|
|
273
|
+
|
|
274
|
+
sage: pconfig = PointConfiguration([[0,0],[0,1],[1,0]])
|
|
275
|
+
sage: pconfig
|
|
276
|
+
A point configuration in affine 2-space over Integer Ring
|
|
277
|
+
consisting of 3 points. The triangulations of this point
|
|
278
|
+
configuration are assumed to be connected, not necessarily
|
|
279
|
+
fine, not necessarily regular.
|
|
280
|
+
sage: triangulation = pconfig.triangulate()
|
|
281
|
+
sage: triangulation
|
|
282
|
+
(<0,1,2>)
|
|
283
|
+
sage: triangulation.point_configuration()
|
|
284
|
+
A point configuration in affine 2-space over Integer Ring
|
|
285
|
+
consisting of 3 points. The triangulations of this point
|
|
286
|
+
configuration are assumed to be connected, not necessarily
|
|
287
|
+
fine, not necessarily regular.
|
|
288
|
+
sage: pconfig == triangulation.point_configuration()
|
|
289
|
+
True
|
|
290
|
+
"""
|
|
291
|
+
return self._point_configuration
|
|
292
|
+
|
|
293
|
+
def _richcmp_(self, right, op):
|
|
294
|
+
r"""
|
|
295
|
+
Compare ``self`` and ``right``.
|
|
296
|
+
|
|
297
|
+
INPUT:
|
|
298
|
+
|
|
299
|
+
- ``right`` -- a triangulation
|
|
300
|
+
|
|
301
|
+
TESTS::
|
|
302
|
+
|
|
303
|
+
sage: pc = PointConfiguration([[0,0],[0,1],[1,0]])
|
|
304
|
+
sage: t1 = pc.triangulate()
|
|
305
|
+
sage: from sage.geometry.triangulation.point_configuration import Triangulation
|
|
306
|
+
sage: t2 = Triangulation([[2,1,0]], pc)
|
|
307
|
+
sage: t1 is t2
|
|
308
|
+
False
|
|
309
|
+
sage: t1 == t2 # indirect doctest
|
|
310
|
+
True
|
|
311
|
+
sage: t1 != Triangulation(((0,1),(1,2)), pc, check=False)
|
|
312
|
+
True
|
|
313
|
+
"""
|
|
314
|
+
return richcmp(self._triangulation, right._triangulation, op)
|
|
315
|
+
|
|
316
|
+
def __iter__(self):
|
|
317
|
+
"""
|
|
318
|
+
Iterate through the simplices of the triangulation.
|
|
319
|
+
|
|
320
|
+
EXAMPLES::
|
|
321
|
+
|
|
322
|
+
sage: PointConfiguration.set_engine('internal') # to make doctests independent of TOPCOM
|
|
323
|
+
sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
|
|
324
|
+
sage: triangulation = pc.triangulate()
|
|
325
|
+
sage: iter = triangulation.__iter__()
|
|
326
|
+
sage: next(iter)
|
|
327
|
+
(1, 3, 4)
|
|
328
|
+
sage: next(iter)
|
|
329
|
+
(2, 3, 4)
|
|
330
|
+
sage: next(iter)
|
|
331
|
+
Traceback (most recent call last):
|
|
332
|
+
...
|
|
333
|
+
StopIteration
|
|
334
|
+
"""
|
|
335
|
+
yield from self._triangulation
|
|
336
|
+
|
|
337
|
+
def __getitem__(self, i):
|
|
338
|
+
"""
|
|
339
|
+
Access the point indices of the `i`-th simplex of the triangulation.
|
|
340
|
+
|
|
341
|
+
INPUT:
|
|
342
|
+
|
|
343
|
+
- ``i`` -- integer; the index of a simplex
|
|
344
|
+
|
|
345
|
+
OUTPUT:
|
|
346
|
+
|
|
347
|
+
A tuple of integers. The vertex indices of the `i`-th simplex.
|
|
348
|
+
|
|
349
|
+
EXAMPLES::
|
|
350
|
+
|
|
351
|
+
sage: PointConfiguration.set_engine('internal') # to make doctests independent of TOPCOM
|
|
352
|
+
sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
|
|
353
|
+
sage: triangulation = pc.triangulate()
|
|
354
|
+
sage: triangulation[1]
|
|
355
|
+
(2, 3, 4)
|
|
356
|
+
"""
|
|
357
|
+
return self._triangulation[i]
|
|
358
|
+
|
|
359
|
+
def __len__(self):
|
|
360
|
+
"""
|
|
361
|
+
Return the length of the triangulation.
|
|
362
|
+
|
|
363
|
+
TESTS::
|
|
364
|
+
|
|
365
|
+
sage: PointConfiguration.set_engine('internal') # to make doctests independent of TOPCOM
|
|
366
|
+
sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
|
|
367
|
+
sage: triangulation = next(pc.triangulations())
|
|
368
|
+
sage: triangulation.__len__()
|
|
369
|
+
2
|
|
370
|
+
sage: len(triangulation) # equivalent
|
|
371
|
+
2
|
|
372
|
+
"""
|
|
373
|
+
return len(self._triangulation)
|
|
374
|
+
|
|
375
|
+
def _repr_(self):
|
|
376
|
+
r"""
|
|
377
|
+
Return a string representation.
|
|
378
|
+
|
|
379
|
+
TESTS::
|
|
380
|
+
|
|
381
|
+
sage: PointConfiguration.set_engine('internal') # to make doctests independent of TOPCOM
|
|
382
|
+
sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1],[2,2]])
|
|
383
|
+
sage: t = pc.triangulations()
|
|
384
|
+
sage: next(t)._repr_()
|
|
385
|
+
'(<1,4,5>, <2,4,5>)'
|
|
386
|
+
"""
|
|
387
|
+
#s = 'A triangulation'
|
|
388
|
+
#s += ' in QQ^'+str(self.point_configuration().ambient_dim())
|
|
389
|
+
#s += ' consisting of '+str(len(self))+' simplices.'
|
|
390
|
+
s = '('
|
|
391
|
+
s += ', '.join([ '<'+','.join(map(str,t))+'>' for t in self._triangulation])
|
|
392
|
+
s += ')'
|
|
393
|
+
return s
|
|
394
|
+
|
|
395
|
+
def plot(self, **kwds):
|
|
396
|
+
r"""
|
|
397
|
+
Produce a graphical representation of the triangulation.
|
|
398
|
+
|
|
399
|
+
EXAMPLES::
|
|
400
|
+
|
|
401
|
+
sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
|
|
402
|
+
sage: triangulation = p.triangulate()
|
|
403
|
+
sage: triangulation
|
|
404
|
+
(<1,3,4>, <2,3,4>)
|
|
405
|
+
sage: triangulation.plot(axes=False) # needs sage.plot
|
|
406
|
+
Graphics object consisting of 12 graphics primitives
|
|
407
|
+
"""
|
|
408
|
+
dim = self.point_configuration().dim()
|
|
409
|
+
|
|
410
|
+
if dim == 2:
|
|
411
|
+
return triangulation_render_2d(self, **kwds)
|
|
412
|
+
|
|
413
|
+
if dim == 3:
|
|
414
|
+
return triangulation_render_3d(self, **kwds)
|
|
415
|
+
|
|
416
|
+
raise NotImplementedError('Plotting '+str(dim)+'-dimensional triangulations not implemented!')
|
|
417
|
+
|
|
418
|
+
def gkz_phi(self):
|
|
419
|
+
r"""
|
|
420
|
+
Calculate the GKZ phi vector of the triangulation.
|
|
421
|
+
|
|
422
|
+
The phi vector is a vector of length equals to the number of
|
|
423
|
+
points in the point configuration. For a fixed triangulation
|
|
424
|
+
`T`, the entry corresponding to the `i`-th point `p_i` is
|
|
425
|
+
|
|
426
|
+
.. MATH::
|
|
427
|
+
|
|
428
|
+
\phi_T(p_i) = \sum_{t\in T, t\owns p_i} Vol(t)
|
|
429
|
+
|
|
430
|
+
that is, the total volume of all simplices containing `p_i`.
|
|
431
|
+
See also [GKZ1994]_ page 220 equation 1.4.
|
|
432
|
+
|
|
433
|
+
OUTPUT: the phi vector of self
|
|
434
|
+
|
|
435
|
+
EXAMPLES::
|
|
436
|
+
|
|
437
|
+
sage: p = PointConfiguration([[0,0],[1,0],[2,1],[1,2],[0,1]])
|
|
438
|
+
sage: p.triangulate().gkz_phi()
|
|
439
|
+
(3, 1, 5, 2, 4)
|
|
440
|
+
sage: p.lexicographic_triangulation().gkz_phi()
|
|
441
|
+
(1, 3, 4, 2, 5)
|
|
442
|
+
"""
|
|
443
|
+
vec = vector(ZZ, self.point_configuration().n_points())
|
|
444
|
+
for simplex in self:
|
|
445
|
+
vol = self.point_configuration().volume(simplex)
|
|
446
|
+
for i in simplex:
|
|
447
|
+
vec[i] = vec[i] + vol
|
|
448
|
+
return vec
|
|
449
|
+
|
|
450
|
+
def enumerate_simplices(self):
|
|
451
|
+
r"""
|
|
452
|
+
Return the enumerated simplices.
|
|
453
|
+
|
|
454
|
+
OUTPUT: a tuple of integers that uniquely specifies the triangulation
|
|
455
|
+
|
|
456
|
+
EXAMPLES::
|
|
457
|
+
|
|
458
|
+
sage: pc = PointConfiguration(matrix([
|
|
459
|
+
....: [ 0, 0, 0, 0, 0, 2, 4,-1, 1, 1, 0, 0, 1, 0],
|
|
460
|
+
....: [ 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0],
|
|
461
|
+
....: [ 0, 2, 0, 0, 0, 0,-1, 0, 1, 0, 1, 0, 0, 1],
|
|
462
|
+
....: [ 0, 1, 1, 0, 0, 1, 0,-2, 1, 0, 0,-1, 1, 1],
|
|
463
|
+
....: [ 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0]
|
|
464
|
+
....: ]).columns())
|
|
465
|
+
sage: triangulation = pc.lexicographic_triangulation()
|
|
466
|
+
sage: triangulation.enumerate_simplices()
|
|
467
|
+
(1678, 1688, 1769, 1779, 1895, 1905, 2112, 2143, 2234, 2360, 2555, 2580,
|
|
468
|
+
2610, 2626, 2650, 2652, 2654, 2661, 2663, 2667, 2685, 2755, 2757, 2759,
|
|
469
|
+
2766, 2768, 2772, 2811, 2881, 2883, 2885, 2892, 2894, 2898)
|
|
470
|
+
|
|
471
|
+
You can recreate the triangulation from this list by passing
|
|
472
|
+
it to the constructor::
|
|
473
|
+
|
|
474
|
+
sage: from sage.geometry.triangulation.point_configuration import Triangulation
|
|
475
|
+
sage: Triangulation([1678, 1688, 1769, 1779, 1895, 1905, 2112, 2143,
|
|
476
|
+
....: 2234, 2360, 2555, 2580, 2610, 2626, 2650, 2652, 2654, 2661, 2663,
|
|
477
|
+
....: 2667, 2685, 2755, 2757, 2759, 2766, 2768, 2772, 2811, 2881, 2883,
|
|
478
|
+
....: 2885, 2892, 2894, 2898], pc)
|
|
479
|
+
(<1,3,4,7,10,13>, <1,3,4,8,10,13>, <1,3,6,7,10,13>, <1,3,6,8,10,13>,
|
|
480
|
+
<1,4,6,7,10,13>, <1,4,6,8,10,13>, <2,3,4,6,7,12>, <2,3,4,7,12,13>,
|
|
481
|
+
<2,3,6,7,12,13>, <2,4,6,7,12,13>, <3,4,5,6,9,12>, <3,4,5,8,9,12>,
|
|
482
|
+
<3,4,6,7,11,12>, <3,4,6,9,11,12>, <3,4,7,10,11,13>, <3,4,7,11,12,13>,
|
|
483
|
+
<3,4,8,9,10,12>, <3,4,8,10,12,13>, <3,4,9,10,11,12>, <3,4,10,11,12,13>,
|
|
484
|
+
<3,5,6,8,9,12>, <3,6,7,10,11,13>, <3,6,7,11,12,13>, <3,6,8,9,10,12>,
|
|
485
|
+
<3,6,8,10,12,13>, <3,6,9,10,11,12>, <3,6,10,11,12,13>, <4,5,6,8,9,12>,
|
|
486
|
+
<4,6,7,10,11,13>, <4,6,7,11,12,13>, <4,6,8,9,10,12>, <4,6,8,10,12,13>,
|
|
487
|
+
<4,6,9,10,11,12>, <4,6,10,11,12,13>)
|
|
488
|
+
"""
|
|
489
|
+
pc = self._point_configuration
|
|
490
|
+
return tuple( pc.simplex_to_int(t) for t in self )
|
|
491
|
+
|
|
492
|
+
def fan(self, origin=None):
|
|
493
|
+
r"""
|
|
494
|
+
Construct the fan of cones over the simplices of the triangulation.
|
|
495
|
+
|
|
496
|
+
INPUT:
|
|
497
|
+
|
|
498
|
+
- ``origin`` -- ``None`` (default) or coordinates of a
|
|
499
|
+
point. The common apex of all cones of the fan. If ``None``,
|
|
500
|
+
the triangulation must be a star triangulation and the
|
|
501
|
+
distinguished central point is used as the origin.
|
|
502
|
+
|
|
503
|
+
OUTPUT:
|
|
504
|
+
|
|
505
|
+
A :class:`~sage.geometry.fan.RationalPolyhedralFan`. The
|
|
506
|
+
coordinates of the points are shifted so that the apex of the
|
|
507
|
+
fan is the origin of the coordinate system.
|
|
508
|
+
|
|
509
|
+
.. NOTE:: If the set of cones over the simplices is not a fan, a
|
|
510
|
+
suitable exception is raised.
|
|
511
|
+
|
|
512
|
+
EXAMPLES::
|
|
513
|
+
|
|
514
|
+
sage: pc = PointConfiguration([(0,0), (1,0), (0,1), (-1,-1)], star=0, fine=True)
|
|
515
|
+
sage: triangulation = pc.triangulate()
|
|
516
|
+
sage: fan = triangulation.fan(); fan
|
|
517
|
+
Rational polyhedral fan in 2-d lattice N
|
|
518
|
+
sage: fan.is_equivalent(toric_varieties.P2().fan()) # needs palp sage.graphs
|
|
519
|
+
True
|
|
520
|
+
|
|
521
|
+
Toric diagrams (the `\ZZ_5` hyperconifold)::
|
|
522
|
+
|
|
523
|
+
sage: vertices=[(0, 1, 0), (0, 3, 1), (0, 2, 3), (0, 0, 2)]
|
|
524
|
+
sage: interior=[(0, 1, 1), (0, 1, 2), (0, 2, 1), (0, 2, 2)]
|
|
525
|
+
sage: points = vertices + interior
|
|
526
|
+
sage: pc = PointConfiguration(points, fine=True)
|
|
527
|
+
sage: triangulation = pc.triangulate()
|
|
528
|
+
sage: fan = triangulation.fan((-1,0,0)); fan
|
|
529
|
+
Rational polyhedral fan in 3-d lattice N
|
|
530
|
+
sage: fan.rays()
|
|
531
|
+
N(1, 1, 0),
|
|
532
|
+
N(1, 3, 1),
|
|
533
|
+
N(1, 2, 3),
|
|
534
|
+
N(1, 0, 2),
|
|
535
|
+
N(1, 1, 1),
|
|
536
|
+
N(1, 1, 2),
|
|
537
|
+
N(1, 2, 1),
|
|
538
|
+
N(1, 2, 2)
|
|
539
|
+
in 3-d lattice N
|
|
540
|
+
"""
|
|
541
|
+
from sage.geometry.fan import Fan
|
|
542
|
+
if origin is None:
|
|
543
|
+
origin = self.point_configuration().star_center()
|
|
544
|
+
R = self.base_ring()
|
|
545
|
+
origin = vector(R, origin)
|
|
546
|
+
points = self.point_configuration().points()
|
|
547
|
+
return Fan(self, (vector(R, p) - origin for p in points))
|
|
548
|
+
|
|
549
|
+
@cached_method
|
|
550
|
+
def simplicial_complex(self):
|
|
551
|
+
r"""
|
|
552
|
+
Return ``self`` as an (abstract) simplicial complex.
|
|
553
|
+
|
|
554
|
+
OUTPUT: a :class:`~sage.topology.simplicial_complex.SimplicialComplex`
|
|
555
|
+
|
|
556
|
+
EXAMPLES::
|
|
557
|
+
|
|
558
|
+
sage: p = polytopes.cuboctahedron()
|
|
559
|
+
sage: sc = p.triangulate(engine='internal').simplicial_complex(); sc # needs sage.graphs
|
|
560
|
+
Simplicial complex with 12 vertices and 16 facets
|
|
561
|
+
|
|
562
|
+
Any convex set is contractable, so its reduced homology groups vanish::
|
|
563
|
+
|
|
564
|
+
sage: sc.homology() # needs sage.graphs
|
|
565
|
+
{0: 0, 1: 0, 2: 0, 3: 0}
|
|
566
|
+
"""
|
|
567
|
+
from sage.topology.simplicial_complex import SimplicialComplex
|
|
568
|
+
return SimplicialComplex(self)
|
|
569
|
+
|
|
570
|
+
@cached_method
|
|
571
|
+
def _boundary_simplex_dictionary(self):
|
|
572
|
+
"""
|
|
573
|
+
Return facets and the simplices they bound.
|
|
574
|
+
|
|
575
|
+
TESTS::
|
|
576
|
+
|
|
577
|
+
sage: triangulation = polytopes.hypercube(2).triangulate(engine='internal')
|
|
578
|
+
sage: triangulation._boundary_simplex_dictionary()
|
|
579
|
+
{(0, 1): ((0, 1, 3),),
|
|
580
|
+
(0, 3): ((0, 1, 3),),
|
|
581
|
+
(1, 2): ((1, 2, 3),),
|
|
582
|
+
(1, 3): ((0, 1, 3), (1, 2, 3)),
|
|
583
|
+
(2, 3): ((1, 2, 3),)}
|
|
584
|
+
|
|
585
|
+
sage: triangulation = polytopes.cube().triangulate(engine='internal')
|
|
586
|
+
sage: triangulation._boundary_simplex_dictionary()
|
|
587
|
+
{(0, 1, 2): ((0, 1, 2, 7),),
|
|
588
|
+
(0, 1, 5): ((0, 1, 5, 7),),
|
|
589
|
+
(0, 1, 7): ((0, 1, 2, 7), (0, 1, 5, 7)),
|
|
590
|
+
(0, 2, 3): ((0, 2, 3, 7),),
|
|
591
|
+
(0, 2, 7): ((0, 1, 2, 7), (0, 2, 3, 7)),
|
|
592
|
+
(0, 3, 4): ((0, 3, 4, 7),),
|
|
593
|
+
(0, 3, 7): ((0, 2, 3, 7), (0, 3, 4, 7)),
|
|
594
|
+
(0, 4, 5): ((0, 4, 5, 7),),
|
|
595
|
+
(0, 4, 7): ((0, 3, 4, 7), (0, 4, 5, 7)),
|
|
596
|
+
(0, 5, 7): ((0, 1, 5, 7), (0, 4, 5, 7)),
|
|
597
|
+
(1, 2, 7): ((0, 1, 2, 7),),
|
|
598
|
+
(1, 5, 6): ((1, 5, 6, 7),),
|
|
599
|
+
(1, 5, 7): ((0, 1, 5, 7), (1, 5, 6, 7)),
|
|
600
|
+
(1, 6, 7): ((1, 5, 6, 7),),
|
|
601
|
+
(2, 3, 7): ((0, 2, 3, 7),),
|
|
602
|
+
(3, 4, 7): ((0, 3, 4, 7),),
|
|
603
|
+
(4, 5, 7): ((0, 4, 5, 7),),
|
|
604
|
+
(5, 6, 7): ((1, 5, 6, 7),)}
|
|
605
|
+
"""
|
|
606
|
+
result = dict()
|
|
607
|
+
for simplex in self:
|
|
608
|
+
for i in range(len(simplex)):
|
|
609
|
+
facet = simplex[:i] + simplex[i+1:]
|
|
610
|
+
result[facet] = result.get(facet, tuple()) + (simplex,)
|
|
611
|
+
return result
|
|
612
|
+
|
|
613
|
+
@cached_method
|
|
614
|
+
def boundary(self):
|
|
615
|
+
"""
|
|
616
|
+
Return the boundary of the triangulation.
|
|
617
|
+
|
|
618
|
+
OUTPUT:
|
|
619
|
+
|
|
620
|
+
The outward-facing boundary simplices (of dimension `d-1`) of
|
|
621
|
+
the `d`-dimensional triangulation as a set. Each boundary is
|
|
622
|
+
returned by a tuple of point indices.
|
|
623
|
+
|
|
624
|
+
EXAMPLES::
|
|
625
|
+
|
|
626
|
+
sage: triangulation = polytopes.cube().triangulate(engine='internal')
|
|
627
|
+
sage: triangulation
|
|
628
|
+
(<0,1,2,7>, <0,1,5,7>, <0,2,3,7>, <0,3,4,7>, <0,4,5,7>, <1,5,6,7>)
|
|
629
|
+
sage: triangulation.boundary()
|
|
630
|
+
frozenset({(0, 1, 2),
|
|
631
|
+
(0, 1, 5),
|
|
632
|
+
(0, 2, 3),
|
|
633
|
+
(0, 3, 4),
|
|
634
|
+
(0, 4, 5),
|
|
635
|
+
(1, 2, 7),
|
|
636
|
+
(1, 5, 6),
|
|
637
|
+
(1, 6, 7),
|
|
638
|
+
(2, 3, 7),
|
|
639
|
+
(3, 4, 7),
|
|
640
|
+
(4, 5, 7),
|
|
641
|
+
(5, 6, 7)})
|
|
642
|
+
sage: triangulation.interior_facets()
|
|
643
|
+
frozenset({(0, 1, 7), (0, 2, 7), (0, 3, 7), (0, 4, 7), (0, 5, 7), (1, 5, 7)})
|
|
644
|
+
"""
|
|
645
|
+
return frozenset(facet for facet, bounded_simplices
|
|
646
|
+
in self._boundary_simplex_dictionary().items()
|
|
647
|
+
if len(bounded_simplices) == 1)
|
|
648
|
+
|
|
649
|
+
@cached_method
|
|
650
|
+
def boundary_simplicial_complex(self):
|
|
651
|
+
r"""
|
|
652
|
+
Return the boundary of ``self`` as an (abstract) simplicial complex.
|
|
653
|
+
|
|
654
|
+
OUTPUT: a :class:`~sage.topology.simplicial_complex.SimplicialComplex`
|
|
655
|
+
|
|
656
|
+
EXAMPLES::
|
|
657
|
+
|
|
658
|
+
sage: p = polytopes.cuboctahedron()
|
|
659
|
+
sage: triangulation = p.triangulate(engine='internal')
|
|
660
|
+
sage: bd_sc = triangulation.boundary_simplicial_complex(); bd_sc # needs sage.graphs
|
|
661
|
+
Simplicial complex with 12 vertices and 20 facets
|
|
662
|
+
|
|
663
|
+
The boundary of every convex set is a topological sphere, so it has
|
|
664
|
+
spherical homology::
|
|
665
|
+
|
|
666
|
+
sage: bd_sc.homology() # needs sage.graphs
|
|
667
|
+
{0: 0, 1: 0, 2: Z}
|
|
668
|
+
|
|
669
|
+
It is a subcomplex of ``self`` as a :meth:`simplicial_complex`::
|
|
670
|
+
|
|
671
|
+
sage: sc = triangulation.simplicial_complex() # needs sage.graphs
|
|
672
|
+
sage: all(f in sc for f in bd_sc.maximal_faces()) # needs sage.graphs
|
|
673
|
+
True
|
|
674
|
+
"""
|
|
675
|
+
from sage.topology.simplicial_complex import SimplicialComplex
|
|
676
|
+
return SimplicialComplex(self.boundary(), maximality_check=False)
|
|
677
|
+
|
|
678
|
+
@cached_method
|
|
679
|
+
def interior_facets(self):
|
|
680
|
+
"""
|
|
681
|
+
Return the interior facets of the triangulation.
|
|
682
|
+
|
|
683
|
+
OUTPUT:
|
|
684
|
+
|
|
685
|
+
The inward-facing boundary simplices (of dimension `d-1`) of
|
|
686
|
+
the `d`-dimensional triangulation as a set. Each boundary is
|
|
687
|
+
returned by a tuple of point indices.
|
|
688
|
+
|
|
689
|
+
EXAMPLES::
|
|
690
|
+
|
|
691
|
+
sage: triangulation = polytopes.cube().triangulate(engine='internal')
|
|
692
|
+
sage: triangulation
|
|
693
|
+
(<0,1,2,7>, <0,1,5,7>, <0,2,3,7>, <0,3,4,7>, <0,4,5,7>, <1,5,6,7>)
|
|
694
|
+
sage: triangulation.boundary()
|
|
695
|
+
frozenset({(0, 1, 2),
|
|
696
|
+
(0, 1, 5),
|
|
697
|
+
(0, 2, 3),
|
|
698
|
+
(0, 3, 4),
|
|
699
|
+
(0, 4, 5),
|
|
700
|
+
(1, 2, 7),
|
|
701
|
+
(1, 5, 6),
|
|
702
|
+
(1, 6, 7),
|
|
703
|
+
(2, 3, 7),
|
|
704
|
+
(3, 4, 7),
|
|
705
|
+
(4, 5, 7),
|
|
706
|
+
(5, 6, 7)})
|
|
707
|
+
sage: triangulation.interior_facets()
|
|
708
|
+
frozenset({(0, 1, 7), (0, 2, 7), (0, 3, 7), (0, 4, 7), (0, 5, 7), (1, 5, 7)})
|
|
709
|
+
"""
|
|
710
|
+
return frozenset(facet for facet, bounded_simplices
|
|
711
|
+
in self._boundary_simplex_dictionary().items()
|
|
712
|
+
if len(bounded_simplices) == 2)
|
|
713
|
+
|
|
714
|
+
def polyhedral_complex(self, **kwds):
|
|
715
|
+
"""
|
|
716
|
+
Return ``self`` as a :class:`~sage.geometry.polyhedral_complex.PolyhedralComplex`.
|
|
717
|
+
|
|
718
|
+
OUTPUT:
|
|
719
|
+
|
|
720
|
+
A :class:`~sage.geometry.polyhedral_complex.PolyhedralComplex` whose maximal cells
|
|
721
|
+
are the simplices of the triangulation.
|
|
722
|
+
|
|
723
|
+
EXAMPLES::
|
|
724
|
+
|
|
725
|
+
sage: P = polytopes.cube()
|
|
726
|
+
sage: pc = PointConfiguration(P.vertices())
|
|
727
|
+
sage: T = pc.placing_triangulation(); T
|
|
728
|
+
(<0,1,2,7>, <0,1,5,7>, <0,2,3,7>, <0,3,4,7>, <0,4,5,7>, <1,5,6,7>)
|
|
729
|
+
sage: C = T.polyhedral_complex(); C # needs sage.graphs
|
|
730
|
+
Polyhedral complex with 6 maximal cells
|
|
731
|
+
sage: [P.vertices_list() for P in C.maximal_cells_sorted()] # needs sage.graphs
|
|
732
|
+
[[[-1, -1, -1], [-1, -1, 1], [-1, 1, 1], [1, -1, -1]],
|
|
733
|
+
[[-1, -1, -1], [-1, 1, -1], [-1, 1, 1], [1, 1, -1]],
|
|
734
|
+
[[-1, -1, -1], [-1, 1, 1], [1, -1, -1], [1, 1, -1]],
|
|
735
|
+
[[-1, -1, 1], [-1, 1, 1], [1, -1, -1], [1, -1, 1]],
|
|
736
|
+
[[-1, 1, 1], [1, -1, -1], [1, -1, 1], [1, 1, 1]],
|
|
737
|
+
[[-1, 1, 1], [1, -1, -1], [1, 1, -1], [1, 1, 1]]]
|
|
738
|
+
"""
|
|
739
|
+
from sage.geometry.polyhedral_complex import PolyhedralComplex
|
|
740
|
+
from sage.geometry.polyhedron.constructor import Polyhedron
|
|
741
|
+
ambient_dim = self.point_configuration().ambient_dim()
|
|
742
|
+
points = self.point_configuration().points()
|
|
743
|
+
return PolyhedralComplex([Polyhedron(vertices=[points[i] for i in simplex])
|
|
744
|
+
for simplex in self],
|
|
745
|
+
ambient_dim=ambient_dim,
|
|
746
|
+
maximality_check=False,
|
|
747
|
+
face_to_face_check=False,
|
|
748
|
+
**kwds)
|
|
749
|
+
|
|
750
|
+
def boundary_polyhedral_complex(self, **kwds):
|
|
751
|
+
r"""
|
|
752
|
+
Return the boundary of ``self`` as a :class:`~sage.geometry.polyhedral_complex.PolyhedralComplex`.
|
|
753
|
+
|
|
754
|
+
OUTPUT:
|
|
755
|
+
|
|
756
|
+
A :class:`~sage.geometry.polyhedral_complex.PolyhedralComplex` whose maximal cells
|
|
757
|
+
are the simplices of the boundary of ``self``.
|
|
758
|
+
|
|
759
|
+
EXAMPLES::
|
|
760
|
+
|
|
761
|
+
sage: P = polytopes.cube()
|
|
762
|
+
sage: pc = PointConfiguration(P.vertices())
|
|
763
|
+
sage: T = pc.placing_triangulation(); T
|
|
764
|
+
(<0,1,2,7>, <0,1,5,7>, <0,2,3,7>, <0,3,4,7>, <0,4,5,7>, <1,5,6,7>)
|
|
765
|
+
sage: bd_C = T.boundary_polyhedral_complex(); bd_C # needs sage.graphs
|
|
766
|
+
Polyhedral complex with 12 maximal cells
|
|
767
|
+
sage: [P.vertices_list() for P in bd_C.maximal_cells_sorted()] # needs sage.graphs
|
|
768
|
+
[[[-1, -1, -1], [-1, -1, 1], [-1, 1, 1]],
|
|
769
|
+
[[-1, -1, -1], [-1, -1, 1], [1, -1, -1]],
|
|
770
|
+
[[-1, -1, -1], [-1, 1, -1], [-1, 1, 1]],
|
|
771
|
+
[[-1, -1, -1], [-1, 1, -1], [1, 1, -1]],
|
|
772
|
+
[[-1, -1, -1], [1, -1, -1], [1, 1, -1]],
|
|
773
|
+
[[-1, -1, 1], [-1, 1, 1], [1, -1, 1]],
|
|
774
|
+
[[-1, -1, 1], [1, -1, -1], [1, -1, 1]],
|
|
775
|
+
[[-1, 1, -1], [-1, 1, 1], [1, 1, -1]],
|
|
776
|
+
[[-1, 1, 1], [1, -1, 1], [1, 1, 1]],
|
|
777
|
+
[[-1, 1, 1], [1, 1, -1], [1, 1, 1]],
|
|
778
|
+
[[1, -1, -1], [1, -1, 1], [1, 1, 1]],
|
|
779
|
+
[[1, -1, -1], [1, 1, -1], [1, 1, 1]]]
|
|
780
|
+
|
|
781
|
+
It is a subcomplex of ``self`` as a :meth:`polyhedral_complex`::
|
|
782
|
+
|
|
783
|
+
sage: C = T.polyhedral_complex() # needs sage.graphs
|
|
784
|
+
sage: bd_C.is_subcomplex(C) # needs sage.graphs
|
|
785
|
+
True
|
|
786
|
+
"""
|
|
787
|
+
from sage.geometry.polyhedral_complex import PolyhedralComplex
|
|
788
|
+
from sage.geometry.polyhedron.constructor import Polyhedron
|
|
789
|
+
ambient_dim = self.point_configuration().ambient_dim()
|
|
790
|
+
points = self.point_configuration().points()
|
|
791
|
+
return PolyhedralComplex([Polyhedron(vertices=[points[i] for i in simplex])
|
|
792
|
+
for simplex in self.boundary()],
|
|
793
|
+
ambient_dim=ambient_dim,
|
|
794
|
+
maximality_check=False,
|
|
795
|
+
face_to_face_check=False,
|
|
796
|
+
**kwds)
|
|
797
|
+
|
|
798
|
+
@cached_method
|
|
799
|
+
def normal_cone(self):
|
|
800
|
+
r"""
|
|
801
|
+
Return the (closure of the) normal cone of the triangulation.
|
|
802
|
+
|
|
803
|
+
Recall that a regular triangulation is one that equals the
|
|
804
|
+
"crease lines" of a convex piecewise-linear function. This
|
|
805
|
+
support function is not unique, for example, you can scale it
|
|
806
|
+
by a positive constant. The set of all piecewise-linear
|
|
807
|
+
functions with fixed creases forms an open cone. This cone can
|
|
808
|
+
be interpreted as the cone of normal vectors at a point of the
|
|
809
|
+
secondary polytope, which is why we call it normal cone. See
|
|
810
|
+
[GKZ1994]_ Section 7.1 for details.
|
|
811
|
+
|
|
812
|
+
OUTPUT:
|
|
813
|
+
|
|
814
|
+
The closure of the normal cone. The `i`-th entry equals the
|
|
815
|
+
value of the piecewise-linear function at the `i`-th point of
|
|
816
|
+
the configuration.
|
|
817
|
+
|
|
818
|
+
For an irregular triangulation, the normal cone is empty. In
|
|
819
|
+
this case, a single point (the origin) is returned.
|
|
820
|
+
|
|
821
|
+
EXAMPLES::
|
|
822
|
+
|
|
823
|
+
sage: triangulation = polytopes.hypercube(2).triangulate(engine='internal')
|
|
824
|
+
sage: triangulation
|
|
825
|
+
(<0,1,3>, <1,2,3>)
|
|
826
|
+
sage: N = triangulation.normal_cone(); N
|
|
827
|
+
4-d cone in 4-d lattice
|
|
828
|
+
sage: N.rays()
|
|
829
|
+
( 0, 0, 0, -1),
|
|
830
|
+
( 0, 0, 1, 1),
|
|
831
|
+
( 0, 0, -1, -1),
|
|
832
|
+
( 1, 0, 0, 1),
|
|
833
|
+
(-1, 0, 0, -1),
|
|
834
|
+
( 0, 1, 0, -1),
|
|
835
|
+
( 0, -1, 0, 1)
|
|
836
|
+
in Ambient free module of rank 4
|
|
837
|
+
over the principal ideal domain Integer Ring
|
|
838
|
+
sage: N.dual().rays() # needs sage.libs.pari
|
|
839
|
+
(1, -1, 1, -1)
|
|
840
|
+
in Ambient free module of rank 4
|
|
841
|
+
over the principal ideal domain Integer Ring
|
|
842
|
+
|
|
843
|
+
TESTS::
|
|
844
|
+
|
|
845
|
+
sage: polytopes.simplex(2).triangulate().normal_cone()
|
|
846
|
+
3-d cone in 3-d lattice
|
|
847
|
+
sage: _.dual().is_trivial() # needs sage.libs.pari
|
|
848
|
+
True
|
|
849
|
+
"""
|
|
850
|
+
if not self.point_configuration().base_ring().is_subring(QQ):
|
|
851
|
+
raise NotImplementedError('Only base rings ZZ and QQ are supported')
|
|
852
|
+
from ppl import Constraint_System, Linear_Expression, C_Polyhedron
|
|
853
|
+
from sage.matrix.constructor import matrix
|
|
854
|
+
from sage.arith.functions import lcm
|
|
855
|
+
pc = self.point_configuration()
|
|
856
|
+
cs = Constraint_System()
|
|
857
|
+
for facet in self.interior_facets():
|
|
858
|
+
s0, s1 = self._boundary_simplex_dictionary()[facet]
|
|
859
|
+
p = set(s0).difference(facet).pop()
|
|
860
|
+
q = set(s1).difference(facet).pop()
|
|
861
|
+
origin = pc.point(p).reduced_affine_vector()
|
|
862
|
+
base_indices = [i for i in s0 if i != p]
|
|
863
|
+
base = matrix([ pc.point(i).reduced_affine_vector()-origin for i in base_indices ])
|
|
864
|
+
sol = base.solve_left( pc.point(q).reduced_affine_vector()-origin )
|
|
865
|
+
relation = [0]*pc.n_points()
|
|
866
|
+
relation[p] = sum(sol)-1
|
|
867
|
+
relation[q] = 1
|
|
868
|
+
for i, base_i in enumerate(base_indices):
|
|
869
|
+
relation[base_i] = -sol[i]
|
|
870
|
+
rel_denom = lcm([QQ(r).denominator() for r in relation])
|
|
871
|
+
relation = [ ZZ(r*rel_denom) for r in relation ]
|
|
872
|
+
ex = Linear_Expression(relation,0)
|
|
873
|
+
cs.insert(ex >= 0)
|
|
874
|
+
from sage.modules.free_module import FreeModule
|
|
875
|
+
ambient = FreeModule(ZZ, self.point_configuration().n_points())
|
|
876
|
+
if cs.empty():
|
|
877
|
+
cone = C_Polyhedron(ambient.dimension(), 'universe')
|
|
878
|
+
else:
|
|
879
|
+
cone = C_Polyhedron(cs)
|
|
880
|
+
from sage.geometry.cone import _Cone_from_PPL
|
|
881
|
+
return _Cone_from_PPL(cone, lattice=ambient)
|
|
882
|
+
|
|
883
|
+
def adjacency_graph(self):
|
|
884
|
+
"""
|
|
885
|
+
Return a graph showing which simplices are adjacent in the triangulation.
|
|
886
|
+
|
|
887
|
+
OUTPUT:
|
|
888
|
+
|
|
889
|
+
A graph consisting of vertices referring to the simplices in the
|
|
890
|
+
triangulation, and edges showing which simplices are adjacent to each
|
|
891
|
+
other.
|
|
892
|
+
|
|
893
|
+
.. SEEALSO::
|
|
894
|
+
|
|
895
|
+
* To obtain the triangulation's 1-skeleton, use
|
|
896
|
+
:meth:`SimplicialComplex.graph` through
|
|
897
|
+
``MyTriangulation.simplicial_complex().graph()``.
|
|
898
|
+
|
|
899
|
+
AUTHORS:
|
|
900
|
+
|
|
901
|
+
* Stephen Farley (2013-08-10): initial version
|
|
902
|
+
|
|
903
|
+
EXAMPLES::
|
|
904
|
+
|
|
905
|
+
sage: p = PointConfiguration([[1,0,0], [0,1,0], [0,0,1], [-1,0,1],
|
|
906
|
+
....: [1,0,-1], [-1,0,0], [0,-1,0], [0,0,-1]])
|
|
907
|
+
sage: t = p.triangulate()
|
|
908
|
+
sage: t.adjacency_graph() # needs sage.graphs
|
|
909
|
+
Graph on 8 vertices
|
|
910
|
+
"""
|
|
911
|
+
vertices = [Set(_) for _ in list(self)]
|
|
912
|
+
from sage.graphs.graph import Graph
|
|
913
|
+
return Graph([vertices,
|
|
914
|
+
lambda x,y: len(x-y) == 1])
|