Skip to content

Commit

Permalink
[minor] adding comments to and refactoring DirectConversionProtocol; …
Browse files Browse the repository at this point in the history
…move the absorptive memory files to a new folder
  • Loading branch information
caitaozhan committed Dec 23, 2024
1 parent dd192c4 commit f55b519
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 69 deletions.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
71 changes: 46 additions & 25 deletions example/Transducer_Examples/ConversionProtocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,10 @@
from sequence.components.memory import Memory
from sequence.utils.encoding import fock
import math
from sequence.kernel.event import Event
from sequence.kernel.process import Process
import sequence.utils.log as log
import matplotlib.pyplot as plt
from sequence.components.transducer import Transducer
from sequence.components.transmon import Transmon

from sequence.constants import KET0, KET1

from sequence.components.detector import Detector
from sequence.components.photon import Photon
Expand All @@ -28,9 +25,6 @@
from qutip import Qobj


ket1 = (0.0 + 0.0j, 1.0 + 0.0j)
ket0 = (1.0 + 0.0j, 0.0 + 0.0j)

MICROWAVE_WAVELENGTH = 999308 # nm
OPTICAL_WAVELENGTH = 1550 # nm

Expand All @@ -44,12 +38,18 @@ def get_conversion_matrix(efficiency: float) -> Qobj:
return Qobj(custom_gate_matrix, dims=[[4], [4]])



class EmittingProtocol(Protocol):
"""Protocol for emission of single microwave photon by transmon.
Attributes:
owner (Node): the owner of this protocol, the protocol runs on the owner
name (str): the name of the protocol
tl (Timeline): the simulation timeline
transducer (Transducer): the transducer component
transmon (Transmon): the transmon component
"""

def __init__(self, owner: "Node", name: str, tl: "Timeline", transmon="Transmon", transducer="Transducer"):
def __init__(self, owner: "Node", name: str, tl: Timeline, transmon: Transmon, transducer: Transducer):
super().__init__(owner, name)
self.owner = owner
self.name = name
Expand All @@ -61,7 +61,7 @@ def start(self) -> None:

self.transmon.get()

if self.transmon.photons_quantum_state[0] == ket1:
if self.transmon.photons_quantum_state[0] == KET1:
if random.random() < self.transmon.efficiency:
self.transmon._receivers[0].receive_photon_from_transmon(self.transmon.new_photon0)
self.transmon.photon_counter += 1
Expand All @@ -72,17 +72,23 @@ def start(self) -> None:

print(f"Microwave photons emitted by the Transmon at Tx: {self.transmon.photon_counter}")


def received_message(self, src: str, msg):
pass



class UpConversionProtocol(Protocol):
"""Protocol for Up-conversion of an input microwave photon into an output optical photon.
Attributes:
owner (Node): the owner of this protocol, the protocol runs on the owner
name (str): the name of the protocol
tl (Timeline): the simulation timeline
transducer (Transducer): the transducer component
node (Node): the receiver node (where DownConversionProtocol runs) -- NOTE this is an error! node's typing should be a str, instead of Node
transmon (Transmon): the transmon component
"""

