Ejemplo n.º 1
0
def subsets(seq, k=None, repetition=False):
    """Generates all k-subsets (combinations) from an n-element set, seq.

       A k-subset of an n-element set is any subset of length exactly k. The
       number of k-subsets of an n-element set is given by binomial(n, k),
       whereas there are 2**n subsets all together. If k is None then all
       2**n subsets will be returned from shortest to longest.

       Examples
       ========

           >>> from sympy.utilities.iterables import subsets

       subsets(seq, k) will return the n!/k!/(n - k)! k-subsets (combinations)
       without repetition, i.e. once an item has been removed, it can no
       longer be "taken":

           >>> list(subsets([1, 2], 2))
           [(1, 2)]
           >>> list(subsets([1, 2]))
           [(), (1,), (2,), (1, 2)]
           >>> list(subsets([1, 2, 3], 2))
           [(1, 2), (1, 3), (2, 3)]


       subsets(seq, k, repetition=True) will return the (n - 1 + k)!/k!/(n - 1)!
       combinations *with* repetition:

           >>> list(subsets([1, 2], 2, repetition=True))
           [(1, 1), (1, 2), (2, 2)]

       If you ask for more items than are in the set you get the empty set unless
       you allow repetitions:

           >>> list(subsets([0, 1], 3, repetition=False))
           []
           >>> list(subsets([0, 1], 3, repetition=True))
           [(0, 0, 0), (0, 0, 1), (0, 1, 1), (1, 1, 1)]

       """
    if k is None:
        for k in range(len(seq) + 1):
            for i in subsets(seq, k, repetition):
                yield i
    else:
        if not repetition:
            for i in combinations(seq, k):
                yield i
        else:
            for i in combinations_with_replacement(seq, k):
                yield i
Ejemplo n.º 2
0
def ksubsets(superset, k):
    """
    Finds the subsets of size k in lexicographic order.

    This uses the itertools generator.

    Examples:
    >>> from sympy.combinatorics.subsets import ksubsets
    >>> list(ksubsets([1,2,3], 2))
    [(1, 2), (1, 3), (2, 3)]
    >>> list(ksubsets([1,2,3,4,5], 2))
    [(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), \
    (2, 5), (3, 4), (3, 5), (4, 5)]
    """
    return combinations(superset, k)
Ejemplo n.º 3
0
def ksubsets(superset, k):
    """
    Finds the subsets of size k in lexicographic order.

    This uses the itertools generator.

    Examples
    ========
    >>> from sympy.combinatorics.subsets import ksubsets
    >>> list(ksubsets([1,2,3], 2))
    [(1, 2), (1, 3), (2, 3)]
    >>> list(ksubsets([1,2,3,4,5], 2))
    [(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), \
    (2, 5), (3, 4), (3, 5), (4, 5)]
    """
    return combinations(superset, k)
Ejemplo n.º 4
0
def sdm_groebner(G, NF, O, K):
    """
    Compute a minimal standard basis of ``G`` with respect to order ``O``.

    The algorithm uses a normal form ``NF``, for example ``sdm_nf_mora``.
    The ground field is assumed to be ``K``, and monomials ordered according
    to ``O``.

    Let `N` denote the submodule generated by elements of `G`. A standard
    basis for `N` is a subset `S` of `N`, such that `in(S) = in(N)`, where for
    any subset `X` of `F`, `in(X)` denotes the submodule generated by the
    initial forms of elements of `X`. [SCA, defn 2.3.2]

    A standard basis is called minimal if no subset of it is a standard basis.

    One may show that standard bases are always generating sets.

    Minimal standard bases are not unique. This algorithm computes a
    deterministic result, depending on the particular order of `G`.

    See [SCA, algorithm 2.3.8, and remark 1.6.3].
    """
    # First compute a standard basis
    S = [f for f in G if f]
    P = list(combinations(S, 2))

    def prune(P, S, h):
        """
        Prune the pair-set by applying the chain criterion
        [SCA, remark 2.5.11].
        """
        remove = set()
        retain = set()
        for (a, b, c) in permutations(S, 3):
            A = sdm_LM(a)
            B = sdm_LM(b)
            C = sdm_LM(c)
            if len(set([A[0], B[0], C[0]])) != 1 or not h in [a, b, c] or \
               any(tuple(x) in retain for x in [a, b, c]):
                continue
            if monomial_divides(B[1:], monomial_lcm(A[1:], C[1:])):
                remove.add((tuple(a), tuple(c)))
                retain.update([tuple(b), tuple(c), tuple(a)])
        return [(f, g) for (f, g) in P if (h not in [f, g]) or \
                    ((tuple(f), tuple(g)) not in remove and \
                     (tuple(g), tuple(f)) not in remove)]

    while P:
        # TODO better data structures!!!
        #print len(P), len(S)
        # Use the "normal selection strategy"
        lcms = [(i, sdm_LM(f)[:1] + monomial_lcm(sdm_LM(f)[1:], sdm_LM(g)[1:])) for \
                i, (f, g) in enumerate(P)]
        i = min(lcms, key=lambda x: O(x[1]))[0]
        f, g = P.pop(i)
        h = NF(sdm_spoly(f, g, O, K), S, O, K)
        if h:
            S.append(h)
            P.extend((h, f) for f in S if sdm_LM(h)[0] == sdm_LM(f)[0])
            P = prune(P, S, h)

    # Now interreduce it. (TODO again, better data structures)
    S = set(tuple(f) for f in S)
    for a, b in permutations(S, 2):
        A = sdm_LM(list(a))
        B = sdm_LM(list(b))
        if sdm_monomial_divides(A, B) and b in S and a in S:
            S.remove(b)

    return sorted((list(f) for f in S), key=lambda f: O(sdm_LM(f)),
                  reverse=True)
