QIROProblem#

class QIROProblem(problem, replacement_routine, cost_operator, mixer, cl_cost_function, init_function)[source]#

Structure to run QIRO algorithms. The idea is based on the paper by J. Finzgar et al. (https://arxiv.org/pdf/2308.13607.pdf).

This class encapsulates the cost operator, mixer operator, and classical cost function for a specific QIRO problem instance. It also provides methods to set the initial state preparation function, classical cost post-processing function, and optimizer for the problem.

For a quick demonstration, we import the relevant functions from already implemented problem instances:

# imports 
from qrisp.qaoa.qiro_problem import QIROProblem
from qrisp.qaoa.qaoa_problem import QAOAProblem
from qrisp.qaoa.problems.create_rdm_graph import create_rdm_graph
from qrisp.qaoa.problems.maxCliqueInfrastr import maxCliqueCostfct, maxCliqueCostOp
from qrisp.qaoa.qiroproblems.qiroMaxCliqueInfrastr import * 
from qrisp.qaoa.mixers import RX_mixer
from qrisp.qaoa.qiro_mixers import qiro_init_function, qiro_RXMixer
from qrisp import QuantumVariable
import matplotlib.pyplot as plt
import networkx as nx

# First we define a graph via the number of nodes and the QuantumVariable arguments
num_nodes = 15
G = create_rdm_graph(num_nodes,0.7, seed =  99)
Gtwo = create_rdm_graph(num_nodes,0.7, seed =  99)
qarg = QuantumVariable(G.number_of_nodes())
qarg2 = QuantumVariable(Gtwo.number_of_nodes())

# set simulator shots
mes_kwargs = {
    #below should be 5k
    "shots" : 5000
    }

#assign cost_function and maxclique_instance, normal QAOA
testCostFun = maxCliqueCostfct(Gtwo)
maxclique_instance = QAOAProblem(maxCliqueCostOp(G), RX_mixer, maxCliqueCostfct(G))

# assign the correct new update functions for qiro from above imports
qiro_instance = QIROProblem(problem = Gtwo,  
                            replacement_routine = create_maxClique_replacement_routine, 
                            cost_operator = create_maxClique_cost_operator_reduced,
                            mixer = qiro_RXMixer,
                            cl_cost_function = maxCliqueCostfct,
                            init_function = qiro_init_function
                            )

# We run the qiro instance and get the results!
res_qiro = qiro_instance.run_qiro(qarg=qarg, depth = 3, n_recursions = 2, 
                                #mes_kwargs = mes_kwargs
                                )
# and also the final graph, that has been adjusted
final_Graph = qiro_instance.problem

# get the normal QAOA results for a comparison
res_qaoa = maxclique_instance.run( qarg = qarg2, depth = 3)

# We can then also print the top 5 results for each...
print("QAOA 5 best results")
maxfive = sorted(res_qaoa, key=res_qaoa.get, reverse=True)[:5]
for key, val in res_qaoa.items(): 
    if key in maxfive:
        print(key)
        print(testCostFun({key:1}))

print("QIRO 5 best results")
maxfive = sorted(res_qiro, key=res_qiro.get, reverse=True)[:5]
for key, val in res_qiro.items():  
    if key in maxfive:

        print(key)
        print(testCostFun({key:1}))

# or compare it with the networkx result of the max_clique algorithm...
print("Networkx solution")
print(nx.approximation.max_clique(Gtwo))

# and finally, we draw the final graph and the original graphs to compare them!
plt.figure(1)
nx.draw(final_Graph, with_labels = True)

plt.figure(2)
nx.draw(G, with_labels = True)
plt.show()  

For an in-depth tutorial, make sure to check out QIROmaxClique!

Parameters:
problemAny

The problem structure to be considered for the algorithm. For example in the case of MaxClique a graph, or MaxSat a list of clauses

qaoaProblemQAOAProblem

A QAOAProblem instance to be used for establishing the correlations.

replacement_routinefunction

A routine for adjusting the problem after the highest correlation value has been found.

qiro_cost_operatorfunction

New cost_operator for the QAOAProblem instance.

qiro_mixer_operatorfunction

New mixer_operator for the QAOAProblem instance.

qiro_init_functionfunction

New mixer_operator for the QAOAProblem instance.

QIROProblem.run_qiro(qarg, depth, n_recursions, mes_kwargs={}, max_iter=50)[source]#

Run the specific QIRO problem instance with given quantum arguments, depth of QAOA circuit, measurement keyword arguments (mes_kwargs) and maximum iterations for optimization (max_iter).

Parameters:
qargQuantumVariable

The quantum variable to which the QAOA circuit is applied.

depthint

The depth of the QAOA circuit.

n_recursionsint

The number of QIRO replacement iterations.

mes_kwargsdict, optional

The keyword arguments for the measurement function. Default is an empty dictionary.

max_iterint, optional

The maximum number of iterations for the optimization method. Default is 50.

Returns:
opt_resdict

The optimal result after running QAOA problem for a specific problem instance. It contains the measurement results after applying the optimal QAOA circuit to the quantum variable.