Creating subclasses of SymbolicRing

asked 2023-01-16 20:30:59 +0100

updated 2023-05-19 14:29:17 +0100

FrédéricC gravatar image

I would like to create a subclass of SymbolicRing to allow variables that are indexed without shoving this information into the variables names, e.g. I would prefer not to use variables with names like x_1_1_1 and I would like to be able to access the indices without parsing the name.

This seems to be supported using _repr_element_, e.g. CallableSymbolicExpressionRing overrides this method. I would like to implement this with minimal change to SymbolicRing or Expression as the only functionality I want to change is how the expressions are displayed and the addition of a variable keeping track of the indices.

When I try to do this, the resulting expressions revert back after applying any operations... Any advice would be appreciated!

from sage.all import *
from sage.symbolic.ring import SymbolicRing
from sage.symbolic.expression import Expression

class IndexedExpression(Expression):
    def __init__(self, var_name, indices):
        formatted_var_name = var_name + "_" + "_".join(str(i) for i in indices)
        super().__init__(SR, SR.var(formatted_var_name))

        self._name = var_name
        self._indices = indices
        self._parent = SR

    def _repr_(self):
        return self._parent._repr_element_(self)

class IndexedSymbolicExpressionRing(SymbolicRing):
    def var(self, var_name, indices):
        expr = IndexedExpression(var_name, indices)
        expr._parent = self
        return expr

    def _repr_(self):
        return "Indexed Symbolic Expression Ring"

    def _repr_element_(self, x):
        return f"{x._name}{x._indices}"

ISR = IndexedSymbolicExpressionRing()

y = ISR.var("y", [1, 1])
print(y)  # y[1, 1]
print(y + y)  # 2*y_1_1 instead of 2*y[1, 1]
edit retag flag offensive close merge delete