It's not possible to create the initial states $\left| \Psi_0\right>$ and $\left|b\right>$ on the IBM 16 qubits version. On the other hand, it is possible to approximate them with an arbitrarily low error1 as the gates implemented by the IBM chips offer this possibility.
Here you ask for 2 different quantum states:
- $\left| b \right>$ is not restricted at all. The state $\left| b \right>$ is represented by a vector of $N$ complex numbers that can be anything (as long as the vector has unitary norm).
- $\left| \Psi_0 \right>$ can be seen as a special case of $\left| b \right>$, where the coefficients $b_i$ are more constrained.
With this analysis, any method that can be used for creating $\left|b\right>$ can also be used to create $\left| \Psi_0 \right>$. On the other hand, as $\left| \Psi_0 \right>$ is more constrained, we can hope that there exists more efficient algorithms to produce $\left| \Psi_0 \right>$.
Useful for $\left|b\right>$ and $\left|\Psi_0\right>$: Based on Synthesis of Quantum Logic Circuits (Shende, Bullock & Markov, 2006), the QISKit Python SDK implements a generic method to initialize an arbitrary quantum state.
Useful for $\left|\Psi_0\right>$: Creating superpositions that correspond to efficiently integrable probability distributions (Grover & Rudolph, 2002) presents quickly an algorithm to initialise a state whose amplitudes represents a probability distribution respecting some constraints. These constraints are respected for $\left|\Psi_0\right>$ according to Quantum algorithm for solving linear systems of equations (Harrow, Hassidim & Lloyd, 2009), last line of page 5.
For the implementation on QISKit, here is a sample to initialise a given quantum state:
import qiskit
statevector_backend = qiskit.get_backend('local_statevector_simulator')
###############################################################
# Make a quantum program for state initialization.
###############################################################
qubit_number = 5
Q_SPECS = {
"name": "StatePreparation",
"circuits": [
{
"name": "initializerCirc",
"quantum_registers": [{
"name": "qr",
"size": qubit_number
}],
"classical_registers": [{
"name": "cr",
"size": qubit_number
}]},
],
}
Q_program = qiskit.QuantumProgram(specs=Q_SPECS)
## State preparation
import numpy as np
from qiskit.extensions.quantum_initializer import _initializer
def psi_0_coefficients(qubit_number: int):
T = 2**qubit_number
tau = np.arange(T)
return np.sqrt(2 / T) * np.sin(np.pi * (tau + 1/2) / T)
def get_coeffs(qubit_number: int):
# Can be changed to anything, the initialize function will take
# care of the initialisation.
return np.ones((2**qubit_number,)) / np.sqrt(2**qubit_number)
#return psi_0_coefficients(qubit_number)
circuit_prep = Q_program.get_circuit("initializerCirc")
qr = Q_program.get_quantum_register("qr")
cr = Q_program.get_classical_register('cr')
coeffs = get_coeffs(qubit_number)
_initializer.initialize(circuit_prep, coeffs, [qr[i] for i in range(len(qr))])
res = qiskit.execute(circuit_prep, statevector_backend).result()
statevector = res.get_statevector("initializerCirc")
print(statevector)
1Here "error" refers to the error between the ideal state and the approximation when dealing on a perfect quantum computer (i.e. no decoherence, no gate error).