This module was designed as a part of the framework for toric varieties
(toric_variety,
fano_toric_variety). While the emphasis is on
complete full-dimensional fans, arbitrary fans are supported. Work
with distinct lattices. The default lattice is ToricLattice of the appropriate
dimension. The only case when you must specify lattice explicitly is creation
of a 0-dimensional fan, where dimension of the ambient space cannot be
guessed.
A rational polyhedral fan is a finite collection of strictly convex rational polyhedral cones, such that the intersection of any two cones of the fan is a face of each of them and each face of each cone is also a cone of the fan.
AUTHORS:
EXAMPLES:
Use Fan() to construct fans “explicitly”:
sage: fan = Fan(cones=[(0,1), (1,2)],
... rays=[(1,0), (0,1), (-1,0)])
sage: fan
Rational polyhedral fan in 2-d lattice N
In addition to giving such lists of cones and rays you can also create cones first using Cone() and then combine them into a fan. See the documentation of Fan() for details.
Instead of building a fan from scratch, for this tutorial we will use an easy way to get two fans assosiated to lattice polytopes: FaceFan() and NormalFan():
sage: fan1 = FaceFan(lattice_polytope.octahedron(3))
sage: fan2 = NormalFan(lattice_polytope.octahedron(3))
Given such “automatic” fans, you may wonder what are their rays and cones:
sage: fan1.rays()
(N(1, 0, 0), N(0, 1, 0), N(0, 0, 1),
N(-1, 0, 0), N(0, -1, 0), N(0, 0, -1))
sage: fan1.ray_matrix()
[ 1 0 0 -1 0 0]
[ 0 1 0 0 -1 0]
[ 0 0 1 0 0 -1]
sage: fan1.generating_cones()
(3-d cone of Rational polyhedral fan in 3-d lattice N,
3-d cone of Rational polyhedral fan in 3-d lattice N,
3-d cone of Rational polyhedral fan in 3-d lattice N,
3-d cone of Rational polyhedral fan in 3-d lattice N,
3-d cone of Rational polyhedral fan in 3-d lattice N,
3-d cone of Rational polyhedral fan in 3-d lattice N,
3-d cone of Rational polyhedral fan in 3-d lattice N,
3-d cone of Rational polyhedral fan in 3-d lattice N)
The last output is not very illuminating. Let’s try to improve it:
sage: for cone in fan1: print cone.rays()
(N(1, 0, 0), N(0, 1, 0), N(0, 0, -1))
(N(0, 1, 0), N(-1, 0, 0), N(0, 0, -1))
(N(1, 0, 0), N(0, -1, 0), N(0, 0, -1))
(N(-1, 0, 0), N(0, -1, 0), N(0, 0, -1))
(N(1, 0, 0), N(0, 1, 0), N(0, 0, 1))
(N(0, 1, 0), N(0, 0, 1), N(-1, 0, 0))
(N(1, 0, 0), N(0, 0, 1), N(0, -1, 0))
(N(0, 0, 1), N(-1, 0, 0), N(0, -1, 0))
You can also do
sage: for cone in fan1: print cone.ambient_ray_indices()
(0, 1, 5)
(1, 3, 5)
(0, 4, 5)
(3, 4, 5)
(0, 1, 2)
(1, 2, 3)
(0, 2, 4)
(2, 3, 4)
to see indices of rays of the fan corresponding to each cone.
While the above cycles were over “cones in fan”, it is obvious that we did not get ALL the cones: every face of every cone in a fan must also be in the fan, but all of the above cones were of dimension three. The reason for this behaviour is that in many cases it is enough to work with generating cones of the fan, i.e. cones which are not faces of bigger cones. When you do need to work with lower dimensional cones, you can easily get access to them using cones():
sage: [cone.ambient_ray_indices() for cone in fan1.cones(2)]
[(0, 1), (0, 2), (1, 2), (1, 3), (2, 3), (0, 4),
(2, 4), (3, 4), (1, 5), (3, 5), (4, 5), (0, 5)]
In fact, you don’t have to type .cones:
sage: [cone.ambient_ray_indices() for cone in fan1(2)]
[(0, 1), (0, 2), (1, 2), (1, 3), (2, 3), (0, 4),
(2, 4), (3, 4), (1, 5), (3, 5), (4, 5), (0, 5)]
You may also need to know the inclusion relations between all of the cones of the fan. In this case check out cone_lattice():
sage: L = fan1.cone_lattice()
sage: L
Finite poset containing 28 elements
sage: L.bottom()
0-d cone of Rational polyhedral fan in 3-d lattice N
sage: L.top()
Rational polyhedral fan in 3-d lattice N
sage: cone = L.level_sets()[2][0]
sage: cone
2-d cone of Rational polyhedral fan in 3-d lattice N
sage: L.hasse_diagram().neighbors(cone)
[3-d cone of Rational polyhedral fan in 3-d lattice N,
3-d cone of Rational polyhedral fan in 3-d lattice N,
1-d cone of Rational polyhedral fan in 3-d lattice N,
1-d cone of Rational polyhedral fan in 3-d lattice N]
Note, that while cone above seems to be a “cone”, it is not:
sage: cone.rays()
Traceback (most recent call last):
...
AttributeError: 'PosetElement' object has no attribute 'rays'
To get your hands on the “real” cone, you need to do one more step:
sage: cone = cone.element
sage: cone.rays()
(N(1, 0, 0), N(0, 1, 0))
You can check how “good” a fan is:
sage: fan1.is_complete()
True
sage: fan1.is_simplicial()
True
sage: fan1.is_smooth()
True
The face fan of the octahedron is really good! Time to remember that we have also constructed its normal fan:
sage: fan2.is_complete()
True
sage: fan2.is_simplicial()
False
sage: fan2.is_smooth()
False
This one does have some “problems,” but we can fix them:
sage: fan3 = fan2.make_simplicial()
sage: fan3.is_simplicial()
True
sage: fan3.is_smooth()
False
Note that we had to save the result of make_simplicial() in a new fan. Fans in Sage are immutable, so any operation that does change them constructs a new fan.
We can also make fan3 smooth, but it will take a bit more work:
sage: cube = lattice_polytope.octahedron(3).polar()
sage: sk = cube.skeleton_points(2)
sage: rays = [cube.point(p) for p in sk]
sage: fan4 = fan3.subdivide(new_rays=rays)
sage: fan4.is_smooth()
True
Let’s see how “different” are fan2 and fan4:
sage: fan2.ngenerating_cones()
6
sage: fan2.nrays()
8
sage: fan4.ngenerating_cones()
48
sage: fan4.nrays()
26
Smoothness does not come for free!
Please take a look at the rest of the available functions below and their complete descriptions. If you need any features that are missing, feel free to suggest them. (Or implement them on your own and submit a patch to Sage for inclusion!)
Bases: sage.geometry.cone.ConvexRationalPolyhedralCone
Construct a cone belonging to a fan.
Warning
This class does not check that the input defines a valid cone of a fan. You must not construct objects of this class directly.
In addition to all of the properties of “regular” cones, such cones know their relation to the fan.
INPUT:
OUTPUT:
EXAMPLES:
The intended way to get objects of this class is the following:
sage: P1xP1 = FaceFan(lattice_polytope.octahedron(2))
sage: cone = P1xP1.generating_cone(0)
sage: cone
2-d cone of Rational polyhedral fan in 2-d lattice N
sage: cone.ambient_ray_indices()
(0, 3)
sage: cone.star_generator_indices()
(0,)
Return indices of generating cones of the “ambient fan” containing self.
OUTPUT:
EXAMPLES:
sage: P1xP1 = FaceFan(lattice_polytope.octahedron(2))
sage: cone = P1xP1.generating_cone(0)
sage: cone.star_generator_indices()
(0,)
TESTS:
A mistake in this function used to cause the problem reported in Trac 9782. We check that now everything is working smoothly:
sage: f = Fan([(0, 2, 4),
... (0, 4, 5),
... (0, 3, 5),
... (0, 1, 3),
... (0, 1, 2),
... (2, 4, 6),
... (4, 5, 6),
... (3, 5, 6),
... (1, 3, 6),
... (1, 2, 6)],
... [(-1, 0, 0),
... (0, -1, 0),
... (0, 0, -1),
... (0, 0, 1),
... (0, 1, 2),
... (0, 1, 3),
... (1, 0, 4)])
sage: f.is_complete()
True
sage: X = ToricVariety(f)
sage: X.fan().is_complete()
True
Return indices of generating cones of the “ambient fan” containing self.
OUTPUT:
EXAMPLES:
sage: P1xP1 = FaceFan(lattice_polytope.octahedron(2))
sage: cone = P1xP1.generating_cone(0)
sage: cone.star_generators()
(2-d cone of Rational polyhedral fan in 2-d lattice N,)
Construct the face fan of the given lattice polytope.
INPUT:
OUTPUT:
See also NormalFan().
EXAMPLES:
Let’s construct the fan corresponding to the product of two projective lines:
sage: diamond = lattice_polytope.octahedron(2)
sage: P1xP1 = FaceFan(diamond)
sage: P1xP1.ray_matrix()
[ 1 0 -1 0]
[ 0 1 0 -1]
sage: for cone in P1xP1: print cone.rays()
(N(1, 0), N(0, -1))
(N(-1, 0), N(0, -1))
(N(1, 0), N(0, 1))
(N(0, 1), N(-1, 0))
Construct a rational polyhedral fan.
Note
Approximate time to construct a fan consisting of cones is
seconds. That is half an hour for 100 cones. This time can be
significantly reduced in the future, but it is still likely to be
(with, say,
instead of
). If you know that your
input does form a valid fan, use check=False option to skip
consistency checks.
INPUT:
OUTPUT:
EXAMPLES:
Let’s construct a fan corresponding to the projective plane in several ways:
sage: cone1 = Cone([(1,0), (0,1)])
sage: cone2 = Cone([(0,1), (-1,-1)])
sage: cone3 = Cone([(-1,-1), (1,0)])
sage: P2 = Fan([cone1, cone2, cone2]) # random output (warning)
sage: P2.ngenerating_cones()
2
Oops! There was a typo and the second cone2 got discarded (you will actually see a warning the first time you do such a thing yourself, i.e. provide a non-minimal generating set of cones of a fan). Let’s fix it:
sage: P2 = Fan([cone1, cone2, cone3])
sage: P2.ngenerating_cones()
3
Looks better. An alternative way is
sage: rays = [(1,0), (0,1), (-1,-1)]
sage: cones = [(0,1), (1,2), (2,0)]
sage: P2a = Fan(cones, rays)
sage: P2a.ngenerating_cones()
3
sage: P2 == P2a
False
That may seem wrong, but it is not:
sage: P2.is_equivalent(P2a)
True
See is_equivalent() for details.
Yet another way to construct this fan is
sage: P2b = Fan(cones, rays, check=False)
sage: P2b.ngenerating_cones()
3
sage: P2a == P2b
True
If you try the above examples, you are likely to notice the difference in speed, so when you are sure that everything is correct, it is a good idea to use check=False option. On the other hand, it is usually NOT a good idea to use normalize=False option:
sage: P2c = Fan(cones, rays, check=False, normalize=False)
Traceback (most recent call last):
...
AttributeError: 'tuple' object has no attribute 'parent'
Yet another way is to use functions FaceFan() and NormalFan() to construct fans from lattice polytopes.
We have not yet used lattice argument, since if was determined automatically:
sage: P2.lattice()
2-d lattice N
sage: P2b.lattice()
2-d lattice N
However, it is necessary to specify it explicitly if you want to construct a fan without rays or cones:
sage: Fan([], [])
Traceback (most recent call last):
...
ValueError: you must specify the lattice
when you construct a fan without rays and cones!
sage: F = Fan([], [], lattice=ToricLattice(2, "L"))
sage: F
Rational polyhedral fan in 2-d lattice L
sage: F.lattice_dim()
2
sage: F.dim()
0
Construct the normal fan of the given lattice polytope.
INPUT:
OUTPUT:
See also FaceFan().
EXAMPLES:
Let’s construct the fan corresponding to the product of two projective lines:
sage: square = lattice_polytope.octahedron(2).polar()
sage: P1xP1 = NormalFan(square)
sage: P1xP1.ray_matrix()
[ 1 0 -1 0]
[ 0 1 0 -1]
sage: for cone in P1xP1: print cone.rays()
(N(1, 0), N(0, -1))
(N(-1, 0), N(0, -1))
(N(1, 0), N(0, 1))
(N(0, 1), N(-1, 0))
Bases: sage.geometry.cone.IntegralRayCollection, _abcoll.Callable, _abcoll.Container
Create a rational polyhedral fan.
Warning
This class does not perform any checks of correctness of input nor does it convert input into the standard representation. Use Fan() to construct fans from “raw data” or FaceFan() and NormalFan() to get fans associated to polytopes.
Fans are immutable, but they cache most of the returned values.
INPUT:
OUTPUT:
Return the Gale transform of self.
OUTPUT:
A matrix over .
EXAMPLES:
sage: fan = FaceFan(lattice_polytope.octahedron(2))
sage: fan.Gale_transform()
[ 1 0 1 0 -2]
[ 0 1 0 1 -2]
sage: _.base_ring()
Integer Ring
Return the Stanley-Reisner ideal.
INPUT:
OUTPUT:
EXAMPLES:
sage: fan = Fan([[0,1,3],[3,4],[2,0],[1,2,4]], [(-3, -2, 1), (0, 0, 1), (3, -2, 1), (-1, -1, 1), (1, -1, 1)])
sage: fan.Stanley_Reisner_ideal( PolynomialRing(QQ,5,'A, B, C, D, E') )
Ideal (A*E, C*D, A*B*C, B*D*E) of Multivariate Polynomial Ring in A, B, C, D, E over Rational Field
Return the Cartesian product of self with other.
INPUT:
OUTPUT:
EXAMPLES:
sage: K = ToricLattice(1, 'K')
sage: fan1 = Fan([[0],[1]],[(1,),(-1,)], lattice=K)
sage: L = ToricLattice(2, 'L')
sage: fan2 = Fan(rays=[(1,0),(0,1),(-1,-1)],
... cones=[[0,1],[1,2],[2,0]], lattice=L)
sage: fan1.cartesian_product(fan2)
Rational polyhedral fan in 3-d lattice K+L
sage: _.ngenerating_cones()
6
Return the smallest cone of self containing all given points.
INPUT:
OUTPUT:
Note
We think of the origin as of the smallest cone containing no rays at all. If there is no ray in self that contains all rays, a ValueError exception will be raised.
EXAMPLES:
sage: cone1 = Cone([(0,-1), (1,0)])
sage: cone2 = Cone([(1,0), (0,1)])
sage: f = Fan([cone1, cone2])
sage: f.rays()
(N(0, 1), N(0, -1), N(1, 0))
sage: f.cone_containing(0) # ray index
1-d cone of Rational polyhedral fan in 2-d lattice N
sage: f.cone_containing(0, 1) # ray indices
Traceback (most recent call last):
...
ValueError: there is no cone in
Rational polyhedral fan in 2-d lattice N
containing all of the given rays! Rays: (N(0, 1), N(0, -1))
sage: f.cone_containing(0, 2) # ray indices
2-d cone of Rational polyhedral fan in 2-d lattice N
sage: f.cone_containing((0,1)) # point
1-d cone of Rational polyhedral fan in 2-d lattice N
sage: f.cone_containing([(0,1)]) # point
1-d cone of Rational polyhedral fan in 2-d lattice N
sage: f.cone_containing((1,1))
2-d cone of Rational polyhedral fan in 2-d lattice N
sage: f.cone_containing((1,1), (1,0))
2-d cone of Rational polyhedral fan in 2-d lattice N
sage: f.cone_containing()
0-d cone of Rational polyhedral fan in 2-d lattice N
sage: f.cone_containing((0,0))
0-d cone of Rational polyhedral fan in 2-d lattice N
sage: f.cone_containing((-1,1))
Traceback (most recent call last):
...
ValueError: there is no cone in
Rational polyhedral fan in 2-d lattice N
containing all of the given points! Points: [N(-1, 1)]
TESTS:
sage: fan = Fan(cones=[(0,1,2,3), (0,1,4)],
... rays=[(1,1,1), (1,-1,1), (1,-1,-1), (1,1,-1), (0,0,1)])
sage: fan.cone_containing(0).rays()
(N(1, 1, 1),)
Return the cone lattice of self.
This lattice will have the origin as the bottom (we do not include the empty set as a cone) and the fan itself as the top.
OUTPUT:
See also cones().
EXAMPLES:
Cone lattices can be computed for arbitrary fans:
sage: cone1 = Cone([(1,0), (0,1)])
sage: cone2 = Cone([(-1,0)])
sage: fan = Fan([cone1, cone2])
sage: fan.ray_matrix()
[ 0 1 -1]
[ 1 0 0]
sage: for cone in fan: print cone.ambient_ray_indices()
(0, 1)
(2,)
sage: L = fan.cone_lattice()
sage: L
Finite poset containing 6 elements
These 6 elements are the origin, three rays, one two-dimensional cone, and the fan itself. Since we do add the fan itself as the largest face, you should be a little bit careful with this last element:
sage: for face in L: print face.element.ambient_ray_indices()
Traceback (most recent call last):
...
AttributeError: 'RationalPolyhedralFan'
object has no attribute 'ambient_ray_indices'
sage: L.top()
Rational polyhedral fan in 2-d lattice N
For example, you can do
sage: for l in L.level_sets()[:-1]:
... print [f.element.ambient_ray_indices() for f in l]
[()]
[(0,), (1,), (2,)]
[(0, 1)]
If the fan is complete, its cone lattice is atomic and coatomic and can (and will!) be computed in a much more efficient way, but the interface is exactly the same:
sage: fan = FaceFan(lattice_polytope.octahedron(2))
sage: L = fan.cone_lattice()
sage: for l in L.level_sets()[:-1]:
... print [f.element.ambient_ray_indices() for f in l]
[()]
[(0,), (1,), (2,), (3,)]
[(0, 1), (1, 2), (0, 3), (2, 3)]
Let’s also consider the cone lattice of a fan generated by a single cone:
sage: fan = Fan([cone1])
sage: L = fan.cone_lattice()
sage: L
Finite poset containing 5 elements
Here these 5 elements correspond to the origin, two rays, one generating cone of dimension two, and the whole fan. While this single cone “is” the whole fan, it is consistent and convenient to distinguish them in the cone lattice.
Return the specified cones of self.
INPUT:
Note
You can specify at most one input parameter.
OUTPUT:
EXAMPLES:
sage: cone1 = Cone([(1,0), (0,1)])
sage: cone2 = Cone([(-1,0)])
sage: fan = Fan([cone1, cone2])
sage: fan(dim=0)
(0-d cone of Rational polyhedral fan in 2-d lattice N,)
sage: fan(codim=2)
(0-d cone of Rational polyhedral fan in 2-d lattice N,)
sage: for cone in fan.cones(1): cone.ray(0)
N(0, 1)
N(1, 0)
N(-1, 0)
sage: fan.cones(2)
(2-d cone of Rational polyhedral fan in 2-d lattice N,)
You cannot specify both dimension and codimension, even if they “agree”:
sage: fan(dim=1, codim=1)
Traceback (most recent call last):
...
ValueError: dimension and codimension
cannot be specified together!
But it is OK to ask for cones of too high or low (co)dimension:
sage: fan(-1)
()
sage: fan(3)
()
sage: fan(codim=4)
()
Check if a given cone is equivalent to a cone of the fan.
INPUT:
OUTPUT:
Note
Recall that a fan is a (finite) collection of cones. A cone is contained in a fan if it is equivalent to one of the cones of the fan. In particular, it is possible that all rays of the cone are in the fan, but the cone itself is not.
If you want to know whether a point is in the support of the fan, you should use support_contains().
EXAMPLES:
We first construct a simple fan:
sage: cone1 = Cone([(0,-1), (1,0)])
sage: cone2 = Cone([(1,0), (0,1)])
sage: f = Fan([cone1, cone2])
Now we check if some cones are in this fan. First, we make sure that the order of rays of the input cone does not matter (check=False option ensures that rays of these cones will be listed exactly as they are given):
sage: f.contains(Cone([(1,0), (0,1)], check=False))
True
sage: f.contains(Cone([(0,1), (1,0)], check=False))
True
Now we check that a non-generating cone is in our fan:
sage: f.contains(Cone([(1,0)]))
True
sage: Cone([(1,0)]) in f # equivalent to the previous command
True
Finally, we test some cones which are not in this fan:
sage: f.contains(Cone([(1,1)]))
False
sage: f.contains(Cone([(1,0), (-0,1)]))
True
A point is not a cone:
sage: n = f.lattice()(1,1); n
N(1, 1)
sage: f.contains(n)
False
Return the cone equivalent to the given one, but sitting in self.
You may need to use this method before calling methods of cone that depend on the ambient structure, such as ambient_ray_indices() or facet_of(). The cone returned by this method will have self as ambient. If cone does not represent a valid cone of self, ValueError exception is raised.
Note
This method is very quick if self is already the ambient structure of cone, so you can use without extra checks and performance hit even if cone is likely to sit in self but in principle may not.
INPUT:
OUTPUT:
EXAMPLES:
Let’s take a 3-d fan generated by a cone on 4 rays:
sage: f = Fan([Cone([(1,0,1), (0,1,1), (-1,0,1), (0,-1,1)])])
Then any ray generates a 1-d cone of this fan, but if you construct such a cone directly, it will not “sit” inside the fan:
sage: ray = Cone([(0,-1,1)])
sage: ray
1-d cone in 3-d lattice N
sage: ray.ambient_ray_indices()
(0,)
sage: ray.adjacent()
()
sage: ray.ambient()
1-d cone in 3-d lattice N
If we want to operate with this ray as a part of the fan, we need to embed it first:
sage: e_ray = f.embed(ray)
sage: e_ray
1-d cone of Rational polyhedral fan in 3-d lattice N
sage: e_ray.rays()
(N(0, -1, 1),)
sage: e_ray is ray
False
sage: e_ray.is_equivalent(ray)
True
sage: e_ray.ambient_ray_indices()
(3,)
sage: e_ray.adjacent()
(1-d cone of Rational polyhedral fan in 3-d lattice N,
1-d cone of Rational polyhedral fan in 3-d lattice N)
sage: e_ray.ambient()
Rational polyhedral fan in 3-d lattice N
Not every cone can be embedded into a fixed fan:
sage: f.embed(Cone([(0,0,1)]))
Traceback (most recent call last):
...
ValueError: 1-d cone in 3-d lattice N does not belong
to Rational polyhedral fan in 3-d lattice N!
sage: f.embed(Cone([(1,0,1), (-1,0,1)]))
Traceback (most recent call last):
...
ValueError: 2-d cone in 3-d lattice N does not belong
to Rational polyhedral fan in 3-d lattice N!
Return the n-th generating cone of self.
INPUT:
OUTPUT:
EXAMPLES:
sage: fan = FaceFan(lattice_polytope.octahedron(2))
sage: fan.generating_cone(0)
2-d cone of Rational polyhedral fan in 2-d lattice N
Return generating cones of self.
OUTPUT:
EXAMPLES:
sage: fan = FaceFan(lattice_polytope.octahedron(2))
sage: fan.generating_cones()
(2-d cone of Rational polyhedral fan in 2-d lattice N,
2-d cone of Rational polyhedral fan in 2-d lattice N,
2-d cone of Rational polyhedral fan in 2-d lattice N,
2-d cone of Rational polyhedral fan in 2-d lattice N)
sage: cone1 = Cone([(1,0), (0,1)])
sage: cone2 = Cone([(-1,0)])
sage: fan = Fan([cone1, cone2])
sage: fan.generating_cones()
(2-d cone of Rational polyhedral fan in 2-d lattice N,
1-d cone of Rational polyhedral fan in 2-d lattice N)
Check if self is complete.
A rational polyhedral fan is complete if its cones fill the whole space.
OUTPUT:
EXAMPLES:
sage: fan = FaceFan(lattice_polytope.octahedron(2))
sage: fan.is_complete()
True
sage: cone1 = Cone([(1,0), (0,1)])
sage: cone2 = Cone([(-1,0)])
sage: fan = Fan([cone1, cone2])
sage: fan.is_complete()
False
Check if self is “mathematically” the same as other.
INPUT:
OUTPUT:
There are three different equivalences between fans and
in the same lattice:
EXAMPLES:
sage: fan1 = Fan(cones=[(0,1), (1,2)],
... rays=[(1,0), (0,1), (-1,-1)],
... check=False)
sage: fan2 = Fan(cones=[(2,1), (0,2)],
... rays=[(1,0), (-1,-1), (0,1)],
... check=False)
sage: fan3 = Fan(cones=[(0,1), (1,2)],
... rays=[(1,0), (0,1), (-1,1)],
... check=False)
sage: fan1 == fan2
False
sage: fan1.is_equivalent(fan2)
True
sage: fan1 == fan3
False
sage: fan1.is_equivalent(fan3)
False
Check if self is in the same -orbit as other.
INPUT:
OUTPUT:
There are three different equivalences between fans and
in the same lattice:
EXAMPLES:
These fans are “mirrors” of each other:
sage: fan1 = Fan(cones=[(0,1), (1,2)],
... rays=[(1,0), (0,1), (-1,-1)],
... check=False)
sage: fan2 = Fan(cones=[(0,1), (1,2)],
... rays=[(1,0), (0,-1), (-1,1)],
... check=False)
sage: fan1 == fan2
False
sage: fan1.is_equivalent(fan2)
False
sage: fan1.is_isomorphic(fan2)
Traceback (most recent call last):
...
NotImplementedError: fan isomorphism is not implemented yet!
Check if self is simplicial.
A rational polyhedral fan is simplicial if all of its cones are, i.e. primitive vectors along generating rays of every cone form a part of a rational basis of the ambient space.
OUTPUT:
EXAMPLES:
sage: fan = FaceFan(lattice_polytope.octahedron(2))
sage: fan.is_simplicial()
True
sage: cone1 = Cone([(1,0), (0,1)])
sage: cone2 = Cone([(-1,0)])
sage: fan = Fan([cone1, cone2])
sage: fan.is_simplicial()
True
In fact, any fan in a two-dimensional ambient space is simplicial. This is no longer the case in dimension three:
sage: fan = NormalFan(lattice_polytope.octahedron(3))
sage: fan.is_simplicial()
False
sage: fan.generating_cone(0).nrays()
4
Check if self is smooth.
A rational polyhedral fan is smooth if all of its cones are, i.e. primitive vectors along generating rays of every cone form a part of an integral basis of the ambient space. (In this case the corresponding toric variety is smooth.)
OUTPUT:
EXAMPLES:
sage: fan = FaceFan(lattice_polytope.octahedron(2))
sage: fan.is_smooth()
True
sage: cone1 = Cone([(1,0), (0,1)])
sage: cone2 = Cone([(-1,0)])
sage: fan = Fan([cone1, cone2])
sage: fan.is_smooth()
True
sage: fan = NormalFan(lattice_polytope.octahedron(2))
sage: fan.is_smooth()
False
sage: fan.generating_cone(0).rays()
(N(-1, 1), N(-1, -1))
sage: fan.generating_cone(0).ray_matrix().det()
2
Return the ideal generated by linear relations
INPUT:
OUTPUT:
Returns the ideal, in the given ring, generated by the linear relations of the rays. In toric geometry, this corresponds to rational equivalence of divisors.
EXAMPLES:
sage: fan = Fan([[0,1,3],[3,4],[2,0],[1,2,4]], [(-3, -2, 1), (0, 0, 1), (3, -2, 1), (-1, -1, 1), (1, -1, 1)])
sage: fan.linear_equivalence_ideal( PolynomialRing(QQ,5,'A, B, C, D, E') )
Ideal (-3*A + 3*C - D + E, -2*A - 2*C - D - E, A + B + C + D + E) of Multivariate Polynomial Ring in A, B, C, D, E over Rational Field
Construct a simplicial fan subdividing self.
It is a synonym for subdivide() with make_simplicial=True option.
INPUT:
OUTPUT:
EXAMPLES:
sage: fan = NormalFan(lattice_polytope.octahedron(3))
sage: fan.is_simplicial()
False
sage: fan.ngenerating_cones()
6
sage: new_fan = fan.make_simplicial()
sage: new_fan.is_simplicial()
True
sage: new_fan.ngenerating_cones()
12
Return the number of generating cones of self.
OUTPUT:
EXAMPLES:
sage: fan = FaceFan(lattice_polytope.octahedron(2))
sage: fan.ngenerating_cones()
4
sage: cone1 = Cone([(1,0), (0,1)])
sage: cone2 = Cone([(-1,0)])
sage: fan = Fan([cone1, cone2])
sage: fan.ngenerating_cones()
2
Plot self.
INPUT:
OUTPUT:
EXAMPLES:
sage: fan = toric_varieties.dP6().fan()
sage: fan.plot()
Return the primitive collections.
OUTPUT:
Returns the subsets
such that
Note
By replacing the multiindices of each
primitive collection with the monomials
one generates the Stanley-Reisner ideal in
.
REFERENCES:
V.V. Batyrev, On the classification of smooth projective toric varieties, Tohoku Math.J. 43 (1991), 569-585
EXAMPLES:
sage: fan = Fan([[0,1,3],[3,4],[2,0],[1,2,4]], [(-3, -2, 1), (0, 0, 1), (3, -2, 1), (-1, -1, 1), (1, -1, 1)])
sage: fan.primitive_collections()
[frozenset([0, 4]), frozenset([2, 3]), frozenset([0, 1, 2]), frozenset([1, 3, 4])]
Construct a new fan subdividing self.
INPUT:
OUTPUT:
Currently the “default” algorithm corresponds to iterative stellar subdivison for each ray in new_rays.
EXAMPLES:
sage: fan = NormalFan(lattice_polytope.octahedron(3))
sage: fan.is_simplicial()
False
sage: fan.ngenerating_cones()
6
sage: fan.nrays()
8
sage: new_fan = fan.subdivide(new_rays=[(1,0,0)])
sage: new_fan.is_simplicial()
False
sage: new_fan.ngenerating_cones()
9
sage: new_fan.nrays()
9
Check if a point is contained in the support of the fan.
The support of a fan is the union of all cones of the fan. If you want to know whether the fan contains a given cone, you should use contains() instead.
INPUT:
OUTPUT:
TESTS:
sage: cone1 = Cone([(0,-1), (1,0)])
sage: cone2 = Cone([(1,0), (0,1)])
sage: f = Fan([cone1, cone2])
We check if some points are in this fan:
sage: f.support_contains(f.lattice()(1,0))
True
sage: f.support_contains(cone1) # a cone is not a point of the lattice
False
sage: f.support_contains((1,0))
True
sage: f.support_contains(1,1)
True
sage: f.support_contains((-1,0))
False
sage: f.support_contains(f.lattice().dual()(1,0)) #random output (warning)
False
sage: f.support_contains(f.lattice().dual()(1,0))
False
sage: f.support_contains(1)
False
sage: f.support_contains(0) # 0 converts to the origin in the lattice
True
sage: f.support_contains(1/2, sqrt(3))
True
sage: f.support_contains(-1/2, sqrt(3))
False
Check if x is a Fan.
INPUT:
OUTPUT:
EXAMPLES:
sage: from sage.geometry.fan import is_Fan
sage: is_Fan(1)
False
sage: fan = FaceFan(lattice_polytope.octahedron(2))
sage: fan
Rational polyhedral fan in 2-d lattice N
sage: is_Fan(fan)
True