From efd1aa837a380ba6656760dc3a6552dde2c767b5 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 23 Aug 2019 15:03:05 +0200 Subject: [PATCH 01/53] TranspileConfig defaults --- qiskit/transpiler/transpile_config.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/qiskit/transpiler/transpile_config.py b/qiskit/transpiler/transpile_config.py index 82d6dc4ab2c3..7910342c2eb0 100644 --- a/qiskit/transpiler/transpile_config.py +++ b/qiskit/transpiler/transpile_config.py @@ -30,6 +30,9 @@ class TranspileConfig(BaseModel): optimization level. 0 means no transformation on the circuit. Higher levels may produce more optimized circuits, but may take longer. """ - def __init__(self, optimization_level, **kwargs): + def __init__(self, optimization_level=0, **kwargs): self.optimization_level = optimization_level super().__init__(**kwargs) + + def __getattr__(self, name): + return None From 4527a17a6b93f4a49cee8d339a23727b2bac1dc8 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 23 Aug 2019 15:07:20 +0200 Subject: [PATCH 02/53] defatuls for TranspileConfig --- CHANGELOG.md | 4 ++++ qiskit/transpiler/transpile_config.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 541b49574573..123d109578a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,10 @@ The format is based on [Keep a Changelog]. ## [0.9.0] - 2019-08-22 +### Changed + +- The `TranspileConfig` was extended to have `None` defaults for + ### Deprecated - The gates `U` and `CX` are being deprecated in favor of `u3` and diff --git a/qiskit/transpiler/transpile_config.py b/qiskit/transpiler/transpile_config.py index 7910342c2eb0..107476cb5eb0 100644 --- a/qiskit/transpiler/transpile_config.py +++ b/qiskit/transpiler/transpile_config.py @@ -30,7 +30,7 @@ class TranspileConfig(BaseModel): optimization level. 0 means no transformation on the circuit. Higher levels may produce more optimized circuits, but may take longer. """ - def __init__(self, optimization_level=0, **kwargs): + def __init__(self, optimization_level=None, **kwargs): self.optimization_level = optimization_level super().__init__(**kwargs) From e95a102ff540e4a389812cd42838d9e24ea77c2a Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Thu, 5 Sep 2019 15:00:02 -0400 Subject: [PATCH 03/53] explicit kwargs --- qiskit/transpiler/transpile_config.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/qiskit/transpiler/transpile_config.py b/qiskit/transpiler/transpile_config.py index 107476cb5eb0..6dfab5a84092 100644 --- a/qiskit/transpiler/transpile_config.py +++ b/qiskit/transpiler/transpile_config.py @@ -30,9 +30,25 @@ class TranspileConfig(BaseModel): optimization level. 0 means no transformation on the circuit. Higher levels may produce more optimized circuits, but may take longer. """ - def __init__(self, optimization_level=None, **kwargs): - self.optimization_level = optimization_level - super().__init__(**kwargs) + def __init__(self, + initial_layout=None, + basis_gates=None, + coupling_map=None, + output_name=None, + backend_properties=None, + optimization_level=None, + callback=None, + seed_transpiler=None, + pass_manager=None): + super().__init__(initial_layout=initial_layout, + basis_gates=basis_gates, + coupling_map=coupling_map, + output_name=output_name, + backend_properties=backend_properties, + optimization_level=optimization_level, + callback=callback, + seed_transpiler=seed_transpiler, + pass_manager=pass_manager) def __getattr__(self, name): return None From 75ca2cdab8d1f23245a4c1d69ebb210e06e4100b Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Thu, 5 Sep 2019 15:06:05 -0400 Subject: [PATCH 04/53] remove __getattr__ None --- qiskit/transpiler/transpile_config.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/qiskit/transpiler/transpile_config.py b/qiskit/transpiler/transpile_config.py index 6dfab5a84092..f49382fb25aa 100644 --- a/qiskit/transpiler/transpile_config.py +++ b/qiskit/transpiler/transpile_config.py @@ -49,6 +49,3 @@ def __init__(self, callback=callback, seed_transpiler=seed_transpiler, pass_manager=pass_manager) - - def __getattr__(self, name): - return None From ca3e1d20a79ffa5dbfeb91ce61393811f77ef5ab Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Sun, 8 Sep 2019 16:05:28 -0400 Subject: [PATCH 05/53] move cm checks to _parse_coupling_map --- qiskit/compiler/transpile.py | 42 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index aa14d3ffeaa0..6e87f26022b1 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -184,18 +184,7 @@ def callback_func(**kwargs): backend_properties, initial_layout, seed_transpiler, optimization_level, pass_manager, callback, output_name) - # Check circuit width against number of qubits in coupling_map(s) - coupling_maps_list = list(config.coupling_map for config in transpile_configs) - for circuit, parsed_coupling_map in zip(circuits, coupling_maps_list): - # If coupling_map is not None - if isinstance(parsed_coupling_map, CouplingMap): - n_qubits = len(circuit.qubits) - max_qubits = parsed_coupling_map.size() - if n_qubits > max_qubits: - raise TranspilerError('Number of qubits ({}) '.format(n_qubits) + - 'in {} '.format(circuit.name) + - 'is greater than maximum ({}) '.format(max_qubits) + - 'in the coupling_map') + # Transpile circuits in parallel circuits = parallel_map(_transpile_circuit, list(zip(circuits, transpile_configs))) @@ -243,7 +232,7 @@ def _parse_transpile_args(circuits, backend, basis_gates = _parse_basis_gates(basis_gates, backend, circuits) - coupling_map = _parse_coupling_map(coupling_map, backend, num_circuits) + coupling_map = _parse_coupling_map(coupling_map, backend, circuits) backend_properties = _parse_backend_properties(backend_properties, backend, num_circuits) @@ -301,18 +290,29 @@ def _parse_basis_gates(basis_gates, backend, circuits): return basis_gates -def _parse_coupling_map(coupling_map, backend, num_circuits): +def _parse_coupling_map(coupling_map, backend, circuits): + num_circuits = len(circuits) # try getting coupling_map from user, else backend if coupling_map is None: if getattr(backend, 'configuration', None): coupling_map = getattr(backend.configuration(), 'coupling_map', None) - # coupling_map could be None, or a list of lists, e.g. [[0, 1], [2, 1]] - if coupling_map is None or isinstance(coupling_map, CouplingMap): - coupling_map = [coupling_map] * num_circuits - elif isinstance(coupling_map, list) and all(isinstance(i, list) and len(i) == 2 - for i in coupling_map): - coupling_map = [coupling_map] * num_circuits - coupling_map = [CouplingMap(cm) if isinstance(cm, list) else cm for cm in coupling_map] + + coupling_map = [coupling_map] * num_circuits + + for index, parsed_coupling_map in enumerate(coupling_map): + if isinstance(parsed_coupling_map, list): + parsed_coupling_map = CouplingMap(parsed_coupling_map) + # If coupling_map is not None + if isinstance(parsed_coupling_map, CouplingMap): + n_qubits = len(circuits[index].qubits) + max_qubits = parsed_coupling_map.size() + if n_qubits > max_qubits: + raise TranspilerError('Number of qubits ({}) '.format(n_qubits) + + 'in {} '.format(circuits[index].name) + + 'is greater than maximum ({}) '.format(max_qubits) + + 'in the coupling_map') + coupling_map[index] = parsed_coupling_map + return coupling_map From ba39d874e88e5510b587fb07e1ef8a645fa5b0c1 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Sun, 8 Sep 2019 16:27:56 -0400 Subject: [PATCH 06/53] transpile_config as a dict --- qiskit/compiler/transpile.py | 19 ++++++++++--------- .../transpiler/preset_passmanagers/level0.py | 8 ++++---- .../transpiler/preset_passmanagers/level1.py | 8 ++++---- .../transpiler/preset_passmanagers/level2.py | 10 +++++----- .../transpiler/preset_passmanagers/level3.py | 10 +++++----- qiskit/transpiler/transpile_circuit.py | 12 ++++++------ 6 files changed, 34 insertions(+), 33 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 6e87f26022b1..035591809c34 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -250,15 +250,16 @@ def _parse_transpile_args(circuits, backend, for args in zip(basis_gates, coupling_map, backend_properties, initial_layout, seed_transpiler, optimization_level, pass_manager, output_name): - transpile_config = TranspileConfig(basis_gates=args[0], - coupling_map=args[1], - backend_properties=args[2], - initial_layout=args[3], - seed_transpiler=args[4], - optimization_level=args[5], - pass_manager=args[6], - callback=callback, - output_name=args[7]) + # TranspileConfig + transpile_config = {'basis_gates': args[0], + 'coupling_map': args[1], + 'backend_properties': args[2], + 'initial_layout': args[3], + 'seed_transpiler': args[4], + 'optimization_level': args[5], + 'pass_manager': args[6], + 'callback': callback, + 'output_name': args[7]} transpile_configs.append(transpile_config) return transpile_configs diff --git a/qiskit/transpiler/preset_passmanagers/level0.py b/qiskit/transpiler/preset_passmanagers/level0.py index 0135d88bc45c..98cc61034f88 100644 --- a/qiskit/transpiler/preset_passmanagers/level0.py +++ b/qiskit/transpiler/preset_passmanagers/level0.py @@ -53,10 +53,10 @@ def level_0_pass_manager(transpile_config): Returns: PassManager: a level 0 pass manager. """ - basis_gates = transpile_config.basis_gates - coupling_map = transpile_config.coupling_map - initial_layout = transpile_config.initial_layout - seed_transpiler = transpile_config.seed_transpiler + basis_gates = transpile_config['basis_gates'] + coupling_map = transpile_config['coupling_map'] + initial_layout = transpile_config['initial_layout'] + seed_transpiler = transpile_config['seed_transpiler'] # 1. Use trivial layout if no layout given _given_layout = SetLayout(initial_layout) diff --git a/qiskit/transpiler/preset_passmanagers/level1.py b/qiskit/transpiler/preset_passmanagers/level1.py index d9426b49e1d3..6c1f7e7e4df7 100644 --- a/qiskit/transpiler/preset_passmanagers/level1.py +++ b/qiskit/transpiler/preset_passmanagers/level1.py @@ -60,10 +60,10 @@ def level_1_pass_manager(transpile_config): Returns: PassManager: a level 1 pass manager. """ - basis_gates = transpile_config.basis_gates - coupling_map = transpile_config.coupling_map - initial_layout = transpile_config.initial_layout - seed_transpiler = transpile_config.seed_transpiler + basis_gates = transpile_config['basis_gates'] + coupling_map = transpile_config['coupling_map'] + initial_layout = transpile_config['initial_layout'] + seed_transpiler = transpile_config['seed_transpiler'] # 1. Use trivial layout if no layout given _given_layout = SetLayout(initial_layout) diff --git a/qiskit/transpiler/preset_passmanagers/level2.py b/qiskit/transpiler/preset_passmanagers/level2.py index ea02e8f0e77c..0133c74e1e15 100644 --- a/qiskit/transpiler/preset_passmanagers/level2.py +++ b/qiskit/transpiler/preset_passmanagers/level2.py @@ -65,11 +65,11 @@ def level_2_pass_manager(transpile_config): Returns: PassManager: a level 2 pass manager. """ - basis_gates = transpile_config.basis_gates - coupling_map = transpile_config.coupling_map - initial_layout = transpile_config.initial_layout - seed_transpiler = transpile_config.seed_transpiler - backend_properties = transpile_config.backend_properties + basis_gates = transpile_config['basis_gates'] + coupling_map = transpile_config['coupling_map'] + initial_layout = transpile_config['initial_layout'] + seed_transpiler = transpile_config['seed_transpiler'] + backend_properties = transpile_config['backend_properties'] # 1. Unroll to the basis first, to prepare for noise-adaptive layout _unroll = Unroller(basis_gates) diff --git a/qiskit/transpiler/preset_passmanagers/level3.py b/qiskit/transpiler/preset_passmanagers/level3.py index 087a3d49a762..4b98aa014143 100644 --- a/qiskit/transpiler/preset_passmanagers/level3.py +++ b/qiskit/transpiler/preset_passmanagers/level3.py @@ -68,11 +68,11 @@ def level_3_pass_manager(transpile_config): Returns: PassManager: a level 3 pass manager. """ - basis_gates = transpile_config.basis_gates - coupling_map = transpile_config.coupling_map - initial_layout = transpile_config.initial_layout - seed_transpiler = transpile_config.seed_transpiler - backend_properties = transpile_config.backend_properties + basis_gates = transpile_config['basis_gates'] + coupling_map = transpile_config['coupling_map'] + initial_layout = transpile_config['initial_layout'] + seed_transpiler = transpile_config['seed_transpiler'] + backend_properties = transpile_config['backend_properties'] # 1. Unroll to the basis first, to prepare for noise-adaptive layout _unroll = Unroller(basis_gates) diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index bbd7208793b8..57fcc7427b12 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -35,12 +35,12 @@ def transpile_circuit(circuit, transpile_config): TranspilerError: if transpile_config is not valid or transpilation incurs error """ # either the pass manager is already selected... - if transpile_config.pass_manager: - pass_manager = transpile_config.pass_manager + if transpile_config['pass_manager']: + pass_manager = transpile_config['pass_manager'] # or we choose an appropriate one based on desired optimization level (default: level 1) else: - level = transpile_config.optimization_level + level = transpile_config['optimization_level'] if level is None: level = 1 @@ -56,10 +56,10 @@ def transpile_circuit(circuit, transpile_config): raise TranspilerError("optimization_level can range from 0 to 3.") # Set a callback on the pass manager there is one - if getattr(transpile_config, 'callback', None): - pass_manager.callback = transpile_config.callback + if transpile_config['callback']: + pass_manager.callback = transpile_config['callback'] out_circuit = pass_manager.run(circuit) - out_circuit.name = transpile_config.output_name + out_circuit.name = transpile_config['output_name'] return out_circuit From 203280fc67bb34b468097909e877d7e140d2be62 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Sun, 8 Sep 2019 17:18:11 -0400 Subject: [PATCH 07/53] pass manager config --- qiskit/compiler/transpile.py | 28 +++++++++---------- qiskit/transpiler/models.py | 4 +-- ...spile_config.py => pass_manager_config.py} | 6 ++-- qiskit/transpiler/passmanager.py | 12 ++++++-- .../transpiler/preset_passmanagers/level0.py | 12 ++++---- .../transpiler/preset_passmanagers/level1.py | 12 ++++---- .../transpiler/preset_passmanagers/level2.py | 14 +++++----- .../transpiler/preset_passmanagers/level3.py | 14 +++++----- qiskit/transpiler/transpile_circuit.py | 18 +++++------- 9 files changed, 62 insertions(+), 58 deletions(-) rename qiskit/transpiler/{transpile_config.py => pass_manager_config.py} (93%) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 035591809c34..d0818bfbe682 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -18,7 +18,7 @@ from qiskit.transpiler import Layout, CouplingMap from qiskit.tools.parallel import parallel_map -from qiskit.transpiler.transpile_config import TranspileConfig +from qiskit.transpiler.pass_manager_config import PassManagerConfig from qiskit.transpiler.transpile_circuit import transpile_circuit from qiskit.pulse import Schedule from qiskit.circuit.quantumregister import Qubit @@ -178,15 +178,15 @@ def callback_func(**kwargs): config = user_config.get_config() optimization_level = config.get('transpile_optimization_level', None) - # Get TranspileConfig(s) to configure the circuit transpilation job(s) + # Get transpiler argument(s) to configure the circuit transpilation job(s) circuits = circuits if isinstance(circuits, list) else [circuits] - transpile_configs = _parse_transpile_args(circuits, backend, basis_gates, coupling_map, + transpile_args = _parse_transpile_args(circuits, backend, basis_gates, coupling_map, backend_properties, initial_layout, seed_transpiler, optimization_level, pass_manager, callback, output_name) # Transpile circuits in parallel - circuits = parallel_map(_transpile_circuit, list(zip(circuits, transpile_configs))) + circuits = parallel_map(_transpile_circuit, list(zip(circuits, transpile_args))) # TODO Merge circuits in if len(circuits) == 1: return circuits[0] @@ -200,7 +200,7 @@ def _transpile_circuit(circuit_config_tuple): Args: circuit_config_tuple (tuple): circuit (QuantumCircuit): circuit to transpile - transpile_config (TranspileConfig): configuration dictating how to transpile + transpile_config (dict): transpile params Returns: QuantumCircuit: transpiled circuit @@ -223,7 +223,7 @@ def _parse_transpile_args(circuits, backend, arg has more priority than the arg set by backend) Returns: - list[TranspileConfig]: a transpile config for each circuit, which is a standardized + list[dicts]: a transpile config for each circuit, which is a standardized object that configures the transpiler and determines the pass manager to use. """ # Each arg could be single or a list. If list, it must be the same size as @@ -250,16 +250,16 @@ def _parse_transpile_args(circuits, backend, for args in zip(basis_gates, coupling_map, backend_properties, initial_layout, seed_transpiler, optimization_level, pass_manager, output_name): - # TranspileConfig - transpile_config = {'basis_gates': args[0], - 'coupling_map': args[1], - 'backend_properties': args[2], - 'initial_layout': args[3], - 'seed_transpiler': args[4], + # PassManagerConfig + transpile_config = {'pass_manager_config': PassManagerConfig(basis_gates=args[0], + coupling_map=args[1], + backend_properties=args[2], + initial_layout=args[3], + seed_transpiler=args[4]), 'optimization_level': args[5], 'pass_manager': args[6], - 'callback': callback, - 'output_name': args[7]} + 'output_name': args[7], + 'callback': callback} transpile_configs.append(transpile_config) return transpile_configs diff --git a/qiskit/transpiler/models.py b/qiskit/transpiler/models.py index 05121384312b..53edb035e64e 100644 --- a/qiskit/transpiler/models.py +++ b/qiskit/transpiler/models.py @@ -12,13 +12,13 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -"""Models for TranspileConfig and RunConfig.""" +"""Models for PassManagerConfig and RunConfig.""" from qiskit.validation import BaseSchema class TranspileConfigSchema(BaseSchema): - """Schema for TranspileConfig.""" + """Schema for PassManagerConfig.""" # Required properties. diff --git a/qiskit/transpiler/transpile_config.py b/qiskit/transpiler/pass_manager_config.py similarity index 93% rename from qiskit/transpiler/transpile_config.py rename to qiskit/transpiler/pass_manager_config.py index f49382fb25aa..5a37b4c926e4 100644 --- a/qiskit/transpiler/transpile_config.py +++ b/qiskit/transpiler/pass_manager_config.py @@ -12,15 +12,15 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -"""Models for TranspileConfig and its related components.""" +"""Models for PassManagerConfig and its related components.""" from qiskit.transpiler.models import TranspileConfigSchema from qiskit.validation import BaseModel, bind_schema @bind_schema(TranspileConfigSchema) -class TranspileConfig(BaseModel): - """Model for TranspileConfig. +class PassManagerConfig(BaseModel): + """Model for PassManagerConfig. Please note that this class only describes the required fields. For the full description of the model, please check ``TranspileConfigSchema``. diff --git a/qiskit/transpiler/passmanager.py b/qiskit/transpiler/passmanager.py index ac3d3899acb7..4ddc64ed4d93 100644 --- a/qiskit/transpiler/passmanager.py +++ b/qiskit/transpiler/passmanager.py @@ -152,7 +152,7 @@ def reset(self): self.valid_passes = set() self.property_set.clear() - def run(self, circuit): + def run(self, circuit, output_name=None, callback=None): """Run all the passes on a QuantumCircuit Args: @@ -166,13 +166,21 @@ def run(self, circuit): del circuit self.reset() # Reset passmanager instance before starting + if callback: + self.callback = callback + self.count = 0 for passset in self.working_list: for pass_ in passset: dag = self._do_pass(pass_, dag, passset.options) circuit = dag_to_circuit(dag) - circuit.name = name + + if output_name: + circuit.name = output_name + else: + circuit.name = name + circuit._layout = self.property_set['layout'] return circuit diff --git a/qiskit/transpiler/preset_passmanagers/level0.py b/qiskit/transpiler/preset_passmanagers/level0.py index 98cc61034f88..62087570b5df 100644 --- a/qiskit/transpiler/preset_passmanagers/level0.py +++ b/qiskit/transpiler/preset_passmanagers/level0.py @@ -35,7 +35,7 @@ from qiskit.transpiler.passes import CheckCXDirection -def level_0_pass_manager(transpile_config): +def level_0_pass_manager(pass_manager_config): """ Level 0 pass manager: no explicit optimization other than mapping to backend. @@ -48,15 +48,15 @@ def level_0_pass_manager(transpile_config): stages are done. Args: - transpile_config (TranspileConfig) + pass_manager_config (PassManagerConfig) Returns: PassManager: a level 0 pass manager. """ - basis_gates = transpile_config['basis_gates'] - coupling_map = transpile_config['coupling_map'] - initial_layout = transpile_config['initial_layout'] - seed_transpiler = transpile_config['seed_transpiler'] + basis_gates = pass_manager_config.basis_gates + coupling_map = pass_manager_config.coupling_map + initial_layout = pass_manager_config.initial_layout + seed_transpiler = pass_manager_config.seed_transpiler # 1. Use trivial layout if no layout given _given_layout = SetLayout(initial_layout) diff --git a/qiskit/transpiler/preset_passmanagers/level1.py b/qiskit/transpiler/preset_passmanagers/level1.py index 6c1f7e7e4df7..3d9960e32bd8 100644 --- a/qiskit/transpiler/preset_passmanagers/level1.py +++ b/qiskit/transpiler/preset_passmanagers/level1.py @@ -40,7 +40,7 @@ from qiskit.transpiler.passes import CheckCXDirection -def level_1_pass_manager(transpile_config): +def level_1_pass_manager(pass_manager_config): """ Level 1 pass manager: light optimization by simple adjacent gate collapsing @@ -55,15 +55,15 @@ def level_1_pass_manager(transpile_config): stages are done. Args: - transpile_config (TranspileConfig) + pass_manager_config (PassManagerConfig) Returns: PassManager: a level 1 pass manager. """ - basis_gates = transpile_config['basis_gates'] - coupling_map = transpile_config['coupling_map'] - initial_layout = transpile_config['initial_layout'] - seed_transpiler = transpile_config['seed_transpiler'] + basis_gates = pass_manager_config.basis_gates + coupling_map = pass_manager_config.coupling_map + initial_layout = pass_manager_config.initial_layout + seed_transpiler = pass_manager_config.seed_transpiler # 1. Use trivial layout if no layout given _given_layout = SetLayout(initial_layout) diff --git a/qiskit/transpiler/preset_passmanagers/level2.py b/qiskit/transpiler/preset_passmanagers/level2.py index 0133c74e1e15..3ea657667735 100644 --- a/qiskit/transpiler/preset_passmanagers/level2.py +++ b/qiskit/transpiler/preset_passmanagers/level2.py @@ -43,7 +43,7 @@ from qiskit.transpiler.passes import CheckCXDirection -def level_2_pass_manager(transpile_config): +def level_2_pass_manager(pass_manager_config): """ Level 2 pass manager: medium optimization by noise adaptive qubit mapping and gate cancellation using commutativity rules. @@ -60,16 +60,16 @@ def level_2_pass_manager(transpile_config): stages are done. Args: - transpile_config (TranspileConfig) + pass_manager_config (PassManagerConfig) Returns: PassManager: a level 2 pass manager. """ - basis_gates = transpile_config['basis_gates'] - coupling_map = transpile_config['coupling_map'] - initial_layout = transpile_config['initial_layout'] - seed_transpiler = transpile_config['seed_transpiler'] - backend_properties = transpile_config['backend_properties'] + basis_gates = pass_manager_config.basis_gates + coupling_map = pass_manager_config.coupling_map + initial_layout = pass_manager_config.initial_layout + seed_transpiler = pass_manager_config.seed_transpiler + backend_properties = pass_manager_config.backend_properties # 1. Unroll to the basis first, to prepare for noise-adaptive layout _unroll = Unroller(basis_gates) diff --git a/qiskit/transpiler/preset_passmanagers/level3.py b/qiskit/transpiler/preset_passmanagers/level3.py index 4b98aa014143..57f7f343ca4e 100644 --- a/qiskit/transpiler/preset_passmanagers/level3.py +++ b/qiskit/transpiler/preset_passmanagers/level3.py @@ -46,7 +46,7 @@ from qiskit.transpiler.passes import CheckCXDirection -def level_3_pass_manager(transpile_config): +def level_3_pass_manager(pass_manager_config): """ Level 3 pass manager: heavy optimization by noise adaptive qubit mapping and gate cancellation using commutativity rules and unitary synthesis. @@ -63,16 +63,16 @@ def level_3_pass_manager(transpile_config): stages are done. Args: - transpile_config (TranspileConfig) + pass_manager_config (PassManagerConfig) Returns: PassManager: a level 3 pass manager. """ - basis_gates = transpile_config['basis_gates'] - coupling_map = transpile_config['coupling_map'] - initial_layout = transpile_config['initial_layout'] - seed_transpiler = transpile_config['seed_transpiler'] - backend_properties = transpile_config['backend_properties'] + basis_gates = pass_manager_config.basis_gates + coupling_map = pass_manager_config.coupling_map + initial_layout = pass_manager_config.initial_layout + seed_transpiler = pass_manager_config.seed_transpiler + backend_properties = pass_manager_config.backend_properties # 1. Unroll to the basis first, to prepare for noise-adaptive layout _unroll = Unroller(basis_gates) diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index 57fcc7427b12..2b40e68a8764 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -26,7 +26,7 @@ def transpile_circuit(circuit, transpile_config): Args: circuit (QuantumCircuit): circuit to transpile - transpile_config (TranspileConfig): configuration dictating how to transpile + transpile_config (PassManagerConfig): configuration dictating how to transpile Returns: QuantumCircuit: transpiled circuit @@ -45,21 +45,17 @@ def transpile_circuit(circuit, transpile_config): level = 1 if level == 0: - pass_manager = level_0_pass_manager(transpile_config) + pass_manager = level_0_pass_manager(transpile_config['pass_manager_config']) elif level == 1: - pass_manager = level_1_pass_manager(transpile_config) + pass_manager = level_1_pass_manager(transpile_config['pass_manager_config']) elif level == 2: - pass_manager = level_2_pass_manager(transpile_config) + pass_manager = level_2_pass_manager(transpile_config['pass_manager_config']) elif level == 3: - pass_manager = level_3_pass_manager(transpile_config) + pass_manager = level_3_pass_manager(transpile_config['pass_manager_config']) else: raise TranspilerError("optimization_level can range from 0 to 3.") - # Set a callback on the pass manager there is one - if transpile_config['callback']: - pass_manager.callback = transpile_config['callback'] - - out_circuit = pass_manager.run(circuit) - out_circuit.name = transpile_config['output_name'] + out_circuit = pass_manager.run(circuit, callback=transpile_config['callback'], + output_name=transpile_config['output_name']) return out_circuit From eccfd270f7a546720a5c4a93fb017722a550c023 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Sun, 8 Sep 2019 17:29:53 -0400 Subject: [PATCH 08/53] circuit is yet another transpiler param --- qiskit/compiler/transpile.py | 26 +++++++++++--------------- qiskit/transpiler/transpile_circuit.py | 8 ++++---- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index d0818bfbe682..f4f2b468017d 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -181,12 +181,12 @@ def callback_func(**kwargs): # Get transpiler argument(s) to configure the circuit transpilation job(s) circuits = circuits if isinstance(circuits, list) else [circuits] transpile_args = _parse_transpile_args(circuits, backend, basis_gates, coupling_map, - backend_properties, initial_layout, - seed_transpiler, optimization_level, - pass_manager, callback, output_name) + backend_properties, initial_layout, + seed_transpiler, optimization_level, + pass_manager, callback, output_name) # Transpile circuits in parallel - circuits = parallel_map(_transpile_circuit, list(zip(circuits, transpile_args))) # TODO Merge circuits in + circuits = parallel_map(_transpile_circuit, transpile_args) if len(circuits) == 1: return circuits[0] @@ -194,20 +194,16 @@ def callback_func(**kwargs): # FIXME: This is a helper function because of parallel tools. -def _transpile_circuit(circuit_config_tuple): +def _transpile_circuit(transpile_params): """Select a PassManager and run a single circuit through it. Args: - circuit_config_tuple (tuple): - circuit (QuantumCircuit): circuit to transpile - transpile_config (dict): transpile params + transpile_params (dict): Returns: QuantumCircuit: transpiled circuit """ - circuit, transpile_config = circuit_config_tuple - - return transpile_circuit(circuit, transpile_config) + return transpile_circuit(transpile_params) def _parse_transpile_args(circuits, backend, @@ -223,8 +219,7 @@ def _parse_transpile_args(circuits, backend, arg has more priority than the arg set by backend) Returns: - list[dicts]: a transpile config for each circuit, which is a standardized - object that configures the transpiler and determines the pass manager to use. + list[dicts]: a list of transpile parameters. """ # Each arg could be single or a list. If list, it must be the same size as # number of circuits. If single, duplicate to create a list of that size. @@ -249,7 +244,7 @@ def _parse_transpile_args(circuits, backend, transpile_configs = [] for args in zip(basis_gates, coupling_map, backend_properties, initial_layout, seed_transpiler, optimization_level, - pass_manager, output_name): + pass_manager, output_name, circuits): # PassManagerConfig transpile_config = {'pass_manager_config': PassManagerConfig(basis_gates=args[0], coupling_map=args[1], @@ -259,7 +254,8 @@ def _parse_transpile_args(circuits, backend, 'optimization_level': args[5], 'pass_manager': args[6], 'output_name': args[7], - 'callback': callback} + 'callback': callback, + 'circuit': args[8]} transpile_configs.append(transpile_config) return transpile_configs diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index 2b40e68a8764..f0def84990bd 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -21,12 +21,11 @@ from qiskit.transpiler.exceptions import TranspilerError -def transpile_circuit(circuit, transpile_config): +def transpile_circuit(transpile_config): """Select a PassManager and run a single circuit through it. Args: - circuit (QuantumCircuit): circuit to transpile - transpile_config (PassManagerConfig): configuration dictating how to transpile + transpile_config (dict): configuration dictating how to transpile Returns: QuantumCircuit: transpiled circuit @@ -55,7 +54,8 @@ def transpile_circuit(circuit, transpile_config): else: raise TranspilerError("optimization_level can range from 0 to 3.") - out_circuit = pass_manager.run(circuit, callback=transpile_config['callback'], + out_circuit = pass_manager.run(transpile_config['circuit'], + callback=transpile_config['callback'], output_name=transpile_config['output_name']) return out_circuit From ea8d6a2a5e3de77f4ebb6bee823d8a8dcfdf4461 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Sun, 8 Sep 2019 17:31:17 -0400 Subject: [PATCH 09/53] TranspileConfigSchema -> PassManagerConfigSchema --- qiskit/transpiler/models.py | 2 +- qiskit/transpiler/pass_manager_config.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/qiskit/transpiler/models.py b/qiskit/transpiler/models.py index 53edb035e64e..f3489f8da7be 100644 --- a/qiskit/transpiler/models.py +++ b/qiskit/transpiler/models.py @@ -17,7 +17,7 @@ from qiskit.validation import BaseSchema -class TranspileConfigSchema(BaseSchema): +class PassManagerConfigSchema(BaseSchema): """Schema for PassManagerConfig.""" # Required properties. diff --git a/qiskit/transpiler/pass_manager_config.py b/qiskit/transpiler/pass_manager_config.py index 5a37b4c926e4..6f97ebd9df54 100644 --- a/qiskit/transpiler/pass_manager_config.py +++ b/qiskit/transpiler/pass_manager_config.py @@ -14,16 +14,16 @@ """Models for PassManagerConfig and its related components.""" -from qiskit.transpiler.models import TranspileConfigSchema +from qiskit.transpiler.models import PassManagerConfigSchema from qiskit.validation import BaseModel, bind_schema -@bind_schema(TranspileConfigSchema) +@bind_schema(PassManagerConfigSchema) class PassManagerConfig(BaseModel): """Model for PassManagerConfig. Please note that this class only describes the required fields. For the - full description of the model, please check ``TranspileConfigSchema``. + full description of the model, please check ``PassManagerConfigSchema``. Attributes: optimization_level (int): a non-negative integer indicating the From cc393d1b6dba23e59fd9f6a4c8ec2e6595ab86ad Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Sun, 8 Sep 2019 17:43:16 -0400 Subject: [PATCH 10/53] removing unsed parameters in PassManagerConfig --- qiskit/transpiler/pass_manager_config.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/qiskit/transpiler/pass_manager_config.py b/qiskit/transpiler/pass_manager_config.py index 6f97ebd9df54..1437e590966f 100644 --- a/qiskit/transpiler/pass_manager_config.py +++ b/qiskit/transpiler/pass_manager_config.py @@ -34,18 +34,10 @@ def __init__(self, initial_layout=None, basis_gates=None, coupling_map=None, - output_name=None, backend_properties=None, - optimization_level=None, - callback=None, - seed_transpiler=None, - pass_manager=None): + seed_transpiler=None): super().__init__(initial_layout=initial_layout, basis_gates=basis_gates, coupling_map=coupling_map, - output_name=output_name, backend_properties=backend_properties, - optimization_level=optimization_level, - callback=callback, - seed_transpiler=seed_transpiler, - pass_manager=pass_manager) + seed_transpiler=seed_transpiler) \ No newline at end of file From 24ce88919a9f04edd20753304415a2ef52987c4f Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Sun, 8 Sep 2019 18:30:52 -0400 Subject: [PATCH 11/53] no need for _transpile_circuit anymore --- qiskit/compiler/transpile.py | 15 +-------------- qiskit/transpiler/pass_manager_config.py | 3 ++- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index f4f2b468017d..72d96ae36d01 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -186,26 +186,13 @@ def callback_func(**kwargs): pass_manager, callback, output_name) # Transpile circuits in parallel - circuits = parallel_map(_transpile_circuit, transpile_args) + circuits = parallel_map(transpile_circuit, transpile_args) if len(circuits) == 1: return circuits[0] return circuits -# FIXME: This is a helper function because of parallel tools. -def _transpile_circuit(transpile_params): - """Select a PassManager and run a single circuit through it. - - Args: - transpile_params (dict): - - Returns: - QuantumCircuit: transpiled circuit - """ - return transpile_circuit(transpile_params) - - def _parse_transpile_args(circuits, backend, basis_gates, coupling_map, backend_properties, initial_layout, seed_transpiler, optimization_level, diff --git a/qiskit/transpiler/pass_manager_config.py b/qiskit/transpiler/pass_manager_config.py index 1437e590966f..13e155502710 100644 --- a/qiskit/transpiler/pass_manager_config.py +++ b/qiskit/transpiler/pass_manager_config.py @@ -30,6 +30,7 @@ class PassManagerConfig(BaseModel): optimization level. 0 means no transformation on the circuit. Higher levels may produce more optimized circuits, but may take longer. """ + def __init__(self, initial_layout=None, basis_gates=None, @@ -40,4 +41,4 @@ def __init__(self, basis_gates=basis_gates, coupling_map=coupling_map, backend_properties=backend_properties, - seed_transpiler=seed_transpiler) \ No newline at end of file + seed_transpiler=seed_transpiler) From fc488b8ffad62312d1ddd2826858956fea79c1d8 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Sun, 8 Sep 2019 18:45:40 -0400 Subject: [PATCH 12/53] pass manager callback at construction time --- qiskit/compiler/transpile.py | 15 ++++----------- qiskit/transpiler/pass_manager_config.py | 6 ++++-- qiskit/transpiler/passmanager.py | 1 + qiskit/transpiler/preset_passmanagers/level0.py | 2 +- qiskit/transpiler/preset_passmanagers/level1.py | 2 +- qiskit/transpiler/preset_passmanagers/level2.py | 2 +- qiskit/transpiler/preset_passmanagers/level3.py | 2 +- 7 files changed, 13 insertions(+), 17 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 72d96ae36d01..86f54118604f 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -213,36 +213,29 @@ def _parse_transpile_args(circuits, backend, num_circuits = len(circuits) basis_gates = _parse_basis_gates(basis_gates, backend, circuits) - coupling_map = _parse_coupling_map(coupling_map, backend, circuits) - backend_properties = _parse_backend_properties(backend_properties, backend, num_circuits) - initial_layout = _parse_initial_layout(initial_layout, circuits) - seed_transpiler = _parse_seed_transpiler(seed_transpiler, num_circuits) - optimization_level = _parse_optimization_level(optimization_level, num_circuits) - pass_manager = _parse_pass_manager(pass_manager, num_circuits) - output_name = _parse_output_name(output_name, circuits) transpile_configs = [] for args in zip(basis_gates, coupling_map, backend_properties, initial_layout, seed_transpiler, optimization_level, pass_manager, output_name, circuits): - # PassManagerConfig transpile_config = {'pass_manager_config': PassManagerConfig(basis_gates=args[0], coupling_map=args[1], backend_properties=args[2], initial_layout=args[3], - seed_transpiler=args[4]), + seed_transpiler=args[4], + callback=callback), 'optimization_level': args[5], 'pass_manager': args[6], 'output_name': args[7], - 'callback': callback, - 'circuit': args[8]} + 'circuit': args[8], + 'callback': callback} transpile_configs.append(transpile_config) return transpile_configs diff --git a/qiskit/transpiler/pass_manager_config.py b/qiskit/transpiler/pass_manager_config.py index 13e155502710..b1d97ed73a6a 100644 --- a/qiskit/transpiler/pass_manager_config.py +++ b/qiskit/transpiler/pass_manager_config.py @@ -36,9 +36,11 @@ def __init__(self, basis_gates=None, coupling_map=None, backend_properties=None, - seed_transpiler=None): + seed_transpiler=None, + callback=None): super().__init__(initial_layout=initial_layout, basis_gates=basis_gates, coupling_map=coupling_map, backend_properties=backend_properties, - seed_transpiler=seed_transpiler) + seed_transpiler=seed_transpiler, + callback=callback) diff --git a/qiskit/transpiler/passmanager.py b/qiskit/transpiler/passmanager.py index 4ddc64ed4d93..ce5175f15b07 100644 --- a/qiskit/transpiler/passmanager.py +++ b/qiskit/transpiler/passmanager.py @@ -157,6 +157,7 @@ def run(self, circuit, output_name=None, callback=None): Args: circuit (QuantumCircuit): circuit to transform via all the registered passes + output_name (str): Returns: QuantumCircuit: Transformed circuit. diff --git a/qiskit/transpiler/preset_passmanagers/level0.py b/qiskit/transpiler/preset_passmanagers/level0.py index 62087570b5df..c2213289ef6e 100644 --- a/qiskit/transpiler/preset_passmanagers/level0.py +++ b/qiskit/transpiler/preset_passmanagers/level0.py @@ -93,7 +93,7 @@ def _direction_condition(property_set): # 6. Remove zero-state reset _reset = RemoveResetInZeroState() - pm0 = PassManager() + pm0 = PassManager(callback=pass_manager_config.callback) if coupling_map: pm0.append(_given_layout) pm0.append(_choose_layout, condition=_choose_layout_condition) diff --git a/qiskit/transpiler/preset_passmanagers/level1.py b/qiskit/transpiler/preset_passmanagers/level1.py index 3d9960e32bd8..b38ab9dac407 100644 --- a/qiskit/transpiler/preset_passmanagers/level1.py +++ b/qiskit/transpiler/preset_passmanagers/level1.py @@ -112,7 +112,7 @@ def _opt_control(property_set): _opt = [Optimize1qGates(), CXCancellation()] - pm1 = PassManager() + pm1 = PassManager(callback=pass_manager_config.callback) if coupling_map: pm1.append(_given_layout) pm1.append(_choose_layout, condition=_choose_layout_condition) diff --git a/qiskit/transpiler/preset_passmanagers/level2.py b/qiskit/transpiler/preset_passmanagers/level2.py index 3ea657667735..93643adf07d3 100644 --- a/qiskit/transpiler/preset_passmanagers/level2.py +++ b/qiskit/transpiler/preset_passmanagers/level2.py @@ -117,7 +117,7 @@ def _opt_control(property_set): _opt = [Optimize1qGates(), CommutativeCancellation()] - pm2 = PassManager() + pm2 = PassManager(callback=pass_manager_config.callback) pm2.append(_unroll) if coupling_map: pm2.append(_given_layout) diff --git a/qiskit/transpiler/preset_passmanagers/level3.py b/qiskit/transpiler/preset_passmanagers/level3.py index 57f7f343ca4e..d11fac258766 100644 --- a/qiskit/transpiler/preset_passmanagers/level3.py +++ b/qiskit/transpiler/preset_passmanagers/level3.py @@ -124,7 +124,7 @@ def _opt_control(property_set): _opt.append(CXDirection(coupling_map)) # if a coupling map has been provided, match coupling - pm3 = PassManager() + pm3 = PassManager(callback=pass_manager_config.callback) pm3.append(_unroll) if coupling_map: pm3.append(_given_layout) From b5ee757b01895b3fd56d9ae33590e96b6aa8498d Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Sun, 8 Sep 2019 20:16:38 -0400 Subject: [PATCH 13/53] docstring --- qiskit/transpiler/passmanager.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/qiskit/transpiler/passmanager.py b/qiskit/transpiler/passmanager.py index ce5175f15b07..e9ce75fbe102 100644 --- a/qiskit/transpiler/passmanager.py +++ b/qiskit/transpiler/passmanager.py @@ -157,7 +157,11 @@ def run(self, circuit, output_name=None, callback=None): Args: circuit (QuantumCircuit): circuit to transform via all the registered passes - output_name (str): + output_name (str): The output circuit name. If not given, the same as the + input circuit + callback (func): A callback function that will be called after each + pass execution. See PassManager() for more details. This parameter will + override the one given at construction-time if given. Returns: QuantumCircuit: Transformed circuit. From 01de59bbc8291e1a3243d1b45fafebc4a7eb6b4c Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Tue, 10 Sep 2019 10:38:54 -0400 Subject: [PATCH 14/53] changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11507ebf7d83..34bf5f197f82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,8 @@ The format is based on [Keep a Changelog]. ### Changed -- The `TranspileConfig` was extended to have `None` defaults for +- The `TranspileConfig` was restructured to include only the information + needed to construct a `PassManager`. ### Deprecated From fe54db62572bd095ef85c52e47d48794c8cd235d Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Tue, 10 Sep 2019 11:40:02 -0400 Subject: [PATCH 15/53] deprecate callback from construction time --- CHANGELOG.md | 2 + qiskit/compiler/transpile.py | 3 +- qiskit/transpiler/pass_manager_config.py | 6 +- qiskit/transpiler/passmanager.py | 65 ++++++++++--------- .../transpiler/preset_passmanagers/level0.py | 2 +- .../transpiler/preset_passmanagers/level1.py | 2 +- .../transpiler/preset_passmanagers/level2.py | 2 +- .../transpiler/preset_passmanagers/level3.py | 2 +- test/python/transpiler/test_passmanager.py | 8 +-- 9 files changed, 48 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34bf5f197f82..ed0ca202768f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,8 @@ The format is based on [Keep a Changelog]. - The decorator `requires_qe_access` is being deprecated in favor of `online_test`. - The `as_dict` method of Qobj is deprecated in favor of `to_dict`. +- The `TranspileConfig` was restructured to include only the information + needed to construct a `PassManager`. ### Added diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 86f54118604f..1e31971c40a0 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -229,8 +229,7 @@ def _parse_transpile_args(circuits, backend, coupling_map=args[1], backend_properties=args[2], initial_layout=args[3], - seed_transpiler=args[4], - callback=callback), + seed_transpiler=args[4]), 'optimization_level': args[5], 'pass_manager': args[6], 'output_name': args[7], diff --git a/qiskit/transpiler/pass_manager_config.py b/qiskit/transpiler/pass_manager_config.py index b1d97ed73a6a..13e155502710 100644 --- a/qiskit/transpiler/pass_manager_config.py +++ b/qiskit/transpiler/pass_manager_config.py @@ -36,11 +36,9 @@ def __init__(self, basis_gates=None, coupling_map=None, backend_properties=None, - seed_transpiler=None, - callback=None): + seed_transpiler=None): super().__init__(initial_layout=initial_layout, basis_gates=basis_gates, coupling_map=coupling_map, backend_properties=backend_properties, - seed_transpiler=seed_transpiler, - callback=callback) + seed_transpiler=seed_transpiler) diff --git a/qiskit/transpiler/passmanager.py b/qiskit/transpiler/passmanager.py index e9ce75fbe102..2891d7fd1222 100644 --- a/qiskit/transpiler/passmanager.py +++ b/qiskit/transpiler/passmanager.py @@ -18,6 +18,7 @@ from collections import OrderedDict import logging from time import time +import warnings from qiskit.dagcircuit import DAGCircuit from qiskit.converters import circuit_to_dag, dag_to_circuit @@ -43,36 +44,15 @@ def __init__(self, passes=None, None. max_iteration (int): The schedule looping iterates until the condition is met or until max_iteration is reached. - callback (func): A callback function that will be called after each - pass execution. The function will be called with 5 keyword - arguments: - pass_ (Pass): the pass being run - dag (DAGCircuit): the dag output of the pass - time (float): the time to execute the pass - property_set (PropertySet): the property set - count (int): the index for the pass execution - - The exact arguments pass expose the internals of the pass - manager and are subject to change as the pass manager internals - change. If you intend to reuse a callback function over - multiple releases be sure to check that the arguments being - passed are the same. - - To use the callback feature you define a function that will - take in kwargs dict and access the variables. For example:: - - def callback_func(**kwargs): - pass_ = kwargs['pass_'] - dag = kwargs['dag'] - time = kwargs['time'] - property_set = kwargs['property_set'] - count = kwargs['count'] - ... - - PassManager(callback=callback_func) + callback (func): DEPRECATED - A callback function that will be called after each + pass execution. """ - self.callback = callback + self.callback = None + if callback: + warnings.warn("Setting a callback at construction time is being deprecated in favor of" + "PassManager.run(..., callback=callback,...)", DeprecationWarning, 2) + self.callback = callback # the pass manager's schedule of passes, including any control-flow. # Populated via PassManager.append(). self.working_list = [] @@ -160,8 +140,33 @@ def run(self, circuit, output_name=None, callback=None): output_name (str): The output circuit name. If not given, the same as the input circuit callback (func): A callback function that will be called after each - pass execution. See PassManager() for more details. This parameter will - override the one given at construction-time if given. + pass execution. The function will be called with 5 keyword + arguments: + pass_ (Pass): the pass being run + dag (DAGCircuit): the dag output of the pass + time (float): the time to execute the pass + property_set (PropertySet): the property set + count (int): the index for the pass execution + + The exact arguments pass expose the internals of the pass + manager and are subject to change as the pass manager internals + change. If you intend to reuse a callback function over + multiple releases be sure to check that the arguments being + passed are the same. + + To use the callback feature you define a function that will + take in kwargs dict and access the variables. For example:: + + def callback_func(**kwargs): + pass_ = kwargs['pass_'] + dag = kwargs['dag'] + time = kwargs['time'] + property_set = kwargs['property_set'] + count = kwargs['count'] + ... + + PassManager(callback=callback_func) + Returns: QuantumCircuit: Transformed circuit. diff --git a/qiskit/transpiler/preset_passmanagers/level0.py b/qiskit/transpiler/preset_passmanagers/level0.py index c2213289ef6e..62087570b5df 100644 --- a/qiskit/transpiler/preset_passmanagers/level0.py +++ b/qiskit/transpiler/preset_passmanagers/level0.py @@ -93,7 +93,7 @@ def _direction_condition(property_set): # 6. Remove zero-state reset _reset = RemoveResetInZeroState() - pm0 = PassManager(callback=pass_manager_config.callback) + pm0 = PassManager() if coupling_map: pm0.append(_given_layout) pm0.append(_choose_layout, condition=_choose_layout_condition) diff --git a/qiskit/transpiler/preset_passmanagers/level1.py b/qiskit/transpiler/preset_passmanagers/level1.py index b38ab9dac407..3d9960e32bd8 100644 --- a/qiskit/transpiler/preset_passmanagers/level1.py +++ b/qiskit/transpiler/preset_passmanagers/level1.py @@ -112,7 +112,7 @@ def _opt_control(property_set): _opt = [Optimize1qGates(), CXCancellation()] - pm1 = PassManager(callback=pass_manager_config.callback) + pm1 = PassManager() if coupling_map: pm1.append(_given_layout) pm1.append(_choose_layout, condition=_choose_layout_condition) diff --git a/qiskit/transpiler/preset_passmanagers/level2.py b/qiskit/transpiler/preset_passmanagers/level2.py index 93643adf07d3..3ea657667735 100644 --- a/qiskit/transpiler/preset_passmanagers/level2.py +++ b/qiskit/transpiler/preset_passmanagers/level2.py @@ -117,7 +117,7 @@ def _opt_control(property_set): _opt = [Optimize1qGates(), CommutativeCancellation()] - pm2 = PassManager(callback=pass_manager_config.callback) + pm2 = PassManager() pm2.append(_unroll) if coupling_map: pm2.append(_given_layout) diff --git a/qiskit/transpiler/preset_passmanagers/level3.py b/qiskit/transpiler/preset_passmanagers/level3.py index d11fac258766..57f7f343ca4e 100644 --- a/qiskit/transpiler/preset_passmanagers/level3.py +++ b/qiskit/transpiler/preset_passmanagers/level3.py @@ -124,7 +124,7 @@ def _opt_control(property_set): _opt.append(CXDirection(coupling_map)) # if a coupling map has been provided, match coupling - pm3 = PassManager(callback=pass_manager_config.callback) + pm3 = PassManager() pm3.append(_unroll) if coupling_map: pm3.append(_given_layout) diff --git a/test/python/transpiler/test_passmanager.py b/test/python/transpiler/test_passmanager.py index 209d508be3bd..66706a4d9ce2 100644 --- a/test/python/transpiler/test_passmanager.py +++ b/test/python/transpiler/test_passmanager.py @@ -56,10 +56,10 @@ def callback(**kwargs): out_dict['dag'] = copy.deepcopy(kwargs['dag']) calls.append(out_dict) - passmanager = PassManager(callback=callback) + passmanager = PassManager() passmanager.append(Unroller(['u2'])) passmanager.append(Optimize1qGates()) - transpile(circuit, FakeRueschlikon(), pass_manager=passmanager) + transpile(circuit, FakeRueschlikon(), pass_manager=passmanager, callback=callback) self.assertEqual(len(calls), 2) self.assertEqual(len(calls[0]), 5) self.assertEqual(calls[0]['count'], 0) @@ -100,9 +100,9 @@ def callback(**kwargs): out_dict['dag'] = copy.deepcopy(kwargs['dag']) calls.append(out_dict) - passmanager = PassManager(callback=callback) + passmanager = PassManager() passmanager.append(CommutativeCancellation()) - passmanager.run(circuit) + passmanager.run(circuit, callback=callback) self.assertEqual(len(calls), 2) self.assertEqual(len(calls[0]), 5) self.assertEqual(calls[0]['count'], 0) From 26b379e6ca3248d390017195eab447fa2402b366 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Tue, 10 Sep 2019 11:54:38 -0400 Subject: [PATCH 16/53] _parse_output_name creates Nones instead of circuit.name --- qiskit/compiler/transpile.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 1e31971c40a0..a96eead00042 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -219,7 +219,7 @@ def _parse_transpile_args(circuits, backend, seed_transpiler = _parse_seed_transpiler(seed_transpiler, num_circuits) optimization_level = _parse_optimization_level(optimization_level, num_circuits) pass_manager = _parse_pass_manager(pass_manager, num_circuits) - output_name = _parse_output_name(output_name, circuits) + output_name = _parse_output_name(output_name, num_circuits) transpile_configs = [] for args in zip(basis_gates, coupling_map, backend_properties, @@ -346,13 +346,13 @@ def _parse_pass_manager(pass_manager, num_circuits): return pass_manager -def _parse_output_name(output_name, circuits): +def _parse_output_name(output_name, num_circuits): # naming and returning circuits # output_name could be either a string or a list if output_name is not None: if isinstance(output_name, str): # single circuit - if len(circuits) == 1: + if num_circuits == 1: return [output_name] # multiple circuits else: @@ -360,7 +360,7 @@ def _parse_output_name(output_name, circuits): "to that of the number of circuits " + "being transpiled") elif isinstance(output_name, list): - if len(circuits) == len(output_name) and \ + if num_circuits == len(output_name) and \ all(isinstance(name, str) for name in output_name): return output_name else: @@ -372,4 +372,4 @@ def _parse_output_name(output_name, circuits): raise TranspilerError("The parameter output_name should be a string or a" "list of strings: %s was used." % type(output_name)) else: - return [circuit.name for circuit in circuits] + return [None] * num_circuits From 4aeb87ef08164c92f7273d7ef809e79fd2040a5b Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Tue, 10 Sep 2019 11:58:53 -0400 Subject: [PATCH 17/53] transpile_config -> transpile_args --- qiskit/compiler/transpile.py | 8 ++++---- qiskit/transpiler/transpile_circuit.py | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index a96eead00042..2e67f0982728 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -221,11 +221,11 @@ def _parse_transpile_args(circuits, backend, pass_manager = _parse_pass_manager(pass_manager, num_circuits) output_name = _parse_output_name(output_name, num_circuits) - transpile_configs = [] + transpile_args_circuits = [] for args in zip(basis_gates, coupling_map, backend_properties, initial_layout, seed_transpiler, optimization_level, pass_manager, output_name, circuits): - transpile_config = {'pass_manager_config': PassManagerConfig(basis_gates=args[0], + transpile_args = {'pass_manager_config': PassManagerConfig(basis_gates=args[0], coupling_map=args[1], backend_properties=args[2], initial_layout=args[3], @@ -235,9 +235,9 @@ def _parse_transpile_args(circuits, backend, 'output_name': args[7], 'circuit': args[8], 'callback': callback} - transpile_configs.append(transpile_config) + transpile_args_circuits.append(transpile_args) - return transpile_configs + return transpile_args_circuits def _parse_basis_gates(basis_gates, backend, circuits): diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index f0def84990bd..54f0d74decf7 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -21,41 +21,41 @@ from qiskit.transpiler.exceptions import TranspilerError -def transpile_circuit(transpile_config): +def transpile_circuit(transpile_args): """Select a PassManager and run a single circuit through it. Args: - transpile_config (dict): configuration dictating how to transpile + transpile_args (dict): configuration dictating how to transpile Returns: QuantumCircuit: transpiled circuit Raises: - TranspilerError: if transpile_config is not valid or transpilation incurs error + TranspilerError: if transpile_args is not valid or transpilation incurs error """ # either the pass manager is already selected... - if transpile_config['pass_manager']: - pass_manager = transpile_config['pass_manager'] + if transpile_args['pass_manager']: + pass_manager = transpile_args['pass_manager'] # or we choose an appropriate one based on desired optimization level (default: level 1) else: - level = transpile_config['optimization_level'] + level = transpile_args['optimization_level'] if level is None: level = 1 if level == 0: - pass_manager = level_0_pass_manager(transpile_config['pass_manager_config']) + pass_manager = level_0_pass_manager(transpile_args['pass_manager_config']) elif level == 1: - pass_manager = level_1_pass_manager(transpile_config['pass_manager_config']) + pass_manager = level_1_pass_manager(transpile_args['pass_manager_config']) elif level == 2: - pass_manager = level_2_pass_manager(transpile_config['pass_manager_config']) + pass_manager = level_2_pass_manager(transpile_args['pass_manager_config']) elif level == 3: - pass_manager = level_3_pass_manager(transpile_config['pass_manager_config']) + pass_manager = level_3_pass_manager(transpile_args['pass_manager_config']) else: raise TranspilerError("optimization_level can range from 0 to 3.") - out_circuit = pass_manager.run(transpile_config['circuit'], - callback=transpile_config['callback'], - output_name=transpile_config['output_name']) + out_circuit = pass_manager.run(transpile_args['circuit'], + callback=transpile_args['callback'], + output_name=transpile_args['output_name']) return out_circuit From 948b3d44a158708dfb11e3a6dd7246f4c7c15a1a Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Tue, 10 Sep 2019 12:32:06 -0400 Subject: [PATCH 18/53] CouplingMap(backend.configuration().coupling_map) --- qiskit/compiler/transpile.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 2e67f0982728..36d330c42b57 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -271,7 +271,9 @@ def _parse_coupling_map(coupling_map, backend, circuits): # try getting coupling_map from user, else backend if coupling_map is None: if getattr(backend, 'configuration', None): - coupling_map = getattr(backend.configuration(), 'coupling_map', None) + configuration = backend.configuration() + if hasattr(configuration, 'coupling_map') and configuration.coupling_map: + coupling_map = CouplingMap(configuration.coupling_map) coupling_map = [coupling_map] * num_circuits From a909c5ff724fff4ca3a6407fb56d2a3ceea8f356 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Tue, 10 Sep 2019 12:37:40 -0400 Subject: [PATCH 19/53] reformat --- qiskit/compiler/transpile.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 36d330c42b57..b696170f157e 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -226,15 +226,15 @@ def _parse_transpile_args(circuits, backend, initial_layout, seed_transpiler, optimization_level, pass_manager, output_name, circuits): transpile_args = {'pass_manager_config': PassManagerConfig(basis_gates=args[0], - coupling_map=args[1], - backend_properties=args[2], - initial_layout=args[3], - seed_transpiler=args[4]), - 'optimization_level': args[5], - 'pass_manager': args[6], - 'output_name': args[7], - 'circuit': args[8], - 'callback': callback} + coupling_map=args[1], + backend_properties=args[2], + initial_layout=args[3], + seed_transpiler=args[4]), + 'optimization_level': args[5], + 'pass_manager': args[6], + 'output_name': args[7], + 'circuit': args[8], + 'callback': callback} transpile_args_circuits.append(transpile_args) return transpile_args_circuits From 73b21c224370e564ecbb7fc769f524124aa98266 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Thu, 31 Oct 2019 10:56:00 -0400 Subject: [PATCH 20/53] fixing test/python/transpiler/test_passmanager_run.py --- test/python/transpiler/test_passmanager_run.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/test/python/transpiler/test_passmanager_run.py b/test/python/transpiler/test_passmanager_run.py index 99077ff9b16e..8d2c9911ef18 100644 --- a/test/python/transpiler/test_passmanager_run.py +++ b/test/python/transpiler/test_passmanager_run.py @@ -20,7 +20,7 @@ from qiskit.test import QiskitTestCase from qiskit.test.mock import FakeMelbourne from qiskit.transpiler import Layout, CouplingMap -from qiskit.transpiler.transpile_config import TranspileConfig +from qiskit.transpiler.pass_manager_config import PassManagerConfig class TestPassManagerRun(QiskitTestCase): @@ -56,12 +56,11 @@ def test_default_pass_manager_single(self): basis_gates = FakeMelbourne().configuration().basis_gates initial_layout = [None, qr[0], qr[1], qr[2], None, qr[3]] - pass_manager = level_1_pass_manager(TranspileConfig( + pass_manager = level_1_pass_manager(PassManagerConfig( basis_gates=basis_gates, coupling_map=CouplingMap(coupling_map), initial_layout=Layout.from_qubit_list(initial_layout), - seed_transpiler=42, - optimization_level=1)) + seed_transpiler=42)) new_circuit = pass_manager.run(circuit) for gate, qargs, _ in new_circuit.data: @@ -103,12 +102,11 @@ def test_default_pass_manager_two(self): basis_gates = FakeMelbourne().configuration().basis_gates initial_layout = [None, qr[0], qr[1], qr[2], None, qr[3]] - pass_manager = level_1_pass_manager(TranspileConfig( + pass_manager = level_1_pass_manager(PassManagerConfig( basis_gates=basis_gates, coupling_map=CouplingMap(coupling_map), initial_layout=Layout.from_qubit_list(initial_layout), - seed_transpiler=42, - optimization_level=1)) + seed_transpiler=42)) new_circuits = pass_manager.run([circuit1, circuit2]) for new_circuit in new_circuits: From bbb1c4551d4de3b9d2753fdefe8b4f27f94b2836 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Thu, 31 Oct 2019 11:39:08 -0400 Subject: [PATCH 21/53] run(..., output_name=None, callback=None) --- qiskit/transpiler/passmanager.py | 25 ++++++++++--------------- qiskit/transpiler/runningpassmanager.py | 10 ++++++++-- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/qiskit/transpiler/passmanager.py b/qiskit/transpiler/passmanager.py index eefe6142e76f..72f4932297d4 100644 --- a/qiskit/transpiler/passmanager.py +++ b/qiskit/transpiler/passmanager.py @@ -126,9 +126,7 @@ def __len__(self): return len(self._pass_sets) def __getitem__(self, index): - max_iteration = self.max_iteration - call_back = self.callback - new_passmanager = PassManager(max_iteration=max_iteration, callback=call_back) + new_passmanager = PassManager(max_iteration=self.max_iteration, callback=self.callback) _pass_sets = self._pass_sets[index] if isinstance(_pass_sets, dict): _pass_sets = [_pass_sets] @@ -137,16 +135,13 @@ def __getitem__(self, index): def __add__(self, other): if isinstance(other, PassManager): - max_iteration = self.max_iteration - call_back = self.callback - new_passmanager = PassManager(max_iteration=max_iteration, callback=call_back) + new_passmanager = PassManager(max_iteration=self.max_iteration, callback=self.callback) new_passmanager._pass_sets = self._pass_sets + other._pass_sets return new_passmanager else: try: - max_iteration = self.max_iteration - call_back = self.callback - new_passmanager = PassManager(max_iteration=max_iteration, callback=call_back) + new_passmanager = PassManager(max_iteration=self.max_iteration, + callback=self.callback) new_passmanager._pass_sets += self._pass_sets new_passmanager.append(other) return new_passmanager @@ -164,7 +159,7 @@ def _normalize_passes(passes): raise TranspilerError('%s is not a pass instance' % pass_.__class__) return passes - def run(self, circuits): + def run(self, circuits, output_name=None, callback=None): """Run all the passes on circuit or circuits Args: @@ -175,9 +170,9 @@ def run(self, circuits): QuantumCircuit or list[QuantumCircuit]: Transformed circuit(s). """ if isinstance(circuits, QuantumCircuit): - return self._run_single_circuit(circuits) + return self._run_single_circuit(circuits, output_name, callback) else: - return self._run_several_circuits(circuits) + return self._run_several_circuits(circuits, output_name, callback) def _create_running_passmanager(self): running_passmanager = RunningPassManager(self.max_iteration, self.callback) @@ -192,7 +187,7 @@ def _in_parallel(circuit, pm_dill=None): result = running_passmanager.run(circuit) return result - def _run_several_circuits(self, circuits): + def _run_several_circuits(self, circuits, output_name=None, callback=None): """Run all the passes on each of the circuits in the circuits list Args: @@ -204,7 +199,7 @@ def _run_several_circuits(self, circuits): return parallel_map(PassManager._in_parallel, circuits, task_kwargs={'pm_dill': dill.dumps(self)}) - def _run_single_circuit(self, circuit): + def _run_single_circuit(self, circuit, output_name=None, callback=None): """Run all the passes on a QuantumCircuit Args: @@ -244,7 +239,7 @@ def callback_func(**kwargs): QuantumCircuit: Transformed circuit. """ running_passmanager = self._create_running_passmanager() - result = running_passmanager.run(circuit) + result = running_passmanager.run(circuit, output_name=output_name, callback=callback) self.property_set = running_passmanager.property_set return result diff --git a/qiskit/transpiler/runningpassmanager.py b/qiskit/transpiler/runningpassmanager.py index e80f77cc3949..635408d5b668 100644 --- a/qiskit/transpiler/runningpassmanager.py +++ b/qiskit/transpiler/runningpassmanager.py @@ -120,7 +120,7 @@ def _normalize_flow_controller(self, flow_controller): raise TranspilerError('The flow controller parameter %s is not callable' % name) return flow_controller - def run(self, circuit): + def run(self, circuit, output_name=None, callback=None): """Run all the passes on a QuantumCircuit Args: @@ -133,12 +133,18 @@ def run(self, circuit): dag = circuit_to_dag(circuit) del circuit + if callback: + self.callback = callback + for passset in self.working_list: for pass_ in passset: dag = self._do_pass(pass_, dag, passset.options) circuit = dag_to_circuit(dag) - circuit.name = name + if output_name: + circuit.name = output_name + else: + circuit.name = name circuit._layout = self.property_set['layout'] return circuit From 142e2981fcd86d4d586d26c01e8128f840c2eded Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Thu, 31 Oct 2019 11:52:29 -0400 Subject: [PATCH 22/53] basis --- qiskit/transpiler/transpile_circuit.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index d432b3a12581..5c6b74b89768 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -45,10 +45,10 @@ def transpile_circuit(transpile_args): # Mølmer-Sørensen (rxx) and the circuit includes gates outside the basis, # first unroll to u3, cx, then run MSBasisDecomposer to target basis. basic_insts = ['measure', 'reset', 'barrier', 'snapshot'] - device_insts = set(transpile_args['basis_gates']).union(basic_insts) + device_insts = set(transpile_args['pass_manager_config'].basis_gates).union(basic_insts) ms_basis_swap = None - if 'rxx' in transpile_args['basis_gates'] and \ + if 'rxx' in transpile_args['pass_manager_config'].basis_gates and \ not device_insts >= transpile_args['circuit'].count_ops().keys(): ms_basis_swap = transpile_args['basis_gates'] transpile_args['basis_gates'] = list(set(['u3', 'cx']).union( From 4c98cc54c448977b0ee8f3b80e40978aac27a81d Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Thu, 31 Oct 2019 13:50:14 -0400 Subject: [PATCH 23/53] kwargs --- qiskit/transpiler/pass_manager_config.py | 6 +++-- qiskit/transpiler/passmanager.py | 29 ++++++++++++++++++++- qiskit/transpiler/runningpassmanager.py | 33 +++--------------------- qiskit/validation/base.py | 3 +-- 4 files changed, 36 insertions(+), 35 deletions(-) diff --git a/qiskit/transpiler/pass_manager_config.py b/qiskit/transpiler/pass_manager_config.py index 13e155502710..b6ac6d184800 100644 --- a/qiskit/transpiler/pass_manager_config.py +++ b/qiskit/transpiler/pass_manager_config.py @@ -36,9 +36,11 @@ def __init__(self, basis_gates=None, coupling_map=None, backend_properties=None, - seed_transpiler=None): + seed_transpiler=None, + **kwargs): super().__init__(initial_layout=initial_layout, basis_gates=basis_gates, coupling_map=coupling_map, backend_properties=backend_properties, - seed_transpiler=seed_transpiler) + seed_transpiler=seed_transpiler, + **kwargs) diff --git a/qiskit/transpiler/passmanager.py b/qiskit/transpiler/passmanager.py index 72f4932297d4..27280f87326a 100644 --- a/qiskit/transpiler/passmanager.py +++ b/qiskit/transpiler/passmanager.py @@ -164,8 +164,35 @@ def run(self, circuits, output_name=None, callback=None): Args: circuits (QuantumCircuit or list[QuantumCircuit]): circuit(s) to - transform via all the registered passes. + transform via all the registered passes. + output_name (str): + callback (func): A callback function that will be called after each + pass execution. The function will be called with 5 keyword + arguments: + pass_ (Pass): the pass being run + dag (DAGCircuit): the dag output of the pass + time (float): the time to execute the pass + property_set (PropertySet): the property set + count (int): the index for the pass execution + + The exact arguments pass expose the internals of the pass + manager and are subject to change as the pass manager internals + change. If you intend to reuse a callback function over + multiple releases be sure to check that the arguments being + passed are the same. + + To use the callback feature you define a function that will + take in kwargs dict and access the variables. For example:: + def callback_func(**kwargs): + pass_ = kwargs['pass_'] + dag = kwargs['dag'] + time = kwargs['time'] + property_set = kwargs['property_set'] + count = kwargs['count'] + ... + + PassManager(callback=callback_func) Returns: QuantumCircuit or list[QuantumCircuit]: Transformed circuit(s). """ diff --git a/qiskit/transpiler/runningpassmanager.py b/qiskit/transpiler/runningpassmanager.py index 635408d5b668..5bbc71c18452 100644 --- a/qiskit/transpiler/runningpassmanager.py +++ b/qiskit/transpiler/runningpassmanager.py @@ -29,7 +29,7 @@ logger = logging.getLogger(__name__) -class RunningPassManager(): +class RunningPassManager: """A RunningPassManager is a running pass manager.""" def __init__(self, max_iteration, callback): @@ -38,34 +38,6 @@ def __init__(self, max_iteration, callback): Args: max_iteration (int): The schedule looping iterates until the condition is met or until max_iteration is reached. - callback (func): A callback function that will be called after each - pass execution. The function will be called with 5 keyword - arguments: - pass_ (Pass): the pass being run - dag (DAGCircuit): the dag output of the pass - time (float): the time to execute the pass - property_set (PropertySet): the property set - count (int): the index for the pass execution - - The exact arguments pass expose the internals of the pass - manager and are subject to change as the pass manager internals - change. If you intend to reuse a callback function over - multiple releases be sure to check that the arguments being - passed are the same. - - To use the callback feature you define a function that will - take in kwargs dict and access the variables. For example:: - - def callback_func(**kwargs): - pass_ = kwargs['pass_'] - dag = kwargs['dag'] - time = kwargs['time'] - property_set = kwargs['property_set'] - count = kwargs['count'] - ... - - PassManager(callback=callback_func) - """ self.callback = callback # the pass manager's schedule of passes, including any control-flow. @@ -125,7 +97,8 @@ def run(self, circuit, output_name=None, callback=None): Args: circuit (QuantumCircuit): circuit to transform via all the registered passes - + output_name (str): The output circuit name. If not given, the same as the + input circuit Returns: QuantumCircuit: Transformed circuit. """ diff --git a/qiskit/validation/base.py b/qiskit/validation/base.py index ee5ee92b3a61..f66104d8d93e 100644 --- a/qiskit/validation/base.py +++ b/qiskit/validation/base.py @@ -214,8 +214,7 @@ def _decorated(self, **kwargs): do_validation = kwargs.pop('validate', True) if do_validation: try: - _ = self.shallow_schema._do_load(kwargs, - postprocess=False) + _ = self.shallow_schema._do_load(kwargs, postprocess=False) except ValidationError as ex: raise ModelValidationError( ex.messages, ex.field_name, ex.data, ex.valid_data, **ex.kwargs) from None From 38f7c56be300d008358b88a110f5b0ae56f94fab Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Thu, 31 Oct 2019 14:11:09 -0400 Subject: [PATCH 24/53] transpile_args[pass_manager_config].basis_gates --- qiskit/transpiler/transpile_circuit.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index 5c6b74b89768..dfb4f68e8524 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -50,9 +50,9 @@ def transpile_circuit(transpile_args): ms_basis_swap = None if 'rxx' in transpile_args['pass_manager_config'].basis_gates and \ not device_insts >= transpile_args['circuit'].count_ops().keys(): - ms_basis_swap = transpile_args['basis_gates'] - transpile_args['basis_gates'] = list(set(['u3', 'cx']).union( - transpile_args['basis_gates'])) + ms_basis_swap = transpile_args['pass_manager_config'].basis_gates + transpile_args['pass_manager_config'].basis_gates = list(set(['u3', 'cx']).union( + transpile_args['pass_manager_config'].basis_gates)) if level is None: level = 1 From af9a9149c876bf62fae8e516620505fa58027fdc Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Thu, 31 Oct 2019 15:06:36 -0400 Subject: [PATCH 25/53] callback at run time --- qiskit/transpiler/passmanager.py | 12 ++++++------ qiskit/transpiler/runningpassmanager.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/qiskit/transpiler/passmanager.py b/qiskit/transpiler/passmanager.py index 27280f87326a..9ffeae774750 100644 --- a/qiskit/transpiler/passmanager.py +++ b/qiskit/transpiler/passmanager.py @@ -165,7 +165,8 @@ def run(self, circuits, output_name=None, callback=None): Args: circuits (QuantumCircuit or list[QuantumCircuit]): circuit(s) to transform via all the registered passes. - output_name (str): + output_name (str): The output circuit name. If not given, the same as the + input circuit callback (func): A callback function that will be called after each pass execution. The function will be called with 5 keyword arguments: @@ -202,7 +203,7 @@ def callback_func(**kwargs): return self._run_several_circuits(circuits, output_name, callback) def _create_running_passmanager(self): - running_passmanager = RunningPassManager(self.max_iteration, self.callback) + running_passmanager = RunningPassManager(self.max_iteration) for pass_set in self._pass_sets: running_passmanager.append(pass_set['passes'], **pass_set['flow_controllers']) return running_passmanager @@ -216,13 +217,10 @@ def _in_parallel(circuit, pm_dill=None): def _run_several_circuits(self, circuits, output_name=None, callback=None): """Run all the passes on each of the circuits in the circuits list - - Args: - circuits (list[QuantumCircuit]): circuit to transform via all the registered passes - Returns: list[QuantumCircuit]: Transformed circuits. """ + # TODO support for List(output_name) and List(callback) return parallel_map(PassManager._in_parallel, circuits, task_kwargs={'pm_dill': dill.dumps(self)}) @@ -266,6 +264,8 @@ def callback_func(**kwargs): QuantumCircuit: Transformed circuit. """ running_passmanager = self._create_running_passmanager() + if callback is None and self.callback: # TODO to remove with __init__(callback) + callback = self.callback result = running_passmanager.run(circuit, output_name=output_name, callback=callback) self.property_set = running_passmanager.property_set return result diff --git a/qiskit/transpiler/runningpassmanager.py b/qiskit/transpiler/runningpassmanager.py index 5bbc71c18452..013df13f5310 100644 --- a/qiskit/transpiler/runningpassmanager.py +++ b/qiskit/transpiler/runningpassmanager.py @@ -32,14 +32,14 @@ class RunningPassManager: """A RunningPassManager is a running pass manager.""" - def __init__(self, max_iteration, callback): + def __init__(self, max_iteration): """Initialize an empty PassManager object (with no passes scheduled). Args: max_iteration (int): The schedule looping iterates until the condition is met or until max_iteration is reached. """ - self.callback = callback + self.callback = None # the pass manager's schedule of passes, including any control-flow. # Populated via PassManager.append(). self.working_list = [] From 5627f46234a54bd574a90b3c7cc06e480541f793 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Thu, 31 Oct 2019 15:10:08 -0400 Subject: [PATCH 26/53] lint --- qiskit/transpiler/passmanager.py | 6 ++++-- qiskit/transpiler/runningpassmanager.py | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/qiskit/transpiler/passmanager.py b/qiskit/transpiler/passmanager.py index 9ffeae774750..7a1c4a0d756e 100644 --- a/qiskit/transpiler/passmanager.py +++ b/qiskit/transpiler/passmanager.py @@ -14,9 +14,8 @@ """PassManager class for the transpiler.""" -from collections import OrderedDict -import dill import warnings +import dill from qiskit.visualization import pass_manager_drawer from qiskit.tools.parallel import parallel_map @@ -221,6 +220,9 @@ def _run_several_circuits(self, circuits, output_name=None, callback=None): list[QuantumCircuit]: Transformed circuits. """ # TODO support for List(output_name) and List(callback) + del output_name + del callback + return parallel_map(PassManager._in_parallel, circuits, task_kwargs={'pm_dill': dill.dumps(self)}) diff --git a/qiskit/transpiler/runningpassmanager.py b/qiskit/transpiler/runningpassmanager.py index 013df13f5310..6b5b3fe3876b 100644 --- a/qiskit/transpiler/runningpassmanager.py +++ b/qiskit/transpiler/runningpassmanager.py @@ -99,6 +99,7 @@ def run(self, circuit, output_name=None, callback=None): circuit (QuantumCircuit): circuit to transform via all the registered passes output_name (str): The output circuit name. If not given, the same as the input circuit + callback (callable): A callback function that will be called after each pass execution. Returns: QuantumCircuit: Transformed circuit. """ From 6b0b4bec6bb611eec47bcfb1352754016f07ee1b Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Sat, 2 Nov 2019 21:06:31 -0400 Subject: [PATCH 27/53] release note --- .../notes/defaults_TranspileConfig-4109a90c278d46df.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml diff --git a/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml b/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml new file mode 100644 index 000000000000..88185bf10392 --- /dev/null +++ b/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml @@ -0,0 +1,5 @@ +--- +other: + - | + The ``TranspileConfig`` was restructured to include only the information + needed to construct a ``PassManager`` and it was renamed to ``PassManagerConfig``. From ad5bb3a7e7328a26b6033af30a5f56d7d9e6391f Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 8 Nov 2019 12:41:52 -0500 Subject: [PATCH 28/53] docstring --- qiskit/transpiler/transpile_circuit.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index dfb4f68e8524..26476d717204 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -26,7 +26,14 @@ def transpile_circuit(transpile_args): """Select a PassManager and run a single circuit through it. Args: - transpile_args (dict): configuration dictating how to transpile + transpile_args (dict): configuration dictating how to transpile. + The format of the dictionary has the following format: + {'circuit': QuantumCircuit, + 'optimization_level': int, + 'pass_manager': PassManager, + 'output_name': string, + 'callback': callable, + 'pass_manager_config': PassManagerConfig} Returns: QuantumCircuit: transpiled circuit From b21e0b35faf2d9a5a4a909104122b43866c83ee9 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 8 Nov 2019 13:03:59 -0500 Subject: [PATCH 29/53] other -> upgrade --- .../notes/defaults_TranspileConfig-4109a90c278d46df.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml b/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml index 88185bf10392..0ddc2e5df490 100644 --- a/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml +++ b/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml @@ -1,5 +1,5 @@ --- -other: +upgrade: - | The ``TranspileConfig`` was restructured to include only the information needed to construct a ``PassManager`` and it was renamed to ``PassManagerConfig``. From 70aaf6c2193662cf1ec2b795cd7ded1154ef04de Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 8 Nov 2019 13:07:54 -0500 Subject: [PATCH 30/53] release note --- .../notes/defaults_TranspileConfig-4109a90c278d46df.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml b/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml index 0ddc2e5df490..8dd7bc979fb1 100644 --- a/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml +++ b/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml @@ -3,3 +3,7 @@ upgrade: - | The ``TranspileConfig`` was restructured to include only the information needed to construct a ``PassManager`` and it was renamed to ``PassManagerConfig``. +deprecations: + - | + ``PassManager(..., callback=..., ...)`` parameter is deprecated. The parameter now + can be set at run-time, ``PassManager.run(..., callback=callback,...)``. From dacb8be29d3e42e8f6b1879ac8691ed84138c380 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Wed, 11 Dec 2019 11:26:11 +0200 Subject: [PATCH 31/53] style --- qiskit/compiler/transpile.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index f67721804d78..0a92546387ba 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -179,9 +179,9 @@ def callback_func(**kwargs): # Get transpiler argument(s) to configure the circuit transpilation job(s) circuits = circuits if isinstance(circuits, list) else [circuits] transpile_args = _parse_transpile_args(circuits, backend, basis_gates, coupling_map, - backend_properties, initial_layout, - seed_transpiler, optimization_level, - pass_manager, callback, output_name) + backend_properties, initial_layout, + seed_transpiler, optimization_level, + pass_manager, callback, output_name) # Check circuit width against number of qubits in coupling_map(s) coupling_maps_list = list(config.coupling_map for config in transpile_args) for circuit, parsed_coupling_map in zip(circuits, coupling_maps_list): From 5ae9f1326c68966e1f58e557bf83d64da7ce15df Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Wed, 11 Dec 2019 13:17:16 +0200 Subject: [PATCH 32/53] fix --- qiskit/compiler/transpile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 0a92546387ba..5c01885905d9 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -183,7 +183,7 @@ def callback_func(**kwargs): seed_transpiler, optimization_level, pass_manager, callback, output_name) # Check circuit width against number of qubits in coupling_map(s) - coupling_maps_list = list(config.coupling_map for config in transpile_args) + coupling_maps_list = list(config['pass_manager_config'].coupling_map for config in transpile_args) for circuit, parsed_coupling_map in zip(circuits, coupling_maps_list): # If coupling_map is not None or n_qubits == 1 n_qubits = len(circuit.qubits) From 0c13b16addafb5ca7a7f5762c32a20ddffbc1b3f Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Tue, 17 Dec 2019 13:39:27 -0500 Subject: [PATCH 33/53] line too long --- qiskit/compiler/transpile.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 5c01885905d9..fb535fdda404 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -183,7 +183,8 @@ def callback_func(**kwargs): seed_transpiler, optimization_level, pass_manager, callback, output_name) # Check circuit width against number of qubits in coupling_map(s) - coupling_maps_list = list(config['pass_manager_config'].coupling_map for config in transpile_args) + coupling_maps_list = list(config['pass_manager_config'].coupling_map for config in + transpile_args) for circuit, parsed_coupling_map in zip(circuits, coupling_maps_list): # If coupling_map is not None or n_qubits == 1 n_qubits = len(circuit.qubits) From 09d0c90991f9d21e402abda7f9cd17c4a055837e Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 23 Dec 2019 14:26:59 -0500 Subject: [PATCH 34/53] reverse the changes in about parallel --- qiskit/compiler/transpile.py | 17 +++++++++++++++-- qiskit/transpiler/transpile_circuit.py | 8 ++------ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index fb535fdda404..0b705bb30b79 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -176,7 +176,7 @@ def callback_func(**kwargs): config = user_config.get_config() optimization_level = config.get('transpile_optimization_level', None) - # Get transpiler argument(s) to configure the circuit transpilation job(s) + # Get transpile_args to configure the circuit transpilation job(s) circuits = circuits if isinstance(circuits, list) else [circuits] transpile_args = _parse_transpile_args(circuits, backend, basis_gates, coupling_map, backend_properties, initial_layout, @@ -202,12 +202,25 @@ def callback_func(**kwargs): 'is greater than maximum ({}) '.format(max_qubits) + 'in the coupling_map') # Transpile circuits in parallel - circuits = parallel_map(transpile_circuit, transpile_args) + circuits = parallel_map(_transpile_circuit, list(zip(circuits, transpile_args))) if len(circuits) == 1: return circuits[0] return circuits +# FIXME: This is a helper function because of parallel tools. +def _transpile_circuit(circuit_config_tuple): + """Select a PassManager and run a single circuit through it. + Args: + circuit_config_tuple (tuple): + circuit (QuantumCircuit): circuit to transpile + transpile_config (TranspileConfig): configuration dictating how to transpile + Returns: + QuantumCircuit: transpiled circuit + """ + circuit, transpile_config = circuit_config_tuple + + return transpile_circuit(circuit, transpile_config) def _parse_transpile_args(circuits, backend, basis_gates, coupling_map, backend_properties, diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index 26476d717204..411ca06f0220 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -22,10 +22,10 @@ from qiskit.transpiler.exceptions import TranspilerError -def transpile_circuit(transpile_args): +def transpile_circuit(circuit, transpile_args): """Select a PassManager and run a single circuit through it. - Args: + circuit (QuantumCircuit): circuit to transpile transpile_args (dict): configuration dictating how to transpile. The format of the dictionary has the following format: {'circuit': QuantumCircuit, @@ -34,12 +34,8 @@ def transpile_circuit(transpile_args): 'output_name': string, 'callback': callable, 'pass_manager_config': PassManagerConfig} - Returns: QuantumCircuit: transpiled circuit - - Raises: - TranspilerError: if transpile_args is not valid or transpilation incurs error """ # either the pass manager is already selected... if transpile_args['pass_manager'] is not None: From 9ec86794377450ade7be97d5ac66b8aa191908a9 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 23 Dec 2019 14:30:55 -0500 Subject: [PATCH 35/53] rollback transpile_circuit --- qiskit/transpiler/transpile_circuit.py | 34 +++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index 411ca06f0220..1cf84d20ed01 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -22,7 +22,7 @@ from qiskit.transpiler.exceptions import TranspilerError -def transpile_circuit(circuit, transpile_args): +def transpile_circuit(circuit, transpile_config): """Select a PassManager and run a single circuit through it. Args: circuit (QuantumCircuit): circuit to transpile @@ -38,44 +38,44 @@ def transpile_circuit(circuit, transpile_args): QuantumCircuit: transpiled circuit """ # either the pass manager is already selected... - if transpile_args['pass_manager'] is not None: - pass_manager = transpile_args['pass_manager'] + if transpile_config['pass_manager'] is not None: + pass_manager = transpile_config['pass_manager'] # or we choose an appropriate one based on desired optimization level (default: level 1) else: - level = transpile_args['optimization_level'] + level = transpile_config['optimization_level'] # Workaround for ion trap support: If basis gates includes # Mølmer-Sørensen (rxx) and the circuit includes gates outside the basis, # first unroll to u3, cx, then run MSBasisDecomposer to target basis. basic_insts = ['measure', 'reset', 'barrier', 'snapshot'] - device_insts = set(transpile_args['pass_manager_config'].basis_gates).union(basic_insts) + device_insts = set(transpile_config['pass_manager_config'].basis_gates).union(basic_insts) ms_basis_swap = None - if 'rxx' in transpile_args['pass_manager_config'].basis_gates and \ - not device_insts >= transpile_args['circuit'].count_ops().keys(): - ms_basis_swap = transpile_args['pass_manager_config'].basis_gates - transpile_args['pass_manager_config'].basis_gates = list(set(['u3', 'cx']).union( - transpile_args['pass_manager_config'].basis_gates)) + if 'rxx' in transpile_config['pass_manager_config'].basis_gates and \ + not device_insts >= transpile_config['circuit'].count_ops().keys(): + ms_basis_swap = transpile_config['pass_manager_config'].basis_gates + transpile_config['pass_manager_config'].basis_gates = list(set(['u3', 'cx']).union( + transpile_config['pass_manager_config'].basis_gates)) if level is None: level = 1 if level == 0: - pass_manager = level_0_pass_manager(transpile_args['pass_manager_config']) + pass_manager = level_0_pass_manager(transpile_config['pass_manager_config']) elif level == 1: - pass_manager = level_1_pass_manager(transpile_args['pass_manager_config']) + pass_manager = level_1_pass_manager(transpile_config['pass_manager_config']) elif level == 2: - pass_manager = level_2_pass_manager(transpile_args['pass_manager_config']) + pass_manager = level_2_pass_manager(transpile_config['pass_manager_config']) elif level == 3: - pass_manager = level_3_pass_manager(transpile_args['pass_manager_config']) + pass_manager = level_3_pass_manager(transpile_config['pass_manager_config']) else: raise TranspilerError("optimization_level can range from 0 to 3.") if ms_basis_swap is not None: pass_manager.append(MSBasisDecomposer(ms_basis_swap)) - out_circuit = pass_manager.run(transpile_args['circuit'], - callback=transpile_args['callback'], - output_name=transpile_args['output_name']) + out_circuit = pass_manager.run(circuit, + callback=transpile_config['callback'], + output_name=transpile_config['output_name']) return out_circuit From 095c0ccc108b61111df3abab6f1a6e415ed6e2cd Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 23 Dec 2019 14:51:39 -0500 Subject: [PATCH 36/53] lint --- qiskit/compiler/transpile.py | 2 ++ qiskit/transpiler/transpile_circuit.py | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 0b705bb30b79..4abcf3cc81b4 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -208,6 +208,7 @@ def callback_func(**kwargs): return circuits[0] return circuits + # FIXME: This is a helper function because of parallel tools. def _transpile_circuit(circuit_config_tuple): """Select a PassManager and run a single circuit through it. @@ -222,6 +223,7 @@ def _transpile_circuit(circuit_config_tuple): return transpile_circuit(circuit, transpile_config) + def _parse_transpile_args(circuits, backend, basis_gates, coupling_map, backend_properties, initial_layout, seed_transpiler, optimization_level, diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index 1cf84d20ed01..5dd8fa8b790b 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -26,7 +26,7 @@ def transpile_circuit(circuit, transpile_config): """Select a PassManager and run a single circuit through it. Args: circuit (QuantumCircuit): circuit to transpile - transpile_args (dict): configuration dictating how to transpile. + transpile_config (dict): configuration dictating how to transpile. The format of the dictionary has the following format: {'circuit': QuantumCircuit, 'optimization_level': int, @@ -36,6 +36,8 @@ def transpile_circuit(circuit, transpile_config): 'pass_manager_config': PassManagerConfig} Returns: QuantumCircuit: transpiled circuit + Raises: + TranspilerError: if transpile_config is not valid or transpilation incurs error """ # either the pass manager is already selected... if transpile_config['pass_manager'] is not None: From 34aec1e29de24e58c064b5a8d3f22b932280ae90 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 23 Dec 2019 14:57:23 -0500 Subject: [PATCH 37/53] release note --- .../notes/defaults_TranspileConfig-4109a90c278d46df.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml b/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml index 8dd7bc979fb1..29eb0e591b9d 100644 --- a/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml +++ b/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml @@ -3,6 +3,12 @@ upgrade: - | The ``TranspileConfig`` was restructured to include only the information needed to construct a ``PassManager`` and it was renamed to ``PassManagerConfig``. + That information is: + - ``initial_layout`` + - ``basis_gates`` + - ``coupling_map`` + - ``backend_properties`` + - ``seed_transpiler`` deprecations: - | ``PassManager(..., callback=..., ...)`` parameter is deprecated. The parameter now From 66d838a7f87d212fe60fc523590963ebd3e40877 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 30 Dec 2019 10:23:35 -0500 Subject: [PATCH 38/53] expanding the parameters --- qiskit/compiler/transpile.py | 8 +++- qiskit/transpiler/transpile_circuit.py | 51 ++++++++++++-------------- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 803105138976..7c74889a65fe 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -221,7 +221,13 @@ def _transpile_circuit(circuit_config_tuple): """ circuit, transpile_config = circuit_config_tuple - return transpile_circuit(circuit, transpile_config) + return transpile_circuit(circuit, + transpile_config['optimization_level'], + transpile_config['pass_manager'], + transpile_config['output_name'], + transpile_config['callback'], + transpile_config['pass_manager_config'] + ) def _parse_transpile_args(circuits, backend, diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index 5dd8fa8b790b..6a34fca081e5 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -22,62 +22,59 @@ from qiskit.transpiler.exceptions import TranspilerError -def transpile_circuit(circuit, transpile_config): +def transpile_circuit(circuit, + optimization_level, + pass_manager, + output_name, + callback, + pass_manager_config): """Select a PassManager and run a single circuit through it. Args: circuit (QuantumCircuit): circuit to transpile - transpile_config (dict): configuration dictating how to transpile. - The format of the dictionary has the following format: - {'circuit': QuantumCircuit, - 'optimization_level': int, - 'pass_manager': PassManager, - 'output_name': string, - 'callback': callable, - 'pass_manager_config': PassManagerConfig} + optimization_level (int): + pass_manager (PassManager): + output_name (string): + callback (callable): + pass_manager_config (PassManagerConfig): Returns: QuantumCircuit: transpiled circuit Raises: TranspilerError: if transpile_config is not valid or transpilation incurs error """ # either the pass manager is already selected... - if transpile_config['pass_manager'] is not None: - pass_manager = transpile_config['pass_manager'] - # or we choose an appropriate one based on desired optimization level (default: level 1) - else: - level = transpile_config['optimization_level'] + if pass_manager is None: + level = optimization_level # Workaround for ion trap support: If basis gates includes # Mølmer-Sørensen (rxx) and the circuit includes gates outside the basis, # first unroll to u3, cx, then run MSBasisDecomposer to target basis. basic_insts = ['measure', 'reset', 'barrier', 'snapshot'] - device_insts = set(transpile_config['pass_manager_config'].basis_gates).union(basic_insts) + device_insts = set(pass_manager_config.basis_gates).union(basic_insts) ms_basis_swap = None - if 'rxx' in transpile_config['pass_manager_config'].basis_gates and \ - not device_insts >= transpile_config['circuit'].count_ops().keys(): - ms_basis_swap = transpile_config['pass_manager_config'].basis_gates - transpile_config['pass_manager_config'].basis_gates = list(set(['u3', 'cx']).union( - transpile_config['pass_manager_config'].basis_gates)) + if 'rxx' in pass_manager_config.basis_gates and \ + not device_insts >= circuit.count_ops().keys(): + ms_basis_swap = pass_manager_config.basis_gates + pass_manager_config.basis_gates = list( + set(['u3', 'cx']).union(pass_manager_config.basis_gates)) if level is None: level = 1 if level == 0: - pass_manager = level_0_pass_manager(transpile_config['pass_manager_config']) + pass_manager = level_0_pass_manager(pass_manager_config) elif level == 1: - pass_manager = level_1_pass_manager(transpile_config['pass_manager_config']) + pass_manager = level_1_pass_manager(pass_manager_config) elif level == 2: - pass_manager = level_2_pass_manager(transpile_config['pass_manager_config']) + pass_manager = level_2_pass_manager(pass_manager_config) elif level == 3: - pass_manager = level_3_pass_manager(transpile_config['pass_manager_config']) + pass_manager = level_3_pass_manager(pass_manager_config) else: raise TranspilerError("optimization_level can range from 0 to 3.") if ms_basis_swap is not None: pass_manager.append(MSBasisDecomposer(ms_basis_swap)) - out_circuit = pass_manager.run(circuit, - callback=transpile_config['callback'], - output_name=transpile_config['output_name']) + out_circuit = pass_manager.run(circuit, callback=callback, output_name=output_name) return out_circuit From 63e3e68f2cc97156d93f9476bd5dd8de5356d365 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 30 Dec 2019 10:44:26 -0500 Subject: [PATCH 39/53] remove optimization level --- qiskit/compiler/transpile.py | 33 +++++++++++-- qiskit/transpiler/transpile_circuit.py | 67 ++++++++------------------ 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 7c74889a65fe..3969774939fc 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -22,6 +22,10 @@ from qiskit import user_config from qiskit.transpiler.exceptions import TranspilerError from qiskit.converters import isinstanceint, isinstancelist +from qiskit.transpiler.preset_passmanagers import (level_0_pass_manager, + level_1_pass_manager, + level_2_pass_manager, + level_3_pass_manager) def transpile(circuits, @@ -218,16 +222,37 @@ def _transpile_circuit(circuit_config_tuple): transpile_config (TranspileConfig): configuration dictating how to transpile Returns: QuantumCircuit: transpiled circuit + Raises: + TranspilerError: if transpile_config is not valid or transpilation incurs error """ circuit, transpile_config = circuit_config_tuple + pass_manager_config = transpile_config['pass_manager_config'] + + if transpile_config['pass_manager'] is not None: + pass_manager = transpile_config['pass_manager'] + else: + if transpile_config['optimization_level'] is not None: + level = transpile_config['optimization_level'] + else: + level = 1 + + if level == 0: + pass_manager = level_0_pass_manager(pass_manager_config) + elif level == 1: + pass_manager = level_1_pass_manager(pass_manager_config) + elif level == 2: + pass_manager = level_2_pass_manager(pass_manager_config) + elif level == 3: + pass_manager = level_3_pass_manager(pass_manager_config) + else: + raise TranspilerError("optimization_level can range from 0 to 3.") + return transpile_circuit(circuit, - transpile_config['optimization_level'], - transpile_config['pass_manager'], + pass_manager, transpile_config['output_name'], transpile_config['callback'], - transpile_config['pass_manager_config'] - ) + pass_manager_config) def _parse_transpile_args(circuits, backend, diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index 6a34fca081e5..867a2dbd9e9e 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -14,16 +14,10 @@ """Circuit transpile function""" -from qiskit.transpiler.preset_passmanagers import (level_0_pass_manager, - level_1_pass_manager, - level_2_pass_manager, - level_3_pass_manager) from qiskit.transpiler.passes.ms_basis_decomposer import MSBasisDecomposer -from qiskit.transpiler.exceptions import TranspilerError def transpile_circuit(circuit, - optimization_level, pass_manager, output_name, callback, @@ -31,49 +25,30 @@ def transpile_circuit(circuit, """Select a PassManager and run a single circuit through it. Args: circuit (QuantumCircuit): circuit to transpile - optimization_level (int): - pass_manager (PassManager): - output_name (string): - callback (callable): - pass_manager_config (PassManagerConfig): + pass_manager (PassManager): The pass manager to use for a custom pipeline of + transpiler passes. + output_name (string): To identify the output circuits + callback (callable): Function that will be called after each pass execution. + pass_manager_config (PassManagerConfig): Configuration instance. + Returns: QuantumCircuit: transpiled circuit - Raises: - TranspilerError: if transpile_config is not valid or transpilation incurs error """ - # either the pass manager is already selected... - if pass_manager is None: - level = optimization_level - - # Workaround for ion trap support: If basis gates includes - # Mølmer-Sørensen (rxx) and the circuit includes gates outside the basis, - # first unroll to u3, cx, then run MSBasisDecomposer to target basis. - basic_insts = ['measure', 'reset', 'barrier', 'snapshot'] - device_insts = set(pass_manager_config.basis_gates).union(basic_insts) - - ms_basis_swap = None - if 'rxx' in pass_manager_config.basis_gates and \ - not device_insts >= circuit.count_ops().keys(): - ms_basis_swap = pass_manager_config.basis_gates - pass_manager_config.basis_gates = list( - set(['u3', 'cx']).union(pass_manager_config.basis_gates)) - - if level is None: - level = 1 - - if level == 0: - pass_manager = level_0_pass_manager(pass_manager_config) - elif level == 1: - pass_manager = level_1_pass_manager(pass_manager_config) - elif level == 2: - pass_manager = level_2_pass_manager(pass_manager_config) - elif level == 3: - pass_manager = level_3_pass_manager(pass_manager_config) - else: - raise TranspilerError("optimization_level can range from 0 to 3.") - - if ms_basis_swap is not None: - pass_manager.append(MSBasisDecomposer(ms_basis_swap)) + # Workaround for ion trap support: If basis gates includes + # Mølmer-Sørensen (rxx) and the circuit includes gates outside the basis, + # first unroll to u3, cx, then run MSBasisDecomposer to target basis. + basic_insts = ['measure', 'reset', 'barrier', 'snapshot'] + device_insts = set(pass_manager_config.basis_gates).union(basic_insts) + + ms_basis_swap = None + if 'rxx' in pass_manager_config.basis_gates and \ + not device_insts >= circuit.count_ops().keys(): + ms_basis_swap = pass_manager_config.basis_gates + pass_manager_config.basis_gates = list( + set(['u3', 'cx']).union(pass_manager_config.basis_gates)) + + if ms_basis_swap is not None: + pass_manager.append(MSBasisDecomposer(ms_basis_swap)) out_circuit = pass_manager.run(circuit, callback=callback, output_name=output_name) From 078979a6727e91c2449d4bb63723df467e6f6134 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 30 Dec 2019 10:59:52 -0500 Subject: [PATCH 40/53] remove pass_manager_config as a transpile_circuit arg --- qiskit/compiler/transpile.py | 28 ++++++++++++++++++++++---- qiskit/transpiler/transpile_circuit.py | 22 +------------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 3969774939fc..de9c4203d47c 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -22,6 +22,7 @@ from qiskit import user_config from qiskit.transpiler.exceptions import TranspilerError from qiskit.converters import isinstanceint, isinstancelist +from qiskit.transpiler.passes.ms_basis_decomposer import MSBasisDecomposer from qiskit.transpiler.preset_passmanagers import (level_0_pass_manager, level_1_pass_manager, level_2_pass_manager, @@ -213,13 +214,18 @@ def callback_func(**kwargs): return circuits -# FIXME: This is a helper function because of parallel tools. def _transpile_circuit(circuit_config_tuple): """Select a PassManager and run a single circuit through it. Args: circuit_config_tuple (tuple): circuit (QuantumCircuit): circuit to transpile - transpile_config (TranspileConfig): configuration dictating how to transpile + transpile_config (dict): configuration dictating how to transpile. The format of the + dictionary has the following format: + {'optimization_level': int, + 'pass_manager': PassManager, + 'output_name': string, + 'callback': callable, + 'pass_manager_config': PassManagerConfig} Returns: QuantumCircuit: transpiled circuit Raises: @@ -229,6 +235,18 @@ def _transpile_circuit(circuit_config_tuple): pass_manager_config = transpile_config['pass_manager_config'] + # Workaround for ion trap support: If basis gates includes + # Mølmer-Sørensen (rxx) and the circuit includes gates outside the basis, + # first unroll to u3, cx, then run MSBasisDecomposer to target basis. + basic_insts = ['measure', 'reset', 'barrier', 'snapshot'] + device_insts = set(pass_manager_config.basis_gates).union(basic_insts) + ms_basis_swap = None + if 'rxx' in pass_manager_config.basis_gates and \ + not device_insts >= circuit.count_ops().keys(): + ms_basis_swap = pass_manager_config.basis_gates + pass_manager_config.basis_gates = list( + set(['u3', 'cx']).union(pass_manager_config.basis_gates)) + if transpile_config['pass_manager'] is not None: pass_manager = transpile_config['pass_manager'] else: @@ -248,11 +266,13 @@ def _transpile_circuit(circuit_config_tuple): else: raise TranspilerError("optimization_level can range from 0 to 3.") + if ms_basis_swap is not None: + pass_manager.append(MSBasisDecomposer(ms_basis_swap)) + return transpile_circuit(circuit, pass_manager, transpile_config['output_name'], - transpile_config['callback'], - pass_manager_config) + transpile_config['callback']) def _parse_transpile_args(circuits, backend, diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index 867a2dbd9e9e..4088c8db2220 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -14,14 +14,11 @@ """Circuit transpile function""" -from qiskit.transpiler.passes.ms_basis_decomposer import MSBasisDecomposer - def transpile_circuit(circuit, pass_manager, output_name, - callback, - pass_manager_config): + callback): """Select a PassManager and run a single circuit through it. Args: circuit (QuantumCircuit): circuit to transpile @@ -29,27 +26,10 @@ def transpile_circuit(circuit, transpiler passes. output_name (string): To identify the output circuits callback (callable): Function that will be called after each pass execution. - pass_manager_config (PassManagerConfig): Configuration instance. Returns: QuantumCircuit: transpiled circuit """ - # Workaround for ion trap support: If basis gates includes - # Mølmer-Sørensen (rxx) and the circuit includes gates outside the basis, - # first unroll to u3, cx, then run MSBasisDecomposer to target basis. - basic_insts = ['measure', 'reset', 'barrier', 'snapshot'] - device_insts = set(pass_manager_config.basis_gates).union(basic_insts) - - ms_basis_swap = None - if 'rxx' in pass_manager_config.basis_gates and \ - not device_insts >= circuit.count_ops().keys(): - ms_basis_swap = pass_manager_config.basis_gates - pass_manager_config.basis_gates = list( - set(['u3', 'cx']).union(pass_manager_config.basis_gates)) - - if ms_basis_swap is not None: - pass_manager.append(MSBasisDecomposer(ms_basis_swap)) - out_circuit = pass_manager.run(circuit, callback=callback, output_name=output_name) return out_circuit From 570c1f144360d1022e4078e6a6a78799bbee2c70 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 30 Dec 2019 11:07:39 -0500 Subject: [PATCH 41/53] output_name and callback are optional --- qiskit/transpiler/transpile_circuit.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index 4088c8db2220..5ea3f497417d 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -17,8 +17,8 @@ def transpile_circuit(circuit, pass_manager, - output_name, - callback): + output_name: None, + callback: None): """Select a PassManager and run a single circuit through it. Args: circuit (QuantumCircuit): circuit to transpile From 15f4dd4bd7de35cc9922d9d0190e099d5c57dd80 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 30 Dec 2019 14:43:01 -0500 Subject: [PATCH 42/53] Update qiskit/compiler/transpile.py Co-Authored-By: Ali Javadi-Abhari --- qiskit/compiler/transpile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index de9c4203d47c..76a475b29531 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -219,7 +219,7 @@ def _transpile_circuit(circuit_config_tuple): Args: circuit_config_tuple (tuple): circuit (QuantumCircuit): circuit to transpile - transpile_config (dict): configuration dictating how to transpile. The format of the + transpile_config (dict): configuration dictating how to transpile. The dictionary has the following format: {'optimization_level': int, 'pass_manager': PassManager, From fa007a0dac0f9f72ef575eb4235265c235974583 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 13 Jan 2020 16:48:31 -0300 Subject: [PATCH 43/53] documentation --- qiskit/transpiler/pass_manager_config.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/qiskit/transpiler/pass_manager_config.py b/qiskit/transpiler/pass_manager_config.py index b6ac6d184800..ff4f6b3a2a00 100644 --- a/qiskit/transpiler/pass_manager_config.py +++ b/qiskit/transpiler/pass_manager_config.py @@ -26,9 +26,12 @@ class PassManagerConfig(BaseModel): full description of the model, please check ``PassManagerConfigSchema``. Attributes: - optimization_level (int): a non-negative integer indicating the - optimization level. 0 means no transformation on the circuit. Higher - levels may produce more optimized circuits, but may take longer. + initial_layout (Layout): Initial position of virtual qubits on physical qubits. + basis_gates (list): List of basis gate names to unroll to. + coupling_map (CouplingMap): Directed graph represented a coupling map. + backend_properties (BackendProperties): Properties returned by a backend, including + information on gate errors, readout errors, qubit coherence times, etc. + seed_transpiler (int): Sets random seed for the stochastic parts of the transpiler. """ def __init__(self, From 6ed96777669fbbfa71bb2205edc7e22fe04dcfbe Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 13 Jan 2020 16:58:57 -0300 Subject: [PATCH 44/53] parse callback --- qiskit/compiler/transpile.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 76a475b29531..308b7e7e8770 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -302,11 +302,12 @@ def _parse_transpile_args(circuits, backend, optimization_level = _parse_optimization_level(optimization_level, num_circuits) pass_manager = _parse_pass_manager(pass_manager, num_circuits) output_name = _parse_output_name(output_name, num_circuits) + callback = _parse_callback(callback, num_circuits) transpile_args_circuits = [] for args in zip(basis_gates, coupling_map, backend_properties, initial_layout, seed_transpiler, optimization_level, - pass_manager, output_name, circuits): + pass_manager, output_name, circuits, callback): transpile_args = {'pass_manager_config': PassManagerConfig(basis_gates=args[0], coupling_map=args[1], backend_properties=args[2], @@ -316,7 +317,7 @@ def _parse_transpile_args(circuits, backend, 'pass_manager': args[6], 'output_name': args[7], 'circuit': args[8], - 'callback': callback} + 'callback': args[9]} transpile_args_circuits.append(transpile_args) return transpile_args_circuits @@ -428,6 +429,12 @@ def _parse_pass_manager(pass_manager, num_circuits): return pass_manager +def _parse_callback(callback, num_circuits): + if not isinstance(callback, list): + callback = [callback] * num_circuits + return callback + + def _parse_output_name(output_name, num_circuits): # naming and returning circuits # output_name could be either a string or a list From 7ec5cebc246ab13f444b921b7cdd7084fdae5ad6 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 13 Jan 2020 17:02:25 -0300 Subject: [PATCH 45/53] remove circuit from transpile_args --- qiskit/compiler/transpile.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 308b7e7e8770..efaf7df00556 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -307,7 +307,7 @@ def _parse_transpile_args(circuits, backend, transpile_args_circuits = [] for args in zip(basis_gates, coupling_map, backend_properties, initial_layout, seed_transpiler, optimization_level, - pass_manager, output_name, circuits, callback): + pass_manager, output_name, callback): transpile_args = {'pass_manager_config': PassManagerConfig(basis_gates=args[0], coupling_map=args[1], backend_properties=args[2], @@ -316,8 +316,7 @@ def _parse_transpile_args(circuits, backend, 'optimization_level': args[5], 'pass_manager': args[6], 'output_name': args[7], - 'circuit': args[8], - 'callback': args[9]} + 'callback': args[8]} transpile_args_circuits.append(transpile_args) return transpile_args_circuits From 08b68ea3d73f6278c6afd156e14a5a78ffd34957 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 13 Jan 2020 17:03:59 -0300 Subject: [PATCH 46/53] Update qiskit/transpiler/transpile_circuit.py Co-Authored-By: Ali Javadi-Abhari --- qiskit/transpiler/transpile_circuit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index 5ea3f497417d..7c6d45b92dac 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -24,7 +24,7 @@ def transpile_circuit(circuit, circuit (QuantumCircuit): circuit to transpile pass_manager (PassManager): The pass manager to use for a custom pipeline of transpiler passes. - output_name (string): To identify the output circuits + output_name (string): name of output circuit callback (callable): Function that will be called after each pass execution. Returns: From 4c87790db9a4440964b7f2daf0b943303d1054ff Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 13 Jan 2020 17:05:06 -0300 Subject: [PATCH 47/53] rename transpile_args_circuits to list_transpile_args.append --- qiskit/compiler/transpile.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index efaf7df00556..2fc3486b61c7 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -304,7 +304,7 @@ def _parse_transpile_args(circuits, backend, output_name = _parse_output_name(output_name, num_circuits) callback = _parse_callback(callback, num_circuits) - transpile_args_circuits = [] + list_transpile_args = [] for args in zip(basis_gates, coupling_map, backend_properties, initial_layout, seed_transpiler, optimization_level, pass_manager, output_name, callback): @@ -317,9 +317,9 @@ def _parse_transpile_args(circuits, backend, 'pass_manager': args[6], 'output_name': args[7], 'callback': args[8]} - transpile_args_circuits.append(transpile_args) + list_transpile_args.append(transpile_args) - return transpile_args_circuits + return list_transpile_args def _parse_basis_gates(basis_gates, backend, circuits): From 7d811efa391dee08215990d94cf54d1c29d16253 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 13 Jan 2020 18:21:28 -0300 Subject: [PATCH 48/53] new path for passes --- qiskit/compiler/transpile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 2fc3486b61c7..f9c0347ade3d 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -22,7 +22,7 @@ from qiskit import user_config from qiskit.transpiler.exceptions import TranspilerError from qiskit.converters import isinstanceint, isinstancelist -from qiskit.transpiler.passes.ms_basis_decomposer import MSBasisDecomposer +from qiskit.transpiler.passes.basis.ms_basis_decomposer import MSBasisDecomposer from qiskit.transpiler.preset_passmanagers import (level_0_pass_manager, level_1_pass_manager, level_2_pass_manager, From e1d7f10da29d7993a5518e5dd79f12fda5680ee2 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 24 Jan 2020 15:26:18 -0300 Subject: [PATCH 49/53] back to old _parse_coupling_map --- qiskit/compiler/transpile.py | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index f9c0347ade3d..447db31e4990 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -295,7 +295,7 @@ def _parse_transpile_args(circuits, backend, num_circuits = len(circuits) basis_gates = _parse_basis_gates(basis_gates, backend, circuits) - coupling_map = _parse_coupling_map(coupling_map, backend, circuits) + coupling_map = _parse_coupling_map(coupling_map, backend, num_circuits) backend_properties = _parse_backend_properties(backend_properties, backend, num_circuits) initial_layout = _parse_initial_layout(initial_layout, circuits) seed_transpiler = _parse_seed_transpiler(seed_transpiler, num_circuits) @@ -342,8 +342,7 @@ def _parse_basis_gates(basis_gates, backend, circuits): return basis_gates -def _parse_coupling_map(coupling_map, backend, circuits): - num_circuits = len(circuits) +def _parse_coupling_map(coupling_map, backend, num_circuits): # try getting coupling_map from user, else backend if coupling_map is None: if getattr(backend, 'configuration', None): @@ -351,21 +350,14 @@ def _parse_coupling_map(coupling_map, backend, circuits): if hasattr(configuration, 'coupling_map') and configuration.coupling_map: coupling_map = CouplingMap(configuration.coupling_map) - coupling_map = [coupling_map] * num_circuits + # coupling_map could be None, or a list of lists, e.g. [[0, 1], [2, 1]] + if coupling_map is None or isinstance(coupling_map, CouplingMap): + coupling_map = [coupling_map] * num_circuits + elif isinstance(coupling_map, list) and all(isinstance(i, list) and len(i) == 2 + for i in coupling_map): + coupling_map = [coupling_map] * num_circuits - for index, parsed_coupling_map in enumerate(coupling_map): - if isinstance(parsed_coupling_map, list): - parsed_coupling_map = CouplingMap(parsed_coupling_map) - # If coupling_map is not None - if isinstance(parsed_coupling_map, CouplingMap): - n_qubits = len(circuits[index].qubits) - max_qubits = parsed_coupling_map.size() - if n_qubits > max_qubits: - raise TranspilerError('Number of qubits ({}) '.format(n_qubits) + - 'in {} '.format(circuits[index].name) + - 'is greater than maximum ({}) '.format(max_qubits) + - 'in the coupling_map') - coupling_map[index] = parsed_coupling_map + coupling_map = [CouplingMap(cm) if isinstance(cm, list) else cm for cm in coupling_map] return coupling_map From 7ad1521f25eee06d4c6d05741a382b5659934bc5 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 24 Jan 2020 15:34:35 -0300 Subject: [PATCH 50/53] undoing _parse_output_name --- qiskit/compiler/transpile.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 447db31e4990..785dd2aaa18d 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -301,7 +301,7 @@ def _parse_transpile_args(circuits, backend, seed_transpiler = _parse_seed_transpiler(seed_transpiler, num_circuits) optimization_level = _parse_optimization_level(optimization_level, num_circuits) pass_manager = _parse_pass_manager(pass_manager, num_circuits) - output_name = _parse_output_name(output_name, num_circuits) + output_name = _parse_output_name(output_name, circuits) callback = _parse_callback(callback, num_circuits) list_transpile_args = [] @@ -426,13 +426,13 @@ def _parse_callback(callback, num_circuits): return callback -def _parse_output_name(output_name, num_circuits): +def _parse_output_name(output_name, circuits): # naming and returning circuits # output_name could be either a string or a list if output_name is not None: if isinstance(output_name, str): # single circuit - if num_circuits == 1: + if len(circuits) == 1: return [output_name] # multiple circuits else: @@ -440,7 +440,7 @@ def _parse_output_name(output_name, num_circuits): "to that of the number of circuits " + "being transpiled") elif isinstance(output_name, list): - if num_circuits == len(output_name) and \ + if len(circuits) == len(output_name) and \ all(isinstance(name, str) for name in output_name): return output_name else: @@ -452,4 +452,4 @@ def _parse_output_name(output_name, num_circuits): raise TranspilerError("The parameter output_name should be a string or a" "list of strings: %s was used." % type(output_name)) else: - return [None] * num_circuits + return [circuit.name for circuit in circuits] From b84e270ac83a1dbfc3d493da7abe69751843f8bd Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 24 Jan 2020 19:07:32 -0300 Subject: [PATCH 51/53] comments on the transpiler configuration --- qiskit/compiler/transpile.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index 785dd2aaa18d..e07c7d248dd6 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -248,8 +248,10 @@ def _transpile_circuit(circuit_config_tuple): set(['u3', 'cx']).union(pass_manager_config.basis_gates)) if transpile_config['pass_manager'] is not None: + # either the pass manager is already selected... pass_manager = transpile_config['pass_manager'] else: + # or we choose an appropriate one based on desired optimization level (default: level 1) if transpile_config['optimization_level'] is not None: level = transpile_config['optimization_level'] else: From 346b8ea216fdf402b67ffc40e77c85c10ccd0179 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 24 Jan 2020 19:11:22 -0300 Subject: [PATCH 52/53] docstring --- qiskit/transpiler/transpile_circuit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py index 7c6d45b92dac..769f5e89ec83 100644 --- a/qiskit/transpiler/transpile_circuit.py +++ b/qiskit/transpiler/transpile_circuit.py @@ -19,7 +19,7 @@ def transpile_circuit(circuit, pass_manager, output_name: None, callback: None): - """Select a PassManager and run a single circuit through it. + """Runs the ``pass_manager`` PassManager with single circuit through it. Args: circuit (QuantumCircuit): circuit to transpile pass_manager (PassManager): The pass manager to use for a custom pipeline of From 8d935be56ad4cf22cb11f8b525995c3381ba7a70 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 3 Feb 2020 15:43:39 -0500 Subject: [PATCH 53/53] remove transpile_circuit --- qiskit/compiler/transpile.py | 7 ++-- qiskit/transpiler/__init__.py | 9 ----- qiskit/transpiler/transpile_circuit.py | 35 ------------------- ...ults_TranspileConfig-4109a90c278d46df.yaml | 3 ++ 4 files changed, 5 insertions(+), 49 deletions(-) delete mode 100644 qiskit/transpiler/transpile_circuit.py diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index e07c7d248dd6..b10cfe331ae0 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -16,7 +16,6 @@ from qiskit.transpiler import Layout, CouplingMap from qiskit.tools.parallel import parallel_map from qiskit.transpiler.pass_manager_config import PassManagerConfig -from qiskit.transpiler.transpile_circuit import transpile_circuit from qiskit.pulse import Schedule from qiskit.circuit.quantumregister import Qubit from qiskit import user_config @@ -271,10 +270,8 @@ def _transpile_circuit(circuit_config_tuple): if ms_basis_swap is not None: pass_manager.append(MSBasisDecomposer(ms_basis_swap)) - return transpile_circuit(circuit, - pass_manager, - transpile_config['output_name'], - transpile_config['callback']) + return pass_manager.run(circuit, callback=transpile_config['callback'], + output_name=transpile_config['output_name']) def _parse_transpile_args(circuits, backend, diff --git a/qiskit/transpiler/__init__.py b/qiskit/transpiler/__init__.py index 9a11eb4d8aba..4eb221197dc2 100644 --- a/qiskit/transpiler/__init__.py +++ b/qiskit/transpiler/__init__.py @@ -19,14 +19,6 @@ .. currentmodule:: qiskit.transpiler -Circuit Transpilation -===================== - -.. autosummary:: - :toctree: ../stubs/ - - transpile_circuit - Pass Managment ============== @@ -73,4 +65,3 @@ from .basepasses import AnalysisPass, TransformationPass from .coupling import CouplingMap from .layout import Layout -from .transpile_circuit import transpile_circuit diff --git a/qiskit/transpiler/transpile_circuit.py b/qiskit/transpiler/transpile_circuit.py deleted file mode 100644 index 769f5e89ec83..000000000000 --- a/qiskit/transpiler/transpile_circuit.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: utf-8 -*- - -# This code is part of Qiskit. -# -# (C) Copyright IBM 2017, 2019. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -"""Circuit transpile function""" - - -def transpile_circuit(circuit, - pass_manager, - output_name: None, - callback: None): - """Runs the ``pass_manager`` PassManager with single circuit through it. - Args: - circuit (QuantumCircuit): circuit to transpile - pass_manager (PassManager): The pass manager to use for a custom pipeline of - transpiler passes. - output_name (string): name of output circuit - callback (callable): Function that will be called after each pass execution. - - Returns: - QuantumCircuit: transpiled circuit - """ - out_circuit = pass_manager.run(circuit, callback=callback, output_name=output_name) - - return out_circuit diff --git a/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml b/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml index 29eb0e591b9d..119448743bcb 100644 --- a/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml +++ b/releasenotes/notes/defaults_TranspileConfig-4109a90c278d46df.yaml @@ -13,3 +13,6 @@ deprecations: - | ``PassManager(..., callback=..., ...)`` parameter is deprecated. The parameter now can be set at run-time, ``PassManager.run(..., callback=callback,...)``. + - | + The function ``transpile_circuit`` is deprecated. To transpile a circuit a + passmanager's ``run`` method should be called ``PassManager.run(cirucit, ...)``. \ No newline at end of file