Repository: Qiskit/qiskit

Issue:
UnitaryGate.control().inverse() increases the number of qubits in the instruction
### Information

- **Qiskit Terra version**: 0.14.1
- **Python version**: 3.7
- **Operating system**: Windows 10

### What is the current behavior?

Generating the inverse of a circuit using `circuit.inverse()` does not yield the correct circuit.

### Steps to reproduce the problem

A minimal example is this:
```
#%% Load packages

import numpy as np
from qiskit.tools.visualization import circuit_drawer
from qiskit.circuit import QuantumCircuit
from qiskit import execute, Aer


def calculate_unitary(circ, decimals=3):
    """ Calculate unitary matrix from circuit """
    backend = Aer.get_backend('unitary_simulator')
    job = execute(circ, backend)
    result = job.result()
    U=result.get_unitary(circ, decimals=decimals)
    return U

#%% Define a quantum circuit
def generate_full_phase_gate():        
    """ Generate a gate that acts by adding a minus sign to the entire state
    
    That is a bit funny gate, but it is valid and when combined to a conditional gate also a gate with physical meaning
    """
    multi = QuantumCircuit(1, name='P')
    multi.z(0)
    multi.x(0)
    multi.z(0)
    multi.x(0)
    full_phase_gate = multi.to_gate()
    return full_phase_gate

def generate_conditional_gate():
    qc = QuantumCircuit(3, name='conditional')
    
    p_gate = generate_full_phase_gate()
   
    cmulti_z_gate1 = p_gate.control(2, ctrl_state='01')
    qc.append(cmulti_z_gate1, [0,1, 2])

    return qc

encoder=generate_conditional_gate()
circuit_drawer(encoder, output='mpl')

#%% We generate a circuit by adding the conditional gate defined above, together with the inverse

qc = QuantumCircuit(3,3)
qc.extend(generate_conditional_gate())
qc.barrier()
qc.extend(generate_conditional_gate().inverse())
U=calculate_unitary(qc, decimals=16)
print(np.round(np.real_if_close(U), 14)+0) # should be the identity!
```


### What is the expected behavior?

Given any circuit, applying the circuit and then the inverse should yield an identity circuit. This is not the case for the minimal example.

### Suggested solutions

The bug seems to be triggered by the generation of the control gate in combination with the custom gate I generated. I tried generating this gate as 
```
from qiskit.extensions import UnitaryGate
full_phase_gate=UnitaryGate([[-1,0],[0,-1]])
```
But that gives similar problems. Perhaps the `UnitaryGate([[-1,0],[0,-1]])` is optimized to `UnitaryGate([[1,0],[0,1]])` in the calculation of the inverse?






Discussion:
Hi @peendebak ,
I am running the latest terra version `0.16.3`, sha 7710880167ddf6e11922ce608e6579e304c7eb04,
and for your particular example, I obtain identity matrix:
```
[[1. 0. 0. 0. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0. 0. 0.]
 [0. 0. 0. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 0. 0. 0.]
 [0. 0. 0. 0. 0. 1. 0. 0.]
 [0. 0. 0. 0. 0. 0. 1. 0.]
 [0. 0. 0. 0. 0. 0. 0. 1.]]
``` 
It seems that the bug related to your example was already addressed. 
@molar-volume Thanks for the feedback. With the updated the qiskit-terra the example above indeed works. But for a variation with the `UnitaryGate` I still get an error when running a circuit with the inverse.

A minimal example:
```
import numpy as np
from qiskit.tools.visualization import circuit_drawer
from qiskit.circuit import QuantumCircuit
from qiskit import execute, Aer
from qiskit.extensions import UnitaryGate


def calculate_unitary(circ, decimals=3):
    """ Calculate unitary matrix from circuit """
    backend = Aer.get_backend('unitary_simulator')
    job = execute(circ, backend)
    result = job.result()
    U=result.get_unitary(circ, decimals=decimals)
    return U

#%% Define a quantum circuit

def generate_conditional_gate():
    qc = QuantumCircuit(3, name='conditional')
    
    p_gate=UnitaryGate([[-1,0],[0,-1]])
   
    cmulti_z_gate1 = p_gate.control(2, ctrl_state='01')
    qc.append(cmulti_z_gate1, [0,1, 2])

    return qc

encoder=generate_conditional_gate()
circuit_drawer(encoder, output='mpl')

qc = QuantumCircuit(3,3)
qc.extend(generate_conditional_gate())
U=calculate_unitary(qc, decimals=16)
print(np.round(np.real_if_close(U), 14)+0) # works!

#%% We generate a circuit by adding the conditional gate defined above, together with the inverse

qc = QuantumCircuit(3,3)
qc.extend(generate_conditional_gate().inverse())
U=calculate_unitary(qc, decimals=16)
print(np.round(np.real_if_close(U), 14)+0) # fails!
```
Results in
```
...
DAGCircuitError: expected 3 wires, got 5
```

