passagemath-polyhedra 10.6.37__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.
- passagemath_polyhedra/__init__.py +3 -0
- passagemath_polyhedra-10.6.37.dist-info/METADATA +367 -0
- passagemath_polyhedra-10.6.37.dist-info/METADATA.bak +369 -0
- passagemath_polyhedra-10.6.37.dist-info/RECORD +209 -0
- passagemath_polyhedra-10.6.37.dist-info/WHEEL +5 -0
- passagemath_polyhedra-10.6.37.dist-info/top_level.txt +3 -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 +3905 -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,389 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-polyhedra
|
|
2
|
+
"""
|
|
3
|
+
Find isomorphisms between fans
|
|
4
|
+
"""
|
|
5
|
+
# ****************************************************************************
|
|
6
|
+
# Copyright (C) 2012 Volker Braun <vbraun.name@gmail.com>
|
|
7
|
+
#
|
|
8
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
9
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
10
|
+
# the License, or (at your option) any later version.
|
|
11
|
+
# https://www.gnu.org/licenses/
|
|
12
|
+
# ****************************************************************************
|
|
13
|
+
from sage.rings.integer_ring import ZZ
|
|
14
|
+
from sage.matrix.constructor import column_matrix, matrix
|
|
15
|
+
from sage.geometry.cone import Cone
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class FanNotIsomorphicError(Exception):
|
|
19
|
+
"""
|
|
20
|
+
Exception to return if there is no fan isomorphism
|
|
21
|
+
"""
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def fan_isomorphic_necessary_conditions(fan1, fan2):
|
|
26
|
+
"""
|
|
27
|
+
Check necessary (but not sufficient) conditions for the fans to be isomorphic.
|
|
28
|
+
|
|
29
|
+
INPUT:
|
|
30
|
+
|
|
31
|
+
- ``fan1``, ``fan2`` -- two fans
|
|
32
|
+
|
|
33
|
+
OUTPUT: boolean; ``False`` if the two fans cannot be isomorphic. ``True``
|
|
34
|
+
if the two fans may be isomorphic.
|
|
35
|
+
|
|
36
|
+
EXAMPLES::
|
|
37
|
+
|
|
38
|
+
sage: fan1 = toric_varieties.P2().fan() # needs palp sage.graphs
|
|
39
|
+
sage: fan2 = toric_varieties.dP8().fan() # needs palp sage.graphs
|
|
40
|
+
sage: from sage.geometry.fan_isomorphism import fan_isomorphic_necessary_conditions
|
|
41
|
+
sage: fan_isomorphic_necessary_conditions(fan1, fan2) # needs palp sage.graphs
|
|
42
|
+
False
|
|
43
|
+
"""
|
|
44
|
+
if fan1.lattice_dim() != fan2.lattice_dim():
|
|
45
|
+
return False
|
|
46
|
+
if fan1.dim() != fan2.dim():
|
|
47
|
+
return False
|
|
48
|
+
if fan1.nrays() != fan2.nrays():
|
|
49
|
+
return False
|
|
50
|
+
if fan1.ngenerating_cones() != fan2.ngenerating_cones():
|
|
51
|
+
return False
|
|
52
|
+
if fan1.is_complete() != fan2.is_complete():
|
|
53
|
+
return False
|
|
54
|
+
return True
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def fan_isomorphism_generator(fan1, fan2):
|
|
58
|
+
"""
|
|
59
|
+
Iterate over the isomorphisms from ``fan1`` to ``fan2``.
|
|
60
|
+
|
|
61
|
+
ALGORITHM:
|
|
62
|
+
|
|
63
|
+
The :meth:`sage.geometry.fan.Fan.vertex_graph` of the two fans is
|
|
64
|
+
compared. For each graph isomorphism, we attempt to lift it to an
|
|
65
|
+
actual isomorphism of fans.
|
|
66
|
+
|
|
67
|
+
INPUT:
|
|
68
|
+
|
|
69
|
+
- ``fan1``, ``fan2`` -- two fans
|
|
70
|
+
|
|
71
|
+
OUTPUT:
|
|
72
|
+
|
|
73
|
+
Yields the fan isomorphisms as matrices acting from the right on
|
|
74
|
+
rays.
|
|
75
|
+
|
|
76
|
+
EXAMPLES::
|
|
77
|
+
|
|
78
|
+
sage: fan = toric_varieties.P2().fan() # needs palp sage.graphs
|
|
79
|
+
sage: from sage.geometry.fan_isomorphism import fan_isomorphism_generator
|
|
80
|
+
sage: sorted(fan_isomorphism_generator(fan, fan)) # needs palp sage.graphs
|
|
81
|
+
[
|
|
82
|
+
[-1 -1] [-1 -1] [ 0 1] [0 1] [ 1 0] [1 0]
|
|
83
|
+
[ 0 1], [ 1 0], [-1 -1], [1 0], [-1 -1], [0 1]
|
|
84
|
+
]
|
|
85
|
+
sage: m1 = matrix([(1, 0), (0, -5), (-3, 4)])
|
|
86
|
+
sage: m2 = matrix([(3, 0), (1, 0), (-2, 1)])
|
|
87
|
+
sage: m1.elementary_divisors() == m2.elementary_divisors() == [1,1,0]
|
|
88
|
+
True
|
|
89
|
+
sage: fan1 = Fan([Cone([m1*vector([23, 14]), m1*vector([ 3,100])]),
|
|
90
|
+
....: Cone([m1*vector([-1,-14]), m1*vector([-100, -5])])])
|
|
91
|
+
sage: fan2 = Fan([Cone([m2*vector([23, 14]), m2*vector([ 3,100])]),
|
|
92
|
+
....: Cone([m2*vector([-1,-14]), m2*vector([-100, -5])])])
|
|
93
|
+
sage: sorted(fan_isomorphism_generator(fan1, fan2)) # needs sage.graphs
|
|
94
|
+
[
|
|
95
|
+
[-12 1 -5]
|
|
96
|
+
[ -4 0 -1]
|
|
97
|
+
[ -5 0 -1]
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
sage: m0 = identity_matrix(ZZ, 2)
|
|
101
|
+
sage: m1 = matrix([(1, 0), (0, -5), (-3, 4)])
|
|
102
|
+
sage: m2 = matrix([(3, 0), (1, 0), (-2, 1)])
|
|
103
|
+
sage: m1.elementary_divisors() == m2.elementary_divisors() == [1,1,0]
|
|
104
|
+
True
|
|
105
|
+
sage: fan0 = Fan([Cone([m0*vector([1,0]), m0*vector([1,1])]),
|
|
106
|
+
....: Cone([m0*vector([1,1]), m0*vector([0,1])])])
|
|
107
|
+
sage: fan1 = Fan([Cone([m1*vector([1,0]), m1*vector([1,1])]),
|
|
108
|
+
....: Cone([m1*vector([1,1]), m1*vector([0,1])])])
|
|
109
|
+
sage: fan2 = Fan([Cone([m2*vector([1,0]), m2*vector([1,1])]),
|
|
110
|
+
....: Cone([m2*vector([1,1]), m2*vector([0,1])])])
|
|
111
|
+
sage: sorted(fan_isomorphism_generator(fan0, fan0)) # needs sage.graphs
|
|
112
|
+
[
|
|
113
|
+
[0 1] [1 0]
|
|
114
|
+
[1 0], [0 1]
|
|
115
|
+
]
|
|
116
|
+
sage: sorted(fan_isomorphism_generator(fan1, fan1)) # needs sage.graphs
|
|
117
|
+
[
|
|
118
|
+
[ -3 -20 28] [1 0 0]
|
|
119
|
+
[ -1 -4 7] [0 1 0]
|
|
120
|
+
[ -1 -5 8], [0 0 1]
|
|
121
|
+
]
|
|
122
|
+
sage: sorted(fan_isomorphism_generator(fan1, fan2)) # needs sage.graphs
|
|
123
|
+
[
|
|
124
|
+
[-24 -3 7] [-12 1 -5]
|
|
125
|
+
[ -7 -1 2] [ -4 0 -1]
|
|
126
|
+
[ -8 -1 2], [ -5 0 -1]
|
|
127
|
+
]
|
|
128
|
+
sage: sorted(fan_isomorphism_generator(fan2, fan1)) # needs sage.graphs
|
|
129
|
+
[
|
|
130
|
+
[ 0 1 -1] [ 0 1 -1]
|
|
131
|
+
[ 1 -13 8] [ 2 -8 1]
|
|
132
|
+
[ 0 -5 4], [ 1 0 -3]
|
|
133
|
+
]
|
|
134
|
+
"""
|
|
135
|
+
if not fan_isomorphic_necessary_conditions(fan1, fan2):
|
|
136
|
+
return
|
|
137
|
+
|
|
138
|
+
graph1 = fan1.vertex_graph()
|
|
139
|
+
graph2 = fan2.vertex_graph()
|
|
140
|
+
graph_iso = graph1.is_isomorphic(graph2, edge_labels=True, certificate=True)
|
|
141
|
+
if not graph_iso[0]:
|
|
142
|
+
return
|
|
143
|
+
graph_iso = graph_iso[1]
|
|
144
|
+
|
|
145
|
+
# Pick a basis of rays in fan1
|
|
146
|
+
max_cone = fan1(fan1.dim())[0]
|
|
147
|
+
fan1_pivot_rays = max_cone.rays()
|
|
148
|
+
fan1_basis = fan1_pivot_rays + fan1.virtual_rays() # A QQ-basis for N_1
|
|
149
|
+
fan1_pivot_cones = [ fan1.embed(Cone([r])) for r in fan1_pivot_rays ]
|
|
150
|
+
|
|
151
|
+
# The fan2 cones as set(set(ray indices))
|
|
152
|
+
fan2_cones = frozenset(
|
|
153
|
+
frozenset(cone.ambient_ray_indices())
|
|
154
|
+
for cone in fan2.generating_cones() )
|
|
155
|
+
|
|
156
|
+
# iterate over all graph isomorphisms graph1 -> graph2
|
|
157
|
+
for perm in graph2.automorphism_group(edge_labels=True):
|
|
158
|
+
# find a candidate m that maps fan1_basis to the image rays under the graph isomorphism
|
|
159
|
+
fan2_pivot_cones = [ perm(graph_iso[c]) for c in fan1_pivot_cones ]
|
|
160
|
+
fan2_pivot_rays = fan2.rays([ c.ambient_ray_indices()[0] for c in fan2_pivot_cones ])
|
|
161
|
+
fan2_basis = fan2_pivot_rays + fan2.virtual_rays()
|
|
162
|
+
try:
|
|
163
|
+
m = matrix(ZZ, fan1_basis).solve_right(matrix(ZZ, fan2_basis))
|
|
164
|
+
m = m.change_ring(ZZ)
|
|
165
|
+
except (ValueError, TypeError):
|
|
166
|
+
continue # no solution
|
|
167
|
+
|
|
168
|
+
# check that the candidate m lifts the vertex graph homomorphism
|
|
169
|
+
graph_image_ray_indices = [ perm(graph_iso[c]).ambient_ray_indices()[0] for c in fan1(1) ]
|
|
170
|
+
try:
|
|
171
|
+
matrix_image_ray_indices = [ fan2.rays().index(r*m) for r in fan1.rays() ]
|
|
172
|
+
except ValueError:
|
|
173
|
+
continue
|
|
174
|
+
if graph_image_ray_indices != matrix_image_ray_indices:
|
|
175
|
+
continue
|
|
176
|
+
|
|
177
|
+
# check that the candidate m maps generating cone to generating cone
|
|
178
|
+
image_cones = frozenset( # The image(fan1) cones as set(set(integers)
|
|
179
|
+
frozenset(graph_image_ray_indices[i]
|
|
180
|
+
for i in cone.ambient_ray_indices())
|
|
181
|
+
for cone in fan1.generating_cones() )
|
|
182
|
+
if image_cones == fan2_cones:
|
|
183
|
+
m.set_immutable()
|
|
184
|
+
yield m
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def find_isomorphism(fan1, fan2, check=False):
|
|
188
|
+
"""
|
|
189
|
+
Find an isomorphism of the two fans.
|
|
190
|
+
|
|
191
|
+
INPUT:
|
|
192
|
+
|
|
193
|
+
- ``fan1``, ``fan2`` -- two fans
|
|
194
|
+
|
|
195
|
+
- ``check`` -- boolean (default: ``False``); passed to the fan
|
|
196
|
+
morphism constructor, see
|
|
197
|
+
:func:`~sage.geometry.fan_morphism.FanMorphism`
|
|
198
|
+
|
|
199
|
+
OUTPUT:
|
|
200
|
+
|
|
201
|
+
A fan isomorphism. If the fans are not isomorphic, a
|
|
202
|
+
:exc:`FanNotIsomorphicError` is raised.
|
|
203
|
+
|
|
204
|
+
EXAMPLES::
|
|
205
|
+
|
|
206
|
+
sage: rays = ((1, 1), (0, 1), (-1, -1), (3, 1))
|
|
207
|
+
sage: cones = [(0,1), (1,2), (2,3), (3,0)]
|
|
208
|
+
sage: fan1 = Fan(cones, rays)
|
|
209
|
+
|
|
210
|
+
sage: m = matrix([[-2,3],[1,-1]])
|
|
211
|
+
sage: m.det() == -1
|
|
212
|
+
True
|
|
213
|
+
sage: fan2 = Fan(cones, [vector(r)*m for r in rays])
|
|
214
|
+
|
|
215
|
+
sage: from sage.geometry.fan_isomorphism import find_isomorphism
|
|
216
|
+
sage: find_isomorphism(fan1, fan2, check=True) # needs sage.graphs
|
|
217
|
+
Fan morphism defined by the matrix
|
|
218
|
+
[-2 3]
|
|
219
|
+
[ 1 -1]
|
|
220
|
+
Domain fan: Rational polyhedral fan in 2-d lattice N
|
|
221
|
+
Codomain fan: Rational polyhedral fan in 2-d lattice N
|
|
222
|
+
|
|
223
|
+
sage: find_isomorphism(fan1, toric_varieties.P2().fan()) # needs palp sage.graphs
|
|
224
|
+
Traceback (most recent call last):
|
|
225
|
+
...
|
|
226
|
+
FanNotIsomorphicError
|
|
227
|
+
|
|
228
|
+
sage: fan1 = Fan(cones=[[1,3,4,5],[0,1,2,3],[2,3,4],[0,1,5]],
|
|
229
|
+
....: rays=[(-1,-1,0),(-1,-1,3),(-1,1,-1),(-1,3,-1),(0,2,-1),(1,-1,1)])
|
|
230
|
+
sage: fan2 = Fan(cones=[[0,2,3,5],[0,1,4,5],[0,1,2],[3,4,5]],
|
|
231
|
+
....: rays=[(-1,-1,-1),(-1,-1,0),(-1,1,-1),(0,2,-1),(1,-1,1),(3,-1,-1)])
|
|
232
|
+
sage: fan1.is_isomorphic(fan2) # needs sage.graphs
|
|
233
|
+
True
|
|
234
|
+
"""
|
|
235
|
+
generator = fan_isomorphism_generator(fan1, fan2)
|
|
236
|
+
try:
|
|
237
|
+
m = next(generator)
|
|
238
|
+
except StopIteration:
|
|
239
|
+
raise FanNotIsomorphicError
|
|
240
|
+
|
|
241
|
+
from sage.geometry.fan_morphism import FanMorphism
|
|
242
|
+
return FanMorphism(m, domain_fan=fan1, codomain=fan2, check=check)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def fan_2d_cyclically_ordered_rays(fan):
|
|
246
|
+
"""
|
|
247
|
+
Return the rays of a 2-dimensional ``fan`` in cyclic order.
|
|
248
|
+
|
|
249
|
+
INPUT:
|
|
250
|
+
|
|
251
|
+
- ``fan`` -- a 2-dimensional fan
|
|
252
|
+
|
|
253
|
+
OUTPUT:
|
|
254
|
+
|
|
255
|
+
A :class:`~sage.geometry.point_collection.PointCollection`
|
|
256
|
+
containing the rays in one particular cyclic order.
|
|
257
|
+
|
|
258
|
+
EXAMPLES::
|
|
259
|
+
|
|
260
|
+
sage: rays = ((1, 1), (-1, -1), (-1, 1), (1, -1))
|
|
261
|
+
sage: cones = [(0,2), (2,1), (1,3), (3,0)]
|
|
262
|
+
sage: fan = Fan(cones, rays)
|
|
263
|
+
sage: fan.rays()
|
|
264
|
+
N( 1, 1),
|
|
265
|
+
N(-1, -1),
|
|
266
|
+
N(-1, 1),
|
|
267
|
+
N( 1, -1)
|
|
268
|
+
in 2-d lattice N
|
|
269
|
+
sage: from sage.geometry.fan_isomorphism import fan_2d_cyclically_ordered_rays
|
|
270
|
+
sage: fan_2d_cyclically_ordered_rays(fan)
|
|
271
|
+
N(-1, -1),
|
|
272
|
+
N(-1, 1),
|
|
273
|
+
N( 1, 1),
|
|
274
|
+
N( 1, -1)
|
|
275
|
+
in 2-d lattice N
|
|
276
|
+
|
|
277
|
+
TESTS::
|
|
278
|
+
|
|
279
|
+
sage: fan = Fan(cones=[], rays=[], lattice=ZZ^2)
|
|
280
|
+
sage: from sage.geometry.fan_isomorphism import fan_2d_cyclically_ordered_rays
|
|
281
|
+
sage: fan_2d_cyclically_ordered_rays(fan)
|
|
282
|
+
Empty collection
|
|
283
|
+
in Ambient free module of rank 2 over the principal ideal domain Integer Ring
|
|
284
|
+
"""
|
|
285
|
+
assert fan.lattice_dim() == 2
|
|
286
|
+
import math
|
|
287
|
+
rays = [ (math.atan2(r[0],r[1]), r) for r in fan.rays() ]
|
|
288
|
+
rays = [ r[1] for r in sorted(rays) ]
|
|
289
|
+
from sage.geometry.point_collection import PointCollection
|
|
290
|
+
return PointCollection(rays, fan.lattice())
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def fan_2d_echelon_forms(fan):
|
|
294
|
+
"""
|
|
295
|
+
Return echelon forms of all cyclically ordered ray matrices.
|
|
296
|
+
|
|
297
|
+
Note that the echelon form of the ordered ray matrices are unique
|
|
298
|
+
up to different cyclic orderings.
|
|
299
|
+
|
|
300
|
+
INPUT:
|
|
301
|
+
|
|
302
|
+
- ``fan`` -- a fan
|
|
303
|
+
|
|
304
|
+
OUTPUT:
|
|
305
|
+
|
|
306
|
+
A set of matrices. The set of all echelon forms for all different
|
|
307
|
+
cyclic orderings.
|
|
308
|
+
|
|
309
|
+
EXAMPLES::
|
|
310
|
+
|
|
311
|
+
sage: fan = toric_varieties.P2().fan() # needs palp sage.graphs
|
|
312
|
+
sage: from sage.geometry.fan_isomorphism import fan_2d_echelon_forms
|
|
313
|
+
sage: fan_2d_echelon_forms(fan) # needs palp sage.graphs
|
|
314
|
+
frozenset({[ 1 0 -1]
|
|
315
|
+
[ 0 1 -1]})
|
|
316
|
+
|
|
317
|
+
sage: fan = toric_varieties.dP7().fan() # needs palp sage.graphs
|
|
318
|
+
sage: sorted(fan_2d_echelon_forms(fan)) # needs palp sage.graphs
|
|
319
|
+
[
|
|
320
|
+
[ 1 0 -1 -1 0] [ 1 0 -1 -1 0] [ 1 0 -1 -1 1] [ 1 0 -1 0 1]
|
|
321
|
+
[ 0 1 0 -1 -1], [ 0 1 1 0 -1], [ 0 1 1 0 -1], [ 0 1 0 -1 -1],
|
|
322
|
+
<BLANKLINE>
|
|
323
|
+
[ 1 0 -1 0 1]
|
|
324
|
+
[ 0 1 1 -1 -1]
|
|
325
|
+
]
|
|
326
|
+
|
|
327
|
+
TESTS::
|
|
328
|
+
|
|
329
|
+
sage: rays = [(1, 1), (-1, -1), (-1, 1), (1, -1)]
|
|
330
|
+
sage: cones = [(0,2), (2,1), (1,3), (3,0)]
|
|
331
|
+
sage: fan1 = Fan(cones, rays)
|
|
332
|
+
sage: from sage.geometry.fan_isomorphism import fan_2d_echelon_form, fan_2d_echelon_forms
|
|
333
|
+
sage: echelon_forms = fan_2d_echelon_forms(fan1)
|
|
334
|
+
sage: S4 = CyclicPermutationGroup(4) # needs sage.groups
|
|
335
|
+
sage: rays.reverse()
|
|
336
|
+
sage: cones = [(3,1), (1,2), (2,0), (0,3)]
|
|
337
|
+
sage: for i in range(100): # needs sage.groups
|
|
338
|
+
....: m = random_matrix(ZZ,2,2)
|
|
339
|
+
....: if abs(det(m)) != 1: continue
|
|
340
|
+
....: perm = S4.random_element()
|
|
341
|
+
....: perm_cones = [ (perm(c[0]+1)-1, perm(c[1]+1)-1) for c in cones ]
|
|
342
|
+
....: perm_rays = [ rays[perm(i+1)-1] for i in range(len(rays)) ]
|
|
343
|
+
....: fan2 = Fan(perm_cones, rays=[m*vector(r) for r in perm_rays])
|
|
344
|
+
....: assert fan_2d_echelon_form(fan2) in echelon_forms
|
|
345
|
+
|
|
346
|
+
The trivial case was fixed in :issue:`18613`::
|
|
347
|
+
|
|
348
|
+
sage: fan = Fan([], lattice=ToricLattice(2))
|
|
349
|
+
sage: fan_2d_echelon_forms(fan)
|
|
350
|
+
frozenset({[]})
|
|
351
|
+
sage: parent(list(_)[0])
|
|
352
|
+
Full MatrixSpace of 2 by 0 dense matrices over Integer Ring
|
|
353
|
+
"""
|
|
354
|
+
if fan.nrays() == 0:
|
|
355
|
+
return frozenset([fan_2d_echelon_form(fan)])
|
|
356
|
+
rays = list(fan_2d_cyclically_ordered_rays(fan))
|
|
357
|
+
echelon_forms = []
|
|
358
|
+
for i in range(2):
|
|
359
|
+
for j in range(len(rays)):
|
|
360
|
+
echelon_forms.append(column_matrix(rays).echelon_form())
|
|
361
|
+
first = rays.pop(0)
|
|
362
|
+
rays.append(first)
|
|
363
|
+
rays.reverse()
|
|
364
|
+
return frozenset(echelon_forms)
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def fan_2d_echelon_form(fan):
|
|
368
|
+
"""
|
|
369
|
+
Return echelon form of a cyclically ordered ray matrix.
|
|
370
|
+
|
|
371
|
+
INPUT:
|
|
372
|
+
|
|
373
|
+
- ``fan`` -- a fan
|
|
374
|
+
|
|
375
|
+
OUTPUT:
|
|
376
|
+
|
|
377
|
+
A matrix. The echelon form of the rays in one particular cyclic
|
|
378
|
+
order.
|
|
379
|
+
|
|
380
|
+
EXAMPLES::
|
|
381
|
+
|
|
382
|
+
sage: fan = toric_varieties.P2().fan() # needs palp sage.graphs
|
|
383
|
+
sage: from sage.geometry.fan_isomorphism import fan_2d_echelon_form
|
|
384
|
+
sage: fan_2d_echelon_form(fan) # needs palp sage.graphs
|
|
385
|
+
[ 1 0 -1]
|
|
386
|
+
[ 0 1 -1]
|
|
387
|
+
"""
|
|
388
|
+
ray_matrix = fan_2d_cyclically_ordered_rays(fan).column_matrix()
|
|
389
|
+
return ray_matrix.echelon_form()
|