Source code for qrisp.qiro.qiroproblems.qiroMaxIndepSet

"""
\********************************************************************************
* Copyright (c) 2024 the Qrisp authors
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License, v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is
* available at https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
"""

from qrisp import rz, rzz, x
import numpy as np
import copy
from qrisp.algorithms.qiro.qiroproblems.qiro_utils import * 


[docs] def create_max_indep_replacement_routine(res, graph, solutions=[], exclusions=[]): """ Creates a replacement routine for the problem structure, i.e., defines the replacement rules. See the `original paper <https://journals.aps.org/prxquantum/abstract/10.1103/PRXQuantum.5.020327>`_ for a description of the update rules. Parameters ---------- res : dict Result dictionary of QAOA optimization procedure. graph : nx.Graph The graph defining the problem instance. solutions : list Qubits which were found to be positively correlated, i.e., part of the problem solution. exclusions : list Qubits which were found to be negatively correlated, i.e., not part of the problem solution, or contradict solution qubits in accordance with the update rules. Returns ------- new_graph : nx.Graph Updated graph for the problem instance. solutions : list Updated set of solutions to the problem. sign : int The sign of the correlation. exclusions : list Updated set of exclusions for the problem. """ # for multi qubit correlations orig_edges = [list(item) for item in graph.edges()] # for single qubit correlations orig_nodes = list(graph.nodes()) max_item = [] max_item, sign = find_max(orig_nodes, orig_edges , res, solutions) # create a copy of the graph new_graph = copy.deepcopy(graph) # we remove nodes from the graph, as suggested by the replacement rules # if the item is an int, it is a single node, else it is an edge if isinstance(max_item, int): if sign > 0: # remove all adjacent nodes to_remove = graph.adj[max_item] new_graph.remove_nodes_from(to_remove) solutions.append(max_item) exclusions += to_remove elif sign < 0: # remove the node new_graph.remove_node(max_item) exclusions.append(max_item) else: if sign > 0: # remove both nodes new_graph.remove_nodes_from(max_item) exclusions += list(max_item) elif sign < 0: # remove all nodes connected to both nodes intersect = list(set( list(graph.adj[max_item[0]].keys()) ) & set( list(graph.adj[max_item[0]].keys()) )) new_graph.remove_nodes_from(intersect) exclusions += intersect return new_graph, solutions, sign, exclusions
[docs] def create_max_indep_cost_operator_reduced(graph, solutions=[]): r""" Creates the ``cost_operator`` for the problem instance. This operator is adjusted to consider qubits that were found to be a part of the problem solution. Parameters ---------- G : nx.Graph The graph for the problem instance. solutions : list Qubits which were found to be positively correlated, i.e., part of the problem solution. Returns ------- cost_operator : function A function receiving a :ref:`QuantumVariable` and a real parameter $\gamma$. This function performs the application of the cost operator. """ def cost_operator(qv, gamma): for pair in list(graph.edges()): #cx(qv[pair[0]], qv[pair[1]]) rzz(3*gamma, qv[pair[0]], qv[pair[1]]) rz(-gamma, qv[pair[0]]) rz(-gamma, qv[pair[1]]) for i in graph.nodes(): if not i in solutions: rz(gamma, qv[i]) return cost_operator
""" def create_maxIndep_mixer_reduced(graph, solutions): def RX_mixer(qv, beta): from qrisp import rx for i in graph.nodes(): if not i in solutions: rx(2 * beta, qv[i]) return RX_mixer def init_function_reduced(graph, solutions): def init_state(qv): from qrisp import h for i in graph.nodes(): if not i in solutions: h(qv[i]) for i in solutions: x(qv[i]) return init_state #TODO: def create_maxIndep_cl_cost_function_reduced(graph): #btw alternative formulation: for edge: check if string[edge[0]] != string[edge[1]] def aClcostFct(res_dic): tot_energy = 0.001 tot_counts = 0 for state in res_dic.keys(): # we assume solution is right temp = True energy = 0 for edge in graph.edges(): if not state[edge[0]] != state[edge[1]]: temp = False # else we just add the number of marked as |1> nodes if temp: intlist = [s for s in range(len(list(state))) if list(state)[s] == "1"] energy = -len(intlist) tot_energy += energy * res_dic[state] tot_counts += res_dic[state] #print(tot_energy/tot_counts) return tot_energy/tot_counts return aClcostFct """