def sym_to_tf(sym_expr): num, den = sym_expr.as_numer_denom() try: tf_num = [ float(n) for n in sorted(sym.Poly(num, s).all_coeffs(), key=monomial_key('grlex', [s])) ] tf_den = [ float(d) for d in sorted(sym.Poly(den, s).all_coeffs(), key=monomial_key('grlex', [s])) ] except sym.PolynomialError: raise ValueError("Only s variable must remain in input expression.") return ctl.tf(tf_num, tf_den)
def dmp_list_terms(f, u, K, order=None): """ List all non-zero terms from ``f`` in the given order ``order``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densebasic import dmp_list_terms >>> f = ZZ.map([[1, 1], [2, 3]]) >>> dmp_list_terms(f, 1, ZZ) [((1, 1), 1), ((1, 0), 1), ((0, 1), 2), ((0, 0), 3)] >>> dmp_list_terms(f, 1, ZZ, order='grevlex') [((1, 1), 1), ((1, 0), 1), ((0, 1), 2), ((0, 0), 3)] """ def sort(terms, O): return sorted(terms, key=lambda term: O(term[0]), reverse=True) terms = _rec_list_terms(f, u, ()) if not terms: return [((0,)*(u + 1), K.zero)] if order is None: return terms else: return sort(terms, monomial_key(order))
def dmp_list_terms(f, u, K, order=None): """ List all non-zero terms from ``f`` in the given order ``order``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densebasic import dmp_list_terms >>> f = ZZ.map([[1, 1], [2, 3]]) >>> dmp_list_terms(f, 1, ZZ) [((1, 1), 1), ((1, 0), 1), ((0, 1), 2), ((0, 0), 3)] >>> dmp_list_terms(f, 1, ZZ, order='grevlex') [((1, 1), 1), ((1, 0), 1), ((0, 1), 2), ((0, 0), 3)] """ def sort(terms, O): return sorted(terms, key=lambda term: O(term[0]), reverse=True) terms = _rec_list_terms(f, u, ()) if not terms: return [((0, ) * (u + 1), K.zero)] if order is None: return terms else: return sort(terms, monomial_key(order))
def get_dixon_matrix(self, polynomial): r""" Construct the Dixon matrix from the coefficients of polynomial \alpha. Each coefficient is viewed as a polynomial of x_1, ..., x_n. """ # A list of coefficients (in x_i, ..., x_n terms) of the power # products a_1, ..., a_n in Dixon's polynomial. coefficients = polynomial.coeffs() monomials = list(itermonomials(self.variables, self.get_upper_degree())) monomials = sorted(monomials, reverse=True, key=monomial_key('lex', self.variables)) dixon_matrix = Matrix( [[Poly(c, *self.variables).coeff_monomial(m) for m in monomials] for c in coefficients]) keep = [ column for column in range(dixon_matrix.shape[-1]) if any([element != 0 for element in dixon_matrix[:, column]]) ] return dixon_matrix[:, keep]
def __init__(self, mm, poly_g, morder='grevlex'): """ @param - mm is a MomentMatrix object @param - poly_g the localizing polynomial """ self.mm = mm self.poly_g = poly_g self.deg_g = poly_g.as_poly().total_degree() #there is no point to a constant localization matrix, #and it will cause crash because how sympy handles 1 assert (self.deg_g > 0) # change this to be everything still in mm.monos post multiplication rawmonos = mn.itermonomials(self.mm.vars, self.mm.degree - self.deg_g) self.row_monos = sorted(rawmonos,\ key=monomial_key(morder, mm.vars[::-1])) self.expanded_polys = [] for yi in self.row_monos: for yj in self.row_monos: self.expanded_polys.append(sp.expand(poly_g * yi * yj)) # mapping from a monomial to a list of indices of # where the monomial appears in the moment matrix self.term_to_indices_dict = defaultdict(list) for i, pi in enumerate(self.expanded_polys): coeffdict = pi.as_coefficients_dict() for mono in coeffdict: coeff = coeffdict[mono] self.term_to_indices_dict[mono].append((i, float(coeff)))
def __init__(self, mm, poly_g, morder='grevlex'): """ @param - mm is a MomentMatrix object @param - poly_g the localizing polynomial """ self.mm = mm self.poly_g = poly_g self.deg_g = poly_g.as_poly().total_degree() #there is no point to a constant localization matrix, #and it will cause crash because how sympy handles 1 assert(self.deg_g>0) # change this to be everything still in mm.monos post multiplication rawmonos = mn.itermonomials(self.mm.vars, self.mm.degree-self.deg_g); self.row_monos = sorted(rawmonos,\ key=monomial_key(morder, mm.vars[::-1])) self.expanded_polys = []; for yi in self.row_monos: for yj in self.row_monos: self.expanded_polys.append(sp.expand(poly_g*yi*yj)) # mapping from a monomial to a list of indices of # where the monomial appears in the moment matrix self.term_to_indices_dict = defaultdict(list) for i,pi in enumerate(self.expanded_polys): coeffdict = pi.as_coefficients_dict() for mono in coeffdict: coeff = coeffdict[mono] self.term_to_indices_dict[mono].append( (i,float(coeff)) )
def get_dixon_matrix(self, polynomial): r""" Construct the Dixon matrix from the coefficients of polynomial \alpha. Each coefficient is viewed as a polynomial of x_1, ..., x_n. """ max_degrees = self.get_max_degrees(polynomial) # list of column headers of the Dixon matrix. monomials = itermonomials(self.variables, max_degrees) monomials = sorted(monomials, reverse=True, key=monomial_key('lex', self.variables)) dixon_matrix = Matrix([[Poly(c, *self.variables).coeff_monomial(m) for m in monomials] for c in polynomial.coeffs()]) # remove columns if needed if dixon_matrix.shape[0] != dixon_matrix.shape[1]: keep = [column for column in range(dixon_matrix.shape[-1]) if any(element != 0 for element in dixon_matrix[:, column])] dixon_matrix = dixon_matrix[:, keep] return dixon_matrix
def symbolic_preprocessing(Ld, B, ring): """ Mini Symbolic Preprocessing for Single S-Polynomial Input: Ld : two 3-tuples(sig, um, f), (sig, vm, g) B : intermediate basis ring : for domain, order stuff Out: Information needed to construct a macaulay matrix. """ order = ring.order domain = ring.domain Fi = set([lbp_mul_term(sc[2], sc[1]) for sc in Ld]) Done = set([Polyn(f).LM for f in Fi]) M = [Polyn(f).monoms() for f in Fi] M = set([i for i in chain(*M)]).difference(Done) while M != Done: MF = M.difference(Done) if MF != set(): m = MF.pop() Done.add(m) for g in B: if monomial_divides(Polyn(g).LM, m): u = term_div((m, domain.one), Polyn(g).LT, domain) ug = (lbp_mul_term(g, u)) #Fi.add(ug) # This is an add reducer step from F4 for m in Polyn(ug).monoms(): M.add(m) else: break # Fi sorted by sig_key, normalized, labeled, Done by monomial order Fi = sorted(Fi, key=lambda f: sig_key(f[0], ring.order), reverse=True) print("---------SORTED Fi----------") for i, f in enumerate(Fi): print(i, f) print("---------------------------") Fi = [lbp(Sign(f), Polyn(f).monic(), Num(f)) for f in Fi] Done = sorted(Done, key=monomial_key(order=ring.order), reverse=True) # pseudo COO sparse format nonzero_entries = [] for i, f in enumerate(Fi): for t in Polyn(f).terms(): nonzero_entries.append(((i, Done.index(t[0])), t[1])) spair_info = dict() spair_info["cols"] = len(Done) spair_info["rows"] = len(Fi) spair_info["nze"] = nonzero_entries spair_info["monomials"] = Done spair_info["spair"] = Fi print("S-Pair Info") for (k, v) in spair_info.items(): print(str(k) + ": " + str(v)) return spair_info
def __init__(self, gens, container, order="lex", TOP=True): SubModule.__init__(self, gens, container) if not isinstance(container, FreeModulePolyRing): raise NotImplementedError('This implementation is for submodules of ' + 'FreeModulePolyRing, got %s' % container) self.order = ModuleOrder(monomial_key(order), self.ring.order, TOP) self._gb = None self._gbe = None
def generate_mappings(order, symbols, key='grevlex', source_order=0): """ generate_mappings(order, symbols, key='grevlex'): Generates a set of mappings between three-tuples of indices denoting monomials and and array indices. Returns both the forward and backward maps. Inputs: order: int Maximum monomial order symbols: list List of sympy.Symbol type objects source_order: int Integer describing order of o Returns: dict: Forward mapping from n-tuple to array index. dict: Reversed version; mapping from array index to tuple mapping. Example: >>> x, y, z = sp.symbols('x y z') >>> map, rmap = generate_mappings(1, [x, y, z]) >>> print(map): {(0, 0, 0): 0, (1, 0, 0): 1, (0, 1, 0): 2, (0, 0, 1): 3} >>> print(rmap): {0: (0, 0, 0), 1: (1, 0, 0), 2: (0, 1, 0), 3: (0, 0, 1)} """ if order < source_order: raise ValueError( "source_order must be <= order for meaningful calculations to occur" ) x, y, z = symbols rsymbols = [z, y, x] monoms = itermonomials(symbols, order, source_order) if key: monom_key = monomial_key(key, rsymbols) monoms = sorted(monoms, key=monom_key) index_dict = {} rindex_dict = {} for i, monom in enumerate(monoms): d = monom.as_powers_dict() n = d[x], d[y], d[z] index_dict[n] = i rindex_dict[i] = n return index_dict, rindex_dict
def test_monomial_key(): assert monomial_key() == lex assert monomial_key('lex') == lex assert monomial_key('grlex') == grlex assert monomial_key('grevlex') == grevlex raises(ValueError, lambda: monomial_key('foo')) raises(ValueError, lambda: monomial_key(1)) M = [x, x**2*z**2, x*y, x**2, S(1), y**2, x**3, y, z, x*y**2*z, x**2*y**2] assert sorted(M, key=monomial_key('lex', [z, y, x])) == \ [S(1), x, x**2, x**3, y, x*y, y**2, x**2*y**2, z, x*y**2*z, x**2*z**2] assert sorted(M, key=monomial_key('grlex', [z, y, x])) == \ [S(1), x, y, z, x**2, x*y, y**2, x**3, x**2*y**2, x*y**2*z, x**2*z**2] assert sorted(M, key=monomial_key('grevlex', [z, y, x])) == \ [S(1), x, y, z, x**2, x*y, y**2, x**3, x**2*y**2, x**2*z**2, x*y**2*z]
def test_monomial_key(): assert monomial_key() == lex assert monomial_key('lex') == lex assert monomial_key('grlex') == grlex assert monomial_key('grevlex') == grevlex raises(ValueError, lambda: monomial_key('foo')) raises(ValueError, lambda: monomial_key(1)) M = [x, x**2*z**2, x*y, x**2, S.One, y**2, x**3, y, z, x*y**2*z, x**2*y**2] assert sorted(M, key=monomial_key('lex', [z, y, x])) == \ [S.One, x, x**2, x**3, y, x*y, y**2, x**2*y**2, z, x*y**2*z, x**2*z**2] assert sorted(M, key=monomial_key('grlex', [z, y, x])) == \ [S.One, x, y, z, x**2, x*y, y**2, x**3, x**2*y**2, x*y**2*z, x**2*z**2] assert sorted(M, key=monomial_key('grevlex', [z, y, x])) == \ [S.One, x, y, z, x**2, x*y, y**2, x**3, x**2*y**2, x**2*z**2, x*y**2*z]
def get_monomials_of_certain_degree(self, degree): """ Returns ------- monomials: list A list of monomials of a certain degree. """ monomials = [Mul(*monomial) for monomial in combinations_with_replacement(self.variables, degree)] return sorted(monomials, reverse=True, key=monomial_key('lex', self.variables))
def SymPower(A,N): d=A.shape[0] X=XVAR("x",d-1);Y=XVAR("y",d-1) X.reverse() IT=sorted(itermonomials(X,N),key=monomial_key('grevlex', X)) nd=binomial(N+d-1,N) L=IT[-nd:] X.reverse() Y.reverse() IT=sorted(itermonomials(Y,N),key=monomial_key('grevlex', Y)) nd=binomial(N+d-1,N) LL=IT[-nd:] Y.reverse() XV=Matrix(X) B=A*XV # display(B) nd=len(L) M=[] #display(L) #display(LL) for i in range(nd): F=LL[i] for j in range(d): F=F.subs(Y[j],B[j]) G=expand(F) M.append([G.coeff(L[k]) for k in range(nd)]) #display(M) MX=Matrix(1,nd,M[0]) for i in range(1,nd): XM=Matrix(1,nd,M[i]) MX=MX.col_join(XM) return MX
def __init__(self, degree, variables, morder='grevlex', monos=None): """ @param degree - highest degree of the first row/column of the moment matrix @param variables - list of sympy symbols @param morder the monomial order lex, grlex, grevlex, ilex, igrlex, igrevlex """ self.degree = degree self.vars = variables self.num_vars = len(self.vars) # this object is a list of all monomials # in num_vars variables up to degree degree if monos is None: rawmonos = mn.itermonomials(self.vars, self.degree) else: rawmonos = monos # the reverse here is a bit random..., but has to be done. # also try grlex sometimes self.row_monos = sorted(rawmonos,\ key=monomial_key(morder, self.vars[::-1])) # expanded monos is the flattened moment matrix itself self.expanded_monos = [] for yi in self.row_monos: for yj in self.row_monos: self.expanded_monos.append(yi*yj) # This list correspond to the actual variables in the sdp solver self.matrix_monos = sorted(set(self.expanded_monos),\ key=monomial_key(morder, self.vars[::-1])) self.num_matrix_monos = len(self.matrix_monos) # mapping from a monomial to a list of indices of # where the monomial appears in the moment matrix self.term_to_indices_dict = defaultdict(list) for i,yi in enumerate(self.expanded_monos): self.term_to_indices_dict[yi].append(i)
def new_itermonomials(symbols, lower_order, upper_order): monom_key = monomial_key('grevlex', symbols) monoms = itermonomials(symbols, upper_order) monoms = sorted(monoms, key=monom_key) new_monoms = [] for monom in monoms: monom_dict = monom.as_powers_dict() order = 0 for symbol in symbols: order += monom_dict[symbol] if order >= lower_order: new_monoms.append(monom) return set(new_monoms)
def __init__(self, degree, variables, morder='grevlex', monos=None): """ @param degree - highest degree of the first row/column of the moment matrix @param variables - list of sympy symbols @param morder the monomial order lex, grlex, grevlex, ilex, igrlex, igrevlex """ self.degree = degree self.vars = variables self.num_vars = len(self.vars) # this object is a list of all monomials # in num_vars variables up to degree degree if monos is None: rawmonos = mn.itermonomials(self.vars, self.degree) else: rawmonos = monos # the reverse here is a bit random..., but has to be done. # also try grlex sometimes self.row_monos = sorted(rawmonos,\ key=monomial_key(morder, self.vars[::-1])) # expanded monos is the flattened moment matrix itself self.expanded_monos = [] for yi in self.row_monos: for yj in self.row_monos: self.expanded_monos.append(yi * yj) # This list correspond to the actual variables in the sdp solver self.matrix_monos = sorted(set(self.expanded_monos),\ key=monomial_key(morder, self.vars[::-1])) self.num_matrix_monos = len(self.matrix_monos) # mapping from a monomial to a list of indices of # where the monomial appears in the moment matrix self.term_to_indices_dict = defaultdict(list) for i, yi in enumerate(self.expanded_monos): self.term_to_indices_dict[yi].append(i)
def sdp_equiv(poly, vargroup): degree = poly.total_degree() mons = sympy.Matrix( sorted(sympy.itermonomials(vargroup, degree // 2), key=monomial_key('grlex', list(reversed(vargroup))))) n = len(mons) Q = symmetric_indeterminate_matrix(n) ind = (mons.T * Q * mons)[0, 0].as_poly(vargroup) n = Q.shape[0] all_q = [] # sorted for i in range(n): all_q.append('q{0}_{0}'.format(i)) for j in range(i + 1, n): all_q.append('q{0}_{1}'.format(i, j)) all_q_sym = sympy.symbols(all_q) eqs = {} for mon in ind.monoms(): ind_coeff = ind.coeff_monomial(mon) poly_coeff = poly.coeff_monomial(mon) if ind_coeff in eqs.keys(): print("duplicate! " + str(ind_coeff)) eqs[ind_coeff] = poly_coeff As = [] bs = [] for lhs in eqs.keys(): bs.append(eqs[lhs]) lhsp = lhs.as_poly(all_q_sym) A = sympy.zeros(n) for monom in lhsp.monoms(): coeff = lhsp.coeff_monomial(monom) index = next((i for i, x in enumerate(monom) if x), None) symbol = all_q[index][1:] ij = symbol.split("_") i = int(ij[0]) j = int(ij[1]) if i == j: A[i, j] = coeff else: A[i, j] = A[j, i] = 0.5 * coeff As.append(A) return As, bs
def __init__(self, dom, *gens, **opts): if not gens: raise GeneratorsNeeded("generators not specified") lev = len(gens) - 1 self.ngens = len(gens) self.zero = self.dtype.zero(lev, dom, ring=self) self.one = self.dtype.one(lev, dom, ring=self) self.domain = self.dom = dom self.symbols = self.gens = gens # NOTE 'order' may not be set if inject was called through CompositeDomain self.order = opts.get('order', monomial_key(self.default_order))
def get_monomials_of_certain_degree(self, degree): """ Returns ======= monomials: list A list of monomials of a certain degree. """ monomials = [Mul(*monomial) for monomial in combinations_with_replacement(self.variables, degree)] return sorted(monomials, reverse=True, key=monomial_key('lex', self.variables))
def __init__(self, dom, *gens, **opts): if not gens: raise GeneratorsNeeded("generators not specified") lev = len(gens) - 1 self.ngens = len(gens) self.zero = self.dtype.zero(lev, dom, ring=self) self.one = self.dtype.one(lev, dom, ring=self) self.domain = self.dom = dom self.symbols = self.gens = gens # NOTE 'order' may not be set if inject was called through CompositeDomain self.order = opts.get('order', monomial_key(self.default_order))
def cuda_s_poly2(cp, ring): """ Another version of s_poly that just calculates each step in separate kernels. and reindexes the monomials on the host in between. May be improved by use of a cuda stream in CUDA-C or PyCUDA """ order = ring.order modulus = ring.domain.mod nvars = len(ring.symbols) # Multiply step f = cp[2] g = cp[5] um = np.array(flatten(cp[1]), dtype=np.uint16) vm = np.array(flatten(cp[4]), dtype=np.uint16) fsm = np.array([Sign(f)[0]] + Polyn(f).monoms(), dtype=np.uint16) gsm = np.array([Sign(g)[0]] + Polyn(f).monoms(), dtype=np.uint16) fc = np.array(Polyn(f).coeffs(), dtype=np.uint16) gc = np.array(Polyn(g).coeffs(), dtype=np.uint16) fsm_dest = np.zeros_like(fsm) gsm_dest = np.zeros_like(gsm) fc_dest = np.zeros_like(fc) gc_dest = np.zeros_like(gc) # launch kernel spoly_mul_numba_kernel(fsm_dest, gsm_dest, fc_dest, gc_dest, fsm, gsm, fc, gc, um, vm, nvars, modulus) # Sub Step # Get all monomials in both umf, vmg, sort by ordering, reindex # f, g in a 2d coefficient array, send to other kernel fnew_monoms = [tuple(f) for f in fsm_dest] gnew_monoms = [tuple(g) for g in gsm_dest] fnew_sig = fnew_monoms[0] gnew_sig = gnew_sig[0] all_monoms = set(fnew_monoms).union(set(gnew_monoms)) all_monoms = sorted(all_monoms, key=monomial_key(order=ring.order), reverse=True) return None
def taylor(p, H, n=3, mord='grlex' ): # important, p MUST be a polynomial with Xlist as generators global NIND, Xlist if type(p) != type(Poly(0, Xlist)): p = Poly(p, Xlist) xInd = Xlist[:NIND] sub0 = {x: 0 for x in xInd} Hi = ext2int(H) mons = sorted(itermonomials(xInd, n), key=monomial_key(mord, xInd)) coefflist = [((onestepstarH(deltastar(p, mon2list(m, xInd), Hi[0]), Hi) / 1).subs(sub0)) / fact(m, xInd) for m in mons] #print(mons,coefflist) return sum([ c * m for c, m in zip(coefflist, mons) ]) # Poly(sum([c*m for c,m in zip(coefflist,mons) ]),Xlist[:NIND])/1
def get_dixon_matrix(self, polynomial): r""" Construct the Dixon matrix from the coefficients of polynomial \alpha. Each coefficient is viewed as a polynomial of x_1, ..., x_n. """ # A list of coefficients (in x_i, ..., x_n terms) of the power # products a_1, ..., a_n in Dixon's polynomial. coefficients = polynomial.coeffs() monomials = list(itermonomials(self.variables, self.get_upper_degree())) monomials = sorted(monomials, reverse=True, key=monomial_key('lex', self.variables)) dixon_matrix = Matrix([[Poly(c, *self.variables).coeff_monomial(m) for m in monomials] for c in coefficients]) keep = [column for column in range(dixon_matrix.shape[-1]) if any([element != 0 for element in dixon_matrix[:, column]])] return dixon_matrix[:, keep]
def get_dixon_matrix(self, polynomial): r""" Construct the Dixon matrix from the coefficients of polynomial \alpha. Each coefficient is viewed as a polynomial of x_1, ..., x_n. """ # A list of coefficients (in x_i, ..., x_n terms) of the power # products a_1, ..., a_n in Dixon's polynomial. coefficients = polynomial.coeffs() max_degrees = [ max( degree_list(Poly(poly, self.variables))[i] for poly in coefficients) for i in range(self.n) ] print('max_degrees = ', max_degrees, '\n') monomials = list(itermonomials_degree_list(self.variables, max_degrees)) monomials = sorted(monomials, reverse=True, key=monomial_key('lex', self.variables)) print('monomials - column headers :: ', monomials, '\n') dixon_matrix = Matrix( [[Poly(c, *self.variables).coeff_monomial(m) for m in monomials] for c in coefficients]) keep = [ column for column in range(dixon_matrix.shape[-1]) if any([element != 0 for element in dixon_matrix[:, column]]) ] return dixon_matrix[:, keep]
def fglm(self, order): """ Convert a Groebner basis from one ordering to another. The FGLM algorithm converts reduced Groebner bases of zero-dimensional ideals from one ordering to another. This method is often used when it is infeasible to compute a Groebner basis with respect to a particular ordering directly. Examples ======== >>> from sympy.abc import x, y >>> from sympy import groebner >>> F = [x**2 - 3*y - x + 1, y**2 - 2*x + y - 1] >>> G = groebner(F, x, y, order='grlex') >>> list(G.fglm('lex')) [2*x - y**2 - y + 1, y**4 + 2*y**3 - 3*y**2 - 16*y + 7] >>> list(groebner(F, x, y, order='lex')) [2*x - y**2 - y + 1, y**4 + 2*y**3 - 3*y**2 - 16*y + 7] References ========== J.C. Faugere, P. Gianni, D. Lazard, T. Mora (1994). Efficient Computation of Zero-dimensional Groebner Bases by Change of Ordering """ opt = self._options src_order = opt.order dst_order = monomial_key(order) if src_order == dst_order: return self if not self.is_zero_dimensional: raise NotImplementedError( "can't convert Groebner bases of ideals with positive dimension" ) polys = list(self._basis) domain = opt.domain opt = opt.clone(dict( domain=domain.get_field(), order=dst_order, )) from sympy.polys.rings import xring _ring, _ = xring(opt.gens, opt.domain, src_order) for i, poly in enumerate(polys): poly = poly.set_domain(opt.domain).rep.to_dict() polys[i] = _ring.from_dict(poly) G = matrix_fglm(polys, _ring, dst_order) G = [Poly._from_dict(dict(g), opt) for g in G] if not domain.is_Field: G = [g.clear_denoms(convert=True)[1] for g in G] opt.domain = domain return self._new(G, opt)
def special_constraint(constraint, kind): """special constraints are the following inequalities (1) x + y <= 1 | xy (2) x1 + x2 + x3 <= 1 | x1x2 + x1x3 + x2x3 (3) x <= y | x - xy (4) x = y | x + y - 2xy (5) x + y >= 1 | 1- x- y + xy (6) x + y = 1 | 1 - x- y + 2xy Parameters ---------- constraint : sympy.core.expr.Expr or subclasses constraint kind : string 'lt', 'gt' or 'eq' Returns ------- sympy.core.expr.Expr, bool constraint and Boolean, if it is a special constraint """ constraint_as_dict = Poly(constraint).as_expr().as_coefficients_dict() constant = constraint_as_dict[1] if constant == 0: del constraint_as_dict[1] length = len(constraint_as_dict) else: length = len(constraint_as_dict) del constraint_as_dict[1] sufficient_cond = [all( coeff==1 or coeff==-1 for coeff in constraint_as_dict.values()), constant in [0, -1], length <= 4] if not all(sufficient_cond): return constraint, False condition_eq_1_2 = [any([length == 3, length == 4]), kind == 'lt', all(coeff==1 for coeff in constraint_as_dict.values()), constant==-1] condition_eq_3_4 = [length == 2, any([kind=='eq', kind=='lt']), sum(constraint_as_dict.values())==0, constant==0] condition_eq_5_6 = [length == 3, any([kind=='eq', kind == 'gt']), all(coeff==1 for coeff in constraint_as_dict.values()), constant==-1] ### x + y <= 1, x + y + z <= 1 if all(condition_eq_1_2): var_combinations = sorted( itermonomials(list(constraint.free_symbols), 2), key=monomial_key('lex', list(constraint.free_symbols)) ) new_constraint = sum([ func for func in var_combinations if (not func.is_integer) and Poly(func).is_multivariate ]) return new_constraint, True ### x <= y , x = y elif all(condition_eq_3_4): if kind == 'lt': new_constraint = [var for var, coeff in constraint_as_dict.items() if coeff==-1][0] var_combinations = sorted( itermonomials(list(constraint.free_symbols), 2), key=monomial_key('lex', list(constraint.free_symbols)) ) new_constraint -= [term for term in var_combinations if term.is_Mul][0] return new_constraint, True if kind == 'eq' : var_combinations = sorted( itermonomials(list(constraint.free_symbols), 2), key=monomial_key('lex', list(constraint.free_symbols)) ) new_constraint = 0 for term in var_combinations: if term.is_symbol: new_constraint += term elif term.is_Mul: new_constraint -= 2*term return new_constraint, True ### x + y >= 1, x + y = 1 if all(condition_eq_5_6): var_combinations = sorted( itermonomials(list(constraint.free_symbols), 2), key=monomial_key('lex', list(constraint.free_symbols)) ) new_constraint = 0 for term in var_combinations: if term.is_integer or term.is_Mul: new_constraint += term if term.is_Mul and kind=='eq': new_constraint += term if term.is_symbol and kind=='gt': new_constraint -= term if term.is_symbol and kind == 'eq': new_constraint -= 2*term return new_constraint, True return constraint, False
def test_monomial_key(): assert monomial_key() == lex assert monomial_key("lex") == lex assert monomial_key("grlex") == grlex assert monomial_key("grevlex") == grevlex raises(ValueError, lambda: monomial_key("foo")) raises(ValueError, lambda: monomial_key(1)) M = [ x, x**2 * z**2, x * y, x**2, S.One, y**2, x**3, y, z, x * y**2 * z, x**2 * y**2, ] assert sorted(M, key=monomial_key("lex", [z, y, x])) == [ S.One, x, x**2, x**3, y, x * y, y**2, x**2 * y**2, z, x * y**2 * z, x**2 * z**2, ] assert sorted(M, key=monomial_key("grlex", [z, y, x])) == [ S.One, x, y, z, x**2, x * y, y**2, x**3, x**2 * y**2, x * y**2 * z, x**2 * z**2, ] assert sorted(M, key=monomial_key("grevlex", [z, y, x])) == [ S.One, x, y, z, x**2, x * y, y**2, x**3, x**2 * y**2, x**2 * z**2, x * y**2 * z, ]
def PolynomialRing(dom, *gens, **opts): r""" Create a generalized multivariate polynomial ring. A generalized polynomial ring is defined by a ground field `K`, a set of generators (typically `x_1, \dots, x_n`) and a monomial order `<`. The monomial order can be global, local or mixed. In any case it induces a total ordering on the monomials, and there exists for every (non-zero) polynomial `f \in K[x_1, \dots, x_n]` a well-defined "leading monomial" `LM(f) = LM(f, >)`. One can then define a multiplicative subset `S = S_> = \{f \in K[x_1, \dots, x_n] | LM(f) = 1\}`. The generalized polynomial ring corresponding to the monomial order is `R = S^{-1}K[x_1, \dots, x_n]`. If `>` is a so-called global order, that is `1` is the smallest monomial, then we just have `S = K` and `R = K[x_1, \dots, x_n]`. Examples ======== A few examples may make this clearer. >>> from sympy.abc import x, y >>> from sympy import QQ Our first ring uses global lexicographic order. >>> R1 = QQ.old_poly_ring(x, y, order=(("lex", x, y),)) The second ring uses local lexicographic order. Note that when using a single (non-product) order, you can just specify the name and omit the variables: >>> R2 = QQ.old_poly_ring(x, y, order="ilex") The third and fourth rings use a mixed orders: >>> o1 = (("ilex", x), ("lex", y)) >>> o2 = (("lex", x), ("ilex", y)) >>> R3 = QQ.old_poly_ring(x, y, order=o1) >>> R4 = QQ.old_poly_ring(x, y, order=o2) We will investigate what elements of `K(x, y)` are contained in the various rings. >>> L = [x, 1/x, y/(1 + x), 1/(1 + y), 1/(1 + x*y)] >>> test = lambda R: [f in R for f in L] The first ring is just `K[x, y]`: >>> test(R1) [True, False, False, False, False] The second ring is R1 localised at the maximal ideal (x, y): >>> test(R2) [True, False, True, True, True] The third ring is R1 localised at the prime ideal (x): >>> test(R3) [True, False, True, False, True] Finally the fourth ring is R1 localised at `S = K[x, y] \setminus yK[y]`: >>> test(R4) [True, False, False, True, False] """ order = opts.get("order", GeneralizedPolynomialRing.default_order) if iterable(order): order = build_product_order(order, gens) order = monomial_key(order) opts['order'] = order if order.is_global: return GlobalPolynomialRing(dom, *gens, **opts) else: return GeneralizedPolynomialRing(dom, *gens, **opts)
def PolynomialRing(dom, *gens, **opts): r""" Create a generalized multivariate polynomial ring. A generalized polynomial ring is defined by a ground field `K`, a set of generators (typically `x_1, \dots, x_n`) and a monomial order `<`. The monomial order can be global, local or mixed. In any case it induces a total ordering on the monomials, and there exists for every (non-zero) polynomial `f \in K[x_1, \dots, x_n]` a well-defined "leading monomial" `LM(f) = LM(f, >)`. One can then define a multiplicative subset `S = S_> = \{f \in K[x_1, \dots, x_n] | LM(f) = 1\}`. The generalized polynomial ring corresponding to the monomial order is `R = S^{-1}K[x_1, \dots, x_n]`. If `>` is a so-called global order, that is `1` is the smallest monomial, then we just have `S = K` and `R = K[x_1, \dots, x_n]`. Examples ======== A few examples may make this clearer. >>> from sympy.abc import x, y >>> from sympy import QQ Our first ring uses global lexicographic order. >>> R1 = QQ.old_poly_ring(x, y, order=(("lex", x, y),)) The second ring uses local lexicographic order. Note that when using a single (non-product) order, you can just specify the name and omit the variables: >>> R2 = QQ.old_poly_ring(x, y, order="ilex") The third and fourth rings use a mixed orders: >>> o1 = (("ilex", x), ("lex", y)) >>> o2 = (("lex", x), ("ilex", y)) >>> R3 = QQ.old_poly_ring(x, y, order=o1) >>> R4 = QQ.old_poly_ring(x, y, order=o2) We will investigate what elements of `K(x, y)` are contained in the various rings. >>> L = [x, 1/x, y/(1 + x), 1/(1 + y), 1/(1 + x*y)] >>> test = lambda R: [f in R for f in L] The first ring is just `K[x, y]`: >>> test(R1) [True, False, False, False, False] The second ring is R1 localised at the maximal ideal (x, y): >>> test(R2) [True, False, True, True, True] The third ring is R1 localised at the prime ideal (x): >>> test(R3) [True, False, True, False, True] Finally the fourth ring is R1 localised at `S = K[x, y] \setminus yK[y]`: >>> test(R4) [True, False, False, True, False] """ order = opts.get("order", GeneralizedPolynomialRing.default_order) if iterable(order): order = build_product_order(order, gens) order = monomial_key(order) opts['order'] = order if order.is_global: return GlobalPolynomialRing(dom, *gens, **opts) else: return GeneralizedPolynomialRing(dom, *gens, **opts)
#%% Misc Array Testing import numpy as np a = np.array([1, 2, 3]) b = 1 + 2j #%% Printing monomials import numpy as np from sympy import symbols from sympy.polys.monomials import itermonomials, monomial_count from sympy.polys.orderings import monomial_key x_str = "" for i in range(2): x_str += 'x_' + str(i) + ', ' x_syms = symbols(x_str) M = itermonomials(x_syms, 5) sortedM = sorted(M, key=monomial_key('grlex', np.flip(x_syms))) print(sortedM) # %%
def cuda_s_poly2(cp, r): """ Another version of s_poly that just calculates each step in separate kernels. and reindexes the monomials on the host in between. May be improved by use of a cuda stream in CUDA-C or PyCUDA """ modulus = r.domain.mod nvars = len(r.symbols) # Multiply step f = cp[2] g = cp[5] fsig_idx = Sign(f)[1] gsig_idx = Sign(g)[1] fnum = Num(f) gnum = Num(g) um = list(cp[1][0]) vm = list(cp[4][0]) # separate uc = cp[1][1] vc = cp[4][1] um = np.array(um, dtype=np.uint16) vm = np.array(vm, dtype=np.uint16) uv_coeffs = [uc, vc] uv_coeffs = np.array(uv_coeffs, dtype=np.int32) fsm = np.array([Sign(f)[0]] + Polyn(f).monoms(), dtype=np.uint16) gsm = np.array([Sign(g)[0]] + Polyn(g).monoms(), dtype=np.uint16) fc = [f for f in Polyn(f).coeffs()] fc = np.array(fc, dtype=np.int32) gc = [g for g in Polyn(g).coeffs()] gc = np.array(gc, dtype=np.int32) fsm_dest = np.zeros_like(fsm) gsm_dest = np.zeros_like(gsm) fc_dest = np.zeros_like(fc) gc_dest = np.zeros_like(gc) # prepare threads threadsperblock = (32, 32) blockspergrid_x = ceil( (fsm_dest.size + gsm_dest.size) / threadsperblock[0]) blockspergrid_y = ceil( (fsm_dest.size + gsm_dest.size) / threadsperblock[1]) blockspergrid = (blockspergrid_x, blockspergrid_y) # launch kernel spoly_mul_numba_kernel[blockspergrid, threadsperblock](fsm_dest, gsm_dest, fc_dest, gc_dest, fsm, gsm, fc, gc, um, vm, uv_coeffs, nvars, modulus) # Sub Step # Get all monomials in both umf, vmg, sort by ordering, reindex # f, g in a 2d coefficient array, send to other kernel if sum(sum(fsm_dest)) == 0: if sum(sum(gsm_dest)) == 0: return (((r.zero_monom), 0), r.from_expr('0'), 0) fnew = [tuple(f) for f in fsm_dest] gnew = [tuple(g) for g in gsm_dest] fnew_sig = fnew[0] gnew_sig = gnew[0] fnew_monoms = [f for f in fnew[1:]] gnew_monoms = [g for g in gnew[1:]] all_monoms = set(fnew_monoms).union(set(gnew_monoms)) all_monoms = sorted(all_monoms, key=monomial_key(order=r.order), reverse=True) spair_matrix = np.zeros((2, len(all_monoms)), dtype=np.int32) for fm, fc in zip(fnew_monoms, fc_dest): spair_matrix[0, all_monoms.index(fm)] = fc for gm, gc in zip(gnew_monoms, gc_dest): spair_matrix[1, all_monoms.index(gm)] = gc # Parse spair_info = parse_gpu_spoly_mul(spair_matrix, all_monoms, fnew_sig, gnew_sig, fsig_idx, gsig_idx, fnum, gnum, r) if not spair_info: return (((r.zero_monom), 0), r.from_expr('0'), 0) lb_spoly = spoly_numba_io(spair_info, r) return lb_spoly