Example #1
0
    def _del_derived(self):
        r"""
        Delete the derived quantities.

        EXAMPLES::

            sage: M = FiniteRankFreeModule(QQ, 3, name='M')
            sage: e = M.basis('e')
            sage: a = M.automorphism(name='a')
            sage: a[e,:] = [[1,0,-1], [0,3,0], [0,0,2]]
            sage: b = a.inverse()
            sage: a._inverse
            Automorphism a^(-1) of the 3-dimensional vector space M over the
             Rational Field
            sage: a._del_derived()
            sage: a._inverse  # has been reset to None

        """
        # First delete the derived quantities pertaining to FreeModuleTensor:
        FreeModuleTensor._del_derived(self)
        # Then reset the inverse automorphism to None:
        if self._inverse is not None:
            self._inverse._inverse = None  # (it was set to self)
            self._inverse = None
        # and delete the matrices:
        self._matrices.clear()
Example #2
0
    def __init__(self, fmodule, degree, name=None, latex_name=None):
        r"""
        Initialize ``self``.

        TESTS::

            sage: from sage.tensor.modules.free_module_alt_form import FreeModuleAltForm
            sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
            sage: e = M.basis('e')
            sage: a = FreeModuleAltForm(M, 2, name='a')
            sage: a[e,0,1] = 2
            sage: TestSuite(a).run(skip="_test_category") # see below

        In the above test suite, _test_category fails because a is not an
        instance of a.parent().category().element_class. Actually alternating
        forms must be constructed via ExtPowerFreeModule.element_class and
        not by a direct call to FreeModuleAltForm::

            sage: a1 = M.dual_exterior_power(2).element_class(M, 2, name='a')
            sage: a1[e,0,1] = 2
            sage: TestSuite(a1).run()

        """
        FreeModuleTensor.__init__(self, fmodule, (0,degree), name=name,
                                  latex_name=latex_name, antisym=range(degree),
                                  parent=fmodule.dual_exterior_power(degree))
        FreeModuleAltForm._init_derived(self) # initialization of derived
Example #3
0
    def __init__(self, fmodule, degree, name=None, latex_name=None):
        r"""
        Initialize ``self``.

        TESTS::

            sage: from sage.tensor.modules.alternating_contr_tensor import AlternatingContrTensor
            sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
            sage: e = M.basis('e')
            sage: a = AlternatingContrTensor(M, 2, name='a')
            sage: a[e,0,1] = 2
            sage: TestSuite(a).run(skip="_test_category") # see below

        In the above test suite, _test_category fails because a is not an
        instance of a.parent().category().element_class. Actually alternating
        tensors must be constructed via ExtPowerFreeModule.element_class and
        not by a direct call to AlternatingContrTensor::

            sage: a1 = M.exterior_power(2).element_class(M, 2, name='a')
            sage: a1[e,0,1] = 2
            sage: TestSuite(a1).run()

        """
        FreeModuleTensor.__init__(self,
                                  fmodule, (degree, 0),
                                  name=name,
                                  latex_name=latex_name,
                                  antisym=range(degree),
                                  parent=fmodule.exterior_power(degree))
    def __init__(self, fmodule, degree, name=None, latex_name=None):
        r"""
        Initialize ``self``.

        TESTS::

            sage: from sage.tensor.modules.free_module_alt_form import FreeModuleAltForm
            sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
            sage: e = M.basis('e')
            sage: a = FreeModuleAltForm(M, 2, name='a')
            sage: a[e,0,1] = 2
            sage: TestSuite(a).run(skip="_test_category") # see below

        In the above test suite, _test_category fails because a is not an
        instance of a.parent().category().element_class. Actually alternating
        forms must be constructed via ExtPowerDualFreeModule.element_class and
        not by a direct call to FreeModuleAltForm::

            sage: a1 = M.dual_exterior_power(2).element_class(M, 2, name='a')
            sage: a1[e,0,1] = 2
            sage: TestSuite(a1).run()

        """
        FreeModuleTensor.__init__(self, fmodule, (0,degree), name=name,
                                  latex_name=latex_name,
                                  antisym=range(degree),
                                  parent=fmodule.dual_exterior_power(degree))
