Skip to content

Commit a2cb44c

Browse files
committed
Fix qasm2 impls
1 parent 26240d2 commit a2cb44c

File tree

2 files changed

+88
-45
lines changed

2 files changed

+88
-45
lines changed
Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from kirin import interp
2-
from kirin.lattice import EmptyLattice
2+
from kirin.analysis import ForwardFrame
33

4+
from bloqade.analysis.address import Address, AddressReg
45
from bloqade.analysis.fidelity import FidelityAnalysis
56

67
from .stmts import PauliChannel, CZPauliChannel, AtomLossChannel
@@ -11,37 +12,68 @@
1112
class FidelityMethodTable(interp.MethodTable):
1213

1314
@interp.impl(PauliChannel)
14-
@interp.impl(CZPauliChannel)
1515
def pauli_channel(
1616
self,
17-
interp: FidelityAnalysis,
18-
frame: interp.Frame[EmptyLattice],
19-
stmt: PauliChannel | CZPauliChannel,
17+
interp_: FidelityAnalysis,
18+
frame: ForwardFrame[Address],
19+
stmt: PauliChannel,
20+
):
21+
(ps,) = stmt.probabilities
22+
fidelity = 1 - sum(ps)
23+
24+
addresses = frame.get(stmt.qargs)
25+
26+
if not isinstance(addresses, AddressReg):
27+
return ()
28+
29+
interp_.update_fidelities(interp_.gate_fidelities, fidelity, addresses)
30+
31+
return ()
32+
33+
@interp.impl(CZPauliChannel)
34+
def cz_pauli_channel(
35+
self,
36+
interp_: FidelityAnalysis,
37+
frame: ForwardFrame[Address],
38+
stmt: CZPauliChannel,
2039
):
21-
probs = stmt.probabilities
22-
try:
23-
ps, ps_ctrl = probs
24-
except ValueError:
25-
(ps,) = probs
26-
ps_ctrl = ()
40+
ps_ctrl, ps_target = stmt.probabilities
41+
42+
fidelity_ctrl = 1 - sum(ps_ctrl)
43+
fidelity_target = 1 - sum(ps_target)
44+
45+
addresses_ctrl = frame.get(stmt.ctrls)
46+
addresses_target = frame.get(stmt.qargs)
2747

28-
p = sum(ps)
29-
p_ctrl = sum(ps_ctrl)
48+
if not isinstance(addresses_ctrl, AddressReg) or not isinstance(
49+
addresses_target, AddressReg
50+
):
51+
return ()
3052

31-
# NOTE: fidelity is just the inverse probability of any noise to occur
32-
fid = (1 - p) * (1 - p_ctrl)
53+
interp_.update_fidelities(
54+
interp_.gate_fidelities, fidelity_ctrl, addresses_ctrl
55+
)
56+
interp_.update_fidelities(
57+
interp_.gate_fidelities, fidelity_target, addresses_target
58+
)
3359

34-
interp.gate_fidelity *= fid
60+
return ()
3561

3662
@interp.impl(AtomLossChannel)
3763
def atom_loss(
3864
self,
39-
interp: FidelityAnalysis,
40-
frame: interp.Frame[EmptyLattice],
65+
interp_: FidelityAnalysis,
66+
frame: ForwardFrame[Address],
4167
stmt: AtomLossChannel,
4268
):
43-
# NOTE: since AtomLossChannel acts on IList[Qubit], we know the assigned address is a tuple
44-
addresses = interp.addr_frame.get(stmt.qargs)
45-
# NOTE: get the corresponding index and reduce survival probability accordingly
46-
for index in addresses.data:
47-
interp.atom_survival_probability[index] *= 1 - stmt.prob
69+
addresses = frame.get(stmt.qargs)
70+
71+
if not isinstance(addresses, AddressReg):
72+
return ()
73+
74+
fidelity = 1 - stmt.prob
75+
interp_.update_fidelities(
76+
interp_.qubit_survival_fidelities, fidelity, addresses
77+
)
78+
79+
return ()

test/analysis/fidelity/test_fidelity.py

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ def main():
2121
fid_analysis = FidelityAnalysis(main.dialects)
2222
fid_analysis.run(main)
2323

