summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--polymatrix/__init__.py975
-rw-r--r--polymatrix/denserepr/__init__.py (renamed from polymatrix/expression/init/__init__.py)0
-rw-r--r--polymatrix/denserepr/from_.py156
-rw-r--r--polymatrix/denserepr/impl.py143
-rw-r--r--polymatrix/expression/__init__.py52
-rw-r--r--polymatrix/expression/expression.py216
-rw-r--r--polymatrix/expression/from_.py56
-rw-r--r--polymatrix/expression/impl/reshapeexprmixin.py10
-rw-r--r--polymatrix/expression/implexpressionbase.py (renamed from polymatrix/expression/impl/impl.py)62
-rw-r--r--polymatrix/expression/init/initadditionexpr.py12
-rw-r--r--polymatrix/expression/init/initblockdiagexpr.py7
-rw-r--r--polymatrix/expression/init/initcacheexpr.py10
-rw-r--r--polymatrix/expression/init/initcombinationsexpr.py12
-rw-r--r--polymatrix/expression/init/initderivativeexpr.py20
-rw-r--r--polymatrix/expression/init/initdeterminantexpr.py10
-rw-r--r--polymatrix/expression/init/initdiagexpr.py10
-rw-r--r--polymatrix/expression/init/initdivergenceexpr.py13
-rw-r--r--polymatrix/expression/init/initdivisionexpr.py12
-rw-r--r--polymatrix/expression/init/initelemmultexpr.py12
-rw-r--r--polymatrix/expression/init/initevalexpr.py37
-rw-r--r--polymatrix/expression/init/initexpression.py10
-rw-r--r--polymatrix/expression/init/initeyeexpr.py10
-rw-r--r--polymatrix/expression/init/initfilterexpr.py17
-rw-r--r--polymatrix/expression/init/initfromsymmetricmatrixexpr.py10
-rw-r--r--polymatrix/expression/init/initfromsympyexpr.py68
-rw-r--r--polymatrix/expression/init/initfromtermsexpr.py33
-rw-r--r--polymatrix/expression/init/initgetitemexpr.py22
-rw-r--r--polymatrix/expression/init/inithalfnewtonpolytopeexpr.py14
-rw-r--r--polymatrix/expression/init/initlinearinexpr.py18
-rw-r--r--polymatrix/expression/init/initlinearmatrixinexpr.py12
-rw-r--r--polymatrix/expression/init/initlinearmonomialsexpr.py15
-rw-r--r--polymatrix/expression/init/initmatrixmultexpr.py12
-rw-r--r--polymatrix/expression/init/initmaxdegreeexpr.py10
-rw-r--r--polymatrix/expression/init/initmaxexpr.py10
-rw-r--r--polymatrix/expression/init/initparametrizeexpr.py15
-rw-r--r--polymatrix/expression/init/initparametrizematrixexpr.py12
-rw-r--r--polymatrix/expression/init/initquadraticinexpr.py17
-rw-r--r--polymatrix/expression/init/initquadraticmonomialsexpr.py15
-rw-r--r--polymatrix/expression/init/initrepmatexpr.py12
-rw-r--r--polymatrix/expression/init/initreshapeexpr.py12
-rw-r--r--polymatrix/expression/init/initsetelementatexpr.py14
-rw-r--r--polymatrix/expression/init/initsqueezeexpr.py10
-rw-r--r--polymatrix/expression/init/initsubtractmonomialsexpr.py12
-rw-r--r--polymatrix/expression/init/initsumexpr.py10
-rw-r--r--polymatrix/expression/init/initsymmetricexpr.py10
-rw-r--r--polymatrix/expression/init/inittoconstantexpr.py10
-rw-r--r--polymatrix/expression/init/inittoquadraticexpr.py10
-rw-r--r--polymatrix/expression/init/inittosortedvariables.py10
-rw-r--r--polymatrix/expression/init/inittosymmetricmatrixexpr.py10
-rw-r--r--polymatrix/expression/init/inittransposeexpr.py10
-rw-r--r--polymatrix/expression/init/inittruncateexpr.py22
-rw-r--r--polymatrix/expression/init/initvstackexpr.py20
-rw-r--r--polymatrix/expression/initexpressionbase.py604
-rw-r--r--polymatrix/expression/mixins/additionexprmixin.py15
-rw-r--r--polymatrix/expression/mixins/assertdegreeexprmixin.py49
-rw-r--r--polymatrix/expression/mixins/blockdiagexprmixin.py2
-rw-r--r--polymatrix/expression/mixins/cacheexprmixin.py2
-rw-r--r--polymatrix/expression/mixins/combinationsexprmixin.py101
-rw-r--r--polymatrix/expression/mixins/derivativeexprmixin.py23
-rw-r--r--polymatrix/expression/mixins/diagexprmixin.py8
-rw-r--r--polymatrix/expression/mixins/divisionexprmixin.py35
-rw-r--r--polymatrix/expression/mixins/elemmultexprmixin.py86
-rw-r--r--polymatrix/expression/mixins/expressionbasemixin.py7
-rw-r--r--polymatrix/expression/mixins/fromsymmetricmatrixexprmixin.py2
-rw-r--r--polymatrix/expression/mixins/fromtupleexprmixin.py (renamed from polymatrix/expression/mixins/fromsympyexprmixin.py)33
-rw-r--r--polymatrix/expression/mixins/legendreseriesmixin.py62
-rw-r--r--polymatrix/expression/mixins/matrixmultexprmixin.py18
-rw-r--r--polymatrix/expression/mixins/parametrizematrixexprmixin.py1
-rw-r--r--polymatrix/expression/mixins/productexprmixin.py132
-rw-r--r--polymatrix/expression/mixins/quadraticinexprmixin.py32
-rw-r--r--polymatrix/expression/mixins/substituteexprmixin.py13
-rw-r--r--polymatrix/expression/mixins/sumexprmixin.py6
-rw-r--r--polymatrix/expression/mixins/symmetricexprmixin.py6
-rw-r--r--polymatrix/expression/mixins/toconstantexprmixin.py5
-rw-r--r--polymatrix/expression/mixins/tosortedvariablesmixin.py1
-rw-r--r--polymatrix/expression/mixins/tosymmetricmatrixexprmixin.py10
-rw-r--r--polymatrix/expression/mixins/transposeexprmixin.py5
-rw-r--r--polymatrix/expression/mixins/vstackexprmixin.py6
-rw-r--r--polymatrix/expression/op.py67
-rw-r--r--polymatrix/expression/to.py129
-rw-r--r--polymatrix/expression/utils/formatsubstitutions.py (renamed from polymatrix/expression/init/initsubstituteexpr.py)31
-rw-r--r--polymatrix/expression/utils/getderivativemonomials.py120
-rw-r--r--polymatrix/expression/utils/getmonomialindices.py3
-rw-r--r--polymatrix/expression/utils/multiplymonomials.py15
-rw-r--r--polymatrix/utils/__init__.py0
-rw-r--r--polymatrix/utils/getstacklines.py23
-rw-r--r--polymatrix/utils/tooperatorexception.py14
-rw-r--r--test_polymatrix/test_expression/test_addition.py9
-rw-r--r--test_polymatrix/test_expression/test_blockdiag.py9
-rw-r--r--test_polymatrix/test_expression/test_derivative.py11
-rw-r--r--test_polymatrix/test_expression/test_divergence.py10
-rw-r--r--test_polymatrix/test_expression/test_eval.py7
-rw-r--r--test_polymatrix/test_expression/test_linearin.py13
-rw-r--r--test_polymatrix/test_expression/test_matrixmult.py10
-rw-r--r--test_polymatrix/test_expression/test_quadraticin.py11
-rw-r--r--test_polymatrix/test_expression/test_substitude.py11
-rw-r--r--test_polymatrix/test_expression/test_subtractmonomials.py12
-rw-r--r--test_polymatrix/test_expression/test_sum.py8
-rw-r--r--test_polymatrix/test_expression/test_symmetric.py8
-rw-r--r--test_polymatrix/test_expression/test_toconstant.py10
-rw-r--r--test_polymatrix/test_expression/test_truncate.py11
-rw-r--r--test_polymatrix/test_expression/test_vstack.py9
-rw-r--r--test_polymatrix/test_tomatrixrepr.py8
103 files changed, 2491 insertions, 1649 deletions
diff --git a/polymatrix/__init__.py b/polymatrix/__init__.py
index 8cffe4b..6c927d1 100644
--- a/polymatrix/__init__.py
+++ b/polymatrix/__init__.py
@@ -1,686 +1,539 @@
-import collections
-import dataclasses
-import itertools
-import math
-import typing
-import numpy as np
-import scipy.sparse
-import sympy
-
-from polymatrix.expression.expression import Expression
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-from polymatrix.expression.mixins.parametrizeexprmixin import ParametrizeExprMixin
-from polymatrix.expression.mixins.parametrizematrixexprmixin import ParametrizeMatrixExprMixin
-from polymatrix.expressionstate.expressionstate import ExpressionState
-from polymatrix.expression.init.initblockdiagexpr import init_block_diag_expr
-from polymatrix.expression.init.initexpression import init_expression
-from polymatrix.expression.init.initeyeexpr import init_eye_expr
-from polymatrix.expression.init.initfromsympyexpr import init_from_sympy_expr
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
-from polymatrix.expression.init.initvstackexpr import init_v_stack_expr
-from polymatrix.polymatrix.polymatrix import PolyMatrix
-from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable
-from polymatrix.statemonad.init.initstatemonad import init_state_monad
-from polymatrix.statemonad.mixins.statemonadmixin import StateMonadMixin
-from polymatrix.expression.utils.monomialtoindex import monomial_to_index
-from polymatrix.expressionstate.init.initexpressionstate import init_expression_state as original_init_expression_state
-from polymatrix.statemonad.statemonad import StateMonad
-
-
-def init_expression_state():
- return original_init_expression_state()
-
-def from_sympy(
- data: tuple[tuple[float]],
-):
- return init_expression(
- init_from_sympy_expr(data)
- )
-
-def from_state_monad(
- data: StateMonad,
-):
- return init_expression(
- data.flat_map(lambda inner_data: init_from_sympy_expr(inner_data)),
- )
-
-def from_polymatrix(
- polymatrix: PolyMatrix,
-):
- return init_expression(
- init_from_terms_expr(polymatrix)
- )
-
-def from_(
- data: str | tuple[tuple[float]],
-):
- if isinstance(data, str):
- return from_(1).parametrize(data)
-
- return from_sympy(data)
-
-def v_stack(
- expressions: tuple[Expression],
-):
- return init_expression(
- init_v_stack_expr(expressions)
- )
-
-def h_stack(
- expressions: tuple[Expression],
-):
- return init_expression(
- init_v_stack_expr(tuple(expr.T for expr in expressions))
- ).T
-
-def block_diag(
- expressions: tuple[Expression],
-):
- return init_expression(
- init_block_diag_expr(expressions)
- )
-
-def eye(
- variable: tuple[Expression],
-):
- return init_expression(
- init_eye_expr(variable=variable)
- )
-
-def kkt_equality(
- variables: Expression,
- equality: Expression = None,
-):
-
- self_variables = variables
- self_equality = equality
-
- def func(state: ExpressionState):
-
- state, equality = self_equality.apply(state=state)
-
- state, equality_der = self_equality.diff(
- self_variables,
- introduce_derivatives=True,
- ).apply(state)
-
- def acc_nu_variables(acc, v):
- state, nu_variables = acc
-
- nu_variable = state.n_param
- state = state.register(n_param=1)
-
- return state, nu_variables + [nu_variable]
-
- *_, (state, nu_variables) = tuple(itertools.accumulate(
- range(equality.shape[0]),
- acc_nu_variables,
- initial=(state, []),
- ))
-
- terms = {}
-
- for row in range(equality_der.shape[1]):
-
- monomial_terms = collections.defaultdict(float)
-
- for eq_idx, nu_variable in enumerate(nu_variables):
-
- underlying_terms = equality_der.get_poly(eq_idx, row)
- if underlying_terms is None:
- continue
+from polymatrix.expressionstate.expressionstate import ExpressionState as internal_ExpressionState
+from polymatrix.expressionstate.init.initexpressionstate 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.from_ import from_sympy as internal_from_sympy
+from polymatrix.expression import v_stack as internal_v_stack
+from polymatrix.expression import h_stack as internal_h_stack
+from polymatrix.expression import product as internal_product
+from polymatrix.denserepr.from_ import from_polymatrix_expr
+from polymatrix.expression.to import shape as internal_shape
+from polymatrix.expression.to import to_constant_repr as internal_to_constant_repr
+from polymatrix.expression.to import to_degrees as internal_to_degrees
+from polymatrix.expression.to import to_sympy_repr as internal_to_sympy_repr
+
+Expression = internal_Expression
+ExpressionState = internal_ExpressionState
+
+init_expression_state = internal_init_expression_state
+from_ = internal_from
+# from_sympy = internal_from_sympy
+v_stack = internal_v_stack
+h_stack = internal_h_stack
+product = internal_product
+to_shape = internal_shape
+to_constant_repr = internal_to_constant_repr
+to_degrees = internal_to_degrees
+to_sympy_repr = internal_to_sympy_repr
+to_matrix_repr = from_polymatrix_expr
+
+# def from_sympy(
+# data: tuple[tuple[float]],
+# ):
+# return init_expression(
+# init_from_sympy_expr(data)
+# )
+
+# def from_state_monad(
+# data: StateMonad,
+# ):
+# return init_expression(
+# data.flat_map(lambda inner_data: init_from_sympy_expr(inner_data)),
+# )
+
+# def from_polymatrix(
+# polymatrix: PolyMatrix,
+# ):
+# return init_expression(
+# init_from_terms_expr(polymatrix)
+# )
+
+# def from_(
+# data: str | tuple[tuple[float]],
+# ):
+# if isinstance(data, str):
+# return from_(1).parametrize(data)
+
+# return from_sympy(data)
+
+# def v_stack(
+# expressions: tuple[Expression],
+# ):
+# return init_expression(
+# init_v_stack_expr(expressions)
+# )
+
+# def h_stack(
+# expressions: tuple[Expression],
+# ):
+# return init_expression(
+# init_v_stack_expr(tuple(expr.T for expr in expressions))
+# ).T
+
+# def block_diag(
+# expressions: tuple[Expression],
+# ):
+# return init_expression(
+# init_block_diag_expr(expressions)
+# )
+
+# def eye(
+# variable: tuple[Expression],
+# ):
+# return init_expression(
+# init_eye_expr(variable=variable)
+# )
+
+# def kkt_equality(
+# equality: Expression,
+# variables: Expression,
+# name: str,
+# ):
+# equality_der = equality.diff(
+# variables,
+# introduce_derivatives=True,
+# )
+
+# nu = equality_der[0, :].T.parametrize(name)
+
+# return nu, equality_der @ nu
+
+# def kkt_inequality(
+# inequality: Expression,
+# variables: Expression,
+# name: str,
+# ):
+
+# inequality_der = inequality.diff(
+# variables,
+# introduce_derivatives=True,
+# )
+
+# nu = inequality_der[0, :].T.parametrize(f'lambda_{name}')
+# r_nu = inequality_der[0, :].T.parametrize(f'r_lambda_{name}')
+# r_ineq = inequality_der[0, :].T.parametrize(f'r_ineq_{name}')
+
+# prim_expr = inequality - r_ineq * r_ineq
+
+# sec_expr = nu - r_nu * r_nu
+
+# compl_expr = nu * inequality
+
+# cost_expr = inequality_der @ nu
+
+# return h_stack((nu, r_nu, r_ineq)), (cost_expr, prim_expr, sec_expr, compl_expr)
+
+
+# def rows(
+# expr: Expression,
+# ) -> StateMonadMixin[ExpressionState, np.ndarray]:
+
+# def func(state: ExpressionState):
+# state, underlying = expr.apply(state)
+
+# def gen_row_terms():
+# for row in range(underlying.shape[0]):
- for monomial, value in underlying_terms.items():
- new_monomial = monomial + (nu_variable,)
+# terms = {}
- monomial_terms[new_monomial] += value
+# for col in range(underlying.shape[1]):
+# polynomial = underlying.get_poly(row, col)
+# if polynomial == None:
+# continue
- # terms[row, 0] = dict(monomial_terms)
- terms[row, 0] = monomial_terms
+# terms[0, col] = polynomial
- cost_expr = init_expression(init_from_terms_expr(
- terms=terms,
- shape=(equality_der.shape[1], 1),
- ))
+# yield init_expression(underlying=init_from_terms_expr(
+# terms=terms,
+# shape=(1, underlying.shape[1])
+# ))
- nu_terms = {}
+# row_terms = tuple(gen_row_terms())
- for eq_idx, nu_variable in enumerate(nu_variables):
- nu_terms[eq_idx, 0] = {(nu_variable,): 1}
+# return state, row_terms
- nu_expr = init_expression(init_from_terms_expr(
- terms=nu_terms,
- shape=(len(nu_variables), 1),
- ))
+# return init_state_monad(func)
- return state, (nu_expr, cost_expr)
- return init_state_monad(func)
+# @dataclasses.dataclass
+# class MatrixBuffer:
+# data: dict[int, np.ndarray]
+# n_row: int
+# n_param: int
-def kkt_inequality(
- variables: Expression,
- inequality: Expression = None,
-):
+# def get_max_degree(self):
+# return max(degree for degree in self.data.keys())
- self_variables = variables
- self_inequality = inequality
+# def add_buffer(self, index: int):
+# if index <= 1:
+# buffer = np.zeros((self.n_row, self.n_param**index), dtype=np.double)
- def func(state: ExpressionState):
-
- state, inequality = self_inequality.apply(state=state)
-
- state, inequality_der = self_inequality.diff(
- self_variables,
- introduce_derivatives=True,
- ).apply(state)
-
- def acc_lambda_variables(acc, v):
- state, lambda_variables = acc
-
- lambda_variable = state.n_param
- state = state.register(n_param=3)
+# else:
+# buffer = scipy.sparse.dok_array((self.n_row, self.n_param**index), dtype=np.double)
- return state, lambda_variables + [lambda_variable]
-
- *_, (state, lambda_variables) = tuple(itertools.accumulate(
- range(inequality.shape[0]),
- acc_lambda_variables,
- initial=(state, []),
- ))
-
- terms = {}
-
- for row in range(inequality_der.shape[1]):
-
- monomial_terms = collections.defaultdict(float)
-
- for inequality_idx, lambda_variable in enumerate(lambda_variables):
-
- polynomial = inequality_der.get_poly(inequality_idx, row)
- if polynomial is None:
- continue
-
- for monomial, value in polynomial.items():
- new_monomial = monomial + (lambda_variable,)
-
- monomial_terms[new_monomial] += value
-
- # terms[row, 0] = dict(monomial_terms)
- terms[row, 0] = monomial_terms
-
- cost_expr = init_expression(init_from_terms_expr(
- terms=terms,
- shape=(inequality_der.shape[1], 1),
- ))
-
- # inequality, dual feasibility, complementary slackness
- # -----------------------------------------------------
-
- inequality_terms = {}
- feasibility_terms = {}
- complementary_terms = {}
-
- for inequality_idx, lambda_variable in enumerate(lambda_variables):
- r_lambda = lambda_variable + 1
- r_inequality = lambda_variable + 2
-
- polynomial = inequality.get_poly(inequality_idx, 0)
- if polynomial is None:
- continue
-
- # f(x) <= -0.01
- inequality_terms[inequality_idx, 0] = polynomial | {(r_inequality, r_inequality): 1}
-
- # dual feasibility, lambda >= 0
- feasibility_terms[inequality_idx, 0] = {(lambda_variable,): 1, (r_lambda, r_lambda): -1}
+# self.data[index] = buffer
- # complementary slackness
- complementary_terms[inequality_idx, 0] = {(r_lambda, r_inequality): 1}
+# def add(self, row: int, col: int, index: int, value: float):
+# if index not in self.data:
+# self.add_buffer(index)
- inequality_expr = init_expression(init_from_terms_expr(
- terms=inequality_terms,
- shape=(len(lambda_variables), 1),
- ))
+# self.data[index][row, col] = value
- feasibility_expr = init_expression(init_from_terms_expr(
- terms=feasibility_terms,
- shape=(len(lambda_variables), 1),
- ))
+# def __getitem__(self, key):
+# if key not in self.data:
+# self.add_buffer(key)
- complementary_expr = init_expression(init_from_terms_expr(
- terms=complementary_terms,
- shape=(len(lambda_variables), 1),
- ))
+# return self.data[key]
- # lambda expression
- # -----------------
- terms = {}
- for inequality_idx, lambda_variable in enumerate(lambda_variables):
- terms[inequality_idx, 0] = {(lambda_variable,): 1}
+# @dataclasses.dataclass
+# class MatrixRepresentations:
+# data: tuple[MatrixBuffer, ...]
+# aux_data: typing.Optional[MatrixBuffer]
+# variable_mapping: tuple[int, ...]
+# state: ExpressionState
- lambda_expr = init_expression(init_from_terms_expr(
- terms=terms,
- shape=(len(lambda_variables), 1),
- ))
+# def merge_matrix_equations(self):
+# def gen_matrices(index: int):
+# for equations in self.data:
+# if index < len(equations):
+# yield equations[index]
- return state, (lambda_expr, cost_expr, inequality_expr, feasibility_expr, complementary_expr)
+# if index < len(self.aux_data):
+# yield self.aux_data[index]
- return init_state_monad(func)
+# indices = set(key for equations in self.data + (self.aux_data,) for key in equations.keys())
-def rows(
- expr: Expression,
-) -> StateMonadMixin[ExpressionState, np.ndarray]:
+# def gen_matrices():
+# for index in indices:
+# if index <= 1:
+# yield index, np.vstack(tuple(gen_matrices(index)))
+# else:
+# yield index, scipy.sparse.vstack(tuple(gen_matrices(index)))
- def func(state: ExpressionState):
- state, underlying = expr.apply(state)
+# return dict(gen_matrices())
- def gen_row_terms():
- for row in range(underlying.shape[0]):
+# def get_value(self, variable, value):
+# variable_indices = get_variable_indices_from_variable(self.state, variable)[1]
- terms = {}
+# def gen_value_index():
+# for variable_index in variable_indices:
+# try:
+# yield self.variable_mapping.index(variable_index)
+# except ValueError:
+# raise ValueError(f'{variable_index} not found in {self.variable_mapping}')
- for col in range(underlying.shape[1]):
- polynomial = underlying.get_poly(row, col)
- if polynomial == None:
- continue
+# value_index = list(gen_value_index())
- terms[0, col] = polynomial
+# return value[value_index]
- yield init_expression(underlying=init_from_terms_expr(
- terms=terms,
- shape=(1, underlying.shape[1])
- ))
+# 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)
+# vec = np.zeros(len(self.variable_mapping))
+# vec[value_index] = value
+# return vec
- row_terms = tuple(gen_row_terms())
+# # def get_matrix(self, eq_idx: int):
+# # equations = self.data[eq_idx].data
- return state, row_terms
+# def get_func(self, eq_idx: int):
+# equations = self.data[eq_idx].data
+# max_idx = max(equations.keys())
- return init_state_monad(func)
+# 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)
-def shape(
- expr: Expression,
-) -> StateMonadMixin[ExpressionState, tuple[int, ...]]:
- def func(state: ExpressionState):
- state, polymatrix = expr.apply(state)
+# elif x.shape[0] == 1:
+# x = x.reshape(-1, 1)
- return state, polymatrix.shape
+# def acc_x_powers(acc, _):
+# next = (acc @ x.T).reshape(-1, 1)
+# return next
- return init_state_monad(func)
+# x_powers = tuple(itertools.accumulate(
+# range(max_idx - 1),
+# acc_x_powers,
+# initial=x,
+# ))[1:]
+# def gen_value():
+# for idx, equation in equations.items():
+# if idx == 0:
+# yield equation
-@dataclasses.dataclass
-class MatrixBuffer:
- data: dict[int, np.ndarray]
- n_row: int
- n_param: int
+# elif idx == 1:
+# yield equation @ x
- def get_max_degree(self):
- return max(degree for degree in self.data.keys())
+# else:
+# yield equation @ x_powers[idx-2]
- def add_buffer(self, index: int):
- if index <= 1:
- buffer = np.zeros((self.n_row, self.n_param**index), dtype=np.double)
+# return sum(gen_value())
- else:
- buffer = scipy.sparse.dok_array((self.n_row, self.n_param**index), dtype=np.double)
+# else:
+# def func(x: np.ndarray) -> np.ndarray:
+# if isinstance(x, tuple) or isinstance(x, list):
+# x = np.array(x).reshape(-1, 1)
- self.data[index] = buffer
-
- def add(self, row: int, col: int, index: int, value: float):
- if index not in self.data:
- self.add_buffer(index)
-
- self.data[index][row, col] = value
-
- def __getitem__(self, key):
- if key not in self.data:
- self.add_buffer(key)
-
- return self.data[key]
-
-
-@dataclasses.dataclass
-class MatrixRepresentations:
- data: tuple[MatrixBuffer, ...]
- aux_data: typing.Optional[MatrixBuffer]
- variable_mapping: tuple[int, ...]
- state: ExpressionState
-
- def merge_matrix_equations(self):
- def gen_matrices(index: int):
- for equations in self.data:
- if index < len(equations):
- yield equations[index]
-
- 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())
-
- def gen_matrices():
- for index in indices:
- if index <= 1:
- yield index, np.vstack(tuple(gen_matrices(index)))
- else:
- yield index, scipy.sparse.vstack(tuple(gen_matrices(index)))
-
- return dict(gen_matrices())
-
- def get_value(self, variable, value):
- variable_indices = get_variable_indices_from_variable(self.state, variable)[1]
-
- def gen_value_index():
- for variable_index in variable_indices:
- try:
- yield self.variable_mapping.index(variable_index)
- except ValueError:
- raise ValueError(f'{variable_index} not found in {self.variable_mapping}')
-
- value_index = list(gen_value_index())
-
- return value[value_index]
-
- 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)
- vec = np.zeros(len(self.variable_mapping))
- vec[value_index] = value
- return vec
-
- def get_func(self, eq_idx: int):
- equations = self.data[eq_idx].data
- 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)
-
- elif x.shape[0] == 1:
- x = x.reshape(-1, 1)
-
- def acc_x_powers(acc, _):
- next = (acc @ x.T).reshape(-1, 1)
- return next
-
- x_powers = tuple(itertools.accumulate(
- range(max_idx - 1),
- acc_x_powers,
- initial=x,
- ))[1:]
-
- def gen_value():
- for idx, equation in equations.items():
- if idx == 0:
- yield equation
-
- elif idx == 1:
- yield equation @ x
-
- else:
- yield equation @ x_powers[idx-2]
-
- return sum(gen_value())
-
- else:
- def func(x: np.ndarray) -> np.ndarray:
- def gen_value():
- for idx, equation in equations.items():
- if idx == 0:
- yield equation
+# def gen_value():
+# for idx, equation in equations.items():
+# if idx == 0:
+# yield equation
- else:
- yield equation @ x
+# else:
+# yield equation @ x
- return sum(gen_value())
+# return sum(gen_value())
- return func
+# return func
-def to_matrix_repr(
- expressions: Expression | tuple[Expression],
- variables: Expression = None,
- sorted: bool = None,
-) -> StateMonadMixin[ExpressionState, tuple[tuple[tuple[np.ndarray, ...], ...], tuple[int, ...]]]:
+# def to_matrix_repr(
+# expressions: Expression | tuple[Expression],
+# variables: Expression = None,
+# sorted: bool = None,
+# ) -> StateMonadMixin[ExpressionState, tuple[tuple[tuple[np.ndarray, ...], ...], tuple[int, ...]]]:
- if isinstance(expressions, Expression):
- expressions = (expressions,)
+# 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 func(state: ExpressionState):
- def acc_underlying_application(acc, v):
- state, underlying_list = acc
+# def acc_underlying_application(acc, v):
+# state, underlying_list = acc
- state, underlying = v.apply(state)
+# 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,)
+# 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()
+# if variables is None:
+# sorted_variable_index = tuple()
- else:
- state, variable_index = get_variable_indices_from_variable(state, variables)
+# 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)
+# if sorted:
+# 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
+# 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.')
+# 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.')
- variable_index_map = {old: new for new, old in enumerate(sorted_variable_index)}
+# variable_index_map = {old: new for new, old in enumerate(sorted_variable_index)}
- n_param = len(sorted_variable_index)
+# n_param = len(sorted_variable_index)
- def gen_numpy_matrices():
- for polymatrix in polymatrix_list:
+# def gen_numpy_matrices():
+# for polymatrix in polymatrix_list:
- n_row = polymatrix.shape[0]
+# n_row = polymatrix.shape[0]
- buffer = MatrixBuffer(
- data={},
- n_row=n_row,
- n_param=n_param,
- )
+# buffer = MatrixBuffer(
+# data={},
+# n_row=n_row,
+# n_param=n_param,
+# )
- for row in range(n_row):
- polymatrix_terms = polymatrix.get_poly(row, 0)
+# for row in range(n_row):
+# polymatrix_terms = polymatrix.get_poly(row, 0)
- if polymatrix_terms is None:
- continue
+# if polymatrix_terms is None:
+# continue
- if len(polymatrix_terms) == 0:
- buffer.add(row, 0, 0, 0)
+# if len(polymatrix_terms) == 0:
+# buffer.add(row, 0, 0, 0)
- else:
- for monomial, value in polymatrix_terms.items():
+# else:
+# for monomial, value in polymatrix_terms.items():
- def gen_new_monomial():
- for var, count in monomial:
- try:
- index = variable_index_map[var]
- except KeyError:
- raise KeyError(f'{var=} ({state.get_key_from_offset(var)}) is incompatible with {variable_index_map=}')
+# def gen_new_monomial():
+# for var, count in monomial:
+# try:
+# index = variable_index_map[var]
+# except KeyError:
+# raise KeyError(f'{var=} ({state.get_key_from_offset(var)}) is incompatible with {variable_index_map=}')
- for _ in range(count):
- yield index
+# for _ in range(count):
+# yield index
- new_monomial = tuple(gen_new_monomial())
+# new_monomial = tuple(gen_new_monomial())
- cols = monomial_to_index(n_param, new_monomial)
+# cols = monomial_to_index(n_param, new_monomial)
- col_value = value / len(cols)
+# col_value = value / len(cols)
- for col in cols:
- buffer.add(row, col, sum(count for _, count in monomial), col_value)
+# for col in cols:
+# degree = sum(count for _, count in monomial)
+# buffer.add(row, col, degree, col_value)
- yield buffer
+# yield buffer
- underlying_matrices = tuple(gen_numpy_matrices())
+# underlying_matrices = tuple(gen_numpy_matrices())
- def gen_auxillary_equations():
- for key, monomial_terms in state.auxillary_equations.items():
- if key in sorted_variable_index:
- yield key, monomial_terms
+# def gen_auxillary_equations():
+# for key, monomial_terms in state.auxillary_equations.items():
+# if key in sorted_variable_index:
+# yield key, monomial_terms
- auxillary_equations = tuple(gen_auxillary_equations())
+# auxillary_equations = tuple(gen_auxillary_equations())
- n_row = len(auxillary_equations)
+# n_row = len(auxillary_equations)
- if n_row == 0:
- auxillary_matrix_equations = None
+# if n_row == 0:
+# auxillary_matrix_equations = None
- else:
- buffer = MatrixBuffer(
- data={},
- n_row=n_row,
- n_param=n_param,
- )
+# else:
+# buffer = MatrixBuffer(
+# data={},
+# n_row=n_row,
+# n_param=n_param,
+# )
- 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))
+# 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))
- cols = monomial_to_index(n_param, new_monomial)
+# cols = monomial_to_index(n_param, new_monomial)
- col_value = value / len(cols)
+# col_value = value / len(cols)
- for col in cols:
- buffer.add(row, col, sum(count for _, count in monomial), col_value)
+# for col in cols:
+# buffer.add(row, col, sum(count for _, count in monomial), col_value)
- auxillary_matrix_equations = buffer
+# auxillary_matrix_equations = buffer
- result = MatrixRepresentations(
- data=underlying_matrices,
- aux_data=auxillary_matrix_equations,
- variable_mapping=sorted_variable_index,
- state=state,
- )
+# result = MatrixRepresentations(
+# data=underlying_matrices,
+# aux_data=auxillary_matrix_equations,
+# variable_mapping=sorted_variable_index,
+# state=state,
+# )
- return state, result
+# return state, result
- return init_state_monad(func)
+# return init_state_monad(func)
-def to_constant_repr(
- expr: Expression,
- assert_constant: bool = True,
-) -> StateMonadMixin[ExpressionState, np.ndarray]:
+# def to_constant_repr(
+# expr: Expression,
+# assert_constant: bool = True,
+# ) -> StateMonadMixin[ExpressionState, np.ndarray]:
- def func(state: ExpressionState):
- state, underlying = expr.apply(state)
+# def func(state: ExpressionState):
+# state, underlying = expr.apply(state)
- A = np.zeros(underlying.shape, dtype=np.double)
+# A = np.zeros(underlying.shape, dtype=np.double)
- for (row, col), polynomial in underlying.gen_terms():
- for monomial, value in polynomial.items():
- if len(monomial) == 0:
- A[row, col] = value
+# for (row, col), polynomial in underlying.gen_terms():
+# for monomial, value in polynomial.items():
+# if len(monomial) == 0:
+# A[row, col] = value
- elif assert_constant:
- raise Exception(f'non-constant term {monomial=}')
+# elif assert_constant:
+# raise Exception(f'non-constant term {monomial=}')
- return state, A
+# return state, A
- return init_state_monad(func)
+# return init_state_monad(func)
-def degrees(
- expr: Expression,
- variables: Expression,
-) -> StateMonadMixin[ExpressionState, np.ndarray]:
+# def 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 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_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)
+# def gen_degrees():
+# polynomial = underlying.get_poly(row, col)
- if polynomial is None:
- yield 0
+# 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)
+# 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(set(gen_degrees()))
- yield tuple(gen_cols())
+# yield tuple(gen_cols())
- return state, tuple(gen_rows())
+# return state, tuple(gen_rows())
- return init_state_monad(func)
+# return init_state_monad(func)
-def to_sympy_repr(
- expr: Expression,
-) -> StateMonadMixin[ExpressionState, sympy.Expr]:
+# def to_sympy_repr(
+# expr: Expression,
+# ) -> StateMonadMixin[ExpressionState, sympy.Expr]:
- def func(state: ExpressionState):
- state, underlying = expr.apply(state)
+# def func(state: ExpressionState):
+# state, underlying = expr.apply(state)
- A = np.zeros(underlying.shape, dtype=object)
+# A = np.zeros(underlying.shape, dtype=object)
- for (row, col), polynomial in underlying.gen_terms():
+# for (row, col), polynomial in underlying.gen_terms():
- sympy_polynomial = 0
+# sympy_polynomial = 0
- for monomial, value in polynomial.items():
- sympy_monomial = 1
+# for monomial, value in polynomial.items():
+# sympy_monomial = 1
- for offset, count in monomial:
+# 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=}'
+# 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=}'
- if isinstance(variable, sympy.core.symbol.Symbol):
- variable_name = variable.name
- elif isinstance(variable, (ParametrizeExprMixin, ParametrizeMatrixExprMixin)):
- variable_name = variable.name
- elif isinstance(variable, str):
- variable_name = variable
- else:
- raise Exception(f'{variable=}')
+# if isinstance(variable, sympy.core.symbol.Symbol):
+# variable_name = variable.name
+# elif isinstance(variable, (ParametrizeExprMixin, ParametrizeMatrixExprMixin)):
+# variable_name = variable.name
+# elif isinstance(variable, str):
+# variable_name = variable
+# else:
+# raise Exception(f'{variable=}')
- start, end = state.offset_dict[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}')
+# if end - start == 1:
+# sympy_var = sympy.Symbol(variable_name)
+# else:
+# sympy_var = sympy.Symbol(f'{variable_name}_{offset - start + 1}')
- # var = get_variable_from_offset(offset)
- sympy_monomial *= sympy_var**count
+# # var = get_variable_from_offset(offset)
+# sympy_monomial *= sympy_var**count
- sympy_polynomial += value * sympy_monomial
+# sympy_polynomial += value * sympy_monomial
- A[row, col] = sympy_polynomial
+# A[row, col] = sympy_polynomial
- return state, A
+# return state, A
- return init_state_monad(func)
+# return init_state_monad(func)
diff --git a/polymatrix/expression/init/__init__.py b/polymatrix/denserepr/__init__.py
index e69de29..e69de29 100644
--- a/polymatrix/expression/init/__init__.py
+++ b/polymatrix/denserepr/__init__.py
diff --git a/polymatrix/denserepr/from_.py b/polymatrix/denserepr/from_.py
new file mode 100644
index 0000000..52fda35
--- /dev/null
+++ b/polymatrix/denserepr/from_.py
@@ -0,0 +1,156 @@
+import dataclasses
+import itertools
+import typing
+import numpy as np
+import scipy.sparse
+from polymatrix.denserepr.impl import DenseReprBufferImpl, DenseReprImpl
+
+from polymatrix.expression.expression import Expression
+from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
+from polymatrix.expressionstate.expressionstate import ExpressionState
+from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable
+from polymatrix.statemonad.init.initstatemonad import init_state_monad
+from polymatrix.statemonad.mixins.statemonadmixin import StateMonadMixin
+from polymatrix.expression.utils.monomialtoindex import monomial_to_index
+
+
+def from_polymatrix_expr(
+ expressions: Expression | tuple[Expression],
+ variables: Expression = None,
+ sorted: bool = None,
+) -> 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=}'
+
+ 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'
+
+ return state, underlying_list + (underlying,)
+
+ *_, (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)
+
+ 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.')
+
+ 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(
+ data={},
+ n_row=n_row,
+ n_param=n_param,
+ )
+
+ 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():
+
+ def gen_new_monomial():
+ for var, count in monomial:
+ try:
+ index = variable_index_map[var]
+ except KeyError:
+ raise KeyError(f'{var=} ({state.get_key_from_offset(var)}) is incompatible with {variable_index_map=}')
+
+ for _ in range(count):
+ yield index
+
+ new_monomial = tuple(gen_new_monomial())
+
+ cols = monomial_to_index(n_param, new_monomial)
+
+ 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())
+
+ def gen_auxillary_equations():
+ for key, monomial_terms in state.auxillary_equations.items():
+ if key in sorted_variable_index:
+ yield key, monomial_terms
+
+ auxillary_equations = tuple(gen_auxillary_equations())
+
+ n_row = len(auxillary_equations)
+
+ if n_row == 0:
+ auxillary_matrix_equations = None
+
+ else:
+ buffer = DenseReprBufferImpl(
+ data={},
+ n_row=n_row,
+ n_param=n_param,
+ )
+
+ 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))
+
+ cols = monomial_to_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)
+
+ auxillary_matrix_equations = buffer
+
+ result = DenseReprImpl(
+ data=underlying_matrices,
+ aux_data=auxillary_matrix_equations,
+ variable_mapping=sorted_variable_index,
+ state=state,
+ )
+
+ return state, result
+
+ return init_state_monad(func) \ No newline at end of file
diff --git a/polymatrix/denserepr/impl.py b/polymatrix/denserepr/impl.py
new file mode 100644
index 0000000..2b57e2a
--- /dev/null
+++ b/polymatrix/denserepr/impl.py
@@ -0,0 +1,143 @@
+import dataclasses
+import itertools
+import typing
+import numpy as np
+import scipy.sparse
+
+from polymatrix.expressionstate.expressionstate import ExpressionState
+from polymatrix.expression.utils.getvariableindices import get_variable_indices_from_variable
+
+
+@dataclasses.dataclass
+class DenseReprBufferImpl:
+ data: dict[int, np.ndarray]
+ n_row: int
+ n_param: int
+
+ def get_max_degree(self):
+ return max(degree for degree in self.data.keys())
+
+ def add_buffer(self, index: int):
+ if index <= 1:
+ 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)
+
+ self.data[index] = buffer
+
+ def add(self, row: int, col: int, index: int, value: float):
+ if index not in self.data:
+ self.add_buffer(index)
+
+ self.data[index][row, col] = value
+
+ def __getitem__(self, key):
+ if key not in self.data:
+ self.add_buffer(key)
+
+ return self.data[key]
+
+
+@dataclasses.dataclass
+class DenseReprImpl:
+ data: tuple[DenseReprBufferImpl, ...]
+ aux_data: typing.Optional[DenseReprBufferImpl]
+ variable_mapping: tuple[int, ...]
+ state: ExpressionState
+
+ def merge_matrix_equations(self):
+ def gen_matrices(index: int):
+ for equations in self.data:
+ if index < len(equations):
+ yield equations[index]
+
+ 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())
+
+ def gen_matrices():
+ for index in indices:
+ if index <= 1:
+ yield index, np.vstack(tuple(gen_matrices(index)))
+ else:
+ yield index, scipy.sparse.vstack(tuple(gen_matrices(index)))
+
+ return dict(gen_matrices())
+
+ def get_value(self, variable, value):
+ variable_indices = get_variable_indices_from_variable(self.state, variable)[1]
+
+ def gen_value_index():
+ for variable_index in variable_indices:
+ try:
+ yield self.variable_mapping.index(variable_index)
+ except ValueError:
+ raise ValueError(f'{variable_index} not found in {self.variable_mapping}')
+
+ value_index = list(gen_value_index())
+
+ return value[value_index]
+
+ 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)
+ vec = np.zeros(len(self.variable_mapping))
+ vec[value_index] = value
+ return vec
+
+ # def get_matrix(self, eq_idx: int):
+ # equations = self.data[eq_idx].data
+
+ def get_func(self, eq_idx: int):
+ equations = self.data[eq_idx].data
+ 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)
+
+ elif x.shape[0] == 1:
+ x = x.reshape(-1, 1)
+
+ def acc_x_powers(acc, _):
+ next = (acc @ x.T).reshape(-1, 1)
+ return next
+
+ x_powers = tuple(itertools.accumulate(
+ range(max_idx - 1),
+ acc_x_powers,
+ initial=x,
+ ))[1:]
+
+ def gen_value():
+ for idx, equation in equations.items():
+ if idx == 0:
+ yield equation
+
+ elif idx == 1:
+ yield equation @ x
+
+ else:
+ 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:
+ yield equation
+
+ else:
+ yield equation @ x
+
+ return sum(gen_value())
+
+ return func \ No newline at end of file
diff --git a/polymatrix/expression/__init__.py b/polymatrix/expression/__init__.py
index e69de29..75704ff 100644
--- a/polymatrix/expression/__init__.py
+++ b/polymatrix/expression/__init__.py
@@ -0,0 +1,52 @@
+import polymatrix.expression.from_
+import polymatrix.expression.implexpressionbase
+
+from collections.abc import Iterable
+
+from polymatrix.utils.getstacklines import get_stack_lines
+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.implexpressionbase.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:
+ return init_expression(
+ underlying=polymatrix.expression.implexpressionbase.BlockDiagExprImpl(
+ underlying=expressions,
+ )
+ )
+
+def product(
+ expressions: Iterable[Expression],
+ degrees: tuple[int, ...] = None,
+):
+ return init_expression(
+ underlying=polymatrix.expression.implexpressionbase.ProductExprImpl(
+ underlying=tuple(expressions),
+ degrees=degrees,
+ stack=get_stack_lines(),
+ )
+ )
+
diff --git a/polymatrix/expression/expression.py b/polymatrix/expression/expression.py
index 25a8c9b..ca7d474 100644
--- a/polymatrix/expression/expression.py
+++ b/polymatrix/expression/expression.py
@@ -4,48 +4,12 @@ import dataclassabc
import typing
import numpy as np
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-from polymatrix.expression.init.initadditionexpr import init_addition_expr
-from polymatrix.expression.init.initcacheexpr import init_cache_expr
-from polymatrix.expression.init.initcombinationsexpr import init_combinations_expr
-from polymatrix.expression.init.initderivativeexpr import init_derivative_expr
-from polymatrix.expression.init.initdeterminantexpr import init_determinant_expr
-from polymatrix.expression.init.initdivergenceexpr import init_divergence_expr
-from polymatrix.expression.init.initdivisionexpr import init_division_expr
-from polymatrix.expression.init.initelemmultexpr import init_elem_mult_expr
-from polymatrix.expression.init.initevalexpr import init_eval_expr
-from polymatrix.expression.init.initfilterexpr import init_filter_expr
-from polymatrix.expression.init.initfromsymmetricmatrixexpr import init_from_symmetric_matrix_expr
-from polymatrix.expression.init.inithalfnewtonpolytopeexpr import init_half_newton_polytope_expr
-from polymatrix.expression.init.initlinearinexpr import init_linear_in_expr
-from polymatrix.expression.init.initfromsympyexpr import init_from_expr_or_none, init_from_sympy_expr
-from polymatrix.expression.init.initgetitemexpr import init_get_item_expr
-from polymatrix.expression.init.initlinearmatrixinexpr import init_linear_matrix_in_expr
-from polymatrix.expression.init.initlinearmonomialsexpr import init_linear_monomials_expr
-from polymatrix.expression.init.initmatrixmultexpr import init_matrix_mult_expr
-from polymatrix.expression.init.initmaxdegreeexpr import init_max_degree_expr
-from polymatrix.expression.init.initmaxexpr import init_max_expr
-from polymatrix.expression.init.initparametrizeexpr import init_parametrize_expr
-from polymatrix.expression.init.initparametrizematrixexpr import init_parametrize_matrix_expr
-from polymatrix.expression.init.initquadraticinexpr import init_quadratic_in_expr
-from polymatrix.expression.init.initrepmatexpr import init_rep_mat_expr
-from polymatrix.expression.init.initreshapeexpr import init_reshape_expr
-from polymatrix.expression.init.initsetelementatexpr import init_set_element_at_expr
-from polymatrix.expression.init.initquadraticmonomialsexpr import init_quadratic_monomials_expr
-from polymatrix.expression.init.initsqueezeexpr import init_squeeze_expr
-from polymatrix.expression.init.initsubstituteexpr import init_substitute_expr
-from polymatrix.expression.init.initsubtractmonomialsexpr import init_subtract_monomials_expr
-from polymatrix.expression.init.initsumexpr import init_sum_expr
-from polymatrix.expression.init.initsymmetricexpr import init_symmetric_expr
-from polymatrix.expression.init.inittoconstantexpr import init_to_constant_expr
-from polymatrix.expression.init.inittoquadraticexpr import init_to_quadratic_expr
-from polymatrix.expression.init.initdiagexpr import init_diag_expr
-from polymatrix.expression.init.inittosortedvariables import init_to_sorted_variables
-from polymatrix.expression.init.inittosymmetricmatrixexpr import init_to_symmetric_matrix_expr
-from polymatrix.expression.init.inittransposeexpr import init_transpose_expr
-from polymatrix.expression.init.inittruncateexpr import init_truncate_expr
+import polymatrix.expression.initexpressionbase
+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, linear_in, linear_monomials, legendre
from polymatrix.polymatrix.polymatrix import PolyMatrix
from polymatrix.expressionstate.expressionstate import ExpressionState
@@ -65,7 +29,7 @@ class Expression(
return self.underlying.apply(state)
def __add__(self, other: ExpressionBaseMixin) -> 'Expression':
- return self._binary(init_addition_expr, self, other)
+ return self._binary(polymatrix.expression.initexpressionbase.init_addition_expr, self, other)
def __getattr__(self, name):
attr = getattr(self.underlying, name)
@@ -82,17 +46,17 @@ class Expression(
def __getitem__(self, key: tuple[int, int]):
return dataclasses.replace(
self,
- underlying=init_get_item_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_get_item_expr(
underlying=self.underlying,
index=key,
),
)
def __matmul__(self, other: typing.Union[ExpressionBaseMixin, np.ndarray]) -> 'Expression':
- return self._binary(init_matrix_mult_expr, self, other)
+ return self._binary(polymatrix.expression.initexpressionbase.init_matrix_mult_expr, self, other)
def __mul__(self, other) -> 'Expression':
- return self._binary(init_elem_mult_expr, self, other)
+ return self._binary(polymatrix.expression.initexpressionbase.init_elem_mult_expr, self, other)
def __pow__(self, num):
curr = 1
@@ -106,10 +70,10 @@ class Expression(
return self * (-1)
def __radd__(self, other):
- return self._binary(init_addition_expr, other, self)
+ return self._binary(polymatrix.expression.initexpressionbase.init_addition_expr, other, self)
def __rmatmul__(self, other):
- return self._binary(init_matrix_mult_expr, other, self)
+ return self._binary(polymatrix.expression.initexpressionbase.init_matrix_mult_expr, other, self)
def __rmul__(self, other):
return self * other
@@ -121,30 +85,37 @@ class Expression(
return self + (-other)
def __truediv__(self, other: ExpressionBaseMixin):
- return self._binary(init_division_expr, self, other)
+ return self._binary(polymatrix.expression.initexpressionbase.init_division_expr, self, other)
+
+ @abc.abstractmethod
+ def copy(self, underlying: ExpressionBaseMixin) -> 'Expression':
+ ...
@staticmethod
def _binary(op, left, right):
- if not isinstance(left, Expression):
- left = init_from_expr_or_none(left)
- if left is None:
+ stack = get_stack_lines()
+
+ if isinstance(left, Expression):
+ right = polymatrix.expression.initexpressionbase.init_from_expr_or_none(right)
+
+ # delegate to upper level
+ if right is None:
return NotImplemented
- return dataclasses.replace(
- right,
- underlying=op(left, right),
+ return left.copy(
+ underlying=op(left, right, stack),
)
else:
- right = init_from_expr_or_none(right)
-
- if right is None:
+ left = polymatrix.expression.initexpressionbase.init_from_expr_or_none(left)
+
+ # delegate to upper level
+ if left is None:
return NotImplemented
- return dataclasses.replace(
- left,
- underlying=op(left, right),
+ return right.copy(
+ underlying=op(left, right, stack),
)
# def _convert_to_expression(self, other):
@@ -156,27 +127,27 @@ class Expression(
# return result
def cache(self) -> 'Expression':
- return dataclasses.replace(
- self,
- underlying=init_cache_expr(
+ return self.copy(
+ underlying=polymatrix.expression.initexpressionbase.init_cache_expr(
underlying=self.underlying,
),
)
- # only applies to monomials and variables
- def combinations(self, number: int):
- return dataclasses.replace(
+ def combinations(
self,
- underlying=init_combinations_expr(
- monomials=self.underlying,
- number=number,
+ degrees: tuple[int, ...] | int,
+ ):
+ return self.copy(
+ underlying=polymatrix.expression.initexpressionbase.init_combinations_expr(
+ expression=self.underlying,
+ degrees=degrees,
),
)
def determinant(self) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_determinant_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_determinant_expr(
underlying=self.underlying,
),
)
@@ -184,7 +155,7 @@ class Expression(
def diag(self):
return dataclasses.replace(
self,
- underlying=init_diag_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_diag_expr(
underlying=self.underlying,
),
)
@@ -196,8 +167,8 @@ class Expression(
) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_derivative_expr(
- underlying=self.underlying,
+ underlying=diff(
+ expression=self,
variables=variables,
introduce_derivatives=introduce_derivatives,
),
@@ -209,7 +180,7 @@ class Expression(
) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_divergence_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_divergence_expr(
underlying=self.underlying,
variables=variables,
),
@@ -222,7 +193,7 @@ class Expression(
) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_eval_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_eval_expr(
underlying=self.underlying,
variables=variable,
values=value,
@@ -237,7 +208,7 @@ class Expression(
) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_filter_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_filter_expr(
underlying=self.underlying,
predicator=predicator,
inverse=inverse,
@@ -248,7 +219,7 @@ class Expression(
def from_symmetric_matrix(self) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_from_symmetric_matrix_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_from_symmetric_matrix_expr(
underlying=self.underlying,
),
)
@@ -261,7 +232,7 @@ class Expression(
) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_half_newton_polytope_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_half_newton_polytope_expr(
monomials=self.underlying,
variables=variables,
filter=filter,
@@ -271,17 +242,21 @@ class Expression(
def linear_matrix_in(self, variable: 'Expression') -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_linear_matrix_in_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_linear_matrix_in_expr(
underlying=self.underlying,
variable=variable,
),
)
- def linear_monomials(self, variables: 'Expression') -> 'Expression':
+ def linear_monomials(
+ self,
+ variables: 'Expression',
+ ) -> 'Expression':
+
return dataclasses.replace(
self,
- underlying=init_linear_monomials_expr(
- underlying=self.underlying,
+ underlying=linear_monomials(
+ expression=self.underlying,
variables=variables,
),
)
@@ -292,23 +267,33 @@ class Expression(
monomials: 'Expression' = None,
ignore_unmatched: bool = None,
) -> 'Expression':
- if monomials is None:
- monomials = self.linear_monomials(variables)
return dataclasses.replace(
self,
- underlying=init_linear_in_expr(
- underlying=self.underlying,
+ underlying=linear_in(
+ expression=self.underlying,
monomials=monomials,
variables=variables,
ignore_unmatched=ignore_unmatched,
),
)
+
+ def legendre(
+ self,
+ degrees: tuple[int, ...] = None,
+ ) -> 'Expression':
+ return dataclasses.replace(
+ self,
+ underlying=legendre(
+ expression=self.underlying,
+ degrees=degrees,
+ ),
+ )
def max(self) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_max_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_max_expr(
underlying=self.underlying,
),
)
@@ -316,7 +301,7 @@ class Expression(
def max_degree(self) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_max_degree_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_max_degree_expr(
underlying=self.underlying,
),
)
@@ -324,7 +309,7 @@ class Expression(
def parametrize(self, name: str = None) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_parametrize_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_parametrize_expr(
underlying=self.underlying,
name=name,
),
@@ -343,12 +328,15 @@ class Expression(
if monomials is None:
monomials = self.quadratic_monomials(variables)
+ stack = get_stack_lines()
+
return dataclasses.replace(
self,
- underlying=init_quadratic_in_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_quadratic_in_expr(
underlying=self.underlying,
monomials=monomials,
variables=variables,
+ stack=stack,
),
)
@@ -358,7 +346,7 @@ class Expression(
) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_quadratic_monomials_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_quadratic_monomials_expr(
underlying=self.underlying,
variables=variables,
),
@@ -367,7 +355,7 @@ class Expression(
def reshape(self, n: int, m: int) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_reshape_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_reshape_expr(
underlying=self.underlying,
new_shape=(n, m),
),
@@ -376,7 +364,7 @@ class Expression(
def rep_mat(self, n: int, m: int) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_rep_mat_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_rep_mat_expr(
underlying=self.underlying,
repetition=(n, m),
),
@@ -391,11 +379,11 @@ class Expression(
if isinstance(value, Expression):
value = value.underlying
else:
- value = init_from_sympy_expr(value)
+ value = polymatrix.expression.initexpressionbase.init_from_expr(value)
return dataclasses.replace(
self,
- underlying=init_set_element_at_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_set_element_at_expr(
underlying=self.underlying,
index=(row, col),
value=value,
@@ -408,7 +396,7 @@ class Expression(
) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_squeeze_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_squeeze_expr(
underlying=self.underlying,
),
)
@@ -420,7 +408,7 @@ class Expression(
) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_subtract_monomials_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_subtract_monomials_expr(
underlying=self.underlying,
monomials=monomials,
),
@@ -433,7 +421,7 @@ class Expression(
) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_substitute_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_substitute_expr(
underlying=self.underlying,
variables=variable,
values=values,
@@ -453,7 +441,7 @@ class Expression(
def sum(self):
return dataclasses.replace(
self,
- underlying=init_sum_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_sum_expr(
underlying=self.underlying,
),
)
@@ -461,7 +449,7 @@ class Expression(
def symmetric(self):
return dataclasses.replace(
self,
- underlying=init_symmetric_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_symmetric_expr(
underlying=self.underlying,
),
)
@@ -469,7 +457,7 @@ class Expression(
def transpose(self) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_transpose_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_transpose_expr(
underlying=self.underlying,
),
)
@@ -481,7 +469,7 @@ class Expression(
def to_constant(self) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_to_constant_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_to_constant_expr(
underlying=self.underlying,
),
)
@@ -497,7 +485,7 @@ class Expression(
def to_symmetric_matrix(self) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_to_symmetric_matrix_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_to_symmetric_matrix_expr(
underlying=self.underlying,
),
)
@@ -506,7 +494,7 @@ class Expression(
def to_sorted_variables(self) -> 'Expression':
return dataclasses.replace(
self,
- underlying=init_to_sorted_variables(
+ underlying=polymatrix.expression.initexpressionbase.init_to_sorted_variables(
underlying=self.underlying,
),
)
@@ -520,7 +508,7 @@ class Expression(
):
return dataclasses.replace(
self,
- underlying=init_truncate_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_truncate_expr(
underlying=self.underlying,
variables=variables,
degrees=degrees,
@@ -531,7 +519,21 @@ class Expression(
@dataclassabc.dataclassabc(frozen=True, repr=False)
class ExpressionImpl(Expression):
- underlying: ExpressionBaseMixin
+ underlying: ExpressionBaseMixin
+
+ def __repr__(self) -> str:
+ return self.underlying.__repr__()
+
+ def copy(self, underlying: ExpressionBaseMixin) -> 'Expression':
+ return dataclasses.replace(
+ self,
+ underlying=underlying,
+ )
- def __repr__(self) -> str:
- return self.underlying.__repr__()
+
+def init_expression(
+ underlying: ExpressionBaseMixin,
+):
+ return ExpressionImpl(
+ underlying=underlying,
+ )
diff --git a/polymatrix/expression/from_.py b/polymatrix/expression/from_.py
new file mode 100644
index 0000000..637c9d1
--- /dev/null
+++ b/polymatrix/expression/from_.py
@@ -0,0 +1,56 @@
+import numpy as np
+import sympy
+
+import polymatrix.expression.initexpressionbase
+
+from polymatrix.expression.expression import init_expression, Expression
+from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
+
+
+DATA_TYPE = str | np.ndarray | sympy.Matrix | sympy.Expr | tuple | ExpressionBaseMixin
+
+def from_expr_or_none(
+ data: DATA_TYPE,
+) -> Expression | None:
+
+ return init_expression(
+ underlying=polymatrix.expression.initexpressionbase.init_from_expr_or_none(
+ data=data,
+ ),
+ )
+
+def from_(
+ data: DATA_TYPE,
+) -> Expression:
+
+ return init_expression(
+ underlying=polymatrix.expression.initexpressionbase.init_from_expr(
+ data=data,
+ ),
+ )
+
+# def from_expr(
+# data: DATA_TYPE,
+# ) -> Expression:
+# return from_(data=data)
+
+# def from_sympy(
+# data: tuple[tuple[float]],
+# ):
+# return init_expression(
+# polymatrix.expression.init.init_from_sympy_expr(data)
+# )
+
+# def from_state_monad(
+# data: StateMonad,
+# ):
+# return init_expression(
+# data.flat_map(lambda inner_data: polymatrix.expression.init.init_from_sympy_expr(inner_data)),
+# )
+
+# def from_polymatrix(
+# polymatrix: PolyMatrix,
+# ):
+# return init_expression(
+# polymatrix.expression.init.init_from_terms_expr(polymatrix)
+# )
diff --git a/polymatrix/expression/impl/reshapeexprmixin.py b/polymatrix/expression/impl/reshapeexprmixin.py
deleted file mode 100644
index 00a93b8..0000000
--- a/polymatrix/expression/impl/reshapeexprmixin.py
+++ /dev/null
@@ -1,10 +0,0 @@
-import dataclassabc
-
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-from polymatrix.expression.mixins.reshapeexprmixin import ReshapeExprMixin
-
-
-@dataclassabc.dataclassabc(frozen=True)
-class ReshapeExprImpl(ReshapeExprMixin):
- underlying: ExpressionBaseMixin
- new_shape: tuple
diff --git a/polymatrix/expression/impl/impl.py b/polymatrix/expression/implexpressionbase.py
index 7a919e5..79761f2 100644
--- a/polymatrix/expression/impl/impl.py
+++ b/polymatrix/expression/implexpressionbase.py
@@ -1,3 +1,6 @@
+from polymatrix.expression.mixins.legendreseriesmixin import LegendreSeriesMixin
+from polymatrix.expression.mixins.productexprmixin import ProductExprMixin
+from polymatrix.utils.getstacklines import FrameSummary
import dataclassabc
from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
@@ -20,7 +23,7 @@ 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.fromsympyexprmixin import FromSympyExprMixin
+from polymatrix.expression.mixins.fromtupleexprmixin import FromTupleExprMixin
from polymatrix.expression.mixins.fromtermsexprmixin import FromTermsExprMixin
from polymatrix.expression.mixins.getitemexprmixin import GetItemExprMixin
from polymatrix.expression.mixins.halfnewtonpolytopeexprmixin import \
@@ -69,14 +72,16 @@ from polymatrix.expression.mixins.tosortedvariablesmixin import ToSortedVariable
class AdditionExprImpl(AdditionExprMixin):
left: ExpressionBaseMixin
right: ExpressionBaseMixin
+ stack: tuple[FrameSummary]
+ def __repr__(self):
+ return f'{self.__class__.__name__}(left={self.left}, right={self.right})'
@dataclassabc.dataclassabc(frozen=True)
class BlockDiagExprImpl(BlockDiagExprMixin):
- underlying: tuple
+ underlying: tuple[ExpressionBaseMixin]
-# @dataclassabc.dataclassabc(frozen=True, eq=False)
@dataclassabc.dataclassabc(frozen=True)
class CacheExprImpl(CacheExprMixin):
underlying: ExpressionBaseMixin
@@ -84,8 +89,8 @@ class CacheExprImpl(CacheExprMixin):
@dataclassabc.dataclassabc(frozen=True)
class CombinationsExprImpl(CombinationsExprMixin):
- monomials: ExpressionBaseMixin
- number: int
+ expression: ExpressionBaseMixin
+ degrees: tuple[int, ...]
@dataclassabc.dataclassabc(frozen=True)
@@ -93,6 +98,10 @@ class DerivativeExprImpl(DerivativeExprMixin):
underlying: ExpressionBaseMixin
variables: tuple
introduce_derivatives: bool
+ stack: tuple[FrameSummary]
+
+ def __repr__(self):
+ return f'{self.__class__.__name__}(variables={self.variables}, underlying={self.underlying})'
@dataclassabc.dataclassabc(frozen=True)
@@ -110,11 +119,11 @@ class DivergenceExprImpl(DivergenceExprMixin):
underlying: ExpressionBaseMixin
variables: tuple
-
-@dataclassabc.dataclassabc(frozen=True, eq=False)
+@dataclassabc.dataclassabc(frozen=True)
class DivisionExprImpl(DivisionExprMixin):
left: ExpressionBaseMixin
right: ExpressionBaseMixin
+ stack: tuple[FrameSummary]
@dataclassabc.dataclassabc(frozen=True)
@@ -147,9 +156,12 @@ class FromSymmetricMatrixExprImpl(FromSymmetricMatrixExprMixin):
@dataclassabc.dataclassabc(frozen=True)
-class FromSympyExprImpl(FromSympyExprMixin):
+class FromTupleExprImpl(FromTupleExprMixin):
data: tuple[tuple[float]]
+ stack: tuple[FrameSummary]
+ def __repr__(self):
+ return f'{self.__class__.__name__}(data={self.data})'
@dataclassabc.dataclassabc(frozen=True)
class FromTermsExprImpl(FromTermsExprMixin):
@@ -191,9 +203,20 @@ class LinearMonomialsExprImpl(LinearMonomialsExprMixin):
@dataclassabc.dataclassabc(frozen=True)
+class LegendreSeriesImpl(LegendreSeriesMixin):
+ underlying: ExpressionBaseMixin
+ degrees: tuple[int, ...] | None
+ stack: tuple[FrameSummary]
+
+
+@dataclassabc.dataclassabc(frozen=True)
class MatrixMultExprImpl(MatrixMultExprMixin):
left: ExpressionBaseMixin
right: ExpressionBaseMixin
+ stack: tuple[FrameSummary]
+
+ def __repr__(self):
+ return f'{self.__class__.__name__}(left={self.left}, right={self.right})'
@dataclassabc.dataclassabc(frozen=True)
@@ -206,14 +229,13 @@ class MaxExprImpl(MaxExprMixin):
underlying: ExpressionBaseMixin
-# @dataclassabc.dataclassabc(frozen=True, eq=False, repr=False)
@dataclassabc.dataclassabc(frozen=True, repr=False)
class ParametrizeExprImpl(ParametrizeExprMixin):
underlying: ExpressionBaseMixin
name: str
def __repr__(self) -> str:
- return f'{self.__class__.__name__}(name={repr(self.name)})'
+ return f'{self.__class__.__name__}(name={self.name})'
@dataclassabc.dataclassabc(frozen=True)
@@ -223,10 +245,21 @@ class ParametrizeMatrixExprImpl(ParametrizeMatrixExprMixin):
@dataclassabc.dataclassabc(frozen=True)
+class ProductExprImpl(ProductExprMixin):
+ underlying: tuple[ExpressionBaseMixin]
+ degrees: tuple[int, ...] | None
+ stack: tuple[FrameSummary]
+
+
+@dataclassabc.dataclassabc(frozen=True)
class QuadraticInExprImpl(QuadraticInExprMixin):
underlying: ExpressionBaseMixin
monomials: ExpressionBaseMixin
variables: tuple
+ stack: tuple[FrameSummary]
+
+ def __repr__(self):
+ return f'{self.__class__.__name__}(variables={self.variables}, monomials={self.monomials}, underlying={self.underlying})'
@dataclassabc.dataclassabc(frozen=True)
@@ -241,10 +274,10 @@ class RepMatExprImpl(RepMatExprMixin):
repetition: tuple
-# @dataclassabc.dataclassabc(frozen=True)
-# class ReshapeExprImpl(ReshapeExprMixin):
-# underlying: ExpressionBaseMixin
-# new_shape: tuple
+@dataclassabc.dataclassabc(frozen=True)
+class ReshapeExprImpl(ReshapeExprMixin):
+ underlying: ExpressionBaseMixin
+ new_shape: tuple
@dataclassabc.dataclassabc(frozen=True)
@@ -262,7 +295,6 @@ class SqueezeExprImpl(SqueezeExprMixin):
@dataclassabc.dataclassabc(frozen=True)
class SubstituteExprImpl(SubstituteExprMixin):
underlying: ExpressionBaseMixin
- # variables: tuple
substitutions: tuple
diff --git a/polymatrix/expression/init/initadditionexpr.py b/polymatrix/expression/init/initadditionexpr.py
deleted file mode 100644
index cdc97b1..0000000
--- a/polymatrix/expression/init/initadditionexpr.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_addition_expr(
- left: ExpressionBaseMixin,
- right: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.AdditionExprImpl(
- left=left,
- right=right,
-)
diff --git a/polymatrix/expression/init/initblockdiagexpr.py b/polymatrix/expression/init/initblockdiagexpr.py
deleted file mode 100644
index a9ad8a6..0000000
--- a/polymatrix/expression/init/initblockdiagexpr.py
+++ /dev/null
@@ -1,7 +0,0 @@
-import polymatrix.expression.impl.impl
-def init_block_diag_expr(
- underlying: tuple,
-):
- return polymatrix.expression.impl.impl.BlockDiagExprImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/initcacheexpr.py b/polymatrix/expression/init/initcacheexpr.py
deleted file mode 100644
index 861ffa1..0000000
--- a/polymatrix/expression/init/initcacheexpr.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_cache_expr(
- underlying: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.CacheExprImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/initcombinationsexpr.py b/polymatrix/expression/init/initcombinationsexpr.py
deleted file mode 100644
index 10931e6..0000000
--- a/polymatrix/expression/init/initcombinationsexpr.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_combinations_expr(
- monomials: ExpressionBaseMixin,
- number: int,
-):
- return polymatrix.expression.impl.impl.CombinationsExprImpl(
- monomials=monomials,
- number=number,
-)
diff --git a/polymatrix/expression/init/initderivativeexpr.py b/polymatrix/expression/init/initderivativeexpr.py
deleted file mode 100644
index b1c9405..0000000
--- a/polymatrix/expression/init/initderivativeexpr.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_derivative_expr(
- underlying: ExpressionBaseMixin,
- variables: ExpressionBaseMixin,
- introduce_derivatives: bool = None,
-):
-
- assert isinstance(variables, ExpressionBaseMixin), f'{variables=}'
-
- if introduce_derivatives is None:
- introduce_derivatives = False
-
- return polymatrix.expression.impl.impl.DerivativeExprImpl(
- underlying=underlying,
- variables=variables,
- introduce_derivatives=introduce_derivatives,
-)
diff --git a/polymatrix/expression/init/initdeterminantexpr.py b/polymatrix/expression/init/initdeterminantexpr.py
deleted file mode 100644
index 660f3ae..0000000
--- a/polymatrix/expression/init/initdeterminantexpr.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_determinant_expr(
- underlying: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.DeterminantExprImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/initdiagexpr.py b/polymatrix/expression/init/initdiagexpr.py
deleted file mode 100644
index 794c5bf..0000000
--- a/polymatrix/expression/init/initdiagexpr.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_diag_expr(
- underlying: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.DiagExprImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/initdivergenceexpr.py b/polymatrix/expression/init/initdivergenceexpr.py
deleted file mode 100644
index 6f5d99d..0000000
--- a/polymatrix/expression/init/initdivergenceexpr.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-from typing import Union
-import polymatrix.expression.impl.impl
-
-
-def init_divergence_expr(
- underlying: ExpressionBaseMixin,
- variables: tuple,
-):
- return polymatrix.expression.impl.impl.DivergenceExprImpl(
- underlying=underlying,
- variables=variables,
-)
diff --git a/polymatrix/expression/init/initdivisionexpr.py b/polymatrix/expression/init/initdivisionexpr.py
deleted file mode 100644
index d7870bc..0000000
--- a/polymatrix/expression/init/initdivisionexpr.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_division_expr(
- left: ExpressionBaseMixin,
- right: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.DivisionExprImpl(
- left=left,
- right=right,
-)
diff --git a/polymatrix/expression/init/initelemmultexpr.py b/polymatrix/expression/init/initelemmultexpr.py
deleted file mode 100644
index ef66c68..0000000
--- a/polymatrix/expression/init/initelemmultexpr.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_elem_mult_expr(
- left: ExpressionBaseMixin,
- right: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.ElemMultExprImpl(
- left=left,
- right=right,
-)
diff --git a/polymatrix/expression/init/initevalexpr.py b/polymatrix/expression/init/initevalexpr.py
deleted file mode 100644
index 29359d6..0000000
--- a/polymatrix/expression/init/initevalexpr.py
+++ /dev/null
@@ -1,37 +0,0 @@
-import typing
-import numpy as np
-from polymatrix.expression.init.initsubstituteexpr import format_substitutions
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_eval_expr(
- underlying: ExpressionBaseMixin,
- variables: typing.Union[typing.Any, tuple, dict],
- values: typing.Union[float, tuple] = None,
-):
-
- substitutions = format_substitutions(
- variables=variables,
- values=values,
- )
-
- def formatted_values(value):
- if isinstance(value, np.ndarray):
- return tuple(value.reshape(-1))
-
- elif isinstance(value, tuple):
- return value
-
- elif isinstance(value, int) or isinstance(value, float):
- return (value,)
-
- else:
- return (float(value),)
-
- substitutions = tuple((variable, formatted_values(value)) for variable, value in substitutions)
-
- return polymatrix.expression.impl.impl.EvalExprImpl(
- underlying=underlying,
- substitutions=substitutions,
- )
diff --git a/polymatrix/expression/init/initexpression.py b/polymatrix/expression/init/initexpression.py
deleted file mode 100644
index 3c3258c..0000000
--- a/polymatrix/expression/init/initexpression.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.expression import ExpressionImpl
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-
-
-def init_expression(
- underlying: ExpressionBaseMixin,
-):
- return ExpressionImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/initeyeexpr.py b/polymatrix/expression/init/initeyeexpr.py
deleted file mode 100644
index 642e4c6..0000000
--- a/polymatrix/expression/init/initeyeexpr.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_eye_expr(
- variable: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.EyeExprImpl(
- variable=variable,
-)
diff --git a/polymatrix/expression/init/initfilterexpr.py b/polymatrix/expression/init/initfilterexpr.py
deleted file mode 100644
index 7164183..0000000
--- a/polymatrix/expression/init/initfilterexpr.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_filter_expr(
- underlying: ExpressionBaseMixin,
- predicator: ExpressionBaseMixin,
- inverse: bool == None,
-):
- if inverse is None:
- inverse = False
-
- return polymatrix.expression.impl.impl.FilterExprImpl(
- underlying=underlying,
- predicator=predicator,
- inverse=inverse,
-)
diff --git a/polymatrix/expression/init/initfromsymmetricmatrixexpr.py b/polymatrix/expression/init/initfromsymmetricmatrixexpr.py
deleted file mode 100644
index b3ef782..0000000
--- a/polymatrix/expression/init/initfromsymmetricmatrixexpr.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_from_symmetric_matrix_expr(
- underlying: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.FromSymmetricMatrixExprImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/initfromsympyexpr.py b/polymatrix/expression/init/initfromsympyexpr.py
deleted file mode 100644
index 4ca6fcf..0000000
--- a/polymatrix/expression/init/initfromsympyexpr.py
+++ /dev/null
@@ -1,68 +0,0 @@
-import typing
-import numpy as np
-import sympy
-
-from polymatrix.expression.impl.impl import FromSympyExprImpl
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-
-
-def init_from_expr_or_none(
- data: typing.Union[np.ndarray, tuple[tuple[float]]],
-) -> ExpressionBaseMixin | None:
- match data:
- case np.ndarray():
- assert len(data.shape) <= 2
-
- def gen_elements():
- for row in data:
- if isinstance(row, np.ndarray):
- yield tuple(row)
- else:
- yield (row,)
-
- data = tuple(gen_elements())
-
- case sympy.Matrix():
- data = tuple(tuple(i for i in data.row(row)) for row in range(data.rows))
-
- case tuple():
-
- match data[0]:
-
- case tuple():
- n_col = len(data[0])
- assert all(len(col) == n_col for col in data)
-
- case _:
- data = tuple((e,) for e in data)
-
- case sympy.Expr():
- data = ((sympy.expand(data),),)
-
- case ExpressionBaseMixin():
- return data
-
- case _:
- if not isinstance(data, (float, int, np.number)):
- # raise Exception(f'{data=}, {type(data)=}')
- return None
-
- data = ((data,),)
-
- return FromSympyExprImpl(
- data=data,
- )
-
-
-def init_from_sympy_expr(
- data: typing.Union[np.ndarray, tuple[tuple[float]]],
-):
- # if isinstance(data, ExpressionBaseMixin):
- # return data
-
- expr = init_from_expr_or_none(data)
-
- if expr is None:
- raise Exception(f'{data=}')
-
- return expr
diff --git a/polymatrix/expression/init/initfromtermsexpr.py b/polymatrix/expression/init/initfromtermsexpr.py
deleted file mode 100644
index b2c1dc3..0000000
--- a/polymatrix/expression/init/initfromtermsexpr.py
+++ /dev/null
@@ -1,33 +0,0 @@
-import typing
-from polymatrix.polymatrix.mixins.polymatrixmixin import PolyMatrixMixin
-import polymatrix.expression.impl.impl
-
-
-def init_from_terms_expr(
- terms: typing.Union[tuple, PolyMatrixMixin],
- shape: tuple[int, int] = None,
-):
-
- if isinstance(terms, PolyMatrixMixin):
- shape = terms.shape
- gen_terms = terms.gen_terms()
-
- else:
- assert shape is not None
-
- if isinstance(terms, tuple):
- gen_terms = terms
-
- elif isinstance(terms, dict):
- gen_terms = terms.items()
-
- else:
- raise Exception(f'{terms=}')
-
- # Expression needs to be hashable
- terms_formatted = tuple((key, tuple(monomials.items())) for key, monomials in gen_terms)
-
- return polymatrix.expression.impl.impl.FromTermsExprImpl(
- terms=terms_formatted,
- shape=shape,
- )
diff --git a/polymatrix/expression/init/initgetitemexpr.py b/polymatrix/expression/init/initgetitemexpr.py
deleted file mode 100644
index f7fc0c9..0000000
--- a/polymatrix/expression/init/initgetitemexpr.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from numpy import isin
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_get_item_expr(
- underlying: ExpressionBaseMixin,
- index: tuple[tuple[int, ...], tuple[int, ...]],
-):
-
- def get_hashable_slice(index):
- if isinstance(index, slice):
- return polymatrix.expression.impl.impl.GetItemExprImpl.Slice(start=index.start, stop=index.stop, step=index.step)
- else:
- return index
-
- proper_index = (get_hashable_slice(index[0]), get_hashable_slice(index[1]))
-
- return polymatrix.expression.impl.impl.GetItemExprImpl(
- underlying=underlying,
- index=proper_index,
-)
diff --git a/polymatrix/expression/init/inithalfnewtonpolytopeexpr.py b/polymatrix/expression/init/inithalfnewtonpolytopeexpr.py
deleted file mode 100644
index 794c938..0000000
--- a/polymatrix/expression/init/inithalfnewtonpolytopeexpr.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_half_newton_polytope_expr(
- monomials: ExpressionBaseMixin,
- variables: ExpressionBaseMixin,
- filter: ExpressionBaseMixin | None = None,
-):
- return polymatrix.expression.impl.impl.HalfNewtonPolytopeExprImpl(
- monomials=monomials,
- variables=variables,
- filter=filter
-)
diff --git a/polymatrix/expression/init/initlinearinexpr.py b/polymatrix/expression/init/initlinearinexpr.py
deleted file mode 100644
index 30705e2..0000000
--- a/polymatrix/expression/init/initlinearinexpr.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_linear_in_expr(
- underlying: ExpressionBaseMixin,
- monomials: ExpressionBaseMixin,
- variables: ExpressionBaseMixin,
- ignore_unmatched: bool = None,
-):
- assert isinstance(variables, ExpressionBaseMixin), f'{variables=}'
-
- return polymatrix.expression.impl.impl.LinearInExprImpl(
- underlying=underlying,
- monomials=monomials,
- variables=variables,
- ignore_unmatched = ignore_unmatched,
-)
diff --git a/polymatrix/expression/init/initlinearmatrixinexpr.py b/polymatrix/expression/init/initlinearmatrixinexpr.py
deleted file mode 100644
index 83e9aea..0000000
--- a/polymatrix/expression/init/initlinearmatrixinexpr.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_linear_matrix_in_expr(
- underlying: ExpressionBaseMixin,
- variable: int,
-):
- return polymatrix.expression.impl.impl.LinearMatrixInExprImpl(
- underlying=underlying,
- variable=variable,
-)
diff --git a/polymatrix/expression/init/initlinearmonomialsexpr.py b/polymatrix/expression/init/initlinearmonomialsexpr.py
deleted file mode 100644
index f830542..0000000
--- a/polymatrix/expression/init/initlinearmonomialsexpr.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_linear_monomials_expr(
- underlying: ExpressionBaseMixin,
- variables: ExpressionBaseMixin,
-):
-
- assert isinstance(variables, ExpressionBaseMixin), f'{variables=}'
-
- return polymatrix.expression.impl.impl.LinearMonomialsExprImpl(
- underlying=underlying,
- variables=variables,
- )
diff --git a/polymatrix/expression/init/initmatrixmultexpr.py b/polymatrix/expression/init/initmatrixmultexpr.py
deleted file mode 100644
index 20bffec..0000000
--- a/polymatrix/expression/init/initmatrixmultexpr.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_matrix_mult_expr(
- left: ExpressionBaseMixin,
- right: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.MatrixMultExprImpl(
- left=left,
- right=right,
-)
diff --git a/polymatrix/expression/init/initmaxdegreeexpr.py b/polymatrix/expression/init/initmaxdegreeexpr.py
deleted file mode 100644
index d232163..0000000
--- a/polymatrix/expression/init/initmaxdegreeexpr.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_max_degree_expr(
- underlying: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.MaxDegreeExprImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/initmaxexpr.py b/polymatrix/expression/init/initmaxexpr.py
deleted file mode 100644
index 41dde90..0000000
--- a/polymatrix/expression/init/initmaxexpr.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_max_expr(
- underlying: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.MaxExprImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/initparametrizeexpr.py b/polymatrix/expression/init/initparametrizeexpr.py
deleted file mode 100644
index 178d963..0000000
--- a/polymatrix/expression/init/initparametrizeexpr.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_parametrize_expr(
- underlying: ExpressionBaseMixin,
- name: str = None,
-):
- if name is None:
- name = 'undefined'
-
- return polymatrix.expression.impl.impl.ParametrizeExprImpl(
- underlying=underlying,
- name=name,
-)
diff --git a/polymatrix/expression/init/initparametrizematrixexpr.py b/polymatrix/expression/init/initparametrizematrixexpr.py
deleted file mode 100644
index bf90510..0000000
--- a/polymatrix/expression/init/initparametrizematrixexpr.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_parametrize_matrix_expr(
- underlying: ExpressionBaseMixin,
- name: str,
-):
- return polymatrix.expression.impl.impl.ParametrizeMatrixExprImpl(
- underlying=underlying,
- name=name,
-)
diff --git a/polymatrix/expression/init/initquadraticinexpr.py b/polymatrix/expression/init/initquadraticinexpr.py
deleted file mode 100644
index 9569cd3..0000000
--- a/polymatrix/expression/init/initquadraticinexpr.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_quadratic_in_expr(
- underlying: ExpressionBaseMixin,
- monomials: ExpressionBaseMixin,
- variables: ExpressionBaseMixin,
-):
-
- assert isinstance(variables, ExpressionBaseMixin), f'{variables=}'
-
- return polymatrix.expression.impl.impl.QuadraticInExprImpl(
- underlying=underlying,
- monomials=monomials,
- variables=variables,
- )
diff --git a/polymatrix/expression/init/initquadraticmonomialsexpr.py b/polymatrix/expression/init/initquadraticmonomialsexpr.py
deleted file mode 100644
index c965312..0000000
--- a/polymatrix/expression/init/initquadraticmonomialsexpr.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_quadratic_monomials_expr(
- underlying: ExpressionBaseMixin,
- variables: ExpressionBaseMixin,
-):
-
- assert isinstance(variables, ExpressionBaseMixin), f'{variables=}'
-
- return polymatrix.expression.impl.impl.QuadraticMonomialsExprImpl(
- underlying=underlying,
- variables=variables,
- )
diff --git a/polymatrix/expression/init/initrepmatexpr.py b/polymatrix/expression/init/initrepmatexpr.py
deleted file mode 100644
index 152fff8..0000000
--- a/polymatrix/expression/init/initrepmatexpr.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_rep_mat_expr(
- underlying: ExpressionBaseMixin,
- repetition: tuple,
-):
- return polymatrix.expression.impl.impl.RepMatExprImpl(
- underlying=underlying,
- repetition=repetition,
-)
diff --git a/polymatrix/expression/init/initreshapeexpr.py b/polymatrix/expression/init/initreshapeexpr.py
deleted file mode 100644
index 4e6ab57..0000000
--- a/polymatrix/expression/init/initreshapeexpr.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from polymatrix.expression.impl.reshapeexprmixin import ReshapeExprImpl
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-
-
-def init_reshape_expr(
- underlying: ExpressionBaseMixin,
- new_shape: tuple,
-):
- return ReshapeExprImpl(
- underlying=underlying,
- new_shape=new_shape,
-)
diff --git a/polymatrix/expression/init/initsetelementatexpr.py b/polymatrix/expression/init/initsetelementatexpr.py
deleted file mode 100644
index 250c35b..0000000
--- a/polymatrix/expression/init/initsetelementatexpr.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_set_element_at_expr(
- underlying: ExpressionBaseMixin,
- index: tuple,
- value: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.SetElementAtExprImpl(
- underlying=underlying,
- index=index,
- value=value,
-)
diff --git a/polymatrix/expression/init/initsqueezeexpr.py b/polymatrix/expression/init/initsqueezeexpr.py
deleted file mode 100644
index d539453..0000000
--- a/polymatrix/expression/init/initsqueezeexpr.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_squeeze_expr(
- underlying: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.SqueezeExprImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/initsubtractmonomialsexpr.py b/polymatrix/expression/init/initsubtractmonomialsexpr.py
deleted file mode 100644
index de720bd..0000000
--- a/polymatrix/expression/init/initsubtractmonomialsexpr.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_subtract_monomials_expr(
- underlying: ExpressionBaseMixin,
- monomials: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.SubtractMonomialsExprImpl(
- underlying=underlying,
- monomials=monomials,
-)
diff --git a/polymatrix/expression/init/initsumexpr.py b/polymatrix/expression/init/initsumexpr.py
deleted file mode 100644
index 288ae72..0000000
--- a/polymatrix/expression/init/initsumexpr.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_sum_expr(
- underlying: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.SumExprImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/initsymmetricexpr.py b/polymatrix/expression/init/initsymmetricexpr.py
deleted file mode 100644
index dc321e5..0000000
--- a/polymatrix/expression/init/initsymmetricexpr.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_symmetric_expr(
- underlying: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.SymmetricExprImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/inittoconstantexpr.py b/polymatrix/expression/init/inittoconstantexpr.py
deleted file mode 100644
index a0084a1..0000000
--- a/polymatrix/expression/init/inittoconstantexpr.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_to_constant_expr(
- underlying: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.ToConstantExprImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/inittoquadraticexpr.py b/polymatrix/expression/init/inittoquadraticexpr.py
deleted file mode 100644
index 77e6943..0000000
--- a/polymatrix/expression/init/inittoquadraticexpr.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_to_quadratic_expr(
- underlying: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.ToQuadraticExprImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/inittosortedvariables.py b/polymatrix/expression/init/inittosortedvariables.py
deleted file mode 100644
index 3f5222a..0000000
--- a/polymatrix/expression/init/inittosortedvariables.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_to_sorted_variables(
- underlying: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.ToSortedVariablesImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/inittosymmetricmatrixexpr.py b/polymatrix/expression/init/inittosymmetricmatrixexpr.py
deleted file mode 100644
index 68b27fe..0000000
--- a/polymatrix/expression/init/inittosymmetricmatrixexpr.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_to_symmetric_matrix_expr(
- underlying: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.ToSymmetricMatrixExprImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/inittransposeexpr.py b/polymatrix/expression/init/inittransposeexpr.py
deleted file mode 100644
index 7807e4d..0000000
--- a/polymatrix/expression/init/inittransposeexpr.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_transpose_expr(
- underlying: ExpressionBaseMixin,
-):
- return polymatrix.expression.impl.impl.TransposeExprImpl(
- underlying=underlying,
-)
diff --git a/polymatrix/expression/init/inittruncateexpr.py b/polymatrix/expression/init/inittruncateexpr.py
deleted file mode 100644
index d36db03..0000000
--- a/polymatrix/expression/init/inittruncateexpr.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_truncate_expr(
- underlying: ExpressionBaseMixin,
- variables: ExpressionBaseMixin,
- degrees: tuple[int],
- inverse: bool = None,
-):
- if isinstance(degrees, int):
- degrees = (degrees,)
-
- if inverse is None:
- inverse = False
-
- return polymatrix.expression.impl.impl.TruncateExprImpl(
- underlying=underlying,
- variables=variables,
- degrees=degrees,
- inverse=inverse,
- )
diff --git a/polymatrix/expression/init/initvstackexpr.py b/polymatrix/expression/init/initvstackexpr.py
deleted file mode 100644
index 3d47979..0000000
--- a/polymatrix/expression/init/initvstackexpr.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from polymatrix.expression.init.initfromsympyexpr import init_from_sympy_expr
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
-
-def init_v_stack_expr(
- underlying: tuple,
-):
-
- def gen_underlying():
-
- for e in underlying:
- if isinstance(e, ExpressionBaseMixin):
- yield e
- else:
- yield init_from_sympy_expr(e)
-
- return polymatrix.expression.impl.impl.VStackExprImpl(
- underlying=tuple(gen_underlying()),
-)
diff --git a/polymatrix/expression/initexpressionbase.py b/polymatrix/expression/initexpressionbase.py
new file mode 100644
index 0000000..1a3e52c
--- /dev/null
+++ b/polymatrix/expression/initexpressionbase.py
@@ -0,0 +1,604 @@
+import typing
+import numpy as np
+import sympy
+
+import polymatrix.expression.implexpressionbase
+
+from polymatrix.utils.getstacklines import FrameSummary
+from polymatrix.utils.getstacklines import get_stack_lines
+from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
+from polymatrix.expression.utils.formatsubstitutions import format_substitutions
+from polymatrix.polymatrix.mixins.polymatrixmixin import PolyMatrixMixin
+from polymatrix.expression.implexpressionbase import FromTupleExprImpl, AdditionExprImpl
+
+
+def init_addition_expr(
+ left: ExpressionBaseMixin,
+ right: ExpressionBaseMixin,
+ stack: tuple[FrameSummary],
+):
+ return AdditionExprImpl(
+ left=left,
+ right=right,
+ stack=stack,
+)
+
+
+def init_block_diag_expr(
+ underlying: tuple,
+):
+ return polymatrix.expression.implexpressionbase.BlockDiagExprImpl(
+ underlying=underlying,
+ )
+
+
+def init_cache_expr(
+ underlying: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.CacheExprImpl(
+ underlying=underlying,
+)
+
+
+def init_combinations_expr(
+ expression: ExpressionBaseMixin,
+ degrees: tuple[int, ...] | int,
+):
+ if isinstance(degrees, int):
+ degrees = (degrees,)
+
+ return polymatrix.expression.implexpressionbase.CombinationsExprImpl(
+ expression=expression,
+ degrees=degrees,
+)
+
+
+# def init_derivative_expr(
+# underlying: ExpressionBaseMixin,
+# variables: ExpressionBaseMixin,
+# stack: tuple[FrameSummary],
+# introduce_derivatives: bool = None,
+# ):
+
+# assert isinstance(variables, ExpressionBaseMixin), f'{variables=}'
+
+# if introduce_derivatives is None:
+# introduce_derivatives = False
+
+# return polymatrix.expression.implexpressionbase.DerivativeExprImpl(
+# underlying=underlying,
+# variables=variables,
+# introduce_derivatives=introduce_derivatives,
+# stack=stack,
+# )
+
+
+def init_determinant_expr(
+ underlying: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.DeterminantExprImpl(
+ underlying=underlying,
+)
+
+
+def init_diag_expr(
+ underlying: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.DiagExprImpl(
+ underlying=underlying,
+)
+
+
+def init_divergence_expr(
+ underlying: ExpressionBaseMixin,
+ variables: tuple,
+):
+ return polymatrix.expression.implexpressionbase.DivergenceExprImpl(
+ underlying=underlying,
+ variables=variables,
+)
+
+
+def init_division_expr(
+ left: ExpressionBaseMixin,
+ right: ExpressionBaseMixin,
+ stack: tuple[FrameSummary],
+):
+ return polymatrix.expression.implexpressionbase.DivisionExprImpl(
+ left=left,
+ right=right,
+ stack=stack,
+)
+
+
+def init_elem_mult_expr(
+ left: ExpressionBaseMixin,
+ right: ExpressionBaseMixin,
+ stack: tuple[FrameSummary],
+):
+ return polymatrix.expression.implexpressionbase.ElemMultExprImpl(
+ left=left,
+ right=right,
+)
+
+
+def init_eval_expr(
+ underlying: ExpressionBaseMixin,
+ variables: typing.Union[typing.Any, tuple, dict],
+ values: typing.Union[float, tuple] = None,
+):
+
+ substitutions = format_substitutions(
+ variables=variables,
+ values=values,
+ )
+
+ def formatted_values(value):
+ if isinstance(value, np.ndarray):
+ return tuple(value.reshape(-1))
+
+ elif isinstance(value, tuple):
+ return value
+
+ elif isinstance(value, int) or isinstance(value, float):
+ return (value,)
+
+ else:
+ return (float(value),)
+
+ substitutions = tuple((variable, formatted_values(value)) for variable, value in substitutions)
+
+ return polymatrix.expression.implexpressionbase.EvalExprImpl(
+ underlying=underlying,
+ substitutions=substitutions,
+ )
+
+
+def init_eye_expr(
+ variable: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.EyeExprImpl(
+ variable=variable,
+)
+
+
+def init_filter_expr(
+ underlying: ExpressionBaseMixin,
+ predicator: ExpressionBaseMixin,
+ inverse: bool = None,
+):
+ if inverse is None:
+ inverse = False
+
+ return polymatrix.expression.implexpressionbase.FilterExprImpl(
+ underlying=underlying,
+ predicator=predicator,
+ inverse=inverse,
+)
+
+
+def init_from_symmetric_matrix_expr(
+ underlying: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.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:
+ if isinstance(data, str):
+ return init_parametrize_expr(
+ underlying=init_from_expr_or_none(1),
+ name=data,
+ )
+
+ elif isinstance(data, np.ndarray):
+ assert len(data.shape) <= 2
+
+ def gen_elements():
+ for row in data:
+ if isinstance(row, np.ndarray):
+ yield tuple(row)
+ else:
+ yield (row,)
+
+ 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))
+
+ elif isinstance(data, sympy.Expr):
+ 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)
+
+ else:
+ data = tuple((e,) for e in data)
+
+ elif isinstance(data, ExpressionBaseMixin):
+ return data
+
+ else:
+ if not isinstance(data, (float, int, np.number)):
+ return None
+
+ data = ((data,),)
+
+ return FromTupleExprImpl(
+ data=data,
+ stack=get_stack_lines(),
+ )
+
+
+def init_from_expr(
+ data: DATA_TYPE
+):
+ expr = init_from_expr_or_none(data)
+
+ if expr is None:
+ raise Exception(f'{data=}')
+
+ return expr
+
+
+def init_from_terms_expr(
+ terms: typing.Union[tuple, PolyMatrixMixin],
+ shape: tuple[int, int] = None,
+):
+
+ if isinstance(terms, PolyMatrixMixin):
+ shape = terms.shape
+ gen_terms = terms.gen_terms()
+
+ else:
+ assert shape is not None
+
+ if isinstance(terms, tuple):
+ gen_terms = terms
+
+ elif isinstance(terms, dict):
+ gen_terms = terms.items()
+
+ else:
+ raise Exception(f'{terms=}')
+
+ # Expression needs to be hashable
+ terms_formatted = tuple((key, tuple(monomials.items())) for key, monomials in gen_terms)
+
+ return polymatrix.expression.implexpressionbase.FromTermsExprImpl(
+ terms=terms_formatted,
+ shape=shape,
+ )
+
+
+def init_get_item_expr(
+ underlying: ExpressionBaseMixin,
+ index: tuple[tuple[int, ...], tuple[int, ...]],
+):
+
+ def get_hashable_slice(index):
+ if isinstance(index, slice):
+ return polymatrix.expression.implexpressionbase.GetItemExprImpl.Slice(start=index.start, stop=index.stop, step=index.step)
+ else:
+ return index
+
+ proper_index = (get_hashable_slice(index[0]), get_hashable_slice(index[1]))
+
+ return polymatrix.expression.implexpressionbase.GetItemExprImpl(
+ underlying=underlying,
+ index=proper_index,
+)
+
+
+def init_half_newton_polytope_expr(
+ monomials: ExpressionBaseMixin,
+ variables: ExpressionBaseMixin,
+ filter: ExpressionBaseMixin | None = None,
+):
+ return polymatrix.expression.implexpressionbase.HalfNewtonPolytopeExprImpl(
+ monomials=monomials,
+ variables=variables,
+ filter=filter
+)
+
+
+# def init_linear_in_expr(
+# underlying: ExpressionBaseMixin,
+# monomials: ExpressionBaseMixin,
+# variables: ExpressionBaseMixin,
+# ignore_unmatched: bool = None,
+# ):
+# assert isinstance(variables, ExpressionBaseMixin), f'{variables=}'
+
+# return polymatrix.expression.implexpressionbase.LinearInExprImpl(
+# underlying=underlying,
+# monomials=monomials,
+# variables=variables,
+# ignore_unmatched = ignore_unmatched,
+# )
+
+
+def init_linear_matrix_in_expr(
+ underlying: ExpressionBaseMixin,
+ variable: int,
+):
+ return polymatrix.expression.implexpressionbase.LinearMatrixInExprImpl(
+ underlying=underlying,
+ variable=variable,
+)
+
+
+# def init_linear_monomials_expr(
+# underlying: ExpressionBaseMixin,
+# variables: ExpressionBaseMixin,
+# ):
+
+# assert isinstance(variables, ExpressionBaseMixin), f'{variables=}'
+
+# return polymatrix.expression.implexpressionbase.LinearMonomialsExprImpl(
+# underlying=underlying,
+# variables=variables,
+# )
+
+
+def init_matrix_mult_expr(
+ left: ExpressionBaseMixin,
+ right: ExpressionBaseMixin,
+ stack: tuple[FrameSummary],
+):
+ return polymatrix.expression.implexpressionbase.MatrixMultExprImpl(
+ left=left,
+ right=right,
+ stack=stack,
+)
+
+
+def init_max_degree_expr(
+ underlying: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.MaxDegreeExprImpl(
+ underlying=underlying,
+)
+
+
+def init_max_expr(
+ underlying: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.MaxExprImpl(
+ underlying=underlying,
+)
+
+
+def init_parametrize_expr(
+ underlying: ExpressionBaseMixin,
+ name: str = None,
+):
+ if name is None:
+ name = 'undefined'
+
+ return polymatrix.expression.implexpressionbase.ParametrizeExprImpl(
+ underlying=underlying,
+ name=name,
+)
+
+
+def init_parametrize_matrix_expr(
+ underlying: ExpressionBaseMixin,
+ name: str,
+):
+ return polymatrix.expression.implexpressionbase.ParametrizeMatrixExprImpl(
+ underlying=underlying,
+ name=name,
+ )
+
+
+def init_quadratic_in_expr(
+ underlying: ExpressionBaseMixin,
+ monomials: ExpressionBaseMixin,
+ variables: ExpressionBaseMixin,
+ stack: tuple[FrameSummary],
+):
+
+ assert isinstance(variables, ExpressionBaseMixin), f'{variables=}'
+
+ return polymatrix.expression.implexpressionbase.QuadraticInExprImpl(
+ underlying=underlying,
+ monomials=monomials,
+ variables=variables,
+ stack=stack,
+ )
+
+
+def init_quadratic_monomials_expr(
+ underlying: ExpressionBaseMixin,
+ variables: ExpressionBaseMixin,
+):
+
+ assert isinstance(variables, ExpressionBaseMixin), f'{variables=}'
+
+ return polymatrix.expression.implexpressionbase.QuadraticMonomialsExprImpl(
+ underlying=underlying,
+ variables=variables,
+ )
+
+
+def init_rep_mat_expr(
+ underlying: ExpressionBaseMixin,
+ repetition: tuple,
+):
+ return polymatrix.expression.implexpressionbase.RepMatExprImpl(
+ underlying=underlying,
+ repetition=repetition,
+)
+
+
+def init_reshape_expr(
+ underlying: ExpressionBaseMixin,
+ new_shape: tuple,
+):
+ return polymatrix.expression.implexpressionbase.ReshapeExprImpl(
+ underlying=underlying,
+ new_shape=new_shape,
+)
+
+
+def init_set_element_at_expr(
+ underlying: ExpressionBaseMixin,
+ index: tuple,
+ value: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.SetElementAtExprImpl(
+ underlying=underlying,
+ index=index,
+ value=value,
+)
+
+
+def init_squeeze_expr(
+ underlying: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.SqueezeExprImpl(
+ underlying=underlying,
+)
+
+
+def init_substitute_expr(
+ underlying: ExpressionBaseMixin,
+ variables: tuple,
+ values: tuple = None,
+):
+
+ substitutions = format_substitutions(
+ variables=variables,
+ values=values,
+ )
+
+ def formatted_values(value) -> ExpressionBaseMixin:
+ if isinstance(value, ExpressionBaseMixin):
+ expr = value
+
+ else:
+ expr = init_from_expr(value)
+
+ return polymatrix.expression.implexpressionbase.ReshapeExprImpl(
+ underlying=expr,
+ new_shape=(-1, 1),
+ )
+
+ substitutions = tuple((variable, formatted_values(value)) for variable, value in substitutions)
+
+ return polymatrix.expression.implexpressionbase.SubstituteExprImpl(
+ underlying=underlying,
+ substitutions=substitutions,
+ )
+
+
+def init_subtract_monomials_expr(
+ underlying: ExpressionBaseMixin,
+ monomials: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.SubtractMonomialsExprImpl(
+ underlying=underlying,
+ monomials=monomials,
+)
+
+
+def init_sum_expr(
+ underlying: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.SumExprImpl(
+ underlying=underlying,
+)
+
+
+def init_symmetric_expr(
+ underlying: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.SymmetricExprImpl(
+ underlying=underlying,
+)
+
+
+def init_to_constant_expr(
+ underlying: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.ToConstantExprImpl(
+ underlying=underlying,
+)
+
+
+def init_to_quadratic_expr(
+ underlying: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.ToQuadraticExprImpl(
+ underlying=underlying,
+)
+
+
+def init_to_sorted_variables(
+ underlying: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.ToSortedVariablesImpl(
+ underlying=underlying,
+)
+
+
+def init_to_symmetric_matrix_expr(
+ underlying: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.ToSymmetricMatrixExprImpl(
+ underlying=underlying,
+)
+
+
+def init_transpose_expr(
+ underlying: ExpressionBaseMixin,
+):
+ return polymatrix.expression.implexpressionbase.TransposeExprImpl(
+ underlying=underlying,
+)
+
+
+def init_truncate_expr(
+ underlying: ExpressionBaseMixin,
+ variables: ExpressionBaseMixin,
+ degrees: tuple[int],
+ inverse: bool = None,
+):
+ if isinstance(degrees, int):
+ degrees = (degrees,)
+
+ if inverse is None:
+ inverse = False
+
+ return polymatrix.expression.implexpressionbase.TruncateExprImpl(
+ underlying=underlying,
+ variables=variables,
+ degrees=degrees,
+ inverse=inverse,
+ )
+
+
+# def init_v_stack_expr(
+# underlying: tuple,
+# ):
+
+# def gen_underlying():
+
+# for e in underlying:
+# if isinstance(e, ExpressionBaseMixin):
+# yield e
+# else:
+# yield init_from_(e)
+
+# return polymatrix.expression.implexpressionbase.VStackExprImpl(
+# underlying=tuple(gen_underlying()),
+# )
diff --git a/polymatrix/expression/mixins/additionexprmixin.py b/polymatrix/expression/mixins/additionexprmixin.py
index e247ebd..6257d55 100644
--- a/polymatrix/expression/mixins/additionexprmixin.py
+++ b/polymatrix/expression/mixins/additionexprmixin.py
@@ -3,11 +3,13 @@ import math
import typing
import dataclassabc
+from polymatrix.utils.getstacklines import FrameSummary
+from polymatrix.utils.tooperatorexception import to_operator_exception
from polymatrix.polymatrix.init.initpolymatrix import init_poly_matrix
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
from polymatrix.polymatrix.mixins.polymatrixmixin import PolyMatrixMixin
from polymatrix.polymatrix.polymatrix import PolyMatrix
from polymatrix.expressionstate.expressionstate import ExpressionState
+from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
class AdditionExprMixin(ExpressionBaseMixin):
@@ -21,6 +23,11 @@ class AdditionExprMixin(ExpressionBaseMixin):
def right(self) -> ExpressionBaseMixin:
...
+ @property
+ @abc.abstractmethod
+ def stack(self) -> tuple[FrameSummary]:
+ ...
+
# overwrites abstract method of `ExpressionBaseMixin`
def apply(
self,
@@ -54,7 +61,11 @@ class AdditionExprMixin(ExpressionBaseMixin):
all_underlying = (left, broadcasted_right)
else:
- assert left.shape == right.shape, f'{left.shape} != {right.shape}'
+ if not (left.shape == right.shape):
+ raise AssertionError(to_operator_exception(
+ message=f'{left.shape} != {right.shape}',
+ stack=self.stack,
+ ))
all_underlying = (left, right)
diff --git a/polymatrix/expression/mixins/assertdegreeexprmixin.py b/polymatrix/expression/mixins/assertdegreeexprmixin.py
deleted file mode 100644
index e57de1c..0000000
--- a/polymatrix/expression/mixins/assertdegreeexprmixin.py
+++ /dev/null
@@ -1,49 +0,0 @@
-
-import abc
-import itertools
-import dataclassabc
-from polymatrix.polymatrix.mixins.polymatrixmixin import PolyMatrixMixin
-
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-from polymatrix.polymatrix.polymatrix import PolyMatrix
-from polymatrix.expressionstate.expressionstate import ExpressionState
-
-
-class AssertDegreeExprMixin(ExpressionBaseMixin):
- @property
- @abc.abstractmethod
- def underlying(self) -> tuple[ExpressionBaseMixin, ...]:
- ...
-
- @property
- @abc.abstractmethod
- def degrees(self) -> tuple[int, ...]:
- ...
-
- # overwrites abstract method of `ExpressionBaseMixin`
- def apply(
- self,
- state: ExpressionState,
- ) -> tuple[ExpressionState, PolyMatrix]:
-
- state, underlying = self.underlying.apply(state)
-
- @dataclassabc.dataclassabc(frozen=True)
- class AssertDegreePolyMatrix(PolyMatrixMixin):
- underlying: PolyMatrixMixin
- degrees: tuple[int, ...]
-
- def get_poly(self, row: int, col: int) -> dict[tuple[int, ...], float]:
- terms = self.underlying.get_poly(row, col)
-
- for monomial in terms.keys():
- pass
-
- return terms
-
- polymatrix = AssertDegreePolyMatrix(
- underlying=underlying,
- degrees=self.degrees,
- )
-
- return state, polymatrix
diff --git a/polymatrix/expression/mixins/blockdiagexprmixin.py b/polymatrix/expression/mixins/blockdiagexprmixin.py
index b210d27..0bafd0d 100644
--- a/polymatrix/expression/mixins/blockdiagexprmixin.py
+++ b/polymatrix/expression/mixins/blockdiagexprmixin.py
@@ -26,8 +26,6 @@ class BlockDiagExprMixin(ExpressionBaseMixin):
state, polymat = expr.apply(state=state)
all_underlying.append(polymat)
- # assert all(underlying.shape[0] == underlying.shape[1] for underlying in all_underlying)
-
@dataclassabc.dataclassabc(frozen=True)
class BlockDiagPolyMatrix(PolyMatrixMixin):
all_underlying: tuple[PolyMatrixMixin]
diff --git a/polymatrix/expression/mixins/cacheexprmixin.py b/polymatrix/expression/mixins/cacheexprmixin.py
index fe6dbb7..7a92259 100644
--- a/polymatrix/expression/mixins/cacheexprmixin.py
+++ b/polymatrix/expression/mixins/cacheexprmixin.py
@@ -10,6 +10,8 @@ from polymatrix.polymatrix.mixins.polymatrixmixin import PolyMatrixMixin
class CacheExprMixin(ExpressionBaseMixin):
+ """ Caches the polynomial matrix using the state """
+
@property
@abc.abstractclassmethod
def underlying(self) -> ExpressionBaseMixin:
diff --git a/polymatrix/expression/mixins/combinationsexprmixin.py b/polymatrix/expression/mixins/combinationsexprmixin.py
index 4841e8e..a9cc247 100644
--- a/polymatrix/expression/mixins/combinationsexprmixin.py
+++ b/polymatrix/expression/mixins/combinationsexprmixin.py
@@ -1,26 +1,29 @@
import abc
import itertools
-import math
from polymatrix.polymatrix.init.initpolymatrix import init_poly_matrix
from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
from polymatrix.polymatrix.polymatrix import PolyMatrix
from polymatrix.expressionstate.expressionstate import ExpressionState
-from polymatrix.expression.utils.getmonomialindices import get_monomial_indices
-from polymatrix.expression.utils.mergemonomialindices import merge_monomial_indices
-from polymatrix.expression.utils.sortmonomials import sort_monomials
+from polymatrix.expression.utils.multiplymonomials import multiply_monomials
class CombinationsExprMixin(ExpressionBaseMixin):
+ """
+ combination using degrees=(0, 1, 2, 3):
+
+ [[x]] -> [[1], [x], [x**2], [x**3]]
+ """
+
@property
@abc.abstractmethod
- def monomials(self) -> ExpressionBaseMixin:
+ def expression(self) -> ExpressionBaseMixin:
...
@property
@abc.abstractmethod
- def number(self) -> int:
+ def degrees(self) -> tuple[int, ...]:
...
# overwrites abstract method of `ExpressionBaseMixin`
@@ -28,34 +31,82 @@ class CombinationsExprMixin(ExpressionBaseMixin):
self,
state: ExpressionState,
) -> tuple[ExpressionState, PolyMatrix]:
- if self.number == 0:
- terms = {(0, 0): {tuple(): 1.0}}
+ # if self.degree == 0:
+ # terms = {(0, 0): {tuple(): 1.0}}
- poly_matrix = init_poly_matrix(
- terms=terms,
- shape=(1, 1),
- )
+ # poly_matrix = init_poly_matrix(
+ # terms=terms,
+ # shape=(1, 1),
+ # )
+
+ # elif self.degree == 1:
+ # state, monomials = self.expression.apply(state=state)
+ # poly_matrix = monomials
+
+ # else:
+
+ 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)
+
+ indices = tuple(gen_indices())
+
+ terms = {}
- elif self.number == 1:
- state, monomials = self.monomials.apply(state=state)
- poly_matrix = monomials
+ for row, indexing in enumerate(indices):
- else:
+ # print(indexing)
- state, monomials = get_monomial_indices(state, self.monomials)
+ if indexing is tuple():
+ terms[row, 0] = {tuple(): 1.0}
+ continue
- combinations = tuple(itertools.combinations_with_replacement(monomials, self.number))
+ def acc_product(acc, v):
+ left_monomials = acc
+ row = v
- terms = {}
+ right_monomials = poly_matrix.get_poly(row, 0).keys()
+ # print(right_monomials)
- for row, combination in enumerate(combinations):
- combination_monomial = merge_monomial_indices(combination)
+ if left_monomials is (None,):
+ return right_monomials
- terms[row, 0] = {combination_monomial: 1.0}
+ monomials = tuple(multiply_monomials(left_monomials, right_monomials))
+ return monomials
- poly_matrix = init_poly_matrix(
- terms=terms,
- shape=(math.comb(len(monomials) + self.number - 1, self.number), 1),
+ *_, monomials = itertools.accumulate(
+ indexing,
+ acc_product,
+ initial=(None,),
)
+ terms[row, 0] = {m: 1.0 for m in monomials}
+
+ poly_matrix = init_poly_matrix(
+ terms=terms,
+ shape=(len(terms), 1),
+ )
+
+ # indices = filter(lambda v: sum(v) <= self.degree, itertools.product(*(range(self.degree) for _ in range(dim))))
+
+ # state, monomials = get_monomial_indices(state, self.monomials)
+
+ # combinations = tuple(itertools.combinations_with_replacement(monomials, self.number))
+
+ # terms = {}
+
+ # for row, combination in enumerate(combinations):
+ # combination_monomial = merge_monomial_indices(combination)
+
+ # terms[row, 0] = {combination_monomial: 1.0}
+
+ # poly_matrix = init_poly_matrix(
+ # terms=terms,
+ # shape=(math.comb(len(monomials) + self.number - 1, self.number), 1),
+ # )
+
return state, poly_matrix
diff --git a/polymatrix/expression/mixins/derivativeexprmixin.py b/polymatrix/expression/mixins/derivativeexprmixin.py
index 183608b..15873b6 100644
--- a/polymatrix/expression/mixins/derivativeexprmixin.py
+++ b/polymatrix/expression/mixins/derivativeexprmixin.py
@@ -8,9 +8,19 @@ from polymatrix.polymatrix.polymatrix import PolyMatrix
from polymatrix.expressionstate.expressionstate import ExpressionState
from polymatrix.expression.utils.getderivativemonomials import get_derivative_monomials
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
class DerivativeExprMixin(ExpressionBaseMixin):
+ """
+ differentiate w.r.t. x:
+
+ [[x**2]] -> [[2*x]]
+
+ introduce_derivatives: not used at the moment
+ """
+
@property
@abc.abstractmethod
def underlying(self) -> ExpressionBaseMixin:
@@ -26,6 +36,11 @@ class DerivativeExprMixin(ExpressionBaseMixin):
def introduce_derivatives(self) -> bool:
...
+ @property
+ @abc.abstractmethod
+ def stack(self) -> tuple[FrameSummary]:
+ ...
+
# overwrites abstract method of `ExpressionBaseMixin`
def apply(
self,
@@ -35,7 +50,11 @@ class DerivativeExprMixin(ExpressionBaseMixin):
state, underlying = self.underlying.apply(state=state)
state, diff_wrt_variables = get_variable_indices_from_variable(state, self.variables)
- assert underlying.shape[1] == 1, f'{underlying.shape=}'
+ if not (underlying.shape[1] == 1):
+ raise AssertionError(to_operator_exception(
+ message=f'{underlying.shape[1]=} is not 1',
+ stack=self.stack,
+ ))
terms = {}
@@ -52,7 +71,7 @@ class DerivativeExprMixin(ExpressionBaseMixin):
monomial_terms=underlying_terms,
diff_wrt_variable=diff_wrt_variable,
state=state,
- considered_variables=set(),
+ considered_variables=set(diff_wrt_variables),
introduce_derivatives=self.introduce_derivatives,
)
diff --git a/polymatrix/expression/mixins/diagexprmixin.py b/polymatrix/expression/mixins/diagexprmixin.py
index 26c75d0..6651e13 100644
--- a/polymatrix/expression/mixins/diagexprmixin.py
+++ b/polymatrix/expression/mixins/diagexprmixin.py
@@ -6,6 +6,14 @@ from polymatrix.expressionstate.mixins.expressionstatemixin import ExpressionSta
from polymatrix.polymatrix.mixins.polymatrixmixin import PolyMatrixMixin
class DiagExprMixin(ExpressionBaseMixin):
+ """
+ [[1],[2]] -> [[1,0],[0,2]]
+
+ or
+
+ [[1,0],[0,2]] -> [[1],[2]]
+ """
+
@property
@abc.abstractclassmethod
def underlying(self) -> ExpressionBaseMixin:
diff --git a/polymatrix/expression/mixins/divisionexprmixin.py b/polymatrix/expression/mixins/divisionexprmixin.py
index 94bfec1..e236456 100644
--- a/polymatrix/expression/mixins/divisionexprmixin.py
+++ b/polymatrix/expression/mixins/divisionexprmixin.py
@@ -2,6 +2,9 @@
import abc
import dataclasses
+from polymatrix.expression.mixins.elemmultexprmixin import ElemMultExprMixin
+from polymatrix.utils.getstacklines import FrameSummary
+from polymatrix.utils.tooperatorexception import to_operator_exception
from polymatrix.polymatrix.init.initpolymatrix import init_poly_matrix
from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
from polymatrix.polymatrix.polymatrix import PolyMatrix
@@ -19,20 +22,40 @@ class DivisionExprMixin(ExpressionBaseMixin):
def right(self) -> ExpressionBaseMixin:
...
+ @property
+ @abc.abstractmethod
+ def stack(self) -> tuple[FrameSummary]:
+ ...
+
# overwrites abstract method of `ExpressionBaseMixin`
def apply(
self,
state: ExpressionState,
) -> tuple[ExpressionState, PolyMatrix]:
- # add an auxillary equation and, therefore, needs to be cached
- if self in state.cache:
- return state, state.cache[self]
-
state, left = self.left.apply(state=state)
state, right = self.right.apply(state=state)
- assert right.shape == (1, 1)
+ # if left.shape == (1, 1):
+ # left, right = right, left
+
+ # 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,
+ ))
+
+ 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()]}}
+ return ElemMultExprMixin.elem_mult(state, left, right)
+
+ # add an auxillary equation and, therefore, needs to be cached
+ if self in state.cache:
+ return state, state.cache[self]
terms = {}
@@ -53,7 +76,7 @@ class DivisionExprMixin(ExpressionBaseMixin):
terms[row, col] = dict(gen_monomial_terms())
def gen_auxillary_terms():
- for monomial, value in right.get_poly(0, 0).items():
+ for monomial, value in right_poly.items():
yield monomial + ((division_variable, 1),), value
auxillary_terms = dict(gen_auxillary_terms())
diff --git a/polymatrix/expression/mixins/elemmultexprmixin.py b/polymatrix/expression/mixins/elemmultexprmixin.py
index 2edf9e6..37c6f6f 100644
--- a/polymatrix/expression/mixins/elemmultexprmixin.py
+++ b/polymatrix/expression/mixins/elemmultexprmixin.py
@@ -28,14 +28,12 @@ class ElemMultExprMixin(ExpressionBaseMixin):
# def shape(self) -> tuple[int, int]:
# return self.left.shape
- # overwrites abstract method of `ExpressionBaseMixin`
- def apply(
- self,
+ @staticmethod
+ def elem_mult(
state: ExpressionState,
- ) -> tuple[ExpressionState, PolyMatrix]:
- state, left = self.left.apply(state=state)
- state, right = self.right.apply(state=state)
-
+ left: PolyMatrix,
+ right: PolyMatrix,
+ ):
if left.shape != right.shape and left.shape == (1, 1):
left, right = right, left
@@ -95,4 +93,76 @@ class ElemMultExprMixin(ExpressionBaseMixin):
shape=left.shape,
)
- return state, poly_matrix
+ return state, poly_matrix
+
+
+ # overwrites abstract method of `ExpressionBaseMixin`
+ def apply(
+ self,
+ state: ExpressionState,
+ ) -> tuple[ExpressionState, PolyMatrix]:
+ state, left = self.left.apply(state=state)
+ state, right = self.right.apply(state=state)
+
+ return self.elem_mult(state, left, right)
+
+ # if left.shape != right.shape and left.shape == (1, 1):
+ # left, right = right, left
+
+ # if right.shape == (1, 1):
+ # right_poly = right.get_poly(0, 0)
+
+ # @dataclassabc.dataclassabc(frozen=True)
+ # class BroadCastedPolyMatrix(PolyMatrixMixin):
+ # underlying: tuple[tuple[int], float]
+ # shape: tuple[int, int]
+
+ # def get_poly(self, row: int, col: int) -> typing.Optional[dict[tuple[int, ...], float]]:
+ # return self.underlying
+
+ # right = BroadCastedPolyMatrix(
+ # underlying=right_poly,
+ # shape=left.shape,
+ # )
+
+ # terms = {}
+
+ # for poly_row in range(left.shape[0]):
+ # for poly_col in range(left.shape[1]):
+
+ # terms_row_col = {}
+
+ # left_terms = left.get_poly(poly_row, poly_col)
+ # if left_terms is None:
+ # continue
+
+ # right_terms = right.get_poly(poly_row, poly_col)
+ # if right_terms is None:
+ # continue
+
+ # for (left_monomial, left_value), (right_monomial, right_value) \
+ # in itertools.product(left_terms.items(), right_terms.items()):
+
+ # value = left_value * right_value
+
+ # # if value == 0:
+ # # continue
+
+ # # monomial = tuple(sorted(left_monomial + right_monomial))
+
+ # new_monomial = merge_monomial_indices((left_monomial, right_monomial))
+
+ # if new_monomial not in terms_row_col:
+ # terms_row_col[new_monomial] = 0
+
+ # terms_row_col[new_monomial] += value
+
+ # if 0 < len(terms_row_col):
+ # terms[poly_row, poly_col] = terms_row_col
+
+ # poly_matrix = init_poly_matrix(
+ # terms=terms,
+ # shape=left.shape,
+ # )
+
+ # return state, poly_matrix
diff --git a/polymatrix/expression/mixins/expressionbasemixin.py b/polymatrix/expression/mixins/expressionbasemixin.py
index f2f8507..8aedc25 100644
--- a/polymatrix/expression/mixins/expressionbasemixin.py
+++ b/polymatrix/expression/mixins/expressionbasemixin.py
@@ -1,6 +1,7 @@
import abc
-from polymatrix.expressionstate.mixins.expressionstatemixin import ExpressionStateMixin
-from polymatrix.polymatrix.mixins.polymatrixmixin import PolyMatrixMixin
+
+from polymatrix.expressionstate.expressionstate import ExpressionState
+from polymatrix.polymatrix.polymatrix import PolyMatrix
class ExpressionBaseMixin(
@@ -8,5 +9,5 @@ class ExpressionBaseMixin(
):
@abc.abstractmethod
- def apply(self, state: ExpressionStateMixin) -> tuple[ExpressionStateMixin, PolyMatrixMixin]:
+ def apply(self, state: ExpressionState) -> tuple[ExpressionState, PolyMatrix]:
...
diff --git a/polymatrix/expression/mixins/fromsymmetricmatrixexprmixin.py b/polymatrix/expression/mixins/fromsymmetricmatrixexprmixin.py
index 906adf8..395eda9 100644
--- a/polymatrix/expression/mixins/fromsymmetricmatrixexprmixin.py
+++ b/polymatrix/expression/mixins/fromsymmetricmatrixexprmixin.py
@@ -11,6 +11,8 @@ from polymatrix.polymatrix.mixins.polymatrixmixin import PolyMatrixMixin
class FromSymmetricMatrixExprMixin(ExpressionBaseMixin):
+ """ inverse of ToSymmetricMatrixExprMixin """
+
@property
@abc.abstractclassmethod
def underlying(self) -> ExpressionBaseMixin:
diff --git a/polymatrix/expression/mixins/fromsympyexprmixin.py b/polymatrix/expression/mixins/fromtupleexprmixin.py
index 25edde0..4157ce7 100644
--- a/polymatrix/expression/mixins/fromsympyexprmixin.py
+++ b/polymatrix/expression/mixins/fromtupleexprmixin.py
@@ -4,16 +4,25 @@ import math
import sympy
import numpy as np
+from polymatrix.utils.getstacklines import FrameSummary
+from polymatrix.utils.tooperatorexception import to_operator_exception
from polymatrix.polymatrix.init.initpolymatrix import init_poly_matrix
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-from polymatrix.expressionstate.mixins.expressionstatemixin import ExpressionStateMixin
from polymatrix.polymatrix.mixins.polymatrixmixin import PolyMatrixMixin
+from polymatrix.expressionstate.mixins.expressionstatemixin import ExpressionStateMixin
+from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
+
+class FromTupleExprMixin(ExpressionBaseMixin):
+ DATA_TYPE = int | float | np.number | sympy.Expr | ExpressionBaseMixin
-class FromSympyExprMixin(ExpressionBaseMixin):
@property
@abc.abstractmethod
- def data(self) -> tuple[tuple[float]]:
+ def data(self) -> tuple[tuple['FromTupleExprMixin.DATA_TYPE']]:
+ ...
+
+ @property
+ @abc.abstractmethod
+ def stack(self) -> tuple[FrameSummary]:
...
# overwrites abstract method of `ExpressionBaseMixin`
@@ -68,18 +77,24 @@ class FromSympyExprMixin(ExpressionBaseMixin):
polynomial[monomial] = value
- # elif isinstance(poly_data, np.number):
- # terms_row_col = {tuple(): float(poly_data)}
-
elif isinstance(poly_data, ExpressionBaseMixin):
state, instance = poly_data.apply(state)
- assert instance.shape == (1, 1)
+ # assert instance.shape == (1, 1)
+ if not (instance.shape == (1, 1)):
+ raise AssertionError(to_operator_exception(
+ message=f'{instance.shape=} is not (1, 1)',
+ stack=self.stack,
+ ))
polynomial = instance.get_poly(0, 0)
else:
- raise Exception(f'{poly_data=}, {type(poly_data)=}')
+ # raise Exception(f'{poly_data=}, {type(poly_data)=}')
+ 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/legendreseriesmixin.py b/polymatrix/expression/mixins/legendreseriesmixin.py
new file mode 100644
index 0000000..3232207
--- /dev/null
+++ b/polymatrix/expression/mixins/legendreseriesmixin.py
@@ -0,0 +1,62 @@
+import abc
+
+from polymatrix.utils.getstacklines import FrameSummary
+from polymatrix.polymatrix.polymatrix import PolyMatrix
+from polymatrix.polymatrix.init.initpolymatrix import init_poly_matrix
+from polymatrix.expressionstate.expressionstate import ExpressionState
+from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
+
+
+class LegendreSeriesMixin(ExpressionBaseMixin):
+ @property
+ @abc.abstractmethod
+ def underlying(self) -> tuple[ExpressionBaseMixin]:
+ ...
+
+ @property
+ @abc.abstractmethod
+ def degrees(self) -> tuple[int, ...] | None:
+ ...
+
+ @property
+ @abc.abstractmethod
+ def stack(self) -> tuple[FrameSummary]:
+ ...
+
+ # overwrites abstract method of `ExpressionBaseMixin`
+ def apply(
+ 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
+
+ terms = {}
+
+ for degree in degrees:
+ # for degree in self.degree:
+ poly = underlying.get_poly(degree, 0)
+
+ terms[degree, 0] = dict(poly)
+
+ if 2 <= degree:
+ poly = underlying.get_poly(degree - 2, 0)
+ factor = - (degree - 1) / (degree + 1)
+
+ for m, v in poly.items():
+ if m in terms[degree, 0]:
+ terms[degree, 0][m] += v*factor
+ else:
+ terms[degree, 0][m] = v*factor
+
+ poly_matrix = init_poly_matrix(
+ terms=terms,
+ shape=(len(terms), 1),
+ )
+
+ return state, poly_matrix
diff --git a/polymatrix/expression/mixins/matrixmultexprmixin.py b/polymatrix/expression/mixins/matrixmultexprmixin.py
index a02b4f1..98527e7 100644
--- a/polymatrix/expression/mixins/matrixmultexprmixin.py
+++ b/polymatrix/expression/mixins/matrixmultexprmixin.py
@@ -1,14 +1,13 @@
import abc
-import itertools
-import math
+from polymatrix.utils.getstacklines import FrameSummary
from polymatrix.polymatrix.init.initpolymatrix import init_poly_matrix
from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
from polymatrix.polymatrix.polymatrix import PolyMatrix
from polymatrix.expressionstate.expressionstate import ExpressionState
-from polymatrix.expression.utils.mergemonomialindices import merge_monomial_indices
from polymatrix.expression.utils.multiplypolynomial import multiply_polynomial
+from polymatrix.utils.tooperatorexception import to_operator_exception
class MatrixMultExprMixin(ExpressionBaseMixin):
@@ -22,6 +21,11 @@ class MatrixMultExprMixin(ExpressionBaseMixin):
def right(self) -> ExpressionBaseMixin:
...
+ @property
+ @abc.abstractmethod
+ def stack(self) -> tuple[FrameSummary]:
+ ...
+
# overwrites abstract method of `ExpressionBaseMixin`
def apply(
self,
@@ -30,7 +34,13 @@ class MatrixMultExprMixin(ExpressionBaseMixin):
state, left = self.left.apply(state=state)
state, right = self.right.apply(state=state)
- assert left.shape[1] == right.shape[0], f'{left.shape[1]} is not equal to {right.shape[0]}'
+ # 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,
+ ))
terms = {}
diff --git a/polymatrix/expression/mixins/parametrizematrixexprmixin.py b/polymatrix/expression/mixins/parametrizematrixexprmixin.py
index f59ddb7..de7be88 100644
--- a/polymatrix/expression/mixins/parametrizematrixexprmixin.py
+++ b/polymatrix/expression/mixins/parametrizematrixexprmixin.py
@@ -8,7 +8,6 @@ from polymatrix.expressionstate.mixins.expressionstatemixin import ExpressionSta
from polymatrix.polymatrix.mixins.polymatrixmixin import PolyMatrixMixin
-# rename ParametrizeSymmetricMatrixExprMixin
class ParametrizeMatrixExprMixin(ExpressionBaseMixin):
@property
@abc.abstractclassmethod
diff --git a/polymatrix/expression/mixins/productexprmixin.py b/polymatrix/expression/mixins/productexprmixin.py
new file mode 100644
index 0000000..bacd29e
--- /dev/null
+++ b/polymatrix/expression/mixins/productexprmixin.py
@@ -0,0 +1,132 @@
+
+import abc
+import itertools
+
+from polymatrix.utils.getstacklines import FrameSummary
+from polymatrix.utils.tooperatorexception import to_operator_exception
+from polymatrix.polymatrix.init.initpolymatrix import init_poly_matrix
+from polymatrix.polymatrix.polymatrix import PolyMatrix
+from polymatrix.expressionstate.expressionstate import ExpressionState
+from polymatrix.expression.utils.multiplymonomials import multiply_monomials
+from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
+
+
+class ProductExprMixin(ExpressionBaseMixin):
+ @property
+ @abc.abstractmethod
+ def underlying(self) -> tuple[ExpressionBaseMixin]:
+ ...
+
+ @property
+ @abc.abstractmethod
+ def degrees(self) -> tuple[int, ...] | None:
+ ...
+
+ @property
+ @abc.abstractmethod
+ def stack(self) -> tuple[FrameSummary]:
+ ...
+
+ # overwrites abstract method of `ExpressionBaseMixin`
+ def apply(
+ self,
+ state: ExpressionState,
+ ) -> tuple[ExpressionState, PolyMatrix]:
+
+ # if self.number == 0:
+ # terms = {(0, 0): {tuple(): 1.0}}
+
+ # poly_matrix = init_poly_matrix(
+ # terms=terms,
+ # shape=(1, 1),
+ # )
+
+ # elif self.number == 1:
+ # state, monomials = self.monomials.apply(state=state)
+ # poly_matrix = monomials
+
+ # else:
+
+ if len(self.underlying) == 0:
+ terms = {(0,0): {tuple(): 1}}
+
+ else:
+
+ def acc_underlying(acc, v):
+ state, acc_polymatrix = acc
+ underlying = v
+
+ state, poly_matrix = underlying.apply(state=state)
+
+ return state, acc_polymatrix + (poly_matrix,)
+
+ *_, (state, underlying) = itertools.accumulate(
+ self.underlying,
+ acc_underlying,
+ initial=(state, tuple())
+ )
+
+ # highest_degrees = tuple(e.shape[0] for e in underlying)
+
+ # if self.degrees is None:
+ # degrees = range(sum(highest_degrees))
+
+ # else:
+ # degrees = self.degrees
+
+ # max_degree = max(degrees)
+
+ # for poly_matrix in underlying:
+ # if not (max_degree <= poly_matrix.shape[0]):
+ # raise AssertionError(to_operator_exception(
+ # message=f'{poly_matrix.shape[0]} < {max_degree}',
+ # stack=self.stack,
+ # ))
+
+ def gen_indices():
+ 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())
+
+ # indices = filter(lambda v: sum(v) <= self.degree, itertools.product(*(range(self.degree) for _ in range(dim))))
+
+ terms = {}
+
+ for row, indexing in enumerate(indices):
+
+ # print(indexing)
+
+ def acc_product(acc, v):
+ left_monomials = acc
+ polymatrix, row = v
+
+ right_monomials = polymatrix.get_poly(row, 0).keys()
+
+ # print(f'{left_monomials=}')
+ # print(f'{right_monomials=}')
+
+ if left_monomials is (None,):
+ return right_monomials
+
+ return tuple(multiply_monomials(left_monomials, right_monomials))
+
+ *_, monomials = itertools.accumulate(
+ zip(underlying, indexing),
+ acc_product,
+ initial=(None,),
+ )
+
+ terms[row, 0] = {m: 1.0 for m in monomials}
+
+ poly_matrix = init_poly_matrix(
+ terms=terms,
+ shape=(len(terms), 1),
+ )
+
+ return state, poly_matrix
diff --git a/polymatrix/expression/mixins/quadraticinexprmixin.py b/polymatrix/expression/mixins/quadraticinexprmixin.py
index 2b23827..052124f 100644
--- a/polymatrix/expression/mixins/quadraticinexprmixin.py
+++ b/polymatrix/expression/mixins/quadraticinexprmixin.py
@@ -9,6 +9,8 @@ from polymatrix.expressionstate.expressionstate 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.splitmonomialindices import split_monomial_indices
+from polymatrix.utils.getstacklines import FrameSummary
+from polymatrix.utils.tooperatorexception import to_operator_exception
class QuadraticInExprMixin(ExpressionBaseMixin):
@@ -27,6 +29,11 @@ class QuadraticInExprMixin(ExpressionBaseMixin):
def variables(self) -> ExpressionBaseMixin:
...
+ @property
+ @abc.abstractmethod
+ def stack(self) -> tuple[FrameSummary]:
+ ...
+
# overwrites abstract method of `ExpressionBaseMixin`
def apply(
self,
@@ -37,14 +44,23 @@ class QuadraticInExprMixin(ExpressionBaseMixin):
state, sos_monomials = get_monomial_indices(state, self.monomials)
state, variable_indices = get_variable_indices_from_variable(state, self.variables)
- assert underlying.shape == (1, 1), f'underlying shape is {underlying.shape}'
+ # assert underlying.shape == (1, 1), f'underlying shape is {underlying.shape}'
+ if not (underlying.shape == (1, 1)):
+ raise AssertionError(to_operator_exception(
+ message=f'underlying shape is {underlying.shape}',
+ stack=self.stack,
+ ))
terms = collections.defaultdict(lambda: collections.defaultdict(float))
underlying_poly = underlying.get_poly(0, 0)
if underlying_poly is None:
- raise Exception(f'{self.underlying} is empty')
+ 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():
@@ -56,12 +72,20 @@ class QuadraticInExprMixin(ExpressionBaseMixin):
try:
col = sos_monomials.index(left)
except ValueError:
- raise ValueError(f'{left=} not in {sos_monomials=}')
+ raise AssertionError(to_operator_exception(
+ message=f'{left=} not in {sos_monomials=}',
+ stack=self.stack,
+ ))
+ # raise ValueError(f'{left=} not in {sos_monomials=}')
try:
row = sos_monomials.index(right)
except ValueError:
- raise ValueError(f'{right=} not in {sos_monomials=}')
+ raise AssertionError(to_operator_exception(
+ message=f'{right=} not in {sos_monomials=}',
+ stack=self.stack,
+ ))
+ # raise ValueError(f'{right=} not in {sos_monomials=}')
terms[row, col][p_monomial] += value
diff --git a/polymatrix/expression/mixins/substituteexprmixin.py b/polymatrix/expression/mixins/substituteexprmixin.py
index e693de1..432c9c6 100644
--- a/polymatrix/expression/mixins/substituteexprmixin.py
+++ b/polymatrix/expression/mixins/substituteexprmixin.py
@@ -1,10 +1,8 @@
-
import abc
import collections
import itertools
import math
import typing
-from polymatrix.expression.impl.reshapeexprmixin import ReshapeExprImpl
from polymatrix.polymatrix.init.initpolymatrix import init_poly_matrix
from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
@@ -42,13 +40,14 @@ class SubstituteExprMixin(ExpressionBaseMixin):
if indices is None:
return acc
- state, substitution = ReshapeExprImpl(
- underlying=expr,
- new_shape=(-1, 1),
- ).apply(state)
+ state, substitution = expr.apply(state)
+
+ # state, substitution = ReshapeExprImpl(
+ # underlying=expr,
+ # new_shape=(-1, 1),
+ # ).apply(state)
# # todo: improve this?
- # substitution = substitution.reshape(-1, 1)
# assert substitution.shape[1] == 1, f'The substitutions have to be a vector {substitution=}'
def gen_polynomials():
diff --git a/polymatrix/expression/mixins/sumexprmixin.py b/polymatrix/expression/mixins/sumexprmixin.py
index 9957f10..9e12e07 100644
--- a/polymatrix/expression/mixins/sumexprmixin.py
+++ b/polymatrix/expression/mixins/sumexprmixin.py
@@ -10,6 +10,12 @@ from polymatrix.polymatrix.mixins.polymatrixmixin import PolyMatrixMixin
class SumExprMixin(ExpressionBaseMixin):
+ """
+ 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:
diff --git a/polymatrix/expression/mixins/symmetricexprmixin.py b/polymatrix/expression/mixins/symmetricexprmixin.py
index 2677501..2b191db 100644
--- a/polymatrix/expression/mixins/symmetricexprmixin.py
+++ b/polymatrix/expression/mixins/symmetricexprmixin.py
@@ -11,6 +11,12 @@ from polymatrix.expressionstate.expressionstate import ExpressionState
class SymmetricExprMixin(ExpressionBaseMixin):
+ """
+ Maps a square matrix to a symmetric square matrix by taking the average of the diagonal elements.
+
+ [[1, 2], [3, 4]] -> [[1, 2.5], [2.5, 4]]
+ """
+
@property
@abc.abstractmethod
def underlying(self) -> ExpressionBaseMixin:
diff --git a/polymatrix/expression/mixins/toconstantexprmixin.py b/polymatrix/expression/mixins/toconstantexprmixin.py
index ca928c6..91fbb2b 100644
--- a/polymatrix/expression/mixins/toconstantexprmixin.py
+++ b/polymatrix/expression/mixins/toconstantexprmixin.py
@@ -9,6 +9,11 @@ from polymatrix.expressionstate.expressionstate import ExpressionState
class ToConstantExprMixin(ExpressionBaseMixin):
+ """
+ Discards non-constant polynomial coefficients
+
+ [[a + b*x + c*x^2]] -> [[a]]
+ """
@property
@abc.abstractmethod
def underlying(self) -> ExpressionBaseMixin:
diff --git a/polymatrix/expression/mixins/tosortedvariablesmixin.py b/polymatrix/expression/mixins/tosortedvariablesmixin.py
index eb80597..d0a5d79 100644
--- a/polymatrix/expression/mixins/tosortedvariablesmixin.py
+++ b/polymatrix/expression/mixins/tosortedvariablesmixin.py
@@ -8,6 +8,7 @@ from polymatrix.polymatrix.polymatrix import PolyMatrix
from polymatrix.expressionstate.expressionstate import ExpressionState
+# to be deleted?
class ToSortedVariablesExprMixin(ExpressionBaseMixin):
@property
@abc.abstractmethod
diff --git a/polymatrix/expression/mixins/tosymmetricmatrixexprmixin.py b/polymatrix/expression/mixins/tosymmetricmatrixexprmixin.py
index 0d8c6ed..a34c2b3 100644
--- a/polymatrix/expression/mixins/tosymmetricmatrixexprmixin.py
+++ b/polymatrix/expression/mixins/tosymmetricmatrixexprmixin.py
@@ -9,6 +9,12 @@ from polymatrix.polymatrix.mixins.polymatrixmixin import PolyMatrixMixin
class ToSymmetricMatrixExprMixin(ExpressionBaseMixin):
+ """
+ Convert a vector to a symmetric matrix
+
+ [1, 2, 3, 4, 5, 6].T -> [[1, 2, 3], [2, 4, 5], [3, 5, 6]]
+ """
+
@property
@abc.abstractclassmethod
def underlying(self) -> ExpressionBaseMixin:
@@ -24,8 +30,6 @@ class ToSymmetricMatrixExprMixin(ExpressionBaseMixin):
assert underlying.shape[1] == 1
- # state, variable_indices = get_variable_indices_from_variable(state, self.underlying)
-
def invert_binomial_coefficient(val):
idx = 1
sum_val = 1
@@ -38,7 +42,6 @@ class ToSymmetricMatrixExprMixin(ExpressionBaseMixin):
return idx
- # n_row = invert_binomial_coefficient(len(variable_indices))
n_row = invert_binomial_coefficient(underlying.shape[0])
terms = {}
@@ -46,7 +49,6 @@ class ToSymmetricMatrixExprMixin(ExpressionBaseMixin):
for row in range(n_row):
for col in range(row, n_row):
- # terms[row, col] = {((variable_indices[var_index], 1),): 1.0}
terms[row, col] = underlying.get_poly(var_index, 0)
if row != col:
diff --git a/polymatrix/expression/mixins/transposeexprmixin.py b/polymatrix/expression/mixins/transposeexprmixin.py
index 5aa59e2..7c60daa 100644
--- a/polymatrix/expression/mixins/transposeexprmixin.py
+++ b/polymatrix/expression/mixins/transposeexprmixin.py
@@ -12,6 +12,11 @@ from polymatrix.expressionstate.expressionstate import ExpressionState
class TransposeExprMixin(ExpressionBaseMixin):
+ """
+ Transpose the polynomial matrix
+
+ [[1, 2, 3]] -> [[1], [2], [3]]
+ """
@property
@abc.abstractmethod
def underlying(self) -> ExpressionBaseMixin:
diff --git a/polymatrix/expression/mixins/vstackexprmixin.py b/polymatrix/expression/mixins/vstackexprmixin.py
index fd68ca3..e787495 100644
--- a/polymatrix/expression/mixins/vstackexprmixin.py
+++ b/polymatrix/expression/mixins/vstackexprmixin.py
@@ -10,6 +10,12 @@ from polymatrix.expressionstate.expressionstate import ExpressionState
class VStackExprMixin(ExpressionBaseMixin):
+ """
+ Vertical stacking of the underlying polynomial matrices
+
+ [[1, 2]], [[3, 4]] -> [[1, 2], [3, 4]]
+ """
+
@property
@abc.abstractmethod
def underlying(self) -> tuple[ExpressionBaseMixin, ...]:
diff --git a/polymatrix/expression/op.py b/polymatrix/expression/op.py
new file mode 100644
index 0000000..0d98401
--- /dev/null
+++ b/polymatrix/expression/op.py
@@ -0,0 +1,67 @@
+import polymatrix.expression.initexpressionbase
+
+from polymatrix.utils.getstacklines import get_stack_lines
+from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
+
+
+def diff(
+ expression: ExpressionBaseMixin,
+ variables: ExpressionBaseMixin,
+ introduce_derivatives: bool = None,
+) -> ExpressionBaseMixin:
+
+ if not isinstance(variables, ExpressionBaseMixin):
+ variables=polymatrix.expression.initexpressionbase.init_from_expr(variables)
+
+ if introduce_derivatives is None:
+ introduce_derivatives = False
+
+ return polymatrix.expression.implexpressionbase.DerivativeExprImpl(
+ underlying=expression,
+ variables=variables,
+ introduce_derivatives=introduce_derivatives,
+ stack=get_stack_lines(),
+ )
+
+
+def legendre(
+ expression: ExpressionBaseMixin,
+ degrees: tuple[int, ...] = None,
+) -> ExpressionBaseMixin:
+
+ return polymatrix.expression.implexpressionbase.LegendreSeriesImpl(
+ underlying=expression,
+ degrees=degrees,
+ stack=get_stack_lines(),
+ )
+
+
+def linear_in(
+ expression: ExpressionBaseMixin,
+ variables: ExpressionBaseMixin,
+ monomials: ExpressionBaseMixin = None,
+ ignore_unmatched: bool = None,
+) -> ExpressionBaseMixin:
+
+ if monomials is None:
+ monomials = linear_monomials(
+ expression=expression,
+ variables=variables,
+ )
+
+ return polymatrix.expression.implexpressionbase.LinearInExprImpl(
+ underlying=expression,
+ monomials=monomials,
+ variables=variables,
+ ignore_unmatched = ignore_unmatched,
+ )
+
+def linear_monomials(
+ expression: ExpressionBaseMixin,
+ variables: ExpressionBaseMixin,
+) -> ExpressionBaseMixin:
+
+ return polymatrix.expression.implexpressionbase.LinearMonomialsExprImpl(
+ underlying=expression,
+ variables=variables,
+ )
diff --git a/polymatrix/expression/to.py b/polymatrix/expression/to.py
new file mode 100644
index 0000000..53cd8a8
--- /dev/null
+++ b/polymatrix/expression/to.py
@@ -0,0 +1,129 @@
+import sympy
+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.expressionstate.expressionstate import ExpressionState
+from polymatrix.statemonad.init.initstatemonad import init_state_monad
+from polymatrix.statemonad.mixins.statemonadmixin import StateMonadMixin
+
+
+def shape(
+ expr: Expression,
+) -> StateMonadMixin[ExpressionState, tuple[int, ...]]:
+ def func(state: ExpressionState):
+ state, polymatrix = expr.apply(state)
+
+ return state, polymatrix.shape
+
+ return init_state_monad(func)
+
+
+def to_constant_repr(
+ expr: Expression,
+ assert_constant: bool = True,
+) -> StateMonadMixin[ExpressionState, np.ndarray]:
+
+ def func(state: ExpressionState):
+ state, underlying = expr.apply(state)
+
+ A = np.zeros(underlying.shape, dtype=np.double)
+
+ for (row, col), polynomial in underlying.gen_terms():
+ for monomial, value in polynomial.items():
+ if len(monomial) == 0:
+ A[row, col] = value
+
+ elif assert_constant:
+ 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_repr(
+ 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_terms():
+
+ 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=}'
+
+ if isinstance(variable, sympy.core.symbol.Symbol):
+ variable_name = variable.name
+ elif isinstance(variable, (ParametrizeExprMixin, ParametrizeMatrixExprMixin)):
+ variable_name = variable.name
+ elif isinstance(variable, str):
+ variable_name = variable
+ else:
+ 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}')
+
+ # var = get_variable_from_offset(offset)
+ sympy_monomial *= sympy_var**count
+
+ sympy_polynomial += value * sympy_monomial
+
+ A[row, col] = sympy_polynomial
+
+ return state, A
+
+ return init_state_monad(func)
diff --git a/polymatrix/expression/init/initsubstituteexpr.py b/polymatrix/expression/utils/formatsubstitutions.py
index e141d9e..c9b2972 100644
--- a/polymatrix/expression/init/initsubstituteexpr.py
+++ b/polymatrix/expression/utils/formatsubstitutions.py
@@ -1,10 +1,4 @@
import typing
-import numpy as np
-
-from polymatrix.expression.init.initfromsympyexpr import init_from_sympy_expr
-from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-import polymatrix.expression.impl.impl
-
def format_substitutions(
variables: typing.Union[typing.Any, tuple, dict],
@@ -48,28 +42,3 @@ def format_substitutions(
return substitutions
-
-def init_substitute_expr(
- underlying: ExpressionBaseMixin,
- variables: tuple,
- values: tuple = None,
-):
-
- substitutions = format_substitutions(
- variables=variables,
- values=values,
- )
-
- def formatted_values(value) -> ExpressionBaseMixin:
- if isinstance(value, ExpressionBaseMixin):
- return value
-
- else:
- return init_from_sympy_expr(value)
-
- substitutions = tuple((variable, formatted_values(value)) for variable, value in substitutions)
-
- return polymatrix.expression.impl.impl.SubstituteExprImpl(
- underlying=underlying,
- substitutions=substitutions,
- )
diff --git a/polymatrix/expression/utils/getderivativemonomials.py b/polymatrix/expression/utils/getderivativemonomials.py
index 4aa7144..9bc1e1e 100644
--- a/polymatrix/expression/utils/getderivativemonomials.py
+++ b/polymatrix/expression/utils/getderivativemonomials.py
@@ -1,4 +1,6 @@
import collections
+import dataclasses
+import itertools
from polymatrix.expressionstate.expressionstate import ExpressionState
@@ -10,63 +12,66 @@ def get_derivative_monomials(
considered_variables: set,
introduce_derivatives: bool,
):
+
+ @dataclasses.dataclass(frozen=True)
+ class DerivativeKey:
+ variable: int
+ with_respect_to: int
- # if self.introduce_derivatives:
-
- # raise Exception('not implemented')
+ if introduce_derivatives:
- # def gen_new_variables():
- # for monomial in monomial_terms.keys():
- # for var in monomial:
- # if var not in diff_wrt_variables and var not in considered_variables:
- # yield var
+ def gen_new_variables():
+ for monomial in monomial_terms.keys():
+ for var in monomial:
+ if var is not diff_wrt_variable and var not in considered_variables:
+ yield var
- # new_variables = set(gen_new_variables())
+ new_variables = set(gen_new_variables())
- # new_considered_variables = considered_variables | new_variables
+ new_considered_variables = considered_variables | new_variables
- # def acc_state_candidates(acc, new_variable):
- # state, candidates = acc
+ def acc_state_candidates(acc, new_variable):
+ state, candidates = acc
- # @dataclasses.dataclass
- # class DerivativeKey:
- # variable: int
- # with_respect_to: int
+ # key representing the derivative of the variable
+ key = DerivativeKey(
+ variable=new_variable,
+ with_respect_to=diff_wrt_variable,
+ )
+ # register if it doesn't already exist
+ state = state.register(key=key, n_param=1)
- # key = DerivativeKey(
- # variable=new_variable,
- # with_respect_to=diff_wrt_variable,
- # )
- # state = state.register(key=key, n_param=1)
+ # for each new variable we expect an auxillary equation
+ state, auxillary_derivation_terms = get_derivative_monomials(
+ monomial_terms=state.auxillary_equations[new_variable],
+ diff_wrt_variable=diff_wrt_variable,
+ state=state,
+ considered_variables=new_considered_variables,
+ introduce_derivatives=True,
+ )
- # state, auxillary_derivation_terms = get_derivative_terms(
- # monomial_terms=state.auxillary_equations[new_variable],
- # diff_wrt_variable=diff_wrt_variable,
- # state=state,
- # considered_variables=new_considered_variables,
- # )
+ if 1 < len(auxillary_derivation_terms):
+ derivation_variable = state.offset_dict[key][0]
- # if 1 < len(auxillary_derivation_terms):
- # derivation_variable = state.offset_dict[key][0]
+ state = dataclasses.replace(
+ state,
+ auxillary_equations=state.auxillary_equations | {derivation_variable: auxillary_derivation_terms},
+ )
- # state = dataclasses.replace(
- # state,
- # auxillary_equations=state.auxillary_equations | {derivation_variable: auxillary_derivation_terms},
- # )
+ return state, candidates + (new_variable,)
- # return state, candidates + (new_variable,)
+ else:
+ return state, candidates
- # else:
- # return state, candidates
+ *_, (state, confirmed_variables) = itertools.accumulate(
+ new_variables,
+ acc_state_candidates,
+ initial=(state, tuple()),
+ )
- # *_, (state, confirmed_variables) = itertools.accumulate(
- # new_variables,
- # acc_state_candidates,
- # initial=(state, tuple()),
- # )
+ else:
+ confirmed_variables = tuple()
- # else:
- # confirmed_variables = tuple()
derivation_terms = collections.defaultdict(float)
@@ -100,20 +105,21 @@ def get_derivative_monomials(
diff_monomial, value = differentiate_monomial(diff_wrt_variable)
derivation_terms[diff_monomial] += value
- # # only used if introduce_derivatives == True
- # for candidate_variable in monomial_cnt.keys():
- # if candidate_variable in considered_variables or candidate_variable in confirmed_variables:
- # key = init_derivative_key(
- # variable=candidate_variable,
- # with_respect_to=diff_wrt_variable,
- # )
- # derivation_variable = state.offset_dict[key][0]
-
- # diff_monomial, value = differentiate_monomial(
- # dependent_variable=candidate_variable,
- # derivation_variable=derivation_variable,
- # )
- # derivation_terms[diff_monomial] += value
+ # 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:
+ key = DerivativeKey(
+ variable=candidate_variable,
+ with_respect_to=diff_wrt_variable,
+ )
+ derivation_variable = state.offset_dict[key][0]
+
+ diff_monomial, value = differentiate_monomial(
+ dependent_variable=candidate_variable,
+ derivation_variable=derivation_variable,
+ )
+ derivation_terms[diff_monomial] += value
# return state, dict(derivation_terms)
return state, derivation_terms \ No newline at end of file
diff --git a/polymatrix/expression/utils/getmonomialindices.py b/polymatrix/expression/utils/getmonomialindices.py
index 6d6c599..ac6d5f7 100644
--- a/polymatrix/expression/utils/getmonomialindices.py
+++ b/polymatrix/expression/utils/getmonomialindices.py
@@ -1,7 +1,8 @@
+from polymatrix.expressionstate.expressionstate import ExpressionState
from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin
-def get_monomial_indices(state, monomials) -> tuple:
+def get_monomial_indices(state: ExpressionState, monomials: ExpressionBaseMixin) -> tuple[ExpressionState, tuple[int, ...]]:
state, monomials_obj = monomials.apply(state)
diff --git a/polymatrix/expression/utils/multiplymonomials.py b/polymatrix/expression/utils/multiplymonomials.py
new file mode 100644
index 0000000..a4b3273
--- /dev/null
+++ b/polymatrix/expression/utils/multiplymonomials.py
@@ -0,0 +1,15 @@
+import itertools
+import math
+
+from polymatrix.expression.utils.mergemonomialindices import merge_monomial_indices
+
+
+def multiply_monomials(left_monomials, right_monomials):
+ def gen_monomials():
+ for left_monomial, right_monomial in itertools.product(left_monomials, right_monomials):
+
+ monomial = merge_monomial_indices((left_monomial, right_monomial))
+
+ yield monomial
+
+ return gen_monomials()
diff --git a/polymatrix/utils/__init__.py b/polymatrix/utils/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/polymatrix/utils/__init__.py
diff --git a/polymatrix/utils/getstacklines.py b/polymatrix/utils/getstacklines.py
new file mode 100644
index 0000000..6fdd69f
--- /dev/null
+++ b/polymatrix/utils/getstacklines.py
@@ -0,0 +1,23 @@
+import dataclasses
+import traceback
+
+
+@dataclasses.dataclass(frozen=True)
+class FrameSummary:
+ filename: str
+ lineno: int
+ name: str
+ line: str
+
+
+def get_stack_lines(index: int = 2) -> tuple[FrameSummary]:
+ def gen_stack_lines():
+ for obj in traceback.extract_stack()[:-index]:
+ yield FrameSummary(
+ filename=obj.filename,
+ lineno=obj.lineno,
+ name=obj.name,
+ line=obj.line,
+ )
+
+ return tuple(gen_stack_lines())
diff --git a/polymatrix/utils/tooperatorexception.py b/polymatrix/utils/tooperatorexception.py
new file mode 100644
index 0000000..5f7db0f
--- /dev/null
+++ b/polymatrix/utils/tooperatorexception.py
@@ -0,0 +1,14 @@
+from polymatrix.utils.getstacklines import FrameSummary
+
+
+def to_operator_exception(
+ 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),
+ ]
+
+ return '\n'.join(exception_lines)
diff --git a/test_polymatrix/test_expression/test_addition.py b/test_polymatrix/test_expression/test_addition.py
index 6c8a9a2..e3e7f05 100644
--- a/test_polymatrix/test_expression/test_addition.py
+++ b/test_polymatrix/test_expression/test_addition.py
@@ -1,8 +1,7 @@
import unittest
-from polymatrix.expression.init.initadditionexpr import init_addition_expr
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
+import polymatrix.expression.initexpressionbase
class TestAddition(unittest.TestCase):
@@ -28,17 +27,17 @@ class TestAddition(unittest.TestCase):
},
}
- left = init_from_terms_expr(
+ left = polymatrix.expression.initexpressionbase.init_from_terms_expr(
terms=left_terms,
shape=(2, 2),
)
- right = init_from_terms_expr(
+ right = polymatrix.expression.initexpressionbase.init_from_terms_expr(
terms=right_terms,
shape=(2, 2),
)
- expr = init_addition_expr(
+ expr = polymatrix.expression.initexpressionbase.init_addition_expr(
left=left,
right=right,
)
diff --git a/test_polymatrix/test_expression/test_blockdiag.py b/test_polymatrix/test_expression/test_blockdiag.py
index a66935e..4a67c77 100644
--- a/test_polymatrix/test_expression/test_blockdiag.py
+++ b/test_polymatrix/test_expression/test_blockdiag.py
@@ -1,8 +1,7 @@
import unittest
-from polymatrix.expression.init.initblockdiagexpr import init_block_diag_expr
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
+import polymatrix.expression.initexpressionbase
class TestBlockDiag(unittest.TestCase):
@@ -26,10 +25,10 @@ class TestBlockDiag(unittest.TestCase):
},
}
- expr = init_block_diag_expr(
+ expr = polymatrix.expression.initexpressionbase.init_block_diag_expr(
underlying=(
- init_from_terms_expr(terms=terms1, shape=(2, 2),),
- init_from_terms_expr(terms=terms2, shape=(2, 2),),
+ polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=terms1, shape=(2, 2),),
+ polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=terms2, shape=(2, 2),),
),
)
diff --git a/test_polymatrix/test_expression/test_derivative.py b/test_polymatrix/test_expression/test_derivative.py
index 27dfbeb..e8f551b 100644
--- a/test_polymatrix/test_expression/test_derivative.py
+++ b/test_polymatrix/test_expression/test_derivative.py
@@ -1,10 +1,7 @@
import unittest
-from polymatrix.expression.init.initderivativeexpr import init_derivative_expr
-from polymatrix.expression.init.initdivergenceexpr import init_divergence_expr
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
-from polymatrix.expression.init.initlinearinexpr import init_linear_in_expr
+import polymatrix.expression.initexpressionbase
class TestDerivative(unittest.TestCase):
@@ -27,9 +24,9 @@ class TestDerivative(unittest.TestCase):
(2, 0): {((2, 1),): 1},
}
- expr = init_derivative_expr(
- underlying=init_from_terms_expr(terms=underlying_terms, shape=(2, 1)),
- variables=init_from_terms_expr(terms=variable_terms, shape=(3, 1),),
+ expr = polymatrix.expression.initexpressionbase.init_derivative_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=underlying_terms, shape=(2, 1)),
+ variables=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=variable_terms, shape=(3, 1),),
)
state = init_expression_state(n_param=3)
diff --git a/test_polymatrix/test_expression/test_divergence.py b/test_polymatrix/test_expression/test_divergence.py
index 387a30f..2d2b6ad 100644
--- a/test_polymatrix/test_expression/test_divergence.py
+++ b/test_polymatrix/test_expression/test_divergence.py
@@ -1,9 +1,7 @@
import unittest
-from polymatrix.expression.init.initdivergenceexpr import init_divergence_expr
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
-from polymatrix.expression.init.initlinearinexpr import init_linear_in_expr
+import polymatrix.expression.initexpressionbase
class TestDivergence(unittest.TestCase):
@@ -30,9 +28,9 @@ class TestDivergence(unittest.TestCase):
(2, 0): {((2, 1),): 1},
}
- expr = init_divergence_expr(
- underlying=init_from_terms_expr(terms=underlying_terms, shape=(3, 1)),
- variables=init_from_terms_expr(terms=variable_terms, shape=(3, 1),),
+ expr = polymatrix.expression.initexpressionbase.init_divergence_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=underlying_terms, shape=(3, 1)),
+ variables=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=variable_terms, shape=(3, 1),),
)
state = init_expression_state(n_param=2)
diff --git a/test_polymatrix/test_expression/test_eval.py b/test_polymatrix/test_expression/test_eval.py
index 9b9454f..5787f2a 100644
--- a/test_polymatrix/test_expression/test_eval.py
+++ b/test_polymatrix/test_expression/test_eval.py
@@ -1,8 +1,7 @@
import unittest
-from polymatrix.expression.init.initevalexpr import init_eval_expr
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
+import polymatrix.expression.initexpressionbase
class TestEval(unittest.TestCase):
@@ -19,8 +18,8 @@ class TestEval(unittest.TestCase):
},
}
- expr = init_eval_expr(
- underlying=init_from_terms_expr(terms=terms, shape=(2, 1)),
+ expr = polymatrix.expression.initexpressionbase.init_eval_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=terms, shape=(2, 1)),
variables=(0, 1),
values=(2.0, 3.0),
)
diff --git a/test_polymatrix/test_expression/test_linearin.py b/test_polymatrix/test_expression/test_linearin.py
index 572c34c..d0fb0d9 100644
--- a/test_polymatrix/test_expression/test_linearin.py
+++ b/test_polymatrix/test_expression/test_linearin.py
@@ -1,9 +1,8 @@
import unittest
-from polymatrix.expression.init.initfromsympyexpr import init_from_sympy_expr
+from polymatrix.expression.initexpressionbase import init_from_
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
-from polymatrix.expression.init.initlinearinexpr import init_linear_in_expr
+import polymatrix.expression.initexpressionbase
class TestLinearIn(unittest.TestCase):
@@ -36,10 +35,10 @@ class TestLinearIn(unittest.TestCase):
(1, 0): {((1, 1),): 1},
}
- expr = init_linear_in_expr(
- underlying=init_from_terms_expr(terms=underlying_terms, shape=(2, 1)),
- monomials=init_from_terms_expr(terms=monomial_terms, shape=(4, 1),),
- variables=init_from_terms_expr(terms=variable_terms, shape=(2, 1),),
+ expr = polymatrix.expression.initexpressionbase.init_linear_in_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=underlying_terms, shape=(2, 1)),
+ monomials=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=monomial_terms, shape=(4, 1),),
+ variables=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=variable_terms, shape=(2, 1),),
)
state = init_expression_state(n_param=2)
diff --git a/test_polymatrix/test_expression/test_matrixmult.py b/test_polymatrix/test_expression/test_matrixmult.py
index 12d0584..b15f7eb 100644
--- a/test_polymatrix/test_expression/test_matrixmult.py
+++ b/test_polymatrix/test_expression/test_matrixmult.py
@@ -1,9 +1,7 @@
import unittest
-from polymatrix.expression.init.initadditionexpr import init_addition_expr
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
-from polymatrix.expression.init.initmatrixmultexpr import init_matrix_mult_expr
+import polymatrix.expression.initexpressionbase
class TestMatrixMult(unittest.TestCase):
@@ -32,17 +30,17 @@ class TestMatrixMult(unittest.TestCase):
},
}
- left = init_from_terms_expr(
+ left = polymatrix.expression.initexpressionbase.init_from_terms_expr(
terms=left_terms,
shape=(2, 2),
)
- right = init_from_terms_expr(
+ right = polymatrix.expression.initexpressionbase.init_from_terms_expr(
terms=right_terms,
shape=(2, 1),
)
- expr = init_matrix_mult_expr(
+ expr = polymatrix.expression.initexpressionbase.init_matrix_mult_expr(
left=left,
right=right,
)
diff --git a/test_polymatrix/test_expression/test_quadraticin.py b/test_polymatrix/test_expression/test_quadraticin.py
index debf779..7f3767d 100644
--- a/test_polymatrix/test_expression/test_quadraticin.py
+++ b/test_polymatrix/test_expression/test_quadraticin.py
@@ -1,8 +1,7 @@
import unittest
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
-from polymatrix.expression.init.initquadraticinexpr import init_quadratic_in_expr
+import polymatrix.expression.initexpressionbase
class TestQuadraticIn(unittest.TestCase):
@@ -35,10 +34,10 @@ class TestQuadraticIn(unittest.TestCase):
(1, 0): {((1, 1),): 1},
}
- expr = init_quadratic_in_expr(
- underlying=init_from_terms_expr(terms=underlying_terms, shape=(1, 1)),
- monomials=init_from_terms_expr(terms=monomial_terms, shape=(3, 1)),
- variables=init_from_terms_expr(terms=variable_terms, shape=(2, 1),),
+ expr = polymatrix.expression.initexpressionbase.init_quadratic_in_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=underlying_terms, shape=(1, 1)),
+ monomials=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=monomial_terms, shape=(3, 1)),
+ variables=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=variable_terms, shape=(2, 1),),
)
state = init_expression_state(n_param=2)
diff --git a/test_polymatrix/test_expression/test_substitude.py b/test_polymatrix/test_expression/test_substitude.py
index 457d35e..4a1f224 100644
--- a/test_polymatrix/test_expression/test_substitude.py
+++ b/test_polymatrix/test_expression/test_substitude.py
@@ -1,8 +1,7 @@
import unittest
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
-from polymatrix.expression.init.initsubstituteexpr import init_substitute_expr
+import polymatrix.expression.initexpressionbase
class TestEval(unittest.TestCase):
@@ -28,10 +27,10 @@ class TestEval(unittest.TestCase):
(0, 0): {((0, 1),): 1},
}
- expr = init_substitute_expr(
- underlying=init_from_terms_expr(terms=terms, shape=(1, 1)),
- variables=init_from_terms_expr(terms=variable_terms, shape=(1, 1),),
- values=(init_from_terms_expr(terms=substitution, shape=(1, 1)),),
+ expr = polymatrix.expression.initexpressionbase.init_substitute_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=terms, shape=(1, 1)),
+ variables=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=variable_terms, shape=(1, 1),),
+ values=(polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=substitution, shape=(1, 1)),),
)
state = init_expression_state(n_param=2)
diff --git a/test_polymatrix/test_expression/test_subtractmonomials.py b/test_polymatrix/test_expression/test_subtractmonomials.py
index 8cd8585..77fcc84 100644
--- a/test_polymatrix/test_expression/test_subtractmonomials.py
+++ b/test_polymatrix/test_expression/test_subtractmonomials.py
@@ -1,11 +1,7 @@
import unittest
-from polymatrix.expression.init.initderivativeexpr import init_derivative_expr
-from polymatrix.expression.init.initdivergenceexpr import init_divergence_expr
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
-from polymatrix.expression.init.initlinearinexpr import init_linear_in_expr
-from polymatrix.expression.init.initsubtractmonomialsexpr import init_subtract_monomials_expr
+import polymatrix.expression.initexpressionbase
class TestDerivative(unittest.TestCase):
@@ -29,9 +25,9 @@ class TestDerivative(unittest.TestCase):
},
}
- expr = init_subtract_monomials_expr(
- underlying=init_from_terms_expr(terms=monomials1, shape=(2, 1)),
- monomials=init_from_terms_expr(terms=monomials2, shape=(2, 1)),
+ expr = polymatrix.expression.initexpressionbase.init_subtract_monomials_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=monomials1, shape=(2, 1)),
+ monomials=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=monomials2, shape=(2, 1)),
)
state = init_expression_state(n_param=3)
diff --git a/test_polymatrix/test_expression/test_sum.py b/test_polymatrix/test_expression/test_sum.py
index 053e428..27c4766 100644
--- a/test_polymatrix/test_expression/test_sum.py
+++ b/test_polymatrix/test_expression/test_sum.py
@@ -1,9 +1,7 @@
import unittest
-from polymatrix.expression.init.initevalexpr import init_eval_expr
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
-from polymatrix.expression.init.initsumexpr import init_sum_expr
+import polymatrix.expression.initexpressionbase
class TestSum(unittest.TestCase):
@@ -20,8 +18,8 @@ class TestSum(unittest.TestCase):
},
}
- expr = init_sum_expr(
- underlying=init_from_terms_expr(terms=terms, shape=(1, 2)),
+ expr = polymatrix.expression.initexpressionbase.init_sum_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=terms, shape=(1, 2)),
)
state = init_expression_state(n_param=2)
diff --git a/test_polymatrix/test_expression/test_symmetric.py b/test_polymatrix/test_expression/test_symmetric.py
index a93d975..5313ff1 100644
--- a/test_polymatrix/test_expression/test_symmetric.py
+++ b/test_polymatrix/test_expression/test_symmetric.py
@@ -1,9 +1,7 @@
import unittest
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
-from polymatrix.expression.init.initquadraticinexpr import init_quadratic_in_expr
-from polymatrix.expression.init.initsymmetricexpr import init_symmetric_expr
+import polymatrix.expression.initexpressionbase
class TestQuadraticIn(unittest.TestCase):
@@ -22,12 +20,12 @@ class TestQuadraticIn(unittest.TestCase):
},
}
- underlying = init_from_terms_expr(
+ underlying = polymatrix.expression.initexpressionbase.init_from_terms_expr(
terms=terms,
shape=(2, 2),
)
- expr = init_symmetric_expr(
+ expr = polymatrix.expression.initexpressionbase.init_symmetric_expr(
underlying=underlying,
)
diff --git a/test_polymatrix/test_expression/test_toconstant.py b/test_polymatrix/test_expression/test_toconstant.py
index f3a0643..c85c482 100644
--- a/test_polymatrix/test_expression/test_toconstant.py
+++ b/test_polymatrix/test_expression/test_toconstant.py
@@ -1,11 +1,7 @@
import unittest
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
-from polymatrix.expression.init.initquadraticinexpr import init_quadratic_in_expr
-from polymatrix.expression.init.initsymmetricexpr import init_symmetric_expr
-from polymatrix.expression.init.inittoconstantexpr import init_to_constant_expr
-from polymatrix.expression.init.inittruncateexpr import init_truncate_expr
+import polymatrix.expression.initexpressionbase
class TestToConstant(unittest.TestCase):
@@ -27,8 +23,8 @@ class TestToConstant(unittest.TestCase):
},
}
- expr = init_to_constant_expr(
- underlying=init_from_terms_expr(terms=terms, shape=(2, 2)),
+ expr = polymatrix.expression.initexpressionbase.init_to_constant_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=terms, shape=(2, 2)),
)
state = init_expression_state(n_param=2)
diff --git a/test_polymatrix/test_expression/test_truncate.py b/test_polymatrix/test_expression/test_truncate.py
index d6cafbe..c73e98d 100644
--- a/test_polymatrix/test_expression/test_truncate.py
+++ b/test_polymatrix/test_expression/test_truncate.py
@@ -1,10 +1,7 @@
import unittest
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
-from polymatrix.expression.init.initquadraticinexpr import init_quadratic_in_expr
-from polymatrix.expression.init.initsymmetricexpr import init_symmetric_expr
-from polymatrix.expression.init.inittruncateexpr import init_truncate_expr
+import polymatrix.expression.initexpressionbase
class TestTruncate(unittest.TestCase):
@@ -30,9 +27,9 @@ class TestTruncate(unittest.TestCase):
}
- expr = init_truncate_expr(
- underlying=init_from_terms_expr(terms=terms, shape=(2, 2)),
- variables=init_from_terms_expr(terms=variable_terms, shape=(2, 1),),
+ expr = polymatrix.expression.initexpressionbase.init_truncate_expr(
+ underlying=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=terms, shape=(2, 2)),
+ variables=polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=variable_terms, shape=(2, 1),),
degrees=(1, 2),
)
diff --git a/test_polymatrix/test_expression/test_vstack.py b/test_polymatrix/test_expression/test_vstack.py
index 8778f8a..27e52f9 100644
--- a/test_polymatrix/test_expression/test_vstack.py
+++ b/test_polymatrix/test_expression/test_vstack.py
@@ -1,8 +1,7 @@
import unittest
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
-from polymatrix.expression.init.initvstackexpr import init_v_stack_expr
+import polymatrix.expression.initexpressionbase
class TestVStack(unittest.TestCase):
@@ -26,10 +25,10 @@ class TestVStack(unittest.TestCase):
},
}
- expr = init_v_stack_expr(
+ expr = polymatrix.expression.initexpressionbase.init_v_stack_expr(
underlying=(
- init_from_terms_expr(terms=terms1, shape=(2, 2),),
- init_from_terms_expr(terms=terms2, shape=(2, 2),),
+ polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=terms1, shape=(2, 2),),
+ polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=terms2, shape=(2, 2),),
),
)
diff --git a/test_polymatrix/test_tomatrixrepr.py b/test_polymatrix/test_tomatrixrepr.py
index 88a35f2..dc023ca 100644
--- a/test_polymatrix/test_tomatrixrepr.py
+++ b/test_polymatrix/test_tomatrixrepr.py
@@ -1,9 +1,7 @@
import unittest
-import polymatrix
+import polymatrix.expression.initexpressionbase
from polymatrix.expressionstate.init.initexpressionstate import init_expression_state
-from polymatrix.expression.init.initfromtermsexpr import init_from_terms_expr
-from polymatrix.expression.init.initlinearinexpr import init_linear_in_expr
class TestToMatrixRepr(unittest.TestCase):
@@ -29,12 +27,12 @@ class TestToMatrixRepr(unittest.TestCase):
(1, 0): {((1, 1),): 1},
}
- expr = init_from_terms_expr(terms=underlying_terms, shape=(3, 1))
+ expr = polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=underlying_terms, shape=(3, 1))
state = init_expression_state(n_param=2)
state, result = polymatrix.to_matrix_repr(
(expr,),
- init_from_terms_expr(terms=variable_terms, shape=(2, 1),),
+ polymatrix.expression.initexpressionbase.init_from_terms_expr(terms=variable_terms, shape=(2, 1),),
).apply(state)
A0 = result.data[0][0]