Skip to content

Commit

Permalink
Merge pull request #90 from eclipse-qrisp/QIRO_upgrades
Browse files Browse the repository at this point in the history
QIRO updates: migrated to new QAOA implementations, improved documentation. 
Removed deprecated QAOA implementations. Minor updates to QAOA implementations and documentation.
  • Loading branch information
renezander90 authored Oct 18, 2024
2 parents 2f29cdc + 20d6426 commit 2549813
Show file tree
Hide file tree
Showing 62 changed files with 1,165 additions and 2,426 deletions.
222 changes: 102 additions & 120 deletions documentation/source/general/tutorial/QIROtutorial.rst

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions documentation/source/reference/Algorithms/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ We encourage you to explore these algorithms, delve into their documentation, an
:maxdepth: 2
:hidden:

qaoa/index
QIRO
qaoa/QAOA
qiro/QIRO
Shor
Grover
QuantumBacktrackingTree
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ Implementations
.. toctree::
:hidden:

qaoaProblems/qaoa.problems.maxCut
qaoaProblems/qaoa.problems.maxSat
qaoaProblems/qaoa.problems.eThrLinTwo
qaoaProblems/qaoa.problems.QUBO
qaoaProblems/qaoa.problems.maxIndepSet
qaoaProblems/qaoa.problems.maxClique
qaoaProblems/qaoa.problems.maxSetPack
qaoaProblems/qaoa.problems.minSetCover
qaoaProblems/qaoa.problems.maxKColorableSubgraph
implementations/maxCut
implementations/maxSat
implementations/eThrLinTwo
implementations/QUBO
implementations/maxIndepSet
implementations/maxClique
implementations/maxSetPack
implementations/minSetCover
implementations/maxKColorableSubgraph


Our voyage into :ref:`MaxCut <MaxCutQAOA>` and :ref:`Max-$\\kappa$-Colorable Subgraph <MkCSQAOA>` problems is detailed in the :ref:`tutorial <tutorial>` section.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Example implementation
::

from qrisp import QuantumVariable
from qrisp.qaoa import QAOAProblem, RX_mixer, create_e3lin2_cl_cost_function, create_e3lin2_cost_operator, e3lin2_init_function
from qrisp.qaoa import QAOAProblem, RX_mixer, create_e3lin2_cl_cost_function, create_e3lin2_cost_operator

clauses = [[0,1,2,1],[1,2,3,0],[0,1,4,0],[0,2,4,1],[2,4,5,1],[1,3,5,1],[2,3,4,0]]
num_variables = 6
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Here, we provide a condensed implementation of QAOA for M$\kappa$CS using all of
Problem description
-------------------

Given a Graph :math:`G = (V,E)` find and $\kappa$ colors, maximize the size (number of edges) of a properly colored subgraph.
Given a Graph :math:`G = (V,E)` and $\kappa$ colors, maximize the size (number of edges) of a properly colored subgraph.

Cost operator
-------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ QAOA MaxSat
Problem description
-------------------

Given :math:`m` disjunctive clauses over :math:`n` Boolean variables :math:`x`, where each clause
Given :math:`m` disjunctive clauses over :math:`n` Boolean variables :math:`x_1,\dotsc,x_n`, where each clause
contains at most :math:`l \geq 2` literals, find a variable assignment that maximizes the number of
satisfied clauses.

Expand Down Expand Up @@ -66,23 +66,24 @@ Example implementation
::

from qrisp import QuantumVariable
from qrisp.qaoa import QAOAProblem, RX_mixer, create_maxsat_cl_cost_function, create_maxsat_cost_operator, maxsat_init_function
from qrisp.qaoa import QAOAProblem, RX_mixer, create_maxsat_cl_cost_function, create_maxsat_cost_operator

clauses = [[1,2,-3],[1,4,-6],[4,5,6],[1,3,-4],[2,4,5],[1,3,5],[-2,-3,6]]
num_variables = 6
qarg = QuantumVariable(num_variables)
num_vars = 6
problem = (num_vars, clauses)
qarg = QuantumVariable(num_vars)

