We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Executing a schedule with one instruction raises an error
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues -->

### Information

- **Qiskit Terra version**:
- **Python version**:
- **Operating system**:

### What is the current behavior?

If I make a schedule with only one instruction:
```
sched = pulse.Acquire(20, pulse.AcquireChannel(0), pulse.MemorySlot(0))
```
then when I `execute` it, it's type is `Instruction` and not `Schedule`, so `execute` wrongly sends it through the `transpiler`, thinking it's a `QuantumCircuit`. Since the transpiler is expecting a circuit, we end up with an attribute error as it tries to access `circuit.qubits`, which isn't a Schedule property.


### Steps to reproduce the problem



### What is the expected behavior?



### Suggested solutions

The easiest fix is to replace `isinstance(experiments, Schedule)` with `isinstance(experiments, (Schedule, pulse.Instruction)`, or perhaps more correctly: `isinstance(experiments, ScheduleComponent)`. Would have to add tests and make sure there aren't other consequences of taking an `Instruction` as input. 


--- 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/assembler/assemble_schedules.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 
3 # This code is part of Qiskit.
4 #
5 # (C) Copyright IBM 2017, 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 """Assemble function for converting a list of circuits into a qobj."""
16 from collections import defaultdict
17 from typing import Any, Dict, List, Tuple
18 import hashlib
19 
20 from qiskit import qobj, pulse
21 from qiskit.assembler.run_config import RunConfig
22 from qiskit.exceptions import QiskitError
23 from qiskit.pulse import instructions, transforms, library
24 from qiskit.qobj import utils as qobj_utils, converters
25 from qiskit.qobj.converters.pulse_instruction import ParametricPulseShapes
26 
27 
28 def assemble_schedules(schedules: List[pulse.Schedule],
29                        qobj_id: int,
30                        qobj_header: qobj.QobjHeader,
31                        run_config: RunConfig) -> qobj.PulseQobj:
32     """Assembles a list of schedules into a qobj that can be run on the backend.
33 
34     Args:
35         schedules: Schedules to assemble.
36         qobj_id: Identifier for the generated qobj.
37         qobj_header: Header to pass to the results.
38         run_config: Configuration of the runtime environment.
39 
40     Returns:
41         The Qobj to be run on the backends.
42 
43     Raises:
44         QiskitError: when frequency settings are not supplied.
45     """
46     if not hasattr(run_config, 'qubit_lo_freq'):
47         raise QiskitError('qubit_lo_freq must be supplied.')
48     if not hasattr(run_config, 'meas_lo_freq'):
49         raise QiskitError('meas_lo_freq must be supplied.')
50 
51     lo_converter = converters.LoConfigConverter(qobj.PulseQobjExperimentConfig,
52                                                 **run_config.to_dict())
53     experiments, experiment_config = _assemble_experiments(schedules,
54                                                            lo_converter,
55                                                            run_config)
56     qobj_config = _assemble_config(lo_converter, experiment_config, run_config)
57 
58     return qobj.PulseQobj(experiments=experiments,
59                           qobj_id=qobj_id,
60                           header=qobj_header,
61                           config=qobj_config)
62 
63 
64 def _assemble_experiments(
65         schedules: List[pulse.Schedule],
66         lo_converter: converters.LoConfigConverter,
67         run_config: RunConfig
68 ) -> Tuple[List[qobj.PulseQobjExperiment], Dict[str, Any]]:
69     """Assembles a list of schedules into PulseQobjExperiments, and returns related metadata that
70     will be assembled into the Qobj configuration.
71 
72     Args:
73         schedules: Schedules to assemble.
74         lo_converter: The configured frequency converter and validator.
75         run_config: Configuration of the runtime environment.
76 
77     Returns:
78         The list of assembled experiments, and the dictionary of related experiment config.
79 
80     Raises:
81         QiskitError: when frequency settings are not compatible with the experiments.
82     """
83     freq_configs = [lo_converter(lo_dict) for lo_dict in getattr(run_config, 'schedule_los', [])]
84 
85     if len(schedules) > 1 and len(freq_configs) not in [0, 1, len(schedules)]:
86         raise QiskitError('Invalid frequency setting is specified. If the frequency is specified, '
87                           'it should be configured the same for all schedules, configured for each '
88                           'schedule, or a list of frequencies should be provided for a single '
89                           'frequency sweep schedule.')
90 
91     instruction_converter = getattr(run_config,
92                                     'instruction_converter',
93                                     converters.InstructionToQobjConverter)
94     instruction_converter = instruction_converter(qobj.PulseQobjInstruction,
95                                                   **run_config.to_dict())
96     compressed_schedules = transforms.compress_pulses(schedules)
97 
98     user_pulselib = {}
99     experiments = []
100     for idx, schedule in enumerate(compressed_schedules):
101         qobj_instructions, max_memory_slot = _assemble_instructions(
102             schedule,
103             instruction_converter,
104             run_config,
105             user_pulselib)
106 
107         # TODO: add other experimental header items (see circuit assembler)
108         qobj_experiment_header = qobj.QobjExperimentHeader(
109             memory_slots=max_memory_slot + 1,  # Memory slots are 0 indexed
110             name=schedule.name or 'Experiment-%d' % idx)
111 
112         experiment = qobj.PulseQobjExperiment(
113             header=qobj_experiment_header,
114             instructions=qobj_instructions)
115         if freq_configs:
116             # This handles the cases where one frequency setting applies to all experiments and
117             # where each experiment has a different frequency
118             freq_idx = idx if len(freq_configs) != 1 else 0
119             experiment.config = freq_configs[freq_idx]
120 
121         experiments.append(experiment)
122 
123     # Frequency sweep
124     if freq_configs and len(experiments) == 1:
125         experiment = experiments[0]
126         experiments = []
127         for freq_config in freq_configs:
128             experiments.append(qobj.PulseQobjExperiment(
129                 header=experiment.header,
130                 instructions=experiment.instructions,
131                 config=freq_config))
132 
133     # Top level Qobj configuration
134     experiment_config = {
135         'pulse_library': [qobj.PulseLibraryItem(name=name, samples=samples)
136                           for name, samples in user_pulselib.items()],
137         'memory_slots': max([exp.header.memory_slots for exp in experiments])
138     }
139 
140     return experiments, experiment_config
141 
142 
143 def _assemble_instructions(
144         schedule: pulse.Schedule,
145         instruction_converter: converters.InstructionToQobjConverter,
146         run_config: RunConfig,
147         user_pulselib: Dict[str, List[complex]]
148 ) -> Tuple[List[qobj.PulseQobjInstruction], int]:
149     """Assembles the instructions in a schedule into a list of PulseQobjInstructions and returns
150     related metadata that will be assembled into the Qobj configuration. Lookup table for
151     pulses defined in all experiments are registered in ``user_pulselib``. This object should be
152     mutable python dictionary so that items are properly updated after each instruction assemble.
153     The dictionary is not returned to avoid redundancy.
154 
155     Args:
156         schedule: Schedule to assemble.
157         instruction_converter: A converter instance which can convert PulseInstructions to
158                                PulseQobjInstructions.
159         run_config: Configuration of the runtime environment.
160         user_pulselib: User pulse library from previous schedule.
161 
162     Returns:
163         A list of converted instructions, the user pulse library dictionary (from pulse name to
164         pulse samples), and the maximum number of readout memory slots used by this Schedule.
165     """
166     max_memory_slot = 0
167     qobj_instructions = []
168 
169     acquire_instruction_map = defaultdict(list)
170     for time, instruction in schedule.instructions:
171 
172         if (isinstance(instruction, instructions.Play) and
173                 isinstance(instruction.pulse, library.ParametricPulse)):
174             pulse_shape = ParametricPulseShapes(type(instruction.pulse)).name
175             if pulse_shape not in run_config.parametric_pulses:
176                 instruction = instructions.Play(instruction.pulse.get_sample_pulse(),
177                                                 instruction.channel,
178                                                 name=instruction.name)
179 
180         if (isinstance(instruction, instructions.Play) and
181                 isinstance(instruction.pulse, library.Waveform)):
182             name = hashlib.sha256(instruction.pulse.samples).hexdigest()
183             instruction = instructions.Play(
184                 library.Waveform(name=name, samples=instruction.pulse.samples),
185                 channel=instruction.channel,
186                 name=name)
187             user_pulselib[name] = instruction.pulse.samples
188 
189         if isinstance(instruction, instructions.Acquire):
190             if instruction.mem_slot:
191                 max_memory_slot = max(max_memory_slot, instruction.mem_slot.index)
192             # Acquires have a single AcquireChannel per inst, but we have to bundle them
193             # together into the Qobj as one instruction with many channels
194             acquire_instruction_map[(time, instruction.duration)].append(instruction)
195             continue
196 
197         if isinstance(instruction, (instructions.Delay, instructions.Directive)):
198             # delay instructions are ignored as timing is explicit within qobj
199             continue
200 
201         qobj_instructions.append(instruction_converter(time, instruction))
202 
203     if acquire_instruction_map:
204         if hasattr(run_config, 'meas_map'):
205             _validate_meas_map(acquire_instruction_map, run_config.meas_map)
206         for (time, _), instrs in acquire_instruction_map.items():
207             qobj_instructions.append(
208                 instruction_converter.convert_bundled_acquires(
209                     time,
210                     instrs
211                 ),
212             )
213 
214     return qobj_instructions, max_memory_slot
215 
216 
217 def _validate_meas_map(instruction_map: Dict[Tuple[int, instructions.Acquire],
218                                              List[instructions.Acquire]],
219                        meas_map: List[List[int]]) -> None:
220     """Validate all qubits tied in ``meas_map`` are to be acquired.
221 
222     Args:
223         instruction_map: A dictionary grouping Acquire instructions according to their start time
224                          and duration.
225         meas_map: List of groups of qubits that must be acquired together.
226 
227     Raises:
228         QiskitError: If the instructions do not satisfy the measurement map.
229     """
230     meas_map_sets = [set(m) for m in meas_map]
231 
232     # Check each acquisition time individually
233     for _, instrs in instruction_map.items():
234         measured_qubits = set()
235         for inst in instrs:
236             measured_qubits.add(inst.channel.index)
237 
238         for meas_set in meas_map_sets:
239             intersection = measured_qubits.intersection(meas_set)
240             if intersection and intersection != meas_set:
241                 raise QiskitError('Qubits to be acquired: {0} do not satisfy required qubits '
242                                   'in measurement map: {1}'.format(measured_qubits, meas_set))
243 
244 
245 def _assemble_config(lo_converter: converters.LoConfigConverter,
246                      experiment_config: Dict[str, Any],
247                      run_config: RunConfig) -> qobj.PulseQobjConfig:
248     """Assembles the QobjConfiguration from experimental config and runtime config.
249 
250     Args:
251         lo_converter: The configured frequency converter and validator.
252         experiment_config: Schedules to assemble.
253         run_config: Configuration of the runtime environment.
254 
255     Returns:
256         The assembled PulseQobjConfig.
257     """
258     qobj_config = run_config.to_dict()
259     qobj_config.update(experiment_config)
260 
261     # Run config not needed in qobj config
262     qobj_config.pop('meas_map', None)
263     qobj_config.pop('qubit_lo_range', None)
264     qobj_config.pop('meas_lo_range', None)
265 
266     # convert enums to serialized values
267     meas_return = qobj_config.get('meas_return', 'avg')
268     if isinstance(meas_return, qobj_utils.MeasReturnType):
269         qobj_config['meas_return'] = meas_return.value
270 
271     meas_level = qobj_config.get('meas_level', 2)
272     if isinstance(meas_level, qobj_utils.MeasLevel):
273         qobj_config['meas_level'] = meas_level.value
274 
275     # convert lo frequencies to Hz
276     qobj_config['qubit_lo_freq'] = [freq / 1e9 for freq in qobj_config['qubit_lo_freq']]
277     qobj_config['meas_lo_freq'] = [freq / 1e9 for freq in qobj_config['meas_lo_freq']]
278 
279     # frequency sweep config
280     schedule_los = qobj_config.pop('schedule_los', [])
281     if len(schedule_los) == 1:
282         lo_dict = schedule_los[0]
283         q_los = lo_converter.get_qubit_los(lo_dict)
284         # Hz -> GHz
285         if q_los:
286             qobj_config['qubit_lo_freq'] = [freq / 1e9 for freq in q_los]
287         m_los = lo_converter.get_meas_los(lo_dict)
288         if m_los:
289             qobj_config['meas_lo_freq'] = [freq / 1e9 for freq in m_los]
290 
291     return qobj.PulseQobjConfig(**qobj_config)
292
```
--- 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/assembler/assemble_schedules.py b/qiskit/assembler/assemble_schedules.py
--- a/qiskit/assembler/assemble_schedules.py
+++ b/qiskit/assembler/assemble_schedules.py
@@ -93,6 +93,10 @@
                                     converters.InstructionToQobjConverter)
     instruction_converter = instruction_converter(qobj.PulseQobjInstruction,
                                                   **run_config.to_dict())
+
+    schedules = [
+        sched if isinstance(sched, pulse.Schedule) else pulse.Schedule(sched) for sched in schedules
+    ]
     compressed_schedules = transforms.compress_pulses(schedules)
 
     user_pulselib = {}

{"golden_diff": "diff --git a/qiskit/assembler/assemble_schedules.py b/qiskit/assembler/assemble_schedules.py\n--- a/qiskit/assembler/assemble_schedules.py\n+++ b/qiskit/assembler/assemble_schedules.py\n@@ -93,6 +93,10 @@\n                                     converters.InstructionToQobjConverter)\n     instruction_converter = instruction_converter(qobj.PulseQobjInstruction,\n                                                   **run_config.to_dict())\n+\n+    schedules = [\n+        sched if isinstance(sched, pulse.Schedule) else pulse.Schedule(sched) for sched in schedules\n+    ]\n     compressed_schedules = transforms.compress_pulses(schedules)\n \n     user_pulselib = {}\n", "issue": "Executing a schedule with one instruction raises an error\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\n- **Qiskit Terra version**:\r\n- **Python version**:\r\n- **Operating system**:\r\n\r\n### What is the current behavior?\r\n\r\nIf I make a schedule with only one instruction:\r\n```\r\nsched = pulse.Acquire(20, pulse.AcquireChannel(0), pulse.MemorySlot(0))\r\n```\r\nthen when I `execute` it, it's type is `Instruction` and not `Schedule`, so `execute` wrongly sends it through the `transpiler`, thinking it's a `QuantumCircuit`. Since the transpiler is expecting a circuit, we end up with an attribute error as it tries to access `circuit.qubits`, which isn't a Schedule property.\r\n\r\n\r\n### Steps to reproduce the problem\r\n\r\n\r\n\r\n### What is the expected behavior?\r\n\r\n\r\n\r\n### Suggested solutions\r\n\r\nThe easiest fix is to replace `isinstance(experiments, Schedule)` with `isinstance(experiments, (Schedule, pulse.Instruction)`, or perhaps more correctly: `isinstance(experiments, ScheduleComponent)`. Would have to add tests and make sure there aren't other consequences of taking an `Instruction` as input. \r\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\n# This code is part of Qiskit.\n#\n# (C) Copyright IBM 2017, 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\"\"\"Assemble function for converting a list of circuits into a qobj.\"\"\"\nfrom collections import defaultdict\nfrom typing import Any, Dict, List, Tuple\nimport hashlib\n\nfrom qiskit import qobj, pulse\nfrom qiskit.assembler.run_config import RunConfig\nfrom qiskit.exceptions import QiskitError\nfrom qiskit.pulse import instructions, transforms, library\nfrom qiskit.qobj import utils as qobj_utils, converters\nfrom qiskit.qobj.converters.pulse_instruction import ParametricPulseShapes\n\n\ndef assemble_schedules(schedules: List[pulse.Schedule],\n                       qobj_id: int,\n                       qobj_header: qobj.QobjHeader,\n                       run_config: RunConfig) -> qobj.PulseQobj:\n    \"\"\"Assembles a list of schedules into a qobj that can be run on the backend.\n\n    Args:\n        schedules: Schedules to assemble.\n        qobj_id: Identifier for the generated qobj.\n        qobj_header: Header to pass to the results.\n        run_config: Configuration of the runtime environment.\n\n    Returns:\n        The Qobj to be run on the backends.\n\n    Raises:\n        QiskitError: when frequency settings are not supplied.\n    \"\"\"\n    if not hasattr(run_config, 'qubit_lo_freq'):\n        raise QiskitError('qubit_lo_freq must be supplied.')\n    if not hasattr(run_config, 'meas_lo_freq'):\n        raise QiskitError('meas_lo_freq must be supplied.')\n\n    lo_converter = converters.LoConfigConverter(qobj.PulseQobjExperimentConfig,\n                                                **run_config.to_dict())\n    experiments, experiment_config = _assemble_experiments(schedules,\n                                                           lo_converter,\n                                                           run_config)\n    qobj_config = _assemble_config(lo_converter, experiment_config, run_config)\n\n    return qobj.PulseQobj(experiments=experiments,\n                          qobj_id=qobj_id,\n                          header=qobj_header,\n                          config=qobj_config)\n\n\ndef _assemble_experiments(\n        schedules: List[pulse.Schedule],\n        lo_converter: converters.LoConfigConverter,\n        run_config: RunConfig\n) -> Tuple[List[qobj.PulseQobjExperiment], Dict[str, Any]]:\n    \"\"\"Assembles a list of schedules into PulseQobjExperiments, and returns related metadata that\n    will be assembled into the Qobj configuration.\n\n    Args:\n        schedules: Schedules to assemble.\n        lo_converter: The configured frequency converter and validator.\n        run_config: Configuration of the runtime environment.\n\n    Returns:\n        The list of assembled experiments, and the dictionary of related experiment config.\n\n    Raises:\n        QiskitError: when frequency settings are not compatible with the experiments.\n    \"\"\"\n    freq_configs = [lo_converter(lo_dict) for lo_dict in getattr(run_config, 'schedule_los', [])]\n\n    if len(schedules) > 1 and len(freq_configs) not in [0, 1, len(schedules)]:\n        raise QiskitError('Invalid frequency setting is specified. If the frequency is specified, '\n                          'it should be configured the same for all schedules, configured for each '\n                          'schedule, or a list of frequencies should be provided for a single '\n                          'frequency sweep schedule.')\n\n    instruction_converter = getattr(run_config,\n                                    'instruction_converter',\n                                    converters.InstructionToQobjConverter)\n    instruction_converter = instruction_converter(qobj.PulseQobjInstruction,\n                                                  **run_config.to_dict())\n    compressed_schedules = transforms.compress_pulses(schedules)\n\n    user_pulselib = {}\n    experiments = []\n    for idx, schedule in enumerate(compressed_schedules):\n        qobj_instructions, max_memory_slot = _assemble_instructions(\n            schedule,\n            instruction_converter,\n            run_config,\n            user_pulselib)\n\n        # TODO: add other experimental header items (see circuit assembler)\n        qobj_experiment_header = qobj.QobjExperimentHeader(\n            memory_slots=max_memory_slot + 1,  # Memory slots are 0 indexed\n            name=schedule.name or 'Experiment-%d' % idx)\n\n        experiment = qobj.PulseQobjExperiment(\n            header=qobj_experiment_header,\n            instructions=qobj_instructions)\n        if freq_configs:\n            # This handles the cases where one frequency setting applies to all experiments and\n            # where each experiment has a different frequency\n            freq_idx = idx if len(freq_configs) != 1 else 0\n            experiment.config = freq_configs[freq_idx]\n\n        experiments.append(experiment)\n\n    # Frequency sweep\n    if freq_configs and len(experiments) == 1:\n        experiment = experiments[0]\n        experiments = []\n        for freq_config in freq_configs:\n            experiments.append(qobj.PulseQobjExperiment(\n                header=experiment.header,\n                instructions=experiment.instructions,\n                config=freq_config))\n\n    # Top level Qobj configuration\n    experiment_config = {\n        'pulse_library': [qobj.PulseLibraryItem(name=name, samples=samples)\n                          for name, samples in user_pulselib.items()],\n        'memory_slots': max([exp.header.memory_slots for exp in experiments])\n    }\n\n    return experiments, experiment_config\n\n\ndef _assemble_instructions(\n        schedule: pulse.Schedule,\n        instruction_converter: converters.InstructionToQobjConverter,\n        run_config: RunConfig,\n        user_pulselib: Dict[str, List[complex]]\n) -> Tuple[List[qobj.PulseQobjInstruction], int]:\n    \"\"\"Assembles the instructions in a schedule into a list of PulseQobjInstructions and returns\n    related metadata that will be assembled into the Qobj configuration. Lookup table for\n    pulses defined in all experiments are registered in ``user_pulselib``. This object should be\n    mutable python dictionary so that items are properly updated after each instruction assemble.\n    The dictionary is not returned to avoid redundancy.\n\n    Args:\n        schedule: Schedule to assemble.\n        instruction_converter: A converter instance which can convert PulseInstructions to\n                               PulseQobjInstructions.\n        run_config: Configuration of the runtime environment.\n        user_pulselib: User pulse library from previous schedule.\n\n    Returns:\n        A list of converted instructions, the user pulse library dictionary (from pulse name to\n        pulse samples), and the maximum number of readout memory slots used by this Schedule.\n    \"\"\"\n    max_memory_slot = 0\n    qobj_instructions = []\n\n    acquire_instruction_map = defaultdict(list)\n    for time, instruction in schedule.instructions:\n\n        if (isinstance(instruction, instructions.Play) and\n                isinstance(instruction.pulse, library.ParametricPulse)):\n            pulse_shape = ParametricPulseShapes(type(instruction.pulse)).name\n            if pulse_shape not in run_config.parametric_pulses:\n                instruction = instructions.Play(instruction.pulse.get_sample_pulse(),\n                                                instruction.channel,\n                                                name=instruction.name)\n\n        if (isinstance(instruction, instructions.Play) and\n                isinstance(instruction.pulse, library.Waveform)):\n            name = hashlib.sha256(instruction.pulse.samples).hexdigest()\n            instruction = instructions.Play(\n                library.Waveform(name=name, samples=instruction.pulse.samples),\n                channel=instruction.channel,\n                name=name)\n            user_pulselib[name] = instruction.pulse.samples\n\n        if isinstance(instruction, instructions.Acquire):\n            if instruction.mem_slot:\n                max_memory_slot = max(max_memory_slot, instruction.mem_slot.index)\n            # Acquires have a single AcquireChannel per inst, but we have to bundle them\n            # together into the Qobj as one instruction with many channels\n            acquire_instruction_map[(time, instruction.duration)].append(instruction)\n            continue\n\n        if isinstance(instruction, (instructions.Delay, instructions.Directive)):\n            # delay instructions are ignored as timing is explicit within qobj\n            continue\n\n        qobj_instructions.append(instruction_converter(time, instruction))\n\n    if acquire_instruction_map:\n        if hasattr(run_config, 'meas_map'):\n            _validate_meas_map(acquire_instruction_map, run_config.meas_map)\n        for (time, _), instrs in acquire_instruction_map.items():\n            qobj_instructions.append(\n                instruction_converter.convert_bundled_acquires(\n                    time,\n                    instrs\n                ),\n            )\n\n    return qobj_instructions, max_memory_slot\n\n\ndef _validate_meas_map(instruction_map: Dict[Tuple[int, instructions.Acquire],\n                                             List[instructions.Acquire]],\n                       meas_map: List[List[int]]) -> None:\n    \"\"\"Validate all qubits tied in ``meas_map`` are to be acquired.\n\n    Args:\n        instruction_map: A dictionary grouping Acquire instructions according to their start time\n                         and duration.\n        meas_map: List of groups of qubits that must be acquired together.\n\n    Raises:\n        QiskitError: If the instructions do not satisfy the measurement map.\n    \"\"\"\n    meas_map_sets = [set(m) for m in meas_map]\n\n    # Check each acquisition time individually\n    for _, instrs in instruction_map.items():\n        measured_qubits = set()\n        for inst in instrs:\n            measured_qubits.add(inst.channel.index)\n\n        for meas_set in meas_map_sets:\n            intersection = measured_qubits.intersection(meas_set)\n            if intersection and intersection != meas_set:\n                raise QiskitError('Qubits to be acquired: {0} do not satisfy required qubits '\n                                  'in measurement map: {1}'.format(measured_qubits, meas_set))\n\n\ndef _assemble_config(lo_converter: converters.LoConfigConverter,\n                     experiment_config: Dict[str, Any],\n                     run_config: RunConfig) -> qobj.PulseQobjConfig:\n    \"\"\"Assembles the QobjConfiguration from experimental config and runtime config.\n\n    Args:\n        lo_converter: The configured frequency converter and validator.\n        experiment_config: Schedules to assemble.\n        run_config: Configuration of the runtime environment.\n\n    Returns:\n        The assembled PulseQobjConfig.\n    \"\"\"\n    qobj_config = run_config.to_dict()\n    qobj_config.update(experiment_config)\n\n    # Run config not needed in qobj config\n    qobj_config.pop('meas_map', None)\n    qobj_config.pop('qubit_lo_range', None)\n    qobj_config.pop('meas_lo_range', None)\n\n    # convert enums to serialized values\n    meas_return = qobj_config.get('meas_return', 'avg')\n    if isinstance(meas_return, qobj_utils.MeasReturnType):\n        qobj_config['meas_return'] = meas_return.value\n\n    meas_level = qobj_config.get('meas_level', 2)\n    if isinstance(meas_level, qobj_utils.MeasLevel):\n        qobj_config['meas_level'] = meas_level.value\n\n    # convert lo frequencies to Hz\n    qobj_config['qubit_lo_freq'] = [freq / 1e9 for freq in qobj_config['qubit_lo_freq']]\n    qobj_config['meas_lo_freq'] = [freq / 1e9 for freq in qobj_config['meas_lo_freq']]\n\n    # frequency sweep config\n    schedule_los = qobj_config.pop('schedule_los', [])\n    if len(schedule_los) == 1:\n        lo_dict = schedule_los[0]\n        q_los = lo_converter.get_qubit_los(lo_dict)\n        # Hz -> GHz\n        if q_los:\n            qobj_config['qubit_lo_freq'] = [freq / 1e9 for freq in q_los]\n        m_los = lo_converter.get_meas_los(lo_dict)\n        if m_los:\n            qobj_config['meas_lo_freq'] = [freq / 1e9 for freq in m_los]\n\n    return qobj.PulseQobjConfig(**qobj_config)\n", "path": "qiskit/assembler/assemble_schedules.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\n# This code is part of Qiskit.\n#\n# (C) Copyright IBM 2017, 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\"\"\"Assemble function for converting a list of circuits into a qobj.\"\"\"\nfrom collections import defaultdict\nfrom typing import Any, Dict, List, Tuple\nimport hashlib\n\nfrom qiskit import qobj, pulse\nfrom qiskit.assembler.run_config import RunConfig\nfrom qiskit.exceptions import QiskitError\nfrom qiskit.pulse import instructions, transforms, library\nfrom qiskit.qobj import utils as qobj_utils, converters\nfrom qiskit.qobj.converters.pulse_instruction import ParametricPulseShapes\n\n\ndef assemble_schedules(schedules: List[pulse.Schedule],\n                       qobj_id: int,\n                       qobj_header: qobj.QobjHeader,\n                       run_config: RunConfig) -> qobj.PulseQobj:\n    \"\"\"Assembles a list of schedules into a qobj that can be run on the backend.\n\n    Args:\n        schedules: Schedules to assemble.\n        qobj_id: Identifier for the generated qobj.\n        qobj_header: Header to pass to the results.\n        run_config: Configuration of the runtime environment.\n\n    Returns:\n        The Qobj to be run on the backends.\n\n    Raises:\n        QiskitError: when frequency settings are not supplied.\n    \"\"\"\n    if not hasattr(run_config, 'qubit_lo_freq'):\n        raise QiskitError('qubit_lo_freq must be supplied.')\n    if not hasattr(run_config, 'meas_lo_freq'):\n        raise QiskitError('meas_lo_freq must be supplied.')\n\n    lo_converter = converters.LoConfigConverter(qobj.PulseQobjExperimentConfig,\n                                                **run_config.to_dict())\n    experiments, experiment_config = _assemble_experiments(schedules,\n                                                           lo_converter,\n                                                           run_config)\n    qobj_config = _assemble_config(lo_converter, experiment_config, run_config)\n\n    return qobj.PulseQobj(experiments=experiments,\n                          qobj_id=qobj_id,\n                          header=qobj_header,\n                          config=qobj_config)\n\n\ndef _assemble_experiments(\n        schedules: List[pulse.Schedule],\n        lo_converter: converters.LoConfigConverter,\n        run_config: RunConfig\n) -> Tuple[List[qobj.PulseQobjExperiment], Dict[str, Any]]:\n    \"\"\"Assembles a list of schedules into PulseQobjExperiments, and returns related metadata that\n    will be assembled into the Qobj configuration.\n\n    Args:\n        schedules: Schedules to assemble.\n        lo_converter: The configured frequency converter and validator.\n        run_config: Configuration of the runtime environment.\n\n    Returns:\n        The list of assembled experiments, and the dictionary of related experiment config.\n\n    Raises:\n        QiskitError: when frequency settings are not compatible with the experiments.\n    \"\"\"\n    freq_configs = [lo_converter(lo_dict) for lo_dict in getattr(run_config, 'schedule_los', [])]\n\n    if len(schedules) > 1 and len(freq_configs) not in [0, 1, len(schedules)]:\n        raise QiskitError('Invalid frequency setting is specified. If the frequency is specified, '\n                          'it should be configured the same for all schedules, configured for each '\n                          'schedule, or a list of frequencies should be provided for a single '\n                          'frequency sweep schedule.')\n\n    instruction_converter = getattr(run_config,\n                                    'instruction_converter',\n                                    converters.InstructionToQobjConverter)\n    instruction_converter = instruction_converter(qobj.PulseQobjInstruction,\n                                                  **run_config.to_dict())\n\n    schedules = [\n        sched if isinstance(sched, pulse.Schedule) else pulse.Schedule(sched) for sched in schedules\n    ]\n    compressed_schedules = transforms.compress_pulses(schedules)\n\n    user_pulselib = {}\n    experiments = []\n    for idx, schedule in enumerate(compressed_schedules):\n        qobj_instructions, max_memory_slot = _assemble_instructions(\n            schedule,\n            instruction_converter,\n            run_config,\n            user_pulselib)\n\n        # TODO: add other experimental header items (see circuit assembler)\n        qobj_experiment_header = qobj.QobjExperimentHeader(\n            memory_slots=max_memory_slot + 1,  # Memory slots are 0 indexed\n            name=schedule.name or 'Experiment-%d' % idx)\n\n        experiment = qobj.PulseQobjExperiment(\n            header=qobj_experiment_header,\n            instructions=qobj_instructions)\n        if freq_configs:\n            # This handles the cases where one frequency setting applies to all experiments and\n            # where each experiment has a different frequency\n            freq_idx = idx if len(freq_configs) != 1 else 0\n            experiment.config = freq_configs[freq_idx]\n\n        experiments.append(experiment)\n\n    # Frequency sweep\n    if freq_configs and len(experiments) == 1:\n        experiment = experiments[0]\n        experiments = []\n        for freq_config in freq_configs:\n            experiments.append(qobj.PulseQobjExperiment(\n                header=experiment.header,\n                instructions=experiment.instructions,\n                config=freq_config))\n\n    # Top level Qobj configuration\n    experiment_config = {\n        'pulse_library': [qobj.PulseLibraryItem(name=name, samples=samples)\n                          for name, samples in user_pulselib.items()],\n        'memory_slots': max([exp.header.memory_slots for exp in experiments])\n    }\n\n    return experiments, experiment_config\n\n\ndef _assemble_instructions(\n        schedule: pulse.Schedule,\n        instruction_converter: converters.InstructionToQobjConverter,\n        run_config: RunConfig,\n        user_pulselib: Dict[str, List[complex]]\n) -> Tuple[List[qobj.PulseQobjInstruction], int]:\n    \"\"\"Assembles the instructions in a schedule into a list of PulseQobjInstructions and returns\n    related metadata that will be assembled into the Qobj configuration. Lookup table for\n    pulses defined in all experiments are registered in ``user_pulselib``. This object should be\n    mutable python dictionary so that items are properly updated after each instruction assemble.\n    The dictionary is not returned to avoid redundancy.\n\n    Args:\n        schedule: Schedule to assemble.\n        instruction_converter: A converter instance which can convert PulseInstructions to\n                               PulseQobjInstructions.\n        run_config: Configuration of the runtime environment.\n        user_pulselib: User pulse library from previous schedule.\n\n    Returns:\n        A list of converted instructions, the user pulse library dictionary (from pulse name to\n        pulse samples), and the maximum number of readout memory slots used by this Schedule.\n    \"\"\"\n    max_memory_slot = 0\n    qobj_instructions = []\n\n    acquire_instruction_map = defaultdict(list)\n    for time, instruction in schedule.instructions:\n\n        if (isinstance(instruction, instructions.Play) and\n                isinstance(instruction.pulse, library.ParametricPulse)):\n            pulse_shape = ParametricPulseShapes(type(instruction.pulse)).name\n            if pulse_shape not in run_config.parametric_pulses:\n                instruction = instructions.Play(instruction.pulse.get_sample_pulse(),\n                                                instruction.channel,\n                                                name=instruction.name)\n\n        if (isinstance(instruction, instructions.Play) and\n                isinstance(instruction.pulse, library.Waveform)):\n            name = hashlib.sha256(instruction.pulse.samples).hexdigest()\n            instruction = instructions.Play(\n                library.Waveform(name=name, samples=instruction.pulse.samples),\n                channel=instruction.channel,\n                name=name)\n            user_pulselib[name] = instruction.pulse.samples\n\n        if isinstance(instruction, instructions.Acquire):\n            if instruction.mem_slot:\n                max_memory_slot = max(max_memory_slot, instruction.mem_slot.index)\n            # Acquires have a single AcquireChannel per inst, but we have to bundle them\n            # together into the Qobj as one instruction with many channels\n            acquire_instruction_map[(time, instruction.duration)].append(instruction)\n            continue\n\n        if isinstance(instruction, (instructions.Delay, instructions.Directive)):\n            # delay instructions are ignored as timing is explicit within qobj\n            continue\n\n        qobj_instructions.append(instruction_converter(time, instruction))\n\n    if acquire_instruction_map:\n        if hasattr(run_config, 'meas_map'):\n            _validate_meas_map(acquire_instruction_map, run_config.meas_map)\n        for (time, _), instrs in acquire_instruction_map.items():\n            qobj_instructions.append(\n                instruction_converter.convert_bundled_acquires(\n                    time,\n                    instrs\n                ),\n            )\n\n    return qobj_instructions, max_memory_slot\n\n\ndef _validate_meas_map(instruction_map: Dict[Tuple[int, instructions.Acquire],\n                                             List[instructions.Acquire]],\n                       meas_map: List[List[int]]) -> None:\n    \"\"\"Validate all qubits tied in ``meas_map`` are to be acquired.\n\n    Args:\n        instruction_map: A dictionary grouping Acquire instructions according to their start time\n                         and duration.\n        meas_map: List of groups of qubits that must be acquired together.\n\n    Raises:\n        QiskitError: If the instructions do not satisfy the measurement map.\n    \"\"\"\n    meas_map_sets = [set(m) for m in meas_map]\n\n    # Check each acquisition time individually\n    for _, instrs in instruction_map.items():\n        measured_qubits = set()\n        for inst in instrs:\n            measured_qubits.add(inst.channel.index)\n\n        for meas_set in meas_map_sets:\n            intersection = measured_qubits.intersection(meas_set)\n            if intersection and intersection != meas_set:\n                raise QiskitError('Qubits to be acquired: {0} do not satisfy required qubits '\n                                  'in measurement map: {1}'.format(measured_qubits, meas_set))\n\n\ndef _assemble_config(lo_converter: converters.LoConfigConverter,\n                     experiment_config: Dict[str, Any],\n                     run_config: RunConfig) -> qobj.PulseQobjConfig:\n    \"\"\"Assembles the QobjConfiguration from experimental config and runtime config.\n\n    Args:\n        lo_converter: The configured frequency converter and validator.\n        experiment_config: Schedules to assemble.\n        run_config: Configuration of the runtime environment.\n\n    Returns:\n        The assembled PulseQobjConfig.\n    \"\"\"\n    qobj_config = run_config.to_dict()\n    qobj_config.update(experiment_config)\n\n    # Run config not needed in qobj config\n    qobj_config.pop('meas_map', None)\n    qobj_config.pop('qubit_lo_range', None)\n    qobj_config.pop('meas_lo_range', None)\n\n    # convert enums to serialized values\n    meas_return = qobj_config.get('meas_return', 'avg')\n    if isinstance(meas_return, qobj_utils.MeasReturnType):\n        qobj_config['meas_return'] = meas_return.value\n\n    meas_level = qobj_config.get('meas_level', 2)\n    if isinstance(meas_level, qobj_utils.MeasLevel):\n        qobj_config['meas_level'] = meas_level.value\n\n    # convert lo frequencies to Hz\n    qobj_config['qubit_lo_freq'] = [freq / 1e9 for freq in qobj_config['qubit_lo_freq']]\n    qobj_config['meas_lo_freq'] = [freq / 1e9 for freq in qobj_config['meas_lo_freq']]\n\n    # frequency sweep config\n    schedule_los = qobj_config.pop('schedule_los', [])\n    if len(schedule_los) == 1:\n        lo_dict = schedule_los[0]\n        q_los = lo_converter.get_qubit_los(lo_dict)\n        # Hz -> GHz\n        if q_los:\n            qobj_config['qubit_lo_freq'] = [freq / 1e9 for freq in q_los]\n        m_los = lo_converter.get_meas_los(lo_dict)\n        if m_los:\n            qobj_config['meas_lo_freq'] = [freq / 1e9 for freq in m_los]\n\n    return qobj.PulseQobjConfig(**qobj_config)\n", "path": "qiskit/assembler/assemble_schedules.py"}]}