Source code for qubiter.device_specific.RigettiTools
# from pyquil import get_qc
# from pyquil.api._base_connection import ForestConnection
from pyquil.gates import RX, RY
from pyquil.quil import Program
import sys
if 'autograd.numpy' not in sys.modules:
import numpy as np
else:
import autograd.numpy as np
[docs]class RigettiTools:
"""
This class has no constructor. It consists of static methods that
facilitate the interaction between Qubiter and PyQuil and the Rigetti
Cloud.
"""
# @staticmethod
# def get_qc(device_name, noisy=False, **kwargs):
# """
# This method creates ForestConnection object and calls PyQuil get_qc()
# method.
#
# Parameters
# ----------
# device_name : str
# noisy : bool
# kwargs : dict
#
# Returns
# -------
# QuantumComputer
#
# """
#
# qvm_url = "http://127.0.0.1:5000"
# compiler_url = "http://127.0.0.1:6000"
# forest_url = "https://forest-server.qcs.rigetti.com"
#
# con = ForestConnection(
# sync_endpoint=qvm_url,
# compiler_endpoint=compiler_url,
# forest_cloud_endpoint=forest_url)
# qc = get_qc(device_name, connection=con,
# noisy=noisy, **kwargs)
# return qc
[docs] @staticmethod
def obs_vec_from_bitstrings(bitstrings, num_qbits, bs_is_array):
"""
This method converts a PyQuil `bitstrings` into a Qubiter
observation vector which it then returns.
Qubiter likes to state the results of an experiment repeated
num_shots (aka num_samples) times by what it calls an observation
vector. An obs vec is a 1-dim array, num_shots long, whose entries
are integers which are the decimal representation of a string,
num_qbits long, of zeros and ones. This string of zeros and ones
gives the state of each qubit in the ZL convention.
PyQuil likes to state the results of an experiment repeated num_shots
times by what it calls bitstrings. A bitstrings is a dict that maps
qubit number to a 1-dim array, num_shots long, of zeros and ones.
Here is an example::
[1]:
bitstrings = qc.run_and_measure(program, trials=10)
bitstrings
[2]:
{0: array([1, 0, 0, 1, 1, 1, 1, 0, 1, 0]),
1: array([1, 0, 0, 1, 1, 1, 1, 0, 1, 0]),
2: array([1, 0, 0, 1, 1, 1, 1, 0, 1, 0])}
However, qc.run() returns a numpy array of zeros and ones and shape
(num_shots, num_qbits), formed from the bitstrings dict just
described. If bs_is_array=False, we assume the input bitstrings is a
dict, and if True, we assume it is an array.
Parameters
----------
bitstrings : dict[int, np.ndarray]
num_qbits : int
bs_is_array : bool
stands for: bitstrings is array
Returns
-------
np.ndarray
shape = (num_shots,)
"""
if not bs_is_array:
assert isinstance(bitstrings, dict)
assert len(bitstrings) == num_qbits,\
"for num_qbits = " + str(num_qbits) + ' got bitstrings=\n' +\
str(bitstrings)
num_shots = bitstrings[0].shape[0]
bs_array = np.vstack([bitstrings[q] for q in range(num_qbits)])
else:
assert isinstance(bitstrings, np.ndarray)
assert bitstrings.shape[1] == num_qbits
num_shots = bitstrings.shape[0]
bs_array = bitstrings.T
obs_vec = np.zeros((num_shots,), dtype=int)
for shot in range(num_shots):
shot_array = bs_array[:, shot]
s = ''.join([str(shot_array[q])
for q in reversed(range(num_qbits))])
obs_vec[shot] = int(s, 2)
return obs_vec
[docs] @staticmethod
def add_xy_meas_coda_to_program(prog, bit_pos_to_xy_str):
"""
This method adds a "coda" (tail ending) to prog using data in
bit_pos_to_xy_str to determine what coda will be.
Parameters
----------
prog : Program
bit_pos_to_xy_str : dict[int, str]
Returns
-------
None
"""
for bit_pos, xy_str in bit_pos_to_xy_str.items():
if xy_str == 'X':
# exp(-i*sigy*pi/4)*sigz*exp(i*sigy*pi/4) = sigx
prog += RY(-np.pi/2, bit_pos)
elif xy_str == 'Y':
# exp(i*sigx*pi/4)*sigz*exp(-i*sigx*pi/4) = sigy
prog += RX(np.pi/2, bit_pos)
else:
assert False, "Unsupported qbit measurement. '" + \
xy_str + "' Should be either 'X' or 'Y'"
if __name__ == "__main__":
def main1():
bitstrings = {
0: np.array([1, 0, 1, 1, 1, 1, 0, 1, 1, 0]),
1: np.array([1, 1, 0, 0, 1, 0, 1, 0, 1, 0]),
2: np.array([0, 0, 0, 1, 1, 1, 1, 0, 1, 1])}
num_qbits = 3
obs_vec = RigettiTools.obs_vec_from_bitstrings(
bitstrings, num_qbits, bs_is_array=False)
print(obs_vec)
def main2():
bitstrings = np.vstack([
[1, 1, 0], [0, 1, 0], [1, 0, 0], [1, 0, 1], [1, 1, 1],
[1, 0, 1], [0, 1, 1], [1, 0, 0], [1, 1, 1], [0, 0, 1]
])
num_qbits = 3
obs_vec = RigettiTools.obs_vec_from_bitstrings(
bitstrings, num_qbits, bs_is_array=True)
print(obs_vec)
main1()
main2()