qaoa_max_indep_set = QAOAProblem(cost_operator=create_maxsat_cost_operator(clauses),
qaoa_max_indep_set = QAOAProblem(cost_operator=create_maxsat_cost_operator(problem),
mixer=RX_mixer,
cl_cost_function=create_maxsat_cl_cost_function(clauses))
cl_cost_function=create_maxsat_cl_cost_function(problem))
results = qaoa_max_indep_set.run(qarg=qarg, depth=5)

That's it! Feel free to experiment with the ``init_type='tqa'`` option in the :meth:`.run <qrisp.qaoa.QAOAProblem.run>` method for improved performance.
In the following, we print the 5 most likely solutions together with their cost values.

::
cl_cost = create_maxsat_cl_cost_function(clauses)
cl_cost = create_maxsat_cl_cost_function(problem)

print("5 most likely solutions")
max_five = sorted(results.items(), key=lambda item: item[1], reverse=True)[:5]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ Quantum Informed Recursive Optimization
.. toctree::
:hidden:

qiroProblems/QIROProblem
qiroProblems/QIROImplemens
QIROProblem
QIROImplementations


An algorithm to facilitate the functionality of Quantum Informed Recursive Optimizations, as developed by J. Finzgar et. al. in `Quantum-Informed Recursive Optimization Algorithms (2023) <https://arxiv.org/abs/2308.13607>`_ .
An algorithm to facilitate the functionality of Quantum Informed Recursive Optimizations, as developed by J. Finzgar et. al. in `Quantum-Informed Recursive Optimization Algorithms (2023) <https://journals.aps.org/prxquantum/abstract/10.1103/PRXQuantum.5.020327>`_ .

It is based on updating the problem instance based on correlations, that are in turn established with a QAOA protocol. For further info have a look at our :ref:`tutorial on QIRO! <qiro_tutorial>`

Expand All @@ -24,16 +24,15 @@ The central data structure of the QIRO module is the :ref:`QIROProblem` class.

The :ref:`QIROProblem` encapsulates the required prerequesites to run the algorithm:

* The ``problem`` to be solved, which is not necessarly a graph,
* the ``replacement_routine``, which has the job of performing the aforementioned specific reductions to the ``problem`` object,
* The ``cost_operator``, ``mixer``, ``init_function`` and ``cl_cost_function`` in analogy to :ref:`QAOAProblem` instanciation.
* The ``problem`` to be solved, which is not necessarly a graph.
* The ``replacement_routine``, which has the job of performing the aforementioned specific reductions to the ``problem`` object.
* The ``cost_operator``, ``mixer``, ``init_function`` and ``cl_cost_function`` in analogy to :ref:`QAOAProblem` instantiation.


.. _QIROMiXers:

Collection of mixers and suplementary material
----------------------------------------------
Qrisp comes with a variety of predefined mixers to tackle various types of problem instances:
Collection of mixers and auxiliary functions
--------------------------------------------

.. autosummary::

Expand All @@ -45,7 +44,7 @@ Qrisp comes with a variety of predefined mixers to tackle various types of probl
QIRO implementations of problem instances
-----------------------------------------

For implemented problem instances see :ref:`the QIRO implementations page <QIROImplemens>`
For implemented problem instances see :ref:`the QIRO implementations page <QIROImplementations>`



Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

.. _QIROImplementations:

.. currentmodule:: qrisp.qiro

Implementations
===============

.. toctree::
:hidden:

implementations/QIROMaxClique
implementations/QIROMaxIndep
implementations/QIROMaxSat
implementations/QIROMaxSetPack


Here, you can find the QIRO implementations for specific problem instances, namely:


* :ref:`MaxIndependentSet <maxIndependentSetQIRO>`
* :ref:`MaxClique <maxCliqueQIRO>`
* :ref:`MaxSat <maxSatQIRO>`
* :ref:`MaxSetPacking <maxSetPackingQIRO>`






Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

.. currentmodule:: qrisp.qiro


QIROProblem
===========

.. currentmodule:: qrisp.qiro
.. autoclass:: QIROProblem


Methods
=======

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
.. _maxcliqueQIRO:

