--- /dev/null
+# Sage doesn't load ~/.sage/init.sage during testing (sage -t), so we
+# have to explicitly mangle our sitedir here so that "mjo.cone"
+# resolves.
+from os.path import abspath
+from site import addsitedir
+addsitedir(abspath('../../'))
+
+from sage.all import *
+
+def rearrangement_cone(p,n):
+ r"""
+ Return the rearrangement cone of order ``p`` in ``n`` dimensions.
+
+ The rearrangement cone in ``n`` dimensions has as its elements
+ vectors of length ``n``. For inclusion in the cone, the smallest
+ ``p`` components of a vector must sum to a nonnegative number.
+
+ For example, the rearrangement cone of order ``p == 1`` has its
+ single smallest component nonnegative. This implies that all
+ components are nonnegative, and that therefore the rearrangement
+ cone of order one is the nonnegative orthant.
+
+ When ``p == n``, the sum of all components of a vector must be
+ nonnegative for inclusion in the cone. That is, the cone is a
+ half-space in ``n`` dimensions.
+
+ INPUT:
+
+ - ``p`` -- The number of components to "rearrange."
+
+ - ``n`` -- The dimension of the ambient space for the resulting cone.
+
+ OUTPUT:
+
+ A polyhedral closed convex cone object representing a rearrangement
+ cone of order ``p`` in ``n`` dimensions.
+
+ EXAMPLES:
+
+ The rearrangement cones of order one are nonnegative orthants::
+
+ sage: rearrangement_cone(1,1) == Cone([(1,)])
+ True
+ sage: rearrangement_cone(1,2) == Cone([(0,1),(1,0)])
+ True
+ sage: rearrangement_cone(1,3) == Cone([(0,0,1),(0,1,0),(1,0,0)])
+ True
+
+ When ``p == n``, the resulting cone will be a half-space, so we
+ expect its lineality to be one less than ``n`` because it will
+ contain a hyperplane but is not the entire space::
+
+ sage: rearrangement_cone(5,5).lineality()
+ 4
+
+ TESTS:
+
+ todo.
+ should be permutation invariant.
+ should have the expected lyapunov rank.
+ just loop through them all for n <= 10 and p < n?
+
+ """
+
+ def d(j):
+ v = [1]*n # Create the list of all ones...
+ v[j] = 1 - p # Now "fix" the ``j``th entry.
+ return v
+
+ V = VectorSpace(QQ, n)
+ G = V.basis() + [ d(j) for j in range(n) ]
+ return Cone(G)