Convex rational polyhedral cones

This module was designed as a part of framework for toric varieties (toric_variety, fano_toric_variety). While the emphasis is on strictly convex cones, non-strictly convex cones are supported as well. Work with distinct lattices (in the sense of discrete subgroups spanning vector spaces) is supported. The default lattice is ToricLattice N of the appropriate dimension. The only case when you must specify lattice explicitly is creation of a 0-dimensional cone, where dimension of the ambient space cannot be guessed.

AUTHORS:

  • Andrey Novoseltsev (2010-05-13): initial version.
  • Andrey Novoseltsev (2010-06-17): substantial improvement during review by Volker Braun.
  • Volker Braun (2010-06-21): various spanned/quotient/dual lattice computations added.

EXAMPLES:

Use Cone() to construct cones:

sage: octant = Cone([(1,0,0), (0,1,0), (0,0,1)])
sage: halfspace = Cone([(1,0,0), (0,1,0), (-1,-1,0), (0,0,1)])
sage: positive_xy = Cone([(1,0,0), (0,1,0)])
sage: four_rays = Cone([(1,1,1), (1,-1,1), (-1,-1,1), (-1,1,1)])

For all of the cones above we have provided primitive generating rays, but in fact this is not necessary - a cone can be constructed from any collection of rays (from the same space, of course). If there are non-primitive (or even non-integral) rays, they will be replaced with primitive ones. If there are extra rays, they will be discarded. Of course, this means that Cone() has to do some work before actually constructing the cone and sometimes it is not desirable, if you know for sure that your input is already “good”. In this case you can use options check=False to force Cone() to use exactly the directions that you have specified and normalize=False to force it to use exactly the rays that you have specified. However, it is better not to use these possibilities without necessity, since cones are assumed to be represented by a minimal set of primitive generating rays. See Cone() for further documentation on construction.

Once you have a cone, you can perform numerous operations on it. The most important ones are, probably, ray accessing methods:

sage: halfspace.rays()
(N(0, 0, 1), N(1, 0, 0), N(-1, 0, 0), N(0, 1, 0), N(0, -1, 0))
sage: halfspace.ray(2)
N(-1, 0, 0)
sage: halfspace.ray_matrix()
[ 0  1 -1  0  0]
[ 0  0  0  1 -1]
[ 1  0  0  0  0]
sage: halfspace.ray_set()
frozenset([N(1, 0, 0), N(-1, 0, 0), N(0, 1, 0), N(0, 0, 1), N(0, -1, 0)])

If you want to do something with each ray of a cone, you can write

sage: for ray in positive_xy: print ray
N(1, 0, 0)
N(0, 1, 0)

You can also get an iterator over only some selected rays:

sage: for ray in halfspace.ray_iterator([1,2,1]): print ray
N(1, 0, 0)
N(-1, 0, 0)
N(1, 0, 0)

There are two dimensions associated to each cone - the dimension of the subspace spanned by the cone and the dimension of the space where it lives:

sage: positive_xy.dim()
2
sage: positive_xy.lattice_dim()
3

You also may be interested in this dimension:

sage: dim(positive_xy.linear_subspace())
0
sage: dim(halfspace.linear_subspace())
2

Or, perhaps, all you care about is whether it is zero or not:

sage: positive_xy.is_strictly_convex()
True
sage: halfspace.is_strictly_convex()
False

You can also perform these checks:

sage: positive_xy.is_simplicial()
True
sage: four_rays.is_simplicial()
False
sage: positive_xy.is_smooth()
True

You can work with subcones that form faces of other cones:

sage: face = four_rays.faces(dim=2)[0]
sage: face
2-d face of 3-d cone in 3-d lattice N
sage: face.rays()
(N(1, 1, 1), N(1, -1, 1))
sage: face.ambient_ray_indices()
(0, 1)
sage: four_rays.rays(face.ambient_ray_indices())
(N(1, 1, 1), N(1, -1, 1))

If you need to know inclusion relations between faces, you can use

sage: L = four_rays.face_lattice()
sage: map(len, L.level_sets())
[1, 4, 4, 1]
sage: face = L.level_sets()[2][0]
sage: face.element.rays()
(N(1, 1, 1), N(1, -1, 1))
sage: L.hasse_diagram().neighbors_in(face)
[1-d face of 3-d cone in 3-d lattice N,
 1-d face of 3-d cone in 3-d lattice N]

Warning

As you can see in the above example, the order of faces in level sets of the face lattice may differ from the order of faces returned by faces(). While the first order is random, the latter one ensures that one-dimensional faces are listed in the same order as generating rays.

When all the functionality provided by cones is not enough, you may want to check if you can do necessary things using lattice polytopes and polyhedra corresponding to cones:

sage: four_rays.lattice_polytope()
A lattice polytope: 3-dimensional, 5 vertices.
sage: four_rays.polyhedron()
A 3-dimensional polyhedron in QQ^3 defined as
the convex hull of 1 vertex and 4 rays.

And of course you are always welcome to suggest new features that should be added to cones!

REFERENCES:

[Fulton](1, 2, 3, 4, 5) Wiliam Fulton, “Introduction to Toric Varieties”, Princeton University Press
sage.geometry.cone.Cone(data, lattice=None, check=True, normalize=True)

Construct a (not necessarily strictly) convex rational polyhedral cone.

INPUT:

  • data – one of the following:
    • Polyhedron object representing a valid cone;
    • list of rays. Each ray should be given as a list or a vector convertible to the rational extension of the given lattice;
  • latticeToricLattice, \ZZ^n, or any other object that behaves like these. If not specified, an attempt will be made to determine an appropriate toric lattice automatically;

  • check – by default the input data will be checked for correctness (e.g. that all rays have the same number of components) and generating rays will be constructed from data. If you know that the input is a minimal set of generators of a valid cone, you may significantly (up to 100 times on simple input) decrease construction time using check=False option;

  • normalize – you can further speed up construction using normalize=False option. In this case data must be a list of immutable primitive rays in lattice. In general, you should not use this option, it is designed for code optimization and does not give as drastic improvement in speed as the previous one.

OUTPUT:

  • convex rational polyhedral cone determined by data.

EXAMPLES:

Let’s define a cone corresponding to the first quadrant of the plane (note, you can even mix objects of different types to represent rays, as long as you let this function to perform all the checks and necessary conversions!):

sage: quadrant = Cone([(1,0), [0,1]])
sage: quadrant
2-d cone in 2-d lattice N
sage: quadrant.rays()
(N(1, 0), N(0, 1))

You may prefer to use ray_matrix() when you want to take a look at rays, they will be given as columns:

sage: quadrant.ray_matrix()
[1 0]
[0 1]

If you give more rays than necessary, the extra ones will be discarded:

sage: Cone([(1,0), (0,1), (1,1), (0,1)]).rays()
(N(1, 0), N(0, 1))

However, this work is not done with check=False option, so use it carefully!

sage: Cone([(1,0), (0,1), (1,1), (0,1)], check=False).rays()
(N(1, 0), N(0, 1), N(1, 1), N(0, 1))

