add_passes -> append (#1508)

This commit is contained in:
Luciano 2018-12-15 21:26:44 -05:00 committed by Ali Javadi-Abhari
parent b9d9060592
commit 3de24f4fa2
5 changed files with 70 additions and 70 deletions

View File

@ -51,7 +51,7 @@ print(compiled_standard.qasm())
# 2. custom compile -- customize PassManager to run specific circuit transformations
from qiskit.transpiler.passes import CXCancellation
pm = transpiler.PassManager()
pm.add_passes(CXCancellation())
pm.append(CXCancellation())
dags = transpiler.transpile(circ, backend_device, pass_manager=pm)
[compiled_custom] = dags
print(compiled_custom.qasm())

View File

@ -11,7 +11,7 @@ The main goal of Qiskit Terra's transpiler is to provide an extensible infrastru
### Pass Manager
- A `PassManager` instance determines the schedule for running registered passes.
- The pass manager is in charge of deciding the next pass to run, not the pass itself.
- Registering passes in the pass manager pipeline is done by the `add_passes` method.
- Registering passes in the pass manager pipeline is done by the `append` method.
- While registering, you can specify basic control primitives over each pass (conditionals and loops).
- Options to control the scheduler:
- Passes can have arguments at init time that can affect their scheduling. If you want to set properties related to how the pass is run, you can do so by accessing these properties (e.g. pass_.max_iteration = 10).
@ -50,7 +50,7 @@ self.passmanager.add_flow_controller('do_x_times', DoXTimesController)
This allows to use the parameter `do_x_times`, which needs to be a callable. In this case, this is used to parametrized the plugin, so it will for-loop 3 times.
```
self.passmanager.add_passes([Pass()], do_x_times=lambda x : 3)
self.passmanager.append([Pass()], do_x_times=lambda x : 3)
```
@ -60,10 +60,10 @@ The `CxCancellation` requires and preserves `ToffoliDecompose`. Same for `Rotati
```
pm = PassManager()
pm.add_passes(CxCancellation()) # requires: ToffoliDecompose / preserves: ToffoliDecompose
pm.add_passes(RotationMerge()) # requires: ToffoliDecompose / preserves: ToffoliDecompose
pm.add_passes(Mapper(coupling_map=coupling_map)) # requires: [] / preserves: []
pm.add_passes(CxCancellation())
pm.append(CxCancellation()) # requires: ToffoliDecompose / preserves: ToffoliDecompose
pm.append(RotationMerge()) # requires: ToffoliDecompose / preserves: ToffoliDecompose
pm.append(Mapper(coupling_map=coupling_map)) # requires: [] / preserves: []
pm.append(CxCancellation())
```
Given the above, the pass manager executes the following sequence of passes:
@ -79,9 +79,9 @@ Given the above, the pass manager executes the following sequence of passes:
A pass behavior can be heavily influenced by its parameters. For example, unrolling using some basis gates is totally different than unrolling to different gates. And a PassManager might use both.
```
pm.add_passes(Unroller(basis_gates=['id','u1','u2','u3','cx']))
pm.add_passes(...)
pm.add_passes(Unroller(basis_gates=['U','CX']))
pm.append(Unroller(basis_gates=['id','u1','u2','u3','cx']))
pm.append(...)
pm.append(Unroller(basis_gates=['U','CX']))
```
where (from `qelib1.inc`):
@ -101,7 +101,7 @@ There are cases when one or more passes have to be run repeatedly, until a condi
```
pm = PassManager()
pm.add_passes([CxCancellation(), RotationMerge(), CalculateDepth()],
pm.append([CxCancellation(), RotationMerge(), CalculateDepth()],
do_while=lambda property_set: not property_set['fixed_point']['depth'])
```
The control argument `do_while` will run these passes until the callable returns `False`. The callable always takes in one argument, the pass manager's property set. In this example, `CalculateDepth` is an analysis pass that updates the property `depth` in the property set.
@ -110,9 +110,9 @@ The control argument `do_while` will run these passes until the callable returns
The pass manager developer can avoid one or more passes by making them conditional (on a property in the property set):
```
pm.add_passes(LayoutMapper(coupling_map))
pm.add_passes(CheckIfMapped(coupling_map))
pm.add_passes(BasicMapper(coupling_map),
pm.append(LayoutMapper(coupling_map))
pm.append(CheckIfMapped(coupling_map))
pm.append(BasicMapper(coupling_map),
condition=lambda property_set: not property_set['is_mapped'])
```

View File

@ -31,7 +31,7 @@ class PassManager():
max_iteration is reached.
"""
# the pass manager's schedule of passes, including any control-flow.
# Populated via PassManager.add_passes().
# Populated via PassManager.append().
self.working_list = []
# global property set is the context of the circuit held by the pass manager
@ -50,7 +50,7 @@ class PassManager():
def _join_options(self, passset_options):
""" Set the options of each passset, based on precedence rules:
passset options (set via ``PassManager.add_passes()``) override
passset options (set via ``PassManager.append()``) override
passmanager options (set via ``PassManager.__init__()``), which override Default.
.
"""
@ -62,8 +62,8 @@ class PassManager():
passset_level = {k: v for k, v in passset_options.items() if v is not None}
return {**default, **passmanager_level, **passset_level}
def add_passes(self, passes, ignore_requires=None, ignore_preserves=None, max_iteration=None,
**flow_controller_conditions):
def append(self, passes, ignore_requires=None, ignore_preserves=None, max_iteration=None,
**flow_controller_conditions):
"""
Args:
passes (list[BasePass] or BasePass): pass(es) to be added to schedule

View File

@ -93,7 +93,7 @@ class TestTranspiler(QiskitTestCase):
dag_circuit = circuit_to_dag(circuit)
pass_manager = PassManager()
pass_manager.add_passes(CXCancellation())
pass_manager.append(CXCancellation())
dag_circuit = transpile_dag(dag_circuit, pass_manager=pass_manager)
resources_after = dag_circuit.count_ops()
@ -116,13 +116,13 @@ class TestTranspiler(QiskitTestCase):
coupling_map = Coupling(couplinglist=[(0, 1), (0, 2)])
pass_manager = PassManager()
pass_manager.add_passes(LookaheadMapper(coupling_map))
pass_manager.append(LookaheadMapper(coupling_map))
mapped_dag = transpile_dag(original_dag, pass_manager=pass_manager)
self.assertEqual(original_dag, mapped_dag)
second_pass_manager = PassManager()
second_pass_manager.add_passes(LookaheadMapper(coupling_map))
second_pass_manager.append(LookaheadMapper(coupling_map))
remapped_dag = transpile_dag(mapped_dag, pass_manager=second_pass_manager)
self.assertEqual(mapped_dag, remapped_dag)
@ -142,7 +142,7 @@ class TestTranspiler(QiskitTestCase):
coupling_map = Coupling(couplinglist=[(0, 1), (1, 2)])
pass_manager = PassManager()
pass_manager.add_passes([LookaheadMapper(coupling_map)])
pass_manager.append([LookaheadMapper(coupling_map)])
mapped_dag = transpile_dag(dag_circuit, pass_manager=pass_manager)
self.assertEqual(mapped_dag.count_ops().get('swap', 0),
@ -170,7 +170,7 @@ class TestTranspiler(QiskitTestCase):
coupling_map = Coupling(couplinglist=[(0, 1), (1, 2)])
pass_manager = PassManager()
pass_manager.add_passes([LookaheadMapper(coupling_map)])
pass_manager.append([LookaheadMapper(coupling_map)])
mapped_dag = transpile_dag(dag_circuit, pass_manager=pass_manager)
self.assertEqual(mapped_dag.count_ops().get('swap', 0),

View File

@ -66,10 +66,10 @@ class TestUseCases(SchedulerTestCase):
def test_chain(self):
""" A single chain of passes, with Requests and Preserves."""
self.passmanager.add_passes(PassC_TP_RA_PA()) # Request: PassA / Preserves: PassA
self.passmanager.add_passes(PassB_TP_RA_PA()) # Request: PassA / Preserves: PassA
self.passmanager.add_passes(PassD_TP_NR_NP(argument1=[1, 2])) # Requires: {}/ Preserves: {}
self.passmanager.add_passes(PassB_TP_RA_PA())
self.passmanager.append(PassC_TP_RA_PA()) # Request: PassA / Preserves: PassA
self.passmanager.append(PassB_TP_RA_PA()) # Request: PassA / Preserves: PassA
self.passmanager.append(PassD_TP_NR_NP(argument1=[1, 2])) # Requires: {}/ Preserves: {}
self.passmanager.append(PassB_TP_RA_PA())
self.assertScheduler(self.dag, self.passmanager, ['run transformation pass PassA_TP_NR_NP',
'run transformation pass PassC_TP_RA_PA',
'run transformation pass PassB_TP_RA_PA',
@ -80,25 +80,25 @@ class TestUseCases(SchedulerTestCase):
def test_conditional_passes_true(self):
""" A pass set with a conditional parameter. The callable is True. """
self.passmanager.add_passes(PassE_AP_NR_NP(True))
self.passmanager.add_passes(PassA_TP_NR_NP(),
condition=lambda property_set: property_set['property'])
self.passmanager.append(PassE_AP_NR_NP(True))
self.passmanager.append(PassA_TP_NR_NP(),
condition=lambda property_set: property_set['property'])
self.assertScheduler(self.dag, self.passmanager, ['run analysis pass PassE_AP_NR_NP',
'set property as True',
'run transformation pass PassA_TP_NR_NP'])
def test_conditional_passes_false(self):
""" A pass set with a conditional parameter. The callable is False. """
self.passmanager.add_passes(PassE_AP_NR_NP(False))
self.passmanager.add_passes(PassA_TP_NR_NP(),
condition=lambda property_set: property_set['property'])
self.passmanager.append(PassE_AP_NR_NP(False))
self.passmanager.append(PassA_TP_NR_NP(),
condition=lambda property_set: property_set['property'])
self.assertScheduler(self.dag, self.passmanager, ['run analysis pass PassE_AP_NR_NP',
'set property as False'])
def test_conditional_and_loop(self):
""" Run a conditional first, then a loop"""
self.passmanager.add_passes(PassE_AP_NR_NP(True))
self.passmanager.add_passes(
self.passmanager.append(PassE_AP_NR_NP(True))
self.passmanager.append(
[PassK_check_fixed_point_property(),
PassA_TP_NR_NP(),
PassF_reduce_dag_property()],
@ -155,8 +155,8 @@ class TestUseCases(SchedulerTestCase):
FlowController.remove_flow_controller('condition')
FlowController.add_flow_controller('condition', ConditionalController)
self.passmanager.add_passes(PassK_check_fixed_point_property())
self.passmanager.add_passes(
self.passmanager.append(PassK_check_fixed_point_property())
self.passmanager.append(
[PassK_check_fixed_point_property(),
PassA_TP_NR_NP(),
PassF_reduce_dag_property()],
@ -209,22 +209,22 @@ class TestUseCases(SchedulerTestCase):
def test_do_not_repeat_based_on_preservation(self):
""" When a pass is still a valid pass (because following passes preserved it), it should not
run again"""
self.passmanager.add_passes([PassB_TP_RA_PA(), PassA_TP_NR_NP(), PassB_TP_RA_PA()])
self.passmanager.append([PassB_TP_RA_PA(), PassA_TP_NR_NP(), PassB_TP_RA_PA()])
self.assertScheduler(self.dag, self.passmanager, ['run transformation pass PassA_TP_NR_NP',
'run transformation pass PassB_TP_RA_PA'])
def test_do_not_repeat_based_on_idempotence(self):
""" Repetition can be optimized to a single execution when the pass is idempotent"""
self.passmanager.add_passes(PassA_TP_NR_NP())
self.passmanager.add_passes([PassA_TP_NR_NP(), PassA_TP_NR_NP()])
self.passmanager.add_passes(PassA_TP_NR_NP())
self.passmanager.append(PassA_TP_NR_NP())
self.passmanager.append([PassA_TP_NR_NP(), PassA_TP_NR_NP()])
self.passmanager.append(PassA_TP_NR_NP())
self.assertScheduler(self.dag, self.passmanager, ['run transformation pass PassA_TP_NR_NP'])
def test_non_idempotent_pass(self):
""" Two or more runs of a non-idempotent pass cannot be optimized. """
self.passmanager.add_passes(PassF_reduce_dag_property())
self.passmanager.add_passes([PassF_reduce_dag_property(), PassF_reduce_dag_property()])
self.passmanager.add_passes(PassF_reduce_dag_property())
self.passmanager.append(PassF_reduce_dag_property())
self.passmanager.append([PassF_reduce_dag_property(), PassF_reduce_dag_property()])
self.passmanager.append(PassF_reduce_dag_property())
self.assertScheduler(self.dag, self.passmanager,
['run transformation pass PassF_reduce_dag_property',
'dag property = 6',
@ -237,7 +237,7 @@ class TestUseCases(SchedulerTestCase):
def test_fenced_property_set(self):
""" Transformation passes are not allowed to modified the property set. """
self.passmanager.add_passes(PassH_Bad_TP())
self.passmanager.append(PassH_Bad_TP())
self.assertSchedulerRaises(self.dag, self.passmanager,
['run transformation pass PassH_Bad_TP'],
TranspilerAccessError)
@ -253,7 +253,7 @@ class TestUseCases(SchedulerTestCase):
circ.cx(qr[1], qr[0])
dag = circuit_to_dag(circ)
self.passmanager.add_passes(PassI_Bad_AP())
self.passmanager.append(PassI_Bad_AP())
self.assertSchedulerRaises(dag, self.passmanager,
['run analysis pass PassI_Bad_AP',
'cx_runs: {(5, 6, 7, 8)}'],
@ -263,10 +263,10 @@ class TestUseCases(SchedulerTestCase):
""" A pass manager that ignores requests does not run the passes decleared in the 'requests'
field of the passes."""
passmanager = PassManager(ignore_requires=True)
passmanager.add_passes(PassC_TP_RA_PA()) # Request: PassA / Preserves: PassA
passmanager.add_passes(PassB_TP_RA_PA()) # Request: PassA / Preserves: PassA
passmanager.add_passes(PassD_TP_NR_NP(argument1=[1, 2])) # Requires: {} / Preserves: {}
passmanager.add_passes(PassB_TP_RA_PA())
passmanager.append(PassC_TP_RA_PA()) # Request: PassA / Preserves: PassA
passmanager.append(PassB_TP_RA_PA()) # Request: PassA / Preserves: PassA
passmanager.append(PassD_TP_NR_NP(argument1=[1, 2])) # Requires: {} / Preserves: {}
passmanager.append(PassB_TP_RA_PA())
self.assertScheduler(self.dag, passmanager, ['run transformation pass PassC_TP_RA_PA',
'run transformation pass PassB_TP_RA_PA',
'run transformation pass PassD_TP_NR_NP',
@ -277,10 +277,10 @@ class TestUseCases(SchedulerTestCase):
""" A pass manager that ignores preserves does not record the passes decleared in the
'preserves' field of the passes as valid passes."""
passmanager = PassManager(ignore_preserves=True)
passmanager.add_passes(PassC_TP_RA_PA()) # Request: PassA / Preserves: PassA
passmanager.add_passes(PassB_TP_RA_PA()) # Request: PassA / Preserves: PassA
passmanager.add_passes(PassD_TP_NR_NP(argument1=[1, 2])) # Requires: {} / Preserves: {}
passmanager.add_passes(PassB_TP_RA_PA())
passmanager.append(PassC_TP_RA_PA()) # Request: PassA / Preserves: PassA
passmanager.append(PassB_TP_RA_PA()) # Request: PassA / Preserves: PassA
passmanager.append(PassD_TP_NR_NP(argument1=[1, 2])) # Requires: {} / Preserves: {}
passmanager.append(PassB_TP_RA_PA())
self.assertScheduler(self.dag, passmanager, ['run transformation pass PassA_TP_NR_NP',
'run transformation pass PassC_TP_RA_PA',
'run transformation pass PassA_TP_NR_NP',
@ -294,9 +294,9 @@ class TestUseCases(SchedulerTestCase):
""" A pass manager that considers every pass as not idempotent, allows the immediate
repetition of a pass"""
passmanager = PassManager(ignore_preserves=True)
passmanager.add_passes(PassA_TP_NR_NP())
passmanager.add_passes(PassA_TP_NR_NP()) # Normally removed for optimization, not here.
passmanager.add_passes(PassB_TP_RA_PA()) # Normally required is ignored for optimization,
passmanager.append(PassA_TP_NR_NP())
passmanager.append(PassA_TP_NR_NP()) # Normally removed for optimization, not here.
passmanager.append(PassB_TP_RA_PA()) # Normally required is ignored for optimization,
# not here
self.assertScheduler(self.dag, passmanager, ['run transformation pass PassA_TP_NR_NP',
'run transformation pass PassA_TP_NR_NP',
@ -306,7 +306,7 @@ class TestUseCases(SchedulerTestCase):
def test_pass_non_idempotence_passset(self):
""" A pass set that is not idempotent. """
passmanager = PassManager()
passmanager.add_passes([PassA_TP_NR_NP(), PassB_TP_RA_PA()], ignore_preserves=True)
passmanager.append([PassA_TP_NR_NP(), PassB_TP_RA_PA()], ignore_preserves=True)
self.assertScheduler(self.dag, passmanager, ['run transformation pass PassA_TP_NR_NP',
'run transformation pass PassA_TP_NR_NP',
'run transformation pass PassB_TP_RA_PA'])
@ -314,8 +314,8 @@ class TestUseCases(SchedulerTestCase):
def test_analysis_pass_is_idempotent(self):
""" Analysis passes are idempotent. """
passmanager = PassManager()
passmanager.add_passes(PassE_AP_NR_NP(argument1=1))
passmanager.add_passes(PassE_AP_NR_NP(argument1=1))
passmanager.append(PassE_AP_NR_NP(argument1=1))
passmanager.append(PassE_AP_NR_NP(argument1=1))
self.assertScheduler(self.dag, passmanager, ['run analysis pass PassE_AP_NR_NP',
'set property as 1'])
@ -323,9 +323,9 @@ class TestUseCases(SchedulerTestCase):
""" A default transformation does not preserves anything and analysis passes
need to be re-run"""
passmanager = PassManager()
passmanager.add_passes(PassE_AP_NR_NP(argument1=1))
passmanager.add_passes(PassA_TP_NR_NP())
passmanager.add_passes(PassE_AP_NR_NP(argument1=1))
passmanager.append(PassE_AP_NR_NP(argument1=1))
passmanager.append(PassA_TP_NR_NP())
passmanager.append(PassE_AP_NR_NP(argument1=1))
self.assertScheduler(self.dag, passmanager, ['run analysis pass PassE_AP_NR_NP',
'set property as 1',
'run transformation pass PassA_TP_NR_NP',
@ -340,20 +340,20 @@ class TestUseCases(SchedulerTestCase):
"""
passmanager = PassManager(ignore_preserves=False, ignore_requires=True)
tp_pass = PassA_TP_NR_NP()
passmanager.add_passes(tp_pass, ignore_preserves=True)
passmanager.append(tp_pass, ignore_preserves=True)
the_pass_in_the_workinglist = next(iter(passmanager.working_list))
self.assertTrue(the_pass_in_the_workinglist.options['ignore_preserves'])
self.assertTrue(the_pass_in_the_workinglist.options['ignore_requires'])
def test_pass_no_return_a_dag(self):
""" Passes instances with same arguments (independently of the order) are the same. """
self.passmanager.add_passes(PassJ_Bad_NoReturn())
self.passmanager.append(PassJ_Bad_NoReturn())
self.assertSchedulerRaises(self.dag, self.passmanager,
['run transformation pass PassJ_Bad_NoReturn'], TranspilerError)
def test_fixed_point_pass(self):
""" A pass set with a do_while parameter that checks for a fixed point. """
self.passmanager.add_passes(
self.passmanager.append(
[PassK_check_fixed_point_property(),
PassA_TP_NR_NP(),
PassF_reduce_dag_property()],
@ -404,7 +404,7 @@ class TestUseCases(SchedulerTestCase):
def test_fixed_point_pass_max_iteration(self):
""" A pass set with a do_while parameter that checks that the max_iteration is raised. """
self.passmanager.add_passes(
self.passmanager.append(
[PassK_check_fixed_point_property(),
PassA_TP_NR_NP(),
PassF_reduce_dag_property()],
@ -448,7 +448,7 @@ class TestControlFlowPlugin(SchedulerTestCase):
def test_control_flow_plugin(self):
""" Adds a control flow plugin with a single parameter and runs it. """
FlowController.add_flow_controller('do_x_times', DoXTimesController)
self.passmanager.add_passes([PassB_TP_RA_PA(), PassC_TP_RA_PA()], do_x_times=lambda x: 3)
self.passmanager.append([PassB_TP_RA_PA(), PassC_TP_RA_PA()], do_x_times=lambda x: 3)
self.assertScheduler(self.dag, self.passmanager, ['run transformation pass PassA_TP_NR_NP',
'run transformation pass PassB_TP_RA_PA',
'run transformation pass PassC_TP_RA_PA',
@ -464,8 +464,8 @@ class TestControlFlowPlugin(SchedulerTestCase):
self.assertEqual(controllers_length - 1, len(FlowController.registered_controllers))
FlowController.add_flow_controller('do_while', DoWhileController)
self.assertEqual(controllers_length, len(FlowController.registered_controllers))
self.passmanager.add_passes([PassB_TP_RA_PA(), PassC_TP_RA_PA()],
do_while=lambda property_set: True, max_iteration=2)
self.passmanager.append([PassB_TP_RA_PA(), PassC_TP_RA_PA()],
do_while=lambda property_set: True, max_iteration=2)
self.assertSchedulerRaises(self.dag, self.passmanager,
['run transformation pass PassA_TP_NR_NP',
'run transformation pass PassB_TP_RA_PA',