qiskit-jku-provider
qiskit-jku-provider copied to clipboard
Extend JKU to support noises
The current way Qiskit handles noises is by supplying a noise model given as part of the qobj file, with the following structure:
"config": {
"noise_model": {
"errors": [
{
"type": "qerror",
"operations": [...],
"gate_qubits": [...],
"probabilities": [...],
"instructions": [...]
}
]
}
},
Here:
- operations is a list of gate types for which the noise will be applied. e.g. ["x", "y", "h"].
- gate qubits is an optional list of sets of qubits (each set of the size corresponding to the operation type; for 1-qubit operations, each set of qubits is a singleton). Noise will be applied only when the gates are applied to qubits that consist of one of the sets in the list.
- probabilities is a list of real positive numbers summing to 1, one probability for each element of instructions. Noise is applied by randomly choosing an element from instructions according to this probability distribution and applying it.
- instruction is a list of noise instructions. Every noise instruction is by itself a list which may list several gates that should be applied sequentially.
A typical noise gate is of the form [{"name": ..., "qubits": ...}]
where name is the name of the gate to be applied, and qubits is a list of the qubits that should be affected among the ones participating in the noise. This list starts from 0 and is relative (i.e. if the affected qubits are 7,4 then applying the noise to qubit "1" will affect qubit 4).
A special case is a Kraus noise, for which an additional params parameter is added, containing the list of matrices which describe this Kraus operator.
Examples:
Pauli noise
{ "type": "qerror", "operations": ["x"], "probabilities": [0.7, 0.1, 0.1, 0.1], "instructions": [ [{"name": "id", "qubits": [0]}], [{"name": "x", "qubits": [0]}], [{"name": "y", "qubits": [0]}], [{"name": "z", "qubits": [0]}] ] }
Ampltidue damping, in Kraus form:
"errors": [
{
"type": "qerror",
"operations": ["h"],
"probabilities": [1.0],
"instructions": [
[{"name": "kraus", "qubits": [0], "params": [
[[[1, 0], [0, 0]], [[0, 0], [0.5, 0]]],
[[[0, 0], [0.86602540378, 0]], [[0, 0], [0, 0]]]]}]
]
}
]
}
Reset
"errors": [
{
"type": "qerror",
"operations": ["h"],
"gate_qubits": [[0]],
"probabilities": [1],
"instructions": [[{"name": "reset", "qubits": [0]}]]
},
{
"type": "qerror",
"operations": ["h"],
"gate_qubits": [[1]],
"probabilities": [1],
"instructions": [[{"name": "reset", "qubits": [0]},
{"name": "x", "qubits": [0]}]]
},
{
"type": "qerror",
"operations": ["x"],
"probabilities": [0.5, 0.25, 0.25],
"instructions": [
[{"name": "id", "qubits": [0]}],
[{"name": "reset", "qubits": [0]}],
[{"name": "reset", "qubits": [0]}, {"name": "x", "qubits": [0]}]
]
},
{
"type": "qerror",
"operations": ["y"],
"probabilities": [0.25, 0.5, 0.25],
"instructions": [
[{"name": "id", "qubits": [0]}],
[{"name": "reset", "qubits": [0]}],
[{"name": "reset", "qubits": [0]}, {"name": "x", "qubits": [0]}]
]
}
]
For now, we can skip implementation for Kraus operators. Unitary noise can be implemented naively by preprocessing the circuit and randomally adding gates corresponding to the errors that should happen. This can be implemented in any simulator.
This is still on the roadmap - planned discussions with JKU
The challenge is of course to support state-dependent Type II Kraus noise within complex datastructures