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

[WIP] Solve a bug of scheduling with backendV2 #9912

Closed
wants to merge 13 commits into from

Conversation

to24toro
Copy link
Contributor

@to24toro to24toro commented Apr 5, 2023

Summary

Based on the comment,
I added a new class MeasureGrouping. It is assumed to be called by target.meas_map.
Using this class, we can become to create scheduling for quantum circuits dynamically.

This PR includes

  • adding a new class MeasureGrouping.
  • dispatching macros.measure.

Details and comments

fix #9488
Solving this issue leads to working on #9420.

[TODO]

  • implement get_qubit_groups in MeasureGrouping.
  • implement generate_schedule which yield something corresponding to inst_schedule_map.
  • call MeasureGrouping when create Target class in backendV2.
  • add add_measuregrouping to qiskit_ibm_provider/backend_converter.py

@qiskit-bot
Copy link
Collaborator

Thank you for opening a new pull request.

Before your PR can be merged it will first need to pass continuous integration tests and be reviewed. Sometimes the review process can be slow, so please be patient.

While you're waiting, please feel free to review other open PRs. While only a subset of people are authorized to approve pull requests for merging, everyone is encouraged to review open pull requests. Doing reviews helps reduce the burden on the core team and helps make the project's code better for everyone.

One or more of the the following people are requested to review this:

@nkanazawa1989 nkanazawa1989 self-assigned this Apr 5, 2023
@nkanazawa1989 nkanazawa1989 added the mod: pulse Related to the Pulse module label Apr 5, 2023
Comment on lines 60 to 62
if backend is None or hasattr(backend, "target"):
if target is None:
target = backend.target
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think the logic here is problematic.
If you provide as arguments inst_map and meas_map, the macro has all the information it needs, but the condition here will raise the exception.

Copy link
Contributor

@nkanazawa1989 nkanazawa1989 left a comment

Choose a reason for hiding this comment

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

Thanks @to24toro this is great start of V2 migration of the pulse module. I also want review from @TsafrirA .

"inst_map or meas_map, and backend cannot be None simultaneously"
) from ex
if isinstance(meas_map, list):
meas_map = utils.format_meas_map(meas_map)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you integrate this into MeasureGrouping?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This function is used in only _measure_v1. So I think that it is no necessary to move into MeasureGrouping.

qiskit/pulse/macros.py Outdated Show resolved Hide resolved
def measure_v2(
qubits: List[int],
backend=None,
target: Optional[Target] = None,
Copy link
Contributor

Choose a reason for hiding this comment

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

You can reduce backend and target by formatting the arguments in measure function before dispatching the logic. Please keep interface minimum for maintainability. Same for v1.

measure_groups.add(tuple(meas_map[qubit]))
for measure_group_qubits in measure_groups:
try:
default_sched = target.get_calibration(measure_name, measure_group_qubits)
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't work because Target has calibration for single qubit (because attached Measure class is single qubit operation). Here, you need to iterate over all qubits in the group and combine them.

Also, I have been wondering if grouping is really needed without constraints. For example, if you combine meas calibration for group of [0, 1] and [2, 3], this will eventually generate a left-aligned block of [0, 1, 2, 3]. I think we just need to combine them without considering the grouping, as long as backend meas map doesn't provide constraint. Probably, we need to pad non-measured qubit timeslot in the group with delays (so that they don't cause overlap within the group). Any thoughts @wshanks ?

