Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/combinat/designs/incidence_structures.py
8818 views
1
"""
2
Incidence structures.
3
4
An incidence structure is specified by a list of points, blocks, and
5
an incidence matrix ([1]_, [2]_).
6
7
REFERENCES:
8
9
.. [1] Block designs and incidence structures from wikipedia,
10
:wikipedia:`Block_design`
11
:wikipedia:`Incidence_structure`
12
13
.. [2] E. Assmus, J. Key, Designs and their codes, CUP, 1992.
14
15
AUTHORS:
16
17
- Peter Dobcsanyi and David Joyner (2007-2008)
18
19
This is a significantly modified form of part of the module block_design.py
20
(version 0.6) written by Peter Dobcsanyi [email protected].
21
22
23
Classes and methods
24
-------------------
25
"""
26
#***************************************************************************
27
# Copyright (C) 2007 #
28
# #
29
# Peter Dobcsanyi and David Joyner #
30
# <[email protected]> <[email protected]> #
31
# #
32
# #
33
# Distributed under the terms of the GNU General Public License (GPL) #
34
# as published by the Free Software Foundation; either version 2 of #
35
# the License, or (at your option) any later version. #
36
# http://www.gnu.org/licenses/ #
37
#***************************************************************************
38
39
from sage.matrix.matrix_space import MatrixSpace
40
from sage.rings.integer_ring import ZZ
41
from sage.rings.arith import binomial
42
43
### utility functions -------------------------------------------------------
44
45
46
def coordinatewise_product(L):
47
"""
48
Returns the coordinatewise product of a list of vectors.
49
50
INPUT:
51
52
- ``L`` is a list of `n`-vectors or lists all of length `n` with a common
53
parent. This returns the vector whose `i`-th coordinate is the product of
54
the `i`-th coordinates of the vectors.
55
56
EXAMPLES::
57
58
sage: from sage.combinat.designs.incidence_structures import coordinatewise_product
59
sage: L = [[1,2,3],[-1,-1,-1],[5,7,11]]
60
sage: coordinatewise_product(L)
61
[-5, -14, -33]
62
"""
63
n = len(L[0])
64
ans = [1]*n
65
for x in L:
66
ans = [ans[i]*x[i] for i in range(n)]
67
return ans
68
69
def IncidenceStructureFromMatrix(M, name=None):
70
"""
71
Builds and incidence structure from a matrix.
72
73
INPUT:
74
75
- ``M`` -- a binary matrix. Creates a set of "points" from the rows and a
76
set of "blocks" from the columns.
77
78
EXAMPLES::
79
80
sage: from sage.combinat.designs.block_design import BlockDesign
81
sage: BD1 = BlockDesign(7,[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
82
sage: M = BD1.incidence_matrix()
83
sage: BD2 = IncidenceStructureFromMatrix(M)
84
sage: BD1 == BD2
85
True
86
"""
87
nm = name
88
v = len(M.rows())
89
b = len(M.columns())
90
#points = range(v)
91
blocks = []
92
for i in range(b):
93
B = []
94
for j in range(v):
95
if M[i, j] != 0:
96
B.append(j)
97
blocks.append(B)
98
return IncidenceStructure(range(v), blocks, name=nm)
99
100
101
class IncidenceStructure(object):
102
"""
103
This the base class for block designs.
104
"""
105
def __init__(self, pts, blks, inc_mat=None, name=None, test=True):
106
"""
107
INPUT:
108
109
- ``pts, blks`` -- a list of points, and a list of lists (list of blocks).
110
111
If each `B` in ``blks`` is contained in ``pts`` then the incidence
112
matrix ` inc_mat`` need not (and should not) be given. Otherwise,
113
``inc_mat`` should be the ``ptsxblks`` `(0,1)`-matrix `A` for which
114
`A_i,j=1` iff ``blks[j]`` is incident with ``pts[i]``.
115
116
- ``inc_mat`` (for giving the `(0,1)`-incidence matrix)
117
118
- ``name`` (a string, such as "Fano plane").
119
120
- ``test`` (boolean) - if ``True``, then each block must be a list of pts.
121
122
EXAMPLES::
123
124
sage: IncidenceStructure(range(7),[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
125
Incidence structure with 7 points and 7 blocks
126
127
Points are sorted ::
128
129
sage: BD1 = IncidenceStructure([4,6,0,3,2,5,1],[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
130
sage: BD1.points()
131
[0, 1, 2, 3, 4, 5, 6]
132
133
TESTS:
134
135
The following shows that :trac:`11333` is fixed. ::
136
137
sage: A = IncidenceStructure([0,1],[[0]])
138
sage: B = IncidenceStructure([1,0],[[0]])
139
sage: B == A
140
True
141
142
REFERENCES:
143
144
- E. Assmus, J. Key, Designs and their codes, CUP, 1992.
145
"""
146
bs = []
147
self.pnts = pts
148
self.pnts.sort()
149
v, blocks = len(pts), blks
150
for block in blocks:
151
if test:
152
for x in block:
153
if not(x in self.pnts):
154
raise ValueError('Point %s is not in the base set.' % x)
155
try:
156
y = block[:]
157
y.sort()
158
bs.append(y)
159
except Exception:
160
bs.append(block)
161
bs.sort(cmp)
162
self.v = v
163
self.blcks = bs
164
self.name = name
165
self._incidence_matrix = inc_mat
166
167
def __iter__(self):
168
"""
169
Iterator over the blocks.
170
171
EXAMPLE::
172
173
sage: sts = designs.steiner_triple_system(9)
174
sage: list(sts)
175
[[0, 1, 5], [0, 2, 4], [0, 3, 6], [0, 7, 8], [1, 2, 3], [1, 4, 7], [1, 6, 8], [2, 5, 8], [2, 6, 7], [3, 4, 8], [3, 5, 7], [4, 5, 6]]
176
"""
177
178
return iter(self.blcks)
179
180
def __repr__(self):
181
"""
182
A print method.
183
184
EXAMPLES::
185
186
sage: from sage.combinat.designs.block_design import BlockDesign
187
sage: BD = BlockDesign(7,[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
188
sage: BD
189
Incidence structure with 7 points and 7 blocks
190
"""
191
repr = 'Incidence structure with %s points and %s blocks' % (len(self.pnts), len(self.blcks))
192
return repr
193
194
def __str__(self):
195
"""
196
A print method.
197
198
EXAMPLES::
199
200
sage: from sage.combinat.designs.block_design import BlockDesign
201
sage: BD = BlockDesign(7,[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
202
sage: print BD
203
BlockDesign<points=[0, 1, 2, 3, 4, 5, 6], blocks=[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]]>
204
sage: BD = IncidenceStructure(range(7),[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
205
sage: print BD
206
IncidenceStructure<points=[0, 1, 2, 3, 4, 5, 6], blocks=[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]]>
207
"""
208
if self.name:
209
repr = '%s<points=%s, blocks=%s>' % (self.name, self.pnts,
210
self.blcks)
211
else:
212
repr = 'IncidenceStructure<points=%s, blocks=%s>' % (self.pnts,
213
self.blcks)
214
return repr
215
216
def automorphism_group(self):
217
"""
218
Returns the subgroup of the automorphism group of the incidence graph
219
which respects the P B partition. It is (isomorphic to) the automorphism
220
group of the block design, although the degrees differ.
221
222
EXAMPLES::
223
224
sage: from sage.combinat.designs.block_design import BlockDesign
225
sage: BD = BlockDesign(7,[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
226
sage: G = BD.automorphism_group(); G
227
Permutation Group with generators [(4,5)(6,7), (4,6)(5,7), (2,3)(6,7), (2,4)(3,5), (1,2)(5,6)]
228
sage: BD = BlockDesign(4,[[0],[0,1],[1,2],[3,3]],test=False)
229
sage: G = BD.automorphism_group(); G
230
Permutation Group with generators [()]
231
sage: BD = BlockDesign(7,[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
232
sage: G = BD.automorphism_group(); G
233
Permutation Group with generators [(4,5)(6,7), (4,6)(5,7), (2,3)(6,7), (2,4)(3,5), (1,2)(5,6)]
234
"""
235
from sage.groups.perm_gps.partn_ref.refinement_matrices import MatrixStruct
236
from sage.groups.perm_gps.permgroup import PermutationGroup
237
from sage.groups.perm_gps.permgroup_named import SymmetricGroup
238
M1 = self.incidence_matrix()
239
M2 = MatrixStruct(M1)
240
M2.run()
241
gens = M2.automorphism_group()[0]
242
v = len(self.points())
243
G = SymmetricGroup(v)
244
gns = []
245
for g in gens:
246
L = [j+1 for j in g]
247
gns.append(G(L))
248
return PermutationGroup(gns)
249
250
def block_design_checker(self, t, v, k, lmbda, type=None):
251
"""
252
This is *not* a wrapper for GAP Design's IsBlockDesign. The GAP
253
Design function IsBlockDesign
254
http://www.gap-system.org/Manuals/pkg/design/htm/CHAP004.htm
255
apparently simply checks the record structure and no mathematical
256
properties. Instead, the function below checks some necessary (but
257
not sufficient) "easy" identities arising from the identity.
258
259
INPUT:
260
261
- ``t`` - the t as in "t-design"
262
263
- ``v`` - the number of points
264
265
- ``k`` - the number of blocks incident to a point
266
267
- ``lmbda`` - each t-tuple of points should be incident with
268
lmbda blocks
269
270
- ``type`` - can be 'simple' or 'binary' or 'connected'
271
Depending on the option, this wraps IsBinaryBlockDesign,
272
IsSimpleBlockDesign, or IsConnectedBlockDesign.
273
274
- Binary: no block has a repeated element.
275
276
- Simple: no block is repeated.
277
278
- Connected: its incidence graph is a connected graph.
279
280
WARNING: This is very fast but can return false positives.
281
282
EXAMPLES::
283
284
sage: from sage.combinat.designs.block_design import BlockDesign
285
sage: BD = BlockDesign(7,[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
286
sage: BD.is_block_design()
287
(True, [2, 7, 3, 1])
288
sage: BD.block_design_checker(2, 7, 3, 1)
289
True
290
sage: BD.block_design_checker(2, 7, 3, 1,"binary")
291
True
292
sage: BD.block_design_checker(2, 7, 3, 1,"connected")
293
True
294
sage: BD.block_design_checker(2, 7, 3, 1,"simple")
295
True
296
"""
297
from sage.sets.set import Set
298
if not(v == len(self.points())):
299
return False
300
b = lmbda*binomial(v, t)/binomial(k, t)
301
r = int(b*k/v)
302
if not(b == len(self.blocks())):
303
return False
304
if not(ZZ(v).divides(b*k)):
305
return False
306
A = self.incidence_matrix()
307
#k = sum(A.columns()[0])
308
#r = sum(A.rows()[0])
309
for i in range(b):
310
if not(sum(A.columns()[i]) == k):
311
return False
312
for i in range(v):
313
if not(sum(A.rows()[i]) == r):
314
return False
315
if type is None:
316
return True
317
if type == "binary":
318
for b in self.blocks():
319
if len(b) != len(Set(b)):
320
return False
321
return True
322
if type == "simple":
323
B = self.blocks()
324
for b in B:
325
if B.count(b) > 1:
326
return False
327
return True
328
if type == "connected":
329
Gamma = self.incidence_graph()
330
if Gamma.is_connected():
331
return True
332
else:
333
return False
334
335
def blocks(self):
336
"""
337
Return the list of blocks.
338
339
EXAMPLES::
340
341
sage: from sage.combinat.designs.block_design import BlockDesign
342
sage: BD = BlockDesign(7,[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
343
sage: BD.blocks()
344
[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]]
345
"""
346
B = self.blcks
347
B.sort()
348
return B
349
350
def __eq__(self, other):
351
"""
352
Returns true if their points and blocks are equal (resp.).
353
354
EXAMPLES::
355
356
sage: from sage.combinat.designs.block_design import BlockDesign
357
sage: BD1 = BlockDesign(7,[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
358
sage: M = BD1.incidence_matrix()
359
sage: BD2 = IncidenceStructureFromMatrix(M)
360
sage: BD1 == BD2
361
True
362
"""
363
bool1 = self.points() == other.points()
364
bool2 = self.blocks() == other.blocks()
365
return (bool1 and bool2)
366
367
def block_sizes(self):
368
"""
369
Return a list of block's sizes.
370
371
EXAMPLES::
372
373
sage: from sage.combinat.designs.block_design import BlockDesign
374
sage: BD = BlockDesign(7,[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
375
sage: BD.block_sizes()
376
[3, 3, 3, 3, 3, 3, 3]
377
"""
378
self._block_sizes = map(len, self.blocks())
379
return self._block_sizes
380
381
def _gap_(self):
382
"""
383
Return the GAP string describing the design.
384
385
EXAMPLES::
386
387
sage: from sage.combinat.designs.block_design import BlockDesign
388
sage: BD = BlockDesign(7,[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
389
sage: BD._gap_()
390
'BlockDesign(7,[[1, 2, 3], [1, 4, 5], [1, 6, 7], [2, 4, 6], [2, 5, 7], [3, 4, 7], [3, 5, 6]])'
391
"""
392
B = self.blocks()
393
v = len(self.points())
394
gB = []
395
for b in B:
396
gB.append([x+1 for x in b])
397
return "BlockDesign("+str(v)+","+str(gB)+")"
398
399
def dual_incidence_structure(self, algorithm=None):
400
"""
401
Wraps GAP Design's DualBlockDesign (see [1]). The dual of a block
402
design may not be a block design.
403
404
Also can be called with ``dual_design``.
405
406
.. NOTE:
407
408
The algorithm="gap" option requires GAP's Design package (included in
409
the gap_packages Sage spkg).
410
411
EXAMPLES::
412
413
sage: from sage.combinat.designs.block_design import BlockDesign
414
sage: D = BlockDesign(4, [[0,2],[1,2,3],[2,3]], test=False)
415
sage: D
416
Incidence structure with 4 points and 3 blocks
417
sage: D.dual_design()
418
Incidence structure with 3 points and 4 blocks
419
sage: print D.dual_design(algorithm="gap") # optional - gap_design
420
IncidenceStructure<points=[0, 1, 2], blocks=[[0], [0, 1, 2], [1], [1, 2]]>
421
sage: BD = IncidenceStructure(range(7),[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]], name="FanoPlane")
422
sage: BD
423
Incidence structure with 7 points and 7 blocks
424
sage: print BD.dual_design(algorithm="gap") # optional - gap_design
425
IncidenceStructure<points=[0, 1, 2, 3, 4, 5, 6], blocks=[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]]>
426
sage: BD.dual_incidence_structure()
427
Incidence structure with 7 points and 7 blocks
428
429
REFERENCE:
430
431
- Soicher, Leonard, Design package manual, available at
432
http://www.gap-system.org/Manuals/pkg/design/htm/CHAP003.htm
433
"""
434
from sage.interfaces.gap import gap
435
from sage.misc.functional import transpose
436
if algorithm == "gap":
437
gap.load_package("design")
438
gD = self._gap_()
439
gap.eval("DD:=DualBlockDesign("+gD+")")
440
v = eval(gap.eval("DD.v"))
441
gblcks = eval(gap.eval("DD.blocks"))
442
gB = []
443
for b in gblcks:
444
gB.append([x-1 for x in b])
445
return IncidenceStructure(range(v), gB, name=None, test=False)
446
pts = self.blocks()
447
M = transpose(self.incidence_matrix())
448
blks = self.points()
449
return IncidenceStructure(pts, blks, M, name=None, test=False)
450
451
dual_design = dual_incidence_structure # to preserve standard terminology
452
453
def incidence_matrix(self):
454
"""
455
Return the incidence matrix `A` of the design. A is a `(v \times b)`
456
matrix defined by: ``A[i,j] = 1`` if ``i`` is in block ``B_j`` and 0
457
otherwise.
458
459
EXAMPLES::
460
461
sage: BD = IncidenceStructure(range(7),[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
462
sage: BD.block_sizes()
463
[3, 3, 3, 3, 3, 3, 3]
464
sage: BD.incidence_matrix()
465
[1 1 1 0 0 0 0]
466
[1 0 0 1 1 0 0]
467
[1 0 0 0 0 1 1]
468
[0 1 0 1 0 1 0]
469
[0 1 0 0 1 0 1]
470
[0 0 1 1 0 0 1]
471
[0 0 1 0 1 1 0]
472
"""
473
if not self._incidence_matrix is None:
474
return self._incidence_matrix
475
else:
476
v = len(self.points())
477
blks = self.blocks()
478
b = len(blks)
479
MS = MatrixSpace(ZZ, v, b)
480
A = MS(0)
481
#A = NUM.zeros((v,b), NUM.Int)
482
for i in range(v):
483
for j, b in enumerate(blks):
484
if i in b:
485
A[i, j] = 1
486
self._incidence_matrix = A
487
return A
488
489
def incidence_graph(self):
490
"""
491
Returns the incidence graph of the design, where the incidence
492
matrix of the design is the adjacency matrix of the graph.
493
494
EXAMPLE::
495
496
sage: BD = IncidenceStructure(range(7),[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
497
sage: BD.incidence_graph()
498
Bipartite graph on 14 vertices
499
sage: A = BD.incidence_matrix()
500
sage: Graph(block_matrix([[A*0,A],[A.transpose(),A*0]])) == BD.incidence_graph()
501
True
502
503
REFERENCE:
504
505
- Sage Reference Manual on Graphs
506
"""
507
from sage.graphs.bipartite_graph import BipartiteGraph
508
A = self.incidence_matrix()
509
return BipartiteGraph(A)
510
#same as return Graph(block_matrix([[A*0,A],[A.transpose(),A*0]]))
511
512
def is_block_design(self):
513
"""
514
Returns a pair ``True, pars`` if the incidence structure is a
515
`t`-design, for some `t`, where ``pars`` is the list of parameters `(t,
516
v, k, lmbda)`. The largest possible `t` is returned, provided `t=10`.
517
518
EXAMPLES::
519
520
sage: BD = IncidenceStructure(range(7),[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
521
sage: BD.is_block_design()
522
(True, [2, 7, 3, 1])
523
sage: BD.block_design_checker(2, 7, 3, 1)
524
True
525
sage: BD = designs.WittDesign(9) # optional - gap_packages (design package)
526
sage: BD.is_block_design() # optional - gap_packages (design package)
527
(True, [2, 9, 3, 1])
528
sage: BD = designs.WittDesign(12) # optional - gap_packages (design package)
529
sage: BD.is_block_design() # optional - gap_packages (design package)
530
(True, [5, 12, 6, 1])
531
sage: BD = designs.AffineGeometryDesign(3, 1, GF(2))
532
sage: BD.is_block_design()
533
(True, [2, 8, 2, 1])
534
"""
535
from sage.rings.arith import binomial
536
from itertools import combinations
537
v = len(self.points())
538
b = len(self.blcks)
539
540
# Definition and consistency of 'k' and 'r'
541
#
542
# r_list stores the degree of each point
543
k = len(self.blcks[0])
544
r_list = [0]*v
545
for block in self.blcks:
546
if len(block) != k:
547
return False
548
for x in block:
549
r_list[x] += 1
550
551
r = r_list[0]
552
if any(x!=r for x in r_list):
553
return False
554
555
# Definition and consistency of 'l' (lambda) and 't'
556
t_found_yet = False
557
558
for t in range(2,min(v,k+1)):
559
560
# Is lambda an integer ?
561
if (b*binomial(k,t)) % binomial(v,t) == 0:
562
l = (b*binomial(k,t))/binomial(v,t)
563
else:
564
continue
565
566
# Associates to every t-subset of [v] the number of its occurrences
567
# as a subset of a block
568
t_counts = {}
569
for block in self.blcks:
570
for t_set in combinations(sorted(block),t):
571
t_counts[t_set] = t_counts.get(t_set,0)+1
572
573
# Checking the consistency of l
574
l_values = t_counts.values()
575
576
if all(l == x for x in l_values):
577
t_found_yet = True
578
t_lambda = t,l
579
580
if t_found_yet:
581
t,l = t_lambda
582
return (True, [t,v,k,l])
583
else:
584
return (False, [0,0,0,0])
585
586
def parameters(self, t=None):
587
"""
588
Returns `(t,v,k,lambda)`. Does not check if the input is a block
589
design.
590
591
INPUT:
592
593
- ``t`` -- `t` such that the design is a `t`-design.
594
595
EXAMPLES::
596
597
sage: from sage.combinat.designs.block_design import BlockDesign
598
sage: BD = BlockDesign(7,[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]], name="FanoPlane")
599
sage: BD.parameters(t=2)
600
(2, 7, 3, 1)
601
sage: BD.parameters(t=3)
602
(3, 7, 3, 0)
603
"""
604
if t is None:
605
from sage.misc.superseded import deprecation
606
deprecation(15664, "the 't' argument will become mandatory soon. 2"+
607
" is used when none is provided.")
608
t = 2
609
610
v = len(self.points())
611
blks = self.blocks()
612
k = len(blks[int(0)])
613
b = len(blks)
614
#A = self.incidence_matrix()
615
#r = sum(A.rows()[0])
616
lmbda = int(b/(binomial(v, t)/binomial(k, t)))
617
return (t, v, k, lmbda)
618
619
def points(self):
620
"""
621
Returns the list of points.
622
623
EXAMPLES::
624
625
sage: from sage.combinat.designs.block_design import BlockDesign
626
sage: BD = BlockDesign(7,[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
627
sage: BD.points()
628
[0, 1, 2, 3, 4, 5, 6]
629
"""
630
return self.pnts
631
632
def points_from_gap(self):
633
"""
634
Literally pushes this block design over to GAP and returns the
635
points of that. Other than debugging, usefulness is unclear.
636
637
REQUIRES: GAP's Design package.
638
639
EXAMPLES::
640
641
sage: from sage.combinat.designs.block_design import BlockDesign
642
sage: BD = BlockDesign(7,[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]])
643
sage: BD.points_from_gap() # optional - gap_packages (design package)
644
doctest:1: DeprecationWarning: Unless somebody protests this method will be removed, as nobody seems to know why it is there.
645
See http://trac.sagemath.org/14499 for details.
646
[1, 2, 3, 4, 5, 6, 7]
647
"""
648
from sage.misc.superseded import deprecation
649
deprecation(14499, ('Unless somebody protests this method will be '
650
'removed, as nobody seems to know why it is there.'))
651
from sage.interfaces.gap import gap
652
gap.load_package("design")
653
gD = self._gap_()
654
gP = gap.eval("BlockDesignPoints("+gD+")").replace("..", ",")
655
return range(eval(gP)[0], eval(gP)[1]+1)
656
657