Skip to content

Commit

Permalink
Partial integration of the backends
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonSekavcnik committed Feb 23, 2024
1 parent 891d66b commit b4d2c72
Show file tree
Hide file tree
Showing 29 changed files with 405 additions and 242 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.local_dir.el
.*.el

.DS_Store
.idea
*.log
Expand Down
98 changes: 15 additions & 83 deletions examples/beam_splitter_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,92 +2,24 @@
Ideal Beam Splitter experiment example
"""

from quasi.simulation import Simulation
from quasi.devices.ideal import BeamSplitter
from quasi.devices.ideal import SinglePhotonSource
from quasi.devices.ideal import SinglePhotonDetector
from quasi.devices.ideal import Fiber
from quasi.devices import connect_ports
from quasi.signals import GenericQuantumSignal
from quasi.simulation import Simulation, SimulationType
from quasi.devices.sources import IdealNPhotonSource
from quasi.devices.control import SimpleTrigger
from quasi.signals import GenericBoolSignal
from quasi.experiment import Experiment

Sim = Simulation()
sim = Simulation()
sim.set_simulation_type(SimulationType.FOCK)


""" ╭───────────╮
│ DEVICES │
╰───────────╯
"""

# Single Photon Sources
sps1 = SinglePhotonSource(name="SPS1")
sps2 = SinglePhotonSource(name="SPS2")


# Beam Splitter
bs = BeamSplitter(name="BS")

# Detectors
spd1 = SinglePhotonDetector(name="SPD1")
spd2 = SinglePhotonDetector(name="SPD2")

# Fibers
fib1 = Fiber(name="FIB1", length=10)
fib2 = Fiber(name="FIB2", length=10)
fib3 = Fiber(name="FIB3", length=10)
fib4 = Fiber(name="FIB4", length=10)

# Prints a table of devices, registered with the simulation
# Each object instance registers itself with simulation with
# Initiation method
Sim.list_devices()

""" ╭────────────────────╮
│ EXPERIMENT SETUP │
╰────────────────────╯
We should create a utility where the devices and connections
can be set up using yaml language
"""

# Connect the devices, through signals
sig1 = GenericQuantumSignal()
sps1.register_signal(signal=sig1, port_label="OUT")
fib1.register_signal(signal=sig1, port_label="IN")

sig2 = GenericQuantumSignal()
sps2.register_signal(signal=sig2, port_label="OUT")
fib2.register_signal(signal=sig2, port_label="IN")

sig3 = GenericQuantumSignal()
fib1.register_signal(signal=sig3, port_label="OUT")
bs.register_signal(signal=sig3, port_label="A")
s1 = IdealNPhotonSource()
s1.set_photon_num(2)

sig4 = GenericQuantumSignal()
fib2.register_signal(signal=sig4, port_label="OUT")
bs.register_signal(signal=sig4, port_label="B")
st = SimpleTrigger()
sig_trigger = GenericBoolSignal()
st.register_signal(signal=sig_trigger, port_label="trigger")

sig5 = GenericQuantumSignal()
bs.register_signal(signal=sig5, port_label="C")
fib3.register_signal(signal=sig5, port_label="IN")
sim.run()

sig6 = GenericQuantumSignal()
bs.register_signal(signal=sig6, port_label="D")
fib4.register_signal(signal=sig6, port_label="IN")

sig7 = GenericQuantumSignal()
fib3.register_signal(signal=sig7, port_label="OUT")
spd1.register_signal(signal=sig7, port_label="IN")

sig8 = GenericQuantumSignal()
fib4.register_signal(signal=sig8, port_label="OUT")
spd2.register_signal(signal=sig8, port_label="IN")

# Registers which devices should be triggered when
# simulation starts
Sim.register_triggers(sps1,sps2)
Sim.list_triggered_devices()
""" ╭────────────────────╮
│ RUN SIMULATION │
╰────────────────────╯
"""
Sim.set_dimensions(50)
Sim.run()
exp = Experiment.get_instance()
print(exp.state.all_fock_probs())
1 change: 0 additions & 1 deletion quasi/devices/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@
from .generic_device import coordinate_gui
#from .port import connect_ports
from .port import Port
from .beam_splitter import BeamSplitter
from .generic_device import DeviceInformation
88 changes: 0 additions & 88 deletions quasi/devices/beam_splitter.py

This file was deleted.

1 change: 0 additions & 1 deletion quasi/devices/beam_splitters/ideal_beam_splitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
ensure_output_compute)
from quasi.devices.port import Port
from quasi.signals import (GenericSignal,
QuantumContentType,
GenericQuantumSignal)

from quasi.gui.icons import icon_list
Expand Down
6 changes: 3 additions & 3 deletions quasi/devices/control/simple_trigger.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class SimpleTrigger(GenericDevice):
Trigger turns on at the start of simulation.
"""
ports = {
"T": Port(label="T",
"trigger": Port(label="trigger",
direction="output",
signal=None,
signal_type=GenericBoolSignal,
Expand All @@ -39,6 +39,6 @@ class SimpleTrigger(GenericDevice):
@coordinate_gui
@wait_input_compute
def compute_outputs(self, *args, **kwargs):
self.ports["T"].signal.set_bool(True)
self.ports["T"].signal.set_computed()
self.ports["trigger"].signal.set_bool(True)
self.ports["trigger"].signal.set_computed()

1 change: 1 addition & 0 deletions quasi/devices/fiber/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .ideal_fiber import IdealFiber
Empty file.
65 changes: 65 additions & 0 deletions quasi/devices/fiber/generic_fiber.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""
This module implements a generic fiber
all fibers must extend this fiber abstraction
"""

from quasi.devices.generic_device import GenericDevice
from quasi.signals.generic_float_signal import GenericFloatSignal
from quasi.devices import Port
from quasi.signals.generic_quantum_signal import GenericQuantumSignal

from abc import ABCMeta, ABC

class EnforcePortsMeta(ABCMeta):
def __init__(cls, name, bases, namespace, **kwargs):
super().__init__(name, bases, namespace)
# Only enforce ports structure on subclasses, not on GenericDevice itself
if bases != (ABC,) and 'GenericDevice' in [base.__name__ for base in bases]:
# Ensure the class has a 'ports' class variable and it's a dictionary
if not hasattr(cls, 'ports') or not isinstance(cls.ports, dict):
raise TypeError(f"{cls.__name__} must have a 'ports' class variable of type dict")

# Specify the required keys
required_keys = {'length', 'input', 'output'}
# Check if the 'ports' dictionary has all the required keys
if not required_keys.issubset(cls.ports.keys()):
missing_keys = required_keys - cls.ports.keys()
raise TypeError(f"{cls.__name__}'s 'ports' dictionary is missing keys: {missing_keys}")


class GenericFiber(GenericDevice, metaclass=EnforcePortsMeta):
"""
Generic Fiber specifies the format for all Fiber Devices
Every Fiber device must extend this abstract base class
"""

ports = {
"length": Port(
label="control",
direction="length",
signal=None,
signal_type=GenericFloatSignal,
device=None),
"input": Port(
label="input",
direction="input",
signal=None,
signal_type=GenericQuantumSignal,
device=None),
"output": Port(
label="output",
direction="output",
signal=None,
signal_type=GenericQuantumSignal,
device=None),
}


def set_length(self, length: float):
"""
Sets the length of the fiber
"""
length_signal = GenericFloatSignal()
length_signal.set_float(length)
self.register_signal(signal=length_signal, port_label="length")
length_signal.set_computed()
72 changes: 72 additions & 0 deletions quasi/devices/fiber/ideal_fiber.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"""
Ideal Fiber Implementation
ideal fiber has no attenuation, it just adds a delay to the signal
the delay is proportional to the length of the fiber
"""
from typing import Union
from quasi.devices import (GenericDevice,
wait_input_compute,
coordinate_gui,
ensure_output_compute)

from quasi.devices.fiber.generic_fiber import GenericFiber
from quasi.devices.port import Port
from quasi.signals.generic_float_signal import GenericFloatSignal
from quasi.signals.generic_int_signal import GenericIntSignal
from quasi.signals.generic_quantum_signal import GenericQuantumSignal
from quasi.gui.icons import icon_list
from quasi.simulation import ModeManager

class IdealFiber(GenericFiber):
"""
Ideal Fiber
- no attenuation
- only time delay
"""

ports = {
"length": Port(
label="length",
direction="input", # Implement control
signal=None,
signal_type=GenericFloatSignal,
device=None),
"input": Port(
label="input",
direction="input",
signal=None,
signal_type=GenericQuantumSignal,
device=None),
"output": Port(
label="output",
direction="output",
signal=None,
signal_type=GenericQuantumSignal,
device=None),
}

# Gui Configuration
gui_icon = icon_list.FIBER
gui_tags = ["ideal"]
gui_name = "Ideal Fiber"
gui_documentation = "ideal_fiber.md"

power_peak = 0
power_average = 0

reference = None


@ensure_output_compute
@coordinate_gui
@wait_input_compute
def compute_outputs(self, *args, **kwargs):
"""
Ideal fiber only adds delay to the signal,
without any distortions
"""
self.ports["output"].signal.set_contents(
timestamp=0,
mode_id=self.ports["input"].signal.mode_id
)
self.ports["output"].signal.set_computed()
Loading

0 comments on commit b4d2c72

Please sign in to comment.