Source code for quara.objects.composite_system

import copy
import itertools
from typing import List, Tuple, Union

import numpy as np

from quara.objects.elemental_system import ElementalSystem
from quara.objects.matrix_basis import MatrixBasis, get_comp_basis


[docs]class CompositeSystem: """Class for describing Composite system""" def __init__(self, systems: List[ElementalSystem]): """Constructor Parameters ---------- systems : List[ElementalSystem] list of ElementalSystem of this CompositeSystem. Raises ------ ValueError duplicate ElementalSystem instance. ValueError duplicate ElementalSystem name. """ # Validation # Check for duplicate ElementalSystem names: List[int] = [] e_sys_ids: List[int] = [] for e_sys in systems: if e_sys.system_id in e_sys_ids: raise ValueError( f"Duplicate ElementalSystem. \n system_id={e_sys.system_id}, name={e_sys.name}" ) e_sys_ids.append(e_sys.system_id) if e_sys.name in names: raise ValueError(f"Duplicate ElementalSystem name. name={e_sys.name}") names.append(e_sys.name) # Sort by name of ElementalSystem # Copy to avoid affecting the original source. # ElementalSystem should remain the same instance as the original source # to check if the instances are the same in the tensor product calculation. # Therefore, use `copy.copy` instead of `copy.deepcopy`. sored_e_syses = copy.copy(systems) sored_e_syses.sort(key=lambda x: x.name) # Set self._elemental_systems: Tuple[ElementalSystem, ...] = tuple(sored_e_syses) is_orthonormal_hermitian_0thpropIs = [ e_sys.is_orthonormal_hermitian_0thprop_identity for e_sys in self._elemental_systems ] self._is_orthonormal_hermitian_0thprop_identity = all( is_orthonormal_hermitian_0thpropIs ) is_hermitian_list = [e_sys.is_hermitian for e_sys in self._elemental_systems] self._is_basis_hermitian = all(is_hermitian_list)
[docs] def comp_basis(self) -> MatrixBasis: """returns computational basis of CompositeSystem. Returns ------- MatrixBasis computational basis of CompositeSystem. """ # calculate tensor product of ElamentalSystem list for getting new MatrixBasis basis_tmp: MatrixBasis if len(self._elemental_systems) == 1: basis_tmp = self._elemental_systems[0].comp_basis else: """ basis_list = [e_sys.comp_basis for e_sys in self._elemental_systems] temp = basis_list[0] for elem in basis_list[1:]: temp = [ np.kron(val1, val2) for val1, val2 in itertools.product(temp, elem) ] basis_tmp = MatrixBasis(temp) """ basis_tmp = get_comp_basis(self.dim) return basis_tmp
[docs] def basis(self) -> MatrixBasis: """returns MatrixBasis of CompositeSystem. Returns ------- MatrixBasis MatrixBasis of CompositeSystem. """ # calculate tensor product of ElamentalSystem list for getting new MatrixBasis basis_tmp: MatrixBasis if len(self._elemental_systems) == 1: basis_tmp = self._elemental_systems[0].basis else: basis_list = [e_sys.basis for e_sys in self._elemental_systems] temp = basis_list[0] for elem in basis_list[1:]: temp = [ np.kron(val1, val2) for val1, val2 in itertools.product(temp, elem) ] basis_tmp = MatrixBasis(temp) return basis_tmp
@property def dim(self) -> int: """returns dim of CompositeSystem. the dim of CompositeSystem equals the dim of basis. Returns ------- int dim of CompositeSystem. """ return self.basis()[0].shape[0] @property def num_e_sys(self) -> int: """returns the number of ElementalSystem. the number of ElementalSystem. Returns ------- int num of ElementalSystem. """ return len(self._elemental_systems)
[docs] def dim_e_sys(self, i: int) -> int: """returns the dimension of the i-th ElementalSystem. the dim of the i-th ElementalSystem. Parameters ---------- i: int the id of an ElementalSystem Returns ------- int the dim of the i-th ElementalSystem """ return self._elemental_systems[i].dim
[docs] def get_basis(self, index: Union[int, Tuple]) -> MatrixBasis: """returns basis specified by index. Parameters ---------- index : Union[int, Tuple] index of basis. if type is int, then regardes it as the index after calculating the basis of CompositeSystem. if type is Tuple, then regardes it as the indices of the basis of ElementalSystems. Returns ------- MatrixBasis basis specified by index. Raises ------ ValueError length of tuple does not equal length of the list of the basis. IndexError specified index does not exist in the list of the basis. """ if type(index) == tuple: # whether size of tuple equals length of the list of ElementalSystems if len(index) != len(self._elemental_systems): raise ValueError( f"length of tuple must equal length of the list of ElementalSystems. length of tuple={len(index)}, length of the list of ElementalSystems={len(self._elemental_systems)}" ) # calculate index in _basis by traversing the tuple from the back. # for example, if length of ElementalSystem is 3 and each dim are dim1, dim2, dim3, # then index in _basis of tuple(x1, x2, x3) can be calculated the following expression: # x1 * (dim2 ** 2) * (dim3 ** 2) + x2 * (dim3 ** 2) + x3 temp_grobal_index = 0 temp_dim = 1 for e_sys_position, local_index in enumerate(reversed(index)): temp_grobal_index += local_index * temp_dim temp_dim = temp_dim * (self._elemental_systems[e_sys_position].dim ** 2) return self.basis()[temp_grobal_index] else: return self.basis()[index]
@property def elemental_systems(self) -> Tuple[ElementalSystem]: """returns list of ElementalSystem of this CompositeSystem. Returns ------- Tuple[ElementalSystem] list of ElementalSystem of this CompositeSystem. """ return self._elemental_systems @property def is_orthonormal_hermitian_0thprop_identity(self) -> bool: """returns whether all ElementalSystem of this CompositeSystem are orthonormal, hermitian and 0th prop identity. Returns ------- bool whether all ElementalSystem of this CompositeSystem are orthonormal, hermitian and 0th prop identity. """ return self._is_orthonormal_hermitian_0thprop_identity @property def is_basis_hermitian(self) -> bool: return self._is_basis_hermitian def __len__(self) -> int: return len(self._elemental_systems) def __getitem__(self, key: int) -> ElementalSystem: return self._elemental_systems[key] def __iter__(self): return iter(self._elemental_systems) def __eq__(self, other) -> bool: if not isinstance(other, CompositeSystem): return False if len(self) != len(other): return False for s, o in zip(self, other): if s is not o: return False return True def __str__(self): desc = "elemental_systems:\n" for i, e_sys in enumerate(self._elemental_systems): desc += f"[{i}] {e_sys.name} (system_id={e_sys.system_id})\n" desc += "\n" desc += f"dim: {self.dim}\n" desc += f"basis:\n" desc += str(self.basis()) return desc def __repr__(self): return f"{self.__class__.__name__}(systems={repr(self.elemental_systems)})"