You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -50,8 +52,19 @@ function multiple_steps_with_history!(
50
52
fitness_history[1, :] = [i.fitness for i in population.individuals]
51
53
transition_counts = []
52
54
55
+
throttling_warned =0
56
+
53
57
for i in1:steps
54
58
step!(population; step_config...)
59
+
60
+
# Check to make sure that the optimizer is not in the 'fitness = 1.0' failure mode
61
+
if population.individuals[1].fitness ==1.0&& throttling_warned < THROTTLE_WARNINGS
62
+
throttling_warned +=1
63
+
@warn "Simulation is throttled: Increase simulation count, or decrease new mutants to fix. Top circuit has fitness = 1.0"
64
+
# If fitness is 1, then all of the simulations done to evaluate a circuit show no errors. This implies the circuit is good, but stops the optimizer from performing well. Increasing simulation count can fix this issue
65
+
# but, decreasing new mutants will also fix the issue. This is because fewer new circuits need to be simulated, causing more simulations on the current circuits to get a better non-1.0 fidelity.
66
+
end
67
+
55
68
fitness_history[i+1,:] = [i.fitness for i in population.individuals]
56
69
push!(transition_counts, counter([i.history for i in population.individuals]))
57
70
step_callback()
@@ -138,21 +151,26 @@ function simulate_and_sort!(
138
151
purified_pairs::Int=1,
139
152
number_registers::Int=2, #TODO (low priority) this should be by-default derived from `indiv`
140
153
code_distance::Int=1,
141
-
noises=[NetworkFidelity(0.9)]
154
+
noises=[NetworkFidelity(0.9)],
155
+
max_performance_calcs::Int=10
142
156
)
143
157
# calculate and update each individual's performance
144
158
function update!(indiv)
145
-
calculate_performance!(indiv;
146
-
num_simulations,
147
-
purified_pairs,
148
-
number_registers,
149
-
code_distance,
150
-
noises)
159
+
# Restrict performance calculation if this indiv has already reached the max calcs.
160
+
# However, if the calculated fidelity is undetermined (1.0), then it needs more calculations to try and get a non-one value (ie: 0.9999).
161
+
# Otherwise, if circuits have a fidelity of 1.0, it is difficult to distinguish between ones that are better (f:0.9999) or worse (f:0.9997).
162
+
if indiv.performance.num_calcs < max_performance_calcs || indiv.fitness ==1.0
163
+
calculate_performance!(indiv;
164
+
num_simulations,
165
+
purified_pairs,
166
+
number_registers,
167
+
code_distance,
168
+
noises)
169
+
end
151
170
indiv.fitness = indiv.performance.purified_pairs_fidelity #TODO make it possible to select the type of fitness to evaluate
152
171
end
153
172
154
173
# Parallel processing for performance calculations. Max threads will be set by the threads specified when running julia. ex) julia -t 16
155
-
max_threads::Int= Threads.nthreads()
156
174
157
175
tmap(update!,population.individuals)
158
176
@@ -177,7 +195,8 @@ function initialize_pop!(
177
195
num_simulations::Int=100,
178
196
purified_pairs::Int=1,
179
197
code_distance::Int=1,
180
-
noises=[NetworkFidelity(0.9)]
198
+
noises=[NetworkFidelity(0.9)],
199
+
max_performance_calcs=10
181
200
)
182
201
valid_pairs=1:number_registers #TODO (low priority) decouple valid_pairs from number_registers
Copy file name to clipboardExpand all lines: src/performance_eval.jl
+33-3Lines changed: 33 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -14,6 +14,13 @@ function calculate_performance!(
14
14
15
15
count_success =0
16
16
counts_marginals = zeros(Int,purified_pairs) # an array to find F₁, F₂, …, Fₖ (tracks how often each purified bell pair is in the desired state)
17
+
18
+
# Edge case: purified pairs/registers have changed, and the circuit has previously had a performance calculation. In this case, the previous performance must be discarded, as its error probabilities are now invalid.
19
+
if indiv.performance.num_calcs >0&& length(indiv.performance.error_probabilities) != purified_pairs+1
20
+
# signal the previous performance to be discarded
21
+
indiv.performance = Performance() # implies it is a blank performance
22
+
end
23
+
17
24
counts_nb_errors = zeros(Int,purified_pairs+1) # an array to find P₀, P₁, …, Pₖ (tracks how often a given total number of errors happens) Careful with indexing it as it includes a P₀!
18
25
19
26
noisy_purification_circuit = indiv.ops
@@ -39,8 +46,8 @@ function calculate_performance!(
39
46
end
40
47
41
48
if count_success ==0
42
-
indiv.performance = Performance(counts_nb_errors, 0,0, 0, 0) #TODO this is probably going to break the optimization runs and lead to picking low performing individuals for certain cost functions -- do this better
43
-
return indiv.performance
49
+
#TODO this is probably going to break the optimization runs and lead to picking low performing individuals for certain cost functions -- do this better
p_success = count_success / num_simulations # proportion of successful simulations
@@ -50,7 +57,30 @@ function calculate_performance!(
50
57
correctable_errors = div(code_distance -1, 2) # maximum number of correctable errors based on code distance after teleportation
51
58
indiv_logical_qubit_fidelity = sum(err_probs[1:min(end, correctable_errors+1)]) # calculates the logical qubit fidelity by summing the probabilities of correctable errors
Helper function to deal with circuit init, and performance averaging. The indiv given will have their performance averaged with the new performance, if their current performance is defined (nonzero). Otherwise, the new performance will overrite their current.
74
+
"""
75
+
function update_performance!(indiv::Individual,new::Performance)
76
+
@assert new.num_calcs >=1# This should always be the case at this point. The new performance should not be empty.
54
77
78
+
if indiv.performance.num_calcs ==0
79
+
# old perf has not been calculated yet/not usable, so use the new one
const THROTTLE_WARNINGS =10# max amount of warnings per multiple_steps_with_history! call
5
+
4
6
"A convenient structure to store various purification performance metrics."
5
7
struct Performance
6
8
"a list of probabilities as such `[probability for no errors, probability for one Bell pair to be erroneous, probability for two Bell pairs to be erroneous, ..., probability for all Bell pairs to be erroneous]`"
@@ -15,12 +17,62 @@ struct Performance
15
17
average_marginal_fidelity::Float64
16
18
"the proportion of runs of a given protocol that do not have detected errors (i.e. Alice and Bob do not measure any errors)"
17
19
success_probability::Float64
20
+
"the number of times that performance has been calculated and averaged for this circuit"
0 commit comments