Skip to content

Commit

Permalink
Merge branch 'master' into clifford_simulator_numba
Browse files Browse the repository at this point in the history
  • Loading branch information
BrunoLiegiBastonLiegi committed Feb 5, 2024
2 parents a671f6e + f67dc84 commit 42b4bce
Show file tree
Hide file tree
Showing 14 changed files with 1,200 additions and 167 deletions.
14 changes: 14 additions & 0 deletions doc/source/api-reference/qibo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1677,6 +1677,14 @@ Frame Potential
.. autofunction:: qibo.quantum_info.frame_potential


Quantum Networks
^^^^^^^^^^^^^^^^

.. autoclass:: qibo.quantum_info.quantum_networks.QuantumNetwork
:members:
:member-order: bysource


Random Ensembles
^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -2073,6 +2081,12 @@ Shannon entropy
.. autofunction:: qibo.quantum_info.shannon_entropy


Total Variation distance
""""""""""""""""""""""""

.. autofunction:: qibo.quantum_info.total_variation_distance


Hellinger distance
""""""""""""""""""

Expand Down
14 changes: 13 additions & 1 deletion src/qibo/backends/clifford.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,14 @@ def apply_gate_clifford(self, gate, symplectic_matrix, nqubits):

return operation(symplectic_matrix, *gate.init_args, nqubits, **kwargs)

def apply_channel(self, channel, state, nqubits):
probabilities = channel.coefficients + (1 - np.sum(channel.coefficients),)
index = np.random.choice(range(len(probabilities)), size=1, p=probabilities)[0]
if index != len(channel.gates):
gate = channel.gates[index]
state = gate.apply_clifford(self, state, nqubits)
return state

def execute_circuit(self, circuit, initial_state=None, nshots: int = 1000):
"""Execute a Clifford circuits.
Expand All @@ -131,7 +139,11 @@ def execute_circuit(self, circuit, initial_state=None, nshots: int = 1000):
(:class:`qibo.quantum_info.clifford.Clifford`): Object giving access to the final results.
"""
for gate in circuit.queue:
if not gate.clifford and not gate.__class__.__name__ == "M":
if (
not gate.clifford
and not gate.__class__.__name__ == "M"
and not isinstance(gate, gates.PauliNoiseChannel)
):
raise_error(RuntimeError, "Circuit contains non-Clifford gates.")

if circuit.repeated_execution and not nshots == 1:
Expand Down
2 changes: 1 addition & 1 deletion src/qibo/gates/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ def matrix(self, backend=None):
ndarray: Matrix representation of gate.
.. note::
``Gate.matrix`` was an defined as an atribute in ``qibo`` versions prior to ``0.2.0``.
``Gate.matrix`` was defined as an atribute in ``qibo`` versions prior to ``0.2.0``.
From ``0.2.0`` on, it has been converted into a method and has replaced the ``asmatrix`` method.
"""
if backend is None: # pragma: no cover
Expand Down
3 changes: 3 additions & 0 deletions src/qibo/gates/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ def apply(self, backend, state, nqubits): # pragma: no cover
def apply_density_matrix(self, backend, state, nqubits):
return backend.apply_channel_density_matrix(self, state, nqubits)

def apply_clifford(self, backend, state, nqubits):
return backend.apply_channel(self, state, nqubits)

def to_choi(self, nqubits: Optional[int] = None, order: str = "row", backend=None):
"""Returns the Choi representation :math:`\\mathcal{E}`
of the Kraus channel :math:`\\{K_{\\alpha}\\}_{\\alpha}`.
Expand Down
5 changes: 5 additions & 0 deletions src/qibo/gates/special.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,8 @@ def fuse(self, gate):
if neighbor is not None:
parent.left_neighbors[q] = neighbor
neighbor.right_neighbors[q] = parent

def apply_clifford(self, backend, state, nqubits):
for gate in self.gates:
state = gate.apply_clifford(backend, state, nqubits)
return state
8 changes: 5 additions & 3 deletions src/qibo/models/error_mitigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,8 @@ def CDR(

train_val = {"noise-free": [], "noisy": []}
for circ in training_circuits:
val = circ(nshots=nshots).expectation_from_samples(observable)
result = backend.execute_circuit(circ, nshots=nshots)
val = result.expectation_from_samples(observable)
train_val["noise-free"].append(val)
val = get_expectation_val_with_readout_mitigation(
circ, observable, noise_model, nshots, readout, qubit_map, backend=backend
Expand Down Expand Up @@ -400,7 +401,8 @@ def vnCDR(
train_val = {"noise-free": [], "noisy": []}

for circ in training_circuits:
val = circ(nshots=nshots).expectation_from_samples(observable)
result = backend.execute_circuit(circ, nshots=nshots)
val = result.expectation_from_samples(observable)
train_val["noise-free"].append(val)
for level in noise_levels:
noisy_c = get_noisy_circuit(circ, level, insertion_gate=insertion_gate)
Expand Down Expand Up @@ -897,7 +899,7 @@ def ICS(
lambda_list = []

for training_circuit in training_circuits:
circuit_result = training_circuit(nshots=nshots)
circuit_result = backend.execute_circuit(training_circuit, nshots=nshots)
expectation = observable.expectation_from_samples(circuit_result.frequencies())

noisy_expectation = get_expectation_val_with_readout_mitigation(
Expand Down
1 change: 1 addition & 0 deletions src/qibo/quantum_info/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from qibo.quantum_info.basis import *
from qibo.quantum_info.clifford import *
from qibo.quantum_info.metrics import *
from qibo.quantum_info.quantum_networks import *
from qibo.quantum_info.random_ensembles import *
from qibo.quantum_info.superoperator_transformations import *
from qibo.quantum_info.utils import *
Loading

0 comments on commit 42b4bce

Please sign in to comment.