Source code for qiskit_dynamics.systems.subsystem_mapping
# This code is part of Qiskit.## (C) Copyright IBM 2025.## This code is licensed under the Apache License, Version 2.0. You may# obtain a copy of this license in the LICENSE.txt file in the root directory# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.## Any modifications or derivative works of this code must retain this# copyright notice, and modified files need to carry a notice indicating# that they have been altered from the originals.# pylint: disable=invalid-name"""Mappings on subsystems."""fromtypingimportOptional,Union,ListfromqiskitimportQiskitErrorimportnumpyasnpfromqiskit_dynamicsimportDYNAMICS_NUMPYasunpfromqiskit_dynamics.systemsimportSubsystem,quantum_system_modelfrom.abstract_subsystem_operatorsimportAbstractSubsystemOperator
[docs]classSubsystemMapping:r"""A linear mapping from a list of subsystems representing a tensor product space to another. This class represents a linear map :math:`A : V_1 \otimes \dots \otimes V_n \rightarrow W_1 \otimes \dots \otimes W_m`, where :math:`A` is specified as a matrix, and the tensor factors of both the input and output spaces are given as lists of :class:`Subsystem` instances. The main usage is for mapping abstract operators or :class:`QuantumSystemModel` instances: the :meth:`.conjugate` method, or simply treating the mapping as ``Callable``, conjugates an operator or all operators within the :class:`QuantumSystemModel` by :math:`A`. As usual, for any subsystems in the ``in_subsystems`` of the mapping that the operator are not explicitly defined on, the operator is assumed to act as the identity. See the :ref:`How-to use advanced system modelling functionality <systems modelling userguide>` userguide entry for example usage of this class. """def__init__(self,matrix:np.ndarray,in_subsystems:Union[Subsystem,List[Subsystem]],out_subsystems:Optional[Union[Subsystem,List[Subsystem]]]=None,):"""Initialize. Args: matrix: The matrix form of the linear map. in_subsystems: The list of input subsystems. out_subsystems: The list of output subsystems. """ifin_subsystemsisNoneorin_subsystems==[]:raiseQiskitError("in_subsystems cannot be None or [] for SystemMapping.")ifisinstance(in_subsystems,Subsystem):in_subsystems=[in_subsystems]ifisinstance(out_subsystems,Subsystem):out_subsystems=[out_subsystems]elifout_subsystemsisNone:out_subsystems=in_subsystemsself._in_subsystems=in_subsystemsself._out_subsystems=out_subsystemsin_dim=np.prod([x.dimforxinin_subsystems])out_dim=np.prod([x.dimforxinout_subsystems])ifmatrix.shape!=(out_dim,in_dim):raiseQiskitError("matrix.shape does not match input and output dimensions.")self._matrix=matrixself._matrix_adj=matrix.conj().transpose()@propertydefin_subsystems(self):"""Subsystems for input to the mapping."""returnself._in_subsystems@propertydefout_subsystems(self):"""Subsystems for mapping output."""returnself._out_subsystems@propertydefmatrix(self):"""Concrete matrix encoding the action of the mapping."""returnself._matrix
[docs]defconjugate(self,operator:Union[AbstractSubsystemOperator,"quantum_system_model.QuantumSystemModel"]):r"""Conjugate a subsystem operator or model. Returns a subsystem operator representing :math:`A O A^\dagger`, where :math:`A` is the mapping matrix, and :math:`O` is the input operator. If applied to a :class:`QuantumSystemModel`, the mapping is applied to all operators in the model. Args: operator: The operator to be conjugated. Returns: Union[MappedOperator, QuantumSystemModel]: The conjugated operator or model. """ifisinstance(operator,AbstractSubsystemOperator):returnMappedOperator(operator,self)eliftype(operator).__name__=="QuantumSystemModel":returnoperator._map_model(lambdax:MappedOperator(x,self))raiseQiskitError(f"Input of type {type(operator)} not recognized by SubsystemMapping.conjugate.")
def__call__(self,operator:Union[AbstractSubsystemOperator,"quantum_system_model.QuantumSystemModel"]):"""Apply the conjugation function."""returnself.conjugate(operator)
classMappedOperator(AbstractSubsystemOperator):"""An operator mapped by a SystemMapping."""def__init__(self,operator,system_mapping):"""Initialize."""self._operator=operatorself._system_mapping=system_mapping# validate that none of the out_subsystems of system_mapping are in the operator definitionifany(sinsystem_mapping.out_subsystemsforsinoperator.subsystems):raiseQiskitError("Output subsystem found in input operator subsystems.")unmapped_subsystems=[]forsinoperator.subsystems:ifsnotinsystem_mapping.in_subsystems:unmapped_subsystems.append(s)self._unmapped_subsystems=unmapped_subsystemssuper().__init__(system_mapping.out_subsystems+unmapped_subsystems)@propertydefoperator(self):"""The operator being mapped."""returnself._operator@propertydefsystem_mapping(self):"""The system mapping being applied to the operator."""returnself._system_mapping@propertydefunmapped_subsystems(self):"""Subsystems of underlying operator unaffected by mapping."""returnself._unmapped_subsystemsdefbase_matrix(self):mat=self._operator.matrix(self.system_mapping.in_subsystems+self.unmapped_subsystems)A=self.system_mapping.matrixiflen(self.unmapped_subsystems)>0:unmapped_dim=np.prod([x.dimforxinself.unmapped_subsystems])A=unp.kron(np.eye(unmapped_dim,dtype=complex),A)returnA@mat@A.conj().transpose()def__str__(self):returnf"""MappedOperator({self._operator}, {self.system_mapping.in_subsystems} ->{self.system_mapping.out_subsystems})"""