Beispiel #1
0
def is_represented_by_unit(a,c,p):
    #we can forget about powers of p, because they are units; then we can work with integers
    a, c, p = ZZ(a), ZZ(c), ZZ(p)
    vala = ZZ(0)
    valc = ZZ(0)
    while a % p == 0:
        vala += 1
        a = ZZ(a / p)
    while c % p == 0:
        valc += 1
        c = ZZ(c/p)
    aa = a.abs()
    # verbose('is_rep_by_unit aa=%s, cc=%s'%(aa,cc_mod_aa))
    G = Zmod(aa)
    cc = G(c)
    Gp = G(p)
    res = []
    sizeG = G.unit_group_order()
    expn = G.unit_group_exponent()
    # verbose('Group of order=%s'%sizeG)
    try:
        n0 = discrete_log(cc,Gp,sizeG,operation = '*')
        n0 = n0 % expn
        if n0 > expn/2:
            n0 -= expn
        res.append( p**ZZ(n0 + valc) )
    except (ValueError,RuntimeError): pass
    try:
        n0 = discrete_log(cc,-Gp,sizeG,operation = '*')
        n0 = n0 % expn
        if n0 > expn/2:
            n0 -= expn
        res.append( ZZ(-1)**n0 * p**ZZ(n0 + valc) )
    except (ValueError,RuntimeError): pass
    return res
Beispiel #2
0
    def log(self, base):
        """
        Return `x` such that `b^x = a`, where `x`
        is `a` and `b` is the base.
        
        INPUT:
        
        
        -  ``self`` - finite field element
        
        -  ``b`` - finite field element that generates the
           multiplicative group.
        
        
        OUTPUT: Integer `x` such that `a^x = b`, if it
        exists. Raises a ValueError exception if no such `x`
        exists.
        
        EXAMPLES::
        
            sage: F = GF(17)
            sage: F(3^11).log(F(3))
            11
            sage: F = GF(113)
            sage: F(3^19).log(F(3))
            19
            sage: F = GF(next_prime(10000))
            sage: F(23^997).log(F(23))
            997
        
        ::
        
            sage: F = FiniteField(2^10, 'a')
            sage: g = F.gen()
            sage: b = g; a = g^37
            sage: a.log(b)
            37
            sage: b^37; a
            a^8 + a^7 + a^4 + a + 1
            a^8 + a^7 + a^4 + a + 1
        
        AUTHORS:

        - David Joyner and William Stein (2005-11)
        """
        from  sage.groups.generic import discrete_log
        
        b = self.parent()(base)
        # TODO: This function is TERRIBLE!
        return discrete_log(self, b)
Beispiel #3
0
    def log(self, base):
        """
        Return `x` such that `b^x = a`, where `x`
        is `a` and `b` is the base.

        INPUT:

        -  ``b`` -- finite field element that generates the
           multiplicative group.

        OUTPUT:

        Integer `x` such that `a^x = b`, if it exists. Raises a
        ``ValueError`` exception if no such `x` exists.

        EXAMPLES::

            sage: F = GF(17)
            sage: F(3^11).log(F(3))
            11
            sage: F = GF(113)
            sage: F(3^19).log(F(3))
            19
            sage: F = GF(next_prime(10000))
            sage: F(23^997).log(F(23))
            997

        ::

            sage: F = FiniteField(2^10, 'a', impl='pari_mod')
            sage: g = F.gen()
            sage: b = g; a = g^37
            sage: a.log(b)
            37
            sage: b^37; a
            a^8 + a^7 + a^4 + a + 1
            a^8 + a^7 + a^4 + a + 1

        AUTHORS:

        - David Joyner and William Stein (2005-11)
        """
        from  sage.groups.generic import discrete_log

        b = self.parent()(base)
        # TODO: This function is TERRIBLE!
        return discrete_log(self, b)