The problem arises from `UnitaryGate.control()` with a subsequent call to `inverse`. To fix your problem, you can just change your `generate_conditional_gate` function to:
```python
def generate_conditional_gate():
    qc = QuantumCircuit(3, name='conditional')
    qc.unitary([[-1,0],[0,-1]], [0])
   
    cmulti_z_gate1 = qc.control(2, ctrl_state='01')
    qc.append(cmulti_z_gate1, [0,1, 2])

    return qc

```

And here's a more minimal example showing the issue. Probably this comes from using the `Isometry` class.
```python
from qiskit.circuit import QuantumCircuit
from qiskit.extensions import UnitaryGate

matrix = [[-1, 0], [0, -1]]

# with circuits
u = QuantumCircuit(1)
u.unitary(matrix, [0])

print('QuantumCircuit.unitary')
print('ctrl:',  u.control().num_qubits)  # 2
print('ctrl+inv:', u.control().inverse().num_qubits)  # 2
print()

# with the unitary gate
u = UnitaryGate(matrix)

print('UnitaryGate')
print('ctrl:', u.control().num_qubits)  # 2
print('ctrl+inv:', u.control().inverse().num_qubits)  # but this is 3!
```

Resolving patch:
diff --git a/qiskit/extensions/unitary.py b/qiskit/extensions/unitary.py
--- a/qiskit/extensions/unitary.py
+++ b/qiskit/extensions/unitary.py
@@ -136,10 +136,11 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None):
             QiskitError: Invalid ctrl_state.
             ExtensionError: Non-unitary controlled unitary.
         """
-        cmat = _compute_control_matrix(self.to_matrix(), num_ctrl_qubits, ctrl_state=None)
+        mat = self.to_matrix()
+        cmat = _compute_control_matrix(mat, num_ctrl_qubits, ctrl_state=None)
         iso = isometry.Isometry(cmat, 0, 0)
         cunitary = ControlledGate('c-unitary', num_qubits=self.num_qubits+num_ctrl_qubits,
-                                  params=[cmat], label=label, num_ctrl_qubits=num_ctrl_qubits,
+                                  params=[mat], label=label, num_ctrl_qubits=num_ctrl_qubits,
                                   definition=iso.definition, ctrl_state=ctrl_state,
                                   base_gate=self.copy())
         from qiskit.quantum_info import Operator


Test patch:
diff --git a/test/python/circuit/test_unitary.py b/test/python/circuit/test_unitary.py
--- a/test/python/circuit/test_unitary.py
+++ b/test/python/circuit/test_unitary.py
@@ -287,9 +287,16 @@ def test_unitary_decomposition(self):
     def test_unitary_decomposition_via_definition(self):
         """Test decomposition for 1Q unitary via definition."""
         mat = numpy.array([[0, 1], [1, 0]])
-        numpy.allclose(Operator(UnitaryGate(mat).definition).data, mat)
+        self.assertTrue(numpy.allclose(Operator(UnitaryGate(mat).definition).data, mat))
 
     def test_unitary_decomposition_via_definition_2q(self):
         """Test decomposition for 2Q unitary via definition."""
         mat = numpy.array([[0, 0, 1, 0], [0, 0, 0, -1], [1, 0, 0, 0], [0, -1, 0, 0]])
-        numpy.allclose(Operator(UnitaryGate(mat).definition).data, mat)
+        self.assertTrue(numpy.allclose(Operator(UnitaryGate(mat).definition).data, mat))
+
+    def test_unitary_control(self):
+        """Test parameters of controlled - unitary."""
+        mat = numpy.array([[0, 1], [1, 0]])
+        gate = UnitaryGate(mat).control()
+        self.assertTrue(numpy.allclose(gate.params, mat))
+        self.assertTrue(numpy.allclose(gate.base_gate.params, mat))