Even worse things can happen with normalize=False option:

sage: Cone([(1,0), (0,1)], check=False, normalize=False)
Traceback (most recent call last):
...
AttributeError: 'tuple' object has no attribute 'parent'

You can construct different “not” cones: not full-dimensional, not strictly convex, not containing any rays:

sage: one_dimensional_cone = Cone([(1,0)])
sage: one_dimensional_cone.dim()
1
sage: half_plane = Cone([(1,0), (0,1), (-1,0)])
sage: half_plane.rays()
(N(0, 1), N(1, 0), N(-1, 0))
sage: half_plane.is_strictly_convex()
False
sage: origin = Cone([(0,0)])
sage: origin.rays()
()
sage: origin.dim()
0
sage: origin.lattice_dim()
2

You may construct the cone above without giving any rays, but in this case you must provide lattice explicitly:

sage: origin = Cone([])
Traceback (most recent call last):
...
ValueError: lattice must be given explicitly if there are no rays!
sage: origin = Cone([], lattice=ToricLattice(2))
sage: origin.dim()
0
sage: origin.lattice_dim()
2
sage: origin.lattice()
2-d lattice N

Of course, you can also provide lattice in other cases:

sage: L = ToricLattice(3, "L")
sage: c1 = Cone([(1,0,0),(1,1,1)], lattice=L)
sage: c1.rays()
(L(1, 0, 0), L(1, 1, 1))

Or you can construct cones from rays of a particular lattice:

sage: ray1 = L(1,0,0)
sage: ray2 = L(1,1,1)
sage: c2 = Cone([ray1, ray2])
sage: c2.rays()
(L(1, 0, 0), L(1, 1, 1))
sage: c1 == c2
True

When the cone in question is not strictly convex, the standard form for the “generating rays” of the linear subspace is “basis vectors and their negatives”, as in the following example:

sage: plane = Cone([(1,0), (0,1), (-1,-1)])
sage: plane.ray_matrix()
[ 1 -1  0  0]
[ 0  0  1 -1]
class sage.geometry.cone.ConvexRationalPolyhedralCone(rays=None, lattice=None, ambient=None, ambient_ray_indices=None)

Bases: sage.geometry.cone.IntegralRayCollection, _abcoll.Container

Create a convex rational polyhedral cone.

Warning

This class does not perform any checks of correctness of input nor does it convert input into the standard representation. Use Cone() to construct cones.

Cones are immutable, but they cache most of the returned values.

INPUT:

  • rays – list of immutable primitive vectors in lattice;
  • latticeToricLattice, \ZZ^n, or any other object that behaves like these. If None, it will be determined as parent() of the first ray. Of course, this cannot be done if there are no rays, so in this case you must give an appropriate lattice directly.

OR (these parameters must be given as keywords):

  • ambient – ambient structure of this cone, a bigger cone or a fan, this cone must be a face of ambient;
  • ambient_ray_indices – increasing list or tuple of integers, indices of rays of ambient generating this cone.

OUTPUT:

  • convex rational polyhedral cone.

Note

Every cone has its ambient structure. If it was not specified, it is this cone itself.

adjacent()

Return faces adjacent to self in the ambient face lattice.

Two distinct faces F_1 and F_2 of the same face lattice are adjacent if all of the following conditions hold:

  • F_1 and F_2 have the same dimension d;
  • F_1 and F_2 share a facet of dimension d-1;
  • F_1 and F_2 are facets of some face of dimension d+1, unless d is the dimension of the ambient structure.

OUTPUT:

EXAMPLES:

sage: octant = Cone([(1,0,0), (0,1,0), (0,0,1)])
sage: octant.adjacent()
()
sage: one_face = octant.faces(1)[0]
sage: len(one_face.adjacent())
2
sage: one_face.adjacent()[1]
1-d face of 3-d cone in 3-d lattice N

Things are a little bit subtle with fans, as we illustrate below.

First, we create a fan from two cones in the plane:

sage: fan = Fan(cones=[(0,1), (1,2)],
...             rays=[(1,0), (0,1), (-1,0)])
sage: cone = fan.generating_cone(0)
sage: len(cone.adjacent())
1

The second generating cone is adjacent to this one. Now we create the same fan, but embedded into the 3-dimensional space:

sage: fan = Fan(cones=[(0,1), (1,2)],
...             rays=[(1,0,0), (0,1,0), (-1,0,0)])
sage: cone = fan.generating_cone(0)
sage: len(cone.adjacent())
1

The result is as before, since we still have:

sage: fan.dim()
2

Now we add another cone to make the fan 3-dimensional:

sage: fan = Fan(cones=[(0,1), (1,2), (3,)],
...             rays=[(1,0,0), (0,1,0), (-1,0,0), (0,0,1)])
sage: cone = fan.generating_cone(0)
sage: len(cone.adjacent())
0

Since now cone has smaller dimension than fan, it and its adjacent cones must be facets of a bigger one, but since cone in this example is generating, it is not contained in any other.

ambient()

Return the ambient structure of self.

OUTPUT:

  • cone or fan containing self as a face.

EXAMPLES:

sage: cone = Cone([(1,2,3), (4,6,5), (9,8,7)])
sage: cone.ambient()
3-d cone in 3-d lattice N
sage: cone.ambient() is cone
True
sage: face = cone.faces(1)[0]
sage: face
1-d face of 3-d cone in 3-d lattice N
sage: face.ambient()
3-d cone in 3-d lattice N
sage: face.ambient() is cone
True
ambient_ray_indices()

Return indices of rays of the ambient structure generating self.

OUTPUT:

  • increasing tuple of integers.

EXAMPLES:

sage: quadrant = Cone([(1,0), (0,1)])
sage: quadrant.ambient_ray_indices()
(0, 1)
sage: quadrant.facets()[1].ambient_ray_indices()
(1,)
cartesian_product(other, lattice=None)

Return the Cartesian product of self with other.

INPUT:

  • other – a cone;
  • lattice – (optional) the ambient lattice for the Cartesian product cone. By default, the direct sum of the ambient lattices of self and other is constructed.

OUTPUT:

EXAMPLES:

sage: c = Cone([(1,)])
sage: c.cartesian_product(c)
2-d cone in 2-d lattice N+N
sage: _.rays()
(N+N(1, 0), N+N(0, 1))
contains(*args)

Check if a given point is contained in self.

INPUT:

  • anything. An attempt will be made to convert all arguments into a single element of the ambient space of self. If it fails, False will be returned.

OUTPUT:

  • True if the given point is contained in self, False otherwise.

EXAMPLES:

sage: c = Cone([(1,0), (0,1)])
sage: c.contains(c.lattice()(1,0))
True
sage: c.contains((1,0))
True
sage: c.contains((1,1))
True
sage: c.contains(1,1)
True
sage: c.contains((-1,0))
False
sage: c.contains(c.dual_lattice()(1,0)) #random output (warning)
False
sage: c.contains(c.dual_lattice()(1,0))
False
sage: c.contains(1)
False
sage: c.contains(1/2, sqrt(3))
True
sage: c.contains(-1/2, sqrt(3))
False
dual()