Beispiel #4
0
def kirkman_triple_system(v,existence=False):
    r"""
    Return a Kirkman Triple System on `v` points.

    A Kirkman Triple System `KTS(v)` is a resolvable Steiner Triple System. It
    exists if and only if `v\equiv 3\pmod{6}`.

    INPUT:

    - `n` (integer)

    - ``existence`` (boolean; ``False`` by default) -- whether to build the
      `KTS(n)` or only answer whether it exists.

    .. SEEALSO::

        :meth:`IncidenceStructure.is_resolvable`

    EXAMPLES:

    A solution to Kirkmman's original problem::

        sage: kts = designs.kirkman_triple_system(15)
        sage: classes = kts.is_resolvable(1)[1]
        sage: names = '0123456789abcde'
        sage: to_name = lambda (r,s,t): ' '+names[r]+names[s]+names[t]+' '
        sage: rows = [join(('Day {}'.format(i) for i in range(1,8)), '   ')]
        sage: rows.extend(join(map(to_name,row), '   ') for row in zip(*classes))
        sage: print join(rows,'\n')
        Day 1   Day 2   Day 3   Day 4   Day 5   Day 6   Day 7
         07e     18e     29e     3ae     4be     5ce     6de
         139     24a     35b     46c     05d     167     028
         26b     03c     14d     257     368     049     15a
         458     569     06a     01b     12c     23d     347
         acd     7bd     78c     89d     79a     8ab     9bc

    TESTS::

        sage: for i in range(3,300,6):
        ....:     _ = designs.kirkman_triple_system(i)
    """
    if v%6 != 3:
        if existence:
            return False
        raise ValueError("There is no KTS({}) as v!=3 mod(6)".format(v))

    if existence:
        return False

    elif v == 3:
        return BalancedIncompleteBlockDesign(3,[[0,1,2]],k=3,lambd=1)

    elif v == 9:
        classes = [[[0, 1, 5], [2, 6, 7], [3, 4, 8]],
                   [[1, 6, 8], [3, 5, 7], [0, 2, 4]],
                   [[1, 4, 7], [0, 3, 6], [2, 5, 8]],
                   [[4, 5, 6], [0, 7, 8], [1, 2, 3]]]
        KTS = BalancedIncompleteBlockDesign(v,[tr for cl in classes for tr in cl],k=3,lambd=1,copy=False)
        KTS._classes = classes
        return KTS

    # Construction 1.1 from [Stinson91] (originally Theorem 6 from [RCW71])
    #
    # For all prime powers q=1 mod 6, there exists a KTS(2q+1)
    elif ((v-1)//2)%6 == 1 and is_prime_power((v-1)//2):
        from sage.rings.finite_rings.constructor import FiniteField as GF
        q = (v-1)//2
        K = GF(q,'x')
        a = K.primitive_element()
        t = (q-1)/6

        # m is the solution of a^m=(a^t+1)/2
        from sage.groups.generic import discrete_log
        m = discrete_log((a**t+1)/2, a)
        assert 2*a**m == a**t+1

        # First parallel class
        first_class = [[(0,1),(0,2),'inf']]
        b0 = K.one(); b1 = a**t; b2 = a**m
        first_class.extend([(b0*a**i,1),(b1*a**i,1),(b2*a**i,2)]
                            for i in range(t)+range(2*t,3*t)+range(4*t,5*t))
        b0 = a**(m+t); b1=a**(m+3*t); b2=a**(m+5*t)
        first_class.extend([[(b0*a**i,2),(b1*a**i,2),(b2*a**i,2)]
                            for i in range(t)])

        # Action of K on the points
        action = lambda v,x : (v+x[0],x[1]) if len(x) == 2 else x

        # relabel to integer
        relabel = {(p,x): i+(x-1)*q
                   for i,p in enumerate(K)
                   for x in [1,2]}
        relabel['inf'] = 2*q

        classes = [[[relabel[action(p,x)] for x in tr] for tr in first_class]
                   for p in K]

        KTS = BalancedIncompleteBlockDesign(v,[tr for cl in classes for tr in cl],k=3,lambd=1,copy=False)

        KTS._classes = classes
        return KTS

    # Construction 1.2 from [Stinson91] (originally Theorem 5 from [RCW71])
    #
    # For all prime powers q=1 mod 6, there exists a KTS(3q)
    elif (v//3)%6 == 1 and is_prime_power(v//3):
        from sage.rings.finite_rings.constructor import FiniteField as GF
        q = v//3
        K = GF(q,'x')
        a = K.primitive_element()
        t = (q-1)/6
        A0 = [(0,0),(0,1),(0,2)]
        B  = [[(a**i,j),(a**(i+2*t),j),(a**(i+4*t),j)] for j in range(3)
              for i in range(t)]
        A  = [[(a**i,0),(a**(i+2*t),1),(a**(i+4*t),2)] for i in range(6*t)]

        # Action of K on the points
        action = lambda v,x: (v+x[0],x[1])

        # relabel to integer
        relabel = {(p,j): i+j*q
                   for i,p in enumerate(K)
                   for j in range(3)}

        B0  = [A0] + B + A[t:2*t] + A[3*t:4*t] + A[5*t:6*t]

        # Classes
        classes = [[[relabel[action(p,x)] for x in tr] for tr in B0]
                   for p in K]

        for i in range(t)+range(2*t,3*t)+range(4*t,5*t):
            classes.append([[relabel[action(p,x)] for x in A[i]] for p in K])

        KTS = BalancedIncompleteBlockDesign(v,[tr for cl in classes for tr in cl],k=3,lambd=1,copy=False)
        KTS._classes = classes
        return KTS

    else:
        # This is Lemma IX.6.4 from [BJL99].
        #
        # This construction takes a (v,{4,7})-PBD. All points are doubled (x has
        # a copy x'), and an infinite point \infty is added.
        #
        # On all blocks of 2*4 points we "paste" a KTS(2*4+1) using the infinite
        # point, in such a way that all {x,x',infty} are set of the design. We
        # do the same for blocks with 2*7 points using a KTS(2*7+1).
        #
        # Note that the triples of points equal to {x,x',\infty} will be added
        # several times.
        #
        # As all those subdesigns are resolvable, each class of the KTS(n) is
        # obtained by considering a set {x,x',\infty} and all sets of all
        # parallel classes of the subdesign which contain this set.

        # We create the small KTS(n') we need, and relabel them such that
        # 01(n'-1),23(n'-1),... are blocks of the design.
        gdd4 = kirkman_triple_system(9)
        gdd7 = kirkman_triple_system(15)

        X = [B for B in gdd4 if 8 in B]
        for b in X:
            b.remove(8)
        X = sum(X, []) + [8]
        gdd4.relabel({v:i for i,v in enumerate(X)})
        gdd4 = gdd4.is_resolvable(True)[1] # the relabeled classes

        X = [B for B in gdd7 if 14 in B]
        for b in X:
            b.remove(14)
        X = sum(X, []) + [14]
        gdd7.relabel({v:i for i,v in enumerate(X)})
        gdd7 = gdd7.is_resolvable(True)[1] # the relabeled classes

        # The first parallel class contains 01(n'-1), the second contains
        # 23(n'-1), etc..
        # Then remove the blocks containing (n'-1)
        for B in gdd4:
            for i,b in enumerate(B):
                if 8 in b: j = min(b); del B[i]; B.insert(0,j); break
        gdd4.sort()
        for B in gdd4:
            B.pop(0)

        for B in gdd7:
            for i,b in enumerate(B):
                if 14 in b: j = min(b); del B[i]; B.insert(0,j); break
        gdd7.sort()
        for B in gdd7:
            B.pop(0)

        # Pasting the KTS(n') without {x,x',\infty} blocks
        classes = [[] for i in range((v-1)/2)]
        gdd = {4:gdd4, 7: gdd7}
        for B in PBD_4_7((v-1)//2,check=False):
            for i,classs in enumerate(gdd[len(B)]):
                classes[B[i]].extend([[2*B[x//2]+x%2 for x in BB] for BB in classs])

        # The {x,x',\infty} blocks
        for i,classs in enumerate(classes):
            classs.append([2*i,2*i+1,v-1])

        KTS = BalancedIncompleteBlockDesign(v,
                                            blocks = [tr for cl in classes for tr in cl],
                                            k=3,
                                            lambd=1,
                                            check=True,
                                            copy =False)
        KTS._classes = classes
        assert KTS.is_resolvable()

        return KTS
Beispiel #5
0
def kirkman_triple_system(v, existence=False):
    r"""
    Return a Kirkman Triple System on `v` points.

    A Kirkman Triple System `KTS(v)` is a resolvable Steiner Triple System. It
    exists if and only if `v\equiv 3\pmod{6}`.

    INPUT:

    - `n` (integer)

    - ``existence`` (boolean; ``False`` by default) -- whether to build the
      `KTS(n)` or only answer whether it exists.

    .. SEEALSO::

        :meth:`IncidenceStructure.is_resolvable`

    EXAMPLES:

    A solution to Kirkmman's original problem::

        sage: kts = designs.kirkman_triple_system(15)
        sage: classes = kts.is_resolvable(1)[1]
        sage: names = '0123456789abcde'
        sage: def to_name(r_s_t):
        ....:     r, s, t = r_s_t
        ....:     return ' ' + names[r] + names[s] + names[t] + ' '
        sage: rows = ['   '.join(('Day {}'.format(i) for i in range(1,8)))]
        sage: rows.extend('   '.join(map(to_name,row)) for row in zip(*classes))
        sage: print('\n'.join(rows))
        Day 1   Day 2   Day 3   Day 4   Day 5   Day 6   Day 7
         07e     18e     29e     3ae     4be     5ce     6de
         139     24a     35b     46c     05d     167     028
         26b     03c     14d     257     368     049     15a
         458     569     06a     01b     12c     23d     347
         acd     7bd     78c     89d     79a     8ab     9bc

    TESTS::

        sage: for i in range(3,300,6):
        ....:     _ = designs.kirkman_triple_system(i)
    """
    if v % 6 != 3:
        if existence:
            return False
        raise ValueError("There is no KTS({}) as v!=3 mod(6)".format(v))

    if existence:
        return False

    elif v == 3:
        return BalancedIncompleteBlockDesign(3, [[0, 1, 2]], k=3, lambd=1)

    elif v == 9:
        classes = [[[0, 1, 5], [2, 6, 7], [3, 4, 8]],
                   [[1, 6, 8], [3, 5, 7], [0, 2, 4]],
                   [[1, 4, 7], [0, 3, 6], [2, 5, 8]],
                   [[4, 5, 6], [0, 7, 8], [1, 2, 3]]]
        KTS = BalancedIncompleteBlockDesign(
            v, [tr for cl in classes for tr in cl], k=3, lambd=1, copy=False)
        KTS._classes = classes
        return KTS

    # Construction 1.1 from [Stinson91] (originally Theorem 6 from [RCW71])
    #
    # For all prime powers q=1 mod 6, there exists a KTS(2q+1)
    elif ((v - 1) // 2) % 6 == 1 and is_prime_power((v - 1) // 2):
        from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
        q = (v - 1) // 2
        K = GF(q, 'x')
        a = K.primitive_element()
        t = (q - 1) // 6

        # m is the solution of a^m=(a^t+1)/2
        from sage.groups.generic import discrete_log
        m = discrete_log((a**t + 1) / 2, a)
        assert 2 * a**m == a**t + 1

        # First parallel class
        first_class = [[(0, 1), (0, 2), 'inf']]
        b0 = K.one()
        b1 = a**t
        b2 = a**m
        first_class.extend([(b0 * a**i, 1), (b1 * a**i, 1), (b2 * a**i, 2)]
                           for i in list(range(t)) +
                           list(range(2 * t, 3 * t)) +
                           list(range(4 * t, 5 * t)))
        b0 = a**(m + t)
        b1 = a**(m + 3 * t)
        b2 = a**(m + 5 * t)
        first_class.extend([[(b0 * a**i, 2), (b1 * a**i, 2), (b2 * a**i, 2)]
                            for i in range(t)])

        # Action of K on the points
        action = lambda v, x: (v + x[0], x[1]) if len(x) == 2 else x

        # relabel to integer
        relabel = {(p, x): i + (x - 1) * q
                   for i, p in enumerate(K) for x in [1, 2]}
        relabel['inf'] = 2 * q

        classes = [[[relabel[action(p, x)] for x in tr] for tr in first_class]
                   for p in K]

        KTS = BalancedIncompleteBlockDesign(
            v, [tr for cl in classes for tr in cl], k=3, lambd=1, copy=False)

        KTS._classes = classes
        return KTS

    # Construction 1.2 from [Stinson91] (originally Theorem 5 from [RCW71])
    #
    # For all prime powers q=1 mod 6, there exists a KTS(3q)
    elif (v // 3) % 6 == 1 and is_prime_power(v // 3):
        from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
        q = v // 3
        K = GF(q, 'x')
        a = K.primitive_element()
        t = (q - 1) // 6
        A0 = [(0, 0), (0, 1), (0, 2)]
        B = [[(a**i, j), (a**(i + 2 * t), j), (a**(i + 4 * t), j)]
             for j in range(3) for i in range(t)]
        A = [[(a**i, 0), (a**(i + 2 * t), 1), (a**(i + 4 * t), 2)]
             for i in range(6 * t)]

        # Action of K on the points
        action = lambda v, x: (v + x[0], x[1])

        # relabel to integer
        relabel = {(p, j): i + j * q
                   for i, p in enumerate(K) for j in range(3)}

        B0 = [A0] + B + A[t:2 * t] + A[3 * t:4 * t] + A[5 * t:6 * t]

        # Classes
        classes = [[[relabel[action(p, x)] for x in tr] for tr in B0]
                   for p in K]

        for i in list(range(t)) + list(range(2 * t, 3 * t)) + list(
                range(4 * t, 5 * t)):
            classes.append([[relabel[action(p, x)] for x in A[i]] for p in K])

        KTS = BalancedIncompleteBlockDesign(
            v, [tr for cl in classes for tr in cl], k=3, lambd=1, copy=False)
        KTS._classes = classes
        return KTS

    else:
        # This is Lemma IX.6.4 from [BJL99].
        #
        # This construction takes a (v,{4,7})-PBD. All points are doubled (x has
        # a copy x'), and an infinite point \infty is added.
        #
        # On all blocks of 2*4 points we "paste" a KTS(2*4+1) using the infinite
        # point, in such a way that all {x,x',infty} are set of the design. We
        # do the same for blocks with 2*7 points using a KTS(2*7+1).
        #
        # Note that the triples of points equal to {x,x',\infty} will be added
        # several times.
        #
        # As all those subdesigns are resolvable, each class of the KTS(n) is
        # obtained by considering a set {x,x',\infty} and all sets of all
        # parallel classes of the subdesign which contain this set.

        # We create the small KTS(n') we need, and relabel them such that
        # 01(n'-1),23(n'-1),... are blocks of the design.
        gdd4 = kirkman_triple_system(9)
        gdd7 = kirkman_triple_system(15)

        X = [B for B in gdd4 if 8 in B]
        for b in X:
            b.remove(8)
        X = sum(X, []) + [8]
        gdd4.relabel({v: i for i, v in enumerate(X)})
        gdd4 = gdd4.is_resolvable(True)[1]  # the relabeled classes

        X = [B for B in gdd7 if 14 in B]
        for b in X:
            b.remove(14)
        X = sum(X, []) + [14]
        gdd7.relabel({v: i for i, v in enumerate(X)})
        gdd7 = gdd7.is_resolvable(True)[1]  # the relabeled classes

        # The first parallel class contains 01(n'-1), the second contains
        # 23(n'-1), etc..
        # Then remove the blocks containing (n'-1)
        for B in gdd4:
            for i, b in enumerate(B):
                if 8 in b:
                    j = min(b)
                    del B[i]
                    B.insert(0, j)
                    break
        gdd4.sort()
        for B in gdd4:
            B.pop(0)

        for B in gdd7:
            for i, b in enumerate(B):
                if 14 in b:
                    j = min(b)
                    del B[i]
                    B.insert(0, j)
                    break
        gdd7.sort()
        for B in gdd7:
            B.pop(0)

        # Pasting the KTS(n') without {x,x',\infty} blocks
        classes = [[] for i in range((v - 1) // 2)]
        gdd = {4: gdd4, 7: gdd7}
        for B in PBD_4_7((v - 1) // 2, check=False):
            for i, classs in enumerate(gdd[len(B)]):
                classes[B[i]].extend([[2 * B[x // 2] + x % 2 for x in BB]
                                      for BB in classs])

        # The {x,x',\infty} blocks
        for i, classs in enumerate(classes):
            classs.append([2 * i, 2 * i + 1, v - 1])

        KTS = BalancedIncompleteBlockDesign(
            v,
            blocks=[tr for cl in classes for tr in cl],
            k=3,
            lambd=1,
            check=True,
            copy=False)
        KTS._classes = classes
        assert KTS.is_resolvable()

        return KTS
Beispiel #6
0
def one_radical_difference_family(K, k):
    r"""
    Search for a radical difference family on ``K`` using dancing links
    algorithm.

    For the definition of radical difference family, see
    :func:`radical_difference_family`. Here, we consider only radical difference
    family with `\lambda = 1`.

    INPUT:

    - ``K`` -- a finite field of cardinality `q`.

    - ``k`` -- a positive integer so that `k(k-1)` divides `q-1`.

    OUTPUT:

    Either a difference family or ``None`` if it does not exist.

    ALGORITHM:

    The existence of a radical difference family is equivalent to a one
    dimensional tiling (or packing) problem in a cyclic group. This subsequent
    problem is solved by a call to the function :func:`one_cyclic_tiling`.

        Let `K^*` be the multiplicative group of the finite field `K`. A radical
        family has the form `\mathcal B = \{x_1 B, \ldots, x_k B\}`, where
        `B=\{x:x^{k}=1\}` (for `k` odd) or `B=\{x:x^{k-1}=1\}\cup \{0\}` (for
        `k` even). Equivalently, `K^*` decomposes as:

        .. MATH::

            K^* = \Delta (x_1 B) \cup ... \cup \Delta (x_k B) = x_1 \Delta B \cup ... \cup x_k \Delta B

        We observe that `C=B\backslash 0` is a subgroup of the (cyclic) group
        `K^*`, that can thus be generated by some element `r`. Furthermore, we
        observe that `\Delta B` is always a union of cosets of `\pm C` (which is
        twice larger than `C`).

        .. MATH::

            \begin{array}{llll}
            (k\text{ odd} ) & \Delta B &= \{r^i-r^j:r^i\neq r^j\} &= \pm C\cdot \{r^i-1: 0 < i \leq m\}\\
            (k\text{ even}) & \Delta B &= \{r^i-r^j:r^i\neq r^j\}\cup C &= \pm C\cdot \{r^i-1: 0 < i < m\}\cup \pm C
            \end{array}

        where

        .. MATH::

            (k\text{ odd})\ m = (k-1)/2 \quad \text{and} \quad (k\text{ even})\ m = k/2.

        Consequently, `\mathcal B = \{x_1 B, \ldots, x_k B\}` is a radical
        difference family if and only if `\{x_1 (\Delta B/(\pm C)), \ldots, x_k
        (\Delta B/(\pm C))\}` is a partition of the cyclic group `K^*/(\pm C)`.

    EXAMPLES::

        sage: from sage.combinat.designs.difference_family import (
        ....:    one_radical_difference_family,
        ....:    is_difference_family)

        sage: one_radical_difference_family(GF(13),4)
        [[0, 1, 3, 9]]

    The parameters that appear in [Bu95]_::

        sage: df = one_radical_difference_family(GF(449), 8); df
        [[0, 1, 18, 25, 176, 324, 359, 444],
         [0, 9, 88, 162, 222, 225, 237, 404],
         [0, 11, 140, 198, 275, 357, 394, 421],
         [0, 40, 102, 249, 271, 305, 388, 441],
         [0, 49, 80, 93, 161, 204, 327, 433],
         [0, 70, 99, 197, 230, 362, 403, 435],
         [0, 121, 141, 193, 293, 331, 335, 382],
         [0, 191, 285, 295, 321, 371, 390, 392]]
        sage: is_difference_family(GF(449), df, 449, 8, 1)
        True
    """
    q = K.cardinality()
    x = K.multiplicative_generator()

    e = k*(k-1)
    if q%e != 1:
        raise ValueError("q%e is not 1")

    # We define A by (see the function's documentation):
    # ΔB = C.A
    if k%2 == 1:
        m = (k-1) // 2
        r = x ** ((q-1) // k)     # k-th root of unity
        A = [r**i - 1 for i in range(1,m+1)]
    else:
        m = k // 2
        r = x ** ((q-1) // (k-1)) # (k-1)-th root of unity
        A = [r**i - 1 for i in range(1,m)]
        A.append(K.one())

    # instead of the complicated multiplicative group K^*/(±C) we use the
    # discrete logarithm to convert everything into the additive group Z/cZ
    c = m * (q-1) // e # cardinal of ±C
    from sage.groups.generic import discrete_log
    logA = [discrete_log(a,x)%c for a in A]

    # if two elments of A are equal modulo c then no tiling is possible
    if len(set(logA)) != m:
        return None

    # brute force
    tiling = one_cyclic_tiling(logA, c)
    if tiling is None:
        return None

    D = K.cyclotomic_cosets(r, [x**i for i in tiling])
    if k%2 == 0:
        for d in D:
            d.insert(K.zero(),0)
    return D