Skip to content

Commit 33bd5ff

Browse files
committed
Add gate name and target qubits to error information
1 parent de4d387 commit 33bd5ff

5 files changed

Lines changed: 84 additions & 52 deletions

File tree

examples/arxiv2303.17211_sc_measurement_free_prep.ipynb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,9 @@
183183
"output_type": "stream",
184184
"text": [
185185
"Circuit is not fault-tolerant. Fault-tolerant error locations:\n",
186-
"[Line 29] Z-Pauli error on Qubit 7\n",
187-
"[Line 29] X-Pauli error on Qubit 6\n",
188-
"[Line 29] Z-Pauli error on Qubit 6\n"
186+
"[Line 29] Z-Pauli error on qubit 7 after CNOT(qubit 6,qubit 7)\n",
187+
"[Line 29] X-Pauli error on qubit 6 after CNOT(qubit 6,qubit 7)\n",
188+
"[Line 29] Z-Pauli error on qubit 6 after CNOT(qubit 6,qubit 7)\n"
189189
]
190190
}
191191
],

examples/cat_state.ipynb

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,12 @@
5858
"id": "4702c9af",
5959
"metadata": {},
6060
"outputs": [
61-
{
62-
"name": "stderr",
63-
"output_type": "stream",
64-
"text": [
65-
"Precompiling QuantumSE...\n",
66-
" 1474.4 ms ✓ QuantumSE\n",
67-
" 1 dependency successfully precompiled in 2 seconds. 65 already precompiled.\n"
68-
]
69-
},
7061
{
7162
"name": "stdout",
7263
"output_type": "stream",
7364
"text": [
7465
"Circuit is not fault-tolerant. Fault-tolerant error locations:\n",
75-
"[Line 19] X-Pauli error on Qubit 0\n"
66+
"[Line 19] X-Pauli error on qubit 0 after CNOT(qubit 0,qubit 2)\n"
7667
]
7768
}
7869
],
@@ -119,6 +110,14 @@
119110
"\n",
120111
"print(res)"
121112
]
113+
},
114+
{
115+
"cell_type": "code",
116+
"execution_count": null,
117+
"id": "2210725d",
118+
"metadata": {},
119+
"outputs": [],
120+
"source": []
122121
}
123122
],
124123
"metadata": {

src/ucc_ft/QuantumSE.jl/src/SymbolicExecution.jl

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ function QuantSymEx(cfg::SymConfig)
102102
# 1-q Clifford
103103
let target_qubit = CEval(cfg.σ, inst.args[2])
104104
eval(inst.args[1])(cfg.ρ, target_qubit)
105-
counter = inject_symbolic_error(cfg.ρ, target_qubit, cfg.source_line)
105+
counter = inject_symbolic_error(cfg.ρ, target_qubit, cfg.source_line, string(inst.args[1]), [target_qubit])
106106
cfg.nerrs += zeroext(cfg.ctx, counter, NERRS)
107107
if cfg.verbose
108108
println(adderrcnt())
@@ -113,8 +113,8 @@ function QuantSymEx(cfg::SymConfig)
113113
# CNOT, CZ
114114
let target_qubit1 = CEval(cfg.σ, inst.args[2]), target_qubit2 = CEval(cfg.σ, inst.args[3])
115115
eval(inst.args[1])(cfg.ρ, target_qubit1, target_qubit2)
116-
counter1 = inject_symbolic_error(cfg.ρ, target_qubit1, cfg.source_line)
117-
counter2 = inject_symbolic_error(cfg.ρ, target_qubit2, cfg.source_line)
116+
counter1 = inject_symbolic_error(cfg.ρ, target_qubit1, cfg.source_line, string(inst.args[1]), [target_qubit1, target_qubit2])
117+
counter2 = inject_symbolic_error(cfg.ρ, target_qubit2, cfg.source_line, string(inst.args[1]), [target_qubit1, target_qubit2])
118118
counter = counter1 | counter2
119119
cfg.nerrs += zeroext(cfg.ctx, counter, NERRS)
120120
if cfg.verbose
@@ -126,7 +126,7 @@ function QuantSymEx(cfg::SymConfig)
126126
elseif inst.args[1] in [:sX, :sY, :sZ] # Symbolic X, Y, Z gates
127127
let target_qubit = CEval(cfg.σ, inst.args[2]), control_sym=CEval(cfg.σ, inst.args[3])
128128
eval(inst.args[1])(cfg.ρ, target_qubit, control_sym)
129-
counter = inject_symbolic_error(cfg.ρ, target_qubit, cfg.source_line)
129+
counter = inject_symbolic_error(cfg.ρ, target_qubit, cfg.source_line, string(inst.args[1]), [target_qubit])
130130
cfg.nerrs += zeroext(cfg.ctx, counter, NERRS)
131131
if cfg.verbose
132132
println(adderrcnt())
@@ -136,7 +136,7 @@ function QuantSymEx(cfg::SymConfig)
136136
elseif inst.args[1] == :sPauli # Symbolic Pauli gate
137137
let target_qubit = CEval(cfg.σ, inst.args[2]), control_sym1=CEval(cfg.σ, inst.args[3]), control_sym2=CEval(cfg.σ, inst.args[4])
138138
eval(inst.args[1])(cfg.ρ, target_qubit, control_sym1, control_sym2)
139-
counter = inject_symbolic_error(cfg.ρ, target_qubit, cfg.source_line)
139+
counter = inject_symbolic_error(cfg.ρ, target_qubit, cfg.source_line, "sPauli", [target_qubit])
140140
cfg.nerrs += zeroext(cfg.ctx, counter, NERRS)
141141
if cfg.verbose
142142
println(adderrcnt())
@@ -145,9 +145,9 @@ function QuantSymEx(cfg::SymConfig)
145145
end
146146
elseif inst.args[1] == :M # Measurement Z basis
147147
let target_qubit = CEval(cfg.σ, inst.args[2]), sym_name=eval(CEval(cfg.σ, inst.args[3]))
148-
counter1 = inject_symbolic_Xerror(cfg.ρ, target_qubit, cfg.source_line)
148+
counter1 = inject_symbolic_Xerror(cfg.ρ, target_qubit, cfg.source_line, "M", [target_qubit])
149149
cfg.σ[:__res__] = eval(inst.args[1])(cfg.ρ, target_qubit, sym_name)
150-
counter2 = inject_symbolic_Xerror(cfg.ρ, target_qubit, cfg.source_line)
150+
counter2 = inject_symbolic_Xerror(cfg.ρ, target_qubit, cfg.source_line, "M", [target_qubit])
151151
counter = counter1 | counter2
152152
cfg.nerrs += zeroext(cfg.ctx, counter, NERRS)
153153
if cfg.verbose
@@ -157,9 +157,9 @@ function QuantSymEx(cfg::SymConfig)
157157
end
158158
elseif inst.args[1] == :MX # Measurement X basis
159159
let target_qubit = CEval(cfg.σ, inst.args[2]), sym_name=eval(CEval(cfg.σ, inst.args[3]))
160-
counter1 = inject_symbolic_Zerror(cfg.ρ, target_qubit, cfg.source_line)
160+
counter1 = inject_symbolic_Zerror(cfg.ρ, target_qubit, cfg.source_line, "MX", [target_qubit])
161161
cfg.σ[:__res__] = eval(inst.args[1])(cfg.ρ, target_qubit, sym_name)
162-
counter2 = inject_symbolic_Zerror(cfg.ρ, target_qubit, cfg.source_line)
162+
counter2 = inject_symbolic_Zerror(cfg.ρ, target_qubit, cfg.source_line, "MX", [target_qubit])
163163
counter = counter1 | counter2
164164
cfg.nerrs += zeroext(cfg.ctx, counter, NERRS)
165165
if cfg.verbose
@@ -169,7 +169,7 @@ function QuantSymEx(cfg::SymConfig)
169169
end
170170
elseif inst.args[1] == :DestructiveM # Destructive Measurement Z basis
171171
let target_qubit = CEval(cfg.σ, inst.args[2]), sym_name=eval(CEval(cfg.σ, inst.args[3]))
172-
counter1 = inject_symbolic_Xerror(cfg.ρ, target_qubit, cfg.source_line)
172+
counter1 = inject_symbolic_Xerror(cfg.ρ, target_qubit, cfg.source_line, "DestructiveM", [target_qubit])
173173
cfg.σ[:__res__] = eval(inst.args[1])(cfg.ρ, target_qubit, sym_name)
174174
#counter2 = inject_symbolic_Xerror(cfg.ρ, target_qubit)
175175
counter = counter1 #| counter2
@@ -181,7 +181,7 @@ function QuantSymEx(cfg::SymConfig)
181181
end
182182
elseif inst.args[1] == :DestructiveMX # Destructive Measurement X basis
183183
let target_qubit = CEval(cfg.σ, inst.args[2]), sym_name=eval(CEval(cfg.σ, inst.args[3]))
184-
counter1 = inject_symbolic_Zerror(cfg.ρ, target_qubit, cfg.source_line)
184+
counter1 = inject_symbolic_Zerror(cfg.ρ, target_qubit, cfg.source_line, "DestructiveMX", [target_qubit])
185185
cfg.σ[:__res__] = eval(inst.args[1])(cfg.ρ, target_qubit, sym_name)
186186
#counter2 = inject_symbolic_Zerror(cfg.ρ, target_qubit)
187187
counter = counter1 #| counter2
@@ -194,7 +194,7 @@ function QuantSymEx(cfg::SymConfig)
194194
elseif inst.args[1] == :INIT # INIT |0>
195195
let target_qubit = CEval(cfg.σ, inst.args[2])
196196
eval(inst.args[1])(cfg.ρ, target_qubit, "INIT")
197-
counter = inject_symbolic_Xerror(cfg.ρ, target_qubit, cfg.source_line)
197+
counter = inject_symbolic_Xerror(cfg.ρ, target_qubit, cfg.source_line, "INIT", [target_qubit])
198198
cfg.nerrs += zeroext(cfg.ctx, counter, NERRS)
199199
if cfg.verbose
200200
println(adderrcnt())
@@ -204,7 +204,7 @@ function QuantSymEx(cfg::SymConfig)
204204
elseif inst.args[1] == :INITP # INIT |+>
205205
let target_qubit = CEval(cfg.σ, inst.args[2])
206206
eval(inst.args[1])(cfg.ρ, target_qubit, "INITP")
207-
counter = inject_symbolic_Zerror(cfg.ρ, target_qubit, cfg.source_line)
207+
counter = inject_symbolic_Zerror(cfg.ρ, target_qubit, cfg.source_line, "INITP", [target_qubit])
208208
cfg.nerrs += zeroext(cfg.ctx, counter, NERRS)
209209
if cfg.verbose
210210
println(adderrcnt())
@@ -214,8 +214,8 @@ function QuantSymEx(cfg::SymConfig)
214214
elseif inst.args[1] == :INIT2CNOT12 # INIT |0> on qubit 2, CNOT on qubits 1, 2
215215
let target_qubit1 = CEval(cfg.σ, inst.args[2]), target_qubit2 = CEval(cfg.σ, inst.args[3])
216216
eval(inst.args[1])(cfg.ρ, target_qubit1, target_qubit2, "INIT2CNOT12")
217-
counter1 = inject_symbolic_error(cfg.ρ, target_qubit1, cfg.source_line)
218-
counter2 = inject_symbolic_Xerror(cfg.ρ, target_qubit2, cfg.source_line)
217+
counter1 = inject_symbolic_error(cfg.ρ, target_qubit1, cfg.source_line, "INIT2CNOT12", [target_qubit1, target_qubit2])
218+
counter2 = inject_symbolic_Xerror(cfg.ρ, target_qubit2, cfg.source_line, "INIT2CNOT12", [target_qubit1, target_qubit2])
219219
counter = counter1 | counter2
220220
cfg.nerrs += zeroext(cfg.ctx, counter, NERRS)
221221
if cfg.verbose
@@ -225,8 +225,8 @@ function QuantSymEx(cfg::SymConfig)
225225
end
226226
elseif inst.args[1] == :CNOT12DestructiveM2 #CNOT on qubits 1, 2, DestructiveM on qubit 2
227227
let target_qubit1 = CEval(cfg.σ, inst.args[2]), target_qubit2 = CEval(cfg.σ, inst.args[3]), sym_name=eval(CEval(cfg.σ, inst.args[4]))
228-
counter1 = inject_symbolic_error(cfg.ρ, target_qubit1, cfg.source_line)
229-
counter2 = inject_symbolic_Xerror(cfg.ρ, target_qubit2, cfg.source_line)
228+
counter1 = inject_symbolic_error(cfg.ρ, target_qubit1, cfg.source_line, "CNOT12DestructiveM2", [target_qubit1, target_qubit2])
229+
counter2 = inject_symbolic_Xerror(cfg.ρ, target_qubit2, cfg.source_line, "CNOT12DestructiveM2", [target_qubit1, target_qubit2])
230230
cfg.σ[:__res__] = eval(inst.args[1])(cfg.ρ, target_qubit1, target_qubit2, sym_name)
231231
counter = counter1 | counter2
232232
cfg.nerrs += zeroext(cfg.ctx, counter, NERRS)
@@ -237,8 +237,8 @@ function QuantSymEx(cfg::SymConfig)
237237
end
238238
elseif inst.args[1] == :CNOT12DestructiveMX1 #CNOT on qubits 1, 2, DestructiveMX on qubit 1
239239
let target_qubit1 = CEval(cfg.σ, inst.args[2]), target_qubit2 = CEval(cfg.σ, inst.args[3]), sym_name=eval(CEval(cfg.σ, inst.args[4]))
240-
counter1 = inject_symbolic_Zerror(cfg.ρ, target_qubit1, cfg.source_line)
241-
counter2 = inject_symbolic_error(cfg.ρ, target_qubit2, cfg.source_line)
240+
counter1 = inject_symbolic_Zerror(cfg.ρ, target_qubit1, cfg.source_line, "CNOT12DestructiveMX1", [target_qubit1, target_qubit2])
241+
counter2 = inject_symbolic_error(cfg.ρ, target_qubit2, cfg.source_line, "CNOT12DestructiveMX1", [target_qubit1, target_qubit2])
242242
cfg.σ[:__res__] = eval(inst.args[1])(cfg.ρ, target_qubit1, target_qubit2, sym_name)
243243
counter = counter1 | counter2
244244
cfg.nerrs += zeroext(cfg.ctx, counter, NERRS)
@@ -249,8 +249,8 @@ function QuantSymEx(cfg::SymConfig)
249249
end
250250
elseif inst.args[1] == :CZ12DestructiveMX1 #CZ on qubits 1, 2, DestructiveMX on qubit 1
251251
let target_qubit1 = CEval(cfg.σ, inst.args[2]), target_qubit2 = CEval(cfg.σ, inst.args[3]), sym_name=eval(CEval(cfg.σ, inst.args[4]))
252-
counter1 = inject_symbolic_Zerror(cfg.ρ, target_qubit1, cfg.source_line)
253-
counter2 = inject_symbolic_error(cfg.ρ, target_qubit2, cfg.source_line)
252+
counter1 = inject_symbolic_Zerror(cfg.ρ, target_qubit1, cfg.source_line, "CZ12DestructiveMX1", [target_qubit1, target_qubit2])
253+
counter2 = inject_symbolic_error(cfg.ρ, target_qubit2, cfg.source_line, "CZ12DestructiveMX1", [target_qubit1, target_qubit2])
254254
cfg.σ[:__res__] = eval(inst.args[1])(cfg.ρ, target_qubit1, target_qubit2, sym_name)
255255
counter = counter1 | counter2
256256
cfg.nerrs += zeroext(cfg.ctx, counter, NERRS)
@@ -263,10 +263,11 @@ function QuantSymEx(cfg::SymConfig)
263263
let target_qubits = CEval(cfg.σ, inst.args[2])
264264
cfg.σ[:__res__] = eval(inst.args[1])(cfg.ρ, target_qubits)
265265
b_num_target_qubits = _range2b(length(target_qubits))
266-
counter1 = zeroext(cfg.ctx, inject_symbolic_Zerror(cfg.ρ, target_qubits[1], cfg.source_line), b_num_target_qubits) #a single Z error suffices
266+
target_qubits_int = map(x -> x isa Int64 ? x : Int(x), target_qubits)
267+
counter1 = zeroext(cfg.ctx, inject_symbolic_Zerror(cfg.ρ, target_qubits[1], cfg.source_line, "CatPreparationMod", target_qubits_int), b_num_target_qubits) #a single Z error suffices
267268
counter2 = bv_val(cfg.ctx, 0, b_num_target_qubits)
268269
for jj in 1:length(target_qubits)
269-
tmp_counter = inject_symbolic_Xerror(cfg.ρ, target_qubits[jj], cfg.source_line)
270+
tmp_counter = inject_symbolic_Xerror(cfg.ρ, target_qubits[jj], cfg.source_line, "CatPreparationMod", target_qubits_int)
270271
counter2 += zeroext(cfg.ctx, tmp_counter, b_num_target_qubits)
271272
if cfg.verbose
272273
println(adderrcnt())
@@ -288,8 +289,9 @@ function QuantSymEx(cfg::SymConfig)
288289
b_num_target_qubits = _range2b(length(target_qubits))
289290
counter1 = zeroext(cfg.ctx, bit_error, b_num_target_qubits) #a single bit-flip error suffices
290291
counter2 = bv_val(cfg.ctx, 0, b_num_target_qubits)
292+
target_qubits_int = map(x -> x isa Int64 ? x : Int(x), target_qubits)
291293
for jj in 1:length(target_qubits)
292-
tmp_counter = inject_symbolic_error(cfg.ρ, target_qubits[jj], cfg.source_line)
294+
tmp_counter = inject_symbolic_error(cfg.ρ, target_qubits[jj], cfg.source_line, "MultiPauliMeasurement", target_qubits_int)
293295
counter2 += zeroext(cfg.ctx, tmp_counter, b_num_target_qubits)
294296
if cfg.verbose
295297
println(adderrcnt())

src/ucc_ft/QuantumSE.jl/src/SymbolicStabilizer.jl

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -913,10 +913,11 @@ function reset_varid()
913913
__allocvarid = 0
914914
end
915915

916-
function inject_symbolic_error(q::SymStabilizerState, target_qubit::Int, source_line::Int = -1)
916+
function inject_symbolic_error(q::SymStabilizerState, target_qubit::Int, source_line::Int = -1, operation_name::String = "", operation_qubits::Vector{Int} = Int[])
917917
line_suffix = source_line >= 0 ? "_L$(source_line)" : ""
918-
xerr_symb = alloc_symb(q.ctx, "symb_Xerror_Q$(target_qubit)$(line_suffix)")
919-
zerr_symb = alloc_symb(q.ctx, "symb_Zerror_Q$(target_qubit)$(line_suffix)")
918+
op_suffix = operation_name != "" ? "_OP$(operation_name)_QS$(join(operation_qubits, "_"))" : ""
919+
xerr_symb = alloc_symb(q.ctx, "symb_Xerror_Q$(target_qubit)$(line_suffix)$(op_suffix)")
920+
zerr_symb = alloc_symb(q.ctx, "symb_Zerror_Q$(target_qubit)$(line_suffix)$(op_suffix)")
920921

921922
#sX!(q, target_qubit, xerr_symb & ~zerr_symb)
922923
#sY!(q, target_qubit, xerr_symb & zerr_symb)
@@ -927,9 +928,10 @@ function inject_symbolic_error(q::SymStabilizerState, target_qubit::Int, source_
927928
return xerr_symb | zerr_symb
928929
end
929930

930-
function inject_symbolic_Xerror(q::SymStabilizerState, target_qubit::Int, source_line::Int = -1)
931+
function inject_symbolic_Xerror(q::SymStabilizerState, target_qubit::Int, source_line::Int = -1, operation_name::String = "", operation_qubits::Vector{Int} = Int[])
931932
line_suffix = source_line >= 0 ? "_L$(source_line)" : ""
932-
xerr_symb = alloc_symb(q.ctx, "symb_Xerror_Q$(target_qubit)$(line_suffix)")
933+
op_suffix = operation_name != "" ? "_OP$(operation_name)_QS$(join(operation_qubits, "_"))" : ""
934+
xerr_symb = alloc_symb(q.ctx, "symb_Xerror_Q$(target_qubit)$(line_suffix)$(op_suffix)")
933935
#zerr_symb = alloc_symb(q, "symb_Zerror")
934936

935937
#sX!(q, target_qubit, xerr_symb & ~zerr_symb)
@@ -941,10 +943,11 @@ function inject_symbolic_Xerror(q::SymStabilizerState, target_qubit::Int, source
941943
return xerr_symb
942944
end
943945

944-
function inject_symbolic_Zerror(q::SymStabilizerState, target_qubit::Int, source_line::Int = -1)
946+
function inject_symbolic_Zerror(q::SymStabilizerState, target_qubit::Int, source_line::Int = -1, operation_name::String = "", operation_qubits::Vector{Int} = Int[])
945947
line_suffix = source_line >= 0 ? "_L$(source_line)" : ""
948+
op_suffix = operation_name != "" ? "_OP$(operation_name)_QS$(join(operation_qubits, "_"))" : ""
946949
#xerr_symb = alloc_symb(q, "symb_Xerror")
947-
zerr_symb = alloc_symb(q.ctx, "symb_Zerror_Q$(target_qubit)$(line_suffix)")
950+
zerr_symb = alloc_symb(q.ctx, "symb_Zerror_Q$(target_qubit)$(line_suffix)$(op_suffix)")
948951

949952
#sX!(q, target_qubit, xerr_symb & ~zerr_symb)
950953
#sY!(q, target_qubit, xerr_symb & zerr_symb)
@@ -957,10 +960,11 @@ end
957960

958961

959962

960-
function inject_symbolic_error_SymPauli(q::SymStabilizerState, target_qubit::Int, control_sym::Z3.Expr, source_line::Int = -1)
963+
function inject_symbolic_error_SymPauli(q::SymStabilizerState, target_qubit::Int, control_sym::Z3.Expr, source_line::Int = -1, operation_name::String = "", operation_qubits::Vector{Int} = Int[])
961964
line_suffix = source_line >= 0 ? "_L$(source_line)" : ""
962-
xerr_symb = alloc_symb(q.ctx, "symb_Xerror_Q$(target_qubit)$(line_suffix)")
963-
zerr_symb = alloc_symb(q.ctx, "symb_Zerror_Q$(target_qubit)$(line_suffix)")
965+
op_suffix = operation_name != "" ? "_OP$(operation_name)_QS$(join(operation_qubits, "_"))" : ""
966+
xerr_symb = alloc_symb(q.ctx, "symb_Xerror_Q$(target_qubit)$(line_suffix)$(op_suffix)")
967+
zerr_symb = alloc_symb(q.ctx, "symb_Zerror_Q$(target_qubit)$(line_suffix)$(op_suffix)")
964968

965969
#sX!(q, target_qubit, xerr_symb & ~zerr_symb)
966970
#sY!(q, target_qubit, xerr_symb & zerr_symb)

0 commit comments

Comments
 (0)