diff --git a/xacc_examples/Pulse_Control/Pulse_Control/README.md b/xacc_examples/Pulse_Control/Pulse_Control/README.md new file mode 100644 index 0000000..95a2807 --- /dev/null +++ b/xacc_examples/Pulse_Control/Pulse_Control/README.md @@ -0,0 +1 @@ +This is a repo for developing time and bandlimited pulse controls for quantum devices. Through the use of Trust Region Policy Optimization, a method of Deep Reinforcement Learning, we can optimize the fidelity of quantum logic gates through the construction of pulses in terms of Discrete Prolate Spheroidal Sequences. diff --git a/xacc_examples/Pulse_Control/Pulse_Control/gym_pulsecontrol/__pycache__/__init__.cpython-36.pyc b/xacc_examples/Pulse_Control/Pulse_Control/gym_pulsecontrol/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..9f6560d Binary files /dev/null and b/xacc_examples/Pulse_Control/Pulse_Control/gym_pulsecontrol/__pycache__/__init__.cpython-36.pyc differ diff --git a/xacc_examples/Pulse_Control/Pulse_Control/gym_pulsecontrol/envs/__init__.py b/xacc_examples/Pulse_Control/Pulse_Control/gym_pulsecontrol/envs/__init__.py new file mode 100644 index 0000000..3924f80 --- /dev/null +++ b/xacc_examples/Pulse_Control/Pulse_Control/gym_pulsecontrol/envs/__init__.py @@ -0,0 +1 @@ +from gym_pulsecontrol.envs.pulsecontrol_env import PulseEnv \ No newline at end of file diff --git a/xacc_examples/Pulse_Control/Pulse_Control/gym_pulsecontrol/envs/__pycache__/__init__.cpython-36.pyc b/xacc_examples/Pulse_Control/Pulse_Control/gym_pulsecontrol/envs/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..711bbb5 Binary files /dev/null and b/xacc_examples/Pulse_Control/Pulse_Control/gym_pulsecontrol/envs/__pycache__/__init__.cpython-36.pyc differ diff --git a/xacc_examples/Pulse_Control/Pulse_Control/gym_pulsecontrol/envs/__pycache__/pulsecontrol_env.cpython-36.pyc b/xacc_examples/Pulse_Control/Pulse_Control/gym_pulsecontrol/envs/__pycache__/pulsecontrol_env.cpython-36.pyc new file mode 100644 index 0000000..0b48cd4 Binary files /dev/null and b/xacc_examples/Pulse_Control/Pulse_Control/gym_pulsecontrol/envs/__pycache__/pulsecontrol_env.cpython-36.pyc differ diff --git a/xacc_examples/Pulse_Control/Pulse_Control/gym_pulsecontrol/envs/pulsecontrol_env.py b/xacc_examples/Pulse_Control/Pulse_Control/gym_pulsecontrol/envs/pulsecontrol_env.py new file mode 100644 index 0000000..6894b56 --- /dev/null +++ b/xacc_examples/Pulse_Control/Pulse_Control/gym_pulsecontrol/envs/pulsecontrol_env.py @@ -0,0 +1,65 @@ +import gym +import xacc +import numpy as np +import scipy as sp +from gym import error, spaces, utils +from gym.utils import seeding + +class PulseEnv(gym.Env): + metadata = {'render.modes': ['human']} + + def __init__(self): + self._state = np.zeros(15) + #self._state = np.zeros(self.slepians_matrix.shape[1]) + self.end_episode_rewards = [] + self.current_reward = [] + self.index = 0 + + def reward_function(self): + self.pulseData = (self._state * self.slepians_matrix).sum(axis=1) + # Add that square pulse instruction to XACC + pulseName = 'Slepian' + str(self.index) + print(pulseName) + xacc.addPulse(pulseName, self.pulseData) + q = xacc.qalloc(1) + # Create the quantum program that contains the slepian pulse + # and the drive channel (D0) is set on the instruction + provider = xacc.getIRProvider('quantum') + prog = provider.createComposite('pulse') + slepianPulse = provider.createInstruction(pulseName, [0]) + slepianPulse.setChannel('d0') + prog.addInstruction(slepianPulse) + # Measure Q0 (using the number of shots that was specified above) + prog.addInstruction(xacc.gate.create("Measure", [0])) + self.qpu.execute(q, prog) + return q.computeMeasurementProbability('1') + + def step(self, action): + a = action.copy() + self._state = self._state + a + self._state = np.clip(self._state, self.observation_space.low, self.observation_space.high) + self.index += 1 + reward = self.reward_function() + print("REWARD IS ", reward) + done = bool((np.abs(1.0-reward) < 1e-4)) + next_state = np.copy(self._state) + return np.array(next_state), reward, done, {} + + def reset(self): + self._state = np.zeros(self.slepians_matrix.shape[1]) + observation = np.copy(self._state) + return observation + + def render(self, mode='human'): + print('Reward=', self.reward_function()) + + def close(self): + pass + + @property + def action_space(self): + return spaces.Box(low=-0.25, high=0.25, shape=(15,))#shape=(self.n_orders,)) + + @property + def observation_space(self): + return spaces.Box(low=-5.0, high=5.0, shape=(15,))#shape=(self.n_orders,)) \ No newline at end of file diff --git a/xacc_examples/Pulse_Control/Pulse_Control/main.py b/xacc_examples/Pulse_Control/Pulse_Control/main.py new file mode 100644 index 0000000..fe5d288 --- /dev/null +++ b/xacc_examples/Pulse_Control/Pulse_Control/main.py @@ -0,0 +1,59 @@ +#%% +import xacc +import gym +import spectrum +import json +#import gym_pulsecontrol +import numpy as np + +from stable_baselines.common.policies import MlpPolicy +from stable_baselines import PPO2 + +# Total time, T, of control pulse +T = 100 +# Number of pulse samples +nbSamples = 200 +W = 0.05 +k = int(2 * nbSamples * W) +n_orders = 15 +# Initialize Slepians +Slepians, eigenvalues = spectrum.dpss(nbSamples, (nbSamples*W), k) +Slepians = Slepians[:, 0:n_orders] + +gym.envs.register( + id='PulseControl-v0', + entry_point='gym_pulsecontrol.envs.pulsecontrol_env:PulseEnv', +) + +env = gym.make('PulseControl-v0') +env.slepians_matrix = Slepians.copy() +env.n_orders = n_orders + +hamiltonianJson = { + "description": "Hamiltonian of a one-qubit system.\n", + "h_str": ["-0.5*omega0*Z0", "omegaa*X0||D0"], + "osc": {}, + "qub": { + "0": 2 + }, + "vars": { + "omega0": 6.2831853, + "omegaa": 0.0314159 + } +} + +# Create a pulse system model object +env.model = xacc.createPulseModel() +# Load the Hamiltonian JSON (string) to the system model +loadResult = env.model.loadHamiltonianJson(json.dumps(hamiltonianJson)) +env.qpu = xacc.getAccelerator('QuaC', {'system-model': env.model.name(), 'shots': 1024 }) +env.channelConfig = xacc.BackendChannelConfigs() +# Setting resolution of pulse +env.channelConfig.dt = nbSamples / T +# Driving on resonance with qubit +env.channelConfig.loFregs_dChannels = [1.0] +env.model.setChannelConfigs(env.channelConfig) + +drl_model = PPO2('MlpPolicy', env, + verbose=0) +drl_model.learn(total_timesteps=50*n_orders) diff --git a/xacc_examples/Pulse_Control/Pulse_Control/setup.py b/xacc_examples/Pulse_Control/Pulse_Control/setup.py new file mode 100644 index 0000000..f9c6b43 --- /dev/null +++ b/xacc_examples/Pulse_Control/Pulse_Control/setup.py @@ -0,0 +1,6 @@ +from setuptools import setup + +setup(name='gym_pulsecontrol', + version='0.0.1', + install_requires=['gym', 'numpy', 'scipy', 'spectrum', 'tensorflow==1.15'] +) \ No newline at end of file diff --git a/xacc_examples/python/first_attempt.py b/xacc_examples/python/first_attempt.py new file mode 100644 index 0000000..7ace830 --- /dev/null +++ b/xacc_examples/python/first_attempt.py @@ -0,0 +1,87 @@ +# One-qubit pulse simulation: Rabi oscillation +# We need to have the XACC install directory in the Python path. +# Just in case users haven't already done that, set it here. +import sys +from pathlib import Path +sys.path.insert(1, str(Path.home()) + '/.xacc') + +# Import xacc and quaC python wrapper +import os +import xacc +import json +import spectrum + +import numpy as np +import matplotlib +# CADES VM don't have display +matplotlib.use('Agg') +import matplotlib.pyplot as plt + +# The Hamiltonian JSON object (OpenPulse format) +# omega0 = 2*pi, rotation speed: 100ns -> pi pulse (assume dt = 1) +hamiltonianJson = { + "description": "Hamiltonian of a one-qubit system.\n", + "h_str": ["-0.5*omega0*Z0", "omegaa*X0||D0"], + "osc": {}, + "qub": { + "0": 2 + }, + "vars": { + "omega0": 6.2831853, + "omegaa": 0.0314159 + } +} + +# Create a pulse system model object +model = xacc.createPulseModel() + +# Load the Hamiltonian JSON (string) to the system model +loadResult = model.loadHamiltonianJson(json.dumps(hamiltonianJson)) + +qpu = xacc.getAccelerator('QuaC', {'system-model': model.name(), 'shots': 1024 }) +channelConfig = xacc.BackendChannelConfigs() + +T = 100 +# Number of sample points to realize a PI pulse +nbSamples = 1000 #512 # 100 +# dt (time between data samples) +channelConfig.dt = nbSamples / T #1.0 +# omega0 = 2*pi => freq = 1.0 (drive at resonance) +channelConfig.loFregs_dChannels = [1.0] +model.setChannelConfigs(channelConfig) + +W = 0.02 +k = int(2 * nbSamples * W) +n_orders = 36 +# Initialize Slepians +Slepians, eigenvalues = spectrum.dpss(nbSamples, (nbSamples*W), k) +Slepians = Slepians[:, 0:n_orders] + +state = 5 * np.ones(Slepians.shape[1]) + +# Square pulse with nbSamples elements +pulseData = (state * Slepians).sum(axis=1) +# Add that square pulse instruction to XACC +pulseName = 'Slepian' +xacc.addPulse(pulseName, pulseData) +q = xacc.qalloc(1) +# Create the quantum program that contains the square pulse +# and the drive channel (D0) is set on the instruction +provider = xacc.getIRProvider('quantum') +prog = provider.createComposite('pulse') +slepianPulse = provider.createInstruction(pulseName, [0]) +slepianPulse.setChannel('d0') +prog.addInstruction(slepianPulse) +# Measure Q0 (using the number of shots that was specified above) +prog.addInstruction(xacc.gate.create("Measure", [0])) + +# Run the simulation +qpu.execute(q, prog) +resultProb = q.computeMeasurementProbability('1') + +print(resultProb) + +# Plot the result +plt.plot(pulseData) +os.chdir(os.path.dirname(os.path.abspath(__file__))) +plt.savefig('Slepian.png') \ No newline at end of file diff --git a/xacc_examples/python/one_qubit.py b/xacc_examples/python/one_qubit.py index e17f86a..12866c9 100644 --- a/xacc_examples/python/one_qubit.py +++ b/xacc_examples/python/one_qubit.py @@ -62,7 +62,7 @@ i = 0 for width in pulseWidth: # Square pulse with nbSamples elements - pulseData = np.ones(width) + pulseData = np.ones(int(width)) # Add that square pulse instruction to XACC pulseName = 'square' + str(width) xacc.addPulse(pulseName, pulseData)