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

Improve CSPLayout performance by reducing constraint complexity #6263

Closed
wants to merge 9 commits into from

Conversation

1ucian0
Copy link
Member

@1ucian0 1ucian0 commented Apr 20, 2021

Based on ideas after talking with @czachow, it was possible to specialised the CSPLayout pass and to reduce the complexity of the constraints to check. This gives an improvement in the performance. How much? It varies a lot, depending on the specific situation. Here is an example (based on #5694) where the goal is to find the perfect solution in Toronto (100 times, to amplify the result):

from qiskit.circuit.library import GraphState
from qiskit.test.mock import FakeToronto
import numpy as np
from qiskit.transpiler.passes import CSPLayout
from qiskit.transpiler import CouplingMap
from qiskit.converters import circuit_to_dag
from time import time

backend = FakeToronto()
config = backend.configuration()

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

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

qc = GraphState(A)
qc.measure_all()

dag = circuit_to_dag(qc)
start = time()
for i in range(100):
    pass_ = CSPLayout(CouplingMap(config.coupling_map), seed=i, call_limit=None, time_limit=None)
    pass_.run(dag)
print(time()-start)
print(pass_.property_set['CSPLayout_stop_reason'])

The current result is: 342.403 sec

With this PR: 40.175 241.838 sec (see #6263 (comment))

@1ucian0 1ucian0 requested a review from a team as a code owner April 20, 2021 13:58
@1ucian0
Copy link
Member Author

1ucian0 commented Apr 29, 2021

@czachow found a case where the solution was not being found (test added in 3b7c991). As a consequence more possible assignments need to be checked, increasing run time.

Copy link
Member

@mtreinish mtreinish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this LGTM, just a couple inline suggestions nothing big though. Also I think there is a missing feature from retworkx that this exposes if you could open an issue about it there too that would be great.

@@ -109,6 +136,10 @@ def run(self, dag):
qubits.index(gate.qargs[1])))
edges = set(self.coupling_map.get_edges())

if not self.strict_direction:
cxs = {frozenset(cx) for cx in cxs}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feel unnecessary as you end up iterating over the set of two qubit ops twice. Why not just have the if block around the loop and do this iteratively as you build cx?

@@ -109,6 +136,10 @@ def run(self, dag):
qubits.index(gate.qargs[1])))
edges = set(self.coupling_map.get_edges())

if not self.strict_direction:
cxs = {frozenset(cx) for cx in cxs}
edges = {frozenset(edge) for edge in edges}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you open a retworkx issue here on this https://github.com/Qiskit/retworkx/issues/new/choose I feel like there should be a native method or function on the PyDiGraph class that CouplingMap wraps to return the set of weakly connected edges for a graph. It'd be a bit faster too if that method exists (you might be able to hack it together inside couplingmap today with .to_undirected https://qiskit.org/documentation/retworkx/stubs/retworkx.PyDiGraph.to_undirected.html#retworkx.PyDiGraph.to_undirected but having a native method would be best.

@@ -65,6 +66,32 @@ def recursiveBacktracking(self, # pylint: disable=invalid-name
single)


class CustomConstraint(Constraint):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rename this to be a bit more descriptive, something like ValidEdgeConstrait or something like that.

@mtreinish mtreinish added this to the 0.18 milestone Jun 7, 2021
@mtreinish mtreinish added the Changelog: None Do not include in changelog label Jun 7, 2021
@mtreinish mtreinish changed the title Faster CSPLayout Improve CSPLayout performance by reducing constraint complexity Jun 7, 2021
@kdk kdk modified the milestones: 0.18, 0.19 Jun 15, 2021
@mtreinish mtreinish modified the milestones: 0.19, 0.20 Nov 2, 2021
@1ucian0
Copy link
Member Author

1ucian0 commented Feb 8, 2022

With VF2 taking traction, I think this PR can be closed.

@1ucian0 1ucian0 closed this Feb 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: None Do not include in changelog performance
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants