import numpy as np
import uuid
from pyquil import Program
from pyquil.gates import *
from netQuil import noise
__all__ = ["Fiber", "Laser", "Device"]
signal_speed = 2.998 * 10 ** 5 #speed of light in km/s
[docs]class Device():
'''
Base class for all source and target devices
'''
[docs] def __init__(self):
self.name = 'Device'
self.success = 0
self.trials = 0
[docs] def apply(self, program, qubits):
'''
This function should be overwritten by children classes, and
should include runtime code defining how child devices impact qubits
:param Pyquil<Program> program: program to manipulate
:param List<int> qubits: list of qubits passing through device
'''
return {delay: None, qubits: None}
[docs] def get_results(self):
'''
Prints device information about trial to console.
'''
pass
[docs] def reset(self):
'''
reset is called between trials and resets all properties.
'''
pass
[docs]class Fiber(Device):
[docs] def __init__(self, length=0.0, attenuation_coefficient = -0.16, apply_error=True):
'''
Simulation of fiber optics with given length and attenuation coefficient.
:param Float length: length of fiber optical cable in km
:param Float attenuation_coefficient: coefficient determining likelihood of photon loss
:param Boolean apply_error: True is device should apply error, otherwise, only returns time delay
'''
decibel_loss = length*attenuation_coefficient
self.attenuation = 10 ** (decibel_loss / 10)
self.apply_error = apply_error
self.length = length
[docs] def apply(self, program, qubits):
'''
Applies device's error and returns time that photon took to pass through simulated device
:param Program program: program to be modified
:param List<int> qubits: qubits being sent
:return: time qubits took to travel through fiber
'''
lost_qubits = []
for i, qubit in enumerate(qubits):
if qubit < 0: continue
if self.apply_error:
q = noise.measure(program, qubit, self.attenuation, "Fiber")
if q is not None:
lost_qubits.append(q)
delay = self.length/signal_speed
return {
'delay': delay,
'lost_qubits': lost_qubits
}
[docs]class Laser(Device):
[docs] def __init__(self, pulse_length=10 * 10 ** -12, expected_photons=1.0, rotation_prob_variance=1.0, wavelength=1550, apply_error=True):
'''
Simulation of laser at 1550nm wavelength. Laser produce photons according to poisson
distribution, centered around expected_photons.
'''
self.variance = rotation_prob_variance
self.wavelength = wavelength
self.photon_expectation = expected_photons
self.pulse_length = pulse_length
self.apply_error = apply_error
self.name = 'Laser'
self.success = 0
self.trials = 0
[docs] def apply(self, program, qubits):
'''
Applies laser effect to qubits
:param Program program: global program
:param List<int> qubits: list of qubits going through laser
:return: time it took qubits to pass through device
'''
for qubit in qubits:
if qubit < 0: continue
if self.apply_error:
numPhotons = np.random.poisson(lam=self.photon_expectation)
self.trials += len(qubits)
if numPhotons == self.photon_expectation: self.success += 1
'''
Rotation Noise
noise.normal_unitary_rotation(program, qubit, 0.5, self.variance)
'''
delay = self.pulse_length
return {
'delay': delay
}
[docs] def get_results(self):
try:
print('{} has a signal to noise ratio of {}/{}'.format(self.name, self.success, self.trials))
except:
pass
[docs] def reset(self):
self.success = 0
self.trials = 0