Example #1
0
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)])
Example #2
0
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}
Example #3
0
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)
Example #4
0
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))
Example #5
0
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'
Example #6
0
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]))
Example #7
0
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()
Example #8
0
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
Example #11
0
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
Example #13
0
#    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):
Example #14
0
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()
Example #16
0
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))
Example #17
0
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):
Example #18
0
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
Example #19
0
    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([
Example #20
0
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
Example #21
0
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)