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

drop all support for qiskit pulse sequences :( #1070

Merged
merged 1 commit into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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