Example #5
0
    def _del_derived(self):
        r"""
        Delete the derived quantities.

        EXAMPLES::

            sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
            sage: a = M.alternating_form(2)
            sage: a._del_derived()

        """
        FreeModuleTensor._del_derived(self)
Example #6
0
    def _del_derived(self):
        r"""
        Delete the derived quantities.

        EXAMPLES::

            sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
            sage: a = M.alternating_form(2)
            sage: a._del_derived()

        """
        FreeModuleTensor._del_derived(self)
Example #7
0
    def __init__(self, fmodule, name=None, latex_name=None, is_identity=False):
        r"""
        TESTS::

            sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
            sage: e = M.basis('e')
            sage: from sage.tensor.modules.free_module_automorphism import FreeModuleAutomorphism
            sage: a = FreeModuleAutomorphism(M, name='a')
            sage: a[e,:] = [[-1,0,0],[0,1,2],[0,1,3]]
            sage: TestSuite(a).run(skip="_test_category") # see below

        In the above test suite, _test_category fails because a is not an
        instance of a.parent().category().element_class. Actually automorphism
        must be constructed via FreeModuleLinearGroup.element_class and
        not by a direct call to FreeModuleAutomorphism::

            sage: a = M.general_linear_group().element_class(M, name='a')
            sage: a[e,:] = [[-1,0,0],[0,1,2],[0,1,3]]
            sage: TestSuite(a).run()

        Test suite on the identity map::

            sage: id = M.general_linear_group().one()
            sage: TestSuite(id).run()

        Test suite on the automorphism obtained as GL.an_element()::

            sage: b = M.general_linear_group().an_element()
            sage: TestSuite(b).run()

        """
        if is_identity:
            if name is None:
                name = 'Id'
            if latex_name is None:
                if name == 'Id':
                    latex_name = r'\mathrm{Id}'
                else:
                    latex_name = name
        FreeModuleTensor.__init__(self,
                                  fmodule, (1, 1),
                                  name=name,
                                  latex_name=latex_name,
                                  parent=fmodule.general_linear_group())
        # MultiplicativeGroupElement attributes:
        # - none
        # Local attributes:
        self._is_identity = is_identity
        self._inverse = None  # inverse automorphism not set yet
        self._matrices = {}
    def __init__(self, fmodule, name=None, latex_name=None, is_identity=False):
        r"""
        TESTS::

            sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
            sage: e = M.basis('e')
            sage: from sage.tensor.modules.free_module_automorphism import FreeModuleAutomorphism
            sage: a = FreeModuleAutomorphism(M, name='a')
            sage: a[e,:] = [[-1,0,0],[0,1,2],[0,1,3]]
            sage: TestSuite(a).run(skip="_test_category") # see below

        In the above test suite, _test_category fails because a is not an
        instance of a.parent().category().element_class. Actually automorphism
        must be constructed via FreeModuleLinearGroup.element_class and
        not by a direct call to FreeModuleAutomorphism::

            sage: a = M.general_linear_group().element_class(M, name='a')
            sage: a[e,:] = [[-1,0,0],[0,1,2],[0,1,3]]
            sage: TestSuite(a).run()

        Test suite on the identity map::

            sage: id = M.general_linear_group().one()
            sage: TestSuite(id).run()

        Test suite on the automorphism obtained as GL.an_element()::

            sage: b = M.general_linear_group().an_element()
            sage: TestSuite(b).run()

        """
        if is_identity:
            if name is None:
                name = 'Id'
            if latex_name is None:
                if name == 'Id':
                    latex_name = r'\mathrm{Id}'
                else:
                    latex_name = name
        FreeModuleTensor.__init__(self, fmodule, (1,1), name=name,
                                  latex_name=latex_name,
                                  parent=fmodule.general_linear_group())
        # MultiplicativeGroupElement attributes:
        # - none
        # Local attributes:
        self._is_identity = is_identity
        self._inverse = None    # inverse automorphism not set yet
        self._matrices = {}