24-
assert fid_analysis.gate_fidelity == fid_analysis._current_gate_fidelity == 1
25-
assert fid_analysis.atom_survival_probability[0] == 1 - p_loss
26-
assert fid_analysis.atom_survival_probability[1] == 1
24+
assert fid_analysis.gate_fidelities == [FidelityRange(1.0, 1.0)] * 2
25+
assert fid_analysis.qubit_survival_fidelities == [
26+
FidelityRange(1 - p_loss, 1 - p_loss),
27+
FidelityRange(1.0, 1.0),
28+
]
2729

2830

2931
def test_cz_noise():
@@ -51,9 +53,12 @@ def main():
5153
fid_analysis = FidelityAnalysis(main.dialects)
5254
fid_analysis.run(main)
5355

54-
expected_fidelity = (1 - 3 * p_ch) ** 2
56+
expected_fidelity = 1 - 3 * p_ch
5557

56-
assert math.isclose(fid_analysis.gate_fidelity, expected_fidelity)
58+
assert (
59+
fid_analysis.gate_fidelities
60+
== [FidelityRange(expected_fidelity, expected_fidelity)] * 2
61+
)
5762

5863

5964
def test_single_qubit_noise():
@@ -72,7 +77,10 @@ def main():
7277

7378
expected_fidelity = 1 - 3 * p_ch
7479

75-
assert math.isclose(fid_analysis.gate_fidelity, expected_fidelity)
80+
assert fid_analysis.gate_fidelities == [
81+
FidelityRange(expected_fidelity, expected_fidelity),
82+
FidelityRange(1.0, 1.0),
83+
]
7684

7785

7886
class NoiseTestModel(noise.MoveNoiseModelABC):
@@ -113,6 +121,7 @@ def main_if():
113121

114122
model = NoiseTestModel(
115123
global_loss_prob=p_loss,
124+
local_loss_prob=p_loss,
116125
global_px=px,
117126
global_py=py,
118127
global_pz=pz,
@@ -122,18 +131,21 @@ def main_if():
122131
fid_analysis = FidelityAnalysis(main.dialects)
123132
fid_analysis.run(main)
124133

125-
model = NoiseTestModel()
126134
NoisePass(main_if.dialects, noise_model=model)(main_if)
127135
fid_if_analysis = FidelityAnalysis(main_if.dialects)
128136
fid_if_analysis.run(main_if)
129137

130-
assert 0 < fid_if_analysis.gate_fidelity == fid_analysis.gate_fidelity < 1
131-
assert (
132-
0
133-
< fid_if_analysis.atom_survival_probability[0]
134-
== fid_analysis.atom_survival_probability[0]
135-
< 1
136-
)
138+
main.print()
139+
main_if.print()
140+
141+
fidelity_if = fid_if_analysis.gate_fidelities[0]
142+
fidelity = fid_analysis.gate_fidelities[0]
143+
144+
survival = fid_analysis.qubit_survival_fidelities[0]
145+
survival_if = fid_if_analysis.qubit_survival_fidelities[0]
146+
147+
assert 0 < fidelity_if.min == fidelity.min == fidelity.max < fidelity_if.max < 1
148+
assert 0 < survival_if.min == survival.min == survival.max < survival_if.max < 1
137149

138150

139151
def test_for():
@@ -184,21 +196,20 @@ def main_for():
184196
fid_analysis = FidelityAnalysis(main.dialects)
185197
fid_analysis.run(main)
186198

187-
model = NoiseTestModel()
188199
NoisePass(main_for.dialects, noise_model=model)(main_for)
189200

190201
main_for.print()
191202

192203
fid_for_analysis = FidelityAnalysis(main_for.dialects)
193204
fid_for_analysis.run(main_for)
194205

195-
assert 0 < fid_for_analysis.gate_fidelity == fid_analysis.gate_fidelity < 1
196-
assert (
197-
0
198-
< fid_for_analysis.atom_survival_probability[0]
199-
== fid_analysis.atom_survival_probability[0]
200-
< 1
201-
)
206+
fid = fid_analysis.gate_fidelities[0]
207+
fid_for = fid_for_analysis.gate_fidelities[0]
208+
survival = fid_analysis.qubit_survival_fidelities[0]
209+
survival_for = fid_for_analysis.qubit_survival_fidelities[0]
210+
211+
assert 0 < fid.min == fid.max == fid_for.min == fid_for.max < 1
212+
assert 0 < survival.min == survival.max == survival_for.min == survival_for.max < 1
202213

203214

204215
def test_stdlib_call():

0 commit comments

Comments
 (0)