Source code for qrisp.qiro.qiroproblems.qiroMaxSatInfrastr

# just write a replacement_routine and throw out not relevant sets

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

[docs] def create_maxSat_replacement_routine( res, oldproblem, solutions, exclusions): """ Creates a replacement routine for the problem structure, i.e. defines the replacement rules. See the original paper for description of the update rules Parameters ---------- res : dict Result dictionary of initial QAOA optimization procedure. oldproblem : List The clauses defining the problem instance. solutions : List Qubits which have been found to be positive correlated, i.e. part of the problem solution. exclusions : List Qubits which have been found to be negative correlated, i.e. not part of the problem solution, or contradict solution qubits in accordance to the update rules. Returns ------- new_problem: list Updated clauses of 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 to the problem. """ numVars = oldproblem[0] clauses = copy.deepcopy(oldproblem[1]) # FOR SINGLE QUBIT CORRELATIONS # make -1 here for consistency in the find max orig_nodes = [i - 1 for i in list(range(1,numVars + 1)) if not i in exclusions] combinations = [] # add check for solution nodes for index1 in range(len(orig_nodes)-1): for index2 in range(index1, len(orig_nodes)): combinations.append((orig_nodes[index1],orig_nodes[index2])) max_item, sign = find_max(orig_nodes, combinations, res, solutions) # we just directly remove clauses from clauses if isinstance(max_item, int): max_item += 1 if sign > 0: for item in clauses: # if negation in item --> remove it if -1 * max_item in item: clauses.remove(item) solutions.append(max_item) exclusions.append(max_item) elif sign < 0: for item in clauses: # if number in item --> remove it if max_item in item: clauses.remove(item) exclusions.append(max_item) else: max_item[0] += 1 max_item[1] += 1 if sign > 0: for item in clauses: # replace with pos. correlated number if its in an item if max_item[1] in item: temp = item.index[max_item[1]] item[temp] = max_item[0] if -1* max_item[1] in item: temp = item.index[-1* max_item[1]] item[temp] = -1* max_item[0] exclusions.append(max_item[1]) elif sign < 0: for item in clauses: # replace with neg. correlated number if its in an item if max_item[1] in item: temp = item.index[max_item[1]] item[temp] = -1 * max_item[0] if -1* max_item[1] in item: temp = item.index[ -1 * max_item[1]] item[temp] = max_item[0] exclusions.append(max_item[1]) # create sign list somewhere? return [numVars, clauses], solutions, sign, exclusions
[docs] def create_maxSat_cost_operator_reduced(problem, solutions=[]): """ | Implementation for MaxSat Cost-Operator, in accordance to the original QAOA-paper. | Adjusted for QIRO to also respect found solutions to the problem Parameters ---------- clauses : List(Lists) Clauses to be considered for MaxSat. Should be given as a list of lists and 1-indexed instead 0-indexed, see example solutions : List Variables that were found to be a part of the solution. Returns ------- cost_operator : function the Operator applied to the circuit-QuantumVariable Examples -------- >>> clauses11 = (6, [[1,2,-3], [1,4,-6], [4,5,6], [1,3,-4], [2,4,5], [1,3,5], [-2,-3,6]]) | Explanation: | First entry of tuple is the number of variables, second is the clauses | Clause [1, 2, -4] is fulfilled by the QuantumStates "1100", "1110" * if the sign is positive : the index has of the QuantumVariable to be "1", if negative sign the index has to be "0". * indices not mentioned can be "0" or "1" (the third integer in this case). * start with 1 in your clauses! because ``int 0`` has no sign and this is problematic. * we want to keep the mathematical formulation, so no handing over strings! """ clauses = problem[1] satlen = len(clauses[0]) def maxSatcostEmbed(qv , gamma): import itertools #clauses = clauses qc = qv for numClause in range(len(clauses)): #go through clauses clause = clauses[numClause] for lenofCombination in range(1,satlen+1): # get all combinations to assign rz, rzz, rzzz, rzzzzzz.... combinations = list(itertools.combinations(clause, lenofCombination)) #print(combinations) #len == 1: just rz if lenofCombination == 1: for index in range(len(combinations)): if abs( combinations[index][0])-1 not in solutions: # sign for rz mixer signu = - np.sign(combinations[index][0]) # always have the "-1" at the end since clauses are not initiated with 0, see above #print(abs( combinations[index][0] - 1 )) rz(signu * gamma/8, qc[ abs( combinations[index][0]) -1 ] ) else: #for all combinations of this length for index in range(len(combinations)): signu = 1 # up to final value in combination perform cx gates --> set up the rzz, rzzz, rzzzz ... gates for index2 in range(lenofCombination-1): # (also remember the sign) signu *= - np.sign(combinations[index][index2]) cx(qc[abs( combinations[index][index2] ) -1], qc[abs( combinations[index][index2+1] ) -1]) signu *= np.sign(combinations[index][lenofCombination-1]) # finalize rzz, rzzz, rzzzz ... gates rz(signu*gamma/8, qc[abs( combinations[index][lenofCombination-1] ) -1]) # and cnot gates back for index2 in reversed(range(lenofCombination-1)): cx( qc[abs(combinations[index][index2] ) -1], qc[abs(combinations[index][index2+1] ) -1 ]) return qc return maxSatcostEmbed