Repository: Qiskit/qiskit

Issue:
`initialize` and `Statevector` don't play nicely
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues -->

### Informations

- **Qiskit Aer version**: 0.5.1
- **Python version**: 3.7.3
- **Operating system**: OSX

### What is the current behavior?

Using `initialize` in a circuit and then running with `Statevector` results in the error "Cannot apply Instruction: reset"

### Steps to reproduce the problem

```
import qiskit as qk
import qiskit.quantum_info as qi
from numpy import sqrt

n = 2

ket0 = [1/sqrt(2),0,0,1/sqrt(2)]

qc = qk.QuantumCircuit(n)
qc.initialize(ket0,range(n))
    
ket_qi = qi.Statevector.from_instruction(qc)
```





Discussion:
Funny cause the circuit has no resets:

```
                                       ┌───┐┌───────────────┐┌───┐»
q_0: ─|0>──────────────────────────────┤ X ├┤ U3(-pi/2,0,0) ├┤ X ├»
          ┌──────────────┐┌───────────┐└─┬─┘└───────────────┘└─┬─┘»
q_1: ─|0>─┤ U3(pi/2,0,0) ├┤ U3(0,0,0) ├──■─────────────────────■──»
          └──────────────┘└───────────┘                           »
«     ┌──────────────┐┌───┐┌───────────┐┌───┐┌───────────┐
«q_0: ┤ U3(pi/2,0,0) ├┤ X ├┤ U3(0,0,0) ├┤ X ├┤ U3(0,0,0) ├
«     └──────────────┘└─┬─┘└───────────┘└─┬─┘└───────────┘
«q_1: ──────────────────■─────────────────■───────────────
«                                                         
```
That circuit has a lot of things I don't like, but at least it has no resets.
@nonhermitian That circuit *does* have resets, notice the two |0> |0> at the start? The definition of initialize has reset instructions on all qubits that are removed by the transpiler if it is the first instruction in a circuit. This is so you can "initialize" subsets of qubits at any stage of a circuit.

I'm transferring this to Qiskit Terra. In the future please post issues related to the Quantum info module in Terra, not Aer.
That is not just the initial state of the qubits?  That is what used to be there.  It is hard to tell the difference here.  So that means that initialize is no longer a unitary operation like it was before?  I guess I missed that as well.
A reset method was added to the Statevector class last release, so the simulation could be updated to work with initialize via adding support of reset to the the from_instruction method.
@nonhermitian I think this was changed recently in the draw function. Now circuits are drawn without any initial states, so any time you see them they refer to reset instructions.
Yeah, it is just that the original text drawing is very close to the reset instructions so it is hard for the user to understand.

Resolving patch:
diff --git a/qiskit/quantum_info/states/densitymatrix.py b/qiskit/quantum_info/states/densitymatrix.py
--- a/qiskit/quantum_info/states/densitymatrix.py
+++ b/qiskit/quantum_info/states/densitymatrix.py
@@ -547,12 +547,22 @@ def _evolve_operator(self, other, qargs=None):
 
     def _append_instruction(self, other, qargs=None):
         """Update the current Statevector by applying an instruction."""
+        from qiskit.circuit.reset import Reset
+        from qiskit.circuit.barrier import Barrier
 
         # Try evolving by a matrix operator (unitary-like evolution)
         mat = Operator._instruction_to_matrix(other)
         if mat is not None:
             self._data = self._evolve_operator(Operator(mat), qargs=qargs).data
             return
+
+        # Special instruction types
+        if isinstance(other, Reset):
+            self._data = self.reset(qargs)._data
+            return
+        if isinstance(other, Barrier):
+            return
+
         # Otherwise try evolving by a Superoperator
         chan = SuperOp._instruction_to_superop(other)
         if chan is not None:
diff --git a/qiskit/quantum_info/states/statevector.py b/qiskit/quantum_info/states/statevector.py
--- a/qiskit/quantum_info/states/statevector.py
+++ b/qiskit/quantum_info/states/statevector.py
@@ -595,29 +595,40 @@ def _shape(self):
 
     def _append_instruction(self, obj, qargs=None):
         """Update the current Statevector by applying an instruction."""
+        from qiskit.circuit.reset import Reset
+        from qiskit.circuit.barrier import Barrier
+
         mat = Operator._instruction_to_matrix(obj)
         if mat is not None:
             # Perform the composition and inplace update the current state
             # of the operator
