def __new__(cls, *var, **options): if not options: self = super().__new__(ZZ) else: if "complex" in options: if options["complex"]: self = super().__new__(CC) elif "rational" in options: if options["rational"]: self = super().__new__(QQ) elif "mod" in options: validate_type(options["mod"], int) if options["mod"] < 0: raise ValueError( "modulus option must be 0 or positive integer") elif options["mod"] > 0: """ positive characteristic """ """ * Require Updates !! Given variables without relation, must return infinite objects. """ if is_prime(options["mod"]): self = super().__new__(FiniteField) else: self = super().__new__(FiniteRing) else: self = super().__new__(ZZ) else: self = super().__new__(ZZ) return self
def factor(f, deg=0): validate_type(f, Poly) validate_type(deg, int) if deg == 0: """ calculate with Cantor-Zassenhaus algorithm """ pass else: if not f.is_univariate(): raise ValueError("f must be a univatiate polynomial") var = f.get_univariate() r, q = f.degree(var) // deg, f.coeff_dom.number() dom_ = f.dom.add_quotient(f.rep) F = [f] while len(F) < r: g = poly(f.dom.random(deg=r * deg - 1, monic=True), dom=dom_) g = g**((q**deg - 1) // 2) - 1 g = poly(g.rep, *f.indet_vars, dom=f.dom) if g == 0: continue F_1 = list() while len(F) > 0: h = F.pop() if h.degree(var) <= deg: continue z = gcd(h, g) if z == 1 or z == h: F_1.append(h) else: F_1.append(z) F_1.append(h // z) F = F_1 return F
def dp_from_int(n, var): validate_type(n, int) validate_type(var, (tuple, list)) coeffs_ = [n] for v in var[1:][::-1]: coeffs_ = [dp(v, coeffs_)] return dp(var[0], coeffs_)
def symbols(c): validate_type(c, str) symbols_ = c.replace(" ", "").split(",") if len(symbols_) == 1: return symbol(symbols_[0]) else: return tuple([symbol(s) for s in symbols_])
def as_dp(f, *symbol): validate_type(f, int, Symbol, DP) if isinstance(f, int): if len(symbol) == 0: raise ValueError("needs one symbol when f is int") else: return dp(symbol[0], [f]) elif isinstance(f, Symbol): return f.as_dp() else: return f
def gcd(f, g): validate_type(f, Poly) validate_type(g, Poly) if not f.is_univariate() or not g.is_univariate(): raise TypeError("arguments must be univariate polynomials") if f.degree() < g.degree(): f, g = g, f q = f % g if q == 0: return g else: return gcd(g, q).get_monic()
def __pow__(f, e): validate_type(e, int) if e < 0: raise ValueError("exponent must be positive") if e == 0: return poly(1, *f.indet_vars, dom=f.dom) num_ = bin(e).replace('0b', '') pow_ = 1 for i in num_: pow_ = pow_ * pow_ if i == '1': pow_ = f * pow_ return pow_
def extend(self, var, rel=0): validate_type(var, Symbol) if var in self.const_vars: raise ValueError("it already has the variable '%s'" % str(var)) validate_type(rel, int, DP) const_vars_ = self.const_vars + (var, ) if rel == 0: return ring(*const_vars_, mod=self.mod, rel=self.rel) else: if self.rel == 0: return ring(*const_vars_, mod=self.mod, rel=rel) else: dps_ = self.rel.as_tuple() + (rel, ) return ring(*const_vars_, mod=self.mod, rel=dps_)
def diff(f, *var): validate_type(f, Poly) if len(var) > 1: raise ValueError( "the number of variable argument must be 0 or 1, not %s" % str(len(var))) elif len(var) == 1: var_ = var[0] sorted_vars = tuple_union(var, tuple_minus(f.inner_vars, var)) rep_ = f.rep.sort_vars(sorted_vars) else: var_ = f.indet_vars[0] rep_ = f.rep return poly(rep_.diff(var_), *f.indet_vars, dom=f.dom)
def reduce(self, rep): validate_type(rep, DP, int) if isinstance(rep, int): if self.reduction_step["mod"]: rep = rep % self.mod return rep else: reduce_ = rep if self.reduction_step["quo"]: reduce_ = _reduce(reduce_, self.quo) if self.reduction_step["rel"]: reduce_ = _reduce(reduce_, self.rel) if self.reduction_step["mod"]: reduce_ = reduce_ % self.mod return reduce_
def diff(self, var): validate_type(var, Symbol) if not var in self.inner_vars: return dp(self.var, (0, )) else: coeffs_ = list() if var == self.var: for i in range(len(self) - 1): coeffs_.append(self[i + 1] * (i + 1)) else: for c in self: if isinstance(c, int): coeffs_.append(0) else: coeffs_.append(c.diff(var)) return dp(self.var, coeffs_)
def as_dist_tuple(self, termorder="lex", with_index=False): validate_type(termorder, str) if termorder == "lex": iters, list_ = list(), list() for v in self.inner_vars[::-1]: iters.append(range(self.degree(v) + 1)[::-1]) for p in itertools.product(*iters): if with_index: list_.append((p[::-1], self[p[::-1]])) else: list_.append(self[p[::-1]]) elif termorder == "grevlex": raise NotImplementedError() else: raise TypeError("given unsupported termorder '%s'" % termorder) return tuple(list_)
def dp_from_dict(var, coeffs): validate_type(coeffs, dict) if len(var) == 0: raise ValueError("needs one variable at least") if len(var) == 1: coeffs_, i, j = [], 0, 0 while i < len(coeffs): try: coeffs_.append(coeffs[j]) i += 1 except KeyError: coeffs_.append(0) finally: j += 1 return dp(var[0], coeffs_) else: pass
def dp_from_list(var, coeffs): validate_type(coeffs, tuple, list) if len(var) == 0: raise ValueError("needs one variable at least") if len(var) == 1: return dp(var[0], coeffs) else: coeffs_ = [] for r in coeffs: if isinstance(r, list): coeffs_.append(dp_from_list(var[1:], r)) elif isinstance(r, int): coeffs_.append(r) else: raise ValueError( "elements of coeffs list must be int or dp, not %s" % r.__class__.__name__) return dp(var[0], coeffs_)
def it_dist(self, termorder="lex", with_index=False): validate_type(termorder, str) if termorder == "lex": iters = [ range(self.degree(v, non_negative=True), -1, -1) for v in self.inner_vars ] for p in itertools.product(*iters): c = self[p] if c == 0: continue if with_index: yield (p, c) else: yield c elif termorder == "grevlex": raise NotImplementedError() else: raise TypeError("given unsupported termorder '%s'" % termorder)
def subs(self, subsdict): validate_type(subsdict, dict) f_ = self for k, v in subsdict.items(): if isinstance(k, Symbol): k = as_dp(k).sort_vars(self.inner_vars) elif isinstance(k, DP): if k.is_monomial(): if k.is_monic(): k = k.sort_vars(self.inner_vars) else: raise ValueError("keys of subsdict must be monic") else: raise ValueError("keys of subsdict must be monomial") else: raise TypeError( "keys of subsdict must be Symbol or DP, not '%s'" % k.__class__.__name__) f_ = f_._subs(k, v) return f_
def __init__(self, value, *var, **options): validate_type(value, dict, tuple, list) if isinstance(value, dict): self.value_dict = value else: self.value_dict = dict() if not var: raise ValueError("require variable with value tuple") i = 0 for v in var: self.value_dict[v] = valur[0] i += 1 if "coeff_dom" in options: self.coeff_dom = options["coeff_dom"] else: self.coeff_dom = ring() if "proj" in options and options["proj"]: self.affine = False else: self.affine = True
def __init__(self, *var, **options): """ Arugments: * var: indeterminate variables * options: allowed keys are "quo" and them of Rings' """ self.indet_vars = var if "coeff_dom" in options: validate_type(options["coeff_dom"], Ring) self.coeff_dom = options["coeff_dom"] else: self.coeff_dom = ring(**options) self.reduction_step = dict() if not self.coeff_dom.mod == 0: self.mod = self.coeff_dom.mod self.reduction_step["mod"] = True else: self.mod = 0 self.reduction_step["mod"] = False if not self.coeff_dom.rel == 0: self.rel = relation(self.coeff_dom.rel) self.reduction_step["rel"] = True else: self.rel = 0 self.reduction_step["rel"] = False self.const_vars = self.coeff_dom.const_vars if "quo" in options and not isinstance(options["quo"], int): self.quo = relation(options["quo"]) self.reduction_step["quo"] = True else: self.quo = 0 self.reduction_step["quo"] = False
def it_dist(self, termorder="lex", with_index=False, zero_skip=True): """ generate coefficients of each index of exponents, return int or DP object with index tuple if with_index is True. """ validate_type(termorder, str) if termorder == "lex": iters = [ range(self.degree(v, non_negative=True), -1, -1) for v in self.indet_vars ] for p in itertools.product(*iters): c = self.rep[p] if zero_skip and c == 0: continue if with_index: yield (p, c) else: yield c elif termorder == "grevlex": raise NotImplementedError() else: raise TypeError("given unsupported termorder '%s'" % termorder)
def __init__(self, rep, *var, **options): if isinstance(rep, Poly): self.rep = rep.rep self.indet_vars = rep.indet_vars self.const_vars = rep.const_vars self.inner_vars = rep.inner_vars self.coeff_dom = rep.coeff_dom self.dom = rep.dom else: if isinstance(rep, DP): pass elif isinstance(rep, int): rep = dp_from_int(rep, var) elif isinstance(rep, Symbol): rep = rep.as_dp() else: raise TypeError("rep must be Poly or DP, not %s" % rep.__class__.__name__) """ * Set domain options Given "dom" option, initialize with it. Not given, construct PolynomialRing object and set to "dom" option """ if "dom" in options: validate_type(options["dom"], PolynomialRing) dom = options["dom"] self.indet_vars, self.const_vars = self._set_var( rep, tuple_union(dom.indet_vars, var)) self.inner_vars = tuple_union(self.indet_vars, self.const_vars) self.coeff_dom = ring(*self.const_vars, mod=dom.coeff_dom.mod, rel=dom.coeff_dom.rel) self.dom = polynomialring(*self.indet_vars, coeff_dom=self.coeff_dom, quo=dom.quo) else: self.indet_vars, self.const_vars = self._set_var(rep, var) self.inner_vars = tuple_union(self.indet_vars, self.const_vars) if "coeff_dom" in options: validate_type(options["coeff_dom"], Ring) self.coeff_dom = options["coeff_dom"] else: if "mod" in options: validate_type(options["mod"], int) mod = options["mod"] else: mod = 0 if "rel" in options: validate_type(options["rel"], int, tuple, DP, Relation) rel = options["rel"] else: rel = 0 self.coeff_dom = ring(*self.const_vars, mod=mod, rel=rel) if len(self.coeff_dom.const_vars) == 0: pass else: self.rep = self.rep.sort_vars( tuple_union(self.inner_vars, self.coeff_dom.const_vars)) if "quo" in options: validate_type(options["rel"], int, tuple, DP, Relation) quo = options["rel"] else: quo = 0 self.dom = polynomialring(*self.indet_vars, coeff_dom=self.coeff_dom, quo=quo) self.rep = self.reduce()
def LC(f, termorder="lex"): validate_type(f, Poly) lc_ = next(f.it_dist(zero_skip=False)) return poly(lc_, *f.indet_vars, dom=f.dom)
def __init__(self, char): validate_type(char, str) self.char = char
def __mul__(p, n): validate_type(n, int, DP) for v in self: self[v] *= n
def symbol(c): validate_type(c, str) return Symbol(c)