Пример #1
0
    def set_up_QAOA_in_pyquil(beta,
                              gamma,
                              p,
                              n_qubits=2,
                              J=np.array([[0, 1], [0, 0]])):

        Hm = [PauliTerm("X", i, 1.0) for i in range(n_qubits)]

        Hc = []
        ####################Prepare the hamiltonian for measurement
        Hamilton = prepare_qaoa_hamiltonian(J, n_qubits)
        ###################
        initial_state = Program()
        for i in range(n_qubits):
            initial_state += H(i)
        for i in range(n_qubits):
            for j in range(n_qubits):
                Hc.append(PauliTerm("Z", i, -J[i, j]) * PauliTerm("Z", j, 1.0))
        exp_Hm = []
        exp_Hc = []
        for term in Hm:
            exp_Hm.append(exponential_map(term))
        for term in Hc:
            exp_Hc.append(exponential_map(term))
        qaoa_circuit = create_circuit(beta, gamma, initial_state, exp_Hm,
                                      exp_Hc)

        return Hamilton, qaoa_circuit
def test_exponentiate_identity():
    q = QubitPlaceholder.register(11)
    mapping = {qp: Qubit(i) for i, qp in enumerate(q)}
    generator = PauliTerm("I", q[1], 0.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst()
    assert address_qubits(prog,
                          mapping) == address_qubits(result_prog, mapping)

    generator = PauliTerm("I", q[1], 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(
        [X(q[0]), PHASE(-1.0, q[0]),
         X(q[0]), PHASE(-1.0, q[0])])
    assert address_qubits(prog,
                          mapping) == address_qubits(result_prog, mapping)

    generator = PauliTerm("I", q[10], 0.08)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(
        [X(q[0]), PHASE(-0.08, q[0]),
         X(q[0]), PHASE(-0.08, q[0])])
    assert address_qubits(prog,
                          mapping) == address_qubits(result_prog, mapping)
Пример #3
0
    def get_parameterized_program(self):
        """
        Return a function that accepts parameters and returns a new Quil
        program

        :returns: a function
        """
        cost_para_programs = []
        driver_para_programs = []

        for _ in range(self.steps):
            cost_list = []
            driver_list = []
            for cost_pauli_sum in self.cost_ham:
                for term in cost_pauli_sum.terms:
                    cost_list.append(exponential_map(term))

            for driver_pauli_sum in self.ref_ham:
                for term in driver_pauli_sum.terms:
                    driver_list.append(exponential_map(term))

            cost_para_programs.append(cost_list)
            driver_para_programs.append(driver_list)

        def psi_ref(params):
            """
            Construct a Quil program for the vector (beta, gamma).

            :param params: array of 2 . p angles, betas first, then gammas
            :return: a pyquil program object
            """
            if len(params) != 2 * self.steps:
                raise ValueError(
                    "params doesn't match the number of parameters set "
                    "by `steps`")
            betas = params[:self.steps]
            gammas = params[self.steps:]

            prog = pq.Program()
            prog += self.ref_state_prep
            for idx in range(self.steps):
                for fprog in cost_para_programs[idx]:
                    prog += fprog(gammas[idx])

                for fprog in driver_para_programs[idx]:
                    prog += fprog(betas[idx])

            return prog

        return psi_ref
Пример #4
0
def test_exponentiate_1():
    # test rotation of single qubit
    generator = PauliTerm("Z", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(RZ(2.0, 0))
    assert prog == result_prog
Пример #5
0
def test_exponentiate_bp1_XZ():
    # testing change of basis position 1
    generator = PauliTerm("Z", 0, 1.0) * PauliTerm("X", 1, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([H(1), CNOT(0, 1), RZ(2.0, 1), CNOT(0, 1), H(1)])
    assert prog == result_prog
Пример #6
0
def trotterize(terms, trotter_order,
               trotter_steps) -> List[List[Callable[[float], Program]]]:
    """
    Trotterize the terms. If terms = [[t11, t12], [t21, t22]] the
    Trotterization approximates exp(t11+t12)*exp(t21+t22) (not quite correct
    but hopefully you get the idea).

    @author = Joel, Carl

    :param List[PauliSum] terms: PauliSums
    :param int trotter_order: trotter order in suzuki_trotter
    :param int trotter_steps: trotter steps in suzuki_trotter
    :return: list of lists of functions(theta) that returns Programs
    """
    # TODO: better docstring
    exp_maps = []
    old_len = None
    order_slices = None
    for term in terms:
        if len(term) != old_len:
            order_slices = suzuki_trotter_karlsson(len(term), trotter_order,
                                                   trotter_steps)
        tmp = []
        for coeff, operator in order_slices:
            tmp.append(exponential_map(1j * coeff * term[operator]))
        exp_maps.append(tmp)
    return exp_maps
Пример #7
0
def test_exponentiate_2():
    # testing general 2-circuit
    generator = PauliTerm("Z", 0, 1.0) * PauliTerm("Z", 1, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(CNOT(0, 1)).inst(RZ(2.0, 1)).inst(CNOT(0, 1))
    assert prog == result_prog
Пример #8
0
def test_exponentiate_3ns():
    # testing circuit for 3-terms non-sequential
    q = QubitPlaceholder.register(8)
    generator = (
        PauliTerm("Y", q[0], 1.0)
        * PauliTerm("I", q[1], 1.0)
        * PauliTerm("Y", q[2], 1.0)
        * PauliTerm("Y", q[3], 1.0)
    )
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(
        [
            RX(math.pi / 2.0, q[0]),
            RX(math.pi / 2.0, q[2]),
            RX(math.pi / 2.0, q[3]),
            CNOT(q[0], q[2]),
            CNOT(q[2], q[3]),
            RZ(2.0, q[3]),
            CNOT(q[2], q[3]),
            CNOT(q[0], q[2]),
            RX(-math.pi / 2.0, q[0]),
            RX(-math.pi / 2.0, q[2]),
            RX(-math.pi / 2.0, q[3]),
        ]
    )
    assert address_qubits(prog) == address_qubits(result_prog)
Пример #9
0
def test_exponentiate_bp0_ZY():
    # testing change of basis position 0
    generator = PauliTerm("Y", 0, 1.0) * PauliTerm("Z", 1, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([RX(math.pi / 2.0, 0), CNOT(0, 1), RZ(2.0, qubit=1),
                                  CNOT(0, 1), RX(-math.pi / 2, 0)])
    assert prog == result_prog
def test_exponentiate_1():
    # test rotation of single qubit
    q = QubitPlaceholder.register(8)
    generator = PauliTerm("Z", q[0], 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(RZ(2.0, q[0]))
    assert address_qubits(prog) == address_qubits(result_prog)
Пример #11
0
def test_ordered():
    term = sZ(3) * sZ(2) * sZ(1)
    prog = exponential_map(term)(0.5)
    assert prog.out() == "CNOT 3 2\n" \
                         "CNOT 2 1\n" \
                         "RZ(1.0) 1\n" \
                         "CNOT 2 1\n" \
                         "CNOT 3 2\n"
Пример #12
0
def test_exponentiate_3cob():
    # testing circuit for 3-terms with change of basis
    generator = PauliTerm("Z", 0, 1.0) * PauliTerm("Y", 1, 1.0) * PauliTerm("X", 2, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([RX(math.pi / 2.0, 1), H(2), CNOT(0, 1),
                                  CNOT(1, 2), RZ(2.0, 2), CNOT(1, 2),
                                  CNOT(0, 1), RX(-math.pi / 2.0, 1), H(2)])
    assert prog == result_prog
Пример #13
0
def test_exponentiate_identity():
    generator = PauliTerm("I", 1, 0.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program()
    assert prog == result_prog

    generator = PauliTerm("I", 1, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program()
    assert prog == result_prog

    generator = PauliTerm("I", 10, 0.08)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program()
    assert prog == result_prog
Пример #14
0
def test_exponentiate_identity():
    generator = PauliTerm("I", 1, 0.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([X(0), PHASE(-0.0, 0), X(0), PHASE(-0.0, 0)])
    assert prog == result_prog

    generator = PauliTerm("I", 1, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([X(0), PHASE(-1.0, 0), X(0), PHASE(-1.0, 0)])
    assert prog == result_prog

    generator = PauliTerm("I", 10, 0.08)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([X(0), PHASE(-0.08, 0), X(0), PHASE(-0.08, 0)])
    assert prog == result_prog
Пример #15
0
def test_exponentiate_identity():
    generator = PauliTerm("I", 1, 0.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([X(0), PHASE(0)(0), X(0), PHASE(0)(0)])
    compare_progs(prog, result_prog)

    generator = PauliTerm("I", 1, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([X(0), PHASE(-1.0)(0), X(0), PHASE(-1.0)(0)])
    compare_progs(prog, result_prog)

    generator = PauliTerm("I", 10, 0.08)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([X(0), PHASE(-0.08)(0), X(0), PHASE(-0.08)(0)])
    compare_progs(prog, result_prog)
def test_ordered():
    q = QubitPlaceholder.register(8)
    mapping = {x: i for i, x in enumerate(q)}
    term = sZ(q[3]) * sZ(q[2]) * sZ(q[1])
    prog = address_qubits(exponential_map(term)(0.5), mapping)
    assert prog.out() == "CNOT 3 2\n" \
                         "CNOT 2 1\n" \
                         "RZ(1.0) 1\n" \
                         "CNOT 2 1\n" \
                         "CNOT 3 2\n"
Пример #17
0
def test_exponentiate_bp1_XZ():
    # testing change of basis position 1
    q = QubitPlaceholder.register(8)
    generator = PauliTerm("Z", q[0], 1.0) * PauliTerm("X", q[1], 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(
        [H(q[1]), CNOT(q[0], q[1]), RZ(2.0, q[1]), CNOT(q[0], q[1]), H(q[1])]
    )
    assert address_qubits(prog) == address_qubits(result_prog)
Пример #18
0
def test_exponentiate_2():
    # testing general 2-circuit
    q = QubitPlaceholder.register(8)
    generator = PauliTerm("Z", q[0], 1.0) * PauliTerm("Z", q[1], 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(CNOT(q[0], q[1])).inst(RZ(2.0, q[1])).inst(CNOT(q[0], q[1]))

    mapping = get_default_qubit_mapping(prog)
    assert address_qubits(prog, mapping) == address_qubits(result_prog, mapping)
Пример #19
0
def test_exponentiate_identity():
    q = QubitPlaceholder.register(11)

    generator = PauliTerm("I", q[1], 0.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    assert len(prog) == 0

    generator = PauliTerm("I", q[1], 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([X(q[0]), PHASE(-1.0, q[0]), X(q[0]), PHASE(-1.0, q[0])])
    assert address_qubits(prog) == address_qubits(result_prog)

    generator = PauliTerm("I", q[10], 0.08)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([X(q[0]), PHASE(-0.08, q[0]), X(q[0]), PHASE(-0.08, q[0])])
    assert address_qubits(prog) == address_qubits(result_prog)
def test_exponentiate_paraprog():
    xterm = PauliTerm("X", 2) * PauliTerm("X", 1)
    paraprog = exponential_map(xterm)
    prog = paraprog(1)
    assert prog.out() == ("H 2\n"
                          "H 1\n"
                          "CNOT 2 1\n"
                          "RZ(2.0) 1\n"
                          "CNOT 2 1\n"
                          "H 2\n"
                          "H 1\n")
Пример #21
0
def exponentiate_driver(pauli_sum, param):
    """
    Calculates the exponential representation of the given QAOA driver term

    :param pauli_sum: PauliSum of the driver
    :param param: parameter set for the driver
    :return: pyQuil.Program for the exponential
    """
    prog = Program()
    for term in pauli_sum.terms:
        prog += exponential_map(term)(param)
    return prog
Пример #22
0
def test_exponentiate_3ns():
    # testing circuit for 3-terms non-sequential
    generator = (PauliTerm("Y", 0, 1.0) *
                 PauliTerm("I", 1, 1.0) *
                 PauliTerm("Y", 2, 1.0) *
                 PauliTerm("Y", 3, 1.0))
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([RX(math.pi / 2.0, 0), RX(math.pi / 2.0, 2),
                                  RX(math.pi / 2.0, 3), CNOT(0, 2),
                                  CNOT(2, 3), RZ(2.0, 3), CNOT(2, 3),
                                  CNOT(0, 2), RX(-math.pi / 2.0, 0),
                                  RX(-math.pi / 2.0, 2), RX(-math.pi / 2.0, 3)])
    assert prog == result_prog
Пример #23
0
def test_multiaddress():
    p = Program()
    q0, q1 = [QubitPlaceholder() for _ in range(2)]
    p += exponential_map(sZ(q0) * sZ(q1))(0.5)

    map1 = {q0: 0, q1: 1}
    map2 = {q0: 9, q1: 10}

    p1 = address_qubits(p, map1)

    with pytest.raises(RuntimeError):
        _ = p.out()  # make sure the original isn't affected

    assert p1.out() == "CNOT 0 1\nRZ(1.0) 1\nCNOT 0 1\n"

    p2 = address_qubits(p, map2)
    assert p1.out() == "CNOT 0 1\nRZ(1.0) 1\nCNOT 0 1\n"
    assert p2.out() == "CNOT 9 10\nRZ(1.0) 10\nCNOT 9 10\n"
def test_exponentiate_3cob():
    # testing circuit for 3-terms with change of basis
    q = QubitPlaceholder.register(8)
    generator = PauliTerm("Z", q[0], 1.0) * PauliTerm(
        "Y", q[1], 1.0) * PauliTerm("X", q[2], 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([
        RX(math.pi / 2.0, q[1]),
        H(q[2]),
        CNOT(q[0], q[1]),
        CNOT(q[1], q[2]),
        RZ(2.0, q[2]),
        CNOT(q[1], q[2]),
        CNOT(q[0], q[1]),
        RX(-math.pi / 2.0, q[1]),
        H(q[2])
    ])
    assert address_qubits(prog) == address_qubits(result_prog)
Пример #25
0
def exponentiate_commuting_pauli_sum_parametric(pauli_sum, term_dict, memref):
    """
    Returns a Program() (NOT A function) that maps all substituent PauliTerms and sums them into a program. NOTE: Use
    this function with care. Substituent PauliTerms in pauli_sum should commute for this to work correctly!

    :param List pauli_sum: list of Pauli terms to exponentiate.
    :param Dict term_dict: Dictionary containing as keys the Pauliterm frozensets, and as values the indices in
        packed_amplitudes (and in Memoreference pointer, same index!), corresponding to the same index in pauli_sum list
    :param MemoryReference memref: memory reference which should be inserted to generate the program

    :returns: A program that parametrizes the exponential.
    :rtype: Program()
    """

    prog = Program()
    for i, term in enumerate(pauli_sum):
        memrefindex = term_dict[term.operations_as_set()]
        prog += exponential_map(1j * term)(memref[memrefindex])

    return prog
Пример #26
0
def exponentiate_reward(pauli_sum, param):
    """
    Calculates the exponential representation of the given QAOA problem hamiltonian term. This is
    separated out from the driver as it allows for manual "compilation" by setting the edges and
    their order to reflect the topology of any hardware the code is supposed to run on.

    :param pauli_sum: PauliSum of the problem hamiltonian
    :param param: parameter set (angles) for the problem hamiltonian
    :param edge_ordering: List of pairs of connected qubits in the desired order, or None for
        the default order.
    :return: pyQuil.Program for the exponential
    """
    prog = Program()
    prog += Pragma('COMMUTING_BLOCKS')
    for term in pauli_sum.terms:
        prog += Pragma('BLOCK')
        prog += exponential_map(term)(param)
        prog += Pragma('END_BLOCK')
    prog += Pragma('END_COMMUTING_BLOCKS')
    return prog
Пример #27
0
def exponential_map_commuting_pauli_terms(terms: Union[List[PauliTerm],
                                                       PauliSum]):
    """
    Returns a function f(theta) which, given theta, returns the Program
    corresponding to exp(-1j sum_i theta[i]*term[i]) =
    prod_i exp(-1j*theta[i]*term[i]). Note that the equality only holds if
    the terms are commuting. This was inspired by pyquil.exponential_map
    and pyquil.exponentiate_commuting_pauli_sum.

    @author = Joel

    :param  terms:
        a list of pauli terms
    :return: a function that takes a vector parameter and returns a Program.
    """

    if isinstance(terms, PauliSum):
        terms = terms.terms
    exp_map = []
    for term in terms:
        exp_map.append(exponential_map(term))

    def wrap(theta):
        """
        Returns the ansatz Program.

        :param np.ndarray theta: parameters
        :return: the Program
        :rtype: pyquil.Program
        """
        prog = Program()
        for idx, angle in enumerate(theta):
            prog += exp_map[idx](angle)
        return prog

    return wrap
Пример #28
0
def test_exponentiate():
    # test rotation of single qubit
    generator = PauliTerm("Z", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(RZ(2.0)(0))
    compare_progs(prog, result_prog)

    # testing general 2-circuit
    generator = PauliTerm("Z", 1, 1.0) * PauliTerm("Z", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(CNOT(0, 1)).inst(RZ(2.0)(1)).inst(CNOT(0, 1))
    compare_progs(prog, result_prog)

    # testing change of basis position 0
    generator = PauliTerm("Z", 1, 1.0) * PauliTerm("X", 0, 1.0)
    param_prog = exponential_map(generator)
    prog = param_prog(1)
    result_prog = Program().inst(
        [H(0), CNOT(0, 1), RZ(2.0)(1),
         CNOT(0, 1), H(0)])
    compare_progs(prog, result_prog)

    # testing change of basis position 1
    generator = PauliTerm("X", 1, 1.0) * PauliTerm("Z", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(
        [H(1), CNOT(0, 1), RZ(2.0)(1),
         CNOT(0, 1), H(1)])
    compare_progs(prog, result_prog)

    # testing change of basis position 0
    generator = PauliTerm("Z", 1, 1.0) * PauliTerm("Y", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([
        RX(math.pi / 2.0)(0),
        CNOT(0, 1),
        RZ(2.0)(1),
        CNOT(0, 1),
        RX(-math.pi / 2)(0)
    ])
    compare_progs(prog, result_prog)

    # testing change of basis position 1
    generator = PauliTerm("Y", 1, 1.0) * PauliTerm("Z", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([
        RX(math.pi / 2.0)(1),
        CNOT(0, 1),
        RZ(2.0)(1),
        CNOT(0, 1),
        RX(-math.pi / 2.0)(1)
    ])
    compare_progs(prog, result_prog)

    # testing circuit for 3-terms with change of basis
    generator = PauliTerm("X", 2, 1.0) * PauliTerm("Y", 1, 1.0) * PauliTerm(
        "Z", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([
        RX(math.pi / 2.0)(1),
        H(2),
        CNOT(0, 1),
        CNOT(1, 2),
        RZ(2.0)(2),
        CNOT(1, 2),
        CNOT(0, 1),
        RX(-math.pi / 2.0)(1),
        H(2)
    ])
    compare_progs(prog, result_prog)

    # testing circuit for 3-terms non-sequential
    generator = PauliTerm("Y", 3, 1.0) * PauliTerm("Y", 2, 1.0) * PauliTerm(
        "I", 1, 1.0) * PauliTerm("Y", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([
        RX(math.pi / 2.0)(0),
        RX(math.pi / 2.0)(2),
        RX(math.pi / 2.0)(3),
        CNOT(0, 2),
        CNOT(2, 3),
        RZ(2.0)(3),
        CNOT(2, 3),
        CNOT(0, 2),
        RX(-math.pi / 2.0)(0),
        RX(-math.pi / 2.0)(2),
        RX(-math.pi / 2.0)(3)
    ])
    compare_progs(prog, result_prog)
Пример #29
0
qvm_server, quilc_server, fc = init_qvm_and_quilc("")
n_qubits = 2
# Hamiltonian
Hm = [PauliTerm("X", i, -1.0) for i in range(n_qubits)]
J = np.array([[0,1],[0,0]]) # weight matrix of the Ising model. Only the coefficient (0,1) is non-zero.

Hc = []
for i in range(n_qubits):
    for j in range(n_qubits):
        Hc.append(PauliTerm("Z", i, -J[i, j]) * PauliTerm("Z", j, 1.0))

# Iterate to compute exponential functions.
exp_Hm = []
exp_Hc = []
for term in Hm:
    exp_Hm.append(exponential_map(term))
for term in Hc:
    exp_Hc.append(exponential_map(term))

n_iter = 10 # number of iterations of the optimization procedure
p = 1
beta = np.random.uniform(0, np.pi*2, p)
gamma = np.random.uniform(0, np.pi*2, p)
initial_state = Program()
for i in range(n_qubits):
    initial_state += H(i)

def create_circuit(beta, gamma):
    circuit = Program()
    circuit += initial_state
    for i in range(p):
Пример #30
0
def test_exponentiate_paraprog():
    xterm = PauliTerm("X", 2) * PauliTerm("X", 1)
    paraprog = exponential_map(xterm)
    prog = paraprog(1)
    assert prog.out() == "H 1\nH 2\nCNOT 1 2\nRZ(2.0) 2\nCNOT 1 2\nH 1\nH 2\n"