Skip to content

Commit d25bba6

Browse files
committed
Add a simple circuit fidelity analysis pass
1 parent 4dbe384 commit d25bba6

File tree

6 files changed

+122
-4
lines changed

6 files changed

+122
-4
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .analysis import FidelityAnalysis as FidelityAnalysis
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from dataclasses import field
2+
3+
from kirin import ir
4+
from kirin.lattice import EmptyLattice
5+
from kirin.analysis import Forward
6+
from kirin.interp.value import Successor
7+
from kirin.analysis.forward import ForwardFrame
8+
9+
10+
class FidelityAnalysis(Forward):
11+
"""
12+
This analysis pass can be used to track the global addresses of qubits and wires.
13+
"""
14+
15+
keys = ["circuit.fidelity"]
16+
lattice = EmptyLattice
17+
18+
# TODO: this should be a tuple[float, float] = (mean, max)
19+
current_fidelity: float = field(init=False)
20+
global_fidelity: float = 1.0
21+
22+
def initialize(self):
23+
super().initialize()
24+
self.current_fidelity = 1.0
25+
return self
26+
27+
def posthook_succ(self, frame: ForwardFrame, succ: Successor):
28+
self.global_fidelity *= self.current_fidelity
29+
30+
def eval_stmt_fallback(self, frame: ForwardFrame, stmt: ir.Statement):
31+
print(
32+
"no implementation for stmt "
33+
+ stmt.print_str(end="")
34+
+ " from "
35+
+ str(type(self))
36+
)
37+
return
38+
39+
def run_method(self, method: ir.Method, args: tuple[EmptyLattice, ...]):
40+
return self.run_callable(method.code, (self.lattice.bottom(),) + args)

src/bloqade/noise/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
from . import native as native
1+
# NOTE: just to register methods
2+
from . import native as native, fidelity as fidelity

src/bloqade/noise/fidelity.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from kirin import interp
2+
from kirin.lattice import EmptyLattice
3+
4+
from bloqade.analysis.fidelity import FidelityAnalysis
5+
6+
from .native import dialect
7+
from .native.stmts import PauliChannel, CZPauliChannel
8+
9+
10+
@dialect.register(key="circuit.fidelity")
11+
class FidelityMethodTable(interp.MethodTable):
12+
13+
@interp.impl(PauliChannel)
14+
@interp.impl(CZPauliChannel)
15+
def single_qubit_gate(
16+
self,
17+
interp: FidelityAnalysis,
18+
frame: interp.Frame[EmptyLattice],
19+
stmt: PauliChannel,
20+
):
21+
ps, ps_ctrl = stmt.probabilities
22+
p = sum(ps)
23+
24+
# NOTE: will be 0 if no ctrls
25+
p_ctrl = sum(ps_ctrl)
26+
27+
# NOTE: fidelity is just the inverse probability of any noise to occur
28+
fid = (1 - p) * (1 - p_ctrl)
29+
30+
interp.current_fidelity *= fid
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
from bloqade import qasm2
2+
from bloqade.noise import native
3+
from bloqade.analysis.fidelity import FidelityAnalysis
4+
from bloqade.qasm2.passes.noise import NoisePass
5+
6+
7+
class NoiseTestModel(native.MoveNoiseModelABC):
8+
def parallel_cz_errors(self, ctrls, qargs, rest):
9+
return {(0.01, 0.01, 0.01, 0.01): ctrls + qargs + rest}
10+
11+
12+
@qasm2.main.add(native.dialect)
13+
def main():
14+
q = qasm2.qreg(2)
15+
qasm2.x(q[0])
16+
return q
17+
18+
19+
main.print()
20+
21+
fid_analysis = FidelityAnalysis(main.dialects)
22+
fid_analysis.run_analysis(main)
23+
24+
assert fid_analysis.global_fidelity == fid_analysis.current_fidelity == 1
25+
26+
27+
px = 0.01
28+
py = 0.01
29+
pz = 0.01
30+
p_loss = 0.01
31+
32+
noise_params = native.GateNoiseParams(
33+
global_loss_prob=p_loss, global_px=px, global_py=py, global_pz=pz
34+
)
35+
36+
model = NoiseTestModel()
37+
38+
39+
NoisePass(main.dialects, noise_model=model, gate_noise_params=noise_params)(main)
40+
41+
42+
main.print()
43+
44+
fid_analysis = FidelityAnalysis(main.dialects)
45+
fid_analysis.run_analysis(main)
46+
47+
print(fid_analysis.global_fidelity)
48+
print(fid_analysis.current_fidelity)

test/qasm2/passes/test_heuristic_noise.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@
1212

1313

1414
class NoiseTestModel(native.MoveNoiseModelABC):
15-
16-
@classmethod
17-
def parallel_cz_errors(cls, ctrls, qargs, rest):
15+
def parallel_cz_errors(self, ctrls, qargs, rest):
1816
return {(0.01, 0.01, 0.01, 0.01): ctrls + qargs + rest}
1917

2018

0 commit comments

Comments
 (0)