Ask Your Question

Revision history [back]

Here's an Action class:

from sage.categories.action import Action
from sage.groups.matrix_gps.matrix_group import is_MatrixGroup
from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing

class InverseLinearMapSubstitutionAction(Action):
    def __init__(self, G, S):
        if not is_MatrixGroup(G):
            raise TypeError("Not a matrix group: %s" % G)
        if not is_MPolynomialRing(S):
            raise TypeError("Not a multivariate polynomial ring: %s" % S)
        if not == S.ngens():
            raise ValueError("Degree of matrix group (%d) does not match number of generators of polynomial ring (%d)" % (, S.ngens()))
        if not S.base_ring().has_coerce_map_from(G.base_ring()):
            raise ValueError("Base rings not compatible")
        super().__init__(G, S, is_left=True, op=operator.mul)

    def _act_(self, g, f):
        return f(*(g.inverse() * vector(self.domain(), self.domain().gens())))

    def _repr_name_(self):
        return "inverse linear map substitution action"

It works:

sage: R.<x,y> = PolynomialRing(QQ)
sage: G = GL(2, QQ)
sage: a = InverseLinearMapSubstitutionAction(G, R); a
Left inverse linear map substitution action by General Linear Group of degree 2 over Rational Field on Multivariate Polynomial Ring in x, y over Rational Field
sage: M = Matrix(QQ, [[0,-1],[1,0]])
sage: f = x + y
sage: a(M, f)
-x + y

The next step to get the notation M*f working would be to call register_action on R. However M*f is already defined to be a matrix over the polynomial ring, and I don't know how to undo or get around this.