|
13 | 13 |
|
14 | 14 |
|
15 | 15 | class TestSingleClickFidelityEstimationUnit(unittest.TestCase):
|
16 |
| - def create_nodes(self, alice_device_positions, bob_device_positions): |
17 |
| - # Set up Alice |
18 |
| - aliceMemory = NVCommunicationDevice(name="AliceMem", num_positions=alice_device_positions) |
19 |
| - alice = QuantumNode(name="Alice", nodeID=1, memDevice=aliceMemory) |
20 |
| - |
21 |
| - # Set up Bob |
22 |
| - bobMemory = NVCommunicationDevice(name="BobMem", num_positions=bob_device_positions) |
23 |
| - bob = QuantumNode(name="Bob", nodeID=2, memDevice=bobMemory) |
24 |
| - |
25 |
| - return alice, bob |
| 16 | + def setUp(self): |
| 17 | + # Setup MHP network and MHP service |
| 18 | + network = setup_physical_network(ConfigPathStorage.NETWORK_NV_LAB_NOCAV_NOCONV) |
| 19 | + alice = network.get_node_by_id(0) |
| 20 | + bob = network.get_node_by_id(1) |
| 21 | + self.mhp_conn = network.get_connection(alice, bob, "mhp_conn") |
| 22 | + mhp_service = SimulatedNodeCentricMHPService("mhp_service", alice, bob, conn=self.mhp_conn) |
| 23 | + self.feuA = SingleClickFidelityEstimationUnit(alice, mhp_service) |
| 24 | + self.feuB = SingleClickFidelityEstimationUnit(alice, mhp_service) |
26 | 25 |
|
27 | 26 | def test_dm_fidelity(self):
|
28 | 27 | # Basic test cases using bell states
|
@@ -52,103 +51,65 @@ def test_dm_fidelity(self):
|
52 | 51 | self.assertEqual(round(dm_fidelity(dm11, dm11, squared=True), ndigits=8), 1)
|
53 | 52 |
|
54 | 53 | def test_success_prob_est(self):
|
55 |
| - # Setup MHP network and MHP service |
56 |
| - network = setup_physical_network(ConfigPathStorage.NETWORK_NV_LAB_NOCAV_NOCONV) |
57 |
| - alice = network.get_node_by_id(0) |
58 |
| - bob = network.get_node_by_id(1) |
59 |
| - mhp_conn = network.get_connection(alice, bob, "mhp_conn") |
60 |
| - mhp_service = SimulatedNodeCentricMHPService("mhp_service", alice, bob, conn=mhp_conn) |
61 |
| - feu = SingleClickFidelityEstimationUnit(alice, mhp_service) |
62 | 54 |
|
63 |
| - print(feu._estimate_success_probability()) |
| 55 | + with self.assertRaises(LinkLayerException): |
| 56 | + self.feuA._estimate_success_probability() |
| 57 | + |
| 58 | + # Should evaluate to total detection probability |
| 59 | + p_succ = self.feuA._estimate_success_probability(1, 0) |
| 60 | + self.assertAlmostEqual(p_succ, 4e-4, places=4) |
| 61 | + |
| 62 | + # Test zero alpha |
| 63 | + p_succ = self.feuA._estimate_success_probability(0) |
| 64 | + self.assertAlmostEqual(p_succ, 0, places=4) |
| 65 | + |
| 66 | + # Test linearity in alpha |
| 67 | + for i in range(11): |
| 68 | + alpha = i/20 |
| 69 | + p_succ = self.feuA._estimate_success_probability(alpha) |
| 70 | + self.assertAlmostEqual(p_succ, 2 * alpha * (4e-4), places=4) |
64 | 71 |
|
65 | 72 | def test_fidelity_estimation(self):
|
66 |
| - # Check various parameters against the estimation |
67 |
| - etaA = 1 # Transmitivity of fibre from A to midpoint |
68 |
| - etaB = 1 # Transmitivity of fibre from B to midpoint |
69 |
| - alphaA = 0.5 # Bright state population at A |
70 |
| - alphaB = 0.5 # Bright state population at B |
71 |
| - pdark = 0 # Probability of a dark count at the midpoint |
72 |
| - dp_photon = 1 # Dephasing parameter of the entangled qubit |
73 |
| - ideal_state = kron(b01.H, b01) # (|01> + |10>)(<01| + <10|) |
74 |
| - |
75 |
| - # Check a lossless scenario with bright state populations of 1/2 |
76 |
| - estimated_state = SingleClickFidelityEstimationUnit._calculate_estimated_state(etaA, etaB, alphaA, alphaB, |
77 |
| - pdark, dp_photon) |
78 |
| - |
79 |
| - estimated_fidelity = dm_fidelity(estimated_state, ideal_state, squared=True) |
80 |
| - self.assertTrue(isclose(estimated_fidelity, 2 / 3)) |
81 |
| - |
82 |
| - # Check a lossless scenario with a dark count probability of 1/2 |
83 |
| - pdark = 0.5 |
84 |
| - estimated_state = SingleClickFidelityEstimationUnit._calculate_estimated_state(etaA, etaB, alphaA, alphaB, |
85 |
| - pdark, dp_photon) |
86 |
| - |
87 |
| - estimated_fidelity = dm_fidelity(ideal_state, estimated_state, squared=True) |
88 |
| - self.assertEqual(round(estimated_fidelity, ndigits=5), 0.5) |
89 |
| - |
90 |
| - # Check that depolarizing the electron completely would estimate 0 fidelity with the desired state |
91 |
| - dp_photon = 0 |
92 |
| - estimated_state = SingleClickFidelityEstimationUnit._calculate_estimated_state(etaA, etaB, alphaA, alphaB, |
93 |
| - pdark, dp_photon) |
94 |
| - |
95 |
| - estimated_fidelity = dm_fidelity(ideal_state, estimated_state, squared=True) |
96 |
| - self.assertEqual(estimated_fidelity, 0) |
97 |
| - |
98 |
| - # Check that effectively setting chance of no clicks to zero yields a state with 0 fidelity to the ideal state |
99 |
| - alphaA = 1 |
100 |
| - alphaB = 1 |
101 |
| - estimated_state = SingleClickFidelityEstimationUnit._calculate_estimated_state(etaA, etaB, alphaA, alphaB, |
102 |
| - pdark, dp_photon) |
103 |
| - |
104 |
| - estimated_fidelity = dm_fidelity(ideal_state, estimated_state, squared=True) |
105 |
| - self.assertEqual(estimated_fidelity, 0) |
106 |
| - |
107 |
| - # Test a few extreme cases |
108 |
| - # Transmitivity of the fibres from a and b are 0 (imagine someone cuts the fibre) |
109 |
| - with self.assertRaises(EasySquidException): |
110 |
| - SingleClickFidelityEstimationUnit._calculate_estimated_state(etaA=0, etaB=0, alphaA=0, alphaB=0, pdark=0, |
111 |
| - dp_photon=0) |
112 |
| - |
113 |
| - with self.assertRaises(EasySquidException): |
114 |
| - SingleClickFidelityEstimationUnit._calculate_estimated_state(etaA=0, etaB=0, alphaA=1, alphaB=1, pdark=0, |
115 |
| - dp_photon=0) |
116 |
| - |
117 |
| - # Probability of a dark count is 1, effectively never get single clicks |
118 |
| - with self.assertRaises(EasySquidException): |
119 |
| - SingleClickFidelityEstimationUnit._calculate_estimated_state(etaA=1, etaB=1, alphaA=1, alphaB=1, pdark=1, |
120 |
| - dp_photon=0) |
| 73 | + # Both electrons excited |
| 74 | + self.assertAlmostEqual(self.feuA._estimate_fidelity(1), 0, places=4) |
| 75 | + |
| 76 | + # No excitation (all dark counts) |
| 77 | + self.assertAlmostEqual(self.feuA._estimate_fidelity(0), 0, places=4) |
| 78 | + |
| 79 | + # Check linearity in alpha (for high enough alpha due to dark counts) |
| 80 | + for i in range(40, 100): |
| 81 | + alpha = i/200 |
| 82 | + F = self.feuA._estimate_fidelity(alpha) |
| 83 | + self.assertAlmostEqual(F, 1 - alpha, places=1) |
| 84 | + |
| 85 | + # Perfect entanglement when no dark counts |
| 86 | + self.mhp_conn.midPoint.pdark = 0 |
| 87 | + self.assertAlmostEqual(self.feuA._estimate_fidelity(0.00001), 1, places=1) |
| 88 | + |
| 89 | + with self.assertRaises(LinkLayerException): |
| 90 | + self.feuA._calculate_estimated_state(0) |
121 | 91 |
|
122 | 92 | def test_minimum_fidelities(self):
|
123 |
| - nodeA, nodeB = self.create_nodes(1, 1) |
124 |
| - mhp_service = SimulatedNodeCentricMHPService("mhp_service", nodeA, nodeB) |
125 |
| - feuA = SingleClickFidelityEstimationUnit(nodeA, mhp_service) |
126 |
| - feuB = SingleClickFidelityEstimationUnit(nodeB, mhp_service) |
127 |
| - |
128 |
| - self.assertTrue(isclose(feuA.estimated_fidelity, 0.9473684210526312)) |
129 |
| - self.assertTrue(isclose(feuB.estimated_fidelity, 0.9473684210526312)) |
130 |
| - self.assertEqual(feuA.achievable_fidelities, feuB.achievable_fidelities) |
131 |
| - self.assertEqual(feuA.achievable_fidelities[0][0], 0.1) |
132 |
| - self.assertTrue(isclose(feuA.achievable_fidelities[0][1], 0.9473684210526312)) |
133 |
| - self.assertEqual(feuA.achievable_fidelities[1][0], 0.3) |
134 |
| - self.assertTrue(isclose(feuA.achievable_fidelities[1][1], 0.8235294278458571)) |
135 |
| - |
136 |
| - self.assertTrue(isclose(feuA.get_max_fidelity(), 0.9473684210526312)) |
137 |
| - |
138 |
| - protoA = mhp_service.get_node_proto(nodeA) |
| 93 | + |
| 94 | + self.assertEqual(self.feuA.achievable_fidelities, self.feuB.achievable_fidelities) |
| 95 | + self.assertEqual(self.feuA.achievable_fidelities[0][0], 0.1) |
| 96 | + self.assertTrue(isclose(self.feuA.achievable_fidelities[0][1], 0.8614038170052276)) |
| 97 | + self.assertEqual(self.feuA.achievable_fidelities[1][0], 0.3) |
| 98 | + self.assertTrue(isclose(self.feuA.achievable_fidelities[1][1], 0.6800331800062903)) |
| 99 | + |
| 100 | + self.assertTrue(isclose(self.feuA.get_max_fidelity(), 0.8614038170052276)) |
| 101 | + |
| 102 | + protoA = self.feuA.mhp_service.get_node_proto(self.feuA.node) |
139 | 103 | protoA.set_allowed_bright_state_populations([0.1, 0.2])
|
140 | 104 |
|
141 | 105 | with self.assertRaises(LinkLayerException):
|
142 |
| - feuA._calculate_achievable_fidelities() |
| 106 | + self.feuA._calculate_achievable_fidelities() |
143 | 107 |
|
144 | 108 | def test_get_bright_state(self):
|
145 |
| - nodeA, nodeB = self.create_nodes(1, 1) |
146 |
| - mhp_service = SimulatedNodeCentricMHPService("mhp_service", nodeA, nodeB) |
147 |
| - feuA = SingleClickFidelityEstimationUnit(nodeA, mhp_service) |
148 |
| - |
149 |
| - self.assertEqual(feuA.select_bright_state(0.9), 0.1) |
150 |
| - self.assertEqual(feuA.select_bright_state(0.8), 0.3) |
151 |
| - self.assertEqual(feuA.select_bright_state(0.95), None) |
| 109 | + self.assertEqual(self.feuA.select_bright_state(0.9), None) |
| 110 | + self.assertEqual(self.feuA.select_bright_state(0.8), 0.1) |
| 111 | + self.assertEqual(self.feuA.select_bright_state(0.7), 0.1) |
| 112 | + self.assertEqual(self.feuA.select_bright_state(0.6), 0.3) |
152 | 113 |
|
153 | 114 |
|
154 | 115 | if __name__ == '__main__':
|
|
0 commit comments