# HLL Algorithm results interpretation

I have the following HLL qiskit implementation and really need some help interpreting the results!

# CODE ------------------------------

from qiskit import QuantumRegister, QuantumCircuit

t = 2  # This is not optimal; As an exercise, set this to the

nqubits = 4  # Total number of qubits
nb = 1  # Number of qubits representing the solution
nl = 2  # Number of qubits representing the eigenvalues

theta = 0  # Angle defining |b>

a = 1  # Matrix diagonal
b = -1/3  # Matrix off-diagonal

# Initialize the quantum and classical registers
qr = QuantumRegister(nqubits)

# Create a Quantum Circuit
qc = QuantumCircuit(qr)

qrb = qr[0:nb]
qrl = qr[nb:nb+nl]
qra = qr[nb+nl:nb+nl+1]

# State preparation.
qc.ry(2*theta, qrb[0])

# QPE with e^{iAt}
for qu in qrl:
qc.h(qu)

qc.p(a*t, qrl[0])
qc.p(a*t*2, qrl[1])

qc.u(b*t, -np.pi/2, np.pi/2, qrb[0])

# Controlled e^{iAt} on \lambda_{1}:
params=b*t

qc.p(np.pi/2,qrb[0])
qc.cx(qrl[0],qrb[0])
qc.ry(params,qrb[0])
qc.cx(qrl[0],qrb[0])
qc.ry(-params,qrb[0])
qc.p(3*np.pi/2,qrb[0])

# Controlled e^{2iAt} on \lambda_{2}:
params = b*t*2

qc.p(np.pi/2,qrb[0])
qc.cx(qrl[1],qrb[0])
qc.ry(params,qrb[0])
qc.cx(qrl[1],qrb[0])
qc.ry(-params,qrb[0])
qc.p(3*np.pi/2,qrb[0])

# Inverse QFT
qc.h(qrl[1])
qc.rz(-np.pi/4,qrl[1])
qc.cx(qrl[0],qrl[1])
qc.rz(np.pi/4,qrl[1])
qc.cx(qrl[0],qrl[1])
qc.rz(-np.pi/4,qrl[0])
qc.h(qrl[0])

# Eigenvalue rotation
t1=(-np.pi +np.pi/3 - 2*np.arcsin(1/3))/4
t2=(-np.pi -np.pi/3 + 2*np.arcsin(1/3))/4
t3=(np.pi -np.pi/3 - 2*np.arcsin(1/3))/4
t4=(np.pi +np.pi/3 + 2*np.arcsin(1/3))/4

qc.cx(qrl[1],qra[0])
qc.ry(t1,qra[0])
qc.cx(qrl[0],qra[0])
qc.ry(t2,qra[0])
qc.cx(qrl[1],qra[0])
qc.ry(t3,qra[0])
qc.cx(qrl[0],qra[0])
qc.ry(t4,qra[0])
qc.measure_all()

#-------------------------------

qc.draw(fold=-1)
from qiskit import BasicAer, ClassicalRegister, IBMQ
from qiskit.compiler import transpile
from qiskit.ignis.mitigation.measurement import (complete_meas_cal,CompleteMeasFitter,
MeasurementFilter)

backend = provider.get_backend('ibmqx2') # calibrate using real hardware
layout = [2,3,0,4]
chip_qubits = 5

# Transpiled circuit for the real hardware
qc_qa_cx = transpile(qc, backend=backend, initial_layout=layout)

meas_cals, state_labels = complete_meas_cal(qubit_list=layout, qr=QuantumRegister(chip_qubits))
qcs = meas_cals + [qc_qa_cx]

job = backend.run(qcs, shots=10)

result = job.result()
counts = result.get_counts()
print(counts) # there are 17 of these ... why?


# OUTPUT -------------------------------

[{'0000': 7, '0001': 2, '0010': 1},
{'0001': 9, '1001': 1},
{'0010': 7, '0011': 3},
{'0001': 1, '0010': 1, '0011': 7, '0110': 1},
{'0000': 1, '0100': 8, '1100': 1},
{'0000': 1, '0100': 1, '0101': 8},
{'0010': 1, '0110': 7, '0111': 2},
{'0010': 2, '0110': 2, '0111': 6},
{'0000': 2, '1000': 5, '1100': 3},
{'0001': 4, '1000': 2, '1001': 3, '1010': 1},
{'0010': 2, '1010': 5, '1011': 3},
{'0001': 1, '0111': 1, '1010': 2, '1011': 5, '1111': 1},
{'0100': 1, '1000': 1, '1100': 5, '1101': 2, '1110': 1},
{'0001': 1, '0101': 1, '1001': 1, '1101': 7},
{'0110': 1, '1010': 1, '1110': 6, '1111': 2},
{'1010': 2, '1011': 1, '1111': 7},
{'0001': 2, '0011': 1, '0101': 1, '0110': 1, '1000': 1, '1100': 2, '1110': 1, '1111': 1}]


# Questions ----------------------------------

(1) It appears that each of terms {} are a superposition state where the count/prob amplitudes are given for the comprising 4 qubit states. Is this a correct way to read this?

(2) If the above is true, why are there 17 states here?

(3) Lastly, how can I relate these counts or the subsequent histogram back to the solution vector X = {1.125,0.375}?

I can't seem to find a decent book on practical quantum computing for linear systems, so any recommendations are great there!

From Qiskit documentation on qiskit.ignis.mitigation.complete_meas_cal:

Return a list of measurement calibration circuits for the full Hilbert space. If the circuit contains $$n$$ qubits, then $$2^n$$ calibration circuits are created, each of which creates a basis state.

You are constructing $$1$$ circuit and the complete_measure_call is returning $$16 = 2^4$$ calibration circuits because you gave it a list of $$4$$ qubits. Your $$17$$ circuits are here: $$1$$ from you and $$16$$ from complete_measure_cal.

In your simulation, the $$16$$ first circuits are measurement calibration and the last one is the result of your implementation. A few remarks though:

1. You are only using 10 shots, which is very small. All the backends accept $$8192$$ jobs, and I would advise to always submit that much jobs as most of the wait time is spent in the queue, not in executing the circuits.
2. You submit calibration circuits but you do not mitigate the measurement errors at the end. With only 10 shots I expect the results to be very imprecise, but have a look here to understand how to use measurement mitigation.
3. If you want only the counts associated to a specific circuit you can specify it in the get_counts method: result.get_counts(qc_qa_cx) will return you only $$1$$ result, the one associated with the circuit qc_qa_cx.
• Thank you so much! This was a huge help Adrien! – Corey Jul 2 at 15:30
• Follow up question. I am now just looking at the histogram for my circuit using 1000. This output is :: {'0000': 1, '0001': 2, '0010': 21, '0011': 8, '0100': 3, '0101': 3, '0110': 6, '0111': 7, '1000': 4, '1001': 4, '1010': 5, '1011': 6, '1100': 18, '1101': 8, '1110': 2, '1111': 2} How does this relate back to the solution? I know that the amplitude of each of the 16, 4 qubit states somehow does. Also, I noticed that as I increased the number of shots, the number of states in the histogram increased. I assume that is it because there are more non-zero amplitude hits? – Corey Jul 2 at 17:39