Example #9
0
    def __mul__(self, other):
        r"""
        Redefinition of
        :meth:`~sage.tensor.modules.free_module_tensor.FreeModuleTensor.__mul__`
        so that * dispatches either to automorphism composition or to the
        tensor product.

        EXAMPLES:

        Automorphism composition::

            sage: M = FiniteRankFreeModule(ZZ, 2, name='M')
            sage: e = M.basis('e')
            sage: a = M.automorphism([[1,2],[1,3]])
            sage: b = M.automorphism([[3,4],[5,7]])
            sage: s = a*b ; s
            Automorphism of the Rank-2 free module M over the Integer Ring
            sage: s.matrix()
            [13 18]
            [18 25]
            sage: s.matrix() == a.matrix() * b.matrix()
            True
            sage: s(e[0]) == a(b(e[0]))
            True
            sage: s(e[1]) == a(b(e[1]))
            True
            sage: s.display()
            13 e_0*e^0 + 18 e_0*e^1 + 18 e_1*e^0 + 25 e_1*e^1

        Tensor product::

            sage: c =  M.tensor((1,1)) ; c
            Type-(1,1) tensor on the Rank-2 free module M over the Integer Ring
            sage: c[:] = [[3,4],[5,7]]
            sage: c[:] == b[:]  # c and b have the same components
            True
            sage: s = a*c ; s
            Type-(2,2) tensor on the Rank-2 free module M over the Integer Ring
            sage: s.display()
            3 e_0*e_0*e^0*e^0 + 4 e_0*e_0*e^0*e^1 + 6 e_0*e_0*e^1*e^0
             + 8 e_0*e_0*e^1*e^1 + 5 e_0*e_1*e^0*e^0 + 7 e_0*e_1*e^0*e^1
             + 10 e_0*e_1*e^1*e^0 + 14 e_0*e_1*e^1*e^1 + 3 e_1*e_0*e^0*e^0
             + 4 e_1*e_0*e^0*e^1 + 9 e_1*e_0*e^1*e^0 + 12 e_1*e_0*e^1*e^1
             + 5 e_1*e_1*e^0*e^0 + 7 e_1*e_1*e^0*e^1 + 15 e_1*e_1*e^1*e^0
             + 21 e_1*e_1*e^1*e^1

        """
        if isinstance(other, FreeModuleAutomorphism):
            return self._mul_(other)  # general linear group law
        else:
            return FreeModuleTensor.__mul__(self, other)  # tensor product
Example #10
0
    def __mul__(self, other):
        r"""
        Redefinition of
        :meth:`~sage.tensor.modules.free_module_tensor.FreeModuleTensor.__mul__`
        so that * dispatches either to automorphism composition or to the
        tensor product.

        EXAMPLES:

        Automorphism composition::

            sage: M = FiniteRankFreeModule(ZZ, 2, name='M')
            sage: e = M.basis('e')
            sage: a = M.automorphism([[1,2],[1,3]])
            sage: b = M.automorphism([[3,4],[5,7]])
            sage: s = a*b ; s
            Automorphism of the Rank-2 free module M over the Integer Ring
            sage: s.matrix()
            [13 18]
            [18 25]
            sage: s.matrix() == a.matrix() * b.matrix()
            True
            sage: s(e[0]) == a(b(e[0]))
            True
            sage: s(e[1]) == a(b(e[1]))
            True
            sage: s.display()
            13 e_0*e^0 + 18 e_0*e^1 + 18 e_1*e^0 + 25 e_1*e^1

        Tensor product::

            sage: c =  M.tensor((1,1)) ; c
            Type-(1,1) tensor on the Rank-2 free module M over the Integer Ring
            sage: c[:] = [[3,4],[5,7]]
            sage: c[:] == b[:]  # c and b have the same components
            True
            sage: s = a*c ; s
            Type-(2,2) tensor on the Rank-2 free module M over the Integer Ring
            sage: s.display()
            3 e_0*e_0*e^0*e^0 + 4 e_0*e_0*e^0*e^1 + 6 e_0*e_0*e^1*e^0
             + 8 e_0*e_0*e^1*e^1 + 5 e_0*e_1*e^0*e^0 + 7 e_0*e_1*e^0*e^1
             + 10 e_0*e_1*e^1*e^0 + 14 e_0*e_1*e^1*e^1 + 3 e_1*e_0*e^0*e^0
             + 4 e_1*e_0*e^0*e^1 + 9 e_1*e_0*e^1*e^0 + 12 e_1*e_0*e^1*e^1
             + 5 e_1*e_1*e^0*e^0 + 7 e_1*e_1*e^0*e^1 + 15 e_1*e_1*e^1*e^0
             + 21 e_1*e_1*e^1*e^1

        """
        if isinstance(other, FreeModuleAutomorphism):
            return self._mul_(other)  # general linear group law
        else:
            return FreeModuleTensor.__mul__(self, other)  # tensor product
