Hyperplanes - Combinatorial and Discrete Geometry

Skip to content
Back to top
View this page
Edit this page

# Hyperplanes

Note

If you want to learn about Sage’s hyperplane arrangements then you should start with `sage.geometry.hyperplane_arrangement.arrangement`. This module is used to represent the individual hyperplanes, but you should never construct the classes from this module directly (but only via the `HyperplaneArrangements`.

A linear expression, for example, \(3x+3y-5z-7\) stands for the hyperplane with the equation \(x+3y-5z=7\). To create it in Sage, you first have to create a `HyperplaneArrangements` object to define the variables \(x\), \(y\), \(z\):

Sage

    sage: H.<x,y,z> = HyperplaneArrangements(QQ)
    sage: h = 3*x + 2*y - 5*z - 7;  h
    Hyperplane 3*x + 2*y - 5*z - 7
    sage: h.coefficients()
    [-7, 3, 2, -5]
    sage: h.normal()
    (3, 2, -5)
    sage: h.constant_term()
    -7
    sage: h.change_ring(GF(3))
    Hyperplane 0*x + 2*y + z + 2
    sage: h.point()
    (21/38, 7/19, -35/38)
    sage: h.linear_part()
    Vector space of degree 3 and dimension 2 over Rational Field
    Basis matrix:
    [  1   0 3/5]
    [  0   1 2/5]

Python

    >>> from sage.all import *
    >>> H = HyperplaneArrangements(QQ, names=('x', 'y', 'z',)); (x, y, z,) = H._first_ngens(3)
    >>> h = Integer(3)*x + Integer(2)*y - Integer(5)*z - Integer(7);  h
    Hyperplane 3*x + 2*y - 5*z - 7
    >>> h.coefficients()
    [-7, 3, 2, -5]
    >>> h.normal()
    (3, 2, -5)
    >>> h.constant_term()
    -7
    >>> h.change_ring(GF(Integer(3)))
    Hyperplane 0*x + 2*y + z + 2
    >>> h.point()
    (21/38, 7/19, -35/38)
    >>> h.linear_part()
    Vector space of degree 3 and dimension 2 over Rational Field
    Basis matrix:
    [  1   0 3/5]
    [  0   1 2/5]

Another syntax to create hyperplanes is to specify coefficients and a constant term:

Sage

    sage: V = H.ambient_space();  V
    3-dimensional linear space over Rational Field with coordinates x, y, z
    sage: h in V
    True
    sage: V([3, 2, -5], -7)
    Hyperplane 3*x + 2*y - 5*z - 7

[Python]

    >>> from sage.all import *
    >>> V = H.ambient_space();  V
    3-dimensional linear space over Rational Field with coordinates x, y, z
    >>> h in V
    True
    >>> V([Integer(3), Integer(2), -Integer(5)], -Integer(7))
    Hyperplane 3*x + 2*y - 5*z - 7

Or constant term and coefficients together in one list/tuple/iterable:

Sage

    sage: V([-7, 3, 2, -5])
    Hyperplane 3*x + 2*y - 5*z - 7
    sage: v = vector([-7, 3, 2, -5]);  v
    (-7, 3, 2, -5)
    sage: V(v)
    Hyperplane 3*x + 2*y - 5*z - 7

Python

    >>> from sage.all import *
    >>> V([-Integer(7), Integer(3), Integer(2), -Integer(5)])
    Hyperplane 3*x + 2*y - 5*z - 7
    >>> v = vector([-Integer(7), Integer(3), Integer(2), -Integer(5)]);  v
    (-7, 3, 2, -5)
    >>> V(v)
    Hyperplane 3*x + 2*y - 5*z - 7

Note that the constant term comes first, which matches the notation for Sage’s `Polyhedron()`

Sage

    sage: Polyhedron(ieqs=[(4,1,2,3)]).Hrepresentation()
    (An inequality (1, 2, 3) x + 4 >= 0,)

[Python]

    >>> from sage.all import *
    >>> Polyhedron(ieqs=[(Integer(4),Integer(1),Integer(2),Integer(3))]).Hrepresentation()
    (An inequality (1, 2, 3) x + 4 >= 0,)

The difference between hyperplanes as implemented in this module and hyperplane arrangements is that:

- hyperplane arrangements contain multiple hyperplanes (of course),

- linear expressions are a module over the base ring, and these module structure is inherited by the hyperplanes.

The latter means that you can add and multiply by a scalar:

Sage

    sage: h = 3*x + 2*y - 5*z - 7;  h
    Hyperplane 3*x + 2*y - 5*z - 7
    sage: -h
    Hyperplane -3*x - 2*y + 5*z + 7
    sage: h + x
    Hyperplane 4*x + 2*y - 5*z - 7
    sage: h + 7
    Hyperplane 3*x + 2*y - 5*z + 0
    sage: 3*h
    Hyperplane 9*x + 6*y - 15*z - 21
    sage: h * RDF(3)
    Hyperplane 9.0*x + 6.0*y - 15.0*z - 21.0

Python

    >>> from sage.all import *
    >>> h = Integer(3)*x + Integer(2)*y - Integer(5)*z - Integer(7);  h
    Hyperplane 3*x + 2*y - 5*z - 7
    >>> -h
    Hyperplane -3*x - 2*y + 5*z + 7
    >>> h + x
    Hyperplane 4*x + 2*y - 5*z - 7
    >>> h + Integer(7)
    Hyperplane 3*x + 2*y - 5*z + 0
    >>> Integer(3)*h
    Hyperplane 9*x + 6*y - 15*z - 21
    >>> h * RDF(Integer(3))
    Hyperplane 9.0*x + 6.0*y - 15.0*z - 21.0

Which you can’t do with hyperplane arrangements:

Sage

    sage: arrangement = H(h, x, y, x+y-1);  arrangement
    Arrangement <y | x | x + y - 1 | 3*x + 2*y - 5*z - 7>
    sage: arrangement + x
    Traceback (most recent call last):
    ...
    TypeError: unsupported operand parent(s) for +:
    'Hyperplane arrangements in 3-dimensional linear space
         over Rational Field with coordinates x, y, z' and
    'Hyperplane arrangements in 3-dimensional linear space
         over Rational Field with coordinates x, y, z'

[Python]

    >>> from sage.all import *
    >>> arrangement = H(h, x, y, x+y-Integer(1));  arrangement
    Arrangement <y | x | x + y - 1 | 3*x + 2*y - 5*z - 7>
    >>> arrangement + x
    Traceback (most recent call last):
    ...
    TypeError: unsupported operand parent(s) for +:
    'Hyperplane arrangements in 3-dimensional linear space
         over Rational Field with coordinates x, y, z' and
    'Hyperplane arrangements in 3-dimensional linear space
         over Rational Field with coordinates x, y, z'

class sage.geometry.hyperplane_arrangement.hyperplane.AmbientVectorSpace(base_ring, names=())

  Bases: `LinearExpressionModule`

  The ambient space for hyperplanes.

  This class is the parent for the `Hyperplane` instances.

  Element

    alias of `Hyperplane`

  change_ring(base_ring)

    Return a ambient vector space with a changed base ring.

    INPUT:

    - `base_ring` – a ring; the new base ring

    OUTPUT: a new `AmbientVectorSpace`

    EXAMPLES:

    Sage

        sage: M.<y> = HyperplaneArrangements(QQ)
        sage: V = M.ambient_space()
        sage: V.change_ring(RR)
        1-dimensional linear space over Real Field with 53 bits of precision with coordinate y

    Python

        >>> from sage.all import *
        >>> M = HyperplaneArrangements(QQ, names=('y',)); (y,) = M._first_ngens(1)
        >>> V = M.ambient_space()
        >>> V.change_ring(RR)
        1-dimensional linear space over Real Field with 53 bits of precision with coordinate y

  dimension()

    Return the ambient space dimension.

    OUTPUT: integer

    EXAMPLES:

    Sage

        sage: M.<x,y> = HyperplaneArrangements(QQ)
        sage: x.parent().dimension()
        2
        sage: x.parent() is M.ambient_space()
        True
        sage: x.dimension()
        1

    Python

        >>> from sage.all import *
        >>> M = HyperplaneArrangements(QQ, names=('x', 'y',)); (x, y,) = M._first_ngens(2)
        >>> x.parent().dimension()
        2
        >>> x.parent() is M.ambient_space()
        True
        >>> x.dimension()
        1

  symmetric_space()

    Construct the symmetric space of `self`.

    Consider a hyperplane arrangement \(A\) in the vector space \(V = k^n\), for some field \(k\). The symmetric space is the symmetric algebra \(S(V^*)\) as the polynomial ring \(k[x_1, x_2, \ldots, x_n]\) where \((x_1, x_2, \ldots, x_n)\) is a basis for \(V\).

    EXAMPLES:

    Sage

        sage: H.<x,y,z> = HyperplaneArrangements(QQ)
        sage: A = H.ambient_space()
        sage: A.symmetric_space()
        Multivariate Polynomial Ring in x, y, z over Rational Field

    Python

        >>> from sage.all import *
        >>> H = HyperplaneArrangements(QQ, names=('x', 'y', 'z',)); (x, y, z,) = H._first_ngens(3)
        >>> A = H.ambient_space()
        >>> A.symmetric_space()
        Multivariate Polynomial Ring in x, y, z over Rational Field

class sage.geometry.hyperplane_arrangement.hyperplane.Hyperplane(parent, coefficients, constant)

  Bases: `LinearExpression`

  A hyperplane.

  You should always use `AmbientVectorSpace` to construct instances of this class.

  INPUT:

  - `parent` – the parent `AmbientVectorSpace`

  - `coefficients` – a vector of coefficients of the linear variables

  - `constant` – the constant term for the linear expression

  EXAMPLES:

  Sage

      sage: H.<x,y> = HyperplaneArrangements(QQ)
      sage: x+y-1
      Hyperplane x + y - 1

      sage: ambient = H.ambient_space()
      sage: ambient._element_constructor_(x+y-1)
      Hyperplane x + y - 1

  Python

      >>> from sage.all import *
      >>> H = HyperplaneArrangements(QQ, names=('x', 'y',)); (x, y,) = H._first_ngens(2)
      >>> x+y-Integer(1)
      Hyperplane x + y - 1

      >>> ambient = H.ambient_space()
      >>> ambient._element_constructor_(x+y-Integer(1))
      Hyperplane x + y - 1

  For technical reasons, we must allow the degenerate cases of an empty space and of a full space:

  Sage

      sage: 0*x
      Hyperplane 0*x + 0*y + 0
      sage: 0*x + 1
      Hyperplane 0*x + 0*y + 1
      sage: x + 0 == x + ambient(0)    # because coercion requires them
      True

  [Python]

      >>> from sage.all import *
      >>> Integer(0)*x
      Hyperplane 0*x + 0*y + 0
      >>> Integer(0)*x + Integer(1)
      Hyperplane 0*x + 0*y + 1
      >>> x + Integer(0) == x + ambient(Integer(0))    # because coercion requires them
      True

  dimension()

    The dimension of the hyperplane.

    OUTPUT: integer

    EXAMPLES:

    Sage

        sage: H.<x,y,z> = HyperplaneArrangements(QQ)
        sage: h = x + y + z - 1
        sage: h.dimension()
        2

    Python

        >>> from sage.all import *
        >>> H = HyperplaneArrangements(QQ, names=('x', 'y', 'z',)); (x, y, z,) = H._first_ngens(3)
        >>> h = x + y + z - Integer(1)
        >>> h.dimension()
        2

  intersection(other)

    The intersection of `self` with `other`.

    INPUT:

    - `other` – a hyperplane, a polyhedron, or something that defines a polyhedron

    OUTPUT: a polyhedron

    EXAMPLES:

    Sage

        sage: H.<x,y,z> = HyperplaneArrangements(QQ)
        sage: h = x + y + z - 1
        sage: h.intersection(x - y)
        A 1-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex and 1 line
        sage: h.intersection(polytopes.cube())
        A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices

    Python

        >>> from sage.all import *
        >>> H = HyperplaneArrangements(QQ, names=('x', 'y', 'z',)); (x, y, z,) = H._first_ngens(3)
        >>> h = x + y + z - Integer(1)
        >>> h.intersection(x - y)
        A 1-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex and 1 line
        >>> h.intersection(polytopes.cube())
        A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices

  linear_part()

    The linear part of the affine space.

    OUTPUT:

    Vector subspace of the ambient vector space, parallel to the hyperplane.

    EXAMPLES:

    Sage

        sage: H.<x,y,z> = HyperplaneArrangements(QQ)
        sage: h = x + 2*y + 3*z - 1
        sage: h.linear_part()
        Vector space of degree 3 and dimension 2 over Rational Field
        Basis matrix:
        [   1    0 -1/3]
        [   0    1 -2/3]

    Python

        >>> from sage.all import *
        >>> H = HyperplaneArrangements(QQ, names=('x', 'y', 'z',)); (x, y, z,) = H._first_ngens(3)
        >>> h = x + Integer(2)*y + Integer(3)*z - Integer(1)
        >>> h.linear_part()
        Vector space of degree 3 and dimension 2 over Rational Field
        Basis matrix:
        [   1    0 -1/3]
        [   0    1 -2/3]

  linear_part_projection(point)

    Orthogonal projection onto the linear part.

    INPUT:

    - `point` – vector of the ambient space, or anything that can be converted into one; not necessarily on the hyperplane

    OUTPUT:

    Coordinate vector of the projection of `point` with respect to the basis of `linear_part()`. In particular, the length of this vector is one less than the ambient space dimension.

    EXAMPLES:

    Sage

        sage: H.<x,y,z> = HyperplaneArrangements(QQ)
        sage: h = x + 2*y + 3*z - 4
        sage: h.linear_part()
        Vector space of degree 3 and dimension 2 over Rational Field
        Basis matrix:
        [   1    0 -1/3]
        [   0    1 -2/3]
        sage: p1 = h.linear_part_projection(0);  p1
        (0, 0)
        sage: p2 = h.linear_part_projection([3,4,5]);  p2
        (8/7, 2/7)
        sage: h.linear_part().basis()
        [(1, 0, -1/3), (0, 1, -2/3)]
        sage: p3 = h.linear_part_projection([1,1,1]);  p3
        (4/7, 1/7)

    Python

        >>> from sage.all import *
        >>> H = HyperplaneArrangements(QQ, names=('x', 'y', 'z',)); (x, y, z,) = H._first_ngens(3)
        >>> h = x + Integer(2)*y + Integer(3)*z - Integer(4)
        >>> h.linear_part()
        Vector space of degree 3 and dimension 2 over Rational Field
        Basis matrix:
        [   1    0 -1/3]
        [   0    1 -2/3]
        >>> p1 = h.linear_part_projection(Integer(0));  p1
        (0, 0)
        >>> p2 = h.linear_part_projection([Integer(3),Integer(4),Integer(5)]);  p2
        (8/7, 2/7)
        >>> h.linear_part().basis()
        [(1, 0, -1/3), (0, 1, -2/3)]
        >>> p3 = h.linear_part_projection([Integer(1),Integer(1),Integer(1)]);  p3
        (4/7, 1/7)

  normal()

    Return the normal vector.

    OUTPUT: a vector over the base ring

    EXAMPLES:

    Sage

        sage: H.<x, y, z> = HyperplaneArrangements(QQ)
        sage: x.normal()
        (1, 0, 0)
        sage: x.A(), x.b()
        ((1, 0, 0), 0)
        sage: (x + 2*y + 3*z + 4).normal()
        (1, 2, 3)

    Python

        >>> from sage.all import *
        >>> H = HyperplaneArrangements(QQ, names=('x', 'y', 'z',)); (x, y, z,) = H._first_ngens(3)
        >>> x.normal()
        (1, 0, 0)
        >>> x.A(), x.b()
        ((1, 0, 0), 0)
        >>> (x + Integer(2)*y + Integer(3)*z + Integer(4)).normal()
        (1, 2, 3)

  orthogonal_projection(point)

    Return the orthogonal projection of a point.

    INPUT:

    - `point` – vector of the ambient space, or anything that can be converted into one; not necessarily on the hyperplane

    OUTPUT:

    A vector in the ambient vector space that lies on the hyperplane.

    In finite characteristic, a `ValueError` is raised if the the norm of the hyperplane normal is zero.

    EXAMPLES:

    Sage

        sage: H.<x,y,z> = HyperplaneArrangements(QQ)
        sage: h = x + 2*y + 3*z - 4
        sage: p1 = h.orthogonal_projection(0);  p1
        (2/7, 4/7, 6/7)
        sage: p1 in h
        True
        sage: p2 = h.orthogonal_projection([3,4,5]);  p2
        (10/7, 6/7, 2/7)
        sage: p1 in h
        True
        sage: p3 = h.orthogonal_projection([1,1,1]);  p3
        (6/7, 5/7, 4/7)
        sage: p3 in h
        True

    Python

        >>> from sage.all import *
        >>> H = HyperplaneArrangements(QQ, names=('x', 'y', 'z',)); (x, y, z,) = H._first_ngens(3)
        >>> h = x + Integer(2)*y + Integer(3)*z - Integer(4)
        >>> p1 = h.orthogonal_projection(Integer(0));  p1
        (2/7, 4/7, 6/7)
        >>> p1 in h
        True
        >>> p2 = h.orthogonal_projection([Integer(3),Integer(4),Integer(5)]);  p2
        (10/7, 6/7, 2/7)
        >>> p1 in h
        True
        >>> p3 = h.orthogonal_projection([Integer(1),Integer(1),Integer(1)]);  p3
        (6/7, 5/7, 4/7)
        >>> p3 in h
        True

  plot(**kwds)

    Plot the hyperplane.

    OUTPUT: a graphics object

    EXAMPLES:

    Sage

        sage: L.<x, y> = HyperplaneArrangements(QQ)
        sage: (x + y - 2).plot()                                                    # needs sage.plot
        Graphics object consisting of 2 graphics primitives

    Python

        >>> from sage.all import *
        >>> L = HyperplaneArrangements(QQ, names=('x', 'y',)); (x, y,) = L._first_ngens(2)
        >>> (x + y - Integer(2)).plot()                                                    # needs sage.plot
        Graphics object consisting of 2 graphics primitives

  point()

    Return the point closest to the origin.

    OUTPUT:

    A vector of the ambient vector space. The closest point to the origin in the \(L^2\)-norm.

    In finite characteristic a random point will be returned if the norm of the hyperplane normal vector is zero.

    EXAMPLES:

    Sage

        sage: H.<x,y,z> = HyperplaneArrangements(QQ)
        sage: h = x + 2*y + 3*z - 4
        sage: h.point()
        (2/7, 4/7, 6/7)
        sage: h.point() in h
        True

        sage: H.<x,y,z> = HyperplaneArrangements(GF(3))
        sage: h = 2*x + y + z + 1
        sage: h.point()
        (1, 0, 0)
        sage: h.point().base_ring()
        Finite Field of size 3

        sage: H.<x,y,z> = HyperplaneArrangements(GF(3))
        sage: h = x + y + z + 1
        sage: h.point()
        (2, 0, 0)

    Python

        >>> from sage.all import *
        >>> H = HyperplaneArrangements(QQ, names=('x', 'y', 'z',)); (x, y, z,) = H._first_ngens(3)
        >>> h = x + Integer(2)*y + Integer(3)*z - Integer(4)
        >>> h.point()
        (2/7, 4/7, 6/7)
        >>> h.point() in h
        True

        >>> H = HyperplaneArrangements(GF(Integer(3)), names=('x', 'y', 'z',)); (x, y, z,) = H._first_ngens(3)
        >>> h = Integer(2)*x + y + z + Integer(1)
        >>> h.point()
        (1, 0, 0)
        >>> h.point().base_ring()
        Finite Field of size 3

        >>> H = HyperplaneArrangements(GF(Integer(3)), names=('x', 'y', 'z',)); (x, y, z,) = H._first_ngens(3)
        >>> h = x + y + z + Integer(1)
        >>> h.point()
        (2, 0, 0)

  polyhedron(**kwds)

    Return the hyperplane as a polyhedron.

    OUTPUT: a `Polyhedron()` instance

    EXAMPLES:

    Sage

        sage: H.<x,y,z> = HyperplaneArrangements(QQ)
        sage: h = x + 2*y + 3*z - 4
        sage: P = h.polyhedron();  P
        A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex and 2 lines
        sage: P.Hrepresentation()
        (An equation (1, 2, 3) x - 4 == 0,)
        sage: P.Vrepresentation()
        (A line in the direction (0, 3, -2),
         A line in the direction (3, 0, -1),
         A vertex at (0, 0, 4/3))

    Python

        >>> from sage.all import *
        >>> H = HyperplaneArrangements(QQ, names=('x', 'y', 'z',)); (x, y, z,) = H._first_ngens(3)
        >>> h = x + Integer(2)*y + Integer(3)*z - Integer(4)
        >>> P = h.polyhedron();  P
        A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex and 2 lines
        >>> P.Hrepresentation()
        (An equation (1, 2, 3) x - 4 == 0,)
        >>> P.Vrepresentation()
        (A line in the direction (0, 3, -2),
         A line in the direction (3, 0, -1),
         A vertex at (0, 0, 4/3))

  primitive(signed=True)

    Return hyperplane defined by primitive equation.

    INPUT:

    - `signed` – boolean (default: `True`); whether to preserve the overall sign

    OUTPUT:

    Hyperplane whose linear expression has common factors and denominators cleared. That is, the same hyperplane (with the same sign) but defined by a rescaled equation. Note that different linear expressions must define different hyperplanes as comparison is used in caching.

    If `signed`, the overall rescaling is by a positive constant only.

    EXAMPLES:

    Sage

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: h = -1/3*x + 1/2*y - 1;  h
        Hyperplane -1/3*x + 1/2*y - 1
        sage: h.primitive()
        Hyperplane -2*x + 3*y - 6
        sage: h == h.primitive()
        False
        sage: (4*x + 8).primitive()
        Hyperplane x + 0*y + 2

        sage: (4*x - y - 8).primitive(signed=True)   # default
        Hyperplane 4*x - y - 8
        sage: (4*x - y - 8).primitive(signed=False)
        Hyperplane -4*x + y + 8

    Python

        >>> from sage.all import *
        >>> H = HyperplaneArrangements(QQ, names=('x', 'y',)); (x, y,) = H._first_ngens(2)
        >>> h = -Integer(1)/Integer(3)*x + Integer(1)/Integer(2)*y - Integer(1);  h
        Hyperplane -1/3*x + 1/2*y - 1
        >>> h.primitive()
        Hyperplane -2*x + 3*y - 6
        >>> h == h.primitive()
        False
        >>> (Integer(4)*x + Integer(8)).primitive()
        Hyperplane x + 0*y + 2

        >>> (Integer(4)*x - y - Integer(8)).primitive(signed=True)   # default
        Hyperplane 4*x - y - 8
        >>> (Integer(4)*x - y - Integer(8)).primitive(signed=False)
        Hyperplane -4*x + y + 8

  to_symmetric_space()

    Return `self` considered as an element in the corresponding symmetric space.

    EXAMPLES:

    Sage

        sage: L.<x, y> = HyperplaneArrangements(QQ)
        sage: h = -1/3*x + 1/2*y
        sage: h.to_symmetric_space()
        -1/3*x + 1/2*y

        sage: hp = -1/3*x + 1/2*y - 1
        sage: hp.to_symmetric_space()
        Traceback (most recent call last):
        ...
        ValueError: the hyperplane must pass through the origin

    Python

        >>> from sage.all import *
        >>> L = HyperplaneArrangements(QQ, names=('x', 'y',)); (x, y,) = L._first_ngens(2)
        >>> h = -Integer(1)/Integer(3)*x + Integer(1)/Integer(2)*y
        >>> h.to_symmetric_space()
        -1/3*x + 1/2*y

        >>> hp = -Integer(1)/Integer(3)*x + Integer(1)/Integer(2)*y - Integer(1)
        >>> hp.to_symmetric_space()
        Traceback (most recent call last):
        ...
        ValueError: the hyperplane must pass through the origin