# Find isomorphisms between fans#

exception sage.geometry.fan_isomorphism.FanNotIsomorphicError[source]#

Bases: `Exception`

Exception to return if there is no fan isomorphism

sage.geometry.fan_isomorphism.fan_2d_cyclically_ordered_rays(fan)[source]#

Return the rays of a 2-dimensional `fan` in cyclic order.

INPUT:

• `fan` – a 2-dimensional fan.

OUTPUT:

A `PointCollection` containing the rays in one particular cyclic order.

EXAMPLES:

```sage: rays = ((1, 1), (-1, -1), (-1, 1), (1, -1))
sage: cones = [(0,2), (2,1), (1,3), (3,0)]
sage: fan = Fan(cones, rays)
sage: fan.rays()
N( 1,  1),
N(-1, -1),
N(-1,  1),
N( 1, -1)
in 2-d lattice N
sage: from sage.geometry.fan_isomorphism import fan_2d_cyclically_ordered_rays
sage: fan_2d_cyclically_ordered_rays(fan)
N(-1, -1),
N(-1,  1),
N( 1,  1),
N( 1, -1)
in 2-d lattice N
```
```>>> from sage.all import *
>>> rays = ((Integer(1), Integer(1)), (-Integer(1), -Integer(1)), (-Integer(1), Integer(1)), (Integer(1), -Integer(1)))
>>> cones = [(Integer(0),Integer(2)), (Integer(2),Integer(1)), (Integer(1),Integer(3)), (Integer(3),Integer(0))]
>>> fan = Fan(cones, rays)
>>> fan.rays()
N( 1,  1),
N(-1, -1),
N(-1,  1),
N( 1, -1)
in 2-d lattice N
>>> from sage.geometry.fan_isomorphism import fan_2d_cyclically_ordered_rays
>>> fan_2d_cyclically_ordered_rays(fan)
N(-1, -1),
N(-1,  1),
N( 1,  1),
N( 1, -1)
in 2-d lattice N
```
sage.geometry.fan_isomorphism.fan_2d_echelon_form(fan)[source]#

Return echelon form of a cyclically ordered ray matrix.

INPUT:

• `fan` – a fan.

OUTPUT:

A matrix. The echelon form of the rays in one particular cyclic order.

EXAMPLES:

```sage: fan = toric_varieties.P2().fan()                                          # needs palp sage.graphs
sage: from sage.geometry.fan_isomorphism import fan_2d_echelon_form
sage: fan_2d_echelon_form(fan)                                                  # needs palp sage.graphs
[ 1  0 -1]
[ 0  1 -1]
```
```>>> from sage.all import *
>>> fan = toric_varieties.P2().fan()                                          # needs palp sage.graphs
>>> from sage.geometry.fan_isomorphism import fan_2d_echelon_form
>>> fan_2d_echelon_form(fan)                                                  # needs palp sage.graphs
[ 1  0 -1]
[ 0  1 -1]
```
sage.geometry.fan_isomorphism.fan_2d_echelon_forms(fan)[source]#

Return echelon forms of all cyclically ordered ray matrices.

Note that the echelon form of the ordered ray matrices are unique up to different cyclic orderings.

INPUT:

• `fan` – a fan.

OUTPUT:

A set of matrices. The set of all echelon forms for all different cyclic orderings.

EXAMPLES:

```sage: fan = toric_varieties.P2().fan()                                          # needs palp sage.graphs
sage: from sage.geometry.fan_isomorphism import fan_2d_echelon_forms
sage: fan_2d_echelon_forms(fan)                                                 # needs palp sage.graphs
frozenset({[ 1  0 -1]
[ 0  1 -1]})

sage: fan = toric_varieties.dP7().fan()                                         # needs palp sage.graphs
sage: sorted(fan_2d_echelon_forms(fan))                                         # needs palp sage.graphs
[
[ 1  0 -1 -1  0]  [ 1  0 -1 -1  0]  [ 1  0 -1 -1  1]  [ 1  0 -1  0  1]
[ 0  1  0 -1 -1], [ 0  1  1  0 -1], [ 0  1  1  0 -1], [ 0  1  0 -1 -1],

[ 1  0 -1  0  1]
[ 0  1  1 -1 -1]
]
```
```>>> from sage.all import *
>>> fan = toric_varieties.P2().fan()                                          # needs palp sage.graphs
>>> from sage.geometry.fan_isomorphism import fan_2d_echelon_forms
>>> fan_2d_echelon_forms(fan)                                                 # needs palp sage.graphs
frozenset({[ 1  0 -1]
[ 0  1 -1]})

>>> fan = toric_varieties.dP7().fan()                                         # needs palp sage.graphs
>>> sorted(fan_2d_echelon_forms(fan))                                         # needs palp sage.graphs
[
[ 1  0 -1 -1  0]  [ 1  0 -1 -1  0]  [ 1  0 -1 -1  1]  [ 1  0 -1  0  1]
[ 0  1  0 -1 -1], [ 0  1  1  0 -1], [ 0  1  1  0 -1], [ 0  1  0 -1 -1],
<BLANKLINE>
[ 1  0 -1  0  1]
[ 0  1  1 -1 -1]
]
```
sage.geometry.fan_isomorphism.fan_isomorphic_necessary_conditions(fan1, fan2)[source]#

