Skip to content

Commit

Permalink
drop all support for qiskit pulse sequences :( (#1070)
Browse files Browse the repository at this point in the history
  • Loading branch information
richrines1 authored Sep 19, 2024
1 parent b409e34 commit 8733f4c
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 140 deletions.
52 changes: 4 additions & 48 deletions cirq-superstaq/cirq_superstaq/compiler_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ def __init__(
| list[list[dict[cirq.Qid, cirq.Qid]]]
),
pulse_gate_circuits: Any | None = None,
pulse_sequences: Any | None = None,
seq: qtrl.sequencer.Sequence | None = None,
jaqal_programs: list[str] | str | None = None,
) -> None:
Expand All @@ -110,7 +109,6 @@ def __init__(
qubits.
pulse_gate_circuits: Pulse-gate `qiskit.QuantumCircuit` or list thereof specifying the
pulse compilation.
pulse_sequences: The qiskit pulse schedules for the compiled circuit(s).
seq: A `qtrl` pulse sequence, if `qtrl` is available locally.
jaqal_programs: The Jaqal program (resp. programs) as a string (resp. list of
strings).
Expand All @@ -120,14 +118,12 @@ def __init__(
self.initial_logical_to_physical = initial_logical_to_physicals
self.final_logical_to_physical = final_logical_to_physicals
self.pulse_gate_circuit = pulse_gate_circuits
self.pulse_sequence = pulse_sequences
self.jaqal_program = jaqal_programs
else:
self.circuits = circuits
self.initial_logical_to_physicals = initial_logical_to_physicals
self.final_logical_to_physicals = final_logical_to_physicals
self.pulse_gate_circuits = pulse_gate_circuits
self.pulse_sequences = pulse_sequences
self.jaqal_programs = jaqal_programs

self.seq = seq
Expand All @@ -147,12 +143,12 @@ def __repr__(self) -> str:
return (
f"CompilerOutput({self.circuit!r}, {self.initial_logical_to_physical!r}, "
f"{self.final_logical_to_physical!r}, {self.pulse_gate_circuit!r}, "
f"{self.pulse_sequence!r}, {self.seq!r}, {self.jaqal_program!r})"
f"{self.seq!r}, {self.jaqal_program!r})"
)
return (
f"CompilerOutput({self.circuits!r}, {self.initial_logical_to_physicals!r}, "
f"{self.final_logical_to_physicals!r}, {self.pulse_gate_circuits!r}, "
f"{self.pulse_sequences!r}, {self.seq!r}, {self.jaqal_programs!r})"
f"{self.seq!r}, {self.jaqal_programs!r})"
)


Expand All @@ -167,8 +163,7 @@ def read_json(json_dict: dict[str, Any], circuits_is_list: bool) -> CompilerOutp
Returns:
A `CompilerOutput` object with the compiled circuit(s). If included in the server response,
the returned object also stores the corresponding pulse gate circuit(s) in its
.pulse_gate_circuit(s) attribute, and pulse sequence(s) in its .pulse_sequences(s) attribute
(provided qiskit-superstaq is available locally).
.pulse_gate_circuit(s) attribute (provided qiskit-superstaq is available locally).
"""

compiled_circuits = css.serialization.deserialize_circuits(json_dict["cirq_circuits"])
Expand All @@ -178,7 +173,7 @@ def read_json(json_dict: dict[str, Any], circuits_is_list: bool) -> CompilerOutp
final_logical_to_physicals: list[dict[cirq.Qid, cirq.Qid]] = list(
map(dict, cirq.read_json(json_text=json_dict["final_logical_to_physicals"]))
)
pulse_gate_circuits = pulses = None
pulse_gate_circuits = None

if "pulse_gate_circuits" in json_dict:
pulse_gate_circuits = css.serialization.deserialize_qiskit_circuits(
Expand All @@ -188,57 +183,18 @@ def read_json(json_dict: dict[str, Any], circuits_is_list: bool) -> CompilerOutp
pulse_start_times=json_dict.get("pulse_start_times"),
)

if "pulses" in json_dict:
if importlib.util.find_spec("qiskit") and importlib.util.find_spec("qiskit.qpy"):
import qiskit

try:
pulses = gss.serialization.deserialize(json_dict["pulses"])
except Exception as e:
s = "s" if circuits_is_list else ""
qiskit_version = qiskit.__version__
if qiskit_version < "1.0":
warnings.warn(
f"Your compiled pulse sequence{s} could not be deserialized, likely "
f"because your Qiskit installation (version {qiskit_version}) is "
"out of date. Please try again after installing a more recent version.\n\n"
f"You can still access your compiled circuit{s} using the .circuit{s} "
"attribute of this output."
)
else:
warnings.warn(
f"Your compiled pulse sequence{s} could not be deserialized. Please let "
"us know at superstaq@infleqtion.com, or file a report at "
"https://github.com/Infleqtion/client-superstaq/issues containing "
"the following information (as well as any other relevant context):\n\n"
f"cirq-superstaq version: {css.__version__}\n"
f"qiskit version: {qiskit_version}\n"
f"error: {e!r}\n\n"
f"You can still access your compiled circuit{s} using the .circuit{s} "
"attribute of this output."
)
else:
s = "s" if circuits_is_list else ""
warnings.warn(
f"Qiskit is required to deserialize compiled pulse sequence{s}. You can "
f"still access your compiled circuit{s} using the .circuit{s} attribute of this "
"output."
)

if circuits_is_list:
return CompilerOutput(
compiled_circuits,
initial_logical_to_physicals,
final_logical_to_physicals,
pulse_gate_circuits=pulse_gate_circuits,
pulse_sequences=pulses,
)
return CompilerOutput(
compiled_circuits[0],
initial_logical_to_physicals[0],
final_logical_to_physicals[0],
pulse_gate_circuits=None if pulse_gate_circuits is None else pulse_gate_circuits[0],
pulse_sequences=None if pulses is None else pulses[0],
)


Expand Down
52 changes: 9 additions & 43 deletions cirq-superstaq/cirq_superstaq/compiler_output_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import cirq
import general_superstaq as gss
import pytest
import qiskit
import qiskit_superstaq as qss

import cirq_superstaq as css

Expand Down Expand Up @@ -82,13 +84,13 @@ def test_compiler_output_repr() -> None:
qubit_map: dict[cirq.Qid, cirq.Qid] = {}
assert (
repr(css.compiler_output.CompilerOutput(circuit, qubit_map, qubit_map))
== f"CompilerOutput({circuit!r}, {{}}, {{}}, None, None, None, None)"
== f"CompilerOutput({circuit!r}, {{}}, {{}}, None, None, None)"
)

circuits = [circuit, circuit]
assert (
repr(css.compiler_output.CompilerOutput(circuits, [qubit_map], [qubit_map]))
== f"CompilerOutput({circuits!r}, [{{}}], [{{}}], None, None, None, None)"
== f"CompilerOutput({circuits!r}, [{{}}], [{{}}], None, None, None)"
)


Expand Down Expand Up @@ -129,28 +131,28 @@ def test_read_json_ibmq() -> None:

json_dict = {
"cirq_circuits": css.serialization.serialize_circuits(circuit),
"pulses": gss.serialization.serialize([mock.DEFAULT]),
"pulse_gate_circuits": qss.serialization.serialize_circuits([qiskit.QuantumCircuit()]),
"initial_logical_to_physicals": cirq.to_json([list(initial_logical_to_physical.items())]),
"final_logical_to_physicals": cirq.to_json([list(final_logical_to_physical.items())]),
}

out = css.compiler_output.read_json(json_dict, circuits_is_list=False)
assert out.circuit == circuit
assert out.pulse_sequence == mock.DEFAULT
assert out.pulse_gate_circuit == qiskit.QuantumCircuit()
assert out.initial_logical_to_physical == initial_logical_to_physical
assert out.final_logical_to_physical == final_logical_to_physical
assert not hasattr(out, "circuits")
assert not hasattr(out, "pulse_sequences")
assert not hasattr(out, "pulse_gate_circuits")
assert not hasattr(out, "initial_logical_to_physicals")
assert not hasattr(out, "final_logical_to_physicals")

out = css.compiler_output.read_json(json_dict, circuits_is_list=True)
assert out.circuits == [circuit]
assert out.pulse_sequences == [mock.DEFAULT]
assert out.pulse_gate_circuits == [qiskit.QuantumCircuit()]
assert out.final_logical_to_physicals == [final_logical_to_physical]
assert out.initial_logical_to_physicals == [initial_logical_to_physical]
assert not hasattr(out, "circuit")
assert not hasattr(out, "pulse_sequence")
assert not hasattr(out, "pulse_gate_circuit")
assert not hasattr(out, "initial_logical_to_physical")
assert not hasattr(out, "final_logical_to_physical")

Expand Down Expand Up @@ -216,42 +218,6 @@ def test_read_json_pulse_gate_circuits() -> None:
assert out.pulse_gate_circuits is None


def test_read_json_ibmq_warnings() -> None:
q0 = cirq.LineQubit(0)
circuit = cirq.Circuit(cirq.H(q0), cirq.measure(q0))
initial_logical_to_physical = {cirq.q(0): cirq.q(1)}
final_logical_to_physical = {cirq.q(0): cirq.q(13)}

json_dict = {
"cirq_circuits": css.serialization.serialize_circuits(circuit),
"pulses": "not deserializable",
"initial_logical_to_physicals": cirq.to_json([list(initial_logical_to_physical.items())]),
"final_logical_to_physicals": cirq.to_json([list(final_logical_to_physical.items())]),
}

with mock.patch.dict("sys.modules", {"qiskit": None}), pytest.warns(
UserWarning, match="Qiskit is required"
):
out = css.compiler_output.read_json(json_dict, circuits_is_list=False)
assert out.circuit == circuit
assert out.pulse_sequence is None

with mock.patch("qiskit.__version__", "0.17.2"), pytest.warns(
UserWarning, match="(version 0.17.2)"
):
out = css.compiler_output.read_json(json_dict, circuits_is_list=True)
assert out.circuits == [circuit]
assert out.pulse_sequences is None

with mock.patch("qiskit.__version__", "2.0.0"), pytest.warns(
UserWarning,
match="Your compiled pulse sequences could not be deserialized. Please let us know",
):
out = css.compiler_output.read_json(json_dict, circuits_is_list=True)
assert out.circuits == [circuit]
assert out.pulse_sequences is None


@mock.patch.dict("sys.modules", {"qtrl": None})
def test_read_json_aqt() -> None:
importlib.reload(css.compiler_output)
Expand Down
20 changes: 15 additions & 5 deletions cirq-superstaq/cirq_superstaq/daily_integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import general_superstaq as gss
import numpy as np
import pytest
import qiskit
from general_superstaq import ResourceEstimate

import cirq_superstaq as css
Expand All @@ -34,11 +35,19 @@ def test_ibmq_compile(service: css.Service) -> None:

out = service.ibmq_compile(circuit, target="ibmq_brisbane_qpu")
assert isinstance(out.circuit, cirq.Circuit)
assert out.pulse_sequence is not None
assert isinstance(out.pulse_gate_circuit, qiskit.QuantumCircuit)
assert len(out.pulse_gate_circuit.op_start_times) == len(out.pulse_gate_circuit)

out = service.ibmq_compile(circuit, target="ibmq_brisbane_qpu")
assert isinstance(out.circuit, cirq.Circuit)
assert out.pulse_sequence is not None
out = service.ibmq_compile([circuit, circuit], target="ibmq_brisbane_qpu")

assert isinstance(out.circuits, list)
assert len(out.circuits) == 2
assert isinstance(out.circuits[1], cirq.Circuit)

assert isinstance(out.pulse_gate_circuits, list)
assert len(out.pulse_gate_circuits) == 2
assert isinstance(out.pulse_gate_circuits[1], qiskit.QuantumCircuit)
assert len(out.pulse_gate_circuits[1].op_start_times) == len(out.pulse_gate_circuits[1])


def test_ibmq_compile_with_token() -> None:
Expand All @@ -53,7 +62,8 @@ def test_ibmq_compile_with_token() -> None:
out = service.ibmq_compile(circuit, target="ibmq_brisbane_qpu")

assert isinstance(out.circuit, cirq.Circuit)
assert out.pulse_sequence is not None
assert isinstance(out.pulse_gate_circuit, qiskit.QuantumCircuit)
assert len(out.pulse_gate_circuit.op_start_times) == len(out.pulse_gate_circuit)


def test_aqt_compile(service: css.Service) -> None:
Expand Down
24 changes: 17 additions & 7 deletions cirq-superstaq/cirq_superstaq/service_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import numpy as np
import pandas as pd
import pytest
import qiskit
import qiskit_superstaq as qss
import sympy
from general_superstaq import ResourceEstimate

Expand Down Expand Up @@ -657,7 +659,7 @@ def test_service_ibmq_compile(mock_post: mock.MagicMock) -> None:

mock_post.return_value.json = lambda: {
"cirq_circuits": css.serialization.serialize_circuits(circuit),
"pulses": gss.serialization.serialize([mock.DEFAULT]),
"pulse_gate_circuits": qss.serialization.serialize_circuits([qiskit.QuantumCircuit()]),
"initial_logical_to_physicals": cirq.to_json([list(initial_logical_to_physical.items())]),
"final_logical_to_physicals": cirq.to_json([list(final_logical_to_physical.items())]),
}
Expand All @@ -680,8 +682,13 @@ def test_service_ibmq_compile(mock_post: mock.MagicMock) -> None:
"dd_strategy": "adaptive",
"dynamical_decoupling": True,
}
assert service.ibmq_compile(circuit, target="ibmq_fake_qpu").pulse_sequence == mock.DEFAULT
assert service.ibmq_compile([circuit], target="ibmq_fake_qpu").pulse_sequences == [mock.DEFAULT]
assert (
service.ibmq_compile(circuit, target="ibmq_fake_qpu").pulse_gate_circuit
== qiskit.QuantumCircuit()
)
assert service.ibmq_compile([circuit], target="ibmq_fake_qpu").pulse_gate_circuits == [
qiskit.QuantumCircuit()
]
assert (
service.ibmq_compile(circuit, target="ibmq_fake_qpu").initial_logical_to_physical
== initial_logical_to_physical
Expand All @@ -697,12 +704,15 @@ def test_service_ibmq_compile(mock_post: mock.MagicMock) -> None:
final_logical_to_physical
]

with mock.patch.dict("sys.modules", {"qiskit": None}), pytest.warns(
UserWarning, match="Qiskit is required"
with mock.patch.dict("sys.modules", {"qiskit_superstaq": None}), pytest.warns(
UserWarning, match="qiskit-superstaq is required"
):
assert service.ibmq_compile(cirq.Circuit(), target="ibmq_fake_qpu").pulse_sequence is None
assert (
service.ibmq_compile([cirq.Circuit()], target="ibmq_fake_qpu").pulse_sequences is None
service.ibmq_compile(cirq.Circuit(), target="ibmq_fake_qpu").pulse_gate_circuit is None
)
assert (
service.ibmq_compile([cirq.Circuit()], target="ibmq_fake_qpu").pulse_gate_circuits
is None
)

with pytest.raises(ValueError, match="'ss_example_qpu' is not a valid IBMQ target."):
Expand Down
15 changes: 1 addition & 14 deletions qiskit-superstaq/qiskit_superstaq/compiler_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ def __init__(
dict[int, int] | list[dict[int, int]] | list[list[dict[int, int]]]
),
pulse_gate_circuits: qiskit.QuantumCircuit | list[qiskit.QuantumCircuit] = None,
pulse_sequences: qiskit.pulse.Schedule | list[qiskit.pulse.Schedule] | None = None,
seq: qtrl.sequencer.Sequence | None = None,
jaqal_programs: str | list[str] | None = None,
) -> None:
Expand All @@ -120,8 +119,6 @@ def __init__(
from logical to physical qubits.
pulse_gate_circuits: Pulse-gate `qiskit.QuantumCircuit` or list thereof specifying the
pulse compilation.
pulse_sequences: `qiskit.pulse.Schedule` or list thereof specifying the pulse
compilation.
seq: `qtrl.sequencer.Sequence` pulse sequence if `qtrl` is available locally.
jaqal_programs: Optional string or list of strings specifying Jaqal programs (for
QSCOUT).
Expand All @@ -131,14 +128,12 @@ def __init__(
self.initial_logical_to_physical = initial_logical_to_physicals
self.final_logical_to_physical = final_logical_to_physicals
self.pulse_gate_circuit = pulse_gate_circuits
self.pulse_sequence = pulse_sequences
self.jaqal_program = jaqal_programs
else:
self.circuits = circuits
self.initial_logical_to_physicals = initial_logical_to_physicals
self.final_logical_to_physicals = final_logical_to_physicals
self.pulse_gate_circuits = pulse_gate_circuits
self.pulse_sequences = pulse_sequences
self.jaqal_programs = jaqal_programs

self.seq = seq
Expand Down Expand Up @@ -213,7 +208,7 @@ def read_json(json_dict: Mapping[str, Any], circuits_is_list: bool) -> CompilerO
map(dict, json.loads(json_dict["final_logical_to_physicals"]))
)

pulse_gate_circuits = pulse_sequences = None
pulse_gate_circuits = None

if "pulse_gate_circuits" in json_dict:
pulse_gate_circuits = qss.deserialize_circuits(json_dict["pulse_gate_circuits"])
Expand All @@ -227,26 +222,18 @@ def read_json(json_dict: Mapping[str, Any], circuits_is_list: bool) -> CompilerO
)
]

if "pulses" in json_dict:
try:
pulse_sequences = gss.serialization.deserialize(json_dict["pulses"])
except Exception:
pulse_sequences = None

if circuits_is_list:
return CompilerOutput(
compiled_circuits,
initial_logical_to_physicals,
final_logical_to_physicals,
pulse_gate_circuits=pulse_gate_circuits,
pulse_sequences=pulse_sequences,
)
return CompilerOutput(
compiled_circuits[0],
initial_logical_to_physicals[0],
final_logical_to_physicals[0],
pulse_gate_circuits=None if pulse_gate_circuits is None else pulse_gate_circuits[0],
pulse_sequences=None if pulse_sequences is None else pulse_sequences[0],
)


Expand Down
Loading

0 comments on commit 8733f4c

Please sign in to comment.