Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GraphState circuit depth excedingly high using optimization_levels 2 & 3 #5694

Closed
nonhermitian opened this issue Jan 25, 2021 · 3 comments · Fixed by #5702
Closed

GraphState circuit depth excedingly high using optimization_levels 2 & 3 #5694

nonhermitian opened this issue Jan 25, 2021 · 3 comments · Fixed by #5702
Labels
bug Something isn't working

Comments

@nonhermitian
Copy link
Contributor

Information

  • Qiskit Terra version: latest
  • Python version:
  • Operating system:

What is the current behavior?

The following graph state fits exactly on the device (72 CX), but optimization_level 2 or 3 transpiles it to ~950 CX gates:

backend = pro.get_backend('ibmq_manhattan')
config = backend.configuration()

rows = [x[0] for x in config.coupling_map]
cols = [x[1] for x in config.coupling_map]

A = np.zeros((65, 65))
A[rows, cols] = 1

qc = qiskit.circuit.library.GraphState(A)
qc.measure_all()

trans_qc = transpile(qc, backend, optimization_level=3)

Steps to reproduce the problem

What is the expected behavior?

Suggested solutions

@nonhermitian nonhermitian added the bug Something isn't working label Jan 25, 2021
@mtreinish
Copy link
Member

I added a callback to your script and printed the depth after each pass. Basically:

def callback(**kwargs):
    print(kwargs['pass_'])
    print(kwargs['dag'].depth())

trans_qc = transpile(qc, backend, optimization_level=3, callback=callback)

The issue here is the CSPLayout is not able to realize the graph state circuit matches a trivial layout and it chooses a suboptimal initial layout and causes stochastic swap to run greatly increasing the number of CX gates. While level 1 tries a trivial layout realizes it's a matches and skips DenseLayout and stochastic swap. I'm not sure the best path to go about fixing this, but maybe to add trying a trivial layout first to level2 and level3's passmanagers before using the CSP layout.

The raw output I got was:

Level 3
<qiskit.transpiler.passes.basis.unroll_3q_or_more.Unroll3qOrMore object at 0x7fb538416a00>
28
<qiskit.transpiler.passes.optimization.remove_reset_in_zero_state.RemoveResetInZeroState object at 0x7fb51f116eb0>
28
<qiskit.transpiler.passes.optimization.optimize_swap_before_measure.OptimizeSwapBeforeMeasure object at 0x7fb51f116f70>
28
<qiskit.transpiler.passes.optimization.remove_diagonal_gates_before_measure.RemoveDiagonalGatesBeforeMeasure object at 0x7fb51f116fa0>
28
<qiskit.transpiler.passes.layout.set_layout.SetLayout object at 0x7fb538416af0>
28
<qiskit.transpiler.passes.layout.csp_layout.CSPLayout object at 0x7fb538416b50>
28
<qiskit.transpiler.passes.layout.dense_layout.DenseLayout object at 0x7fb538416be0>
28
<qiskit.transpiler.passes.layout.full_ancilla_allocation.FullAncillaAllocation object at 0x7fb538416d00>
28
<qiskit.transpiler.passes.layout.enlarge_with_ancilla.EnlargeWithAncilla object at 0x7fb538416d60>
28
<qiskit.transpiler.passes.layout.apply_layout.ApplyLayout object at 0x7fb538416df0>
28
<qiskit.transpiler.passes.utils.check_map.CheckMap object at 0x7fb538416e80>
28
<qiskit.transpiler.passes.utils.barrier_before_final_measurements.BarrierBeforeFinalMeasurements object at 0x7fb538416ee0>
28
<qiskit.transpiler.passes.routing.stochastic_swap.StochasticSwap object at 0x7fb538416f40>
89
<qiskit.transpiler.passes.basis.unroll_custom_definitions.UnrollCustomDefinitions object at 0x7fb538416eb0>
89
<qiskit.transpiler.passes.basis.basis_translator.BasisTranslator object at 0x7fb538416fd0>
543
<qiskit.transpiler.passes.analysis.depth.Depth object at 0x7fb51f116d30>
543
<qiskit.transpiler.passes.utils.fixed_point.FixedPoint object at 0x7fb51f116d90>
543
<qiskit.transpiler.passes.optimization.collect_2q_blocks.Collect2qBlocks object at 0x7fb51f0a00d0>
543
<qiskit.transpiler.passes.optimization.consolidate_blocks.ConsolidateBlocks object at 0x7fb51f0a0160>
391
<qiskit.transpiler.passes.synthesis.unitary_synthesis.UnitarySynthesis object at 0x7fb51f0a0190>
477
<qiskit.transpiler.passes.optimization.optimize_1q_decomposition.Optimize1qGatesDecomposition object at 0x7fb51f0a0370>
344
<qiskit.transpiler.passes.optimization.commutation_analysis.CommutationAnalysis object at 0x7fb51f0a04c0>
344
<qiskit.transpiler.passes.optimization.commutative_cancellation.CommutativeCancellation object at 0x7fb51f0a0460>
335
<qiskit.transpiler.passes.basis.unroll_custom_definitions.UnrollCustomDefinitions object at 0x7fb538416eb0>
335
<qiskit.transpiler.passes.basis.basis_translator.BasisTranslator object at 0x7fb538416fd0>
370
<qiskit.transpiler.passes.analysis.depth.Depth object at 0x7fb51f116d30>
370
<qiskit.transpiler.passes.utils.fixed_point.FixedPoint object at 0x7fb51f116d90>
370
<qiskit.transpiler.passes.optimization.collect_2q_blocks.Collect2qBlocks object at 0x7fb51f0a00d0>
370
<qiskit.transpiler.passes.optimization.consolidate_blocks.ConsolidateBlocks object at 0x7fb51f0a0160>
357
<qiskit.transpiler.passes.synthesis.unitary_synthesis.UnitarySynthesis object at 0x7fb51f0a0190>
366
<qiskit.transpiler.passes.optimization.optimize_1q_decomposition.Optimize1qGatesDecomposition object at 0x7fb51f0a0370>
335
<qiskit.transpiler.passes.optimization.commutation_analysis.CommutationAnalysis object at 0x7fb51f0a04c0>
335
<qiskit.transpiler.passes.optimization.commutative_cancellation.CommutativeCancellation object at 0x7fb51f0a0460>
332
<qiskit.transpiler.passes.basis.unroll_custom_definitions.UnrollCustomDefinitions object at 0x7fb538416eb0>
332
<qiskit.transpiler.passes.basis.basis_translator.BasisTranslator object at 0x7fb538416fd0>
340
<qiskit.transpiler.passes.analysis.depth.Depth object at 0x7fb51f116d30>
340
<qiskit.transpiler.passes.utils.fixed_point.FixedPoint object at 0x7fb51f116d90>
340
<qiskit.transpiler.passes.optimization.collect_2q_blocks.Collect2qBlocks object at 0x7fb51f0a00d0>
340
<qiskit.transpiler.passes.optimization.consolidate_blocks.ConsolidateBlocks object at 0x7fb51f0a0160>
336
<qiskit.transpiler.passes.synthesis.unitary_synthesis.UnitarySynthesis object at 0x7fb51f0a0190>
336
<qiskit.transpiler.passes.optimization.optimize_1q_decomposition.Optimize1qGatesDecomposition object at 0x7fb51f0a0370>
336
<qiskit.transpiler.passes.optimization.commutation_analysis.CommutationAnalysis object at 0x7fb51f0a04c0>
336
<qiskit.transpiler.passes.optimization.commutative_cancellation.CommutativeCancellation object at 0x7fb51f0a0460>
333
<qiskit.transpiler.passes.basis.unroll_custom_definitions.UnrollCustomDefinitions object at 0x7fb538416eb0>
333
<qiskit.transpiler.passes.basis.basis_translator.BasisTranslator object at 0x7fb538416fd0>
333
<qiskit.transpiler.passes.analysis.depth.Depth object at 0x7fb51f116d30>
333
<qiskit.transpiler.passes.utils.fixed_point.FixedPoint object at 0x7fb51f116d90>
333
<qiskit.transpiler.passes.optimization.collect_2q_blocks.Collect2qBlocks object at 0x7fb51f0a00d0>
333
<qiskit.transpiler.passes.optimization.consolidate_blocks.ConsolidateBlocks object at 0x7fb51f0a0160>
333
<qiskit.transpiler.passes.synthesis.unitary_synthesis.UnitarySynthesis object at 0x7fb51f0a0190>
333
<qiskit.transpiler.passes.optimization.optimize_1q_decomposition.Optimize1qGatesDecomposition object at 0x7fb51f0a0370>
333
<qiskit.transpiler.passes.optimization.commutation_analysis.CommutationAnalysis object at 0x7fb51f0a04c0>
333
<qiskit.transpiler.passes.optimization.commutative_cancellation.CommutativeCancellation object at 0x7fb51f0a0460>
333
<qiskit.transpiler.passes.basis.unroll_custom_definitions.UnrollCustomDefinitions object at 0x7fb538416eb0>
333
<qiskit.transpiler.passes.basis.basis_translator.BasisTranslator object at 0x7fb538416fd0>
333
<qiskit.transpiler.passes.analysis.depth.Depth object at 0x7fb51f116d30>
333
<qiskit.transpiler.passes.utils.fixed_point.FixedPoint object at 0x7fb51f116d90>
333
<qiskit.transpiler.passes.optimization.collect_2q_blocks.Collect2qBlocks object at 0x7fb51f0a00d0>
333
<qiskit.transpiler.passes.optimization.consolidate_blocks.ConsolidateBlocks object at 0x7fb51f0a0160>
333
<qiskit.transpiler.passes.synthesis.unitary_synthesis.UnitarySynthesis object at 0x7fb51f0a0190>
333
<qiskit.transpiler.passes.optimization.optimize_1q_decomposition.Optimize1qGatesDecomposition object at 0x7fb51f0a0370>
333
<qiskit.transpiler.passes.optimization.commutation_analysis.CommutationAnalysis object at 0x7fb51f0a04c0>
333
<qiskit.transpiler.passes.optimization.commutative_cancellation.CommutativeCancellation object at 0x7fb51f0a0460>
333
<qiskit.transpiler.passes.basis.unroll_custom_definitions.UnrollCustomDefinitions object at 0x7fb538416eb0>
333
<qiskit.transpiler.passes.basis.basis_translator.BasisTranslator object at 0x7fb538416fd0>
333
<qiskit.transpiler.passes.optimization.remove_reset_in_zero_state.RemoveResetInZeroState object at 0x7fb51f116eb0>
333

