### Navigation

- index
- modules |
- next |
- previous |
- Combinatorial Geometry »

# Hyperplane Arrangements

Before talking about hyperplane arrangements, let us start with individual hyperplanes. This package uses certain linear expressions to represent hyperplanes, that is, a linear expression \(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: 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.normal()
    (3, 2, -5)
    sage: h.constant_term()
    -7

The individual hyperplanes behave like the linear expression with regard to addition and scalar multiplication, which is why you can do linear combinations of the coordinates:

    sage: -2*h
    Hyperplane -6*x - 4*y + 10*z + 14
    sage: x, y, z
    (Hyperplane x + 0*y + 0*z + 0, Hyperplane 0*x + y + 0*z + 0, Hyperplane 0*x + 0*y + z + 0)

See `sage.geometry.hyperplane_arrangement.hyperplane` for more functionality of the individual hyperplanes.

## Arrangements

There are several ways to create hyperplane arrangements:

Notation (i): by passing individual hyperplanes to the `HyperplaneArrangements` object:

    sage: H.<x,y> = HyperplaneArrangements(QQ)
    sage: box = x | y | x-1 | y-1;  box
    Arrangement <y - 1 | y | x - 1 | x>
    sage: box == H(x, y, x-1, y-1)    # alternative syntax
    True

Notation (ii): by passing anything that defines a hyperplane, for example a coefficient vector and constant term:

    sage: H = HyperplaneArrangements(QQ, ('x', 'y'))
    sage: triangle = H([(1, 0), 0], [(0, 1), 0], [(1,1), -1]);  triangle
    Arrangement <y | x | x + y - 1>

    sage: H.inject_variables()
    Defining x, y
    sage: triangle == x | y | x+y-1
    True

The default base field is \(\QQ\), the rational numbers. Finite fields are also supported:

    sage: H.<x,y,z> = HyperplaneArrangements(GF(5))
    sage: a = H([(1,2,3), 4], [(5,6,7), 8]);  a
    Arrangement <y + 2*z + 3 | x + 2*y + 3*z + 4>

Notation (iii): a list or tuple of hyperplanes:

    sage: H.<x,y,z> = HyperplaneArrangements(GF(5))
    sage: k = [x+i for i in range(4)];  k
    [Hyperplane x + 0*y + 0*z + 0, Hyperplane x + 0*y + 0*z + 1,
     Hyperplane x + 0*y + 0*z + 2, Hyperplane x + 0*y + 0*z + 3]
    sage: H(k)
    Arrangement <x | x + 1 | x + 2 | x + 3>

Notation (iv): using the library of arrangements:

    sage: hyperplane_arrangements.braid(4)
    Arrangement of 6 hyperplanes of dimension 4 and rank 3
    sage: hyperplane_arrangements.semiorder(3)
    Arrangement of 6 hyperplanes of dimension 3 and rank 2
    sage: hyperplane_arrangements.graphical(graphs.PetersenGraph())
    Arrangement of 15 hyperplanes of dimension 10 and rank 9
    sage: hyperplane_arrangements.Ish(5)
    Arrangement of 20 hyperplanes of dimension 5 and rank 4

Notation (v): from the bounding hyperplanes of a polyhedron:

    sage: a = polytopes.n_cube(3).hyperplane_arrangement();  a
    Arrangement of 6 hyperplanes of dimension 3 and rank 3
    sage: a.n_regions()
    27

New arrangements from old:

    sage: a = hyperplane_arrangements.braid(3)
    sage: b = a.add_hyperplane([4, 1, 2, 3])
    sage: b
    Arrangement <t1 - t2 | t0 - t1 | t0 - t2 | t0 + 2*t1 + 3*t2 + 4>
    sage: c = b.deletion([4, 1, 2, 3])
    sage: a == c
    True

    sage: a = hyperplane_arrangements.braid(3)
    sage: b = a.union(hyperplane_arrangements.semiorder(3))
    sage: b == a | hyperplane_arrangements.semiorder(3)    # alternate syntax
    True
    sage: b == hyperplane_arrangements.Catalan(3)
    True

    sage: a
    Arrangement <t1 - t2 | t0 - t1 | t0 - t2>
    sage: a = hyperplane_arrangements.coordinate(4)
    sage: h = a.hyperplanes()[0]
    sage: b = a.restriction(h)
    sage: b == hyperplane_arrangements.coordinate(3)
    True

A hyperplane arrangement is essential is the normals to its hyperplane span the ambient space. Otherwise, it is inessential. The essentialization is formed by intersecting the hyperplanes by this normal space (actually, it is a bit more complicated over finite fields):

    sage: a = hyperplane_arrangements.braid(4);  a
    Arrangement of 6 hyperplanes of dimension 4 and rank 3
    sage: a.is_essential()
    False
    sage: a.rank() < a.dimension()  # double-check
    True
    sage: a.essentialization()
    Arrangement of 6 hyperplanes of dimension 3 and rank 3

The connected components of the complement of the hyperplanes of an arrangement in \(\RR^n\) are called the regions of the arrangement:

    sage: a = hyperplane_arrangements.semiorder(3)
    sage: b = a.essentialization();   b
    Arrangement of 6 hyperplanes of dimension 2 and rank 2
    sage: b.n_regions()
    19
    sage: b.regions()
    (A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 6 vertices,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices and 1 ray,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices and 1 ray,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices and 1 ray,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices and 1 ray,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices and 1 ray,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices and 1 ray,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays)
    sage: b.bounded_regions()
    (A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 6 vertices,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices,
    A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices)
    sage: b.n_bounded_regions()
    7
    sage: a.unbounded_regions()
    (A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line,
     A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices, 1 ray, 1 line,
     A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line,
     A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices, 1 ray, 1 line,
     A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line,
     A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices, 1 ray, 1 line,
     A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices, 1 ray, 1 line,
     A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line,
     A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices, 1 ray, 1 line,
     A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line,
     A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices, 1 ray, 1 line,
     A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line)

The distance between regions is defined as the number of hyperplanes separating them. For example:

    sage: r1 = b.regions()[0]
    sage: r2 = b.regions()[1]
    sage: b.distance_between_regions(r1, r2)
    1
    sage: [hyp for hyp in b if b.is_separating_hyperplane(r1, r2, hyp)]
    [Hyperplane 2*t1 + t2 + 1]
    sage: b.distance_enumerator(r1)  # generating function for distances from r1
    6*x^3 + 6*x^2 + 6*x + 1

Note

bounded region really mean relatively bounded here. A region is relatively bounded if its intersection with space spanned by the normals of the hyperplanes in the arrangement is bounded.

The intersection poset of a hyperplane arrangement is the collection of all nonempty intersections of hyperplanes in the arrangement, ordered by reverse inclusion. It includes the ambient space of the arrangement (as the intersection over the empty set):

    sage: a = hyperplane_arrangements.braid(3)
    sage: p = a.intersection_poset()
    sage: p.is_ranked()
    True
    sage: p.order_polytope()
    A 5-dimensional polyhedron in QQ^5 defined as the convex hull of 10 vertices

The characteristic polynomial is a basic invariant of a hyperplane arrangement. It is defined as

\[\chi(x) := \sum_{w\in P} \mu(w) x^{dim(w)}\]

where the sum is \(P\) is the `intersection_poset()` of the arrangement and \(\mu\) is the Moebius function of \(P\):

    sage: a = hyperplane_arrangements.semiorder(5)
    sage: a.characteristic_polynomial()               # long time (about a second on Core i7)
    x^5 - 20*x^4 + 180*x^3 - 790*x^2 + 1380*x
    sage: a.poincare_polynomial()                     # long time
    1380*x^4 + 790*x^3 + 180*x^2 + 20*x + 1
    sage: a.n_regions()                               # long time
    2371
    sage: charpoly = a.characteristic_polynomial()    # long time
    sage: charpoly(-1)                                # long time
    -2371
    sage: a.n_bounded_regions()                       # long time
    751
    sage: charpoly(1)                                 # long time
    751

For finer invariants derived from the intersection poset, see `whitney_number()` and `doubly_indexed_whitney_number()`.

Miscellaneous methods (see documentation for an explanation):

    sage: a = hyperplane_arrangements.semiorder(3)
    sage: a.has_good_reduction(5)
    True
    sage: b = a.change_ring(GF(5))
    sage: pa = a.intersection_poset()
    sage: pb = b.intersection_poset()
    sage: pa.is_isomorphic(pb)
    True
    sage: a.face_vector()
    (0, 12, 30, 19)
    sage: a.face_vector()
    (0, 12, 30, 19)
    sage: a.is_central()
    False
    sage: a.is_linear()
    False
    sage: a.sign_vector((1,1,1))
    (-1, 1, -1, 1, -1, 1)
    sage: a.varchenko_matrix()
    [          1          h2       h2*h4       h2*h3    h2*h3*h4 h2*h3*h4*h5]
    [         h2           1          h4          h3       h3*h4    h3*h4*h5]
    [      h2*h4          h4           1       h3*h4          h3       h3*h5]
    [      h2*h3          h3       h3*h4           1          h4       h4*h5]
    [   h2*h3*h4       h3*h4          h3          h4           1          h5]
    [h2*h3*h4*h5    h3*h4*h5       h3*h5       h4*h5          h5           1]

There are extensive methods for visualizing hyperplane arrangements in low dimensions. See `plot()` for details.

TESTS:

    sage: H.<x,y> = HyperplaneArrangements(QQ)
    sage: h = H([(1, 106), 106266], [(83, 101), 157866], [(111, 110), 186150], [(453, 221), 532686],
    ....:       [(407, 237), 516882], [(55, 32), 75620], [(221, 114), 289346], [(452, 115), 474217],
    ....:       [(406, 131), 453521], [(28, 9), 32446], [(287, 19), 271774], [(241, 35), 244022],
    ....:       [(231, 1), 210984], [(185, 17), 181508], [(23, -8), 16609])
    sage: h.n_regions()
    85

    sage: H()
    Empty hyperplane arrangement of dimension 2

    sage: Zero = HyperplaneArrangements(QQ)
    sage: Zero
    Hyperplane arrangements in 0-dimensional linear space over Rational Field with coordinate
    sage: Zero()
    Empty hyperplane arrangement of dimension 0
    sage: Zero.an_element()
    Empty hyperplane arrangement of dimension 0

AUTHORS:

- David Perkinson (2013-06): initial version
- Qiaoyu Yang (2013-07)
- Kuai Yu (2013-07)
- Volker Braun (2013-10): Better Sage integration, major code refactoring.

This module implements hyperplane arrangements defined over the rationals or over finite fields. The original motivation was to make a companion to Richard Stanley’s notes [RS] on hyperplane arrangements.

REFERENCES:

[RS] | Stanley, Richard: Hyperplane Arrangements, Geometric Combinatorics (E. Miller, V. Reiner, and B. Sturmfels, eds.), IAS/Park City Mathematics Series, vol. 13, American Mathematical Society, Providence, RI, 2007, pp. 389-496.

class `sage.geometry.hyperplane_arrangement.arrangement.``HyperplaneArrangementElement`(parent, hyperplanes, check=True)

  Bases: `sage.structure.element.Element`

  An element in a hyperplane arrangement.

  Warning

  You should never create `HyperplaneArrangementElement` instances directly, always use the parent.

  `add_hyperplane`(other)

    The union of `self` with `other`.

    INPUT:

    - `other` – a hyperplane arrangement or something that can be converted into a hyperplane arrangement

    OUTPUT:

    A new hyperplane arrangement.

    EXAMPLES:

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: A = H([1,2,3], [0,1,1], [0,1,-1], [1,-1,0], [1,1,0])
        sage: B = H([1,1,1], [1,-1,1], [1,0,-1])
        sage: A.union(B)
        Arrangement of 8 hyperplanes of dimension 2 and rank 2
        sage: A | B   # syntactic sugar
        Arrangement of 8 hyperplanes of dimension 2 and rank 2

    A single hyperplane is coerced into a hyperplane arrangement if necessary:

        sage: A.union(x+y-1)
        Arrangement of 6 hyperplanes of dimension 2 and rank 2
        sage: A.add_hyperplane(x+y-1)    # alias
        Arrangement of 6 hyperplanes of dimension 2 and rank 2

        sage: P.<x,y> = HyperplaneArrangements(RR)
        sage: C = P(2*x + 4*y + 5)
        sage: C.union(A)
        Arrangement of 6 hyperplanes of dimension 2 and rank 2

  `bounded_regions`()

    Return the relatively bounded regions of the arrangement.

    A region is relatively bounded if its intersection with the space spanned by the normals to the hyperplanes is bounded. This is the same as being bounded in the case that the hyperplane arrangement is essential. It is assumed that the arrangement is defined over the rationals.

    OUTPUT:

    Tuple of polyhedra. The relatively bounded regions of the arrangement.

    See also

    `unbounded_regions()`

    EXAMPLES:

        sage: A = hyperplane_arrangements.semiorder(3)
        sage: A.bounded_regions()
        (A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices and 1 line,
         A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices and 1 line,
         A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices and 1 line,
         A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 6 vertices and 1 line,
         A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices and 1 line,
         A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices and 1 line,
         A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices and 1 line)
        sage: A.bounded_regions()[0].is_compact()    # the regions are only *relatively* bounded
        False
        sage: A.is_essential()
        False

  `change_ring`(base_ring)

    Return hyperplane arrangement over the new base ring.

    INPUT:

    - `base_ring` – the new base ring; must be a field for hyperplane arrangements

    OUTPUT:

    The hyperplane arrangement obtained by changing the base field, as a new hyperplane arrangement.

    EXAMPLES:

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: A = H([(1,1), 0], [(2,3), -1])
        sage: A.change_ring(FiniteField(2))
        Arrangement <y + 1 | x + y>

  `characteristic_polynomial`()

    Return the characteristic polynomial of the hyperplane arrangement.

    OUTPUT:

    The characteristic polynomial in \(\QQ[x]\).

    EXAMPLES:

        sage: a = hyperplane_arrangements.coordinate(2)
        sage: a.characteristic_polynomial()
        x^2 - 2*x + 1

    TESTS:

        sage: H.<s,t,u,v> = HyperplaneArrangements(QQ)
        sage: m = matrix([(0, -1, 0, 1, -1), (0, -1, 1, -1, 0), (0, -1, 1, 0, -1),
        ....:   (0, 1, 0, 0, 0), (0, 1, 0, 1, -1), (0, 1, 1, -1, 0), (0, 1, 1, 0, -1)])
        sage: R.<x> = QQ[]
        sage: expected_charpoly = (x - 1) * x * (x^2 - 6*x + 12)
        sage: for s in SymmetricGroup(4):   # long time (about a second on a Core i7)
        ....:     m_perm = [m.column(i) for i in [0, s(1), s(2), s(3), s(4)]]
        ....:     m_perm = matrix(m_perm).transpose()
        ....:     charpoly = H(m_perm.rows()).characteristic_polynomial()
        ....:     assert charpoly == expected_charpoly

  `cone`(variable='t')

    Return the cone over the hyperplane arrangement.

    INPUT:

    - `variable` – string; the name of the additional variable

    OUTPUT:

    A new yperplane arrangement. Its equations consist of \([0, -d, a_1, \ldots, a_n]\) for each \([d, a_1, \ldots, a_n]\) in the original arrangement and the equation \([0, 1, 0, \ldots, 0]\).

    EXAMPLES:

        sage: a.<x,y,z> = hyperplane_arrangements.semiorder(3)
        sage: b = a.cone()
        sage: a.characteristic_polynomial().factor()
        x * (x^2 - 6*x + 12)
        sage: b.characteristic_polynomial().factor()
        (x - 1) * x * (x^2 - 6*x + 12)
        sage: a.hyperplanes()
        (Hyperplane 0*x + y - z - 1,
         Hyperplane 0*x + y - z + 1,
         Hyperplane x - y + 0*z - 1,
         Hyperplane x - y + 0*z + 1,
         Hyperplane x + 0*y - z - 1,
         Hyperplane x + 0*y - z + 1)
        sage: b.hyperplanes()
        (Hyperplane -t + 0*x + y - z + 0,
         Hyperplane -t + x - y + 0*z + 0,
         Hyperplane -t + x + 0*y - z + 0,
         Hyperplane t + 0*x + 0*y + 0*z + 0,
         Hyperplane t + 0*x + y - z + 0,
         Hyperplane t + x - y + 0*z + 0,
         Hyperplane t + x + 0*y - z + 0)

  `deletion`(hyperplanes)

    Return the hyperplane arrangement obtained by removing `h`.

    INPUT:

    - `h` – a hyperplane or hyperplane arrangement

    OUTPUT:

    A new hyperplane arrangement with the given hyperplane(s) `h` removed.

    See also

    `restriction()`

    EXAMPLES:

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: A = H([0,1,0], [1,0,1], [-1,0,1], [0,1,-1], [0,1,1]);  A
        Arrangement of 5 hyperplanes of dimension 2 and rank 2
        sage: A.deletion(x)
        Arrangement <y - 1 | y + 1 | x - y | x + y>
        sage: h = H([0,1,0], [0,1,1])
        sage: A.deletion(h)
        Arrangement <y - 1 | y + 1 | x - y>

    TESTS:

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: A = H([0,1,0], [1,0,1], [-1,0,1], [0,1,-1], [0,1,1])
        sage: h = H([0,4,0])
        sage: A.deletion(h)
        Arrangement <y - 1 | y + 1 | x - y | x + y>
        sage: l = H([1,2,3])
        sage: A.deletion(l)
        Traceback (most recent call last):
        ...
        ValueError: hyperplane is not in the arrangement

  `dimension`()

    Return the ambient space dimension of the arrangement.

    OUTPUT:

    An integer.

    EXAMPLES:

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

  `distance_between_regions`(region1, region2)

    Return the number of hyperplanes separating the two regions.

    INPUT:

    - `region1`, `region2` – regions of the arrangement or representative points of regions

    OUTPUT:

    An integer. The number of hyperplanes separating the two regions.

    EXAMPLES:

        sage: c = hyperplane_arrangements.coordinate(2)
        sage: r = c.region_containing_point([-1, -1])
        sage: s = c.region_containing_point([1, 1])
        sage: c.distance_between_regions(r, s)
        2
        sage: c.distance_between_regions(s, s)
        0

  `distance_enumerator`(base_region)

    Return the generating function for the number of hyperplanes at given distance.

    INPUT:

    - `base_region` – region of arrangement or point in region

    OUTPUT:

    A polynomial \(f(x)\) for which the coefficient of \(x^i\) is the number of hyperplanes of distance \(i\) from `base_region`, i.e., the number of hyperplanes separated by \(i\) hyperplanes from `base_region`.

    EXAMPLES:

        sage: c = hyperplane_arrangements.coordinate(3)
        sage: c.distance_enumerator(c.region_containing_point([1,1,1]))
        x^3 + 3*x^2 + 3*x + 1

  `doubly_indexed_whitney_number`(i, j, kind=1)

    Return the \(i,j\)-th doubly-indexed Whitney number.

    If `kind=1`, this number is obtained by adding the Moebius function values \(mu(x,y)\) over all \(x, y\) in the intersection poset with \(\mathrm{rank}(x) = i\) and \(\mathrm{rank}(y) = j\).

    If \(kind=2\), this number is the number of elements \(x,y\) in the intersection poset such that \(x \leq y\) with ranks \(i\) and \(j\), respectively.

    INPUT:

    - `i`, `j` – integers
    - `kind` – (default: 1) 1 or 2

    OUTPUT:

    Integer. The \((i,j)\)-th entry of the `kind` Whitney number.

    See also

    `whitney_number()`, `whitney_data()`

    EXAMPLES:

        sage: A = hyperplane_arrangements.Shi(3)
        sage: A.doubly_indexed_whitney_number(0, 2)
        9
        sage: A.whitney_number(2)
        9
        sage: A.doubly_indexed_whitney_number(1, 2)
        -15

    REFERENCES:

    [GZ] | Greene; Zaslavsky “On the Interpretation of Whitney Numbers Through Arrangements of Hyperplanes, Zonotopes, Non-Radon Partitions, and Orientations of Graphs” Transactions of the American Mathematical Society, Vol. 280, No. 1. (Nov., 1983), pp. 97-126.

  `essentialization`()

    Return the essentialization of the hyperplane arrangement.

    The essentialization of a hyperplane arrangement whose base field has characteristic 0 is obtained by intersecting the hyperplanes by the space spanned by their normal vectors.

    OUTPUT:

    The essentialization as a new hyperplane arrangement.

    EXAMPLES:

        sage: a = hyperplane_arrangements.braid(3)
        sage: a.is_essential()
        False
        sage: a.essentialization()
        Arrangement <t1 - t2 | t1 + 2*t2 | 2*t1 + t2>

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: B = H([(1,0),1], [(1,0),-1])
        sage: B.is_essential()
        False
        sage: B.essentialization()
        Arrangement <-x + 1 | x + 1>
        sage: B.essentialization().parent()
        Hyperplane arrangements in 1-dimensional linear space over
        Rational Field with coordinate x

        sage: H.<x,y> = HyperplaneArrangements(GF(2))
        sage: C = H([(1,1),1], [(1,1),0])
        sage: C.essentialization()
        Arrangement <y | y + 1>

        sage: h = hyperplane_arrangements.semiorder(4)
        sage: h.essentialization()
        Arrangement of 12 hyperplanes of dimension 3 and rank 3

    TESTS:

        sage: b = hyperplane_arrangements.coordinate(2)
        sage: b.is_essential()
        True
        sage: b.essentialization() is b
        True

  `face_vector`()

    Return the face vector.

    OUTPUT:

    A vector of integers.

    The \(d\)-th entry is the number of faces of dimension \(d\). A face is is the intersection of a region with a hyperplane of the arrangehment.

    EXAMPLES:

        sage: A = hyperplane_arrangements.Shi(3)
        sage: A.face_vector()
        (0, 6, 21, 16)

  `has_good_reduction`(p)

    Return whether the hyperplane arrangement has good reduction mod \(p\).

    Let \(A\) be a hyperplane arrangement with equations defined over the integers, and let \(B\) be the hyperplane arrangement defined by reducing these equations modulo a prime \(p\). Then \(A\) has good reduction modulo \(p\) if the intersection posets of \(A\) and \(B\) are isomorphic.

    INPUT:

    - `p` – prime number

    OUTPUT:

    A boolean.

    EXAMPLES:

        sage: a = hyperplane_arrangements.semiorder(3)
        sage: a.has_good_reduction(5)
        True
        sage: a.has_good_reduction(3)
        False
        sage: b = a.change_ring(GF(3))
        sage: a.characteristic_polynomial()
        x^3 - 6*x^2 + 12*x
        sage: b.characteristic_polynomial()  # not equal to that for a
        x^3 - 6*x^2 + 10*x

  `hyperplanes`()

    Return the number of hyperplanes in the arrangement.

    OUTPUT:

    An integer.

    EXAMPLES:

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: A = H([1,1,0], [2,3,-1], [4,5,3])
        sage: A.hyperplanes()
        (Hyperplane x + 0*y + 1, Hyperplane 3*x - y + 2, Hyperplane 5*x + 3*y + 4)

    Note that the hyperplanes can be indexed as if they were a list:

        sage: A[0]
        Hyperplane x + 0*y + 1

  `intersection_poset`()

    Return the intersection poset of the hyperplane arrangement.

    OUTPUT:

    The poset of non-empty intersections of hyperplanes.

    EXAMPLES:

        sage: a = hyperplane_arrangements.coordinate(2)
        sage: a.intersection_poset()
        Finite poset containing 4 elements

        sage: A = hyperplane_arrangements.semiorder(3)
        sage: A.intersection_poset()
        Finite poset containing 19 elements

  `is_central`()

    Test whether the intersection of all the hyperplanes is nonempty.

    OUTPUT:

    A boolean whether the hyperplane arrangement is such that the intersection of all the hyperplanes in the arrangement is nonempty.

    EXAMPLES:

        sage: a = hyperplane_arrangements.braid(2)
        sage: a.is_central()
        True

  `is_essential`()

    Test whether the hyperplane arrangement is essential.

    A hyperplane arrangement is essential if the span of the normals of its hyperplanes spans the ambient space.

    See also

    `essentialization()`

    OUTPUT:

    A boolean indicating whether the hyperplane arrangement is essential.

    EXAMPLES:

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: H(x, x+1).is_essential()
        False
        sage: H(x, y).is_essential()
        True

  `is_linear`()

    Test whether all hyperplanes pass through the origin.

    OUTPUT:

    A boolean. Whether all the hyperplanes pass through the origin.

    EXAMPLES:

        sage: a = hyperplane_arrangements.semiorder(3)
        sage: a.is_linear()
        False
        sage: b = hyperplane_arrangements.braid(3)
        sage: b.is_linear()
        True

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: c = H(x+1, y+1)
        sage: c.is_linear()
        False
        sage: c.is_central()
        True

  `is_separating_hyperplane`(region1, region2, hyperplane)

    Test whether the `hyperplane` separates the given regions.

    INPUT:

    - `region1`, `region2` – polyhedra or list/tuple/iterable of coordinates which are regions of the arrangement or an interior point of a region
    - `hyperplane` – a hyperplane

    OUTPUT:

    A boolean. Whether the hyperplane `hyperplane` separate the given regions.

    EXAMPLES:

        sage: A.<x,y> = hyperplane_arrangements.coordinate(2)
        sage: A.is_separating_hyperplane([1,1], [2,1], y)
        False
        sage: A.is_separating_hyperplane([1,1], [-1,1], x)
        True
        sage: r = A.region_containing_point([1,1])
        sage: s = A.region_containing_point([-1,1])
        sage: A.is_separating_hyperplane(r, s, x)
        True

  `n_bounded_regions`()

    Return the number of (relatively) bounded regions.

    OUTPUT:

    An integer. The number of relatively bounded regions of the hyperplane arrangement.

    EXAMPLES:

        sage: A = hyperplane_arrangements.semiorder(3)
        sage: A.n_bounded_regions()
        7

    TESTS:

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: A = H([(1,1),0], [(2,3),-1], [(4,5),3])
        sage: B = A.change_ring(FiniteField(7))
        sage: B.n_bounded_regions()
        Traceback (most recent call last):
        ...
        TypeError: base field must have characteristic zero

  `n_hyperplanes`()

    Return the number of hyperplanes in the arrangement.

    OUTPUT:

    An integer.

    EXAMPLES:

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: A = H([1,1,0], [2,3,-1], [4,5,3])
        sage: A.n_hyperplanes()
        3
        sage: len(A)    # equivalent
        3

  `n_regions`()

    The number of regions of the hyperplane arrangement.

    OUTPUT:

    An integer.

    EXAMPLES:

        sage: A = hyperplane_arrangements.semiorder(3)
        sage: A.n_regions()
        19

    TESTS:

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: A = H([(1,1), 0], [(2,3), -1], [(4,5), 3])
        sage: B = A.change_ring(FiniteField(7))
        sage: B.n_regions()
        Traceback (most recent call last):
        ...
        TypeError: base field must have characteristic zero

  `plot`(**kwds)

    Plot the hyperplane arrangement.

    OUTPUT:

    A graphics object.

    EXAMPLES:

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

  `poincare_polynomial`()

    Return the Poincare polynomial of the hyperplane arrangement.

    OUTPUT:

    The Poincare polynomial in \(\QQ[x]\).

    EXAMPLES:

        sage: a = hyperplane_arrangements.coordinate(2)
        sage: a.poincare_polynomial()
        x^2 + 2*x + 1

  `rank`()

    Return the rank.

    OUTPUT:

    The dimension of the span of the normals to the hyperplanes in the arrangement.

    EXAMPLES:

        sage: H.<x,y,z> = HyperplaneArrangements(QQ)
        sage: A = H([[0, 1, 2, 3],[-3, 4, 5, 6]])
        sage: A.dimension()
        3
        sage: A.rank()
        2

        sage: B = hyperplane_arrangements.braid(3)
        sage: B.hyperplanes()
        (Hyperplane 0*t0 + t1 - t2 + 0,
         Hyperplane t0 - t1 + 0*t2 + 0,
         Hyperplane t0 + 0*t1 - t2 + 0)
        sage: B.dimension()
        3
        sage: B.rank()
        2

        sage: p = polytopes.n_simplex(5)
        sage: H = p.hyperplane_arrangement()
        sage: H.rank()
        5

  `region_containing_point`(p)

    The region in the hyperplane arrangement containing a given point.

    The base field must have characteristic zero.

    INPUT:

    - `p` – point

    OUTPUT:

    A polyhedron. A `ValueError` is raised if the point is not interior to a region, that is, sits on a hyperplane.

    EXAMPLES:

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: A = H([(1,0), 0], [(0,1), 1], [(0,1), -1], [(1,-1), 0], [(1,1), 0])
        sage: A.region_containing_point([1,2])
        A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 2 rays

    TESTS:

        sage: A = H([(1,1),0], [(2,3),-1], [(4,5),3])
        sage: B = A.change_ring(FiniteField(7))
        sage: B.region_containing_point((1,2))
        Traceback (most recent call last):
        ...
        ValueError: base field must have characteristic zero

        sage: A = H([(1,1),0], [(2,3),-1], [(4,5),3])
        sage: A.region_containing_point((1,-1))
        Traceback (most recent call last):
        ...
        ValueError: point sits on a hyperplane

  `regions`()

    Return the regions of the hyperplane arrangement.

    The base field must have characteristic zero.

    OUTPUT:

    A tuple containing the regions as polyhedra.

    The regions are the connected components of the complement of the union of the hyperplanes as a subset of \(\RR^n\).

    EXAMPLES:

        sage: a = hyperplane_arrangements.braid(2)
        sage: a.regions()
        (A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex, 1 ray, 1 line,
         A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex, 1 ray, 1 line)

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: A = H(x, y+1)
        sage: A.regions()
        (A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays,
         A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays,
         A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays,
         A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays)

        sage: chessboard = []
        sage: N = 8
        sage: for x0, y0 in CartesianProduct(range(N+1), range(N+1)):
        ....:     chessboard.extend([x-x0, y-y0])
        sage: chessboard = H(chessboard)
        sage: len(chessboard.bounded_regions())   # long time, 359 ms on a Core i7
        64

  `restriction`(hyperplane)

    Return the restriction to a hyperplane.

    INPUT:

    - `hyperplane` – a hyperplane of the hyperplane arrangement

    OUTPUT:

    The restriction of the hyperplane arrangement to the given `hyperplane`.

    EXAMPLES:

        sage: A.<u,x,y,z> = hyperplane_arrangements.braid(4);  A
        Arrangement of 6 hyperplanes of dimension 4 and rank 3
        sage: H = A[0];  H
        Hyperplane 0*u + 0*x + y - z + 0
        sage: R = A.restriction(H);  R
        Arrangement <x - z | u - x | u - z>
        sage: D = A.deletion(H);  D
        Arrangement of 5 hyperplanes of dimension 4 and rank 3
        sage: ca = A.characteristic_polynomial()
        sage: cr = R.characteristic_polynomial()
        sage: cd = D.characteristic_polynomial()
        sage: ca
        x^4 - 6*x^3 + 11*x^2 - 6*x
        sage: cd - cr
        x^4 - 6*x^3 + 11*x^2 - 6*x

    See also

    `deletion()`

  `sign_vector`(p)

    Indicates on which side of each hyperplane the given point \(p\) lies.

    The base field must have characteristic zero.

    INPUT:

    - `p` – point as a list/tuple/iterable

    OUTPUT:

    A vector whose entries are in \([-1, 0, +1]\).

    EXAMPLES:

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: A = H([(1,0), 0], [(0,1), 1]);  A
        Arrangement <y + 1 | x>
        sage: A.sign_vector([2, -2])
        (-1, 1)
        sage: A.sign_vector((-1, -1))
        (0, -1)

    TESTS:

        sage: H.<x,y> = HyperplaneArrangements(GF(3))
        sage: A = H(x, y)
        sage: A.sign_vector([1, 2])
        Traceback (most recent call last):
        ...
        ValueError: characteristic must be zero

  `unbounded_regions`()

    Return the relatively bounded regions of the arrangement.

    OUTPUT:

    Tuple of polyhedra. The regions of the arrangement that are not relatively bounded. It is assumed that the arrangement is defined over the rationals.

    See also

    `bounded_regions()`

    EXAMPLES:

        sage: A = hyperplane_arrangements.semiorder(3)
        sage: B = A.essentialization()
        sage: B.n_regions() - B.n_bounded_regions()
        12
        sage: B.unbounded_regions()
        (A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices and 1 ray,
        A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices and 1 ray,
        A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays,
        A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices and 1 ray,
        A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays,
        A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices and 1 ray,
        A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays,
        A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices and 1 ray,
        A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays,
        A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices and 1 ray,
        A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays,
        A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays)

  `union`(other)

    The union of `self` with `other`.

    INPUT:

    - `other` – a hyperplane arrangement or something that can be converted into a hyperplane arrangement

    OUTPUT:

    A new hyperplane arrangement.

    EXAMPLES:

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: A = H([1,2,3], [0,1,1], [0,1,-1], [1,-1,0], [1,1,0])
        sage: B = H([1,1,1], [1,-1,1], [1,0,-1])
        sage: A.union(B)
        Arrangement of 8 hyperplanes of dimension 2 and rank 2
        sage: A | B   # syntactic sugar
        Arrangement of 8 hyperplanes of dimension 2 and rank 2

    A single hyperplane is coerced into a hyperplane arrangement if necessary:

        sage: A.union(x+y-1)
        Arrangement of 6 hyperplanes of dimension 2 and rank 2
        sage: A.add_hyperplane(x+y-1)    # alias
        Arrangement of 6 hyperplanes of dimension 2 and rank 2

        sage: P.<x,y> = HyperplaneArrangements(RR)
        sage: C = P(2*x + 4*y + 5)
        sage: C.union(A)
        Arrangement of 6 hyperplanes of dimension 2 and rank 2

  `varchenko_matrix`(names='h')

    Return the Varchenko matrix of the arrangement.

    Let \(H_1, \ldots, H_s\) and \(R_1, \ldots, R_t\) denote the hyperplanes and regions, respectively, of the arrangement. Let \(S = \QQ[h_1, \ldots, h_s]\), a polynomial ring with indeterminate \(h_i\) corresponding to hyperplane \(H_i\). The Varchenko matrix is the \(t \times t\) matrix with \(i,j\)-th entry the product of those \(h_k\) such that \(H_k\) separates \(R_i\) and \(R_j\).

    INPUT:

    - `names` – string or list/tuple/iterable of strings. The variable names for the polynomial ring \(S\).

    OUTPUT:

    The Varchenko matrix.

    EXAMPLES:

        sage: a = hyperplane_arrangements.coordinate(3)
        sage: v = a.varchenko_matrix();  v
        [    1    h2    h1]
        [   h2     1 h1*h2]
        [   h1 h1*h2     1]
        sage: factor(det(v))
        (h2 - 1) * (h2 + 1) * (h1 - 1) * (h1 + 1)

  `vertices`(exclude_sandwiched=False)

    Return the vertices.

    The vertices are the zero-dimensional faces, see `face_vector()`.

    INPUT:

    - `exclude_sandwiched` – boolean (default: `False`). Whether to exclude hyperplanes that are sandwiched between parallel hyperplanes. Useful if you only need the convex hull.

    OUTPUT:

    The vertices in a sorted tuple. Each vertex is returned as a vector in the ambient vector space.

    EXAMPLES:

        sage: A = hyperplane_arrangements.Shi(3).essentialization()
        sage: A.dimension()
        2
        sage: A.face_vector()
        (6, 21, 16)
        sage: A.vertices()
        ((-2/3, 1/3), (-1/3, -1/3), (0, -1), (0, 0), (1/3, -2/3), (2/3, -1/3))
        sage: point2d(A.vertices(), size=20) + A.plot()
        Graphics object consisting of 7 graphics primitives

        sage: H.<x,y> = HyperplaneArrangements(QQ)
        sage: chessboard = []
        sage: N = 8
        sage: for x0, y0 in CartesianProduct(range(N+1), range(N+1)):
        ....:     chessboard.extend([x-x0, y-y0])
        sage: chessboard = H(chessboard)
        sage: len(chessboard.vertices())
        81
        sage: chessboard.vertices(exclude_sandwiched=True)
        ((0, 0), (0, 8), (8, 0), (8, 8))

  `whitney_data`()

    Return the Whitney numbers.

    See also

    `whitney_number()`, `doubly_indexed_whitney_number()`

    OUTPUT:

    A pair of integer matrices. The two matrices are the doubly-indexed Whitney numbers of the first or second kind, respectively. The \(i,j\)-th entry is the \(i,j\)-th doubly-indexed Whitney number.

    EXAMPLES:

        sage: A = hyperplane_arrangements.Shi(3)
        sage: A.whitney_data()
        (
        [  1  -6   9]  [ 1  6  6]
        [  0   6 -15]  [ 0  6 15]
        [  0   0   6], [ 0  0  6]
        )

  `whitney_number`(k, kind=1)

    Return the `k`-th Whitney number.

    If `kind=1`, this number is obtained by summing the Moebius function values \(mu(0, x)\) over all \(x\) in the intersection poset with \(\mathrm{rank}(x) = k\).

    If `kind=2`, this number is the number of elements \(x, y\) in the intersection poset such that \(x \leq y\) with ranks \(i\) and \(j\), respectively.

    See [GZ] for more details.

    INPUT:

    - `k` – integer
    - `kind` – 1 or 2 (default: 1)

    OUTPUT:

    Integer. The `k`-th Whitney number.

    See also

    `doubly_indexed_whitney_number()` `whitney_data()`

    EXAMPLES:

        sage: A = hyperplane_arrangements.Shi(3)
        sage: A.whitney_number(0)
        1
        sage: A.whitney_number(1)
        -6
        sage: A.whitney_number(2)
        9
        sage: A.characteristic_polynomial()
        x^3 - 6*x^2 + 9*x
        sage: A.whitney_number(1,kind=2)
        6
        sage: p = A.intersection_poset()
        sage: r = p.rank_function()
        sage: len([i for i in p if r(i) == 1])
        6

class `sage.geometry.hyperplane_arrangement.arrangement.``HyperplaneArrangements`(base_ring, names=())

  Bases: `sage.structure.parent.Parent`, `sage.structure.unique_representation.UniqueRepresentation`

  Hyperplane arrangements.

  For more information on hyperplane arrangements, see `sage.geometry.hyperplane_arrangements.arrangement`.

  INPUT:

  - `base_ring` – ring; the base ring
  - `names` – tuple of strings; the variable names

  EXAMPLES:

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

  `Element`

    alias of `HyperplaneArrangementElement`

  `ambient_space`()

    Return the ambient space.

    The ambient space is the parent of hyperplanes. That is, new hyperplanes are always constructed internally from the ambient space instance.

    EXAMPLES:

        sage: L.<x, y> = HyperplaneArrangements(QQ)
        sage: L.ambient_space()([(1,0), 0])
        Hyperplane x + 0*y + 0
        sage: L.ambient_space()([(1,0), 0]) == x
        True

  `base_ring`()

    Return the base ring.

    OUTPUT:

    The base ring of the hyperplane arrangement.

    EXAMPLES:

        sage: L.<x,y> = HyperplaneArrangements(QQ)
        sage: L.base_ring()
        Rational Field

  `change_ring`(base_ring)

    Return hyperplane arrangements over a different base ring.

    INPUT:

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

    OUTPUT:

    A new `HyperplaneArrangements` instance over the new base ring.

    EXAMPLES:

        sage: L.<x,y> = HyperplaneArrangements(QQ)
        sage: L.gen(0)
        Hyperplane x + 0*y + 0
        sage: L.change_ring(RR).gen(0)
        Hyperplane 1.00000000000000*x + 0.000000000000000*y + 0.000000000000000

    TESTS:

        sage: L.change_ring(QQ) is L
        True

  `gen`(i)

    Return the \(i\)-th coordinate hyperplane.

    INPUT:

    - `i` – integer

    OUTPUT:

    A linear expression.

    EXAMPLES:

        sage: L.<x, y, z> = HyperplaneArrangements(QQ);  L
        Hyperplane arrangements in 3-dimensional linear space over Rational Field with coordinates x, y, z
        sage: L.gen(0)
        Hyperplane x + 0*y + 0*z + 0

  `gens`()

    Return the coordinate hyperplanes.

    OUTPUT:

    A tuple of linear expressions, one for each linear variable.

    EXAMPLES:

        sage: L = HyperplaneArrangements(QQ, ('x', 'y', 'z'))
        sage: L.gens()
        (Hyperplane x + 0*y + 0*z + 0,
         Hyperplane 0*x + y + 0*z + 0,
         Hyperplane 0*x + 0*y + z + 0)

  `ngens`()

    Return the number of linear variables.

    OUTPUT:

    An integer.

    EXAMPLES:

        sage: L.<x, y, z> = HyperplaneArrangements(QQ);  L
        Hyperplane arrangements in 3-dimensional linear space over Rational Field with coordinates x, y, z
        sage: L.ngens()
        3

### Navigation

- index
- modules |
- next |
- previous |
- Combinatorial Geometry »