Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/source/reference/simulators/noisy_sampling_simulator.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,17 @@ Using a NoisySamplingSimulator
.. autoclass:: perceval.simulators.NoisySamplingSimulator
:members:
:inherited-members:


ExqaliburNoisySamplingSimulator
===============================

The :code:`ExqaliburNoisySamplingSimulator` does the same things as the :code:`NoisySamplingSimulator`, but its methods
are implemented in exqalibur so it runs faster.

Also, this simulator requires the backend to be a wrapper around a pure exqalibur sampling backend.
The :ref:`CliffordClifford2017` backend is an example of such a backend.

.. autoclass:: perceval.simulators.ExqaliburNoisySamplingSimulator
:members:
:inherited-members:
2 changes: 1 addition & 1 deletion perceval/backends/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from ._abstract_backends import ABackend, ASamplingBackend, AStrongSimulationBackend, IFFBackend
from ._abstract_backends import ABackend, ASamplingBackend, AStrongSimulationBackend, IFFBackend, ExqaliburBackendWrapper
from ._clifford2017 import Clifford2017Backend
from ._mps import MPSBackend
from ._naive import NaiveBackend
Expand Down
7 changes: 7 additions & 0 deletions perceval/backends/_abstract_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,10 @@ def set_feed_forward(self, components: list[tuple[tuple, AComponent]], m: int) -
:param m: The number of modes in the circuit.
"""
pass


class ExqaliburBackendWrapper(ABC):

@abstractmethod
def get_exqalibur_backend(self):
pass
7 changes: 5 additions & 2 deletions perceval/backends/_clifford2017.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@
import exqalibur as xq
from perceval.utils import FockState
from perceval.components import ACircuit
from ._abstract_backends import ASamplingBackend
from ._abstract_backends import ASamplingBackend, ExqaliburBackendWrapper


class Clifford2017Backend(ASamplingBackend):
class Clifford2017Backend(ASamplingBackend, ExqaliburBackendWrapper):
def __init__(self):
super().__init__()
self._clifford = xq.Clifford2017()
Expand All @@ -59,3 +59,6 @@ def samples(self, count: int):
@property
def name(self) -> str:
return "CliffordClifford2017"

def get_exqalibur_backend(self):
return self._clifford
7 changes: 5 additions & 2 deletions perceval/backends/_slap.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@
from perceval.components import (ACircuit, AFFConfigurator, FFCircuitProvider, Experiment, IDetector,
DetectionType, AComponent, Circuit, Barrier, FFConfigurator)

from ._abstract_backends import AStrongSimulationBackend, IFFBackend
from ._abstract_backends import AStrongSimulationBackend, IFFBackend, ExqaliburBackendWrapper


class SLAPBackend(AStrongSimulationBackend, IFFBackend):
class SLAPBackend(AStrongSimulationBackend, IFFBackend, ExqaliburBackendWrapper):

def __init__(self, mask=None):
super().__init__()
Expand Down Expand Up @@ -186,3 +186,6 @@ def set_feed_forward(self, components: list[tuple[tuple, AComponent]], m: int) -
self.set_circuit(main_unitary)
for mp in maps:
self._slap.add_feed_forward_config(mp)

def get_exqalibur_backend(self):
return self._slap
12 changes: 9 additions & 3 deletions perceval/runtime/processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,16 @@ def linear_circuit(self, flatten: bool = False) -> Circuit:

def samples(self, max_samples: int, max_shots: int = None, progress_callback=None) -> dict:
self.check_min_detected_photons_filter()
from perceval.simulators import NoisySamplingSimulator
from perceval.backends import ASamplingBackend

# TODO: move imports on top of this file after moving Processor to runtime
from perceval.backends import ExqaliburBackendWrapper, ASamplingBackend
from perceval.simulators import ExqaliburNoisySamplingSimulator, NoisySamplingSimulator

assert isinstance(self.backend, ASamplingBackend), "A sampling backend is required to call samples method"
sampling_simulator = NoisySamplingSimulator(self.backend)
if isinstance(self.backend, ExqaliburBackendWrapper):
sampling_simulator = ExqaliburNoisySamplingSimulator(self.backend)
else:
sampling_simulator = NoisySamplingSimulator(self.backend)
sampling_simulator.sleep_between_batches = 0 # Remove sleep time between batches of samples in local simulation
sampling_simulator.set_circuit(self.linear_circuit())
sampling_simulator.set_selection(
Expand Down
16 changes: 16 additions & 0 deletions perceval/serialization/_detector_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from multipledispatch import dispatch

from perceval.serialization import _schema_circuit_pb2 as pb
from perceval.components import BSLayeredPPNR, Detector

Expand Down Expand Up @@ -63,3 +65,17 @@ def deserialize_detector(pb_d: pb.Detector) -> Detector:
detector = Detector(n_wires, max_detections, wire_efficiency)
detector.name = pb_d.name
return detector


@dispatch(BSLayeredPPNR)
def serialize_idetector(detector):
pb_detector = pb.IDetector()
pb_detector.ppnr.CopyFrom(serialize_bs_layer(detector))
return pb_detector


@dispatch(Detector)
def serialize_idetector(detector):
pb_detector = pb.IDetector()
pb_detector.detector.CopyFrom(serialize_detector(detector))
return pb_detector
20 changes: 3 additions & 17 deletions perceval/serialization/_experiment_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@

from multipledispatch import dispatch

from perceval.components import Experiment, Herald, Port, APort, IDetector, BSLayeredPPNR, Detector, AComponent
from perceval.components import Experiment, Herald, Port, APort, IDetector, AComponent
from perceval.serialization import _schema_circuit_pb2 as pb
from perceval.serialization import serialize
from perceval.serialization._circuit_serialization import serialize_port, serialize_herald, ComponentSerializer
from perceval.serialization._constants import VALUE_NOT_SET
from perceval.serialization._detector_serialization import serialize_detector, serialize_bs_layer
from perceval.serialization._detector_serialization import serialize_idetector


class ExperimentSerializer:
Expand Down Expand Up @@ -92,24 +92,10 @@ def _serialize_ports(self, in_ports: dict[APort, list[int]], out_ports: dict[APo
pb_port = self._serialize_port(port)
self._serialized.output_ports[modes[0]].CopyFrom(pb_port)

@staticmethod
@dispatch(BSLayeredPPNR)
def _serialize_detector(detector):
pb_detector = pb.IDetector()
pb_detector.ppnr.CopyFrom(serialize_bs_layer(detector))
return pb_detector

@staticmethod
@dispatch(Detector)
def _serialize_detector(detector):
pb_detector = pb.IDetector()
pb_detector.detector.CopyFrom(serialize_detector(detector))
return pb_detector

def _serialize_detectors(self, detectors: list[IDetector]):
for i, detector in enumerate(detectors):
if detector is not None:
pb_detector = self._serialize_detector(detector)
pb_detector = serialize_idetector(detector)
self._serialized.detectors[i].CopyFrom(pb_detector)

def _serialize_components(self, components: list[tuple[tuple, AComponent]]):
Expand Down
16 changes: 14 additions & 2 deletions perceval/serialization/serialize_binary.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,28 @@
from multipledispatch import dispatch

from ._circuit_serialization import serialize_circuit
from ._detector_serialization import serialize_idetector
from ._matrix_serialization import serialize_matrix
from perceval.components.linear_circuit import ACircuit
from perceval.components.detector import IDetector
from perceval.utils.matrix import Matrix


@dispatch(ACircuit)
def serialize_binary(circuit: ACircuit):
def serialize_binary(circuit: ACircuit) -> bytes:
return serialize_circuit(circuit).SerializeToString()


@dispatch(Matrix)
def serialize_binary(matrix: Matrix):
def serialize_binary(matrix: Matrix) -> bytes:
return serialize_matrix(matrix).SerializeToString()


@dispatch(IDetector)
def serialize_binary(detector: IDetector) -> bytes:
return serialize_idetector(detector).SerializeToString()


@dispatch(list)
def serialize_binary(l: list) -> list[bytes]:
return [serialize_binary(o) for o in l]
2 changes: 1 addition & 1 deletion perceval/simulators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@
from .simulator import Simulator
from .simulator_factory import SimulatorFactory
from .stepper import Stepper
from .noisy_sampling_simulator import NoisySamplingSimulator
from .noisy_sampling_simulator import NoisySamplingSimulator, ExqaliburNoisySamplingSimulator
from .feed_forward_simulator import FFSimulator
Loading
Loading