Group, ring, etc. actions on objects

The terminology and notation used is suggestive of groups acting on sets, but this framework can be used for modules, algebras, etc.

A group action \(G \times S \rightarrow S\) is a functor from \(G\) to Sets.

Warning

An Action object only keeps a weak reference to the underlying set which is acted upon. This decision was made in Issue #715 in order to allow garbage collection within the coercion framework (this is where actions are mainly used) and avoid memory leaks.

sage: from sage.categories.action import Action
sage: class P: pass
sage: A = Action(P(),P())
sage: import gc
sage: _ = gc.collect()
sage: A
<repr(<sage.categories.action.Action at 0x...>) failed:
 RuntimeError: This action acted on a set that became garbage collected>
>>> from sage.all import *
>>> from sage.categories.action import Action
>>> class P: pass
>>> A = Action(P(),P())
>>> import gc
>>> _ = gc.collect()
>>> A
<repr(<sage.categories.action.Action at 0x...>) failed:
 RuntimeError: This action acted on a set that became garbage collected>
from sage.categories.action import Action
class P: pass
A = Action(P(),P())
import gc
_ = gc.collect()
A

To avoid garbage collection of the underlying set, it is sufficient to create a strong reference to it before the action is created.

sage: _ = gc.collect()
sage: from sage.categories.action import Action
sage: class P: pass
sage: q = P()
sage: A = Action(P(),q)
sage: gc.collect()
0
sage: A
Left action by <__main__.P ... at ...> on <__main__.P ... at ...>
>>> from sage.all import *
>>> _ = gc.collect()
>>> from sage.categories.action import Action
>>> class P: pass
>>> q = P()
>>> A = Action(P(),q)
>>> gc.collect()
0
>>> A
Left action by <__main__.P ... at ...> on <__main__.P ... at ...>
_ = gc.collect()
from sage.categories.action import Action
class P: pass
q = P()
A = Action(P(),q)
gc.collect()
A

AUTHOR:

  • Robert Bradshaw: initial version

class sage.categories.action.Action[source]

Bases: Functor

The action of G on S.

INPUT:

  • G – a parent or Python type

  • S – a parent or Python type

  • is_left – boolean (default: True); whether elements of G are on the left

  • op – (default: None) operation. This is not used by Action itself, but other classes may use it

G[source]
act(g, x)[source]

This is a consistent interface for acting on x by g, regardless of whether it’s a left or right action.

If needed, g and x are converted to the correct parent.

EXAMPLES:

sage: R.<x> = ZZ []
sage: from sage.structure.coerce_actions import IntegerMulAction
sage: A = IntegerMulAction(ZZ, R, True)   # Left action
sage: A.act(5, x)
5*x
sage: A.act(int(5), x)
5*x
sage: A = IntegerMulAction(ZZ, R, False)  # Right action
sage: A.act(5, x)
5*x
sage: A.act(int(5), x)
5*x
>>> from sage.all import *
>>> R = ZZ ['x']; (x,) = R._first_ngens(1)
>>> from sage.structure.coerce_actions import IntegerMulAction
>>> A = IntegerMulAction(ZZ, R, True)   # Left action
>>> A.act(Integer(5), x)
5*x
>>> A.act(int(Integer(5)), x)
5*x
>>> A = IntegerMulAction(ZZ, R, False)  # Right action
>>> A.act(Integer(5), x)
5*x
>>> A.act(int(Integer(5)), x)
5*x
R.<x> = ZZ []
from sage.structure.coerce_actions import IntegerMulAction
A = IntegerMulAction(ZZ, R, True)   # Left action
A.act(5, x)
A.act(int(5), x)
A = IntegerMulAction(ZZ, R, False)  # Right action
A.act(5, x)
A.act(int(5), x)
actor()[source]
codomain()[source]
domain()[source]
is_left()[source]
left_domain()[source]
op[source]
operation()[source]
right_domain()[source]
class sage.categories.action.ActionEndomorphism[source]

Bases: Morphism

The endomorphism defined by the action of one element.

EXAMPLES:

sage: A = ZZ['x'].get_action(QQ, self_on_left=False, op=operator.mul)
sage: A
Left scalar multiplication by Rational Field
 on Univariate Polynomial Ring in x over Integer Ring
sage: A(1/2)
Action of 1/2 on Univariate Polynomial Ring in x over Integer Ring
under Left scalar multiplication by Rational Field on Univariate
Polynomial Ring in x over Integer Ring.
>>> from sage.all import *
>>> A = ZZ['x'].get_action(QQ, self_on_left=False, op=operator.mul)
>>> A
Left scalar multiplication by Rational Field
 on Univariate Polynomial Ring in x over Integer Ring
>>> A(Integer(1)/Integer(2))
Action of 1/2 on Univariate Polynomial Ring in x over Integer Ring
under Left scalar multiplication by Rational Field on Univariate
Polynomial Ring in x over Integer Ring.
A = ZZ['x'].get_action(QQ, self_on_left=False, op=operator.mul)
A
A(1/2)
class sage.categories.action.InverseAction[source]

Bases: Action

An action that acts as the inverse of the given action.

EXAMPLES:

