Esempio n. 1
0
def PBD_from_TD(k,t,u):
    r"""
    Return a `(kt,\{k,t\})`-PBD if `u=0` and a `(kt+u,\{k,k+1,t,u\})`-PBD otherwise.

    This is theorem 23 from [ClaytonSmith]_. The PBD is obtained from the blocks
    a truncated `TD(k+1,t)`, to which are added the blocks corresponding to the
    groups of the TD. When `u=0`, a `TD(k,t)` is used instead.

    INPUT:

    - ``k,t,u`` -- integers such that `0\leq u \leq t`.

    EXAMPLES::

        sage: from sage.combinat.designs.bibd import PBD_from_TD
        sage: from sage.combinat.designs.bibd import is_pairwise_balanced_design
        sage: PBD = PBD_from_TD(2,2,1); PBD
        [[0, 2, 4], [0, 3], [1, 2], [1, 3, 4], [0, 1], [2, 3]]
        sage: is_pairwise_balanced_design(PBD,2*2+1,[2,3])
        True

    """
    from orthogonal_arrays import transversal_design
    TD = transversal_design(k+bool(u),t, check=False)
    TD = [[x for x in X if x<k*t+u] for X in TD]
    for i in range(k):
        TD.append(range(t*i,t*i+t))
    if u>=2:
        TD.append(range(k*t,k*t+u))
    return TD
Esempio n. 2
0
def PBD_from_TD(k, t, u):
    r"""
    Return a `(kt,\{k,t\})`-PBD if `u=0` and a `(kt+u,\{k,k+1,t,u\})`-PBD otherwise.

    This is theorem 23 from [ClaytonSmith]_. The PBD is obtained from the blocks
    a truncated `TD(k+1,t)`, to which are added the blocks corresponding to the
    groups of the TD. When `u=0`, a `TD(k,t)` is used instead.

    INPUT:

    - ``k,t,u`` -- integers such that `0\leq u \leq t`.

    EXAMPLES::

        sage: from sage.combinat.designs.bibd import PBD_from_TD
        sage: from sage.combinat.designs.bibd import is_pairwise_balanced_design
        sage: PBD = PBD_from_TD(2,2,1); PBD
        [[0, 2, 4], [0, 3], [1, 2], [1, 3, 4], [0, 1], [2, 3]]
        sage: is_pairwise_balanced_design(PBD,2*2+1,[2,3])
        True

    """
    from orthogonal_arrays import transversal_design
    TD = transversal_design(k + bool(u), t, check=False)
    TD = [[x for x in X if x < k * t + u] for X in TD]
    for i in range(k):
        TD.append(range(t * i, t * i + t))
    if u >= 2:
        TD.append(range(k * t, k * t + u))
    return TD
