Noisy state preparation and measurement¶

The QLM's noise models include noisy state preparations and measurements. To describe those, you will need to specify the initial density matrix as well as the observable corresponding to the measurement.

Simple example¶

Here is a code snippet where we specify a perfect initial state $|0\rangle \langle 0|$ and imperfect measurement:

In [1]:
import numpy as np
from qat.hardware import DefaultGatesSpecification, HardwareModel

eps=0.1

gates_spec = DefaultGatesSpecification(gate_times = {"state_prep": 1, "meas": 1, "X": 10},
                                       state_prep=np.array([[1.0, 0.0],
                                                           [0.0, 0.0]]),
                                       meas=np.array([[eps, 0.0],
                                                      [0.0, 1.0-eps]]))

hw_model = HardwareModel(gates_spec)

Note that we suppose that the initial density matrix is factorized among the different qubits:

$$\rho_0 = \rho^{(1)} \otimes \rho^{(2)} \dots \otimes \rho^{(n)}$$

and we input, in the state_prep field, the density matrix $\rho_0 = \rho^{i}$ (assuming all qubits are initialized to the same density matrix). Note that one can also specify a different density matrix for each qubit by input a dictionary instead (see below).

As for the measurement observable, it is also assumed to be factorizable among all qubits. At the qubit level, it is specified as a two-outcome POVM $\lbrace I -E, E \rbrace$. The operation elements $E$ and $I-E$ are positive semi definite. The outcome probabilities are given by $p(0) = Tr(\rho (I-E))$ and $p(1) = Tr(\rho E)$. A perfect measurement is described by $E = |1\rangle \langle 1|$.

Qubit-wise specification¶

One can also specify different initial states for each qubit by replacing the np.array by a dictionary, with one key per qubit:

In [2]:
eps0, eps1 = 0.1, 0.05
gates_spec = DefaultGatesSpecification(gate_times = {"state_prep": 1, "meas": 1, "X": 10},
                                       state_prep={0: np.array([[1.0, 0.0],
                                                           [0.0, 0.0]]),
                                                   1: np.array([[1.0, 0.0],
                                                           [0.0, 0.0]])},
                                       meas={0: np.array([[eps0, 0.0],
                                                         [0.0, 1.0-eps0]]),
                                             1: np.array([[eps1, 0.0],
                                                        [0.0, 1.0-eps1]])}
                                      )
hw_model = HardwareModel(gates_spec)

Running a noisy computation¶

We now run a computation with a QPU affected by these SPAM errors:

In [3]:
from qat.qpus import NoisyQProc

qpu_spam = NoisyQProc(hardware_model=hw_model)
In [4]:
from qat.lang.AQASM import X, Program
prog = Program()
reg = prog.qalloc(2)
prog.apply(X, reg[0])
job = prog.to_circ().to_job()

results = qpu_spam.submit(job)
for sample in results:
    print(sample)
/tmp/ipykernel_42572/3606463432.py:7: UserWarning: Solution may be inaccurate. Try another solver, adjusting the solver settings, or solve with verbose=True for more information.
  results = qpu_spam.submit(job)
Sample(_amplitude=None, probability=np.float64(0.09499999999999989), _state=b'\x00', err=None, intermediate_measurements=None, qregs=[QRegister(scope=<qat.lang.AQASM.program.Program object at 0x14c19ce367b0>, length=2, start=0, msb=None, _subtype_metadata=None, qbits=[<qat.lang.AQASM.bits.Qbit object at 0x14c19ce36a50>, <qat.lang.AQASM.bits.Qbit object at 0x14c19cfcad50>])])
Sample(_amplitude=None, probability=np.float64(0.005000000000000057), _state=b'\x01', err=None, intermediate_measurements=None, qregs=[QRegister(scope=<qat.lang.AQASM.program.Program object at 0x14c19ce367b0>, length=2, start=0, msb=None, _subtype_metadata=None, qbits=[<qat.lang.AQASM.bits.Qbit object at 0x14c19ce36a50>, <qat.lang.AQASM.bits.Qbit object at 0x14c19cfcad50>])])
Sample(_amplitude=None, probability=np.float64(0.8549999999999994), _state=b'\x02', err=None, intermediate_measurements=None, qregs=[QRegister(scope=<qat.lang.AQASM.program.Program object at 0x14c19ce367b0>, length=2, start=0, msb=None, _subtype_metadata=None, qbits=[<qat.lang.AQASM.bits.Qbit object at 0x14c19ce36a50>, <qat.lang.AQASM.bits.Qbit object at 0x14c19cfcad50>])])
Sample(_amplitude=None, probability=np.float64(0.04500000000000054), _state=b'\x03', err=None, intermediate_measurements=None, qregs=[QRegister(scope=<qat.lang.AQASM.program.Program object at 0x14c19ce367b0>, length=2, start=0, msb=None, _subtype_metadata=None, qbits=[<qat.lang.AQASM.bits.Qbit object at 0x14c19ce36a50>, <qat.lang.AQASM.bits.Qbit object at 0x14c19cfcad50>])])
In [ ]: