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
5.24k stars 2.36k forks source link

allow QuantumChannel as target in process_fidelity? #4694

Closed qci-amos closed 3 years ago

qci-amos commented 4 years ago

Hi all,

I've been looking at your process_fidelity method along with your Process Tomography tutorial.

I noticed that in process_fidelity, you do not allow users to pass in a noisy QuantumChannel for target like you do for the channel argument: https://github.com/Qiskit/qiskit-terra/blob/7af29f44581a5f2d16069ac24d284be45c8deb9f/qiskit/quantum_info/operators/measures.py#L85-L91

If I try, I get the exception:

QiskitError: 'Channel cannot be converted to Operator representation'

The reason I ran into this is because in the process tomography tutorial: https://github.com/Qiskit/qiskit-tutorials/blob/master/legacy_tutorials/ignis/6b_process_tomography.ipynb it passes in numpy matrices instead of Choi instances which ends up giving the wrong fidelities (and you see it's passing in the noisy Choi data for the 2nd argument which is target):

print('fit fidelity (process):', np.real(process_fidelity(choi_ideal, choi_lstsq.data, require_cptp=False)))

I came up with a little test program to explore this:

from qiskit import *
from qiskit.quantum_info import Statevector, process_fidelity, purity, state_fidelity, average_gate_fidelity
from qiskit.quantum_info.operators.channel import PTM, Chi, Choi, SuperOp
from qiskit.quantum_info.operators import Operator
from qiskit.quantum_info import process_fidelity
from qiskit.ignis.verification.tomography import process_tomography_circuits, ProcessTomographyFitter

def get_choi(circuit, with_noise=False):
    if with_noise:
        # Generate process tomography circuits and run on qasm simulator
        qpt_circs = process_tomography_circuits(circuit, circuit.qregs[0])
        job = qiskit.execute(qpt_circs, Aer.get_backend('qasm_simulator'), shots=500)

        # Extract tomography data so that counts are indexed by measurement configuration
        qpt_tomo = ProcessTomographyFitter(job.result(), qpt_circs)

        choi_lstsq = qpt_tomo.fit(method='lstsq')
        return choi_lstsq

    job = qiskit.execute(circuit, Aer.get_backend("unitary_simulator"))
    ideal_unitary = job.result().get_unitary(circuit)

    TOL = 1e-14
    ideal_unitary.real[abs(ideal_unitary.real) < TOL] = 0.0
    ideal_unitary.imag[abs(ideal_unitary.imag) < TOL] = 0.0
    choi_ideal = Choi(outer(ideal_unitary.ravel(order="F")))
    return choi_ideal

def superop_pf(channel, target):
    # this alters qiskit's process_fidelity to use SuperOp for target
    channel = SuperOp(channel)
    input_dim, output_dim = channel.dim
    target = SuperOp(target)
    channel = channel.adjoint() @ target
    fid = np.trace(channel.data) / (input_dim**2)
    return float(np.real(fid))

def chow_eq8(Rexp, Rideal):
    nq = np.log(Rexp.shape[0]) / np.log(4)
    d = 2.0 * nq
    F = np.trace(Rexp.T @ Rideal)/(d*d)
    return F.real

circuit = QuantumCircuit(1)
circuit.rx(np.pi, 0)
choi_pi = get_choi(circuit)
ptm_pi = PTM(choi_pi)

rows = []
for theta in np.linspace(-1,1,9):
    circuit = QuantumCircuit(1)
    circuit.rx(theta*np.pi, 0)
    choi_theta = get_choi(circuit, with_noise=True)
    ptm_theta = PTM(choi_theta)

    eq8 = chow_eq8(np.matrix(ptm_pi.data), np.matrix(ptm_theta.data))

    #errors:
    #pf=process_fidelity(choi_pi, choi_theta, require_cp=False),

    rows.append(dict(
        theta=theta,
        tutorial=process_fidelity(choi_pi.data, choi_theta.data, require_cp=False),
        pf=process_fidelity(choi_theta, choi_pi, require_cp=False),
        superop_pf=superop_pf(choi_pi, choi_theta),
        eq8=eq8
    ))

pd.options.display.float_format = '{:,.4f}'.format    
df = pd.DataFrame(rows)
df

and I get:

image

It seems like you could allow users to pass in a noisy QuantumChannel for target if you add code to convert it to a SuperOp instead of always an Operator.

qci-amos commented 3 years ago

it looks like this was fixed at some point: https://github.com/Qiskit/qiskit-terra/blob/a2193a5c3df131775e1b2d0f2f8fe31dc035ae0c/qiskit/quantum_info/operators/measures.py#L70-L72

that is, it looks like a QuantumChannel is now an option for both channel and target.