def convert_add(add): if add.ADD(): lh = convert_add(add.additive(0)) rh = convert_add(add.additive(1)) return sympy.Add(lh, rh, evaluate=False) elif add.SUB(): lh = convert_add(add.additive(0)) rh = convert_add(add.additive(1)) return sympy.Add(lh, sympy.Mul(-1, rh, evaluate=False), evaluate=False) else: return convert_mp(add.mp())
def symbolic_shape(self): """ The symbolic shape of the object. This includes the domain, halo, and padding regions. While halo and padding are known quantities (integers), the domain size is given as a symbol. """ halo = [sympy.Add(*i, evaluate=False) for i in self._size_halo] padding = [sympy.Add(*i, evaluate=False) for i in self._size_padding] domain = [i.symbolic_size for i in self.dimensions] ret = tuple(sympy.Add(i, j, k, evaluate=False) for i, j, k in zip(domain, halo, padding)) return DimensionTuple(*ret, getters=self.dimensions)
def convert_add(add): if add.ADD(): lh = convert_add(add.additive(0)) rh = convert_add(add.additive(1)) return sympy.Add(lh, rh, evaluate=False) elif add.SUB(): lh = convert_add(add.additive(0)) rh = convert_add(add.additive(1)) # return sympy.Add(lh, -1 * rh, evaluate=False) # just keep the origin expression, don't simplify return sympy.Add(lh, sympy.Mul(-1, rh, evaluate=False), evaluate=False) else: return convert_mp(add.mp())
def __generate_elementary_modes_via_fixed_size_constraint(self): fixed_size_constraint = self.model.solver.interface.Constraint( sympy.Add(*self.indicator_variables), name='fixed_size_constraint', lb=1, ub=1) self.model.solver._add_constraint(fixed_size_constraint, sloppy=True) while True: logger.debug("Looking for solutions with cardinality " + str(fixed_size_constraint.lb)) try: self.model.solver.problem.populate_solution_pool() except Exception as e: raise e solution_num = self.model.solver.problem.solution.pool.get_num() if solution_num > 0: exclusion_lists = list() for i in range(solution_num): elementary_flux_mode = list() exclusion_list = list() problem_solution = self.model.solver.problem.solution for reaction in self._reactions: if problem_solution.pool.get_values( i, reaction._indicator_variable_fwd.name) >= 0.9: reaction_copy = copy(reaction) reaction_copy.lower_bound = 0 elementary_flux_mode.append(reaction_copy) exclusion_list.append( reaction._indicator_variable_fwd) elif problem_solution.pool.get_values( i, reaction._indicator_variable_rev.name) >= 0.9: reaction_copy = copy(reaction) reaction_copy.upper_bound = 0 elementary_flux_mode.append(reaction_copy) exclusion_list.append( reaction._indicator_variable_rev) exclusion_lists.append(exclusion_list) yield elementary_flux_mode for exclusion_list in exclusion_lists: exclusion_constraint = self.model.solver.interface.Constraint( sympy.Add(*exclusion_list), ub=len(exclusion_list) - 1) self.model.solver._add_constraint(exclusion_constraint, sloppy=True) new_fixed_size = fixed_size_constraint.ub + 1 if new_fixed_size > len(self._reactions): break fixed_size_constraint.ub, fixed_size_constraint.lb = new_fixed_size, new_fixed_size
def symbolic_shape(self): """ Return the symbolic shape of the object. This includes the padding, halo, and domain regions. While halo and padding are known quantities (integers), the domain size is represented by a symbol. """ halo_sizes = [sympy.Add(*i, evaluate=False) for i in self._extent_halo] padding_sizes = [ sympy.Add(*i, evaluate=False) for i in self._extent_padding ] domain_sizes = [i.symbolic_size for i in self.indices] return tuple( sympy.Add(i, j, k, evaluate=False) for i, j, k in zip(domain_sizes, halo_sizes, padding_sizes))
def generatef(): z = sympy.Symbol("z") # The k is mapped to the positive and negative powers of exp, respectively. # Note that some implementations of the fft gives the order differently. I had to use examples to figure out how this one worked. pos_terms = lambda k: sympy.exp(k * sympy.I * z) * coefs[k] neg_terms = lambda k: sympy.exp((k - N) * sympy.I * z) * coefs[k] # The first part of the function is the summation of the positive powers of exp, and the last part is the summation of the negative powers. first = sympy.Add(*map(pos_terms, range(0, N // 2 + 1))) last = sympy.Add(*map(neg_terms, range(N // 2 + 1, N))) # The function C^2 -> C^2 that graphs the orbit is finally scaled. f = sympy.Add(first, last) / N print "f(z) = ", f,
def check_quadratic_equations(self): # Look for something quadratic to solve 'x^2 * (u) + x * (v) + (w) = 0' for eq in self.cl_eqs: eq_expand = sp.expand(eq) if not eq_expand.is_Add: continue for x in [ s for s in eq_expand.free_symbols if s in self.vars and sp.degree(eq_expand, s) == 2]: w = sp.Add(*[ t for t in eq_expand.args if x not in t.free_symbols ]) v = sp.cancel(sp.Add(*[ t for t in eq_expand.args if sp.degree(t, x) == 1 ]) / x) u = sp.cancel((eq_expand - w - v * x) / x**2) # The discriminant must be a square, otherwise the isomorphism we want to setup is not an algebraic map! discr = v**2 - 4*u*w sqrt_D = is_square(discr) if sqrt_D == None: continue # Case (u) = 0: if u.is_complex: c_u_is_zero = 0 else: c_u_is_zero = System(self.vars, [ e for e in self.cl_eqs if e != eq ] + [ u, x * v + w ], self.op_eqs).compute_class() if c_u_is_zero == None: continue # Case (u) != 0: # Case A: discr = 0 and x = -v / (2 * u) c_A_cl_eqs = [ eq_subs_by_fraction(e, x, -v, 2*u) for e in self.cl_eqs if e != eq ] + [ discr ] c_A_op_eqs = [ eq_subs_by_fraction(e, x, -v, 2*u) for e in self.op_eqs ] + [ u ] c_A = System(self.vars.difference({x,}), c_A_cl_eqs, c_A_op_eqs).compute_class() if c_A == None: continue # Case B: discr != 0 and x = (-v + sqrt_D) / (2 * u) c_B_cl_eqs = [ eq_subs_by_fraction(e, x, -v + sqrt_D, 2*u) for e in self.cl_eqs if e != eq ] c_B_op_eqs = [ eq_subs_by_fraction(e, x, -v + sqrt_D, 2*u) for e in self.op_eqs ] + [ u, discr ] c_B = System(self.vars.difference({x,}), c_B_cl_eqs, c_B_op_eqs).compute_class() if c_B == None: continue # Case C: discr != 0 and x = (-v - sqrt_D) / (2 * u) c_C_cl_eqs = [ eq_subs_by_fraction(e, x, -v - sqrt_D, 2*u) for e in self.cl_eqs if e != eq ] c_C_op_eqs = [ eq_subs_by_fraction(e, x, -v - sqrt_D, 2*u) for e in self.op_eqs ] + [ u, discr ] c_C = System(self.vars.difference({x,}), c_C_cl_eqs, c_C_op_eqs).compute_class() if c_C == None: continue return c_u_is_zero + c_A + c_B + c_C return None
def appendTwoPointsRestriction(self): # Ограничение совпадение двух точек self.oldPoints = self.Points.copy() ind_point = [] for i in range(len(self.chsTwoPoint)): ind_point.append(self.pointsFlatten.index(self.chsTwoPoint[i])) self.chsTwoPoint.clear() list_of_la.append(globals()['la%s' % str(self.counter_la)]) self.function_with_restriction.append(sp.Mul(list_of_la[self.counter_la], list_of_sym_coord[ind_point[2]] - list_of_sym_coord[ind_point[0]])) self.counter_la += 1 list_of_la.append(globals()['la%s' % str(self.counter_la)]) # Добавили новую лямбду в массив всех текущих лябмд self.function_with_restriction.append(sp.Mul(list_of_la[self.counter_la], list_of_sym_coord[ind_point[3]] - list_of_sym_coord[ind_point[1]])) self.counter_la += 1 list_of_la.append(globals()['la%s' % str(self.counter_la)]) self.function_with_restriction.append(sp.Mul(list_of_la[self.counter_la], list_of_sym_coord[ind_point[2]] - self.pointsFlatten[ind_point[2]])) self.counter_la += 1 list_of_la.append(globals()['la%s' % str(self.counter_la)]) self.function_with_restriction.append(sp.Mul(list_of_la[self.counter_la], list_of_sym_coord[ind_point[3]] - self.pointsFlatten[ind_point[3]])) self.counter_la += 1 #self.function_with_restriction = sp.Add(*self.function_with_restriction) #print("hh", self.function_with_restriction) #print("jjj", self.function_no_restriction) self.Restriction = sp.Add(sp.Add(*self.function_with_restriction), sp.Add(*self.function_no_restriction)) # Сложили две части уравнений print("Current function: ", self.Restriction) list_of_sym = list_of_sym_coord + list_of_la print("List of sym = ", list_of_sym) list_diff = list(sp.diff(self.Restriction, x) for x in list_of_sym) # Находим производные для функции # по всем символьным переменным print(list_diff) cur_point = sp.solve(list_diff, list(list_of_sym)) # Здесь решили уравнение и получили новое значение в виде словаря, print(cur_point) # надо откинуть лямбды cur_point_without_lambda = [] i = 0 while i < len(list_of_sym_coord): cur_two_coord = [] cur_two_coord.append(cur_point.get(list_of_sym[i])) cur_two_coord.append(cur_point.get(list_of_sym[i+1])) cur_point_without_lambda.append(cur_two_coord) i += 2 for i in range(len(cur_point_without_lambda)): #self.Points[i] = cur_point_without_lambda[i] self.repaintByPoint(self.Points[i][0],self.Points[i][1],cur_point_without_lambda[i][0],cur_point_without_lambda[i][1]) print("New points: ", self.Points)
def add_flat(lh, rh): if hasattr(lh, 'is_Add') and lh.is_Add or hasattr(rh, 'is_Add') and rh.is_Add: args = [] if hasattr(lh, 'is_Add') and lh.is_Add: args += list(lh.args) else: args += [lh] if hasattr(rh, 'is_Add') and rh.is_Add: args = args + list(rh.args) else: args += [rh] return sympy.Add(*args, evaluate=False) else: return sympy.Add(lh, rh, evaluate=False)
def simplify(self, sig=1e-6, debug=False): """ Simplify a polynomial response function by removing less significant terms. This returns a new copy of the response function and does not update the original one. Args: sig(float): Significance. Default is 1.0e-6. Returns: New response equation. .. note:: May reduce accuracy of response surface. Use with care. """ import itertools if not self.eqn.is_polynomial(): return self.eqn ranges = [y for _x, y in self.vars] terms = [] if not isinstance(self.eqn, sympy.Add): return self.eqn for term in self.eqn.args: mabs = 0 for p in itertools.product(*ranges): res = abs(term.subs(zip(self.vnames, p))) if res > mabs: mabs = res if debug: print "%s\t has maximum of %s" % (term, mabs) terms.append((term, mabs)) maxval = max([val for _t, val in terms]) eqn = sympy.Add(*[t for t, val in terms if val/maxval > sig]) return sympy.simplify(eqn)
def sum(A_expr, axis=None): assert axis is None or axis == 0 or axis == 1 if axis is None: A_sum_expr = sympy.Add(*A_expr) return A_sum_expr if axis == 0: A_sum_expr = sympy.Matrix.zeros(1, A_expr.cols) for c in range(A_expr.cols): A_sum_expr[0, c] = sympy.Add(*A_expr[:, c]) return A_sum_expr if axis == 1: A_sum_expr = sympy.Matrix.zeros(A_expr.rows, 1) for r in range(A_expr.rows): A_sum_expr[r, 0] = sympy.Add(*A_expr[r, :]) return A_sum_expr
def create_milp_problem(kernel, metabolites, Model, Variable, Constraint, Objective): """ Create the MILP as defined by equation (13) in [1]_. Parameters ---------- kernel : numpy.array A 2-dimensional array that represents the left nullspace of the stoichiometric matrix which is the nullspace of the transpose of the stoichiometric matrix. metabolites : iterable The metabolites in the nullspace. The length of this vector must equal the first dimension of the nullspace. Model : optlang.Model Model class for a specific optlang interface. Variable : optlang.Variable Variable class for a specific optlang interface. Constraint : optlang.Constraint Constraint class for a specific optlang interface. Objective : optlang.Objective Objective class for a specific optlang interface. References ---------- .. [1] Gevorgyan, A., M. G Poolman, and D. A Fell. "Detection of Stoichiometric Inconsistencies in Biomolecular Models." Bioinformatics 24, no. 19 (2008): 2245. """ assert len(metabolites) == kernel.shape[0],\ "metabolite vector and first nullspace dimension must be equal" ns_problem = Model() k_vars = list() for met in metabolites: # The element y[i] of the mass vector. y_var = Variable(met.id) k_var = Variable("k_{}".format(met.id), type="binary") k_vars.append(k_var) ns_problem.add([y_var, k_var]) # This constraint is equivalent to 0 <= y[i] <= k[i]. ns_problem.add(Constraint( y_var - k_var, ub=0, name="switch_{}".format(met.id))) ns_problem.update() # add nullspace constraints for (j, column) in enumerate(kernel.T): expression = sympy.Add( *[coef * ns_problem.variables[met.id] for (met, coef) in zip(metabolites, column) if coef != 0.0]) constraint = Constraint(expression, lb=0, ub=0, name="ns_{}".format(j)) ns_problem.add(constraint) # The objective is to minimize the binary indicators k[i], subject to # the above inequality constraints. ns_problem.objective = Objective(1) ns_problem.objective.set_linear_coefficients( {k_var: 1. for k_var in k_vars}) ns_problem.objective.direction = "min" return ns_problem, k_vars
def add_cut(problem, indicators, bound, Constraint): """ Add an integer cut to the problem. Ensure that the same solution involving these indicator variables cannot be found by enforcing their sum to be less than before. Parameters ---------- problem : optlang.Model Specific optlang interface Model instance. indicators : iterable Binary indicator `optlang.Variable`s. bound : int Should be one less than the sum of indicators. Corresponds to P - 1 in equation (14) in [1]_. Constraint : optlang.Constraint Constraint class for a specific optlang interface. References ---------- .. [1] Gevorgyan, A., M. G Poolman, and D. A Fell. "Detection of Stoichiometric Inconsistencies in Biomolecular Models." Bioinformatics 24, no. 19 (2008): 2245. """ cut = Constraint(sympy.Add(*indicators), ub=bound) problem.add(cut) return cut
def testAdd(self): self.compare( mathics.Expression( 'Plus', mathics.Integer(1), mathics.Symbol('Global`x')), sympy.Add( sympy.Integer(1), sympy.Symbol('_Mathics_User_Global`x')))
def wiener_filtering(complex_field: Field, output_weight_field: Field, sigma): assert complex_field.index_dimensions == 3 assert output_weight_field.index_dimensions == 1 assignments = [] norm_factor = complex_field.index_shape[0] * complex_field.index_shape[1] wiener_sum = [] for stack_index in range(complex_field.index_shape[0]): for patch_index in range(complex_field.index_shape[1]): magnitude = sum(complex_field.center(stack_index, patch_index, i) ** 2 for i in (0, 1)) val = magnitude / norm_factor # implementation differ whether to apply norm_factor on val on wien wien = val / (val + sigma * sigma) wiener_sum.append(wien**2) assignments.extend( pystencils.Assignment(complex_field.center(stack_index, patch_index, i), complex_field.center(stack_index, patch_index, i) * wien) for i in (0, 1) ) assignments.append(pystencils.Assignment( output_weight_field.center(stack_index), 1 / sympy.Add(*wiener_sum) )) return AssignmentCollection(assignments)
def _print_Add(self, expr): args = expr.args new = [] for arg in args: new.append(self._print(arg)) return super()._print_Add(sympy.Add(*args, evaluate=False), order='none')
def single_block_matching( input_field: Field, comparision_field: Field, output_block_scores: Field, block_stencil, matching_offset, match_index, matching_function=pystencils_reco.functions.squared_difference, ): assignments = [] i, m = match_index, matching_offset rhs = [] for s in block_stencil: shifted = tuple(i + j for i, j in zip(s, m)) rhs.append( matching_function(input_field[s], comparision_field[shifted])) lhs = output_block_scores(i) assignment = pystencils.Assignment(lhs, sympy.Add(*rhs)) assignments.append(assignment) return AssignmentCollection(assignments, perform_cse=False)
def MLE_(a_i,t_i,s_i): l, p, m1, m2 = sym.symbols('l,p,m1,m2', positive=True) L1 = p ** a * (1 - p) ** (1 - a) J1 = np.prod([L1.subs(a, i) for i in a_i]) print(J1) L2 = l * sym.exp(-l * t) J2 = np.prod([L2.subs(t, i) for i in t_i]) print(J2) L3 = sym.Add((1 - a) * m1 * sym.exp(-m1 * s), a * m2 * sym.exp(-m2 * s)) J3 = np.prod([L3.subs({a: i, s: s_i[j]}) for j, i in enumerate(a_i)]) print(J3) print(sym.expand_log(sym.log(J3))) logJ = sym.expand_log(sym.log(J1 * J2 * J3)) print(logJ) sol_p = float(sym.solve(sym.diff(logJ, p), p)[0]) sol_l = float(sym.solve(sym.diff(logJ, l), l)[0]) sol_m1 = float(sym.solve(sym.diff(logJ, m1), m1)[0]) sol_m2 = float(sym.solve(sym.diff(logJ, m2), m2)[0]) print(sol_p, sol_l, sol_m1, sol_m2) return sol_p, sol_l, sol_m1, sol_m2
def hard_thresholding(complex_field: Field, output_weight_field, threshold): assert complex_field.index_dimensions == 3 assert output_weight_field.index_dimensions == 1 assignments = [] for stack_index in range(complex_field.index_shape[0]): num_nonzeros = [] for patch_index in range(complex_field.index_shape[1]): magnitude = sum(complex_field.center(stack_index, patch_index, i) ** 2 for i in (0, 1)) assignments.extend( pystencils.Assignment(complex_field.center(stack_index, patch_index, i), sympy.Piecewise( (complex_field.center(stack_index, patch_index, i), magnitude > threshold ** 2), (0, True))) for i in (0, 1) ) num_nonzeros.append(sympy.Piecewise((1, magnitude > threshold ** 2), (0, True))) assignments.append(pystencils.Assignment( output_weight_field.center(stack_index), sympy.Add(*num_nonzeros) )) return AssignmentCollection(assignments)
def trunc(self, digits=6): """ Truncates coefficients of the response equation to a certain number of digits. This returns a new copy of the response function and does not update the original one. Args: digits: How many significant digits to keep. Default is 6. Returns: New response equation. .. note:: May reduce accuracy of response surface. Use with care. """ if not isinstance(self._eqn, sympy.Add): return self._eqn print[t.as_coeff_Mul() for t in self._eqn.args] print[(t.as_coeff_Mul()[0].evalf(digits), t.as_coeff_Mul()[1]) for t in self._eqn.args] return sympy.Add(*[ sympy.Mul(t.as_coeff_Mul()[0].evalf(digits), t.as_coeff_Mul()[1]) for t in self._eqn.args ])
def __buildProp(self, variables): diffs = [_sp.diff(self.__func, symb) for symb in self.__variables] tmp = diffs[0]**2 for diff, deltas in zip(diffs, self.__errorSymbs): tmp = _sp.Add(tmp, _sp.MatMul(diff**2, deltas**2)) return (tmp - diffs[0]**2)**( 1 / 2) # propagation assuming no correlations between errors
def integrals_solving_possibilities(self) -> List['Expression']: integrals = [] for exp in preorder_traversal(self.sympy_expr): exp = Expression(exp) if exp.is_integral(): integrals.append(exp) possibilities = [] for integral in integrals: applied_integral = integral.apply_integral() # without integral constant integral_solved = self.get_copy() integral_solved.replace(integral, applied_integral) possibilities.append(integral_solved) # with integral constant integral_solved = self.get_copy() integral_solved.replace(integral, applied_integral) c = sympy.symbols('c') expression_with_constant = Expression( sympy.Add(integral_solved.sympy_expr, c)) possibilities.append(expression_with_constant) return possibilities
def __init__(self, constants, embeddings, bottom_embedding, dry_run=False): self._operands = list(constants) self._embeddings = [embedding for embedding in embeddings] # number of unknown variables self._n_nuknown = 0 # stack which stores (val, embed) tuples self._stack = [] # equations got from applying `=` on the stack self._equations = [] self.stack_log = [] # functions operate on value self._val_funcs = { OPERATIONS.ADD: sympy.Add, OPERATIONS.SUB: lambda a, b: sympy.Add(-a, b), OPERATIONS.MUL: sympy.Mul, OPERATIONS.DIV: lambda a, b: sympy.Mul(1 / a, b) } self._op_chars = { OPERATIONS.ADD: '+', OPERATIONS.SUB: '-', OPERATIONS.MUL: '*', OPERATIONS.DIV: '/', OPERATIONS.EQL: '=' } self._bottom_embed = bottom_embedding if dry_run: self.apply = self.apply_embed_only
def parameter_term(expression, symbol): """ Determine the term, e.g. T*log(T) that belongs to the symbol in expression Parameters ---------- expression : symbol : Returns ------- """ if expression == symbol: # the parameter is the symbol, so the multiplicative term is 1. term = 1 else: if isinstance(expression, sympy.Piecewise): expression = expression.args[0][0] if isinstance(expression, sympy.Symbol): # this is not mathematically correct, but we just need to be able to split it into args expression = sympy.Add(expression, 1) if not isinstance(expression, sympy.Add): raise ValueError('Parameter {} is a {} not a sympy.Add or a Piecewise Add'.format(expression, type(expression))) expression_terms = expression.args term = None for term_coeff in expression_terms: coeff, root = term_coeff.as_coeff_mul(symbol) if root == (symbol,): term = coeff break if term is None: raise ValueError('No multiplicative terms found for Symbol {} in parameter {}'.format(symbol, expression)) return term
def jacobi(dst, src): assert dst.spatial_dimensions == src.spatial_dimensions assert src.index_dimensions == 0 and dst.index_dimensions == 0 neighbors = [] for d in range(src.spatial_dimensions): neighbors += [src.neighbor(d, offset) for offset in (1, -1)] return ps.Assignment(dst.center, sp.Add(*neighbors) / len(neighbors))
def constitutive_relations(self): if not self.components: return [] coords, mappings, lin_op, nlin_op, constraints = self.system_model() inv_tm, inv_js, _ = mappings out_ports = [idx for p, idx in inv_js.items() if p in self.ports] logger.debug("Getting IO ports: %s", out_ports) network_size = len(inv_js) # number of ports n = len(inv_tm) # number of state space coords coord_vect = sp.Matrix(coords) relations = [ sp.Add(l, r) for i, (l, r) in enumerate(zip(lin_op * coord_vect, nlin_op)) if not n <= i < n + 2 * (network_size - len(out_ports)) # noqa ] if isinstance(constraints, list): for constraint in constraints: logger.debug("Adding constraint %s", repr(constraint)) if constraint: relations.append(constraint) else: logger.warning("Constraints %s is not a list. Discarding", repr(constraints)) subs = [] for local_idx, c_idx in enumerate(out_ports): p, = {pp for pp in self.ports if pp.index == local_idx} label = p.index subs.append(sp.symbols((f"e_{c_idx}", f"e_{label}"))) subs.append(sp.symbols((f"f_{c_idx}", f"f_{label}"))) return [r.subs(subs).simplify().nsimplify() for r in relations if r]
def convert_postfix(postfix): if hasattr(postfix, 'exp'): exp_nested = postfix.exp() else: exp_nested = postfix.exp_nofunc() exp = convert_exp(exp_nested) for op in postfix.postfix_op(): if op.BANG(): if isinstance(exp, list): raise LaTeXParsingError("Cannot apply postfix to derivative") exp = sympy.factorial(exp, evaluate=False) elif op.eval_at(): ev = op.eval_at() at_b = None at_a = None if ev.eval_at_sup(): at_b = do_subs(exp, ev.eval_at_sup()) if ev.eval_at_sub(): at_a = do_subs(exp, ev.eval_at_sub()) if at_b is not None and at_a is not None: exp = sympy.Add(at_b, -1 * at_a, evaluate=False) elif at_b is not None: exp = at_b elif at_a is not None: exp = at_a return exp
def check_linear_equations(self): # Look for something of the form 'x * (w) + (u) = 0' with x not in (w), (u) for eq in self.cl_eqs: eq_expand = sp.expand(eq) if not eq_expand.is_Add: continue for x in [ s for s in eq_expand.free_symbols if s in self.vars and sp.degree(eq_expand, s) == 1]: u = sp.Add(*[ t for t in eq_expand.args if x not in t.free_symbols ]) w = sp.expand((eq_expand - u) / x) # Now either (w) = 0 (implying (u) = 0 as well): if w.is_complex: c_1 = 0 else: c_1 = System(self.vars, [ e for e in self.cl_eqs if e != eq ] + [ w, u ], self.op_eqs).compute_class() if c_1 == None: continue # Or (w) != 0 and we can use the equation to solve for x = -u / w: c_2_cl_eqs = [ eq_subs_by_fraction(e, x, -u, w) for e in self.cl_eqs if e != eq ] c_2_op_eqs = [ eq_subs_by_fraction(e, x, -u, w) for e in self.op_eqs ] + [ w ] c_2 = System(self.vars.difference({x,}), c_2_cl_eqs, c_2_op_eqs).compute_class() if c_2 == None: continue return c_1 + c_2 return None
def expand_diff_products(expr): """Fully expands all derivatives by applying product rule""" if isinstance(expr, Diff): arg = expand_diff_products(expr.args[0]) if arg.func == sp.Add: new_args = [ Diff(e, target=expr.target, superscript=expr.superscript) for e in arg.args ] return sp.Add(*new_args) if arg.func not in (sp.Mul, sp.Pow): return Diff(arg, target=expr.target, superscript=expr.superscript) else: prod_list = normalize_product(arg) result = 0 for i in range(len(prod_list)): pre_factor = prod(prod_list[j] for j in range(len(prod_list)) if i != j) result += pre_factor * Diff(prod_list[i], target=expr.target, superscript=expr.superscript) return result else: new_args = [expand_diff_products(e) for e in expr.args] return expr.func(*new_args) if new_args else expr
def apply_wieners(complex_field: Field, wieners: Field, output_weight_field: Field): assert complex_field.index_dimensions == 3 assert wieners.index_dimensions == 2 assert output_weight_field.index_dimensions == 1 assignments = [] wiener_sum = [] for stack_index in range(complex_field.index_shape[0]): for patch_index in range(complex_field.index_shape[1]): wien = wieners(stack_index, patch_index) wiener_sum.append(wien**2) assignments.extend( pystencils.Assignment(complex_field.center(stack_index, patch_index, i), complex_field.center(stack_index, patch_index, i) * wien) for i in (0, 1) ) assignments.append(pystencils.Assignment( output_weight_field.center(stack_index), 1 / sympy.Add(*wiener_sum) )) return AssignmentCollection(assignments)