def test_eval(): x = Parameter('x') assert substitute(x, {x: 5}) == 5 y = Parameter('y') assert substitute(x + y, {x: 5, y: 6}) == 11 assert substitute(x + y, {x: 5}) == 5 + y assert substitute(quil_exp(x), {y: 5}) != np.exp(5) assert substitute(quil_exp(x), {x: 5}) == np.exp(5) assert np.isclose(substitute(quil_sin(x * x**2 / y), { x: 5.0, y: 10.0 }), np.sin(12.5)) assert np.isclose(substitute(quil_sqrt(x), { x: 5.0, y: 10.0 }), np.sqrt(5.0)) assert np.isclose(substitute(quil_cis(x), { x: 5.0, y: 10.0 }), np.exp(1j * 5.0)) assert np.isclose(substitute(x - y, {x: 5.0, y: 10.0}), -5.) assert substitute(quil_cis(x), {y: 5}) == quil_cis(x) assert np.allclose(substitute_array([quil_sin(x), quil_cos(x)], {x: 5}), [np.sin(5), np.cos(5)])
def test_contained_parameters(): x = Parameter('x') assert _contained_parameters(x) == {x} y = Parameter('y') assert _contained_parameters(x + y) == {x, y} assert _contained_parameters(x ** y ** sin(x * y * 4)) == {x, y}
def CRX_diags(n): M = np.identity(2**n).astype(object) parameters = [Parameter('p' + str(i)) for i in range(2**(n - 1))] for i, p in enumerate(parameters): M[2 * i:2 * (i + 1), 2 * i:2 * (i + 1)] = X(p) CRX_diag = DefGate('CRX_diag_{}'.format(n), M, parameters) return str(CRX_diag)
def controlled_i_X(n, a, b): theta = Parameter('theta') cirx = controlled_i( np.array([[quil_cos(theta / 2), -1j * quil_sin(theta / 2)], [-1j * quil_sin(theta / 2), quil_cos(theta / 2)]])) CIRX = DefGate('CIRX', cirx, [theta]) return str(CIRX) + '\n' + str(CIRX.get_constructor()(n)(a, b))
def test_dagger(): # these gates are their own inverses p = Program().inst(I(0), X(0), Y(0), Z(0), H(0), CNOT(0, 1), CCNOT(0, 1, 2), SWAP(0, 1), CSWAP(0, 1, 2)) assert p.dagger().out() == 'CSWAP 0 1 2\nSWAP 0 1\n' \ 'CCNOT 0 1 2\nCNOT 0 1\nH 0\n' \ 'Z 0\nY 0\nX 0\nI 0\n' # these gates require negating a parameter p = Program().inst(PHASE(pi, 0), RX(pi, 0), RY(pi, 0), RZ(pi, 0), CPHASE(pi, 0, 1), CPHASE00(pi, 0, 1), CPHASE01(pi, 0, 1), CPHASE10(pi, 0, 1), PSWAP(pi, 0, 1)) assert p.dagger().out() == 'PSWAP(-pi) 0 1\n' \ 'CPHASE10(-pi) 0 1\n' \ 'CPHASE01(-pi) 0 1\n' \ 'CPHASE00(-pi) 0 1\n' \ 'CPHASE(-pi) 0 1\n' \ 'RZ(-pi) 0\n' \ 'RY(-pi) 0\n' \ 'RX(-pi) 0\n' \ 'PHASE(-pi) 0\n' # these gates are special cases p = Program().inst(S(0), T(0), ISWAP(0, 1)) assert p.dagger().out() == 'PSWAP(pi/2) 0 1\n' \ 'RZ(pi/4) 0\n' \ 'PHASE(-pi/2) 0\n' # must invert defined gates G = np.array([[0, 1], [0 + 1j, 0]]) p = Program().defgate("G", G).inst(("G", 0)) assert p.dagger().out() == 'DEFGATE G-INV:\n' \ ' 0.0, -i\n' \ ' 1.0, 0.0\n\n' \ 'G-INV 0\n' # can also pass in a list of inverses inv_dict = {"G": "J"} p = Program().defgate("G", G).inst(("G", 0)) assert p.dagger(inv_dict=inv_dict).out() == 'J 0\n' # defined parameterized gates cannot auto generate daggered version https://github.com/rigetticomputing/pyquil/issues/304 theta = Parameter('theta') gparam_matrix = np.array([[quil_cos(theta / 2), -1j * quil_sin(theta / 2)], [-1j * quil_sin(theta / 2), quil_cos(theta / 2)]]) g_param_def = DefGate('GPARAM', gparam_matrix, [theta]) p = Program(g_param_def) with pytest.raises(TypeError): p.dagger() # defined parameterized gates should passback parameters https://github.com/rigetticomputing/pyquil/issues/304 GPARAM = g_param_def.get_constructor() p = Program(GPARAM(pi)(1, 2)) assert p.dagger().out() == 'GPARAM-INV(pi) 1 2\n'
def test_def_gate_with_variables(): # Note that technically the RX gate includes -i instead of just i but this messes a bit with the test since # it's not smart enough to figure out that -1*i == -i theta = Parameter('theta') rx = np.array([[quil_cos(theta / 2), 1j * quil_sin(theta / 2)], [1j * quil_sin(theta / 2), quil_cos(theta / 2)]]) defgate = 'DEFGATE RX(%theta):\n' \ ' cos(%theta/2), i*sin(%theta/2)\n' \ ' i*sin(%theta/2), cos(%theta/2)\n\n' parse_equals(defgate, DefGate('RX', rx, [theta]))
def controlled_Ry(program): theta = Parameter('theta') cry = np.array([[1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., quil_cos(0.5 * theta), quil_sin(0.5 * theta)], [0., 0., -quil_sin(0.5 * theta), quil_cos(0.5 * theta)]]) dg = DefGate('CRY', cry, [theta]) program.inst(dg) return dg.get_constructor()
def test_def_gate_with_parameters(): theta = Parameter('theta') rx = np.array([[quil_cos(theta / 2), -1j * quil_sin(theta / 2)], [-1j * quil_sin(theta / 2), quil_cos(theta / 2)]]) p = Program().defgate("RX", rx, [theta]) assert p.out() == 'DEFGATE RX(%theta):\n' \ ' cos(%theta/2), -i*sin(%theta/2)\n' \ ' -i*sin(%theta/2), cos(%theta/2)\n\n' dg = DefGate('MY_RX', rx, [theta]) MY_RX = dg.get_constructor() p = Program().inst(MY_RX(np.pi)(0)) assert p.out() == 'MY_RX(pi) 0\n'
def create_CRX(): """ Defining control RX pyquil Gate :return: instruction for CRX """ theta = Parameter('theta') crx = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, quil_cos(theta / 2), -1j * quil_sin(theta / 2)], [0, 0, -1j * quil_sin(theta / 2), quil_cos(theta / 2)]]) dg = DefGate('CRX', crx, [theta]) return dg
def create_CRZ(): """ Defining control RX pyquil Gate :return: instruction for CRZ """ theta = Parameter('theta') crz = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, quil_exp(-1j*theta / 2), 0], [0, 0, 0, quil_exp(1j*theta / 2)]]) dg = DefGate('CRZ', crz, [theta]) return dg
def test_expression_to_string(): x = Parameter('x') assert str(x) == '%x' y = Parameter('y') assert str(y) == '%y' assert str(x + y) == '%x+%y' assert str(3 * x + y) == '3*%x+%y' assert str(3 * (x + y)) == '3*(%x+%y)' assert str(x + y + 2) == '%x+%y+2' assert str(x - y - 2) == '%x-%y-2' assert str(x - (y - 2)) == '%x-(%y-2)' assert str((x + y) - 2) == '%x+%y-2' assert str(x + (y - 2)) == '%x+%y-2' assert str(x ** y ** 2) == '%x^%y^2' assert str(x ** (y ** 2)) == '%x^%y^2' assert str((x ** y) ** 2) == '(%x^%y)^2' assert str(sin(x)) == 'sin(%x)' assert str(3 * sin(x + y)) == '3*sin(%x+%y)'
def state_two_prep(state, qubits): if not isinstance(state, Program): print("The input *state* must be in the form of a PyQuil Program") # Define the new gate from a matrix theta = Parameter('theta') crtest = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, quil_cos(theta / 2), -quil_sin(theta / 2)], [0, 0, quil_sin(theta / 2), quil_cos(theta / 2)]]) gate_definition = DefGate('CRTEST', crtest, [theta]) CRTEST = gate_definition.get_constructor() state += gate_definition state += H(qubits[0]) state += Z(qubits[0]) state += CRTEST(np.pi / 42)(qubits[0], qubits[1]) return state
# limitations under the License. ############################################################################## import warnings from abc import ABC, abstractmethod from collections import namedtuple from typing import Union, List, Tuple import networkx as nx import numpy as np from pyquil.noise import NoiseModel from pyquil.parameters import Parameter from pyquil.quilatom import unpack_qubit from pyquil.quilbase import Gate THETA = Parameter("theta") "Used as the symbolic parameter in RZ, CPHASE gates." DEFAULT_QUBIT_TYPE = "Xhalves" DEFAULT_EDGE_TYPE = "CZ" Qubit = namedtuple("Qubit", ["id", "type", "dead"]) Edge = namedtuple("Edge", ["targets", "type", "dead"]) _ISA = namedtuple("_ISA", ["qubits", "edges"]) QubitSpecs = namedtuple("_QubitSpecs", ["id", "fRO", "f1QRB", "T1", "T2", "fActiveReset"]) EdgeSpecs = namedtuple("_QubitQubitSpecs", ["targets", "fBellState", "fCZ", "fCZ_std_err", "fCPHASE"]) _Specs = namedtuple("_Specs", ["qubits_specs", "edges_specs"]) class ISA(_ISA):
def _variable(variable): # type: (QuilParser.VariableContext) -> Parameter return Parameter(variable.IDENTIFIER().getText())
from pyquil.api import WavefunctionSimulator from pyquil.parameters import Parameter, quil_sin, quil_cos, quil_exp from pyquil.latex import to_latex from math import pi, log2, sqrt import itertools import numpy as np import matplotlib.ticker as ticker import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D fig = plt.figure() ax = fig.add_subplot(111, projection='3d') t1 = [x for x in np.linspace(-np.pi / 2, 3 * np.pi / 2, 32)] #phi t2 = [x for x in np.linspace(0, np.pi / 2, 32)] #alpha phi = Parameter('phi') u_1 = np.array([[1, 0], [0, quil_exp(phi)]]) # Get the Quil definition for the new gate u_1_definition = DefGate('U1', u_1, [phi]) # Get the gate constructor U1 = u_1_definition.get_constructor() alpha = Parameter('alpha') u_2 = np.array([[quil_cos(alpha), 0], [0, quil_sin(alpha)]]) # Get the Quil definition for the new gate u_2_definition = DefGate('U2', u_2, [alpha]) # Get the gate constructor U2 = u_2_definition.get_constructor()
def controlled_X(n, a, b): theta = Parameter('theta') crx = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, quil_cos(theta / 2), -1j * quil_sin(theta / 2)], [0, 0, -1j * quil_sin(theta / 2), quil_cos(theta / 2)]]) CRX = DefGate('CRX', crx, [theta]) return str(CRX) + '\n' + str(CRX.get_constructor()(n)(a, b))
from matplotlib import pyplot as pp from scipy.optimize import minimize # PyQUIL import pyquil.api as api from pyquil.gates import * from pyquil.quil import DefGate from pyquil import Program, get_qc from pyquil.paulis import PauliSum, PauliTerm from pyquil.parameters import Parameter, quil_sin, quil_cos # Grove from grove.pyvqe.vqe import VQE # We define a few gates that don't come natively with PyQuil but we need for the UCC ansatz phi = Parameter("phi") # We define the RX gate with a -1 phase nrx = np.array([[-quil_cos(phi / 2), 1j * quil_sin(phi / 2)], [1j * quil_sin(phi / 2), -quil_cos(phi / 2)]]) nrx_def = DefGate("NRX", nrx, [phi]) NRX = nrx_def.get_constructor() # We define the RY gate with a -1 phase nry = np.array([[-quil_cos(phi / 2), quil_sin(phi / 2)], [-quil_sin(phi / 2), -quil_cos(phi / 2)]]) nry_def = DefGate("NRY", nry, [phi]) NRY = nry_def.get_constructor() # Ansatz definition def ansatz(params):
def compute_circuit(angles_vector_in_degrees_str): rotation_deg_of_freedom = 28 a = [0] * rotation_deg_of_freedom for i in range(rotation_deg_of_freedom): a[i] = radians(float(angles_vector_in_degrees_str[i])) theta = Parameter('theta') anot = np.array([[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) aary = np.array( [[quil_cos(theta / 2), -1 * quil_sin(theta / 2), 0, 0, 0, 0, 0, 0], [quil_sin(theta / 2), quil_cos(theta / 2), 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 1]]) ccry = np.array( [[1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, quil_cos(theta / 2), -1 * quil_sin(theta / 2)], [0, 0, 0, 0, 0, 0, quil_sin(theta / 2), quil_cos(theta / 2)]]) #TODO: Ascertain what kind of gates this is? cary = np.array( [[1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, quil_cos(theta / 2), -1 * quil_sin(theta / 2), 0, 0, 0], [0, 0, 0, quil_sin(theta / 2), quil_cos(theta / 2), 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 1]]) dg_anot = DefGate('ANOT', anot) dg_aary = DefGate('AARY', aary, [theta]) dg_ccry = DefGate('CCRY', ccry, [theta]) dg_cary = DefGate('CARY', cary, [theta]) ANOT = dg_anot.get_constructor() AARY = dg_aary.get_constructor() CCRY = dg_ccry.get_constructor() CARY = dg_cary.get_constructor() qvm = api.QVMConnection() p = pq.Program() p.inst(dg_anot) p.inst(dg_aary) p.inst(dg_ccry) p.inst(dg_cary) #p.inst(X(0)) #p.inst(X(1)) #p.inst(X(2)) # CD rotation p.inst(AARY(a[0] * 2)(2, 1, 0)) # CE rotation p.inst(AARY(a[1] * 2)(2, 0, 1)) # CF rotation p.inst(CNOT(1, 0)) p.inst(AARY(a[2] * 2)(0, 2, 1)) p.inst(CNOT(1, 0)) # CG rotation p.inst(AARY(a[3] * 2)(0, 1, 2)) # CA rotation p.inst(CNOT(2, 0)) p.inst(AARY(a[4] * 2)(0, 1, 2)) p.inst(CNOT(2, 0)) # CB rotation p.inst(CNOT(2, 1)) p.inst(AARY(a[5] * 2)(0, 1, 2)) p.inst(CNOT(2, 1)) # CC' rotation p.inst(CNOT(1, 0)) p.inst(CNOT(1, 2)) p.inst(AARY(a[6] * 2)(0, 2, 1)) p.inst(CNOT(1, 2)) p.inst(CNOT(1, 0)) # DE rotation p.inst(ANOT(1, 0)) p.inst(AARY(a[7] * 2)(0, 2, 1)) p.inst(ANOT(1, 0)) # DF rotation p.inst(X(2)) p.inst(CCRY(a[8] * 2)(0, 2, 1)) p.inst(X(2)) # DG rotation p.inst(ANOT(2, 0)) p.inst(AARY(a[9] * 2)(0, 1, 2)) p.inst(ANOT(2, 0)) # DA rotation p.inst(X(1)) p.inst(CCRY(a[10] * 2)(0, 1, 2)) p.inst(X(1)) # DB rotation p.inst(CNOT(1, 0)) p.inst(ANOT(1, 2)) p.inst(CCRY(a[11] * 2)(0, 2, 1)) p.inst(ANOT(1, 2)) p.inst(CNOT(1, 0)) # DC' rotation p.inst(ANOT(1, 2)) p.inst(CCRY(a[12] * 2)(0, 2, 1)) p.inst(ANOT(1, 2)) # EF rotation p.inst(X(2)) p.inst(CCRY(a[13] * 2)(1, 2, 0)) p.inst(X(2)) # EG rotation p.inst(ANOT(2, 1)) p.inst(AARY(a[14] * 2)(0, 1, 2)) p.inst(ANOT(2, 1)) # EA rotation p.inst(CNOT(0, 1)) p.inst(ANOT(0, 2)) p.inst(CCRY(a[15] * 2)(1, 2, 0)) p.inst(ANOT(0, 2)) p.inst(CNOT(0, 1)) # EB rotation p.inst(X(0)) p.inst(CCRY(a[16] * 2)(0, 1, 2)) p.inst(X(0)) # EC' rotation p.inst(ANOT(0, 2)) p.inst(CCRY(a[17] * 2)(1, 2, 0)) p.inst(ANOT(0, 2)) # FG rotation p.inst(CARY(a[18] * 2)(2, 1, 0)) # FA rotation p.inst(CNOT(2, 1)) p.inst(CCRY(a[19] * 2)(0, 1, 2)) p.inst(CNOT(2, 1)) # FB rotation p.inst(CNOT(2, 0)) p.inst(CCRY(a[20] * 2)(0, 1, 2)) p.inst(CNOT(2, 0)) # FC' rotation p.inst(CCRY(a[21] * 2)(0, 1, 2)) # GA rotation p.inst(X(1)) p.inst(CCRY(a[22] * 2)(1, 2, 0)) p.inst(X(1)) # GB rotation p.inst(X(0)) p.inst(CCRY(a[23] * 2)(0, 2, 1)) p.inst(X(0)) # GC' rotation p.inst(ANOT(1, 0)) p.inst(CCRY(a[24] * 2)(0, 2, 1)) p.inst(ANOT(1, 0)) # AB rotation p.inst(CNOT(1, 0)) p.inst(CCRY(a[25] * 2)(0, 2, 1)) p.inst(CNOT(1, 0)) # AC' rotation p.inst(CCRY(a[26] * 2)(0, 2, 1)) # BC' rotation p.inst(CCRY(a[27] * 2)(1, 2, 0)) wavefunction = qvm.wavefunction(p) print(wavefunction) return p
else: g, y, x = egcd(b % a, a) return (g, x - (b // a) * y, y) def modinv(a, m): g, x, y = egcd(a, m) if g != 1: raise Exception('modular inverse does not exist') else: return x % m qvm = QVMConnection() k = Parameter('k') ccrk = np.array([ [1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, quil_exp((2 * np.pi * 1j) / (2**k))], ]) ccrk_gate_def = DefGate('CCRK', ccrk, [k]) CCRK = ccrk_gate_def.get_constructor() crk = np.array([
class QAECircuit(object): """Class to build a quantum autoencode. Generates a program that performs a parameterized rotation gate on all the input qubits, followed by all possible combinations of parameterized controlled rotation gates and then another single qubit rotation gate on all qubits. It then daggers and "flips" (reverses qubits) and appends it to the original program. Attributes ---------- theta: pyquil.parameters.Parameter Parameter for defining parameterized gates crx: numpy.Array Matrix representation of controlled RX gate crx_def: pyquil.quilbase.DefGate Controlled RX gate definition CRX: pyquil.quilbase.Gate pyquil Gate for parameterized RX cry: numpy.Array Matrix representation of controlled RY gate cry_def: pyquil.quilbase.DefGate Controlled RY gate definition CRY: pyquil.quilbase.Gate pyquil Gate for parameterized RY crz: numpy.Array Matrix representation of controlled RZ gate crz_def: pyquil.quilbase.DefGate Controlled RZ gate definition CRZ: pyquil.quilbase.Gate pyquil Gate for parameterized RZ gates_dict : dictionary Dictionary of string representation => pyquil.quilbase.Gate. Contains all rotation gates and controlled rotation gates """ theta = Parameter('theta') crx = np.array([ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, quil_cos(theta / 2), -1j * quil_sin(theta / 2)], [0, 0, -1j * quil_sin(theta / 2), quil_cos(theta / 2)] ]) crx_def = DefGate('CRX', crx, [theta]) CRX = crx_def.get_constructor() cry = np.array([ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, quil_cos(theta / 2), -1 * quil_sin(theta / 2)], [0, 0, quil_sin(theta / 2), quil_cos(theta / 2)] ]) cry_def = DefGate('CRY', cry, [theta]) CRY = cry_def.get_constructor() crz = np.array([ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, quil_cos(theta / 2) - 1j * quil_sin(theta / 2), 0], [0, 0, 0, quil_cos(theta / 2) + 1j * quil_sin(theta / 2)] ]) crz_def = DefGate('CRZ', crz, [theta]) CRZ = crx_def.get_constructor() gates_dict = { 'RX': RX, 'CRX': CRX, 'RY': RY, 'CRY': CRY, 'RZ': RZ, 'CRZ': CRZ, } def __init__(self, num_qubits, num_latent_qubits, thetas, axes=None, qubits=None): """Initialize the circuit. Parameters ---------- num_qubits : int, required Total number of qubits required by the circuit. This should be (2 * num_input_qubits - num_latent_qubits) num_latent_qubits : int, required Number of latent space qubits thetas : list[numeric], required List of rotation parameters for each gate this should be of length 2n + n(n-1) where n is the number of input qubits axes : list[string], optional (default None) List of rotation directions per block of gates. Possible values are 'X', 'Y', 'Z' Sets all values to 'X' when not set qubits : list[int], optional (default None) List of qubit labels for the circuit Set to 0 - (num_qubits - 1) when not passed Useful to optimize the circuit based on topology of a QPU Attributes ---------- num_input_qubits: int Number of qubits input to the first portion of the circuit. """ self.num_qubits = num_qubits self.num_latent_qubits = num_latent_qubits self.num_input_qubits = int((num_qubits + num_latent_qubits) / 2) if qubits is None: self.qubits = [] for i in range(self.num_qubits): self.qubits.append(i) else: self.qubits = qubits if axes is None: self.axes = ['X'] * (self.num_input_qubits + 2) else: self.axes = axes self.thetas = thetas self.program = Program() def def_gates_program(self): """Create a program with defined with controlled rotation gates. Returns ------- pyquil.quil.Program pyquil Program with defined controlled rotation gates """ return Program(QAECircuit.crx_def, QAECircuit.cry_def, QAECircuit.crz_def) def build_circuit(self): """Build quantum autoencoder circuit. Returns ------- pyquil.quil.Program pyquil Program """ self.program += self.def_gates_program() qubits = self.qubits[:self.num_input_qubits] thetas = self.thetas[:self.num_input_qubits] axis = self.axes[0] self.program += self.build_rotation_block(axis, qubits, thetas) for i in range(self.num_input_qubits): axis = self.axes[i+1] control_qubit = qubits[i] start_theta = self.num_input_qubits + (self.num_input_qubits - 1) * i end_theta = start_theta + (self.num_input_qubits - 1) thetas = self.thetas[start_theta:end_theta] self.program += self.build_controlled_rotation_block(axis, qubits, thetas, control_qubit) axis = self.axes[self.num_input_qubits+1] start_theta = self.num_input_qubits + (self.num_input_qubits - 1) * self.num_input_qubits end_theta = start_theta + self.num_input_qubits thetas = self.thetas[start_theta:end_theta] self.program += self.build_rotation_block(axis, qubits, thetas) return self.program + self.dagger_and_flip(self.program, self.qubits) def build_rotation_block(self, axis, qubits, thetas): """Build a circuit block made from single qubit rotation gates. Parameters ---------- axis : string, required Axis for the rotation gates. 'X', 'Y', or 'Z' qubits : list[int], required List of qubit labels to attach the gates to thetas : list[numeric], required List of rotation paramaters for each gate. Length should match that of qubits Returns ------- pyquil.quil.Program pyquil Program that consists of rotation gates acting on passed in qubits """ gate = self.gate_from_axis(axis, 1) program = Program() for i, qubit in enumerate(qubits): program += Program(gate(thetas[i], qubit)) return program def build_controlled_rotation_block(self, axis, qubits, thetas, qubit_control): """Build a circuit block made from two qubit controlled rotation gates. Parameters ---------- axis : string, required Axis for the rotation gates. 'X', 'Y', or 'Z' qubits : list[int], required List of qubit labels to attach the gates to thetas : list[numeric], required List of rotation paramaters for each gate. Length should match that of qubits qubit_control : int, required Qubit that acts as the control on the controlled rotation gates Returns ------- pyquil.quil.Program pyquil Program that consists of controlled rotation gates acting on passed in qubits """ gate = self.gate_from_axis(axis, 2) program = Program() i = 0 for qubit in qubits: if qubit != qubit_control: theta = thetas[i] i += 1 program += Program(gate(theta)(qubit_control, qubit)) return program def gate_from_axis(self, axes, num_qubits): """Get a gate based on an axis and number of qubits it acts on. Parameters ===== axes : string, required Axis rotation gate to fetch num_qubits : int, required Number of qubits the gate acts on (1 or 2) Returns ------- pyquil.quilbase.Gate Rotation gate or controlled rotation gate based on axis and number of qubits """ gate_str = "R{}".format(axes) if 2 == num_qubits: gate_str = "C" + gate_str return QAECircuit.gates_dict[gate_str] def dagger_and_flip(self, program, qubits): """Build and return a daggered and flipped version of a program. Parameters ---------- program : pyquil.quil.Program Program to be daggered and flipped qubits : type List of qubits to be used when flipping the programself. e.g. [1, 2, 3, 4] are used in the program, they will be replaced with [4, 3, 2, 1] in the flipped version. If a list larger than the number of qubits is passed, the mapping accounts for this. e.g. qubits [1, 2, 3, 4] are using by `program` but `qubits` passed is [1, 2, 3, 4, 5, 6] in the returned program, [6, 5, 4, 3] will only be used. The mapping is as follows: 1 => 6, 2 => 5, 3 => 4, 4 => 2. Returns ------- pyquil.quil.Program A flipped and daggered program Notes ----- This only works for rotation and controlled rotation gates. See pyquil.quil.Program.dagger() for further implmementation """ qubits_reversed = dict(zip(qubits, reversed(qubits))) flipped_program = Program() for gate in reversed(program.instructions): gate_qubits = [] for i in gate.qubits: gate_qubits.append(qubits_reversed[i.index]) # Daggered versions of all gates are just a rotation in the opposite direction negated_params = list(map(lambda x: -1 * x, gate.params)) flipped_program.inst(QAECircuit.gates_dict[gate.name](*negated_params)(*gate_qubits)) return flipped_program
from pyquil.gates import X, Z, Y from pyquil.gates import MEASURE from pyquil.gates import H from pyquil.gates import CNOT from pyquil.api import QVMConnection from pyquil.gates import SWAP from pyquil.parameters import Parameter, quil_sin, quil_cos from pyquil.quilbase import DefGate import numpy as np import scipy from scipy.linalg import expm, sinm, cosm from image_processing import * theta = Parameter('theta') K = np.array([[0.5065, 0.2425], [0.2425, 0.4935]]) gamma = 100 # 2 F = K + 1 / gamma * np.eye(2) class QSVM(): def __init__(self, F, qvm): self.F = F self.program = Program() # empty pyquil program self.qvm = qvm self.first, self.second, self.y, self.anc = (0, 1, 2, 3) self.theta0 = None self.theta1 = None
from pyquil import Program from pyquil.parameters import Parameter, quil_sin, quil_cos from pyquil.quilbase import DefGate from pyquil.gates import * import numpy as np thetaParameter = Parameter('theta') controlledRx = np.array( [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, quil_cos(thetaParameter / 2), -1j * quil_sin(thetaParameter / 2)], [0, 0, -1j * quil_sin(thetaParameter / 2), quil_cos(thetaParameter / 2)]]) gate_definition = DefGate('CRX', controlledRx, [thetaParameter]) CONTROLRX = gate_definition.get_constructor() program = Program() program = program + gate_definition program = program + H(0) program = program + CONTROLRX(np.pi / 2)(0, 1) print(program)