Level 2
<qiskit.transpiler.passes.layout.set_layout.SetLayout object at 0x7fb538507ee0>
28
<qiskit.transpiler.passes.layout.csp_layout.CSPLayout object at 0x7fb538507e50>
28
<qiskit.transpiler.passes.layout.dense_layout.DenseLayout object at 0x7fb538507e20>
28
<qiskit.transpiler.passes.layout.full_ancilla_allocation.FullAncillaAllocation object at 0x7fb538507d30>
28
<qiskit.transpiler.passes.layout.enlarge_with_ancilla.EnlargeWithAncilla object at 0x7fb538507d00>
28
<qiskit.transpiler.passes.layout.apply_layout.ApplyLayout object at 0x7fb51ec42550>
28
<qiskit.transpiler.passes.basis.unroll_3q_or_more.Unroll3qOrMore object at 0x7fb51ec42610>
28
<qiskit.transpiler.passes.utils.check_map.CheckMap object at 0x7fb51f13d490>
28
<qiskit.transpiler.passes.utils.barrier_before_final_measurements.BarrierBeforeFinalMeasurements object at 0x7fb51f26c640>
28
<qiskit.transpiler.passes.routing.stochastic_swap.StochasticSwap object at 0x7fb51ed9ee50>
96
<qiskit.transpiler.passes.basis.unroll_custom_definitions.UnrollCustomDefinitions object at 0x7fb51ed9edf0>
96
<qiskit.transpiler.passes.basis.basis_translator.BasisTranslator object at 0x7fb51ed9e610>
592
<qiskit.transpiler.passes.optimization.remove_reset_in_zero_state.RemoveResetInZeroState object at 0x7fb51ed9ebe0>
592
<qiskit.transpiler.passes.analysis.depth.Depth object at 0x7fb51ed9edc0>
592
<qiskit.transpiler.passes.utils.fixed_point.FixedPoint object at 0x7fb51ed9e8e0>
592
<qiskit.transpiler.passes.optimization.optimize_1q_decomposition.Optimize1qGatesDecomposition object at 0x7fb51ed9e370>
320
<qiskit.transpiler.passes.optimization.commutation_analysis.CommutationAnalysis object at 0x7fb51ed9ecd0>
320
<qiskit.transpiler.passes.optimization.commutative_cancellation.CommutativeCancellation object at 0x7fb51ed9e9a0>
320
<qiskit.transpiler.passes.basis.unroll_custom_definitions.UnrollCustomDefinitions object at 0x7fb51ed9edf0>
320
<qiskit.transpiler.passes.basis.basis_translator.BasisTranslator object at 0x7fb51ed9e610>
320
<qiskit.transpiler.passes.analysis.depth.Depth object at 0x7fb51ed9edc0>
320
<qiskit.transpiler.passes.utils.fixed_point.FixedPoint object at 0x7fb51ed9e8e0>
320
<qiskit.transpiler.passes.optimization.optimize_1q_decomposition.Optimize1qGatesDecomposition object at 0x7fb51ed9e370>
320
<qiskit.transpiler.passes.optimization.commutation_analysis.CommutationAnalysis object at 0x7fb51ed9ecd0>
320
<qiskit.transpiler.passes.optimization.commutative_cancellation.CommutativeCancellation object at 0x7fb51ed9e9a0>
320
<qiskit.transpiler.passes.basis.unroll_custom_definitions.UnrollCustomDefinitions object at 0x7fb51ed9edf0>
320
<qiskit.transpiler.passes.basis.basis_translator.BasisTranslator object at 0x7fb51ed9e610>
320
<qiskit.transpiler.passes.analysis.depth.Depth object at 0x7fb51ed9edc0>
320
<qiskit.transpiler.passes.utils.fixed_point.FixedPoint object at 0x7fb51ed9e8e0>
320
<qiskit.transpiler.passes.optimization.optimize_1q_decomposition.Optimize1qGatesDecomposition object at 0x7fb51ed9e370>
320
<qiskit.transpiler.passes.optimization.commutation_analysis.CommutationAnalysis object at 0x7fb51ed9ecd0>
320
<qiskit.transpiler.passes.optimization.commutative_cancellation.CommutativeCancellation object at 0x7fb51ed9e9a0>
320
<qiskit.transpiler.passes.basis.unroll_custom_definitions.UnrollCustomDefinitions object at 0x7fb51ed9edf0>
320
<qiskit.transpiler.passes.basis.basis_translator.BasisTranslator object at 0x7fb51ed9e610>
320

