1
1
import abc
2
- from numpy import kron , zeros
2
+ from numpy import kron , sqrt
3
3
from netsquid .qubits import dm_fidelity
4
- from easysquid .toolbox import EasySquidException
5
4
from qlinklayer .toolbox import LinkLayerException
6
5
from netsquid .qubits .ketstates import s00 , s01 , s10 , s11 , b01 , b11
7
6
@@ -45,7 +44,6 @@ def __init__(self, node, mhp_service):
45
44
"""
46
45
self .node = node
47
46
self .mhp_service = mhp_service
48
- self .estimated_fidelity = self ._estimate_fidelity ()
49
47
self .achievable_fidelities = self ._calculate_achievable_fidelities ()
50
48
51
49
def update_components (self , node = None , mhp_service = None ):
@@ -82,11 +80,9 @@ def _calculate_achievable_fidelities(self):
82
80
raise LinkLayerException ("A and B have different bright state sets! Fidelity calculation unsupported" )
83
81
84
82
achievable = []
85
- params = self ._extract_params ()
86
83
for alphaA , alphaB in zip (bright_statesA , bright_statesB ):
87
- params = (params [0 ], params [1 ], alphaA , alphaB , params [4 ], params [5 ])
88
84
ideal_state = kron (b01 .H , b01 ) # (|01> + |10>)(<01| + <10|)
89
- estimated_state = self ._calculate_estimated_state (* params )
85
+ estimated_state = self ._calculate_estimated_state (alphaA , alphaB )
90
86
fidelity = float (dm_fidelity (estimated_state , ideal_state , squared = True ))
91
87
achievable .append ((alphaA , fidelity ))
92
88
@@ -126,16 +122,15 @@ def recalculate_estimate(self):
126
122
self .estimated_fidelity = self ._estimate_fidelity ()
127
123
return self .estimated_fidelity
128
124
129
- def _estimate_fidelity (self ):
125
+ def _estimate_fidelity (self , alphaA = None , alphaB = None ):
130
126
"""
131
127
Calculates the fidelity by extracting parameters from the mhp components, calculating an estimated state of
132
128
the entangled qubit, and computing the fidelity with the ideal state.
133
129
:return: float
134
130
Estimated fidelity based on the component parameters
135
131
"""
136
- params = self ._extract_params ()
137
132
ideal_state = kron (b01 .H , b01 ) # (|01> + |10>)(<01| + <10|)
138
- estimated_state = self ._calculate_estimated_state (* params )
133
+ estimated_state = self ._calculate_estimated_state (alphaA , alphaB )
139
134
return float (dm_fidelity (estimated_state , ideal_state , squared = True ))
140
135
141
136
def _compute_total_detection_probabilities (self ):
@@ -167,29 +162,51 @@ def _compute_total_detection_probability_of_node(self, node):
167
162
168
163
return total_detection_eff
169
164
170
- def _compute_conditional_detection_probabilities (self , alpha ):
165
+ def _compute_conditional_detection_probabilities (self , alphaA = None , alphaB = None ):
171
166
"""
172
167
Computes the probabilites p_uu, p_ud, pdu, pdd as given in eq (10) in https://arxiv.org/src/1712.07567v2/anc/SupplementaryInformation.pdf
173
168
Note that this assumed low detection efficiencies
174
- :return:
169
+ If either alphaA or alphaB is None, then alpha is assumed to be the same for the two nodes.
170
+
171
+ :return: tuple of floats
172
+ (p_uu, p_ud, pdu, pdd)
175
173
"""
174
+ if alphaA is None and alphaB is None :
175
+ raise LinkLayerException ("alphaA or alphaB needs to be specified" )
176
+ if alphaA is None :
177
+ alphaA = alphaB
178
+ if alphaB is None :
179
+ alphaB = alphaA
176
180
177
181
p_det_A , p_det_B = self ._compute_total_detection_probabilities ()
178
182
p_dc = self .mhp_service .conn .midpoint .pdark
183
+ # Dark count probabilities for both detectors
184
+ p_no_dc = (1 - p_dc )** 2
185
+ p_at_least_one_dc = 1 - p_no_dc
186
+
187
+ prob_click_given_two_photons = (p_no_dc * (p_det_A * (1 - p_det_B ) + p_det_B * (1 - p_det_A ) + p_det_A * p_det_B ) +
188
+ p_at_least_one_dc * (1 - p_det_A ) * (1 - p_det_B ))
189
+ p_uu = alphaA * alphaB * prob_click_given_two_photons
179
190
180
- # TODO I don't think this is correct
181
- prob_click_given_two_photons = (( 1 - p_dc ) ** 2 * ( p_det_A * ( 1 - p_det_B ) + p_det_B * (1 - p_det_A ) + p_det_A * p_det_B ) +
182
- 2 * p_dc * (1 - p_dc ) * ( 1 - p_det_A ) * ( 1 - p_det_B ))
183
- p_uu = alpha ** 2 * prob_click_given_two_photons
191
+ prob_click_given_photon_A = p_no_dc * p_det_A + p_at_least_one_dc * ( 1 - p_det_A )
192
+ prob_click_given_photon_B = p_no_dc * p_det_B + p_at_least_one_dc * (1 - p_det_B )
193
+ p_ud = alphaA * (1 - alphaB ) * prob_click_given_photon_A
194
+ p_du = alphaB * ( 1 - alphaA ) * prob_click_given_photon_B
184
195
185
- prob_click_given_photon_A = (1 - p_dc )** 2 * p_det_A + 2 * p_dc * (1 - p_dc )* (1 - p_det_A )
186
- prob_click_given_photon_B = (1 - p_dc )** 2 * p_det_B + 2 * p_dc * (1 - p_dc )* (1 - p_det_B )
187
- p_ud = alpha * (1 - alpha ) * prob_click_given_photon_A
188
- p_du = alpha * (1 - alpha ) * prob_click_given_photon_B
196
+ prob_click_given_no_photons = p_at_least_one_dc
197
+ p_dd = (1 - alphaA ) * (1 - alphaB ) * prob_click_given_no_photons
189
198
190
- prob_click_given_no_photons =
199
+ return p_uu , p_ud , p_du , p_dd
191
200
192
- # TODO NOT FINISHED!!!
201
+ def _estimate_success_probability (self , alphaA = None , alphaB = None ):
202
+ """
203
+ Computes the success probability as the sum of p_uu, p_ud, p_du, p_dd as defined in eq (10) in
204
+ https://arxiv.org/src/1712.07567v2/anc/SupplementaryInformation.pdf
205
+ If either alphaA or alphaB is None, then alpha is assumed to be the same for the two nodes.
206
+ :return: float
207
+ The success probability
208
+ """
209
+ return sum (self ._compute_conditional_detection_probabilities (alphaA , alphaB ))
193
210
194
211
def _extract_params (self ):
195
212
"""
@@ -212,85 +229,29 @@ def _extract_params(self):
212
229
213
230
return etaA , etaB , alphaA , alphaB , pdark , dp_photon
214
231
215
- @staticmethod
216
- def _calculate_estimated_state (etaA , etaB , alphaA , alphaB , pdark , dp_photon ):
217
- """
218
- Calculates an estimated state based on the provided parameters. Adapted from "Near-term repeater experiments
219
- with NV centers: overcoming the limitations of direct transmission"
220
- :param etaA: float
221
- Transmitivity of fibre from A to midpoint
222
- :param etaB: float
223
- Transmitivity of fibre from B to midpoint
224
- :param alphaA: float
225
- Bright state population of generated state at node A
226
- :param alphaB: float
227
- Bright state population of generated state at node B
228
- :param pdark: float
229
- Probability of a dark count occurrence at the midpoint
230
- :param dp_photon: float
231
- Dephasing parameter of photon
232
+ def _calculate_estimated_state (self , alphaA = None , alphaB = None ):
233
+ """
234
+ Calculates an estimated state based on the provided parameters. See eq (8) in
235
+ https://arxiv.org/src/1712.07567v2/anc/SupplementaryInformation.pdf
236
+
232
237
:return: obj `~numpy.matrix`
233
238
A density matrix of the estimated entangled state
234
239
"""
235
- if pdark == 1 :
236
- raise EasySquidException ("Probability of dark count 1 does not allow for generating entanglement!" )
237
-
238
- # Calculate the probability that the left or right detector click depending on the probability of emission
239
- # Probability of click for photon from A
240
- p0 = alphaA * (1 - alphaB ) * etaA
241
-
242
- # Probability of click for photon from B
243
- p0 += (1 - alphaA ) * alphaB * etaB
244
-
245
- # Probility of click for photons from both
246
- p0 += alphaA * alphaB * (1 - (1 - etaA ) * (1 - etaB ))
247
- p0 *= 0.5
248
-
249
- # Due to symmetries the probability is the same for the other detector
250
- p1 = p0
240
+ if self ._estimate_success_probability (alphaA , alphaB ) == 0 :
241
+ raise LinkLayerException ("Cannot estimate state when success probability is zero" )
242
+ p_uu , p_ud , p_du , p_dd = self ._compute_conditional_detection_probabilities (alphaA , alphaB )
251
243
252
- # Calculate the probability that neither detector clicks
253
- p2 = (1 - etaA * alphaA ) * (1 - etaB * alphaB )
244
+ visibility = self .mhp_service .conn .midpoint .visibility
254
245
255
- if p2 == 1 :
256
- raise EasySquidException ("Probability of photons reaching detectors is zero!" )
246
+ ent_state = (p_ud * dm10 + # |10><10| part
247
+ p_du * dm01 + # |01><01| part
248
+ sqrt (visibility * p_ud * p_du ) * kron (s10 .H , s01 ) + # |10><01| part
249
+ sqrt (visibility * p_ud * p_du ) * kron (s01 .H , s10 )) # |01><10| part
257
250
258
- # Calculate the probability of dark counts occuring within the detection window
259
- # Time window in nanoseconds, dark rate in Hz
251
+ unnormalised_state = ent_state + p_uu * dm11 + p_dd * dm00
260
252
261
- # Calculate the probability of entanglement (only one photon causes the detector to click)
262
- pent = alphaA * (1 - alphaB ) * etaA + \
263
- (1 - alphaA ) * alphaB * etaB
264
-
265
- # Calculate the post-measurement state in the case that a detector clicks due to a photon from A or B
266
- a = dp_photon
267
- b = 1 - dp_photon
268
- rho0 = (pent / (p0 + p1 )) * (a * dm_psi_plus + b * dm_psi_minus ) + (1 - pent / (p0 + p1 )) * dm11
269
-
270
- # Calculate the post-measurement state in the case that a dark count causes the detector to click
271
- if p2 != 0 :
272
- # Probability that neither endpoint emits a photon
273
- rho2 = (1 - alphaA ) * (1 - alphaB ) * dm00
274
-
275
- # Probability that left endpoint emits a photon and it gets lost
276
- rho2 += (alphaA * (1 - alphaB ) * (1 - etaA )) * dm10
277
-
278
- # Probability that right endpoint emits a photon and it gets lost
279
- rho2 += ((1 - alphaA ) * alphaB * (1 - etaB )) * dm01
280
-
281
- # Probability that both endpoints emit a photon and both are lost
282
- rho2 += (1 - etaA ) * (1 - etaB ) * alphaA * alphaB * dm11
283
- rho2 *= (1 / p2 )
284
-
285
- # Probability of no clicks is zero then there is no influence
286
- else :
287
- rho2 = zeros ((4 , 4 ))
288
-
289
- # Calculate the probability of registering a click in only one detector
290
- Y = (p0 + p1 ) * (1 - pdark ) + 2 * p2 * pdark * (1 - pdark )
291
-
292
- # Calculate the effective accepted state if a click in one detector occurs
293
- estimated_rho = (1 / Y ) * ((p0 + p1 ) * (1 - pdark ) * rho0 + 2 * p2 * pdark * (1 - pdark ) * rho2 )
253
+ # Normalise the state
254
+ estimated_rho = unnormalised_state / (p_uu + p_ud + p_du + p_dd )
294
255
295
256
return estimated_rho
296
257
@@ -324,17 +285,19 @@ def optimize_bright_state_population(self, p_success, min_fidelity):
324
285
325
286
return bright_state_populations
326
287
327
- def estimate_time_to_process (self , scheduler_request , units = "seconds" ):
288
+ def estimate_nr_of_attempts (self , scheduler_request ):
328
289
"""
329
- Computes the estimated time to process a request (assuming that this is the only request in the queues
330
- and that its ready)
290
+ Computes the estimated number of entanglement generation attempts needed generate ONE pair in the given request
291
+ (assuming that this is the only request in the queues and that its ready)
331
292
332
- The 'units' argument can be used to choose whether what is returned is in seconds or nr of mhp cycles
333
293
:param scheduler_request: :obj:`~qlinklayer.scheduler.SchedulerRequest`
334
- :param units: str (either "seconds" or "mhp_cycles")
335
- :return: float or int
294
+ :return: float
336
295
"""
337
- if not units in ["seconds" , "mhp_cycles" ]:
338
- raise ValueError ("'units' need to be 'seconds' or 'mhp_cycles'" )
339
- # TODO implement this
340
- return 1
296
+ alpha = self .select_bright_state (scheduler_request .min_fidelity )
297
+ # Get success probability given alpha
298
+ p_succ = self ._estimate_success_probability (alpha )
299
+
300
+ # Estimate number of attempts needed
301
+ est_nr_attempts = 1 / p_succ
302
+
303
+ return est_nr_attempts
0 commit comments