Example #11
0
    def _new_comp(self, basis):
        r"""
        Create some (uninitialized) components of ``self`` in a given basis.

        INPUT:

        - ``basis`` -- basis of the free module on which ``self`` is defined

        OUTPUT:

        - an instance of :class:`~sage.tensor.modules.comp.Components` or,
          if ``self`` is the identity, of the subclass
          :class:`~sage.tensor.modules.comp.KroneckerDelta`

        EXAMPLES::

            sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
            sage: e = M.basis('e')
            sage: a = M.automorphism()
            sage: a._new_comp(e)
            2-indices components w.r.t. Basis (e_0,e_1,e_2) on the Rank-3 free
             module M over the Integer Ring
            sage: id = M.identity_map()
            sage: id._new_comp(e)
            Kronecker delta of size 3x3
            sage: type(id._new_comp(e))
            <class 'sage.tensor.modules.comp.KroneckerDelta'>

        """
        from .comp import KroneckerDelta

        if self._is_identity:
            fmodule = self._fmodule
            return KroneckerDelta(
                fmodule._ring, basis, start_index=fmodule._sindex, output_formatter=fmodule._output_formatter
            )
        return FreeModuleTensor._new_comp(self, basis)
Example #12
0
    def _new_comp(self, basis):
        r"""
        Create some (uninitialized) components of ``self`` in a given basis.

        INPUT:

        - ``basis`` -- basis of the free module on which ``self`` is defined

        OUTPUT:

        - an instance of :class:`~sage.tensor.modules.comp.Components` or,
          if ``self`` is the identity, of the subclass
          :class:`~sage.tensor.modules.comp.KroneckerDelta`

        EXAMPLES::

            sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
            sage: e = M.basis('e')
            sage: a = M.automorphism()
            sage: a._new_comp(e)
            2-indices components w.r.t. Basis (e_0,e_1,e_2) on the Rank-3 free
             module M over the Integer Ring
            sage: id = M.identity_map()
            sage: id._new_comp(e)
            Kronecker delta of size 3x3
            sage: type(id._new_comp(e))
            <class 'sage.tensor.modules.comp.KroneckerDelta'>

        """
        from comp import KroneckerDelta
        if self._is_identity:
            fmodule = self._fmodule
            return KroneckerDelta(fmodule._ring,
                                  basis,
                                  start_index=fmodule._sindex,
                                  output_formatter=fmodule._output_formatter)
        return FreeModuleTensor._new_comp(self, basis)
Example #13
0
    def __call__(self, *arg):
        r"""
        Redefinition of :meth:`FreeModuleTensor.__call__` to allow for a single
        argument (module element).

        EXAMPLES:

        Call with a single argument: return a module element::

            sage: M = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1)
            sage: e = M.basis('e')
            sage: a = M.automorphism([[-1,0,0],[0,1,2],[0,1,3]], name='a')
            sage: v = M([2,1,4], name='v')
            sage: s = a.__call__(v) ; s
            Element a(v) of the Rank-3 free module M over the Integer Ring
            sage: s.display()
            a(v) = -2 e_1 + 9 e_2 + 13 e_3
            sage: s == a(v)
            True
            sage: s == a.contract(v)
            True

        Call with two arguments (:class:`FreeModuleTensor` behaviour): return a
        scalar::

            sage: b = M.linear_form(name='b')
            sage: b[:] = 7, 0, 2
            sage: a.__call__(b,v)
            12
            sage: a(b,v) == a.__call__(b,v)
            True
            sage: a(b,v) == s(b)
            True

        Identity map with a single argument: return a module element::

            sage: id = M.identity_map()
            sage: s = id.__call__(v) ; s
            Element v of the Rank-3 free module M over the Integer Ring
            sage: s == v
            True
            sage: s == id(v)
            True
            sage: s == id.contract(v)
            True

        Identity map with two arguments (:class:`FreeModuleTensor` behaviour):
        return a scalar::

            sage: id.__call__(b,v)
            22
            sage: id(b,v) == id.__call__(b,v)
            True
            sage: id(b,v) == b(v)
            True

        """
        from .free_module_tensor import FiniteRankFreeModuleElement
        if len(arg) > 1:
            # The automorphism acting as a type-(1,1) tensor on a pair
            # (linear form, module element), returning a scalar:
            if self._is_identity:
                if len(arg) != 2:
                    raise TypeError("wrong number of arguments")
                linform = arg[0]
                if linform._tensor_type != (0,1):
                    raise TypeError("the first argument must be a linear form")
                vector = arg[1]
                if not isinstance(vector, FiniteRankFreeModuleElement):
                    raise TypeError("the second argument must be a module" +
                                    " element")
                return linform(vector)
            else: # self is not the identity automorphism:
                return FreeModuleTensor.__call__(self, *arg)
        # The automorphism acting as such, on a module element, returning a
        # module element:
        vector = arg[0]
        if not isinstance(vector, FiniteRankFreeModuleElement):
            raise TypeError("the argument must be an element of a free module")
        if self._is_identity:
            return vector
        basis = self.common_basis(vector)
        t = self._components[basis]
        v = vector._components[basis]
        fmodule = self._fmodule
        result = vector._new_instance()
        for i in fmodule.irange():
            res = 0
            for j in fmodule.irange():
                res += t[[i,j]]*v[[j]]
            result.set_comp(basis)[i] = res
        # Name of the output:
        result._name = None
        if self._name is not None and vector._name is not None:
            result._name = self._name + "(" + vector._name + ")"
        # LaTeX symbol for the output:
        result._latex_name = None
        if self._latex_name is not None and vector._latex_name is not None:
            result._latex_name = self._latex_name + r"\left(" + \
                              vector._latex_name + r"\right)"
        return result
Example #14
0
    def add_comp(self, basis=None):
        r"""

        Return the components of ``self`` w.r.t. a given module basis for
        assignment, keeping the components w.r.t. other bases.

        To delete the components w.r.t. other bases, use the method
        :meth:`set_comp` instead.

        INPUT:

        - ``basis`` -- (default: ``None``) basis in which the components are
          defined; if none is provided, the components are assumed to refer to
          the module's default basis

        .. WARNING::

            If the automorphism has already components in other bases, it
            is the user's responsability to make sure that the components
            to be added are consistent with them.

        OUTPUT:

        - components in the given basis, as an instance of the
          class :class:`~sage.tensor.modules.comp.Components`;
          if such components did not exist previously, they are created

        EXAMPLES:

        Adding components to an automorphism of a rank-3 free
        `\ZZ`-module::

            sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
            sage: e = M.basis('e')
            sage: a = M.automorphism(name='a')
            sage: a[e,:] = [[1,0,0],[0,-1,2],[0,1,-3]]
            sage: f = M.basis('f', from_family=(-e[0], 3*e[1]+4*e[2],
            ....:                               5*e[1]+7*e[2])) ; f
            Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer
             Ring
            sage: a.add_comp(f)[:] = [[1,0,0], [0, 80, 143], [0, -47, -84]]

        The components in basis ``e`` have been kept::

            sage: a._components # random (dictionary output)
            {Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer
             Ring: 2-indices components w.r.t. Basis (e_0,e_1,e_2) on the
             Rank-3 free module M over the Integer Ring,
             Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer
             Ring: 2-indices components w.r.t. Basis (f_0,f_1,f_2) on the
             Rank-3 free module M over the Integer Ring}

        For the identity map, it is not permitted to invoke :meth:`add_comp`::

            sage: id = M.identity_map()
            sage: id.add_comp(e)
            Traceback (most recent call last):
            ...
            TypeError: the components of the identity map cannot be changed

        Indeed, the components are automatically set by a call to
        :meth:`comp`::

            sage: id.comp(e)
            Kronecker delta of size 3x3
            sage: id.comp(f)
            Kronecker delta of size 3x3

        """
        if self._is_identity:
            raise TypeError("the components of the identity map cannot be " +
                            "changed")
        else:
            return FreeModuleTensor.add_comp(self, basis=basis)
