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

Labeled gate pulse gate #7130

Closed
Closed
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
13 changes: 9 additions & 4 deletions qiskit/pulse/instruction_schedule_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,9 +434,14 @@ def _get_instruction_string(inst: Union[str, Instruction]):
if isinstance(inst, str):
return inst
else:
try:
return inst.name
except AttributeError as ex:
if not hasattr(inst, "name"):
raise PulseError(
'Input "inst" has no attribute "name". This should be a circuit "Instruction".'
) from ex
)
base_name = inst.name

label = getattr(inst, "label", None)
if label:
return f"{base_name}_{label}"

return base_name
2 changes: 2 additions & 0 deletions qiskit/transpiler/passes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
PulseGates
RZXCalibrationBuilder
RZXCalibrationBuilderNoEcho
LabelIdentifier

Scheduling
=============
Expand Down Expand Up @@ -203,6 +204,7 @@
from .calibration import PulseGates
from .calibration import RZXCalibrationBuilder
from .calibration import RZXCalibrationBuilderNoEcho
from .calibration import LabelIdentifier

# circuit scheduling
from .scheduling import TimeUnitConversion
Expand Down
1 change: 1 addition & 0 deletions qiskit/transpiler/passes/calibration/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
"""Module containing transpiler calibration passes."""

from .builders import RZXCalibrationBuilder, RZXCalibrationBuilderNoEcho, PulseGates
from .label_identifier import LabelIdentifier
57 changes: 57 additions & 0 deletions qiskit/transpiler/passes/calibration/label_identifier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2021.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""Instruction replacement for labeled gate."""

from qiskit.dagcircuit import DAGCircuit
from qiskit.pulse import InstructionScheduleMap
from qiskit.transpiler.basepasses import TransformationPass


class LabelIdentifier(TransformationPass):
"""Replace instruction with Gate with unique name if label is defined.

Note:
Once this pass is called, the labeled gate will be no longer recognized by the
circuit equivalence library. Thus further optimization on the
instruction will be just ignored.
"""

def __init__(
self,
inst_map: InstructionScheduleMap,
):
"""Create new pass.

Args:
inst_map: Instruction schedule map that user may override.
"""
super().__init__()
self.inst_map = inst_map

def run(self, dag: DAGCircuit) -> DAGCircuit:
"""Run label identifier pass on dag.

Args:
dag: DAG to identify instruction label.

Returns:
DAG circuit with replaced instruction.
"""
for node in dag.topological_op_nodes():
label = getattr(node.op, "label", None)
if label:
qubits = list(dag.qubits.index(q) for q in node.qargs)
if self.inst_map.has(instruction=node.op, qubits=qubits):
node.name = f"{node.name}_{label}"

return dag
2 changes: 2 additions & 0 deletions qiskit/transpiler/preset_passmanagers/level0.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
from qiskit.transpiler.passes import ValidatePulseGates
from qiskit.transpiler.passes import PulseGates
from qiskit.transpiler.passes import Error
from qiskit.transpiler.passes import LabelIdentifier

from qiskit.transpiler import TranspilerError

Expand Down Expand Up @@ -234,6 +235,7 @@ def _direction_condition(property_set):
pm0.append(_direction, condition=_direction_condition)
pm0.append(_unroll)
if inst_map and inst_map.has_custom_gate():
pm0.append(LabelIdentifier(inst_map=inst_map))
pm0.append(PulseGates(inst_map=inst_map))
pm0.append(_scheduling)
pm0.append(_alignments)
Expand Down
2 changes: 2 additions & 0 deletions qiskit/transpiler/preset_passmanagers/level1.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
from qiskit.transpiler.passes import ValidatePulseGates
from qiskit.transpiler.passes import PulseGates
from qiskit.transpiler.passes import Error
from qiskit.transpiler.passes import LabelIdentifier

from qiskit.transpiler import TranspilerError

Expand Down Expand Up @@ -271,6 +272,7 @@ def _opt_control(property_set):
pm1.append(_reset)
pm1.append(_depth_check + _opt + _unroll, do_while=_opt_control)
if inst_map and inst_map.has_custom_gate():
pm1.append(LabelIdentifier(inst_map=inst_map))
pm1.append(PulseGates(inst_map=inst_map))
pm1.append(_scheduling)
pm1.append(_alignments)
Expand Down
2 changes: 2 additions & 0 deletions qiskit/transpiler/preset_passmanagers/level2.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
from qiskit.transpiler.passes import ValidatePulseGates
from qiskit.transpiler.passes import PulseGates
from qiskit.transpiler.passes import Error
from qiskit.transpiler.passes import LabelIdentifier

from qiskit.transpiler import TranspilerError

Expand Down Expand Up @@ -309,6 +310,7 @@ def _opt_control(property_set):
pm2.append(_reset)
pm2.append(_depth_check + _opt + _unroll, do_while=_opt_control)
if inst_map and inst_map.has_custom_gate():
pm2.append(LabelIdentifier(inst_map=inst_map))
pm2.append(PulseGates(inst_map=inst_map))
pm2.append(_scheduling)
pm2.append(_alignments)
Expand Down
2 changes: 2 additions & 0 deletions qiskit/transpiler/preset_passmanagers/level3.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
from qiskit.transpiler.passes import ValidatePulseGates
from qiskit.transpiler.passes import PulseGates
from qiskit.transpiler.passes import Error
from qiskit.transpiler.passes import LabelIdentifier

from qiskit.transpiler import TranspilerError

Expand Down Expand Up @@ -320,6 +321,7 @@ def _opt_control(property_set):
pm3.append(_reset)
pm3.append(_depth_check + _opt + _unroll, do_while=_opt_control)
if inst_map and inst_map.has_custom_gate():
pm3.append(LabelIdentifier(inst_map=inst_map))
pm3.append(PulseGates(inst_map=inst_map))
pm3.append(_scheduling)
pm3.append(_alignments)
Expand Down