def points_from_gap(self): """ Literally pushes this block design over to GAP and returns the points of that. Other than debugging, usefulness is unclear. REQUIRES: GAP's Design package. EXAMPLES:: sage: from sage.combinat.designs.block_design import BlockDesign 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]]) sage: BD.points_from_gap() # optional - gap_packages (design package) doctest:1: DeprecationWarning: Unless somebody protests this method will be removed, as nobody seems to know why it is there. See http://trac.sagemath.org/14499 for details. [1, 2, 3, 4, 5, 6, 7] """ from sage.misc.superseded import deprecation deprecation(14499, ('Unless somebody protests this method will be ' 'removed, as nobody seems to know why it is there.')) from sage.interfaces.gap import gap, GapElement from sage.sets.set import Set gap.load_package("design") gD = self._gap_() gP = gap.eval("BlockDesignPoints("+gD+")").replace("..",",") return range(eval(gP)[0],eval(gP)[1]+1)
def WittDesign(n): """ INPUT: - ``n`` is in `9,10,11,12,21,22,23,24`. Wraps GAP Design's WittDesign. If ``n=24`` then this function returns the large Witt design `W_{24}`, the unique (up to isomorphism) `5-(24,8,1)` design. If ``n=12`` then this function returns the small Witt design `W_{12}`, the unique (up to isomorphism) `5-(12,6,1)` design. The other values of `n` return a block design derived from these. .. NOTE:: Requires GAP's Design package (included in the gap_packages Sage spkg). EXAMPLES:: sage: BD = designs.WittDesign(9) # optional - gap_packages (design package) sage: BD.is_t_design(return_parameters=True) # optional - gap_packages (design package) (True, (2, 9, 3, 1)) sage: BD # optional - gap_packages (design package) Incidence structure with 9 points and 12 blocks sage: print(BD) # optional - gap_packages (design package) Incidence structure with 9 points and 12 blocks """ from sage.interfaces.gap import gap gap.load_package("design") gap.eval("B:=WittDesign(%s)"%n) v = eval(gap.eval("B.v")) gblcks = eval(gap.eval("B.blocks")) gB = [] for b in gblcks: gB.append([x-1 for x in b]) return BlockDesign(v, gB, name="WittDesign", check=True)
def WittDesign(n): """ INPUT: - ``n`` is in `9,10,11,12,21,22,23,24`. Wraps GAP Design's WittDesign. If ``n=24`` then this function returns the large Witt design `W_{24}`, the unique (up to isomorphism) `5-(24,8,1)` design. If ``n=12`` then this function returns the small Witt design `W_{12}`, the unique (up to isomorphism) `5-(12,6,1)` design. The other values of `n` return a block design derived from these. .. NOTE: Requires GAP's Design package (included in the gap_packages Sage spkg). EXAMPLES:: sage: BD = designs.WittDesign(9) # optional - gap_packages (design package) sage: BD.is_t_design(return_parameters=True) # optional - gap_packages (design package) (True, (2, 9, 3, 1)) sage: BD # optional - gap_packages (design package) Incidence structure with 9 points and 12 blocks sage: print BD # optional - gap_packages (design package) Incidence structure with 9 points and 12 blocks """ from sage.interfaces.gap import gap, GapElement gap.load_package("design") gap.eval("B:=WittDesign(%s)"%n) v = eval(gap.eval("B.v")) gblcks = eval(gap.eval("B.blocks")) gB = [] for b in gblcks: gB.append([x-1 for x in b]) return BlockDesign(v, gB, name="WittDesign", check=True)
def ProjectiveGeometryDesign(n, d, F, algorithm=None): """ Returns a projective geometry design. A projective geometry design of parameters `n,d,F` has for points the lines of `F^{n+1}`, and for blocks the `d+1`-dimensional subspaces of `F^{n+1}`, each of which contains `\\frac {|F|^{d+1}-1} {|F|-1}` lines. INPUT: - ``n`` is the projective dimension - ``d`` is the dimension of the subspaces of `P = PPn(F)` which make up the blocks. - ``F`` is a finite field. - ``algorithm`` -- set to ``None`` by default, which results in using Sage's own implementation. In order to use GAP's implementation instead (i.e. its ``PGPointFlatBlockDesign`` function) set ``algorithm="gap"``. Note that GAP's "design" package must be available in this case, and that it can be installed with the ``gap_packages`` spkg. EXAMPLES: The points of the following design are the `\\frac {2^{2+1}-1} {2-1}=7` lines of `\mathbb{Z}_2^{2+1}`. It has `7` blocks, corresponding to each 2-dimensional subspace of `\mathbb{Z}_2^{2+1}`:: sage: designs.ProjectiveGeometryDesign(2, 1, GF(2)) Incidence structure with 7 points and 7 blocks sage: BD = designs.ProjectiveGeometryDesign(2, 1, GF(2), algorithm="gap") # optional - gap_packages (design package) sage: BD.is_block_design() # optional - gap_packages (design package) (True, [2, 7, 3, 1]) """ q = F.order() from sage.interfaces.gap import gap, GapElement from sage.sets.set import Set if algorithm is None: V = VectorSpace(F, n + 1) points = list(V.subspaces(1)) flats = list(V.subspaces(d + 1)) blcks = [] for p in points: b = [] for i in range(len(flats)): if p.is_subspace(flats[i]): b.append(i) blcks.append(b) v = (q**(n + 1) - 1) / (q - 1) return BlockDesign(v, blcks, name="ProjectiveGeometryDesign") if algorithm == "gap": # Requires GAP's Design gap.load_package("design") gap.eval("D := PGPointFlatBlockDesign( %s, %s, %d )" % (n, q, d)) v = eval(gap.eval("D.v")) gblcks = eval(gap.eval("D.blocks")) gB = [] for b in gblcks: gB.append([x - 1 for x in b]) return BlockDesign(v, gB, name="ProjectiveGeometryDesign")
def dual(self, algorithm=None): """ Return the dual of the incidence structure. INPUT: - ``algorithm`` -- whether to use Sage's implementation (``algorithm=None``, default) or use GAP's (``algorithm="gap"``). .. NOTE:: The ``algorithm="gap"`` option requires GAP's Design package (included in the gap_packages Sage spkg). EXAMPLES: The dual of a projective plane is a projective plane:: sage: PP = designs.DesarguesianProjectivePlaneDesign(4) sage: PP.dual().is_t_design(return_parameters=True) (True, (2, 21, 5, 1)) TESTS:: sage: D = designs.IncidenceStructure(4, [[0,2],[1,2,3],[2,3]]) sage: D Incidence structure with 4 points and 3 blocks sage: D.dual() Incidence structure with 3 points and 4 blocks sage: print D.dual(algorithm="gap") # optional - gap_packages IncidenceStructure<points=[0, 1, 2], blocks=[[0], [0, 1, 2], [1], [1, 2]]> sage: blocks = [[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]] sage: BD = designs.IncidenceStructure(7, blocks, name="FanoPlane"); sage: BD Incidence structure with 7 points and 7 blocks sage: print BD.dual(algorithm="gap") # optional - gap_packages 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]]> sage: BD.dual() Incidence structure with 7 points and 7 blocks REFERENCE: - Soicher, Leonard, Design package manual, available at http://www.gap-system.org/Manuals/pkg/design/htm/CHAP003.htm """ if algorithm == "gap": from sage.interfaces.gap import gap gap.load_package("design") gD = self._gap_() gap.eval("DD:=DualBlockDesign("+gD+")") v = eval(gap.eval("DD.v")) gblcks = eval(gap.eval("DD.blocks")) gB = [] for b in gblcks: gB.append([x-1 for x in b]) return IncidenceStructure(range(v), gB, name=None, check=False) else: return IncidenceStructure( incidence_matrix=self.incidence_matrix().transpose(), check=False)
def ProjectiveGeometryDesign(n, d, F, algorithm=None): """ Returns a projective geometry design. A projective geometry design of parameters `n,d,F` has for points the lines of `F^{n+1}`, and for blocks the `d+1`-dimensional subspaces of `F^{n+1}`, each of which contains `\\frac {|F|^{d+1}-1} {|F|-1}` lines. INPUT: - ``n`` is the projective dimension - ``d`` is the dimension of the subspaces of `P = PPn(F)` which make up the blocks. - ``F`` is a finite field. - ``algorithm`` -- set to ``None`` by default, which results in using Sage's own implementation. In order to use GAP's implementation instead (i.e. its ``PGPointFlatBlockDesign`` function) set ``algorithm="gap"``. Note that GAP's "design" package must be available in this case, and that it can be installed with the ``gap_packages`` spkg. EXAMPLES: The points of the following design are the `\\frac {2^{2+1}-1} {2-1}=7` lines of `\mathbb{Z}_2^{2+1}`. It has `7` blocks, corresponding to each 2-dimensional subspace of `\mathbb{Z}_2^{2+1}`:: sage: designs.ProjectiveGeometryDesign(2, 1, GF(2)) Incidence structure with 7 points and 7 blocks sage: BD = designs.ProjectiveGeometryDesign(2, 1, GF(2), algorithm="gap") # optional - gap_packages (design package) sage: BD.is_block_design() # optional - gap_packages (design package) (True, [2, 7, 3, 1]) """ q = F.order() from sage.interfaces.gap import gap, GapElement from sage.sets.set import Set if algorithm is None: V = VectorSpace(F, n+1) points = list(V.subspaces(1)) flats = list(V.subspaces(d+1)) blcks = [] for p in points: b = [] for i in range(len(flats)): if p.is_subspace(flats[i]): b.append(i) blcks.append(b) v = (q**(n+1)-1)/(q-1) return BlockDesign(v, blcks, name="ProjectiveGeometryDesign") if algorithm == "gap": # Requires GAP's Design gap.load_package("design") gap.eval("D := PGPointFlatBlockDesign( %s, %s, %d )"%(n,q,d)) v = eval(gap.eval("D.v")) gblcks = eval(gap.eval("D.blocks")) gB = [] for b in gblcks: gB.append([x-1 for x in b]) return BlockDesign(v, gB, name="ProjectiveGeometryDesign")
def points_from_gap(self): """ Literally pushes this block design over to GAP and returns the points of that. Other than debugging, usefulness is unclear. REQUIRES: GAP's Design package. EXAMPLES:: sage: from sage.combinat.designs.block_design import BlockDesign 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]]) sage: BD.points_from_gap() # optional - gap_packages (design package) doctest:1: DeprecationWarning: Unless somebody protests this method will be removed, as nobody seems to know why it is there. See http://trac.sagemath.org/14499 for details. [1, 2, 3, 4, 5, 6, 7] """ from sage.misc.superseded import deprecation deprecation(14499, ('Unless somebody protests this method will be ' 'removed, as nobody seems to know why it is there.')) from sage.interfaces.gap import gap gap.load_package("design") gD = self._gap_() gP = gap.eval("BlockDesignPoints(" + gD + ")").replace("..", ",") return range(eval(gP)[0], eval(gP)[1] + 1)
def dual(self, algorithm=None): """ Return the dual of the incidence structure. INPUT: - ``algorithm`` -- whether to use Sage's implementation (``algorithm=None``, default) or use GAP's (``algorithm="gap"``). .. NOTE:: The ``algorithm="gap"`` option requires GAP's Design package (included in the gap_packages Sage spkg). EXAMPLES: The dual of a projective plane is a projective plane:: sage: PP = designs.DesarguesianProjectivePlaneDesign(4) sage: PP.dual().is_t_design(return_parameters=True) (True, (2, 21, 5, 1)) TESTS:: sage: D = designs.IncidenceStructure(4, [[0,2],[1,2,3],[2,3]]) sage: D Incidence structure with 4 points and 3 blocks sage: D.dual() Incidence structure with 3 points and 4 blocks sage: print D.dual(algorithm="gap") # optional - gap_packages IncidenceStructure<points=[0, 1, 2], blocks=[[0], [0, 1, 2], [1], [1, 2]]> sage: blocks = [[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]] sage: BD = designs.IncidenceStructure(7, blocks, name="FanoPlane"); sage: BD Incidence structure with 7 points and 7 blocks sage: print BD.dual(algorithm="gap") # optional - gap_packages 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]]> sage: BD.dual() Incidence structure with 7 points and 7 blocks REFERENCE: - Soicher, Leonard, Design package manual, available at http://www.gap-system.org/Manuals/pkg/design/htm/CHAP003.htm """ if algorithm == "gap": from sage.interfaces.gap import gap gap.load_package("design") gD = self._gap_() gap.eval("DD:=DualBlockDesign(" + gD + ")") v = eval(gap.eval("DD.v")) gblcks = eval(gap.eval("DD.blocks")) gB = [] for b in gblcks: gB.append([x - 1 for x in b]) return IncidenceStructure(range(v), gB, name=None, check=False) else: return IncidenceStructure( incidence_matrix=self.incidence_matrix().transpose(), check=False)
def dual_incidence_structure(self, algorithm=None): """ Wraps GAP Design's DualBlockDesign (see [1]). The dual of a block design may not be a block design. Also can be called with ``dual_design``. .. NOTE: The algorithm="gap" option requires GAP's Design package (included in the gap_packages Sage spkg). EXAMPLES:: sage: from sage.combinat.designs.block_design import BlockDesign sage: D = BlockDesign(4, [[0,2],[1,2,3],[2,3]], test=False) sage: D Incidence structure with 4 points and 3 blocks sage: D.dual_design() Incidence structure with 3 points and 4 blocks sage: print D.dual_design(algorithm="gap") # optional - gap_design IncidenceStructure<points=[0, 1, 2], blocks=[[0], [0, 1, 2], [1], [1, 2]]> 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") sage: BD Incidence structure with 7 points and 7 blocks sage: print BD.dual_design(algorithm="gap") # optional - gap_design 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]]> sage: BD.dual_incidence_structure() Incidence structure with 7 points and 7 blocks REFERENCE: - Soicher, Leonard, Design package manual, available at http://www.gap-system.org/Manuals/pkg/design/htm/CHAP003.htm """ from sage.interfaces.gap import gap, GapElement from sage.sets.set import Set from sage.misc.flatten import flatten from sage.combinat.designs.block_design import BlockDesign from sage.misc.functional import transpose if algorithm == "gap": gap.load_package("design") gD = self._gap_() gap.eval("DD:=DualBlockDesign(" + gD + ")") v = eval(gap.eval("DD.v")) gblcks = eval(gap.eval("DD.blocks")) gB = [] for b in gblcks: gB.append([x - 1 for x in b]) return IncidenceStructure(range(v), gB, name=None, test=False) pts = self.blocks() M = transpose(self.incidence_matrix()) blks = self.points() return IncidenceStructure(pts, blks, M, name=None, test=False)
def dual_incidence_structure(self, algorithm=None): """ Wraps GAP Design's DualBlockDesign (see [1]). The dual of a block design may not be a block design. Also can be called with ``dual_design``. .. NOTE: The algorithm="gap" option requires GAP's Design package (included in the gap_packages Sage spkg). EXAMPLES:: sage: from sage.combinat.designs.block_design import BlockDesign sage: D = BlockDesign(4, [[0,2],[1,2,3],[2,3]], test=False) sage: D Incidence structure with 4 points and 3 blocks sage: D.dual_design() Incidence structure with 3 points and 4 blocks sage: print D.dual_design(algorithm="gap") # optional - gap_design IncidenceStructure<points=[0, 1, 2], blocks=[[0], [0, 1, 2], [1], [1, 2]]> 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") sage: BD Incidence structure with 7 points and 7 blocks sage: print BD.dual_design(algorithm="gap") # optional - gap_design 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]]> sage: BD.dual_incidence_structure() Incidence structure with 7 points and 7 blocks REFERENCE: - Soicher, Leonard, Design package manual, available at http://www.gap-system.org/Manuals/pkg/design/htm/CHAP003.htm """ from sage.interfaces.gap import gap, GapElement from sage.sets.set import Set from sage.misc.flatten import flatten from sage.combinat.designs.block_design import BlockDesign from sage.misc.functional import transpose if algorithm=="gap": gap.load_package("design") gD = self._gap_() gap.eval("DD:=DualBlockDesign("+gD+")") v = eval(gap.eval("DD.v")) gblcks = eval(gap.eval("DD.blocks")) gB = [] for b in gblcks: gB.append([x-1 for x in b]) return IncidenceStructure(range(v), gB, name=None, test=False) pts = self.blocks() M = transpose(self.incidence_matrix()) blks = self.points() return IncidenceStructure(pts, blks, M, name=None, test=False)
def ProjectiveGeometryDesign(n, d, F, algorithm=None): """ INPUT: - ``n`` is the projective dimension - ``v`` is the number of points `PPn(GF(q))` - ``d`` is the dimension of the subspaces of `P = PPn(GF(q))` which make up the blocks - ``b`` is the number of `d`-dimensional subspaces of `P` Wraps GAP Design's PGPointFlatBlockDesign. Does *not* require GAP's Design. EXAMPLES:: sage: designs.ProjectiveGeometryDesign(2, 1, GF(2)) Incidence structure with 7 points and 7 blocks sage: BD = designs.ProjectiveGeometryDesign(2, 1, GF(2), algorithm="gap") # optional - gap_packages (design package) sage: BD.is_block_design() # optional - gap_packages (design package) (True, [2, 7, 3, 1]) """ q = F.order() from sage.interfaces.gap import gap, GapElement from sage.sets.set import Set if algorithm == None: V = VectorSpace(F, n + 1) points = list(V.subspaces(1)) flats = list(V.subspaces(d + 1)) blcks = [] for p in points: b = [] for i in range(len(flats)): if p.is_subspace(flats[i]): b.append(i) blcks.append(b) v = (q**(n + 1) - 1) / (q - 1) return BlockDesign(v, blcks, name="ProjectiveGeometryDesign") if algorithm == "gap": # Requires GAP's Design gap.load_package("design") gap.eval("D := PGPointFlatBlockDesign( %s, %s, %d )" % (n, q, d)) v = eval(gap.eval("D.v")) gblcks = eval(gap.eval("D.blocks")) gB = [] for b in gblcks: gB.append([x - 1 for x in b]) return BlockDesign(v, gB, name="ProjectiveGeometryDesign")
def ProjectiveGeometryDesign(n, d, F, algorithm=None): """ INPUT: - ``n`` is the projective dimension - ``v`` is the number of points `PPn(GF(q))` - ``d`` is the dimension of the subspaces of `P = PPn(GF(q))` which make up the blocks - ``b`` is the number of `d`-dimensional subspaces of `P` Wraps GAP Design's PGPointFlatBlockDesign. Does *not* require GAP's Design. EXAMPLES:: sage: designs.ProjectiveGeometryDesign(2, 1, GF(2)) Incidence structure with 7 points and 7 blocks sage: BD = designs.ProjectiveGeometryDesign(2, 1, GF(2), algorithm="gap") # optional - gap_packages (design package) sage: BD.is_block_design() # optional - gap_packages (design package) (True, [2, 7, 3, 1]) """ q = F.order() from sage.interfaces.gap import gap, GapElement from sage.sets.set import Set if algorithm == None: V = VectorSpace(F, n+1) points = list(V.subspaces(1)) flats = list(V.subspaces(d+1)) blcks = [] for p in points: b = [] for i in range(len(flats)): if p.is_subspace(flats[i]): b.append(i) blcks.append(b) v = (q**(n+1)-1)/(q-1) return BlockDesign(v, blcks, name="ProjectiveGeometryDesign") if algorithm == "gap": # Requires GAP's Design gap.load_package("design") gap.eval("D := PGPointFlatBlockDesign( %s, %s, %d )"%(n,q,d)) v = eval(gap.eval("D.v")) gblcks = eval(gap.eval("D.blocks")) gB = [] for b in gblcks: gB.append([x-1 for x in b]) return BlockDesign(v, gB, name="ProjectiveGeometryDesign")
def WittDesign(n): """ INPUT: - ``n`` is in `9,10,11,12,21,22,23,24`. Wraps GAP Design's WittDesign. If ``n=24`` then this function returns the large Witt design `W_{24}`, the unique (up to isomorphism) `5-(24,8,1)` design. If ``n=12`` then this function returns the small Witt design `W_{12}`, the unique (up to isomorphism) `5-(12,6,1)` design. The other values of `n` return a block design derived from these. .. NOTE: Requires GAP's Design package (included in the gap_packages Sage spkg). EXAMPLES:: sage: BD = designs.WittDesign(9) # optional - gap_packages (design package) sage: BD.parameters() # optional - gap_packages (design package) (2, 9, 3, 1) sage: BD # optional - gap_packages (design package) Incidence structure with 9 points and 12 blocks sage: print BD # optional - gap_packages (design package) WittDesign<points=[0, 1, 2, 3, 4, 5, 6, 7, 8], blocks=[[0, 1, 7], [0, 2, 5], [0, 3, 4], [0, 6, 8], [1, 2, 6], [1, 3, 5], [1, 4, 8], [2, 3, 8], [2, 4, 7], [3, 6, 7], [4, 5, 6], [5, 7, 8]]> sage: BD = designs.WittDesign(12) # optional - gap_packages (design package) sage: BD.parameters(t=5) # optional - gap_packages (design package) (5, 12, 6, 1) """ from sage.interfaces.gap import gap, GapElement gap.load_package("design") gap.eval("B:=WittDesign(%s)" % n) v = eval(gap.eval("B.v")) gblcks = eval(gap.eval("B.blocks")) gB = [] for b in gblcks: gB.append([x - 1 for x in b]) return BlockDesign(v, gB, name="WittDesign", test=True)
def ProjectiveGeometryDesign(n, d, F, algorithm=None, check=True): """ Return a projective geometry design. A projective geometry design of parameters `n,d,F` has for points the lines of `F^{n+1}`, and for blocks the `d+1`-dimensional subspaces of `F^{n+1}`, each of which contains `\\frac {|F|^{d+1}-1} {|F|-1}` lines. INPUT: - ``n`` is the projective dimension - ``d`` is the dimension of the subspaces of `P = PPn(F)` which make up the blocks. - ``F`` is a finite field. - ``algorithm`` -- set to ``None`` by default, which results in using Sage's own implementation. In order to use GAP's implementation instead (i.e. its ``PGPointFlatBlockDesign`` function) set ``algorithm="gap"``. Note that GAP's "design" package must be available in this case, and that it can be installed with the ``gap_packages`` spkg. EXAMPLES: The set of `d`-dimensional subspaces in a `n`-dimensional projective space forms `2`-designs (or balanced incomplete block designs):: sage: PG = designs.ProjectiveGeometryDesign(4,2,GF(2)) sage: PG Incidence structure with 31 points and 155 blocks sage: PG.is_t_design(return_parameters=True) (True, (2, 31, 7, 7)) sage: PG = designs.ProjectiveGeometryDesign(3,1,GF(4,'z')) sage: PG.is_t_design(return_parameters=True) (True, (2, 85, 5, 1)) Check that the constructor using gap also works:: sage: BD = designs.ProjectiveGeometryDesign(2, 1, GF(2), algorithm="gap") # optional - gap_packages (design package) sage: BD.is_t_design(return_parameters=True) # optional - gap_packages (design package) (True, (2, 7, 3, 1)) """ if algorithm is None: from sage.matrix.echelon_matrix import reduced_echelon_matrix_iterator from copy import copy points = {} points = { p: i for i, p in enumerate( reduced_echelon_matrix_iterator( F, 1, n + 1, copy=True, set_immutable=True)) } blocks = [] for m1 in reduced_echelon_matrix_iterator(F, d + 1, n + 1, copy=False): b = [] for m2 in reduced_echelon_matrix_iterator(F, 1, d + 1, copy=False): m = m2 * m1 m.echelonize() m.set_immutable() b.append(points[m]) blocks.append(b) return BlockDesign(len(points), blocks, name="ProjectiveGeometryDesign", check=check) if algorithm == "gap": # Requires GAP's Design from sage.interfaces.gap import gap gap.load_package("design") gap.eval("D := PGPointFlatBlockDesign( %s, %s, %d )" % (n, F.order(), d)) v = eval(gap.eval("D.v")) gblcks = eval(gap.eval("D.blocks")) gB = [] for b in gblcks: gB.append([x - 1 for x in b]) return BlockDesign(v, gB, name="ProjectiveGeometryDesign", check=check)
def ProjectiveGeometryDesign(n, d, F, algorithm=None, point_coordinates=True, check=True): r""" Return a projective geometry design. The projective geometry design `PG_d(n,q)` has for points the lines of `\GF{q}^{n+1}`, and for blocks the `d+1`-dimensional subspaces of `\GF{q}^{n+1}`, each of which contains `\frac {|\GF{q}|^{d+1}-1} {|\GF{q}|-1}` lines. It is a `2`-design with parameters .. MATH:: v = \binom{n+1}{1}_q,\ k = \binom{d+1}{1}_q,\ \lambda = \binom{n-1}{d-1}_q where the `q`-binomial coefficient `\binom{m}{r}_q` is defined by .. MATH:: \binom{m}{r}_q = \frac{(q^m - 1)(q^{m-1} - 1) \cdots (q^{m-r+1}-1)} {(q^r-1)(q^{r-1}-1)\cdots (q-1)} .. SEEALSO:: :func:`AffineGeometryDesign` INPUT: - ``n`` is the projective dimension - ``d`` is the dimension of the subspaces which make up the blocks. - ``F`` -- a finite field or a prime power. - ``algorithm`` -- set to ``None`` by default, which results in using Sage's own implementation. In order to use GAP's implementation instead (i.e. its ``PGPointFlatBlockDesign`` function) set ``algorithm="gap"``. Note that GAP's "design" package must be available in this case, and that it can be installed with the ``gap_packages`` spkg. - ``point_coordinates`` -- ``True`` by default. Ignored and assumed to be ``False`` if ``algorithm="gap"``. If ``True``, the ground set is indexed by coordinates in `\GF{q}^{n+1}`. Otherwise the ground set is indexed by integers. - ``check`` -- (optional, default to ``True``) whether to check the output. EXAMPLES: The set of `d`-dimensional subspaces in a `n`-dimensional projective space forms `2`-designs (or balanced incomplete block designs):: sage: PG = designs.ProjectiveGeometryDesign(4, 2, GF(2)) sage: PG Incidence structure with 31 points and 155 blocks sage: PG.is_t_design(return_parameters=True) (True, (2, 31, 7, 7)) sage: PG = designs.ProjectiveGeometryDesign(3, 1, GF(4)) sage: PG.is_t_design(return_parameters=True) (True, (2, 85, 5, 1)) Check with ``F`` being a prime power:: sage: PG = designs.ProjectiveGeometryDesign(3, 2, 4) sage: PG Incidence structure with 85 points and 85 blocks Use coordinates:: sage: PG = designs.ProjectiveGeometryDesign(2, 1, GF(3)) sage: PG.blocks()[0] [(1, 0, 0), (1, 0, 1), (1, 0, 2), (0, 0, 1)] Use indexing by integers:: sage: PG = designs.ProjectiveGeometryDesign(2,1,GF(3),point_coordinates=0) sage: PG.blocks()[0] [0, 1, 2, 12] Check that the constructor using gap also works:: sage: BD = designs.ProjectiveGeometryDesign(2, 1, GF(2), algorithm="gap") # optional - gap_packages (design package) sage: BD.is_t_design(return_parameters=True) # optional - gap_packages (design package) (True, (2, 7, 3, 1)) """ try: q = int(F) except TypeError: q = F.cardinality() else: from sage.rings.finite_rings.finite_field_constructor import GF F = GF(q) if algorithm is None: from sage.matrix.echelon_matrix import reduced_echelon_matrix_iterator points = {p:i for i,p in enumerate(reduced_echelon_matrix_iterator(F,1,n+1,copy=True,set_immutable=True))} blocks = [] for m1 in reduced_echelon_matrix_iterator(F,d+1,n+1,copy=False): b = [] for m2 in reduced_echelon_matrix_iterator(F,1,d+1,copy=False): m = m2*m1 m.echelonize() m.set_immutable() b.append(points[m]) blocks.append(b) B = BlockDesign(len(points), blocks, name="ProjectiveGeometryDesign", check=check) if point_coordinates: B.relabel({i:p[0] for p,i in six.iteritems(points)}) elif algorithm == "gap": # Requires GAP's Design from sage.interfaces.gap import gap gap.load_package("design") gap.eval("D := PGPointFlatBlockDesign( %s, %s, %d )"%(n,F.order(),d)) v = eval(gap.eval("D.v")) gblcks = eval(gap.eval("D.blocks")) gB = [] for b in gblcks: gB.append([x-1 for x in b]) B = BlockDesign(v, gB, name="ProjectiveGeometryDesign", check=check) if check: from sage.combinat.q_analogues import q_binomial q = F.cardinality() if not B.is_t_design(t=2, v=q_binomial(n+1,1,q), k=q_binomial(d+1,1,q), l=q_binomial(n-1, d-1, q)): raise RuntimeError("error in ProjectiveGeometryDesign " "construction. Please e-mail [email protected]") return B
def dual_incidence_structure(self, algorithm=None): """ Returns the dual of the incidence structure. Note that the dual of a block design may not be a block design. INPUT: - ``algorithm`` -- whether to use Sage's implementation (``algorithm=None``, default) or use GAP's (``algorithm="gap"``). .. NOTE:: The ``algorithm="gap"`` option requires GAP's Design package (included in the gap_packages Sage spkg). Also can be called with ``dual_design``. EXAMPLES: The dual of a projective plane is a projective plane:: sage: PP = designs.ProjectivePlaneDesign(4) sage: PP.dual_design().is_block_design() (True, [2, 21, 5, 1]) sage: PP = designs.ProjectivePlaneDesign(4) # optional - gap_packages sage: PP.dual_design(algorithm="gap").is_block_design() # optional - gap_packages (True, [2, 21, 5, 1]) TESTS:: sage: from sage.combinat.designs.block_design import BlockDesign sage: D = BlockDesign(4, [[0,2],[1,2,3],[2,3]], test=False) sage: D Incidence structure with 4 points and 3 blocks sage: D.dual_design() Incidence structure with 3 points and 4 blocks sage: print D.dual_design(algorithm="gap") # optional - gap_packages IncidenceStructure<points=[0, 1, 2], blocks=[[0], [0, 1, 2], [1], [1, 2]]> 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") sage: BD Incidence structure with 7 points and 7 blocks sage: print BD.dual_design(algorithm="gap") # optional - gap_packages 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]]> sage: BD.dual_incidence_structure() Incidence structure with 7 points and 7 blocks REFERENCE: - Soicher, Leonard, Design package manual, available at http://www.gap-system.org/Manuals/pkg/design/htm/CHAP003.htm """ if algorithm == "gap": from sage.interfaces.gap import gap gap.load_package("design") gD = self._gap_() gap.eval("DD:=DualBlockDesign("+gD+")") v = eval(gap.eval("DD.v")) gblcks = eval(gap.eval("DD.blocks")) gB = [] for b in gblcks: gB.append([x-1 for x in b]) return IncidenceStructure(range(v), gB, name=None, test=False) else: M = self.incidence_matrix() new_blocks = [list(r.dict(copy=False)) for r in M.rows()] return IncidenceStructure(range(M.ncols()), new_blocks, name=None, test=False)
def ProjectiveGeometryDesign(n, d, F, algorithm=None, point_coordinates=True, check=True): r""" Return a projective geometry design. The projective geometry design `PG_d(n,q)` has for points the lines of `\GF{q}^{n+1}`, and for blocks the `d+1`-dimensional subspaces of `\GF{q}^{n+1}`, each of which contains `\frac {|\GF{q}|^{d+1}-1} {|\GF{q}|-1}` lines. It is a `2`-design with parameters .. MATH:: v = \binom{n+1}{1}_q,\ k = \binom{d+1}{1}_q,\ \lambda = \binom{n-1}{d-1}_q where the `q`-binomial coefficient `\binom{m}{r}_q` is defined by .. MATH:: \binom{m}{r}_q = \frac{(q^m - 1)(q^{m-1} - 1) \cdots (q^{m-r+1}-1)} {(q^r-1)(q^{r-1}-1)\cdots (q-1)} .. SEEALSO:: :func:`AffineGeometryDesign` INPUT: - ``n`` is the projective dimension - ``d`` is the dimension of the subspaces which make up the blocks. - ``F`` -- a finite field or a prime power. - ``algorithm`` -- set to ``None`` by default, which results in using Sage's own implementation. In order to use GAP's implementation instead (i.e. its ``PGPointFlatBlockDesign`` function) set ``algorithm="gap"``. Note that GAP's "design" package must be available in this case, and that it can be installed with the ``gap_packages`` spkg. - ``point_coordinates`` -- ``True`` by default. Ignored and assumed to be ``False`` if ``algorithm="gap"``. If ``True``, the ground set is indexed by coordinates in `\GF{q}^{n+1}`. Otherwise the ground set is indexed by integers. - ``check`` -- (optional, default to ``True``) whether to check the output. EXAMPLES: The set of `d`-dimensional subspaces in a `n`-dimensional projective space forms `2`-designs (or balanced incomplete block designs):: sage: PG = designs.ProjectiveGeometryDesign(4, 2, GF(2)) sage: PG Incidence structure with 31 points and 155 blocks sage: PG.is_t_design(return_parameters=True) (True, (2, 31, 7, 7)) sage: PG = designs.ProjectiveGeometryDesign(3, 1, GF(4)) sage: PG.is_t_design(return_parameters=True) (True, (2, 85, 5, 1)) Check with ``F`` being a prime power:: sage: PG = designs.ProjectiveGeometryDesign(3, 2, 4) sage: PG Incidence structure with 85 points and 85 blocks Use coordinates:: sage: PG = designs.ProjectiveGeometryDesign(2, 1, GF(3)) sage: PG.blocks()[0] [(1, 0, 0), (1, 0, 1), (1, 0, 2), (0, 0, 1)] Use indexing by integers:: sage: PG = designs.ProjectiveGeometryDesign(2,1,GF(3),point_coordinates=0) sage: PG.blocks()[0] [0, 1, 2, 12] Check that the constructor using gap also works:: sage: BD = designs.ProjectiveGeometryDesign(2, 1, GF(2), algorithm="gap") # optional - gap_packages (design package) sage: BD.is_t_design(return_parameters=True) # optional - gap_packages (design package) (True, (2, 7, 3, 1)) """ try: q = int(F) except TypeError: q = F.cardinality() else: from sage.rings.finite_rings.finite_field_constructor import GF F = GF(q) if algorithm is None: from sage.matrix.echelon_matrix import reduced_echelon_matrix_iterator points = {p:i for i,p in enumerate(reduced_echelon_matrix_iterator(F,1,n+1,copy=True,set_immutable=True))} blocks = [] for m1 in reduced_echelon_matrix_iterator(F,d+1,n+1,copy=False): b = [] for m2 in reduced_echelon_matrix_iterator(F,1,d+1,copy=False): m = m2*m1 m.echelonize() m.set_immutable() b.append(points[m]) blocks.append(b) B = BlockDesign(len(points), blocks, name="ProjectiveGeometryDesign", check=check) if point_coordinates: B.relabel({i:p[0] for p,i in points.iteritems()}) elif algorithm == "gap": # Requires GAP's Design from sage.interfaces.gap import gap gap.load_package("design") gap.eval("D := PGPointFlatBlockDesign( %s, %s, %d )"%(n,F.order(),d)) v = eval(gap.eval("D.v")) gblcks = eval(gap.eval("D.blocks")) gB = [] for b in gblcks: gB.append([x-1 for x in b]) B = BlockDesign(v, gB, name="ProjectiveGeometryDesign", check=check) if check: from sage.combinat.q_analogues import q_binomial q = F.cardinality() if not B.is_t_design(t=2, v=q_binomial(n+1,1,q), k=q_binomial(d+1,1,q), l=q_binomial(n-1, d-1, q)): raise RuntimeError("error in ProjectiveGeometryDesign " "construction. Please e-mail [email protected]") return B
def dual_incidence_structure(self, algorithm=None): """ Returns the dual of the incidence structure. Note that the dual of a block design may not be a block design. INPUT: - ``algorithm`` -- whether to use Sage's implementation (``algorithm=None``, default) or use GAP's (``algorithm="gap"``). .. NOTE:: The ``algorithm="gap"`` option requires GAP's Design package (included in the gap_packages Sage spkg). Also can be called with ``dual_design``. EXAMPLES: The dual of a projective plane is a projective plane:: sage: PP = designs.DesarguesianProjectivePlaneDesign(4) sage: PP.dual_design().is_block_design() (True, [2, 21, 5, 1]) sage: PP = designs.DesarguesianProjectivePlaneDesign(4) # optional - gap_packages sage: PP.dual_design(algorithm="gap").is_block_design() # optional - gap_packages (True, [2, 21, 5, 1]) TESTS:: sage: from sage.combinat.designs.block_design import BlockDesign sage: D = BlockDesign(4, [[0,2],[1,2,3],[2,3]], test=False) sage: D Incidence structure with 4 points and 3 blocks sage: D.dual_design() Incidence structure with 3 points and 4 blocks sage: print D.dual_design(algorithm="gap") # optional - gap_packages IncidenceStructure<points=[0, 1, 2], blocks=[[0], [0, 1, 2], [1], [1, 2]]> 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") sage: BD Incidence structure with 7 points and 7 blocks sage: print BD.dual_design(algorithm="gap") # optional - gap_packages 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]]> sage: BD.dual_incidence_structure() Incidence structure with 7 points and 7 blocks REFERENCE: - Soicher, Leonard, Design package manual, available at http://www.gap-system.org/Manuals/pkg/design/htm/CHAP003.htm """ if algorithm == "gap": from sage.interfaces.gap import gap gap.load_package("design") gD = self._gap_() gap.eval("DD:=DualBlockDesign(" + gD + ")") v = eval(gap.eval("DD.v")) gblcks = eval(gap.eval("DD.blocks")) gB = [] for b in gblcks: gB.append([x - 1 for x in b]) return IncidenceStructure(range(v), gB, name=None, test=False) else: M = self.incidence_matrix() new_blocks = [list(r.dict(copy=False)) for r in M.rows()] return IncidenceStructure(range(M.ncols()), new_blocks, name=None, test=False)
def ProjectiveGeometryDesign(n, d, F, algorithm=None, point_coordinates=True, check=True): """ Return a projective geometry design. A projective geometry design of parameters `n,d,F` has for points the lines of `F^{n+1}`, and for blocks the `d+1`-dimensional subspaces of `F^{n+1}`, each of which contains `\\frac {|F|^{d+1}-1} {|F|-1}` lines. INPUT: - ``n`` is the projective dimension - ``d`` is the dimension of the subspaces of `P = PPn(F)` which make up the blocks. - ``F`` is a finite field. - ``algorithm`` -- set to ``None`` by default, which results in using Sage's own implementation. In order to use GAP's implementation instead (i.e. its ``PGPointFlatBlockDesign`` function) set ``algorithm="gap"``. Note that GAP's "design" package must be available in this case, and that it can be installed with the ``gap_packages`` spkg. - ``point_coordinates`` -- ``True`` by default. Ignored and assumed to be ``False`` if ``algorithm="gap"``. If ``True``, the ground set is indexed by coordinates in `F^{n+1}`. Otherwise the ground set is indexed by integers, EXAMPLES: The set of `d`-dimensional subspaces in a `n`-dimensional projective space forms `2`-designs (or balanced incomplete block designs):: sage: PG = designs.ProjectiveGeometryDesign(4,2,GF(2)) sage: PG Incidence structure with 31 points and 155 blocks sage: PG.is_t_design(return_parameters=True) (True, (2, 31, 7, 7)) sage: PG = designs.ProjectiveGeometryDesign(3,1,GF(4,'z')) sage: PG.is_t_design(return_parameters=True) (True, (2, 85, 5, 1)) Use coordinates:: sage: PG = designs.ProjectiveGeometryDesign(2,1,GF(3)) sage: PG.blocks()[0] [(1, 0, 0), (1, 0, 1), (1, 0, 2), (0, 0, 1)] Use indexing by integers:: sage: PG = designs.ProjectiveGeometryDesign(2,1,GF(3),point_coordinates=0) sage: PG.blocks()[0] [0, 1, 2, 12] Check that the constructor using gap also works:: sage: BD = designs.ProjectiveGeometryDesign(2, 1, GF(2), algorithm="gap") # optional - gap_packages (design package) sage: BD.is_t_design(return_parameters=True) # optional - gap_packages (design package) (True, (2, 7, 3, 1)) """ if algorithm is None: from sage.matrix.echelon_matrix import reduced_echelon_matrix_iterator from copy import copy points = {} points = {p:i for i,p in enumerate(reduced_echelon_matrix_iterator(F,1,n+1,copy=True,set_immutable=True))} blocks = [] for m1 in reduced_echelon_matrix_iterator(F,d+1,n+1,copy=False): b = [] for m2 in reduced_echelon_matrix_iterator(F,1,d+1,copy=False): m = m2*m1 m.echelonize() m.set_immutable() b.append(points[m]) blocks.append(b) B = BlockDesign(len(points), blocks, name="ProjectiveGeometryDesign", check=check) if point_coordinates: B.relabel({i:p[0] for p,i in points.iteritems()}) return B if algorithm == "gap": # Requires GAP's Design from sage.interfaces.gap import gap gap.load_package("design") gap.eval("D := PGPointFlatBlockDesign( %s, %s, %d )"%(n,F.order(),d)) v = eval(gap.eval("D.v")) gblcks = eval(gap.eval("D.blocks")) gB = [] for b in gblcks: gB.append([x-1 for x in b]) return BlockDesign(v, gB, name="ProjectiveGeometryDesign", check=check)