QIRO MaxClique
==============

.. currentmodule:: qrisp.qiro.qiroproblems.qiroMaxClique


Problem description
-------------------

Given a Graph :math:`G = (V,E)` maximize the size of a clique, i.e. a subset :math:`V' \subset V` in which all pairs of vertices are adjacent.


Replacement routine
-------------------

In this instance the replacements can be rather significant. In-depth investigation may show relaxations to be perform better on larger instances.
Based on the **maximum absolute entry** of the correlation matrix M and its sign, one of the following replacements is employed:

* If :math:`\text{M}_{ii} \geq 0` is the maximum absolute value, then the :math:`i`-th vertex is set to be in the clique set. In turn, all vertices that **do not share an edge with this vertex can be removed from the graph**, since including them in the solution would violate the problem constraints.

* If :math:`\text{M}_{ii} < 0` is the maximum absolute value, we remove :math:`i`-th vertex from the graph.

* If :math:`\text{M}_{ij} > 0, (i, j) ∈ E` was selected, we keep both vertices as part of the solution and remove all non-neighboring vertices. The likelihood of this rule failing is low, but remains to be investigated.

* If :math:`\text{M}_{ij} < 0, (i, j) ∈ E` was selected, we remove all vertices that **do not** share an edge with either vertex :math:`i` or :math:`j`. Since one of the vertices :math:`i` and :math:`j` will be part of the final solution (but not both), any vertex that is **not** connected to either :math:`i` or :math:`j` (or both) is guaranteed to violate the problem constraints, and can be removed from the graph.


.. autofunction:: create_max_clique_replacement_routine


QIRO Cost operator
------------------

.. autofunction:: create_max_clique_cost_operator_reduced


Example implementation
----------------------

::

from qrisp import QuantumVariable
from qrisp.qiro import QIROProblem, create_max_clique_replacement_routine, create_max_clique_cost_operator_reduced, qiro_RXMixer, qiro_init_function
from qrisp.qaoa import max_clique_problem, create_max_clique_cl_cost_function
import matplotlib.pyplot as plt
import networkx as nx

# Define a random graph via the number of nodes and the QuantumVariable arguments
num_nodes = 15
G = nx.erdos_renyi_graph(num_nodes, 0.7, seed=99)
qarg = QuantumVariable(G.number_of_nodes())

# QIRO
qiro_instance = QIROProblem(problem=G,
replacement_routine= reate_max_clique_replacement_routine,
cost_operator=create_max_clique_cost_operator_reduced,
mixer=qiro_RXMixer,
cl_cost_function=create_max_clique_cl_cost_function,
init_function=qiro_init_function
)
res_qiro = qiro_instance.run_qiro(qarg=qarg, depth=3, n_recursions=2)

# The final graph that has been adjusted
final_graph = qiro_instance.problem

That’s it! In the following, we print the 5 most likely solutions together with their cost values, and compare to the NetworkX solution.

::

cl_cost = create_max_clique_cl_cost_function(G)
print("5 most likely QIRO solutions")
max_five_qiro = sorted(res_qiro, key=res_qiro.get, reverse=True)[:5]
for res in max_five_qiro:
print([index for index, value in enumerate(res) if value == '1'])
print(cl_cost({res : 1}))

print("Networkx solution")
print(nx.approximation.max_clique(G))

Finally, we visualize the final QIRO graph and the most likely solution.

::

# Draw the final graph and the original graph for comparison
plt.figure(1)
nx.draw(final_graph, with_labels=True, node_color='#ADD8E6', edge_color='#D3D3D3')
plt.title('Final QIRO graph')

plt.figure(2)
most_likely = [index for index, value in enumerate(max_five_qiro[0]) if value == '1']
nx.draw(G, with_labels=True,
node_color=['#FFCCCB' if node in most_likely else '#ADD8E6' for node in G.nodes()],
edge_color=['#FFCCCB' if edge[0] in most_likely and edge[1] in most_likely else '#D3D3D3' for edge in G.edges()])
plt.title('Original graph with most likely QIRO solution')
plt.show()
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
.. _maxIndependentSetQIRO:

QIRO MaxIndepSet
================

.. currentmodule:: qrisp.qiro.qiroproblems.qiroMaxIndepSet


Problem description
-------------------

Given a Graph :math:`G = (V,E)` maximize the size of an independent set, i.e. a subset :math:`V' \subset V` in which all pairs of vertices are mutually non-adjacent.


Replacement routine
-------------------

Based on the **maximum absolute entry** of the correlation matrix M and its sign, one of the following replacements is employed:

* If :math:`\text{M}_{ii} \geq 0` is the maximum absolute value, then the :math:`i`-th vertex is set to be in the independent set (IS). In turn, all vertices that share an edge with this vertex can be removed from the graph, since including them in the solution would violate the problem constraints.

* If :math:`\text{M}_{ii} < 0` is the maximum absolute value, we remove :math:`i`-th vertex from the graph.

* If :math:`\text{M}_{ij} > 0, (i, j) ∈ E` was selected, we remove both vertices from the graph with the argument, that, since both of them would be in the same state in the final solution, including both as part of the solution would violate the constraint, as they share an edge. In turn, they can be removed from the graph.

* If :math:`\text{M}_{ij} < 0, (i, j) ∈ E` was selected, we remove all vertices that share an edge with both vertices :math:`i` and :math:`j`. Since one of the vertices :math:`i` and :math:`j` will be part of the final solution (but not both), any vertex that is connected to both :math:`i` and :math:`j` is guaranteed to violate the problem constraints, and can be removed from the graph. In this case, it may be possible that no vertex is found to be a canditate for being removed. We will then simply choose the second biggest absolute value of **M** for the replacement routine.


.. autofunction:: create_max_indep_replacement_routine


QIRO Cost operator
------------------

.. autofunction:: create_max_indep_cost_operator_reduced


Example implementation
----------------------
::

from qrisp import QuantumVariable
from qrisp.qiro import QIROProblem, create_max_indep_replacement_routine, create_max_indep_cost_operator_reduced, qiro_RXMixer, qiro_init_function
from qrisp.qaoa import create_max_indep_set_cl_cost_function
import matplotlib.pyplot as plt
import networkx as nx

# Define a random graph via the number of nodes and the QuantumVariable arguments
num_nodes = 13
G = nx.erdos_renyi_graph(num_nodes, 0.4, seed = 107)
qarg = QuantumVariable(G.number_of_nodes())

qiro_instance = QIROProblem(G,
replacement_routine=create_max_indep_replacement_routine,
cost_operator=create_max_indep_cost_operator_reduced,
mixer=qiro_RXMixer,
cl_cost_function=create_max_indep_set_cl_cost_function,
init_function=qiro_init_function
)
res_qiro = qiro_instance.run_qiro(qarg=qarg, depth=3, n_recursions=2)

That’s it! In the following, we print the 5 most likely solutions together with their cost values, and compare to the NetworkX solution.

::
cl_cost = create_max_indep_set_cl_cost_function(G)

print("5 most likely QIRO solutions")
max_five_qiro = sorted(res_qiro, key=res_qiro.get, reverse=True)[:5]
for res in max_five_qiro:
print([index for index, value in enumerate(res) if value == '1'])
print(cl_cost({res : 1}))

print("Networkx solution")
print(nx.approximation.maximum_independent_set(G))

Finally, we visualize the final QIRO graph and the most likely solution.

::

# The final graph that has been adjusted
final_graph = qiro_instance.problem
# Draw the final graph and the original graph for comparison
plt.figure(1)
nx.draw(final_graph, with_labels=True, node_color='#ADD8E6', edge_color='#D3D3D3')
plt.title('Final QIRO graph')

plt.figure(2)
most_likely = [index for index, value in enumerate(max_five_qiro[0]) if value == '1']
nx.draw(G, with_labels=True,
node_color=['#FFCCCB' if node in most_likely else '#ADD8E6' for node in G.nodes()],
edge_color='#D3D3D3')
plt.title('Original graph with most likely QIRO solution')
plt.show()
Loading

0 comments on commit 2549813

Please sign in to comment.