Level 1
<qiskit.transpiler.passes.layout.set_layout.SetLayout object at 0x7fb51ee50ca0>
28
<qiskit.transpiler.passes.layout.trivial_layout.TrivialLayout object at 0x7fb51edf7700>
28
<qiskit.transpiler.passes.layout.layout_2q_distance.Layout2qDistance object at 0x7fb51ebffb20>
28
<qiskit.transpiler.passes.layout.full_ancilla_allocation.FullAncillaAllocation object at 0x7fb51ee162e0>
28
<qiskit.transpiler.passes.layout.enlarge_with_ancilla.EnlargeWithAncilla object at 0x7fb51ee16760>
28
<qiskit.transpiler.passes.layout.apply_layout.ApplyLayout object at 0x7fb51f049a60>
28
<qiskit.transpiler.passes.basis.unroll_3q_or_more.Unroll3qOrMore object at 0x7fb51eef1cd0>
28
<qiskit.transpiler.passes.utils.check_map.CheckMap object at 0x7fb51ee95100>
28
<qiskit.transpiler.passes.basis.unroll_custom_definitions.UnrollCustomDefinitions object at 0x7fb51ef01190>
28
<qiskit.transpiler.passes.basis.basis_translator.BasisTranslator object at 0x7fb51f102190>
335
<qiskit.transpiler.passes.optimization.remove_reset_in_zero_state.RemoveResetInZeroState object at 0x7fb51f06b0a0>
335
<qiskit.transpiler.passes.analysis.depth.Depth object at 0x7fb51ecae790>
335
<qiskit.transpiler.passes.utils.fixed_point.FixedPoint object at 0x7fb51ecae5b0>
335
<qiskit.transpiler.passes.optimization.optimize_1q_decomposition.Optimize1qGatesDecomposition object at 0x7fb51eef92e0>
84
<qiskit.transpiler.passes.optimization.cx_cancellation.CXCancellation object at 0x7fb51eef98b0>
84
<qiskit.transpiler.passes.analysis.depth.Depth object at 0x7fb51ecae790>
84
<qiskit.transpiler.passes.utils.fixed_point.FixedPoint object at 0x7fb51ecae5b0>
84
<qiskit.transpiler.passes.optimization.optimize_1q_decomposition.Optimize1qGatesDecomposition object at 0x7fb51eef92e0>
84
<qiskit.transpiler.passes.optimization.cx_cancellation.CXCancellation object at 0x7fb51eef98b0>
84
<qiskit.transpiler.passes.analysis.depth.Depth object at 0x7fb51ecae790>
84
<qiskit.transpiler.passes.utils.fixed_point.FixedPoint object at 0x7fb51ecae5b0>
84
<qiskit.transpiler.passes.optimization.optimize_1q_decomposition.Optimize1qGatesDecomposition object at 0x7fb51eef92e0>
84
<qiskit.transpiler.passes.optimization.cx_cancellation.CXCancellation object at 0x7fb51eef98b0>
84

