Qiskit / qiskit

Qiskit is an open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
https://www.ibm.com/quantum/qiskit
Apache License 2.0
5k stars 2.32k forks source link

QuantumCircuit.initialize() does not support parameters #7298

Open HGmin1159 opened 2 years ago

HGmin1159 commented 2 years ago

What is the expected enhancement?

I found that when I built custom data encoding methods in parameterized quantum circuit, we cannot use parameter instance(;qiskit.circuit.Parameter) at the qiskit.QuantumCircuit.initialize() function. It returned error according to follow code in qiskit.QuantumCircuit.initialize line 74~75 because the contemporary parameter instance cannot works with numpy.absolute.

if not math.isclose(sum(np.absolute(params) ** 2), 1.0, abs_tol=_EPS):
        raise QiskitError("Sum of amplitudes-squared does not equal one.")

So I changed the code as follow and tested simple circuits.

check_param = False
    try:
      if not math.isclose(sum(np.absolute(params) ** 2), 1.0, abs_tol=_EPS):
        check_param=True
    except:
      pass
    if check_param :raise QiskitError("Sum of amplitudes-squared does not equal one.")
def amplitude_encoding(num_qubits,x):
    qc = QuantumCircuit(num_qubits,name ="Amplitude Encoding")
    qc.initialize(x, range(num_qubits))
    encode = qc.to_instruction()
    return encode
param_set = [Parameter("X"+str(i)) for i in range(8)]
qc = QuantumCircuit(3)
## Custom Encoding Instruction
featuremap = amplitude_encoding(3,param_set)
qc.append(featuremap,range(3))
qc.measure_all()
qc.draw("mpl")
shots = 2048
data = np.array([1,2,3,4,5,6,7,8]);datas = data/np.linalg.norm(data)
backend = BasicAer.get_backend('qasm_simulator')
circuit = qc.bind_parameters({qc.parameters[i]:datas[i] for i in range(8)})
job = backend.run(transpile(circuit, backend),shots=shots)
result = job.result().get_counts()
result_frame = pd.DataFrame([[int(i,2),j] for i,j in result.items()]).sort_values(by=0)
result_frame.index = range(8);result_frame.columns = ["Qubit","Counts"];result_frame["Prob_Estimates"] = result_frame["Counts"]/shots;result_frame["Prob_True"] = datas**2
result_frame

image-20211120132732776

I could find that ratio of counts are almost similar with intended encoding probability which is ideal result. There is a table of result below. If we can use them, we can encode data into amplitudes like which can be used in many situation because it perfectly matches with the form of real Euclidean vector. Above refinement is not perfect because it cannot catch the vector norm problem when binding real parameter. But I think the advantages of implementing the amplitude encoding overweight the problem. So maybe we can use it until new version comes out

Cryoris commented 2 years ago

If you want to define a parameterized initialize instruction you can use the RawFeatureVector of Qiskit ML:

>>> from qiskit_machine_learning.circuit.library import RawFeatureVector
>>> from qiskit.circuit import QuantumCircuit
>>> circuit = QuantumCircuit(3)
>>> circuit.compose(RawFeatureVector(2 ** circuit.num_qubits), inplace=True)
>>> circuit.draw()
     ┌───────────────────────────────────────────────────────────────────┐
q_0: ┤0                                                                  ├
     │                                                                   │
q_1: ┤1 Parameterizedinitialize(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7]) ├
     │                                                                   │
q_2: ┤2                                                                  ├
     └───────────────────────────────────────────────────────────────────┘
>>> bound = circuit.bind_parameters(list(range(8)))
>>> bound.decompose().draw()
     ┌─────────────────────────────────────────────────────────────────────────┐
q_0: ┤0                                                                        ├
     │                                                                         │
q_1: ┤1 Initialize(0,0.084515,0.16903,0.25355,0.33806,0.42258,0.50709,0.59161) ├
     │                                                                         │
q_2: ┤2                                                                        ├
     └─────────────────────────────────────────────────────────────────────────┘
HGmin1159 commented 2 years ago

Oh, I didn't know that. Thank you sir. Maybe I need to check all of the relevant qiskit functions and organize them.

Thank you again.

Cryoris commented 2 years ago

If we want to have this feature in Terra we can just port it from Qiskit Machine Learning 🙂 I think we actually wanted to do this some time ago but never got around to doing it 😄

1ucian0 commented 2 years ago

Would it be fair to rename this issue to QuantumCircuit.initialize() does not support parameters?

HGmin1159 commented 2 years ago

Done it. Thank you Sir. I've never used github issue before ,so I didn't know there is a name in issue lol.