Esempio n. 3
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
Esempio n. 4
0
def BIBD_from_TD(v,k,existence=False):
    r"""
    Return a BIBD through TD-based constructions.

    INPUT:

    - ``v,k`` (integers) -- computes a `(v,k,1)`-BIBD.

    - ``existence`` (boolean) -- instead of building the design, return:

        - ``True`` -- meaning that Sage knows how to build the design

        - ``Unknown`` -- meaning that Sage does not know how to build the
          design, but that the design may exist (see :mod:`sage.misc.unknown`).

        - ``False`` -- meaning that the design does not exist.

    This method implements three constructions:

    - If there exists a `TD(k,v)` and a `(v,k,1)`-BIBD then there exists a
      `(kv,k,1)`-BIBD.

      The BIBD is obtained from all blocks of the `TD`, and from the blocks of
      the `(v,k,1)`-BIBDs defined over the `k` groups of the `TD`.

    - If there exists a `TD(k,v)` and a `(v+1,k,1)`-BIBD then there exists a
      `(kv+1,k,1)`-BIBD.

      The BIBD is obtained from all blocks of the `TD`, and from the blocks of
      the `(v+1,k,1)`-BIBDs defined over the sets `V_1\cup \infty,\dots,V_k\cup
      \infty` where the `V_1,\dots,V_k` are the groups of the TD.

    - If there exists a `TD(k,v)` and a `(v+k,k,1)`-BIBD then there exists a
      `(kv+k,k,1)`-BIBD.

      The BIBD is obtained from all blocks of the `TD`, and from the blocks of
      the `(v+k,k,1)`-BIBDs defined over the sets `V_1\cup
      \{\infty_1,\dots,\infty_k\},\dots,V_k\cup \{\infty_1,\dots,\infty_k\}`
      where the `V_1,\dots,V_k` are the groups of the TD. By making sure that
      all copies of the `(v+k,k,1)`-BIBD contain the block
      `\{\infty_1,\dots,\infty_k\}`, the result is also a BIBD.

    These constructions can be found in
    `<http://www.argilo.net/files/bibd.pdf>`_.

    EXAMPLES:

    First construction::

        sage: from sage.combinat.designs.bibd import BIBD_from_TD
        sage: BIBD_from_TD(25,5,existence=True)
        True
        sage: _ = BlockDesign(25,BIBD_from_TD(25,5))

    Second construction::

        sage: from sage.combinat.designs.bibd import BIBD_from_TD
        sage: BIBD_from_TD(21,5,existence=True)
        True
        sage: _ = BlockDesign(21,BIBD_from_TD(21,5))

    Third construction::

        sage: from sage.combinat.designs.bibd import BIBD_from_TD
        sage: BIBD_from_TD(85,5,existence=True)
        True
        sage: _ = BlockDesign(85,BIBD_from_TD(85,5))

    No idea::

        sage: from sage.combinat.designs.bibd import BIBD_from_TD
        sage: BIBD_from_TD(20,5,existence=True)
        Unknown
        sage: BIBD_from_TD(20,5)
        Traceback (most recent call last):
        ...
        NotImplementedError: I do not know how to build a (20,5,1)-BIBD!
    """
    # First construction
    if (v%k == 0 and
        balanced_incomplete_block_design(v//k,k,existence=True) and
        transversal_design(k,v//k,existence=True)):

        if existence:
            return True

        v = v//k
        BIBDvk = balanced_incomplete_block_design(v,k)._blocks
        TDkv = transversal_design(k,v,check=False)

        BIBD = TDkv._blocks
        for i in range(k):
            BIBD.extend([[x+i*v for x in B] for B in BIBDvk])

    # Second construction
    elif ((v-1)%k == 0 and
        balanced_incomplete_block_design((v-1)//k+1,k,existence=True) and
        transversal_design(k,(v-1)//k,existence=True)):

        if existence:
            return True

        v = (v-1)//k
        BIBDv1k = balanced_incomplete_block_design(v+1,k)._blocks
        TDkv = transversal_design(k,v,check=False)._blocks

        inf = v*k
        BIBD = TDkv
        for i in range(k):
            BIBD.extend([[inf if x == v else x+i*v for x in B] for B in BIBDv1k])

    # Third construction
    elif ((v-k)%k == 0 and
        balanced_incomplete_block_design((v-k)//k+k,k,existence=True) and
        transversal_design(k,(v-k)//k,existence=True)):

        if existence:
            return True

        v = (v-k)//k
        BIBDvpkk = balanced_incomplete_block_design(v+k,k)
        TDkv = transversal_design(k,v,check=False)._blocks
        inf = v*k
        BIBD = TDkv

        # makes sure that [v,...,v+k-1] is a block of BIBDvpkk. Then, we remove it.
        BIBDvpkk = _relabel_bibd(BIBDvpkk,v+k)
        BIBDvpkk = [B for B in BIBDvpkk if min(B) < v]

        for i in range(k):
            BIBD.extend([[(x-v)+inf if x >= v else x+i*v for x in B] for B in BIBDvpkk])

        BIBD.append(range(k*v,v*k+k))

    # No idea ...
    else:
        if existence:
            return Unknown
        else:
            raise NotImplementedError("I do not know how to build a ({},{},1)-BIBD!".format(v,k))

    return BIBD
Esempio n. 5
0
def PBD_4_5_8_9_12(v, check=True):
    """
    Returns 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`` (integer)

    - ``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.BalancedIncompleteBlockDesign(40,4).blocks() # indirect doctest
        [[0, 1, 2, 12], [0, 3, 6, 9], [0, 4, 8, 11], [0, 5, 7, 10],
         [0, 13, 26, 39], [0, 14, 28, 38], [0, 15, 25, 27],
         [0, 16, 32, 35], [0, 17, 34, 37], [0, 18, 33, 36],
        ...
    """
    if not v % 4 in [0, 1]:
        raise ValueError
    if v == 0:
        return []
    if v == 13:
        PBD = v_4_1_BIBD(v, check=False)
    elif v == 28:
        PBD = v_4_1_BIBD(v, check=False)
    elif v == 29:
        TD47 = transversal_design(4, 7)
        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)
        PBD = (TD59 + [[i * 9 + j for j in range(9)] for i in range(5)])
    elif v == 48:
        TD4_12 = transversal_design(4, 12)
        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)

        # 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:
        _check_pbd(PBD, v, [4, 5, 8, 9, 12])

    return PBD
Esempio n. 6
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
Esempio n. 7
0
def BIBD_from_TD(v, k, existence=False):
    r"""
    Return a BIBD through TD-based constructions.

    INPUT:

    - ``v,k`` (integers) -- computes a `(v,k,1)`-BIBD.

    - ``existence`` (boolean) -- instead of building the design, return:

        - ``True`` -- meaning that Sage knows how to build the design

        - ``Unknown`` -- meaning that Sage does not know how to build the
          design, but that the design may exist (see :mod:`sage.misc.unknown`).

        - ``False`` -- meaning that the design does not exist.

    This method implements three constructions:

    - If there exists a `TD(k,v)` and a `(v,k,1)`-BIBD then there exists a
      `(kv,k,1)`-BIBD.

      The BIBD is obtained from all blocks of the `TD`, and from the blocks of
      the `(v,k,1)`-BIBDs defined over the `k` groups of the `TD`.

    - If there exists a `TD(k,v)` and a `(v+1,k,1)`-BIBD then there exists a
      `(kv+1,k,1)`-BIBD.

      The BIBD is obtained from all blocks of the `TD`, and from the blocks of
      the `(v+1,k,1)`-BIBDs defined over the sets `V_1\cup \infty,\dots,V_k\cup
      \infty` where the `V_1,\dots,V_k` are the groups of the TD.

    - If there exists a `TD(k,v)` and a `(v+k,k,1)`-BIBD then there exists a
      `(kv+k,k,1)`-BIBD.

      The BIBD is obtained from all blocks of the `TD`, and from the blocks of
      the `(v+k,k,1)`-BIBDs defined over the sets `V_1\cup
      \{\infty_1,\dots,\infty_k\},\dots,V_k\cup \{\infty_1,\dots,\infty_k\}`
      where the `V_1,\dots,V_k` are the groups of the TD. By making sure that
      all copies of the `(v+k,k,1)`-BIBD contain the block
      `\{\infty_1,\dots,\infty_k\}`, the result is also a BIBD.

    These constructions can be found in
    `<http://www.argilo.net/files/bibd.pdf>`_.

    EXAMPLES:

    First construction::

        sage: from sage.combinat.designs.bibd import BIBD_from_TD
        sage: BIBD_from_TD(25,5,existence=True)
        True
        sage: _ = designs.BlockDesign(25,BIBD_from_TD(25,5))

    Second construction::

        sage: from sage.combinat.designs.bibd import BIBD_from_TD
        sage: BIBD_from_TD(21,5,existence=True)
        True
        sage: _ = designs.BlockDesign(21,BIBD_from_TD(21,5))

    Third construction::

        sage: from sage.combinat.designs.bibd import BIBD_from_TD
        sage: BIBD_from_TD(85,5,existence=True)
        True
        sage: _ = designs.BlockDesign(85,BIBD_from_TD(85,5))

    No idea::

        sage: from sage.combinat.designs.bibd import BIBD_from_TD
        sage: BIBD_from_TD(20,5,existence=True)
        Unknown
        sage: BIBD_from_TD(20,5)
        Traceback (most recent call last):
        ...
        NotImplementedError: I do not know how to build a (20,5,1)-BIBD!
    """
    # First construction
    if (v % k == 0
            and balanced_incomplete_block_design(v // k, k, existence=True)
            and transversal_design(k, v // k, existence=True)):

        if existence:
            return True

        v = v // k
        BIBDvk = balanced_incomplete_block_design(v, k)._blocks
        TDkv = transversal_design(k, v, check=False)

        BIBD = TDkv._blocks
        for i in range(k):
            BIBD.extend([[x + i * v for x in B] for B in BIBDvk])

    # Second construction
    elif ((v - 1) % k == 0 and balanced_incomplete_block_design(
        (v - 1) // k + 1, k, existence=True)
          and transversal_design(k, (v - 1) // k, existence=True)):

        if existence:
            return True

        v = (v - 1) // k
        BIBDv1k = balanced_incomplete_block_design(v + 1, k)._blocks
        TDkv = transversal_design(k, v, check=False)._blocks

        inf = v * k
        BIBD = TDkv
        for i in range(k):
            BIBD.extend([[inf if x == v else x + i * v for x in B]
                         for B in BIBDv1k])

    # Third construction
    elif ((v - k) % k == 0 and balanced_incomplete_block_design(
        (v - k) // k + k, k, existence=True)
          and transversal_design(k, (v - k) // k, existence=True)):

        if existence:
            return True

        v = (v - k) // k
        BIBDvpkk = balanced_incomplete_block_design(v + k, k)
        TDkv = transversal_design(k, v, check=False)._blocks
        inf = v * k
        BIBD = TDkv

        # makes sure that [v,...,v+k-1] is a block of BIBDvpkk. Then, we remove it.
        BIBDvpkk = _relabel_bibd(BIBDvpkk, v + k)
        BIBDvpkk = [B for B in BIBDvpkk if min(B) < v]

        for i in range(k):
            BIBD.extend([[(x - v) + inf if x >= v else x + i * v for x in B]
                         for B in BIBDvpkk])

        BIBD.append(range(k * v, v * k + k))

    # No idea ...
    else:
        if existence:
            return Unknown
        else:
            raise NotImplementedError(
                "I do not know how to build a ({},{},1)-BIBD!".format(v, k))

    return BIBD
Esempio n. 8
0
def PBD_4_5_8_9_12(v, check=True):
    """
    Returns 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`` (integer)

    - ``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.BalancedIncompleteBlockDesign(40,4).blocks() # indirect doctest
        [[0, 1, 2, 12], [0, 3, 6, 9], [0, 4, 8, 11], [0, 5, 7, 10],
         [0, 13, 26, 39], [0, 14, 28, 38], [0, 15, 25, 27],
         [0, 16, 32, 35], [0, 17, 34, 37], [0, 18, 33, 36],
        ...
    """
    if not v%4 in [0,1]:
        raise ValueError
    if v == 0:
        return []
    if v == 13:
        PBD = v_4_1_BIBD(v, check=False)
    elif v == 28:
        PBD = v_4_1_BIBD(v, check=False)
    elif v == 29:
        TD47 = transversal_design(4,7)
        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)
        PBD = (TD59+[[i*9+j for j in range(9)] for i in range(5)])
    elif v == 48:
        TD4_12 = transversal_design(4,12)
        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)

        # 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:
        _check_pbd(PBD,v,[4,5,8,9,12])

    return PBD