Example #1
0
def BIBD_from_PBD(PBD, v, k, check=True, base_cases={}):
    r"""
    Return a `(v,k,1)`-BIBD from a `(r,K)`-PBD where `r=(v-1)/(k-1)`.

    This is Theorem 7.20 from [Stinson2004]_.

    INPUT:

    - ``v,k`` -- integers.

    - ``PBD`` -- A PBD on `r=(v-1)/(k-1)` points, such that for any block of
      ``PBD`` of size `s` there must exist a `((k-1)s+1,k,1)`-BIBD.

    - ``check`` (boolean) -- whether to check that output is correct before
      returning it. As this is expected to be useless (but we are cautious
      guys), you may want to disable it whenever you want speed. Set to ``True``
      by default.

    - ``base_cases`` -- caching system, for internal use.

    EXAMPLES::

        sage: from sage.combinat.designs.bibd import PBD_4_5_8_9_12
        sage: from sage.combinat.designs.bibd import BIBD_from_PBD
        sage: from sage.combinat.designs.bibd import is_pairwise_balanced_design
        sage: PBD = PBD_4_5_8_9_12(17)
        sage: bibd = is_pairwise_balanced_design(BIBD_from_PBD(PBD,52,4),52,[4])
    """
    r = (v - 1) // (k - 1)
    bibd = []
    for X in PBD:
        n = len(X)
        N = (k - 1) * n + 1
        if not (n, k) in base_cases:
            base_cases[n, k] = _relabel_bibd(
                balanced_incomplete_block_design(N, k), N)

        for XX in base_cases[n, k]:
            if N - 1 in XX:
                continue
            bibd.append([X[x // (k - 1)] + (x % (k - 1)) * r for x in XX])

    for x in range(r):
        bibd.append([x + i * r for i in range(k - 1)] + [v - 1])

    if check:
        assert is_pairwise_balanced_design(bibd, v, [k])

    return bibd
Example #2
0
def BIBD_from_PBD(PBD,v,k,check=True,base_cases={}):
    r"""
    Return a `(v,k,1)`-BIBD from a `(r,K)`-PBD where `r=(v-1)/(k-1)`.

    This is Theorem 7.20 from [Stinson2004]_.

    INPUT:

    - ``v,k`` -- integers.

    - ``PBD`` -- A PBD on `r=(v-1)/(k-1)` points, such that for any block of
      ``PBD`` of size `s` there must exist a `((k-1)s+1,k,1)`-BIBD.

    - ``check`` (boolean) -- whether to check that output is correct before
      returning it. As this is expected to be useless (but we are cautious
      guys), you may want to disable it whenever you want speed. Set to ``True``
      by default.

    - ``base_cases`` -- caching system, for internal use.

    EXAMPLES::

        sage: from sage.combinat.designs.bibd import PBD_4_5_8_9_12
        sage: from sage.combinat.designs.bibd import BIBD_from_PBD
        sage: from sage.combinat.designs.bibd import is_pairwise_balanced_design
        sage: PBD = PBD_4_5_8_9_12(17)
        sage: bibd = is_pairwise_balanced_design(BIBD_from_PBD(PBD,52,4),52,[4])
    """
    r = (v-1) // (k-1)
    bibd = []
    for X in PBD:
        n = len(X)
        N = (k-1)*n+1
        if not (n,k) in base_cases:
            base_cases[n,k] = _relabel_bibd(balanced_incomplete_block_design(N,k), N)

        for XX in base_cases[n,k]:
            if N-1 in XX:
                continue
            bibd.append([X[x//(k-1)] + (x%(k-1))*r for x in XX])

    for x in range(r):
        bibd.append([x+i*r for i in range(k-1)]+[v-1])

    if check:
        assert is_pairwise_balanced_design(bibd,v,[k])

    return bibd
Example #3
0
def v_5_1_BIBD(v, check=True):
    r"""
    Return a `(v,5,1)`-BIBD.

    This method follows the constuction from [ClaytonSmith]_.

    INPUT:

    - ``v`` (integer)

    .. SEEALSO::

        * :func:`balanced_incomplete_block_design`

    EXAMPLES::

        sage: from sage.combinat.designs.bibd import v_5_1_BIBD
        sage: i = 0
        sage: while i<200:
        ....:    i += 20
        ....:    _ = v_5_1_BIBD(i+1)
        ....:    _ = v_5_1_BIBD(i+5)

    TESTS:

    Check that the needed difference families are there::

        sage: for v in [21,41,61,81,141,161,281]:
        ....:     assert designs.difference_family(v,5,existence=True)
        ....:     _ = designs.difference_family(v,5)
    """
    v = int(v)

    assert (v > 1)
    assert (v%20 == 5 or v%20 == 1)  # note: equivalent to (v-1)%4 == 0 and (v*(v-1))%20 == 0

    # Lemma 27
    if v%5 == 0 and (v//5)%4 == 1 and is_prime_power(v//5):
        bibd = BIBD_5q_5_for_q_prime_power(v//5)
    # Lemma 28
    elif v in [21,41,61,81,141,161,281]:
        from difference_family import difference_family
        G,D = difference_family(v,5)
        bibd = BIBD_from_difference_family(G, D, check=False)
    # Lemma 29
    elif v == 165:
        bibd = BIBD_from_PBD(v_5_1_BIBD(41,check=False),165,5,check=False)
    elif v == 181:
        bibd = BIBD_from_PBD(v_5_1_BIBD(45,check=False),181,5,check=False)
    elif v in (201,285,301,401,421,425):
        # Call directly the BIBD_from_TD function
        # note: there are (201,5,1) and (421,5)-difference families that can be
        # obtained from the general constructor
        bibd = BIBD_from_TD(v,5)
    # Theorem 31.2
    elif (v-1)//4 in [80, 81, 85, 86, 90, 91, 95, 96, 110, 111, 115, 116, 120, 121, 250, 251, 255, 256, 260, 261, 265, 266, 270, 271]:
        r = (v-1)//4
        if r <= 96:
            k,t,u = 5, 16, r-80
        elif r <= 121:
            k,t,u = 10, 11, r-110
        else:
            k,t,u = 10, 25, r-250
        bibd = BIBD_from_PBD(PBD_from_TD(k,t,u),v,5,check=False)

    else:
        r,s,t,u = _get_r_s_t_u(v)
        bibd = BIBD_from_PBD(PBD_from_TD(5,t,u),v,5,check=False)

    if check:
        assert is_pairwise_balanced_design(bibd,v,[5])

    return bibd
Example #4
0
def PBD_4_5_8_9_12(v, check=True):
    """
    Return a `(v,\{4,5,8,9,12\})`-PBD on `v` elements.

    A `(v,\{4,5,8,9,12\})`-PBD exists if and only if `v\equiv 0,1 \pmod 4`. The
    construction implemented here appears page 168 in [Stinson2004]_.

    INPUT:

    - ``v`` -- an integer congruent to `0` or `1` modulo `4`.

    - ``check`` (boolean) -- whether to check that output is correct before
      returning it. As this is expected to be useless (but we are cautious
      guys), you may want to disable it whenever you want speed. Set to ``True``
      by default.

    EXAMPLES::

        sage: designs.balanced_incomplete_block_design(40,4).blocks() # indirect doctest
        [[0, 1, 2, 12], [0, 3, 6, 9], [0, 4, 8, 10],
         [0, 5, 7, 11], [0, 13, 26, 39], [0, 14, 25, 28],
         [0, 15, 27, 38], [0, 16, 22, 32], [0, 17, 23, 34],
        ...

    Check that :trac:`16476` is fixed::

        sage: from sage.combinat.designs.bibd import PBD_4_5_8_9_12
        sage: for v in (0,1,4,5,8,9,12,13,16,17,20,21,24,25):
        ....:     _ = PBD_4_5_8_9_12(v)
    """
    if not v%4 in [0,1]:
        raise ValueError
    if v <= 1:
        PBD = []
    elif v <= 12:
        PBD = [range(v)]
    elif v == 13 or v == 28:
        PBD = v_4_1_BIBD(v, check=False)
    elif v == 29:
        TD47 = transversal_design(4,7)._blocks
        four_more_sets = [[28]+[i*7+j for j in range(7)] for i in range(4)]
        PBD = TD47 + four_more_sets
    elif v == 41:
        TD59 = transversal_design(5,9)
        PBD = ([[x for x in X if x<41] for X in TD59]
                +[[i*9+j for j in range(9)] for i in range(4)]
                +[[36,37,38,39,40]])
    elif v == 44:
        TD59 = transversal_design(5,9)
        PBD = ([[x for x in X if x<44] for X in TD59]
                +[[i*9+j for j in range(9)] for i in range(4)]
                +[[36,37,38,39,40,41,42,43]])
    elif v == 45:
        TD59 = transversal_design(5,9)._blocks
        PBD = (TD59+[[i*9+j for j in range(9)] for i in range(5)])
    elif v == 48:
        TD4_12 = transversal_design(4,12)._blocks
        PBD = (TD4_12+[[i*12+j for j in range(12)] for i in range(4)])
    elif v == 49:
        # Lemma 7.16 : A (49,{4,13})-PBD
        TD4_12 = transversal_design(4,12)._blocks

        # Replacing the block of size 13 with a BIBD
        BIBD_13_4 = v_4_1_BIBD(13)
        for i in range(4):
            for B in BIBD_13_4:
                TD4_12.append([i*12+x if x != 12 else 48
                               for x in B])

        PBD = TD4_12
    else:
        t,u = _get_t_u(v)
        TD = transversal_design(5,t)
        TD = [[x for x in X if x<4*t+u] for X in TD]
        for B in [range(t*i,t*(i+1)) for i in range(4)]:
            TD.extend(_PBD_4_5_8_9_12_closure([B]))

        if u > 1:
            TD.extend(_PBD_4_5_8_9_12_closure([range(4*t,4*t+u)]))

        PBD = TD

    if check:
        assert is_pairwise_balanced_design(PBD,v,[4,5,8,9,12])

    return PBD
Example #5
0
def v_4_1_BIBD(v, check=True):
    r"""
    Return a `(v,4,1)`-BIBD.

    A `(v,4,1)`-BIBD is an edge-decomposition of the complete graph `K_v` into
    copies of `K_4`. For more information, see
    :func:`balanced_incomplete_block_design`. It exists if and only if `v\equiv 1,4
    \pmod {12}`.

    See page 167 of [Stinson2004]_ for the construction details.

    .. SEEALSO::

        * :func:`balanced_incomplete_block_design`

    INPUT:

    - ``v`` (integer) -- number of points.

    - ``check`` (boolean) -- whether to check that output is correct before
      returning it. As this is expected to be useless (but we are cautious
      guys), you may want to disable it whenever you want speed. Set to ``True``
      by default.

    EXAMPLES::

        sage: from sage.combinat.designs.bibd import v_4_1_BIBD  # long time
        sage: for n in range(13,100):                            # long time
        ....:    if n%12 in [1,4]:                               # long time
        ....:       _ = v_4_1_BIBD(n, check = True)              # long time

    TESTS:

    Check that the `(25,4)` and `(37,4)`-difference family are available::

        sage: assert designs.difference_family(25,4,existence=True)
        sage: _ = designs.difference_family(25,4)
        sage: assert designs.difference_family(37,4,existence=True)
        sage: _ = designs.difference_family(37,4)

    Check some larger `(v,4,1)`-BIBD (see :trac:`17557`)::

        sage: for v in range(400):                                      # long time
        ....:     if v%12 in [1,4]:                                     # long time
        ....:         _ = designs.balanced_incomplete_block_design(v,4) # long time
    """
    k = 4
    if v == 0:
        return []
    if v <= 12 or v%12 not in [1,4]:
        raise EmptySetError("A K_4-decomposition of K_v exists iif v=2,4 mod 12, v>12 or v==0")

    # Step 1. Base cases.
    if v == 13:
        # note: this construction can also be obtained from difference_family
        from block_design import projective_plane
        return projective_plane(3)._blocks
    if v == 16:
        from block_design import AffineGeometryDesign
        from sage.rings.finite_rings.constructor import FiniteField
        return AffineGeometryDesign(2,1,FiniteField(4,'x'))._blocks
    if v == 25 or v == 37:
        from difference_family import difference_family
        G,D = difference_family(v,4)
        return BIBD_from_difference_family(G,D,check=False)
    if v == 28:
        return [[0, 1, 23, 26], [0, 2, 10, 11], [0, 3, 16, 18], [0, 4, 15, 20],
                [0, 5, 8, 9], [0, 6, 22, 25], [0, 7, 14, 21], [0, 12, 17, 27],
                [0, 13, 19, 24], [1, 2, 24, 27], [1, 3, 11, 12], [1, 4, 17, 19],
                [1, 5, 14, 16], [1, 6, 9, 10], [1, 7, 20, 25], [1, 8, 15, 22],
                [1, 13, 18, 21], [2, 3, 21, 25], [2, 4, 12, 13], [2, 5, 18, 20],
                [2, 6, 15, 17], [2, 7, 19, 22], [2, 8, 14, 26], [2, 9, 16, 23],
                [3, 4, 22, 26], [3, 5, 7, 13], [3, 6, 14, 19], [3, 8, 20, 23],
                [3, 9, 15, 27], [3, 10, 17, 24], [4, 5, 23, 27], [4, 6, 7, 8],
                [4, 9, 14, 24], [4, 10, 16, 21], [4, 11, 18, 25], [5, 6, 21, 24],
                [5, 10, 15, 25], [5, 11, 17, 22], [5, 12, 19, 26], [6, 11, 16, 26],
                [6, 12, 18, 23], [6, 13, 20, 27], [7, 9, 17, 18], [7, 10, 26, 27],
                [7, 11, 23, 24], [7, 12, 15, 16], [8, 10, 18, 19], [8, 11, 21, 27],
                [8, 12, 24, 25], [8, 13, 16, 17], [9, 11, 19, 20], [9, 12, 21, 22],
                [9, 13, 25, 26], [10, 12, 14, 20], [10, 13, 22, 23], [11, 13, 14, 15],
                [14, 17, 23, 25], [14, 18, 22, 27], [15, 18, 24, 26], [15, 19, 21, 23],
                [16, 19, 25, 27], [16, 20, 22, 24], [17, 20, 21, 26]]

    # Step 2 : this is function PBD_4_5_8_9_12
    PBD = PBD_4_5_8_9_12((v-1)/(k-1),check=False)

    # Step 3 : Theorem 7.20
    bibd = BIBD_from_PBD(PBD,v,k,check=False)

    if check:
        assert is_pairwise_balanced_design(bibd,v,[k])

    return bibd
Example #6
0
def BIBD_from_difference_family(G, D, lambd=None, check=True):
    r"""
    Return the BIBD associated to the difference family ``D`` on the group ``G``.

    Let `G` be a group. A `(G,k,\lambda)`-*difference family* is a family `B =
    \{B_1,B_2,\ldots,B_b\}` of `k`-subsets of `G` such that for each element of
    `G \backslash \{0\}` there exists exactly `\lambda` pairs of elements
    `(x,y)`, `x` and `y` belonging to the same block, such that `x - y = g` (or
    x y^{-1} = g` in multiplicative notation).

    If `\{B_1, B_2, \ldots, B_b\}` is a `(G,k,\lambda)`-difference family then
    its set of translates `\{B_i \cdot g; i \in \{1,\ldots,b\}, g \in G\}` is a
    `(v,k,\lambda)`-BIBD where `v` is the cardinality of `G`.

    INPUT:

    - ``G`` - a finite additive Abelian group

    - ``D`` - a difference family on ``G`` (short blocks are allowed).

    - ``lambd`` - the `\lambda` parameter (optional, only used if ``check`` is
      ``True``)

    - ``check`` - whether or not we check the output (default: ``True``)

    EXAMPLES::

        sage: G = Zmod(21)
        sage: D = [[0,1,4,14,16]]
        sage: print sorted(G(x-y) for x in D[0] for y in D[0] if x != y)
        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

        sage: from sage.combinat.designs.bibd import BIBD_from_difference_family
        sage: BIBD_from_difference_family(G, D)
        [[0, 1, 4, 14, 16],
         [1, 2, 5, 15, 17],
         [2, 3, 6, 16, 18],
         [3, 4, 7, 17, 19],
         [4, 5, 8, 18, 20],
         [5, 6, 9, 19, 0],
         [6, 7, 10, 20, 1],
         [7, 8, 11, 0, 2],
         [8, 9, 12, 1, 3],
         [9, 10, 13, 2, 4],
         [10, 11, 14, 3, 5],
         [11, 12, 15, 4, 6],
         [12, 13, 16, 5, 7],
         [13, 14, 17, 6, 8],
         [14, 15, 18, 7, 9],
         [15, 16, 19, 8, 10],
         [16, 17, 20, 9, 11],
         [17, 18, 0, 10, 12],
         [18, 19, 1, 11, 13],
         [19, 20, 2, 12, 14],
         [20, 0, 3, 13, 15]]
    """
    from difference_family import group_law, block_stabilizer
    identity, mul, inv = group_law(G)
    bibd = []
    Gset = set(G)
    p_to_i = {g:i for i,g in enumerate(Gset)}
    for b in D:
        b = [G(_) for _ in b]
        S = block_stabilizer(G,b)
        GG = Gset.copy()
        while GG:
            g = GG.pop()
            if S: GG.difference_update(mul(s,g) for s in S)
            bibd.append([p_to_i[mul(i,g)] for i in b])

    if check:
        if lambd is None:
            k = len(bibd[0])
            v = G.cardinality()
            lambd = (len(bibd) * k * (k-1)) // (v * (v-1))
        assert is_pairwise_balanced_design(bibd, G.cardinality(), [len(D[0])], lambd=lambd)

    return bibd
Example #7
0
def PBD_4_5_8_9_12(v, check=True):
    """
    Return a `(v,\{4,5,8,9,12\})`-PBD on `v` elements.

    A `(v,\{4,5,8,9,12\})`-PBD exists if and only if `v\equiv 0,1 \pmod 4`. The
    construction implemented here appears page 168 in [Stinson2004]_.

    INPUT:

    - ``v`` -- an integer congruent to `0` or `1` modulo `4`.

    - ``check`` (boolean) -- whether to check that output is correct before
      returning it. As this is expected to be useless (but we are cautious
      guys), you may want to disable it whenever you want speed. Set to ``True``
      by default.

    EXAMPLES::

        sage: designs.balanced_incomplete_block_design(40,4).blocks() # indirect doctest
        [[0, 1, 2, 12], [0, 3, 6, 9], [0, 4, 8, 10],
         [0, 5, 7, 11], [0, 13, 26, 39], [0, 14, 25, 28],
         [0, 15, 27, 38], [0, 16, 22, 32], [0, 17, 23, 34],
        ...

    Check that :trac:`16476` is fixed::

        sage: from sage.combinat.designs.bibd import PBD_4_5_8_9_12
        sage: for v in (0,1,4,5,8,9,12,13,16,17,20,21,24,25):
        ....:     _ = PBD_4_5_8_9_12(v)
    """
    if not v % 4 in [0, 1]:
        raise ValueError
    if v <= 1:
        PBD = []
    elif v <= 12:
        PBD = [range(v)]
    elif v == 13 or v == 28:
        PBD = v_4_1_BIBD(v, check=False)
    elif v == 29:
        TD47 = transversal_design(4, 7)._blocks
        four_more_sets = [[28] + [i * 7 + j for j in range(7)]
                          for i in range(4)]
        PBD = TD47 + four_more_sets
    elif v == 41:
        TD59 = transversal_design(5, 9)
        PBD = ([[x for x in X if x < 41]
                for X in TD59] + [[i * 9 + j for j in range(9)]
                                  for i in range(4)] + [[36, 37, 38, 39, 40]])
    elif v == 44:
        TD59 = transversal_design(5, 9)
        PBD = ([[x for x in X if x < 44] for X in TD59] +
               [[i * 9 + j for j in range(9)]
                for i in range(4)] + [[36, 37, 38, 39, 40, 41, 42, 43]])
    elif v == 45:
        TD59 = transversal_design(5, 9)._blocks
        PBD = (TD59 + [[i * 9 + j for j in range(9)] for i in range(5)])
    elif v == 48:
        TD4_12 = transversal_design(4, 12)._blocks
        PBD = (TD4_12 + [[i * 12 + j for j in range(12)] for i in range(4)])
    elif v == 49:
        # Lemma 7.16 : A (49,{4,13})-PBD
        TD4_12 = transversal_design(4, 12)._blocks

        # Replacing the block of size 13 with a BIBD
        BIBD_13_4 = v_4_1_BIBD(13)
        for i in range(4):
            for B in BIBD_13_4:
                TD4_12.append([i * 12 + x if x != 12 else 48 for x in B])

        PBD = TD4_12
    else:
        t, u = _get_t_u(v)
        TD = transversal_design(5, t)
        TD = [[x for x in X if x < 4 * t + u] for X in TD]
        for B in [range(t * i, t * (i + 1)) for i in range(4)]:
            TD.extend(_PBD_4_5_8_9_12_closure([B]))

        if u > 1:
            TD.extend(_PBD_4_5_8_9_12_closure([range(4 * t, 4 * t + u)]))

        PBD = TD

    if check:
        assert is_pairwise_balanced_design(PBD, v, [4, 5, 8, 9, 12])

    return PBD
Example #8
0
def v_4_1_BIBD(v, check=True):
    r"""
    Return a `(v,4,1)`-BIBD.

    A `(v,4,1)`-BIBD is an edge-decomposition of the complete graph `K_v` into
    copies of `K_4`. For more information, see
    :func:`balanced_incomplete_block_design`. It exists if and only if `v\equiv 1,4
    \pmod {12}`.

    See page 167 of [Stinson2004]_ for the construction details.

    .. SEEALSO::

        * :func:`balanced_incomplete_block_design`

    INPUT:

    - ``v`` (integer) -- number of points.

    - ``check`` (boolean) -- whether to check that output is correct before
      returning it. As this is expected to be useless (but we are cautious
      guys), you may want to disable it whenever you want speed. Set to ``True``
      by default.

    EXAMPLES::

        sage: from sage.combinat.designs.bibd import v_4_1_BIBD  # long time
        sage: for n in range(13,100):                            # long time
        ....:    if n%12 in [1,4]:                               # long time
        ....:       _ = v_4_1_BIBD(n, check = True)              # long time

    TESTS:

    Check that the `(25,4)` and `(37,4)`-difference family are available::

        sage: assert designs.difference_family(25,4,existence=True)
        sage: _ = designs.difference_family(25,4)
        sage: assert designs.difference_family(37,4,existence=True)
        sage: _ = designs.difference_family(37,4)

    Check some larger `(v,4,1)`-BIBD (see :trac:`17557`)::

        sage: for v in range(400):                                      # long time
        ....:     if v%12 in [1,4]:                                     # long time
        ....:         _ = designs.balanced_incomplete_block_design(v,4) # long time
    """
    k = 4
    if v == 0:
        return []
    if v <= 12 or v % 12 not in [1, 4]:
        raise EmptySetError(
            "A K_4-decomposition of K_v exists iif v=2,4 mod 12, v>12 or v==0")

    # Step 1. Base cases.
    if v == 13:
        # note: this construction can also be obtained from difference_family
        from block_design import projective_plane
        return projective_plane(3)._blocks
    if v == 16:
        from block_design import AffineGeometryDesign
        from sage.rings.finite_rings.constructor import FiniteField
        return AffineGeometryDesign(2, 1, FiniteField(4, 'x'))._blocks
    if v == 25 or v == 37:
        from difference_family import difference_family
        G, D = difference_family(v, 4)
        return BIBD_from_difference_family(G, D, check=False)
    if v == 28:
        return [[0, 1, 23, 26], [0, 2, 10, 11], [0, 3, 16, 18], [0, 4, 15, 20],
                [0, 5, 8, 9], [0, 6, 22, 25], [0, 7, 14, 21], [0, 12, 17, 27],
                [0, 13, 19, 24],
                [1, 2, 24, 27], [1, 3, 11, 12], [1, 4, 17, 19], [1, 5, 14, 16],
                [1, 6, 9, 10], [1, 7, 20, 25], [1, 8, 15, 22], [1, 13, 18, 21],
                [2, 3, 21, 25], [2, 4, 12, 13], [2, 5, 18, 20], [2, 6, 15, 17],
                [2, 7, 19, 22], [2, 8, 14, 26], [2, 9, 16, 23], [3, 4, 22, 26],
                [3, 5, 7, 13], [3, 6, 14, 19], [3, 8, 20, 23], [3, 9, 15, 27],
                [3, 10, 17, 24], [4, 5, 23, 27], [4, 6, 7, 8], [4, 9, 14, 24],
                [4, 10, 16, 21], [4, 11, 18, 25], [5, 6, 21, 24],
                [5, 10, 15, 25], [5, 11, 17, 22], [5, 12, 19, 26],
                [6, 11, 16, 26], [6, 12, 18, 23], [6, 13, 20, 27],
                [7, 9, 17, 18], [7, 10, 26, 27], [7, 11, 23, 24],
                [7, 12, 15, 16], [8, 10, 18, 19], [8, 11, 21, 27],
                [8, 12, 24, 25], [8, 13, 16, 17], [9, 11, 19, 20],
                [9, 12, 21, 22], [9, 13, 25, 26], [10, 12, 14, 20],
                [10, 13, 22, 23], [11, 13, 14, 15], [14, 17, 23, 25],
                [14, 18, 22, 27], [15, 18, 24, 26], [15, 19, 21, 23],
                [16, 19, 25, 27], [16, 20, 22, 24], [17, 20, 21, 26]]

    # Step 2 : this is function PBD_4_5_8_9_12
    PBD = PBD_4_5_8_9_12((v - 1) / (k - 1), check=False)

    # Step 3 : Theorem 7.20
    bibd = BIBD_from_PBD(PBD, v, k, check=False)

    if check:
        assert is_pairwise_balanced_design(bibd, v, [k])

    return bibd
Example #9
0
def BIBD_from_difference_family(G, D, lambd=None, check=True):
    r"""
    Return the BIBD associated to the difference family ``D`` on the group ``G``.

    Let `G` be a group. A `(G,k,\lambda)`-*difference family* is a family `B =
    \{B_1,B_2,\ldots,B_b\}` of `k`-subsets of `G` such that for each element of
    `G \backslash \{0\}` there exists exactly `\lambda` pairs of elements
    `(x,y)`, `x` and `y` belonging to the same block, such that `x - y = g` (or
    x y^{-1} = g` in multiplicative notation).

    If `\{B_1, B_2, \ldots, B_b\}` is a `(G,k,\lambda)`-difference family then
    its set of translates `\{B_i \cdot g; i \in \{1,\ldots,b\}, g \in G\}` is a
    `(v,k,\lambda)`-BIBD where `v` is the cardinality of `G`.

    INPUT::

    - ``G`` - a finite additive Abelian group

    - ``D`` - a difference family on ``G`` (short blocks are allowed).

    - ``lambd`` - the `\lambda` parameter (optional, only used if ``check`` is
      ``True``)

    - ``check`` - whether or not we check the output (default: ``True``)

    EXAMPLES::

        sage: G = Zmod(21)
        sage: D = [[0,1,4,14,16]]
        sage: print sorted(G(x-y) for x in D[0] for y in D[0] if x != y)
        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

        sage: from sage.combinat.designs.bibd import BIBD_from_difference_family
        sage: BIBD_from_difference_family(G, D)
        [[0, 1, 4, 14, 16],
         [1, 2, 5, 15, 17],
         [2, 3, 6, 16, 18],
         [3, 4, 7, 17, 19],
         [4, 5, 8, 18, 20],
         [5, 6, 9, 19, 0],
         [6, 7, 10, 20, 1],
         [7, 8, 11, 0, 2],
         [8, 9, 12, 1, 3],
         [9, 10, 13, 2, 4],
         [10, 11, 14, 3, 5],
         [11, 12, 15, 4, 6],
         [12, 13, 16, 5, 7],
         [13, 14, 17, 6, 8],
         [14, 15, 18, 7, 9],
         [15, 16, 19, 8, 10],
         [16, 17, 20, 9, 11],
         [17, 18, 0, 10, 12],
         [18, 19, 1, 11, 13],
         [19, 20, 2, 12, 14],
         [20, 0, 3, 13, 15]]
    """
    from difference_family import group_law, block_stabilizer
    identity, mul, inv = group_law(G)
    bibd = []
    Gset = set(G)
    p_to_i = {g: i for i, g in enumerate(Gset)}
    for b in D:
        b = map(G, b)
        S = block_stabilizer(G, b)
        GG = Gset.copy()
        while GG:
            g = GG.pop()
            if S: GG.difference_update(mul(s, g) for s in S)
            bibd.append([p_to_i[mul(i, g)] for i in b])

    if check:
        if lambd is None:
            k = len(bibd[0])
            v = G.cardinality()
            lambd = (len(bibd) * k * (k - 1)) // (v * (v - 1))
        assert is_pairwise_balanced_design(bibd,
                                           G.cardinality(), [len(D[0])],
                                           lambd=lambd)

    return bibd
Example #10
0
def v_5_1_BIBD(v, check=True):
    r"""
    Return a `(v,5,1)`-BIBD.

    This method follows the constuction from [ClaytonSmith]_.

    INPUT:

    - ``v`` (integer)

    .. SEEALSO::

        * :func:`balanced_incomplete_block_design`

    EXAMPLES::

        sage: from sage.combinat.designs.bibd import v_5_1_BIBD
        sage: i = 0
        sage: while i<200:
        ....:    i += 20
        ....:    _ = v_5_1_BIBD(i+1)
        ....:    _ = v_5_1_BIBD(i+5)

    TESTS:

    Check that the needed difference families are there::

        sage: for v in [21,41,61,81,141,161,281]:
        ....:     assert designs.difference_family(v,5,existence=True)
        ....:     _ = designs.difference_family(v,5)
    """
    v = int(v)

    assert (v > 1)
    assert (v % 20 == 5 or v % 20 == 1
            )  # note: equivalent to (v-1)%4 == 0 and (v*(v-1))%20 == 0

    # Lemma 27
    if v % 5 == 0 and (v // 5) % 4 == 1 and is_prime_power(v // 5):
        bibd = BIBD_5q_5_for_q_prime_power(v // 5)
    # Lemma 28
    elif v in [21, 41, 61, 81, 141, 161, 281]:
        from difference_family import difference_family
        G, D = difference_family(v, 5)
        bibd = BIBD_from_difference_family(G, D, check=False)
    # Lemma 29
    elif v == 165:
        bibd = BIBD_from_PBD(v_5_1_BIBD(41, check=False), 165, 5, check=False)
    elif v == 181:
        bibd = BIBD_from_PBD(v_5_1_BIBD(45, check=False), 181, 5, check=False)
    elif v in (201, 285, 301, 401, 421, 425):
        # Call directly the BIBD_from_TD function
        # note: there are (201,5,1) and (421,5)-difference families that can be
        # obtained from the general constructor
        bibd = BIBD_from_TD(v, 5)
    # Theorem 31.2
    elif (v - 1) // 4 in [
            80, 81, 85, 86, 90, 91, 95, 96, 110, 111, 115, 116, 120, 121, 250,
            251, 255, 256, 260, 261, 265, 266, 270, 271
    ]:
        r = (v - 1) // 4
        if r <= 96:
            k, t, u = 5, 16, r - 80
        elif r <= 121:
            k, t, u = 10, 11, r - 110
        else:
            k, t, u = 10, 25, r - 250
        bibd = BIBD_from_PBD(PBD_from_TD(k, t, u), v, 5, check=False)

    else:
        r, s, t, u = _get_r_s_t_u(v)
        bibd = BIBD_from_PBD(PBD_from_TD(5, t, u), v, 5, check=False)

    if check:
        assert is_pairwise_balanced_design(bibd, v, [5])

    return bibd