-            state = self.evolve(mat, qargs=qargs)
-            self._data = state.data
-        else:
-            # If the instruction doesn't have a matrix defined we use its
-            # circuit decomposition definition if it exists, otherwise we
-            # cannot compose this gate and raise an error.
-            if obj.definition is None:
-                raise QiskitError('Cannot apply Instruction: {}'.format(obj.name))
-            for instr, qregs, cregs in obj.definition:
-                if cregs:
-                    raise QiskitError(
-                        'Cannot apply instruction with classical registers: {}'.format(
-                            instr.name))
-                # Get the integer position of the flat register
-                if qargs is None:
-                    new_qargs = [tup.index for tup in qregs]
-                else:
-                    new_qargs = [qargs[tup.index] for tup in qregs]
-                self._append_instruction(instr, qargs=new_qargs)
+            self._data = self.evolve(mat, qargs=qargs).data
+            return
+
+        # Special instruction types
+        if isinstance(obj, Reset):
+            self._data = self.reset(qargs)._data
+            return
+        if isinstance(obj, Barrier):
+            return
+
+        # If the instruction doesn't have a matrix defined we use its
+        # circuit decomposition definition if it exists, otherwise we
+        # cannot compose this gate and raise an error.
+        if obj.definition is None:
+            raise QiskitError('Cannot apply Instruction: {}'.format(obj.name))
+
+        for instr, qregs, cregs in obj.definition:
+            if cregs:
+                raise QiskitError(
+                    'Cannot apply instruction with classical registers: {}'.format(
+                        instr.name))
+            # Get the integer position of the flat register
+            if qargs is None:
+                new_qargs = [tup.index for tup in qregs]
+            else:
+                new_qargs = [qargs[tup.index] for tup in qregs]
+            self._append_instruction(instr, qargs=new_qargs)
 
     def _evolve_instruction(self, obj, qargs=None):
         """Return a new statevector by applying an instruction."""


Test patch:
diff --git a/test/python/quantum_info/states/test_densitymatrix.py b/test/python/quantum_info/states/test_densitymatrix.py
--- a/test/python/quantum_info/states/test_densitymatrix.py
+++ b/test/python/quantum_info/states/test_densitymatrix.py
@@ -142,6 +142,22 @@ def test_from_circuit(self):
         rho = DensityMatrix.from_instruction(circuit)
         self.assertEqual(rho, target)
 
+        # Test initialize instruction
+        init = Statevector([1, 0, 0, 1j]) / np.sqrt(2)
+        target = DensityMatrix(init)
+        circuit = QuantumCircuit(2)
+        circuit.initialize(init.data, [0, 1])
+        rho = DensityMatrix.from_instruction(circuit)
+        self.assertEqual(rho, target)
+
+        # Test reset instruction
+        target = DensityMatrix([1, 0])
+        circuit = QuantumCircuit(1)
+        circuit.h(0)
+        circuit.reset(0)
+        rho = DensityMatrix.from_instruction(circuit)
+        self.assertEqual(rho, target)
+
     def test_from_instruction(self):
         """Test initialization from an instruction."""
         target_vec = Statevector(np.dot(HGate().to_matrix(), [1, 0]))
diff --git a/test/python/quantum_info/states/test_statevector.py b/test/python/quantum_info/states/test_statevector.py
--- a/test/python/quantum_info/states/test_statevector.py
+++ b/test/python/quantum_info/states/test_statevector.py
@@ -130,6 +130,21 @@ def test_from_circuit(self):
         psi = Statevector.from_instruction(circuit)
         self.assertEqual(psi, target)
 
+        # Test initialize instruction
+        target = Statevector([1, 0, 0, 1j]) / np.sqrt(2)
+        circuit = QuantumCircuit(2)
+        circuit.initialize(target.data, [0, 1])
+        psi = Statevector.from_instruction(circuit)
+        self.assertEqual(psi, target)
+
+        # Test reset instruction
+        target = Statevector([1, 0])
+        circuit = QuantumCircuit(1)
+        circuit.h(0)
+        circuit.reset(0)
+        psi = Statevector.from_instruction(circuit)
+        self.assertEqual(psi, target)
+
     def test_from_instruction(self):
         """Test initialization from an instruction."""
         target = np.dot(HGate().to_matrix(), [1, 0])