Quantum State Discrimination¶
Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
Overview¶
Quantum state discrimination (QSD) [1-2] is a fundamental question in quantum communication, quantum computation, and quantum cryptography. In this tutorial, we will explain how to discriminate two orthogonal bipartite pure states $\lvert\psi\rangle$ and $\lvert\phi\rangle$, which satisfies $\langle\psi\lvert\phi\rangle=0$, under the constraint of Local Operations and Classical Communication (LOCC). We refer all the theoretical details to the original paper [3].
QSD Protocol¶
Firstly, we want to make the problem definition clear. Consider two spatially separated parties $A$ (Alice) and $B$ (Bob) sharing a given two-qubit system. The system state is $\lvert\varphi\rangle$ previously distributed by another party $C$ (Charlie). Alice and Bob were only notified that $\lvert\varphi\rangle$ is either $\lvert\psi\rangle$ or $\lvert\phi\rangle$ (both are pure states), satisfying $\langle\psi\lvert\phi\rangle=0$. Then, Charlie provides many copies of $\lvert\psi\rangle$ and $\lvert\phi\rangle$ to them, and he asks Alice and Bob to cooperate with each other to figure out which state they are actually sharing.
Solving this problem under our LOCCNet framework is trivial. As always, let's start with the simplest one-round LOCC protocol with a QNN architecture shown in Figure 1. Then, the difficulty lies in the design of an appropriate loss function $L$. Since we choose to let both parties measure their subsystem, there will be four possible measurement results $m_Am_B\in\{00, 01, 10, 11\}$. To distinguish $\lvert\psi\rangle$ and $\lvert\phi\rangle$, we will label the former state with measurement results $m_Am_B\in\{00, 10\}$ and the latter with $m_Am_B\in\{01, 11\}$. This step can be understood as adding labels to the data in supervised learning. With these labels, we can define the loss function as the probability of guessing wrong label,
$$ L = p_{\lvert\psi\rangle\_01}+p_{\lvert\psi\rangle\_11}+p_{\lvert\phi\rangle\_10}+p_{\lvert\phi\rangle\_00}, \tag{1} $$where $p_{\lvert\psi\rangle\_01}$ stands for the probability of measuring 01 when the input state is $\lvert\psi\rangle$. Then we can begin the training stage to minimize the loss function.
We summarize the workflow below:
- Alice and Bob share a two-qubit system, which state is either $\lvert\psi\rangle$ or $\lvert\phi\rangle$.
- Alice operates a general rotation gate $U_A$ on her qubit.
- Alice measures her qubit on the computational basis, and the result $m_A\in \{0, 1\}$. Then, she communicates with Bob about the measurement result through a classical channel.
- Bob operates different gates on his qubit depending on Alice's measurement result. If, $m_A=0$ Bob acts $U_{B0}$ on his qubit; If $m_A = 1$, then Bob acts $U_{B1}$. Then, Bob measures his qubit and obtain $m_B \in \{0,1\}$. Note: Both $U_{B0}$ and $U_{B1}$ are universal single-qubit gate
u3()
. - Calculate the loss function $L = p_{\lvert\psi\rangle\_01}+p_{\lvert\psi\rangle\_11}+ p_{\lvert\phi\rangle\_10}+ p_{\lvert\phi\rangle\_00}$, and use gradient-based optimization methods to minimize it.
- Repeat 1-5 until the loss function converges.
- Input the pre-shared state $\lvert\varphi\rangle$ to make a decision and compare with Charlie's answer.
Simulation with Paddle Quantum¶
First, import relevant packages.
import numpy as np
from scipy.stats import unitary_group
import paddle
import paddle_quantum
from paddle_quantum.locc import LoccNet
# Change to density matrix mode
paddle_quantum.set_backend('density_matrix')
Randomly generate two orthogonal pure states $\lvert\psi\rangle$ and $\lvert\phi\rangle$ by Charlie.
def states_orthogonal_random(n, num=2):
# Randomly generate two orthogonal states
assert num <= 2 ** n, "return too many orthognal states"
U = unitary_group.rvs(2 ** n)
return_list = [np.array(U[i], dtype=np.complex64) for i in range(num)]
return return_list
Below is the main part of our LOCC protocol:
class Net(LoccNet):
def __init__(self):
super(Net, self).__init__()
# Add the first party Alice
# The first parameter 1 stands for how many qubits A holds
# The second parameter records the name of this party
self.add_new_party(1, party_name='Alice')
# Add the first party Bob
# The first parameter 1 stands for how many qubits B holds
# The second parameter records the name of this party
self.add_new_party(1, party_name='Bob')
# Rewrite the input states into density matrices
_states = states_orthogonal_random(2)
_states = [paddle_quantum.State(np.outer(init_state, init_state.conjugate())) for init_state in _states]
# Initialize the system by distributing states
self.set_init_state(_states[0], [('Alice', 0), ('Bob', 0)])
self.psi = self.init_status
self.phi = self.reset_state(self.init_status, _states[1], [('Alice', 0), ('Bob', 0)])
# Alice's local operations
self.cirA = self.create_ansatz('Alice')
# Add single-qubit universal gate
self.cirA.u3(0)
# Bob has to prepare two circuits according Alice's measurement result
self.cirB = [self.create_ansatz('Bob'), self.create_ansatz('Bob')]
# Add single-qubit universal gate
self.cirB[0].u3(0)
self.cirB[1].u3(0)
def run_circuit(self, party, cir, state, res):
# Run circuit
after_state = cir(state)
# Measure the circuit and record the measurement results
after_state = self.measure(status=after_state, which_qubits=(party, 0), results_desired=res)
return after_state
def forward(self):
# Training steps
# Quantum state after Alice's operation
psi = self.run_circuit('Alice', self.cirA, self.psi, ['0', '1'])
phi = self.run_circuit('Alice', self.cirA, self.phi, ['0', '1'])
# Calculate the loss function
loss = 0
for each_psi in psi:
if each_psi.measured_result == '0':
psi_01 = self.run_circuit('Bob', self.cirB[0], each_psi, '1')
loss += psi_01.prob
elif each_psi.measured_result == '1':
psi_11 = self.run_circuit('Bob', self.cirB[1], each_psi, '1')
loss += psi_11.prob
for each_phi in phi:
if each_phi.measured_result == '0':
phi_00 = self.run_circuit('Bob', self.cirB[0], each_phi, '0')
loss += phi_00.prob
elif each_phi.measured_result == '1':
phi_10 = self.run_circuit('Bob', self.cirB[1], each_phi, '0')
loss += phi_10.prob
return loss
def evaluate(self):
# Test step
choice = np.random.choice(['phi', 'psi'])
if choice == 'phi':
self.status = self.phi
else:
self.status = self.psi
print('Charlie chooses the state', choice)
# Alice's operations
status = self.run_circuit('Alice', self.cirA, self.status, ['0', '1'])
# Bob's operations
result_0 = list()
result_1 = list()
for each_status in status:
if each_status.measured_result == '0':
status = self.run_circuit('Bob', self.cirB[0], each_status, ['0', '1'])
result_0.append(status[0].prob.numpy()[0])
result_0.append(status[1].prob.numpy()[0])
elif each_status.measured_result == '1':
status = self.run_circuit('Bob', self.cirB[1], each_status, ['0', '1'])
result_1.append(status[0].prob.numpy()[0])
result_1.append(status[1].prob.numpy()[0])
print("The probability that Alice and Bob recognize it as psi:", result_0[0] + result_1[0])
print("The probability that Alice and Bob recognize it as phi:", result_0[1] + result_1[1])
Train the QNN parameters, and Charlie randomly select one of the two orthogonal states $\lvert\psi\rangle$ and $\lvert\phi\rangle$ and see whether Alice and Bob can distinguish it correctly.
ITR = 100 # Set the number of training iterations
LR = 0.1 # Set learning rate
SEED = 999 # Fix randome seed for parameters in PQC
np.random.seed(SEED)
paddle.seed(SEED)
net = Net()
params = net.cirA.parameters() + net.cirB[0].parameters() + net.cirB[1].parameters()
opt = paddle.optimizer.Adam(learning_rate=LR, parameters=params)
# Train the LOCC net for ITR iterations by gradient descent
for itr in range(ITR):
loss = net()
loss.backward()
opt.minimize(loss)
opt.clear_grad()
if itr % 10 == 0:
print("itr " + str(itr) + ":", loss.numpy()[0])
print("Minimum loss:", loss.numpy()[0])
print("======================== test stage ===============================")
np.random.seed(10)
net.evaluate()
np.random.seed(6)
net.evaluate()
itr 0: 1.1238832 itr 10: 0.32665575 itr 20: 0.085007355 itr 30: 0.085270524 itr 40: 0.026622297 itr 50: 0.015240545 itr 60: 0.007836903 itr 70: 0.004827206 itr 80: 0.0035075857 itr 90: 0.002215183 Minimum loss: 0.0016813411 ======================== test stage =============================== Charlie chooses the state psi The probability that Alice and Bob recognize it as psi: 0.9990063 The probability that Alice and Bob recognize it as phi: 0.0009937042 Charlie chooses the state phi The probability that Alice and Bob recognize it as psi: 0.0006236615 The probability that Alice and Bob recognize it as phi: 0.9993763
Conclusion¶
It can be seen from the simulation results that the trained quantum circuit can distinguish two orthogonal quantum states almost perfectly with an accuracy $>99.9\%$. There is an interesting question that can we generalize this discrimination scheme by adding more states to the category.
References¶
[1] Barnett, Stephen M., and Sarah Croke. "Quantum state discrimination." Advances in Optics and Photonics 1.2 (2009): 238-278.
[2] Chefles, Anthony. "Quantum state discrimination." Contemporary Physics 41.6 (2000): 401-424.
[3] Walgate, Jonathan, et al. "Local distinguishability of multipartite orthogonal quantum states." Physical Review Letters 85.23 (2000): 4972.