diff options
author | Michael Schneeberger <michael.schneeberger@fhnw.ch> | 2024-03-27 14:52:22 +0100 |
---|---|---|
committer | Michael Schneeberger <michael.schneeberger@fhnw.ch> | 2024-03-27 14:52:22 +0100 |
commit | ebc557009b5343be74d1ef8e3a9e1c9b44d24a8f (patch) | |
tree | c1e6c67fb86e7afd864b3188db6829a463b47aba | |
parent | add minimal documentation to the expression mixins (diff) | |
download | polymatrix-ebc557009b5343be74d1ef8e3a9e1c9b44d24a8f.tar.gz polymatrix-ebc557009b5343be74d1ef8e3a9e1c9b44d24a8f.zip |
format Python files with ruff
Diffstat (limited to '')
84 files changed, 1326 insertions, 1357 deletions
diff --git a/polymatrix/__init__.py b/polymatrix/__init__.py index 45968aa..8ec096f 100644 --- a/polymatrix/__init__.py +++ b/polymatrix/__init__.py @@ -1,5 +1,7 @@ from polymatrix.expressionstate.abc import ExpressionState as internal_ExpressionState -from polymatrix.expressionstate.init import init_expression_state as internal_init_expression_state +from polymatrix.expressionstate.init import ( + init_expression_state as internal_init_expression_state, +) from polymatrix.expression.expression import Expression as internal_Expression from polymatrix.expression.from_ import from_ as internal_from from polymatrix.expression import v_stack as internal_v_stack diff --git a/polymatrix/denserepr/from_.py b/polymatrix/denserepr/from_.py index 7bafb5d..4af345a 100644 --- a/polymatrix/denserepr/from_.py +++ b/polymatrix/denserepr/from_.py @@ -1,71 +1,86 @@ import itertools import numpy as np -from polymatrix.denserepr.impl import DenseReprBufferImpl, DenseReprImpl - -from polymatrix.expression.expression import Expression -from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin -from polymatrix.expressionstate.abc import ExpressionState -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable from polymatrix.statemonad.init import init_state_monad from polymatrix.statemonad.mixins import StateMonadMixin +from polymatrix.expressionstate.abc import ExpressionState +from polymatrix.expression.expression import Expression +from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) from polymatrix.denserepr.utils.monomialtoindex import variable_indices_to_column_index +from polymatrix.denserepr.impl import DenseReprBufferImpl, DenseReprImpl def from_polymatrix( expressions: Expression | tuple[Expression], variables: Expression = None, sorted: bool = None, -) -> StateMonadMixin[ExpressionState, tuple[tuple[tuple[np.ndarray, ...], ...], tuple[int, ...]]]: - +) -> StateMonadMixin[ + ExpressionState, tuple[tuple[tuple[np.ndarray, ...], ...], tuple[int, ...]] +]: if isinstance(expressions, Expression): expressions = (expressions,) - assert isinstance(variables, ExpressionBaseMixin) or variables is None, f'{variables=}' + assert ( + isinstance(variables, ExpressionBaseMixin) or variables is None + ), f"{variables=}" def func(state: ExpressionState): - def acc_underlying_application(acc, v): state, underlying_list = acc state, underlying = v.apply(state) - assert underlying.shape[1] == 1, f'{underlying.shape[1]=} is not 1' - + assert underlying.shape[1] == 1, f"{underlying.shape[1]=} is not 1" + return state, underlying_list + (underlying,) - *_, (state, polymatrix_list) = tuple(itertools.accumulate( - expressions, - acc_underlying_application, - initial=(state, tuple()), - )) + *_, (state, polymatrix_list) = tuple( + itertools.accumulate( + expressions, + acc_underlying_application, + initial=(state, tuple()), + ) + ) if variables is None: sorted_variable_index = tuple() - + else: state, variable_index = get_variable_indices_from_variable(state, variables) if sorted: - tagged_variable_index = tuple((offset, state.get_name_from_offset(offset)) for offset in variable_index) + tagged_variable_index = tuple( + (offset, state.get_name_from_offset(offset)) + for offset in variable_index + ) + + sorted_variable_index = tuple( + v[0] for v in sorted(tagged_variable_index, key=lambda v: v[1]) + ) - sorted_variable_index = tuple(v[0] for v in sorted(tagged_variable_index, key=lambda v: v[1])) - else: sorted_variable_index = variable_index sorted_variable_index_set = set(sorted_variable_index) if len(sorted_variable_index) != len(sorted_variable_index_set): - duplicates = tuple(state.get_name_from_offset(var) for var in sorted_variable_index_set if 1 < sorted_variable_index.count(var)) - raise Exception(f'{duplicates=}. Make sure you give a unique name for each variables.') - + duplicates = tuple( + state.get_name_from_offset(var) + for var in sorted_variable_index_set + if 1 < sorted_variable_index.count(var) + ) + raise Exception( + f"{duplicates=}. Make sure you give a unique name for each variables." + ) + variable_index_map = {old: new for new, old in enumerate(sorted_variable_index)} n_param = len(sorted_variable_index) def gen_numpy_matrices(): for polymatrix in polymatrix_list: - n_row = polymatrix.shape[0] buffer = DenseReprBufferImpl( @@ -76,13 +91,13 @@ def from_polymatrix( for row in range(n_row): polymatrix_terms = polymatrix.get_poly(row, 0) - + if polymatrix_terms is None: continue if len(polymatrix_terms) == 0: buffer.add(row, 0, 0, 0) - + else: for monomial, value in polymatrix_terms.items(): @@ -92,21 +107,25 @@ def from_polymatrix( index = variable_index_map[var] except KeyError: # todo: improve this error message! - raise KeyError(f'{var=} ({state.get_key_from_offset(var)}) is incompatible with {variable_index_map=}') + raise KeyError( + f"{var=} ({state.get_key_from_offset(var)}) is incompatible with {variable_index_map=}" + ) for _ in range(count): yield index new_variable_indices = tuple(gen_new_monomial()) - cols = variable_indices_to_column_index(n_param, new_variable_indices) + cols = variable_indices_to_column_index( + n_param, new_variable_indices + ) col_value = value / len(cols) for col in cols: degree = sum(count for _, count in monomial) buffer.add(row, col, degree, col_value) - + yield buffer underlying_matrices = tuple(gen_numpy_matrices()) @@ -132,14 +151,20 @@ def from_polymatrix( for row, (key, monomial_terms) in enumerate(auxillary_equations): for monomial, value in monomial_terms.items(): - new_monomial = tuple(variable_index_map[var] for var, count in monomial for _ in range(count)) + new_monomial = tuple( + variable_index_map[var] + for var, count in monomial + for _ in range(count) + ) cols = variable_indices_to_column_index(n_param, new_monomial) col_value = value / len(cols) for col in cols: - buffer.add(row, col, sum(count for _, count in monomial), col_value) + buffer.add( + row, col, sum(count for _, count in monomial), col_value + ) auxillary_matrix_equations = buffer @@ -152,4 +177,4 @@ def from_polymatrix( return state, result - return init_state_monad(func)
\ No newline at end of file + return init_state_monad(func) diff --git a/polymatrix/denserepr/impl.py b/polymatrix/denserepr/impl.py index 5f54f86..9007c2f 100644 --- a/polymatrix/denserepr/impl.py +++ b/polymatrix/denserepr/impl.py @@ -5,7 +5,9 @@ import numpy as np import scipy.sparse from polymatrix.expressionstate.abc import ExpressionState -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) @dataclasses.dataclass @@ -22,8 +24,10 @@ class DenseReprBufferImpl: buffer = np.zeros((self.n_row, self.n_param**index), dtype=np.double) else: - buffer = scipy.sparse.dok_array((self.n_row, self.n_param**index), dtype=np.double) - + buffer = scipy.sparse.dok_array( + (self.n_row, self.n_param**index), dtype=np.double + ) + self.data[index] = buffer def add(self, row: int, col: int, index: int, value: float): @@ -55,7 +59,11 @@ class DenseReprImpl: if index < len(self.aux_data): yield self.aux_data[index] - indices = set(key for equations in self.data + (self.aux_data,) for key in equations.keys()) + indices = set( + key + for equations in self.data + (self.aux_data,) + for key in equations.keys() + ) def gen_matrices(): for index in indices: @@ -74,7 +82,9 @@ class DenseReprImpl: try: yield self.variable_mapping.index(variable_index) except ValueError: - raise ValueError(f'{variable_index} not found in {self.variable_mapping}') + raise ValueError( + f"{variable_index} not found in {self.variable_mapping}" + ) value_index = list(gen_value_index()) @@ -82,7 +92,10 @@ class DenseReprImpl: def set_value(self, variable, value): variable_indices = get_variable_indices_from_variable(self.state, variable)[1] - value_index = list(self.variable_mapping.index(variable_index) for variable_index in variable_indices) + value_index = list( + self.variable_mapping.index(variable_index) + for variable_index in variable_indices + ) vec = np.zeros(len(self.variable_mapping)) vec[value_index] = value return vec @@ -95,6 +108,7 @@ class DenseReprImpl: max_idx = max(equations.keys()) if 2 <= max_idx: + def func(x: np.ndarray) -> np.ndarray: if isinstance(x, tuple) or isinstance(x, list): x = np.array(x).reshape(-1, 1) @@ -106,11 +120,13 @@ class DenseReprImpl: next = (acc @ x.T).reshape(-1, 1) return next - x_powers = tuple(itertools.accumulate( - range(max_idx - 1), - acc_x_powers, - initial=x, - ))[1:] + x_powers = tuple( + itertools.accumulate( + range(max_idx - 1), + acc_x_powers, + initial=x, + ) + )[1:] def gen_value(): for idx, equation in equations.items(): @@ -121,15 +137,16 @@ class DenseReprImpl: yield equation @ x else: - yield equation @ x_powers[idx-2] + yield equation @ x_powers[idx - 2] return sum(gen_value()) else: + def func(x: np.ndarray) -> np.ndarray: if isinstance(x, tuple) or isinstance(x, list): x = np.array(x).reshape(-1, 1) - + def gen_value(): for idx, equation in equations.items(): if idx == 0: @@ -140,4 +157,4 @@ class DenseReprImpl: return sum(gen_value()) - return func
\ No newline at end of file + return func diff --git a/polymatrix/denserepr/utils/monomialtoindex.py b/polymatrix/denserepr/utils/monomialtoindex.py index c13adfd..a40f2ee 100644 --- a/polymatrix/denserepr/utils/monomialtoindex.py +++ b/polymatrix/denserepr/utils/monomialtoindex.py @@ -2,10 +2,12 @@ import itertools def variable_indices_to_column_index( - n_var: int, - variable_indices: tuple[int, ...], + n_var: int, + variable_indices: tuple[int, ...], ) -> int: - variable_indices_perm = itertools.permutations(variable_indices) - - return set(sum(idx*(n_var**level) for level, idx in enumerate(monomial)) for monomial in variable_indices_perm) + + return set( + sum(idx * (n_var**level) for level, idx in enumerate(monomial)) + for monomial in variable_indices_perm + ) diff --git a/polymatrix/expression/__init__.py b/polymatrix/expression/__init__.py index 97a45cd..a731191 100644 --- a/polymatrix/expression/__init__.py +++ b/polymatrix/expression/__init__.py @@ -10,25 +10,26 @@ from polymatrix.expression.expression import init_expression, Expression def v_stack( expressions: Iterable[Expression], ) -> Expression: - - def gen_underlying(): - for expr in expressions: - if isinstance(expr, Expression): - yield expr - else: - yield polymatrix.expression.from_.from_(expr) - - return init_expression( - underlying=polymatrix.expression.impl.VStackExprImpl( + def gen_underlying(): + for expr in expressions: + if isinstance(expr, Expression): + yield expr + else: + yield polymatrix.expression.from_.from_(expr) + + return init_expression( + underlying=polymatrix.expression.impl.VStackExprImpl( underlying=tuple(gen_underlying()), ), ) + def h_stack( expressions: Iterable[Expression], ) -> Expression: return v_stack((expr.T for expr in expressions)).T + def block_diag( expressions: tuple[Expression], ) -> Expression: @@ -38,15 +39,15 @@ def block_diag( ) ) + def product( - expressions: Iterable[Expression], - degrees: tuple[int, ...] = None, + expressions: Iterable[Expression], + degrees: tuple[int, ...] = None, ): return init_expression( underlying=polymatrix.expression.impl.ProductExprImpl( underlying=tuple(expressions), - degrees=degrees, + degrees=degrees, stack=get_stack_lines(), ) ) - diff --git a/polymatrix/expression/expression.py b/polymatrix/expression/expression.py index f190482..6a84807 100644 --- a/polymatrix/expression/expression.py +++ b/polymatrix/expression/expression.py @@ -7,31 +7,37 @@ import numpy as np import polymatrix.expression.init from polymatrix.utils.getstacklines import get_stack_lines -from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin -from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin -from polymatrix.expression.op import diff, integrate, linear_in, linear_monomials, legendre, filter_, degree from polymatrix.polymatrix.abc import PolyMatrix from polymatrix.expressionstate.abc import ExpressionState +from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin +from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin +from polymatrix.expression.op import ( + diff, + integrate, + linear_in, + linear_monomials, + legendre, + filter_, + degree, +) class Expression( ExpressionBaseMixin, abc.ABC, ): - @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... - # overwrites the abstract method of `PolyMatrixExprBaseMixin` + # overwrites the abstract method of `ExpressionBaseMixin` def apply(self, state: ExpressionState) -> tuple[ExpressionState, PolyMatrix]: return self.underlying.apply(state) def read(self, state: ExpressionState) -> PolyMatrix: return self.apply(state)[1] - def __add__(self, other: ExpressionBaseMixin) -> 'Expression': + def __add__(self, other: ExpressionBaseMixin) -> "Expression": return self._binary(polymatrix.expression.init.init_addition_expr, self, other) def __getattr__(self, name): @@ -39,7 +45,7 @@ class Expression( if isinstance(attr, ExpressionBaseMixin): return dataclasses.replace( - self, + self, underlying=attr, ) @@ -52,12 +58,16 @@ class Expression( underlying=self.underlying, index=key, ), - ) + ) - def __matmul__(self, other: typing.Union[ExpressionBaseMixin, np.ndarray]) -> 'Expression': - return self._binary(polymatrix.expression.init.init_matrix_mult_expr, self, other) + def __matmul__( + self, other: typing.Union[ExpressionBaseMixin, np.ndarray] + ) -> "Expression": + return self._binary( + polymatrix.expression.init.init_matrix_mult_expr, self, other + ) - def __mul__(self, other) -> 'Expression': + def __mul__(self, other) -> "Expression": return self._binary(polymatrix.expression.init.init_elem_mult_expr, self, other) def __pow__(self, num): @@ -75,11 +85,13 @@ class Expression( return self._binary(polymatrix.expression.init.init_addition_expr, other, self) def __rmatmul__(self, other): - return self._binary(polymatrix.expression.init.init_matrix_mult_expr, other, self) + return self._binary( + polymatrix.expression.init.init_matrix_mult_expr, other, self + ) def __rmul__(self, other): return self * other - + def __rsub__(self, other): return other + (-self) @@ -90,12 +102,10 @@ class Expression( return self._binary(polymatrix.expression.init.init_division_expr, self, other) @abc.abstractmethod - def copy(self, underlying: ExpressionBaseMixin) -> 'Expression': - ... + def copy(self, underlying: ExpressionBaseMixin) -> "Expression": ... @staticmethod def _binary(op, left, right): - stack = get_stack_lines() if isinstance(left, Expression): @@ -120,7 +130,7 @@ class Expression( underlying=op(left, right, stack), ) - def cache(self) -> 'Expression': + def cache(self) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_cache_expr( underlying=self.underlying, @@ -128,24 +138,24 @@ class Expression( ) def combinations( - self, - degrees: tuple[int, ...] | int, - ): + self, + degrees: tuple[int, ...] | int, + ): return self.copy( underlying=polymatrix.expression.init.init_combinations_expr( expression=self.underlying, degrees=degrees, ), ) - - def degree(self) -> 'Expression': + + def degree(self) -> "Expression": return self.copy( underlying=degree( underlying=self.underlying, ), ) - def determinant(self) -> 'Expression': + def determinant(self) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_determinant_expr( underlying=self.underlying, @@ -160,10 +170,10 @@ class Expression( ) def diff( - self, - variables: 'Expression', + self, + variables: "Expression", introduce_derivatives: bool = None, - ) -> 'Expression': + ) -> "Expression": return self.copy( underlying=diff( expression=self, @@ -173,9 +183,9 @@ class Expression( ) def divergence( - self, + self, variables: tuple, - ) -> 'Expression': + ) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_divergence_expr( underlying=self.underlying, @@ -185,9 +195,9 @@ class Expression( def eval( self, - variable: tuple, + variable: tuple, value: tuple[float, ...] = None, - ) -> 'Expression': + ) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_eval_expr( underlying=self.underlying, @@ -199,9 +209,9 @@ class Expression( # also applies to monomials (and variables?) def filter( self, - predicator: 'Expression', + predicator: "Expression", inverse: bool = None, - ) -> 'Expression': + ) -> "Expression": return self.copy( underlying=filter_( underlying=self.underlying, @@ -211,7 +221,7 @@ class Expression( ) # only applies to symmetric matrix - def from_symmetric_matrix(self) -> 'Expression': + def from_symmetric_matrix(self) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_from_symmetric_matrix_expr( underlying=self.underlying, @@ -221,9 +231,9 @@ class Expression( # only applies to monomials def half_newton_polytope( self, - variables: 'Expression', - filter: 'Expression | None' = None, - ) -> 'Expression': + variables: "Expression", + filter: "Expression | None" = None, + ) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_half_newton_polytope_expr( monomials=self.underlying, @@ -233,11 +243,8 @@ class Expression( ) def integrate( - self, - variables: 'Expression', - from_: tuple[float, ...], - to: tuple[float, ...] - ) -> 'Expression': + self, variables: "Expression", from_: tuple[float, ...], to: tuple[float, ...] + ) -> "Expression": return self.copy( underlying=integrate( expression=self, @@ -247,7 +254,7 @@ class Expression( ), ) - def linear_matrix_in(self, variable: 'Expression') -> 'Expression': + def linear_matrix_in(self, variable: "Expression") -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_linear_matrix_in_expr( underlying=self.underlying, @@ -256,10 +263,9 @@ class Expression( ) def linear_monomials( - self, - variables: 'Expression', - ) -> 'Expression': - + self, + variables: "Expression", + ) -> "Expression": return self.copy( underlying=linear_monomials( expression=self.underlying, @@ -268,12 +274,11 @@ class Expression( ) def linear_in( - self, - variables: 'Expression', - monomials: 'Expression' = None, - ignore_unmatched: bool = None, - ) -> 'Expression': - + self, + variables: "Expression", + monomials: "Expression" = None, + ignore_unmatched: bool = None, + ) -> "Expression": return self.copy( underlying=linear_in( expression=self.underlying, @@ -282,11 +287,11 @@ class Expression( ignore_unmatched=ignore_unmatched, ), ) - + def legendre( self, degrees: tuple[int, ...] = None, - ) -> 'Expression': + ) -> "Expression": return self.copy( underlying=legendre( expression=self.underlying, @@ -294,22 +299,24 @@ class Expression( ), ) - def max(self) -> 'Expression': + def max(self) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_max_expr( underlying=self.underlying, ), ) - def parametrize(self, name: str = None) -> 'Expression': + def parametrize(self, name: str = None) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_parametrize_expr( underlying=self.underlying, name=name, ), ) - - def quadratic_in(self, variables: 'Expression', monomials: 'Expression' = None) -> 'Expression': + + def quadratic_in( + self, variables: "Expression", monomials: "Expression" = None + ) -> "Expression": if monomials is None: monomials = self.quadratic_monomials(variables) @@ -325,9 +332,9 @@ class Expression( ) def quadratic_monomials( - self, - variables: 'Expression', - ) -> 'Expression': + self, + variables: "Expression", + ) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_quadratic_monomials_expr( underlying=self.underlying, @@ -335,7 +342,7 @@ class Expression( ), ) - def reshape(self, n: int, m: int) -> 'Expression': + def reshape(self, n: int, m: int) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_reshape_expr( underlying=self.underlying, @@ -343,7 +350,7 @@ class Expression( ), ) - def rep_mat(self, n: int, m: int) -> 'Expression': + def rep_mat(self, n: int, m: int) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_rep_mat_expr( underlying=self.underlying, @@ -354,9 +361,9 @@ class Expression( def set_element_at( self, row: int, - col: int, - value: 'Expression', - ) -> 'Expression': + col: int, + value: "Expression", + ) -> "Expression": if isinstance(value, Expression): value = value.underlying else: @@ -370,10 +377,10 @@ class Expression( ), ) - #remove? + # remove? def squeeze( self, - ) -> 'Expression': + ) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_squeeze_expr( underlying=self.underlying, @@ -382,9 +389,9 @@ class Expression( # only applies to monomials def subtract_monomials( - self, - monomials: 'Expression', - ) -> 'Expression': + self, + monomials: "Expression", + ) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_subtract_monomials_expr( underlying=self.underlying, @@ -394,9 +401,9 @@ class Expression( def substitute( self, - variable: tuple, - values: tuple['Expression', ...] = None, - ) -> 'Expression': + variable: tuple, + values: tuple["Expression", ...] = None, + ) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_substitute_expr( underlying=self.underlying, @@ -407,9 +414,9 @@ class Expression( def subs( self, - variable: tuple, - values: tuple['Expression', ...] = None, - ) -> 'Expression': + variable: tuple, + values: tuple["Expression", ...] = None, + ) -> "Expression": return self.substitute( variable=variable, values=values, @@ -429,7 +436,7 @@ class Expression( ), ) - def transpose(self) -> 'Expression': + def transpose(self) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_transpose_expr( underlying=self.underlying, @@ -437,17 +444,17 @@ class Expression( ) @property - def T(self) -> 'Expression': + def T(self) -> "Expression": return self.transpose() - def to_constant(self) -> 'Expression': + def to_constant(self) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_to_constant_expr( underlying=self.underlying, ), ) - def to_symmetric_matrix(self) -> 'Expression': + def to_symmetric_matrix(self) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_to_symmetric_matrix_expr( underlying=self.underlying, @@ -455,7 +462,7 @@ class Expression( ) # only applies to variables - def to_sorted_variables(self) -> 'Expression': + def to_sorted_variables(self) -> "Expression": return self.copy( underlying=polymatrix.expression.init.init_to_sorted_variables( underlying=self.underlying, @@ -464,10 +471,10 @@ class Expression( # also applies to monomials? def truncate( - self, + self, degrees: tuple[int], - variables: tuple | None = None, - inverse: bool = None, + variables: tuple | None = None, + inverse: bool = None, ): return self.copy( underlying=polymatrix.expression.init.init_truncate_expr( @@ -485,15 +492,14 @@ class ExpressionImpl(Expression): def __repr__(self) -> str: return self.underlying.__repr__() - - def copy(self, underlying: ExpressionBaseMixin) -> 'Expression': + + def copy(self, underlying: ExpressionBaseMixin) -> "Expression": return dataclasses.replace( - self, + self, underlying=underlying, ) - def init_expression( underlying: ExpressionBaseMixin, ): diff --git a/polymatrix/expression/from_.py b/polymatrix/expression/from_.py index daa916a..00f484e 100644 --- a/polymatrix/expression/from_.py +++ b/polymatrix/expression/from_.py @@ -8,22 +8,30 @@ from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.statemonad.abc import StateMonad -FromDataTypes = str | np.ndarray | sympy.Matrix | sympy.Expr | tuple | ExpressionBaseMixin | StateMonad +FromDataTypes = ( + str + | np.ndarray + | sympy.Matrix + | sympy.Expr + | tuple + | ExpressionBaseMixin + | StateMonad +) + def from_expr_or_none( - data: FromDataTypes, + data: FromDataTypes, ) -> Expression | None: - - return init_expression( + return init_expression( underlying=polymatrix.expression.init.init_from_expr_or_none( data=data, ), ) + def from_( data: FromDataTypes, ) -> Expression: - return init_expression( underlying=polymatrix.expression.init.init_from_expr( data=data, diff --git a/polymatrix/expression/impl.py b/polymatrix/expression/impl.py index 22c33bc..b902c22 100644 --- a/polymatrix/expression/impl.py +++ b/polymatrix/expression/impl.py @@ -9,381 +9,386 @@ from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.expression.mixins.additionexprmixin import AdditionExprMixin from polymatrix.expression.mixins.blockdiagexprmixin import BlockDiagExprMixin from polymatrix.expression.mixins.cacheexprmixin import CacheExprMixin -from polymatrix.expression.mixins.combinationsexprmixin import \ - CombinationsExprMixin -from polymatrix.expression.mixins.derivativeexprmixin import \ - DerivativeExprMixin -from polymatrix.expression.mixins.determinantexprmixin import \ - DeterminantExprMixin +from polymatrix.expression.mixins.combinationsexprmixin import CombinationsExprMixin +from polymatrix.expression.mixins.derivativeexprmixin import DerivativeExprMixin +from polymatrix.expression.mixins.determinantexprmixin import DeterminantExprMixin from polymatrix.expression.mixins.diagexprmixin import DiagExprMixin -from polymatrix.expression.mixins.divergenceexprmixin import \ - DivergenceExprMixin +from polymatrix.expression.mixins.divergenceexprmixin import DivergenceExprMixin from polymatrix.expression.mixins.divisionexprmixin import DivisionExprMixin from polymatrix.expression.mixins.elemmultexprmixin import ElemMultExprMixin from polymatrix.expression.mixins.evalexprmixin import EvalExprMixin from polymatrix.expression.mixins.eyeexprmixin import EyeExprMixin from polymatrix.expression.mixins.filterexprmixin import FilterExprMixin -from polymatrix.expression.mixins.fromsymmetricmatrixexprmixin import \ - FromSymmetricMatrixExprMixin +from polymatrix.expression.mixins.fromsymmetricmatrixexprmixin import ( + FromSymmetricMatrixExprMixin, +) from polymatrix.expression.mixins.fromtupleexprmixin import FromTupleExprMixin -from polymatrix.expression.mixins.fromtermsexprmixin import FromPolynomialDataExprMixin, PolynomialMatrixTupledData +from polymatrix.expression.mixins.fromtermsexprmixin import ( + FromPolynomialDataExprMixin, + PolynomialMatrixTupledData, +) from polymatrix.expression.mixins.getitemexprmixin import GetItemExprMixin -from polymatrix.expression.mixins.halfnewtonpolytopeexprmixin import \ - HalfNewtonPolytopeExprMixin +from polymatrix.expression.mixins.halfnewtonpolytopeexprmixin import ( + HalfNewtonPolytopeExprMixin, +) from polymatrix.expression.mixins.linearinexprmixin import LinearInExprMixin -from polymatrix.expression.mixins.linearmatrixinexprmixin import \ - LinearMatrixInExprMixin -from polymatrix.expression.mixins.linearmonomialsexprmixin import \ - LinearMonomialsExprMixin -from polymatrix.expression.mixins.matrixmultexprmixin import \ - MatrixMultExprMixin +from polymatrix.expression.mixins.linearmatrixinexprmixin import LinearMatrixInExprMixin +from polymatrix.expression.mixins.linearmonomialsexprmixin import ( + LinearMonomialsExprMixin, +) +from polymatrix.expression.mixins.matrixmultexprmixin import MatrixMultExprMixin from polymatrix.expression.mixins.degreeexprmixin import DegreeExprMixin from polymatrix.expression.mixins.maxexprmixin import MaxExprMixin -from polymatrix.expression.mixins.parametrizeexprmixin import \ - ParametrizeExprMixin -from polymatrix.expression.mixins.parametrizematrixexprmixin import \ - ParametrizeMatrixExprMixin -from polymatrix.expression.mixins.quadraticinexprmixin import \ - QuadraticInExprMixin -from polymatrix.expression.mixins.quadraticmonomialsexprmixin import \ - QuadraticMonomialsExprMixin +from polymatrix.expression.mixins.parametrizeexprmixin import ParametrizeExprMixin +from polymatrix.expression.mixins.parametrizematrixexprmixin import ( + ParametrizeMatrixExprMixin, +) +from polymatrix.expression.mixins.quadraticinexprmixin import QuadraticInExprMixin +from polymatrix.expression.mixins.quadraticmonomialsexprmixin import ( + QuadraticMonomialsExprMixin, +) from polymatrix.expression.mixins.repmatexprmixin import RepMatExprMixin from polymatrix.expression.mixins.reshapeexprmixin import ReshapeExprMixin -from polymatrix.expression.mixins.setelementatexprmixin import \ - SetElementAtExprMixin +from polymatrix.expression.mixins.setelementatexprmixin import SetElementAtExprMixin from polymatrix.expression.mixins.squeezeexprmixin import SqueezeExprMixin -from polymatrix.expression.mixins.substituteexprmixin import \ - SubstituteExprMixin -from polymatrix.expression.mixins.subtractmonomialsexprmixin import \ - SubtractMonomialsExprMixin +from polymatrix.expression.mixins.substituteexprmixin import SubstituteExprMixin +from polymatrix.expression.mixins.subtractmonomialsexprmixin import ( + SubtractMonomialsExprMixin, +) from polymatrix.expression.mixins.sumexprmixin import SumExprMixin from polymatrix.expression.mixins.symmetricexprmixin import SymmetricExprMixin -from polymatrix.expression.mixins.toconstantexprmixin import \ - ToConstantExprMixin -from polymatrix.expression.mixins.toquadraticexprmixin import \ - ToQuadraticExprMixin -from polymatrix.expression.mixins.tosymmetricmatrixexprmixin import \ - ToSymmetricMatrixExprMixin +from polymatrix.expression.mixins.toconstantexprmixin import ToConstantExprMixin +from polymatrix.expression.mixins.toquadraticexprmixin import ToQuadraticExprMixin +from polymatrix.expression.mixins.tosymmetricmatrixexprmixin import ( + ToSymmetricMatrixExprMixin, +) from polymatrix.expression.mixins.transposeexprmixin import TransposeExprMixin from polymatrix.expression.mixins.truncateexprmixin import TruncateExprMixin from polymatrix.expression.mixins.vstackexprmixin import VStackExprMixin -from polymatrix.expression.mixins.tosortedvariablesmixin import ToSortedVariablesExprMixin +from polymatrix.expression.mixins.tosortedvariablesmixin import ( + ToSortedVariablesExprMixin, +) @dataclassabc.dataclassabc(frozen=True) class AdditionExprImpl(AdditionExprMixin): - left: ExpressionBaseMixin - right: ExpressionBaseMixin - stack: tuple[FrameSummary] + left: ExpressionBaseMixin + right: ExpressionBaseMixin + stack: tuple[FrameSummary] + + # implement custom __repr__ method that returns a representation without the stack + def __repr__(self): + return f"{self.__class__.__name__}(left={self.left}, right={self.right})" - # implement custom __repr__ method that returns a representation without the stack - def __repr__(self): - return f'{self.__class__.__name__}(left={self.left}, right={self.right})' @dataclassabc.dataclassabc(frozen=True) class BlockDiagExprImpl(BlockDiagExprMixin): - underlying: tuple[ExpressionBaseMixin] + underlying: tuple[ExpressionBaseMixin] @dataclassabc.dataclassabc(frozen=True) class CacheExprImpl(CacheExprMixin): - underlying: ExpressionBaseMixin + underlying: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class CombinationsExprImpl(CombinationsExprMixin): - expression: ExpressionBaseMixin - degrees: tuple[int, ...] + expression: ExpressionBaseMixin + degrees: tuple[int, ...] @dataclassabc.dataclassabc(frozen=True) class DerivativeExprImpl(DerivativeExprMixin): - underlying: ExpressionBaseMixin - variables: tuple - introduce_derivatives: bool - stack: tuple[FrameSummary] + underlying: ExpressionBaseMixin + variables: tuple + introduce_derivatives: bool + stack: tuple[FrameSummary] - # implement custom __repr__ method that returns a representation without the stack - def __repr__(self): - return f'{self.__class__.__name__}(variables={self.variables}, underlying={self.underlying})' + # implement custom __repr__ method that returns a representation without the stack + def __repr__(self): + return f"{self.__class__.__name__}(variables={self.variables}, underlying={self.underlying})" @dataclassabc.dataclassabc(frozen=True) class DeterminantExprImpl(DeterminantExprMixin): - underlying: ExpressionBaseMixin + underlying: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class DiagExprImpl(DiagExprMixin): - underlying: ExpressionBaseMixin + underlying: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class DivergenceExprImpl(DivergenceExprMixin): - underlying: ExpressionBaseMixin - variables: tuple + underlying: ExpressionBaseMixin + variables: tuple + @dataclassabc.dataclassabc(frozen=True) class DivisionExprImpl(DivisionExprMixin): - left: ExpressionBaseMixin - right: ExpressionBaseMixin - stack: tuple[FrameSummary] + left: ExpressionBaseMixin + right: ExpressionBaseMixin + stack: tuple[FrameSummary] - # implement custom __repr__ method that returns a representation without the stack - def __repr__(self): - return f'{self.__class__.__name__}(left={self.left}, right={self.right})' + # implement custom __repr__ method that returns a representation without the stack + def __repr__(self): + return f"{self.__class__.__name__}(left={self.left}, right={self.right})" @dataclassabc.dataclassabc(frozen=True) class ElemMultExprImpl(ElemMultExprMixin): - left: ExpressionBaseMixin - right: ExpressionBaseMixin + left: ExpressionBaseMixin + right: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class EvalExprImpl(EvalExprMixin): - underlying: ExpressionBaseMixin - substitutions: tuple + underlying: ExpressionBaseMixin + substitutions: tuple @dataclassabc.dataclassabc(frozen=True) class EyeExprImpl(EyeExprMixin): - variable: ExpressionBaseMixin + variable: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class FilterExprImpl(FilterExprMixin): - underlying: ExpressionBaseMixin - predicator: ExpressionBaseMixin - inverse: bool + underlying: ExpressionBaseMixin + predicator: ExpressionBaseMixin + inverse: bool @dataclassabc.dataclassabc(frozen=True) class FromSymmetricMatrixExprImpl(FromSymmetricMatrixExprMixin): - underlying: ExpressionBaseMixin + underlying: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class FromTupleExprImpl(FromTupleExprMixin): - data: tuple[tuple[float]] - stack: tuple[FrameSummary] + data: tuple[tuple[float]] + stack: tuple[FrameSummary] + + # implement custom __repr__ method that returns a representation without the stack + def __repr__(self): + return f"{self.__class__.__name__}(data={self.data})" - # implement custom __repr__ method that returns a representation without the stack - def __repr__(self): - return f'{self.__class__.__name__}(data={self.data})' @dataclassabc.dataclassabc(frozen=True) class FromPolynomialDataExprImpl(FromPolynomialDataExprMixin): - data: PolynomialMatrixTupledData - shape: tuple[int, int] + data: PolynomialMatrixTupledData + shape: tuple[int, int] @dataclassabc.dataclassabc(frozen=True) class GetItemExprImpl(GetItemExprMixin): - underlying: ExpressionBaseMixin - index: tuple[tuple[int, ...], tuple[int, ...]] + underlying: ExpressionBaseMixin + index: tuple[tuple[int, ...], tuple[int, ...]] @dataclassabc.dataclassabc(frozen=True) class HalfNewtonPolytopeExprImpl(HalfNewtonPolytopeExprMixin): - monomials: ExpressionBaseMixin - variables: ExpressionBaseMixin - filter: ExpressionBaseMixin | None + monomials: ExpressionBaseMixin + variables: ExpressionBaseMixin + filter: ExpressionBaseMixin | None @dataclassabc.dataclassabc(frozen=True) class IntegrateExprImpl(IntegrateExprMixin): - underlying: ExpressionBaseMixin - variables: ExpressionBaseMixin - from_: tuple[float, ...] - to: tuple[float, ...] - stack: tuple[FrameSummary] + underlying: ExpressionBaseMixin + variables: ExpressionBaseMixin + from_: tuple[float, ...] + to: tuple[float, ...] + stack: tuple[FrameSummary] - # implement custom __repr__ method that returns a representation without the stack - def __repr__(self): - return f'{self.__class__.__name__}(underlying={self.underlying}, variables={self.variables}, from_={self.from_}, to={self.to})' + # implement custom __repr__ method that returns a representation without the stack + def __repr__(self): + return f"{self.__class__.__name__}(underlying={self.underlying}, variables={self.variables}, from_={self.from_}, to={self.to})" @dataclassabc.dataclassabc(frozen=True) class LinearInExprImpl(LinearInExprMixin): - underlying: ExpressionBaseMixin - monomials: ExpressionBaseMixin - variables: ExpressionBaseMixin - ignore_unmatched: bool + underlying: ExpressionBaseMixin + monomials: ExpressionBaseMixin + variables: ExpressionBaseMixin + ignore_unmatched: bool @dataclassabc.dataclassabc(frozen=True) class LinearMatrixInExprImpl(LinearMatrixInExprMixin): - underlying: ExpressionBaseMixin - variable: int + underlying: ExpressionBaseMixin + variable: int @dataclassabc.dataclassabc(frozen=True) class LinearMonomialsExprImpl(LinearMonomialsExprMixin): - underlying: ExpressionBaseMixin - variables: tuple + underlying: ExpressionBaseMixin + variables: tuple @dataclassabc.dataclassabc(frozen=True) class LegendreSeriesImpl(LegendreSeriesMixin): - underlying: ExpressionBaseMixin - degrees: tuple[int, ...] | None - stack: tuple[FrameSummary] + underlying: ExpressionBaseMixin + degrees: tuple[int, ...] | None + stack: tuple[FrameSummary] - # implement custom __repr__ method that returns a representation without the stack - def __repr__(self): - return f'{self.__class__.__name__}(underlying={self.underlying}, degrees={self.degrees})' + # implement custom __repr__ method that returns a representation without the stack + def __repr__(self): + return f"{self.__class__.__name__}(underlying={self.underlying}, degrees={self.degrees})" @dataclassabc.dataclassabc(frozen=True) class MatrixMultExprImpl(MatrixMultExprMixin): - left: ExpressionBaseMixin - right: ExpressionBaseMixin - stack: tuple[FrameSummary] + left: ExpressionBaseMixin + right: ExpressionBaseMixin + stack: tuple[FrameSummary] - # implement custom __repr__ method that returns a representation without the stack - def __repr__(self): - return f'{self.__class__.__name__}(left={self.left}, right={self.right})' + # implement custom __repr__ method that returns a representation without the stack + def __repr__(self): + return f"{self.__class__.__name__}(left={self.left}, right={self.right})" @dataclassabc.dataclassabc(frozen=True) class DegreeExprImpl(DegreeExprMixin): - underlying: ExpressionBaseMixin - stack: tuple[FrameSummary] + underlying: ExpressionBaseMixin + stack: tuple[FrameSummary] - # implement custom __repr__ method that returns a representation without the stack - def __repr__(self): - return f'{self.__class__.__name__}(underlying={self.underlying})' + # implement custom __repr__ method that returns a representation without the stack + def __repr__(self): + return f"{self.__class__.__name__}(underlying={self.underlying})" @dataclassabc.dataclassabc(frozen=True) class MaxExprImpl(MaxExprMixin): - underlying: ExpressionBaseMixin + underlying: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True, repr=False) class ParametrizeExprImpl(ParametrizeExprMixin): - underlying: ExpressionBaseMixin - name: str + underlying: ExpressionBaseMixin + name: str - def __repr__(self) -> str: - return f'{self.__class__.__name__}(name={self.name}, underlying={self.underlying})' + def __repr__(self) -> str: + return ( + f"{self.__class__.__name__}(name={self.name}, underlying={self.underlying})" + ) @dataclassabc.dataclassabc(frozen=True) class ParametrizeMatrixExprImpl(ParametrizeMatrixExprMixin): - underlying: ExpressionBaseMixin - name: str + underlying: ExpressionBaseMixin + name: str @dataclassabc.dataclassabc(frozen=True) class ProductExprImpl(ProductExprMixin): - underlying: tuple[ExpressionBaseMixin] - degrees: tuple[int, ...] | None - stack: tuple[FrameSummary] + underlying: tuple[ExpressionBaseMixin] + degrees: tuple[int, ...] | None + stack: tuple[FrameSummary] - # implement custom __repr__ method that returns a representation without the stack - def __repr__(self): - return f'{self.__class__.__name__}(underlying={self.underlying}, degrees={self.degrees})' + # implement custom __repr__ method that returns a representation without the stack + def __repr__(self): + return f"{self.__class__.__name__}(underlying={self.underlying}, degrees={self.degrees})" @dataclassabc.dataclassabc(frozen=True) class QuadraticInExprImpl(QuadraticInExprMixin): - underlying: ExpressionBaseMixin - monomials: ExpressionBaseMixin - variables: tuple - stack: tuple[FrameSummary] + underlying: ExpressionBaseMixin + monomials: ExpressionBaseMixin + variables: tuple + stack: tuple[FrameSummary] - # implement custom __repr__ method that returns a representation without the stack - def __repr__(self): - return f'{self.__class__.__name__}(variables={self.variables}, monomials={self.monomials}, underlying={self.underlying})' + # implement custom __repr__ method that returns a representation without the stack + def __repr__(self): + return f"{self.__class__.__name__}(variables={self.variables}, monomials={self.monomials}, underlying={self.underlying})" @dataclassabc.dataclassabc(frozen=True) class QuadraticMonomialsExprImpl(QuadraticMonomialsExprMixin): - underlying: ExpressionBaseMixin - variables: tuple + underlying: ExpressionBaseMixin + variables: tuple @dataclassabc.dataclassabc(frozen=True) class RepMatExprImpl(RepMatExprMixin): - underlying: ExpressionBaseMixin - repetition: tuple + underlying: ExpressionBaseMixin + repetition: tuple @dataclassabc.dataclassabc(frozen=True) class ReshapeExprImpl(ReshapeExprMixin): - underlying: ExpressionBaseMixin - new_shape: tuple + underlying: ExpressionBaseMixin + new_shape: tuple @dataclassabc.dataclassabc(frozen=True) class SetElementAtExprImpl(SetElementAtExprMixin): - underlying: ExpressionBaseMixin - index: tuple - value: ExpressionBaseMixin + underlying: ExpressionBaseMixin + index: tuple + value: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class SqueezeExprImpl(SqueezeExprMixin): - underlying: ExpressionBaseMixin + underlying: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class SubstituteExprImpl(SubstituteExprMixin): - underlying: ExpressionBaseMixin - substitutions: tuple + underlying: ExpressionBaseMixin + substitutions: tuple @dataclassabc.dataclassabc(frozen=True) class SubtractMonomialsExprImpl(SubtractMonomialsExprMixin): - underlying: ExpressionBaseMixin - monomials: ExpressionBaseMixin + underlying: ExpressionBaseMixin + monomials: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class SumExprImpl(SumExprMixin): - underlying: ExpressionBaseMixin + underlying: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class SymmetricExprImpl(SymmetricExprMixin): - underlying: ExpressionBaseMixin + underlying: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class ToConstantExprImpl(ToConstantExprMixin): - underlying: ExpressionBaseMixin + underlying: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class ToQuadraticExprImpl(ToQuadraticExprMixin): - underlying: ExpressionBaseMixin + underlying: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class ToSortedVariablesImpl(ToSortedVariablesExprMixin): - underlying: ExpressionBaseMixin + underlying: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class ToSymmetricMatrixExprImpl(ToSymmetricMatrixExprMixin): - underlying: ExpressionBaseMixin + underlying: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class TransposeExprImpl(TransposeExprMixin): - underlying: ExpressionBaseMixin + underlying: ExpressionBaseMixin @dataclassabc.dataclassabc(frozen=True) class TruncateExprImpl(TruncateExprMixin): - underlying: ExpressionBaseMixin - variables: ExpressionBaseMixin - degrees: tuple[int] - inverse: bool + underlying: ExpressionBaseMixin + variables: ExpressionBaseMixin + degrees: tuple[int] + inverse: bool @dataclassabc.dataclassabc(frozen=True) class VStackExprImpl(VStackExprMixin): - underlying: tuple + underlying: tuple diff --git a/polymatrix/expression/init.py b/polymatrix/expression/init.py index 7465f26..681c0d7 100644 --- a/polymatrix/expression/init.py +++ b/polymatrix/expression/init.py @@ -15,19 +15,19 @@ from polymatrix.expression.impl import FromTupleExprImpl, AdditionExprImpl def init_addition_expr( - left: ExpressionBaseMixin, - right: ExpressionBaseMixin, - stack: tuple[FrameSummary], + left: ExpressionBaseMixin, + right: ExpressionBaseMixin, + stack: tuple[FrameSummary], ): return AdditionExprImpl( left=left, right=right, stack=stack, -) + ) def init_block_diag_expr( - underlying: tuple, + underlying: tuple, ): return polymatrix.expression.impl.BlockDiagExprImpl( underlying=underlying, @@ -35,16 +35,16 @@ def init_block_diag_expr( def init_cache_expr( - underlying: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, ): return polymatrix.expression.impl.CacheExprImpl( underlying=underlying, -) + ) def init_combinations_expr( - expression: ExpressionBaseMixin, - degrees: tuple[int, ...] | int, + expression: ExpressionBaseMixin, + degrees: tuple[int, ...] | int, ): if isinstance(degrees, int): degrees = (degrees,) @@ -52,66 +52,65 @@ def init_combinations_expr( return polymatrix.expression.impl.CombinationsExprImpl( expression=expression, degrees=degrees, -) + ) def init_determinant_expr( - underlying: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, ): return polymatrix.expression.impl.DeterminantExprImpl( underlying=underlying, -) + ) def init_diag_expr( - underlying: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, ): return polymatrix.expression.impl.DiagExprImpl( underlying=underlying, -) + ) def init_divergence_expr( - underlying: ExpressionBaseMixin, - variables: tuple, + underlying: ExpressionBaseMixin, + variables: tuple, ): return polymatrix.expression.impl.DivergenceExprImpl( underlying=underlying, variables=variables, -) + ) def init_division_expr( - left: ExpressionBaseMixin, - right: ExpressionBaseMixin, - stack: tuple[FrameSummary], + left: ExpressionBaseMixin, + right: ExpressionBaseMixin, + stack: tuple[FrameSummary], ): return polymatrix.expression.impl.DivisionExprImpl( left=left, right=right, stack=stack, -) + ) def init_elem_mult_expr( - left: ExpressionBaseMixin, - right: ExpressionBaseMixin, - stack: tuple[FrameSummary], + left: ExpressionBaseMixin, + right: ExpressionBaseMixin, + stack: tuple[FrameSummary], ): return polymatrix.expression.impl.ElemMultExprImpl( left=left, right=right, -) + ) def init_eval_expr( - underlying: ExpressionBaseMixin, - variables: typing.Union[typing.Any, tuple, dict], - values: typing.Union[float, tuple] = None, + underlying: ExpressionBaseMixin, + variables: typing.Union[typing.Any, tuple, dict], + values: typing.Union[float, tuple] = None, ): - substitutions = format_substitutions( - variables=variables, + variables=variables, values=values, ) @@ -128,7 +127,9 @@ def init_eval_expr( else: return (float(value),) - substitutions = tuple((variable, formatted_values(value)) for variable, value in substitutions) + substitutions = tuple( + (variable, formatted_values(value)) for variable, value in substitutions + ) return polymatrix.expression.impl.EvalExprImpl( underlying=underlying, @@ -137,24 +138,24 @@ def init_eval_expr( def init_eye_expr( - variable: ExpressionBaseMixin, + variable: ExpressionBaseMixin, ): return polymatrix.expression.impl.EyeExprImpl( variable=variable, -) - + ) def init_from_symmetric_matrix_expr( - underlying: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, ): return polymatrix.expression.impl.FromSymmetricMatrixExprImpl( underlying=underlying, -) + ) DATA_TYPE = str | np.ndarray | sympy.Matrix | sympy.Expr | tuple | ExpressionBaseMixin + def init_from_expr_or_none( data: DATA_TYPE, ) -> ExpressionBaseMixin | None: @@ -163,7 +164,7 @@ def init_from_expr_or_none( underlying=init_from_expr_or_none(1), name=data, ) - + elif isinstance(data, StateMonad): return data.flat_map(lambda inner_data: init_from_expr_or_none(inner_data)) @@ -180,13 +181,12 @@ def init_from_expr_or_none( data = tuple(gen_elements()) elif isinstance(data, sympy.Matrix): - data = tuple(tuple(i for i in data.row(row)) for row in range(data.rows)) + data = tuple(tuple(i for i in data.row(row)) for row in range(data.rows)) elif isinstance(data, sympy.Expr): - data = ((sympy.expand(data),),) + data = ((sympy.expand(data),),) elif isinstance(data, tuple): - if isinstance(data[0], tuple): n_col = len(data[0]) assert all(len(col) == n_col for col in data) @@ -197,25 +197,23 @@ def init_from_expr_or_none( elif isinstance(data, ExpressionBaseMixin): return data - else: - if not isinstance(data, (float, int, np.number)): - return None - + elif isinstance(data, (float, int, np.number)): data = ((data,),) + else: + return None + return FromTupleExprImpl( - data=data, - stack=get_stack_lines(), + data=data, + stack=get_stack_lines(), ) -def init_from_expr( - data: DATA_TYPE -): +def init_from_expr(data: DATA_TYPE): expr = init_from_expr_or_none(data) if expr is None: - raise Exception(f'{data=}') + raise Exception(f"{data=}") return expr @@ -224,7 +222,6 @@ def init_from_terms_expr( data: PolyMatrixMixin | PolynomialMatrixData, shape: tuple[int, int] = None, ): - if isinstance(data, PolyMatrixMixin): shape = data.shape poly_matrix_data = data.gen_data() @@ -239,10 +236,12 @@ def init_from_terms_expr( poly_matrix_data = data.items() else: - raise Exception(f'{data=}') + raise Exception(f"{data=}") # Expression needs to be hashable - data_as_tuple = tuple((coord, tuple(polynomial.items())) for coord, polynomial in poly_matrix_data) + data_as_tuple = tuple( + (coord, tuple(polynomial.items())) for coord, polynomial in poly_matrix_data + ) return polymatrix.expression.impl.FromPolynomialDataExprImpl( terms=data_as_tuple, @@ -251,13 +250,14 @@ def init_from_terms_expr( def init_get_item_expr( - underlying: ExpressionBaseMixin, - index: tuple[tuple[int, ...], tuple[int, ...]], + underlying: ExpressionBaseMixin, + index: tuple[tuple[int, ...], tuple[int, ...]], ): - def get_hashable_slice(index): if isinstance(index, slice): - return polymatrix.expression.impl.GetItemExprImpl.Slice(start=index.start, stop=index.stop, step=index.step) + return polymatrix.expression.impl.GetItemExprImpl.Slice( + start=index.start, stop=index.stop, step=index.step + ) else: return index @@ -266,68 +266,65 @@ def init_get_item_expr( return polymatrix.expression.impl.GetItemExprImpl( underlying=underlying, index=proper_index, -) + ) def init_half_newton_polytope_expr( - monomials: ExpressionBaseMixin, - variables: ExpressionBaseMixin, - filter: ExpressionBaseMixin | None = None, + monomials: ExpressionBaseMixin, + variables: ExpressionBaseMixin, + filter: ExpressionBaseMixin | None = None, ): return polymatrix.expression.impl.HalfNewtonPolytopeExprImpl( - monomials=monomials, - variables=variables, - filter=filter -) + monomials=monomials, variables=variables, filter=filter + ) def init_linear_matrix_in_expr( - underlying: ExpressionBaseMixin, - variable: int, + underlying: ExpressionBaseMixin, + variable: int, ): return polymatrix.expression.impl.LinearMatrixInExprImpl( underlying=underlying, variable=variable, -) + ) def init_matrix_mult_expr( - left: ExpressionBaseMixin, - right: ExpressionBaseMixin, - stack: tuple[FrameSummary], + left: ExpressionBaseMixin, + right: ExpressionBaseMixin, + stack: tuple[FrameSummary], ): return polymatrix.expression.impl.MatrixMultExprImpl( left=left, right=right, stack=stack, -) - + ) def init_max_expr( - underlying: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, ): return polymatrix.expression.impl.MaxExprImpl( underlying=underlying, -) + ) def init_parametrize_expr( - underlying: ExpressionBaseMixin, - name: str = None, + underlying: ExpressionBaseMixin, + name: str = None, ): if name is None: - name = 'undefined' + name = "undefined" return polymatrix.expression.impl.ParametrizeExprImpl( underlying=underlying, name=name, -) + ) def init_parametrize_matrix_expr( - underlying: ExpressionBaseMixin, - name: str, + underlying: ExpressionBaseMixin, + name: str, ): return polymatrix.expression.impl.ParametrizeMatrixExprImpl( underlying=underlying, @@ -336,13 +333,12 @@ def init_parametrize_matrix_expr( def init_quadratic_in_expr( - underlying: ExpressionBaseMixin, - monomials: ExpressionBaseMixin, - variables: ExpressionBaseMixin, - stack: tuple[FrameSummary], + underlying: ExpressionBaseMixin, + monomials: ExpressionBaseMixin, + variables: ExpressionBaseMixin, + stack: tuple[FrameSummary], ): - - assert isinstance(variables, ExpressionBaseMixin), f'{variables=}' + assert isinstance(variables, ExpressionBaseMixin), f"{variables=}" return polymatrix.expression.impl.QuadraticInExprImpl( underlying=underlying, @@ -353,11 +349,10 @@ def init_quadratic_in_expr( def init_quadratic_monomials_expr( - underlying: ExpressionBaseMixin, - variables: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, + variables: ExpressionBaseMixin, ): - - assert isinstance(variables, ExpressionBaseMixin), f'{variables=}' + assert isinstance(variables, ExpressionBaseMixin), f"{variables=}" return polymatrix.expression.impl.QuadraticMonomialsExprImpl( underlying=underlying, @@ -366,60 +361,59 @@ def init_quadratic_monomials_expr( def init_rep_mat_expr( - underlying: ExpressionBaseMixin, - repetition: tuple, + underlying: ExpressionBaseMixin, + repetition: tuple, ): return polymatrix.expression.impl.RepMatExprImpl( underlying=underlying, repetition=repetition, -) + ) def init_reshape_expr( - underlying: ExpressionBaseMixin, - new_shape: tuple, + underlying: ExpressionBaseMixin, + new_shape: tuple, ): return polymatrix.expression.impl.ReshapeExprImpl( underlying=underlying, new_shape=new_shape, -) + ) def init_set_element_at_expr( - underlying: ExpressionBaseMixin, - index: tuple, - value: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, + index: tuple, + value: ExpressionBaseMixin, ): return polymatrix.expression.impl.SetElementAtExprImpl( underlying=underlying, index=index, value=value, -) + ) def init_squeeze_expr( - underlying: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, ): return polymatrix.expression.impl.SqueezeExprImpl( underlying=underlying, -) + ) def init_substitute_expr( - underlying: ExpressionBaseMixin, - variables: tuple, - values: tuple = None, + underlying: ExpressionBaseMixin, + variables: tuple, + values: tuple = None, ): - substitutions = format_substitutions( - variables=variables, + variables=variables, values=values, ) def formatted_values(value) -> ExpressionBaseMixin: if isinstance(value, ExpressionBaseMixin): expr = value - + else: expr = init_from_expr(value) @@ -428,7 +422,9 @@ def init_substitute_expr( new_shape=(-1, 1), ) - substitutions = tuple((variable, formatted_values(value)) for variable, value in substitutions) + substitutions = tuple( + (variable, formatted_values(value)) for variable, value in substitutions + ) return polymatrix.expression.impl.SubstituteExprImpl( underlying=underlying, @@ -437,76 +433,76 @@ def init_substitute_expr( def init_subtract_monomials_expr( - underlying: ExpressionBaseMixin, - monomials: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, + monomials: ExpressionBaseMixin, ): return polymatrix.expression.impl.SubtractMonomialsExprImpl( underlying=underlying, monomials=monomials, -) + ) def init_sum_expr( - underlying: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, ): return polymatrix.expression.impl.SumExprImpl( underlying=underlying, -) + ) def init_symmetric_expr( - underlying: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, ): return polymatrix.expression.impl.SymmetricExprImpl( underlying=underlying, -) + ) def init_to_constant_expr( - underlying: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, ): return polymatrix.expression.impl.ToConstantExprImpl( underlying=underlying, -) + ) def init_to_quadratic_expr( - underlying: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, ): return polymatrix.expression.impl.ToQuadraticExprImpl( underlying=underlying, -) + ) def init_to_sorted_variables( - underlying: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, ): return polymatrix.expression.impl.ToSortedVariablesImpl( underlying=underlying, -) + ) def init_to_symmetric_matrix_expr( - underlying: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, ): return polymatrix.expression.impl.ToSymmetricMatrixExprImpl( underlying=underlying, -) + ) def init_transpose_expr( - underlying: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, ): return polymatrix.expression.impl.TransposeExprImpl( underlying=underlying, -) + ) def init_truncate_expr( - underlying: ExpressionBaseMixin, - degrees: tuple[int], - variables: ExpressionBaseMixin | None = None, - inverse: bool | None = None, + underlying: ExpressionBaseMixin, + degrees: tuple[int], + variables: ExpressionBaseMixin | None = None, + inverse: bool | None = None, ): if isinstance(degrees, int): degrees = (degrees,) diff --git a/polymatrix/expression/mixins/additionexprmixin.py b/polymatrix/expression/mixins/additionexprmixin.py index 0ba8a2e..bc83ff3 100644 --- a/polymatrix/expression/mixins/additionexprmixin.py +++ b/polymatrix/expression/mixins/additionexprmixin.py @@ -1,18 +1,18 @@ import abc import math -from polymatrix.expression.utils.broadcastpolymatrix import broadcast_poly_matrix from polymatrix.utils.getstacklines import FrameSummary from polymatrix.polymatrix.init import init_poly_matrix from polymatrix.polymatrix.abc import PolyMatrix from polymatrix.expressionstate.abc import ExpressionState from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin +from polymatrix.expression.utils.broadcastpolymatrix import broadcast_poly_matrix class AdditionExprMixin(ExpressionBaseMixin): - """ - Adds two polymatrices - + """ + Adds two polymatrices + [[2*x1+x2], [x1**2]] + [[3*x2], [x1]] -> [[2*x1+4*x2], [x1+x1**2]]. If one summand is of size (1, 1), then perform broadcast: @@ -22,22 +22,19 @@ class AdditionExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def left(self) -> ExpressionBaseMixin: - ... + def left(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def right(self) -> ExpressionBaseMixin: - ... + def right(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def stack(self) -> tuple[FrameSummary]: - ... + def stack(self) -> tuple[FrameSummary]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: state, left = self.left.apply(state=state) @@ -49,11 +46,9 @@ class AdditionExprMixin(ExpressionBaseMixin): for row in range(left.shape[0]): for col in range(left.shape[1]): - poly_data = {} for underlying in (left, right): - polynomial = underlying.get_poly(row, col) if polynomial is None: continue @@ -63,7 +58,6 @@ class AdditionExprMixin(ExpressionBaseMixin): else: for monomial, value in polynomial.items(): - if monomial not in poly_data: poly_data[monomial] = value @@ -81,4 +75,4 @@ class AdditionExprMixin(ExpressionBaseMixin): shape=left.shape, ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/blockdiagexprmixin.py b/polymatrix/expression/mixins/blockdiagexprmixin.py index be8e78a..4688139 100644 --- a/polymatrix/expression/mixins/blockdiagexprmixin.py +++ b/polymatrix/expression/mixins/blockdiagexprmixin.py @@ -1,32 +1,29 @@ - import abc import itertools import dataclassabc -from polymatrix.polymatrix.mixins import PolyMatrixMixin -from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin +from polymatrix.polymatrix.mixins import PolyMatrixMixin from polymatrix.polymatrix.abc import PolyMatrix from polymatrix.expressionstate.abc import ExpressionState +from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin class BlockDiagExprMixin(ExpressionBaseMixin): - """ + """ Create a block diagonal polymatrix from provided polymatrices - + [[x1]], [[x2], [x3]] -> [[x1, 0], [0, x2], [0, x3]]. """ @property @abc.abstractmethod - def underlying(self) -> tuple[ExpressionBaseMixin, ...]: - ... + def underlying(self) -> tuple[ExpressionBaseMixin, ...]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - all_underlying = [] for expr in self.underlying: state, polymat = expr.apply(state=state) @@ -39,26 +36,30 @@ class BlockDiagExprMixin(ExpressionBaseMixin): shape: tuple[int, int] def get_poly(self, row: int, col: int) -> dict[tuple[int, ...], float]: - - for polymatrix, ((row_start, col_start), (row_end, col_end)) in zip(self.all_underlying, self.underlying_row_col_range): + for polymatrix, ((row_start, col_start), (row_end, col_end)) in zip( + self.all_underlying, self.underlying_row_col_range + ): if row_start <= row < row_end: if col_start <= col < col_end: return polymatrix.get_poly( - row=row-row_start, - col=col-col_start, + row=row - row_start, + col=col - col_start, ) else: return None - raise Exception(f'row {row} is out of bounds') + raise Exception(f"row {row} is out of bounds") - underlying_row_col_range = tuple(itertools.pairwise( - itertools.accumulate( - (expr.shape for expr in all_underlying), - lambda acc, v: tuple(v1+v2 for v1, v2 in zip(acc, v)), - initial=(0, 0)) - )) + underlying_row_col_range = tuple( + itertools.pairwise( + itertools.accumulate( + (expr.shape for expr in all_underlying), + lambda acc, v: tuple(v1 + v2 for v1, v2 in zip(acc, v)), + initial=(0, 0), + ) + ) + ) shape = underlying_row_col_range[-1][1] diff --git a/polymatrix/expression/mixins/cacheexprmixin.py b/polymatrix/expression/mixins/cacheexprmixin.py index 22e5a6a..94cd7dc 100644 --- a/polymatrix/expression/mixins/cacheexprmixin.py +++ b/polymatrix/expression/mixins/cacheexprmixin.py @@ -1,28 +1,25 @@ - import abc import dataclasses -from polymatrix.polymatrix.mixins import PolyMatrixAsDictMixin +from polymatrix.polymatrix.mixins import PolyMatrixAsDictMixin +from polymatrix.polymatrix.mixins import PolyMatrixMixin from polymatrix.polymatrix.init import init_poly_matrix -from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.expressionstate.mixins import ExpressionStateMixin -from polymatrix.polymatrix.mixins import PolyMatrixMixin +from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin class CacheExprMixin(ExpressionBaseMixin): - """ Caches the polynomial matrix using the state """ - + """Caches the polynomial matrix using the state""" + @property @abc.abstractclassmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionStateMixin, ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]: - if self in state.cache: return state, state.cache[self] @@ -39,7 +36,7 @@ class CacheExprMixin(ExpressionBaseMixin): ) state = dataclasses.replace( - state, + state, cache=state.cache | {self: poly_matrix}, ) diff --git a/polymatrix/expression/mixins/combinationsexprmixin.py b/polymatrix/expression/mixins/combinationsexprmixin.py index 632efd5..8a99455 100644 --- a/polymatrix/expression/mixins/combinationsexprmixin.py +++ b/polymatrix/expression/mixins/combinationsexprmixin.py @@ -1,12 +1,11 @@ - import abc import itertools -from polymatrix.polymatrix.utils.multiplypolynomial import multiply_polynomial +from polymatrix.polymatrix.utils.multiplypolynomial import multiply_polynomial from polymatrix.polymatrix.init import init_poly_matrix -from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.polymatrix.abc import PolyMatrix from polymatrix.expressionstate.abc import ExpressionState +from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin class CombinationsExprMixin(ExpressionBaseMixin): @@ -15,37 +14,35 @@ class CombinationsExprMixin(ExpressionBaseMixin): [[x]] -> [[1], [x], [x**2], [x**3]] """ - + @property @abc.abstractmethod - def expression(self) -> ExpressionBaseMixin: - ... + def expression(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def degrees(self) -> tuple[int, ...]: - ... + def degrees(self) -> tuple[int, ...]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - state, poly_matrix = self.expression.apply(state=state) assert poly_matrix.shape[1] == 1 def gen_indices(): for degree in self.degrees: - yield from itertools.combinations_with_replacement(range(poly_matrix.shape[0]), degree) + yield from itertools.combinations_with_replacement( + range(poly_matrix.shape[0]), degree + ) indices = tuple(gen_indices()) poly_matrix_data = {} for row, indexing in enumerate(indices): - # x.combinations((0, 1, 2)) produces [1, x, x**2] if len(indexing) == 0: poly_matrix_data[row, 0] = {tuple(): 1.0} @@ -56,7 +53,7 @@ class CombinationsExprMixin(ExpressionBaseMixin): if len(left) == 0: return right - + result = {} multiply_polynomial(left, right, result) return result @@ -67,11 +64,11 @@ class CombinationsExprMixin(ExpressionBaseMixin): initial={}, ) - poly_matrix_data[row, 0] = polynomial + poly_matrix_data[row, 0] = polynomial poly_matrix = init_poly_matrix( data=poly_matrix_data, shape=(len(poly_matrix_data), 1), ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/degreeexprmixin.py b/polymatrix/expression/mixins/degreeexprmixin.py index 71b936a..e847102 100644 --- a/polymatrix/expression/mixins/degreeexprmixin.py +++ b/polymatrix/expression/mixins/degreeexprmixin.py @@ -34,13 +34,14 @@ class DegreeExprMixin(ExpressionBaseMixin): polynomial = underlying.get_poly(row, col) if polynomial is None or len(polynomial) == 0: - continue - - def gen_degrees(): - for monomial, _ in polynomial.items(): - yield sum(count for _, count in monomial) - - poly_matrix_data[row, col] = {tuple(): max(gen_degrees())} + poly_matrix_data[row, col] =0 + + else: + def gen_degrees(): + for monomial, _ in polynomial.items(): + yield sum(count for _, count in monomial) + + poly_matrix_data[row, col] = {tuple(): max(gen_degrees())} poly_matrix = init_poly_matrix( data=poly_matrix_data, diff --git a/polymatrix/expression/mixins/derivativeexprmixin.py b/polymatrix/expression/mixins/derivativeexprmixin.py index 64f2640..31a1e31 100644 --- a/polymatrix/expression/mixins/derivativeexprmixin.py +++ b/polymatrix/expression/mixins/derivativeexprmixin.py @@ -1,4 +1,3 @@ - import abc import typing @@ -7,7 +6,9 @@ from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.polymatrix.abc import PolyMatrix from polymatrix.expressionstate.abc import ExpressionState from polymatrix.expression.utils.getderivativemonomials import differentiate_polynomial -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) from polymatrix.utils.getstacklines import FrameSummary from polymatrix.utils.tooperatorexception import to_operator_exception @@ -23,43 +24,39 @@ class DerivativeExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def variables(self) -> ExpressionBaseMixin: - ... + def variables(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def introduce_derivatives(self) -> bool: - ... + def introduce_derivatives(self) -> bool: ... @property @abc.abstractmethod - def stack(self) -> tuple[FrameSummary]: - ... + def stack(self) -> tuple[FrameSummary]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - - state, underlying = self.underlying.apply(state=state) + state, underlying = self.underlying.apply(state=state) state, variables = get_variable_indices_from_variable(state, self.variables) if not (underlying.shape[1] == 1): - raise AssertionError(to_operator_exception( - message=f'{underlying.shape[1]=} is not 1', - stack=self.stack, - )) + raise AssertionError( + to_operator_exception( + message=f"{underlying.shape[1]=} is not 1", + stack=self.stack, + ) + ) poly_matrix_data = {} for row in range(underlying.shape[0]): - underlying_poly = underlying.get_poly(row, 0) if underlying_poly is None: @@ -67,7 +64,6 @@ class DerivativeExprMixin(ExpressionBaseMixin): # derivate each variable and map result to the corresponding column for col, variable in enumerate(variables): - state, diff_polynomial = differentiate_polynomial( polynomial=underlying_poly, diff_wrt_variable=variable, @@ -84,4 +80,4 @@ class DerivativeExprMixin(ExpressionBaseMixin): shape=(underlying.shape[0], len(variables)), ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/determinantexprmixin.py b/polymatrix/expression/mixins/determinantexprmixin.py index d848bd2..5694ddd 100644 --- a/polymatrix/expression/mixins/determinantexprmixin.py +++ b/polymatrix/expression/mixins/determinantexprmixin.py @@ -1,4 +1,3 @@ - import abc import collections import dataclasses @@ -13,8 +12,7 @@ from polymatrix.expressionstate.abc import ExpressionState class DeterminantExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... # # overwrites the abstract method of `ExpressionBaseMixin` # @property @@ -23,7 +21,7 @@ class DeterminantExprMixin(ExpressionBaseMixin): # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: # raise Exception('not implemented') @@ -42,7 +40,6 @@ class DeterminantExprMixin(ExpressionBaseMixin): rel_index = 0 for row in range(underlying.shape[0]): - polynomial = collections.defaultdict(float) # f in f-v^T@x-r^2 @@ -54,9 +51,8 @@ class DeterminantExprMixin(ExpressionBaseMixin): else: for monomial, value in underlying_poly.items(): polynomial[monomial] += value - - for inner_row in range(row): + for inner_row in range(row): # -v^T@x in f-v^T@x-r^2 # terms = underlying.get_poly(row, inner_row) try: @@ -74,7 +70,6 @@ class DeterminantExprMixin(ExpressionBaseMixin): auxillary_polynomial = collections.defaultdict(float) for inner_col in range(row): - # P@x in P@x-v key = tuple(reversed(sorted((inner_row, inner_col)))) try: @@ -83,9 +78,11 @@ class DeterminantExprMixin(ExpressionBaseMixin): pass else: for monomial, value in underlying_poly.items(): - new_monomial = monomial + (index_start + rel_index + inner_col,) + new_monomial = monomial + ( + index_start + rel_index + inner_col, + ) auxillary_polynomial[new_monomial] += value - + # -v in P@x-v try: underlying_poly = underlying.get_poly(row, inner_row) @@ -110,9 +107,9 @@ class DeterminantExprMixin(ExpressionBaseMixin): ) state = dataclasses.replace( - state, + state, auxillary_equations=state.auxillary_equations | auxillary_equations, cache=state.cache | {self: poly_matrix}, ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/diagexprmixin.py b/polymatrix/expression/mixins/diagexprmixin.py index 046dd5c..826cb94 100644 --- a/polymatrix/expression/mixins/diagexprmixin.py +++ b/polymatrix/expression/mixins/diagexprmixin.py @@ -5,6 +5,7 @@ from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.expressionstate.mixins import ExpressionStateMixin from polymatrix.polymatrix.mixins import PolyMatrixMixin + class DiagExprMixin(ExpressionBaseMixin): """ [[1],[2]] -> [[1,0],[0,2]] @@ -13,21 +14,20 @@ class DiagExprMixin(ExpressionBaseMixin): [[1,0],[0,2]] -> [[1],[2]] """ - + @property @abc.abstractclassmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionStateMixin, ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]: - state, underlying = self.underlying.apply(state) if underlying.shape[1] == 1: + @dataclassabc.dataclassabc(frozen=True) class DiagPolyMatrix(PolyMatrixMixin): underlying: PolyMatrixMixin @@ -45,7 +45,7 @@ class DiagExprMixin(ExpressionBaseMixin): ) else: - assert underlying.shape[0] == underlying.shape[1], f'{underlying.shape=}' + assert underlying.shape[0] == underlying.shape[1], f"{underlying.shape=}" @dataclassabc.dataclassabc(frozen=True) class TracePolyMatrix(PolyMatrixMixin): @@ -58,4 +58,4 @@ class DiagExprMixin(ExpressionBaseMixin): return state, TracePolyMatrix( underlying=underlying, shape=(underlying.shape[0], 1), - )
\ No newline at end of file + ) diff --git a/polymatrix/expression/mixins/divergenceexprmixin.py b/polymatrix/expression/mixins/divergenceexprmixin.py index fbe6da0..b4deb25 100644 --- a/polymatrix/expression/mixins/divergenceexprmixin.py +++ b/polymatrix/expression/mixins/divergenceexprmixin.py @@ -1,4 +1,3 @@ - import abc import collections import typing @@ -8,36 +7,36 @@ from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.polymatrix.abc import PolyMatrix from polymatrix.expressionstate.abc import ExpressionState from polymatrix.expression.utils.getderivativemonomials import differentiate_polynomial -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) class DivergenceExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def variables(self) -> typing.Union[tuple, ExpressionBaseMixin]: - ... + def variables(self) -> typing.Union[tuple, ExpressionBaseMixin]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - state, underlying = self.underlying.apply(state=state) state, variables = get_variable_indices_from_variable(state, self.variables) - assert underlying.shape[1] == 1, f'{underlying.shape=}' - assert len(variables) == underlying.shape[0], f'{variables=}, {underlying.shape=}' + assert underlying.shape[1] == 1, f"{underlying.shape=}" + assert ( + len(variables) == underlying.shape[0] + ), f"{variables=}, {underlying.shape=}" polynomial_data = collections.defaultdict(float) for row, variable in enumerate(variables): - polynomial = underlying.get_poly(row, 0) if polynomial is None: @@ -59,4 +58,4 @@ class DivergenceExprMixin(ExpressionBaseMixin): shape=(1, 1), ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/divisionexprmixin.py b/polymatrix/expression/mixins/divisionexprmixin.py index 71bb86f..f2a7f0a 100644 --- a/polymatrix/expression/mixins/divisionexprmixin.py +++ b/polymatrix/expression/mixins/divisionexprmixin.py @@ -1,4 +1,3 @@ - import abc import dataclasses @@ -14,25 +13,21 @@ from polymatrix.expressionstate.abc import ExpressionState class DivisionExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def left(self) -> ExpressionBaseMixin: - ... + def left(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def right(self) -> ExpressionBaseMixin: - ... + def right(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def stack(self) -> tuple[FrameSummary]: - ... + def stack(self) -> tuple[FrameSummary]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - state, left = self.left.apply(state=state) state, right = self.right.apply(state=state) @@ -42,22 +37,24 @@ class DivisionExprMixin(ExpressionBaseMixin): # assert right.shape == (1, 1) if not (right.shape == (1, 1)): - raise AssertionError(to_operator_exception( - message=f'{right.shape=} is not (1, 1)', - stack=self.stack, - )) + raise AssertionError( + to_operator_exception( + message=f"{right.shape=} is not (1, 1)", + stack=self.stack, + ) + ) right_poly = right.get_poly(0, 0) if len(right_poly) == 1 and tuple() in right_poly: - right_inv = {(0, 0): {tuple(): 1/right_poly[tuple()]}} + right_inv = {(0, 0): {tuple(): 1 / right_poly[tuple()]}} return ElemMultExprMixin.elem_mult( - state=state, - left=left, + state=state, + left=left, right=init_poly_matrix( data=right_inv, shape=(1, 1), - ) + ), ) # add an auxillary equation and, therefore, needs to be cached @@ -71,7 +68,6 @@ class DivisionExprMixin(ExpressionBaseMixin): for row in range(left.shape[0]): for col in range(left.shape[1]): - underlying_poly = left.get_poly(row, col) if underlying_poly is None: continue @@ -99,9 +95,10 @@ class DivisionExprMixin(ExpressionBaseMixin): ) state = dataclasses.replace( - state, - auxillary_equations=state.auxillary_equations | {division_variable: auxillary_poly}, + state, + auxillary_equations=state.auxillary_equations + | {division_variable: auxillary_poly}, cache=state.cache | {self: poly_matrix}, ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/elemmultexprmixin.py b/polymatrix/expression/mixins/elemmultexprmixin.py index bfe6397..ce5e97c 100644 --- a/polymatrix/expression/mixins/elemmultexprmixin.py +++ b/polymatrix/expression/mixins/elemmultexprmixin.py @@ -1,4 +1,3 @@ - import abc import itertools import typing @@ -15,13 +14,11 @@ from polymatrix.polymatrix.utils.mergemonomialindices import merge_monomial_indi class ElemMultExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def left(self) -> ExpressionBaseMixin: - ... + def left(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def right(self) -> ExpressionBaseMixin: - ... + def right(self) -> ExpressionBaseMixin: ... @staticmethod def elem_mult( @@ -40,7 +37,9 @@ class ElemMultExprMixin(ExpressionBaseMixin): underlying: tuple[tuple[int], float] shape: tuple[int, int] - def get_poly(self, row: int, col: int) -> typing.Optional[dict[tuple[int, ...], float]]: + def get_poly( + self, row: int, col: int + ) -> typing.Optional[dict[tuple[int, ...], float]]: return self.underlying right = BroadCastedPolyMatrix( @@ -52,7 +51,6 @@ class ElemMultExprMixin(ExpressionBaseMixin): for poly_row in range(left.shape[0]): for poly_col in range(left.shape[1]): - polynomial = {} left_polynomial = left.get_poly(poly_row, poly_col) @@ -63,9 +61,12 @@ class ElemMultExprMixin(ExpressionBaseMixin): if right_polynomial is None: continue - for (left_monomial, left_value), (right_monomial, right_value) \ - in itertools.product(left_polynomial.items(), right_polynomial.items()): - + for (left_monomial, left_value), ( + right_monomial, + right_value, + ) in itertools.product( + left_polynomial.items(), right_polynomial.items() + ): value = left_value * right_value # if value == 0: @@ -73,7 +74,9 @@ class ElemMultExprMixin(ExpressionBaseMixin): # monomial = tuple(sorted(left_monomial + right_monomial)) - new_monomial = merge_monomial_indices((left_monomial, right_monomial)) + new_monomial = merge_monomial_indices( + (left_monomial, right_monomial) + ) if new_monomial not in polynomial: polynomial[new_monomial] = 0 @@ -88,12 +91,11 @@ class ElemMultExprMixin(ExpressionBaseMixin): shape=left.shape, ) - return state, poly_matrix - + return state, poly_matrix # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: state, left = self.left.apply(state=state) diff --git a/polymatrix/expression/mixins/evalexprmixin.py b/polymatrix/expression/mixins/evalexprmixin.py index b86cafa..881ee83 100644 --- a/polymatrix/expression/mixins/evalexprmixin.py +++ b/polymatrix/expression/mixins/evalexprmixin.py @@ -1,4 +1,3 @@ - import abc import itertools import math @@ -7,26 +6,25 @@ from polymatrix.polymatrix.init import init_poly_matrix from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.polymatrix.abc import PolyMatrix from polymatrix.expressionstate.abc import ExpressionState -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) class EvalExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def substitutions(self) -> tuple: - ... + def substitutions(self) -> tuple: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - state, underlying = self.underlying.apply(state=state) def acc_variable_indices_and_values(acc, next): @@ -42,21 +40,22 @@ class EvalExprMixin(ExpressionBaseMixin): values = tuple(values[0] for _ in indices) else: - assert len(indices) == len(values), f'{variable=}, {indices=} ({len(indices)}), {values=} ({len(values)})' - + assert ( + len(indices) == len(values) + ), f"{variable=}, {indices=} ({len(indices)}), {values=} ({len(values)})" + return state, acc_indices + indices, acc_values + values *_, (state, variable_indices, values) = itertools.accumulate( self.substitutions, acc_variable_indices_and_values, - initial=(state, tuple(), tuple()) + initial=(state, tuple(), tuple()), ) - + poly_matrix_data = {} for row in range(underlying.shape[0]): for col in range(underlying.shape[1]): - underlying_polynomial = underlying.get_poly(row, col) if underlying_polynomial is None: continue @@ -64,24 +63,26 @@ class EvalExprMixin(ExpressionBaseMixin): polynomial = {} for monomial, value in underlying_polynomial.items(): - + def acc_monomial(acc, next): new_monomial, value = acc variable, count = next if variable in variable_indices: index = variable_indices.index(variable) - new_value = value * values[index]**count + new_value = value * values[index] ** count return new_monomial, new_value else: return new_monomial + (next,), value - *_, (new_monomial, new_value) = tuple(itertools.accumulate( - monomial, - acc_monomial, - initial=(tuple(), value), - )) + *_, (new_monomial, new_value) = tuple( + itertools.accumulate( + monomial, + acc_monomial, + initial=(tuple(), value), + ) + ) if new_monomial not in polynomial: polynomial[new_monomial] = 0 @@ -100,7 +101,7 @@ class EvalExprMixin(ExpressionBaseMixin): shape=underlying.shape, ) - return state, poly_matrix + return state, poly_matrix # if len(self.values) == 1: # values = tuple(self.values[0] for _ in self.variables) diff --git a/polymatrix/expression/mixins/expressionbasemixin.py b/polymatrix/expression/mixins/expressionbasemixin.py index 1412f6a..06162ce 100644 --- a/polymatrix/expression/mixins/expressionbasemixin.py +++ b/polymatrix/expression/mixins/expressionbasemixin.py @@ -4,10 +4,6 @@ from polymatrix.expressionstate.abc import ExpressionState from polymatrix.polymatrix.abc import PolyMatrix -class ExpressionBaseMixin( - abc.ABC -): - +class ExpressionBaseMixin(abc.ABC): @abc.abstractmethod - def apply(self, state: ExpressionState) -> tuple[ExpressionState, PolyMatrix]: - ... + def apply(self, state: ExpressionState) -> tuple[ExpressionState, PolyMatrix]: ... diff --git a/polymatrix/expression/mixins/eyeexprmixin.py b/polymatrix/expression/mixins/eyeexprmixin.py index e7cd928..47f5a0e 100644 --- a/polymatrix/expression/mixins/eyeexprmixin.py +++ b/polymatrix/expression/mixins/eyeexprmixin.py @@ -1,4 +1,3 @@ - import abc import itertools import dataclassabc @@ -12,15 +11,13 @@ from polymatrix.expressionstate.abc import ExpressionState class EyeExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def variable(self) -> ExpressionBaseMixin: - ... + def variable(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - state, variable = self.variable.apply(state) @dataclassabc.dataclassabc(frozen=True) @@ -36,7 +33,7 @@ class EyeExprMixin(ExpressionBaseMixin): return None else: - raise Exception(f'{(row, col)=} is out of bounds') + raise Exception(f"{(row, col)=} is out of bounds") n_row = variable.shape[0] diff --git a/polymatrix/expression/mixins/filterexprmixin.py b/polymatrix/expression/mixins/filterexprmixin.py index 657191b..c8fa427 100644 --- a/polymatrix/expression/mixins/filterexprmixin.py +++ b/polymatrix/expression/mixins/filterexprmixin.py @@ -1,4 +1,3 @@ - import abc from polymatrix.polymatrix.init import init_poly_matrix @@ -8,28 +7,25 @@ from polymatrix.expressionstate.abc import ExpressionState class FilterExprMixin(ExpressionBaseMixin): - """ - [[x1, x2, x3]], [[1, 0, 1]] -> [[x1, x3]]. + """ + [[x1, x2, x3]], [[1, 0, 1]] -> [[x1, x3]]. """ @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def predicator(self) -> ExpressionBaseMixin: - ... + def predicator(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def inverse(self) -> bool: - ... + def inverse(self) -> bool: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: state, underlying = self.underlying.apply(state=state) @@ -44,7 +40,6 @@ class FilterExprMixin(ExpressionBaseMixin): row_index = 0 for row in range(underlying.shape[0]): - underlying_polynomial = underlying.get_poly(row, 0) if underlying_polynomial is None: @@ -76,4 +71,4 @@ class FilterExprMixin(ExpressionBaseMixin): shape=(row_index, 1), ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/filterlinearpartexprmixin.py b/polymatrix/expression/mixins/filterlinearpartexprmixin.py index 562ac61..046f191 100644 --- a/polymatrix/expression/mixins/filterlinearpartexprmixin.py +++ b/polymatrix/expression/mixins/filterlinearpartexprmixin.py @@ -1,4 +1,3 @@ - import abc import collections @@ -12,17 +11,15 @@ from polymatrix.expressionstate.abc import ExpressionState class FilterLinearPartExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def variable(self) -> int: - ... + def variable(self) -> int: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: state, underlying = self.underlying.apply(state=state) @@ -30,7 +27,7 @@ class FilterLinearPartExprMixin(ExpressionBaseMixin): def gen_variable_monomials(): for _, term in variables.gen_data(): - assert len(term) == 1, f'{term} should have only a single monomial' + assert len(term) == 1, f"{term} should have only a single monomial" for monomial in term.keys(): yield set(monomial) @@ -41,7 +38,6 @@ class FilterLinearPartExprMixin(ExpressionBaseMixin): for row in range(underlying.shape[0]): for col in range(underlying.shape[1]): - underlying_polynomial = underlying.get_poly(row, col) if underlying_polynomial is None: continue @@ -49,9 +45,7 @@ class FilterLinearPartExprMixin(ExpressionBaseMixin): polynomial = collections.defaultdict(float) for monomial, value in underlying_polynomial.items(): - for variable_monomial in variable_monomials: - remainder = list(monomial) try: @@ -62,16 +56,18 @@ class FilterLinearPartExprMixin(ExpressionBaseMixin): continue # take the first that matches - if all(variable not in remainder for variable in variable_monomial): + if all( + variable not in remainder for variable in variable_monomial + ): polynomial[remainder] += value break poly_matrix_data[row, col] = dict(polynomial) - + poly_matrix = init_poly_matrix( data=poly_matrix_data, shape=underlying.shape, ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/fromtermsexprmixin.py b/polymatrix/expression/mixins/fromtermsexprmixin.py index c0d4dd5..e99fc9a 100644 --- a/polymatrix/expression/mixins/fromtermsexprmixin.py +++ b/polymatrix/expression/mixins/fromtermsexprmixin.py @@ -1,4 +1,3 @@ - import abc from polymatrix.polymatrix.init import init_poly_matrix @@ -13,7 +12,6 @@ PolynomialMatrixTupledData = tuple[tuple[tuple[int, int], PolynomialTupledData], class FromPolynomialDataExprMixin(ExpressionBaseMixin): - # an Expression needs to be hashable @property @abc.abstractmethod @@ -27,10 +25,9 @@ class FromPolynomialDataExprMixin(ExpressionBaseMixin): # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionStateMixin, ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]: - data = {coord: dict(polynomial) for coord, polynomial in self.data} poly_matrix = init_poly_matrix( diff --git a/polymatrix/expression/mixins/fromtupleexprmixin.py b/polymatrix/expression/mixins/fromtupleexprmixin.py index 92b965c..e99742b 100644 --- a/polymatrix/expression/mixins/fromtupleexprmixin.py +++ b/polymatrix/expression/mixins/fromtupleexprmixin.py @@ -1,4 +1,3 @@ - import abc import math import sympy @@ -17,25 +16,21 @@ class FromTupleExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def data(self) -> tuple[tuple['FromTupleExprMixin.DATA_TYPE']]: - ... + def data(self) -> tuple[tuple["FromTupleExprMixin.DATA_TYPE"]]: ... @property @abc.abstractmethod - def stack(self) -> tuple[FrameSummary]: - ... + def stack(self) -> tuple[FrameSummary]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionStateMixin, ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]: - polynomials = {} for poly_row, col_data in enumerate(self.data): for poly_col, poly_data in enumerate(col_data): - if isinstance(poly_data, (bool, np.bool_)): poly_data = int(poly_data) @@ -55,7 +50,7 @@ class FromTupleExprMixin(ExpressionBaseMixin): continue except ValueError: - raise ValueError(f'{poly_data=}') + raise ValueError(f"{poly_data=}") for symbol in poly.gens: state = state.register(key=symbol, n_param=1) @@ -65,7 +60,6 @@ class FromTupleExprMixin(ExpressionBaseMixin): # a5 x1 x3**2 -> c=a5, m_cnt=(1, 0, 2) for value, monomial_count in zip(poly.coeffs(), poly.monoms()): - if math.isclose(value, 0): continue @@ -84,18 +78,22 @@ class FromTupleExprMixin(ExpressionBaseMixin): state, instance = poly_data.apply(state) if not (instance.shape == (1, 1)): - raise AssertionError(to_operator_exception( - message=f'{instance.shape=} is not (1, 1)', - stack=self.stack, - )) + raise AssertionError( + to_operator_exception( + message=f"{instance.shape=} is not (1, 1)", + stack=self.stack, + ) + ) polynomial = instance.get_poly(0, 0) else: - raise AssertionError(to_operator_exception( - message=f'unknown data type {type(poly_data)=}', - stack=self.stack, - )) + raise AssertionError( + to_operator_exception( + message=f"unknown data type {type(poly_data)=}", + stack=self.stack, + ) + ) polynomials[poly_row, poly_col] = polynomial diff --git a/polymatrix/expression/mixins/getitemexprmixin.py b/polymatrix/expression/mixins/getitemexprmixin.py index 76a5ee4..dbefe00 100644 --- a/polymatrix/expression/mixins/getitemexprmixin.py +++ b/polymatrix/expression/mixins/getitemexprmixin.py @@ -1,4 +1,3 @@ - import abc import dataclasses import dataclassabc @@ -19,17 +18,15 @@ class GetItemExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def index(self) -> tuple[tuple[int, ...], tuple[int, ...]]: - ... + def index(self) -> tuple[tuple[int, ...], tuple[int, ...]]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: state, underlying = self.underlying.apply(state=state) @@ -60,7 +57,7 @@ class GetItemExprMixin(ExpressionBaseMixin): return (index,) proper_index = ( - get_proper_index(self.index[0], underlying.shape[0]), + get_proper_index(self.index[0], underlying.shape[0]), get_proper_index(self.index[1], underlying.shape[1]), ) @@ -68,7 +65,7 @@ class GetItemExprMixin(ExpressionBaseMixin): class GetItemPolyMatrix(PolyMatrixMixin): underlying: PolyMatrixMixin index: tuple[int, int] - + @property def shape(self) -> tuple[int, int]: return (len(self.index[0]), len(self.index[1])) @@ -77,17 +74,20 @@ class GetItemExprMixin(ExpressionBaseMixin): try: n_row = self.index[0][row] except IndexError: - raise IndexError(f'tuple index {row} out of range given {self.index[0]}') + raise IndexError( + f"tuple index {row} out of range given {self.index[0]}" + ) try: n_col = self.index[1][col] except IndexError: - raise IndexError(f'tuple index {col} out of range given {self.index[1]}') - + raise IndexError( + f"tuple index {col} out of range given {self.index[1]}" + ) + return self.underlying.get_poly(n_row, n_col) return state, GetItemPolyMatrix( underlying=underlying, index=proper_index, ) -
\ No newline at end of file diff --git a/polymatrix/expression/mixins/halfnewtonpolytopeexprmixin.py b/polymatrix/expression/mixins/halfnewtonpolytopeexprmixin.py index 445e776..52e5814 100644 --- a/polymatrix/expression/mixins/halfnewtonpolytopeexprmixin.py +++ b/polymatrix/expression/mixins/halfnewtonpolytopeexprmixin.py @@ -1,10 +1,11 @@ - import abc import dataclasses import itertools import math from polymatrix.expression.utils.getmonomialindices import get_monomial_indices -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) from polymatrix.polymatrix.init import init_poly_matrix from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin @@ -15,27 +16,25 @@ from polymatrix.polymatrix.mixins import PolyMatrixMixin class HalfNewtonPolytopeExprMixin(ExpressionBaseMixin): @property @abc.abstractclassmethod - def monomials(self) -> ExpressionBaseMixin: - ... + def monomials(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def variables(self) -> ExpressionBaseMixin: - ... + def variables(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def filter(self) -> ExpressionBaseMixin | None: - ... + def filter(self) -> ExpressionBaseMixin | None: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionStateMixin, ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]: - state, sos_monomials = get_monomial_indices(state, self.monomials) - state, variable_indices = get_variable_indices_from_variable(state, self.variables) + state, variable_indices = get_variable_indices_from_variable( + state, self.variables + ) if self.filter is not None: state, filter_monomials = get_monomial_indices(state, self.filter) @@ -51,6 +50,7 @@ class HalfNewtonPolytopeExprMixin(ExpressionBaseMixin): def gen_min_max_degree_per_variable(): for var_index in variable_indices: + def gen_degrees_per_variable(): for monom in sos_monomials: for monom_var_index, count in monom: @@ -68,23 +68,25 @@ class HalfNewtonPolytopeExprMixin(ExpressionBaseMixin): state, filtered_monomials = acc state, degree_monomials = get_monomial_indices( - state, + state, self.variables.combinations(degree), ) if filter_monomials is not None: + def gen_filtered_monomials1(): for monom in degree_monomials: if monom not in filter_monomials: yield monom - + degree_monomials_filt = tuple(gen_filtered_monomials1()) - + else: degree_monomials_filt = degree_monomials def gen_filtered_monomials(): for monom in degree_monomials_filt: + def is_candidate(): for var_index, count in monom: min_deg, max_deg = var_index_to_min_max[var_index] diff --git a/polymatrix/expression/mixins/integrateexprmixin.py b/polymatrix/expression/mixins/integrateexprmixin.py index 4844fcd..38cf522 100644 --- a/polymatrix/expression/mixins/integrateexprmixin.py +++ b/polymatrix/expression/mixins/integrateexprmixin.py @@ -1,4 +1,3 @@ - import abc import itertools @@ -7,7 +6,9 @@ from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.polymatrix.abc import PolyMatrix from polymatrix.expressionstate.abc import ExpressionState from polymatrix.expression.utils.getderivativemonomials import differentiate_polynomial -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) from polymatrix.utils.getstacklines import FrameSummary from polymatrix.utils.tooperatorexception import to_operator_exception @@ -21,85 +22,82 @@ class IntegrateExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def variables(self) -> ExpressionBaseMixin: - ... + def variables(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def from_(self) -> tuple[float, ...]: - ... + def from_(self) -> tuple[float, ...]: ... @property @abc.abstractmethod - def to(self) -> tuple[float, ...]: - ... + def to(self) -> tuple[float, ...]: ... @property @abc.abstractmethod - def stack(self) -> tuple[FrameSummary]: - ... + def stack(self) -> tuple[FrameSummary]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - - state, underlying = self.underlying.apply(state=state) + state, underlying = self.underlying.apply(state=state) state, variables = get_variable_indices_from_variable(state, self.variables) if not (underlying.shape[1] == 1): - raise AssertionError(to_operator_exception( - message=f'{underlying.shape[1]=} is not 1', - stack=self.stack, - )) - + raise AssertionError( + to_operator_exception( + message=f"{underlying.shape[1]=} is not 1", + stack=self.stack, + ) + ) + if not (len(variables) == len(self.from_)): - raise AssertionError(to_operator_exception( - message=f'length of tuples do not match: {variables=}, {self.from_=}, {self.to}', - stack=self.stack, - )) + raise AssertionError( + to_operator_exception( + message=f"length of tuples do not match: {variables=}, {self.from_=}, {self.to}", + stack=self.stack, + ) + ) poly_matrix_data = {} for row in range(underlying.shape[0]): - underlying_poly = underlying.get_poly(row, 0) if underlying_poly is None: continue # integrate each variable and map result to the corresponding column - for col, (variable, from_, to) in enumerate(zip(variables, self.from_, self.to)): - + for col, (variable, from_, to) in enumerate( + zip(variables, self.from_, self.to) + ): integrated_polynomial = dict() for monomial, value in underlying_poly.items(): - monomial_cnt = dict(monomial) if variable in monomial_cnt: - + def acc_integrated_term(acc, v): monomial, value = acc curr_var, curr_var_cnt = v if curr_var is variable: exponent = curr_var_cnt + 1 - return monomial, value * (to**exponent - from_**exponent)/exponent - + return monomial, value * ( + to**exponent - from_**exponent + ) / exponent + else: return monomial + v, value *_, (integrated_monomial, value) = itertools.accumulate( - monomial, - acc_integrated_term, - initial=(tuple(), 1) + monomial, acc_integrated_term, initial=(tuple(), 1) ) integrated_polynomial[integrated_monomial] = value @@ -111,4 +109,4 @@ class IntegrateExprMixin(ExpressionBaseMixin): shape=(underlying.shape[0], len(variables)), ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/legendreseriesmixin.py b/polymatrix/expression/mixins/legendreseriesmixin.py index aa3de58..bec4c6c 100644 --- a/polymatrix/expression/mixins/legendreseriesmixin.py +++ b/polymatrix/expression/mixins/legendreseriesmixin.py @@ -10,49 +10,45 @@ from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin class LegendreSeriesMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> tuple[ExpressionBaseMixin]: - ... + def underlying(self) -> tuple[ExpressionBaseMixin]: ... @property @abc.abstractmethod - def degrees(self) -> tuple[int, ...] | None: - ... + def degrees(self) -> tuple[int, ...] | None: ... @property @abc.abstractmethod - def stack(self) -> tuple[FrameSummary]: - ... + def stack(self) -> tuple[FrameSummary]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - state, underlying = self.underlying.apply(state) if self.degrees is None: degrees = range(underlying.shape[0]) else: degrees = self.degrees - + poly_matrix_data = {} for degree in degrees: - # for degree in self.degree: + # for degree in self.degree: poly = underlying.get_poly(degree, 0) poly_matrix_data[degree, 0] = dict(poly) if 2 <= degree: poly = underlying.get_poly(degree - 2, 0) - factor = - (degree - 1) / (degree + 1) + factor = -(degree - 1) / (degree + 1) for m, v in poly.items(): if m in poly_matrix_data[degree, 0]: - poly_matrix_data[degree, 0][m] += v*factor + poly_matrix_data[degree, 0][m] += v * factor else: - poly_matrix_data[degree, 0][m] = v*factor + poly_matrix_data[degree, 0][m] = v * factor poly_matrix = init_poly_matrix( data=poly_matrix_data, diff --git a/polymatrix/expression/mixins/linearinexprmixin.py b/polymatrix/expression/mixins/linearinexprmixin.py index a900b7f..8354754 100644 --- a/polymatrix/expression/mixins/linearinexprmixin.py +++ b/polymatrix/expression/mixins/linearinexprmixin.py @@ -1,4 +1,3 @@ - import abc import collections @@ -7,7 +6,9 @@ from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.polymatrix.abc import PolyMatrix from polymatrix.expressionstate.abc import ExpressionState from polymatrix.expression.utils.getmonomialindices import get_monomial_indices -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) class LinearInExprMixin(ExpressionBaseMixin): @@ -33,48 +34,51 @@ class LinearInExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def monomials(self) -> ExpressionBaseMixin: - ... + def monomials(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def variables(self) -> ExpressionBaseMixin: - ... + def variables(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def ignore_unmatched(self) -> bool: - ... + def ignore_unmatched(self) -> bool: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - state, underlying = self.underlying.apply(state=state) state, monomials = get_monomial_indices(state, self.monomials) - state, variable_indices = get_variable_indices_from_variable(state, self.variables) + state, variable_indices = get_variable_indices_from_variable( + state, self.variables + ) assert underlying.shape[1] == 1 poly_matrix_data = collections.defaultdict(dict) for row in range(underlying.shape[0]): - polynomial = underlying.get_poly(row, 0) if polynomial is None: continue for monomial, value in polynomial.items(): - - x_monomial = tuple((var_idx, count) for var_idx, count in monomial if var_idx in variable_indices) - p_monomial = tuple((var_idx, count) for var_idx, count in monomial if var_idx not in variable_indices) + x_monomial = tuple( + (var_idx, count) + for var_idx, count in monomial + if var_idx in variable_indices + ) + p_monomial = tuple( + (var_idx, count) + for var_idx, count in monomial + if var_idx not in variable_indices + ) try: col = monomials.index(x_monomial) @@ -82,13 +86,13 @@ class LinearInExprMixin(ExpressionBaseMixin): if self.ignore_unmatched: continue else: - raise Exception(f'{x_monomial} not in {monomials}') + raise Exception(f"{x_monomial} not in {monomials}") poly_matrix_data[row, col][p_monomial] = value - + poly_matrix = init_poly_matrix( data=dict(poly_matrix_data), shape=(underlying.shape[0], len(monomials)), ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/linearmatrixinexprmixin.py b/polymatrix/expression/mixins/linearmatrixinexprmixin.py index 620d0fd..8239947 100644 --- a/polymatrix/expression/mixins/linearmatrixinexprmixin.py +++ b/polymatrix/expression/mixins/linearmatrixinexprmixin.py @@ -1,4 +1,3 @@ - import abc import collections from numpy import var @@ -7,28 +6,30 @@ from polymatrix.polymatrix.init import init_poly_matrix from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.polymatrix.abc import PolyMatrix from polymatrix.expressionstate.abc import ExpressionState -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) # is this class needed? class LinearMatrixInExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def variables(self) -> tuple: - ... + def variables(self) -> tuple: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: state, underlying = self.underlying.apply(state=state) - state, variable_index = get_variable_indices_from_variable(state, variables=self.variable) + state, variable_index = get_variable_indices_from_variable( + state, variables=self.variable + ) assert len(variable_index) == 1 @@ -36,27 +37,23 @@ class LinearMatrixInExprMixin(ExpressionBaseMixin): for row in range(underlying.shape[0]): for col in range(underlying.shape[1]): - underlying_poly = underlying.get_poly(row, col) if underlying_poly is None: continue for monomial, value in underlying_poly.items(): - if len(monomial) == 1: - variable, _ = monomial[0] if variable == variable_index: - poly_matrix_data[row, col][tuple()] = value break - + poly_matrix = init_poly_matrix( data=dict(poly_matrix_data), shape=underlying.shape, ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/linearmonomialsexprmixin.py b/polymatrix/expression/mixins/linearmonomialsexprmixin.py index c7de7f1..c4a5df7 100644 --- a/polymatrix/expression/mixins/linearmonomialsexprmixin.py +++ b/polymatrix/expression/mixins/linearmonomialsexprmixin.py @@ -1,4 +1,3 @@ - import abc import dataclasses @@ -6,7 +5,9 @@ from polymatrix.polymatrix.init import init_poly_matrix from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.expressionstate.mixins import ExpressionStateMixin from polymatrix.polymatrix.mixins import PolyMatrixMixin -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) from polymatrix.polymatrix.utils.sortmonomials import sort_monomials @@ -30,33 +31,35 @@ class LinearMonomialsExprMixin(ExpressionBaseMixin): @property @abc.abstractclassmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def variables(self) -> ExpressionBaseMixin: - ... + def variables(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionStateMixin, ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]: - state, underlying = self.underlying.apply(state=state) - state, variable_indices = get_variable_indices_from_variable(state, self.variables) + state, variable_indices = get_variable_indices_from_variable( + state, self.variables + ) def gen_linear_monomials(): for row in range(underlying.shape[0]): for col in range(underlying.shape[1]): - polynomial = underlying.get_poly(row, col) if polynomial is None: continue for monomial in polynomial.keys(): - x_monomial = tuple((var_idx, count) for var_idx, count in monomial if var_idx in variable_indices) + x_monomial = tuple( + (var_idx, count) + for var_idx, count in monomial + if var_idx in variable_indices + ) yield x_monomial @@ -74,7 +77,7 @@ class LinearMonomialsExprMixin(ExpressionBaseMixin): ) state = dataclasses.replace( - state, + state, cache=state.cache | {self: poly_matrix}, ) diff --git a/polymatrix/expression/mixins/matrixmultexprmixin.py b/polymatrix/expression/mixins/matrixmultexprmixin.py index 22a6c94..9402a19 100644 --- a/polymatrix/expression/mixins/matrixmultexprmixin.py +++ b/polymatrix/expression/mixins/matrixmultexprmixin.py @@ -1,4 +1,3 @@ - import abc from polymatrix.utils.getstacklines import FrameSummary @@ -13,22 +12,19 @@ from polymatrix.utils.tooperatorexception import to_operator_exception class MatrixMultExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def left(self) -> ExpressionBaseMixin: - ... + def left(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def right(self) -> ExpressionBaseMixin: - ... + def right(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def stack(self) -> tuple[FrameSummary]: - ... + def stack(self) -> tuple[FrameSummary]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: state, left = self.left.apply(state=state) @@ -37,20 +33,20 @@ class MatrixMultExprMixin(ExpressionBaseMixin): # assert left.shape[1] == right.shape[0], f'{left.shape[1]} is not equal to {right.shape[0]}' if not (left.shape[1] == right.shape[0]): - raise AssertionError(to_operator_exception( - message=f'{left.shape[1]} is not equal to {right.shape[0]}', - stack=self.stack, - )) + raise AssertionError( + to_operator_exception( + message=f"{left.shape[1]} is not equal to {right.shape[0]}", + stack=self.stack, + ) + ) poly_matrix_data = {} for poly_row in range(left.shape[0]): for poly_col in range(right.shape[1]): - polynomial = {} for index_k in range(left.shape[1]): - left_polynomial = left.get_poly(poly_row, index_k) if left_polynomial is None: continue diff --git a/polymatrix/expression/mixins/maxexprmixin.py b/polymatrix/expression/mixins/maxexprmixin.py index e0cdcad..650dc68 100644 --- a/polymatrix/expression/mixins/maxexprmixin.py +++ b/polymatrix/expression/mixins/maxexprmixin.py @@ -1,4 +1,3 @@ - import abc from polymatrix.polymatrix.init import init_poly_matrix @@ -11,15 +10,13 @@ from polymatrix.polymatrix.mixins import PolyMatrixMixin class MaxExprMixin(ExpressionBaseMixin): @property @abc.abstractclassmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionStateMixin, ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]: - state, underlying = self.underlying.apply(state) poly_matrix_data = {} @@ -28,7 +25,6 @@ class MaxExprMixin(ExpressionBaseMixin): def gen_values(): for col in range(underlying.shape[1]): - polynomial = underlying.get_poly(row, col) if polynomial is None: continue diff --git a/polymatrix/expression/mixins/parametrizeexprmixin.py b/polymatrix/expression/mixins/parametrizeexprmixin.py index 0160b9a..290b2eb 100644 --- a/polymatrix/expression/mixins/parametrizeexprmixin.py +++ b/polymatrix/expression/mixins/parametrizeexprmixin.py @@ -1,4 +1,3 @@ - import abc import dataclasses @@ -11,20 +10,17 @@ from polymatrix.polymatrix.mixins import PolyMatrixMixin class ParametrizeExprMixin(ExpressionBaseMixin): @property @abc.abstractclassmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractclassmethod - def name(self) -> str: - ... + def name(self) -> str: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionStateMixin, ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]: - state, underlying = self.underlying.apply(state) assert underlying.shape[1] == 1 @@ -38,7 +34,7 @@ class ParametrizeExprMixin(ExpressionBaseMixin): start = state.n_param state = state.register( - key=self.name, + key=self.name, n_param=underlying.shape[0], ) @@ -62,7 +58,7 @@ class ParametrizeExprMixin(ExpressionBaseMixin): ) # state = dataclasses.replace( - # state, + # state, # cache=state.cache | {self: poly_matrix}, # ) diff --git a/polymatrix/expression/mixins/parametrizematrixexprmixin.py b/polymatrix/expression/mixins/parametrizematrixexprmixin.py index 4eda9bf..175a5c3 100644 --- a/polymatrix/expression/mixins/parametrizematrixexprmixin.py +++ b/polymatrix/expression/mixins/parametrizematrixexprmixin.py @@ -1,4 +1,3 @@ - import abc import dataclasses @@ -12,20 +11,17 @@ from polymatrix.polymatrix.mixins import PolyMatrixMixin class ParametrizeMatrixExprMixin(ExpressionBaseMixin): @property @abc.abstractclassmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractclassmethod - def name(self) -> str: - ... + def name(self) -> str: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionStateMixin, ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]: - # cache polymatrix to not re-parametrize at every apply call if self in state.cache: return state, state.cache[self] @@ -39,13 +35,14 @@ class ParametrizeMatrixExprMixin(ExpressionBaseMixin): for row in range(underlying.shape[0]): for _ in range(row, underlying.shape[0]): - - poly_matrix_data[var_index, 0] = {((state.n_param + var_index, 1),): 1.0} + poly_matrix_data[var_index, 0] = { + ((state.n_param + var_index, 1),): 1.0 + } var_index += 1 state = state.register( - key=self, + key=self, n_param=var_index, ) @@ -55,7 +52,7 @@ class ParametrizeMatrixExprMixin(ExpressionBaseMixin): ) state = dataclasses.replace( - state, + state, cache=state.cache | {self: poly_matrix}, ) diff --git a/polymatrix/expression/mixins/productexprmixin.py b/polymatrix/expression/mixins/productexprmixin.py index b41865b..6089a1d 100644 --- a/polymatrix/expression/mixins/productexprmixin.py +++ b/polymatrix/expression/mixins/productexprmixin.py @@ -1,4 +1,3 @@ - import abc import itertools from polymatrix.polymatrix.typing import PolynomialData @@ -14,28 +13,24 @@ from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin class ProductExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> tuple[ExpressionBaseMixin]: - ... + def underlying(self) -> tuple[ExpressionBaseMixin]: ... @property @abc.abstractmethod - def degrees(self) -> tuple[int, ...] | None: - ... + def degrees(self) -> tuple[int, ...] | None: ... @property @abc.abstractmethod - def stack(self) -> tuple[FrameSummary]: - ... + def stack(self) -> tuple[FrameSummary]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - if len(self.underlying) == 0: - poly_matrix_data = {(0,0): {tuple(): 1}} - + poly_matrix_data = {(0, 0): {tuple(): 1}} + else: def acc_underlying(acc, v): @@ -47,20 +42,20 @@ class ProductExprMixin(ExpressionBaseMixin): return state, acc_polymatrix + (poly_matrix,) *_, (state, underlying) = itertools.accumulate( - self.underlying, - acc_underlying, - initial=(state, tuple()) + self.underlying, acc_underlying, initial=(state, tuple()) ) def gen_indices(): - product_indices = itertools.product(*(range(e.shape[0]) for e in underlying)) + product_indices = itertools.product( + *(range(e.shape[0]) for e in underlying) + ) if self.degrees is None: yield from product_indices else: yield from filter(lambda v: sum(v) in self.degrees, product_indices) - + indices = tuple(gen_indices()) poly_matrix_data = {} @@ -68,17 +63,16 @@ class ProductExprMixin(ExpressionBaseMixin): for row, indexing in enumerate(indices): def acc_product( - left: PolynomialData, - v: tuple[ExpressionBaseMixin, int], + left: PolynomialData, + v: tuple[ExpressionBaseMixin, int], ) -> PolynomialData: - poly_matrix, row = v right = poly_matrix.get_poly(row, 0) if len(left) == 0: return right - + result = {} multiply_polynomial(left, right, result) return result @@ -96,4 +90,4 @@ class ProductExprMixin(ExpressionBaseMixin): shape=(len(poly_matrix_data), 1), ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/quadraticinexprmixin.py b/polymatrix/expression/mixins/quadraticinexprmixin.py index 8869903..144fbab 100644 --- a/polymatrix/expression/mixins/quadraticinexprmixin.py +++ b/polymatrix/expression/mixins/quadraticinexprmixin.py @@ -1,4 +1,3 @@ - import abc import collections @@ -7,7 +6,9 @@ from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.polymatrix.abc import PolyMatrix from polymatrix.expressionstate.abc import ExpressionState from polymatrix.expression.utils.getmonomialindices import get_monomial_indices -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) from polymatrix.polymatrix.utils.splitmonomialindices import split_monomial_indices from polymatrix.utils.getstacklines import FrameSummary from polymatrix.utils.tooperatorexception import to_operator_exception @@ -18,82 +19,95 @@ class QuadraticInExprMixin(ExpressionBaseMixin): [[4 + 2*x1 + 3*x1**2]] -> [[4, 1], [1, 3]] """ - @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def monomials(self) -> ExpressionBaseMixin: - ... + def monomials(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def variables(self) -> ExpressionBaseMixin: - ... + def variables(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def stack(self) -> tuple[FrameSummary]: - ... + def stack(self) -> tuple[FrameSummary]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - state, underlying = self.underlying.apply(state=state) state, sos_monomials = get_monomial_indices(state, self.monomials) - state, variable_indices = get_variable_indices_from_variable(state, self.variables) + state, variable_indices = get_variable_indices_from_variable( + state, self.variables + ) if not (underlying.shape == (1, 1)): - raise AssertionError(to_operator_exception( - message=f'underlying shape is {underlying.shape}', - stack=self.stack, - )) + raise AssertionError( + to_operator_exception( + message=f"underlying shape is {underlying.shape}", + stack=self.stack, + ) + ) - poly_matrix_data = collections.defaultdict(lambda: collections.defaultdict(float)) + poly_matrix_data = collections.defaultdict( + lambda: collections.defaultdict(float) + ) underlying_poly = underlying.get_poly(0, 0) if underlying_poly is None: - raise AssertionError(to_operator_exception( - message=f'{underlying} is empty', - # message=f'{self.underlying} is empty', - stack=self.stack, - )) + raise AssertionError( + to_operator_exception( + message=f"{underlying} is empty", + # message=f'{self.underlying} is empty', + stack=self.stack, + ) + ) for monomial, value in underlying_poly.items(): - - x_monomial = tuple((var_idx, count) for var_idx, count in monomial if var_idx in variable_indices) - p_monomial = tuple((var_idx, count) for var_idx, count in monomial if var_idx not in variable_indices) + x_monomial = tuple( + (var_idx, count) + for var_idx, count in monomial + if var_idx in variable_indices + ) + p_monomial = tuple( + (var_idx, count) + for var_idx, count in monomial + if var_idx not in variable_indices + ) left, right = split_monomial_indices(x_monomial) try: col = sos_monomials.index(left) except ValueError: - raise AssertionError(to_operator_exception( - message=f'{left=} not in {sos_monomials=}', - stack=self.stack, - )) + raise AssertionError( + to_operator_exception( + message=f"{left=} not in {sos_monomials=}", + stack=self.stack, + ) + ) try: row = sos_monomials.index(right) except ValueError: - raise AssertionError(to_operator_exception( - message=f'{right=} not in {sos_monomials=}', - stack=self.stack, - )) + raise AssertionError( + to_operator_exception( + message=f"{right=} not in {sos_monomials=}", + stack=self.stack, + ) + ) poly_matrix_data[row, col][p_monomial] += value poly_matrix = init_poly_matrix( data=dict((k, dict(v)) for k, v in poly_matrix_data.items()), - shape=2*(len(sos_monomials),), + shape=2 * (len(sos_monomials),), ) return state, poly_matrix diff --git a/polymatrix/expression/mixins/quadraticmonomialsexprmixin.py b/polymatrix/expression/mixins/quadraticmonomialsexprmixin.py index 3a7de30..6880dcf 100644 --- a/polymatrix/expression/mixins/quadraticmonomialsexprmixin.py +++ b/polymatrix/expression/mixins/quadraticmonomialsexprmixin.py @@ -1,4 +1,3 @@ - import abc import dataclasses @@ -6,7 +5,9 @@ from polymatrix.polymatrix.init import init_poly_matrix from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.expressionstate.mixins import ExpressionStateMixin from polymatrix.polymatrix.mixins import PolyMatrixMixin -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) from polymatrix.polymatrix.utils.splitmonomialindices import split_monomial_indices @@ -30,40 +31,44 @@ class QuadraticMonomialsExprMixin(ExpressionBaseMixin): @property @abc.abstractclassmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def variables(self) -> ExpressionBaseMixin: - ... + def variables(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionStateMixin, ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]: - state, underlying = self.underlying.apply(state=state) - state, variable_indices = get_variable_indices_from_variable(state, self.variables) + state, variable_indices = get_variable_indices_from_variable( + state, self.variables + ) def gen_sos_monomials(): for row in range(underlying.shape[0]): for col in range(underlying.shape[1]): - polynomial = underlying.get_poly(row, col) if polynomial is None: continue for monomial in polynomial.keys(): - x_monomial = tuple((var_idx, count) for var_idx, count in monomial if var_idx in variable_indices) + x_monomial = tuple( + (var_idx, count) + for var_idx, count in monomial + if var_idx in variable_indices + ) left, right = split_monomial_indices(x_monomial) yield left yield right - sos_monomials = tuple(sorted(set(gen_sos_monomials()), key=lambda m: (len(m), m))) + sos_monomials = tuple( + sorted(set(gen_sos_monomials()), key=lambda m: (len(m), m)) + ) def gen_data(): for index, monomial in enumerate(sos_monomials): @@ -77,7 +82,7 @@ class QuadraticMonomialsExprMixin(ExpressionBaseMixin): ) state = dataclasses.replace( - state, + state, cache=state.cache | {self: poly_matrix}, ) diff --git a/polymatrix/expression/mixins/repmatexprmixin.py b/polymatrix/expression/mixins/repmatexprmixin.py index 48748be..e5d7606 100644 --- a/polymatrix/expression/mixins/repmatexprmixin.py +++ b/polymatrix/expression/mixins/repmatexprmixin.py @@ -5,23 +5,21 @@ from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.expressionstate.mixins import ExpressionStateMixin from polymatrix.polymatrix.mixins import PolyMatrixMixin + class RepMatExprMixin(ExpressionBaseMixin): @property @abc.abstractclassmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractclassmethod - def repetition(self) -> tuple[int, int]: - ... + def repetition(self) -> tuple[int, int]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionStateMixin, ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]: - state, underlying = self.underlying.apply(state) @dataclassabc.dataclassabc(frozen=True) @@ -39,5 +37,5 @@ class RepMatExprMixin(ExpressionBaseMixin): return state, RepMatPolyMatrix( underlying=underlying, - shape=tuple(s*r for s, r in zip(underlying.shape, self.repetition)), - )
\ No newline at end of file + shape=tuple(s * r for s, r in zip(underlying.shape, self.repetition)), + ) diff --git a/polymatrix/expression/mixins/reshapeexprmixin.py b/polymatrix/expression/mixins/reshapeexprmixin.py index 915e750..b74ee0d 100644 --- a/polymatrix/expression/mixins/reshapeexprmixin.py +++ b/polymatrix/expression/mixins/reshapeexprmixin.py @@ -9,23 +9,23 @@ from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.expressionstate.mixins import ExpressionStateMixin from polymatrix.polymatrix.mixins import PolyMatrixMixin + class ReshapeExprMixin(ExpressionBaseMixin): @property @abc.abstractclassmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractclassmethod - def new_shape(self) -> tuple[int | ExpressionBaseMixin, int | ExpressionBaseMixin]: - ... + def new_shape( + self, + ) -> tuple[int | ExpressionBaseMixin, int | ExpressionBaseMixin]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionStateMixin, ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]: - state, underlying = self.underlying.apply(state) @dataclassabc.dataclassabc(frozen=True) @@ -49,16 +49,16 @@ class ReshapeExprMixin(ExpressionBaseMixin): # for idx in self.new_shape: if isinstance(index, int): pass - + elif isinstance(index, ExpressionBaseMixin): state, polymatrix = index.apply(state) index = polymatrix.shape[0] else: - raise Exception(f'{index=}') + raise Exception(f"{index=}") return state, acc_indices + (index,) - + *_, (state, new_shape) = itertools.accumulate( self.new_shape, acc_new_shape, @@ -84,10 +84,10 @@ class ReshapeExprMixin(ExpressionBaseMixin): else: yield e - new_shape = tuple(gen_shape()) + new_shape = tuple(gen_shape()) return state, ReshapePolyMatrix( underlying=underlying, shape=new_shape, underlying_shape=underlying.shape, - )
\ No newline at end of file + ) diff --git a/polymatrix/expression/mixins/setelementatexprmixin.py b/polymatrix/expression/mixins/setelementatexprmixin.py index 9250d3c..207d1b2 100644 --- a/polymatrix/expression/mixins/setelementatexprmixin.py +++ b/polymatrix/expression/mixins/setelementatexprmixin.py @@ -1,4 +1,3 @@ - import abc import dataclasses import typing @@ -20,22 +19,19 @@ class SetElementAtExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def index(self) -> tuple[tuple[int, ...], tuple[int, ...]]: - ... + def index(self) -> tuple[tuple[int, ...], tuple[int, ...]]: ... @property @abc.abstractmethod - def value(self) -> ExpressionBaseMixin: - ... + def value(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: state, underlying = self.underlying.apply(state=state) @@ -66,4 +62,3 @@ class SetElementAtExprMixin(ExpressionBaseMixin): shape=underlying.shape, polynomial=polynomial, ) -
\ No newline at end of file diff --git a/polymatrix/expression/mixins/squeezeexprmixin.py b/polymatrix/expression/mixins/squeezeexprmixin.py index 888300f..67ade46 100644 --- a/polymatrix/expression/mixins/squeezeexprmixin.py +++ b/polymatrix/expression/mixins/squeezeexprmixin.py @@ -1,4 +1,3 @@ - import abc from polymatrix.polymatrix.init import init_poly_matrix @@ -11,12 +10,11 @@ from polymatrix.expressionstate.abc import ExpressionState class SqueezeExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: state, underlying = self.underlying.apply(state=state) @@ -27,7 +25,6 @@ class SqueezeExprMixin(ExpressionBaseMixin): row_index = 0 for row in range(underlying.shape[0]): - polynomial = underlying.get_poly(row, 0) if polynomial is None: continue @@ -47,4 +44,4 @@ class SqueezeExprMixin(ExpressionBaseMixin): shape=(row_index, 1), ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/substituteexprmixin.py b/polymatrix/expression/mixins/substituteexprmixin.py index 2bc36d1..d2ab740 100644 --- a/polymatrix/expression/mixins/substituteexprmixin.py +++ b/polymatrix/expression/mixins/substituteexprmixin.py @@ -8,27 +8,26 @@ from polymatrix.polymatrix.init import init_poly_matrix from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.polymatrix.abc import PolyMatrix from polymatrix.expressionstate.abc import ExpressionState -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) from polymatrix.polymatrix.utils.multiplypolynomial import multiply_polynomial class SubstituteExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def substitutions(self) -> tuple[tuple[typing.Any, ExpressionBaseMixin], ...]: - ... + def substitutions(self) -> tuple[tuple[typing.Any, ExpressionBaseMixin], ...]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - state, underlying = self.underlying.apply(state=state) def acc_substitutions(acc, next): @@ -55,23 +54,24 @@ class SubstituteExprMixin(ExpressionBaseMixin): return state, acc_variable + indices, acc_substitution + polynomials - *_, (state, variable_indices, substitutions) = tuple(itertools.accumulate( - self.substitutions, - acc_substitutions, - initial=(state, tuple(), tuple()), - )) + *_, (state, variable_indices, substitutions) = tuple( + itertools.accumulate( + self.substitutions, + acc_substitutions, + initial=(state, tuple(), tuple()), + ) + ) if len(substitutions) == 1: substitutions = tuple(substitutions[0] for _ in variable_indices) else: - assert len(variable_indices) == len(substitutions), f'{substitutions=}' + assert len(variable_indices) == len(substitutions), f"{substitutions=}" poly_matrix_data = {} for row in range(underlying.shape[0]): for col in range(underlying.shape[1]): - polynomial = underlying.get_poly(row, col) if polynomial is None: continue @@ -79,7 +79,6 @@ class SubstituteExprMixin(ExpressionBaseMixin): polynomial = collections.defaultdict(float) for monomial, value in polynomial.items(): - substituted_monomial = {tuple(): value} for variable, count in monomial: @@ -88,20 +87,27 @@ class SubstituteExprMixin(ExpressionBaseMixin): substitution = substitutions[index] for _ in range(count): - next = {} - multiply_polynomial(substituted_monomial, substitution, next) + multiply_polynomial( + substituted_monomial, substitution, next + ) substituted_monomial = next else: next = {} - multiply_polynomial(substituted_monomial, {((variable, count),): 1.0}, next) + multiply_polynomial( + substituted_monomial, {((variable, count),): 1.0}, next + ) substituted_monomial = next for monomial, value in substituted_monomial.items(): polynomial[monomial] += value - polynomial = {key: val for key, val in polynomial.items() if not math.isclose(val, 0, abs_tol=1e-12)} + polynomial = { + key: val + for key, val in polynomial.items() + if not math.isclose(val, 0, abs_tol=1e-12) + } if 0 < len(polynomial): poly_matrix_data[row, col] = polynomial @@ -111,4 +117,4 @@ class SubstituteExprMixin(ExpressionBaseMixin): shape=underlying.shape, ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/subtractmonomialsexprmixin.py b/polymatrix/expression/mixins/subtractmonomialsexprmixin.py index 5baddd1..6bac539 100644 --- a/polymatrix/expression/mixins/subtractmonomialsexprmixin.py +++ b/polymatrix/expression/mixins/subtractmonomialsexprmixin.py @@ -1,4 +1,3 @@ - import abc import dataclasses @@ -8,31 +7,31 @@ from polymatrix.expressionstate.mixins import ExpressionStateMixin from polymatrix.polymatrix.mixins import PolyMatrixMixin from polymatrix.expression.utils.getmonomialindices import get_monomial_indices from polymatrix.polymatrix.utils.sortmonomials import sort_monomials -from polymatrix.polymatrix.utils.subtractmonomialindices import SubtractError, subtract_monomial_indices +from polymatrix.polymatrix.utils.subtractmonomialindices import ( + SubtractError, + subtract_monomial_indices, +) class SubtractMonomialsExprMixin(ExpressionBaseMixin): """ [[1], [x], [x**3]], [[x]] -> [[1], [x**2]] """ - + @property @abc.abstractclassmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def monomials(self) -> ExpressionBaseMixin: - ... + def monomials(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionStateMixin, ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]: - - state, underlying = get_monomial_indices(state, self.underlying) + state, underlying = get_monomial_indices(state, self.underlying) state, sub_monomials = get_monomial_indices(state, self.monomials) def gen_remainders(): @@ -48,7 +47,7 @@ class SubtractMonomialsExprMixin(ExpressionBaseMixin): remainders = sort_monomials(set(gen_remainders())) - data = {(row, 0): {remainder: 1.0} for row, remainder in enumerate(remainders)} + data = {(row, 0): {remainder: 1.0} for row, remainder in enumerate(remainders)} poly_matrix = init_poly_matrix( data=data, @@ -56,7 +55,7 @@ class SubtractMonomialsExprMixin(ExpressionBaseMixin): ) state = dataclasses.replace( - state, + state, cache=state.cache | {self: poly_matrix}, ) diff --git a/polymatrix/expression/mixins/sumexprmixin.py b/polymatrix/expression/mixins/sumexprmixin.py index 8e649d3..4ade032 100644 --- a/polymatrix/expression/mixins/sumexprmixin.py +++ b/polymatrix/expression/mixins/sumexprmixin.py @@ -1,4 +1,3 @@ - import abc import collections import dataclasses @@ -10,30 +9,27 @@ from polymatrix.polymatrix.mixins import PolyMatrixMixin class SumExprMixin(ExpressionBaseMixin): - """ - For each row of the matrix sum the colum elements. - + """ + For each row of the matrix sum the colum elements. + [[1, 2, 3], [4, 5, 6]] -> [[6], [15]] """ @property @abc.abstractclassmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionStateMixin, ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]: - state, underlying = self.underlying.apply(state) poly_matrix_data = collections.defaultdict(dict) for row in range(underlying.shape[0]): for col in range(underlying.shape[1]): - underlying_poly = underlying.get_poly(row, col) if underlying_poly is None: diff --git a/polymatrix/expression/mixins/symmetricexprmixin.py b/polymatrix/expression/mixins/symmetricexprmixin.py index 624f0ee..c8020f9 100644 --- a/polymatrix/expression/mixins/symmetricexprmixin.py +++ b/polymatrix/expression/mixins/symmetricexprmixin.py @@ -1,4 +1,3 @@ - import abc import collections import itertools @@ -16,18 +15,16 @@ class SymmetricExprMixin(ExpressionBaseMixin): [[1, 2], [3, 4]] -> [[1, 2.5], [2.5, 4]] """ - + @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - state, underlying = self.underlying.apply(state=state) assert underlying.shape[0] == underlying.shape[1] @@ -41,14 +38,13 @@ class SymmetricExprMixin(ExpressionBaseMixin): return self.underlying.shape def get_poly(self, row: int, col: int) -> dict[tuple[int, ...], float]: - def gen_symmetric_monomials(): for i_row, i_col in ((row, col), (col, row)): polynomial = self.underlying.get_poly(i_row, i_col) - + if polynomial is not None: yield polynomial - + all_monomials = tuple(gen_symmetric_monomials()) if len(all_monomials) == 0: diff --git a/polymatrix/expression/mixins/toconstantexprmixin.py b/polymatrix/expression/mixins/toconstantexprmixin.py index 53db4c2..9c8b9b7 100644 --- a/polymatrix/expression/mixins/toconstantexprmixin.py +++ b/polymatrix/expression/mixins/toconstantexprmixin.py @@ -1,4 +1,3 @@ - import abc import collections @@ -14,14 +13,14 @@ class ToConstantExprMixin(ExpressionBaseMixin): [[a + b*x + c*x^2]] -> [[a]] """ + @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: state, underlying = self.underlying.apply(state=state) @@ -30,17 +29,16 @@ class ToConstantExprMixin(ExpressionBaseMixin): for row in range(underlying.shape[0]): for col in range(underlying.shape[1]): - polynomial = underlying.get_poly(row, col) if polynomial is None: continue if tuple() in polynomial: poly_matrix_data[row, col][tuple()] = polynomial[tuple()] - + poly_matrix = init_poly_matrix( data=dict(poly_matrix_data), shape=underlying.shape, ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/toquadraticexprmixin.py b/polymatrix/expression/mixins/toquadraticexprmixin.py index 1234606..936ec76 100644 --- a/polymatrix/expression/mixins/toquadraticexprmixin.py +++ b/polymatrix/expression/mixins/toquadraticexprmixin.py @@ -1,4 +1,3 @@ - import abc import collections import dataclasses @@ -13,17 +12,16 @@ class ToQuadraticExprMixin(ExpressionBaseMixin): """ [[1 + x1**2 + x1**3]] -> [[1 + x1**2 + x2*x1]] - with auxilliary equation: x1**2 - x2 + with auxilliary equation: x1**2 - x2 """ - + @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: state, underlying = self.underlying.apply(state=state) @@ -37,7 +35,6 @@ class ToQuadraticExprMixin(ExpressionBaseMixin): polynomial = collections.defaultdict(float) for monomial, value in monomial_terms.items(): - if 2 < len(monomial): current_aux = state[0].n_param polynomial[(monomial[0], current_aux)] += value @@ -56,7 +53,7 @@ class ToQuadraticExprMixin(ExpressionBaseMixin): (current_aux,): -1, } - else: + else: polynomial[monomial] += value # return dict(terms_row_col) @@ -64,7 +61,6 @@ class ToQuadraticExprMixin(ExpressionBaseMixin): for row in range(underlying.shape[0]): for col in range(underlying.shape[1]): - polynomial = underlying.get_poly(row, col) if polynomial is None: continue @@ -84,7 +80,8 @@ class ToQuadraticExprMixin(ExpressionBaseMixin): state = dataclasses.replace( state[0], - auxillary_equations=dict(gen_auxillary_equations()) | auxillary_equations_from_quadratic, + auxillary_equations=dict(gen_auxillary_equations()) + | auxillary_equations_from_quadratic, ) poly_matrix = init_poly_matrix( @@ -92,4 +89,4 @@ class ToQuadraticExprMixin(ExpressionBaseMixin): shape=underlying.shape, ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/tosortedvariablesmixin.py b/polymatrix/expression/mixins/tosortedvariablesmixin.py index 32e2162..4dfa518 100644 --- a/polymatrix/expression/mixins/tosortedvariablesmixin.py +++ b/polymatrix/expression/mixins/tosortedvariablesmixin.py @@ -1,6 +1,7 @@ - import abc -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) from polymatrix.polymatrix.init import init_poly_matrix from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin @@ -12,27 +13,32 @@ from polymatrix.expressionstate.abc import ExpressionState class ToSortedVariablesExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - state, variable_indices = get_variable_indices_from_variable(state, self.underlying) + state, variable_indices = get_variable_indices_from_variable( + state, self.underlying + ) - tagged_variable_index = tuple((offset, state.get_name_from_offset(offset)) for offset in variable_indices) + tagged_variable_index = tuple( + (offset, state.get_name_from_offset(offset)) for offset in variable_indices + ) - ordered_variable_index = tuple(v[0] for v in sorted(tagged_variable_index, key=lambda v: v[1])) + ordered_variable_index = tuple( + v[0] for v in sorted(tagged_variable_index, key=lambda v: v[1]) + ) def gen_sorted_vector(): for row, index in enumerate(ordered_variable_index): yield (row, 0), {((index, 1),): 1} - + poly_matrix = init_poly_matrix( data=dict(gen_sorted_vector()), shape=(len(variable_indices), 1), ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/tosymmetricmatrixexprmixin.py b/polymatrix/expression/mixins/tosymmetricmatrixexprmixin.py index 488c991..3c50f76 100644 --- a/polymatrix/expression/mixins/tosymmetricmatrixexprmixin.py +++ b/polymatrix/expression/mixins/tosymmetricmatrixexprmixin.py @@ -1,7 +1,8 @@ - import abc -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) from polymatrix.polymatrix.init import init_poly_matrix from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.expressionstate.mixins import ExpressionStateMixin @@ -17,15 +18,13 @@ class ToSymmetricMatrixExprMixin(ExpressionBaseMixin): @property @abc.abstractclassmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionStateMixin, ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]: - state, underlying = self.underlying.apply(state) assert underlying.shape[1] == 1 @@ -38,7 +37,7 @@ class ToSymmetricMatrixExprMixin(ExpressionBaseMixin): idx += 1 sum_val += idx - assert sum_val == val, f'{sum_val=}, {val=}' + assert sum_val == val, f"{sum_val=}, {val=}" return idx diff --git a/polymatrix/expression/mixins/transposeexprmixin.py b/polymatrix/expression/mixins/transposeexprmixin.py index 99fc247..1f01c60 100644 --- a/polymatrix/expression/mixins/transposeexprmixin.py +++ b/polymatrix/expression/mixins/transposeexprmixin.py @@ -1,4 +1,3 @@ - import abc import dataclassabc @@ -14,14 +13,14 @@ class TransposeExprMixin(ExpressionBaseMixin): [[1, 2, 3]] -> [[1], [2], [3]] """ + @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... # overwrites the abstract method of `PolyMatrixExprBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: state, underlying = self.underlying.apply(state=state) @@ -37,4 +36,4 @@ class TransposeExprMixin(ExpressionBaseMixin): return state, TransposePolyMatrix( underlying=underlying, shape=(underlying.shape[1], underlying.shape[0]), - )
\ No newline at end of file + ) diff --git a/polymatrix/expression/mixins/truncateexprmixin.py b/polymatrix/expression/mixins/truncateexprmixin.py index 2fcb970..3171221 100644 --- a/polymatrix/expression/mixins/truncateexprmixin.py +++ b/polymatrix/expression/mixins/truncateexprmixin.py @@ -1,37 +1,34 @@ - import abc from polymatrix.polymatrix.init import init_poly_matrix from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin from polymatrix.polymatrix.abc import PolyMatrix from polymatrix.expressionstate.abc import ExpressionState -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.utils.getvariableindices import ( + get_variable_indices_from_variable, +) class TruncateExprMixin(ExpressionBaseMixin): @property @abc.abstractmethod - def underlying(self) -> ExpressionBaseMixin: - ... + def underlying(self) -> ExpressionBaseMixin: ... @property @abc.abstractmethod - def variables(self) -> ExpressionBaseMixin | None: - ... + def variables(self) -> ExpressionBaseMixin | None: ... @property @abc.abstractmethod - def degrees(self) -> tuple[int]: - ... + def degrees(self) -> tuple[int]: ... @property @abc.abstractmethod - def inverse(self) -> bool: - ... + def inverse(self) -> bool: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: state, underlying = self.underlying.apply(state=state) @@ -40,14 +37,15 @@ class TruncateExprMixin(ExpressionBaseMixin): cond = lambda idx: True else: - state, variable_indices = get_variable_indices_from_variable(state, self.variables) + state, variable_indices = get_variable_indices_from_variable( + state, self.variables + ) cond = lambda idx: idx in variable_indices poly_matrix_data = {} for row in range(underlying.shape[0]): for col in range(underlying.shape[1]): - polynomial = underlying.get_poly(row, col) if polynomial is None: continue @@ -55,17 +53,18 @@ class TruncateExprMixin(ExpressionBaseMixin): polynomial = {} for monomial, value in polynomial.items(): - - degree = sum((count for var_idx, count in monomial if cond(var_idx))) + degree = sum( + (count for var_idx, count in monomial if cond(var_idx)) + ) if (degree in self.degrees) is not self.inverse: polynomial[monomial] = value - + poly_matrix_data[row, col] = polynomial - + poly_matrix = init_poly_matrix( data=dict(poly_matrix_data), shape=underlying.shape, ) - return state, poly_matrix + return state, poly_matrix diff --git a/polymatrix/expression/mixins/vstackexprmixin.py b/polymatrix/expression/mixins/vstackexprmixin.py index 98ab663..2dec7bf 100644 --- a/polymatrix/expression/mixins/vstackexprmixin.py +++ b/polymatrix/expression/mixins/vstackexprmixin.py @@ -1,4 +1,3 @@ - import abc import itertools import dataclassabc @@ -15,25 +14,25 @@ class VStackExprMixin(ExpressionBaseMixin): [[1, 2]], [[3, 4]] -> [[1, 2], [3, 4]] """ - + @property @abc.abstractmethod - def underlying(self) -> tuple[ExpressionBaseMixin, ...]: - ... + def underlying(self) -> tuple[ExpressionBaseMixin, ...]: ... # overwrites the abstract method of `ExpressionBaseMixin` def apply( - self, + self, state: ExpressionState, ) -> tuple[ExpressionState, PolyMatrix]: - all_underlying = [] for expr in self.underlying: state, polymatrix = expr.apply(state=state) all_underlying.append(polymatrix) for underlying in all_underlying: - assert underlying.shape[1] == all_underlying[0].shape[1], f'{underlying.shape[1]} not equal {all_underlying[0].shape[1]}' + assert ( + underlying.shape[1] == all_underlying[0].shape[1] + ), f"{underlying.shape[1]} not equal {all_underlying[0].shape[1]}" @dataclassabc.dataclassabc(frozen=True) class VStackPolyMatrix(PolyMatrixMixin): @@ -42,20 +41,24 @@ class VStackExprMixin(ExpressionBaseMixin): shape: tuple[int, int] def get_poly(self, row: int, col: int) -> dict[tuple[int, ...], float]: - for polymatrix, (row_start, row_end) in zip(self.all_underlying, self.underlying_row_range): - if row_start <= row < row_end: + for polymatrix, (row_start, row_end) in zip( + self.all_underlying, self.underlying_row_range + ): + if row_start <= row < row_end: return polymatrix.get_poly( row=row - row_start, col=col, ) - raise Exception(f'row {row} is out of bounds') + raise Exception(f"row {row} is out of bounds") - underlying_row_range = tuple(itertools.pairwise( - itertools.accumulate( - (expr.shape[0] for expr in all_underlying), - initial=0) - )) + underlying_row_range = tuple( + itertools.pairwise( + itertools.accumulate( + (expr.shape[0] for expr in all_underlying), initial=0 + ) + ) + ) n_row = sum(polymatrix.shape[0] for polymatrix in all_underlying) diff --git a/polymatrix/expression/op.py b/polymatrix/expression/op.py index 612a2db..0ca55ee 100644 --- a/polymatrix/expression/op.py +++ b/polymatrix/expression/op.py @@ -5,34 +5,32 @@ from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin def diff( - expression: ExpressionBaseMixin, + expression: ExpressionBaseMixin, variables: ExpressionBaseMixin, introduce_derivatives: bool = None, ) -> ExpressionBaseMixin: - if not isinstance(variables, ExpressionBaseMixin): - variables=polymatrix.expression.init.init_from_expr(variables) + variables = polymatrix.expression.init.init_from_expr(variables) if introduce_derivatives is None: introduce_derivatives = False return polymatrix.expression.impl.DerivativeExprImpl( - underlying=expression, - variables=variables, - introduce_derivatives=introduce_derivatives, - stack=get_stack_lines(), - ) + underlying=expression, + variables=variables, + introduce_derivatives=introduce_derivatives, + stack=get_stack_lines(), + ) def filter_( - underlying: ExpressionBaseMixin, - predicator: ExpressionBaseMixin, - inverse: bool = None, + underlying: ExpressionBaseMixin, + predicator: ExpressionBaseMixin, + inverse: bool = None, ) -> ExpressionBaseMixin: - if inverse is None: inverse = False - + return polymatrix.expression.impl.FilterExprImpl( underlying=underlying, predicator=predicator, @@ -41,45 +39,42 @@ def filter_( def integrate( - expression: ExpressionBaseMixin, + expression: ExpressionBaseMixin, variables: ExpressionBaseMixin, from_: tuple[float, ...], to: tuple[float, ...], ) -> ExpressionBaseMixin: - if not isinstance(variables, ExpressionBaseMixin): - variables=polymatrix.expression.init.init_from_expr(variables) + variables = polymatrix.expression.init.init_from_expr(variables) assert len(from_) == len(to) return polymatrix.expression.impl.IntegrateExprImpl( - underlying=expression, - variables=variables, - from_=from_, + underlying=expression, + variables=variables, + from_=from_, to=to, - stack=get_stack_lines(), - ) + stack=get_stack_lines(), + ) def legendre( expression: ExpressionBaseMixin, degrees: tuple[int, ...] = None, ) -> ExpressionBaseMixin: - return polymatrix.expression.impl.LegendreSeriesImpl( underlying=expression, degrees=degrees, stack=get_stack_lines(), ) - + def linear_in( - expression: ExpressionBaseMixin, - variables: ExpressionBaseMixin, + expression: ExpressionBaseMixin, + variables: ExpressionBaseMixin, monomials: ExpressionBaseMixin = None, - ignore_unmatched: bool = None, + ignore_unmatched: bool = None, ) -> ExpressionBaseMixin: - if monomials is None: monomials = linear_monomials( expression=expression, @@ -90,21 +85,22 @@ def linear_in( underlying=expression, monomials=monomials, variables=variables, - ignore_unmatched = ignore_unmatched, + ignore_unmatched=ignore_unmatched, ) + def linear_monomials( - expression: ExpressionBaseMixin, + expression: ExpressionBaseMixin, variables: ExpressionBaseMixin, ) -> ExpressionBaseMixin: - return polymatrix.expression.impl.LinearMonomialsExprImpl( underlying=expression, variables=variables, ) + def degree( - underlying: ExpressionBaseMixin, + underlying: ExpressionBaseMixin, ): return polymatrix.expression.impl.DegreeExprImpl( underlying=underlying, diff --git a/polymatrix/expression/to.py b/polymatrix/expression/to.py index cebc75a..c334a9e 100644 --- a/polymatrix/expression/to.py +++ b/polymatrix/expression/to.py @@ -3,29 +3,29 @@ import numpy as np from polymatrix.expression.expression import Expression from polymatrix.expression.mixins.parametrizeexprmixin import ParametrizeExprMixin -from polymatrix.expression.mixins.parametrizematrixexprmixin import ParametrizeMatrixExprMixin -from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable +from polymatrix.expression.mixins.parametrizematrixexprmixin import ( + ParametrizeMatrixExprMixin, +) from polymatrix.expressionstate.abc import ExpressionState from polymatrix.statemonad.init import init_state_monad from polymatrix.statemonad.mixins import StateMonadMixin -# def shape( -# expr: Expression, -# ) -> StateMonadMixin[ExpressionState, tuple[int, ...]]: -# def func(state: ExpressionState): -# state, polymatrix = expr.apply(state) +def shape( + expr: Expression, +) -> StateMonadMixin[ExpressionState, tuple[int, ...]]: + def func(state: ExpressionState): + state, polymatrix = expr.apply(state) -# return state, polymatrix.shape + return state, polymatrix.shape -# return init_state_monad(func) + return init_state_monad(func) def to_constant( expr: Expression, assert_constant: bool = True, ) -> StateMonadMixin[ExpressionState, np.ndarray]: - def func(state: ExpressionState): state, underlying = expr.apply(state) @@ -35,87 +35,55 @@ def to_constant( for monomial, value in polynomial.items(): if len(monomial) == 0: A[row, col] = value - + elif assert_constant: - raise Exception(f'non-constant term {monomial=}') + raise Exception(f"non-constant term {monomial=}") return state, A return init_state_monad(func) -# def to_degrees( -# expr: Expression, -# variables: Expression, -# ) -> StateMonadMixin[ExpressionState, np.ndarray]: - -# def func(state: ExpressionState): -# state, underlying = expr.apply(state) -# state, variable_indices = get_variable_indices_from_variable(state, variables) - -# def gen_rows(): -# for row in range(underlying.shape[0]): -# def gen_cols(): -# for col in range(underlying.shape[1]): - -# def gen_degrees(): -# polynomial = underlying.get_poly(row, col) - -# if polynomial is None: -# yield 0 - -# else: -# for monomial, _ in polynomial.items(): -# yield sum(count for var, count in monomial if var in variable_indices) - -# yield tuple(set(gen_degrees())) - -# yield tuple(gen_cols()) - -# return state, tuple(gen_rows()) - -# return init_state_monad(func) - - def to_sympy( expr: Expression, ) -> StateMonadMixin[ExpressionState, sympy.Expr]: - def func(state: ExpressionState): state, underlying = expr.apply(state) A = np.zeros(underlying.shape, dtype=object) for (row, col), polynomial in underlying.gen_data(): - sympy_polynomial = 0 for monomial, value in polynomial.items(): sympy_monomial = 1 for offset, count in monomial: - variable = state.get_key_from_offset(offset) # def get_variable_from_offset(offset: int): # for variable, (start, end) in state.offset_dict.items(): # if start <= offset < end: - # assert end - start == 1, f'{start=}, {end=}, {variable=}' + # assert end - start == 1, f'{start=}, {end=}, {variable=}' if isinstance(variable, sympy.core.symbol.Symbol): variable_name = variable.name - elif isinstance(variable, (ParametrizeExprMixin, ParametrizeMatrixExprMixin)): + elif isinstance( + variable, (ParametrizeExprMixin, ParametrizeMatrixExprMixin) + ): variable_name = variable.name elif isinstance(variable, str): variable_name = variable else: - raise Exception(f'{variable=}') + raise Exception(f"{variable=}") start, end = state.offset_dict[variable] if end - start == 1: sympy_var = sympy.Symbol(variable_name) else: - sympy_var = sympy.Symbol(f'{variable_name}_{offset - start + 1}') + sympy_var = sympy.Symbol( + f"{variable_name}_{offset - start + 1}" + ) # var = get_variable_from_offset(offset) sympy_monomial *= sympy_var**count diff --git a/polymatrix/expression/utils/broadcastpolymatrix.py b/polymatrix/expression/utils/broadcastpolymatrix.py index e8b3ff3..56f7568 100644 --- a/polymatrix/expression/utils/broadcastpolymatrix.py +++ b/polymatrix/expression/utils/broadcastpolymatrix.py @@ -5,11 +5,10 @@ from polymatrix.polymatrix.abc import PolyMatrix def broadcast_poly_matrix( - left: PolyMatrix, - right: PolyMatrix, - stack: tuple[FrameSummary], + left: PolyMatrix, + right: PolyMatrix, + stack: tuple[FrameSummary], ) -> PolyMatrix: - # broadcast left if left.shape == (1, 1) and right.shape != (1, 1): left = init_broadcast_poly_matrix( @@ -26,9 +25,11 @@ def broadcast_poly_matrix( else: if not (left.shape == right.shape): - raise AssertionError(to_operator_exception( - message=f'{left.shape} != {right.shape}', - stack=stack, - )) + raise AssertionError( + to_operator_exception( + message=f"{left.shape} != {right.shape}", + stack=stack, + ) + ) return left, right diff --git a/polymatrix/expression/utils/formatsubstitutions.py b/polymatrix/expression/utils/formatsubstitutions.py index c9b2972..8a72bf0 100644 --- a/polymatrix/expression/utils/formatsubstitutions.py +++ b/polymatrix/expression/utils/formatsubstitutions.py @@ -1,44 +1,44 @@ import typing + def format_substitutions( - variables: typing.Union[typing.Any, tuple, dict], - values: float | tuple = None, + variables: typing.Union[typing.Any, tuple, dict], + values: float | tuple = None, ): - """ - (variables = x, values = 1.0) # ok - (variables = x, values = np.array(1.0)) # ok - (variables = (x, y, z), values = 1.0) # ok - (variables = (x, y, z), values = (1.0, 2.0, 3.0)) # ok - (variables = {x: 1.0, y: 2.0, z: 3.0}) # ok - (variables = ((x, 1.0), (y, 2.0), (z, 3.0))) # ok + """ + (variables = x, values = 1.0) # ok + (variables = x, values = np.array(1.0)) # ok + (variables = (x, y, z), values = 1.0) # ok + (variables = (x, y, z), values = (1.0, 2.0, 3.0)) # ok + (variables = {x: 1.0, y: 2.0, z: 3.0}) # ok + (variables = ((x, 1.0), (y, 2.0), (z, 3.0))) # ok - (variables = v, values = (1.0, 2.0)) # ok - (variables = (v1, v2), values = ((1.0, 2.0), (3.0,))) # ok - (variables = (v1, v2), values = (1.0, 2.0, 3.0)) # not ok - """ + (variables = v, values = (1.0, 2.0)) # ok + (variables = (v1, v2), values = ((1.0, 2.0), (3.0,))) # ok + (variables = (v1, v2), values = (1.0, 2.0, 3.0)) # not ok + """ - if values is not None: - if isinstance(variables, tuple): - if isinstance(values, tuple): - assert len(variables) == len(values), f'{variables=}, {values=}' + if values is not None: + if isinstance(variables, tuple): + if isinstance(values, tuple): + assert len(variables) == len(values), f"{variables=}, {values=}" - else: - values = tuple(values for _ in variables) + else: + values = tuple(values for _ in variables) - else: - variables = (variables,) - values = (values,) + else: + variables = (variables,) + values = (values,) - substitutions = zip(variables, values) - - elif isinstance(variables, dict): - substitutions = variables.items() + substitutions = zip(variables, values) - elif isinstance(variables, tuple): - substitutions = variables + elif isinstance(variables, dict): + substitutions = variables.items() - else: - raise Exception(f'{variables=}') + elif isinstance(variables, tuple): + substitutions = variables - return substitutions + else: + raise Exception(f"{variables=}") + return substitutions diff --git a/polymatrix/expression/utils/getderivativemonomials.py b/polymatrix/expression/utils/getderivativemonomials.py index 8fb4729..9f2c48e 100644 --- a/polymatrix/expression/utils/getderivativemonomials.py +++ b/polymatrix/expression/utils/getderivativemonomials.py @@ -7,20 +7,19 @@ from polymatrix.polymatrix.typing import PolynomialData def differentiate_polynomial( - polynomial: PolynomialData, - diff_wrt_variable: int, + polynomial: PolynomialData, + diff_wrt_variable: int, state: ExpressionState, considered_variables: set, introduce_derivatives: bool, ): - @dataclasses.dataclass(frozen=True) class DerivativeKey: variable: int with_respect_to: int if introduce_derivatives: - + def gen_new_variables(): for monomial in polynomial.keys(): for var in monomial: @@ -56,7 +55,8 @@ def differentiate_polynomial( state = dataclasses.replace( state, - auxillary_equations=state.auxillary_equations | {derivation_variable: auxillary_derivation_terms}, + auxillary_equations=state.auxillary_equations + | {derivation_variable: auxillary_derivation_terms}, ) return state, candidates + (new_variable,) @@ -73,17 +73,14 @@ def differentiate_polynomial( else: confirmed_variables = tuple() - diff_polynomial = collections.defaultdict(float) for monomial, value in polynomial.items(): - monomial_cnt = dict(monomial) def differentiate_monomial(dependent_variable, derivation_variable=None): def gen_diff_monomial(): for current_variable, current_count in monomial: - if current_variable is dependent_variable: sel_counter = current_count - 1 @@ -109,7 +106,10 @@ def differentiate_polynomial( # only used if introduce_derivatives == True if introduce_derivatives: for candidate_variable in monomial_cnt.keys(): - if candidate_variable in considered_variables or candidate_variable in confirmed_variables: + if ( + candidate_variable in considered_variables + or candidate_variable in confirmed_variables + ): key = DerivativeKey( variable=candidate_variable, with_respect_to=diff_wrt_variable, @@ -117,10 +117,10 @@ def differentiate_polynomial( derivation_variable = state.offset_dict[key][0] diff_monomial, value = differentiate_monomial( - dependent_variable=candidate_variable, + dependent_variable=candidate_variable, derivation_variable=derivation_variable, ) diff_polynomial[diff_monomial] += value return state, dict(diff_polynomial) - # return state, derivation_terms
\ No newline at end of file + # return state, derivation_terms diff --git a/polymatrix/expression/utils/getmonomialindices.py b/polymatrix/expression/utils/getmonomialindices.py index 238f80a..9145002 100644 --- a/polymatrix/expression/utils/getmonomialindices.py +++ b/polymatrix/expression/utils/getmonomialindices.py @@ -3,21 +3,19 @@ from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin def get_monomial_indices( - state: ExpressionState, - expression: ExpressionBaseMixin, + state: ExpressionState, + expression: ExpressionBaseMixin, ) -> tuple[ExpressionState, tuple[int, ...]]: - state, poly_matrix = expression.apply(state) - assert poly_matrix.shape[1] == 1, f'{poly_matrix.shape=}' + assert poly_matrix.shape[1] == 1, f"{poly_matrix.shape=}" def gen_indices(): for row in range(poly_matrix.shape[0]): row_terms = poly_matrix.get_poly(row, 0) - assert len(row_terms) == 1, f'{row_terms} contains more than one term' - + assert len(row_terms) == 1, f"{row_terms} contains more than one term" + yield from row_terms.keys() return state, tuple(gen_indices()) - diff --git a/polymatrix/expression/utils/getvariableindices.py b/polymatrix/expression/utils/getvariableindices.py index d61da57..9799da3 100644 --- a/polymatrix/expression/utils/getvariableindices.py +++ b/polymatrix/expression/utils/getvariableindices.py @@ -6,31 +6,33 @@ from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin def get_variable_indices_from_variable( - state: ExpressionState, - variable: ExpressionBaseMixin | int | typing.Any, + state: ExpressionState, + variable: ExpressionBaseMixin | int | typing.Any, ) -> tuple[int, ...] | None: - if isinstance(variable, ExpressionBaseMixin): state, variable_polynomial = variable.apply(state) assert variable_polynomial.shape[1] == 1 def gen_variables_indices(): - for row in range(variable_polynomial.shape[0]): row_terms = variable_polynomial.get_poly(row, 0) - assert len(row_terms) == 1, f'{row_terms} does not contain a single term' - + assert ( + len(row_terms) == 1 + ), f"{row_terms} does not contain a single term" + for monomial in row_terms.keys(): - assert len(monomial) <= 1, f'{monomial=} contains more than one variable' + assert ( + len(monomial) <= 1 + ), f"{monomial=} contains more than one variable" if len(monomial) == 0: continue - - assert monomial[0][1] == 1, f'{monomial[0]=}' + + assert monomial[0][1] == 1, f"{monomial[0]=}" yield monomial[0][0] - + variable_indices = tuple(gen_variables_indices()) elif isinstance(variable, int): @@ -47,7 +49,6 @@ def get_variable_indices_from_variable( # not used, remove? def get_variable_indices(state, variables): - if not isinstance(variables, tuple): variables = (variables,) diff --git a/polymatrix/expressionstate/abc.py b/polymatrix/expressionstate/abc.py index a2e1154..0c88dd4 100644 --- a/polymatrix/expressionstate/abc.py +++ b/polymatrix/expressionstate/abc.py @@ -1,4 +1,5 @@ -from polymatrix.expressionstate.mixins import ExpressionStateMixin +from polymatrix.expressionstate.mixins import ExpressionStateMixin + class ExpressionState(ExpressionStateMixin): - pass + pass diff --git a/polymatrix/expressionstate/impl.py b/polymatrix/expressionstate/impl.py index 3188b5d..c25dae5 100644 --- a/polymatrix/expressionstate/impl.py +++ b/polymatrix/expressionstate/impl.py @@ -1,11 +1,11 @@ import dataclassabc -from polymatrix.expressionstate.abc import ExpressionState +from polymatrix.expressionstate.abc import ExpressionState @dataclassabc.dataclassabc(frozen=True) class ExpressionStateImpl(ExpressionState): - n_param: int - offset_dict: dict - auxillary_equations: dict[int, dict[tuple[int], float]] - cache: dict + n_param: int + offset_dict: dict + auxillary_equations: dict[int, dict[tuple[int], float]] + cache: dict diff --git a/polymatrix/expressionstate/init.py b/polymatrix/expressionstate/init.py index 1748d43..31b40f0 100644 --- a/polymatrix/expressionstate/init.py +++ b/polymatrix/expressionstate/init.py @@ -2,18 +2,18 @@ from polymatrix.expressionstate.impl import ExpressionStateImpl def init_expression_state( - n_param: int = None, - offset_dict: dict = None, + n_param: int = None, + offset_dict: dict = None, ): - if n_param is None: - n_param = 0 + if n_param is None: + n_param = 0 - if offset_dict is None: - offset_dict = {} + if offset_dict is None: + offset_dict = {} - return ExpressionStateImpl( - n_param=n_param, - offset_dict=offset_dict, - auxillary_equations={}, - cache={}, -) + return ExpressionStateImpl( + n_param=n_param, + offset_dict=offset_dict, + auxillary_equations={}, + cache={}, + ) diff --git a/polymatrix/expressionstate/mixins.py b/polymatrix/expressionstate/mixins.py index ad23ea2..ae8d0fb 100644 --- a/polymatrix/expressionstate/mixins.py +++ b/polymatrix/expressionstate/mixins.py @@ -8,12 +8,11 @@ from polymatrix.statemonad.mixins import StateCacheMixin class ExpressionStateMixin( StateCacheMixin, ): - @property @abc.abstractmethod def n_param(self) -> int: - """ - number of parameters used in polynomial matrix expressions + """ + number of parameters used in polynomial matrix expressions """ ... @@ -25,18 +24,17 @@ class ExpressionStateMixin( a variable consists of one or more parameters indexed by a start and an end index """ - + ... @property @abc.abstractmethod - def auxillary_equations(self) -> dict[int, dict[tuple[int], float]]: - ... + def auxillary_equations(self) -> dict[int, dict[tuple[int], float]]: ... def get_name_from_offset(self, offset: int): for variable, (start, end) in self.offset_dict.items(): if start <= offset < end: - return f'{str(variable)}_{offset-start}' + return f"{str(variable)}_{offset-start}" def get_key_from_offset(self, offset: int): for variable, (start, end) in self.offset_dict.items(): @@ -44,21 +42,21 @@ class ExpressionStateMixin( return variable def register( - self, - n_param: int, + self, + n_param: int, key: typing.Any = None, - ) -> 'ExpressionStateMixin': - + ) -> "ExpressionStateMixin": if key is None: updated_state = dataclasses.replace( - self, + self, n_param=self.n_param + n_param, ) elif key not in self.offset_dict: updated_state = dataclasses.replace( self, - offset_dict=self.offset_dict | {key: (self.n_param, self.n_param + n_param)}, + offset_dict=self.offset_dict + | {key: (self.n_param, self.n_param + n_param)}, n_param=self.n_param + n_param, ) diff --git a/polymatrix/polymatrix/abc.py b/polymatrix/polymatrix/abc.py index aee2b40..ba909c4 100644 --- a/polymatrix/polymatrix/abc.py +++ b/polymatrix/polymatrix/abc.py @@ -4,4 +4,4 @@ from polymatrix.polymatrix.mixins import PolyMatrixAsDictMixin class PolyMatrix(PolyMatrixAsDictMixin, abc.ABC): - pass + pass diff --git a/polymatrix/polymatrix/impl.py b/polymatrix/polymatrix/impl.py index 04a7872..1777ea8 100644 --- a/polymatrix/polymatrix/impl.py +++ b/polymatrix/polymatrix/impl.py @@ -2,16 +2,16 @@ import dataclassabc from polymatrix.polymatrix.abc import PolyMatrix from polymatrix.polymatrix.mixins import BroadcastPolyMatrixMixin -from polymatrix.polymatrix.typing import PolynomialData +from polymatrix.polymatrix.typing import PolynomialData @dataclassabc.dataclassabc(frozen=True) class PolyMatrixImpl(PolyMatrix): - data: dict[tuple[int, int], PolynomialData] - shape: tuple[int, int] + data: dict[tuple[int, int], PolynomialData] + shape: tuple[int, int] @dataclassabc.dataclassabc(frozen=True) class BroadcastPolyMatrixImpl(BroadcastPolyMatrixMixin): - data: tuple[tuple[int], float] - shape: tuple[int, int] + data: tuple[tuple[int], float] + shape: tuple[int, int] diff --git a/polymatrix/polymatrix/init.py b/polymatrix/polymatrix/init.py index fa7bd20..55f941b 100644 --- a/polymatrix/polymatrix/init.py +++ b/polymatrix/polymatrix/init.py @@ -3,22 +3,20 @@ from polymatrix.polymatrix.typing import PolynomialData def init_poly_matrix( - data: dict[tuple[int, int], PolynomialData], - shape: tuple[int, int], + data: dict[tuple[int, int], PolynomialData], + shape: tuple[int, int], ): - - return PolyMatrixImpl( - data=data, - shape=shape, -) + return PolyMatrixImpl( + data=data, + shape=shape, + ) def init_broadcast_poly_matrix( - data: PolynomialData, - shape: tuple[int, int], + data: PolynomialData, + shape: tuple[int, int], ): - - return BroadcastPolyMatrixImpl( - data=data, - shape=shape, -) + return BroadcastPolyMatrixImpl( + data=data, + shape=shape, + ) diff --git a/polymatrix/polymatrix/mixins.py b/polymatrix/polymatrix/mixins.py index 0ce4dad..997ff9f 100644 --- a/polymatrix/polymatrix/mixins.py +++ b/polymatrix/polymatrix/mixins.py @@ -7,21 +7,21 @@ from polymatrix.polymatrix.typing import PolynomialData class PolyMatrixMixin(abc.ABC): @property @abc.abstractclassmethod - def shape(self) -> tuple[int, int]: - ... + def shape(self) -> tuple[int, int]: ... - def gen_data(self) -> typing.Generator[tuple[tuple[int, int], PolynomialData], None, None]: + def gen_data( + self, + ) -> typing.Generator[tuple[tuple[int, int], PolynomialData], None, None]: for row in range(self.shape[0]): for col in range(self.shape[1]): polynomial = self.get_poly(row, col) if polynomial is None: continue - + yield (row, col), polynomial @abc.abstractclassmethod - def get_poly(self, row: int, col: int) -> PolynomialData | None: - ... + def get_poly(self, row: int, col: int) -> PolynomialData | None: ... class PolyMatrixAsDictMixin( @@ -30,8 +30,7 @@ class PolyMatrixAsDictMixin( ): @property @abc.abstractmethod - def data(self) -> dict[tuple[int, int], PolynomialData]: - ... + def data(self) -> dict[tuple[int, int], PolynomialData]: ... # overwrites the abstract method of `PolyMatrixMixin` def get_poly(self, row: int, col: int) -> PolynomialData | None: @@ -45,8 +44,7 @@ class BroadcastPolyMatrixMixin( ): @property @abc.abstractmethod - def data(self) -> PolynomialData: - ... + def data(self) -> PolynomialData: ... # overwrites the abstract method of `PolyMatrixMixin` def get_poly(self, col: int, row: int) -> PolynomialData | None: diff --git a/polymatrix/polymatrix/typing.py b/polymatrix/polymatrix/typing.py index 2518d9e..f8fb9f6 100644 --- a/polymatrix/polymatrix/typing.py +++ b/polymatrix/polymatrix/typing.py @@ -1,8 +1,7 @@ - # monomial x1**2 x2 # with indices {x1: 0, x2: 1} # is represented as ((0, 2), (1, 1)) MonomialData = tuple[tuple[int, int], ...] PolynomialData = dict[MonomialData, int | float] -PolynomialMatrixData = dict[tuple[int, int], PolynomialData]
\ No newline at end of file +PolynomialMatrixData = dict[tuple[int, int], PolynomialData] diff --git a/polymatrix/polymatrix/utils/mergemonomialindices.py b/polymatrix/polymatrix/utils/mergemonomialindices.py index 8285c98..5a05265 100644 --- a/polymatrix/polymatrix/utils/mergemonomialindices.py +++ b/polymatrix/polymatrix/utils/mergemonomialindices.py @@ -15,7 +15,7 @@ def merge_monomial_indices( ((1, 2),) # x2**2 ) -> ((0, 2), (1, 3)) # x1**1 x2**3 """ - + if len(monomials) == 0: return tuple() @@ -23,7 +23,6 @@ def merge_monomial_indices( return monomials[0] else: - m1_dict = dict(monomials[0]) for other in monomials[1:]: diff --git a/polymatrix/polymatrix/utils/multiplypolynomial.py b/polymatrix/polymatrix/utils/multiplypolynomial.py index 17fd154..fe8b13b 100644 --- a/polymatrix/polymatrix/utils/multiplypolynomial.py +++ b/polymatrix/polymatrix/utils/multiplypolynomial.py @@ -4,23 +4,24 @@ import math from polymatrix.polymatrix.utils.mergemonomialindices import merge_monomial_indices from polymatrix.polymatrix.typing import PolynomialData + def multiply_polynomial( - left: PolynomialData, - right: PolynomialData, - result: PolynomialData, - ) -> None: + left: PolynomialData, + right: PolynomialData, + result: PolynomialData, +) -> None: """ Multiplies two polynomials `left` and `right` and adds the result to the mutable polynomial `result`. """ - - for (left_monomial, left_value), (right_monomial, right_value) \ - in itertools.product(left.items(), right.items()): + for (left_monomial, left_value), (right_monomial, right_value) in itertools.product( + left.items(), right.items() + ): value = left_value * right_value if math.isclose(value, 0, abs_tol=1e-12): continue - + monomial = merge_monomial_indices((left_monomial, right_monomial)) if monomial not in result: diff --git a/polymatrix/polymatrix/utils/sortmonomialindices.py b/polymatrix/polymatrix/utils/sortmonomialindices.py index 2a13bc3..cf6fa61 100644 --- a/polymatrix/polymatrix/utils/sortmonomialindices.py +++ b/polymatrix/polymatrix/utils/sortmonomialindices.py @@ -2,9 +2,11 @@ from polymatrix.polymatrix.typing import MonomialData def sort_monomial_indices( - monomial: MonomialData, + monomial: MonomialData, ) -> MonomialData: - return tuple(sorted( - monomial, - key=lambda m: m[0], - )) + return tuple( + sorted( + monomial, + key=lambda m: m[0], + ) + ) diff --git a/polymatrix/polymatrix/utils/sortmonomials.py b/polymatrix/polymatrix/utils/sortmonomials.py index e1c82e7..810ef9b 100644 --- a/polymatrix/polymatrix/utils/sortmonomials.py +++ b/polymatrix/polymatrix/utils/sortmonomials.py @@ -1,9 +1,12 @@ from polymatrix.polymatrix.typing import MonomialData + def sort_monomials( - monomials: tuple[MonomialData], + monomials: tuple[MonomialData], ) -> tuple[MonomialData]: - return tuple(sorted( - monomials, - key=lambda m: (sum(count for _, count in m), len(m), m), - )) + return tuple( + sorted( + monomials, + key=lambda m: (sum(count for _, count in m), len(m), m), + ) + ) diff --git a/polymatrix/polymatrix/utils/splitmonomialindices.py b/polymatrix/polymatrix/utils/splitmonomialindices.py index 8d5d148..9f15670 100644 --- a/polymatrix/polymatrix/utils/splitmonomialindices.py +++ b/polymatrix/polymatrix/utils/splitmonomialindices.py @@ -2,22 +2,22 @@ from polymatrix.polymatrix.typing import MonomialData def split_monomial_indices( - monomial: MonomialData, + monomial: MonomialData, ) -> tuple[MonomialData, MonomialData]: left = [] right = [] is_left = True - for idx, count in monomial: + for idx, count in monomial: count_left = count // 2 if count % 2: if is_left: count_left = count_left + 1 - + is_left = not is_left - + count_right = count - count_left if 0 < count_left: @@ -25,5 +25,5 @@ def split_monomial_indices( if 0 < count_right: right.append((idx, count - count_left)) - + return tuple(left), tuple(right) diff --git a/polymatrix/polymatrix/utils/subtractmonomialindices.py b/polymatrix/polymatrix/utils/subtractmonomialindices.py index c62bf3e..3a671c5 100644 --- a/polymatrix/polymatrix/utils/subtractmonomialindices.py +++ b/polymatrix/polymatrix/utils/subtractmonomialindices.py @@ -8,8 +8,8 @@ class SubtractError(Exception): def subtract_monomial_indices( - m1: MonomialData, - m2: MonomialData, + m1: MonomialData, + m2: MonomialData, ) -> MonomialData: m1_dict = dict(m1) diff --git a/polymatrix/statemonad/__init__.py b/polymatrix/statemonad/__init__.py index 915eb31..bff288a 100644 --- a/polymatrix/statemonad/__init__.py +++ b/polymatrix/statemonad/__init__.py @@ -10,7 +10,6 @@ def from_(val): def zip(monads: tuple[StateMonad]): - def zip_func(state): values = tuple() @@ -21,5 +20,3 @@ def zip(monads: tuple[StateMonad]): return state, values return init_state_monad(zip_func) - - diff --git a/polymatrix/statemonad/abc.py b/polymatrix/statemonad/abc.py index ffb52de..671b5bd 100644 --- a/polymatrix/statemonad/abc.py +++ b/polymatrix/statemonad/abc.py @@ -1,7 +1,7 @@ import abc -from polymatrix.statemonad.mixins import StateMonadMixin +from polymatrix.statemonad.mixins import StateMonadMixin class StateMonad(StateMonadMixin, abc.ABC): - pass + pass diff --git a/polymatrix/statemonad/impl.py b/polymatrix/statemonad/impl.py index 4bffb5d..14ad503 100644 --- a/polymatrix/statemonad/impl.py +++ b/polymatrix/statemonad/impl.py @@ -1,9 +1,9 @@ -from typing import Callable +from typing import Callable import dataclassabc -from polymatrix.statemonad.abc import StateMonad +from polymatrix.statemonad.abc import StateMonad @dataclassabc.dataclassabc(frozen=True) class StateMonadImpl(StateMonad): - apply_func: Callable + apply_func: Callable diff --git a/polymatrix/statemonad/init.py b/polymatrix/statemonad/init.py index 7ef47cc..f3a8bd6 100644 --- a/polymatrix/statemonad/init.py +++ b/polymatrix/statemonad/init.py @@ -4,8 +4,8 @@ from polymatrix.statemonad.impl import StateMonadImpl def init_state_monad( - apply_func: Callable, + apply_func: Callable, ): - return StateMonadImpl( - apply_func=apply_func, -) + return StateMonadImpl( + apply_func=apply_func, + ) diff --git a/polymatrix/statemonad/mixins.py b/polymatrix/statemonad/mixins.py index dad7662..4b65353 100644 --- a/polymatrix/statemonad/mixins.py +++ b/polymatrix/statemonad/mixins.py @@ -6,41 +6,39 @@ from typing import Callable, Tuple, TypeVar, Generic class StateCacheMixin(abc.ABC): @property @abc.abstractmethod - def cache(self) -> dict: - ... + def cache(self) -> dict: ... -State = TypeVar('State', bound=StateCacheMixin) -U = TypeVar('U') -V = TypeVar('V') +State = TypeVar("State", bound=StateCacheMixin) +U = TypeVar("U") +V = TypeVar("V") class StateMonadMixin( Generic[State, U], - abc.ABC, + abc.ABC, ): @property @abc.abstractmethod - def apply_func(self) -> Callable[[State], tuple[State, U]]: - ... - - def map(self, fn: Callable[[U], V]) -> 'StateMonadMixin[State, V]': + def apply_func(self) -> Callable[[State], tuple[State, U]]: ... + def map(self, fn: Callable[[U], V]) -> "StateMonadMixin[State, V]": def internal_map(state: State) -> Tuple[State, U]: n_state, val = self.apply(state) return n_state, fn(val) return dataclasses.replace(self, apply_func=internal_map) - def flat_map(self, fn: Callable[[U], 'StateMonadMixin']) -> 'StateMonadMixin[State, V]': - + def flat_map( + self, fn: Callable[[U], "StateMonadMixin"] + ) -> "StateMonadMixin[State, V]": def internal_map(state: State) -> Tuple[State, V]: n_state, val = self.apply(state) return fn(val).apply(n_state) return dataclasses.replace(self, apply_func=internal_map) - def zip(self, other: 'StateMonadMixin') -> 'StateMonadMixin': + def zip(self, other: "StateMonadMixin") -> "StateMonadMixin": def internal_map(state: State) -> Tuple[State, V]: state, val1 = self.apply(state) state, val2 = other.apply(state) @@ -48,7 +46,7 @@ class StateMonadMixin( return dataclasses.replace(self, apply_func=internal_map) - def cache(self) -> 'StateMonadMixin': + def cache(self) -> "StateMonadMixin": def internal_map(state: State) -> Tuple[State, V]: if self in state.cache: return state, state.cache[self] @@ -56,7 +54,7 @@ class StateMonadMixin( state, val = self.apply(state) state = dataclasses.replace( - state, + state, cache=state.cache | {self: val}, ) @@ -69,4 +67,3 @@ class StateMonadMixin( def read(self, state: State) -> U: return self.apply_func(state)[1] - diff --git a/polymatrix/utils/tooperatorexception.py b/polymatrix/utils/tooperatorexception.py index 5f7db0f..1c84be7 100644 --- a/polymatrix/utils/tooperatorexception.py +++ b/polymatrix/utils/tooperatorexception.py @@ -2,13 +2,16 @@ from polymatrix.utils.getstacklines import FrameSummary def to_operator_exception( - message: str, - stack: tuple[FrameSummary], + message: str, + stack: tuple[FrameSummary], ) -> str: exception_lines = [ message, - f' Assertion traceback (most recent call last):', - *(f' File "{stack_line.filename}", line {stack_line.lineno}\n {stack_line.line}' for stack_line in stack), + f" Assertion traceback (most recent call last):", + *( + f' File "{stack_line.filename}", line {stack_line.lineno}\n {stack_line.line}' + for stack_line in stack + ), ] - return '\n'.join(exception_lines) + return "\n".join(exception_lines) |