Ejemplo n.º 5
0
def sdm_groebner(G, NF, O, K):
    """
    Compute a minimal standard basis of ``G`` with respect to order ``O``.

    The algorithm uses a normal form ``NF``, for example ``sdm_nf_mora``.
    The ground field is assumed to be ``K``, and monomials ordered according
    to ``O``.

    Let `N` denote the submodule generated by elements of `G`. A standard
    basis for `N` is a subset `S` of `N`, such that `in(S) = in(N)`, where for
    any subset `X` of `F`, `in(X)` denotes the submodule generated by the
    initial forms of elements of `X`. [SCA, defn 2.3.2]

    A standard basis is called minimal if no subset of it is a standard basis.

    One may show that standard bases are always generating sets.

    Minimal standard bases are not unique. This algorithm computes a
    deterministic result, depending on the particular order of `G`.

    See [SCA, algorithm 2.3.8, and remark 1.6.3].
    """
    # First compute a standard basis
    S = [f for f in G if f]
    P = list(combinations(S, 2))

    def prune(P, S, h):
        """
        Prune the pair-set by applying the chain criterion
        [SCA, remark 2.5.11].
        """
        remove = set()
        retain = set()
        for (a, b, c) in permutations(S, 3):
            A = sdm_LM(a)
            B = sdm_LM(b)
            C = sdm_LM(c)
            if len(set([A[0], B[0], C[0]])) != 1 or not h in [a, b, c] or \
               any(tuple(x) in retain for x in [a, b, c]):
                continue
            if monomial_divides(B[1:], monomial_lcm(A[1:], C[1:])):
                remove.add((tuple(a), tuple(c)))
                retain.update([tuple(b), tuple(c), tuple(a)])
        return [(f, g) for (f, g) in P if (h not in [f, g]) or \
                    ((tuple(f), tuple(g)) not in remove and \
                     (tuple(g), tuple(f)) not in remove)]

    while P:
        # TODO better data structures!!!
        #print len(P), len(S)
        # Use the "normal selection strategy"
        lcms = [(i, sdm_LM(f)[:1] + monomial_lcm(sdm_LM(f)[1:], sdm_LM(g)[1:])) for \
                i, (f, g) in enumerate(P)]
        i = min(lcms, key=lambda x: O(x[1]))[0]
        f, g = P.pop(i)
        h = NF(sdm_spoly(f, g, O, K), S, O, K)
        if h:
            S.append(h)
            P.extend((h, f) for f in S if sdm_LM(h)[0] == sdm_LM(f)[0])
            P = prune(P, S, h)

    # Now interreduce it. (TODO again, better data structures)
    S = set(tuple(f) for f in S)
    for a, b in permutations(S, 2):
        A = sdm_LM(list(a))
        B = sdm_LM(list(b))
        if sdm_monomial_divides(A, B) and b in S and a in S:
            S.remove(b)

    return sorted((list(f) for f in S),
                  key=lambda f: O(sdm_LM(f)),
                  reverse=True)