Example #15
0
    def set_comp(self, basis=None):
        r"""
        Return the components of ``self`` w.r.t. a given module basis for
        assignment.

        The components with respect to other bases are deleted, in order to
        avoid any inconsistency. To keep them, use the method :meth:`add_comp`
        instead.

        INPUT:

        - ``basis`` -- (default: ``None``) basis in which the components are
          defined; if none is provided, the components are assumed to refer to
          the module's default basis

        OUTPUT:

        - components in the given basis, as an instance of the
          class :class:`~sage.tensor.modules.comp.Components`; if such
          components did not exist previously, they are created.

        EXAMPLES:

        Setting the components of an automorphism of a rank-3 free
        `\ZZ`-module::

            sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
            sage: e = M.basis('e')
            sage: a = M.automorphism(name='a')
            sage: a.set_comp(e)
            2-indices components w.r.t. Basis (e_0,e_1,e_2) on the Rank-3 free
             module M over the Integer Ring
            sage: a.set_comp(e)[:] = [[1,0,0],[0,1,2],[0,1,3]]
            sage: a.matrix(e)
            [1 0 0]
            [0 1 2]
            [0 1 3]

        Since ``e`` is the module's default basis, one has::

            sage: a.set_comp() is a.set_comp(e)
            True

        The method :meth:`set_comp` can be used to modify a single component::

            sage: a.set_comp(e)[0,0] = -1
            sage: a.matrix(e)
            [-1  0  0]
            [ 0  1  2]
            [ 0  1  3]

        A short cut to :meth:`set_comp` is the bracket operator, with the basis
        as first argument::

            sage: a[e,:] = [[1,0,0],[0,-1,2],[0,1,-3]]
            sage: a.matrix(e)
            [ 1  0  0]
            [ 0 -1  2]
            [ 0  1 -3]
            sage: a[e,0,0] = -1
            sage: a.matrix(e)
            [-1  0  0]
            [ 0 -1  2]
            [ 0  1 -3]

        The call to :meth:`set_comp` erases the components previously defined
        in other bases; to keep them, use the method :meth:`add_comp` instead::

            sage: f = M.basis('f', from_family=(-e[0], 3*e[1]+4*e[2],
            ....:                               5*e[1]+7*e[2])) ; f
            Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer
             Ring
            sage: a._components
            {Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer
             Ring: 2-indices components w.r.t. Basis (e_0,e_1,e_2) on the
             Rank-3 free module M over the Integer Ring}
            sage: a.set_comp(f)[:] = [[-1,0,0], [0,1,0], [0,0,-1]]

        The components w.r.t. basis ``e`` have been erased::

            sage: a._components
            {Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer
             Ring: 2-indices components w.r.t. Basis (f_0,f_1,f_2) on the
             Rank-3 free module M over the Integer Ring}

        Of course, they can be computed from those in basis ``f`` by means of
        a change-of-basis formula, via the method :meth:`comp` or
        :meth:`matrix`::

            sage: a.matrix(e)
            [ -1   0   0]
            [  0  41 -30]
            [  0  56 -41]

        For the identity map, it is not permitted to set components::

            sage: id = M.identity_map()
            sage: id.set_comp(e)
            Traceback (most recent call last):
            ...
            TypeError: the components of the identity map cannot be changed

        Indeed, the components are automatically set by a call to
        :meth:`comp`::

            sage: id.comp(e)
            Kronecker delta of size 3x3
            sage: id.comp(f)
            Kronecker delta of size 3x3

        """
        if self._is_identity:
            raise TypeError("the components of the identity map cannot be " +
                            "changed")
        else:
            return FreeModuleTensor.set_comp(self, basis=basis)
