Prev Tutorial: Variational Quantum Circuit
Next Tutorial: State Vector
Introduction
The density matrix is a crucial concept in quantum mechanics, which is used to describe the state of a quantum system, especially when there is interaction between the system and the environment. The following is a detailed introduction to the density matrix in the quantum field:
The density matrix, also known as the density operator, is a Hermitian matrix with a trace of 1 and a squared trace of less than or equal to 1. In quantum mechanics, the density matrix is used to represent the superposition of probabilities of a system being in multiple quantum states. For the state of a quantum system, its density matrix can be expressed as \(
\rho=\sum_i p_i|\psi_i\rangle\langle\psi_i|\), where \(p_i\) is the probability that the system is in the state \(|\psi_i\rangle\), satisfying \(p_i \geq 0\) and \(\sum_i\) \(p_i=1 \) , which is the normalization condition.
In QPanda3 Quantum Information
QPanda3 uses DensityMatrix in Quantum Informaton to abstract and simulate density matrix
Constructing a DensityMatrix object
Here is API doc
Default constructor
The default is to construct a density matrix for a quantum system with only one qubit and a current state of all 0s
For internal tensor product operations, the qbit index with the larger value is used as the left operand. For example, when performing a tensor product operation on a quantum system consisting of \(q[0]\), \(q[1]\), and \(q[2]\), the result corresponds to \(\left | q[2] \right \rangle \otimes \left | q[1] \right \rangle \otimes \left | q[0] \right \rangle \)
Python
dm = DensityMatrix()
print(dm)
Output
{
{
{(1,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},
}
}
From qubit total
Specify the total number of qubits in the quantum system, and generate a density matrix where the state of each quantum is currently 0
For internal tensor product operations, the qbit index with the larger value is used as the left operand. For example, when performing a tensor product operation on a quantum system consisting of \(q[0]\), \(q[1]\), and \(q[2]\), the result corresponds to \(\left | q[2] \right \rangle \otimes \left | q[1] \right \rangle \otimes \left | q[0] \right \rangle \)
Python
dm = DensityMatrix(3)
print(dm)
Output
{
{
{(1,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
}
From a complex array
Construct a density matrix based on the input two-dimensional complex array.If the matrix corresponding to the two-dimensional complex array does not satisfy the condition of trace 1 and positive definiteness, an exception is thrown. If the number of elements in a given complex array is not a power of 2, it will be automatically expanded to a power of 2. This expansion operation will expand the number of elements as little as possible
For internal tensor product operations, the qbit index with the larger value is used as the left operand. For example, when performing a tensor product operation on a quantum system consisting of \(q[0]\), \(q[1]\), and \(q[2]\), the result corresponds to \(\left | q[2] \right \rangle \otimes \left | q[1] \right \rangle \otimes \left | q[0] \right \rangle \)
Python
import numpy as np
data = np.array(
[[0.18056413 + 0.j, 0.12215589 + 0.06893592j, - 0.05337882 - 0.06077268j, - 0.06164719 - 0.00112235j],
[0.12215589 - 0.06893592j, 0.38670196 + 0.j, - 0.251278 - 0.09109501j, 0.11033526 + 0.04016816j],
[-0.05337882 + 0.06077268j, - 0.251278 + 0.09109501j, 0.26018725 + 0.j, - 0.14253993 + 0.02027215j],
[-0.06164719 + 0.00112235j, 0.11033526 - 0.04016816j, - 0.14253993 - 0.02027215j, 0.17254666 + 0.j]]
)
dm = DensityMatrix(data)
print(dm)
Output
{
{
{(0.180564,0)},{(0.122156,0.0689359)},{(-0.0533788,-0.0607727)},{(-0.0616472,-0.00112235)},
}
{
{(0.122156,-0.0689359)},{(0.386702,0)},{(-0.251278,-0.091095)},{(0.110335,0.0401682)},
}
{
{(-0.0533788,0.0607727)},{(-0.251278,0.091095)},{(0.260187,0)},{(-0.14254,0.0202721)},
}
{
{(-0.0616472,0.00112235)},{(0.110335,-0.0401682)},{(-0.14254,-0.0202721)},{(0.172547,0)},
}
}
From DensityMatrix
Construct a new DensityMatrix object based on an existing DensityMatrix object
Python
import numpy as np
data = np.array(
[[0.18056413 + 0.j, 0.12215589 + 0.06893592j, - 0.05337882 - 0.06077268j, - 0.06164719 - 0.00112235j],
[0.12215589 - 0.06893592j, 0.38670196 + 0.j, - 0.251278 - 0.09109501j, 0.11033526 + 0.04016816j],
[-0.05337882 + 0.06077268j, - 0.251278 + 0.09109501j, 0.26018725 + 0.j, - 0.14253993 + 0.02027215j],
[-0.06164719 + 0.00112235j, 0.11033526 - 0.04016816j, - 0.14253993 - 0.02027215j, 0.17254666 + 0.j]]
)
dm = DensityMatrix(data)
dm2 = DensityMatrix(dm)
print(dm2)
Output
{
{
{(0.180564,0)},{(0.122156,0.0689359)},{(-0.0533788,-0.0607727)},{(-0.0616472,-0.00112235)},
}
{
{(0.122156,-0.0689359)},{(0.386702,0)},{(-0.251278,-0.091095)},{(0.110335,0.0401682)},
}
{
{(-0.0533788,0.0607727)},{(-0.251278,0.091095)},{(0.260187,0)},{(-0.14254,0.0202721)},
}
{
{(-0.0616472,0.00112235)},{(0.110335,-0.0401682)},{(-0.14254,-0.0202721)},{(0.172547,0)},
}
}
From StateVector
Construct a new DensityMatrix object from an existing StateVector object
Python
import numpy as np
def test_construct_from_stv():
stv = StateVector(np.array([1 + 1.j, 2 + 2.j, 3 + 3.j, 4 + 4.j, 5 + 5.j, 6 + 6.j, 7 + 7.j, 8 + 8.j]))
dm = DensityMatrix(stv)
print("dm:",dm)
if __name__ == "__main__":
test_construct_from_stv()
Output
dm: {
{
{(0.00490196,0)},{(0.00980392,0)},{(0.0147059,0)},{(0.0196078,0)},{(0.0245098,0)},{(0.0294118,0)},{(0.0343137,0)},{(0.0392157,0)},
}
{
{(0.00980392,0)},{(0.0196078,0)},{(0.0294118,0)},{(0.0392157,0)},{(0.0490196,0)},{(0.0588235,0)},{(0.0686275,0)},{(0.0784314,0)},
}
{
{(0.0147059,0)},{(0.0294118,0)},{(0.0441176,0)},{(0.0588235,0)},{(0.0735294,0)},{(0.0882353,0)},{(0.102941,0)},{(0.117647,0)},
}
{
{(0.0196078,0)},{(0.0392157,0)},{(0.0588235,0)},{(0.0784314,0)},{(0.0980392,0)},{(0.117647,0)},{(0.137255,0)},{(0.156863,0)},
}
{
{(0.0245098,0)},{(0.0490196,0)},{(0.0735294,0)},{(0.0980392,0)},{(0.122549,0)},{(0.147059,0)},{(0.171569,0)},{(0.196078,0)},
}
{
{(0.0294118,0)},{(0.0588235,0)},{(0.0882353,0)},{(0.117647,0)},{(0.147059,0)},{(0.176471,0)},{(0.205882,0)},{(0.235294,0)},
}
{
{(0.0343137,0)},{(0.0686275,0)},{(0.102941,0)},{(0.137255,0)},{(0.171569,0)},{(0.205882,0)},{(0.240196,0)},{(0.27451,0)},
}
{
{(0.0392157,0)},{(0.0784314,0)},{(0.117647,0)},{(0.156863,0)},{(0.196078,0)},{(0.235294,0)},{(0.27451,0)},{(0.313725,0)},
}
}
Obtain internal data
Get numpy.ndarray
Get the internal data of the density matrix and return it in the form of numpy.ndarray
Here is API doc for DensityMatrix.ndarray
Python
import numpy as np
def test():
data = np.array(
[[0.18056413 + 0.j , 0.12215589 + 0.06893592j ,- 0.05337882 - 0.06077268j, - 0.06164719 - 0.00112235j],
[0.12215589 - 0.06893592j , 0.38670196 + 0.j, - 0.251278 - 0.09109501j, 0.11033526 + 0.04016816j],
[-0.05337882 + 0.06077268j ,- 0.251278 + 0.09109501j,0.26018725 + 0.j, - 0.14253993 + 0.02027215j],
[-0.06164719 + 0.00112235j ,0.11033526 - 0.04016816j, - 0.14253993 - 0.02027215j, 0.17254666 + 0.j]]
)
dm = DensityMatrix(data)
data = dm.ndarray()
print("data:",data)
if __name__ == "__main__":
test()
Output
data: [[ 0.18056413+0.j 0.12215589+0.06893592j -0.05337882-0.06077268j
-0.06164719-0.00112235j]
[ 0.12215589-0.06893592j 0.38670196+0.j -0.251278 -0.09109501j
0.11033526+0.04016816j]
[-0.05337882+0.06077268j -0.251278 +0.09109501j 0.26018725+0.j
-0.14253993+0.02027215j]
[-0.06164719+0.00112235j 0.11033526-0.04016816j -0.14253993-0.02027215j
0.17254666+0.j ]]
Get element
Get an element of internal data by matrix row and column index
Here is API doc for DensityMatrix.dim
Here is API doc for DensityMatrix.at
Python
import numpy as np
def test_dim_at():
data = np.array(
[[0.18056413 + 0.j, 0.12215589 + 0.06893592j, - 0.05337882 - 0.06077268j, - 0.06164719 - 0.00112235j],
[0.12215589 - 0.06893592j, 0.38670196 + 0.j, - 0.251278 - 0.09109501j, 0.11033526 + 0.04016816j],
[-0.05337882 + 0.06077268j, - 0.251278 + 0.09109501j, 0.26018725 + 0.j, - 0.14253993 + 0.02027215j],
[-0.06164719 + 0.00112235j, 0.11033526 - 0.04016816j, - 0.14253993 - 0.02027215j, 0.17254666 + 0.j]]
)
dm = DensityMatrix(data)
print("element in dm:")
for i in range(dm.dim()):
for j in range(dm.dim()):
print(dm.at(i,j))
if __name__ == "__main__":
test_dim_at()
Output
element in dm:
(0.18056413+0j)
(0.12215589+0.06893592j)
(-0.05337882-0.06077268j)
(-0.06164719-0.00112235j)
(0.12215589-0.06893592j)
(0.38670196+0j)
(-0.251278-0.09109501j)
(0.11033526+0.04016816j)
(-0.05337882+0.06077268j)
(-0.251278+0.09109501j)
(0.26018725+0j)
(-0.14253993+0.02027215j)
(-0.06164719+0.00112235j)
(0.11033526-0.04016816j)
(-0.14253993-0.02027215j)
(0.17254666+0j)
Purity
Obtain the purity of the density matrix
Here is API doc for DensityMatrix.purity
Python
import numpy as np
def test_purity():
data = np.array(
[[0.18056413 + 0.j, 0.12215589 + 0.06893592j, - 0.05337882 - 0.06077268j, - 0.06164719 - 0.00112235j],
[0.12215589 - 0.06893592j, 0.38670196 + 0.j, - 0.251278 - 0.09109501j, 0.11033526 + 0.04016816j],
[-0.05337882 + 0.06077268j, - 0.251278 + 0.09109501j, 0.26018725 + 0.j, - 0.14253993 + 0.02027215j],
[-0.06164719 + 0.00112235j, 0.11033526 - 0.04016816j, - 0.14253993 - 0.02027215j, 0.17254666 + 0.j]]
)
dm = DensityMatrix(data)
print("dm:", dm)
purity = dm.purity()
print("purity:",purity)
if __name__ == "__main__":
test_purity()
Output
dm: {
{
{(0.180564,0)},{(0.122156,0.0689359)},{(-0.0533788,-0.0607727)},{(-0.0616472,-0.00112235)},
}
{
{(0.122156,-0.0689359)},{(0.386702,0)},{(-0.251278,-0.091095)},{(0.110335,0.0401682)},
}
{
{(-0.0533788,0.0607727)},{(-0.251278,0.091095)},{(0.260187,0)},{(-0.14254,0.0202721)},
}
{
{(-0.0616472,0.00112235)},{(0.110335,-0.0401682)},{(-0.14254,-0.0202721)},{(0.172547,0)},
}
}
purity: (0.5515582694688418+0j)
StateVector
Obtain the corresponding state vector
Here is API doc for DensityMatrix.to_statevector
Python
def test_to_statevector():
dm = DensityMatrix(3)
stv = dm.to_statevector()
print("stv:",stv)
if __name__ == "__main__":
test_to_statevector()
Output
stv: [(1+0j), 0j, 0j, 0j, 0j, 0j, 0j, 0j]
Evolution with QCircuit
Use quantum circuit QCircuit to evolve
Evolve without updating
Use the quantum circuit QCircuit to evolve the density matrix without updating the internal data of the original DensityMatrix object; The result of evolution is returned as a new DensityMatrix object
Here is API doc for DensityMatrix.evolve
Python
def test_evolve():
dm = DensityMatrix(3)
cir = QCircuit()
cir << X(0)<<SWAP(1,2)<<CP(1,0,3.14)
dm2 = dm.evolve(cir)
print("dm2:",dm2)
if __name__ == "__main__":
test_evolve()
Output
dm2: {
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(1,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
}
Evolve with updating
Use the quantum circuit QCircuit to evolve the density matrix and update the internal data of the original DensityMatrix object
Here is API doc for DensityMatrix.update_by_evolve
Python
def test_update_by_evolve():
dm = DensityMatrix(3)
cir = QCircuit()
cir << X(0) << SWAP(1, 2) << CP(1, 0, 3.14)
dm.update_by_evolve(cir)
print("dm:", dm)
if __name__ == "__main__":
test_update_by_evolve()
Output
dm: {
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(1,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
{
{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},{(0,0)},
}
}
Boolean function
Valid
Verify whether the internal data of the density matrix is legal The term "legal" here refers to whether it meets the requirements of being semi-positive definite and having a trace of 1
Here is API doc for DensityMatrix.is_valid
Python
import numpy as np
def test_is_valid():
data = np.array(
[[0.18056413 + 0.j, 0.12215589 + 0.06893592j, - 0.05337882 - 0.06077268j, - 0.06164719 - 0.00112235j],
[0.12215589 - 0.06893592j, 0.38670196 + 0.j, - 0.251278 - 0.09109501j, 0.11033526 + 0.04016816j],
[-0.05337882 + 0.06077268j, - 0.251278 + 0.09109501j, 0.26018725 + 0.j, - 0.14253993 + 0.02027215j],
[-0.06164719 + 0.00112235j, 0.11033526 - 0.04016816j, - 0.14253993 - 0.02027215j, 0.17254666 + 0.j]]
)
dm = DensityMatrix(data)
print("is_valid:",dm.is_valid())
if __name__ == "__main__":
test_is_valid()
Output
Equal
Determine whether the internal data of two DensityMatrix are the same
Here is API doc
Python
import numpy as np
def test_eq():
data = np.array(
[[0.18056413 + 0.j, 0.12215589 + 0.06893592j, - 0.05337882 - 0.06077268j, - 0.06164719 - 0.00112235j],
[0.12215589 - 0.06893592j, 0.38670196 + 0.j, - 0.251278 - 0.09109501j, 0.11033526 + 0.04016816j],
[-0.05337882 + 0.06077268j, - 0.251278 + 0.09109501j, 0.26018725 + 0.j, - 0.14253993 + 0.02027215j],
[-0.06164719 + 0.00112235j, 0.11033526 - 0.04016816j, - 0.14253993 - 0.02027215j, 0.17254666 + 0.j]]
)
dm = DensityMatrix(data)
dm2 = dm
print("dm==dm2:",dm==dm2)
if __name__ == "__main__":
test_eq()
Output