"""
return self.codomain().from_vector(self.matrix()*x.to_vector())
+ def _composition_(self, other, homset):
+ """
+ Compose two clan operators to get another one (and NOT a formal
+ composite object) back.
+
+ SETUP::
+
+ sage: from mjo.clan.clan_operator import ClanOperator
+ sage: from mjo.clan.clan import HnClan, SnClan, VinbergClan
+
+ EXAMPLES::
+
+ sage: C1 = VinbergClan()
+ sage: C2 = HnClan(2)
+ sage: C3 = SnClan(2)
+ sage: mat1 = matrix(QQ, [[1,2,3,4,5],
+ ....: [6,7,8,9,0],
+ ....: [1,2,3,4,5],
+ ....: [6,7,8,9,0]])
+ sage: mat2 = matrix(QQ, [[1,2,3,4],
+ ....: [5,6,7,8],
+ ....: [9,0,1,2]])
+ sage: g = ClanOperator(C1, C2, mat1)
+ sage: f = ClanOperator(C2, C3, mat2)
+ sage: f*g
+ Clan operator represented by the matrix:
+ [ 40 50 60 70 20]
+ [ 96 122 148 174 60]
+ [ 22 34 46 58 50]
+ Domain: Vinberg clan over Rational Field
+ Codomain: Clan S^2 over Rational Field
+
+ """
+ return ClanOperator(
+ other.domain(),
+ self.codomain(),
+ self.matrix()*other.matrix())
+
+ def __mul__(self, other):
+ """
+ Compose two clan operators, or scale myself by an element of the
+ ambient vector space.
+
+ We need to override the real ``__mul__`` function to prevent the
+ coercion framework from throwing an error when it fails to convert
+ a base ring element into a morphism.
+
+ SETUP::
+
+ sage: from mjo.clan.clan import HnClan
+ sage: from mjo.clan.clan_operator import ClanOperator
+
+ EXAMPLES:
+
+ We can scale an operator on a rational algebra by a rational number::
+
+ sage: C = HnClan(2)
+ sage: b0,b1,b2,b3 = C.gens()
+ sage: x = 4*b0 + 8*b1 + 32*b2 + 64*b3
+ sage: x.operator()
+ Clan operator represented by the matrix:
+ [ 4 0 0 0]
+ [ 8 34 0 0]
+ [32 0 34 0]
+ [ 0 16 64 64]
+ Domain: Clan H^2 over Rational Field
+ Codomain: Clan H^2 over Rational Field
+ sage: x.operator()*(1/2)
+ Clan operator represented by the matrix:
+ [ 2 0 0 0]
+ [ 4 17 0 0]
+ [16 0 17 0]
+ [ 0 8 32 32]
+ Domain: Clan H^2 over Rational Field
+ Codomain: Clan H^2 over Rational Field
+
+ """
+ try:
+ if other in self.codomain().base_ring():
+ return ClanOperator(
+ self.domain(),
+ self.codomain(),
+ self.matrix()*other)
+ except NotImplementedError:
+ # This can happen with certain arguments if the base_ring()
+ # is weird and doesn't know how to test membership.
+ pass
+
+ # This should eventually delegate to _composition_ after performing
+ # some sanity checks for us.
+ return super().__mul__(other)
+
+ def __pow__(self, n):
+ """
+ Raise this clan operator to the power ``n``.
+
+ SETUP::
+
+ sage: from mjo.clan.clan_operator import ClanOperator
+ sage: from mjo.clan.clan import HnClan, SnClan
+
+ EXAMPLES::
+
+ sage: C = SnClan(2)
+ sage: f = C.random_element().operator()
+ sage: f^0
+ Clan operator represented by the matrix:
+ [1 0 0]
+ [0 1 0]
+ [0 0 1]
+ Domain: Clan S^2 over Rational Field
+ Codomain: Clan S^2 over Rational Field
+ sage: id = C.one().operator()
+ sage: id^2
+ Clan operator represented by the matrix:
+ [1 0 0]
+ [0 1 0]
+ [0 0 1]
+ Domain: Clan S^2 over Rational Field
+ Codomain: Clan S^2 over Rational Field
+
+ TESTS:
+
+ Exponentiation doesn't work when the domain and codomain
+ differ, even if their dimensions are compatible::
+
+ sage: C1 = SnClan(1)
+ sage: C2 = HnClan(1)
+ sage: I = C1.one().operator().matrix()
+ sage: L = ClanOperator(C1, C2, I)
+ sage: L^2
+ Traceback (most recent call last):
+ ...
+ TypeError: ...domain must equal right...
+
+ """
+ if (n == 1):
+ return self
+ elif (n == 0):
+ # Raising a vector space morphism to the zero power gives
+ # you back a special IdentityMorphism that is useless to us.
+ mat = self.matrix()**self.base_ring().zero()
+ return ClanOperator(self.domain(), self.codomain(), mat)
+
+ # Actually multiply them for n >= 2 so that the domain and
+ # codomain checks in __mul__ aren't skipped (as they would be
+ # if we simply exponentiated the matrix).
+ from functools import reduce
+ from itertools import repeat
+ from operator import mul
+ return reduce(mul, repeat(self, n))
+
def _repr_(self):
r"""