Skip to content

Commit

Permalink
add purity and pure state vector method
Browse files Browse the repository at this point in the history
  • Loading branch information
dsdsdshe committed Aug 30, 2023
1 parent b2e1ca8 commit aa583d5
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 46 deletions.
4 changes: 2 additions & 2 deletions ccsrc/include/simulator/densitymatrix/densitymatrix_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ class DensityMatrixState {
virtual void SetDM(const matrix_t& qs_out);
virtual void CopyQS(const qs_data_p_t& qs_src);

//! Judge whether the density matrix is pure
virtual bool IsPure() const;
//! Get the purity of density matrix
virtual calc_type Purity() const;

//! Get the partial trace of density matrix
virtual matrix_t GetPartialTrace(const qbits_t& objs) const;
Expand Down
4 changes: 2 additions & 2 deletions ccsrc/include/simulator/densitymatrix/densitymatrix_state.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ void DensityMatrixState<qs_policy_t_>::CopyQS(const qs_data_p_t& qs_src) {
}

template <typename qs_policy_t_>
bool DensityMatrixState<qs_policy_t_>::IsPure() const {
return qs_policy_t::IsPure(qs, dim);
auto DensityMatrixState<qs_policy_t_>::Purity() const -> calc_type {
return qs_policy_t::Purity(qs, dim);
}

template <typename qs_policy_t_>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ struct CPUDensityMatrixPolicyBase {
static qs_data_p_t Copy(const qs_data_p_t& qs, index_t dim);
static calc_type Purity(const qs_data_p_t& qs, index_t dim);
static matrix_t GetPartialTrace(const qs_data_p_t& qs, const qbits_t& objs, index_t dim);
static bool IsPure(const qs_data_p_t& qs, index_t dim);
static py_qs_datas_t PureStateVector(const qs_data_p_t& qs, index_t dim);
static void ApplyTerms(qs_data_p_t* qs_p, const std::vector<PauliTerm<calc_type>>& ham, index_t dim);
static void ApplyCsr(qs_data_p_t* qs_p, const std::shared_ptr<sparse::CsrHdMatrix<calc_type>>& a, index_t dim);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,20 +252,12 @@ auto CPUDensityMatrixPolicyBase<derived_, calc_type_>::GetPartialTrace(const qs_
return res;
}

template <typename derived_, typename calc_type_>
bool CPUDensityMatrixPolicyBase<derived_, calc_type_>::IsPure(const qs_data_p_t& qs, index_t dim) {
auto p = Purity(qs, dim);
if (std::abs(p - 1) < 1e-8) {
return true;
} else {
return false;
}
}

template <typename derived_, typename calc_type_>
auto CPUDensityMatrixPolicyBase<derived_, calc_type_>::PureStateVector(const qs_data_p_t& qs, index_t dim)
-> py_qs_datas_t {
if (!IsPure(qs, dim)) {
auto p = Purity(qs, dim);
if (std::abs(p - 1) > 1e-8) {
throw(std::runtime_error("PureStateVector(): Cannot transform mixed density matrix to vector."));
}
if (qs == nullptr) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ auto BindSim(pybind11::module& module, const std::string_view& name) { // NOLIN
.def("get_qs", &sim_t::GetQS)
.def("set_qs", &sim_t::SetQS)
.def("set_dm", &sim_t::SetDM)
.def("is_pure", &sim_t::IsPure)
.def("purity", &sim_t::Purity)
.def("get_partial_trace", &sim_t::GetPartialTrace)
.def("pure_state_vector", &sim_t::PureStateVector)
.def("apply_hamiltonian", &sim_t::ApplyHamiltonian)
Expand Down
78 changes: 54 additions & 24 deletions docs/api_python/mindquantum.simulator.Simulator.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,20 @@ mindquantum.simulator.Simulator

返回模拟器的数据类型。

.. py:method:: entropy()
计算当前量子态的冯诺伊曼熵。

冯诺伊曼熵 :math:`S` 的定义如下。

.. math::
S(\rho) = -\text{tr}(\rho \ln \rho)
其中 :math:`\rho` 是密度矩阵。

返回:
numbers.Number,当前量子态的冯诺伊曼熵。

.. py:method:: get_expectation(hamiltonian, circ_right=None, circ_left=None, simulator_left=None, pr=None)
得到给定hamiltonian的期望。hamiltonian可能是非厄米共轭的。该方法旨在计算期望值,如下所示:
Expand Down Expand Up @@ -122,6 +136,31 @@ mindquantum.simulator.Simulator
返回:
GradOpsWrapper,一个包含生成梯度算子信息的梯度算子包装器。

.. py:method:: get_partial_trace(obj_qubits)
计算当前密度矩阵的偏迹。

参数:
- **obj_qubits** (Union[int, list[int]]) - 对哪些量子比特(子系统)求偏迹。

返回:
numpy.ndarray,密度矩阵的偏迹。

.. py:method:: get_pure_state_vector()
若当前密度矩阵是纯态,则获得相应的态矢量。

密度矩阵 :math:`\rho` 和态矢量 :math:`\left| \psi \right>` 的关系如下。

.. math::
\rho = \left| \psi \right>\!\left< \psi \right|
注意:态矢量 :math:`\left| \psi \right>` 可能包含一个任意的全局相位 :math:`e^{i\phi}`。

返回:
numpy.ndarray,由当前纯态密度矩阵计算出的态矢量。

.. py:method:: get_qs(ket=False)
获取模拟器的当前量子态。
Expand All @@ -140,6 +179,21 @@ mindquantum.simulator.Simulator
返回:
int,当前模拟器的量子比特数。

.. py:method:: purity()
计算当前量子态的纯度。

纯度 :math:`\gamma` 的定义如下所示。

.. math::
\gamma \equiv \text{tr}(\rho^2)
其中 :math:`\rho` 是密度矩阵。

返回:
numbers.Number,当前量子态的纯度。

.. py:method:: reset()
将模拟器重置为0态。
Expand Down Expand Up @@ -170,27 +224,3 @@ mindquantum.simulator.Simulator

参数:
- **number** (int) - 设置模拟器中线程池所使用的线程数。

.. py:method:: get_partial_trace(obj_qubits)
计算密度矩阵的偏迹。

参数:
- **obj_qubits** (Union[int, list[int]]) - 对哪些量子比特(子系统)求偏迹。

返回:
numpy.ndarray,密度矩阵的偏迹。

.. py:method:: entropy()
计算量子态的冯诺伊曼熵。

冯诺伊曼熵 :math:`S` 的定义如下。

.. math::
S(\rho) = -\text{tr}(\rho \ln \rho)
其中 :math:`\rho` 是密度矩阵。

返回:
numbers.Number,量子态的冯诺伊曼熵。
8 changes: 8 additions & 0 deletions mindquantum/simulator/backend_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,11 @@ def get_partial_trace(self, obj_qubits):
def entropy(self):
"""Get the von-Neumann entropy of quantum state."""
raise NotImplementedError(f"entropy not implemented for {self.device_name()}")

def purity(self):
"""Calculate the purity of quantum state."""
raise NotImplementedError(f"purity not implemented for {self.device_name()}")

def get_pure_state_vector(self) -> np.ndarray:
"""Get the state vector from a pure density matrix."""
raise NotImplementedError(f"get_pure_state_vector not implemented for {self.device_name()}")
18 changes: 16 additions & 2 deletions mindquantum/simulator/mqsim.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ def set_qs(self, quantum_state: np.ndarray):
raise ValueError("Wrong quantum state.")
self.sim.set_qs(quantum_state / norm_factor)

def get_partial_trace(self, obj_qubits):
def get_partial_trace(self, obj_qubits) -> np.ndarray:
"""Get partial trace of density matrix."""
if isinstance(obj_qubits, int):
obj_qubits = [obj_qubits]
Expand All @@ -505,7 +505,7 @@ def get_partial_trace(self, obj_qubits):
raise ValueError(f"{self.name} simulator not support partial trace method.")
return np.array(self.sim.get_partial_trace(obj_qubits))

def entropy(self):
def entropy(self) -> float:
"""Get the von-Neumann entropy of quantum state."""
if self.name.startswith('mqvector'):
return 0
Expand All @@ -517,3 +517,17 @@ def entropy(self):
if i > 0:
res += -i * np.log(i)
return res

def purity(self) -> float:
"""Calculate the purity of quantum state."""
if self.name.startswith('mqvector'):
return 1.0
return self.sim.purity()

def get_pure_state_vector(self) -> np.ndarray:
"""Get the state vector from a pure density matrix."""
if self.name.startswith('mqvector'):
return self.get_qs()
if 1 - self.purity() > 1e-8:
raise ValueError("Cannot transform mixed density matrix to vector.")
return np.array(self.sim.pure_state_vector())
58 changes: 54 additions & 4 deletions mindquantum/simulator/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,13 +490,13 @@ def set_threads_number(self, number):

def get_partial_trace(self, obj_qubits):
"""
Calculate the partial trace of density matrix.
Calculate the partial trace of current density matrix.
Args:
obj_qubits (Union[int, list[int]]): Specific which qubits (subsystems) to trace over.
Returns:
numpy.ndarray, the partial trace of density matrix.
numpy.ndarray, the partial trace of current density matrix.
Examples:
>>> from mindquantum.core.circuit import Circuit
Expand All @@ -513,7 +513,7 @@ def get_partial_trace(self, obj_qubits):

def entropy(self):
r"""
Calculate the von Neumann entropy of quantum state.
Calculate the von Neumann entropy of current quantum state.
Definition of von Neumann entropy :math:`S` shown as below.
Expand All @@ -524,7 +524,7 @@ def entropy(self):
where :math:`\rho` is density matrix.
Returns:
numbers.Number, the von Neumann entropy of quantum state.
numbers.Number, the von Neumann entropy of current quantum state.
Examples:
>>> from mindquantum.simulator import Simulator
Expand All @@ -535,6 +535,56 @@ def entropy(self):
"""
return self.backend.entropy()

def purity(self):
r"""
Calculate the purity of current quantum state.
Definition of purity :math:`\gamma` shown as below.
.. math::
\gamma \equiv \text{tr}(\rho^2)
where :math:`\rho` is density matrix.
Returns:
numbers.Number, the purity of current quantum state.
Examples:
>>> from mindquantum.simulator import Simulator
>>> sim = Simulator('mqmatrix', 1)
>>> sim.set_qs([[0.5, 0], [0, 0.5]])
>>> sim.purity()
0.5
"""
return self.backend.purity()

def get_pure_state_vector(self):
r"""
Get state vector if current density matrix is pure.
The relation between density matrix :math:`\rho` and state vector
:math:`\left| \psi \right>` shown as below.
.. math::
\rho = \left| \psi \right>\!\left< \psi \right|
Note that the state vector :math:`\left| \psi \right>` may have an
arbitrary global phase :math:`e^{i\phi}`.
Returns:
numpy.ndarray, a state vector calculated from current density matrix.
Examples:
>>> from mindquantum.simulator import Simulator
>>> sim = Simulator('mqmatrix', 1)
>>> sim.set_qs([[0.5, 0.5], [0.5, 0.5]])
>>> sim.get_pure_state_vector()
array([0.70710678+0.j, 0.70710678+0.j])
"""
return self.backend.get_pure_state_vector()


def inner_product(bra_simulator: Simulator, ket_simulator: Simulator):
"""
Expand Down

0 comments on commit aa583d5

Please sign in to comment.