def __new__(cls, expr1, expr2): expr1 = sympify(expr1) expr2 = sympify(expr2) if default_sort_key(expr1) > default_sort_key(expr2): return -Cross(expr2, expr1) obj = Expr.__new__(cls, expr1, expr2) obj._expr1 = expr1 obj._expr2 = expr2 return obj
def sort_key(self, order=None): """Return a canonical key that can be used for sorting. Ordering is based on the size and sorted elements of the partition and ties are broken with the rank. Examples ======== >>> from sympy.utilities.iterables import default_sort_key >>> from sympy.combinatorics.partitions import Partition >>> from sympy.abc import x >>> a = Partition([1, 2]) >>> b = Partition([3, 4]) >>> c = Partition([1, x]) >>> d = Partition(list(range(4))) >>> l = [d, b, a + 1, a, c] >>> l.sort(key=default_sort_key); l [{{1, 2}}, {{1}, {2}}, {{1, x}}, {{3, 4}}, {{0, 1, 2, 3}}] """ if order is None: members = self.members else: members = tuple(sorted(self.members, key=lambda w: default_sort_key(w, order))) return list(map(default_sort_key, (self.size, members, self.rank)))
def sort_key(self, order=None): """Return a canonical key that can be used for sorting. Ordering is based on the size and sorted elements of the partition and ties are broken with the rank. Examples ======== >>> from sympy.utilities.iterables import default_sort_key >>> from sympy.combinatorics.partitions import Partition >>> from sympy.abc import x >>> a = Partition([1, 2]) >>> b = Partition([3, 4]) >>> c = Partition([1, x]) >>> d = Partition(list(range(4))) >>> l = [d, b, a + 1, a, c] >>> l.sort(key=default_sort_key); l [Partition(FiniteSet(1, 2)), Partition(FiniteSet(1), FiniteSet(2)), Partition(FiniteSet(1, x)), Partition(FiniteSet(3, 4)), Partition(FiniteSet(0, 1, 2, 3))] """ if order is None: members = self.members else: members = tuple( sorted(self.members, key=lambda w: default_sort_key(w, order))) return tuple(map(default_sort_key, (self.size, members, self.rank)))
def sort_key(self, order=None): """Return a canonical key that can be used for sorting. Ordering is based on the size and sorted elements of the partition and ties are broken with the rank. Examples ======== >>> from sympy.utilities.iterables import default_sort_key >>> from sympy.combinatorics.partitions import Partition >>> from sympy.abc import x >>> a = Partition([[1, 2]]) >>> b = Partition([[3, 4]]) >>> c = Partition([[1, x]]) >>> d = Partition([range(4)]) >>> l = [d, b, a + 1, a, c] >>> l.sort(key=default_sort_key); l [{{1, 2}}, {{1}, {2}}, {{1, x}}, {{3, 4}}, {{0, 1, 2, 3}}] """ if order is None: members = self.members else: members = tuple( sorted(self.members, key=lambda w: default_sort_key(w, order))) return self.size, members, self.rank
def _eigenvects_DOM(M, **kwargs): DOM = DomainMatrix.from_Matrix(M, field=True, extension=True) if DOM.domain != EX: rational, algebraic = dom_eigenvects(DOM) eigenvects = dom_eigenvects_to_sympy(rational, algebraic, M.__class__, **kwargs) eigenvects = sorted(eigenvects, key=lambda x: default_sort_key(x[0])) return eigenvects return None
def as_expr_variables(self, order_symbols): if order_symbols is None: order_symbols = self.args[1:] else: if not all(o[1] == order_symbols[0][1] for o in order_symbols) and \ not all(p == self.point[0] for p in self.point): raise NotImplementedError('Order at points other than 0 ' 'or oo not supported, got %s as a point.' % point) if order_symbols[0][1] != self.point[0]: raise NotImplementedError( "Multiplying Order at different points is not supported.") order_symbols = dict(order_symbols) for s, p in dict(self.args[1:]).items(): if s not in order_symbols.keys(): order_symbols[s] = p order_symbols = sorted(order_symbols.items(), key=lambda x: default_sort_key(x[0])) return self.expr, tuple(order_symbols)
def sort_args_by_name(self): """ Sort arguments in the tensor product so that their order is lexicographical. Examples ======== >>> from sympy import MatrixSymbol, MatrixExpr, Sum, Symbol >>> from sympy.abc import i, j, k, l, N >>> from sympy.codegen.array_utils import CodegenArrayContraction >>> A = MatrixSymbol("A", N, N) >>> B = MatrixSymbol("B", N, N) >>> C = MatrixSymbol("C", N, N) >>> D = MatrixSymbol("D", N, N) >>> cg = CodegenArrayContraction.from_MatMul(C*D*A*B) >>> cg CodegenArrayContraction(CodegenArrayTensorProduct(C, D, A, B), (1, 2), (3, 4), (5, 6)) >>> cg.sort_args_by_name() CodegenArrayContraction(CodegenArrayTensorProduct(A, B, C, D), (0, 7), (1, 2), (5, 6)) """ expr = self.expr if not isinstance(expr, CodegenArrayTensorProduct): return self args = expr.args sorted_data = sorted(enumerate(args), key=lambda x: default_sort_key(x[1])) pos_sorted, args_sorted = zip(*sorted_data) reordering_map = {i: pos_sorted.index(i) for i, arg in enumerate(args)} contraction_tuples = self._get_contraction_tuples() contraction_tuples = [[(reordering_map[j], k) for j, k in i] for i in contraction_tuples] c_tp = CodegenArrayTensorProduct(*args_sorted) new_contr_indices = self._contraction_tuples_to_contraction_indices( c_tp, contraction_tuples) return CodegenArrayContraction(c_tp, *new_contr_indices)
def sort_args_by_name(self): """ Sort arguments in the tensor product so that their order is lexicographical. Examples ======== >>> from sympy import MatrixSymbol, MatrixExpr, Sum, Symbol >>> from sympy.abc import i, j, k, l, N >>> from sympy.codegen.array_utils import CodegenArrayContraction >>> A = MatrixSymbol("A", N, N) >>> B = MatrixSymbol("B", N, N) >>> C = MatrixSymbol("C", N, N) >>> D = MatrixSymbol("D", N, N) >>> cg = CodegenArrayContraction.from_MatMul(C*D*A*B) >>> cg CodegenArrayContraction(CodegenArrayTensorProduct(C, D, A, B), (1, 2), (3, 4), (5, 6)) >>> cg.sort_args_by_name() CodegenArrayContraction(CodegenArrayTensorProduct(A, B, C, D), (0, 7), (1, 2), (5, 6)) """ expr = self.expr if not isinstance(expr, CodegenArrayTensorProduct): return self args = expr.args sorted_data = sorted(enumerate(args), key=lambda x: default_sort_key(x[1])) pos_sorted, args_sorted = zip(*sorted_data) reordering_map = {i: pos_sorted.index(i) for i, arg in enumerate(args)} contraction_tuples = self._get_contraction_tuples() contraction_tuples = [[(reordering_map[j], k) for j, k in i] for i in contraction_tuples] c_tp = CodegenArrayTensorProduct(*args_sorted) new_contr_indices = self._contraction_tuples_to_contraction_indices( c_tp, contraction_tuples ) return CodegenArrayContraction(c_tp, *new_contr_indices)
def _sort_key(arg): return default_sort_key(arg[0].as_independent(x)[1])
def _sorted_args(self): from sympy.core.compatibility import default_sort_key return tuple(sorted(self.args, key=lambda w: default_sort_key(w)))
def _sorted_args(self): from sympy.core.compatibility import default_sort_key return sorted(self.args, key=lambda w: default_sort_key(w))
def set_equivalence_relationship(self, other): plausibles_set, is_equivalent = self.plausibles_set() if len(plausibles_set) == 1: if is_equivalent: eq, *_ = plausibles_set if isinstance(other, (list, tuple)): is_equivalent = True plausibles_set = set() for other in other: _plausibles_set, _is_equivalent = other.plausibles_set( ) plausibles_set |= _plausibles_set is_equivalent &= _is_equivalent else: plausibles_set, is_equivalent = other.plausibles_set() assert eq not in plausibles_set, 'cyclic proof detected' equivalent = [*plausibles_set] if len(equivalent) == 1: equivalent, *_ = equivalent elif not equivalent: return if is_equivalent: from sympy.core.compatibility import default_sort_key if isinstance(equivalent, (list, tuple)): p, *q = sorted( (eq, *equivalent), key=lambda inf: default_sort_key(inf.cond)) else: p, q = sorted( (eq, equivalent), key=lambda inf: default_sort_key(inf.cond)) p.equivalent = q else: del eq._assumptions['plausible'] eq.given = equivalent return True else: eq, *_ = plausibles_set if isinstance(other, list): plausibles_set = set() for other in other: _plausibles_set, is_equivalent = other.plausibles_set() plausibles_set |= _plausibles_set if not is_equivalent: return else: plausibles_set, is_equivalent = other.plausibles_set() if not is_equivalent: return assert eq not in plausibles_set, 'cyclic proof detected' equivalent = [*plausibles_set] if len(equivalent) == 1: equivalent, *_ = equivalent elif not equivalent: return del eq._assumptions['plausible'] eq.given = equivalent return True
def recurse_expr(expr, index_ranges={}): if expr.is_Mul: nonmatargs = [] matargs = [] pos_arg = [] pos_ind = [] dlinks = {} link_ind = [] counter = 0 for arg in expr.args: arg_symbol, arg_indices = recurse_expr(arg, index_ranges) if arg_indices is None: nonmatargs.append(arg_symbol) continue i1, i2 = arg_indices pos_arg.append(arg_symbol) pos_ind.append(i1) pos_ind.append(i2) link_ind.extend([None, None]) if i1 in dlinks: other_i1 = dlinks[i1] link_ind[2*counter] = other_i1 link_ind[other_i1] = 2*counter if i2 in dlinks: other_i2 = dlinks[i2] link_ind[2*counter + 1] = other_i2 link_ind[other_i2] = 2*counter + 1 dlinks[i1] = 2*counter dlinks[i2] = 2*counter + 1 counter += 1 cur_ind_pos = link_ind.index(None) first_index = pos_ind[cur_ind_pos] while True: d = cur_ind_pos // 2 r = cur_ind_pos % 2 if r == 1: matargs.append(transpose(pos_arg[d])) else: matargs.append(pos_arg[d]) next_ind_pos = link_ind[2*d + 1 - r] if next_ind_pos is None: last_index = pos_ind[2*d + 1 - r] break cur_ind_pos = next_ind_pos return Mul.fromiter(nonmatargs)*MatMul.fromiter(matargs), (first_index, last_index) elif expr.is_Add: res = [recurse_expr(i) for i in expr.args] res = [ ((transpose(i), (j[1], j[0])) if default_sort_key(j[0]) > default_sort_key(j[1]) else (i, j)) for (i, j) in res ] addends, last_indices = zip(*res) last_indices = list(set(last_indices)) if len(last_indices) > 1: print(last_indices) raise ValueError("incompatible summation") return MatAdd.fromiter(addends), last_indices[0] elif isinstance(expr, KroneckerDelta): i1, i2 = expr.args return S.One, (i1, i2) elif isinstance(expr, MatrixElement): matrix_symbol, i1, i2 = expr.args if i1 in index_ranges: r1, r2 = index_ranges[i1] if r1 != 0 or matrix_symbol.shape[0] != r2+1: raise ValueError("index range mismatch: {0} vs. (0, {1})".format( (r1, r2), matrix_symbol.shape[0])) if i2 in index_ranges: r1, r2 = index_ranges[i2] if r1 != 0 or matrix_symbol.shape[1] != r2+1: raise ValueError("index range mismatch: {0} vs. (0, {1})".format( (r1, r2), matrix_symbol.shape[1])) if (i1 == i2) and (i1 in index_ranges): return trace(matrix_symbol), None return matrix_symbol, (i1, i2) elif isinstance(expr, Sum): return recurse_expr( expr.args[0], index_ranges={i[0]: i[1:] for i in expr.args[1:]} ) else: return expr, None