Skip to content

Commit

Permalink
Deprecate Qobj and assemble (#12649)
Browse files Browse the repository at this point in the history
* deprecate qobj and assemble

* reno

* shallow deprecation of assemble

* test.python.compiler.test_disassembler

* fakebackend pulse

* test.python.circuit.test_parameters

* PulseQobjInstruction  is used by GenericBackendV2

* test.python.scheduler.test_basic_scheduler

* test.python.result.test_result

* test.python.pulse.test_calibration_entries

* test.python.compiler.test_assembler

* test.python.transpiler.test_star_prerouting

* test.python.pulse.test_instruction_schedule_map

* test.python.providers.basic_provider.test_basic_simulator

* test.python.primitives.test_backend_sampler_v2

* test.python.compiler.test_disassembler

* test.python.compiler.test_compiler

* test.python.circuit.test_scheduled_circuit

* test.python.providers.test_fake_backends

* test.python.circuit.test_unitary

* test.python.transpiler.test_sabre_swap

* test.python.providers.fake_provider.test_fake_backends

* Aer using Provider ABC

* aer warnings

* reno

* another pass on reno

* test.python.pulse

* test.python.compiler.test_compiler

* add module to fiterwarning

* test.python.compiler.test_transpiler

* fixing obscure expcetion handleing for comparison

* Apply suggestions from code review

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>

* remove catch

* new deprecate warning message

* lint qiskit/assembler/assemble_circuits.py

* concurrency warnings

* ignore aer warnings

* Update test/python/providers/fake_provider/test_fake_backends.py

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>

* Update test/python/circuit/test_parameters.py

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>

* Update qiskit/providers/models/pulsedefaults.py

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>

* Update test/python/providers/fake_provider/test_fake_backends.py

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>

* Update test/python/providers/fake_provider/test_generic_backend_v2.py

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>

* lint

* #12649 (comment)

* #12649 (comment)

* Update test/python/transpiler/test_sabre_swap.py

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>

* Update qiskit/providers/models/pulsedefaults.py

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>

* ignore Treating CircuitInstruction...

* another unnecessary catch from aer

* another unnecessary catch from aer, again

* removing more unnecesary catches

---------

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
  • Loading branch information
1ucian0 and ElePT committed Jul 25, 2024
1 parent aaaf107 commit 6ce5250
Show file tree
Hide file tree
Showing 40 changed files with 2,128 additions and 1,481 deletions.
171 changes: 107 additions & 64 deletions qiskit/assembler/assemble_circuits.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

"""Assemble function for converting a list of circuits into a qobj."""
import copy
import warnings
from collections import defaultdict
from typing import Dict, List, Optional, Tuple

Expand All @@ -35,6 +36,7 @@
QobjHeader,
)
from qiskit.utils.parallel import parallel_map
from qiskit.utils import deprecate_func


PulseLibrary = Dict[str, List[complex]]
Expand Down Expand Up @@ -87,20 +89,26 @@ def _assemble_circuit(
metadata = circuit.metadata
if metadata is None:
metadata = {}
header = QobjExperimentHeader(
qubit_labels=qubit_labels,
n_qubits=num_qubits,
qreg_sizes=qreg_sizes,
clbit_labels=clbit_labels,
memory_slots=memory_slots,
creg_sizes=creg_sizes,
name=circuit.name,
global_phase=float(circuit.global_phase),
metadata=metadata,
)
with warnings.catch_warnings():
# The class QobjExperimentHeader is deprecated
warnings.filterwarnings("ignore", category=DeprecationWarning, module="qiskit")
header = QobjExperimentHeader(
qubit_labels=qubit_labels,
n_qubits=num_qubits,
qreg_sizes=qreg_sizes,
clbit_labels=clbit_labels,
memory_slots=memory_slots,
creg_sizes=creg_sizes,
name=circuit.name,
global_phase=float(circuit.global_phase),
metadata=metadata,
)

# TODO: why do we need n_qubits and memory_slots in both the header and the config
config = QasmQobjExperimentConfig(n_qubits=num_qubits, memory_slots=memory_slots)
with warnings.catch_warnings():
# The class QasmQobjExperimentConfig is deprecated
warnings.filterwarnings("ignore", category=DeprecationWarning, module="qiskit")
config = QasmQobjExperimentConfig(n_qubits=num_qubits, memory_slots=memory_slots)
calibrations, pulse_library = _assemble_pulse_gates(circuit, run_config)
if calibrations:
config.calibrations = calibrations
Expand All @@ -118,7 +126,7 @@ def _assemble_circuit(

instructions = []
for op_context in circuit.data:
instruction = op_context.operation.assemble()
instruction = op_context.operation._assemble()

# Add register attributes to the instruction
qargs = op_context.qubits
Expand Down Expand Up @@ -151,13 +159,16 @@ def _assemble_circuit(
]

conditional_reg_idx = memory_slots + max_conditional_idx
conversion_bfunc = QasmQobjInstruction(
name="bfunc",
mask="0x%X" % mask, # pylint: disable=consider-using-f-string
relation="==",
val="0x%X" % val, # pylint: disable=consider-using-f-string
register=conditional_reg_idx,
)
with warnings.catch_warnings():
# The class QasmQobjInstruction is deprecated
warnings.filterwarnings("ignore", category=DeprecationWarning, module="qiskit")
conversion_bfunc = QasmQobjInstruction(
name="bfunc",
mask="0x%X" % mask, # pylint: disable=consider-using-f-string
relation="==",
val="0x%X" % val, # pylint: disable=consider-using-f-string
register=conditional_reg_idx,
)
instructions.append(conversion_bfunc)
instruction.conditional = conditional_reg_idx
max_conditional_idx += 1
Expand All @@ -166,10 +177,13 @@ def _assemble_circuit(
del instruction._condition

instructions.append(instruction)
return (
QasmQobjExperiment(instructions=instructions, header=header, config=config),
pulse_library,
)
with warnings.catch_warnings():
# The class QasmQobjExperiment is deprecated
warnings.filterwarnings("ignore", category=DeprecationWarning, module="qiskit")
return (
QasmQobjExperiment(instructions=instructions, header=header, config=config),
pulse_library,
)


def _assemble_pulse_gates(
Expand Down Expand Up @@ -299,42 +313,14 @@ def _configure_experiment_los(
return experiments


def assemble_circuits(
def _assemble_circuits(
circuits: List[QuantumCircuit], run_config: RunConfig, qobj_id: int, qobj_header: QobjHeader
) -> QasmQobj:
"""Assembles a list of circuits into a qobj that can be run on the backend.
Args:
circuits: circuit(s) to assemble
run_config: configuration of the runtime environment
qobj_id: identifier for the generated qobj
qobj_header: header to pass to the results
Returns:
The qobj to be run on the backends
Examples:
.. code-block:: python
from qiskit.circuit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit.assembler import assemble_circuits
from qiskit.assembler.run_config import RunConfig
# Build a circuit to convert into a Qobj
q = QuantumRegister(2)
c = ClassicalRegister(2)
qc = QuantumCircuit(q, c)
qc.h(q[0])
qc.cx(q[0], q[1])
qc.measure(q, c)
# Assemble a Qobj from the input circuit
qobj = assemble_circuits(circuits=[qc],
qobj_id="custom-id",
qobj_header=[],
run_config=RunConfig(shots=2000, memory=True, init_qubits=True))
"""
# assemble the circuit experiments
experiments_and_pulse_libs = parallel_map(_assemble_circuit, circuits, [run_config])
with warnings.catch_warnings():
# Still constructs Qobj, that is deprecated. The message is hard to trace to a module,
# because concurrency is hard.
warnings.filterwarnings("ignore", category=DeprecationWarning)
experiments_and_pulse_libs = parallel_map(_assemble_circuit, circuits, [run_config])
experiments = []
pulse_library = {}
for exp, lib in experiments_and_pulse_libs:
Expand All @@ -346,10 +332,16 @@ def assemble_circuits(
experiments, calibrations = _extract_common_calibrations(experiments)

# configure LO freqs per circuit
lo_converter = converters.LoConfigConverter(QasmQobjExperimentConfig, **run_config.to_dict())
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=DeprecationWarning, module="qiskit")
lo_converter = converters.LoConfigConverter(
QasmQobjExperimentConfig, **run_config.to_dict()
)
experiments = _configure_experiment_los(experiments, lo_converter, run_config)

qobj_config = QasmQobjConfig()
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=DeprecationWarning, module="qiskit")
qobj_config = QasmQobjConfig()
if run_config:
qobj_config_dict = run_config.to_dict()

Expand Down Expand Up @@ -379,7 +371,10 @@ def assemble_circuits(
if m_los:
qobj_config_dict["meas_lo_freq"] = [freq / 1e9 for freq in m_los]

qobj_config = QasmQobjConfig(**qobj_config_dict)
with warnings.catch_warnings():
# The class QasmQobjConfig is deprecated
warnings.filterwarnings("ignore", category=DeprecationWarning, module="qiskit")
qobj_config = QasmQobjConfig(**qobj_config_dict)

qubit_sizes = []
memory_slot_sizes = []
Expand All @@ -402,7 +397,55 @@ def assemble_circuits(

if calibrations and calibrations.gates:
qobj_config.calibrations = calibrations
with warnings.catch_warnings():
# The class QasmQobj is deprecated
warnings.filterwarnings("ignore", category=DeprecationWarning, module="qiskit")
return QasmQobj(
qobj_id=qobj_id, config=qobj_config, experiments=experiments, header=qobj_header
)

return QasmQobj(
qobj_id=qobj_id, config=qobj_config, experiments=experiments, header=qobj_header
)

@deprecate_func(
since="1.2",
removal_timeline="in the 2.0 release",
additional_msg="The `Qobj` class and related functionality are part of the deprecated `BackendV1` "
"workflow, and no longer necessary for `BackendV2`. If a user workflow requires "
"`Qobj` it likely relies on deprecated functionality and should be updated to "
"use `BackendV2`.",
)
def assemble_circuits(
circuits: List[QuantumCircuit], run_config: RunConfig, qobj_id: int, qobj_header: QobjHeader
) -> QasmQobj:
"""Assembles a list of circuits into a qobj that can be run on the backend.
Args:
circuits: circuit(s) to assemble
run_config: configuration of the runtime environment
qobj_id: identifier for the generated qobj
qobj_header: header to pass to the results
Returns:
The qobj to be run on the backends
Examples:
.. code-block:: python
from qiskit.circuit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit.assembler import assemble_circuits
from qiskit.assembler.run_config import RunConfig
# Build a circuit to convert into a Qobj
q = QuantumRegister(2)
c = ClassicalRegister(2)
qc = QuantumCircuit(q, c)
qc.h(q[0])
qc.cx(q[0], q[1])
qc.measure(q, c)
# Assemble a Qobj from the input circuit
qobj = assemble_circuits(circuits=[qc],
qobj_id="custom-id",
qobj_header=[],
run_config=RunConfig(shots=2000, memory=True, init_qubits=True))
"""
# assemble the circuit experiments
return _assemble_circuits(circuits, run_config, qobj_id, qobj_header)
9 changes: 9 additions & 0 deletions qiskit/assembler/disassemble.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

from qiskit.qobj import PulseQobjInstruction
from qiskit.qobj.converters import QobjToInstructionConverter
from qiskit.utils import deprecate_func

# A ``CircuitModule`` is a representation of a circuit execution on the backend.
# It is currently a list of quantum circuits to execute, a run Qobj dictionary
Expand All @@ -37,6 +38,14 @@
PulseModule = NewType("PulseModule", Tuple[List[pulse.Schedule], Dict[str, Any], Dict[str, Any]])


@deprecate_func(
since="1.2",
removal_timeline="in the 2.0 release",
additional_msg="The `Qobj` class and related functionality are part of the deprecated "
"`BackendV1` workflow, and no longer necessary for `BackendV2`. If a user "
"workflow requires `Qobj` it likely relies on deprecated functionality and "
"should be updated to use `BackendV2`.",
)
def disassemble(qobj) -> Union[CircuitModule, PulseModule]:
"""Disassemble a qobj and return the circuits or pulse schedules, run_config, and user header.
Expand Down
19 changes: 17 additions & 2 deletions qiskit/circuit/instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from __future__ import annotations

import copy
import warnings
from itertools import zip_longest
import math
from typing import List, Type
Expand All @@ -47,7 +48,7 @@
from qiskit.circuit.operation import Operation

from qiskit.circuit.annotated_operation import AnnotatedOperation, InverseModifier

from qiskit.utils import deprecate_func

_CUTOFF_PRECISION = 1e-10

Expand Down Expand Up @@ -359,9 +360,23 @@ def unit(self, unit):
"""Set the time unit of duration."""
self._unit = unit

@deprecate_func(
since="1.2",
removal_timeline="in the 2.0 release",
additional_msg="The `Qobj` class and related functionality are part of the deprecated "
"`BackendV1` workflow, and no longer necessary for `BackendV2`. If a user "
"workflow requires `Qobj` it likely relies on deprecated functionality and "
"should be updated to use `BackendV2`.",
)
def assemble(self):
"""Assemble a QasmQobjInstruction"""
instruction = QasmQobjInstruction(name=self.name)
return self._assemble()

def _assemble(self):
with warnings.catch_warnings():
# The class QasmQobjInstruction is deprecated
warnings.filterwarnings("ignore", category=DeprecationWarning, module="qiskit")
instruction = QasmQobjInstruction(name=self.name)
# Evaluate parameters
if self.params:
params = [x.evalf(x) if hasattr(x, "evalf") else x for x in self.params]
Expand Down
Loading

0 comments on commit 6ce5250

Please sign in to comment.