mtreinish added a commit to mtreinish/qiskit-core that referenced this issue Jan 25, 2021
In the preset passmanagers level2 and level3 the initial layout is
generated by the CSP layout pass and then if an answer can't be found
the specified layout method is used instead. However, as was reported in
issue Qiskit#5694 the CSP layout completely misses when the trivial layout case
perfectly maps the input circuit to the device. This results in level 1
significantly out performing level2 and level3 because it has to go to
routing and inserts a lot of swaps. To address this hole in the CSP
layout case this commit updates the preset passmanagers for level 2 and
level 3 to always try a trivial layout first, if this doesn't result in
a perfect mapping the pass is unchanged it will use CSP layout and then
the configured layout method.

Fixes Qiskit#5694
mtreinish added a commit to mtreinish/qiskit-core that referenced this issue Jan 25, 2021
In the preset passmanagers level2 and level3 the initial layout is
generated by the CSP layout pass and then if an answer can't be found
the specified layout method is used instead. However, as was reported in
issue Qiskit#5694 the CSP layout completely misses when the trivial layout case
perfectly maps the input circuit to the device. This results in level 1
significantly out performing level2 and level3 because it has to go to
routing and inserts a lot of swaps. To address this hole in the CSP
layout case this commit updates the preset passmanagers for level 2 and
level 3 to always try a trivial layout first, if this doesn't result in
a perfect mapping the pass is unchanged it will use CSP layout and then
the configured layout method.

Fixes Qiskit#5694
@1ucian0
Copy link
Member

1ucian0 commented Jan 27, 2021

I think this issue can be unfolded, since it uncovers several independent-but-related problems:

  • CSPLayout finds the "trivial layout" solution, but reaches the limit first. It requires 214 sec and 19009 calls (level 2 limits are 1000 calls and 10 sec, level 3 limits are 10000 calls and 60 sec, whatever happen first)
  • DenseLayout does not find the trivial layout. It is fast finding a layout, but results has 911 CNOTs.
  • SabreLayout does not find the trivial layout. It is fast finding a layout, but results has 744 CNOTs.

Possible solutions (not mutually exclusive):

  • During conversations, @kdk and @levbishop suggested the "best of" solution (see PR PassManager controller: "best of" #3018). I think that's reasonable for level 3, but I'm not fully sure about level 2.
  • CSPLayout can have "dynamic" limits, depending on the coupling map.
  • Always try trivial layout first, as suggested in Always try initial layout as first guess in preset passmanagers #5702. The problem with this approach is that is breaks noise awareness. In smaller cases, trivial layout is one of the possible solutions but not the only one.
  • CSPLayout can fallback to trivial layout if no solution is found (either because timeout or because there is no solution). The problem is, again, that will hide noise aware possible solutions from more sophisticated selectors.

While the "best of" passmanager controller would solve this for level 3 (and maybe level 2?), in my opinion all the layout selectors should be able to find the trivial layout when that's the only possible solution. If agreed, I could submit issues for each of them.

@1ucian0
Copy link
Member

1ucian0 commented Jan 27, 2021

Actually, the problem of hiding the noise awareness (described in the last two bullets) is a problem that we currently have. PR #5075 will make CSP noise-aware. Probably Layout2qDistance needs to be noise aware too.

@mergify mergify bot closed this as completed in #5702 Apr 14, 2021
mergify bot pushed a commit that referenced this issue Apr 14, 2021
* Always try initial layout as first guess in preset passmanagers

In the preset passmanagers level2 and level3 the initial layout is
generated by the CSP layout pass and then if an answer can't be found
the specified layout method is used instead. However, as was reported in
issue #5694 the CSP layout completely misses when the trivial layout case
perfectly maps the input circuit to the device. This results in level 1
significantly out performing level2 and level3 because it has to go to
routing and inserts a lot of swaps. To address this hole in the CSP
layout case this commit updates the preset passmanagers for level 2 and
level 3 to always try a trivial layout first, if this doesn't result in
a perfect mapping the pass is unchanged it will use CSP layout and then
the configured layout method.

Fixes #5694

* Tweak flow to not use trivial unless perfect

* Fix lint

* Add comments and explain flow

Co-authored-by: Luciano Bello <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants