.. _advanced: ############## Advanced usage ############## Options for M3Mitigation class ------------------------------ ``iter_threshold`` ~~~~~~~~~~~~~~~~~~ The main :class:`mthree.M3Mitigation` class accepts the `iter_threshold` keyword argument that determines when the automated method selector pickes the iterative method over direct LU factorization (selection also depends on free memory). .. jupyter-execute:: from qiskit.providers.fake_provider import FakeCasablanca import mthree backend = FakeCasablanca() mit = mthree.M3Mitigation(backend, iter_threshold=4321) Options for calibration ----------------------- ``shots`` ~~~~~~~~~ When calibrating the mitigator, it is possible to vary the number of shots per calibration circuit: .. jupyter-execute:: mit = mthree.M3Mitigation(backend) mit.cals_from_system(range(5), shots=4321) ``method`` ~~~~~~~~~~ There are three ways to do the calibration. The default ``balanced`` method executes :math:`2N` circuits with varying bitstring patterns such that the :math:`|0\rangle` and :math:`|1\rangle` states are each prepared :math:`N` times and averaged over. For example, the balanced bit-strings over four qubits are .. jupyter-execute:: mthree.circuits.balanced_cal_strings(4) The ``independent`` method also sends :math:`2N` circuits but measures only a single qubit at a time. As such, this is a truely uncorrelated calibration process. Finally, a ``marginal`` calibration can also be done that sends only two circuits, :math:`|0\rangle^{\otimes N}` and :math:`|1\rangle^{\otimes N}`, and marginalizes over the results to get the needed :math:`2N` error rates. These two states are a sub-set of the ``balanced`` calibrations, and are what Qiskit uses in its readout mitigation. This method is very sensitive to state preparation errors, and should not be used in practice. An example setting the method is .. jupyter-execute:: mit = mthree.M3Mitigation(backend) mit.cals_from_system(range(5), method='independent') ``rep_delay`` ~~~~~~~~~~~~~ .. caution:: Do not set this unless you know what you are doing. The ``rep_delay`` keyword argument sets the time between calibration circuits on IBM Quantum systems. This option exists to test and reduce the presence of state prep errors. The calibration circuits in M3 all contain conditional resets at the beginning so as to minimize the need for setting this option. .. jupyter-execute:: mit = mthree.M3Mitigation(backend) mit.cals_from_system(range(5), rep_delay=400e-6) ``initial_reset`` ----------------- .. caution:: Do not set this unless you know what you are doing. A boolean value that specifies whether reset instructions should be used at the beginning of the calibration circuits. Ideally this helps to supress any residual state prep errors that occur from imperfect reset of the qubits. Can be used in concert with, or as an alternative to ``rep_delay``. Note that, in order for this to work, the circuits that need to be mitigated must also have reset instructions at the beginning. Otherwise you are calibrating for no state-prep errors, but the actual circuits may still suffer from these errors. Options when applying corrections --------------------------------- Here we first calibrate a mitigator and generate raw counts: .. jupyter-execute:: from qiskit import * qc = QuantumCircuit(6) qc.reset(range(6)) qc.h(3) qc.cx(3,1) qc.cx(3,5) qc.cx(1,0) qc.cx(5,4) qc.cx(1,2) qc.measure_all() mit = mthree.M3Mitigation(backend) mit.cals_from_system(range(6)) trans_qc = transpile(qc, backend) raw_counts = backend.run(trans_qc, shots=8192).result().get_counts() ``method`` ~~~~~~~~~~ There are two ways to solve the linear system of equations generated by M3. First, the ``direct`` method uses LU-factorization by constructing the reduced assignment matrix. Second the ``iterative`` method uses preconditioned iterative solvers to find the solution vector without explicit matrix construction. By default M3 uses an ``auto`` method that selects the appropriate solution method based on the number of unique bit-strings and the available free memory on the computer. To override this, one can simply set the option: .. jupyter-execute:: quasis = mit.apply_correction(raw_counts, range(6), method='iterative') ``distance`` ~~~~~~~~~~~~ Optionally one may trucate the M3 assignment matrix to only those elements of the matrix that are transistions between elements less than or equal to a given Hamming distance away from each other. This does not change the dimensionality of the underlying matrix, but rather changes the sparsity pattern of the elements. This is done using the ``distance`` keyword argument. By default, M3 computes the corrections out to the full distance. In practice, including only up to ``distance=3`` elements yields accurate answers in most cases. .. jupyter-execute:: quasis = mit.apply_correction(raw_counts, range(6), distance=3) ``details`` ~~~~~~~~~~~ Allows one to see additional information about the solution. This changes the return of the :method:``mthree.M3Mitigation.apply_correction`` method to a tuple of two values: .. jupyter-execute:: quasis, details = mit.apply_correction(raw_counts, range(6), details=True) print(details) ``max_iter`` ~~~~~~~~~~~~ .. caution:: Do not set this unless you know what you are doing. Sets the maximum number of iterations performed by the iterative solver. .. jupyter-execute:: quasis = mit.apply_correction(raw_counts, range(6), method='iterative', max_iter=10) ``tol`` ~~~~~~~ .. caution:: Do not set this unless you know what you are doing. Sets the tolerance of the iterative solver. Might need adjustments to ``max_iter`` if value is set too low. .. jupyter-execute:: quasis = mit.apply_correction(raw_counts, range(6), method='iterative', tol=1e-6)