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
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)
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)
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)