Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fidelities #906

Merged
merged 11 commits into from
Jun 10, 2024
33 changes: 28 additions & 5 deletions src/qibolab/dummy/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,8 @@
"Ec": 0.0,
"Ej": 0.0,
"g": 0.0,
"assignment_fidelity": 0.0,
"assignment_fidelity": [0.5, 0.1],
"gate_fidelity": [0.5, 0.1],
"peak_voltage": 0,
"pi_pulse_amplitude": 0,
"T1": 0.0,
Expand Down Expand Up @@ -546,7 +547,8 @@
"Ec": 0.0,
"Ej": 0.0,
"g": 0.0,
"assignment_fidelity": 0.0,
"assignment_fidelity": [0.5, 0.1],
"gate_fidelity": [0.5, 0.1],
"peak_voltage": 0,
"pi_pulse_amplitude": 0,
"T1": 0.0,
Expand Down Expand Up @@ -582,7 +584,8 @@
"Ec": 0.0,
"Ej": 0.0,
"g": 0.0,
"assignment_fidelity": 0.0,
"assignment_fidelity": [0.5, 0.1],
"gate_fidelity": [0.5, 0.1],
"peak_voltage": 0,
"pi_pulse_amplitude": 0,
"T1": 0.0,
Expand Down Expand Up @@ -618,7 +621,8 @@
"Ec": 0.0,
"Ej": 0.0,
"g": 0.0,
"assignment_fidelity": 0.0,
"assignment_fidelity": [0.5, 0.1],
"gate_fidelity": [0.5, 0.1],
"peak_voltage": 0,
"pi_pulse_amplitude": 0,
"T1": 0.0,
Expand Down Expand Up @@ -654,7 +658,8 @@
"Ec": 0.0,
"Ej": 0.0,
"g": 0.0,
"assignment_fidelity": 0.0,
"assignment_fidelity": [0.5, 0.1],
"gate_fidelity": [0.5, 0.1],
"peak_voltage": 0,
"pi_pulse_amplitude": 0,
"T1": 0.0,
Expand All @@ -678,6 +683,24 @@
"mixer_readout_phi": 0.0
}
},
"two_qubit":{
"0-2": {
"gate_fidelity": [0.5, 0.1],
"cz_fidelity": [0.5, 0.1]
},
"1-2": {
"gate_fidelity": [0.5, 0.1],
"cz_fidelity": [0.5, 0.1]
},
"3-2": {
"gate_fidelity": [0.5, 0.1],
"cz_fidelity": [0.5, 0.1]
},
"4-2": {
"gate_fidelity": [0.5, 0.1],
"cz_fidelity": [0.5, 0.1]
}
},
"coupler": {
"0": {
"sweetspot": 0.0
Expand Down
28 changes: 27 additions & 1 deletion src/qibolab/qubits.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,15 @@

Not all channels are required to operate a qubit.
"""
EXCLUDED_FIELDS = CHANNEL_NAMES + ("name", "native_gates", "kernel", "_flux")
EXCLUDED_FIELDS = CHANNEL_NAMES + (
"name",
"native_gates",
"kernel",
"_flux",
"qubit1",
"qubit2",
Comment on lines +23 to +24
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are these names coming from?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

qubit1: Qubit

since now EXCLUDE_FIELDS is also used in QubitPair
if fld.name not in EXCLUDED_FIELDS

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I now wonder whether it would be a better option to have one each...

Btw, we don't even strictly need the EXCLUDED_FIELDS constant, but we could use field(..., metadata={"excluded": True}) or use Annotated[..., EXCLUDED] as type hint (defining an EXCLUDED constant), to keep it local to the ignored field.

Copy link
Member

@alecandido alecandido Jun 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(a possible way of defining unique constants can be found in the standard library https://github.com/python/cpython/blob/b03d71d0d8415281e71ae4f1455222db4b4b66d2/Lib/dataclasses.py#L184-L186)

(at runtime, you could filter dataclass.fields() by using EXCLUDED not in field.type.__metadata__)

"coupler",
)
"""Qubit dataclass fields that are excluded by the ``characterization``
property."""

Expand Down Expand Up @@ -61,6 +69,9 @@ class Qubit:
"""Assignment fidelity."""
readout_fidelity: float = 0.0
"""Readout fidelity."""
gate_fidelity: float = 0.0
"""Gate fidelity from standard RB."""

effective_temperature: float = 0.0
"""Effective temperature."""
peak_voltage: float = 0
Expand Down Expand Up @@ -163,6 +174,21 @@ class QubitPair:
Acts as target on two-qubit gates.
"""

gate_fidelity: float = 0.0
"""Gate fidelity from standard 2q RB."""

cz_fidelity: float = 0.0
"""Gate fidelity from CZ interleaved RB."""

coupler: Optional[Coupler] = None

native_gates: TwoQubitNatives = field(default_factory=TwoQubitNatives)

@property
def characterization(self):
"""Dictionary containing characterization parameters."""
return {
fld.name: getattr(self, fld.name)
for fld in fields(self)
if fld.name not in EXCLUDED_FIELDS
}
47 changes: 31 additions & 16 deletions src/qibolab/serialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,22 @@ def load_qubits(
for c, char in runcard["characterization"]["coupler"].items()
}

for c, pair in runcard["topology"].items():
q0, q1 = pair
for pair, char in zip(
Jacfomg marked this conversation as resolved.
Show resolved Hide resolved
runcard["topology"].items(),
runcard["characterization"]["two_qubit"].values(),
):
q0, q1 = pair[1]
pairs[(q0, q1)] = pairs[(q1, q0)] = QubitPair(
Jacfomg marked this conversation as resolved.
Show resolved Hide resolved
qubits[q0], qubits[q1], couplers[json.loads(c)]
qubits[q0], qubits[q1], **char, coupler=couplers[json.loads(pair[0])]
)
else:
for pair in runcard["topology"]:
elif "two_qubit" in runcard["characterization"]:
for pair, char in zip(
Jacfomg marked this conversation as resolved.
Show resolved Hide resolved
Jacfomg marked this conversation as resolved.
Show resolved Hide resolved
runcard["topology"], runcard["characterization"]["two_qubit"].values()
):
q0, q1 = pair
pairs[(q0, q1)] = pairs[(q1, q0)] = QubitPair(qubits[q0], qubits[q1], None)
pairs[(q0, q1)] = pairs[(q1, q0)] = QubitPair(
qubits[q0], qubits[q1], **char, coupler=None
)

qubits, pairs, couplers = register_gates(runcard, qubits, pairs, couplers)

Expand Down Expand Up @@ -110,8 +117,7 @@ def register_gates(
for pair, gatedict in native_gates.get("two_qubit", {}).items():
q0, q1 = tuple(int(q) if q.isdigit() else q for q in pair.split("-"))
native_gates = TwoQubitNatives.from_dict(qubits, couplers, gatedict)
coupler = pairs[(q0, q1)].coupler
pairs[(q0, q1)] = QubitPair(qubits[q0], qubits[q1], coupler, native_gates)
pairs[(q0, q1)].native_gates = native_gates
if native_gates.symmetric:
pairs[(q1, q0)] = pairs[(q0, q1)]

Expand Down Expand Up @@ -144,17 +150,20 @@ def dump_native_gates(
}

# two-qubit native gates
native_gates["two_qubit"] = {}
for pair in pairs.values():
natives = pair.native_gates.raw
if len(natives) > 0:
pair_name = f"{pair.qubit1.name}-{pair.qubit2.name}"
native_gates["two_qubit"][pair_name] = natives
if pairs:
Jacfomg marked this conversation as resolved.
Show resolved Hide resolved
native_gates["two_qubit"] = {}
for pair in pairs.values():
natives = pair.native_gates.raw
if len(natives) > 0:
pair_name = f"{pair.qubit1.name}-{pair.qubit2.name}"
native_gates["two_qubit"][pair_name] = natives

return native_gates


def dump_characterization(qubits: QubitMap, couplers: CouplerMap = None) -> dict:
def dump_characterization(
qubits: QubitMap, pairs: QubitPairMap = None, couplers: CouplerMap = None
) -> dict:
"""Dump qubit characterization section to dictionary following the runcard
format, using qubit and pair objects."""
characterization = {
Expand All @@ -163,6 +172,11 @@ def dump_characterization(qubits: QubitMap, couplers: CouplerMap = None) -> dict
},
}

if pairs:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if pairs:
if pairs is not None:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pairs is an empty dictionary, if I make it a None when there is no qubit pairs it will start complaining in several places when it gets asked for values. So could I keep this to check for empty dictionaries ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess he meant len(pairs) > 0.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah sure, that I can do

characterization["two_qubit"] = {
json.dumps(p): pair.characterization for p, pair in pairs.items()
}

if couplers:
characterization["coupler"] = {
json.dumps(c.name): {"sweetspot": c.sweetspot} for c in couplers.values()
Expand Down Expand Up @@ -221,8 +235,9 @@ def dump_runcard(platform: Platform, path: Path):
settings["native_gates"] = dump_native_gates(
platform.qubits, platform.pairs, platform.couplers
)

settings["characterization"] = dump_characterization(
platform.qubits, platform.couplers
platform.qubits, platform.pairs, platform.couplers
)

(path / RUNCARD).write_text(json.dumps(settings, sort_keys=False, indent=4))
Expand Down
18 changes: 18 additions & 0 deletions tests/dummy_qrc/qblox/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,24 @@
"iq_angle": 7.997,
"threshold": 0.002323
}
},
"two_qubit":{
"0-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
},
"1-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
},
"3-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
},
"4-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
}
}
}
}
18 changes: 18 additions & 0 deletions tests/dummy_qrc/qm/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,24 @@
"mixer_readout_g": 0.0,
"mixer_readout_phi": 0.0
}
},
"two_qubit":{
"0-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
},
"1-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
},
"3-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
},
"4-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
}
}
}
}
18 changes: 18 additions & 0 deletions tests/dummy_qrc/qm_octave/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,24 @@
"mixer_readout_g": 0.0,
"mixer_readout_phi": 0.0
}
},
"two_qubit":{
"0-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
},
"1-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
},
"3-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
},
"4-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
}
}
}
}
3 changes: 1 addition & 2 deletions tests/dummy_qrc/rfsoc/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@
"phase": 0
}
}
},
"two_qubit": {}
}
},
"characterization": {
"single_qubit": {
Expand Down
18 changes: 18 additions & 0 deletions tests/dummy_qrc/zurich/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,24 @@
"iq_angle": 0.481
}
},
"two_qubit":{
"0-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
},
"1-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
},
"3-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
},
"4-2": {
"gate_fidelity": [0.0, 0.0],
"cz_fidelity": [0.0, 0.0]
}
},
"coupler": {
"0": {
"sweetspot": 0.0
Expand Down
2 changes: 1 addition & 1 deletion tests/test_dummy.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def test_dummy_execute_coupler_pulse():
def test_dummy_execute_pulse_sequence_couplers():
platform = create_platform("dummy_couplers")
qubit_ordered_pair = QubitPair(
platform.qubits[1], platform.qubits[2], platform.couplers[1]
platform.qubits[1], platform.qubits[2], coupler=platform.couplers[1]
)
sequence = PulseSequence()

Expand Down
Loading