Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/geometry/hyperplane_arrangement/library.py
8817 views
1
r"""
2
Library of Hyperplane Arrangements
3
4
A collection of useful or interesting hyperplane arrangements. See
5
:mod:`sage.geometry.hyperplane_arrangement.arrangement` for details
6
about how to construct your own hyperplane arrangements.
7
"""
8
#*****************************************************************************
9
# Copyright (C) 2013 David Perkinson <[email protected]>
10
#
11
# Distributed under the terms of the GNU General Public License (GPL)
12
# http://www.gnu.org/licenses/
13
#*****************************************************************************
14
15
from sage.graphs.all import graphs
16
from sage.matrix.constructor import matrix, random_matrix
17
from sage.rings.all import QQ, ZZ
18
from sage.misc.misc_c import prod
19
20
from sage.combinat.combinat import stirling_number2
21
from sage.rings.arith import binomial
22
from sage.rings.polynomial.polynomial_ring import polygen
23
24
from sage.geometry.hyperplane_arrangement.arrangement import HyperplaneArrangements
25
26
27
def make_parent(base_ring, dimension, names=None):
28
"""
29
Construct the parent for the hyperplane arrangements.
30
31
For internal use only.
32
33
INPUT:
34
35
- ``base_ring`` -- a ring
36
37
- ``dimenison`` -- integer
38
39
- ``names`` -- ``None`` (default) or a list/tuple/iterable of
40
strings
41
42
OUTPUT:
43
44
A new
45
:class:`~sage.geometry.hyperplane_arrangement.arrangement.HyperplaneArrangements`
46
instance.
47
48
EXAMPLES::
49
50
sage: from sage.geometry.hyperplane_arrangement.library import make_parent
51
sage: make_parent(QQ, 3)
52
Hyperplane arrangements in 3-dimensional linear space over
53
Rational Field with coordinates t0, t1, t2
54
"""
55
if names is None:
56
names = tuple('t'+str(i) for i in range(dimension))
57
else:
58
names = tuple(map(str, names))
59
if len(names) != dimension:
60
raise ValueError('number of variable names does not match dimension')
61
return HyperplaneArrangements(base_ring, names=names)
62
63
64
65
class HyperplaneArrangementLibrary(object):
66
"""
67
The library of hyperplane arrangements.
68
"""
69
70
def braid(self, n, K=QQ, names=None):
71
r"""
72
The braid arrangement.
73
74
INPUT:
75
76
- ``n`` -- integer
77
78
- ``K`` -- field (default: ``QQ``)
79
80
- ``names`` -- tuple of strings or ``None`` (default); the
81
variable names for the ambient space
82
83
OUTPUT:
84
85
The hyperplane arrangement consisting of the `n(n-1)/2`
86
hyperplanes `\{ x_i - x_j = 0 : 1 \leq i \leq j \leq n \}`.
87
88
EXAMPLES::
89
90
sage: hyperplane_arrangements.braid(4)
91
Arrangement of 6 hyperplanes of dimension 4 and rank 3
92
"""
93
x = polygen(QQ, 'x')
94
A = self.graphical(graphs.CompleteGraph(n), K, names=names)
95
charpoly = prod(x-i for i in range(n))
96
A.characteristic_polynomial.set_cache(charpoly)
97
return A
98
99
def bigraphical(self, G, A=None, K=QQ, names=None):
100
r"""
101
Return a bigraphical hyperplane arrangement.
102
103
INPUT:
104
105
- ``G`` -- graph
106
107
- ``A`` -- list, matrix, dictionary (default: ``None``
108
gives semiorder), or the string 'generic'
109
110
- ``K`` -- field (default: `\QQ`)
111
112
- ``names`` -- tuple of strings or ``None`` (default); the
113
variable names for the ambient space
114
115
OUTPUT:
116
117
The hyperplane arrangement with hyperplanes `x_i - x_j =
118
A[i,j]` and `x_j - x_i = A[j,i]` for each edge `v_i, v_j` of
119
``G``. The indices `i,j` are the indices of elements of
120
``G.vertices()``.
121
122
EXAMPLES::
123
124
sage: G = graphs.CycleGraph(4)
125
sage: G.edges()
126
[(0, 1, None), (0, 3, None), (1, 2, None), (2, 3, None)]
127
sage: G.edges(labels=False)
128
[(0, 1), (0, 3), (1, 2), (2, 3)]
129
sage: A = {0:{1:1, 3:2}, 1:{0:3, 2:0}, 2:{1:2, 3:1}, 3:{2:0, 0:2}}
130
sage: HA = hyperplane_arrangements.bigraphical(G, A)
131
sage: HA.n_regions()
132
63
133
sage: hyperplane_arrangements.bigraphical(G, 'generic').n_regions()
134
65
135
sage: hyperplane_arrangements.bigraphical(G).n_regions()
136
59
137
138
REFERENCES:
139
140
.. [BigraphicalArrangements] S. Hopkins, D. Perkinson.
141
"Bigraphical Arrangements".
142
:arxiv:`1212.4398`
143
"""
144
n = G.num_verts()
145
if A is None: # default to G-semiorder arrangement
146
A = matrix(K, n, lambda i, j: 1)
147
elif A == 'generic':
148
A = random_matrix(ZZ, n, x=10000)
149
A = matrix(K, A)
150
H = make_parent(K, n, names)
151
x = H.gens()
152
hyperplanes = []
153
for e in G.edges():
154
i = G.vertices().index(e[0])
155
j = G.vertices().index(e[1])
156
hyperplanes.append( x[i] - x[j] - A[i][j])
157
hyperplanes.append(-x[i] + x[j] - A[j][i])
158
return H(*hyperplanes)
159
160
def Catalan(self, n, K=QQ, names=None):
161
r"""
162
Return the Catalan arrangement.
163
164
INPUT:
165
166
- ``n`` -- integer
167
168
- ``K`` -- field (default: `\QQ`)
169
170
- ``names`` -- tuple of strings or ``None`` (default); the
171
variable names for the ambient space
172
173
OUTPUT:
174
175
The arrangement of `3n(n-1)/2` hyperplanes `\{ x_i - x_j =
176
-1,0,1 : 1 \leq i \leq j \leq n \}`.
177
178
EXAMPLES::
179
180
sage: hyperplane_arrangements.Catalan(5)
181
Arrangement of 30 hyperplanes of dimension 5 and rank 4
182
183
TESTS::
184
185
sage: h = hyperplane_arrangements.Catalan(5)
186
sage: h.characteristic_polynomial()
187
x^5 - 30*x^4 + 335*x^3 - 1650*x^2 + 3024*x
188
sage: h.characteristic_polynomial.clear_cache() # long time
189
sage: h.characteristic_polynomial() # long time
190
x^5 - 30*x^4 + 335*x^3 - 1650*x^2 + 3024*x
191
"""
192
H = make_parent(K, n, names)
193
x = H.gens()
194
hyperplanes = []
195
for i in range(n):
196
for j in range(i+1, n):
197
for k in [-1, 0, 1]:
198
hyperplanes.append(x[i] - x[j] - k)
199
Cn = H(*hyperplanes)
200
x = polygen(QQ, 'x')
201
charpoly = x*prod([x-n-i for i in range(1, n)])
202
Cn.characteristic_polynomial.set_cache(charpoly)
203
return Cn
204
205
def coordinate(self, n, K=QQ, names=None):
206
r"""
207
Return the coordinate hyperplane arrangement.
208
209
INPUT:
210
211
- ``n`` -- integer
212
213
- ``K`` -- field (default: `\QQ`)
214
215
- ``names`` -- tuple of strings or ``None`` (default); the
216
variable names for the ambient space
217
218
OUTPUT:
219
220
The coordinate hyperplane arrangement, which is the central
221
hyperplane arrangement consisting of the coordinate
222
hyperplanes `x_i = 0`.
223
224
EXAMPLES::
225
226
sage: hyperplane_arrangements.coordinate(5)
227
Arrangement of 5 hyperplanes of dimension 5 and rank 5
228
"""
229
H = make_parent(K, n, names)
230
x = H.gens()
231
return H(x)
232
233
def G_semiorder(self, G, K=QQ, names=None):
234
r"""
235
Return the semiorder hyperplane arrangement of a graph.
236
237
INPUT:
238
239
- ``G`` -- graph
240
241
- ``K`` -- field (default: `\QQ`)
242
243
- ``names`` -- tuple of strings or ``None`` (default); the
244
variable names for the ambient space
245
246
OUTPUT:
247
248
The semiorder hyperplane arrangement of a graph G is the
249
arrangement `\{ x_i - x_j = -1,1 \}` where `ij` is an edge of
250
``G``.
251
252
EXAMPLES::
253
254
sage: G = graphs.CompleteGraph(5)
255
sage: hyperplane_arrangements.G_semiorder(G)
256
Arrangement of 20 hyperplanes of dimension 5 and rank 4
257
sage: g = graphs.HouseGraph()
258
sage: hyperplane_arrangements.G_semiorder(g)
259
Arrangement of 12 hyperplanes of dimension 5 and rank 4
260
"""
261
n = G.num_verts()
262
H = make_parent(K, n, names)
263
x = H.gens()
264
hyperplanes = []
265
for e in G.edges():
266
i = G.vertices().index(e[0])
267
j = G.vertices().index(e[1])
268
hyperplanes.append(x[i] - x[j] - 1)
269
hyperplanes.append(x[i] - x[j] + 1)
270
return H(*hyperplanes)
271
272
def G_Shi(self, G, K=QQ, names=None):
273
r"""
274
Return the Shi hyperplane arrangement of a graph `G`.
275
276
INPUT:
277
278
- ``G`` -- graph
279
280
- ``K`` -- field (default: `\QQ`)
281
282
- ``names`` -- tuple of strings or ``None`` (default); the
283
variable names for the ambient space
284
285
OUTPUT:
286
287
The Shi hyperplane arrangement of the given graph ``G``.
288
289
EXAMPLES::
290
291
sage: G = graphs.CompleteGraph(5)
292
sage: hyperplane_arrangements.G_Shi(G)
293
Arrangement of 20 hyperplanes of dimension 5 and rank 4
294
sage: g = graphs.HouseGraph()
295
sage: hyperplane_arrangements.G_Shi(g)
296
Arrangement of 12 hyperplanes of dimension 5 and rank 4
297
sage: a = hyperplane_arrangements.G_Shi(graphs.WheelGraph(4)); a
298
Arrangement of 12 hyperplanes of dimension 4 and rank 3
299
"""
300
n = G.num_verts()
301
H = make_parent(K, n, names)
302
x = H.gens()
303
hyperplanes = []
304
for e in G.edges():
305
i = G.vertices().index(e[0])
306
j = G.vertices().index(e[1])
307
hyperplanes.append(x[i] - x[j])
308
hyperplanes.append(x[i] - x[j] - 1)
309
return H(*hyperplanes)
310
311
def graphical(self, G, K=QQ, names=None):
312
r"""
313
Return the graphical hyperplane arrangement of a graph ``G``.
314
315
INPUT:
316
317
- ``G`` -- graph
318
319
- ``K`` -- field (default: `\QQ`)
320
321
- ``names`` -- tuple of strings or ``None`` (default); the
322
variable names for the ambient space
323
324
OUTPUT:
325
326
The graphical hyperplane arrangement of a graph G, which is
327
the arrangement `\{ x_i - x_j = 0 \}` for all edges `ij` of the
328
graph ``G``.
329
330
EXAMPLES::
331
332
sage: G = graphs.CompleteGraph(5)
333
sage: hyperplane_arrangements.graphical(G)
334
Arrangement of 10 hyperplanes of dimension 5 and rank 4
335
sage: g = graphs.HouseGraph()
336
sage: hyperplane_arrangements.graphical(g)
337
Arrangement of 6 hyperplanes of dimension 5 and rank 4
338
339
TESTS::
340
341
sage: h = hyperplane_arrangements.graphical(g)
342
sage: h.characteristic_polynomial()
343
x^5 - 6*x^4 + 14*x^3 - 15*x^2 + 6*x
344
sage: h.characteristic_polynomial.clear_cache() # long time
345
sage: h.characteristic_polynomial() # long time
346
x^5 - 6*x^4 + 14*x^3 - 15*x^2 + 6*x
347
"""
348
n = G.num_verts()
349
H = make_parent(K, n, names)
350
x = H.gens()
351
hyperplanes = []
352
for e in G.edges():
353
i = G.vertices().index(e[0])
354
j = G.vertices().index(e[1])
355
hyperplanes.append(x[i] - x[j])
356
A = H(*hyperplanes)
357
charpoly = G.chromatic_polynomial()
358
A.characteristic_polynomial.set_cache(charpoly)
359
return A
360
361
def Ish(self, n, K=QQ, names=None):
362
r"""
363
Return the Ish arrangement.
364
365
INPUT:
366
367
- ``n`` -- integer
368
369
- ``K`` -- field (default:``QQ``)
370
371
- ``names`` -- tuple of strings or ``None`` (default); the
372
variable names for the ambient space
373
374
OUTPUT:
375
376
The Ish arrangement, which is the set of `n(n-1)` hyperplanes.
377
378
.. MATH::
379
380
\{ x_i - x_j = 0 : 1 \leq i \leq j \leq n \}
381
\cup
382
\{ x_1 - x_j = i : 1 \leq i \leq j \leq n \}.
383
384
EXAMPLES::
385
386
sage: a = hyperplane_arrangements.Ish(3); a
387
Arrangement of 6 hyperplanes of dimension 3 and rank 2
388
sage: a.characteristic_polynomial()
389
x^3 - 6*x^2 + 9*x
390
sage: b = hyperplane_arrangements.Shi(3)
391
sage: b.characteristic_polynomial()
392
x^3 - 6*x^2 + 9*x
393
394
TESTS::
395
396
sage: a.characteristic_polynomial.clear_cache() # long time
397
sage: a.characteristic_polynomial() # long time
398
x^3 - 6*x^2 + 9*x
399
400
REFERENCES:
401
402
.. [AR] D. Armstrong, B. Rhoades
403
"The Shi arrangement and the Ish arrangement"
404
:arxiv:`1009.1655`
405
"""
406
H = make_parent(K, n, names)
407
x = H.gens()
408
hyperplanes = []
409
for i in range(n):
410
for j in range(i+1, n):
411
hyperplanes.append(x[i] - x[j])
412
hyperplanes.append(x[0] - x[j] - (i+1))
413
A = H(*hyperplanes)
414
x = polygen(QQ, 'x')
415
charpoly = x * sum([(-1)**k * stirling_number2(n, n-k) *
416
prod([(x - 1 - j) for j in range(k, n-1)]) for k in range(0, n)])
417
A.characteristic_polynomial.set_cache(charpoly)
418
return A
419
420
def linial(self, n, K=QQ, names=None):
421
r"""
422
Return the linial hyperplane arrangement.
423
424
INPUT:
425
426
- ``n`` -- integer
427
428
- ``K`` -- field (default: `\QQ`)
429
430
- ``names`` -- tuple of strings or ``None`` (default); the
431
variable names for the ambient space
432
433
OUTPUT:
434
435
The linial hyperplane arrangement is the set of hyperplanes
436
`\{x_i - x_j = 1 : 1\leq i < j \leq n\}`.
437
438
EXAMPLES::
439
440
sage: a = hyperplane_arrangements.linial(4); a
441
Arrangement of 6 hyperplanes of dimension 4 and rank 3
442
sage: a.characteristic_polynomial()
443
x^4 - 6*x^3 + 15*x^2 - 14*x
444
445
TESTS::
446
447
sage: h = hyperplane_arrangements.linial(5)
448
sage: h.characteristic_polynomial()
449
x^5 - 10*x^4 + 45*x^3 - 100*x^2 + 90*x
450
sage: h.characteristic_polynomial.clear_cache() # long time
451
sage: h.characteristic_polynomial() # long time
452
x^5 - 10*x^4 + 45*x^3 - 100*x^2 + 90*x
453
"""
454
H = make_parent(K, n, names)
455
x = H.gens()
456
hyperplanes = []
457
for i in range(n):
458
for j in range(i+1, n):
459
hyperplanes.append(x[i] - x[j] - 1)
460
A = H(*hyperplanes)
461
x = polygen(QQ, 'x')
462
charpoly = x * sum(binomial(n, k)*(x - k)**(n - 1) for k in range(n + 1)) / 2**n
463
A.characteristic_polynomial.set_cache(charpoly)
464
return A
465
466
def semiorder(self, n, K=QQ, names=None):
467
r"""
468
Return the semiorder arrangement.
469
470
INPUT:
471
472
- ``n`` -- integer
473
474
- ``K`` -- field (default: `\QQ`)
475
476
- ``names`` -- tuple of strings or ``None`` (default); the
477
variable names for the ambient space
478
479
OUTPUT:
480
481
The semiorder arrangement, which is the set of `n(n-1)`
482
hyperplanes `\{ x_i - x_j = -1,1 : 1 \leq i \leq j \leq n\}`.
483
484
EXAMPLES::
485
486
sage: hyperplane_arrangements.semiorder(4)
487
Arrangement of 12 hyperplanes of dimension 4 and rank 3
488
489
TESTS::
490
491
sage: h = hyperplane_arrangements.semiorder(5)
492
sage: h.characteristic_polynomial()
493
x^5 - 20*x^4 + 180*x^3 - 790*x^2 + 1380*x
494
sage: h.characteristic_polynomial.clear_cache() # long time
495
sage: h.characteristic_polynomial() # long time
496
x^5 - 20*x^4 + 180*x^3 - 790*x^2 + 1380*x
497
"""
498
H = make_parent(K, n, names)
499
x = H.gens()
500
hyperplanes = []
501
for i in range(n):
502
for j in range(i+1, n):
503
for k in [-1, 1]:
504
hyperplanes.append(x[i] - x[j] - k)
505
A = H(*hyperplanes)
506
x = polygen(QQ, 'x')
507
charpoly = x * sum([stirling_number2(n, k) * prod([x - k - i for i in range(1, k)])
508
for k in range(1, n+1)])
509
A.characteristic_polynomial.set_cache(charpoly)
510
return A
511
512
def Shi(self, n, K=QQ, names=None):
513
r"""
514
Return the Shi arrangement.
515
516
INPUT:
517
518
- ``n`` -- integer
519
520
- ``K`` -- field (default:``QQ``)
521
522
- ``names`` -- tuple of strings or ``None`` (default); the
523
variable names for the ambient space
524
525
OUTPUT:
526
527
The Shi arrangement is the set of `n(n-1)` hyperplanes: `\{ x_i - x_j
528
= 0,1 : 1 \leq i \leq j \leq n \}`.
529
530
EXAMPLES::
531
532
sage: hyperplane_arrangements.Shi(4)
533
Arrangement of 12 hyperplanes of dimension 4 and rank 3
534
535
TESTS::
536
537
sage: h = hyperplane_arrangements.Shi(4)
538
sage: h.characteristic_polynomial()
539
x^4 - 12*x^3 + 48*x^2 - 64*x
540
sage: h.characteristic_polynomial.clear_cache() # long time
541
sage: h.characteristic_polynomial() # long time
542
x^4 - 12*x^3 + 48*x^2 - 64*x
543
"""
544
H = make_parent(K, n, names)
545
x = H.gens()
546
hyperplanes = []
547
for i in range(n):
548
for j in range(i+1, n):
549
for const in [0, 1]:
550
hyperplanes.append(x[i] - x[j] - const)
551
A = H(*hyperplanes)
552
x = polygen(QQ, 'x')
553
charpoly = x * sum([(-1)**k * stirling_number2(n, n-k) *
554
prod([(x - 1 - j) for j in range(k, n-1)]) for k in range(0, n)])
555
A.characteristic_polynomial.set_cache(charpoly)
556
return A
557
558
559
hyperplane_arrangements = HyperplaneArrangementLibrary()
560
561
562