Check necessary (but not sufficient) conditions for the fans to be isomorphic.

INPUT:

• `fan1`, `fan2` – two fans.

OUTPUT:

Boolean. `False` if the two fans cannot be isomorphic. `True` if the two fans may be isomorphic.

EXAMPLES:

```sage: fan1 = toric_varieties.P2().fan()                                         # needs palp sage.graphs
sage: fan2 = toric_varieties.dP8().fan()                                        # needs palp sage.graphs
sage: from sage.geometry.fan_isomorphism import fan_isomorphic_necessary_conditions
sage: fan_isomorphic_necessary_conditions(fan1, fan2)                           # needs palp sage.graphs
False
```
```>>> from sage.all import *
>>> fan1 = toric_varieties.P2().fan()                                         # needs palp sage.graphs
>>> fan2 = toric_varieties.dP8().fan()                                        # needs palp sage.graphs
>>> from sage.geometry.fan_isomorphism import fan_isomorphic_necessary_conditions
>>> fan_isomorphic_necessary_conditions(fan1, fan2)                           # needs palp sage.graphs
False
```
sage.geometry.fan_isomorphism.fan_isomorphism_generator(fan1, fan2)[source]#

Iterate over the isomorphisms from `fan1` to `fan2`.

ALGORITHM:

The `sage.geometry.fan.Fan.vertex_graph()` of the two fans is compared. For each graph isomorphism, we attempt to lift it to an actual isomorphism of fans.

INPUT:

• `fan1`, `fan2` – two fans.

OUTPUT:

Yields the fan isomorphisms as matrices acting from the right on rays.

EXAMPLES:

