diff --git a/qiskit/qubo/qubo_qiskit.py b/qiskit/qubo/qubo_qiskit.py
new file mode 100644
index 00000000..44291144
--- /dev/null
+++ b/qiskit/qubo/qubo_qiskit.py
@@ -0,0 +1,42 @@
+import copy
+import sys
+
+from qiskit.algorithms.minimum_eigensolvers import QAOA
+from qiskit.algorithms.optimizers import COBYLA
+from qiskit.primitives import Sampler
+from qiskit_optimization import QuadraticProgram
+from qiskit_optimization.algorithms import MinimumEigenOptimizer
+from qiskit_optimization.problems import VarType
+
+if len(sys.argv) != 3:
+ raise TypeError('This script expects exactly 2 arguments. Input file (argument 1) and output file (argument 2).')
+
+input_path = sys.argv[1]
+output_path = sys.argv[2]
+
+qp = QuadraticProgram()
+qp.read_from_lp_file(input_path)
+
+
+def relax_problem(problem):
+ """Change all variables to continuous."""
+ relaxed_problem = copy.deepcopy(problem)
+ for variable in relaxed_problem.variables:
+ variable.vartype = VarType.CONTINUOUS
+
+ return relaxed_problem
+
+qubo = qp
+# qubo = relax_problem(QuadraticProgramToQubo().convert(qp))
+# print(qp.prettyprint())
+
+qaoa_mes = QAOA(Sampler(), optimizer=COBYLA(), initial_point=[0.0, 1.0])
+
+qaoa = MinimumEigenOptimizer(qaoa_mes)
+
+qaoa_result = qaoa.solve(qubo)
+print(qaoa_result.prettyprint())
+
+f = open(output_path, 'w')
+f.write(qaoa_result.prettyprint())
+f.close()
diff --git a/qiskit/requirements.txt b/qiskit/requirements.txt
index b0bb8f99..f04ef842 100644
--- a/qiskit/requirements.txt
+++ b/qiskit/requirements.txt
@@ -5,5 +5,5 @@
numpy
pygmlparser
qiskit == 0.44.*
-qiskit_optimization
+qiskit_optimization[cplex]
qiskit-aer
diff --git a/src/main/java/edu/kit/provideq/toolbox/meta/ProblemType.java b/src/main/java/edu/kit/provideq/toolbox/meta/ProblemType.java
index 49d081b4..142a9875 100644
--- a/src/main/java/edu/kit/provideq/toolbox/meta/ProblemType.java
+++ b/src/main/java/edu/kit/provideq/toolbox/meta/ProblemType.java
@@ -4,6 +4,7 @@
import edu.kit.provideq.toolbox.SolveRequest;
import edu.kit.provideq.toolbox.featuremodel.SolveFeatureModelRequest;
import edu.kit.provideq.toolbox.maxcut.SolveMaxCutRequest;
+import edu.kit.provideq.toolbox.qubo.SolveQuboRequest;
import edu.kit.provideq.toolbox.sat.SolveSatRequest;
/**
@@ -38,7 +39,14 @@ public enum ProblemType {
* @see
* "Explaining Anomalies in Feature Models", Kowal et al., 2026
*/
- FEATURE_MODEL_ANOMALY_VOID("feature-model-anomaly-void", SolveFeatureModelRequest.class);
+ FEATURE_MODEL_ANOMALY_VOID("feature-model-anomaly-void", SolveFeatureModelRequest.class),
+ /**
+ * QUBO (Quadratic Unconstrained Binary Optimization)
+ * A combinatorial optimization problem.
+ * For a given quadratic term with binary decision variables,
+ * find the minimal variable assignment of the term.
+ */
+ QUBO("qubo", SolveQuboRequest.class);
private final String id;
private final Class extends SolveRequest>> requestType;
diff --git a/src/main/java/edu/kit/provideq/toolbox/qubo/QuboMetaSolver.java b/src/main/java/edu/kit/provideq/toolbox/qubo/QuboMetaSolver.java
new file mode 100644
index 00000000..7458e573
--- /dev/null
+++ b/src/main/java/edu/kit/provideq/toolbox/qubo/QuboMetaSolver.java
@@ -0,0 +1,44 @@
+package edu.kit.provideq.toolbox.qubo;
+
+import edu.kit.provideq.toolbox.meta.MetaSolver;
+import edu.kit.provideq.toolbox.meta.Problem;
+import edu.kit.provideq.toolbox.meta.ProblemType;
+import edu.kit.provideq.toolbox.meta.setting.MetaSolverSetting;
+import edu.kit.provideq.toolbox.qubo.solvers.QiskitQuboSolver;
+import edu.kit.provideq.toolbox.qubo.solvers.QuboSolver;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * Simple {@link MetaSolver} for MaxCut problems.
+ */
+@Component
+public class QuboMetaSolver extends MetaSolver {
+
+ @Autowired
+ public QuboMetaSolver(QiskitQuboSolver qiskitQuboSolver) {
+ super(ProblemType.QUBO, qiskitQuboSolver);
+ }
+
+ @Override
+ public QuboSolver findSolver(
+ Problem problem,
+ List metaSolverSettings) {
+ return (new ArrayList<>(this.solvers)).get((new Random()).nextInt(this.solvers.size()));
+ }
+
+ @Override
+ public List getExampleProblems() {
+ return List.of("""
+ Maximize
+ 3x + y
+ Subject To
+ Binary
+ x y
+ End
+ """);
+ }
+}
diff --git a/src/main/java/edu/kit/provideq/toolbox/qubo/SolveQuboRequest.java b/src/main/java/edu/kit/provideq/toolbox/qubo/SolveQuboRequest.java
new file mode 100644
index 00000000..47381ab8
--- /dev/null
+++ b/src/main/java/edu/kit/provideq/toolbox/qubo/SolveQuboRequest.java
@@ -0,0 +1,11 @@
+package edu.kit.provideq.toolbox.qubo;
+
+import edu.kit.provideq.toolbox.SolveRequest;
+
+/**
+ * POST Requests to /solve/qubo should have a response body of this form.
+ * The needed formula the qubo formula to solve in the
+ * LP format.
+ */
+public class SolveQuboRequest extends SolveRequest {
+}
diff --git a/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QiskitQuboSolver.java b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QiskitQuboSolver.java
new file mode 100644
index 00000000..371370cf
--- /dev/null
+++ b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QiskitQuboSolver.java
@@ -0,0 +1,60 @@
+package edu.kit.provideq.toolbox.qubo.solvers;
+
+import edu.kit.provideq.toolbox.PythonProcessRunner;
+import edu.kit.provideq.toolbox.Solution;
+import edu.kit.provideq.toolbox.SubRoutinePool;
+import edu.kit.provideq.toolbox.meta.Problem;
+import edu.kit.provideq.toolbox.meta.ProblemType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Component;
+
+@Component
+public class QiskitQuboSolver extends QuboSolver {
+ private final String quboPath;
+ private final ApplicationContext context;
+
+ @Autowired
+ public QiskitQuboSolver(
+ @Value("${qiskit.directory.qubo}") String quboPath,
+ ApplicationContext context) {
+ this.quboPath = quboPath;
+ this.context = context;
+ }
+
+ @Override
+ public String getName() {
+ return "Qiskit Qubo";
+ }
+
+ @Override
+ public boolean canSolve(Problem problem) {
+ return problem.type() == ProblemType.QUBO;
+ }
+
+ @Override
+ public void solve(Problem problem, Solution solution,
+ SubRoutinePool subRoutinePool) {
+ // Run Qiskit solver via console
+ var processResult = context
+ .getBean(
+ PythonProcessRunner.class,
+ quboPath,
+ "qubo_qiskit.py")
+ .addProblemFilePathToProcessCommand()
+ .addSolutionFilePathToProcessCommand()
+ .problemFileName("problem.lp")
+ .run(problem.type(), solution.getId(), problem.problemData());
+
+ // Return if process failed
+ if (!processResult.success()) {
+ solution.setDebugData(processResult.output());
+ solution.abort();
+ return;
+ }
+
+ solution.setSolutionData(processResult.output());
+ solution.complete();
+ }
+}
diff --git a/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QuboSolver.java b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QuboSolver.java
new file mode 100644
index 00000000..3224ecd8
--- /dev/null
+++ b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QuboSolver.java
@@ -0,0 +1,6 @@
+package edu.kit.provideq.toolbox.qubo.solvers;
+
+import edu.kit.provideq.toolbox.meta.ProblemSolver;
+
+public abstract class QuboSolver implements ProblemSolver {
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index a179b8b9..3d1d213e 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -6,6 +6,7 @@ gams.directory.sat=${gams.directory}/sat
qiskit.directory=qiskit
qiskit.directory.max-cut=${qiskit.directory}/max-cut
+qiskit.directory.qubo=${qiskit.directory}/qubo
cirq.directory=cirq
cirq.directory.max-cut=${cirq.directory}/max-cut