Return the dual cone of self.

OUTPUT:

EXAMPLES:

sage: cone = Cone([(1,0), (-1,3)])
sage: cone.dual().rays()
(M(3, 1), M(0, 1))

Now let’s look at a more complicated case:

sage: cone = Cone([(-2,-1,2), (4,1,0), (-4,-1,-5), (4,1,5)])
sage: cone.is_strictly_convex()
False
sage: cone.dim()
3
sage: cone.dual().rays()
(M(7, -18, -2), M(1, -4, 0))
sage: cone.dual().dual() is cone
True

We correctly handle the degenerate cases:

sage: N = ToricLattice(2)
sage: Cone([], lattice=N).dual().rays()  # empty cone
(M(1, 0), M(-1, 0), M(0, 1), M(0, -1))
sage: Cone([(1,0)], lattice=N).dual().rays()  # ray in 2d
(M(1, 0), M(0, 1), M(0, -1))
sage: Cone([(1,0),(-1,0)], lattice=N).dual().rays()  # line in 2d
(M(0, 1), M(0, -1))
sage: Cone([(1,0),(0,1)], lattice=N).dual().rays()  # strictly convex cone
(M(1, 0), M(0, 1))
sage: Cone([(1,0),(-1,0),(0,1)], lattice=N).dual().rays()  # half space 
(M(0, 1),)
sage: Cone([(1,0),(0,1),(-1,-1)], lattice=N).dual().rays()  # whole space
()
embed(cone)

Return the cone equivalent to the given one, but sitting in self as a face.

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:

  • a cone, equivalent to cone but sitting inside self.

EXAMPLES:

Let’s take a 3-d cone on 4 rays:

sage: c = Cone([(1,0,1), (0,1,1), (-1,0,1), (0,-1,1)])

Then any ray generates a 1-d face of this cone, but if you construct such a face directly, it will not “sit” inside the cone:

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 face of the cone, we need to embed it first:

sage: e_ray = c.embed(ray)
sage: e_ray
1-d face of 3-d cone 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 face of 3-d cone in 3-d lattice N,
 1-d face of 3-d cone in 3-d lattice N)
sage: e_ray.ambient()
3-d cone in 3-d lattice N

Not every cone can be embedded into a fixed ambient cone:

sage: c.embed(Cone([(0,0,1)]))
Traceback (most recent call last):
...
ValueError: 1-d cone in 3-d lattice N is not a face
of 3-d cone in 3-d lattice N!
sage: c.embed(Cone([(1,0,1), (-1,0,1)]))
Traceback (most recent call last):
...
ValueError: 2-d cone in 3-d lattice N is not a face
of 3-d cone in 3-d lattice N!
face_lattice()

Return the face lattice of self.

This lattice will have the origin as the bottom (we do not include the empty set as a face) and this cone itself as the top.

OUTPUT:

EXAMPLES:

Let’s take a look at the face lattice of the first quadrant:

sage: quadrant = Cone([(1,0), (0,1)])
sage: L = quadrant.face_lattice()
sage: L
Finite poset containing 4 elements

To see all faces arranged by dimension, you can do this:

sage: for level in L.level_sets(): print level
[0-d face of 2-d cone in 2-d lattice N]
[1-d face of 2-d cone in 2-d lattice N,
 1-d face of 2-d cone in 2-d lattice N]
[2-d cone in 2-d lattice N]

To work with a particular face of a particular dimension it is not enough to do just

sage: face = L.level_sets()[1][0]
sage: face
1-d face of 2-d cone in 2-d lattice N
sage: face.rays()
Traceback (most recent call last):
...
AttributeError: 'PosetElement' object has no attribute 'rays'

To get the actual face you need one more step:

sage: face = face.element

Now you can look at the actual rays of this face...

sage: face.rays()
(N(1, 0),)

... or you can see indices of the rays of the orginal cone that correspond to the above ray:

sage: face.ambient_ray_indices()
(0,)
sage: quadrant.ray(0)
N(1, 0)

An alternative to extracting faces from the face lattice is to use faces() method:

sage: face is quadrant.faces(dim=1)[0]
True

The advantage of working with the face lattice directly is that you can (relatively easily) get faces that are related to the given one:

sage: face = L.level_sets()[1][0]
sage: D = L.hasse_diagram()
sage: D.neighbors(face)
[0-d face of 2-d cone in 2-d lattice N,
 2-d cone in 2-d lattice N]

However, you can achieve some of this functionality using facets(), facet_of(), and adjacent() methods:

sage: face = quadrant.faces(1)[0]
sage: face
1-d face of 2-d cone in 2-d lattice N
sage: face.rays()
(N(1, 0),)
sage: face.facets()
(0-d face of 2-d cone in 2-d lattice N,)
sage: face.facet_of()
(2-d cone in 2-d lattice N,)
sage: face.adjacent()
(1-d face of 2-d cone in 2-d lattice N,)
sage: face.adjacent()[0].rays()
(N(0, 1),)

Note that if cone is a face of supercone, then the face lattice of cone consists of (appropriate) faces of supercone:

sage: supercone = Cone([(1,2,3,4), (5,6,7,8),
...                     (1,2,4,8), (1,3,9,7)])
sage: supercone.face_lattice()
Finite poset containing 16 elements
sage: supercone.face_lattice().top()
4-d cone in 4-d lattice N
sage: cone = supercone.facets()[0]
sage: cone
3-d face of 4-d cone in 4-d lattice N
sage: cone.face_lattice()
Finite poset containing 8 elements
sage: cone.face_lattice().bottom()
0-d face of 4-d cone in 4-d lattice N
sage: cone.face_lattice().top()
3-d face of 4-d cone in 4-d lattice N
sage: cone.face_lattice().top().element == cone
True
faces(dim=None, codim=None)

Return faces of self of specified (co)dimension.

INPUT:

  • dim – integer, dimension of the requested faces;
  • codim – integer, codimension of the requested faces.

Note

You can specify at most one parameter. If you don’t give any, then all faces will be returned.

OUTPUT:

  • if either dim or codim is given, the output will be a tuple of cones;
  • if neither dim nor codim is given, the output will be the tuple of tuples as above, giving faces of all existing dimensions. If you care about inclusion relations between faces, consider using face_lattice() or adjacent(), facet_of(), and facets().

EXAMPLES:

Let’s take a look at the faces of the first quadrant:

sage: quadrant = Cone([(1,0), (0,1)])
sage: quadrant.faces()
((0-d face of 2-d cone in 2-d lattice N,),
 (1-d face of 2-d cone in 2-d lattice N,
  1-d face of 2-d cone in 2-d lattice N),
 (2-d cone in 2-d lattice N,))
sage: quadrant.faces(dim=1)
(1-d face of 2-d cone in 2-d lattice N,
 1-d face of 2-d cone in 2-d lattice N)
sage: face = quadrant.faces(dim=1)[0]

Now you can look at the actual rays of this face...

sage: face.rays()
(N(1, 0),)

... or you can see indices of the rays of the orginal cone that correspond to the above ray:

sage: face.ambient_ray_indices()
(0,)
sage: quadrant.ray(0)
N(1, 0)

Note that it is OK to ask for faces of too small or high dimension:

sage: quadrant.faces(-1)
()
sage: quadrant.faces(3)
()

In the case of non-strictly convex cones even faces of small non-negative dimension may be missing:

sage: halfplane = Cone([(1,0), (0,1), (-1,0)])
sage: halfplane.faces(0)
()
sage: halfplane.faces()
((1-d face of 2-d cone in 2-d lattice N,),
 (2-d cone in 2-d lattice N,))
sage: plane = Cone([(1,0), (0,1), (-1,-1)])
sage: plane.faces(1)
()
sage: plane.faces()
((2-d cone in 2-d lattice N,),)

TESTS:

Now we check that “general” cones whose dimension is smaller than the dimension of the ambient space work as expected (see Trac #9188):

sage: c = Cone([(1,1,1,3),(1,-1,1,3),(-1,-1,1,3)])
sage: c.faces()
((0-d face of 3-d cone in 4-d lattice N,),
 (1-d face of 3-d cone in 4-d lattice N,
  1-d face of 3-d cone in 4-d lattice N,
  1-d face of 3-d cone in 4-d lattice N),
 (2-d face of 3-d cone in 4-d lattice N,
  2-d face of 3-d cone in 4-d lattice N,
  2-d face of 3-d cone in 4-d lattice N),
 (3-d cone in 4-d lattice N,))

We also ensure that a call to this function does not break facets() method (see Trac #9780):

sage: cone = toric_varieties.dP8().fan().generating_cone(0)
sage: cone
2-d cone of Rational polyhedral fan in 2-d lattice N
sage: [f.rays() for f in cone.facets()]
[(N(1, 1),), (N(0, 1),)]
sage: len(cone.faces())
3
sage: [f.rays() for f in cone.facets()]
[(N(1, 1),), (N(0, 1),)]        
facet_normals()

Return normals to facets of self.

Note

  1. For a not full-dimensional cone facet normals will specify hyperplanes whose intersections with the space spanned by self give facets of self.
  2. For a not strictly convex cone facet normals will be orthogonal to the linear subspace of self, i.e. they always will be elements of the dual cone of self.
  3. The order of normals is random and may be different from the one in facets().
  4. The sign of the facet normals is chosen such that they point to the “inside” of the cone if there is such a thing.

OUTPUT:

  • tuple of vectors.

If the ambient lattice() of self is a toric lattice, the facet nomals will be elements of the dual lattice. If it is a general lattice (like ZZ^n) that does not have a dual() method, the facet normals will be returned as integral vectors.

EXAMPLES:

sage: cone = Cone([(1,0), (-1,3)])
sage: cone.facet_normals()
(M(3, 1), M(0, 1))

Now let’s look at a more complicated case:

sage: cone = Cone([(-2,-1,2), (4,1,0), (-4,-1,-5), (4,1,5)])
sage: cone.is_strictly_convex()
False
sage: cone.dim()
3
sage: cone.linear_subspace().dimension()
1
sage: lsg = (QQ^3)(cone.linear_subspace().gen(0)); lsg
(1, 1/4, 5/4)
sage: cone.facet_normals()
(M(7, -18, -2), M(1, -4, 0))
sage: [lsg*normal for normal in cone.facet_normals()]
[0, 0]

A lattice that does not have a dual() method:

sage: Cone([(1,1),(0,1)], lattice=ZZ^2).facet_normals()
((-1, 1), (1, 0))

We correctly handle the degenerate cases:

sage: N = ToricLattice(2)
sage: Cone([], lattice=N).facet_normals()  # empty cone
()
sage: Cone([(1,0)], lattice=N).facet_normals()  # ray in 2d
(M(1, 0),)
sage: Cone([(1,0),(-1,0)], lattice=N).facet_normals()  # line in 2d
()
sage: Cone([(1,0),(0,1)], lattice=N).facet_normals()  # strictly convex cone
(M(1, 0), M(0, 1))
sage: Cone([(1,0),(-1,0),(0,1)], lattice=N).facet_normals()  # half space 
(M(0, 1),)
sage: Cone([(1,0),(0,1),(-1,-1)], lattice=N).facet_normals()  # whole space
()
facet_of()

Return cones of the ambient face lattice having self as a facet.

OUTPUT:

EXAMPLES:

sage: octant = Cone([(1,0,0), (0,1,0), (0,0,1)])
sage: octant.facet_of()
()
sage: one_face = octant.faces(1)[0]
sage: len(one_face.facet_of())
2
sage: one_face.facet_of()[1]
2-d face of 3-d cone in 3-d lattice N

While fan is the top element of its own cone lattice, which is a variant of a face lattice, we do not refer to cones as its facets:

sage: fan = Fan([octant])
sage: fan.generating_cone(0).facet_of()
()

Subcones of generating cones work as before:

sage: one_cone = fan(1)[0]
sage: len(one_cone.facet_of())
2
facets()

Return facets (faces of codimension 1) of self.

OUTPUT:

EXAMPLES:

sage: quadrant = Cone([(1,0), (0,1)])
sage: quadrant.facets()
(1-d face of 2-d cone in 2-d lattice N,
 1-d face of 2-d cone in 2-d lattice N)
interior_contains(*args)

Check if a given point is contained in the interior of self.

For a cone of strictly lower-dimension than the ambient space, the interior is always empty. You probably want to use relative_interior_contains() in this case.

INPUT:

  • anything. An attempt will be made to convert all arguments into a single element of the ambient space of self. If it fails, False will be returned.

OUTPUT:

  • True if the given point is contained in the interior of self, False otherwise.

EXAMPLES:

sage: c = Cone([(1,0), (0,1)])
sage: c.contains((1,1))
True
sage: c.interior_contains((1,1))
True
sage: c.contains((1,0))
True
sage: c.interior_contains((1,0))
False
intersection(other)

Compute the intersection of two cones.

INPUT:

OUTPUT:

EXAMPLES:

sage: cone1 = Cone([(1,0), (-1, 3)])
sage: cone2 = Cone([(-1,0), (2, 5)])
sage: cone1.intersection(cone2).rays()
(N(2, 5), N(-1, 3))
is_equivalent(other)

Check if self is “mathematically” the same as other.

INPUT:

  • other - cone.

OUTPUT:

  • True if self and other define the same cones as sets of points in the same lattice, False otherwise.

There are three different equivalences between cones C_1 and C_2 in the same lattice:

  1. They have the same generating rays in the same order. This is tested by C1 == C2.
  2. They describe the same sets of points. This is tested by C1.is_equivalent(C2).
  3. They are in the same orbit of GL(n,\ZZ) (and, therefore, correspond to isomorphic affine toric varieties). This is tested by C1.is_isomorphic(C2).

EXAMPLES:

sage: cone1 = Cone([(1,0), (-1, 3)])
sage: cone2 = Cone([(-1,3), (1, 0)])
sage: cone1.rays()
(N(1, 0), N(-1, 3))
sage: cone2.rays()
(N(-1, 3), N(1, 0))
sage: cone1 == cone2
False
sage: cone1.is_equivalent(cone2)
True
is_face_of(cone)

Check if self forms a face of another cone.

INPUT:

  • cone – cone.

OUTPUT:

  • True if self is a face of cone, False otherwise.

EXAMPLES:

sage: quadrant = Cone([(1,0), (0,1)])
sage: cone1 = Cone([(1,0)])
sage: cone2 = Cone([(1,2)])
sage: quadrant.is_face_of(quadrant)
True
sage: cone1.is_face_of(quadrant)
True
sage: cone2.is_face_of(quadrant)
False
is_isomorphic(other)

Check if self is in the same GL(n, \ZZ)-orbit as other.

INPUT:

  • other - cone.

OUTPUT:

  • True if self and other are in the same GL(n, \ZZ)-orbit, False otherwise.

There are three different equivalences between cones C_1 and C_2 in the same lattice:

  1. They have the same generating rays in the same order. This is tested by C1 == C2.
  2. They describe the same sets of points. This is tested by C1.is_equivalent(C2).
  3. They are in the same orbit of GL(n,\ZZ) (and, therefore, correspond to isomorphic affine toric varieties). This is tested by C1.is_isomorphic(C2).

EXAMPLES:

sage: cone1 = Cone([(1,0), (0, 3)])
sage: cone2 = Cone([(-1,3), (1, 0)])
sage: cone1.is_isomorphic(cone2)
Traceback (most recent call last):
...
NotImplementedError: cone isomorphism is not implemented yet!
is_simplicial()

Check if self is simplicial.

A cone is called simplicial if primitive vectors along its generating rays form a part of a rational basis of the ambient space.

OUTPUT:

  • True if self is simplicial, False otherwise.

EXAMPLES:

sage: cone1 = Cone([(1,0), (0, 3)])
sage: cone2 = Cone([(1,0), (0, 3), (-1,-1)])
sage: cone1.is_simplicial()
True
sage: cone2.is_simplicial()
False
is_smooth()

Check if self is smooth.

A cone is called smooth if primitive vectors along its generating rays form a part of an integral basis of the ambient space. Equivalently, they generate the whole lattice on the linear subspace spanned by the rays.

OUTPUT:

  • True if self is smooth, False otherwise.

EXAMPLES:

sage: cone1 = Cone([(1,0), (0, 1)])
sage: cone2 = Cone([(1,0), (-1, 3)])
sage: cone1.is_smooth()
True
sage: cone2.is_smooth()
False

The following cones are the same up to a SL(2,\ZZ) coordinate transformation:

sage: Cone([(1,0,0), (2,1,-1)]).is_smooth()
True
sage: Cone([(1,0,0), (2,1,1)]).is_smooth()
True
sage: Cone([(1,0,0), (2,1,2)]).is_smooth()
True
is_strictly_convex()

Check if self is strictly convex.

A cone is called strictly convex if it does not contain any lines.

OUTPUT:

  • True if self is strictly convex, False otherwise.

EXAMPLES:

sage: cone1 = Cone([(1,0), (0, 1)])
sage: cone2 = Cone([(1,0), (-1, 0)])
sage: cone1.is_strictly_convex()
True
sage: cone2.is_strictly_convex()
False
is_trivial()

Checks if the cone has no rays.

OUTPUT:

  • True if the cone has no rays, False otherwise.

EXAMPLES:

sage: c0 = Cone([(0)], lattice=ToricLattice(3))
sage: c0.is_trivial()
True
sage: c0.nrays()
0
lattice_polytope()

Return the lattice polytope associated to self.

The vertices of this polytope are primitive vectors along the generating rays of self and the origin, if self is strictly convex. In this case the origin is the last vertex, so the i-th ray of the cone always corresponds to the i-th vertex of the polytope.

See also polyhedron().

OUTPUT:

EXAMPLES:

sage: quadrant = Cone([(1,0), (0,1)])
sage: lp = quadrant.lattice_polytope()
sage: lp
A lattice polytope: 2-dimensional, 3 vertices.
sage: lp.vertices()
[1 0 0]
[0 1 0]

sage: line = Cone([(1,0), (-1,0)])
sage: lp = line.lattice_polytope()
sage: lp
A lattice polytope: 1-dimensional, 2 vertices.
sage: lp.vertices()
[ 1 -1]
[ 0  0]
line_set()

Return a set of lines generating the linear subspace of self.

OUTPUT:

  • frozenset of primitive vectors in the lattice of self giving directions of lines that span the linear subspace of self. These lines are arbitrary, but fixed. See also lines().

EXAMPLES:

sage: halfplane = Cone([(1,0), (0,1), (-1,0)])
sage: halfplane.line_set()
frozenset([N(1, 0)])
sage: fullplane = Cone([(1,0), (0,1), (-1,-1)])
sage: fullplane.line_set()
frozenset([N(0, 1), N(1, 0)])
linear_subspace()

Return the largest linear subspace contained inside of self.

OUTPUT:

  • subspace of the ambient space of self.

EXAMPLES:

sage: halfplane = Cone([(1,0), (0,1), (-1,0)])
sage: halfplane.linear_subspace()
Vector space of degree 2 and dimension 1 over Rational Field
Basis matrix:
[1 0]
lines()

Return lines generating the linear subspace of self.

OUTPUT:

  • tuple of primitive vectors in the lattice of self giving directions of lines that span the linear subspace of self. These lines are arbitrary, but fixed. If you do not care about the order, see also line_set().

EXAMPLES:

sage: halfplane = Cone([(1,0), (0,1), (-1,0)])
sage: halfplane.lines()
(N(1, 0),)
sage: fullplane = Cone([(1,0), (0,1), (-1,-1)])
sage: fullplane.lines()
(N(1, 0), N(0, 1))
orthogonal_sublattice(*args, **kwds)

The sublattice (in the dual lattice) orthogonal to the sublattice spanned by the cone.

Let M= self.dual_lattice() be the lattice dual to the ambient lattice of the given cone \sigma. Then, in the notation of [Fulton], this method returns the sublattice

M(\sigma) \stackrel{\text{def}}{=} 
\sigma^\perp \cap M
\subset M

INPUT:

  • either nothing or something that can be turned into an element of this lattice.

OUTPUT:

  • if no arguments were given, a toric sublattice, otherwise the corresponding element of it.

EXAMPLES:

sage: c = Cone([(1,1,1), (1,-1,1), (-1,-1,1), (-1,1,1)])
sage: c.orthogonal_sublattice()
Sublattice <>
sage: c12 = Cone([(1,1,1), (1,-1,1)])
sage: c12.sublattice()
Sublattice <N(1, 1, 1), N(0, 1, 0)>
sage: c12.orthogonal_sublattice()
Sublattice <M(-1, 0, 1)>
plot(**options)

Plot self.

INPUT:

OUTPUT:

  • a plot.

EXAMPLES:

sage: quadrant = Cone([(1,0), (0,1)])
sage: quadrant.plot()
polyhedron()

Return the polyhedron associated to self.

Mathematically this polyhedron is the same as self.

See also lattice_polytope().

OUTPUT:

EXAMPLES:

sage: quadrant = Cone([(1,0), (0,1)])
sage: quadrant.polyhedron()
A 2-dimensional polyhedron in QQ^2 defined as the convex hull
of 1 vertex and 2 rays.
sage: line = Cone([(1,0), (-1,0)])
sage: line.polyhedron()
A 1-dimensional polyhedron in QQ^2 defined as the convex hull
of 1 vertex and 1 line.

Here is an example of a trivial cone (see Trac #10237):

sage: origin = Cone([], lattice=ZZ^2)
sage: origin.polyhedron()
A 0-dimensional polyhedron in QQ^2 defined as the convex hull
of 1 vertex.
relative_interior_contains(*args)

Check if a given point is contained in the relative interior of self.

For a full-dimensional cone the relative interior is simply the interior, so this method will do the same check as interior_contains(). For a strictly lower-dimensional cone, the relative interior is the cone without its facets.

INPUT:

  • anything. An attempt will be made to convert all arguments into a single element of the ambient space of self. If it fails, False will be returned.

OUTPUT:

  • True if the given point is contained in the relative interior of self, False otherwise.

EXAMPLES:

sage: c = Cone([(1,0,0), (0,1,0)])
sage: c.contains((1,1,0))
True
sage: c.relative_interior_contains((1,1,0))
True
sage: c.interior_contains((1,1,0))
False
sage: c.contains((1,0,0))
True
sage: c.relative_interior_contains((1,0,0))
False
sage: c.interior_contains((1,0,0))
False
relative_orthogonal_quotient(supercone)

The quotient of the dual spanned lattice by the dual of the supercone’s spanned lattice.

In the notation of [Fulton], if supercone = \rho >
\sigma = self is a cone that contains \sigma as a face, then M(\rho) = supercone.orthogonal_sublattice() is a saturated sublattice of M(\sigma) = self.orthogonal_sublattice(). This method returns the quotient lattice. The lifts of the quotient generators are \dim(\rho)-\dim(\sigma) linearly independent M-lattice lattice points that, together with M(\rho), generate M(\sigma).

OUTPUT:

If we call the output Mrho, then

  • Mrho.cover() == self.orthogonal_sublattice(), and
  • Mrho.relations() == supercone.orthogonal_sublattice().

Note

  • M(\sigma) / M(\rho) has no torsion since the sublattice M(\rho) is saturated.
  • In the codimension one case, (a lift of) the generator of M(\sigma) / M(\rho) is chosen to be positive on \sigma.

EXAMPLES:

sage: rho = Cone([(1,1,1,3),(1,-1,1,3),(-1,-1,1,3),(-1,1,1,3)])
sage: rho.orthogonal_sublattice()
Sublattice <M(0, 0, 3, -1)>
sage: sigma = rho.facets()[0]
sage: sigma.orthogonal_sublattice()
Sublattice <M(0, 1, 1, 0), M(0, 3, 0, 1)>
sage: sigma.is_face_of(rho)
True
sage: Q = sigma.relative_orthogonal_quotient(rho); Q
1-d lattice, quotient
of Sublattice <M(0, 1, 1, 0), M(0, 3, 0, 1)>
by Sublattice <M(0, 0, 3, -1)>
sage: Q.gens()
(M[0, 1, 1, 0],)

Different codimension:

sage: rho = Cone([[1,-1,1,3],[-1,-1,1,3]])
sage: sigma = rho.facets()[0]
sage: sigma.orthogonal_sublattice()
Sublattice <M(0, 1, 1, 0), M(1, 1, 0, 0), M(0, 3, 0, 1)>
sage: rho.orthogonal_sublattice()
Sublattice <M(0, 1, 1, 0), M(0, 3, 0, 1)>
sage: sigma.relative_orthogonal_quotient(rho).gens()
(M[-1, -1, 0, 0],)

Sign choice in the codimension one case:

sage: sigma1 = Cone([(1, 2, 3), (1, -1, 1), (-1, 1, 1), (-1, -1, 1)])  # 3d
sage: sigma2 = Cone([(1, 1, -1), (1, 2, 3), (1, -1, 1), (1, -1, -1)])  # 3d
sage: rho = sigma1.intersection(sigma2)
sage: rho.relative_orthogonal_quotient(sigma1).gens()
(M[-5, -2, 3],)
sage: rho.relative_orthogonal_quotient(sigma2).gens()
(M[5, 2, -3],)
relative_quotient(subcone)

The quotient of the spanned lattice by the lattice spanned by a subcone.

In the notation of [Fulton], let N be the ambient lattice and N_\sigma the sublattice spanned by the given cone \sigma. If \rho < \sigma is a subcone, then N_\rho = rho.sublattice() is a saturated sublattice of N_\sigma = self.sublattice(). This method returns the quotient lattice. The lifts of the quotient generators are \dim(\sigma)-\dim(\rho) linearly independent primitive lattice lattice points that, together with N_\rho, generate N_\sigma.

OUTPUT:

Note

  • The quotient N_\sigma / N_\rho of spanned sublattices has no torsion since the sublattice N_\rho is saturated.
  • In the codimension one case, the generator of N_\sigma / N_\rho is chosen to be in the same direction as the image \sigma / N_\rho

EXAMPLES:

sage: sigma = Cone([(1,1,1,3),(1,-1,1,3),(-1,-1,1,3),(-1,1,1,3)])
sage: rho   = Cone([(-1, -1, 1, 3), (-1, 1, 1, 3)])
sage: sigma.sublattice()
Sublattice <N(1, 1, 1, 3), N(1, 0, 0, 0), N(0, 1, 0, 0)>
sage: rho.sublattice()
Sublattice <N(-1, 1, 1, 3), N(0, 1, 0, 0)>
sage: sigma.relative_quotient(rho)
1-d lattice, quotient
of Sublattice <N(1, 1, 1, 3), N(1, 0, 0, 0), N(0, 1, 0, 0)>
by Sublattice <N(1, 0, -1, -3), N(0, 1, 0, 0)>
sage: sigma.relative_quotient(rho).gens()
(N[1, 0, 0, 0],)

More complicated example:

sage: rho = Cone([(1, 2, 3), (1, -1, 1)])
sage: sigma = Cone([(1, 2, 3), (1, -1, 1), (-1, 1, 1), (-1, -1, 1)])
sage: N_sigma = sigma.sublattice()
sage: N_sigma
Sublattice <N(3, 0, 1), N(2, 1, 0), N(1, 0, 0)>
sage: N_rho = rho.sublattice()
sage: N_rho
Sublattice <N(1, -1, 1), N(0, 3, 2)>
sage: sigma.relative_quotient(rho).gens()
(N[0, -2, -1],)
sage: N = rho.lattice()
sage: N_sigma == N.span(N_rho.gens() + tuple(q.lift()
...              for q in sigma.relative_quotient(rho).gens()))
True

Sign choice in the codimension one case:

sage: sigma1 = Cone([(1, 2, 3), (1, -1, 1), (-1, 1, 1), (-1, -1, 1)])  # 3d
sage: sigma2 = Cone([(1, 1, -1), (1, 2, 3), (1, -1, 1), (1, -1, -1)])  # 3d
sage: rho = sigma1.intersection(sigma2)
sage: rho.sublattice()
Sublattice <N(1, -1, 1), N(0, 3, 2)>
sage: sigma1.relative_quotient(rho)
1-d lattice, quotient
of Sublattice <N(3, 0, 1), N(2, 1, 0), N(1, 0, 0)>
by Sublattice <N(1, 2, 3), N(0, 3, 2)>
sage: sigma1.relative_quotient(rho).gens()
(N[0, -2, -1],)
sage: sigma2.relative_quotient(rho).gens()
(N[0, -1, -1],)
strict_quotient()

Return the quotient of self by the linear subspace.

We define the strict quotient of a cone to be the image of this cone in the quotient of the ambient space by the linear subspace of the cone, i.e. it is the “complementary part” to the linear subspace.

OUTPUT:

  • cone.

EXAMPLES:

sage: halfplane = Cone([(1,0), (0,1), (-1,0)])
sage: ssc = halfplane.strict_quotient()
sage: ssc
1-d cone in 1-d lattice N
sage: ssc.rays()
(N(1),)
sage: line = Cone([(1,0), (-1,0)])
sage: ssc = line.strict_quotient()
sage: ssc
0-d cone in 1-d lattice N
sage: ssc.rays()
()
sublattice(*args, **kwds)

The sublattice spanned by the cone.

Let \sigma be the given cone and N= self.lattice() the ambient lattice. Then, in the notation of [Fulton], this method returns the sublattice

N_\sigma \stackrel{\text{def}}{=} \mathop{span}( N\cap \sigma )

INPUT:

  • either nothing or something that can be turned into an element of this lattice.

OUTPUT:

  • if no arguments were given, a toric sublattice, otherwise the corresponding element of it.

Note

  • The sublattice spanned by the cone is the saturation of the sublattice generated by the rays of the cone.
  • See sage.geometry.cone.IntegralRayCollection.ray_basis() if you only need a \QQ-basis.
  • The returned lattice points are usually not rays of the cone. In fact, for a non-smooth cone the rays do not generate the sublattice N_\sigma, but only a finite index sublattice.

EXAMPLES:

sage: cone = Cone([(1, 1, 1), (1, -1, 1), (-1, -1, 1), (-1, 1, 1)])
sage: cone.ray_basis_matrix()
[ 1  1 -1]
[ 1 -1 -1]
[ 1  1  1]
sage: cone.ray_basis_matrix().det()
-4
sage: cone.sublattice()
Sublattice <N(1, 1, 1), N(0, 1, 0), N(1, 0, 0)>
sage: matrix( cone.sublattice().gens() ).det()
-1

Another example:

sage: c = Cone([(1,2,3), (4,-5,1)])
sage: c
2-d cone in 3-d lattice N
sage: c.rays()
(N(1, 2, 3), N(4, -5, 1))
sage: c.sublattice()
Sublattice <N(1, 2, 3), N(0, 13, 11)>
sage: c.sublattice(5, -3, 4)
N(5, -3, 4)
sage: c.sublattice(1, 0, 0)            
Traceback (most recent call last):
...
TypeError: element (= [1, 0, 0]) is not in free module
sublattice_complement(*args, **kwds)

A complement of the sublattice spanned by the cone.

In other words, sublattice() and sublattice_complement() together form a \ZZ-basis for the ambient lattice().

In the notation of [Fulton], let \sigma be the given cone and N= self.lattice() the ambient lattice. Then this method returns

N(\sigma) \stackrel{\text{def}}{=} N / N_\sigma

lifted (non-canonically) to a sublattice of N.

INPUT:

  • either nothing or something that can be turned into an element of this lattice.

OUTPUT:

  • if no arguments were given, a toric sublattice, otherwise the corresponding element of it.

EXAMPLES:

sage: C2_Z2 = Cone([(1,0),(1,2)])     # C^2/Z_2
sage: c1, c2 = C2_Z2.facets()
sage: c2.sublattice()
Sublattice <N(1, 2)>
sage: c2.sublattice_complement()
Sublattice <N(0, 1)>

A more complicated example:

sage: c = Cone([(1,2,3), (4,-5,1)])
sage: c.sublattice()
Sublattice <N(1, 2, 3), N(0, 13, 11)>
sage: c.sublattice_complement()
Sublattice <N(-7, -8, -16)>
sage: m = matrix( c.sublattice().gens() + c.sublattice_complement().gens() )
sage: m
[  1   2   3]
[  0  13  11]
[ -7  -8 -16]
sage: m.det()
-1
sublattice_quotient(*args, **kwds)

The quotient of the ambient lattice by the sublattice spanned by the cone.

INPUT:

  • either nothing or something that can be turned into an element of this lattice.

OUTPUT:

EXAMPLES:

sage: C2_Z2 = Cone([(1,0),(1,2)])     # C^2/Z_2
sage: c1, c2 = C2_Z2.facets()
sage: c2.sublattice_quotient()
1-d lattice, quotient of 2-d lattice N by Sublattice <N(1, 2)>
sage: N = C2_Z2.lattice()
sage: n = N(1,1)
sage: n_bar = c2.sublattice_quotient(n); n_bar
N[1, 1]
sage: n_bar.lift()
N(1, 1)
sage: vector(n_bar)
(-1)
class sage.geometry.cone.IntegralRayCollection(rays, lattice)

Bases: sage.structure.sage_object.SageObject, _abcoll.Hashable, _abcoll.Iterable

Create a collection of integral rays.

Warning

No correctness check or normalization is performed on the input data. This class is designed for internal operations and you probably should not use it directly.

This is a base class for convex rational polyhedral cones and fans.

Ray collections are immutable, but they cache most of the returned values.

INPUT:

  • rays – list of immutable vectors in lattice;
  • latticeToricLattice, \ZZ^n, or any other object that behaves like these. If None, it will be determined as parent() of the first ray. Of course, this cannot be done if there are no rays, so in this case you must give an appropriate lattice directly. Note that None is not the default value - you always must give this argument explicitly, even if it is None.

OUTPUT:

  • collection of given integral rays.
cartesian_product(other, lattice=None)

Return the Cartesian product of self with other.

INPUT:

  • other – an IntegralRayCollection;
  • lattice – (optional) the ambient lattice for the result. By default, the direct sum of the ambient lattices of self and other is constructed.

OUTPUT:

By the Cartesian product of ray collections (r_0, \dots, r_{n-1}) and (s_0, \dots, s_{m-1}) we understand the ray collection of the form ((r_0, 0), \dots, (r_{n-1}, 0), (0, s_0), \dots, (0, s_{m-1})), which is suitable for Cartesian products of cones and fans. The ray order is guaranteed to be as described.

EXAMPLES:

sage: c = Cone([(1,)])
sage: c.cartesian_product(c)    # indirect doctest
2-d cone in 2-d lattice N+N
sage: _.rays()
(N+N(1, 0), N+N(0, 1))
dim()

Return the dimension of the subspace spanned by rays of self.

OUTPUT:

  • integer.

EXAMPLES:

sage: c = Cone([(1,0)])
sage: c.lattice_dim()
2
sage: c.dim()
1
dual_lattice()

Return the dual of the ambient lattice of self.

OUTPUT:

  • lattice. If possible (that is, if lattice() has a dual() method), the dual lattice is returned. Otherwise, \ZZ^n is returned, where n is the dimension of self.

EXAMPLES:

sage: c = Cone([(1,0)])
sage: c.dual_lattice()
2-d lattice M
sage: Cone([], ZZ^3).dual_lattice()
Ambient free module of rank 3
over the principal ideal domain Integer Ring
lattice()

Return the ambient lattice of self.

OUTPUT:

  • lattice.

EXAMPLES:

sage: c = Cone([(1,0)])
sage: c.lattice()
2-d lattice N
sage: Cone([], ZZ^3).lattice()
Ambient free module of rank 3
over the principal ideal domain Integer Ring
lattice_dim()

Return the dimension of the ambient lattice of self.

OUTPUT:

  • integer.

EXAMPLES:

sage: c = Cone([(1,0)])
sage: c.lattice_dim()
2
sage: c.dim()
1
nrays()

Return the number of rays of self.

OUTPUT:

  • integer.

EXAMPLES:

sage: c = Cone([(1,0), (0,1)])
sage: c.nrays()
2
plot(**options)

Plot self.

INPUT:

OUTPUT:

  • a plot.

EXAMPLES:

sage: quadrant = Cone([(1,0), (0,1)])
sage: quadrant.plot()
ray(n)

Return the n-th ray of self.

INPUT:

  • n – integer, an index of a ray of self. Enumeration of rays starts with zero.

OUTPUT:

  • ray, an element of the lattice of self.

EXAMPLES:

sage: c = Cone([(1,0), (0,1)])
sage: c.ray(0)
N(1, 0)
ray_basis()

Returns a linearly independent subset of the rays.

OUTPUT:

Returns a random but fixed choice of a \QQ-basis (of N-lattice points) for the vector space spanned by the rays.

EXAMPLES:

sage: c = Cone([(1,1,1,1), (1,-1,1,1), (-1,-1,1,1), (-1,1,1,1), (0,0,0,1)])
sage: c.ray_basis()
(N(1, 1, 1, 1), N(1, -1, 1, 1), N(-1, -1, 1, 1), N(0, 0, 0, 1))
ray_basis_matrix()

Returns a linearly independent subset of the rays as a matrix.

OUTPUT:

  • Returns a random but fixed choice of a \QQ-basis (of N-lattice points) for the vector space spanned by the rays.
  • The linearly independent rays are the columns of the returned matrix.

EXAMPLES:

sage: c = Cone([(1,1,1,1), (1,-1,1,1), (-1,-1,1,1), (-1,1,1,1), (0,0,0,1)])
sage: c.ray_basis_matrix()
[ 1  1 -1  0]
[ 1 -1 -1  0]
[ 1  1  1  0]
[ 1  1  1  1]
ray_iterator(ray_list=None)

Return an iterator over (some of) the rays of self.

INPUT:

  • ray_list – list of integers, the indices of the requested rays. If not specified, an iterator over all rays of self will be returned.

OUTPUT:

  • iterator.

EXAMPLES:

sage: c = Cone([(1,0), (0,1), (-1, 0)])
sage: for ray in c.ray_iterator(): print ray
N(0, 1)
N(1, 0)
N(-1, 0)
sage: for ray in c.ray_iterator([2,1]): print ray
N(-1, 0)
N(1, 0)
ray_matrix()

Return a matrix whose columns are rays of self.

It can be convenient for linear algebra operations on rays, as well as for easy-to-read output.

OUTPUT:

  • matrix.

EXAMPLES:

sage: c = Cone([(1,0), (0,1), (-1, 0)])
sage: c.ray_matrix()
[ 0  1 -1]
[ 1  0  0]
ray_set()

Return rays of self as a frozenset.

Use rays() if you want to get rays in the fixed order.

OUTPUT:

  • frozenset of rays.

EXAMPLES:

sage: c = Cone([(1,0), (0,1), (-1, 0)])
sage: c.ray_set()
frozenset([N(0, 1), N(1, 0), N(-1, 0)])
rays(ray_list=None)

Return rays of self as a tuple.

INPUT:

  • ray_list – list of integers, the indices of the requested rays. If not specified, all rays of self will be returned. You may want to use ray_set() if you do not care about the order of rays. See also ray_iterator().

OUTPUT:

  • tuple of rays.

EXAMPLES:

sage: c = Cone([(1,0), (0,1), (-1, 0)])
sage: c.rays()
(N(0, 1), N(1, 0), N(-1, 0))
sage: c.rays([0, 2])
(N(0, 1), N(-1, 0))
sage.geometry.cone.is_Cone(x)

Check if x is a cone.

INPUT:

  • x – anything.

OUTPUT:

  • True if x is a cone and False otherwise.

EXAMPLES:

sage: from sage.geometry.cone import is_Cone
sage: is_Cone(1)
False
sage: quadrant = Cone([(1,0), (0,1)])
sage: quadrant
2-d cone in 2-d lattice N
sage: is_Cone(quadrant)
True
sage.geometry.cone.normalize_rays(rays, lattice)

Normalize a list of rational rays: make them primitive and immutable.

INPUT:

  • rays – list of rays which can be converted to the rational extension of lattice;
  • latticeToricLattice, \ZZ^n, or any other object that behaves like these. If None, an attempt will be made to determine an appropriate toric lattice automatically.

OUTPUT:

  • list of immutable primitive vectors of the lattice in the same directions as original rays.

EXAMPLES:

sage: from sage.geometry.cone import normalize_rays
sage: normalize_rays([(0, 1), (0, 2), (3, 2), (5/7, 10/3)], None)
[N(0, 1), N(0, 1), N(3, 2), N(3, 14)]
sage: L = ToricLattice(2, "L")
sage: normalize_rays([(0, 1), (0, 2), (3, 2), (5/7, 10/3)], L.dual())
[L*(0, 1), L*(0, 1), L*(3, 2), L*(3, 14)]
sage: ray_in_L = L(0,1)
sage: normalize_rays([ray_in_L, (0, 2), (3, 2), (5/7, 10/3)], None)
[L(0, 1), L(0, 1), L(3, 2), L(3, 14)]
sage: normalize_rays([(0, 1), (0, 2), (3, 2), (5/7, 10/3)], ZZ^2)
[(0, 1), (0, 1), (3, 2), (3, 14)]
sage: normalize_rays([(0, 1), (0, 2), (3, 2), (5/7, 10/3)], ZZ^3)
Traceback (most recent call last):
...
TypeError: cannot convert (0, 1) to
Vector space of dimension 3 over Rational Field!
sage: normalize_rays([], ZZ^3)
[]

Previous topic

Toric lattices

Next topic

Rational polyhedral fans

This Page