```sage: fan = toric_varieties.P2().fan()                                          # needs palp sage.graphs
sage: from sage.geometry.fan_isomorphism import fan_isomorphism_generator
sage: sorted(fan_isomorphism_generator(fan, fan))                               # needs palp sage.graphs
[
[-1 -1]  [-1 -1]  [ 0  1]  [0 1]  [ 1  0]  [1 0]
[ 0  1], [ 1  0], [-1 -1], [1 0], [-1 -1], [0 1]
]
sage: m1 = matrix([(1, 0), (0, -5), (-3, 4)])
sage: m2 = matrix([(3, 0), (1, 0), (-2, 1)])
sage: m1.elementary_divisors() == m2.elementary_divisors() == [1,1,0]
True
sage: fan1 = Fan([Cone([m1*vector([23, 14]), m1*vector([   3,100])]),
....:             Cone([m1*vector([-1,-14]), m1*vector([-100, -5])])])
sage: fan2 = Fan([Cone([m2*vector([23, 14]), m2*vector([   3,100])]),
....:             Cone([m2*vector([-1,-14]), m2*vector([-100, -5])])])
sage: sorted(fan_isomorphism_generator(fan1, fan2))                             # needs sage.graphs
[
[-12  1 -5]
[ -4  0 -1]
[ -5  0 -1]
]

sage: m0 = identity_matrix(ZZ, 2)
sage: m1 = matrix([(1, 0), (0, -5), (-3, 4)])
sage: m2 = matrix([(3, 0), (1, 0), (-2, 1)])
sage: m1.elementary_divisors() == m2.elementary_divisors() == [1,1,0]
True
sage: fan0 = Fan([Cone([m0*vector([1,0]), m0*vector([1,1])]),
....:             Cone([m0*vector([1,1]), m0*vector([0,1])])])
sage: fan1 = Fan([Cone([m1*vector([1,0]), m1*vector([1,1])]),
....:             Cone([m1*vector([1,1]), m1*vector([0,1])])])
sage: fan2 = Fan([Cone([m2*vector([1,0]), m2*vector([1,1])]),
....:             Cone([m2*vector([1,1]), m2*vector([0,1])])])
sage: sorted(fan_isomorphism_generator(fan0, fan0))                             # needs sage.graphs
[
[0 1]  [1 0]
[1 0], [0 1]
]
sage: sorted(fan_isomorphism_generator(fan1, fan1))                             # needs sage.graphs
[
[ -3 -20  28]  [1 0 0]
[ -1  -4   7]  [0 1 0]
[ -1  -5   8], [0 0 1]
]
sage: sorted(fan_isomorphism_generator(fan1, fan2))                             # needs sage.graphs
[
[-24  -3   7]  [-12   1  -5]
[ -7  -1   2]  [ -4   0  -1]
[ -8  -1   2], [ -5   0  -1]
]
sage: sorted(fan_isomorphism_generator(fan2, fan1))                             # needs sage.graphs
[
[  0   1  -1]  [ 0  1 -1]
[  1 -13   8]  [ 2 -8  1]
[  0  -5   4], [ 1  0 -3]
]
```
```>>> from sage.all import *
>>> fan = toric_varieties.P2().fan()                                          # needs palp sage.graphs
>>> from sage.geometry.fan_isomorphism import fan_isomorphism_generator
>>> sorted(fan_isomorphism_generator(fan, fan))                               # needs palp sage.graphs
[
[-1 -1]  [-1 -1]  [ 0  1]  [0 1]  [ 1  0]  [1 0]
[ 0  1], [ 1  0], [-1 -1], [1 0], [-1 -1], [0 1]
]
>>> m1 = matrix([(Integer(1), Integer(0)), (Integer(0), -Integer(5)), (-Integer(3), Integer(4))])
>>> m2 = matrix([(Integer(3), Integer(0)), (Integer(1), Integer(0)), (-Integer(2), Integer(1))])
>>> m1.elementary_divisors() == m2.elementary_divisors() == [Integer(1),Integer(1),Integer(0)]
True
>>> fan1 = Fan([Cone([m1*vector([Integer(23), Integer(14)]), m1*vector([   Integer(3),Integer(100)])]),
...             Cone([m1*vector([-Integer(1),-Integer(14)]), m1*vector([-Integer(100), -Integer(5)])])])
>>> fan2 = Fan([Cone([m2*vector([Integer(23), Integer(14)]), m2*vector([   Integer(3),Integer(100)])]),
...             Cone([m2*vector([-Integer(1),-Integer(14)]), m2*vector([-Integer(100), -Integer(5)])])])
>>> sorted(fan_isomorphism_generator(fan1, fan2))                             # needs sage.graphs
[
[-12  1 -5]
[ -4  0 -1]
[ -5  0 -1]
]

>>> m0 = identity_matrix(ZZ, Integer(2))
>>> m1 = matrix([(Integer(1), Integer(0)), (Integer(0), -Integer(5)), (-Integer(3), Integer(4))])
>>> m2 = matrix([(Integer(3), Integer(0)), (Integer(1), Integer(0)), (-Integer(2), Integer(1))])
>>> m1.elementary_divisors() == m2.elementary_divisors() == [Integer(1),Integer(1),Integer(0)]
True
>>> fan0 = Fan([Cone([m0*vector([Integer(1),Integer(0)]), m0*vector([Integer(1),Integer(1)])]),
...             Cone([m0*vector([Integer(1),Integer(1)]), m0*vector([Integer(0),Integer(1)])])])
>>> fan1 = Fan([Cone([m1*vector([Integer(1),Integer(0)]), m1*vector([Integer(1),Integer(1)])]),
...             Cone([m1*vector([Integer(1),Integer(1)]), m1*vector([Integer(0),Integer(1)])])])
>>> fan2 = Fan([Cone([m2*vector([Integer(1),Integer(0)]), m2*vector([Integer(1),Integer(1)])]),
...             Cone([m2*vector([Integer(1),Integer(1)]), m2*vector([Integer(0),Integer(1)])])])
>>> sorted(fan_isomorphism_generator(fan0, fan0))                             # needs sage.graphs
[
[0 1]  [1 0]
[1 0], [0 1]
]
>>> sorted(fan_isomorphism_generator(fan1, fan1))                             # needs sage.graphs
[
[ -3 -20  28]  [1 0 0]
[ -1  -4   7]  [0 1 0]
[ -1  -5   8], [0 0 1]
]
>>> sorted(fan_isomorphism_generator(fan1, fan2))                             # needs sage.graphs
[
[-24  -3   7]  [-12   1  -5]
[ -7  -1   2]  [ -4   0  -1]
[ -8  -1   2], [ -5   0  -1]
]
>>> sorted(fan_isomorphism_generator(fan2, fan1))                             # needs sage.graphs
[
[  0   1  -1]  [ 0  1 -1]
[  1 -13   8]  [ 2 -8  1]
[  0  -5   4], [ 1  0 -3]
]
```
sage.geometry.fan_isomorphism.find_isomorphism(fan1, fan2, check=False)[source]#

