def test_issue_7840(): # daveknippers' example C393 = sympify( # noqa 'Piecewise((C391 - 1.65, C390 < 0.5), (Piecewise((C391 - 1.65, \ C391 > 2.35), (C392, True)), True))' ) C391 = sympify( # noqa 'Piecewise((2.05*C390**(-1.03), C390 < 0.5), (2.5*C390**(-0.625), True))' ) C393 = C393.subs('C391',C391) # noqa # simple substitution sub = {} sub['C390'] = 0.703451854 sub['C392'] = 1.01417794 ss_answer = C393.subs(sub) # cse substitutions, new_eqn = cse(C393) for pair in substitutions: sub[pair[0].name] = pair[1].subs(sub) cse_answer = new_eqn[0].subs(sub) # both methods should be the same assert ss_answer == cse_answer # GitRay's example expr = sympify( "Piecewise((Symbol('ON'), Equality(Symbol('mode'), Symbol('ON'))), \ (Piecewise((Piecewise((Symbol('OFF'), StrictLessThan(Symbol('x'), \ Symbol('threshold'))), (Symbol('ON'), S.true)), Equality(Symbol('mode'), \ Symbol('AUTO'))), (Symbol('OFF'), S.true)), S.true))" ) substitutions, new_eqn = cse(expr) # this Piecewise should be exactly the same assert new_eqn[0] == expr # there should not be any replacements assert len(substitutions) < 1
def add_assignment(self, name, expr, root_name=None, wrt_set=None): assert isinstance(name, str) assert name not in self.assignments if wrt_set is None: wrt_set = frozenset() if root_name is None: root_name = name self.assignments[name] = sym.sympify(expr)
def reduced_row_echelon_form(m): """Calculates a reduced row echelon form of a matrix `m`. :arg m: a 2D :class:`numpy.ndarray` or a list of lists or a sympy Matrix :return: reduced row echelon form as a 2D :class:`numpy.ndarray` and a list of pivots """ mat = np.array(m, dtype=object) index = 0 nrows = mat.shape[0] ncols = mat.shape[1] pivot_cols = [] for i in range(ncols): if index == nrows: break pivot = nrows for k in range(index, nrows): if mat[k, i] != 0 and pivot == nrows: pivot = k if abs(mat[k, i]) == 1: pivot = k break if pivot == nrows: continue if pivot != index: mat[[pivot, index], :] = mat[[index, pivot], :] pivot_cols.append(i) scale = mat[index, i] if isinstance(scale, (int, sym.Integer)): scale = int(scale) for j in range(mat.shape[1]): elem = mat[index, j] if isinstance(scale, int) and isinstance(elem, (int, sym.Integer)): quo = int(elem) // scale if quo * scale == elem: mat[index, j] = quo continue mat[index, j] = sym.sympify(elem) / scale for j in range(nrows): if (j == index): continue scale = mat[j, i] if scale != 0: mat[j, :] = mat[j, :] - mat[index, :] * scale index = index + 1 return mat, pivot_cols
def get_stored_ids_and_unscaled_projection_matrix(self): from pytools import ProcessLogger plog = ProcessLogger(logger, "compute PDE for Taylor coefficients") mis = self.get_full_coefficient_identifiers() coeff_ident_enumerate_dict = { tuple(mi): i for (i, mi) in enumerate(mis) } diff_op = self.get_pde_as_diff_op() assert len(diff_op.eqs) == 1 pde_dict = {k.mi: v for k, v in diff_op.eqs[0].items()} for ident in pde_dict.keys(): if ident not in coeff_ident_enumerate_dict: # Order of the expansion is less than the order of the PDE. # In that case, the compression matrix is the identity matrix # and there's nothing to project from_input_coeffs_by_row = [[(i, 1)] for i in range(len(mis))] from_output_coeffs_by_row = [[] for _ in range(len(mis))] shape = (len(mis), len(mis)) op = CSEMatVecOperator(from_input_coeffs_by_row, from_output_coeffs_by_row, shape) return mis, op # Calculate the multi-index that appears last in in the PDE in # reverse degree lexicographic order (degrevlex). max_mi_idx = max(coeff_ident_enumerate_dict[ident] for ident in pde_dict.keys()) max_mi = mis[max_mi_idx] max_mi_coeff = pde_dict[max_mi] max_mi_mult = -1 / sym.sympify(max_mi_coeff) def is_stored(mi): """ A multi_index mi is not stored if mi >= max_mi """ return any(mi[d] < max_mi[d] for d in range(self.dim)) stored_identifiers = [] from_input_coeffs_by_row = [] from_output_coeffs_by_row = [] for i, mi in enumerate(mis): # If the multi-index is to be stored, keep the projection matrix # entry empty if is_stored(mi): idx = len(stored_identifiers) stored_identifiers.append(mi) from_input_coeffs_by_row.append([(idx, 1)]) from_output_coeffs_by_row.append([]) continue diff = [mi[d] - max_mi[d] for d in range(self.dim)] # eg: u_xx + u_yy + u_zz is represented as # [((2, 0, 0), 1), ((0, 2, 0), 1), ((0, 0, 2), 1)] assignment = [] for other_mi, coeff in pde_dict.items(): j = coeff_ident_enumerate_dict[add_mi(other_mi, diff)] if i == j: # Skip the u_zz part here. continue # PDE might not have max_mi_coeff = -1, divide by -max_mi_coeff # to get a relation of the form, u_zz = - u_xx - u_yy for Laplace 3D. assignment.append((j, coeff * max_mi_mult)) from_input_coeffs_by_row.append([]) from_output_coeffs_by_row.append(assignment) plog.done() logger.debug( "number of Taylor coefficients was reduced from {orig} to {red}". format(orig=len(self.get_full_coefficient_identifiers()), red=len(stored_identifiers))) shape = (len(mis), len(stored_identifiers)) op = CSEMatVecOperator(from_input_coeffs_by_row, from_output_coeffs_by_row, shape) return stored_identifiers, op