Пример #1
0
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)
Пример #2
0
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)
Пример #3
0
    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)
Пример #4
0
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)
Пример #6
0
    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)
Пример #7
0
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
Пример #8
0
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
Пример #9
0
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
Пример #10
0
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
Пример #13
0
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
Пример #14
0
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)
Пример #16
0
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
Пример #17
0
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
Пример #18
0
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)
Пример #19
0
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
Пример #21
0
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
Пример #22
0
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()
Пример #23
0
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)
Пример #24
0
@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
Пример #25
0
    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
Пример #26
0
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.")
Пример #27
0
    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
Пример #29
0
    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
Пример #30
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())