sage: V = QQ^3                                                                  # needs sage.modules
sage: v = V((1, 2, 3))                                                          # needs sage.modules
sage: cm = get_coercion_model()

sage: # needs sage.modules
sage: a = cm.get_action(V, QQ, operator.mul)
sage: a
Right scalar multiplication by Rational Field
 on Vector space of dimension 3 over Rational Field
sage: ~a
Right inverse action by Rational Field
 on Vector space of dimension 3 over Rational Field
sage: (~a)(v, 1/3)
(3, 6, 9)

sage: # needs sage.modules
sage: b = cm.get_action(QQ, V, operator.mul)
sage: b
Left scalar multiplication by Rational Field
 on Vector space of dimension 3 over Rational Field
sage: ~b
Left inverse action by Rational Field
 on Vector space of dimension 3 over Rational Field
sage: (~b)(1/3, v)
(3, 6, 9)

sage: c = cm.get_action(ZZ, list, operator.mul)
sage: c
Left action by Integer Ring on <... 'list'>
sage: ~c
Traceback (most recent call last):
...
TypeError: no inverse defined for Left action by Integer Ring on <... 'list'>
>>> from sage.all import *
>>> V = QQ**Integer(3)                                                                  # needs sage.modules
>>> v = V((Integer(1), Integer(2), Integer(3)))                                                          # needs sage.modules
>>> cm = get_coercion_model()

>>> # needs sage.modules
>>> a = cm.get_action(V, QQ, operator.mul)
>>> a
Right scalar multiplication by Rational Field
 on Vector space of dimension 3 over Rational Field
>>> ~a
Right inverse action by Rational Field
 on Vector space of dimension 3 over Rational Field
>>> (~a)(v, Integer(1)/Integer(3))
(3, 6, 9)

>>> # needs sage.modules
>>> b = cm.get_action(QQ, V, operator.mul)
>>> b
Left scalar multiplication by Rational Field
 on Vector space of dimension 3 over Rational Field
>>> ~b
Left inverse action by Rational Field
 on Vector space of dimension 3 over Rational Field
>>> (~b)(Integer(1)/Integer(3), v)
(3, 6, 9)

>>> c = cm.get_action(ZZ, list, operator.mul)
>>> c
Left action by Integer Ring on <... 'list'>
>>> ~c
Traceback (most recent call last):
...
TypeError: no inverse defined for Left action by Integer Ring on <... 'list'>
V = QQ^3                                                                  # needs sage.modules
v = V((1, 2, 3))                                                          # needs sage.modules
cm = get_coercion_model()
# needs sage.modules
a = cm.get_action(V, QQ, operator.mul)
a
~a
(~a)(v, 1/3)
# needs sage.modules
b = cm.get_action(QQ, V, operator.mul)
b
~b
(~b)(1/3, v)
c = cm.get_action(ZZ, list, operator.mul)
c
~c
codomain()[source]
class sage.categories.action.PrecomposedAction[source]

Bases: Action

A precomposed action first applies given maps, and then applying an action to the return values of the maps.

EXAMPLES:

We demonstrate that an example discussed on Issue #14711 did not become a problem:

sage: # needs sage.libs.flint sage.modular
sage: E = ModularSymbols(11).2
sage: s = E.modular_symbol_rep()
sage: del E,s
sage: import gc
sage: _ = gc.collect()
sage: E = ModularSymbols(11).2
sage: v = E.manin_symbol_rep()
sage: c,x = v[0]
sage: y = x.modular_symbol_rep()
sage: coercion_model.get_action(QQ, parent(y), op=operator.mul)
Left scalar multiplication by Rational Field
 on Abelian Group of all Formal Finite Sums over Rational Field
 with precomposition on right by Coercion map:
  From: Abelian Group of all Formal Finite Sums over Integer Ring
  To:   Abelian Group of all Formal Finite Sums over Rational Field
>>> from sage.all import *
>>> # needs sage.libs.flint sage.modular
>>> E = ModularSymbols(Integer(11)).gen(2)
>>> s = E.modular_symbol_rep()
>>> del E,s
>>> import gc
>>> _ = gc.collect()
>>> E = ModularSymbols(Integer(11)).gen(2)
>>> v = E.manin_symbol_rep()
>>> c,x = v[Integer(0)]
>>> y = x.modular_symbol_rep()
>>> coercion_model.get_action(QQ, parent(y), op=operator.mul)
Left scalar multiplication by Rational Field
 on Abelian Group of all Formal Finite Sums over Rational Field
 with precomposition on right by Coercion map:
  From: Abelian Group of all Formal Finite Sums over Integer Ring
  To:   Abelian Group of all Formal Finite Sums over Rational Field
# needs sage.libs.flint sage.modular
E = ModularSymbols(11).2
s = E.modular_symbol_rep()
del E,s
import gc
_ = gc.collect()
E = ModularSymbols(11).2
v = E.manin_symbol_rep()
c,x = v[0]
y = x.modular_symbol_rep()
coercion_model.get_action(QQ, parent(y), op=operator.mul)
codomain()[source]
domain()[source]
left_precomposition

The left map to precompose with, or None if there is no left precomposition map.

right_precomposition

The right map to precompose with, or None if there is no right precomposition map.