# HG changeset patch
# User Volker Braun <vbraun@stp.dias.ie>
# Date 1323989089 0
# Node ID 56a45af1784924d5bbe71724966f00eeaa3dd23c
# Parent  f1be9901d3afcf00286cb0edf407c2bc069de0ce
Trac #11597: Dimension of the singular set

This patch adds a method dimension_singularities()
to toric varieties that computes the dimension of the singular
set. This is usually one of the first questions one has, so I
find it rather convenient to have a method for it. It also adds
an optional fan.is_smooth(codim=d) argument for expert use,
though in practice I think its easy to get confused with
dimension and codimension so I did not add a similar optional
argument to toric_variety.is_smooth().

diff --git a/sage/geometry/fan.py b/sage/geometry/fan.py
--- a/sage/geometry/fan.py
+++ b/sage/geometry/fan.py
@@ -2188,14 +2188,20 @@
             self._is_simplicial = all(cone.is_simplicial() for cone in self)
         return self._is_simplicial
 
-    def is_smooth(self):
+    def is_smooth(self, codim=None):
         r"""
         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.)
+        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.
+
+        A `n`-dimensional fan is smooth up to a given codimension `d`
+        if all cones of codimension `\geq d` are smooth, that is, all
+        cones of dimension `\leq n-d` are smooth. In this case the
+        singular set of the corresponding toric variety is of
+        dimension `< d`.
 
         OUTPUT:
 
@@ -2214,11 +2220,19 @@
             sage: fan = NormalFan(lattice_polytope.octahedron(2))
             sage: fan.is_smooth()
             False
+            sage: fan.is_smooth(codim=1)
+            True
             sage: fan.generating_cone(0).rays()
             (N(-1, 1), N(-1, -1))
             sage: fan.generating_cone(0).ray_matrix().det()
             2
         """
+        if not codim is None:
+            for d in range(codim, self.lattice_dim()+1):
+                if not all(cone.is_smooth() for cone in self(codim=d)):
+                    return False
+            return True
+
         if "_is_smooth" not in self.__dict__:
             self._is_smooth = all(cone.is_smooth() for cone in self)
         return self._is_smooth
diff --git a/sage/schemes/generic/toric_variety.py b/sage/schemes/generic/toric_variety.py
--- a/sage/schemes/generic/toric_variety.py
+++ b/sage/schemes/generic/toric_variety.py
@@ -236,7 +236,7 @@
 from sage.geometry.cone import Cone, is_Cone
 from sage.geometry.fan import Fan
 from sage.matrix.all import matrix
-from sage.misc.all import latex, prod, uniq
+from sage.misc.all import latex, prod, uniq, cached_method
 from sage.structure.unique_representation import UniqueRepresentation
 from sage.modules.free_module_element import vector
 from sage.rings.all import PolynomialRing, ZZ, QQ, is_Field
@@ -1087,6 +1087,34 @@
         except AttributeError:
             pass
 
+    @cached_method
+    def dimension_singularities(self):
+        r"""
+        Return the dimension of the singular set.
+
+        OUTPUT:
+
+        Integer. The dimension of the singular set of the toric
+        variety. Often the singular set is a reducible subvariety, and
+        this method will return the dimension of the
+        largest-dimensional component. 
+
+        Returns -1 if the toric variety is smooth.
+
+        EXAMPLES::
+
+            sage: toric_varieties.P4_11169().dimension_singularities()
+            1
+            sage: toric_varieties.Conifold().dimension_singularities()
+            0
+            sage: toric_varieties.P2().dimension_singularities()
+            -1
+        """
+        for codim in range(0,self.dimension()+1):
+            if any(not cone.is_smooth() for cone in self.fan(codim)):
+                return self.dimension() - codim
+        return -1
+
     def is_homogeneous(self, polynomial):
         r"""
         Check if ``polynomial`` is homogeneous.
