def sdm_spoly(f, g, O, K, phantom=None): """ Compute the generalized s-polynomial of ``f`` and ``g``. The ground field is assumed to be ``K``, and monomials ordered according to ``O``. This is invalid if either of ``f`` or ``g`` is zero. If the leading terms of `f` and `g` involve different basis elements of `F`, their s-poly is defined to be zero. Otherwise it is a certain linear combination of `f` and `g` in which the leading terms cancel. See [SCA, defn 2.3.6] for details. If ``phantom`` is not ``None``, it should be a pair of module elements on which to perform the same operation(s) as on ``f`` and ``g``. The in this case both results are returned. Examples ======== >>> from diofant.polys import QQ, lex >>> f = [((2, 1, 1), QQ(1)), ((1, 0, 1), QQ(1))] >>> g = [((2, 3, 0), QQ(1))] >>> h = [((1, 2, 3), QQ(1))] >>> sdm_spoly(f, h, lex, QQ) [] >>> sdm_spoly(f, g, lex, QQ) [((1, 2, 1), 1)] """ if not f or not g: return sdm_zero() LM1 = sdm_LM(f) LM2 = sdm_LM(g) if LM1[0] != LM2[0]: return sdm_zero() LM1 = LM1[1:] LM2 = LM2[1:] lcm = monomial_lcm(LM1, LM2) m1 = monomial_div(lcm, LM1) m2 = monomial_div(lcm, LM2) c = K.quo(-sdm_LC(f, K), sdm_LC(g, K)) r1 = sdm_add(sdm_mul_term(f, (m1, K.one), O, K), sdm_mul_term(g, (m2, c), O, K), O, K) if phantom is None: return r1 r2 = sdm_add(sdm_mul_term(phantom[0], (m1, K.one), O, K), sdm_mul_term(phantom[1], (m2, c), O, K), O, K) return r1, r2
def _basis(G, ring): """ Computes a list of monomials which are not divisible by the leading monomials wrt to ``O`` of ``G``. These monomials are a basis of `K[X_1, \ldots, X_n]/(G)`. """ order = ring.order leading_monomials = [g.LM for g in G] candidates = [ring.zero_monom] basis = [] while candidates: t = candidates.pop() basis.append(t) new_candidates = [_incr_k(t, k) for k in range(ring.ngens) if all(monomial_div(_incr_k(t, k), lmg) is None for lmg in leading_monomials)] candidates.extend(new_candidates) candidates.sort(key=lambda m: order(m), reverse=True) basis = list(set(basis)) return sorted(basis, key=lambda m: order(m))
def dmp_terms_gcd(f, u, K): """ Remove GCD of terms from ``f`` in ``K[X]``. Examples ======== >>> from diofant.polys.domains import ZZ >>> f = ZZ.map([[1, 0], [1, 0, 0], [], []]) >>> dmp_terms_gcd(f, 1, ZZ) ((2, 1), [[1], [1, 0]]) """ if dmp_ground_TC(f, u, K) or dmp_zero_p(f, u): return (0, ) * (u + 1), f F = dmp_to_dict(f, u) G = monomial_min(*list(F.keys())) if all(g == 0 for g in G): return G, f f = {} for monom, coeff in F.items(): f[monomial_div(monom, G)] = coeff return G, dmp_from_dict(f, u, K)
def staircase(n): """ Compute all monomials with degree less than ``n`` that are not divisible by any element of ``leading_monomials``. """ if n == 0: return [1] S = [] for mi in combinations_with_replacement(range(len(opt.gens)), n): m = [0] * len(opt.gens) for i in mi: m[i] += 1 if all([monomial_div(m, lmg) is None for lmg in leading_monomials]): S.append(m) return [Monomial(s).as_expr(*opt.gens) for s in S] + staircase(n - 1)
def test_monomial_div(): assert monomial_div((3, 4, 1), (1, 2, 0)) == (2, 2, 1)
def matrix_fglm(F, ring, O_to): """ Converts the reduced Groebner basis ``F`` of a zero-dimensional ideal w.r.t. ``O_from`` to a reduced Groebner basis w.r.t. ``O_to``. References ========== .. [1] J.C. Faugere, P. Gianni, D. Lazard, T. Mora (1994). Efficient Computation of Zero-dimensional Groebner Bases by Change of Ordering. """ domain = ring.domain ngens = ring.ngens ring_to = ring.clone(order=O_to) old_basis = _basis(F, ring) M = _representing_matrices(old_basis, F, ring) # V contains the normalforms (wrt O_from) of S S = [ring.zero_monom] V = [[domain.one] + [domain.zero] * (len(old_basis) - 1)] G = [] L = [(i, 0) for i in range(ngens)] # (i, j) corresponds to x_i * S[j] L.sort(key=lambda k_l: O_to(_incr_k(S[k_l[1]], k_l[0])), reverse=True) t = L.pop() P = _identity_matrix(len(old_basis), domain) while True: s = len(S) v = _matrix_mul(M[t[0]], V[t[1]]) _lambda = _matrix_mul(P, v) if all(_lambda[i] == domain.zero for i in range(s, len(old_basis))): # there is a linear combination of v by V lt = ring.term_new(_incr_k(S[t[1]], t[0]), domain.one) rest = ring.from_dict({S[i]: _lambda[i] for i in range(s)}) g = (lt - rest).set_ring(ring_to) if g: G.append(g) else: # v is linearly independant from V P = _update(s, _lambda, P) S.append(_incr_k(S[t[1]], t[0])) V.append(v) L.extend([(i, s) for i in range(ngens)]) L = list(set(L)) L.sort(key=lambda k_l: O_to(_incr_k(S[k_l[1]], k_l[0])), reverse=True) L = [(k, l) for (k, l) in L if all(monomial_div(_incr_k(S[l], k), g.LM) is None for g in G)] if not L: G = [ g.monic() for g in G ] return sorted(G, key=lambda g: O_to(g.LM), reverse=True) t = L.pop()