Find an isomorphism of the two fans.

INPUT:

• `fan1`, `fan2` – two fans.

• `check` – boolean (default: `False`). Passed to the fan morphism constructor, see `FanMorphism()`.

OUTPUT:

A fan isomorphism. If the fans are not isomorphic, a `FanNotIsomorphicError` is raised.

EXAMPLES:

```sage: rays = ((1, 1), (0, 1), (-1, -1), (3, 1))
sage: cones = [(0,1), (1,2), (2,3), (3,0)]
sage: fan1 = Fan(cones, rays)

sage: m = matrix([[-2,3],[1,-1]])
sage: m.det() == -1
True
sage: fan2 = Fan(cones, [vector(r)*m for r in rays])

sage: from sage.geometry.fan_isomorphism import find_isomorphism
sage: find_isomorphism(fan1, fan2, check=True)                                  # needs sage.graphs
Fan morphism defined by the matrix
[-2  3]
[ 1 -1]
Domain fan: Rational polyhedral fan in 2-d lattice N
Codomain fan: Rational polyhedral fan in 2-d lattice N

sage: find_isomorphism(fan1, toric_varieties.P2().fan())                        # needs palp sage.graphs
Traceback (most recent call last):
...
FanNotIsomorphicError

sage: fan1 = Fan(cones=[[1,3,4,5],[0,1,2,3],[2,3,4],[0,1,5]],
....:            rays=[(-1,-1,0),(-1,-1,3),(-1,1,-1),(-1,3,-1),(0,2,-1),(1,-1,1)])
sage: fan2 = Fan(cones=[[0,2,3,5],[0,1,4,5],[0,1,2],[3,4,5]],
....:            rays=[(-1,-1,-1),(-1,-1,0),(-1,1,-1),(0,2,-1),(1,-1,1),(3,-1,-1)])
sage: fan1.is_isomorphic(fan2)                                                  # needs sage.graphs
True
```
```>>> from sage.all import *
>>> rays = ((Integer(1), Integer(1)), (Integer(0), Integer(1)), (-Integer(1), -Integer(1)), (Integer(3), Integer(1)))
>>> cones = [(Integer(0),Integer(1)), (Integer(1),Integer(2)), (Integer(2),Integer(3)), (Integer(3),Integer(0))]
>>> fan1 = Fan(cones, rays)

>>> m = matrix([[-Integer(2),Integer(3)],[Integer(1),-Integer(1)]])
>>> m.det() == -Integer(1)
True
>>> fan2 = Fan(cones, [vector(r)*m for r in rays])

>>> from sage.geometry.fan_isomorphism import find_isomorphism
>>> find_isomorphism(fan1, fan2, check=True)                                  # needs sage.graphs
Fan morphism defined by the matrix
[-2  3]
[ 1 -1]
Domain fan: Rational polyhedral fan in 2-d lattice N
Codomain fan: Rational polyhedral fan in 2-d lattice N

>>> find_isomorphism(fan1, toric_varieties.P2().fan())                        # needs palp sage.graphs
Traceback (most recent call last):
...
FanNotIsomorphicError

>>> fan1 = Fan(cones=[[Integer(1),Integer(3),Integer(4),Integer(5)],[Integer(0),Integer(1),Integer(2),Integer(3)],[Integer(2),Integer(3),Integer(4)],[Integer(0),Integer(1),Integer(5)]],
...            rays=[(-Integer(1),-Integer(1),Integer(0)),(-Integer(1),-Integer(1),Integer(3)),(-Integer(1),Integer(1),-Integer(1)),(-Integer(1),Integer(3),-Integer(1)),(Integer(0),Integer(2),-Integer(1)),(Integer(1),-Integer(1),Integer(1))])
>>> fan2 = Fan(cones=[[Integer(0),Integer(2),Integer(3),Integer(5)],[Integer(0),Integer(1),Integer(4),Integer(5)],[Integer(0),Integer(1),Integer(2)],[Integer(3),Integer(4),Integer(5)]],
...            rays=[(-Integer(1),-Integer(1),-Integer(1)),(-Integer(1),-Integer(1),Integer(0)),(-Integer(1),Integer(1),-Integer(1)),(Integer(0),Integer(2),-Integer(1)),(Integer(1),-Integer(1),Integer(1)),(Integer(3),-Integer(1),-Integer(1))])
>>> fan1.is_isomorphic(fan2)                                                  # needs sage.graphs
True
```