diff --git a/qiskit/transpiler/passes/optimization/elide_permutations.py b/qiskit/transpiler/passes/optimization/elide_permutations.py index ca6902f15b43..81d0aa8bf1ae 100644 --- a/qiskit/transpiler/passes/optimization/elide_permutations.py +++ b/qiskit/transpiler/passes/optimization/elide_permutations.py @@ -96,8 +96,8 @@ def _apply_mapping(qargs): elif isinstance(node.op, PermutationGate): starting_indices = [qubit_mapping[dag.find_bit(qarg).index] for qarg in node.qargs] pattern = node.op.params[0] - pattern_indices = [qubit_mapping[idx] for idx in pattern] - for i, j in zip(starting_indices, pattern_indices): + updated_indices = [starting_indices[idx] for idx in pattern] + for i, j in zip(starting_indices, updated_indices): qubit_mapping[i] = j input_qubit_mapping = {qubit: index for index, qubit in enumerate(dag.qubits)} self.property_set["original_layout"] = Layout(input_qubit_mapping) diff --git a/releasenotes/notes/fix-elide-permutations-1b9e1d10c3abb2a4.yaml b/releasenotes/notes/fix-elide-permutations-1b9e1d10c3abb2a4.yaml new file mode 100644 index 000000000000..156960eb7c19 --- /dev/null +++ b/releasenotes/notes/fix-elide-permutations-1b9e1d10c3abb2a4.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixed a bug in the transpiler pass :class:`~.ElidePermutations` where the + qubit mapping was not updated correctly in the presence of :class:`.PermutationGate`\s. diff --git a/test/python/transpiler/test_elide_permutations.py b/test/python/transpiler/test_elide_permutations.py index c96b5ca32d89..6f3051cec0d6 100644 --- a/test/python/transpiler/test_elide_permutations.py +++ b/test/python/transpiler/test_elide_permutations.py @@ -207,6 +207,37 @@ def test_permutation_in_middle(self): res = self.swap_pass(qc) self.assertEqual(res, expected) + def test_partial_permutation_in_middle(self): + """Test with a permutation gate in the middle of a circuit, + with the permutation gate defined only on a subset of qubits. + """ + qc = QuantumCircuit(5) + qc.cx(0, 1) + qc.append(PermutationGate([1, 2, 0]), [0, 2, 4]) + qc.cx(2, 3) + + # The permutation corresponding to the permutation gate maps + # 2 -> 0, 4 -> 2, 0 -> 4, and 1 -> 1, 3 -> 3. + # Instead of the permutation gate, we can relabel the qubits + # 0 -> 2, 1 -> 1, 2 -> 4, 3 -> 3, 4 -> 2. + # Hence cx(2, 3) becomes cx(4, 3). + expected = QuantumCircuit(5) + expected.cx(0, 1) + expected.cx(4, 3) + + pass_ = ElidePermutations() + res = pass_(qc) + + # Make sure that the pass removes the permutation gate and remaps + # the following gate + self.assertEqual(res, expected) + + # Make sure that the transpiled circuit *with* the final permutation + # is equivalent to the original circuit + perm = pass_.property_set["virtual_permutation_layout"].to_permutation(qc.qubits) + res.append(PermutationGate(perm), [0, 1, 2, 3, 4]) + self.assertEqual(Operator(res), Operator(qc)) + def test_permutation_at_beginning(self): """Test permutation in beginning of bell is elided.""" qc = QuantumCircuit(3, 3)