Unverified Commit 16130be9 authored by dwuggh's avatar dwuggh
Browse files

structurize

parent 916f1777
import numpy as np
from functools import reduce
from utils import *
from QOperator import *
from QChannel import *
from .utils import *
from .QOperator import *
from .QChannel import *
class DensityOperator(QOperator):
......@@ -61,20 +61,31 @@ class DensityOperator(QOperator):
return result
# bell measurement: only result 00 and 11 will be reserved
'''
In the paper, measurement error is modeled by perfect measurement preceded by
inversion of the state with probability $p_m$.
'''
def bell_measure(self, q1, q2, pauli, p_m = 0):
channel1 = measure_x(q1) if pauli == 'x' else measure_z(q2)
channel2 = measure_x(q1) if pauli == 'x' else measure_z(q2)
# the 4 projection operator
P_00 = multiply(channel1.kraus_operators[0], channel2.kraus_operators[0])
P_01 = multiply(channel1.kraus_operators[0], channel2.kraus_operators[1])
P_10 = multiply(channel1.kraus_operators[1], channel2.kraus_operators[0])
P_11 = multiply(channel1.kraus_operators[1], channel2.kraus_operators[1])
p1 = (1 - p_m) ** 2 + p_m ** 2
p2 = 2 * p_m * (1 - p_m)
p1 = np.sqrt(p1)
p2 = np.sqrt(p2)
# this channel will cause probability loss because of post-selection
loss_channel = QChannel([P_00, P_11])
# self.print()
loss_channel = QChannel([P_00.scale_to(p1), P_01.scale_to(p2), P_10.scale_to(p2), P_11.scale_to(p1)])
self.channel(loss_channel)
# self.print()
operator = self.partial_trace([q1, q2])
self.operator = operator.operator
self.qubits = operator.qubits
# self.print()
......
import numpy as np
from functools import reduce
from utils import *
from QOperator import *
from .utils import *
from .QOperator import *
class QChannel(object):
......@@ -23,6 +23,13 @@ class QChannel(object):
# op = op.broadcast(qnum)
'''
depolarizing channel for $n$ qubits
$$
ε(ρ) = (1 - p)ρ + \\frac{ρ}{4^n - 1} \sum (⊗ A_i) ρ (⊗ A_i^\dagger)
$$
'''
def depolarizing_channel(p, qubits = [0]) -> QChannel:
operators = []
qnum = len(qubits)
......@@ -32,7 +39,7 @@ def depolarizing_channel(p, qubits = [0]) -> QChannel:
operators.append(QOperator(qubits, E_0))
# 4 ** qnum - 1 other operators
for i in range(4 ** qnum):
# i = 0 is just the identity operator, which has already been considered above
# the i = 0 case is just I, which has already been considered above
if i == 0:
continue
indices = np.flip(get_n_digits(i, 4, qnum))
......
import numpy as np
from utils import *
from .utils import *
class QOperator(object):
def __init__(self, qubits, operator: np.ndarray):
......@@ -26,6 +26,11 @@ class QOperator(object):
qubits = np.array(qubits)
return QOperator(qubits, self.operator)
# scale this operator by a scalar.
def scale_to(self, scalar):
operator = self.operator * scalar
return QOperator(self.qubits, operator)
# construct gate in the big hilbert space
# G = I ⊗ G
def broadcast(self, qnum: int):
......
from .utils import *
from .QOperator import *
from .QChannel import *
from .DensityOperator import *
from .fidelity import *
from .purify_circuits import *
# from os.path import dirname, basename, isfile
# import glob
# from importlib import reload
# modules = glob.glob(dirname(__file__)+"/*.py")
# __all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]
# from . import *
# for module in __all__:
# reload(module)
# del dirname, basename, isfile, glob, modules
from .QOperator import *
from .DensityOperator import *
def entanglement_fidelity(ρ1: DensityOperator, ρ2: DensityOperator):
return np.matmul(ρ1.operator, ρ2.operator).trace()
def bell_fidelity(ρ: DensityOperator):
perfect_bell = bell_pair(0, [0, 1])
return entanglement_fidelity(perfect_bell, ρ)
import numpy as np
from functools import reduce
from utils import *
from QOperator import *
from QChannel import *
from DensityOperator import *
from fidelity import *
from .utils import *
from .QOperator import *
from .QChannel import *
from .DensityOperator import *
from .fidelity import *
......@@ -18,10 +18,10 @@ q4 ---|-----∎--⊤--M(x)
q3 ---∎--⊤-----Z--M(x)
data2 ------σ------------
'''
def nickerson_1(ρ: DensityOperator, err_model: ErrorModel, data1, data2, q1, q2, q3 ,q4, pauli):
def bell_purify_1(ρ: DensityOperator, err_model: ErrorModel, data1, data2, q1, q2, q3 ,q4, pauli):
ρ1 = bell_pair(err_model.p_n, [q1, q3])
ρ.merge(ρ1)
ρ.print()
# ρ.print()
# 2 control-pauli gate
c1 = cpauli(pauli, [q1, data1])
......@@ -29,7 +29,7 @@ def nickerson_1(ρ: DensityOperator, err_model: ErrorModel, data1, data2, q1, q2
ρ.evolution(c1, err_model.p_g)
ρ.evolution(c2, err_model.p_g)
ρ.print()
# ρ.print()
ρ2 = bell_pair(err_model.p_n, [q2, q4])
ρ.merge(ρ2)
......@@ -48,7 +48,7 @@ def nickerson_1(ρ: DensityOperator, err_model: ErrorModel, data1, data2, q1, q2
'''
q1, q2, q3, q4 are the 4 ancilla qubits
`stringent_plus` indicates whether the blank-separated region is performed
`stringent` indicates whether the blank-separated region is performed
q2 ------∎--⊤--M(x)--∎--⊤--M(x)---- --∎--⊤--M(x)-- ------
q1 ---∎--|--X--------|--Z-------⊤-- --|--Z-------- --M(x)
data1 ---|--|-----------|----------σ-- --|----------- ------
......@@ -57,7 +57,7 @@ q4 ---|--∎--⊤--M(x)--∎--⊤--M(x)---- --∎--⊤--M(x)-- ------
q3 ---∎-----X-----------Z-------⊤-- -----Z-------- --M(x)
data2 -----------------------------σ-- -------------- ------
'''
def nickerson_2(ρ: DensityOperator, err_model: ErrorModel, data1, data2, q1, q2, q3 ,q4, pauli, stringent_plus = True):
def bell_purify_2(ρ: DensityOperator, err_model: ErrorModel, data1, data2, q1, q2, q3 ,q4, pauli, stringent = True):
# for efficiency improvement
ρ1 = bell_pair(err_model.p_n, [q1, q3])
......@@ -90,7 +90,7 @@ def nickerson_2(ρ: DensityOperator, err_model: ErrorModel, data1, data2, q1, q2
ρ.evolution(c5, err_model.p_g)
ρ.evolution(c6, err_model.p_g)
if stringent_plus:
if stringent:
ρ4 = bell_pair(err_model.p_n, [q2, q4])
ρ.merge(ρ4)
......@@ -106,17 +106,22 @@ def nickerson_2(ρ: DensityOperator, err_model: ErrorModel, data1, data2, q1, q2
ρ.bell_measure(q1, q3, 'x', err_model.p_m)
'''
qubit indexing:
2 5
1 4
0 3
'''
def make_bell(err_model: ErrorModel, stringent = True, stringent_plus = True):
ρ = bell_pair(err_model.p_n, [0, 3])
nickerson_1(ρ, err_model, 0, 3, 1, 2, 4, 5, 'z')
nickerson_1(ρ, err_model, 0, 3, 1, 2, 4, 5, 'x')
bell_purify_1(ρ, err_model, 0, 3, 1, 2, 4, 5, 'z')
print(bell_fidelity(ρ))
bell_purify_1(ρ, err_model, 0, 3, 1, 2, 4, 5, 'x')
print(bell_fidelity(ρ))
if stringent:
nickerson_2(ρ, err_model, 0, 3, 1, 2, 4, 5, 'z', stringent_plus)
nickerson_2(ρ, err_model, 0, 3, 1, 2, 4, 5, 'x', stringent_plus)
bell_purify_2(ρ, err_model, 0, 3, 1, 2, 4, 5, 'z', stringent)
print(bell_fidelity(ρ))
bell_purify_2(ρ, err_model, 0, 3, 1, 2, 4, 5, 'x', stringent)
print(bell_fidelity(ρ))
return ρ
......
from QOperator import pauli
from utils import ErrorModel
import calc_channel as cc
import numpy as np
......@@ -28,9 +26,6 @@ D: 9, 10, 11
def test_1():
np.set_printoptions(edgeitems=16, linewidth=200,
# formatter=dict(float=lambda x: "%.3g" % x)
)
err_model = cc.ErrorModel()
ρ1 = cc.bell_pair(err_model.p_n, [1, 3])
ρ2 = cc.bell_pair(err_model.p_n, [2, 4])
......@@ -71,9 +66,12 @@ if __name__ == "__main__":
# a = test_1()
# test_3()
np.set_printoptions(edgeitems=16, linewidth=200,
formatter=dict(float=lambda x: "%5.6g" % x)
formatter=dict(float=lambda x: "%6.4g" % x)
)
err_model = cc.ErrorModel(0.1, 0.01)
ρ = cc.make_bell(err_model, True, False)
ρ.print()
# test_2()
perfect_bell = cc.bell_pair(0, [0, 1])
err_model = cc.ErrorModel(0.1, 0.005, 0.005)
noise_bell = cc.bell_pair(err_model.p_n, [0, 1])
print("no purification: ", cc.entanglement_fidelity(perfect_bell, noise_bell))
ρ = cc.make_bell(err_model, False, False)
print("with purification: ", cc.entanglement_fidelity(perfect_bell, ρ))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment