def test_ref_program_pass(): ref_prog = Program().inst([X(0), Y(1), Z(2)]) fakeQVM = Mock(spec=qvm_module.SyncConnection()) inst = QAOA(fakeQVM, 2, driver_ref=ref_prog) param_prog = inst.get_parameterized_program() test_prog = param_prog([0, 0]) compare_progs(ref_prog, test_prog)
def test_pass_hamiltonians(): ref_ham = [ PauliSum([PauliTerm("X", 0, -1.0)]), PauliSum([PauliTerm("X", 1, -1.0)]) ] cost_ham = [ PauliTerm("I", 0, 0.5) + PauliTerm("Z", 0, -0.5) * PauliTerm("Z", 1, 1.0) ] fakeQVM = Mock() inst = QAOA(fakeQVM, 2, steps=1, cost_ham=cost_ham, ref_hamiltonian=ref_ham) c = inst.cost_ham r = inst.ref_ham assert isinstance(c, list) assert isinstance(r, list) assert isinstance(c[0], PauliSum) assert isinstance(r[0], PauliSum) assert len(c) == 1 assert len(r) == 2 with pytest.raises(TypeError): QAOA(fakeQVM, 2, steps=1, cost_ham=PauliTerm("X", 0, 1.0), ref_hamiltonian=ref_ham, rand_seed=42)
def __init__(self, distance_matrix, steps=2, ftol=1.0e-3, xtol=1.0e-3, initial_state="all", starting_node=0): self.distance_matrix = distance_matrix self.starting_node = starting_node # Since we fixed the starting city, the effective number of nodes is smaller by 1 self.reduced_number_of_nodes = len(self.distance_matrix) - 1 self.qvm = api.QVMConnection() self.steps = steps self.ftol = ftol self.xtol = xtol self.betas = None self.gammas = None self.qaoa_inst = None self.number_of_qubits = self.get_number_of_qubits() self.solution = None self.distribution = None cost_operators = self.create_phase_separator() driver_operators = self.create_mixer() initial_state_program = self.create_initial_state_program(initial_state) minimizer_kwargs = {'method': 'Nelder-Mead', 'options': {'ftol': self.ftol, 'xtol': self.xtol, 'disp': False}} vqe_option = {'disp': print_fun, 'return_all': True, 'samples': None} self.qaoa_inst = QAOA(self.qvm, self.number_of_qubits, steps=self.steps, cost_ham=cost_operators, ref_hamiltonian=driver_operators, driver_ref=initial_state_program, store_basis=True, minimizer=scipy.optimize.minimize, minimizer_kwargs=minimizer_kwargs, vqe_options=vqe_option)
def test_probabilities(): p = 1 n_qubits = 2 # known set of angles for barbell angles = [1.96348709, 4.71241069] wf = np.array([ -1.17642098e-05 - 1j * 7.67538040e-06, -7.67563580e-06 - 1j * 7.07106781e-01, -7.67563580e-06 - 1j * 7.07106781e-01, -1.17642098e-05 - 1j * 7.67538040e-06 ]) with patch("grove.pyqaoa.qaoa.WavefunctionSimulator") as mock_wfs: fake_wfs = Mock(WavefunctionSimulator) fake_wfs.wavefunction.return_value = Wavefunction(wf) mock_wfs.return_value = fake_wfs fake_qc = Mock(QuantumComputer) inst = QAOA(qc=fake_qc, qubits=list(range(n_qubits)), steps=p, rand_seed=42) probs = inst.probabilities(angles) assert isinstance(probs, np.ndarray) prob_true = np.zeros((inst.nstates, 1)) prob_true[1] = 0.5 prob_true[2] = 0.5 assert np.isclose(probs, prob_true).all()
def __init__(self, nodes_array, steps=3, ftol=1.0e-4, xtol=1.0e-4, all_ones_coefficient=-2): self.nodes_array = nodes_array self.qvm = api.QVMConnection() self.steps = steps self.ftol = ftol self.xtol = xtol self.betas = None self.gammas = None self.qaoa_inst = None self.most_freq_string = None self.number_of_qubits = self.get_number_of_qubits() self.all_ones_coefficient = all_ones_coefficient cost_operators = self.create_cost_operators() driver_operators = self.create_driver_operators() minimizer_kwargs = {'method': 'Nelder-Mead', 'options': {'ftol': self.ftol, 'xtol': self.xtol, 'disp': False}} vqe_option = {'disp': print_fun, 'return_all': True, 'samples': None} self.qaoa_inst = QAOA(self.qvm, list(range(self.number_of_qubits)), steps=self.steps, cost_ham=cost_operators, ref_hamiltonian=driver_operators, store_basis=True, minimizer=scipy.optimize.minimize, minimizer_kwargs=minimizer_kwargs, vqe_options=vqe_option)
def __init__(self, distance_matrix, steps=1, ftol=1.0e-2, xtol=1.0e-2, use_constraints=False): self.distance_matrix = distance_matrix self.qvm = api.QVMConnection() self.steps = steps self.ftol = ftol self.xtol = xtol self.betas = None self.gammas = None self.qaoa_inst = None self.number_of_qubits = self.get_number_of_qubits() self.solution = None self.naive_distribution = None self.most_frequent_string = None self.sampling_results = None self.use_constraints = use_constraints cost_operators = self.create_cost_operators() driver_operators = self.create_driver_operators() minimizer_kwargs = {'method': 'Nelder-Mead', 'options': {'ftol': self.ftol, 'xtol': self.xtol, 'disp': False}} vqe_option = {'disp': print_fun, 'return_all': True, 'samples': None} qubits = list(range(self.number_of_qubits)) self.qaoa_inst = QAOA(self.qvm, qubits, steps=self.steps, cost_ham=cost_operators, ref_ham=driver_operators, store_basis=True, minimizer=scipy.optimize.minimize, minimizer_kwargs=minimizer_kwargs, vqe_options=vqe_option)
def test_ref_program_pass(): ref_prog = Program().inst([X(0), Y(1), Z(2)]) fakeQVM = Mock(spec=qvm_module.QVMConnection()) inst = QAOA(fakeQVM, range(2), driver_ref=ref_prog) param_prog = inst.get_parameterized_program() test_prog = param_prog([0, 0]) assert ref_prog == test_prog
def test_ref_program_pass(): ref_prog = Program().inst([X(0), Y(1), Z(2)]) fakeQVM = Mock(QuantumComputer) inst = QAOA(fakeQVM, list(range(2)), driver_ref=ref_prog) param_prog = inst.get_parameterized_program() test_prog = param_prog([0, 0]) assert ref_prog == test_prog
def test_get_string(): qvm = qvm_module.SyncConnection() qaoa = QAOA(qvm, n_qubits=1) prog = Program() prog.inst(X(0)) qaoa.get_parameterized_program = lambda: lambda angles: prog samples = 10 bitstring, freq = qaoa.get_string(betas=None, gammas=None, samples=samples) assert len(freq) <= samples assert bitstring[0] == 1
def test_get_string(): with patch('pyquil.api.QVMConnection') as cxn: cxn.run_and_measure.return_value = [[1] * 10] qaoa = QAOA(cxn, n_qubits=1) prog = Program() prog.inst(X(0)) qaoa.get_parameterized_program = lambda: lambda angles: prog samples = 10 bitstring, freq = qaoa.get_string(betas=None, gammas=None, samples=samples) assert len(freq) <= samples assert bitstring[0] == 1
def get_optimized_circuit(init_state): qaoa = QAOA(qvm, qubits=range(n_system), steps=p, ref_ham=Hm, cost_ham=Hc, driver_ref=init_state, store_basis=True, minimizer=fmin_bfgs, minimizer_kwargs={'maxiter': 50}) beta, gamma = qaoa.get_angles() return qaoa.get_parameterized_program()(np.hstack((beta, gamma)))
def solve_tsp(weights, connection=None, steps=1, ftol=1.0e-4, xtol=1.0e-4, samples=1000): """ Method for solving travelling salesman problem. :param weights: Weight matrix. weights[i, j] = cost to traverse edge from city i to j. If weights[i, j] = 0, then no edge exists between cities i and j. :param connection: (Optional) connection to the QVM. Default is None. :param steps: (Optional. Default=1) Trotterization order for the QAOA algorithm. :param ftol: (Optional. Default=1.0e-4) ftol parameter for the Nelder-Mead optimizer :param xtol: (Optional. Default=1.0e-4) xtol parameter for the Nelder-Mead optimizer :param samples: (Optional. Default=1000) number of bit string samples to use. """ if connection is None: connection = api.QVMConnection() number_of_cities = weights.shape[0] list_of_qubits = list(range(number_of_cities**2)) number_of_qubits = len(list_of_qubits) cost_operators = create_cost_hamiltonian(weights) driver_operators = create_mixer_operators(number_of_cities) initial_state_program = create_initial_state_program(number_of_cities) minimizer_kwargs = { 'method': 'Nelder-Mead', 'options': { 'ftol': ftol, 'xtol': xtol, 'disp': False } } vqe_option = {'disp': print_fun, 'return_all': True, 'samples': None} qaoa_inst = QAOA(connection, list_of_qubits, steps=steps, cost_ham=cost_operators, ref_ham=driver_operators, driver_ref=initial_state_program, store_basis=True, minimizer=scipy.optimize.minimize, minimizer_kwargs=minimizer_kwargs, vqe_options=vqe_option) betas, gammas = qaoa_inst.get_angles() most_frequent_string, _ = qaoa_inst.get_string(betas, gammas, samples=samples) solution = binary_state_to_points_order(most_frequent_string) return solution
def test_get_string(): with patch('pyquil.api.QuantumComputer') as qc: qc.run.return_value = [[1] * 10] qaoa = QAOA(qc, [0]) prog = Program() prog.inst(X(0)) qaoa.get_parameterized_program = lambda: lambda angles: prog samples = 10 bitstring, freq = qaoa.get_string(betas=None, gammas=None, samples=samples) assert len(freq) <= samples assert bitstring[0] == 1
def test_get_angles(): p = 2 n_qubits = 2 fakeQVM = Mock() with patch('grove.pyqaoa.qaoa.VQE', spec=VQE) as mockVQEClass: inst = mockVQEClass.return_value result = Mock() result.x = [1.2, 2.1, 3.4, 4.3] inst.vqe_run.return_value = result MCinst = QAOA(fakeQVM, n_qubits, steps=p, cost_ham=[PauliSum([PauliTerm("X", 0)])]) betas, gammas = MCinst.get_angles() assert betas == [1.2, 2.1] assert gammas == [3.4, 4.3]
def __init__(self, full_nodes_array, steps=3, ftol=1.0e-4, xtol=1.0e-4, initial_state="all", starting_node=0): reduced_nodes_array, costs_to_starting_node = self.reduce_nodes_array( full_nodes_array, starting_node) self.nodes_array = reduced_nodes_array self.starting_node = starting_node self.full_nodes_array = full_nodes_array self.costs_to_starting_node = costs_to_starting_node self.qvm = api.QVMConnection() self.steps = steps self.ftol = ftol self.xtol = xtol self.betas = None self.gammas = None self.qaoa_inst = None self.most_freq_string = None self.number_of_qubits = self.get_number_of_qubits() self.initial_state = initial_state cost_operators = self.create_phase_separator() driver_operators = self.create_mixer() initial_state_program = self.create_initial_state_program() minimizer_kwargs = { 'method': 'Nelder-Mead', 'options': { 'ftol': self.ftol, 'xtol': self.xtol, 'disp': False } } vqe_option = {'disp': print_fun, 'return_all': True, 'samples': None} self.qaoa_inst = QAOA(self.qvm, list(range(self.number_of_qubits)), steps=self.steps, cost_ham=cost_operators, ref_hamiltonian=driver_operators, driver_ref=initial_state_program, store_basis=True, minimizer=scipy.optimize.minimize, minimizer_kwargs=minimizer_kwargs, vqe_options=vqe_option)
def numpart_qaoa(asset_list, A=1.0, minimizer_kwargs=None, steps=1): """ generate number partition driver and cost functions :param asset_list: list to binary parition :param A: (float) optional constant for level separation. Default=1. :param minimizer_kwargs: Arguments for the QAOA minimizer :param steps: (int) number of steps approximating the solution. """ cost_operators = [] ref_operators = [] for ii in range(len(asset_list)): for jj in range(ii + 1, len(asset_list)): cost_operators.append(PauliSum([PauliTerm("Z", ii, 2*asset_list[ii]) * PauliTerm("Z", jj, A*asset_list[jj])])) ref_operators.append(PauliSum([PauliTerm("X", ii, -1.0)])) cost_operators.append(PauliSum([PauliTerm("I", 0, len(asset_list))])) if minimizer_kwargs is None: minimizer_kwargs = {'method': 'Nelder-Mead', 'options': {'ftol': 1.0e-2, 'xtol': 1.0e-2, 'disp': True}} qaoa_inst = QAOA(CXN, len(asset_list), steps=steps, cost_ham=cost_operators, ref_ham=ref_operators, store_basis=True, minimizer=minimize, minimizer_kwargs=minimizer_kwargs, vqe_options={'disp': True}) return qaoa_inst
def maxcut_qaoa(graph, steps=1, rand_seed=None): """ Max cut set up method """ 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)])) qaoa_inst = QAOA(CXN, len(graph.nodes()), steps=steps, cost_ham=cost_operators, ref_hamiltonian=driver_operators, store_basis=True, rand_seed=rand_seed, minimizer=minimize, minimizer_kwargs={'method': 'Nelder-Mead', 'options': {'ftol': 1.0e-2, 'xtol': 1.0e-2, 'disp': False}}, vqe_options={'disp': print_fun, 'return_all': True}) return qaoa_inst
def construct_QAOA(G,p, minimizer_kwargs= {'method': 'BFGS', 'options': {'ftol': 1.0e-2, 'xtol': 1.0e-2,'disp': True}}, init_betas=None, init_gammas=None, vqe_options = {'disp': print, 'return_all': True}): # setting up connection with the QVM qvm_connection = api.QVMConnection() # labelling qubits according to graph qubits = [int(n) for n in list(G.nodes)] # turning unweighted graphs into weighted graph with weight wij = 1 for (u, v) in G.edges(): if G.edges[u,v] == {}: G.edges[u,v]['weight'] = 1 # constructing cost and mixer hamiltonian elements in list # N.B. This algorithm only works if all the terms in the cost Hamiltonian commute with each other. Hc = cost(G) Hb = mixer(G) return QAOA(qvm_connection, qubits, steps=p, cost_ham = Hc, ref_ham= Hb, minimizer_kwargs=minimizer_kwargs, vqe_options = vqe_options)
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): 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() nx.draw(graph) cost_operators = [] driver_operators = [] #Creates cost hamiltonian from weights + nodes, adds accountability for weights from original rigetti QAOA code for i, j in graph.edges(): weight = graph.get_edge_data(i, j)['weight'] / largest_weight cost_operators.append( PauliTerm("Z", i, weight) * PauliTerm("Z", j) + PauliTerm("I", 0, -weight)) #creates driver hamiltonian for i in graph.nodes(): driver_operators.append(PauliSum([PauliTerm("X", i, -1.0)])) if connection is None: connection = get_qc(f"{len(graph.nodes)}q-qvm") 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, 'return_all': True, 'samples': samples} qaoa_inst = QAOA(connection, list(graph.nodes()), steps=steps, cost_ham=cost_operators, ref_ham=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
def maxcut_qaoa_weighted(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() maxcut_graph.add_weighted_edges_from(graph) # for edge in graph: # maxcut_graph.add_edge(*edge) graph = maxcut_graph.copy() cost_operators = [] driver_operators = [] for i, j, w in graph.edges(data=True): print(i,j,w) value=w["weight"] cost_operators.append(value*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 = get_qc(f"{len(graph.nodes)}q-qvm") 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, 'return_all': True, 'samples': samples} qaoa_inst = QAOA(connection, list(graph.nodes()), steps=steps, cost_ham=cost_operators, ref_ham=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
def solve_tsp(nodes_array, connection=None, steps=3, ftol=1.0e-4, xtol=1.0e-4): """ Method for solving travelling salesman problem. :param nodes_array: An array of points, which represent coordinates of the cities. :param connection: (Optional) connection to the QVM. Default is None. :param steps: (Optional. Default=1) Trotterization order for the QAOA algorithm. :param ftol: (Optional. Default=1.0e-4) ftol parameter for the Nelder-Mead optimizer :param xtol: (Optional. Default=1.0e-4) xtol parameter for the Nelder-Mead optimizer """ if connection is None: connection = api.QVMConnection() list_of_qubits = list(range(len(nodes_array)**2)) number_of_qubits = len(list_of_qubits) cost_operators = create_cost_hamiltonian(nodes_array) driver_operators = create_mixer_operators(len(nodes_array)) initial_state_program = create_initial_state_program(len(nodes_array)) minimizer_kwargs = { 'method': 'Nelder-Mead', 'options': { 'ftol': ftol, 'xtol': xtol, 'disp': False } } vqe_option = {'disp': print_fun, 'return_all': True, 'samples': None} qaoa_inst = QAOA(connection, number_of_qubits, steps=steps, cost_ham=cost_operators, ref_hamiltonian=driver_operators, driver_ref=initial_state_program, store_basis=True, minimizer=scipy.optimize.minimize, minimizer_kwargs=minimizer_kwargs, vqe_options=vqe_option) betas, gammas = qaoa_inst.get_angles() most_frequent_string, _ = qaoa_inst.get_string(betas, gammas, samples=1000) solution = binary_state_to_points_order(most_frequent_string) return solution
def test_probabilities(): p = 1 n_qubits = 2 # known set of angles for barbell angles = [1.96348709, 4.71241069] wf = np.array([-1.17642098e-05 - 1j*7.67538040e-06, -7.67563580e-06 - 1j*7.07106781e-01, -7.67563580e-06 - 1j*7.07106781e-01, -1.17642098e-05 - 1j*7.67538040e-06]) fakeQVM = Mock(spec=qvm_module.SyncConnection()) fakeQVM.wavefunction = Mock(return_value=(Wavefunction(wf), 0)) inst = QAOA(fakeQVM, n_qubits, steps=p, rand_seed=42) true_probs = np.zeros_like(wf) for xx in range(wf.shape[0]): true_probs[xx] = np.conj(wf[xx]) * wf[xx] probs = inst.probabilities(angles) assert isinstance(probs, np.ndarray) prob_true = np.zeros((2**inst.n_qubits, 1)) prob_true[1] = 0.5 prob_true[2] = 0.5 assert np.isclose(probs, prob_true).all()
def test_unembed_solution(): with patch('pyquil.api.QVMConnection') as cxn: embedding = {0: 20, 1: 23, 2: 13, 3: 15} qaoa = QAOA(qvm=cxn, qubits=[0, 1, 2, 3], embedding=embedding) sol = [0, 1, 1, 1] assert qaoa.unembed_solution(sol) == (1, 1, 0, 1) with patch('pyquil.api.QVMConnection') as cxn: embedding = {0: 9, 1: 3, 2: 7, 3: 17, 4: 5} qaoa = QAOA(qvm=cxn, qubits=[0, 1, 2, 3, 4], embedding=embedding) sol = [0, 1, 1, 1, 0] assert qaoa.unembed_solution(sol) == (1, 0, 1, 0, 1)
@author: joost """ from hamiltonians import cost,mixer import networkx as nx import pyquil.latex import pyquil.api as api from grove.pyqaoa.qaoa import QAOA G = nx.random_regular_graph(2,3) Hc = cost(G) Hb = mixer(G) qvm_connection = api.QVMConnection() qubits = [int(n) for n in list(G.nodes)] Q = QAOA(qvm_connection, qubits, steps=2, cost_ham = Hc, ref_ham= Hb) params = [3,7,2,5] # b1, b2, g1, g2 prog = Q.get_parameterized_program() circuit = prog(params) # print to latex doc s = pyquil.latex.to_latex(circuit) print(s) # python figure #pyquil.latex.display(circuit) # Does not work for some reason
def __init__(self, clauses, m=None, steps=1, grid_size=None, tol=1e-5, gate_noise=None, verbose=False, visualize=False): self.clauses = clauses self.m = m self.verbose = verbose self.visualize = visualize self.step_by_step_results = None self.optimization_history = None self.gate_noise = gate_noise if grid_size is None: self.grid_size = len(clauses) + len(qubits) else: self.grid_size = grid_size cost_operators, mapping = self.create_operators_from_clauses() self.mapping = mapping driver_operators = self.create_driver_operators() # minimizer_kwargs = {'method': 'BFGS', # 'options': {'gtol': tol, 'disp': False}} # bounds = [(0, np.pi)]*steps + [(0, 2*np.pi)]*steps # minimizer_kwargs = {'method': 'L-BFGS-B', # 'options': {'gtol': tol, 'disp': False}, # 'bounds': bounds} minimizer_kwargs = { 'method': 'Nelder-Mead', 'options': { 'ftol': tol, 'tol': tol, 'disp': False } } if self.verbose: print_fun = print else: print_fun = pass_fun qubits = list(range(len(mapping))) if gate_noise: self.samples = int(1e3) pauli_channel = [gate_noise] * 3 else: self.samples = None pauli_channel = None connection = ForestConnection() qvm = QVM(connection=connection, gate_noise=pauli_channel) topology = nx.complete_graph(len(qubits)) device = NxDevice(topology=topology) qc = QuantumComputer(name="my_qvm", qam=qvm, device=device, compiler=QVMCompiler( device=device, endpoint=connection.compiler_endpoint)) vqe_option = { 'disp': print_fun, 'return_all': True, 'samples': self.samples } self.qaoa_inst = QAOA(qc, qubits, steps=steps, init_betas=None, init_gammas=None, cost_ham=cost_operators, ref_ham=driver_operators, minimizer=scipy.optimize.minimize, minimizer_kwargs=minimizer_kwargs, rand_seed=None, vqe_options=vqe_option, store_basis=True) self.ax = None
class OptimizationEngine(object): """ The optimization engine for the VQF algorithm. This class takes a problem encoded as clauses, further encodes it into hamiltonian and solves it using QAOA. Args: clauses (list): List of clauses (sympy expressions) representing the problem. m (int): Number to be factored. Needed only for the purpose of tagging result files. steps (int, optional): Number of steps in the QAOA algorithm. Default: 1 grid_size (int, optional): The resolution of the grid for grid search. Default: None tol (float, optional): Parameter of BFGS optimization method. Gradient norm must be less than tol before successful termination. Default:1e-5 gate_noise (float, optional): Specifies gate noise for qvm. Default: None. verbose (bool): Boolean flag, if True, information about the execution will be printed to the console. Default: False visualize (bool): Flag indicating if visualizations should be created. Default: False Attributes: clauses (list): See Args. grid_size (int): See Args. mapping (dict): Maps variables into qubit indices. qaoa_inst (object): Instance of QAOA class from Grove. samples (int): If noise model is active, specifies how many samples we should take for any given quantum program. ax (object): Matplotlib `axis` object, used for plotting optimization trajectory. """ def __init__(self, clauses, m=None, steps=1, grid_size=None, tol=1e-5, gate_noise=None, verbose=False, visualize=False): self.clauses = clauses self.m = m self.verbose = verbose self.visualize = visualize self.step_by_step_results = None self.optimization_history = None self.gate_noise = gate_noise if grid_size is None: self.grid_size = len(clauses) + len(qubits) else: self.grid_size = grid_size cost_operators, mapping = self.create_operators_from_clauses() self.mapping = mapping driver_operators = self.create_driver_operators() # minimizer_kwargs = {'method': 'BFGS', # 'options': {'gtol': tol, 'disp': False}} # bounds = [(0, np.pi)]*steps + [(0, 2*np.pi)]*steps # minimizer_kwargs = {'method': 'L-BFGS-B', # 'options': {'gtol': tol, 'disp': False}, # 'bounds': bounds} minimizer_kwargs = { 'method': 'Nelder-Mead', 'options': { 'ftol': tol, 'tol': tol, 'disp': False } } if self.verbose: print_fun = print else: print_fun = pass_fun qubits = list(range(len(mapping))) if gate_noise: self.samples = int(1e3) pauli_channel = [gate_noise] * 3 else: self.samples = None pauli_channel = None connection = ForestConnection() qvm = QVM(connection=connection, gate_noise=pauli_channel) topology = nx.complete_graph(len(qubits)) device = NxDevice(topology=topology) qc = QuantumComputer(name="my_qvm", qam=qvm, device=device, compiler=QVMCompiler( device=device, endpoint=connection.compiler_endpoint)) vqe_option = { 'disp': print_fun, 'return_all': True, 'samples': self.samples } self.qaoa_inst = QAOA(qc, qubits, steps=steps, init_betas=None, init_gammas=None, cost_ham=cost_operators, ref_ham=driver_operators, minimizer=scipy.optimize.minimize, minimizer_kwargs=minimizer_kwargs, rand_seed=None, vqe_options=vqe_option, store_basis=True) self.ax = None 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: if self.verbose: print("Constant term", single_term) pauli_terms.append(PauliTerm("I", 0, int(single_term))) elif len(single_term.free_symbols) == 1: if self.verbose: print("Single term", single_term) 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: if self.verbose: print("Double term", single_term) 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 create_driver_operators(self): """ Creates driver hamiltonian. """ driver_operators = [] for key, value in self.mapping.items(): driver_operators.append(PauliSum([PauliTerm("X", value, -1.0)])) return driver_operators def perform_qaoa(self): """ Finds optimal angles for QAOA. Returns: sampling_results (Counter): Counter, where each element represents a bitstring that has been obtained. mapping (dict): See class description. """ # betas, gammas = self.simple_grid_search_angles(save_data=True) # betas, gammas = self.step_by_step_grid_search_angles(starting_angles=self.step_by_step_results) betas, gammas = self.find_initial_angles_with_interp( starting_angles=self.step_by_step_results) self.step_by_step_results = [betas, gammas] self.qaoa_inst.betas = betas self.qaoa_inst.gammas = gammas betas, gammas, bfgs_evaluations = self.get_angles() self.qaoa_inst.betas = betas self.qaoa_inst.gammas = gammas try: _, sampling_results = self.qaoa_inst.get_string(betas, gammas, samples=10000) except: pdb.set_trace() return sampling_results, self.mapping, bfgs_evaluations def get_angles(self): """ Finds optimal angles with the quantum variational eigensolver method. It's direct copy of the function `get_angles` from Grove. I decided to copy it here to access to the optimization trajectory (`angles_history`). Returns: best_betas, best_gammas (np.arrays): best values of the betas and gammas found. """ stacked_params = np.hstack( (self.qaoa_inst.betas, self.qaoa_inst.gammas)) vqe = VQE(self.qaoa_inst.minimizer, minimizer_args=self.qaoa_inst.minimizer_args, minimizer_kwargs=self.qaoa_inst.minimizer_kwargs) cost_ham = reduce(lambda x, y: x + y, self.qaoa_inst.cost_ham) # maximizing the cost function! param_prog = self.qaoa_inst.get_parameterized_program() result, bfgs_evaluations = vqe.vqe_run(param_prog, cost_ham, stacked_params, qc=self.qaoa_inst.qc, **self.qaoa_inst.vqe_options) best_betas = result.x[:self.qaoa_inst.steps] best_gammas = result.x[self.qaoa_inst.steps:] optimization_trajectory = result.iteration_params energy_history = result.expectation_vals if self.ax is not None and self.visualize and self.qaoa_inst.steps == 1: plot_optimization_trajectory(self.ax, optimization_trajectory) if len(optimization_trajectory) != 0 and len(energy_history) != 0: self.optimization_history = np.hstack([ np.array(optimization_trajectory), np.array([energy_history]).T ]) else: self.optimization_history = np.array([]) return best_betas, best_gammas, bfgs_evaluations def simple_grid_search_angles(self, save_data=False): """ Finds optimal angles for QAOA by performing grid search on all the angles. This is not recommended for higher values of steps parameter, since it results in grid_size**(2*steps) evaluations. Returns: best_betas, best_gammas (np.arrays): best values of the betas and gammas found. """ best_betas = None best_gammas = None best_energy = np.inf # For some reasons np.meshgrid returns columns in order, where values in second # grow slower than in the first one. This a fix to it. if self.qaoa_inst.steps == 1: column_order = [0] else: column_order = [1, 0] + list(range(2, self.qaoa_inst.steps)) new_indices = np.argsort(column_order) beta_ranges = [np.linspace(0, np.pi, self.grid_size) ] * self.qaoa_inst.steps all_betas = np.vstack(np.meshgrid(*beta_ranges)).reshape( self.qaoa_inst.steps, -1).T all_betas = all_betas[:, column_order] gamma_ranges = [np.linspace(0, 2 * np.pi, self.grid_size) ] * self.qaoa_inst.steps all_gammas = np.vstack(np.meshgrid(*gamma_ranges)).reshape( self.qaoa_inst.steps, -1).T all_gammas = all_gammas[:, column_order] vqe = VQE(self.qaoa_inst.minimizer, minimizer_args=self.qaoa_inst.minimizer_args, minimizer_kwargs=self.qaoa_inst.minimizer_kwargs) cost_hamiltonian = reduce(lambda x, y: x + y, self.qaoa_inst.cost_ham) all_energies = [] data_to_save = [] if save_data: file_name = "_".join( [str(self.m), "grid", str(self.grid_size), str(time.time())]) + ".csv" for betas in all_betas: for gammas in all_gammas: stacked_params = np.hstack((betas, gammas)) program = self.qaoa_inst.get_parameterized_program() energy = vqe.expectation(program(stacked_params), cost_hamiltonian, self.samples, self.qaoa_inst.qc) all_energies.append(energy) if self.verbose: print(betas, gammas, energy, end="\r") if save_data: data_to_save.append(np.hstack([betas, gammas, energy])) if energy < best_energy: best_energy = energy best_betas = betas best_gammas = gammas if self.verbose: print("Lowest energy:", best_energy) print("Angles:", best_betas, best_gammas) if save_data: np.savetxt(file_name, np.array(data_to_save), delimiter=",") if self.visualize: if self.qaoa_inst.steps == 1: self.ax = plot_energy_landscape(all_betas, all_gammas, np.array(all_energies), log_legend=True) else: plot_variance_landscape(all_betas, all_gammas, np.array(all_energies)) return best_betas, best_gammas def step_by_step_grid_search_angles(self, starting_angles=None): """ Finds optimal angles for QAOA by performing "step-by-step" grid search. It finds optimal angles by performing grid search on the QAOA instance with steps=1. Then it fixes these angles and performs grid search on the second pair of angles. This method requires steps*grid_size**2 evaluations and hence is more suitable for higger values of steps. Returns: best_betas, best_gammas (np.arrays): best values of the betas and gammas found. """ max_step = self.qaoa_inst.steps if starting_angles is None: all_steps = range(1, max_step + 1) best_betas = np.array([]) best_gammas = np.array([]) elif len(starting_angles[0]) == max_step - 1: all_steps = [max_step] best_betas = starting_angles[0] best_gammas = starting_angles[1] elif len(starting_angles[0]) == max_step: best_betas = starting_angles[0] best_gammas = starting_angles[1] return best_betas, best_gammas else: all_steps = range(1, max_step + 1) best_betas = np.array([]) best_gammas = np.array([]) self.qaoa_inst.betas = best_betas self.qaoa_inst.gammas = best_gammas for current_step in all_steps: if self.verbose: print("step:", current_step, "\n") beta, gamma = self.one_step_grid_search(current_step) best_betas = np.append(best_betas, beta) best_gammas = np.append(best_gammas, gamma) self.qaoa_inst.betas = best_betas self.qaoa_inst.gammas = best_gammas return best_betas, best_gammas def one_step_grid_search(self, current_step): """ Grid search on n-th pair of QAOA angles, where n=current_step. Args: current_step (int): specify on which layer do we perform search. Returns: best_beta, best_gamma (floats): best values of the beta and gamma found. """ self.qaoa_inst.steps = current_step best_beta = None best_gamma = None best_energy = np.inf fixed_betas = self.qaoa_inst.betas fixed_gammas = self.qaoa_inst.gammas beta_range = np.linspace(0, np.pi, self.grid_size) gamma_range = np.linspace(0, 2 * np.pi, self.grid_size) vqe = VQE(self.qaoa_inst.minimizer, minimizer_args=self.qaoa_inst.minimizer_args, minimizer_kwargs=self.qaoa_inst.minimizer_kwargs) cost_hamiltonian = reduce(lambda x, y: x + y, self.qaoa_inst.cost_ham) for beta in beta_range: for gamma in gamma_range: betas = np.append(fixed_betas, beta) gammas = np.append(fixed_gammas, gamma) stacked_params = np.hstack((betas, gammas)) program = self.qaoa_inst.get_parameterized_program() energy = vqe.expectation(program(stacked_params), cost_hamiltonian, self.samples, self.qaoa_inst.qc) print(beta, gamma, end="\r") if energy < best_energy: best_energy = energy best_beta = beta best_gamma = gamma return best_beta, best_gamma def find_initial_angles_with_interp(self, starting_angles): """ Implements INTERP strategy proposed in https://arxiv.org/pdf/1812.01041.pdf, appendix B.1 """ if self.qaoa_inst.steps == 1: betas, gammas = self.simple_grid_search_angles(save_data=False) return betas, gammas p = self.qaoa_inst.steps - 1 if len(starting_angles[0]) == p: previous_betas = np.hstack([0, starting_angles[0], 0]) previous_gammas = np.hstack([0, starting_angles[1], 0]) new_betas = [] new_gammas = [] for i in range(1, p + 2): beta_i = previous_betas[i] beta_i_minus_1 = previous_betas[i - 1] new_beta_i = (i - 1) / p * beta_i_minus_1 + (p - i + 1) / p * beta_i new_betas.append(new_beta_i) gamma_i = previous_gammas[i] gamma_i_minus_1 = previous_gammas[i - 1] new_gamma_i = (i - 1) / p * gamma_i_minus_1 + (p - i + 1) / p * gamma_i new_gammas.append(new_gamma_i) return np.array(new_betas), np.array(new_gammas) elif len(starting_angles[0]) == p + 1: best_betas = starting_angles[0] best_gammas = starting_angles[1] return best_betas, best_gammas else: Exception( "INTERP strategy won't work without proper starting angles.")
def make_clamped_QAOA(self, data_point, iter): """ Internal helper function for building QAOA circuit to get RBM expectation using Rigetti Quantum simulator Returns --------------------------------------------------- nus: (list) optimal parameters for cost hamiltonians in each layer of QAOA gammas: (list) optimal parameters for mixer hamiltonians in each layer of QAOA para_prog: (fxn closure) fxn to return QAOA circuit for any supplied nus and gammas --------------------------------------------------- """ # Indices visible_indices = [i for i in range(self.visible_units)] hidden_indices = [ i + self.visible_units for i in range(self.hidden_units) ] total_indices = [i for i in range(self.total_units)] # Partial Mixer and Partial Cost Hamiltonian partial_mixer_operator = [] for i in hidden_indices: partial_mixer_operator.append(PauliSum([PauliTerm("X", i, 1.0)])) partial_cost_operator = [] for i in visible_indices: for j in hidden_indices: partial_cost_operator.append( PauliSum([ PauliTerm( "Z", i, -1.0 * self.WEIGHTS[i][j - self.visible_units]) * PauliTerm("Z", j, 1.0) ])) if self.BIAS is not None: for i in hidden_indices: partial_cost_operator.append( PauliSum([ PauliTerm("Z", i, -1.0 * self.BIAS[i - self.visible_units]) ])) state_prep = pq.Program() # state_prep = arbitrary_state.create_arbitrary_state(data_point,visible_indices) # Prepare Visible units as computational basis state corresponding to data point. for i, j in enumerate(data_point): #print(i,j) if j == 1: state_prep += X(i) # Prepare Hidden units in a thermal state of the partial mixer hamiltonian. for i in hidden_indices: tmp = pq.Program() tmp.inst(RX(self.state_prep_angle, i + self.total_units), CNOT(i + self.total_units, i)) state_prep += tmp # QAOA on parital mixer and partial cost hamiltonian evolution partial_QAOA = QAOA(qvm=self.qvm, qubits=total_indices, steps=self.qaoa_steps, ref_ham=partial_mixer_operator, cost_ham=partial_cost_operator, driver_ref=state_prep, store_basis=True, minimizer=fmin_bfgs, minimizer_kwargs={'maxiter': 100 // iter}, vqe_options={'samples': self.quant_meas_num}, rand_seed=1234) nus, gammas = partial_QAOA.get_angles() program = partial_QAOA.get_parameterized_program() return nus, gammas, program, 1
class ForestTSPSolver(object): """docstring for TSPSolver""" def __init__(self, nodes_array, steps=3, ftol=1.0e-4, xtol=1.0e-4, all_ones_coefficient=-2): self.nodes_array = nodes_array self.qvm = api.QVMConnection() self.steps = steps self.ftol = ftol self.xtol = xtol self.betas = None self.gammas = None self.qaoa_inst = None self.most_freq_string = None self.number_of_qubits = self.get_number_of_qubits() self.all_ones_coefficient = all_ones_coefficient cost_operators = self.create_cost_operators() driver_operators = self.create_driver_operators() minimizer_kwargs = {'method': 'Nelder-Mead', 'options': {'ftol': self.ftol, 'xtol': self.xtol, 'disp': False}} vqe_option = {'disp': print_fun, 'return_all': True, 'samples': None} self.qaoa_inst = QAOA(self.qvm, list(range(self.number_of_qubits)), steps=self.steps, cost_ham=cost_operators, ref_hamiltonian=driver_operators, store_basis=True, minimizer=scipy.optimize.minimize, minimizer_kwargs=minimizer_kwargs, vqe_options=vqe_option) def solve_tsp(self): self.find_angles() return self.get_solution() def find_angles(self): self.betas, self.gammas = self.qaoa_inst.get_angles() return self.betas, self.gammas def get_results(self): most_freq_string, sampling_results = self.qaoa_inst.get_string(self.betas, self.gammas, samples=10000) self.most_freq_string = most_freq_string return sampling_results.most_common() def get_solution(self): if self.most_freq_string is None: self.most_freq_string, sampling_results = self.qaoa_inst.get_string(self.betas, self.gammas, samples=10000) quantum_order = TSP_utilities.binary_state_to_points_order_full(self.most_freq_string) return quantum_order def create_cost_operators(self): cost_operators = [] cost_operators += self.create_weights_cost_operators() # 0 - 1: 3 # 0 - 2: 4 # 1 - 2: 5 # cost_operators += self.create_single_weight_operator(0, 1, 3) # cost_operators += self.create_single_weight_operator(0, 2, 4) # cost_operators += self.create_single_weight_operator(1, 2, 5) # cost_operators += self.create_single_z_operator(0, 1, 0, 3) # cost_operators += self.create_single_z_operator(0, 1, 0, -3) cost_operators += self.create_penalty_operators_for_bilocation() cost_operators += self.create_penalty_operators_for_repetition() return cost_operators def create_single_weight_operator(self, i, j, weight): # Positive weights makes given connection more probable. cost_operators = [] for t in [0, 1]: cost_operators.append(create_single_z_operator(i, j, t, weight)) # qubit_1 = t * number_of_nodes + i # qubit_2 = (t + 1) * number_of_nodes + j # # cost_operators.append(PauliTerm("I", 0, weight) - PauliTerm("Z", qubit_1, weight) * PauliTerm("Z", qubit_2)) # cost_operators.append(PauliTerm("Z", qubit_1, weight) * PauliTerm("Z", qubit_2) - PauliTerm("I", 0, weight)) # cost_operators.append(PauliTerm("Z", qubit_2, weight) * PauliTerm("Z", qubit_1) - PauliTerm("I", 0, weight)) return cost_operators def create_single_z_operator(self, i, j, t, weight): number_of_nodes = 3 qubit_1 = t * number_of_nodes + i qubit_2 = (t + 1) * number_of_nodes + j cost_operators = [] cost_operators.append(PauliTerm("Z", qubit_1, weight) * PauliTerm("Z", qubit_2) - PauliTerm("I", 0, weight)) cost_operators.append(PauliTerm("Z", qubit_2, weight) * PauliTerm("Z", qubit_1) - PauliTerm("I", 0, weight)) return cost_operators def create_penalty_operators_for_bilocation(self): # Additional cost for visiting more than one node in given time t cost_operators = [] number_of_nodes = len(self.nodes_array) for t in range(number_of_nodes): range_of_qubits = list(range(t * number_of_nodes, (t + 1) * number_of_nodes)) cost_operators += self.create_penalty_operators_for_qubit_range(range_of_qubits) return cost_operators def create_penalty_operators_for_repetition(self): # Additional cost for visiting given node more than one time cost_operators = [] number_of_nodes = len(self.nodes_array) for i in range(number_of_nodes): range_of_qubits = list(range(i, number_of_nodes**2, number_of_nodes)) cost_operators += self.create_penalty_operators_for_qubit_range(range_of_qubits) return cost_operators def create_penalty_operators_for_qubit_range(self, range_of_qubits): cost_operators = [] tsp_matrix = TSP_utilities.get_tsp_matrix(self.nodes_array) weight = -10 * np.max(tsp_matrix) # weight = -0.5 for i in range_of_qubits: if i == range_of_qubits[0]: z_term = PauliTerm("Z", i, weight) all_ones_term = PauliTerm("I", 0, 0.5 * weight) - PauliTerm("Z", i, 0.5 * weight) else: z_term = z_term * PauliTerm("Z", i) all_ones_term = all_ones_term * (PauliTerm("I", 0, 0.5) - PauliTerm("Z", i, 0.5)) z_term = PauliSum([z_term]) cost_operators.append(PauliTerm("I", 0, weight) - z_term + self.all_ones_coefficient * all_ones_term) return cost_operators def create_weights_cost_operators(self): cost_operators = [] number_of_nodes = len(self.nodes_array) tsp_matrix = TSP_utilities.get_tsp_matrix(self.nodes_array) for i in range(number_of_nodes): for j in range(i, number_of_nodes): for t in range(number_of_nodes - 1): weight = -tsp_matrix[i][j] / 2 if tsp_matrix[i][j] != 0: qubit_1 = t * number_of_nodes + i qubit_2 = (t + 1) * number_of_nodes + j cost_operators.append(PauliTerm("I", 0, weight) - PauliTerm("Z", qubit_1, weight) * PauliTerm("Z", qubit_2)) return cost_operators def create_driver_operators(self): driver_operators = [] for i in range(self.number_of_qubits): driver_operators.append(PauliSum([PauliTerm("X", i, -1.0)])) return driver_operators def get_number_of_qubits(self): return len(self.nodes_array)**2
def make_unclamped_QAOA(self): """ Internal helper function for building QAOA circuit to get RBM expectation using Rigetti Quantum simulator Returns --------------------------------------------------- nus: (list) optimal parameters for cost hamiltonians in each layer of QAOA gammas: (list) optimal parameters for mixer hamiltonians in each layer of QAOA para_prog: (fxn closure) fxn to return QAOA circuit for any supplied nus and gammas --------------------------------------------------- """ # Indices visible_indices = [i for i in range(self.visible_units)] hidden_indices = [ i + self.visible_units for i in range(self.hidden_units) ] total_indices = [i for i in range(self.total_units)] # Full Mixer and Cost Hamiltonian Operator full_mixer_operator = [] for i in total_indices: full_mixer_operator.append(PauliSum([PauliTerm("X", i, 1.0)])) full_cost_operator = [] for i in visible_indices: for j in hidden_indices: full_cost_operator.append( PauliSum([ PauliTerm( "Z", i, -1.0 * self.WEIGHTS[i][j - self.visible_units]) * PauliTerm("Z", j, 1.0) ])) if self.BIAS is not None: for i in hidden_indices: print(i, self.visible_units, i - self.visible_units, self.BIAS[i - self.visible_units]) full_cost_operator.append( PauliSum([ PauliTerm("Z", i, -1.0 * self.BIAS[i - self.visible_units]) ])) # Prepare all the units in a thermal state of the full mixer hamiltonian. state_prep = pq.Program() for i in total_indices: tmp = pq.Program() tmp.inst(RX(self.state_prep_angle, i + self.total_units), CNOT(i + self.total_units, i)) state_prep += tmp # QAOA on full mixer and full cost hamiltonian evolution full_QAOA = QAOA(self.qvm, qubits=total_indices, steps=self.qaoa_steps, ref_ham=full_mixer_operator, cost_ham=full_cost_operator, driver_ref=state_prep, store_basis=True, minimizer=fmin_bfgs, minimizer_kwargs={'maxiter': 100}, vqe_options={'samples': self.quant_meas_num}, rand_seed=1234) nus, gammas = full_QAOA.get_angles() program = full_QAOA.get_parameterized_program() return nus, gammas, program, 0
minimizer_kwargs = { 'method': 'Nelder-Mead', 'options': { 'ftol': 1.0e-3, 'xtol': 1.0e-3, 'disp': False } } def print_fun(x): print(x) vqe_option = {'disp': print_fun, 'return_all': True, 'samples': None} qaoa_inst = QAOA(qvm, qubits, steps=2, cost_ham=create_phase_separator(), ref_ham=create_mixing_hamiltonian(), driver_ref=create_initial_state_program(), minimizer=minimize, minimizer_kwargs=minimizer_kwargs, rand_seed=None, vqe_options=vqe_option, store_basis=True) print("Solution", calculate_solution())