def main(): print(header.lstrip()) print('all_bfs = {') for dim, _dbfs in all_bfs.items(): print(' {} : {{'.format(dim)) for order, _bfs in _dbfs.items(): print(' {} : ['.format(order)) vs = [x, y, z][:dim] bfs = [ sm.horner( sm.simplify( bf.subs({ x: -1 + 2 * x, y: -1 + 2 * y, z: -1 + 2 * z }))) for bf in _bfs ] bfgs = [[sm.horner(sm.simplify(bf.diff(v))) for v in vs] for bf in bfs] print(' [') for bf in bfs: print((' ' * 16), str(bf).replace('1.0*', ''), ',') print(' ],') print(' [') for bfg in bfgs: print((' ' * 16), str(bfg).replace('1.0*', ''), ',') print(' ],') print(' ],') print(' },') print('}')
def sympy_get_monomials(dimension, degree, vector=False): xs = smp.symbols(['x[{:d}]'.format(ii) for ii in range(dimension)], real=True) monos = smp.polys.monomials.itermonomials(xs, degree) for xx in xs: monos = [smp.horner(mm, wrt=xx) for mm in monos] monos = sorted(monos, key=smp.polys.orderings.monomial_key('grlex', xs[::-1]))[1:] if vector: expressions = [ Constant([0 for ll in range(kk)] + [1] + [0 for ll in range(kk + 1, dimension)]) for kk in range(dimension) ] expressions += [ Expression(['0' for ll in range(kk)] + [smp.ccode(mm)] + ['0' for ll in range(kk + 1, dimension)], degree=int(smp.degree(mm))) for mm in monos for kk in range(dimension) ] else: expressions = [Constant(1)] expressions += [ Expression(smp.ccode(mm), degree=int(smp.degree(mm))) for mm in monos ] return expressions
def compute_fast_beta(self): self.fast_beta = [] for i in range(len(self.beta)): self.fast_beta.append([[sp.utilities.lambdify((self.xi), sp.horner(sp.Poly((self.beta[i][j][k].coef[::-1]), self.xi)), np) for k in range(len(self.beta[i][j]))] for j in range(self.m + 1)]) return None
def poly_factorize(poly): """Factorize multivariate polynomials into a sum of products of monomials. This function can be used to decompose polynomials into a form which minimizes the number of additions and multiplications, and which thus can be evaluated efficently.""" max_deg = {} if 'horner' in dir(sympy): return sympy.horner(poly) if not isinstance(poly, Poly): poly = Poly(sympy.expand(poly), *poly.atoms(Symbol)) denom, poly = poly.as_integer() # Determine the order of factorization. We proceed through the # symbols, starting with the one present in the highest order # in the polynomial. for i, sym in enumerate(poly.symbols): max_deg[i] = 0 for monom in poly.monoms: for i, symvar in enumerate(monom): max_deg[i] = max(max_deg[i], symvar) ret_poly = 0 monoms = list(poly.monoms) for isym, maxdeg in sorted(max_deg.items(), key=itemgetter(1), reverse=True): drop_idx = [] new_poly = [] for i, monom in enumerate(monoms): if monom[isym] > 0: drop_idx.append(i) new_poly.append((poly.coeff(*monom), monom)) if not new_poly: continue ret_poly += sympy.factor(Poly(new_poly, *poly.symbols)) for idx in reversed(drop_idx): del monoms[idx] # Add any remaining O(1) terms. new_poly = [] for i, monom in enumerate(monoms): new_poly.append((poly.coeff(*monom), monom)) if new_poly: ret_poly += Poly(new_poly, *poly.symbols) return ret_poly / denom
def compute_fast_beta(self): self.fast_beta = [] for i in range(len(self.beta)): self.fast_beta.append([[ sp.utilities.lambdify( (self.xi), sp.horner(sp.Poly((self.beta[i][j][k].coef[::-1]), self.xi)), np) for k in range(len(self.beta[i][j])) ] for j in range(self.m + 1)]) return None
def _parse(cls, raw): raw = list(raw) x = sympy.Symbol(cls._spce.x) exprs = list(map(sympy.parse_expr, raw)) # attemps polynom extraction try: # polys = [sympy.poly(f, x, domain="RR") for f in exprs] polys = sympy.parallel_poly_from_expr(exprs, x, domain="RR")[0] except sympy.PolynomialError: pass else: ncoeff = max(len(p.all_coeffs()) for p in polys) coeffs = np.zeros((len(polys), ncoeff), dtype=cls.dtype) coeffs[:, 0] = 1 for i, p in enumerate(polys): c = p.all_coeffs()[::-1] coeffs[i, : len(c)] = c expr = sympy.horner(sympy.Poly.from_list(cls._spce.symbols(ncoeff)[::-1], x)) return expr, coeffs # extraction for formulas in list(map(sympy.simplify, exprs)), exprs: expr = set() coeffs = [] for e, c in map(cls._spce.extract, formulas): expr.add(e) if len(expr) > 1: break coeffs.append(c) else: (expr,) = list(expr) coeff0 = np.array(coeffs[0], dtype=object) coeffs = np.array(coeffs, dtype=cls.dtype) const = np.all(coeffs[:1] == coeffs, axis=0) symbols = np.array(cls._spce.symbols(len(const))) # put back constants expr = expr.xreplace(dict(zip(symbols[const], coeff0[const]))) # shift symbols for old, new in zip(symbols[~const], symbols): if old != new: assert new not in expr.free_symbols expr.replace(old, new) # shift coeffs coeffs = coeffs[:, ~const] # horner-ify expr = expr.replace(cls._horner_test, sympy.horner) return expr, coeffs return RuntimeError("\t\n".join(["can't unify expression:"] + raw))
def run_transmute_test(data, degree, prec, time, *, expr=None, plot=True, _print=False, run_all=True, use_cache=True, thetas=None, alphas=None, alpha0=None): """ Run transmute test on the data If run_all=True, runs the test on all forms of the exponential. Otherwise, only use part_frac_complex (the fastest). """ nucs, matrix = load_sparse_csr(data) expr = get_CRAM_from_cache(degree, prec, expr=expr, plot=plot, use_cache=use_cache) num, den = fraction(expr) if not (thetas and alphas and alpha0): thetas, alphas, alpha0 = thetas_alphas(expr, prec) part_frac = thetas_alphas_to_expr_real(thetas, alphas, alpha0) part_frac_complex = thetas_alphas_to_expr_complex(thetas, alphas, alpha0) # part_frac_complex2 = thetas_alphas_to_expr_complex2(thetas, alphas, alpha0) e = {} from ..py_solve import py_solve py_solve_expm = getattr(py_solve, 'expmI%d' % degree) e['transmutagen generated C solver'] = lambda m: py_solve_expm(m).T e['part_frac_complex UMFPACK'] = lambda m: (use_solver( useUmfpack=True) or lambdify_expr(part_frac_complex)(m)) e['part_frac_complex SuperLU'] = lambda m: (use_solver( useUmfpack=False) or lambdify_expr(part_frac_complex)(m)) e['scipy.sparse.linalg.expm'] = lambda m: expm(-m) if run_all: e['rat_func'] = lambdify_expr(expr) e['rat_func_horner'] = lambdify_expr(horner(num) / horner(den)) e['part_frac'] = lambdify_expr(part_frac) # e['part_frac_complex2'] = lambdify_expr(part_frac_complex2) res = {} for func in sorted(e): if _print: print(func) arg = -matrix * time res[func] = time_and_run(e[func], arg, _print=_print) return res
def gen_lobatto(max_order): assert max_order > 2 x = sm.symbols('x') lobs = [0, 1] lobs[0] = (1 - x) / 2 lobs[1] = (1 + x) / 2 dlobs = [lob.diff('x') for lob in lobs] legs = [sm.legendre(0, 'y')] clegs = [sm.ccode(legs[0])] dlegs = [sm.legendre(0, 'y').diff('y')] cdlegs = [sm.ccode(dlegs[0])] clobs = [sm.ccode(lob) for lob in lobs] cdlobs = [sm.ccode(dlob) for dlob in dlobs] denoms = [] # for lobs. for ii in range(2, max_order + 1): coef = sm.sympify('sqrt(2 * (2 * %s - 1)) / 2' % ii) leg = sm.legendre(ii - 1, 'y') pleg = leg.as_poly() coefs = pleg.all_coeffs() denom = max(sm.denom(val) for val in coefs) cleg = sm.ccode(sm.horner(leg * denom) / denom) dleg = leg.diff('y') cdleg = sm.ccode(sm.horner(dleg * denom) / denom) lob = sm.simplify(coef * sm.integrate(leg, ('y', -1, x))) lobnc = sm.simplify(sm.integrate(leg, ('y', -1, x))) plobnc = lobnc.as_poly() coefs = plobnc.all_coeffs() denom = sm.denom(coef) * max(sm.denom(val) for val in coefs) clob = sm.ccode(sm.horner(lob * denom) / denom) dlob = lob.diff('x') cdlob = sm.ccode(sm.horner(dlob * denom) / denom) legs.append(leg) clegs.append(cleg) dlegs.append(dleg) cdlegs.append(cdleg) lobs.append(lob) clobs.append(clob) dlobs.append(dlob) cdlobs.append(cdlob) denoms.append(denom) coef = sm.sympify('sqrt(2 * (2 * %s - 1)) / 2' % (max_order + 1)) leg = sm.legendre(max_order, 'y') pleg = leg.as_poly() coefs = pleg.all_coeffs() denom = max(sm.denom(val) for val in coefs) cleg = sm.ccode(sm.horner(leg * denom) / denom) dleg = leg.diff('y') cdleg = sm.ccode(sm.horner(dleg * denom) / denom) legs.append(leg) clegs.append(cleg) dlegs.append(dleg) cdlegs.append(cdleg) kerns = [] ckerns = [] dkerns = [] cdkerns = [] for ii, lob in enumerate(lobs[2:]): kern = sm.simplify(lob / (lobs[0] * lobs[1])) dkern = kern.diff('x') denom = denoms[ii] / 4 ckern = sm.ccode(sm.horner(kern * denom) / denom) cdkern = sm.ccode(sm.horner(dkern * denom) / denom) kerns.append(kern) ckerns.append(ckern) dkerns.append(dkern) cdkerns.append(cdkern) return (legs, clegs, dlegs, cdlegs, lobs, clobs, dlobs, cdlobs, kerns, ckerns, dkerns, cdkerns, denoms)
def gen_lobatto(max_order): assert max_order > 2 x = sm.symbols('x') lobs = [0, 1] lobs[0] = (1 - x) / 2 lobs[1] = (1 + x) / 2 dlobs = [lob.diff('x') for lob in lobs] legs = [sm.legendre(0, 'y')] clegs = [sm.ccode(legs[0])] dlegs = [sm.legendre(0, 'y').diff('y')] cdlegs = [sm.ccode(dlegs[0])] clobs = [sm.ccode(lob) for lob in lobs] cdlobs = [sm.ccode(dlob) for dlob in dlobs] denoms = [] # for lobs. for ii in range(2, max_order + 1): coef = sm.sympify('sqrt(2 * (2 * %s - 1)) / 2' % ii) leg = sm.legendre(ii - 1, 'y') pleg = leg.as_poly() coefs = pleg.all_coeffs() denom = max(sm.denom(val) for val in coefs) cleg = sm.ccode(sm.horner(leg*denom)/denom) dleg = leg.diff('y') cdleg = sm.ccode(sm.horner(dleg*denom)/denom) lob = sm.simplify(coef * sm.integrate(leg, ('y', -1, x))) lobnc = sm.simplify(sm.integrate(leg, ('y', -1, x))) plobnc = lobnc.as_poly() coefs = plobnc.all_coeffs() denom = sm.denom(coef) * max(sm.denom(val) for val in coefs) clob = sm.ccode(sm.horner(lob*denom)/denom) dlob = lob.diff('x') cdlob = sm.ccode(sm.horner(dlob*denom)/denom) legs.append(leg) clegs.append(cleg) dlegs.append(dleg) cdlegs.append(cdleg) lobs.append(lob) clobs.append(clob) dlobs.append(dlob) cdlobs.append(cdlob) denoms.append(denom) coef = sm.sympify('sqrt(2 * (2 * %s - 1)) / 2' % (max_order + 1)) leg = sm.legendre(max_order, 'y') pleg = leg.as_poly() coefs = pleg.all_coeffs() denom = max(sm.denom(val) for val in coefs) cleg = sm.ccode(sm.horner(leg*denom)/denom) dleg = leg.diff('y') cdleg = sm.ccode(sm.horner(dleg*denom)/denom) legs.append(leg) clegs.append(cleg) dlegs.append(dleg) cdlegs.append(cdleg) kerns = [] ckerns = [] dkerns = [] cdkerns = [] for ii, lob in enumerate(lobs[2:]): kern = sm.simplify(lob / (lobs[0] * lobs[1])) dkern = kern.diff('x') denom = denoms[ii] / 4 ckern = sm.ccode(sm.horner(kern*denom)/denom) cdkern = sm.ccode(sm.horner(dkern*denom)/denom) kerns.append(kern) ckerns.append(ckern) dkerns.append(dkern) cdkerns.append(cdkern) return (legs, clegs, dlegs, cdlegs, lobs, clobs, dlobs, cdlobs, kerns, ckerns, dkerns, cdkerns, denoms)
def parse(f, fac=1, vec=False, toOpenCL=True, CLBuiltins=False, keep=False): """ Parsing function. @param f : functions to parse as string @param fac : numeric factor for all formulas @param vec : is OpenCL output is generated to use vector builtin types @param toOpenCL : is OpenCL output @param CLBuiltins : is OpenCL output uses fma builtin function @param keep : low parsing """ msg = 'Vector works only in OpenCL parsing' assert not (vec and not toOpenCL), msg assert not (CLBuiltins and not toOpenCL),\ "CLBuiltins only in OpenCL parsing" t = "float__N__" if vec else "float" cteEnd = ".0" if toOpenCL else "." res = "" # Split each line fl = f.split('\n') # sympy formulas y = sp.symbols('y') print (y) sw = [None] * f.count(';') i = 0 for wl in fl: if len(wl) > 2: # replace pow power = re.search('pow\(y, ([0-9]+)\)', wl) if power is not None: np = "y" + "*y" * (int(power.group(1)) - 1) wl = wl.replace(power.group(0), np) sw[i] = '(' sw[i] += str(sp.horner(eval(wl.split(';')[0].split('=')[1]) * fac)) sw[i] += ')/' + str(fac) i += 1 for i, s in enumerate(sw): if not keep: if toOpenCL: res += "inline " + t + " " res += weights_names[i] + "(" + t + " y){\n" res += ' return ' else: res += 'lambda y, s: s * ' res += '(' # replace y**n power = re.findall('y\*\*[0-9]+', s) if power is not None: for pw in power: n = int(pw.split('**')[1]) npower = 'y' + "*y" * (n - 1) s = s.replace(pw, npower) s = s.replace(' ', '') if CLBuiltins: s = createFMA(s) # From integers to floats s = re.sub(r"(?P<id>[0-9]+)", r"\g<id>" + cteEnd, s) s = s.replace('*', ' * ') s = s.replace('/', ' / ') s = s.replace('+', ' + ') s = s.replace('-', ' - ') s = s.replace('( - ', '(-') s = s.replace(' ', ' ') s = s.replace(", - ", ", -") res += s + ')' if toOpenCL: res += ";}" if i < len(sw) - 1: res += "\n" else: res += "w[{0}] = ".format(i) # replace y**n power = re.findall('y\*\*[0-9]+', s) if power is not None: for pw in power: n = int(pw.split('**')[1]) npower = 'y' + "*y" * (n - 1) s = s.replace(pw, npower) # From integers to floats s = re.sub(r"(?P<id>[0-9]+)", r"\g<id>.", s) s = s.replace('*', ' * ') s = s.replace('/', ' / ') s = s.replace('+', ' + ') s = s.replace('-', ' - ') s = s.replace('( - ', '(-') s = s.replace(' ', ' ') s = s.replace(", - ", ", -") res += s + "\n" return res