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 find_max
from qrisp.algorithms.qiro.qiro_mixers import qiro_controlled_RX_mixer_gen
from qrisp import QuantumBool, mcx
from qrisp.algorithms.qaoa import controlled_RX_mixer_gen


[docs] def create_max_indep_replacement_routine(res, problem_updated): """ 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. problem_updated : List Updates that happened during the QIRO routine. Consits of the updated problem, a list of Qubits which were found to be positively correlated, i.e. part of the problem solution, and a list Qubits which were found to be negatively correlated, i.e. they 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. """ graph = problem_updated[0] solutions = problem_updated[1] exclusions = problem_updated[2] # for multi qubit correlations orig_edges = [list(item) for item in graph.edges()] # for single qubit correlations orig_nodes = list(graph.nodes()) max_item, sign = find_max(orig_nodes, orig_edges , res, solutions) if max_item == None: return graph, solutions, 0 ,exclusions # create a copy of the graph new_graph = copy.copy(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 then its mostly appeared as a "1" in the results--> part of solution set if sign < 0: # remove all adjacent nodes to_remove = list(graph.adj[max_item]) new_graph.remove_nodes_from(to_remove) solutions.append(max_item) exclusions += to_remove # if sign >0 then its mostly appeared as a "0" in the results 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(problem_updated): 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 ---------- problem_updated : List Updates that happened during the QIRO routine. Consits of the updated problem, a list of Qubits which were found to be positively correlated, i.e. part of the problem solution, and a list Qubits which were found to be negatively correlated, i.e. they contradict solution qubits in accordance with the update rules. Returns ------- cost_operator : function A function receiving a :ref:`QuantumVariable` and a real parameter $\gamma$. This function performs the application of the cost operator. """ problem = problem_updated[0] solutions = problem_updated[1] def cost_operator(qv, gamma): for pair in list(problem.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 problem.nodes(): if not i in solutions: rz(gamma, qv[i]) return cost_operator
[docs] def create_max_indep_controlled_mixer_reduced(problem_updated): r""" Creates the ``controlled_RX_mixer`` for a QIRO instance of the maximal independet set problem for a given graph ``G`` following `Hadfield et al. <https://arxiv.org/abs/1709.03489>`_ The belonging ``predicate`` function indicates if a set can be swapped into the solution. Parameters ---------- problem_updated : List Updates that happened during the QIRO routine. Consits of the updated problem, a list of Qubits which were found to be positively correlated, i.e. part of the problem solution, and a list Qubits which were found to be negatively correlated, i.e. they contradict solution qubits in accordance with the update rules. Returns ------- controlled_RX_mixer : function A Python function receiving a :ref:`QuantumVariable` and real parameter $\beta$. This function performs the application of the mixer associated to the graph ``G``. """ problem = problem_updated[0] solutions = problem_updated[1] exclusions = problem_updated[2] neighbors_dict = {node: list(problem.adj[node]) for node in problem.nodes()} def qiro_predicate(qv,i): qbl = QuantumBool() if len(neighbors_dict[i])==0: x(qbl) else: mcx([qv[j] for j in neighbors_dict[i]],qbl,ctrl_state='0'*len(neighbors_dict[i])) return qbl controlled_RX_mixer=qiro_controlled_RX_mixer_gen(qiro_predicate, solutions+exclusions) return controlled_RX_mixer
[docs] def qiro_max_indep_set_init_function(solutions =[], exclusions = []): r""" To be used for the controlled mixer approach of QIRO MIS. Only flips qubits which we found to be a part of the problem soultion. Parameters ---------- solutions : List List of Qubits which were found to be positively correlated, i.e. part of the problem solution exclusions : List List Qubits which were found to be negatively correlated, i.e. they contradict solution qubits in accordance with the update rules. """ def init_function(qv): for i in range(len(qv)): if i in solutions: x(qv[i]) return init_function