Repository: Qiskit/qiskit-terra
Pull request #5790 (2021-02-05 15:53:08)

Fix PauliTwoDesign.assign_parameters
Fix PauliTwoDesign.assign_parameters adds initial rotation layer

### Summary

Fix a bug where assigning parameters would add an additional RY layer to the `PauliTwoDesign` circuit:

```python
In [1]: from qiskit.circuit.library import PauliTwoDesign

In [2]: q = PauliTwoDesign(2)
q
In [3]: import numpy as np

In [4]: vals = np.arange(q.num_parameters)

In [5]: q.assign_parameters(vals).draw()
Out[5]:
     ┌─────────┐┌─────────┐┌───────┐   ┌───────┐   ┌───────┐   ┌───────┐
q_0: ┤ RY(π/4) ├┤ RY(π/4) ├┤ RZ(0) ├─■─┤ RY(2) ├─■─┤ RX(4) ├─■─┤ RX(6) ├
     ├─────────┤├─────────┤├───────┤ │ ├───────┤ │ ├───────┤ │ ├───────┤
q_1: ┤ RY(π/4) ├┤ RY(π/4) ├┤ RZ(1) ├─■─┤ RY(3) ├─■─┤ RX(5) ├─■─┤ RZ(7) ├
     └─────────┘└─────────┘└───────┘   └───────┘   └───────┘   └───────┘

In [6]: q.assign_parameters(vals).draw()
Out[6]:
     ┌─────────┐┌─────────┐┌─────────┐┌───────┐   ┌───────┐   ┌───────┐   ┌───────┐
q_0: ┤ RY(π/4) ├┤ RY(π/4) ├┤ RY(π/4) ├┤ RZ(0) ├─■─┤ RY(2) ├─■─┤ RX(4) ├─■─┤ RX(6) ├
     ├─────────┤├─────────┤├─────────┤├───────┤ │ ├───────┤ │ ├───────┤ │ ├───────┤
q_1: ┤ RY(π/4) ├┤ RY(π/4) ├┤ RY(π/4) ├┤ RZ(1) ├─■─┤ RY(3) ├─■─┤ RX(5) ├─■─┤ RZ(7) ├
     └─────────┘└─────────┘└─────────┘└───────┘   └───────┘   └───────┘   └───────┘
```


Patch:
diff --git a/qiskit/circuit/library/n_local/n_local.py b/qiskit/circuit/library/n_local/n_local.py
index c56d31056..26fde1288 100644
--- a/qiskit/circuit/library/n_local/n_local.py
+++ b/qiskit/circuit/library/n_local/n_local.py
@@ -857,7 +857,7 @@ class NLocal(BlueprintCircuit):
         for i, (block, ent) in enumerate(zip(blocks, entanglements)):
             layer = QuantumCircuit(*self.qregs)
             if isinstance(ent, str):
-                ent = get_entangler_map(block.num_block_qubits, self.num_qubits, ent)
+                ent = get_entangler_map(block.num_qubits, self.num_qubits, ent)
             for indices in ent:
                 layer.compose(block, indices, inplace=True)
 
diff --git a/qiskit/circuit/library/n_local/pauli_two_design.py b/qiskit/circuit/library/n_local/pauli_two_design.py
index 37dfbfd49..1e9efb5a2 100644
--- a/qiskit/circuit/library/n_local/pauli_two_design.py
+++ b/qiskit/circuit/library/n_local/pauli_two_design.py
@@ -68,6 +68,8 @@ class PauliTwoDesign(TwoLocal):
 
     def __init__(self, num_qubits: Optional[int] = None, reps: int = 3,
                  seed: Optional[int] = None, insert_barriers: bool = False):
+        from qiskit.circuit.library import RYGate  # pylint: disable=cyclic-import
+
         # store a random number generator
         self._seed = seed
         self._rng = np.random.default_rng(seed)
@@ -78,6 +80,10 @@ class PauliTwoDesign(TwoLocal):
         super().__init__(num_qubits, reps=reps, entanglement_blocks='cz', entanglement='pairwise',
                          insert_barriers=insert_barriers)
 
+        # set the initial layer
+        self._prepended_blocks = [RYGate(np.pi / 4)]
+        self._prepended_entanglement = ['linear']
+
     def _invalidate(self):
         self._rng = np.random.default_rng(self._seed)  # reset number generator
         super()._invalidate()
@@ -109,10 +115,3 @@ class PauliTwoDesign(TwoLocal):
             The number of possibly distinct parameters.
         """
         return (self.reps + 1) * self.num_qubits
-
-    def _build(self):
-        super()._build()
-        initial_layer = QuantumCircuit(self.num_qubits)
-        initial_layer.ry(np.pi / 4, range(self.num_qubits))
-
-        self.compose(initial_layer, front=True, inplace=True)


Test patch:
diff --git a/test/python/circuit/library/test_random_pauli.py b/test/python/circuit/library/test_random_pauli.py
index d3024d3b6..5fa728195 100644
--- a/test/python/circuit/library/test_random_pauli.py
+++ b/test/python/circuit/library/test_random_pauli.py
@@ -70,6 +70,18 @@ class TestPauliTwoDesign(QiskitTestCase):
 
             self.assertEqual(top_gates, new_top_gates)
 
+    def test_assign_keeps_one_initial_layer(self):
+        """Test assigning parameters does not add an additional initial layer."""
+        circuit = PauliTwoDesign(2)
+        values = list(range(circuit.num_parameters))
+
+        bound0 = circuit.assign_parameters(values)
+        bound1 = circuit.assign_parameters(values)
+        bound2 = circuit.assign_parameters(values)
+
+        self.assertEqual(bound0, bound1)
+        self.assertEqual(bound0, bound2)
+
 
 if __name__ == '__main__':
     unittest.main()