def testInversion(self): ''' Try a simple three level SC qubit system and see if can prepare the excited state. ''' #Setup a three level qubit and a 100MHz delta Q1 = SCQubit(3, 4.987456e9, -100e6, name='Q1') systemParams = SystemParams() systemParams.add_sub_system(Q1) systemParams.add_control_ham( inphase=Hamiltonian(0.5 * (Q1.loweringOp + Q1.raisingOp)), quadrature=Hamiltonian(0.5 * (-1j * Q1.loweringOp + 1j * Q1.raisingOp))) systemParams.create_full_Ham() systemParams.measurement = Q1.levelProjector(1) #Setup the pulse parameters for the optimization pulseParams = PulseParams() pulseParams.timeSteps = 1e-9 * np.ones(30) pulseParams.rhoStart = Q1.levelProjector(0) pulseParams.rhoGoal = Q1.levelProjector(1) pulseParams.add_control_line(freq=-Q1.omega) pulseParams.H_int = Hamiltonian(Q1.omega * np.diag(np.arange(Q1.dim))) pulseParams.optimType = 'state2state' #Call the optimization optimize_pulse(pulseParams, systemParams) #Now test the optimized pulse and make sure it puts all the population in the excited state result = simulate_sequence(pulseParams, systemParams, pulseParams.rhoStart, simType='unitary')[0] assert result > 0.99
def testInversion(self): ''' Try a simple three level SC qubit system and see if can prepare the excited state. ''' #Setup a three level qubit and a 100MHz delta Q1 = SCQubit(3, 4.987456e9, -100e6, name='Q1') systemParams = SystemParams() systemParams.add_sub_system(Q1) systemParams.add_control_ham(inphase = Hamiltonian(0.5*(Q1.loweringOp + Q1.raisingOp)), quadrature = Hamiltonian(0.5*(-1j*Q1.loweringOp + 1j*Q1.raisingOp))) systemParams.create_full_Ham() systemParams.measurement = Q1.levelProjector(1) #Setup the pulse parameters for the optimization pulseParams = PulseParams() pulseParams.timeSteps = 1e-9*np.ones(30) pulseParams.rhoStart = Q1.levelProjector(0) pulseParams.rhoGoal = Q1.levelProjector(1) pulseParams.add_control_line(freq=-Q1.omega) pulseParams.H_int = Hamiltonian(Q1.omega*np.diag(np.arange(Q1.dim))) pulseParams.optimType = 'state2state' #Call the optimization optimize_pulse(pulseParams, systemParams) #Now test the optimized pulse and make sure it puts all the population in the excited state result = simulate_sequence(pulseParams, systemParams, pulseParams.rhoStart, simType='unitary')[0] assert result > 0.99
def testDRAG(self): ''' Try a unitary inversion pulse on a three level SCQuibt and see if we get something close to DRAG ''' #Setup a three level qubit and a 100MHz delta Q1 = SCQubit(3, 4.987456e9, -150e6, name='Q1') systemParams = SystemParams() systemParams.add_sub_system(Q1) systemParams.add_control_ham(inphase = Hamiltonian(0.5*(Q1.loweringOp + Q1.raisingOp)), quadrature = Hamiltonian(0.5*(-1j*Q1.loweringOp + 1j*Q1.raisingOp))) systemParams.add_control_ham(inphase = Hamiltonian(0.5*(Q1.loweringOp + Q1.raisingOp)), quadrature = Hamiltonian(0.5*(-1j*Q1.loweringOp + 1j*Q1.raisingOp))) systemParams.create_full_Ham() systemParams.measurement = Q1.levelProjector(1) #Setup the pulse parameters for the optimization numPoints = 30 pulseTime = 15e-9 pulseParams = PulseParams() pulseParams.timeSteps = (pulseTime/numPoints)*np.ones(numPoints) pulseParams.rhoStart = Q1.levelProjector(0) pulseParams.rhoGoal = Q1.levelProjector(1) pulseParams.Ugoal = Q1.pauliX pulseParams.add_control_line(freq=-Q1.omega, bandwidth=300e6, maxAmp=200e6) pulseParams.add_control_line(freq=-Q1.omega, phase=-np.pi/2, bandwidth=300e6, maxAmp=200e6) pulseParams.H_int = Hamiltonian((Q1.omega)*np.diag(np.arange(Q1.dim))) pulseParams.optimType = 'unitary' pulseParams.derivType = 'finiteDiff' #Start with a Gaussian tmpGauss = np.exp(-np.linspace(-2,2,numPoints)**2) tmpScale = 0.5/(np.sum(pulseParams.timeSteps*tmpGauss)) pulseParams.startControlAmps = np.vstack((tmpScale*tmpGauss, np.zeros(numPoints))) #Call the optimization optimize_pulse(pulseParams, systemParams) if plotResults: plt.plot(np.cumsum(pulseParams.timeSteps)*1e9,pulseParams.controlAmps.T/1e6); plt.ylabel('Pulse Amplitude (MHz)') plt.xlabel('Time (ns)') plt.legend(('X Quadrature', 'Y Quadrature')) plt.title('DRAG Pulse from Optimal Control') plt.show() #Now test the optimized pulse and make sure it does give us the desired unitary result = simulate_sequence(pulseParams, systemParams, pulseParams.rhoStart, simType='unitary') assert np.abs(np.trace(np.dot(result[1].conj().T, pulseParams.Ugoal)))**2/np.abs(np.trace(np.dot(pulseParams.Ugoal.conj().T, pulseParams.Ugoal)))**2 > 0.99
class SingleQutrit(unittest.TestCase): def setUp(self): #Setup the system self.systemParams = SystemParams() self.qubit = SCQubit(3, 5e9, -100e6, name='Q1', T1=2e-6) self.systemParams.add_sub_system(self.qubit) self.systemParams.add_control_ham( inphase=Hamiltonian( 0.5 * (self.qubit.loweringOp + self.qubit.raisingOp)), quadrature=Hamiltonian( -0.5 * (-1j * self.qubit.loweringOp + 1j * self.qubit.raisingOp))) self.systemParams.measurement = self.qubit.pauliZ self.systemParams.create_full_Ham() #Add the 2us T1 dissipator self.systemParams.dissipators = [Dissipator(self.qubit.T1Dissipator)] #Define the initial state as the ground state self.rhoIn = self.qubit.levelProjector(0) def tearDown(self): pass def testTwoPhoton(self): ''' Test spectroscopy and the two photon transition from the ground to the second excited state. ''' freqSweep = 1e9 * np.linspace(4.9, 5.1, 1000) rabiFreq = 1e6 #Setup the pulseSequences as a series of 10us low-power pulses pulseSeqs = [] for freq in freqSweep: tmpPulseSeq = PulseSequence() tmpPulseSeq.add_control_line(freq=freq, phase=0) tmpPulseSeq.controlAmps = np.array([[rabiFreq]], dtype=np.float64) tmpPulseSeq.timeSteps = np.array([10e-6]) tmpPulseSeq.maxTimeStep = np.Inf tmpPulseSeq.H_int = Hamiltonian( np.diag(freq * np.arange(3, dtype=np.complex128))) pulseSeqs.append(tmpPulseSeq) results = simulate_sequence_stack(pulseSeqs, self.systemParams, self.rhoIn, simType='lindblad')[0] if plotResults: plt.figure() plt.plot(freqSweep / 1e9, results) plt.xlabel('Frequency') plt.ylabel(r'$\sigma_z$') plt.title('Qutrit Spectroscopy') plt.show()
class SingleQutrit(unittest.TestCase): def setUp(self): #Setup the system self.systemParams = SystemParams() self.qubit = SCQubit(3, 5e9, -100e6, name='Q1', T1=2e-6) self.systemParams.add_sub_system(self.qubit) self.systemParams.add_control_ham(inphase = Hamiltonian(0.5*(self.qubit.loweringOp + self.qubit.raisingOp)), quadrature = Hamiltonian(-0.5*(-1j*self.qubit.loweringOp + 1j*self.qubit.raisingOp))) self.systemParams.measurement = self.qubit.pauliZ self.systemParams.create_full_Ham() #Add the 2us T1 dissipator self.systemParams.dissipators = [Dissipator(self.qubit.T1Dissipator)] #Define the initial state as the ground state self.rhoIn = self.qubit.levelProjector(0) def tearDown(self): pass def testTwoPhoton(self): ''' Test spectroscopy and the two photon transition from the ground to the second excited state. ''' freqSweep = 1e9*np.linspace(4.9, 5.1, 1000) rabiFreq = 1e6 #Setup the pulseSequences as a series of 10us low-power pulses pulseSeqs = [] for freq in freqSweep: tmpPulseSeq = PulseSequence() tmpPulseSeq.add_control_line(freq=freq, phase=0) tmpPulseSeq.controlAmps = np.array([[rabiFreq]], dtype=np.float64) tmpPulseSeq.timeSteps = np.array([10e-6]) tmpPulseSeq.maxTimeStep = np.Inf tmpPulseSeq.H_int = Hamiltonian(np.diag(freq*np.arange(3, dtype=np.complex128))) pulseSeqs.append(tmpPulseSeq) results = simulate_sequence_stack(pulseSeqs, self.systemParams, self.rhoIn, simType='lindblad')[0] if plotResults: plt.figure() plt.plot(freqSweep/1e9,results) plt.xlabel('Frequency') plt.ylabel(r'$\sigma_z$') plt.title('Qutrit Spectroscopy') plt.show()
class SingleQubit(unittest.TestCase): def setUp(self): #Setup the system self.systemParams = SystemParams() self.qubit = SCQubit(2, 0e9, name='Q1', T1=1e-6) self.systemParams.add_sub_system(self.qubit) #self.systemParams.add_control_ham(inphase = Hamiltonian(0.5*(self.qubit.loweringOp + self.qubit.raisingOp)), quadrature = Hamiltonian(0.5*(-1j*self.qubit.loweringOp + 1j*self.qubit.raisingOp))) self.systemParams.add_control_ham( inphase=Hamiltonian(0.5 * self.qubit.pauliX), quadrature=Hamiltonian(0.5 * self.qubit.pauliY)) self.systemParams.measurement = self.qubit.pauliZ self.systemParams.create_full_Ham() #Define Rabi frequency and pulse lengths self.rabiFreq = 10e6 self.pulseLengths = np.linspace(0, 100e-9, 40) #Define the initial state as the ground state self.rhoIn = self.qubit.levelProjector(0) def tearDown(self): pass def testRabiRotatingFrame(self): ''' Test Rabi oscillations in the rotating frame, i.e. with zero drift Hamiltonian drive frequency of zero. ''' #Setup the pulseSequences pulseSeqs = [] for pulseLength in self.pulseLengths: tmpPulseSeq = PulseSequence() tmpPulseSeq.add_control_line(freq=0e9, phase=0) tmpPulseSeq.controlAmps = self.rabiFreq * np.array( [[1]], dtype=np.float64) tmpPulseSeq.timeSteps = np.array([pulseLength]) tmpPulseSeq.maxTimeStep = pulseLength tmpPulseSeq.H_int = None pulseSeqs.append(tmpPulseSeq) results = simulate_sequence_stack(pulseSeqs, self.systemParams, self.rhoIn, simType='unitary')[0] expectedResults = np.cos(2 * pi * self.rabiFreq * self.pulseLengths) if plotResults: plt.figure() plt.plot(self.pulseLengths, results) plt.plot(self.pulseLengths, expectedResults, color='r', linestyle='--', linewidth=2) plt.title('10MHz Rabi Oscillations in Rotating Frame') plt.xlabel('Pulse Length') plt.ylabel(r'$\sigma_z$') plt.legend(('Simulated Results', '10MHz Cosine')) plt.show() np.testing.assert_allclose(results, expectedResults, atol=1e-4) def testRabiInteractionFrame(self): ''' Test Rabi oscillations after moving into an interaction frame that is different to the pulsing frame and with an irrational timestep for good measure. ''' #Setup the system self.systemParams.subSystems[0] = SCQubit(2, 5e9, 'Q1') self.systemParams.create_full_Ham() #Setup the pulseSequences pulseSeqs = [] for pulseLength in self.pulseLengths: tmpPulseSeq = PulseSequence() tmpPulseSeq.add_control_line(freq=-5.0e9, phase=0) tmpPulseSeq.controlAmps = self.rabiFreq * np.array( [[1]], dtype=np.float64) tmpPulseSeq.timeSteps = np.array([pulseLength]) tmpPulseSeq.maxTimeStep = pi / 2 * 1e-10 tmpPulseSeq.H_int = Hamiltonian( np.array([[0, 0], [0, 5.005e9]], dtype=np.complex128)) pulseSeqs.append(tmpPulseSeq) results = simulate_sequence_stack(pulseSeqs, self.systemParams, self.rhoIn, simType='unitary')[0] expectedResults = np.cos(2 * pi * self.rabiFreq * self.pulseLengths) if plotResults: plt.figure() plt.plot(self.pulseLengths, results) plt.plot(self.pulseLengths, expectedResults, color='r', linestyle='--', linewidth=2) plt.title('10MHz Rabi Oscillations in Interaction Frame') plt.xlabel('Pulse Length') plt.ylabel(r'$\sigma_z$') plt.legend(('Simulated Results', '10MHz Cosine')) plt.show() np.testing.assert_allclose(results, expectedResults, atol=1e-4) def testRamsey(self): ''' Just look at Ramsey decay to make sure we get the off-resonance right. ''' #Setup the system self.systemParams.subSystems[0] = SCQubit(2, 5e9, 'Q1') self.systemParams.create_full_Ham() self.systemParams.dissipators = [Dissipator(self.qubit.T1Dissipator)] #Setup the pulseSequences delays = np.linspace(0, 8e-6, 200) t90 = 0.25 * (1 / self.rabiFreq) offRes = 0.56789e6 pulseSeqs = [] for delay in delays: tmpPulseSeq = PulseSequence() #Shift the pulsing frequency down by offRes tmpPulseSeq.add_control_line(freq=-(5.0e9 - offRes), phase=0) #Pulse sequence is X90, delay, X90 tmpPulseSeq.controlAmps = self.rabiFreq * np.array( [[1, 0, 1]], dtype=np.float64) tmpPulseSeq.timeSteps = np.array([t90, delay, t90]) #Interaction frame with some odd frequency tmpPulseSeq.H_int = Hamiltonian( np.array([[0, 0], [0, 5.00e9]], dtype=np.complex128)) pulseSeqs.append(tmpPulseSeq) results = simulate_sequence_stack(pulseSeqs, self.systemParams, self.rhoIn, simType='lindblad')[0] expectedResults = -np.cos(2 * pi * offRes * (delays + t90)) * np.exp(-delays / (2 * self.qubit.T1)) if plotResults: plt.figure() plt.plot(1e6 * delays, results) plt.plot(1e6 * delays, expectedResults, color='r', linestyle='--', linewidth=2) plt.title('Ramsey Fringes 0.56789MHz Off-Resonance') plt.xlabel('Pulse Spacing (us)') plt.ylabel(r'$\sigma_z$') plt.legend( ('Simulated Results', '0.57MHz Cosine with T1 limited decay.')) plt.show() def testYPhase(self): ''' Make sure the frame-handedness matches what we expect: i.e. if the qubit frequency is greater than the driver frequency this corresponds to a positive rotation. ''' #Setup the system self.systemParams.subSystems[0] = SCQubit(2, 5e9, 'Q1') self.systemParams.create_full_Ham() #Add a Y control Hamiltonian self.systemParams.add_control_ham( inphase=Hamiltonian(0.5 * self.qubit.pauliX), quadrature=Hamiltonian(0.5 * self.qubit.pauliY)) #Setup the pulseSequences delays = np.linspace(0, 8e-6, 200) t90 = 0.25 * (1 / self.rabiFreq) offRes = 1.2345e6 pulseSeqs = [] for delay in delays: tmpPulseSeq = PulseSequence() #Shift the pulsing frequency down by offRes tmpPulseSeq.add_control_line(freq=-(5.0e9 - offRes), phase=0) tmpPulseSeq.add_control_line(freq=-(5.0e9 - offRes), phase=-pi / 2) #Pulse sequence is X90, delay, Y90 tmpPulseSeq.controlAmps = self.rabiFreq * np.array( [[1, 0, 0], [0, 0, 1]], dtype=np.float64) tmpPulseSeq.timeSteps = np.array([t90, delay, t90]) #Interaction frame with some odd frequency tmpPulseSeq.H_int = Hamiltonian( np.array([[0, 0], [0, 5.00e9]], dtype=np.complex128)) pulseSeqs.append(tmpPulseSeq) results = simulate_sequence_stack(pulseSeqs, self.systemParams, self.rhoIn, simType='lindblad')[0] expectedResults = -np.sin(2 * pi * offRes * (delays + t90)) if plotResults: plt.figure() plt.plot(1e6 * delays, results) plt.plot(1e6 * delays, expectedResults, color='r', linestyle='--', linewidth=2) plt.title('Ramsey Fringes {0:.2f} MHz Off-Resonance'.format( offRes / 1e6)) plt.xlabel('Pulse Spacing (us)') plt.ylabel(r'$\sigma_z$') plt.legend(('Simulated Results', ' {0:.2f} MHz -Sin.'.format(offRes / 1e6))) plt.show() def testT1Recovery(self): ''' Test a simple T1 recovery without any pulses. Start in the first excited state and watch recovery down to ground state. ''' self.systemParams.dissipators = [Dissipator(self.qubit.T1Dissipator)] #Just setup a series of delays delays = np.linspace(0, 5e-6, 40) pulseSeqs = [] for tmpDelay in delays: tmpPulseSeq = PulseSequence() tmpPulseSeq.add_control_line() tmpPulseSeq.controlAmps = np.array([[0]]) tmpPulseSeq.timeSteps = np.array([tmpDelay]) tmpPulseSeq.maxTimeStep = tmpDelay tmpPulseSeq.H_int = None pulseSeqs.append(tmpPulseSeq) results = simulate_sequence_stack(pulseSeqs, self.systemParams, np.array([[0, 0], [0, 1]], dtype=np.complex128), simType='lindblad')[0] expectedResults = 1 - 2 * np.exp(-delays / self.qubit.T1) if plotResults: plt.figure() plt.plot(1e6 * delays, results) plt.plot(1e6 * delays, expectedResults, color='r', linestyle='--', linewidth=2) plt.xlabel(r'Recovery Time ($\mu$s)') plt.ylabel(r'Expectation Value of $\sigma_z$') plt.title(r'$T_1$ Recovery to the Ground State') plt.legend(('Simulated Results', 'Exponential T1 Recovery')) plt.show() np.testing.assert_allclose(results, expectedResults, atol=1e-4)
from PySim.Simulation import simulate_sequence_stack from PySim.QuantumSystems import SCQubit, Hamiltonian from copy import deepcopy #Setup the system systemParams = SystemParams() qubit = SCQubit(2, 0e9, delta=200e6, name='Q1', T1=1e-6) systemParams.add_sub_system(qubit) systemParams.add_control_ham(inphase = Hamiltonian(0.5*(qubit.loweringOp + qubit.raisingOp)), quadrature = Hamiltonian(0.5*(-1j*qubit.loweringOp + 1j*qubit.raisingOp))) systemParams.add_control_ham(inphase = Hamiltonian(0.5*(qubit.loweringOp + qubit.raisingOp)), quadrature = Hamiltonian(0.5*(-1j*qubit.loweringOp + 1j*qubit.raisingOp))) systemParams.measurement = qubit.pauliZ systemParams.create_full_Ham() #Define the initial state as the ground state rhoIn = qubit.levelProjector(0) #First the basic sequence basePulseSeq = PulseSequence() basePulseSeq.add_control_line(freq=0e9, phase=0) basePulseSeq.add_control_line(freq=0e9, phase=pi/2) basePulseSeq.H_int = None #Some parameters for the pulse timeStep = 1.0/1.2e9 #How many discrete timesteps to break it up into stepsArray = np.arange(12,61) # stepsArray = np.arange(24,121)
class SingleQubit(unittest.TestCase): def setUp(self): #Setup the system self.systemParams = SystemParams() self.qubit = SCQubit(2,0e9, name='Q1', T1=1e-6) self.systemParams.add_sub_system(self.qubit) #self.systemParams.add_control_ham(inphase = Hamiltonian(0.5*(self.qubit.loweringOp + self.qubit.raisingOp)), quadrature = Hamiltonian(0.5*(-1j*self.qubit.loweringOp + 1j*self.qubit.raisingOp))) self.systemParams.add_control_ham(inphase = Hamiltonian(0.5*self.qubit.pauliX), quadrature = Hamiltonian(0.5*self.qubit.pauliY)) self.systemParams.measurement = self.qubit.pauliZ self.systemParams.create_full_Ham() #Define Rabi frequency and pulse lengths self.rabiFreq = 10e6 self.pulseLengths = np.linspace(0,100e-9,40) #Define the initial state as the ground state self.rhoIn = self.qubit.levelProjector(0) def tearDown(self): pass def testRabiRotatingFrame(self): ''' Test Rabi oscillations in the rotating frame, i.e. with zero drift Hamiltonian drive frequency of zero. ''' #Setup the pulseSequences pulseSeqs = [] for pulseLength in self.pulseLengths: tmpPulseSeq = PulseSequence() tmpPulseSeq.add_control_line(freq=0e9, phase=0) tmpPulseSeq.controlAmps = self.rabiFreq*np.array([[1]], dtype=np.float64) tmpPulseSeq.timeSteps = np.array([pulseLength]) tmpPulseSeq.maxTimeStep = pulseLength tmpPulseSeq.H_int = None pulseSeqs.append(tmpPulseSeq) results = simulate_sequence_stack(pulseSeqs, self.systemParams, self.rhoIn, simType='unitary')[0] expectedResults = np.cos(2*pi*self.rabiFreq*self.pulseLengths) if plotResults: plt.figure() plt.plot(self.pulseLengths,results) plt.plot(self.pulseLengths, expectedResults, color='r', linestyle='--', linewidth=2) plt.title('10MHz Rabi Oscillations in Rotating Frame') plt.xlabel('Pulse Length') plt.ylabel(r'$\sigma_z$') plt.legend(('Simulated Results', '10MHz Cosine')) plt.show() np.testing.assert_allclose(results, expectedResults , atol = 1e-4) def testRabiInteractionFrame(self): ''' Test Rabi oscillations after moving into an interaction frame that is different to the pulsing frame and with an irrational timestep for good measure. ''' #Setup the system self.systemParams.subSystems[0] = SCQubit(2,5e9, 'Q1') self.systemParams.create_full_Ham() #Setup the pulseSequences pulseSeqs = [] for pulseLength in self.pulseLengths: tmpPulseSeq = PulseSequence() tmpPulseSeq.add_control_line(freq=-5.0e9, phase=0) tmpPulseSeq.controlAmps = self.rabiFreq*np.array([[1]], dtype=np.float64) tmpPulseSeq.timeSteps = np.array([pulseLength]) tmpPulseSeq.maxTimeStep = pi/2*1e-10 tmpPulseSeq.H_int = Hamiltonian(np.array([[0,0], [0, 5.005e9]], dtype = np.complex128)) pulseSeqs.append(tmpPulseSeq) results = simulate_sequence_stack(pulseSeqs, self.systemParams, self.rhoIn, simType='unitary')[0] expectedResults = np.cos(2*pi*self.rabiFreq*self.pulseLengths) if plotResults: plt.figure() plt.plot(self.pulseLengths,results) plt.plot(self.pulseLengths, expectedResults, color='r', linestyle='--', linewidth=2) plt.title('10MHz Rabi Oscillations in Interaction Frame') plt.xlabel('Pulse Length') plt.ylabel(r'$\sigma_z$') plt.legend(('Simulated Results', '10MHz Cosine')) plt.show() np.testing.assert_allclose(results, expectedResults , atol = 1e-4) def testRamsey(self): ''' Just look at Ramsey decay to make sure we get the off-resonance right. ''' #Setup the system self.systemParams.subSystems[0] = SCQubit(2,5e9, 'Q1') self.systemParams.create_full_Ham() self.systemParams.dissipators = [Dissipator(self.qubit.T1Dissipator)] #Setup the pulseSequences delays = np.linspace(0,8e-6,200) t90 = 0.25*(1/self.rabiFreq) offRes = 0.56789e6 pulseSeqs = [] for delay in delays: tmpPulseSeq = PulseSequence() #Shift the pulsing frequency down by offRes tmpPulseSeq.add_control_line(freq=-(5.0e9-offRes), phase=0) #Pulse sequence is X90, delay, X90 tmpPulseSeq.controlAmps = self.rabiFreq*np.array([[1, 0, 1]], dtype=np.float64) tmpPulseSeq.timeSteps = np.array([t90, delay, t90]) #Interaction frame with some odd frequency tmpPulseSeq.H_int = Hamiltonian(np.array([[0,0], [0, 5.00e9]], dtype = np.complex128)) pulseSeqs.append(tmpPulseSeq) results = simulate_sequence_stack(pulseSeqs, self.systemParams, self.rhoIn, simType='lindblad')[0] expectedResults = -np.cos(2*pi*offRes*(delays+t90))*np.exp(-delays/(2*self.qubit.T1)) if plotResults: plt.figure() plt.plot(1e6*delays,results) plt.plot(1e6*delays, expectedResults, color='r', linestyle='--', linewidth=2) plt.title('Ramsey Fringes 0.56789MHz Off-Resonance') plt.xlabel('Pulse Spacing (us)') plt.ylabel(r'$\sigma_z$') plt.legend(('Simulated Results', '0.57MHz Cosine with T1 limited decay.')) plt.show() def testYPhase(self): ''' Make sure the frame-handedness matches what we expect: i.e. if the qubit frequency is greater than the driver frequency this corresponds to a positive rotation. ''' #Setup the system self.systemParams.subSystems[0] = SCQubit(2,5e9, 'Q1') self.systemParams.create_full_Ham() #Add a Y control Hamiltonian self.systemParams.add_control_ham(inphase = Hamiltonian(0.5*self.qubit.pauliX), quadrature = Hamiltonian(0.5*self.qubit.pauliY)) #Setup the pulseSequences delays = np.linspace(0,8e-6,200) t90 = 0.25*(1/self.rabiFreq) offRes = 1.2345e6 pulseSeqs = [] for delay in delays: tmpPulseSeq = PulseSequence() #Shift the pulsing frequency down by offRes tmpPulseSeq.add_control_line(freq=-(5.0e9-offRes), phase=0) tmpPulseSeq.add_control_line(freq=-(5.0e9-offRes), phase=-pi/2) #Pulse sequence is X90, delay, Y90 tmpPulseSeq.controlAmps = self.rabiFreq*np.array([[1, 0, 0],[0,0,1]], dtype=np.float64) tmpPulseSeq.timeSteps = np.array([t90, delay, t90]) #Interaction frame with some odd frequency tmpPulseSeq.H_int = Hamiltonian(np.array([[0,0], [0, 5.00e9]], dtype = np.complex128)) pulseSeqs.append(tmpPulseSeq) results = simulate_sequence_stack(pulseSeqs, self.systemParams, self.rhoIn, simType='lindblad')[0] expectedResults = -np.sin(2*pi*offRes*(delays+t90)) if plotResults: plt.figure() plt.plot(1e6*delays,results) plt.plot(1e6*delays, expectedResults, color='r', linestyle='--', linewidth=2) plt.title('Ramsey Fringes {0:.2f} MHz Off-Resonance'.format(offRes/1e6)) plt.xlabel('Pulse Spacing (us)') plt.ylabel(r'$\sigma_z$') plt.legend(('Simulated Results', ' {0:.2f} MHz -Sin.'.format(offRes/1e6) )) plt.show() def testT1Recovery(self): ''' Test a simple T1 recovery without any pulses. Start in the first excited state and watch recovery down to ground state. ''' self.systemParams.dissipators = [Dissipator(self.qubit.T1Dissipator)] #Just setup a series of delays delays = np.linspace(0,5e-6,40) pulseSeqs = [] for tmpDelay in delays: tmpPulseSeq = PulseSequence() tmpPulseSeq.add_control_line() tmpPulseSeq.controlAmps = np.array([[0]]) tmpPulseSeq.timeSteps = np.array([tmpDelay]) tmpPulseSeq.maxTimeStep = tmpDelay tmpPulseSeq.H_int = None pulseSeqs.append(tmpPulseSeq) results = simulate_sequence_stack(pulseSeqs, self.systemParams, np.array([[0,0],[0,1]], dtype=np.complex128), simType='lindblad')[0] expectedResults = 1-2*np.exp(-delays/self.qubit.T1) if plotResults: plt.figure() plt.plot(1e6*delays,results) plt.plot(1e6*delays, expectedResults, color='r', linestyle='--', linewidth=2) plt.xlabel(r'Recovery Time ($\mu$s)') plt.ylabel(r'Expectation Value of $\sigma_z$') plt.title(r'$T_1$ Recovery to the Ground State') plt.legend(('Simulated Results', 'Exponential T1 Recovery')) plt.show() np.testing.assert_allclose(results, expectedResults, atol=1e-4)
systemParams = SystemParams() qubit = SCQubit(2, 0e9, delta=200e6, name='Q1', T1=1e-6) systemParams.add_sub_system(qubit) systemParams.add_control_ham( inphase=Hamiltonian(0.5 * (qubit.loweringOp + qubit.raisingOp)), quadrature=Hamiltonian(0.5 * (-1j * qubit.loweringOp + 1j * qubit.raisingOp))) systemParams.add_control_ham( inphase=Hamiltonian(0.5 * (qubit.loweringOp + qubit.raisingOp)), quadrature=Hamiltonian(0.5 * (-1j * qubit.loweringOp + 1j * qubit.raisingOp))) systemParams.measurement = qubit.pauliZ systemParams.create_full_Ham() #Define the initial state as the ground state rhoIn = qubit.levelProjector(0) #First the basic sequence basePulseSeq = PulseSequence() basePulseSeq.add_control_line(freq=0e9, phase=0) basePulseSeq.add_control_line(freq=0e9, phase=pi / 2) basePulseSeq.H_int = None #Some parameters for the pulse timeStep = 1.0 / 1.2e9 #How many discrete timesteps to break it up into stepsArray = np.arange(12, 61) # stepsArray = np.arange(24,121) ''' Test a square Hadamard pulse. '''
def testDRAG(self): ''' Try a unitary inversion pulse on a three level SCQuibt and see if we get something close to DRAG ''' #Setup a three level qubit and a 100MHz delta Q1 = SCQubit(3, 4.987456e9, -150e6, name='Q1') systemParams = SystemParams() systemParams.add_sub_system(Q1) systemParams.add_control_ham( inphase=Hamiltonian(0.5 * (Q1.loweringOp + Q1.raisingOp)), quadrature=Hamiltonian(0.5 * (-1j * Q1.loweringOp + 1j * Q1.raisingOp))) systemParams.add_control_ham( inphase=Hamiltonian(0.5 * (Q1.loweringOp + Q1.raisingOp)), quadrature=Hamiltonian(0.5 * (-1j * Q1.loweringOp + 1j * Q1.raisingOp))) systemParams.create_full_Ham() systemParams.measurement = Q1.levelProjector(1) #Setup the pulse parameters for the optimization numPoints = 30 pulseTime = 15e-9 pulseParams = PulseParams() pulseParams.timeSteps = (pulseTime / numPoints) * np.ones(numPoints) pulseParams.rhoStart = Q1.levelProjector(0) pulseParams.rhoGoal = Q1.levelProjector(1) pulseParams.Ugoal = Q1.pauliX pulseParams.add_control_line(freq=-Q1.omega, bandwidth=300e6, maxAmp=200e6) pulseParams.add_control_line(freq=-Q1.omega, phase=-np.pi / 2, bandwidth=300e6, maxAmp=200e6) pulseParams.H_int = Hamiltonian( (Q1.omega) * np.diag(np.arange(Q1.dim))) pulseParams.optimType = 'unitary' pulseParams.derivType = 'finiteDiff' #Start with a Gaussian tmpGauss = np.exp(-np.linspace(-2, 2, numPoints)**2) tmpScale = 0.5 / (np.sum(pulseParams.timeSteps * tmpGauss)) pulseParams.startControlAmps = np.vstack( (tmpScale * tmpGauss, np.zeros(numPoints))) #Call the optimization optimize_pulse(pulseParams, systemParams) if plotResults: plt.plot( np.cumsum(pulseParams.timeSteps) * 1e9, pulseParams.controlAmps.T / 1e6) plt.ylabel('Pulse Amplitude (MHz)') plt.xlabel('Time (ns)') plt.legend(('X Quadrature', 'Y Quadrature')) plt.title('DRAG Pulse from Optimal Control') plt.show() #Now test the optimized pulse and make sure it does give us the desired unitary result = simulate_sequence(pulseParams, systemParams, pulseParams.rhoStart, simType='unitary') assert np.abs(np.trace(np.dot( result[1].conj().T, pulseParams.Ugoal)))**2 / np.abs( np.trace(np.dot(pulseParams.Ugoal.conj().T, pulseParams.Ugoal)))**2 > 0.99
from scipy.constants import pi '''System Setup''' systemParams = SystemParams() qubit = SCQubit(3, 0e9, -100e6, name='Q1', T1=50e-9) systemParams.add_sub_system(qubit) systemParams.add_control_ham( inphase=Hamiltonian(0.5 * (qubit.loweringOp + qubit.raisingOp)), quadrature=Hamiltonian(-0.5 * (-1j * qubit.loweringOp + 1j * qubit.raisingOp))) systemParams.add_control_ham( inphase=Hamiltonian(0.5 * (qubit.loweringOp + qubit.raisingOp)), quadrature=Hamiltonian(-0.5 * (-1j * qubit.loweringOp + 1j * qubit.raisingOp))) systemParams.measurement = qubit.levelProjector(1) systemParams.create_full_Ham() #Add the T1 dissipator systemParams.dissipators = [Dissipator(qubit.T1Dissipator)] ''' Simple Rabi Driving We'll vary the Rabi power (but always keep the time to a calibrated pi pulse. We expect to see a maximum at some intermediate regime where we have a balance between selectivity and T1 decay ''' pulseSeqs = [] pulseTimes = 1e-9 * np.arange(4, 100, 2) rhoIn = qubit.levelProjector(0) for pulseTime in pulseTimes:
systemParams.expand_operator('Q1', Y) + systemParams.expand_operator('Q2', Y))) #Setup the measurement operator # systemParams.measurement = -systemParams.expand_operator('Q1', Q1.pauliZ) systemParams.measurement = np.diag( np.array([0.55, 0.7, 0.75, 0.72, 0.76, 0.76, 0.76, 0.78, 0.80])) #Add the T1 dissipators systemParams.dissipators.append( Dissipator(systemParams.expand_operator('Q1', Q1.T1Dissipator))) systemParams.dissipators.append( Dissipator(systemParams.expand_operator('Q2', Q2.T1Dissipator))) #Setup the initial state as the ground state rhoIn = np.kron(Q1.levelProjector(0), Q2.levelProjector(0)) sampRate = 1.2e9 timeStep = 1.0 / sampRate drive1Freq = Q1.omega - 1e6 drive2Freq = Q2.omega - 1e6 #Calibrate a 240ns Gaussian pulse on Q1 numPoints = 144 xPts = np.linspace(-2, 2, numPoints) gaussPulse = np.exp(-(xPts**2)) tmpControls = np.zeros((4, numPoints)) tmpControls[0] = gaussPulse #Load an optimal control pulse from Jay's GRAPE
systemParams.add_control_ham(inphase = Hamiltonian(crossCoupling21*systemParams.expand_operator('Q1', X) + systemParams.expand_operator('Q2', X)), quadrature = Hamiltonian(crossCoupling21*systemParams.expand_operator('Q1', Y) + systemParams.expand_operator('Q2', Y))) systemParams.add_control_ham(inphase = Hamiltonian(crossCoupling21*systemParams.expand_operator('Q1', X) + systemParams.expand_operator('Q2', X)), quadrature = Hamiltonian(crossCoupling21*systemParams.expand_operator('Q1', Y) + systemParams.expand_operator('Q2', Y))) #Setup the measurement operator # systemParams.measurement = -systemParams.expand_operator('Q1', Q1.pauliZ) systemParams.measurement = np.diag(np.array([0.55, 0.7, 0.75, 0.72, 0.76, 0.76, 0.76, 0.78, 0.80])) #Add the T1 dissipators systemParams.dissipators.append(Dissipator(systemParams.expand_operator('Q1', Q1.T1Dissipator))) systemParams.dissipators.append(Dissipator(systemParams.expand_operator('Q2', Q2.T1Dissipator))) #Setup the initial state as the ground state rhoIn = np.kron(Q1.levelProjector(0), Q2.levelProjector(0)) sampRate = 1.2e9 timeStep = 1.0/sampRate drive1Freq = Q1.omega-1e6 drive2Freq = Q2.omega-1e6 #Calibrate a 240ns Gaussian pulse on Q1 numPoints = 144 xPts = np.linspace(-2,2,numPoints) gaussPulse = np.exp(-(xPts**2)) tmpControls = np.zeros((4,numPoints)) tmpControls[0] = gaussPulse #Load an optimal control pulse from Jay's GRAPE
#Create the full Hamiltonian systemParams.create_full_Ham() #Some Pauli operators for the controls X = 0.5*(Q1.loweringOp + Q1.raisingOp) Y = 0.5*(-1j*Q1.loweringOp + 1j*Q2.raisingOp) #The cross-coupling from Q1 drive to Q2 crossCoupling = 1 #Add the Q1 drive Hamiltonians systemParams.add_control_ham(inphase = Hamiltonian(systemParams.expand_operator('Q1', X) + crossCoupling*systemParams.expand_operator('Q2', X)), quadrature = Hamiltonian(systemParams.expand_operator('Q1', Y) + crossCoupling*systemParams.expand_operator('Q2', Y))) #Setup the measurement operator # systemParams.measurement = np.kron(Q1.levelProjector(1), Q2.levelProjector(1)) systemParams.measurement = 0.5*np.kron(Q1.levelProjector(0), Q2.levelProjector(0)) + 0.67*np.kron(Q1.levelProjector(1), Q2.levelProjector(0)) + \ 0.64*np.kron(Q1.levelProjector(0), Q2.levelProjector(1)) + 0.72*np.kron(Q1.levelProjector(0), Q2.levelProjector(2)) + \ 0.75*np.kron(Q1.levelProjector(1), Q2.levelProjector(1)) + 0.78*np.kron(Q1.levelProjector(1), Q2.levelProjector(2)) #Add the T1 dissipators systemParams.dissipators.append(Dissipator(systemParams.expand_operator('Q1', Q1.T1Dissipator))) systemParams.dissipators.append(Dissipator(systemParams.expand_operator('Q2', Q2.T1Dissipator))) #Setup the initial state as the ground state rhoIn = np.zeros((systemParams.dim, systemParams.dim)) rhoIn[0,0] = 1 #First run 1D spectroscopy around the Bell-Rabi drive frequency freqSweep = 1e9*np.linspace(5.02, 5.040, 20) # freqSweep = [5.023e9] ampSweep = np.linspace(-1,1,80)
from PySim.Simulation import simulate_sequence_stack, simulate_sequence from PySim.OptimalControl import optimize_pulse, PulseParams import numpy as np import matplotlib.pyplot as plt from scipy.constants import pi '''System Setup''' systemParams = SystemParams() qubit = SCQubit(3, 0e9, -100e6, name='Q1', T1=50e-9) systemParams.add_sub_system(qubit) systemParams.add_control_ham(inphase = Hamiltonian(0.5*(qubit.loweringOp + qubit.raisingOp)), quadrature = Hamiltonian(-0.5*(-1j*qubit.loweringOp + 1j*qubit.raisingOp))) systemParams.add_control_ham(inphase = Hamiltonian(0.5*(qubit.loweringOp + qubit.raisingOp)), quadrature = Hamiltonian(-0.5*(-1j*qubit.loweringOp + 1j*qubit.raisingOp))) systemParams.measurement = qubit.levelProjector(1) systemParams.create_full_Ham() #Add the T1 dissipator systemParams.dissipators = [Dissipator(qubit.T1Dissipator)] ''' Simple Rabi Driving We'll vary the Rabi power (but always keep the time to a calibrated pi pulse. We expect to see a maximum at some intermediate regime where we have a balance between selectivity and T1 decay ''' pulseSeqs = [] pulseTimes = 1e-9*np.arange(4,100, 2)