Repository: Qiskit/qiskit

Issue:
mcry mode='basic' does not use ancillas
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues -->

### Information

- **0.14.2**:
- **3**:
- **Ubuntu**:

### What is the current behavior?
The mcry gate (implemented in https://github.com/Qiskit/qiskit-terra/blob/master/qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py) has a 'basic' mode that expects ancillas, but calls mct in its default 'noancilla' mode. (so both mcry(mode = 'noancilla') and mcry(mode='basic') use no ancillas and a lot of gates).


### Steps to reproduce the problem



### What is the expected behavior?
mcry in mode='basic' should call mct with mode='basic'


### Suggested solutions





Discussion:

Resolving patch:
diff --git a/qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py b/qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py
--- a/qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py
+++ b/qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py
@@ -16,6 +16,7 @@
 import logging
 from math import pi
 from qiskit.circuit import QuantumCircuit, QuantumRegister, Qubit
+from qiskit.circuit.library.standard_gates.x import MCXGate
 from qiskit.circuit.library.standard_gates.u3 import _generate_gray_code
 from qiskit.exceptions import QiskitError
 
@@ -31,7 +32,7 @@ def _apply_cu3(circuit, theta, phi, lam, control, target, use_basis_gates=True):
         circuit.cx(control, target)
         circuit.u3(theta / 2, phi, 0, target)
     else:
-        circuit.cu3(theta, phi, lam, control, target)
+        circuit.cu(theta, phi, lam, 0, control, target)
 
 
 def _apply_mcu3_graycode(circuit, theta, phi, lam, ctls, tgt, use_basis_gates):
@@ -120,7 +121,7 @@ def mcrx(self, theta, q_controls, q_target, use_basis_gates=False):
                              target_qubit, use_basis_gates=use_basis_gates)
 
 
-def mcry(self, theta, q_controls, q_target, q_ancillae, mode='basic',
+def mcry(self, theta, q_controls, q_target, q_ancillae, mode=None,
          use_basis_gates=False):
     """
     Apply Multiple-Controlled Y rotation gate
@@ -169,11 +170,20 @@ def mcry(self, theta, q_controls, q_target, q_ancillae, mode='basic',
     self._check_qargs(all_qubits)
     self._check_dups(all_qubits)
 
+    # auto-select the best mode
+    if mode is None:
+        # if enough ancillary qubits are provided, use the 'v-chain' method
+        additional_vchain = MCXGate.get_num_ancilla_qubits(len(control_qubits), 'v-chain')
+        if len(ancillary_qubits) >= additional_vchain:
+            mode = 'basic'
+        else:
+            mode = 'noancilla'
+
     if mode == 'basic':
-        self.u3(theta / 2, 0, 0, q_target)
-        self.mct(q_controls, q_target, q_ancillae)
-        self.u3(-theta / 2, 0, 0, q_target)
-        self.mct(q_controls, q_target, q_ancillae)
+        self.ry(theta / 2, q_target)
+        self.mcx(q_controls, q_target, q_ancillae, mode='v-chain')
+        self.ry(-theta / 2, q_target)
+        self.mcx(q_controls, q_target, q_ancillae, mode='v-chain')
     elif mode == 'noancilla':
         n_c = len(control_qubits)
         if n_c == 1:  # cu3


Test patch:
diff --git a/test/python/circuit/test_controlled_gate.py b/test/python/circuit/test_controlled_gate.py
--- a/test/python/circuit/test_controlled_gate.py
+++ b/test/python/circuit/test_controlled_gate.py
@@ -549,6 +549,19 @@ def test_multi_controlled_y_rotation_matrix_basic_mode(self, num_controls, use_b
             with self.subTest(msg='control state = {}'.format(ctrl_state)):
                 self.assertTrue(matrix_equal(simulated, expected))
 
+    def test_mcry_defaults_to_vchain(self):
+        """Test mcry defaults to the v-chain mode if sufficient work qubits are provided."""
+        circuit = QuantumCircuit(5)
+        control_qubits = circuit.qubits[:3]
+        target_qubit = circuit.qubits[3]
+        additional_qubits = circuit.qubits[4:]
+        circuit.mcry(0.2, control_qubits, target_qubit, additional_qubits)
+
+        # If the v-chain mode is selected, all qubits are used. If the noancilla mode would be
+        # selected, the bottom qubit would remain unused.
+        dag = circuit_to_dag(circuit)
+        self.assertEqual(len(list(dag.idle_wires())), 0)
+
     @data(1, 2)
     def test_mcx_gates_yield_explicit_gates(self, num_ctrl_qubits):
         """Test the creating a MCX gate yields the explicit definition if we know it."""