We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Scheduler needs to respect MemSlots in QuantumCircuit Measures
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues -->

### Information

Known bug from my PR https://github.com/Qiskit/qiskit-terra/pull/2650

### What is the current behavior?
When passing a circuit through the basic scheduler (`qiskit.scheduler.schedule`), the resulting `Schedule` will always measure qubit results into the `MemorySlot` which matches the qubit index.
For example:
```
qc.measure(q[0], c[3])
```
will measure qubit 0 into `MemorySlot(0)` rather than `MemorySlot(3)` -- it will use the default Acquire from the cmd_def which is probably something like `Acquire([0, 1], [MemSlot(0), MemSlot(1)])`. The correct behaviour is to use the classical reg from the instruction and then modify the `AcquireInstruction` from the `Schedule` returned by the `cmd_def`. It's unclear what we should do with the other qubits that are measured within the same `meas_map` group, if the user doesn't specify those other qubits to be measured.

We need a follow up PR to handle this more carefully. The solution likely needs to update the helper function: `qiskit.scheduler.methods.basic.translate_gates_to_pulse_defs.get_measure_schedule`


### Steps to reproduce the problem
### What is the expected behavior?
### Suggested solutions
see above


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `qiskit/scheduler/methods/basic.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 
3 # This code is part of Qiskit.
4 #
5 # (C) Copyright IBM 2019.
6 #
7 # This code is licensed under the Apache License, Version 2.0. You may
8 # obtain a copy of this license in the LICENSE.txt file in the root directory
9 # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
10 #
11 # Any modifications or derivative works of this code must retain this
12 # copyright notice, and modified files need to carry a notice indicating
13 # that they have been altered from the originals.
14 
15 """The most straightforward scheduling methods: scheduling as early or as late as possible.
16 
17 Warning: Currently for both of these methods, the MemorySlots in circuit Measures are ignored.
18 Qubits will be measured into the MemorySlot which matches the measured qubit's index. (Issue #2704)
19 """
20 
21 from collections import defaultdict, namedtuple
22 from typing import List
23 
24 from qiskit.circuit.measure import Measure
25 from qiskit.circuit.quantumcircuit import QuantumCircuit
26 from qiskit.exceptions import QiskitError
27 from qiskit.extensions.standard.barrier import Barrier
28 from qiskit.pulse.exceptions import PulseError
29 from qiskit.pulse.schedule import Schedule
30 
31 from qiskit.scheduler.config import ScheduleConfig
32 
33 
34 CircuitPulseDef = namedtuple('CircuitPulseDef', [
35     'schedule',  # The schedule which implements the quantum circuit command
36     'qubits'])   # The labels of the qubits involved in the command according to the circuit
37 
38 
39 def as_soon_as_possible(circuit: QuantumCircuit,
40                         schedule_config: ScheduleConfig) -> Schedule:
41     """
42     Return the pulse Schedule which implements the input circuit using an "as soon as possible"
43     (asap) scheduling policy. Circuit instructions are first each mapped to equivalent pulse
44     Schedules according to the command definition given by the schedule_config. Then, this circuit
45     instruction-equivalent Schedule is appended at the earliest time at which all qubits involved
46     in the instruction are available.
47 
48     Args:
49         circuit: The quantum circuit to translate
50         schedule_config: Backend specific parameters used for building the Schedule
51     Returns:
52         A schedule corresponding to the input `circuit` with pulses occurring as early as possible
53     """
54     sched = Schedule(name=circuit.name)
55 
56     qubit_time_available = defaultdict(int)
57 
58     def update_times(inst_qubits: List[int], time: int = 0) -> None:
59         """Update the time tracker for all inst_qubits to the given time."""
60         for q in inst_qubits:
61             qubit_time_available[q] = time
62 
63     circ_pulse_defs = translate_gates_to_pulse_defs(circuit, schedule_config)
64     for circ_pulse_def in circ_pulse_defs:
65         time = max(qubit_time_available[q] for q in circ_pulse_def.qubits)
66         if isinstance(circ_pulse_def.schedule, Barrier):
67             update_times(circ_pulse_def.qubits, time)
68         else:
69             sched = sched.insert(time, circ_pulse_def.schedule)
70             update_times(circ_pulse_def.qubits, time + circ_pulse_def.schedule.duration)
71     return sched
72 
73 
74 def as_late_as_possible(circuit: QuantumCircuit,
75                         schedule_config: ScheduleConfig) -> Schedule:
76     """
77     Return the pulse Schedule which implements the input circuit using an "as late as possible"
78     (alap) scheduling policy. Circuit instructions are first each mapped to equivalent pulse
79     Schedules according to the command definition given by the schedule_config. Then, this circuit
80     instruction-equivalent Schedule is appended at the latest time that it can be without allowing
81     unnecessary time between instructions or allowing instructions with common qubits to overlap.
82 
83     This method should improves the outcome fidelity over ASAP scheduling, because we may
84     maximize the time that the qubit remains in the ground state.
85 
86     Args:
87         circuit: The quantum circuit to translate
88         schedule_config: Backend specific parameters used for building the Schedule
89     Returns:
90         A schedule corresponding to the input `circuit` with pulses occurring as late as possible
91     """
92     sched = Schedule(name=circuit.name)
93     # Align channel end times.
94     circuit.barrier()
95     # We schedule in reverse order to get ALAP behaviour. We need to know how far out from t=0 any
96     # qubit will become occupied. We add positive shifts to these times as we go along.
97     # The time is initialized to 0 because all qubits are involved in the final barrier.
98     qubit_available_until = defaultdict(lambda: 0)
99 
100     def update_times(inst_qubits: List[int], shift: int = 0, cmd_start_time: int = 0) -> None:
101         """Update the time tracker for all inst_qubits to the given time."""
102         for q in inst_qubits:
103             qubit_available_until[q] = cmd_start_time
104         for q in qubit_available_until.keys():
105             if q not in inst_qubits:
106                 # Uninvolved qubits might be free for the duration of the new instruction
107                 qubit_available_until[q] += shift
108 
109     circ_pulse_defs = translate_gates_to_pulse_defs(circuit, schedule_config)
110     for circ_pulse_def in reversed(circ_pulse_defs):
111         cmd_sched = circ_pulse_def.schedule
112         # The new instruction should end when one of its qubits becomes occupied
113         cmd_start_time = (min([qubit_available_until[q] for q in circ_pulse_def.qubits])
114                           - getattr(cmd_sched, 'duration', 0))  # Barrier has no duration
115         # We have to translate qubit times forward when the cmd_start_time is negative
116         shift_amount = max(0, -cmd_start_time)
117         cmd_start_time = max(cmd_start_time, 0)
118         if not isinstance(circ_pulse_def.schedule, Barrier):
119             sched = cmd_sched.shift(cmd_start_time).insert(shift_amount, sched, name=sched.name)
120         update_times(circ_pulse_def.qubits, shift_amount, cmd_start_time)
121     return sched
122 
123 
124 def translate_gates_to_pulse_defs(circuit: QuantumCircuit,
125                                   schedule_config: ScheduleConfig) -> List[CircuitPulseDef]:
126     """
127     Without concern for the final schedule, extract and return a list of Schedules and the qubits
128     they operate on, for each element encountered in the input circuit. Measures are grouped when
129     possible, so qc.measure(q0, c0)/qc.measure(q1, c1) will generate a synchronous measurement
130     pulse.
131 
132     Args:
133         circuit: The quantum circuit to translate
134         schedule_config: Backend specific parameters used for building the Schedule
135     Returns:
136         A list of CircuitPulseDefs: the pulse definition for each circuit element
137     Raises:
138         QiskitError: If circuit uses a command that isn't defined in config.cmd_def
139     """
140     circ_pulse_defs = []
141 
142     cmd_def = schedule_config.cmd_def
143     measured_qubits = set()  # Collect qubits that would like to be measured
144 
145     def get_measure_schedule() -> CircuitPulseDef:
146         """Create a schedule to measure the qubits queued for measuring."""
147         measures = set()
148         all_qubits = set()
149         sched = Schedule()
150         for q in measured_qubits:
151             measures.add(tuple(schedule_config.meas_map[q]))
152         for qubits in measures:
153             all_qubits.update(qubits)
154             # TODO (Issue #2704): Respect MemorySlots from the input circuit
155             sched |= cmd_def.get('measure', qubits)
156         measured_qubits.clear()
157         return CircuitPulseDef(schedule=sched, qubits=list(all_qubits))
158 
159     for inst, qubits, _ in circuit.data:
160         inst_qubits = [qubit.index for qubit in qubits]  # We want only the indices of the qubits
161         if any(q in measured_qubits for q in inst_qubits):
162             # If we are operating on a qubit that was scheduled to be measured, process that first
163             circ_pulse_defs.append(get_measure_schedule())
164         if isinstance(inst, Barrier):
165             circ_pulse_defs.append(CircuitPulseDef(schedule=inst, qubits=inst_qubits))
166         elif isinstance(inst, Measure):
167             measured_qubits.update(inst_qubits)
168         else:
169             try:
170                 circ_pulse_defs.append(
171                     CircuitPulseDef(schedule=cmd_def.get(inst.name, inst_qubits, *inst.params),
172                                     qubits=inst_qubits))
173             except PulseError:
174                 raise QiskitError("Operation '{0}' on qubit(s) {1} not supported by the backend "
175                                   "command definition. Did you remember to transpile your input "
176                                   "circuit for the same backend?".format(inst.name, inst_qubits))
177     if measured_qubits:
178         circ_pulse_defs.append(get_measure_schedule())
179 
180     return circ_pulse_defs
181
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/qiskit/scheduler/methods/basic.py b/qiskit/scheduler/methods/basic.py
--- a/qiskit/scheduler/methods/basic.py
+++ b/qiskit/scheduler/methods/basic.py
@@ -27,6 +27,8 @@
 from qiskit.extensions.standard.barrier import Barrier
 from qiskit.pulse.exceptions import PulseError
 from qiskit.pulse.schedule import Schedule
+from qiskit.pulse.channels import MemorySlot
+from qiskit.pulse.commands import AcquireInstruction
 
 from qiskit.scheduler.config import ScheduleConfig
 
@@ -140,31 +142,50 @@
     circ_pulse_defs = []
 
     cmd_def = schedule_config.cmd_def
-    measured_qubits = set()  # Collect qubits that would like to be measured
+    qubit_mem_slots = {}  # Map measured qubit index to classical bit index
 
     def get_measure_schedule() -> CircuitPulseDef:
         """Create a schedule to measure the qubits queued for measuring."""
         measures = set()
         all_qubits = set()
         sched = Schedule()
-        for q in measured_qubits:
-            measures.add(tuple(schedule_config.meas_map[q]))
+        for qubit in qubit_mem_slots:
+            measures.add(tuple(schedule_config.meas_map[qubit]))
         for qubits in measures:
             all_qubits.update(qubits)
-            # TODO (Issue #2704): Respect MemorySlots from the input circuit
-            sched |= cmd_def.get('measure', qubits)
-        measured_qubits.clear()
+            unused_mem_slots = set(qubits) - set(qubit_mem_slots.values())
+            default_sched = cmd_def.get('measure', qubits)
+            for time, inst in default_sched.instructions:
+                if isinstance(inst, AcquireInstruction):
+                    mem_slots = []
+                    for channel in inst.acquires:
+                        if channel.index in qubit_mem_slots.keys():
+                            mem_slots.append(MemorySlot(qubit_mem_slots[channel.index]))
+                        else:
+                            mem_slots.append(MemorySlot(unused_mem_slots.pop()))
+                    new_acquire = AcquireInstruction(command=inst.command,
+                                                     acquires=inst.acquires,
+                                                     mem_slots=mem_slots)
+                    sched._union((time, new_acquire))
+                # Measurement pulses should only be added if its qubit was measured by the user
+                elif inst.channels[0].index in qubit_mem_slots.keys():
+                    sched._union((time, inst))
+        qubit_mem_slots.clear()
         return CircuitPulseDef(schedule=sched, qubits=list(all_qubits))
 
-    for inst, qubits, _ in circuit.data:
+    for inst, qubits, clbits in circuit.data:
         inst_qubits = [qubit.index for qubit in qubits]  # We want only the indices of the qubits
-        if any(q in measured_qubits for q in inst_qubits):
+        if any(q in qubit_mem_slots for q in inst_qubits):
             # If we are operating on a qubit that was scheduled to be measured, process that first
             circ_pulse_defs.append(get_measure_schedule())
         if isinstance(inst, Barrier):
             circ_pulse_defs.append(CircuitPulseDef(schedule=inst, qubits=inst_qubits))
         elif isinstance(inst, Measure):
-            measured_qubits.update(inst_qubits)
+            if (len(inst_qubits) != 1 and len(clbits) != 1):
+                raise QiskitError("Qubit '{0}' or classical bit '{1}' errored because the "
+                                  "circuit Measure instruction only takes one of "
+                                  "each.".format(inst_qubits, clbits))
+            qubit_mem_slots[inst_qubits[0]] = clbits[0].index
         else:
             try:
                 circ_pulse_defs.append(
@@ -174,7 +195,7 @@
                 raise QiskitError("Operation '{0}' on qubit(s) {1} not supported by the backend "
                                   "command definition. Did you remember to transpile your input "
                                   "circuit for the same backend?".format(inst.name, inst_qubits))
-    if measured_qubits:
+    if qubit_mem_slots:
         circ_pulse_defs.append(get_measure_schedule())
 
     return circ_pulse_defs

{"golden_diff": "diff --git a/qiskit/scheduler/methods/basic.py b/qiskit/scheduler/methods/basic.py\n--- a/qiskit/scheduler/methods/basic.py\n+++ b/qiskit/scheduler/methods/basic.py\n@@ -27,6 +27,8 @@\n from qiskit.extensions.standard.barrier import Barrier\n from qiskit.pulse.exceptions import PulseError\n from qiskit.pulse.schedule import Schedule\n+from qiskit.pulse.channels import MemorySlot\n+from qiskit.pulse.commands import AcquireInstruction\n \n from qiskit.scheduler.config import ScheduleConfig\n \n@@ -140,31 +142,50 @@\n     circ_pulse_defs = []\n \n     cmd_def = schedule_config.cmd_def\n-    measured_qubits = set()  # Collect qubits that would like to be measured\n+    qubit_mem_slots = {}  # Map measured qubit index to classical bit index\n \n     def get_measure_schedule() -> CircuitPulseDef:\n         \"\"\"Create a schedule to measure the qubits queued for measuring.\"\"\"\n         measures = set()\n         all_qubits = set()\n         sched = Schedule()\n-        for q in measured_qubits:\n-            measures.add(tuple(schedule_config.meas_map[q]))\n+        for qubit in qubit_mem_slots:\n+            measures.add(tuple(schedule_config.meas_map[qubit]))\n         for qubits in measures:\n             all_qubits.update(qubits)\n-            # TODO (Issue #2704): Respect MemorySlots from the input circuit\n-            sched |= cmd_def.get('measure', qubits)\n-        measured_qubits.clear()\n+            unused_mem_slots = set(qubits) - set(qubit_mem_slots.values())\n+            default_sched = cmd_def.get('measure', qubits)\n+            for time, inst in default_sched.instructions:\n+                if isinstance(inst, AcquireInstruction):\n+                    mem_slots = []\n+                    for channel in inst.acquires:\n+                        if channel.index in qubit_mem_slots.keys():\n+                            mem_slots.append(MemorySlot(qubit_mem_slots[channel.index]))\n+                        else:\n+                            mem_slots.append(MemorySlot(unused_mem_slots.pop()))\n+                    new_acquire = AcquireInstruction(command=inst.command,\n+                                                     acquires=inst.acquires,\n+                                                     mem_slots=mem_slots)\n+                    sched._union((time, new_acquire))\n+                # Measurement pulses should only be added if its qubit was measured by the user\n+                elif inst.channels[0].index in qubit_mem_slots.keys():\n+                    sched._union((time, inst))\n+        qubit_mem_slots.clear()\n         return CircuitPulseDef(schedule=sched, qubits=list(all_qubits))\n \n-    for inst, qubits, _ in circuit.data:\n+    for inst, qubits, clbits in circuit.data:\n         inst_qubits = [qubit.index for qubit in qubits]  # We want only the indices of the qubits\n-        if any(q in measured_qubits for q in inst_qubits):\n+        if any(q in qubit_mem_slots for q in inst_qubits):\n             # If we are operating on a qubit that was scheduled to be measured, process that first\n             circ_pulse_defs.append(get_measure_schedule())\n         if isinstance(inst, Barrier):\n             circ_pulse_defs.append(CircuitPulseDef(schedule=inst, qubits=inst_qubits))\n         elif isinstance(inst, Measure):\n-            measured_qubits.update(inst_qubits)\n+            if (len(inst_qubits) != 1 and len(clbits) != 1):\n+                raise QiskitError(\"Qubit '{0}' or classical bit '{1}' errored because the \"\n+                                  \"circuit Measure instruction only takes one of \"\n+                                  \"each.\".format(inst_qubits, clbits))\n+            qubit_mem_slots[inst_qubits[0]] = clbits[0].index\n         else:\n             try:\n                 circ_pulse_defs.append(\n@@ -174,7 +195,7 @@\n                 raise QiskitError(\"Operation '{0}' on qubit(s) {1} not supported by the backend \"\n                                   \"command definition. Did you remember to transpile your input \"\n                                   \"circuit for the same backend?\".format(inst.name, inst_qubits))\n-    if measured_qubits:\n+    if qubit_mem_slots:\n         circ_pulse_defs.append(get_measure_schedule())\n \n     return circ_pulse_defs\n", "issue": "Scheduler needs to respect MemSlots in QuantumCircuit Measures\n<!-- \u26a0\ufe0f If you do not respect this template, your issue will be closed -->\r\n<!-- \u26a0\ufe0f Make sure to browse the opened and closed issues -->\r\n\r\n### Information\r\n\r\nKnown bug from my PR https://github.com/Qiskit/qiskit-terra/pull/2650\r\n\r\n### What is the current behavior?\r\nWhen passing a circuit through the basic scheduler (`qiskit.scheduler.schedule`), the resulting `Schedule` will always measure qubit results into the `MemorySlot` which matches the qubit index.\r\nFor example:\r\n```\r\nqc.measure(q[0], c[3])\r\n```\r\nwill measure qubit 0 into `MemorySlot(0)` rather than `MemorySlot(3)` -- it will use the default Acquire from the cmd_def which is probably something like `Acquire([0, 1], [MemSlot(0), MemSlot(1)])`. The correct behaviour is to use the classical reg from the instruction and then modify the `AcquireInstruction` from the `Schedule` returned by the `cmd_def`. It's unclear what we should do with the other qubits that are measured within the same `meas_map` group, if the user doesn't specify those other qubits to be measured.\r\n\r\nWe need a follow up PR to handle this more carefully. The solution likely needs to update the helper function: `qiskit.scheduler.methods.basic.translate_gates_to_pulse_defs.get_measure_schedule`\r\n\r\n\r\n### Steps to reproduce the problem\r\n### What is the expected behavior?\r\n### Suggested solutions\r\nsee above\r\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\n# This code is part of Qiskit.\n#\n# (C) Copyright IBM 2019.\n#\n# This code is licensed under the Apache License, Version 2.0. You may\n# obtain a copy of this license in the LICENSE.txt file in the root directory\n# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.\n#\n# Any modifications or derivative works of this code must retain this\n# copyright notice, and modified files need to carry a notice indicating\n# that they have been altered from the originals.\n\n\"\"\"The most straightforward scheduling methods: scheduling as early or as late as possible.\n\nWarning: Currently for both of these methods, the MemorySlots in circuit Measures are ignored.\nQubits will be measured into the MemorySlot which matches the measured qubit's index. (Issue #2704)\n\"\"\"\n\nfrom collections import defaultdict, namedtuple\nfrom typing import List\n\nfrom qiskit.circuit.measure import Measure\nfrom qiskit.circuit.quantumcircuit import QuantumCircuit\nfrom qiskit.exceptions import QiskitError\nfrom qiskit.extensions.standard.barrier import Barrier\nfrom qiskit.pulse.exceptions import PulseError\nfrom qiskit.pulse.schedule import Schedule\n\nfrom qiskit.scheduler.config import ScheduleConfig\n\n\nCircuitPulseDef = namedtuple('CircuitPulseDef', [\n    'schedule',  # The schedule which implements the quantum circuit command\n    'qubits'])   # The labels of the qubits involved in the command according to the circuit\n\n\ndef as_soon_as_possible(circuit: QuantumCircuit,\n                        schedule_config: ScheduleConfig) -> Schedule:\n    \"\"\"\n    Return the pulse Schedule which implements the input circuit using an \"as soon as possible\"\n    (asap) scheduling policy. Circuit instructions are first each mapped to equivalent pulse\n    Schedules according to the command definition given by the schedule_config. Then, this circuit\n    instruction-equivalent Schedule is appended at the earliest time at which all qubits involved\n    in the instruction are available.\n\n    Args:\n        circuit: The quantum circuit to translate\n        schedule_config: Backend specific parameters used for building the Schedule\n    Returns:\n        A schedule corresponding to the input `circuit` with pulses occurring as early as possible\n    \"\"\"\n    sched = Schedule(name=circuit.name)\n\n    qubit_time_available = defaultdict(int)\n\n    def update_times(inst_qubits: List[int], time: int = 0) -> None:\n        \"\"\"Update the time tracker for all inst_qubits to the given time.\"\"\"\n        for q in inst_qubits:\n            qubit_time_available[q] = time\n\n    circ_pulse_defs = translate_gates_to_pulse_defs(circuit, schedule_config)\n    for circ_pulse_def in circ_pulse_defs:\n        time = max(qubit_time_available[q] for q in circ_pulse_def.qubits)\n        if isinstance(circ_pulse_def.schedule, Barrier):\n            update_times(circ_pulse_def.qubits, time)\n        else:\n            sched = sched.insert(time, circ_pulse_def.schedule)\n            update_times(circ_pulse_def.qubits, time + circ_pulse_def.schedule.duration)\n    return sched\n\n\ndef as_late_as_possible(circuit: QuantumCircuit,\n                        schedule_config: ScheduleConfig) -> Schedule:\n    \"\"\"\n    Return the pulse Schedule which implements the input circuit using an \"as late as possible\"\n    (alap) scheduling policy. Circuit instructions are first each mapped to equivalent pulse\n    Schedules according to the command definition given by the schedule_config. Then, this circuit\n    instruction-equivalent Schedule is appended at the latest time that it can be without allowing\n    unnecessary time between instructions or allowing instructions with common qubits to overlap.\n\n    This method should improves the outcome fidelity over ASAP scheduling, because we may\n    maximize the time that the qubit remains in the ground state.\n\n    Args:\n        circuit: The quantum circuit to translate\n        schedule_config: Backend specific parameters used for building the Schedule\n    Returns:\n        A schedule corresponding to the input `circuit` with pulses occurring as late as possible\n    \"\"\"\n    sched = Schedule(name=circuit.name)\n    # Align channel end times.\n    circuit.barrier()\n    # We schedule in reverse order to get ALAP behaviour. We need to know how far out from t=0 any\n    # qubit will become occupied. We add positive shifts to these times as we go along.\n    # The time is initialized to 0 because all qubits are involved in the final barrier.\n    qubit_available_until = defaultdict(lambda: 0)\n\n    def update_times(inst_qubits: List[int], shift: int = 0, cmd_start_time: int = 0) -> None:\n        \"\"\"Update the time tracker for all inst_qubits to the given time.\"\"\"\n        for q in inst_qubits:\n            qubit_available_until[q] = cmd_start_time\n        for q in qubit_available_until.keys():\n            if q not in inst_qubits:\n                # Uninvolved qubits might be free for the duration of the new instruction\n                qubit_available_until[q] += shift\n\n    circ_pulse_defs = translate_gates_to_pulse_defs(circuit, schedule_config)\n    for circ_pulse_def in reversed(circ_pulse_defs):\n        cmd_sched = circ_pulse_def.schedule\n        # The new instruction should end when one of its qubits becomes occupied\n        cmd_start_time = (min([qubit_available_until[q] for q in circ_pulse_def.qubits])\n                          - getattr(cmd_sched, 'duration', 0))  # Barrier has no duration\n        # We have to translate qubit times forward when the cmd_start_time is negative\n        shift_amount = max(0, -cmd_start_time)\n        cmd_start_time = max(cmd_start_time, 0)\n        if not isinstance(circ_pulse_def.schedule, Barrier):\n            sched = cmd_sched.shift(cmd_start_time).insert(shift_amount, sched, name=sched.name)\n        update_times(circ_pulse_def.qubits, shift_amount, cmd_start_time)\n    return sched\n\n\ndef translate_gates_to_pulse_defs(circuit: QuantumCircuit,\n                                  schedule_config: ScheduleConfig) -> List[CircuitPulseDef]:\n    \"\"\"\n    Without concern for the final schedule, extract and return a list of Schedules and the qubits\n    they operate on, for each element encountered in the input circuit. Measures are grouped when\n    possible, so qc.measure(q0, c0)/qc.measure(q1, c1) will generate a synchronous measurement\n    pulse.\n\n    Args:\n        circuit: The quantum circuit to translate\n        schedule_config: Backend specific parameters used for building the Schedule\n    Returns:\n        A list of CircuitPulseDefs: the pulse definition for each circuit element\n    Raises:\n        QiskitError: If circuit uses a command that isn't defined in config.cmd_def\n    \"\"\"\n    circ_pulse_defs = []\n\n    cmd_def = schedule_config.cmd_def\n    measured_qubits = set()  # Collect qubits that would like to be measured\n\n    def get_measure_schedule() -> CircuitPulseDef:\n        \"\"\"Create a schedule to measure the qubits queued for measuring.\"\"\"\n        measures = set()\n        all_qubits = set()\n        sched = Schedule()\n        for q in measured_qubits:\n            measures.add(tuple(schedule_config.meas_map[q]))\n        for qubits in measures:\n            all_qubits.update(qubits)\n            # TODO (Issue #2704): Respect MemorySlots from the input circuit\n            sched |= cmd_def.get('measure', qubits)\n        measured_qubits.clear()\n        return CircuitPulseDef(schedule=sched, qubits=list(all_qubits))\n\n    for inst, qubits, _ in circuit.data:\n        inst_qubits = [qubit.index for qubit in qubits]  # We want only the indices of the qubits\n        if any(q in measured_qubits for q in inst_qubits):\n            # If we are operating on a qubit that was scheduled to be measured, process that first\n            circ_pulse_defs.append(get_measure_schedule())\n        if isinstance(inst, Barrier):\n            circ_pulse_defs.append(CircuitPulseDef(schedule=inst, qubits=inst_qubits))\n        elif isinstance(inst, Measure):\n            measured_qubits.update(inst_qubits)\n        else:\n            try:\n                circ_pulse_defs.append(\n                    CircuitPulseDef(schedule=cmd_def.get(inst.name, inst_qubits, *inst.params),\n                                    qubits=inst_qubits))\n            except PulseError:\n                raise QiskitError(\"Operation '{0}' on qubit(s) {1} not supported by the backend \"\n                                  \"command definition. Did you remember to transpile your input \"\n                                  \"circuit for the same backend?\".format(inst.name, inst_qubits))\n    if measured_qubits:\n        circ_pulse_defs.append(get_measure_schedule())\n\n    return circ_pulse_defs\n", "path": "qiskit/scheduler/methods/basic.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\n# This code is part of Qiskit.\n#\n# (C) Copyright IBM 2019.\n#\n# This code is licensed under the Apache License, Version 2.0. You may\n# obtain a copy of this license in the LICENSE.txt file in the root directory\n# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.\n#\n# Any modifications or derivative works of this code must retain this\n# copyright notice, and modified files need to carry a notice indicating\n# that they have been altered from the originals.\n\n\"\"\"The most straightforward scheduling methods: scheduling as early or as late as possible.\n\nWarning: Currently for both of these methods, the MemorySlots in circuit Measures are ignored.\nQubits will be measured into the MemorySlot which matches the measured qubit's index. (Issue #2704)\n\"\"\"\n\nfrom collections import defaultdict, namedtuple\nfrom typing import List\n\nfrom qiskit.circuit.measure import Measure\nfrom qiskit.circuit.quantumcircuit import QuantumCircuit\nfrom qiskit.exceptions import QiskitError\nfrom qiskit.extensions.standard.barrier import Barrier\nfrom qiskit.pulse.exceptions import PulseError\nfrom qiskit.pulse.schedule import Schedule\nfrom qiskit.pulse.channels import MemorySlot\nfrom qiskit.pulse.commands import AcquireInstruction\n\nfrom qiskit.scheduler.config import ScheduleConfig\n\n\nCircuitPulseDef = namedtuple('CircuitPulseDef', [\n    'schedule',  # The schedule which implements the quantum circuit command\n    'qubits'])   # The labels of the qubits involved in the command according to the circuit\n\n\ndef as_soon_as_possible(circuit: QuantumCircuit,\n                        schedule_config: ScheduleConfig) -> Schedule:\n    \"\"\"\n    Return the pulse Schedule which implements the input circuit using an \"as soon as possible\"\n    (asap) scheduling policy. Circuit instructions are first each mapped to equivalent pulse\n    Schedules according to the command definition given by the schedule_config. Then, this circuit\n    instruction-equivalent Schedule is appended at the earliest time at which all qubits involved\n    in the instruction are available.\n\n    Args:\n        circuit: The quantum circuit to translate\n        schedule_config: Backend specific parameters used for building the Schedule\n    Returns:\n        A schedule corresponding to the input `circuit` with pulses occurring as early as possible\n    \"\"\"\n    sched = Schedule(name=circuit.name)\n\n    qubit_time_available = defaultdict(int)\n\n    def update_times(inst_qubits: List[int], time: int = 0) -> None:\n        \"\"\"Update the time tracker for all inst_qubits to the given time.\"\"\"\n        for q in inst_qubits:\n            qubit_time_available[q] = time\n\n    circ_pulse_defs = translate_gates_to_pulse_defs(circuit, schedule_config)\n    for circ_pulse_def in circ_pulse_defs:\n        time = max(qubit_time_available[q] for q in circ_pulse_def.qubits)\n        if isinstance(circ_pulse_def.schedule, Barrier):\n            update_times(circ_pulse_def.qubits, time)\n        else:\n            sched = sched.insert(time, circ_pulse_def.schedule)\n            update_times(circ_pulse_def.qubits, time + circ_pulse_def.schedule.duration)\n    return sched\n\n\ndef as_late_as_possible(circuit: QuantumCircuit,\n                        schedule_config: ScheduleConfig) -> Schedule:\n    \"\"\"\n    Return the pulse Schedule which implements the input circuit using an \"as late as possible\"\n    (alap) scheduling policy. Circuit instructions are first each mapped to equivalent pulse\n    Schedules according to the command definition given by the schedule_config. Then, this circuit\n    instruction-equivalent Schedule is appended at the latest time that it can be without allowing\n    unnecessary time between instructions or allowing instructions with common qubits to overlap.\n\n    This method should improves the outcome fidelity over ASAP scheduling, because we may\n    maximize the time that the qubit remains in the ground state.\n\n    Args:\n        circuit: The quantum circuit to translate\n        schedule_config: Backend specific parameters used for building the Schedule\n    Returns:\n        A schedule corresponding to the input `circuit` with pulses occurring as late as possible\n    \"\"\"\n    sched = Schedule(name=circuit.name)\n    # Align channel end times.\n    circuit.barrier()\n    # We schedule in reverse order to get ALAP behaviour. We need to know how far out from t=0 any\n    # qubit will become occupied. We add positive shifts to these times as we go along.\n    # The time is initialized to 0 because all qubits are involved in the final barrier.\n    qubit_available_until = defaultdict(lambda: 0)\n\n    def update_times(inst_qubits: List[int], shift: int = 0, cmd_start_time: int = 0) -> None:\n        \"\"\"Update the time tracker for all inst_qubits to the given time.\"\"\"\n        for q in inst_qubits:\n            qubit_available_until[q] = cmd_start_time\n        for q in qubit_available_until.keys():\n            if q not in inst_qubits:\n                # Uninvolved qubits might be free for the duration of the new instruction\n                qubit_available_until[q] += shift\n\n    circ_pulse_defs = translate_gates_to_pulse_defs(circuit, schedule_config)\n    for circ_pulse_def in reversed(circ_pulse_defs):\n        cmd_sched = circ_pulse_def.schedule\n        # The new instruction should end when one of its qubits becomes occupied\n        cmd_start_time = (min([qubit_available_until[q] for q in circ_pulse_def.qubits])\n                          - getattr(cmd_sched, 'duration', 0))  # Barrier has no duration\n        # We have to translate qubit times forward when the cmd_start_time is negative\n        shift_amount = max(0, -cmd_start_time)\n        cmd_start_time = max(cmd_start_time, 0)\n        if not isinstance(circ_pulse_def.schedule, Barrier):\n            sched = cmd_sched.shift(cmd_start_time).insert(shift_amount, sched, name=sched.name)\n        update_times(circ_pulse_def.qubits, shift_amount, cmd_start_time)\n    return sched\n\n\ndef translate_gates_to_pulse_defs(circuit: QuantumCircuit,\n                                  schedule_config: ScheduleConfig) -> List[CircuitPulseDef]:\n    \"\"\"\n    Without concern for the final schedule, extract and return a list of Schedules and the qubits\n    they operate on, for each element encountered in the input circuit. Measures are grouped when\n    possible, so qc.measure(q0, c0)/qc.measure(q1, c1) will generate a synchronous measurement\n    pulse.\n\n    Args:\n        circuit: The quantum circuit to translate\n        schedule_config: Backend specific parameters used for building the Schedule\n    Returns:\n        A list of CircuitPulseDefs: the pulse definition for each circuit element\n    Raises:\n        QiskitError: If circuit uses a command that isn't defined in config.cmd_def\n    \"\"\"\n    circ_pulse_defs = []\n\n    cmd_def = schedule_config.cmd_def\n    qubit_mem_slots = {}  # Map measured qubit index to classical bit index\n\n    def get_measure_schedule() -> CircuitPulseDef:\n        \"\"\"Create a schedule to measure the qubits queued for measuring.\"\"\"\n        measures = set()\n        all_qubits = set()\n        sched = Schedule()\n        for qubit in qubit_mem_slots:\n            measures.add(tuple(schedule_config.meas_map[qubit]))\n        for qubits in measures:\n            all_qubits.update(qubits)\n            unused_mem_slots = set(qubits) - set(qubit_mem_slots.values())\n            default_sched = cmd_def.get('measure', qubits)\n            for time, inst in default_sched.instructions:\n                if isinstance(inst, AcquireInstruction):\n                    mem_slots = []\n                    for channel in inst.acquires:\n                        if channel.index in qubit_mem_slots.keys():\n                            mem_slots.append(MemorySlot(qubit_mem_slots[channel.index]))\n                        else:\n                            mem_slots.append(MemorySlot(unused_mem_slots.pop()))\n                    new_acquire = AcquireInstruction(command=inst.command,\n                                                     acquires=inst.acquires,\n                                                     mem_slots=mem_slots)\n                    sched._union((time, new_acquire))\n                # Measurement pulses should only be added if its qubit was measured by the user\n                elif inst.channels[0].index in qubit_mem_slots.keys():\n                    sched._union((time, inst))\n        qubit_mem_slots.clear()\n        return CircuitPulseDef(schedule=sched, qubits=list(all_qubits))\n\n    for inst, qubits, clbits in circuit.data:\n        inst_qubits = [qubit.index for qubit in qubits]  # We want only the indices of the qubits\n        if any(q in qubit_mem_slots for q in inst_qubits):\n            # If we are operating on a qubit that was scheduled to be measured, process that first\n            circ_pulse_defs.append(get_measure_schedule())\n        if isinstance(inst, Barrier):\n            circ_pulse_defs.append(CircuitPulseDef(schedule=inst, qubits=inst_qubits))\n        elif isinstance(inst, Measure):\n            if (len(inst_qubits) != 1 and len(clbits) != 1):\n                raise QiskitError(\"Qubit '{0}' or classical bit '{1}' errored because the \"\n                                  \"circuit Measure instruction only takes one of \"\n                                  \"each.\".format(inst_qubits, clbits))\n            qubit_mem_slots[inst_qubits[0]] = clbits[0].index\n        else:\n            try:\n                circ_pulse_defs.append(\n                    CircuitPulseDef(schedule=cmd_def.get(inst.name, inst_qubits, *inst.params),\n                                    qubits=inst_qubits))\n            except PulseError:\n                raise QiskitError(\"Operation '{0}' on qubit(s) {1} not supported by the backend \"\n                                  \"command definition. Did you remember to transpile your input \"\n                                  \"circuit for the same backend?\".format(inst.name, inst_qubits))\n    if qubit_mem_slots:\n        circ_pulse_defs.append(get_measure_schedule())\n\n    return circ_pulse_defs\n", "path": "qiskit/scheduler/methods/basic.py"}]}