qiskit-ignis icon indicating copy to clipboard operation
qiskit-ignis copied to clipboard

QPT fitter should marginalize counts over measured qubits

Open singular-value opened this issue 5 years ago • 7 comments

Informations

  • Qiskit Ignis version: master
  • Python version: 3.7.1
  • Operating system: macOS Mojave

What is the current behavior?

ProcessTomographyFitter.fit() gives an array with NaNs, because the counts dictionary is not marginalized.

Steps to reproduce the problem

Do something like:

qpt_tomo = q.ignis.verification.tomography.ProcessTomographyFitter(job.result(), qpt_circs)
choi_lstsq = qpt_tomo.fit(method='lstsq')

on a device that does not return pre-marginalized counts (maybe this is only on OpenPulse interfaces).

What is the expected behavior?

Should give a choi matrix that can be plotted as a state city.

Suggested solutions

Something like, in qiskit/ignis/verification/tomography/fitters/base_fitter.py:TomographyFitter._fitter_data, add cts = qiskit.ignis.verification.tomography.data.marginal_counts(cts, meas_qubits=meas_qubits) on the first line of the for loop. This would require propogating the measured qubits to this function somehow though...

singular-value avatar Oct 22 '19 19:10 singular-value

because the counts dictionary is not marginalized.

Could you explain what you mean here with an example?

dcmckayibm avatar Nov 03 '19 02:11 dcmckayibm

@chriseclectic wasn't there a marginal counts in terra? I can't seem to find it

dcmckayibm avatar Nov 03 '19 02:11 dcmckayibm

@chriseclectic wasn't there a marginal counts in terra? I can't seem to find it

I think that the plan is to move the code of marginal_counts from tomography to terra (qiskit.tools), see: https://github.com/Qiskit/qiskit-ignis/blob/master/qiskit/ignis/verification/tomography/init.py

ShellyGarion avatar Nov 03 '19 09:11 ShellyGarion

@dcmckayibm sorry about the delay, I'll make a code snippet to reproduce, but will be a few days. Thanks!

singular-value avatar Nov 12 '19 04:11 singular-value

Here is a code snippet to reproduce. It's the smallest one I could come up with:

import qiskit as q
provider = ...
backend = provider.get_backend('ibmq_johannesburg')
defaults = backend.defaults()
circ_inst_map = defaults.circuit_instruction_map
pulse_gate = q.circuit.Gate(name='pulse_gate', num_qubits=1, params=[])
circ_inst_map.add('pulse_gate', qubits=[0], schedule=q.pulse.Schedule())  # pulse_gate does nothing
qreg = q.QuantumRegister(1)
circ = q.QuantumCircuit(qreg)
_ = circ.append(pulse_gate, [0], [])
basis_gates = backend.configuration().basis_gates
basis_gates.append('pulse_gate')
qpt_circs = q.ignis.verification.tomography.process_tomography_circuits(
    circ, prepared_qubits=[qreg[0]], measured_qubits=[qreg[0]])
qpt_circs = [q.transpile(qpt_circ, backend=backend, basis_gates=basis_gates) for qpt_circ in qpt_circs]
qpt_schedules = [q.schedule(qpt_circ, inst_map=circ_inst_map, backend=backend) for qpt_circ in qpt_circs]
job = q.execute(qpt_schedules, backend=backend, shots=100)
qpt_tomo = q.ignis.verification.tomography.ProcessTomographyFitter(job.result(), qpt_circs)
choi_lstsq = qpt_tomo.fit(method='lstsq')

and stacktrace for the last line:

~/Developer/qiskit/qiskit-ignis/qiskit/ignis/verification/tomography/fitters/base_fitter.py:292: RuntimeWarning: invalid value encountered in true_divide
  probs = np.array(cts) / shots
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-13-cab92b209680> in <module>
----> 1 choi_lstsq = qpt_tomo.fit(method='lstsq')

~/Developer/qiskit/qiskit-ignis/qiskit/ignis/verification/tomography/fitters/process_fitter.py in fit(self, method, standard_weights, beta, **kwargs)
    137         if method == 'lstsq':
    138             return Choi(lstsq_fit(data, basis_matrix, weights=weights,
--> 139                                   trace=dim, **kwargs))
    140         if method == 'cvx':
    141             return Choi(cvx_fit(data, basis_matrix, weights=weights, trace=dim,

~/Developer/qiskit/qiskit-ignis/qiskit/ignis/verification/tomography/fitters/lstsq_fit.py in lstsq_fit(data, basis_matrix, weights, PSD, trace)
     89 
     90     # Perform least squares fit using Scipy.linalg lstsq function
---> 91     rho_fit, _, _, _ = lstsq(a, b)
     92 
     93     # Reshape fit to a density matrix

~/anaconda3/envs/QiskitDevenv/lib/python3.7/site-packages/scipy/linalg/basic.py in lstsq(a, b, cond, overwrite_a, overwrite_b, check_finite, lapack_driver)
   1151     """
   1152     a1 = _asarray_validated(a, check_finite=check_finite)
-> 1153     b1 = _asarray_validated(b, check_finite=check_finite)
   1154     if len(a1.shape) != 2:
   1155         raise ValueError('Input array a should be 2-D')

~/anaconda3/envs/QiskitDevenv/lib/python3.7/site-packages/scipy/_lib/_util.py in _asarray_validated(a, check_finite, sparse_ok, objects_ok, mask_ok, as_inexact)
    237             raise ValueError('masked arrays are not supported')
    238     toarray = np.asarray_chkfinite if check_finite else np.asarray
--> 239     a = toarray(a)
    240     if not objects_ok:
    241         if a.dtype is np.dtype('O'):

~/anaconda3/envs/QiskitDevenv/lib/python3.7/site-packages/numpy/lib/function_base.py in asarray_chkfinite(a, dtype, order)
    494     if a.dtype.char in typecodes['AllFloat'] and not np.isfinite(a).all():
    495         raise ValueError(
--> 496             "array must not contain infs or NaNs")
    497     return a
    498 

ValueError: array must not contain infs or NaNs

The error is confusing, but the root cause is that OpenPulse jobs return measurement outcomes over all device qubits, not just the one that we are explicitly measuring. So for example, job.result().get_counts(i) returns a dictionary where the keys are 20-long-bitstrings, which in turn messes up qiskit-ignis/qiskit/ignis/verification/tomography/fitters/base_fitter.py:_fitter_data

Perhaps the most correct fix is to change this behavior on OpenPulse backends--i.e. only return measurement outcomes over the qubits that are explicitly measured.

singular-value avatar Dec 19 '19 16:12 singular-value

I can fix this problem locally in tomography by explicitly marginalizing if the size of the returned result is not the same as the number of clbits, but this is really a hack and not a good one - this problem should be fixed in the OpenPulse backends, or (better, in my opinion) in the Result object.

gadial avatar Jun 02 '20 07:06 gadial

Seeing something that looks like this report with ValueError: array must not contain infs or NaNs. I've been comparing to IBM's tutorials and find some that work that look identical in syntax for the statement that fails (rho_fit_qc = tomo_fitter_qc.fit(method='lstsq'))...but it isn't working with my circuit/gate combination.

Version: Pycharm 2020.3.5, python 3.8, qiskit 0.28.0, qiskit-ignis 0.6.0

Here are the errors:

/Users/juliegermain/opt/anaconda3/envs/QuantumResearch/bin/python "/Users/juliegermain/Library/Application Support/JetBrains/PyCharmCE2020.3/scratches/EntSwap_withDensityMatrix.py" /Users/juliegermain/opt/anaconda3/envs/QuantumResearch/lib/python3.8/site-packages/qiskit/ignis/verification/tomography/basis/circuits.py:468: DeprecationWarning: The QuantumCircuit.iadd() method is being deprecated. Use the compose() (potentially with the inplace=True argument) and tensor() methods which are more flexible w.r.t circuit register compatibility. prep += circuit /Users/juliegermain/opt/anaconda3/envs/QuantumResearch/lib/python3.8/site-packages/qiskit/circuit/quantumcircuit.py:942: DeprecationWarning: The QuantumCircuit.extend() method is being deprecated. Use the compose() (potentially with the inplace=True argument) and tensor() methods which are more flexible w.r.t circuit register compatibility. return self.extend(rhs) /Users/juliegermain/opt/anaconda3/envs/QuantumResearch/lib/python3.8/site-packages/qiskit/ignis/verification/tomography/basis/circuits.py:478: DeprecationWarning: The QuantumCircuit.add() method is being deprecated.Use the compose() method which is more flexible w.r.t circuit register compatibility. circ = prep + meas /Users/juliegermain/opt/anaconda3/envs/QuantumResearch/lib/python3.8/site-packages/qiskit/circuit/quantumcircuit.py:933: DeprecationWarning: The QuantumCircuit.combine() method is being deprecated. Use the compose() method which is more flexible w.r.t circuit register compatibility. return self.combine(rhs) /Users/juliegermain/opt/anaconda3/envs/QuantumResearch/lib/python3.8/site-packages/qiskit/ignis/verification/tomography/fitters/base_fitter.py:348: RuntimeWarning: invalid value encountered in true_divide probs = np.array(cts) / shots Time taken: 3.728592872619629 Traceback (most recent call last): File "/Users/juliegermain/Library/Application Support/JetBrains/PyCharmCE2020.3/scratches/EntSwap_withDensityMatrix.py", line 93, in rho_fit_qc = tomo_fitter_qc.fit(method='lstsq') # needed to calculate fidelity File "/Users/juliegermain/opt/anaconda3/envs/QuantumResearch/lib/python3.8/site-packages/qiskit/ignis/verification/tomography/fitters/state_fitter.py", line 122, in fit return super().fit(method, standard_weights, beta, File "/Users/juliegermain/opt/anaconda3/envs/QuantumResearch/lib/python3.8/site-packages/qiskit/ignis/verification/tomography/fitters/base_fitter.py", line 220, in fit return lstsq_fit(data, basis_matrix, File "/Users/juliegermain/opt/anaconda3/envs/QuantumResearch/lib/python3.8/site-packages/qiskit/ignis/verification/tomography/fitters/lstsq_fit.py", line 100, in lstsq_fit rho_fit, _, _, _ = lstsq(meas_matrix, exp_values) File "/Users/juliegermain/opt/anaconda3/envs/QuantumResearch/lib/python3.8/site-packages/scipy/linalg/basic.py", line 1142, in lstsq b1 = _asarray_validated(b, check_finite=check_finite) File "/Users/juliegermain/opt/anaconda3/envs/QuantumResearch/lib/python3.8/site-packages/scipy/_lib/_util.py", line 262, in _asarray_validated a = toarray(a) File "/Users/juliegermain/opt/anaconda3/envs/QuantumResearch/lib/python3.8/site-packages/numpy/lib/function_base.py", line 488, in asarray_chkfinite raise ValueError( ValueError: array must not contain infs or NaNs

Here is the code:

from qiskit import * from qiskit.visualization import plot_histogram from qiskit.providers.ibmq import least_busy from qiskit.tools.monitor import job_monitor import qiskit.quantum_info as qi

Tomography functions

from qiskit.ignis.verification.tomography import state_tomography_circuits, StateTomographyFitter

import matplotlib.pyplot as plt import time #======================================= qA = QuantumRegister(1,'alice') qC1= QuantumRegister(1,'charlie1') qC2= QuantumRegister(1,'charlie2') qB = QuantumRegister(1,'bob') cr = ClassicalRegister(2)

qc = QuantumCircuit(qA,qC1,qC2,qB,cr)

for i in range(0,4): qc.reset(i)

Entangle 2 pair

qc.h(qC1) qc.h(qC2) qc.cx(qC1,qA) qc.cx(qC2,qB)

qc.barrier()

entangle one "arm" of a pair to the 2nd pair

qc.h(qA) qc.h(qC2) qc.cx(qC2,qA) qc.h(qA) qc.h(qC2)

qc.barrier()

entangle 2nd "arm" to the 2nd pair...no all 4 entangled

qc.h(qB) qc.h(qC1) qc.cx(qC1,qB) qc.h(qB) qc.h(qC1)

qc.barrier()

#============================================

Get ideal output state

ideal_state_qc = qi.Statevector.from_instruction(qc) #===========================================

Get Experimental density matrix (rho_qc)

Generate circuits and run on simulator

t = time.time() qst_qc = state_tomography_circuits(qc,(qA,qC1,qC2,qB)) job = qiskit.execute(qst_qc, Aer.get_backend('qasm_simulator'), shots=5000)

Fit result

tomo_fitter_qc = StateTomographyFitter(job.result(), qst_qc) print('Time taken:', time.time() - t)

t = time.time() rho_fit_qc = tomo_fitter_qc.fit(method='lstsq') # needed to calculate fidelity print('Time taken fit:', time.time() - t)

Calculate Fidelity

F_qc = qi.state_fidelity(rho_fit_qc, ideal_state_qc) print('State Fidelity: F = {:.5f}'.format(F_qc))

jgermain48 avatar Aug 25 '21 19:08 jgermain48