Example #16
0
    def components(self, basis=None, from_basis=None):
        r"""
        Return the components of ``self`` w.r.t to a given module basis.

        If the components are not known already, they are computed by the
        tensor change-of-basis formula from components in another basis.

        INPUT:

        - ``basis`` -- (default: ``None``) basis in which the components are
          required; if none is provided, the components are assumed to refer
          to the module's default basis
        - ``from_basis`` -- (default: ``None``) basis from which the
          required components are computed, via the tensor change-of-basis
          formula, if they are not known already in the basis ``basis``;
          if none, a basis from which both the components and a change-of-basis
          to ``basis`` are known is selected.

        OUTPUT:

        - components in the basis ``basis``, as an instance of the
          class :class:`~sage.tensor.modules.comp.Components`,
          or, for the identity automorphism, of the subclass
          :class:`~sage.tensor.modules.comp.KroneckerDelta`

        EXAMPLES:

        Components of an automorphism on a rank-3 free `\ZZ`-module::

            sage: M = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1)
            sage: e = M.basis('e')
            sage: a = M.automorphism([[-1,0,0],[0,1,2],[0,1,3]], name='a')
            sage: a.components(e)
            2-indices components w.r.t. Basis (e_1,e_2,e_3) on the Rank-3 free
             module M over the Integer Ring
            sage: a.components(e)[:]
            [-1  0  0]
            [ 0  1  2]
            [ 0  1  3]

        Since e is the module's default basis, it can be omitted::

            sage: a.components() is a.components(e)
            True

        A shortcut is ``a.comp()``::

            sage: a.comp() is a.components()
            True
            sage: a.comp(e) is a.components()
            True

        Components in another basis::

            sage: f1 = -e[2]
            sage: f2 = 4*e[1] + 3*e[3]
            sage: f3 = 7*e[1] + 5*e[3]
            sage: f = M.basis('f', from_family=(f1,f2,f3))
            sage: a.components(f)
            2-indices components w.r.t. Basis (f_1,f_2,f_3) on the Rank-3 free
             module M over the Integer Ring
            sage: a.components(f)[:]
            [  1  -6 -10]
            [ -7  83 140]
            [  4 -48 -81]

        Some check of the above matrix::

            sage: a(f[1]).display(f)
            a(f_1) = f_1 - 7 f_2 + 4 f_3
            sage: a(f[2]).display(f)
            a(f_2) = -6 f_1 + 83 f_2 - 48 f_3
            sage: a(f[3]).display(f)
            a(f_3) = -10 f_1 + 140 f_2 - 81 f_3

        Components of the identity map::

            sage: id = M.identity_map()
            sage: id.components(e)
            Kronecker delta of size 3x3
            sage: id.components(e)[:]
            [1 0 0]
            [0 1 0]
            [0 0 1]
            sage: id.components(f)
            Kronecker delta of size 3x3
            sage: id.components(f)[:]
            [1 0 0]
            [0 1 0]
            [0 0 1]

        """
        if self._is_identity:
            if basis is None:
                basis = self._fmodule._def_basis
            if basis not in self._components:
                self._components[basis] = self._new_comp(basis)
            return self._components[basis]
        else:
            return FreeModuleTensor.components(self, basis=basis,
                                               from_basis=from_basis)