mirror of https://github.com/Qiskit/qiskit.git
Removed the usage of stochastic swap trivial_flag as it can lead to single-qubit gates being omitted (#3285)
* removed usage of trivial_flag that indicates when a layer should be skipped by layer_update (#3197) * removed trivial_flag from stochastic_swap and added a test for omitted gates * lint
This commit is contained in:
parent
812e213a01
commit
31cdd7428c
|
@ -129,13 +129,12 @@ class StochasticSwap(TransformationPass):
|
|||
trials (int): Number of attempts the randomized algorithm makes.
|
||||
|
||||
Returns:
|
||||
Tuple: success_flag, best_circuit, best_depth, best_layout, trivial_flag
|
||||
Tuple: success_flag, best_circuit, best_depth, best_layout
|
||||
|
||||
If success_flag is True, then best_circuit contains a DAGCircuit with
|
||||
the swap circuit, best_depth contains the depth of the swap circuit,
|
||||
and best_layout contains the new positions of the data qubits after the
|
||||
swap circuit has been applied. The trivial_flag is set if the layer
|
||||
has no multi-qubit gates.
|
||||
swap circuit has been applied.
|
||||
|
||||
Raises:
|
||||
TranspilerError: if anything went wrong.
|
||||
|
@ -235,13 +234,13 @@ class StochasticSwap(TransformationPass):
|
|||
for i, layer in enumerate(layerlist):
|
||||
|
||||
# Attempt to find a permutation for this layer
|
||||
success_flag, best_circuit, best_depth, best_layout, trivial_flag \
|
||||
success_flag, best_circuit, best_depth, best_layout \
|
||||
= self._layer_permutation(layer["partition"], layout,
|
||||
qubit_subset, coupling_graph,
|
||||
trials)
|
||||
logger.debug("mapper: layer %d", i)
|
||||
logger.debug("mapper: success_flag=%s,best_depth=%s,trivial_flag=%s",
|
||||
success_flag, str(best_depth), trivial_flag)
|
||||
logger.debug("mapper: success_flag=%s,best_depth=%s",
|
||||
success_flag, str(best_depth))
|
||||
|
||||
# If this fails, try one gate at a time in this layer
|
||||
if not success_flag:
|
||||
|
@ -252,29 +251,21 @@ class StochasticSwap(TransformationPass):
|
|||
# Go through each gate in the layer
|
||||
for j, serial_layer in enumerate(serial_layerlist):
|
||||
|
||||
success_flag, best_circuit, best_depth, best_layout, trivial_flag = \
|
||||
success_flag, best_circuit, best_depth, best_layout = \
|
||||
self._layer_permutation(
|
||||
serial_layer["partition"],
|
||||
layout, qubit_subset,
|
||||
coupling_graph,
|
||||
trials)
|
||||
logger.debug("mapper: layer %d, sublayer %d", i, j)
|
||||
logger.debug("mapper: success_flag=%s,best_depth=%s,"
|
||||
"trivial_flag=%s",
|
||||
success_flag, str(best_depth), trivial_flag)
|
||||
logger.debug("mapper: success_flag=%s,best_depth=%s,",
|
||||
success_flag, str(best_depth))
|
||||
|
||||
# Give up if we fail again
|
||||
if not success_flag:
|
||||
raise TranspilerError("swap mapper failed: " +
|
||||
"layer %d, sublayer %d" % (i, j))
|
||||
|
||||
# If this layer is only single-qubit gates,
|
||||
# and we have yet to see multi-qubit gates,
|
||||
# continue to the next inner iteration
|
||||
if trivial_flag:
|
||||
logger.debug("mapper: skip to next sublayer")
|
||||
continue
|
||||
|
||||
# Update the record of qubit positions
|
||||
# for each inner iteration
|
||||
layout = best_layout
|
||||
|
@ -330,7 +321,7 @@ def _layer_permutation(layer_partition, layout, qubit_subset,
|
|||
rng (RandomState): Random number generator.
|
||||
|
||||
Returns:
|
||||
Tuple: success_flag, best_circuit, best_depth, best_layout, trivial_flag
|
||||
Tuple: success_flag, best_circuit, best_depth, best_layout
|
||||
|
||||
Raises:
|
||||
TranspilerError: if anything went wrong.
|
||||
|
@ -364,7 +355,7 @@ def _layer_permutation(layer_partition, layout, qubit_subset,
|
|||
logger.debug("layer_permutation: nothing to do")
|
||||
circ = DAGCircuit()
|
||||
circ.add_qreg(canonical_register)
|
||||
return True, circ, 0, layout, (not bool(gates))
|
||||
return True, circ, 0, layout
|
||||
|
||||
# Begin loop over trials of randomized algorithm
|
||||
num_qubits = len(layout)
|
||||
|
@ -418,7 +409,7 @@ def _layer_permutation(layer_partition, layout, qubit_subset,
|
|||
# trials have failed
|
||||
if best_layout is None:
|
||||
logger.debug("layer_permutation: failed!")
|
||||
return False, None, None, None, False
|
||||
return False, None, None, None
|
||||
|
||||
edgs = best_edges.edges()
|
||||
trivial_layout = Layout.generate_trivial_layout(canonical_register)
|
||||
|
@ -431,7 +422,7 @@ def _layer_permutation(layer_partition, layout, qubit_subset,
|
|||
# Otherwise, we return our result for this layer
|
||||
logger.debug("layer_permutation: success!")
|
||||
best_lay = best_layout.to_layout(qregs)
|
||||
return True, best_circuit, best_depth, best_lay, False
|
||||
return True, best_circuit, best_depth, best_lay
|
||||
|
||||
|
||||
def regtuple_to_numeric(items, qregs):
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import unittest
|
||||
from qiskit.transpiler.passes import StochasticSwap
|
||||
from qiskit.transpiler import CouplingMap
|
||||
from qiskit.transpiler import CouplingMap, PassManager
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
from qiskit.converters import circuit_to_dag
|
||||
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
|
||||
|
@ -511,6 +511,31 @@ class TestStochasticSwap(QiskitTestCase):
|
|||
with self.assertRaises(TranspilerError):
|
||||
_ = pass_.run(dag)
|
||||
|
||||
def test_single_gates_omitted(self):
|
||||
"""Test if single qubit gates are omitted."""
|
||||
|
||||
coupling_map = [[0, 1], [1, 0], [1, 2], [1, 3], [2, 1], [3, 1], [3, 4], [4, 3]]
|
||||
qr = QuantumRegister(5, 'q')
|
||||
cr = ClassicalRegister(5, 'c')
|
||||
circuit = QuantumCircuit(qr, cr)
|
||||
circuit.cx(qr[0], qr[4])
|
||||
circuit.cx(qr[1], qr[2])
|
||||
circuit.u3(1, 1.5, 0.7, qr[3])
|
||||
|
||||
expected = QuantumCircuit(qr, cr)
|
||||
expected.cx(qr[1], qr[2])
|
||||
expected.u3(1, 1.5, 0.7, qr[3])
|
||||
expected.swap(qr[0], qr[1])
|
||||
expected.swap(qr[3], qr[4])
|
||||
expected.cx(qr[1], qr[3])
|
||||
|
||||
expected_dag = circuit_to_dag(expected)
|
||||
|
||||
stochastic = StochasticSwap(CouplingMap(coupling_map), seed=0)
|
||||
after = PassManager(stochastic).run(circuit)
|
||||
after = circuit_to_dag(after)
|
||||
self.assertEqual(expected_dag, after)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
Loading…
Reference in New Issue