Closed SimoneGasperini closed 2 years ago
I would appreciate a way to encode lists of numbers, if nothing else it would be helpful for debugging.
I think that we do not have such an encoding in the circuit library yet. However, you can encode your data (after normalizing it) as a quantum state using the StatePreparation class. See this code for example:
import numpy as np
from qiskit.circuit.library import StatePreparation
from qiskit.quantum_info import Statevector
arr = [2, 1, 2, 0, 0, 1, 3, 2]
norm = np.linalg.norm(arr)
SP = StatePreparation(arr / norm)
print(SP)
qc = QuantumCircuit(3)
qc.append(SP, [0,1,2])
print (qc)
print(qc.decompose().decompose().decompose().decompose().decompose())
print (Statevector(qc))
Ok thank you @ShellyGarion!
So there we are actually implementing "amplitude encoding", right? I run that circuit by using the qasm_simulator
backend and the final measurements on the 3-qubits-system are the following:
Makes sense! The probabilities seems indeed to correspond to the square of each entry in the original (normalized) array:
(arr / norm)**2 = [0.174, 0.043, 0.174, 0.0, 0.0, 0.043, 0.391, 0.174]
This issue seems to have been resolved, as far as I can see? I'll close it now, but please feel free to re-open, or make a new issue if there's more to discuss.
A general procedure to encode a list/array of non-negative numbers (e.g. arr = [2, 1, 2, 0, 0, 1, 3, 2]
in the quantum state $|\psi\rangle$ (basis encoding) could be implemented as follows:
import numpy as np
from qiskit import QuantumCircuit
from qiskit.circuit.library import StatePreparation
len_qr1 = int(np.ceil(np.log2(len(arr)))) # index quantum register
len_qr2 = int(np.log2(max(arr))) + 1 # element quantum register
num_qubits = len_qr1 + len_qr2
statevector = np.zeros(2**num_qubits)
for i, el in enumerate(arr):
index_reg = '{0:b}'.format(i).zfill(len_qr1)
element_reg = '{0:b}'.format(el).zfill(len_qr2)
statevector[int(element_reg + index_reg, 2)] = 1
statevector /= np.linalg.norm(statevector) # normalization
qc = QuantumCircuit(num_qubits)
sp = StatePreparation(statevector)
qc.append(sp, range(num_qubits))
from qiskit import Aer, execute
from qiskit.visualization import plot_histogram
qc.measure_all()
backend = Aer.get_backend('qasm_simulator')
job = execute(qc, backend=backend, shots=10000)
counts = job.result().get_counts()
plot_histogram(counts)
PS: this works properly only if $\mathrm{len}(\mathrm{arr})$ is a power of 2 (could be generalized with a bit of work) and it requires a number of qubits $$N\sim\log_2(\mathrm{len}(\mathrm{arr})) + \log_2(\mathrm{max}(\mathrm{arr}))$$
Suppose I am given the following Python list/array as an example:
arr = [2, 1, 2, 0, 0, 1, 3, 2]
To encode this data into a quantum state I can use the "bit-string basis encoding" technique, writing both the integer elements and the integer indices of
arr
as binary strings $s \in \{ 0,1 \}^*$ and then transforming them into a quantum state on the computational basis. In this case, I would need $n=3$ qubits to encode the indices $i=0,\dots,N-1$ with $N=2^n=8$ and $n_*=2$ more qubits to encode the digits $\mathrm{arr}_i\in \{ 0,1,2,3 \}$, ending up with the following state:$$|\psi \rangle = \frac{1}{\sqrt{N}} \sum_{i=0}^{N-1} |\mathrm{arr}_i \rangle |i\rangle$$
The Qiskit code implementing the quantum circuit to prepare the state $|\psi \rangle$ would look like this:
Questions: 1) Is this correct? Are there more efficient techniques for data encoding? 2) Does Qiskit provide any functionality to automatically prepare the quantum state given a generic Python list?