def _eval_(self, x): r""" EXAMPLES:: sage: fresnel_cos(pi) fresnel_cos(pi) sage: fresnel_cos(oo) 1/2 sage: fresnel_cos(-oo) -1/2 sage: fresnel_cos(I*oo) 1/2*I sage: fresnel_cos(-I*oo) -1/2*I """ if isinstance(x, Expression): if x.is_negative(): return -fresnel_cos(-x) if x.is_trivial_zero(): return x if x.is_infinity(): if x.is_positive_infinity(): return Rational((1, 2)) elif x.imag_part().is_positive_infinity(): return I * Rational((1, 2)) elif x.imag_part().is_negative_infinity(): return -I * Rational((1, 2)) elif x < 0: return -fresnel_cos(-x) elif not x: return x
def dc_calc_gauss(modulus, number): arg = request.args.get("val", []) if not arg: return flask.abort(404) try: if modulus == 1: # there is a bug in sage for modulus = 1 return r"""\(\displaystyle \tau_{%s}(\chi_{1}(1,·)) = \sum_{r\in \mathbb{Z}/\mathbb{Z}} \chi_{1}(1,r) 1^{%s}= 1. \)""" % ( int(arg), int(arg)) from dirichlet_conrey import DirichletGroup_conrey chi = DirichletGroup_conrey(modulus)[number] chi = chi.sage_character() g = chi.gauss_sum_numerical(100, int(arg)) real = round(g.real(), 10) imag = round(g.imag(), 10) if imag == 0.: g = str(real) elif real == 0.: g = str(imag) + "i" else: g = latex(g) from sage.rings.rational import Rational x = Rational('%s/%s' % (int(arg), modulus)) n = x.numerator() n = str(n) + "r" if not n == 1 else "r" d = x.denominator() return r"\(\displaystyle \tau_{%s}(\chi_{%s}(%s,·)) = \sum_{r\in \mathbb{Z}/%s\mathbb{Z}} \chi_{%s}(%s,r) e\left(\frac{%s}{%s}\right) = %s. \)" % ( int(arg), modulus, number, modulus, modulus, number, n, d, g) except Exception, e: return "<span style='color:red;'>ERROR: %s</span>" % e
def dc_calc_gauss(modulus, number): arg = request.args.get("val", []) if not arg: return flask.abort(404) try: if modulus == 1: # there is a bug in sage for modulus = 1 return r"""\(\displaystyle \tau_{%s}(\chi_{1}(1,·)) = \sum_{r\in \mathbb{Z}/\mathbb{Z}} \chi_{1}(1,r) 1^{%s}= 1. \)""" % (int(arg), int(arg)) from dirichlet_conrey import DirichletGroup_conrey chi = DirichletGroup_conrey(modulus)[number] chi = chi.sage_character() g = chi.gauss_sum_numerical(100, int(arg)) real = round(g.real(), 10) imag = round(g.imag(), 10) if imag == 0.: g = str(real) elif real == 0.: g = str(imag) + "i" else: g = latex(g) from sage.rings.rational import Rational x = Rational('%s/%s' % (int(arg), modulus)) n = x.numerator() n = str(n) + "r" if not n == 1 else "r" d = x.denominator() return r"\(\displaystyle \tau_{%s}(\chi_{%s}(%s,·)) = \sum_{r\in \mathbb{Z}/%s\mathbb{Z}} \chi_{%s}(%s,r) e\left(\frac{%s}{%s}\right) = %s. \)" % (int(arg), modulus, number, modulus, modulus, number, n, d, g) except Exception, e: return "<span style='color:red;'>ERROR: %s</span>" % e
def circle_image(A, B): G = Graphics() G += circle((0, 0), 1, color='grey') from collections import defaultdict tmp = defaultdict(int) for a in A: for j in range(a): if gcd(j, a) == 1: rational = Rational(j) / Rational(a) tmp[(rational.numerator(), rational.denominator())] += 1 for b in B: for j in range(b): if gcd(j, b) == 1: rational = Rational(j) / Rational(b) tmp[(rational.numerator(), rational.denominator())] -= 1 C = ComplexField() for val in tmp: if tmp[val] > 0: G += text(str(tmp[val]), exp(C(-.2 + 2 * 3.14159 * I * val[0] / val[1])), fontsize=30, axes=False, color="green") if tmp[val] < 0: G += text(str(abs(tmp[val])), exp(C(.2 + 2 * 3.14159 * I * val[0] / val[1])), fontsize=30, axes=False, color="blue") return G
def piecewise_linear_image(A,B): # Jumps up and down going around circle, not used v = circle_drops(A,B) G = Graphics() w = [(Rational(i)/len(v), j) for i,j in enumerate(v)] for pt in w: G += line([(pt[0],pt[1]),(pt[0]+Rational(1)/len(w),pt[1])]) return G
def piecewise_constant_image(A, B): # Jumps up and down going around circle, not used v = circle_drops(A, B) G = Graphics() w = ((Rational(i) / len(v), j) for i, j in enumerate(v)) for p0, p1 in w: G += line([(p0, p1), (p0 + Rational(1) / len(w), p1)]) return G
def gauss_sum(self, val): val = int(val) mod, num = self.modulus, self.number chi = self.chi.sage_character() g = chi.gauss_sum_numerical(100, val) g = complex2str(g) from sage.rings.rational import Rational x = Rational('%s/%s' % (val, mod)) n = x.numerator() n = str(n) + "r" if not n == 1 else "r" d = x.denominator() Gtex = '\Z/%s\Z' % mod chitex = self.char2tex(mod, num, tag=False) chitexr = self.char2tex(mod, num, 'r', tag=False) deftex = r'\sum_{r\in %s} %s e\left(\frac{%s}{%s}\right)'%(Gtex,chitexr,n,d) return r"\(\displaystyle \tau_{%s}(%s) = %s = %s. \)" % (val, chitex, deftex, g)
def schonheim(v, k, t): r""" Schonheim lower bound for size of covering design INPUT: v -- integer, size of point set k -- integer, cardinality of each block t -- integer, cardinality of sets being covered OUTPUT: The Schonheim lower bound for such a covering design's size: $C(v,k,t) \leq \lceil(\frac{v}{k} \lceil \frac{v-1}{k-1} \cdots \lceil \frac{v-t+1}{k-t+1} \rceil \cdots \rceil \rceil$ EXAMPLES: sage: from sage.combinat.designs.covering_design import schonheim sage: schonheim(10,3,2) 17 sage: schonheim(32,16,8) 930 """ bound = 1 for i in range(t - 1, -1, -1): bound = Rational((bound * (v - i), k - i)).ceil() return bound
def __call__(self, r, base_at_infinity=True): r""" Evaluates the modular symbol at {0,`r`} or {oo,`r`}. EXAMPLES:: sage: m = EllipticCurve('11a1').modular_symbol(implementation="eclib") sage: m(0) 1/5 """ from sage.rings.rational import Rational if r != oo: r = Rational(r) r = r.numer() % r.denom() / r.denom() return self._modsym(r, sign=self._sign, base_at_infinity=base_at_infinity) * self._scaling
def evalpolelt(label, gen, genlabel='a'): """ label is a compact polynomial expression in genlabel ( '*' and '**' are removed ) """ res = 0 regexp = r'([+-]?)([+-]?\d*o?\d*)(%s\d*)?' % genlabel for m in re.finditer(regexp, label): s, c, e = m.groups() if c == '' and e is None: break if c == '': c = 1 else: """ c may be an int or a rational a/b """ from sage.rings.rational import Rational c = str(c).replace('o', '/') c = Rational(c) if s == '-': c = -c if e is None: e = 0 elif e == genlabel: e = 1 else: e = int(e[1:]) res += c * gen**e return res
def _solve_problem(self, problem): """Solve the division problem in PBW basis.""" basis = [ self._partition_to_PBW(partition) for partition in self._multidegree_to_root_sum(problem["deg"]) ] if problem["side"] == "right": LHS = [p * problem["known_LHS"] for p in basis] if problem["side"] == "left": LHS = [problem["known_LHS"] * p for p in basis] target_basis = { tuple(partition): i for i, partition in enumerate( self._multidegree_to_root_sum(problem["deg_RHS"])) } A = self._vectorize_polynomials_list(LHS, target_basis) b = self._vectorize_polynomial(problem["RHS"], target_basis) sol = A.T.solve_right(b) output = sum(Rational(c) * basis[i] for i, c in enumerate(sol)) self.maps[problem["edge"]] = output
def place_list(self,mx,Mx,frac=1,mark_origin=True): """ return a tuple of 1. values that are all the integer multiple of <frac>*self.numerical_value between mx and Mx 2. the multiple of the basis unit. Give <frac> as literal real. Recall that python evaluates 1/2 to 0. If you pass 0.5, it will be converted back to 1/2 for a nice display. """ try : frac=Rational(frac) # If the user enters "0.5", it is converted to 1/2 except TypeError : pass if frac==0: raise ValueError,"frac is zero in AxesUnit.place_list(). Maybe you ignore that python evaluates 1/2 to 0 ? (writes literal 0.5 instead) \n Or are you trying to push me in an infinite loop ?" l=[] k=var("TheTag") for x in MultipleBetween(frac*self.numerical_value,mx,Mx,mark_origin): if self.latex_symbol == "": l.append((x,"$"+latex(x)+"$")) else : pos=(x/self.numerical_value)*k text="$"+latex(pos).replace("TheTag",self.latex_symbol)+"$" # This risks to be Sage-version dependent. l.append((x,text)) return l
def __init__(self,numerical_value,latex_symbol=""): try : numerical_value=Rational(numerical_value) except TypeError : pass self.numerical_value=numerical_value self.latex_symbol=latex_symbol
def convert_symbolic_to_polynomial(symbolic_poly,poly_ring,sym_vars): try: c = Rational(symbolic_poly) return c*poly_ring.one() except: pass base_ring = poly_ring.base_ring() poly = symbolic_poly.polynomial(base_ring) p_vars = symbolic_poly.variables() var_map = {} for v in p_vars: for i,s_v in enumerate(sym_vars): if v==s_v: var_map[v] = poly_ring.gens()[i] final_poly = poly_ring.zero() if len(p_vars)==1: for e,c in zip(poly.exponents(),poly.coefficients()): final_poly = final_poly + c*var_map[p_vars[0]]**e else: for e,c in zip(poly.exponents(),poly.coefficients()): mon = c*poly_ring.one() for e_i,e_m in enumerate(e): mon = mon * var_map[p_vars[e_i]]**e_m final_poly = final_poly + mon return final_poly
def __call__(self, r): r""" Evaluates the modular symbol at `r`. EXAMPLES:: sage: m = EllipticCurve('11a1').modular_symbol(use_eclib=True) sage: m(0) 1/5 """ # this computes {0,oo} - {0,r} = {r,oo} from sage.rings.rational import Rational if r != oo: r = Rational(r) r = r.numer() % r.denom() / r.denom() return (self._atzero - self._modsym(r)) * self._scaling
def __call__(self, r): r""" Evaluates the modular symbol at `r`. EXAMPLES:: sage: m = EllipticCurve('11a1').modular_symbol(implementation="eclib") sage: m(0) 1/5 """ # this computes {0,oo} - {0,r} = {r,oo} from sage.rings.rational import Rational if r != oo: r = Rational(r) r = r.numer() % r.denom() / r.denom() return (self._atzero - self._modsym(r))*self._scaling
def _sympysage_rational(self): """ EXAMPLES:: sage: from sympy.core.numbers import Rational sage: assert SR(-5/7)._sympy_() == Rational(int(-5),int(7)) sage: assert SR(-5/7) == Rational(int(-5),int(7))._sage_() """ from sage.rings.integer import Integer from sage.rings.rational import Rational return Rational((Integer(self.p), Integer(self.q)))
def extract(cls, obj): """ Takes an object extracted by the json parser and decodes the special-formating dictionaries used to store special types. """ if isinstance(obj, dict) and 'data' in obj: if len(obj) == 2 and '__ComplexList__' in obj: return [complex(*v) for v in obj['data']] elif len(obj) == 2 and '__QQList__' in obj: return [QQ(tuple(v)) for v in obj['data']] elif len(obj) == 3 and '__NFList__' in obj and 'base' in obj: base = cls.extract(obj['base']) return [cls._extract(base, c) for c in obj['data']] elif len(obj) == 2 and '__IntDict__' in obj: return {Integer(k): cls.extract(v) for k,v in obj['data']} elif len(obj) == 3 and '__Vector__' in obj and 'base' in obj: base = cls.extract(obj['base']) return vector([cls._extract(base, v) for v in obj['data']]) elif len(obj) == 2 and '__Rational__' in obj: return Rational(*obj['data']) elif len(obj) == 3 and '__RealLiteral__' in obj and 'prec' in obj: return LmfdbRealLiteral(RealField(obj['prec']), obj['data']) elif len(obj) == 2 and '__complex__' in obj: return complex(*obj['data']) elif len(obj) == 3 and '__Complex__' in obj and 'prec' in obj: return ComplexNumber(ComplexField(obj['prec']), *obj['data']) elif len(obj) == 3 and '__NFElt__' in obj and 'parent' in obj: return cls._extract(cls.extract(obj['parent']), obj['data']) elif len(obj) == 3 and ('__NFRelative__' in obj or '__NFAbsolute__' in obj) and 'vname' in obj: poly = cls.extract(obj['data']) return NumberField(poly, name=obj['vname']) elif len(obj) == 2 and '__NFCyclotomic__' in obj: return CyclotomicField(obj['data']) elif len(obj) == 2 and '__IntegerRing__' in obj: return ZZ elif len(obj) == 2 and '__RationalField__' in obj: return QQ elif len(obj) == 3 and '__RationalPoly__' in obj and 'vname' in obj: return QQ[obj['vname']]([QQ(tuple(v)) for v in obj['data']]) elif len(obj) == 4 and '__Poly__' in obj and 'vname' in obj and 'base' in obj: base = cls.extract(obj['base']) return base[obj['vname']]([cls._extract(base, c) for c in obj['data']]) elif len(obj) == 5 and '__PowerSeries__' in obj and 'vname' in obj and 'base' in obj and 'prec' in obj: base = cls.extract(obj['base']) prec = infinity if obj['prec'] == 'inf' else int(obj['prec']) return base[[obj['vname']]]([cls._extract(base, c) for c in obj['data']], prec=prec) elif len(obj) == 2 and '__date__' in obj: return datetime.datetime.strptime(obj['data'], "%Y-%m-%d").date() elif len(obj) == 2 and '__time__' in obj: return datetime.datetime.strptime(obj['data'], "%H:%M:%S.%f").time() elif len(obj) == 2 and '__datetime__' in obj: return datetime.datetime.strptime(obj['data'], "%Y-%m-%d %H:%M:%S.%f") return obj
def gauss_sum(self, val): val = int(val) mod, num = self.modulus, self.number chi = self.chi.sage_character() g = chi.gauss_sum_numerical(100, val) real = round(g.real(), 10) imag = round(g.imag(), 10) if imag == 0.: g = str(real) elif real == 0.: g = str(imag) + "i" else: g = latex(g) from sage.rings.rational import Rational x = Rational('%s/%s' % (val, mod)) n = x.numerator() n = str(n) + "r" if not n == 1 else "r" d = x.denominator() Gtex = '\mathbb{Z}/%s\mathbb{Z}' % mod chitex = self.char2tex(mod, num, tag=False) chitexr = self.char2tex(mod, num, 'r', tag=False) deftex = r'\sum_{r\in %s} %s e\left(\frac{%s}{%s}\right)'%(Gtex,chitexr,n,d) return r"\(\displaystyle \tau_{%s}(%s) = %s = %s. \)" % (val, chitex, deftex, g)
def circle_image(A, B): G = Graphics() G += circle((0, 0), 1, color='black', thickness=3) G += circle( (0, 0), 1.4, color='black', alpha=0 ) # This adds an invisible framing circle to the plot, which protects the aspect ratio from being skewed. from collections import defaultdict tmp = defaultdict(int) for a in A: for j in range(a): if gcd(j, a) == 1: rational = Rational(j) / Rational(a) tmp[(rational.numerator(), rational.denominator())] += 1 for b in B: for j in range(b): if gcd(j, b) == 1: rational = Rational(j) / Rational(b) tmp[(rational.numerator(), rational.denominator())] -= 1 C = ComplexField() color1 = (41 / 255, 95 / 255, 45 / 255) color2 = (0 / 255, 0 / 255, 150 / 255) for val in tmp: if tmp[val] > 0: G += text(str(tmp[val]), exp(C(-.2 + 2 * 3.14159 * I * val[0] / val[1])), fontsize=30, axes=False, color=color1) if tmp[val] < 0: G += text(str(abs(tmp[val])), exp(C(.2 + 2 * 3.14159 * I * val[0] / val[1])), fontsize=30, axes=False, color=color2) return G
def create_from_singular_matrix(cls, poly_ring, singular_output, matrix_name="MM"): mat = {} for line in singular_output.split('\n'): if line.find(matrix_name) == 0: indices = line.split('[')[1] indices = indices.split(']')[0] indices = indices.split(',') indices = [int(i) for i in indices] eqn = line.split('=')[1] eq = poly_ring.zero() for mon_pos in eqn.split('+'): for i, mon in enumerate(mon_pos.split('-')): if i == 0: coeff = poly_ring.one() else: coeff = -poly_ring.one() for part in mon.split('*'): try: coeff = coeff * Rational(part) except: try: num = part.split('(')[1] num = num.split(')')[0] num = Integer(num) try: pow = Integer(part.split('^')[1]) except: pow = 1 coeff = coeff * poly_ring.gens()[num - 1]**pow except: pass if mon != '': eq = eq + coeff mat[(indices[0], indices[1])] = eq ngens = max([k[1] for k in mat.iterkeys()]) nel = max([k[0] for k in mat.iterkeys()]) gens = [] for i in range(ngens): gen = [] for j in range(nel): gen.append(mat[(j + 1, i + 1)]) gens.append(gen) return SingularModule(gens)
def _rational_(self): r""" TESTS:: sage: UCF = UniversalCyclotomicField() sage: QQ(UCF.zero()) # indirect doctest 0 sage: parent(_) Rational Field sage: QQ(UCF.one()) # indirect doctest 1 sage: parent(_) Rational Field sage: QQ(E(3)/2 + E(3,2)/2) # indirect doctest -1/2 """ if not self._obj.IsRat(): raise TypeError("Unable to coerce to a rational") return Rational(self._obj.sage())
def circle_image(A,B): G = Graphics() G += circle((0,0), 1 , color = 'grey') from collections import defaultdict tmp = defaultdict(int) for a in A: for j in range(a): if gcd(j,a) == 1: rational = Rational(j)/Rational(a) tmp[(rational.numerator(),rational.denominator())] += 1 for b in B: for j in range(b): if gcd(j,b) == 1: rational = Rational(j)/Rational(b) tmp[(rational.numerator(),rational.denominator())] -= 1 C = ComplexField() for val in tmp: if tmp[val] > 0: G += text(str(tmp[val]),exp(C(2*3.14159*I*val[0]/val[1])), fontsize = 30, axes = False, color = "green") if tmp[val] < 0: G += text(str(abs(tmp[val])),exp(C(2*3.14159*I*val[0]/val[1])), fontsize = 30, axes = False, color = "red") return G
def trivial_covering_design(v, k, t): r""" Construct a trivial covering design. INPUT: v -- integer, size of point set k -- integer, cardinality of each block t -- integer, cardinality of sets being covered OUTPUT: (v,k,t) covering design EXAMPLE: sage: C = trivial_covering_design(8,3,1) sage: print C C(8,3,1) = 3 Method: Trivial 0 1 2 0 6 7 3 4 5 sage: C = trivial_covering_design(5,3,2) sage: print C 4 <= C(5,3,2) <= 10 Method: Trivial 0 1 2 0 1 3 0 1 4 0 2 3 0 2 4 0 3 4 1 2 3 1 2 4 1 3 4 2 3 4 NOTES: Cases are: \begin{enumerate} \item $t=0$: This could be empty, but it's a useful convention to have one block (which is empty if $k=0$). \item $t=1$: This contains $\lceil v/k \rceil$ blocks: $[0,...,k-1]$,[k,...,2k-1],...$. The last block wraps around if $k$ does not divide $v$. \item anything else: Just use every $k$-subset of $[0,1,...,v-1]$. \end{enumerate} """ if t == 0: #single block [0,...,k-1] blk = [] for i in range(k): blk.append(i) return CoveringDesign(v, k, t, 1, range(v), [blk], 1, "Trivial") if t == 1: #blocks [0,...,k-1],[k,...,2k-1],... size = Rational((v, k)).ceil() blocks = [] for i in range(size - 1): blk = [] for j in range(i * k, (i + 1) * k): blk.append(j) blocks.append(blk) blk = [] # last block: if k does not divide v, wrap around for j in range((size - 1) * k, v): blk.append(j) for j in range(k - len(blk)): blk.append(j) blk.sort() blocks.append(blk) return CoveringDesign(v, k, t, size, range(v), blocks, size, "Trivial") # default case, all k-subsets return CoveringDesign(v, k, t, binomial(v, k), range(v), Combinations(range(v), k), schonheim(v, k, t), "Trivial")
def trivial_covering_design(v, k, t): r""" Construct a trivial covering design. INPUT: - ``v`` -- integer, size of point set - ``k`` -- integer, cardinality of each block - ``t`` -- integer, cardinality of sets being covered OUTPUT: A trivial `(v, k, t)` covering design EXAMPLES:: sage: C = trivial_covering_design(8, 3, 1) sage: print(C) C(8, 3, 1) = 3 Method: Trivial 0 1 2 0 6 7 3 4 5 sage: C = trivial_covering_design(5, 3, 2) sage: print(C) 4 <= C(5, 3, 2) <= 10 Method: Trivial 0 1 2 0 1 3 0 1 4 0 2 3 0 2 4 0 3 4 1 2 3 1 2 4 1 3 4 2 3 4 NOTES: Cases are: * `t=0`: This could be empty, but it's a useful convention to have one block (which is empty if $k=0$). * `t=1` : This contains `\lceil v/k \rceil` blocks: `[0, ..., k-1], [k, ..., 2k-1], ...`. The last block wraps around if `k` does not divide `v`. * anything else: Just use every `k`-subset of `[0, 1,..., v-1]`. """ if t == 0: # single block [0, ..., k-1] blk = [] for i in range(k): blk.append(i) return CoveringDesign(v, k, t, 1, range(v), [blk], 1, "Trivial") if t == 1: # blocks [0, ..., k-1], [k, ..., 2k-1], ... size = Rational((v, k)).ceil() blocks = [] for i in range(size - 1): blk = [] for j in range(i * k, (i + 1) * k): blk.append(j) blocks.append(blk) blk = [] # last block: if k does not divide v, wrap around for j in range((size - 1) * k, v): blk.append(j) for j in range(k - len(blk)): blk.append(j) blk.sort() blocks.append(blk) return CoveringDesign(v, k, t, size, range(v), blocks, size, "Trivial") # default case, all k-subsets return CoveringDesign(v, k, t, binomial(v, k), range(v), Combinations(range(v), k), schonheim(v, k, t), "Trivial")
def __rmul__(self,scalar): vec = [] for v in self.vec: vec.append(v*Rational(scalar)) return LogarithmicDifferentialForm(self.form.degree(),vec,self.diff_forms)
def integrate(arg, polynomial=None, algorithm='triangulate', raw_output=False, verbose=False, **kwds): r""" Call to the function integrate from LattE integrale. INPUT: - ``arg`` -- a cdd or LattE description string. - ``polynomial`` -- multivariate polynomial or valid LattE polynomial description string. If given, the valuation parameter of LattE is set to integrate, and is set to volume otherwise. - ``algorithm`` -- (default: 'triangulate') the integration method. Use 'triangulate' for polytope triangulation or 'cone-decompose' for tangent cone decomposition method. - ``raw_output`` -- if ``True`` then return directly the output string from LattE. - ``verbose`` -- if ``True`` then return directly verbose output from LattE. - For all other options of the integrate program, consult the LattE manual. OUTPUT: Either a string (if ``raw_output`` if set to ``True``) or a rational. EXAMPLES:: sage: from sage.interfaces.latte import integrate # optional - latte_int sage: P = 2 * polytopes.cube() sage: x, y, z = polygen(QQ, 'x, y, z') Integrating over a polynomial over a polytope in either the H or V representation:: sage: integrate(P.cdd_Hrepresentation(), x^2*y^2*z^2, cdd=True) # optional - latte_int 4096/27 sage: integrate(P.cdd_Vrepresentation(), x^2*y^2*z^2, cdd=True) # optional - latte_int 4096/27 Computing the volume of a polytope in either the H or V representation:: sage: integrate(P.cdd_Hrepresentation(), cdd=True) # optional - latte_int 64 sage: integrate(P.cdd_Vrepresentation(), cdd=True) # optional - latte_int 64 Polynomials given as a string in LattE description are also accepted:: sage: integrate(P.cdd_Hrepresentation(), '[[1,[2,2,2]]]', cdd=True) # optional - latte_int 4096/27 TESTS:: Testing raw output:: sage: from sage.interfaces.latte import integrate # optional - latte_int sage: P = polytopes.cuboctahedron() sage: cddin = P.cdd_Vrepresentation() sage: x, y, z = polygen(QQ, 'x, y, z') sage: f = 3*x^2*y^4*z^6 + 7*y^3*z^5 sage: integrate(cddin, f, cdd=True, raw_output=True) # optional - latte_int '629/47775' Testing the ``verbose`` option to integrate over a polytope:: sage: ans = integrate(cddin, f, cdd=True, verbose=True, raw_output=True) # optional - latte_int This is LattE integrale ... ... Invocation: integrate --valuation=integrate --triangulate --redundancy-check=none --cdd --monomials=... /dev/stdin ... Testing triangulate algorithm:: sage: from sage.interfaces.latte import integrate # optional - latte_int sage: P = polytopes.cuboctahedron() sage: cddin = P.cdd_Vrepresentation() sage: integrate(cddin, algorithm='triangulate', cdd=True) # optional - latte_int 20/3 Testing convex decomposition algorithm:: sage: from sage.interfaces.latte import integrate # optional - latte_int sage: P = polytopes.cuboctahedron() sage: cddin = P.cdd_Vrepresentation() sage: integrate(cddin, algorithm='cone-decompose', cdd=True) # optional - latte_int 20/3 Testing raw output:: sage: from sage.interfaces.latte import integrate # optional - latte_int sage: P = polytopes.cuboctahedron() sage: cddin = P.cdd_Vrepresentation() sage: integrate(cddin, cdd=True, raw_output=True) # optional - latte_int '20/3' Testing polynomial given as a string in LattE description:: sage: from sage.interfaces.latte import integrate # optional - latte_int sage: P = polytopes.cuboctahedron() sage: integrate(P.cdd_Hrepresentation(), '[[3,[2,4,6]],[7,[0, 3, 5]]]', cdd=True) # optional - latte_int 629/47775 Testing the ``verbose`` option to compute the volume of a polytope:: sage: from sage.interfaces.latte import integrate # optional - latte_int sage: P = polytopes.cuboctahedron() sage: cddin = P.cdd_Vrepresentation() sage: ans = integrate(cddin, cdd=True, raw_output=True, verbose=True) # optional - latte_int This is LattE integrale ... ... Invocation: integrate --valuation=volume --triangulate --redundancy-check=none --cdd /dev/stdin ... """ # Check that LattE is present Latte().require() from sage.rings.rational import Rational args = ['integrate'] got_polynomial = True if polynomial is not None else False if got_polynomial: args.append('--valuation=integrate') else: args.append('--valuation=volume') if algorithm == 'triangulate': args.append('--triangulate') elif algorithm == 'cone-decompose': args.append('--cone-decompose') if 'redundancy_check' not in kwds: args.append('--redundancy-check=none') for key, value in kwds.items(): if value is None or value is False: continue key = key.replace('_', '-') if value is True: args.append('--{}'.format(key)) else: args.append('--{}={}'.format(key, value)) if got_polynomial: if not isinstance(polynomial, six.string_types): # transform polynomial to LattE description monomials_list = to_latte_polynomial(polynomial) else: monomials_list = str(polynomial) from sage.misc.temporary_file import tmp_filename filename_polynomial = tmp_filename() with open(filename_polynomial, 'w') as f: f.write(monomials_list) args += ['--monomials=' + filename_polynomial] args += ['/dev/stdin'] # The cwd argument is needed because latte # always produces diagnostic output files. latte_proc = Popen(args, stdin=PIPE, stdout=PIPE, stderr=(None if verbose else PIPE), cwd=str(SAGE_TMP)) ans, err = latte_proc.communicate(arg) ret_code = latte_proc.poll() if ret_code: if err is None: err = ", see error message above" else: err = ":\n" + err raise RuntimeError( "LattE integrale program failed (exit code {})".format(ret_code) + err.strip()) ans = ans.splitlines() ans = ans[-5].split() assert (ans[0] == 'Answer:') ans = ans[1] if raw_output: return ans else: return Rational(ans)
def symbolic_to_rpn(symbolic): # if symbolic in sage_constants.keys(): # return RPNProgram([wild(sage_constants[symbolic])]) if isinstance(symbolic, (int, float, complex)): return RPNProgram([symbolic]) if isinstance(symbolic, Integer): return RPNProgram([int(symbolic)]) elif isinstance(symbolic, (RealLiteral, RealNumber)): return RPNProgram([float(symbolic)]) elif isinstance(symbolic, ComplexNumber): return RPNProgram([complex(symbolic)]) elif isinstance(symbolic, Rational): num, den = symbolic.numerator(), symbolic.denominator() if den == 1: return RPNProgram([int(num)]) else: return RPNProgram([int(num), int(den), rpn_funcs[u"÷"]]) elif symbolic in constants.keys(): return RPNProgram([wild(constants[symbolic])]) # Todo: Implement symbolic matrices. try: operands = symbolic.operands() except: print symbolic raise num, den = symbolic.numerator_denominator() op = symbolic.operator() if symbolic.is_numeric() and op is None: if symbolic.is_real(): symbolic = symbolic.pyobject() return symbolic_to_rpn(symbolic) elif symbolic.real(): return RPNProgram( symbolic_to_rpn(symbolic.real()) + symbolic_to_rpn(symbolic.imag()) + [1j, rpn_funcs[u"⋅"], rpn_funcs[u"+"]]) else: return RPNProgram( symbolic_to_rpn(symbolic.imag()) + [1j, rpn_funcs[u"⋅"]]) # Initialize the RPN Program rpn = RPNProgram() if op in (operator.mul, mul_vararg) and den != 1: numrpn = symbolic_to_rpn(num) denrpn = symbolic_to_rpn(den) if numrpn[-1] == operator.neg: rpn.extend(numrpn[:-1]) else: rpn.extend(numrpn) rpn.extend(denrpn) rpn.append(op_translate[operator.div]) if numrpn[-1] == operator.neg: rpn.append(op_translate[operator.neg]) # elif symbolic.is_integer(): # rpn.append(int(symbolic)) # elif symbolic.is_real(): # rpn.append(float(symbolic)) # elif symbolic.is_numeric(): # rpn.append(complex(symbolic)) elif op in (operator.add, add_vararg): subrpn = symbolic_to_rpn(operands[0]) rpn.extend(subrpn) for term in operands[1:]: if term.operator() in ( operator.mul, mul_vararg) and term.operands( )[-1].is_real() and term.operands()[-1] < 0: subrpn = symbolic_to_rpn(-term) + \ [op_translate[operator.neg]] else: subrpn = symbolic_to_rpn(term) if subrpn[-1] == op_translate[operator.neg]: rpn.extend(subrpn[:-1]) rpn.append(op_translate[operator.sub]) else: rpn.extend(subrpn) rpn.append(op_translate[operator.add]) elif op in (operator.mul, mul_vararg): if operands[-1].is_numeric(): operands.insert(0, operands[-1]) del operands[-1] isneg = False if operands[0] == -1: del operands[0] isneg = True subrpn = symbolic_to_rpn(operands[0]) rpn.extend(subrpn) for factor in operands[1:]: subrpn = symbolic_to_rpn(factor) rpn.extend(subrpn) rpn.append(op_translate[operator.mul]) if isneg: rpn.append(op_translate[operator.neg]) elif op in (sage.functions.min_max.min_symbolic, sage.functions.min_max.max_symbolic): subrpn = symbolic_to_rpn(operands[0]) rpn.extend(subrpn) for operand in operands[1:]: subrpn = symbolic_to_rpn(operand) rpn.extend(subrpn) rpn.append(op_translate[op]) elif op == operator.pow: if operands[1] == Rational("1/2"): rpn.extend(symbolic_to_rpn(operands[0])) rpn.append(op_translate[sage.functions.all.sqrt]) elif operands[1] == Rational("-1/2"): rpn.append(int(1)) rpn.extend(symbolic_to_rpn(operands[0])) rpn.append(op_translate[sage.functions.all.sqrt]) rpn.append(op_translate[operator.div]) elif operands[1] == -1: rpn.append(int(1)) rpn.extend(symbolic_to_rpn(operands[0])) rpn.append(op_translate[operator.div]) else: for operand in operands: rpn.extend(symbolic_to_rpn(operand)) rpn.append(op_translate[op]) elif op: for operand in operands: rpn.extend(symbolic_to_rpn(operand)) rpn.append(op_translate[op]) else: rpn.append(wild(str(symbolic))) return rpn