def to_function(self): if not self.position.is_diag: raise ValueError("Position must be diagonal!") def rec_a(i): return float(1 / np.sqrt(i + 1)) def rec_b(i): return -float(np.sqrt(i) / np.sqrt(i + 1)) dirs = self.position.dirs hermite_dirs = [] for i, d in enumerate(dirs): var = func.Function.xyz[d] h0 = func.Function('1', dirs=dirs) μ, σ = self.position.mean[i], self.position.cov[i][i] f1 = np.sqrt(σ) * (var - μ) h1 = func.Function(f1, dirs=dirs) hermite_dirs.append([h0, h1]) for j in range(1, self.degree): hermite_dirs[i].append(hermite_dirs[i][-1] * hermite_dirs[i][1] * rec_a(j) + hermite_dirs[i][-2] * rec_b(j)) result = func.Function('0', dirs=dirs) for im, m in enumerate(self.multi_indices()): result_m = func.Function(self.coeffs[im], dirs=dirs) for i in range(0, self.position.dim): result_m *= hermite_dirs[i][m[i]] result += result_m return result
def __call__(self, arg): if not isinstance(arg, (func.Function, Operator)): try: arg = Operator(arg, dirs=self.dirs) except TypeError: arg = func.Function(arg, dirs=self.dirs) variables = [func.Function.x_sub[d] for d in self.dirs] sym = self.sym.subs(self.f(*variables), arg.sym).doit() return Operator(sym, dirs=self.dirs) if isinstance(arg, Operator) \ else func.Function(sym, dirs=self.dirs)
def test_construct_from_string(self): function_str1 = 'x*cos(y) + exp(z)**2' function_str2 = 'x0*cos(x1) + exp(x2)**2' function_sym1 = x * sym.cos(y) + sym.exp(z)**2 function_sym2 = v[0] * sym.cos(v[1]) + sym.exp(v[2])**2 function1 = func.Function(function_str1) function2 = func.Function(function_str2) function3 = func.Function(function_sym1) function4 = func.Function(function_sym2) self.assertTrue(function1 == function2) self.assertTrue(function2 == function3) self.assertTrue(function3 == function4)
def split(self): MAX_ORDER = 5 variables = [func.Function.x_sub[d] for d in self.dirs] unknown, dim = self.f(*variables), len(variables) result, rem = {}, self.sym.expand() mult = list( m for m in itertools.product(range(MAX_ORDER + 1), repeat=dim) if sum(m) <= MAX_ORDER) for m in mult: if rem == 0: break test, der = 1, unknown for i, v in zip(m, variables): test *= v**i / math.factorial(i) der = sympy.diff(der, v, i) remargs = rem.args if isinstance(rem, sympy.Add) else [rem] term, rem = 0, 0 for arg in remargs: # Convoluted to avoid rounding errors termarg = arg.subs(unknown, test).doit() if termarg == 0: rem += arg else: term += termarg if isinstance(term, sympy.Basic): term = sympy.simplify(term) if term != 0: result[tuple(m)] = func.Function(term, dirs=self.dirs) if rem != 0: raise ValueError("Nonzero remainder") return result
def discretize(self, f): if not isinstance(f, symfunc.Function): f = symfunc.Function(f) f = f.as_string(format='array', toC=True) function = core.discretize(f, self.nodes, self.position.mean, self.position.factor) return function
def tensorize(args, sparse=None): for a in args: if not isinstance(a, Varf): raise ValueError("Invalid argument(s)") if len(args) == 1: return args[0] sparse = rc.settings['sparse'] if sparse is None else sparse index_set, degree = args[0].index_set, args[0].degree mats = {} factor = 1 for a in args: if not isinstance(a, Varf) or \ not a.index_set == index_set or \ not a.degree == degree: raise ValueError("Invalid argument(s)") key = frozenset(a.position.dirs) mats[key] = a.matrix factor *= a.factor.sym matrix = core.tensorize(mats, sparse=sparse, index_set=index_set) position = pos.Position.tensorize([a.position for a in args]) factor = func.Function(factor, dirs=position.dirs) return Varf(matrix, position, factor=factor, index_set=index_set)
def __init__(self, coeffs, position, factor=1, index_set="triangle", significant=0): self.coeffs = coeffs self.position = position self.index_set = index_set dim, npolys = self.position.dim, len(self.coeffs) if position.dirs == []: self.degree = 0 else: self.degree = core.iterator_get_degree(dim, npolys, index_set=index_set) if not len(self.multi_indices()) == len(self.coeffs): raise ValueError("Invalid arguments: length of self.coeffs \ does not match number of multi-indices!") if significant != 0: for i, c in enumerate(self.coeffs): self.coeffs[i] = round(c, significant) self.factor = func.Function(factor, dirs=self.position.dirs) if not self.coeffs.flags['C_CONTIGUOUS']: self.coeffs = self.coeffs.copy(order='C')
def map(self, factor): if not isinstance(factor, func.Function): factor = func.Function(factor, dirs=self.dirs) if not factor.dirs == self.dirs: raise ValueError("Directions differ") variables = [func.Function.x_sub[d] for d in self.dirs] unknown = self.f(*variables) sym = self.sym.subs(unknown, (unknown * factor).sym) sym = (sym.doit() / factor.sym).expand() return Operator(sym, dirs=self.dirs)
def __init__(self, matrix, position, factor=1, index_set="triangle"): self.is_sparse = isinstance(matrix, ss.csr_matrix) self.matrix = matrix self.position = position self.index_set = index_set dim, npolys = self.position.dim, self.matrix.shape[0] self.degree = core.iterator_get_degree(dim, npolys, index_set=index_set) assert len(self.multi_indices()) == self.matrix.shape[0] self.factor = func.Function(factor, dirs=self.position.dirs)
def wrapper(*args, **kwargs): do_tensorize = rc.settings['tensorize'] if 'tensorize' in kwargs: do_tensorize = kwargs['tensorize'] del kwargs['tensorize'] if not do_tensorize: return func(*args, **kwargs) quad, function = args[0], args[arg_num] if not quad.position.is_diag or \ isinstance(function, np.ndarray) or \ quad.position.dim is 1: return func(*args, **kwargs) results = [] if not isinstance(function, symfunc.Function): function = symfunc.Function(function, dim=quad.position.dim) for add in function.split(): if len(add) == 2: new_args = list(args).copy() new_args[arg_num] = add[0] results.append( func(*new_args, **kwargs) * float(add[1])) continue func_dirs = [] for d in range(quad.position.dim): new_args = list(args).copy() new_args[0] = quad.project(d) new_args[arg_num] = add[d] func_dir = func(*new_args, **kwargs) func_dirs.append(func_dir) if rc.settings['debug']: print("Tensorizing results") kwargs_func = {'sparse': kwargs['sparse']} \ if 'sparse' in kwargs else {} t = type(func_dirs[0]) tens_fun = t.tensorize if t is hv.Varf or t is hs.Series \ else core.tensorize tensorized = tens_fun(func_dirs, **kwargs_func) # pdb.set_trace() results.append(tensorized * float(add[-1])) return sum(results[1:], results[0])
def test_simple_split(self): newf = func.Function f = func.Function('x*y**2 + 5*exp(z)*y + 3*log(x*z)') split = f.split() self.assertTrue(len(f.dirs) == 3) self.assertTrue(len(split) == 3) for i in range(3): if split[i][-1] == 1: self.assertTrue(len(split[i]) == 4) self.assertTrue(split[i][0] == newf('x', dirs=[0])) self.assertTrue(split[i][1] == newf('y*y', dirs=[1])) if split[i][-1] == 5: self.assertTrue(len(split[i]) == 4) self.assertTrue(split[i][0] == newf('1', dirs=[0])) self.assertTrue(split[i][1] == newf('y', dirs=[1])) self.assertTrue(split[i][2] == newf('exp(z)', dirs=[2])) if split[i][-1] == 3: self.assertTrue(len(split[i]) == 2) self.assertTrue(split[i][0] == newf('log(x*z)', dim=3))
def _tensorize(s1, s2): if not isinstance(s1, Series) or not isinstance(s2, Series): raise ValueError("Arguments must be Series!") if s1.position.dim == 0: return Series(s1.coeffs[0] * s2.coeffs, s2.position, factor=s2.factor, index_set=s2.index_set) if s2.position.dim == 0: return Series(s2.coeffs[0] * s1.coeffs, s1.position, factor=s1.factor, index_set=s1.index_set) # Inner product only makes sense in weighted space # Product in appropriate weighted space common = set(s1.position.dirs).intersection(s2.position.dirs) f1 = s1.factor.project(list(common)) f2 = s2.factor.project(list(common)) if not f1 == f2: raise ValueError("Factors should be match!") if not s1.degree == s2.degree: raise ValueError("s1 and s2 should have the same degree") if not s1.index_set == s2.index_set: raise ValueError("s1 and s2 should have the same index_set") f1, f2 = s1.factor.sym / f1.sym, s2.factor.sym / f2.sym d1, d2 = s1.position.dirs, s2.position.dirs c1, c2 = s1.coeffs, s2.coeffs result = core.inner(c1, c2, d1, d2, index_set=s1.index_set) position = pos.Position.tensorize([s1.position, s2.position]) factor = func.Function(f1 * f2, dirs=position.dirs) return Series(result, position, factor=factor, index_set=s1.index_set)
def plot(self, series, factor=None, ax=None): assert self.position.is_diag assert self.position == series.position if factor is None: factor = self.position.weight() if not isinstance(factor, np.ndarray): # ipdb.set_trace() factor = symfunc.Function(factor, dirs=self.position.dirs) factor = self.discretize(factor) n_nodes = [] r_nodes = [] for i in range(self.position.dim): n_nodes.append(len(self.nodes[i])) r_nodes.append( self.project(i).discretize('x')) # Problematic line? solution = self.eval(series) * factor solution = solution.reshape(*n_nodes).T if self.position.dim == 1: return ax.plot(*r_nodes, solution) elif self.position.dim == 2: return ax.contourf(*r_nodes, solution, 100)
def __init__(self, expr, dirs=None): if isinstance(expr, Operator): self.sym = expr.sym self.dirs = expr.dirs return aux = func.Function(expr) if aux.sym == 0: if dirs is None: raise ValueError("Invalid argument!") self.sym, self.dirs = aux.sym, dirs return functions = list(aux.sym.atoms(sympy.core.function.AppliedUndef)) if len(functions) != 1: raise TypeError("There should be exactly 1 functional argument!") self.sym = aux.sym.subs(functions[0].func, self.f) variables = list(self.sym.atoms( sympy.core.function.AppliedUndef))[0].args self.dirs = [func.Function.x_sub.index(v) for v in variables] assert len(self.dirs) == len(functions[0].args)
def test_as_xyz(self): function_str1 = 'x0*cos(x1) + exp(2*x2)' function_str2 = 'x*cos(y) + exp(2*z)' function = func.Function(function_str1) self.assertTrue(str(function.sym) == function_str1) self.assertTrue(str(function.as_xyz()) == function_str2)
return symbolic for i in range(nterms): print("Solving for power " + str(i)) unk[i] = sym.Function('u{}'.format(i))(x) u[i] = unk[i] rhs = sym.Integer(0) if i > 0: rhs += -L1.subs(f, u[i - 1]) if i > 1: rhs += -L2.subs(f, u[i - 2]) split = func.Function(rhs.doit().expand(), dim=2).split() for term in split: x_part = term[-1] * term[0].as_xyz() y_part = term[1].as_xyz() t_rhs = quad_num.transform(y_part, degree) centered[i] += round(t_rhs.coeffs[0], 10) * x_part u[i] += x_part * iL0(y_part) u[i] = func.Function.sanitize(u[i]) centered[i] = func.Function.sanitize(centered[i]) # }}} # Some manual calculations {{{ # Operator fx = sym.Function('fx')(x) LFP = ((1 / β) * sym.exp(-β * Vp) * (fx * sym.exp(β * Vp)).diff(x)).diff(x)
def __mul__(self, other): if not isinstance(other, func.Function): other = func.Function(other, dirs=self.dirs) if not self.dirs == other.dirs: raise ValueError("Invalid argument!") return Operator(self.sym * other.sym, dirs=self.dirs)