Repository: Qiskit/qiskit

Issue:
qpy import of circuit with StatePreparation fails
### Environment

- **Qiskit Terra version**: 0.21.0
- **Python version**: 3.8.9
- **Operating system**: macOS (M1)
- Qiskit version 0.37.0


### What is happening?

When reimporting a simple circuit containing a StatePreparation with `qiskit.qpy`, one gets the error `qiskit.exceptions.QiskitError: 'The num_qubits parameter to StatePreparation should only be used when params is an integer'`.

### How can we reproduce the issue?

Minimal example:
```
#!/usr/bin/python3
import qiskit
import qiskit.qpy
print(qiskit.__qiskit_version__)
qc = qiskit.QuantumCircuit(1)
qc.prepare_state([0,1], [0])
with open("tmp.qpy", "wb") as file:
    qiskit.qpy.dump(qc, file)
with open("tmp.qpy", "rb") as file:
    new_qc = qiskit.qpy.load(file)
#qiskit.exceptions.QiskitError: 'The num_qubits parameter to StatePreparation should only be used when params is an integer'
```

### What should happen?

Reimporting a circuit with qiskit.qpy should be possible.

### Any suggestions?

_No response_


Discussion:
This may be akin to issue #7847 wherein the serializer has an issue with a non-standard gate. Fixing this would require specifying the 'StatePreparation' here:

https://github.com/Qiskit/qiskit-terra/blob/2bab09c1aae84e5bf38ba52fa3a272667c1887cc/qiskit/qpy/binary_io/circuits.py#L272

Resolving patch:
diff --git a/qiskit/qpy/binary_io/circuits.py b/qiskit/qpy/binary_io/circuits.py
--- a/qiskit/qpy/binary_io/circuits.py
+++ b/qiskit/qpy/binary_io/circuits.py
@@ -267,7 +267,7 @@ def _read_instruction(file_obj, circuit, registers, custom_operations, version,
             gate.ctrl_state = instruction.ctrl_state
         gate.condition = condition_tuple
     else:
-        if gate_name in {"Initialize", "UCRXGate", "UCRYGate", "UCRZGate"}:
+        if gate_name in {"Initialize", "StatePreparation", "UCRXGate", "UCRYGate", "UCRZGate"}:
             gate = gate_class(params)
         else:
             if gate_name == "Barrier":


Test patch:
diff --git a/test/python/circuit/test_circuit_load_from_qpy.py b/test/python/circuit/test_circuit_load_from_qpy.py
--- a/test/python/circuit/test_circuit_load_from_qpy.py
+++ b/test/python/circuit/test_circuit_load_from_qpy.py
@@ -624,6 +624,37 @@ def test_initialize_qft(self):
         )
         self.assertDeprecatedBitProperties(qc, new_circ)
 
+    def test_statepreparation(self):
+        """Test that state preparation with a complex statevector and qft work."""
+        k = 5
+        state = (1 / np.sqrt(8)) * np.array(
+            [
+                np.exp(-1j * 2 * np.pi * k * (0) / 8),
+                np.exp(-1j * 2 * np.pi * k * (1) / 8),
+                np.exp(-1j * 2 * np.pi * k * (2) / 8),
+                np.exp(-1j * 2 * np.pi * k * 3 / 8),
+                np.exp(-1j * 2 * np.pi * k * 4 / 8),
+                np.exp(-1j * 2 * np.pi * k * 5 / 8),
+                np.exp(-1j * 2 * np.pi * k * 6 / 8),
+                np.exp(-1j * 2 * np.pi * k * 7 / 8),
+            ]
+        )
+
+        qubits = 3
+        qc = QuantumCircuit(qubits, qubits)
+        qc.prepare_state(state)
+        qc.append(QFT(qubits), range(qubits))
+        qc.measure(range(qubits), range(qubits))
+        qpy_file = io.BytesIO()
+        dump(qc, qpy_file)
+        qpy_file.seek(0)
+        new_circ = load(qpy_file)[0]
+        self.assertEqual(qc, new_circ)
+        self.assertEqual(
+            [x.operation.label for x in qc.data], [x.operation.label for x in new_circ.data]
+        )
+        self.assertDeprecatedBitProperties(qc, new_circ)
+
     def test_single_bit_teleportation(self):
         """Test a teleportation circuit with single bit conditions."""
         qr = QuantumRegister(1)