def test_pauliop_inputs(): with pytest.raises(ValueError): PauliTerm("X", -2)
def test_trivial_pauli_str_to_pauli_term(): assert str_to_pauli_term('I') == PauliTerm('I', 0) assert str_to_pauli_term('I', set([10])) == PauliTerm('I', 0) return
def test_len(): term = PauliTerm("Z", 0, 1.0) * PauliTerm("Z", 1, 1.0) assert len(term) == 2
def test_simplify_term_single(): term = PauliTerm('Z', 0) * PauliTerm('I', 1) * PauliTerm('X', 2, 0.5j) * PauliTerm('Z', 0, 1.0) assert term.id() == 'X2' assert term.coefficient == 0.5j
def vqe_qc(vqe_strategy, vqe_qc_backend, vqe_parametricflag, sample_molecule): """ Initialize a VQE experiment with a custom hamiltonian given as constant input, given a QC-type backend (tomography is always set to True then) """ _vqe = None qc = None vqe_cq = None if vqe_strategy == "custom_program": if vqe_qc_backend == 'Aspen-qvm': qc = get_qc('Aspen-4-2Q-A-qvm') vqe_cq = [1, 2] elif vqe_qc_backend == 'Aspen-pyqvm': qc = get_qc('Aspen-4-2Q-A-pyqvm') vqe_cq = [1, 2] elif vqe_qc_backend == 'Nq-qvm': qc = get_qc('2q-qvm') elif vqe_qc_backend == 'Nq-pyqvm': qc = get_qc('2q-pyqvm') custom_ham = PauliSum([PauliTerm(*x) for x in HAMILTONIAN]) _vqe = VQEexperiment(hamiltonian=custom_ham, qc=qc, custom_qubits=vqe_cq, method='QC', strategy=vqe_strategy, parametric=True, tomography=True, shotN=NSHOTS_SMALL) elif vqe_strategy == "HF": if vqe_qc_backend == 'Aspen-qvm': qc = get_qc('Aspen-4-2Q-A-qvm') vqe_cq = [1, 2] elif vqe_qc_backend == 'Aspen-pyqvm': qc = get_qc('Aspen-4-2Q-A-pyqvm') vqe_cq = [1, 2] elif vqe_qc_backend == 'Nq-qvm': qc = get_qc('2q-qvm') elif vqe_qc_backend == 'Nq-pyqvm': qc = get_qc('2q-pyqvm') cwd = os.path.abspath(os.path.dirname(__file__)) fname = os.path.join(cwd, "resources", "H.hdf5") molecule = MolecularData(filename=fname) _vqe = VQEexperiment(molecule=molecule, qc=qc, custom_qubits=vqe_cq, method='QC', strategy=vqe_strategy, parametric=vqe_parametricflag, tomography=True, shotN=NSHOTS_SMALL) elif vqe_strategy == "UCCSD": if vqe_qc_backend == 'Aspen-qvm': qc = get_qc('Aspen-4-4Q-A-qvm') vqe_cq = [7, 0, 1, 2] elif vqe_qc_backend == 'Aspen-pyqvm': qc = get_qc('Aspen-4-4Q-A-pyqvm') vqe_cq = [7, 0, 1, 2] elif vqe_qc_backend == 'Nq-qvm': qc = get_qc('4q-qvm') elif vqe_qc_backend == 'Nq-pyqvm': qc = get_qc('4q-pyqvm') _vqe = VQEexperiment(molecule=sample_molecule, qc=qc, custom_qubits=vqe_cq, method='QC', strategy=vqe_strategy, parametric=vqe_parametricflag, tomography=True, shotN=NSHOTS_SMALL) return _vqe
def test_commuting_sets(): term1 = PauliTerm("X", 0) * PauliTerm("X", 1) term2 = PauliTerm("Y", 0) * PauliTerm("Y", 1) term3 = PauliTerm("Y", 0) * PauliTerm("Z", 2) pauli_sum = term1 + term2 + term3 commuting_sets(pauli_sum, 3)
def test_term_with_coeff(): assert PauliTerm('X', 0, 1.j) == term_with_coeff(sX(0), 1.j) assert PauliTerm('X', 0, -1.0) == term_with_coeff(sX(0), -1) with pytest.raises(ValueError): term_with_coeff(sI(0), None)
def _gen_PauliTerm(term, coeff=1.): pauli_term = ID() * coeff for q, p in term: pauli_term *= PauliTerm(p, q) return pauli_term
def test_exponentiate_prog(): ham = PauliTerm("Z", 0) result_prog = Program(RZ(2.0, 0)) prog = exponentiate(ham) compare_progs(result_prog, prog)
def maxcut_qaoa(graph, steps=1, rand_seed=None, connection=None, samples=None, initial_beta=None, initial_gamma=None, minimizer_kwargs=None, vqe_option=None): """ Max cut set up method :param graph: Graph definition. Either networkx or list of tuples :param steps: (Optional. Default=1) Trotterization order for the QAOA algorithm. :param rand_seed: (Optional. Default=None) random seed when beta and gamma angles are not provided. :param connection: (Optional) connection to the QVM. Default is None. :param samples: (Optional. Default=None) VQE option. Number of samples (circuit preparation and measurement) to use in operator averaging. :param initial_beta: (Optional. Default=None) Initial guess for beta parameters. :param initial_gamma: (Optional. Default=None) Initial guess for gamma parameters. :param minimizer_kwargs: (Optional. Default=None). Minimizer optional arguments. If None set to {'method': 'Nelder-Mead', 'options': {'ftol': 1.0e-2, 'xtol': 1.0e-2, 'disp': False} :param vqe_option: (Optional. Default=None). VQE optional arguments. If None set to vqe_option = {'disp': print_fun, 'return_all': True, 'samples': samples} """ if not isinstance(graph, nx.Graph) and isinstance(graph, list): maxcut_graph = nx.Graph() for edge in graph: maxcut_graph.add_edge(*edge) graph = maxcut_graph.copy() cost_operators = [] driver_operators = [] for i, j in graph.edges(): cost_operators.append(PauliTerm("Z", i, 0.5)*PauliTerm("Z", j) + PauliTerm("I", 0, -0.5)) for i in graph.nodes(): driver_operators.append(PauliSum([PauliTerm("X", i, -1.0)])) if connection is None: connection = CXN if minimizer_kwargs is None: minimizer_kwargs = {'method': 'Nelder-Mead', 'options': {'ftol': 1.0e-2, 'xtol': 1.0e-2, 'disp': False}} if vqe_option is None: vqe_option = {'disp': print_fun, 'return_all': True, 'samples': samples} qaoa_inst = QAOA(connection, len(graph.nodes()), steps=steps, cost_ham=cost_operators, ref_hamiltonian=driver_operators, store_basis=True, rand_seed=rand_seed, init_betas=initial_beta, init_gammas=initial_gamma, minimizer=minimize, minimizer_kwargs=minimizer_kwargs, vqe_options=vqe_option) return qaoa_inst
import numpy as np import pytest from scipy.optimize import minimize from pyquil.paulis import PauliSum, PauliTerm from pyquil.api import WavefunctionSimulator, local_qvm, get_qc from pyquil.quil import Program from pyquil.gates import RX, CNOT from entropica_qaoa.vqe.optimizer import scipy_optimizer from entropica_qaoa.vqe.cost_function import (PrepareAndMeasureOnWFSim, PrepareAndMeasureOnQVM) # gonna need this program and hamiltonian for both tests. So define them globally # hamiltonian = PauliSum.from_compact_str("(-1.0)*Z0*Z1 + 0.8*Z0 + (-0.5)*Z1") term1 = PauliTerm("Z", 0, -1) term1 *= PauliTerm("Z", 1) term2 = PauliTerm("Z", 0, 0.8) term3 = PauliTerm("Z", 1, -0.5) hamiltonian = PauliSum([term1, term2, term3]) prepare_ansatz = Program() params = prepare_ansatz.declare("params", memory_type="REAL", memory_size=4) prepare_ansatz.inst(RX(params[0], 0)) prepare_ansatz.inst(RX(params[1], 1)) prepare_ansatz.inst(CNOT(0, 1)) prepare_ansatz.inst(RX(params[2], 0)) prepare_ansatz.inst(RX(params[3], 1)) p0 = [0, 0, 0, 0]
def test_simplify_term_single(): term = PauliTerm("Z", 0) * PauliTerm("I", 1) * PauliTerm( "X", 2, 0.5j) * PauliTerm("Z", 0, 1.0) assert term.id() == "X2" assert term.coefficient == 0.5j
def test_numpy_integer_types(): (idx_np, ) = np.arange(1, dtype=np.int64) assert isinstance(idx_np, np.int64) # on python 3 this fails unless explicitly allowing for numpy integer types PauliTerm("X", idx_np)
def test_trotterize(): term_one = PauliTerm("X", 0, 1.0) term_two = PauliTerm("Z", 0, 1.0) with pytest.raises(ValueError): trotterize(term_one, term_two, trotter_order=0) with pytest.raises(ValueError): trotterize(term_one, term_two, trotter_order=5) prog = trotterize(term_one, term_one) result_prog = Program().inst( [H(0), RZ(2.0, 0), H(0), H(0), RZ(2.0, 0), H(0)]) assert prog == result_prog # trotter_order 1 steps 1 prog = trotterize(term_one, term_two, trotter_steps=1) result_prog = Program().inst([H(0), RZ(2.0, 0), H(0), RZ(2.0, 0)]) assert prog == result_prog # trotter_order 1 steps 2 prog = trotterize(term_one, term_two, trotter_steps=2) result_prog = Program().inst([ H(0), RZ(1.0, 0), H(0), RZ(1.0, 0), H(0), RZ(1.0, 0), H(0), RZ(1.0, 0) ]) assert prog == result_prog # trotter_order 2 steps 1 prog = trotterize(term_one, term_two, trotter_order=2) result_prog = Program().inst( [H(0), RZ(1.0, 0), H(0), RZ(2.0, 0), H(0), RZ(1.0, 0), H(0)]) assert prog == result_prog # trotter_order 2 steps 2 prog = trotterize(term_one, term_two, trotter_order=2, trotter_steps=2) result_prog = Program().inst([ H(0), RZ(0.5, 0), H(0), RZ(1.0, 0), H(0), RZ(0.5, 0), H(0), H(0), RZ(0.5, 0), H(0), RZ(1.0, 0), H(0), RZ(0.5, 0), H(0), ]) assert prog == result_prog # trotter_order 3 steps 1 prog = trotterize(term_one, term_two, trotter_order=3, trotter_steps=1) result_prog = Program().inst([ H(0), RZ(14.0 / 24, 0), H(0), RZ(4.0 / 3.0, 0), H(0), RZ(1.5, 0), H(0), RZ(-4.0 / 3.0, 0), H(0), RZ(-2.0 / 24, 0), H(0), RZ(2.0, 0), ]) assert prog == result_prog
def test_exponentiate_prog(): ham = PauliTerm("Z", 0) result_prog = Program(RZ(2.0, 0)) prog = exponentiate(ham) assert prog == result_prog
def create_operators_from_clauses(self): """ Creates cost hamiltonian from clauses. For details see section IIC from the article. """ operators = [] mapping = {} variable_counter = 0 for clause in self.clauses: if clause == 0: continue variables = list(clause.free_symbols) for variable in variables: if str(variable) not in mapping.keys(): mapping[str(variable)] = variable_counter variable_counter += 1 pauli_terms = [] quadratic_pauli_terms = [] if type(clause) == Add: clause_terms = clause.args elif type(clause) == Mul: clause_terms = [clause] for single_term in clause_terms: if len(single_term.free_symbols) == 0: pauli_terms.append(PauliTerm("I", 0, int(single_term))) elif len(single_term.free_symbols) == 1: multiplier = 1 if type(single_term) == Mul: multiplier = int(single_term.args[0]) symbol = list(single_term.free_symbols)[0] symbol_id = mapping[str(symbol)] pauli_terms.append( PauliTerm("I", symbol_id, 1 / 2 * multiplier)) pauli_terms.append( PauliTerm("Z", symbol_id, -1 / 2 * multiplier)) elif len(single_term.free_symbols) == 2 and type( single_term) == Mul: multiplier = 1 if isinstance(single_term.args[0], Number): multiplier = int(single_term.args[0]) symbol_1 = list(single_term.free_symbols)[0] symbol_2 = list(single_term.free_symbols)[1] symbol_id_1 = mapping[str(symbol_1)] symbol_id_2 = mapping[str(symbol_2)] pauli_term_1 = PauliTerm( "I", symbol_id_1, 1 / 2 * multiplier) - PauliTerm( "Z", symbol_id_1, 1 / 2 * multiplier) pauli_term_2 = PauliTerm("I", symbol_id_2, 1 / 2) - PauliTerm( "Z", symbol_id_2, 1 / 2) quadratic_pauli_terms.append(pauli_term_1 * pauli_term_2) else: Exception( "Terms of orders higher than quadratic are not handled." ) clause_operator = PauliSum(pauli_terms) for quadratic_term in quadratic_pauli_terms: clause_operator += quadratic_term squared_clause_operator = clause_operator**2 if self.verbose: print("C:", clause_operator) print("C**2:", squared_clause_operator) operators.append(squared_clause_operator) return operators, mapping
def test_init_pauli_term(): with pytest.raises(ValueError): PauliTerm('X', 0, 'a')
def ising(h, J, num_steps=0, verbose=True, rand_seed=None, connection=None, samples=None, initial_beta=None, initial_gamma=None, minimizer_kwargs=None, vqe_option=None): """ Ising set up method :param h: External magnectic term of the Ising problem. List. :param J: Interaction term of the Ising problem. Dictionary. :param num_steps: (Optional.Default=2 * len(h)) Trotterization order for the QAOA algorithm. :param verbose: (Optional.Default=True) Verbosity of the code. :param rand_seed: (Optional. Default=None) random seed when beta and gamma angles are not provided. :param connection: (Optional) connection to the QVM. Default is None. :param samples: (Optional. Default=None) VQE option. Number of samples (circuit preparation and measurement) to use in operator averaging. :param initial_beta: (Optional. Default=None) Initial guess for beta parameters. :param initial_gamma: (Optional. Default=None) Initial guess for gamma parameters. :param minimizer_kwargs: (Optional. Default=None). Minimizer optional arguments. If None set to {'method': 'Nelder-Mead', 'options': {'ftol': 1.0e-2, 'xtol': 1.0e-2, 'disp': False} :param vqe_option: (Optional. Default=None). VQE optional arguments. If None set to vqe_option = {'disp': print_fun, 'return_all': True, 'samples': samples} :return: Most frequent Ising string, Energy of the Ising string, Circuit used to obtain result. :rtype: List, Integer or float, 'pyquil.quil.Program'. """ if num_steps == 0: num_steps = 2 * len(h) n_nodes = len(h) cost_operators = [] driver_operators = [] for i, j in J.keys(): cost_operators.append( PauliSum([PauliTerm("Z", i, J[(i, j)]) * PauliTerm("Z", j)])) for i in range(n_nodes): cost_operators.append(PauliSum([PauliTerm("Z", i, h[i])])) for i in range(n_nodes): driver_operators.append(PauliSum([PauliTerm("X", i, -1.0)])) if connection is None: connection = CXN if minimizer_kwargs is None: minimizer_kwargs = { 'method': 'Nelder-Mead', 'options': { 'ftol': 1.0e-2, 'xtol': 1.0e-2, 'disp': False } } if vqe_option is None: vqe_option = { 'disp': print_fun, 'return_all': True, 'samples': samples } if not verbose: vqe_option['disp'] = None qaoa_inst = QAOA(connection, n_nodes, steps=num_steps, cost_ham=cost_operators, ref_hamiltonian=driver_operators, store_basis=True, rand_seed=rand_seed, init_betas=initial_beta, init_gammas=initial_gamma, minimizer=minimize, minimizer_kwargs=minimizer_kwargs, vqe_options=vqe_option) betas, gammas = qaoa_inst.get_angles() most_freq_string, sampling_results = qaoa_inst.get_string(betas, gammas) most_freq_string_ising = [ising_trans(it) for it in most_freq_string] energy_ising = energy_value(h, J, most_freq_string_ising) param_prog = qaoa_inst.get_parameterized_program() circuit = param_prog(np.hstack((betas, gammas))) return most_freq_string_ising, energy_ising, circuit
def test_get_qubits(): term = PauliTerm('Z', 0) * PauliTerm('X', 1) assert term.get_qubits() == [0, 1] sum_term = PauliTerm('X', 0, 0.5) + 0.5j * PauliTerm('Y', 10) * PauliTerm('Y', 0, 0.5j) assert sum_term.get_qubits() == [0, 10]
def test_enumerate(): term = PauliTerm("Z", 0, 1.0) * PauliTerm("Z", 1, 1.0) * PauliTerm("X", 5, 5) position_op_pairs = [(0, "Z"), (1, "Z"), (5, "X")] for key, val in term: assert (key, val) in position_op_pairs
def test_simplify_term_id_1(): term = PauliTerm('I', 0, 0.5) assert term.id() == '' assert term.coefficient == 0.5
def test_ids(): term_1 = PauliTerm("Z", 0, 1.0) * PauliTerm("Z", 1, 1.0) * PauliTerm("X", 5, 5) term_2 = PauliTerm("X", 5, 5) * PauliTerm("Z", 0, 1.0) * PauliTerm("Z", 1, 1.0) assert term_1.id() == term_2.id()
def test_simplify_term_multindex(): term = PauliTerm('X', 0, coefficient=-0.5) * PauliTerm('Z', 0, coefficient=-1.0) \ * PauliTerm('X', 2, 0.5) assert term.id() == 'Y0X2' assert term.coefficient == -0.25j
def test_pauliop_inputs(): with pytest.raises(AssertionError): PauliTerm('X', -2)
def test_1q_pauli_str_to_pauli_term(): for pauli_str in ['X', 'Y', 'Z']: assert str_to_pauli_term(pauli_str) == PauliTerm(pauli_str, 0) assert str_to_pauli_term(pauli_str, set([10])) == PauliTerm(pauli_str, 10) return
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)) assert 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)) assert 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)]) assert 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)]) assert 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)]) assert 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)]) assert 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)]) assert 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)]) assert prog == result_prog
def test_conjugate_request(server, mock_rb_cxn): response = mock_rb_cxn.apply_clifford_to_pauli(Program("H 0"), PauliTerm("X", 0, 1.0)) assert isinstance(response, PauliTerm) assert str(response) == "(1+0j)*Z0"
def test_exponentiate_commuting_pauli_sum(): pauli_sum = PauliSum([PauliTerm('Z', 0, 0.5), PauliTerm('Z', 1, 0.5)]) prog = Program().inst(RZ(1.)(0)).inst(RZ(1.)(1)) result_prog = exponentiate_commuting_pauli_sum(pauli_sum)(1.) assert prog == result_prog
def test_sum_len(): pauli_sum = PauliTerm("Z", 0, 1.0) + PauliTerm("Z", 1, 1.0) assert len(pauli_sum) == 2
def test_operations_as_set(): term_1 = PauliTerm("Z", 0, 1.0) * PauliTerm("Z", 1, 1.0) * PauliTerm( "X", 5, 5) term_2 = PauliTerm("X", 5, 5) * PauliTerm("Z", 0, 1.0) * PauliTerm( "Z", 1, 1.0) assert term_1.operations_as_set() == term_2.operations_as_set()