Repository: Qiskit/qiskit

Issue:
bug in permutation circuits
The permutation circuits from the circuit library do not implement some permutation correctly. For example:

```py
from qiskit.circuit.library import Permutation
Permutation(8, [5,4,1,7,6,3,0,2]).decompose().draw()
```

here the 5th qubit has to end up in the 0th location, but it ends up in the 6th location because two swaps act on it.

```
                 
q_0: ────X─────X─
         │     │ 
q_1: ─X──┼──X──┼─
      │  │  │  │ 
q_2: ─┼──┼──X──┼─
      │  │     │ 
q_3: ─┼──┼──X──┼─
      │  │  │  │ 
q_4: ─X──┼──┼──┼─
         │  │  │ 
q_5: ────X──┼──┼─
            │  │ 
q_6: ───────┼──X─
            │    
q_7: ───────X────
                 
```


Discussion:

Resolving patch:
diff --git a/qiskit/circuit/library/generalized_gates/permutation.py b/qiskit/circuit/library/generalized_gates/permutation.py
--- a/qiskit/circuit/library/generalized_gates/permutation.py
+++ b/qiskit/circuit/library/generalized_gates/permutation.py
@@ -73,9 +73,24 @@ def __init__(self,
         inner = QuantumCircuit(num_qubits, name=name)
 
         super().__init__(num_qubits, name=name)
-        for i in range(num_qubits):
-            if (pattern[i] != -1) and (pattern[i] != i):
-                inner.swap(i, int(pattern[i]))
-                pattern[pattern[i]] = -1
+        for i, j in _get_ordered_swap(pattern):
+            inner.swap(i, j)
+
         all_qubits = self.qubits
         self.append(inner, all_qubits)
+
+
+def _get_ordered_swap(permutation_in):
+    """This attempts to sort the input permutation by iterating through the
+    permutation list and swapping the element with where the actual index occurs and
+    and tracking the swaps.
+    """
+    permutation = list(permutation_in[:])
+    swap_list = []
+    for i, val in enumerate(permutation):
+        if val != i:
+            j = permutation.index(i)
+            swap_list.append((i, j))
+            permutation[i], permutation[j] = permutation[j], permutation[i]
+    swap_list.reverse()
+    return swap_list


Test patch:
diff --git a/test/python/circuit/library/test_permutation.py b/test/python/circuit/library/test_permutation.py
--- a/test/python/circuit/library/test_permutation.py
+++ b/test/python/circuit/library/test_permutation.py
@@ -13,14 +13,18 @@
 """Test library of permutation logic quantum circuits."""
 
 import unittest
+import numpy as np
+from ddt import ddt, data
 
 from qiskit.test.base import QiskitTestCase
 from qiskit.circuit import QuantumCircuit
 from qiskit.circuit.exceptions import CircuitError
 from qiskit.circuit.library import Permutation
+from qiskit.circuit.library.generalized_gates.permutation import _get_ordered_swap
 from qiskit.quantum_info import Operator
 
 
+@ddt
 class TestPermutationLibrary(QiskitTestCase):
     """Test library of permutation logic quantum circuits."""
 
@@ -38,6 +42,19 @@ def test_permutation_bad(self):
         """Test that [0,..,n-1] permutation is required (no -1 for last element)."""
         self.assertRaises(CircuitError, Permutation, 4, [1, 0, -1, 2])
 
+    @data(4, 5, 10, 20)
+    def test_get_ordered_swap(self, width):
+        """Test get_ordered_swap function produces correct swap list."""
+        np.random.seed(1)
+        for _ in range(5):
+            permutation = np.random.permutation(width)
+            swap_list = _get_ordered_swap(permutation)
+            output = list(range(width))
+            for i, j in swap_list:
+                output[i], output[j] = output[j], output[i]
+            self.assertTrue(np.array_equal(permutation, output))
+            self.assertLess(len(swap_list), width)
+
 
 if __name__ == '__main__':
     unittest.main()