def __init__(self, owner: "Node", name: str, tl: "Timeline", transducer: "Transducer", node: "Node", transmon: "Transmon"):
def __init__(self, owner: Node, name: str, tl: Timeline, transducer: Transducer, node: Node, transmon: Transmon):
super().__init__(owner, name)
self.owner = owner
self.name = name
Expand All @@ -91,9 +97,16 @@ def __init__(self, owner: "Node", name: str, tl: "Timeline", transducer: "Transd
self.transmon = transmon
self.node = node

def start(self, photon: "Photon") -> None:
"""start the protocol"""
if self.transducer.photon_counter > 0:
def start(self, photon: Photon) -> None:
"""start the protocol
NOTE (caitao, 12/21/2024): this start() method should be empty.
The content of this function should be at a new convert() method that receives photons from the from the transducer
Args:
photon (Photon): photon from arrived at the transducer from the transmon
"""
if self.transducer.photon_counter > 0: # NOTE shouldn't use this photon_counter to determine
custom_gate = get_conversion_matrix(self.transducer.efficiency)

transmon_state_vector = np.array(self.transmon.input_quantum_state).reshape((4, 1))
Expand All @@ -106,7 +119,7 @@ def start(self, photon: "Photon") -> None:

if random.random() < self.transducer.efficiency:
photon.wavelength = OPTICAL_WAVELENGTH
self.transducer._receivers[0].receive_photon(self.node, photon)
self.transducer._receivers[0].receive_photon(self.node, photon) # NOTE the receiver should be the quantum channel
print("Successful up-conversion")
self.transducer.output_quantum_state = [0.0 + 0.0j, 0.0 + 0.0j, 1.0 + 0.0j, 0.0 + 0.0j]
print(f"State after successful up-conversion: {self.transducer.output_quantum_state}")
Expand All @@ -121,9 +134,14 @@ def received_message(self, src: str, msg):
pass



class DownConversionProtocol(Protocol):
"""Protocol for Down-conversion of an input optical photon into an output microwave photon.
Attributes:
owner (Node): the owner of this protocol, the protocol runs on the owner
name (str): the name of the protocol
tl (Timeline): the simulation timeline
transducer (Transducer): the transducer component
"""

def __init__(self, owner: "Node", name: str, tl: "Timeline", transducer: "Transducer", transmon: "Transmon"):
Expand All @@ -134,10 +152,16 @@ def __init__(self, owner: "Node", name: str, tl: "Timeline", transducer: "Transd
self.transducer = transducer

def start(self, photon: "Photon") -> None:
"""start the protocol"""
if self.transducer.photon_counter > 0:

transducer_state = [0.0 + 0.0j, 0.0 + 0.0j, 1.0 + 0.0j, 0.0 + 0.0j]
"""start the protocol
NOTE (caitao, 12/21/2024): this start() method should be empty.
The content of this function should be at a new convert() method that receives photons from the from the transducer
Args:
photon (Photon): the photon received at the transducer from the quantum channel
"""
if self.transducer.photon_counter > 0: # NOTE shouldn't use this photon_counter to determine

transducer_state = [0.0 + 0.0j, 0.0 + 0.0j, 1.0 + 0.0j, 0.0 + 0.0j] # NOTE Why is this the transducer's state
custom_gate = get_conversion_matrix(self.transducer.efficiency)

transducer_state_vector = np.array(transducer_state).reshape((4, 1))
Expand All @@ -164,6 +188,3 @@ def start(self, photon: "Photon") -> None:
def received_message(self, src: str, msg):
pass




49 changes: 24 additions & 25 deletions example/Transducer_Examples/DirectConversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
sys.path.append('.')

import numpy as np
import sequence.utils.log as log
import matplotlib.pyplot as plt

from sequence.kernel.timeline import Timeline
Expand All @@ -14,6 +13,7 @@
from sequence.components.transmon import Transmon
from sequence.components.transducer import Transducer
from sequence.components.detector import FockDetector
from sequence.constants import KET0, KET1

from example.Transducer_Examples.ConversionProtocols import EmittingProtocol
from example.Transducer_Examples.ConversionProtocols import UpConversionProtocol
Expand All @@ -26,24 +26,20 @@
FREQUENCY = 1e9
MICROWAVE_WAVELENGTH = 999308 # nm
OPTICAL_WAVELENGTH = 1550 # nm
MEAN_PHOTON_NUM=1

# Timeline
START_TIME = 0
EMISSION_DURATION = 10 # ps
CONVERSION_DURATION = 10 # ps
PERIOD = EMISSION_DURATION + CONVERSION_DURATION + CONVERSION_DURATION

# Transmon
ket0 = (1.0 + 0.0j, 0.0 + 0.0j)
ket1 = (0.0 + 0.0j, 1.0 + 0.0j)

state_list= [ket1, ket0]
state_list= [KET1, KET0]
TRANSMON_EFFICIENCY = 1

# Transducer
EFFICIENCY_UP = 0.5
EFFICIENCY_DOWN = 0.5
EFFICIENCY_UP = 0.6
EFFICIENCY_DOWN = 0.6

# Fock Detector
MICROWAVE_DETECTOR_EFFICIENCY_Rx = 1
Expand All @@ -54,6 +50,7 @@
ATTENUATION = 0
DISTANCE = 1e3


class Counter:
def __init__(self):
self.count = 0
Expand All @@ -62,7 +59,7 @@ def trigger(self, detector, info):
self.count += 1


#NODES OF THE NETWORK
# NODES OF THE NETWORK


class SenderNode(Node):
Expand All @@ -75,23 +72,27 @@ class SenderNode(Node):
timeline (Timeline): timeline
transmon_name (str): name of the transmon
detector_name (str): name of the detector
counter2 (Counter): the counter for the detector
transducer_name (str): name of the transducer
counter (Counter): the counter for the transducer
emitting_protocol (EmittingProtocol): the protocol for emitting photons
upconversion_protocol (UpConversionProtocol): the protocol for up converting the microwave to optical photon
"""
def __init__(self, name, timeline, node2):
super().__init__(name, timeline)

# transmon
self.transmon_name = name + ".transmon"
transmon = Transmon(name=self.transmon_name, owner=self, timeline=timeline, wavelengths=[MICROWAVE_WAVELENGTH, OPTICAL_WAVELENGTH], photon_counter=0, efficiency=TRANSMON_EFFICIENCY, photons_quantum_state= state_list)
transmon = Transmon(name=self.transmon_name, owner=self, timeline=timeline, wavelengths=[MICROWAVE_WAVELENGTH, OPTICAL_WAVELENGTH], \
photon_counter=0, efficiency=TRANSMON_EFFICIENCY, photons_quantum_state=state_list)
self.add_component(transmon)

# detector
detector_name = name + ".fockdetector"
detector = FockDetector(detector_name, timeline, wavelength=MICROWAVE_WAVELENGTH, efficiency=MICROWAVE_DETECTOR_EFFICIENCY_Tx)
self.add_component(detector)
self.counter = Counter()
detector.attach(self.counter)
self.counter2 = Counter()
detector.attach(self.counter2)

# transducer
self.transducer_name = name + ".transducer"
Expand All @@ -110,7 +111,6 @@ def __init__(self, name, timeline, node2):
self.upconversion_protocol = UpConversionProtocol(self, name + ".upconversion_protocol", timeline, transducer, node2, transmon)



class ReceiverNode(Node):
"""Receiver node in the Direct Conversion Protocol.
Expand All @@ -136,7 +136,8 @@ def __init__(self, name, timeline):
self.counter = Counter()

# transmon
transmon = Transmon(name=self.transmon_name, owner=self, timeline=timeline, wavelengths=[MICROWAVE_WAVELENGTH, OPTICAL_WAVELENGTH], photons_quantum_state=state_list, photon_counter=0, efficiency=1)
transmon = Transmon(name=self.transmon_name, owner=self, timeline=timeline, wavelengths=[MICROWAVE_WAVELENGTH, OPTICAL_WAVELENGTH], \
photons_quantum_state=state_list, photon_counter=0, efficiency=1)
self.add_component(transmon)

# fock detector
Expand All @@ -155,12 +156,11 @@ def __init__(self, name, timeline):
# down conversion protocol
self.downconversion_protocol = DownConversionProtocol(self, name + ".downconversion_protocol", timeline, transducer, transmon)


def receive_photon(self, src, photon):
self.components[self.transducer_name].receive_photon_from_channel(photon)


#MAIN
# MAIN

if __name__ == "__main__":

Expand All @@ -170,7 +170,7 @@ def receive_photon(self, src, photon):
node2 = ReceiverNode("node2", tl)
node1 = SenderNode("node1", tl, node2)

qc1 = QuantumChannel("qc.node1.node2", tl, attenuation=ATTENUATION, distance=DISTANCE)
qc1 = QuantumChannel("qc.node1.node2", tl, attenuation=ATTENUATION, distance=DISTANCE) # NOTE: this quantum channel is not used
qc1.set_ends(node1, node2.name)

if EFFICIENCY_UP >= 0 and EFFICIENCY_UP <= 1 and EFFICIENCY_DOWN >= 0 and EFFICIENCY_DOWN <= 1:
Expand Down Expand Up @@ -205,14 +205,14 @@ def receive_photon(self, src, photon):
detector2 = node2.get_components_by_type("FockDetector")[0]

print(f"--------------------")
print(f"Direct Quantum Transduction Protocol starts, the qubit that we are going to convert is: {ket1}")
print(f"Direct Quantum Transduction Protocol starts, the qubit that we are going to convert is: {KET1}")

for trial in range(NUM_TRIALS):

print(f"--------------------")
print(f"Trial {trial}:")

# reset timeline
# reset timeline # NOTE should not reset timeline, instead, each experiment should keep running for some time.
tl.time = 0
tl.init()

Expand All @@ -224,17 +224,17 @@ def receive_photon(self, src, photon):
transducer2.photon_counter = 0
detector2.photon_counter = 0

process0 = Process(node1.emitting_protocol, "start", [])
process0 = Process(node1.emitting_protocol, "start", []) # NOTE: there should only be one event to kick the simulation (following 2 events shouldn't exist here)
event_time0 = (cumulative_time + EMISSION_DURATION)
event0 = Event(event_time0, process0)
tl.schedule(event0)
process1 = Process(node1.upconversion_protocol, "start", [Photon])

process1 = Process(node1.upconversion_protocol, "start", [Photon]) # NOTE: class Photon shouldn't be the parameter, it should be Photon object
event_time1 = (event_time0 + CONVERSION_DURATION)
event1 = Event(event_time1, process1)
tl.schedule(event1)

process2 = Process(node2.downconversion_protocol, "start", [Photon])
process2 = Process(node2.downconversion_protocol, "start", [Photon]) # NOTE: class Photon shouldn't be the parameter, it should be Photon object
event_time2 =(event_time1 + CONVERSION_DURATION)
event2 = Event(event_time2, process2)
tl.schedule(event2)
Expand All @@ -257,7 +257,6 @@ def receive_photon(self, src, photon):
converted_photons.append(total_photons_successful)



# RESULTS

print(f"- - - - - - - - - -")
Expand Down
10 changes: 5 additions & 5 deletions sequence/components/photon.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Photons may be encoded directly with polarization or time bin schemes, or may herald the encoded state of single atom memories.
"""
from typing import Dict, Any, List, Union, TYPE_CHECKING
from numpy import log2
from numpy import log2, ndarray

if TYPE_CHECKING:
from numpy.random._generator import Generator
Expand All @@ -15,6 +15,7 @@
from ..components.circuit import Circuit
from ..utils.encoding import polarization
from ..kernel.quantum_state import FreeQuantumState
from ..constants import EPSILON


class Photon:
Expand Down Expand Up @@ -43,8 +44,7 @@ class Photon:
_measure_circuit = Circuit(1)
_measure_circuit.measure(0)

def __init__(self, name: str, timeline: "Timeline", wavelength=0, location=None, encoding_type=polarization,
quantum_state=None, use_qm=False):
def __init__(self, name: str, timeline: "Timeline", wavelength=0, location=None, encoding_type=polarization, quantum_state=None, use_qm=False):
"""Constructor for the photon class.
Args:
Expand Down Expand Up @@ -84,8 +84,8 @@ def __init__(self, name: str, timeline: "Timeline", wavelength=0, location=None,
quantum_state = (complex(1), complex(0))
else:
assert type(quantum_state) is tuple
assert all([abs(a) <= 1.01 for a in quantum_state]), "Illegal value with abs > 1 in photon state"
assert abs(sum([abs(a) ** 2 for a in quantum_state]) - 1) < 1e-5, "Squared amplitudes do not sum to 1"
assert all([abs(a) < 1 + EPSILON for a in quantum_state]), "Illegal value with abs > 1 in photon state"
assert abs(sum([abs(a) ** 2 for a in quantum_state]) - 1) < EPSILON, "Squared amplitudes do not sum to 1"
num_qubits = log2(len(quantum_state))
assert num_qubits == 1, "Length of amplitudes for single photon should be 2"
self.quantum_state = FreeQuantumState()
Expand Down
3 changes: 2 additions & 1 deletion sequence/components/transducer.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ def add_output(self, outputs: List):
self.add_receiver(i)

def receive_photon_from_transmon(self, photon: "Photon") -> None:
self.photon_counter += 1
"""Receive a photon from the transmon"""
self.photon_counter += 1 # NOTE should schedule an UpConvert event in the future and pass on the argument photon to the UpConverion protocol's convert() method

def receive_photon_from_channel(self, photon: "Photon") -> None:
self.photon_counter += 1
Loading

0 comments on commit f55b519

Please # to comment.