@@ -104,3 +189,21 @@ def measure_all(backend) -> Schedule:
A schedule corresponding to the inputs provided.
"""
return measure(qubits=list(range(backend.configuration().n_qubits)), backend=backend)


def combine_schedules(qubits: List, schedule: Schedule, default_schedule: Union[Schedule, ScheduleBlock],measure_group_qubits: List, qubit_mem_slots: Optional[Dict[int, int]] = None):
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this should be a function remap_memory_slot(schedule: Schedule, qubit_mem_slots: Dict[int, int]) -> Schedule because it seems just replacing the slot index. @TsafrirA does it help creg index matching? Let us know if you have other ideas.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I change the code at 509392a

Comment on lines 57 to 58
if hasattr(backend, "target"):
return measure_v2(qubits, backend, target, meas_map, qubit_mem_slots, measure_name)
Copy link
Contributor

@nkanazawa1989 nkanazawa1989 Apr 13, 2023

Choose a reason for hiding this comment

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

Suggested change
if hasattr(backend, "target"):
return measure_v2(qubits, backend, target, meas_map, qubit_mem_slots, measure_name)
if target or hasattr(backend, "target"):
return measure_v2(
qubits=qubits,
target=target or backend.target,
meas_map=meas_map or getattr(backend, "meas_map", MeasureGrouping()),
qubit_mem_slots=qubit_mem_slots,
measure_name=measure_name,
)

Note that backend is optional here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I change the code at 509392a

@@ -1045,6 +1048,10 @@ def build_coupling_map(self, two_q_gate=None):
else:
return None

def add_measuregrouping(self, meas_map=None):
Copy link
Contributor

Choose a reason for hiding this comment

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

You can update the constructor of Target with meas_map (because this is hardware constraints and user cannot modify once it's set). Then store it as a protected member and provide only property method for it so that user cannot override.

@@ -16,12 +16,14 @@

from qiskit.pulse import channels, exceptions, instructions, utils
from qiskit.pulse.instruction_schedule_map import InstructionScheduleMap
from qiskit.pulse.schedule import Schedule
from qiskit.pulse.schedule import Schedule, ScheduleBlock
from qiskit.transpiler.target import Target


def measure(
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you start pending deprecation for inst_map and V1 backend? We have a convenient decorator now:
https://github.com/Qiskit/qiskit-terra/blob/58aceb59e9bc1e16f29b09402e1984b16d211da3/qiskit/utils/deprecation.py#L100-L111

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should I move deprecate_arg part to _measure_v1?

"""
Gets qubit groups including at least one qubit of `qubits` from meas_map.
"""
return [
Copy link
Contributor

Choose a reason for hiding this comment

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

For backward compatibility, you need to add case for self.meas_map = None. I think, in this case, you just need to return input qubits as-is (because no grouping constraint is applied).

@to24toro to24toro force-pushed the feature/add_meas_group_class branch 3 times, most recently from 5da678c to 509392a Compare April 18, 2023 02:28
Comment on lines 20 to 21
from qiskit.transpiler.target import Target
from qiskit.utils.deprecation import deprecate_arg
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seems that this import statement causes a circular import, so we need to resolve it.

Comment on lines 187 to 193
if meas_map is not None:
if meas_map is Dict:
pass
else:
pass

meas_map = target.meas_map.get_qubit_groups(qubits)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In _measure_v2, meas_map is assumed to be a List. For example, the conventional meas_map = [[1, 2], [2, 3, 4]] will be converted to [1, 2, 3, 4].
If meas_map is None as input, you can obtain a List like [1, 2, 3, 4] from meas_map = target.meas_map.get_qubit_groups(qubits).

However, processing for Dict and List[List] types of meas_map has not been implemented yet.
I would like to know what would be the best way to handle Dict and List[List] types of meas_map.

@@ -315,6 +319,7 @@ def __init__(
"length of the input qubit_properties list"
)
self.qubit_properties = qubit_properties
self._meas_group = MeasureGrouping(meas_group)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I defined MeasureGrouping in meas_group. I named as meas_group because meas_map exists in MeasureGrouping. I would like to know if the naming is reasonable.

@to24toro to24toro force-pushed the feature/add_meas_group_class branch 2 times, most recently from f89279e to 5977d0f Compare April 18, 2023 04:33
macros.py

target

delete raise statement in measure_v2

modify instructions.Acquire to Acquire
@to24toro
Copy link
Contributor Author

I would like to re-submit a PR to organize it again. See #10105.

@to24toro to24toro closed this May 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mod: pulse Related to the Pulse module
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Schedule with V2 backend fails
4 participants