From 168449133e3a5d9edc8f9c9a2aef50b3b39e9ee1 Mon Sep 17 00:00:00 2001 From: ekulos-code Date: Wed, 29 Jan 2025 15:15:59 +0100 Subject: [PATCH 01/39] Add basic structure for OpenQASM processing --- .../CircuitProcessingConfiguration.java | 39 +++++++++++++ .../solver/CircuitProcessingSolver.java | 12 ++++ .../solver/MoveToExecutionSolver.java | 58 +++++++++++++++++++ .../solver/MoveToMitigationSolver.java | 44 ++++++++++++++ .../solver/MoveToOptimizationSolver.java | 44 ++++++++++++++ .../solver/executor/ExecutionResult.java | 13 +++++ .../solver/executor/ExecutionSolver.java | 36 ++++++++++++ .../executor/ExecutorConfiguration.java | 32 ++++++++++ .../ErrorMitigationConfiguration.java | 34 +++++++++++ .../mitigation/ErrorMitigationSolver.java | 35 +++++++++++ .../OptimizationConfiguration.java | 32 ++++++++++ .../optimization/OptimizationSolver.java | 35 +++++++++++ 12 files changed, 414 insertions(+) create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionResult.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java new file mode 100644 index 00000000..193657ce --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java @@ -0,0 +1,39 @@ +package edu.kit.provideq.toolbox.circuit.processing; + +import edu.kit.provideq.toolbox.circuit.processing.solver.MoveToExecutionSolver; +import edu.kit.provideq.toolbox.circuit.processing.solver.MoveToMitigationSolver; +import edu.kit.provideq.toolbox.circuit.processing.solver.MoveToOptimizationSolver; +import edu.kit.provideq.toolbox.meta.Problem; +import edu.kit.provideq.toolbox.meta.ProblemManager; +import edu.kit.provideq.toolbox.meta.ProblemType; +import java.util.Set; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class CircuitProcessingConfiguration { + public static final ProblemType CIRCUIT_PROCESSING = new ProblemType<>( + "circuit-processing", + String.class, + String.class, + null + ); + + @Bean + ProblemManager getCircuitProcessingManager( + MoveToExecutionSolver moveToExecutionSolver, + MoveToOptimizationSolver moveToOptimizationSolver, + MoveToMitigationSolver moveToMitigationSolver + ) { + return new ProblemManager<>( + CIRCUIT_PROCESSING, + Set.of( + moveToExecutionSolver, + moveToOptimizationSolver, + moveToMitigationSolver + ), + // TODO: dummy problem + Set.of(new Problem<>(CIRCUIT_PROCESSING)) + ); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java new file mode 100644 index 00000000..7c978ad2 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java @@ -0,0 +1,12 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver; + +import edu.kit.provideq.toolbox.circuit.processing.CircuitProcessingConfiguration; +import edu.kit.provideq.toolbox.meta.ProblemSolver; +import edu.kit.provideq.toolbox.meta.ProblemType; + +public abstract class CircuitProcessingSolver implements ProblemSolver { + @Override + public ProblemType getProblemType() { + return CircuitProcessingConfiguration.CIRCUIT_PROCESSING; + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java new file mode 100644 index 00000000..19d555c8 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java @@ -0,0 +1,58 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver; + +import edu.kit.provideq.toolbox.Solution; +import edu.kit.provideq.toolbox.SolutionStatus; +import edu.kit.provideq.toolbox.circuit.processing.solver.executor.ExecutionResult; +import edu.kit.provideq.toolbox.circuit.processing.solver.executor.ExecutorConfiguration; +import edu.kit.provideq.toolbox.meta.SolvingProperties; +import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; +import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import java.util.List; + +@Component +public class MoveToExecutionSolver extends CircuitProcessingSolver { + private static final SubRoutineDefinition EXECUTOR_SUBROUTINE = + new SubRoutineDefinition<>( + ExecutorConfiguration.EXECUTOR_CONFIG, + "Creates a execution solver" + ); + + @Override + public String getName() { + return "Execute QASM Code"; + } + + @Override + public String getDescription() { + return "Move QASM input to the executors"; + } + + @Override + public List> getSubRoutines() { + return List.of(EXECUTOR_SUBROUTINE); + } + + @Override + public Mono> solve( + String input, + SubRoutineResolver subRoutineResolver, + SolvingProperties properties + ) { + return subRoutineResolver.runSubRoutine(EXECUTOR_SUBROUTINE, input) + .map(executionResultSolution -> { + Solution solution = new Solution<>(this); + SolutionStatus status = executionResultSolution.getStatus(); + if (status == SolutionStatus.ERROR) { + solution.fail(); + solution.setDebugData("An error occurred while executing the circuit"); + return solution; + } + solution.complete(); + solution.setSolutionData(executionResultSolution.getSolutionData().toString()); + return solution; + }); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java new file mode 100644 index 00000000..4c70a353 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java @@ -0,0 +1,44 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver; + +import edu.kit.provideq.toolbox.Solution; +import edu.kit.provideq.toolbox.circuit.processing.solver.mitigation.ErrorMitigationConfiguration; +import edu.kit.provideq.toolbox.meta.SolvingProperties; +import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; +import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import java.util.List; + +@Component +public class MoveToMitigationSolver extends CircuitProcessingSolver { + private static final SubRoutineDefinition MITIGATOR_SUBROUTINE = + new SubRoutineDefinition<>( + ErrorMitigationConfiguration.MITIGATION_CONFIG, + "Creates a mitigation solver" + ); + + @Override + public String getName() { + return "Mitigate QASM Code Errors"; + } + + @Override + public String getDescription() { + return "Move QASM input to the error mitigators"; + } + + @Override + public List> getSubRoutines() { + return List.of(MITIGATOR_SUBROUTINE); + } + + @Override + public Mono> solve( + String input, + SubRoutineResolver subRoutineResolver, + SolvingProperties properties + ) { + return subRoutineResolver.runSubRoutine(MITIGATOR_SUBROUTINE, input); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java new file mode 100644 index 00000000..a6d938f6 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java @@ -0,0 +1,44 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver; + +import edu.kit.provideq.toolbox.Solution; +import edu.kit.provideq.toolbox.circuit.processing.solver.optimization.OptimizationConfiguration; +import edu.kit.provideq.toolbox.meta.SolvingProperties; +import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; +import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import java.util.List; + +@Component +public class MoveToOptimizationSolver extends CircuitProcessingSolver { + private static final SubRoutineDefinition OPTIMIZER_SUBROUTINE = + new SubRoutineDefinition<>( + OptimizationConfiguration.OPTIMIZATION_CONFIG, + "Creates a optimization solver" + ); + + @Override + public String getName() { + return "Optimize QASM Code"; + } + + @Override + public String getDescription() { + return "Move QASM input to the optimizers"; + } + + @Override + public List> getSubRoutines() { + return List.of(OPTIMIZER_SUBROUTINE); + } + + @Override + public Mono> solve( + String input, + SubRoutineResolver subRoutineResolver, + SolvingProperties properties + ) { + return subRoutineResolver.runSubRoutine(OPTIMIZER_SUBROUTINE, input); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionResult.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionResult.java new file mode 100644 index 00000000..4751c2b7 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionResult.java @@ -0,0 +1,13 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver.executor; + +import java.util.Optional; + +public record ExecutionResult(Optional resultString, Optional circuit) { + public boolean hasResult() { + return resultString.isPresent(); + } + + public boolean hasCircuit() { + return circuit.isPresent(); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java new file mode 100644 index 00000000..9043bdea --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java @@ -0,0 +1,36 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver.executor; + +import edu.kit.provideq.toolbox.Solution; +import edu.kit.provideq.toolbox.meta.ProblemSolver; +import edu.kit.provideq.toolbox.meta.ProblemType; +import edu.kit.provideq.toolbox.meta.SolvingProperties; +import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import java.util.Optional; + +@Component +public class ExecutionSolver implements ProblemSolver { + @Override + public String getName() { + return "Execute OpenQASM circuit"; + } + + @Override + public String getDescription() { + return "Execute an OpenQASM circuit"; + } + + @Override + public Mono> solve(String input, SubRoutineResolver subRoutineResolver, SolvingProperties properties) { + var solution = new Solution<>(this); + solution.setSolutionData(new ExecutionResult(Optional.of(input), Optional.empty())); + return Mono.just(solution); + } + + @Override + public ProblemType getProblemType() { + return ExecutorConfiguration.EXECUTOR_CONFIG; + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java new file mode 100644 index 00000000..d93390f2 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java @@ -0,0 +1,32 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver.executor; + +import edu.kit.provideq.toolbox.meta.Problem; +import edu.kit.provideq.toolbox.meta.ProblemManager; +import edu.kit.provideq.toolbox.meta.ProblemType; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Set; + +@Configuration +public class ExecutorConfiguration { + public static final ProblemType EXECUTOR_CONFIG = new ProblemType<>( + "circuit-processing-executor", + String.class, + ExecutionResult.class, + null + ); + + @Bean + ProblemManager getExecutorProblemManager( + ExecutionSolver executionSolver + ) { + return new ProblemManager<>( + EXECUTOR_CONFIG, + Set.of( + executionSolver + ), + Set.of(new Problem<>(EXECUTOR_CONFIG)) + ); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java new file mode 100644 index 00000000..953efc12 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java @@ -0,0 +1,34 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver.mitigation; + +import edu.kit.provideq.toolbox.circuit.processing.solver.executor.ExecutionResult; +import edu.kit.provideq.toolbox.circuit.processing.solver.executor.ExecutionSolver; +import edu.kit.provideq.toolbox.meta.Problem; +import edu.kit.provideq.toolbox.meta.ProblemManager; +import edu.kit.provideq.toolbox.meta.ProblemType; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Set; + +@Configuration +public class ErrorMitigationConfiguration { + public static final ProblemType MITIGATION_CONFIG = new ProblemType<>( + "circuit-processing-mitigation", + String.class, + String.class, + null + ); + + @Bean + ProblemManager getMitigationProblemManager( + ErrorMitigationSolver errorMitigationSolver + ) { + return new ProblemManager<>( + MITIGATION_CONFIG, + Set.of( + errorMitigationSolver + ), + Set.of(new Problem<>(MITIGATION_CONFIG)) + ); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java new file mode 100644 index 00000000..5c70686a --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java @@ -0,0 +1,35 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver.mitigation; + +import edu.kit.provideq.toolbox.Solution; +import edu.kit.provideq.toolbox.meta.ProblemSolver; +import edu.kit.provideq.toolbox.meta.ProblemType; +import edu.kit.provideq.toolbox.meta.SolvingProperties; +import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +@Component +public class ErrorMitigationSolver implements ProblemSolver { + + @Override + public String getName() { + return "Mitigate Errors for OpenQASM"; + } + + @Override + public String getDescription() { + return "Run error mitigation strategies on an OpenQASM circuit"; + } + + @Override + public Mono> solve(String input, SubRoutineResolver subRoutineResolver, SolvingProperties properties) { + var solution = new Solution<>(this); + solution.setSolutionData(input); + return Mono.just(solution); + } + + @Override + public ProblemType getProblemType() { + return ErrorMitigationConfiguration.MITIGATION_CONFIG; + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java new file mode 100644 index 00000000..78dfbbfd --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java @@ -0,0 +1,32 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver.optimization; + +import edu.kit.provideq.toolbox.meta.Problem; +import edu.kit.provideq.toolbox.meta.ProblemManager; +import edu.kit.provideq.toolbox.meta.ProblemType; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Set; + +@Configuration +public class OptimizationConfiguration { + public static final ProblemType OPTIMIZATION_CONFIG = new ProblemType<>( + "circuit-processing-optimization", + String.class, + String.class, + null + ); + + @Bean + ProblemManager getOptimizationProblemManager( + OptimizationSolver optimizationSolver + ) { + return new ProblemManager<>( + OPTIMIZATION_CONFIG, + Set.of( + optimizationSolver + ), + Set.of(new Problem<>(OPTIMIZATION_CONFIG)) + ); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java new file mode 100644 index 00000000..fcf51939 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java @@ -0,0 +1,35 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver.optimization; + +import edu.kit.provideq.toolbox.Solution; +import edu.kit.provideq.toolbox.meta.ProblemSolver; +import edu.kit.provideq.toolbox.meta.ProblemType; +import edu.kit.provideq.toolbox.meta.SolvingProperties; +import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +@Component +public class OptimizationSolver implements ProblemSolver { + + @Override + public String getName() { + return "Optimize OpenQASM circuit"; + } + + @Override + public String getDescription() { + return "Run optimization algorithms on an OpenQASM circuit"; + } + + @Override + public Mono> solve(String input, SubRoutineResolver subRoutineResolver, SolvingProperties properties) { + var solution = new Solution<>(this); + solution.setSolutionData(input); + return Mono.just(solution); + } + + @Override + public ProblemType getProblemType() { + return OptimizationConfiguration.OPTIMIZATION_CONFIG; + } +} From 57e8ca0aafefd93bbe7ac9626204181f238832a6 Mon Sep 17 00:00:00 2001 From: ekulos-code Date: Mon, 10 Mar 2025 12:27:27 +0100 Subject: [PATCH 02/39] Add execution and optimization solvers --- .../decompose_multi_cx_optimizer.py | 19 ++++ .../remove_redundancies_optimizer.py | 19 ++++ .../aer-noisy/aer_noisy_executor.py | 27 +++++ .../default-executor/default_executor.py | 18 +++ .../projectq-executor/projectq_executor.py | 17 +++ .../qulacs-executor/qulacs_executor.py | 18 +++ solvers/circuitprocessing/requirements.txt | 5 + .../CircuitProcessingConfiguration.java | 21 +++- .../solver/CircuitProcessingSolver.java | 7 ++ .../solver/MoveToExecutionSolver.java | 2 +- .../solver/executor/ExecutionSolver.java | 100 +++++++++++++++- .../optimization/OptimizationSolver.java | 107 +++++++++++++++++- src/main/resources/application.properties | 3 + 13 files changed, 353 insertions(+), 10 deletions(-) create mode 100644 solvers/circuitoptimizing/decompose-multi-cx/decompose_multi_cx_optimizer.py create mode 100644 solvers/circuitoptimizing/remove-redundancies/remove_redundancies_optimizer.py create mode 100644 solvers/circuitprocessing/aer-noisy/aer_noisy_executor.py create mode 100644 solvers/circuitprocessing/default-executor/default_executor.py create mode 100644 solvers/circuitprocessing/projectq-executor/projectq_executor.py create mode 100644 solvers/circuitprocessing/qulacs-executor/qulacs_executor.py create mode 100644 solvers/circuitprocessing/requirements.txt diff --git a/solvers/circuitoptimizing/decompose-multi-cx/decompose_multi_cx_optimizer.py b/solvers/circuitoptimizing/decompose-multi-cx/decompose_multi_cx_optimizer.py new file mode 100644 index 00000000..3d62f964 --- /dev/null +++ b/solvers/circuitoptimizing/decompose-multi-cx/decompose_multi_cx_optimizer.py @@ -0,0 +1,19 @@ +import sys +from pytket.qasm import circuit_from_qasm_str, circuit_to_qasm_str +from pytket.predicates import CompilationUnit +from pytket.passes import DecomposeMultiQubitsCX + + +input_circuit = sys.argv[1] + +try: + circuit = circuit_from_qasm_str(input_circuit) +except Exception as e: + print("Was not able to convert to OpenQASM: ", e) + sys.exit(1) + +pass1 = DecomposeMultiQubitsCX() +cu = CompilationUnit(circuit) +pass1.apply(cu) + +print(circuit_to_qasm_str(cu.circuit)) \ No newline at end of file diff --git a/solvers/circuitoptimizing/remove-redundancies/remove_redundancies_optimizer.py b/solvers/circuitoptimizing/remove-redundancies/remove_redundancies_optimizer.py new file mode 100644 index 00000000..58b57e68 --- /dev/null +++ b/solvers/circuitoptimizing/remove-redundancies/remove_redundancies_optimizer.py @@ -0,0 +1,19 @@ +import sys +from pytket.qasm import circuit_from_qasm_str, circuit_to_qasm_str +from pytket.predicates import CompilationUnit +from pytket.passes import RemoveRedundancies + + +input_circuit = sys.argv[1] + +try: + circuit = circuit_from_qasm_str(input_circuit) +except Exception as e: + print("Was not able to convert to OpenQASM: ", e) + sys.exit(1) + +pass1 = RemoveRedundancies() +cu = CompilationUnit(circuit) +pass1.apply(cu) + +print(circuit_to_qasm_str(cu.circuit)) \ No newline at end of file diff --git a/solvers/circuitprocessing/aer-noisy/aer_noisy_executor.py b/solvers/circuitprocessing/aer-noisy/aer_noisy_executor.py new file mode 100644 index 00000000..9db4439b --- /dev/null +++ b/solvers/circuitprocessing/aer-noisy/aer_noisy_executor.py @@ -0,0 +1,27 @@ +import sys +from pytket.qasm import circuit_from_qasm_str +from pytket.extensions.qiskit import AerBackend + +from qiskit_aer.noise import NoiseModel +from qiskit_aer.noise.errors import depolarizing_error + +input_circuit = sys.argv[1] +shots = sys.argv[2] + +try: + circuit = circuit_from_qasm_str(input_circuit) +except Exception as e: + print("Was not able to convert to OpenQASM: ", e) + sys.exit(1) + +# https://docs.quantinuum.com/tket/user-guide/manual/manual_noise.html +noise_model = NoiseModel() +noise_model.add_readout_error([[0.9, 0.1],[0.1, 0.9]], [0]) +noise_model.add_readout_error([[0.95, 0.05],[0.05, 0.95]], [1]) +noise_model.add_quantum_error(depolarizing_error(0.1, 2), ["cx"], [0, 1]) + +backend = AerBackend(noise_model) +c = backend.get_compiled_circuit(circuit) +handle = backend.process_circuit(c, n_shots=int(shots)) +counts = backend.get_result(handle).get_counts() +print(counts) \ No newline at end of file diff --git a/solvers/circuitprocessing/default-executor/default_executor.py b/solvers/circuitprocessing/default-executor/default_executor.py new file mode 100644 index 00000000..9ce98997 --- /dev/null +++ b/solvers/circuitprocessing/default-executor/default_executor.py @@ -0,0 +1,18 @@ +import sys +from pytket.qasm import circuit_from_qasm_str +from pytket.extensions.qiskit import AerBackend + +input_circuit = sys.argv[1] +shots = int(sys.argv[2]) + +try: + circuit = circuit_from_qasm_str(input_circuit) +except Exception as e: + print("Was not able to convert to OpenQASM: ", e) + sys.exit(1) + +backend = AerBackend() +c = backend.get_compiled_circuit(circuit) +handle = backend.process_circuit(c, n_shots=shots) +counts = backend.get_result(handle).get_counts() +print(counts) \ No newline at end of file diff --git a/solvers/circuitprocessing/projectq-executor/projectq_executor.py b/solvers/circuitprocessing/projectq-executor/projectq_executor.py new file mode 100644 index 00000000..8600c2bd --- /dev/null +++ b/solvers/circuitprocessing/projectq-executor/projectq_executor.py @@ -0,0 +1,17 @@ +import sys +from pytket.qasm import circuit_from_qasm_str +from pytket.extensions.projectq import ProjectQBackend + +input_circuit = sys.argv[1] +shots = int(sys.argv[2]) + +try: + circuit = circuit_from_qasm_str(input_circuit) +except Exception as e: + print("Was not able to convert to OpenQASM: ", e) + sys.exit(1) + +backend = ProjectQBackend() +handle = backend.process_circuit(circuit, n_shots=shots) +result = backend.get_result(handle) +print(result.get_shots()) \ No newline at end of file diff --git a/solvers/circuitprocessing/qulacs-executor/qulacs_executor.py b/solvers/circuitprocessing/qulacs-executor/qulacs_executor.py new file mode 100644 index 00000000..9652f6b0 --- /dev/null +++ b/solvers/circuitprocessing/qulacs-executor/qulacs_executor.py @@ -0,0 +1,18 @@ +import sys +from pytket.qasm import circuit_from_qasm_str +from pytket.extensions.qulacs import QulacsBackend + +input_circuit = sys.argv[1] +shots = int(sys.argv[2]) + +try: + circuit = circuit_from_qasm_str(input_circuit) +except Exception as e: + print("Was not able to convert to OpenQASM: ", e) + sys.exit(1) + +backend = QulacsBackend() +c = backend.get_compiled_circuit(circuit) +handle = backend.process_circuit(c, n_shots=shots) +counts = backend.get_result(handle).get_counts() +print(counts) \ No newline at end of file diff --git a/solvers/circuitprocessing/requirements.txt b/solvers/circuitprocessing/requirements.txt new file mode 100644 index 00000000..40a709cf --- /dev/null +++ b/solvers/circuitprocessing/requirements.txt @@ -0,0 +1,5 @@ +pytket +pytket-qiskit +pytket-pyquil +pytket-projectq +pytket-qulacs \ No newline at end of file diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java index 193657ce..2a72d788 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java @@ -25,6 +25,24 @@ ProblemManager getCircuitProcessingManager( MoveToOptimizationSolver moveToOptimizationSolver, MoveToMitigationSolver moveToMitigationSolver ) { + Problem demo = new Problem<>(CIRCUIT_PROCESSING); + demo.setInput(""" + OPENQASM 2.0; + include "qelib1.inc"; + qreg q[2]; + creg c[2]; + h q[0]; + cx q[0],q[1]; + measure q[0] -> c[0]; + measure q[1] -> c[1];"""); + Problem secondDemo = new Problem<>(CIRCUIT_PROCESSING); + secondDemo.setInput(""" + OPENQASM 2.0; + include "qelib1.inc"; + qreg q[3]; + crz(0.5) q[0], q[1]; + t q[2]; + cswap q[2], q[0], q[1];"""); return new ProblemManager<>( CIRCUIT_PROCESSING, Set.of( @@ -32,8 +50,7 @@ ProblemManager getCircuitProcessingManager( moveToOptimizationSolver, moveToMitigationSolver ), - // TODO: dummy problem - Set.of(new Problem<>(CIRCUIT_PROCESSING)) + Set.of(demo, secondDemo) ); } } diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java index 7c978ad2..507ce9c6 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java @@ -3,8 +3,15 @@ import edu.kit.provideq.toolbox.circuit.processing.CircuitProcessingConfiguration; import edu.kit.provideq.toolbox.meta.ProblemSolver; import edu.kit.provideq.toolbox.meta.ProblemType; +import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; public abstract class CircuitProcessingSolver implements ProblemSolver { + public static final SubRoutineDefinition CIRCUIT_PROCESSING_SUBROUTINE = + new SubRoutineDefinition<>( + CircuitProcessingConfiguration.CIRCUIT_PROCESSING, + "Creates a circuit processing solver" + ); + @Override public ProblemType getProblemType() { return CircuitProcessingConfiguration.CIRCUIT_PROCESSING; diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java index 19d555c8..8d919d7c 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java @@ -47,7 +47,7 @@ public Mono> solve( SolutionStatus status = executionResultSolution.getStatus(); if (status == SolutionStatus.ERROR) { solution.fail(); - solution.setDebugData("An error occurred while executing the circuit"); + solution.setDebugData(executionResultSolution.getDebugData()); return solution; } solution.complete(); diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java index 9043bdea..c96df7f1 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java @@ -5,13 +5,38 @@ import edu.kit.provideq.toolbox.meta.ProblemType; import edu.kit.provideq.toolbox.meta.SolvingProperties; import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import edu.kit.provideq.toolbox.meta.setting.SolverSetting; +import edu.kit.provideq.toolbox.meta.setting.basic.IntegerSetting; +import edu.kit.provideq.toolbox.meta.setting.basic.SelectSetting; +import edu.kit.provideq.toolbox.process.PythonProcessRunner; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; +import java.util.List; import java.util.Optional; @Component public class ExecutionSolver implements ProblemSolver { + private static final String SETTING_NUMBER_OF_SHOTS = "Number of shots"; + private static final String SETTING_SELECT_SIMULATOR = "Selected Simulator"; + private static final int DEFAULT_NUMBER_OF_SHOTS = 1024; + private static final QuantumSimulator DEFAULT_SIMULATOR = QuantumSimulator.AER; + + private final String scriptPath; + private final ApplicationContext context; + + @Autowired + public ExecutionSolver( + @Value("${circuitprocessing.base.directory}") String scriptPath, + ApplicationContext context + ) { + this.context = context; + this.scriptPath = scriptPath; + } + @Override public String getName() { return "Execute OpenQASM circuit"; @@ -22,10 +47,51 @@ public String getDescription() { return "Execute an OpenQASM circuit"; } + @Override + public List getSolverSettings() { + return List.of( + new IntegerSetting( + SETTING_NUMBER_OF_SHOTS, + "The number of shots to run", + 1, + 10000, + DEFAULT_NUMBER_OF_SHOTS), + new SelectSetting<>( + SETTING_SELECT_SIMULATOR, + "The simulator to run the code with", + List.of(QuantumSimulator.values()), + QuantumSimulator.AER, + QuantumSimulator::getValue + ) + ); + } + @Override public Mono> solve(String input, SubRoutineResolver subRoutineResolver, SolvingProperties properties) { var solution = new Solution<>(this); - solution.setSolutionData(new ExecutionResult(Optional.of(input), Optional.empty())); + + int shotNumber = properties.getSetting(SETTING_NUMBER_OF_SHOTS) + .map(IntegerSetting::getValue) + .orElse(DEFAULT_NUMBER_OF_SHOTS); + + QuantumSimulator selectedSimulator = properties + .>getSetting(SETTING_SELECT_SIMULATOR) + .map(s -> s.getSelectedOptionT(QuantumSimulator::fromValue)) + .orElse(DEFAULT_SIMULATOR); + + var processResult = context + .getBean(PythonProcessRunner.class, scriptPath + selectedSimulator.getScriptPath()) + .withArguments(input, String.valueOf(shotNumber)) + .readOutputString() + .run(getProblemType(), solution.getId()); + + if (processResult.success()) { + solution.complete(); + solution.setSolutionData(new ExecutionResult(processResult.output(), Optional.of(input))); + return Mono.just(solution); + } + solution.fail(); + processResult.errorOutput().ifPresent(solution::setDebugData); return Mono.just(solution); } @@ -33,4 +99,36 @@ public Mono> solve(String input, SubRoutineResolver su public ProblemType getProblemType() { return ExecutorConfiguration.EXECUTOR_CONFIG; } + + enum QuantumSimulator { + AER("AerBackend", "default-executor/default_executor.py"), + // PROJECTQ("ProjectQBackend", "projectq-executor/projectq_executor.py"), + QULACS("QulacsBackend", "qulacs-executor/qulacs_executor.py"), + AER_NOISY("Aer Noisy Backend (max. 2 qubits)", "aer-noisy/aer_noisy_executor.py"); + + private final String value; + private final String scriptPath; + + QuantumSimulator(String value, String scriptPath) { + this.value = value; + this.scriptPath = scriptPath; + } + + public String getValue() { + return value; + } + + public String getScriptPath() { + return scriptPath; + } + + public static QuantumSimulator fromValue(String value) { + for (QuantumSimulator simulator : values()) { + if (simulator.value.equals(value)) { + return simulator; + } + } + throw new IllegalArgumentException("Unknown value: " + value); + } + } } diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java index fcf51939..846fad84 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java @@ -1,15 +1,36 @@ package edu.kit.provideq.toolbox.circuit.processing.solver.optimization; import edu.kit.provideq.toolbox.Solution; -import edu.kit.provideq.toolbox.meta.ProblemSolver; -import edu.kit.provideq.toolbox.meta.ProblemType; -import edu.kit.provideq.toolbox.meta.SolvingProperties; -import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import edu.kit.provideq.toolbox.circuit.processing.solver.CircuitProcessingSolver; +import edu.kit.provideq.toolbox.meta.*; +import edu.kit.provideq.toolbox.meta.setting.SolverSetting; +import edu.kit.provideq.toolbox.meta.setting.basic.SelectSetting; +import edu.kit.provideq.toolbox.process.PythonProcessRunner; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; +import java.util.List; + @Component public class OptimizationSolver implements ProblemSolver { + private static final String SETTING_SELECT_OPTIMIZER = "Selected Optimization Pass"; + private static final OptimizationSolver.QuantumOptimizer DEFAULT_OPTIMIZER = + QuantumOptimizer.DECOMPOSE_MULTI_CX; + + private final String scriptPath; + private final ApplicationContext context; + + @Autowired + public OptimizationSolver( + @Value("${circuitoptimizing.base.directory}") String scriptPath, + ApplicationContext context + ) { + this.scriptPath = scriptPath; + this.context = context; + } @Override public String getName() { @@ -22,9 +43,51 @@ public String getDescription() { } @Override - public Mono> solve(String input, SubRoutineResolver subRoutineResolver, SolvingProperties properties) { + public List> getSubRoutines() { + return List.of(CircuitProcessingSolver.CIRCUIT_PROCESSING_SUBROUTINE); + } + + @Override + public List getSolverSettings() { + return List.of( + new SelectSetting<>( + SETTING_SELECT_OPTIMIZER, + "The optimization pass to refactor the code with", + List.of(OptimizationSolver.QuantumOptimizer.values()), + QuantumOptimizer.DECOMPOSE_MULTI_CX, + OptimizationSolver.QuantumOptimizer::getValue + ) + ); + } + + @Override + public Mono> solve( + String input, + SubRoutineResolver subRoutineResolver, + SolvingProperties properties + ) { var solution = new Solution<>(this); - solution.setSolutionData(input); + + OptimizationSolver.QuantumOptimizer selectedOptimizer = properties + .>getSetting(SETTING_SELECT_OPTIMIZER) + .map(s -> s.getSelectedOptionT(OptimizationSolver.QuantumOptimizer::fromValue)) + .orElse(DEFAULT_OPTIMIZER); + + var processResult = context + .getBean(PythonProcessRunner.class, scriptPath + selectedOptimizer.getScriptPath()) + .withArguments(input) + .readOutputString() + .run(getProblemType(), solution.getId()); + + if (processResult.success() && processResult.output().isPresent()) { + solution.complete(); + solution.setSolutionData(processResult.output().get()); + return subRoutineResolver + .runSubRoutine(CircuitProcessingSolver.CIRCUIT_PROCESSING_SUBROUTINE, + processResult.output().get()); + } + solution.fail(); + processResult.errorOutput().ifPresent(solution::setDebugData); return Mono.just(solution); } @@ -32,4 +95,36 @@ public Mono> solve(String input, SubRoutineResolver subRoutineR public ProblemType getProblemType() { return OptimizationConfiguration.OPTIMIZATION_CONFIG; } + + enum QuantumOptimizer { + DECOMPOSE_MULTI_CX("DecomposeMultiQubitsCX", + "decompose-multi-cx/decompose_multi_cx_optimizer.py"), + REMOVE_REDUNDANCIES("RemoveRedundancies", + "remove-redundancies/remove_redundancies_optimizer.py"); + + private final String value; + private final String scriptPath; + + QuantumOptimizer(String value, String scriptPath) { + this.value = value; + this.scriptPath = scriptPath; + } + + public String getValue() { + return value; + } + + public String getScriptPath() { + return scriptPath; + } + + public static OptimizationSolver.QuantumOptimizer fromValue(String value) { + for (OptimizationSolver.QuantumOptimizer simulator : values()) { + if (simulator.value.equals(value)) { + return simulator; + } + } + throw new IllegalArgumentException("Unknown value: " + value); + } + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index bd50b1eb..cbf3eb66 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -44,3 +44,6 @@ demonstrators.directory=demonstrators cplex.directory=${demonstrators.directory}/cplex cplex.directory.mip=${cplex.directory}/mip-solver/mip-solver.py + +circuitprocessing.base.directory=${solvers.directory}/circuitprocessing/ +circuitoptimizing.base.directory=${solvers.directory}/circuitoptimizing/ \ No newline at end of file From a7f335e7286f5e38707f2304cb9c563d312d39c2 Mon Sep 17 00:00:00 2001 From: ekulos-code Date: Mon, 10 Mar 2025 13:28:22 +0100 Subject: [PATCH 03/39] Merge dev, account for checkstyle errors --- .../processing/CircuitProcessingConfiguration.java | 3 +-- .../processing/solver/MoveToExecutionSolver.java | 3 +-- .../processing/solver/MoveToMitigationSolver.java | 3 +-- .../processing/solver/MoveToOptimizationSolver.java | 3 +-- .../processing/solver/executor/ExecutionSolver.java | 11 +++++++---- .../solver/executor/ExecutorConfiguration.java | 6 ++---- .../mitigation/ErrorMitigationConfiguration.java | 8 ++------ .../solver/mitigation/ErrorMitigationSolver.java | 6 +++++- .../optimization/OptimizationConfiguration.java | 6 ++---- .../solver/optimization/OptimizationSolver.java | 9 ++++++--- 10 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java index 2a72d788..c0092195 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java @@ -15,8 +15,7 @@ public class CircuitProcessingConfiguration { public static final ProblemType CIRCUIT_PROCESSING = new ProblemType<>( "circuit-processing", String.class, - String.class, - null + String.class ); @Bean diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java index 8d919d7c..8d1d6b60 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java @@ -7,11 +7,10 @@ import edu.kit.provideq.toolbox.meta.SolvingProperties; import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import java.util.List; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; -import java.util.List; - @Component public class MoveToExecutionSolver extends CircuitProcessingSolver { private static final SubRoutineDefinition EXECUTOR_SUBROUTINE = diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java index 4c70a353..56e68fcd 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java @@ -5,11 +5,10 @@ import edu.kit.provideq.toolbox.meta.SolvingProperties; import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import java.util.List; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; -import java.util.List; - @Component public class MoveToMitigationSolver extends CircuitProcessingSolver { private static final SubRoutineDefinition MITIGATOR_SUBROUTINE = diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java index a6d938f6..d213b4ec 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java @@ -5,11 +5,10 @@ import edu.kit.provideq.toolbox.meta.SolvingProperties; import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import java.util.List; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; -import java.util.List; - @Component public class MoveToOptimizationSolver extends CircuitProcessingSolver { private static final SubRoutineDefinition OPTIMIZER_SUBROUTINE = diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java index c96df7f1..58ed0aeb 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java @@ -9,15 +9,14 @@ import edu.kit.provideq.toolbox.meta.setting.basic.IntegerSetting; import edu.kit.provideq.toolbox.meta.setting.basic.SelectSetting; import edu.kit.provideq.toolbox.process.PythonProcessRunner; +import java.util.List; +import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; -import java.util.List; -import java.util.Optional; - @Component public class ExecutionSolver implements ProblemSolver { private static final String SETTING_NUMBER_OF_SHOTS = "Number of shots"; @@ -67,7 +66,11 @@ public List getSolverSettings() { } @Override - public Mono> solve(String input, SubRoutineResolver subRoutineResolver, SolvingProperties properties) { + public Mono> solve( + String input, + SubRoutineResolver subRoutineResolver, + SolvingProperties properties + ) { var solution = new Solution<>(this); int shotNumber = properties.getSetting(SETTING_NUMBER_OF_SHOTS) diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java index d93390f2..7701bc1a 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java @@ -3,18 +3,16 @@ import edu.kit.provideq.toolbox.meta.Problem; import edu.kit.provideq.toolbox.meta.ProblemManager; import edu.kit.provideq.toolbox.meta.ProblemType; +import java.util.Set; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.util.Set; - @Configuration public class ExecutorConfiguration { public static final ProblemType EXECUTOR_CONFIG = new ProblemType<>( "circuit-processing-executor", String.class, - ExecutionResult.class, - null + ExecutionResult.class ); @Bean diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java index 953efc12..26afe47f 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java @@ -1,22 +1,18 @@ package edu.kit.provideq.toolbox.circuit.processing.solver.mitigation; -import edu.kit.provideq.toolbox.circuit.processing.solver.executor.ExecutionResult; -import edu.kit.provideq.toolbox.circuit.processing.solver.executor.ExecutionSolver; import edu.kit.provideq.toolbox.meta.Problem; import edu.kit.provideq.toolbox.meta.ProblemManager; import edu.kit.provideq.toolbox.meta.ProblemType; +import java.util.Set; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.util.Set; - @Configuration public class ErrorMitigationConfiguration { public static final ProblemType MITIGATION_CONFIG = new ProblemType<>( "circuit-processing-mitigation", String.class, - String.class, - null + String.class ); @Bean diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java index 5c70686a..5f6c3f87 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java @@ -22,7 +22,11 @@ public String getDescription() { } @Override - public Mono> solve(String input, SubRoutineResolver subRoutineResolver, SolvingProperties properties) { + public Mono> solve( + String input, + SubRoutineResolver subRoutineResolver, + SolvingProperties properties + ) { var solution = new Solution<>(this); solution.setSolutionData(input); return Mono.just(solution); diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java index 78dfbbfd..bfbe3f17 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java @@ -3,18 +3,16 @@ import edu.kit.provideq.toolbox.meta.Problem; import edu.kit.provideq.toolbox.meta.ProblemManager; import edu.kit.provideq.toolbox.meta.ProblemType; +import java.util.Set; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.util.Set; - @Configuration public class OptimizationConfiguration { public static final ProblemType OPTIMIZATION_CONFIG = new ProblemType<>( "circuit-processing-optimization", String.class, - String.class, - null + String.class ); @Bean diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java index 846fad84..8c883e00 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java @@ -2,18 +2,21 @@ import edu.kit.provideq.toolbox.Solution; import edu.kit.provideq.toolbox.circuit.processing.solver.CircuitProcessingSolver; -import edu.kit.provideq.toolbox.meta.*; +import edu.kit.provideq.toolbox.meta.ProblemSolver; +import edu.kit.provideq.toolbox.meta.ProblemType; +import edu.kit.provideq.toolbox.meta.SolvingProperties; +import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; +import edu.kit.provideq.toolbox.meta.SubRoutineResolver; import edu.kit.provideq.toolbox.meta.setting.SolverSetting; import edu.kit.provideq.toolbox.meta.setting.basic.SelectSetting; import edu.kit.provideq.toolbox.process.PythonProcessRunner; +import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; -import java.util.List; - @Component public class OptimizationSolver implements ProblemSolver { private static final String SETTING_SELECT_OPTIMIZER = "Selected Optimization Pass"; From 1d63db97703bd07f893dc9705d70a66219c7d95b Mon Sep 17 00:00:00 2001 From: Elscrux Date: Fri, 14 Mar 2025 00:37:57 +0100 Subject: [PATCH 04/39] feat: Update python process runner to execute via venv --- .../toolbox/process/PythonProcessRunner.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java b/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java index b4b7c277..94303e73 100644 --- a/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java +++ b/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java @@ -19,10 +19,20 @@ public class PythonProcessRunner extends ProcessRunner { * Creates a process runner for a Python script. * * @param scriptPath the filepath of the Python script to run. + * @param venvName the name of the virtual environment to use. */ - public PythonProcessRunner(String scriptPath) { + public PythonProcessRunner(String scriptPath, String venvName) { super(new ProcessBuilder()); + String osName = System.getProperty("os.name").toLowerCase(); + String activate; + if (osName.contains("win")) { + activate = String.format("./venv/%s/Scripts/activate.bat", venvName); + } else { + activate = String.format("source ./venv/%s/bin/activate", venvName); + } + + withArguments(activate, "&&"); withArguments(PYTHON_EXECUTABLE_NAME, scriptPath); } } From 4777948b71f3abb8760ed2febad33fc3e48f4c45 Mon Sep 17 00:00:00 2001 From: Elscrux Date: Fri, 14 Mar 2025 00:38:43 +0100 Subject: [PATCH 05/39] feat: Restructure requirement files --- demonstrators/cplex/mip-solver/mip-solver.py | 6 ++- .../cplex/{ => mip-solver}/requirements.txt | 0 scripts/install-python-dependencies.py | 35 +++++++++++++----- solvers/cirq/max-cut/requirements.txt | 7 ++++ solvers/cirq/requirements.txt | 3 -- solvers/custom/hs-knapsack/requirements.txt | 1 - .../exact-solution-counter.py | 0 .../sharp-sat-bruteforce/requirements.txt | 1 + .../ganak => sharp-sat-ganak}/README.md | 0 .../ganak => sharp-sat-ganak}/bin/ganak-linux | Bin .../ganak => sharp-sat-ganak}/bin/ganak-mac | Bin solvers/dwave/qubo/requirements.txt | 2 + solvers/dwave/requirements.txt | 5 --- solvers/gams/max-cut/requirements.txt | 3 ++ solvers/gams/requirements.txt | 5 --- solvers/gams/sat/requirements.txt | 2 + solvers/qiskit/knapsack/knapsack_qiskit.py | 5 ++- solvers/qiskit/knapsack/requirements.txt | 2 + solvers/qiskit/max-cut/requirements.txt | 5 +++ solvers/qiskit/qubo/requirements.txt | 2 + solvers/qiskit/requirements.txt | 8 ---- solvers/qrisp/qubo/requirements.txt | 4 ++ solvers/qrisp/requirements.txt | 4 -- solvers/qrisp/sat/requirements.txt | 3 ++ solvers/qrisp/vrp/requirements.txt | 4 ++ 25 files changed, 67 insertions(+), 40 deletions(-) rename demonstrators/cplex/{ => mip-solver}/requirements.txt (100%) create mode 100644 solvers/cirq/max-cut/requirements.txt delete mode 100644 solvers/cirq/requirements.txt rename solvers/custom/{sharp-sat/bruteforce => sharp-sat-bruteforce}/exact-solution-counter.py (100%) create mode 100644 solvers/custom/sharp-sat-bruteforce/requirements.txt rename solvers/custom/{sharp-sat/ganak => sharp-sat-ganak}/README.md (100%) rename solvers/custom/{sharp-sat/ganak => sharp-sat-ganak}/bin/ganak-linux (100%) mode change 100755 => 100644 rename solvers/custom/{sharp-sat/ganak => sharp-sat-ganak}/bin/ganak-mac (100%) create mode 100644 solvers/dwave/qubo/requirements.txt delete mode 100644 solvers/dwave/requirements.txt create mode 100644 solvers/gams/max-cut/requirements.txt delete mode 100644 solvers/gams/requirements.txt create mode 100644 solvers/gams/sat/requirements.txt create mode 100644 solvers/qiskit/knapsack/requirements.txt create mode 100644 solvers/qiskit/max-cut/requirements.txt create mode 100644 solvers/qiskit/qubo/requirements.txt delete mode 100644 solvers/qiskit/requirements.txt create mode 100644 solvers/qrisp/qubo/requirements.txt delete mode 100644 solvers/qrisp/requirements.txt create mode 100644 solvers/qrisp/sat/requirements.txt create mode 100644 solvers/qrisp/vrp/requirements.txt diff --git a/demonstrators/cplex/mip-solver/mip-solver.py b/demonstrators/cplex/mip-solver/mip-solver.py index d3894f2f..55d0f09b 100644 --- a/demonstrators/cplex/mip-solver/mip-solver.py +++ b/demonstrators/cplex/mip-solver/mip-solver.py @@ -6,8 +6,10 @@ import sys from io import StringIO -if len(sys.argv) != 4: - raise TypeError('This script expects exactly 3 arguments: max number of variables, step size, and number of repetitons') + +arg_count = len(sys.argv) - 1 +if arg_count != 3: + raise TypeError(f'This script expects exactly 3 arguments but got {arg_count}: max number of variables, step size, and number of repetitons') maxNbVars = int(sys.argv[1]) stepSize = int(sys.argv[2]) diff --git a/demonstrators/cplex/requirements.txt b/demonstrators/cplex/mip-solver/requirements.txt similarity index 100% rename from demonstrators/cplex/requirements.txt rename to demonstrators/cplex/mip-solver/requirements.txt diff --git a/scripts/install-python-dependencies.py b/scripts/install-python-dependencies.py index eb0c1f8b..f175b7fe 100644 --- a/scripts/install-python-dependencies.py +++ b/scripts/install-python-dependencies.py @@ -1,19 +1,34 @@ import os import subprocess +import platform script_dir = os.path.dirname(os.path.realpath(__file__)) +root_dir = os.path.dirname(script_dir) base_dirs = [ - os.path.join(script_dir, '..', 'solvers'), - os.path.join(script_dir, '..', 'demonstrators') + os.path.join(root_dir, 'demonstrators'), + os.path.join(root_dir, 'solvers'), ] for base_dir in base_dirs: for root, dirs, files in os.walk(base_dir): - # Check if 'requirements.txt' is in the current directory - req_file = os.path.join(root, 'requirements.txt') - if os.path.exists(req_file): - print(f"Found requirements.txt in {root}, installing dependencies...") - try: - subprocess.run(['pip', 'install', '-r', req_file], check=True) # single thread to avoid dep. errors - except subprocess.CalledProcessError as e: - print(f"Error installing requirements for {root}: {e}") + # Iterate over framework directory (cirq, gams, qiskit, etc.) + for framework_name in dirs: + framework_dir = os.path.join(root, framework_name) + + # Iterate over problem directory (knapsack, tsp, etc.) + for solver_name in os.listdir(framework_dir): + solver_dir = os.path.join(framework_dir, solver_name) + req_file = os.path.join(solver_dir, 'requirements.txt') + if os.path.exists(req_file): + venv_name = f"{os.path.basename(root)}_{framework_name}_{solver_name}" + print(f"Setting up virtual environment '{venv_name}' for {solver_dir}...") + try: + venv_path = os.path.join('venv', venv_name) + subprocess.run(['python3', '-m', 'venv', venv_path], check=True) + if platform.system() == 'Windows': + pip_executable = os.path.join(venv_path, 'Scripts', 'pip.exe') + else: + pip_executable = os.path.join(venv_path, 'bin', 'pip') + subprocess.run([pip_executable, 'install', '-r', req_file], check=True) + except subprocess.CalledProcessError as e: + print(f"Error setting up virtual environment for {solver_dir}: {e}") diff --git a/solvers/cirq/max-cut/requirements.txt b/solvers/cirq/max-cut/requirements.txt new file mode 100644 index 00000000..746a80ce --- /dev/null +++ b/solvers/cirq/max-cut/requirements.txt @@ -0,0 +1,7 @@ +# This file describes the python package requirements for the Cirq MaxCut solver +matplotlib +cirq==1.5.0.dev20241009204224 +networkx +pandas +sympy +numpy \ No newline at end of file diff --git a/solvers/cirq/requirements.txt b/solvers/cirq/requirements.txt deleted file mode 100644 index 7380d35f..00000000 --- a/solvers/cirq/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -# Cirq MaxCut -matplotlib -cirq==1.5.0.dev20241009204224 diff --git a/solvers/custom/hs-knapsack/requirements.txt b/solvers/custom/hs-knapsack/requirements.txt index 5f6abbe6..a62c979e 100644 --- a/solvers/custom/hs-knapsack/requirements.txt +++ b/solvers/custom/hs-knapsack/requirements.txt @@ -1,3 +1,2 @@ # This file describes the python package requirements for the knapsack problem solver - knapsack-pip == 0.2 diff --git a/solvers/custom/sharp-sat/bruteforce/exact-solution-counter.py b/solvers/custom/sharp-sat-bruteforce/exact-solution-counter.py similarity index 100% rename from solvers/custom/sharp-sat/bruteforce/exact-solution-counter.py rename to solvers/custom/sharp-sat-bruteforce/exact-solution-counter.py diff --git a/solvers/custom/sharp-sat-bruteforce/requirements.txt b/solvers/custom/sharp-sat-bruteforce/requirements.txt new file mode 100644 index 00000000..b42500de --- /dev/null +++ b/solvers/custom/sharp-sat-bruteforce/requirements.txt @@ -0,0 +1 @@ +# This file describes the python package requirements for the Sharp SAT solver diff --git a/solvers/custom/sharp-sat/ganak/README.md b/solvers/custom/sharp-sat-ganak/README.md similarity index 100% rename from solvers/custom/sharp-sat/ganak/README.md rename to solvers/custom/sharp-sat-ganak/README.md diff --git a/solvers/custom/sharp-sat/ganak/bin/ganak-linux b/solvers/custom/sharp-sat-ganak/bin/ganak-linux old mode 100755 new mode 100644 similarity index 100% rename from solvers/custom/sharp-sat/ganak/bin/ganak-linux rename to solvers/custom/sharp-sat-ganak/bin/ganak-linux diff --git a/solvers/custom/sharp-sat/ganak/bin/ganak-mac b/solvers/custom/sharp-sat-ganak/bin/ganak-mac similarity index 100% rename from solvers/custom/sharp-sat/ganak/bin/ganak-mac rename to solvers/custom/sharp-sat-ganak/bin/ganak-mac diff --git a/solvers/dwave/qubo/requirements.txt b/solvers/dwave/qubo/requirements.txt new file mode 100644 index 00000000..694e1464 --- /dev/null +++ b/solvers/dwave/qubo/requirements.txt @@ -0,0 +1,2 @@ +# This file describes the python package requirements for the Dwave Qubo solver +dwave-ocean-sdk == 6.4.1 diff --git a/solvers/dwave/requirements.txt b/solvers/dwave/requirements.txt deleted file mode 100644 index 6e6460d8..00000000 --- a/solvers/dwave/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -# This file describes the python package requirements for all Dwave scripts -# supported by ProvideQ - -# required for Dwave Qubo solver -dwave-ocean-sdk == 6.4.1 diff --git a/solvers/gams/max-cut/requirements.txt b/solvers/gams/max-cut/requirements.txt new file mode 100644 index 00000000..a134aa9a --- /dev/null +++ b/solvers/gams/max-cut/requirements.txt @@ -0,0 +1,3 @@ +# This file describes the python package requirements for the GAMS Max-Cut solver +networkx +gamsapi[core,connect] \ No newline at end of file diff --git a/solvers/gams/requirements.txt b/solvers/gams/requirements.txt deleted file mode 100644 index 0d3afc12..00000000 --- a/solvers/gams/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -# This file describes the python package requirements for all GAMS scripts -# supported by ProvideQ - -# required for GAMS MaxCut solver -networkx diff --git a/solvers/gams/sat/requirements.txt b/solvers/gams/sat/requirements.txt new file mode 100644 index 00000000..b05a3184 --- /dev/null +++ b/solvers/gams/sat/requirements.txt @@ -0,0 +1,2 @@ +# This file describes the python package requirements for the GAMS SAT solver +gamsapi[core,connect] \ No newline at end of file diff --git a/solvers/qiskit/knapsack/knapsack_qiskit.py b/solvers/qiskit/knapsack/knapsack_qiskit.py index 0123c101..ae6416cd 100644 --- a/solvers/qiskit/knapsack/knapsack_qiskit.py +++ b/solvers/qiskit/knapsack/knapsack_qiskit.py @@ -9,8 +9,9 @@ from qiskit_optimization.converters import QuadraticProgramToQubo from qiskit_algorithms import QAOA -if len(sys.argv) != 3: - raise TypeError('This script expects exactly 2 arguments. Input file (argument 1) and output file (argument 2).') +arg_count = len(sys.argv) - 1 +if arg_count != 2: + raise TypeError(f'This script expects exactly 2 arguments but got {arg_count}. Input file (argument 1) and output file (argument 2).') input_path = sys.argv[1] output_path = sys.argv[2] diff --git a/solvers/qiskit/knapsack/requirements.txt b/solvers/qiskit/knapsack/requirements.txt new file mode 100644 index 00000000..e0471f77 --- /dev/null +++ b/solvers/qiskit/knapsack/requirements.txt @@ -0,0 +1,2 @@ +# This file describes the python package requirements for the Qiskit Knapsack solver +qiskit-optimization == 0.6.1 diff --git a/solvers/qiskit/max-cut/requirements.txt b/solvers/qiskit/max-cut/requirements.txt new file mode 100644 index 00000000..ce8fc4e2 --- /dev/null +++ b/solvers/qiskit/max-cut/requirements.txt @@ -0,0 +1,5 @@ +# This file describes the python package requirements for the Qiskit Max-Cut solver +pygmlparser == 1.0.1 +qiskit-optimization == 0.6.1 +numpy +networkx \ No newline at end of file diff --git a/solvers/qiskit/qubo/requirements.txt b/solvers/qiskit/qubo/requirements.txt new file mode 100644 index 00000000..dbf99f32 --- /dev/null +++ b/solvers/qiskit/qubo/requirements.txt @@ -0,0 +1,2 @@ +# This file describes the python package requirements for the Qiskit QUBO solver +qiskit-optimization == 0.6.1 diff --git a/solvers/qiskit/requirements.txt b/solvers/qiskit/requirements.txt deleted file mode 100644 index 3ed4515e..00000000 --- a/solvers/qiskit/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -# This file describes the python package requirements for all Qiskit scripts -# supported by ProvideQ - -# required for Qiskit MaxCut solver -pygmlparser == 1.0.1 - -#required for MaxCut and QUBO Solver, will automatically download a matching Qiskit, NumPy, and Qiskit-Algorithms version. -qiskit-optimization == 0.6.1 diff --git a/solvers/qrisp/qubo/requirements.txt b/solvers/qrisp/qubo/requirements.txt new file mode 100644 index 00000000..10cb2e71 --- /dev/null +++ b/solvers/qrisp/qubo/requirements.txt @@ -0,0 +1,4 @@ +# This file describes the python package requirements for the Qrisp QUBO solver +qrisp == 0.4.4 +numpy == 1.26.4 +gurobipy == 11.0.1 # for lp file reading \ No newline at end of file diff --git a/solvers/qrisp/requirements.txt b/solvers/qrisp/requirements.txt deleted file mode 100644 index f42a2bda..00000000 --- a/solvers/qrisp/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -qrisp == 0.4.4 -numpy == 1.26.4 -gurobipy == 11.0.1 # for lp file reading -tsplib95 == 0.7.1 # for tsplib file parsing \ No newline at end of file diff --git a/solvers/qrisp/sat/requirements.txt b/solvers/qrisp/sat/requirements.txt new file mode 100644 index 00000000..30f9c9c3 --- /dev/null +++ b/solvers/qrisp/sat/requirements.txt @@ -0,0 +1,3 @@ +# This file describes the python package requirements for the Qrisp SAT solver +qrisp == 0.4.4 +numpy == 1.26.4 \ No newline at end of file diff --git a/solvers/qrisp/vrp/requirements.txt b/solvers/qrisp/vrp/requirements.txt new file mode 100644 index 00000000..c7737696 --- /dev/null +++ b/solvers/qrisp/vrp/requirements.txt @@ -0,0 +1,4 @@ +# This file describes the python package requirements for the Qrisp VRP solver +qrisp == 0.4.4 +numpy == 1.26.4 +tsplib95 == 0.7.1 # for tsplib file parsing \ No newline at end of file From 4657c1cf61d68579f953f56d4c68455999fcb67b Mon Sep 17 00:00:00 2001 From: Elscrux Date: Fri, 14 Mar 2025 00:39:21 +0100 Subject: [PATCH 06/39] feat: Restructure application.properties and pass venv to python process runners --- .../demonstrators/CplexMipDemonstrator.java | 7 ++- .../solvers/PythonKnapsackSolver.java | 7 ++- .../solvers/QiskitKnapsackSolver.java | 11 ++-- .../maxcut/solvers/CirqMaxCutSolver.java | 7 ++- .../maxcut/solvers/GamsMaxCutSolver.java | 2 +- .../maxcut/solvers/QiskitMaxCutSolver.java | 7 ++- .../toolbox/process/ProcessRunner.java | 8 +-- .../toolbox/process/PythonProcessRunner.java | 49 ++++++++++++++++-- .../toolbox/qubo/solvers/DwaveQuboSolver.java | 7 ++- .../qubo/solvers/QiskitQuboSolver.java | 7 ++- .../toolbox/qubo/solvers/QrispQuboSolver.java | 9 ++-- .../toolbox/sat/solvers/GamsSatSolver.java | 2 +- .../sat/solvers/QrispExactGroverSolver.java | 7 ++- .../sat/solvers/QrispGroverSolver.java | 7 ++- .../toolbox/sharpsat/solvers/GanakSolver.java | 3 +- .../solvers/PythonBruteForceSolver.java | 7 ++- .../toolbox/tsp/solvers/LkhTspSolver.java | 17 ++++--- .../toolbox/tsp/solvers/QuboTspSolver.java | 2 +- .../vrp/clusterer/KmeansClusterer.java | 2 +- .../vrp/clusterer/TwoPhaseClusterer.java | 2 +- .../toolbox/vrp/solvers/LkhVrpSolver.java | 15 +++--- .../toolbox/vrp/solvers/QrispVrpSolver.java | 7 ++- .../resources/application-linux.properties | 6 +-- src/main/resources/application-mac.properties | 6 +-- .../resources/application-windows.properties | 6 +-- src/main/resources/application.properties | 50 +------------------ 26 files changed, 146 insertions(+), 114 deletions(-) diff --git a/src/main/java/edu/kit/provideq/toolbox/demonstrators/CplexMipDemonstrator.java b/src/main/java/edu/kit/provideq/toolbox/demonstrators/CplexMipDemonstrator.java index 04e91313..d3f8269a 100644 --- a/src/main/java/edu/kit/provideq/toolbox/demonstrators/CplexMipDemonstrator.java +++ b/src/main/java/edu/kit/provideq/toolbox/demonstrators/CplexMipDemonstrator.java @@ -23,13 +23,16 @@ public class CplexMipDemonstrator implements Demonstrator { private static final int DEFAULT_REPETITIONS = 3; private final String scriptPath; + private final String venv; private final ApplicationContext context; @Autowired public CplexMipDemonstrator( - @Value("${cplex.directory.mip}") String scriptPath, + @Value("${path.cplex.mip}") String scriptPath, + @Value("${venv.cplex.mip}") String venv, ApplicationContext context) { this.scriptPath = scriptPath; + this.venv = venv; this.context = context; } @@ -94,7 +97,7 @@ public Mono> solve( .orElse(DEFAULT_REPETITIONS); var processResult = context - .getBean(PythonProcessRunner.class, scriptPath) + .getBean(PythonProcessRunner.class, scriptPath, venv) .withArguments(maxNumberVariables.toString(), stepSize.toString(), repetitions.toString()) .readOutputString() .run(getProblemType(), solution.getId()); diff --git a/src/main/java/edu/kit/provideq/toolbox/knapsack/solvers/PythonKnapsackSolver.java b/src/main/java/edu/kit/provideq/toolbox/knapsack/solvers/PythonKnapsackSolver.java index 27e57eff..20905e36 100644 --- a/src/main/java/edu/kit/provideq/toolbox/knapsack/solvers/PythonKnapsackSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/knapsack/solvers/PythonKnapsackSolver.java @@ -18,13 +18,16 @@ @Component public class PythonKnapsackSolver extends KnapsackSolver { private final String scriptPath; + private final String venv; private final ApplicationContext context; @Autowired public PythonKnapsackSolver( - @Value("${custom.script.hs_knapsack}") String scriptPath, + @Value("${path.custom.hs-knapsack}") String scriptPath, + @Value("${venv.custom.hs-knapsack}") String venv, ApplicationContext context) { this.scriptPath = scriptPath; + this.venv = venv; this.context = context; } @@ -48,7 +51,7 @@ public Mono> solve( var solution = new Solution<>(this); var processResult = context - .getBean(PythonProcessRunner.class, scriptPath) + .getBean(PythonProcessRunner.class, scriptPath, venv) .withArguments( ProcessRunner.INPUT_FILE_PATH, ProcessRunner.OUTPUT_FILE_PATH) diff --git a/src/main/java/edu/kit/provideq/toolbox/knapsack/solvers/QiskitKnapsackSolver.java b/src/main/java/edu/kit/provideq/toolbox/knapsack/solvers/QiskitKnapsackSolver.java index edfb6ba1..8d8e3eae 100644 --- a/src/main/java/edu/kit/provideq/toolbox/knapsack/solvers/QiskitKnapsackSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/knapsack/solvers/QiskitKnapsackSolver.java @@ -17,14 +17,17 @@ */ @Component public class QiskitKnapsackSolver extends KnapsackSolver { - private final String knapsackPath; + private final String scriptPath; + private final String venv; private final ApplicationContext context; @Autowired public QiskitKnapsackSolver( - @Value("${qiskit.script.knapsack}") String knapsackPath, + @Value("${path.qiskit.knapsack}") String scriptPath, + @Value("${venv.qiskit.knapsack}") String venv, ApplicationContext context) { - this.knapsackPath = knapsackPath; + this.scriptPath = scriptPath; + this.venv = venv; this.context = context; } @@ -47,7 +50,7 @@ public Mono> solve( var solution = new Solution<>(this); var processResult = context - .getBean(PythonProcessRunner.class, knapsackPath) + .getBean(PythonProcessRunner.class, scriptPath, venv) .withArguments( ProcessRunner.INPUT_FILE_PATH, ProcessRunner.OUTPUT_FILE_PATH diff --git a/src/main/java/edu/kit/provideq/toolbox/maxcut/solvers/CirqMaxCutSolver.java b/src/main/java/edu/kit/provideq/toolbox/maxcut/solvers/CirqMaxCutSolver.java index a73c0986..fb12470e 100644 --- a/src/main/java/edu/kit/provideq/toolbox/maxcut/solvers/CirqMaxCutSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/maxcut/solvers/CirqMaxCutSolver.java @@ -19,12 +19,15 @@ public class CirqMaxCutSolver extends MaxCutSolver { private final ApplicationContext context; private final String scriptPath; + private final String venv; @Autowired public CirqMaxCutSolver( - @Value("${cirq.script.max-cut}") String scriptPath, + @Value("${path.cirq.max-cut}") String scriptPath, + @Value("${venv.cirq.max-cut}") String venv, ApplicationContext context) { this.scriptPath = scriptPath; + this.venv = venv; this.context = context; } @@ -47,7 +50,7 @@ public Mono> solve( var solution = new Solution<>(this); var processResult = context - .getBean(PythonProcessRunner.class, scriptPath) + .getBean(PythonProcessRunner.class, scriptPath, venv) .withArguments( ProcessRunner.INPUT_FILE_PATH, ProcessRunner.OUTPUT_FILE_PATH diff --git a/src/main/java/edu/kit/provideq/toolbox/maxcut/solvers/GamsMaxCutSolver.java b/src/main/java/edu/kit/provideq/toolbox/maxcut/solvers/GamsMaxCutSolver.java index 07a8e17e..0726eac2 100644 --- a/src/main/java/edu/kit/provideq/toolbox/maxcut/solvers/GamsMaxCutSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/maxcut/solvers/GamsMaxCutSolver.java @@ -22,7 +22,7 @@ public class GamsMaxCutSolver extends MaxCutSolver { @Autowired public GamsMaxCutSolver( - @Value("${gams.script.max-cut}") String scriptPath, + @Value("${path.gams.max-cut}") String scriptPath, ApplicationContext context) { this.scriptPath = scriptPath; this.context = context; diff --git a/src/main/java/edu/kit/provideq/toolbox/maxcut/solvers/QiskitMaxCutSolver.java b/src/main/java/edu/kit/provideq/toolbox/maxcut/solvers/QiskitMaxCutSolver.java index 7734cf5f..36bea4fd 100644 --- a/src/main/java/edu/kit/provideq/toolbox/maxcut/solvers/QiskitMaxCutSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/maxcut/solvers/QiskitMaxCutSolver.java @@ -23,13 +23,16 @@ public class QiskitMaxCutSolver extends MaxCutSolver { private static final String SOLUTION_LINE_PREFIX = "solution:"; private final String scriptPath; + private final String venv; private final ApplicationContext context; @Autowired public QiskitMaxCutSolver( - @Value("${qiskit.script.max-cut}") String scriptPath, + @Value("${path.qiskit.max-cut}") String scriptPath, + @Value("${venv.qiskit.max-cut}") String venv, ApplicationContext context) { this.scriptPath = scriptPath; + this.venv = venv; this.context = context; } @@ -64,7 +67,7 @@ public Mono> solve( // Run Qiskit solver via console var processResult = context - .getBean(PythonProcessRunner.class, scriptPath) + .getBean(PythonProcessRunner.class, scriptPath, venv) .withArguments( ProcessRunner.INPUT_FILE_PATH, ProcessRunner.OUTPUT_FILE_PATH diff --git a/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java b/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java index fcfc7f96..1f80221b 100644 --- a/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java +++ b/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java @@ -45,9 +45,9 @@ public class ProcessRunner { protected final ProcessBuilder processBuilder; protected ResourceProvider resourceProvider; - private final List, UUID, Optional>> preProcessors; - private final List, UUID, Optional>> postProcessors; - private final List> argumentTransformers; + protected final List, UUID, Optional>> preProcessors; + protected final List, UUID, Optional>> postProcessors; + protected final List> argumentTransformers; /** * The directory of the problem that is being solved. @@ -250,7 +250,7 @@ public ProcessRunner withArguments(String... arguments) { return this; } - private void addCommand(String command) { + protected void addCommand(String command) { List existingCommands = processBuilder.command(); existingCommands.add(command); processBuilder.command(existingCommands); diff --git a/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java b/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java index 94303e73..82b7f2da 100644 --- a/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java +++ b/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java @@ -1,5 +1,7 @@ package edu.kit.provideq.toolbox.process; +import java.util.List; +import java.util.Optional; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @@ -25,14 +27,51 @@ public PythonProcessRunner(String scriptPath, String venvName) { super(new ProcessBuilder()); String osName = System.getProperty("os.name").toLowerCase(); - String activate; if (osName.contains("win")) { - activate = String.format("./venv/%s/Scripts/activate.bat", venvName); + withArguments( + String.format("./venv/%s/Scripts/activate.bat", venvName), + "&&", + PYTHON_EXECUTABLE_NAME, + scriptPath); } else { - activate = String.format("source ./venv/%s/bin/activate", venvName); + processBuilder.command( + "sh", + "-c", + String.format(". ./venv/%s/bin/activate && python %s", venvName, scriptPath)); } + } + + @Override + public ProcessRunner withArguments(String... arguments) { + String osName = System.getProperty("os.name").toLowerCase(); + if (osName.contains("win")) { + return super.withArguments(arguments); + } + + preProcessors.add((problemType, solutionId) -> { + for (String argument : arguments) { + for (var transformer : argumentTransformers) { + argument = transformer.apply(argument); + } + + if (processBuilder.command().isEmpty()) { + processBuilder.command(argument); + } else { + List existingCommands = processBuilder.command(); + System.out.println(String.format("Adding argument %s to existing commands %s", argument, String.join(" ", existingCommands))); + int lastIndex = existingCommands.size() - 1; + String lastCommand = existingCommands.get(lastIndex); + existingCommands.remove(lastIndex); + + var newArgument = lastCommand + " " + argument; + existingCommands.add(newArgument); + processBuilder.command(existingCommands); + } + } + + return Optional.empty(); + }); - withArguments(activate, "&&"); - withArguments(PYTHON_EXECUTABLE_NAME, scriptPath); + return this; } } diff --git a/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/DwaveQuboSolver.java b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/DwaveQuboSolver.java index dfc33932..dc445dd0 100644 --- a/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/DwaveQuboSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/DwaveQuboSolver.java @@ -53,13 +53,16 @@ public static AnnealingMethod fromValue(String value) { } private final String scriptPath; + private final String venv; private final ApplicationContext context; @Autowired public DwaveQuboSolver( - @Value("${dwave.script.qubo}") String scriptPath, + @Value("${path.dwave.qubo}") String scriptPath, + @Value("${venv.dwave.qubo}") String venv, ApplicationContext context) { this.scriptPath = scriptPath; + this.venv = venv; this.context = context; } @@ -110,7 +113,7 @@ public Mono> solve( final var solution = new Solution<>(this); - var processRunner = context.getBean(PythonProcessRunner.class, scriptPath); + var processRunner = context.getBean(PythonProcessRunner.class, scriptPath, venv); if (dwaveToken.isPresent() && !dwaveToken.get().isEmpty()) { processRunner.withEnvironmentVariable("DWAVE_API_TOKEN", dwaveToken.get()); 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 index c652202b..78858b3d 100644 --- a/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QiskitQuboSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QiskitQuboSolver.java @@ -18,13 +18,16 @@ @Component public class QiskitQuboSolver extends QuboSolver { private final String scriptPath; + private final String venv; private final ApplicationContext context; @Autowired public QiskitQuboSolver( - @Value("${qiskit.script.qubo}") String scriptPath, + @Value("${path.qiskit.qubo}") String scriptPath, + @Value("${venv.qiskit.qubo}") String venv, ApplicationContext context) { this.scriptPath = scriptPath; + this.venv = venv; this.context = context; } @@ -48,7 +51,7 @@ public Mono> solve( // Run Qiskit solver via console var processResult = context - .getBean(PythonProcessRunner.class, scriptPath) + .getBean(PythonProcessRunner.class, scriptPath, venv) .withArguments( ProcessRunner.INPUT_FILE_PATH, ProcessRunner.OUTPUT_FILE_PATH diff --git a/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QrispQuboSolver.java b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QrispQuboSolver.java index fc9e2994..f4e8ef16 100644 --- a/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QrispQuboSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QrispQuboSolver.java @@ -23,14 +23,17 @@ public class QrispQuboSolver extends QuboSolver { private static final String SETTING_MAX_NUMBER_OF_VARS = "Max Number of Variables"; private static final int DEFAULT_MAX_NUMBER_OF_VARS = 4; - private final ApplicationContext context; private final String scriptPath; + private final String venv; + private final ApplicationContext context; @Autowired public QrispQuboSolver( - @Value("${qrisp.script.qubo}") String scriptPath, + @Value("${path.qrisp.qubo}") String scriptPath, + @Value("${venv.qrisp.qubo}") String venv, ApplicationContext context) { this.scriptPath = scriptPath; + this.venv = venv; this.context = context; } @@ -78,7 +81,7 @@ public Mono> solve( } var processResult = context - .getBean(PythonProcessRunner.class, scriptPath) + .getBean(PythonProcessRunner.class, scriptPath, venv) .withArguments( ProcessRunner.INPUT_FILE_PATH, "--output-file", ProcessRunner.OUTPUT_FILE_PATH, diff --git a/src/main/java/edu/kit/provideq/toolbox/sat/solvers/GamsSatSolver.java b/src/main/java/edu/kit/provideq/toolbox/sat/solvers/GamsSatSolver.java index 1da97f11..290994aa 100644 --- a/src/main/java/edu/kit/provideq/toolbox/sat/solvers/GamsSatSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/sat/solvers/GamsSatSolver.java @@ -26,7 +26,7 @@ public class GamsSatSolver extends SatSolver { @Autowired public GamsSatSolver( - @Value("${gams.script.sat}") String scriptPath, + @Value("${path.gams.sat}") String scriptPath, ApplicationContext context) { this.scriptPath = scriptPath; this.context = context; diff --git a/src/main/java/edu/kit/provideq/toolbox/sat/solvers/QrispExactGroverSolver.java b/src/main/java/edu/kit/provideq/toolbox/sat/solvers/QrispExactGroverSolver.java index 3b513ef4..c894d0ff 100644 --- a/src/main/java/edu/kit/provideq/toolbox/sat/solvers/QrispExactGroverSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/sat/solvers/QrispExactGroverSolver.java @@ -32,12 +32,15 @@ public class QrispExactGroverSolver extends SatSolver { ); private final String scriptPath; + private final String venv; private final ApplicationContext context; public QrispExactGroverSolver( - @Value("${qrisp.script.exact-sat}") String scriptPath, + @Value("${path.qrisp.sat.exact}") String scriptPath, + @Value("${venv.qrisp.sat}") String venv, ApplicationContext context) { this.scriptPath = scriptPath; + this.venv = venv; this.context = context; } @@ -98,7 +101,7 @@ private Mono> runPythonSolver( Solution solution ) { ProcessResult processResult = context - .getBean(PythonProcessRunner.class, scriptPath) + .getBean(PythonProcessRunner.class, scriptPath, venv) .withArguments( ProcessRunner.INPUT_FILE_PATH, "--solution-count", String.valueOf(solutionCount), diff --git a/src/main/java/edu/kit/provideq/toolbox/sat/solvers/QrispGroverSolver.java b/src/main/java/edu/kit/provideq/toolbox/sat/solvers/QrispGroverSolver.java index 951fb0f5..bf173db7 100644 --- a/src/main/java/edu/kit/provideq/toolbox/sat/solvers/QrispGroverSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/sat/solvers/QrispGroverSolver.java @@ -22,13 +22,16 @@ @Component public class QrispGroverSolver extends SatSolver { private final String scriptPath; + private final String venv; private final ApplicationContext context; @Autowired public QrispGroverSolver( - @Value("${qrisp.script.sat}") String scriptPath, + @Value("${path.qrisp.sat.grover}") String scriptPath, + @Value("${venv.qrisp.sat}") String venv, ApplicationContext context) { this.scriptPath = scriptPath; + this.venv = venv; this.context = context; } @@ -61,7 +64,7 @@ public Mono> solve( } ProcessResult processResult = context - .getBean(PythonProcessRunner.class, scriptPath) + .getBean(PythonProcessRunner.class, scriptPath, venv) .withArguments( ProcessRunner.INPUT_FILE_PATH, "--output-file", ProcessRunner.OUTPUT_FILE_PATH diff --git a/src/main/java/edu/kit/provideq/toolbox/sharpsat/solvers/GanakSolver.java b/src/main/java/edu/kit/provideq/toolbox/sharpsat/solvers/GanakSolver.java index 83e64bea..257a26d3 100644 --- a/src/main/java/edu/kit/provideq/toolbox/sharpsat/solvers/GanakSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/sharpsat/solvers/GanakSolver.java @@ -31,9 +31,8 @@ public class GanakSolver extends SharpSatSolver { @Autowired public GanakSolver( - @Value("${custom.binary.ganak-sat}") String binaryPath, + @Value("${path.custom.sharp-sat-ganak}") String binaryPath, ApplicationContext context) { - this.binaryPath = binaryPath; this.context = context; } diff --git a/src/main/java/edu/kit/provideq/toolbox/sharpsat/solvers/PythonBruteForceSolver.java b/src/main/java/edu/kit/provideq/toolbox/sharpsat/solvers/PythonBruteForceSolver.java index 3587c9f9..4e0fb85a 100644 --- a/src/main/java/edu/kit/provideq/toolbox/sharpsat/solvers/PythonBruteForceSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/sharpsat/solvers/PythonBruteForceSolver.java @@ -21,13 +21,16 @@ @Component public class PythonBruteForceSolver extends SharpSatSolver { private final String scriptPath; + private final String venv; private final ApplicationContext context; @Autowired public PythonBruteForceSolver( - @Value("${custom.script.bruteforce-sat}") String scriptPath, + @Value("${path.custom.sharp-sat-bruteforce}") String scriptPath, + @Value("${venv.custom.sharp-sat-bruteforce}") String venv, ApplicationContext context) { this.scriptPath = scriptPath; + this.venv = venv; this.context = context; } @@ -77,7 +80,7 @@ public Mono> solve(String input, SubRoutineResolver subRoutine } ProcessResult processResult = context - .getBean(PythonProcessRunner.class, scriptPath) + .getBean(PythonProcessRunner.class, scriptPath, venv) .withArguments( ProcessRunner.INPUT_FILE_PATH, "--output-file", ProcessRunner.OUTPUT_FILE_PATH diff --git a/src/main/java/edu/kit/provideq/toolbox/tsp/solvers/LkhTspSolver.java b/src/main/java/edu/kit/provideq/toolbox/tsp/solvers/LkhTspSolver.java index e454ddf8..25818f2f 100644 --- a/src/main/java/edu/kit/provideq/toolbox/tsp/solvers/LkhTspSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/tsp/solvers/LkhTspSolver.java @@ -16,17 +16,20 @@ */ @Component public class LkhTspSolver extends TspSolver { - private final String pythonWrapperScriptPath; - private final ApplicationContext context; + private final String scriptPath; private final String binaryPath; + private final String venv; + private final ApplicationContext context; @Autowired public LkhTspSolver( - @Value("${custom.script.lkh}") String pythonWrapperScriptPath, - @Value("${custom.binary.lkh}") String lkhBinaryPath, + @Value("${path.custom.lkh}") String scriptPath, + @Value("${path.custom.lkh.binary}") String binaryPath, + @Value("${venv.custom.lkh}") String venv, ApplicationContext context) { - this.pythonWrapperScriptPath = pythonWrapperScriptPath; - this.binaryPath = lkhBinaryPath; + this.scriptPath = scriptPath; + this.binaryPath = binaryPath; + this.venv = venv; this.context = context; } @@ -48,7 +51,7 @@ public Mono> solve( ) { var solution = new Solution<>(this); var processResult = context - .getBean(PythonProcessRunner.class, pythonWrapperScriptPath) + .getBean(PythonProcessRunner.class, scriptPath, venv) .withArguments( "--lkh-instance", binaryPath, ProcessRunner.INPUT_FILE_PATH, diff --git a/src/main/java/edu/kit/provideq/toolbox/tsp/solvers/QuboTspSolver.java b/src/main/java/edu/kit/provideq/toolbox/tsp/solvers/QuboTspSolver.java index 013c644e..6f993a41 100644 --- a/src/main/java/edu/kit/provideq/toolbox/tsp/solvers/QuboTspSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/tsp/solvers/QuboTspSolver.java @@ -33,7 +33,7 @@ public class QuboTspSolver extends TspSolver { @Autowired public QuboTspSolver( - @Value("${custom.binary.berger-vrp}") String binaryPath, + @Value("${path.custom.berger-vrp}") String binaryPath, ApplicationContext context) { this.binaryPath = binaryPath; this.context = context; diff --git a/src/main/java/edu/kit/provideq/toolbox/vrp/clusterer/KmeansClusterer.java b/src/main/java/edu/kit/provideq/toolbox/vrp/clusterer/KmeansClusterer.java index 9b2bf28c..0d64661d 100644 --- a/src/main/java/edu/kit/provideq/toolbox/vrp/clusterer/KmeansClusterer.java +++ b/src/main/java/edu/kit/provideq/toolbox/vrp/clusterer/KmeansClusterer.java @@ -28,7 +28,7 @@ public class KmeansClusterer extends VrpClusterer { @Autowired public KmeansClusterer( - @Value("${custom.binary.berger-vrp}") String binaryPath, + @Value("${path.custom.berger-vrp}") String binaryPath, ApplicationContext context) { super(binaryPath, context); } diff --git a/src/main/java/edu/kit/provideq/toolbox/vrp/clusterer/TwoPhaseClusterer.java b/src/main/java/edu/kit/provideq/toolbox/vrp/clusterer/TwoPhaseClusterer.java index 1ea89f86..7f5aac5b 100644 --- a/src/main/java/edu/kit/provideq/toolbox/vrp/clusterer/TwoPhaseClusterer.java +++ b/src/main/java/edu/kit/provideq/toolbox/vrp/clusterer/TwoPhaseClusterer.java @@ -26,7 +26,7 @@ public class TwoPhaseClusterer extends VrpClusterer { @Autowired public TwoPhaseClusterer( - @Value("${custom.binary.berger-vrp}") String binaryPath, + @Value("${path.custom.berger-vrp}") String binaryPath, ApplicationContext context) { super(binaryPath, context); } diff --git a/src/main/java/edu/kit/provideq/toolbox/vrp/solvers/LkhVrpSolver.java b/src/main/java/edu/kit/provideq/toolbox/vrp/solvers/LkhVrpSolver.java index 1cc17536..a61a3b89 100644 --- a/src/main/java/edu/kit/provideq/toolbox/vrp/solvers/LkhVrpSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/vrp/solvers/LkhVrpSolver.java @@ -18,16 +18,19 @@ @Component public class LkhVrpSolver extends VrpSolver { private final String scriptPath; + private final String binaryPath; + private final String venv; private final ApplicationContext context; - private final String solverBinary; @Autowired public LkhVrpSolver( - @Value("${custom.script.lkh}") String scriptPath, - @Value("${custom.binary.lkh}") String solverBinary, + @Value("${path.custom.lkh}") String scriptPath, + @Value("${path.custom.lkh.binary}") String binaryPath, + @Value("${venv.custom.lkh}") String venv, ApplicationContext context) { this.scriptPath = scriptPath; - this.solverBinary = solverBinary; + this.binaryPath = binaryPath; + this.venv = venv; this.context = context; } @@ -50,9 +53,9 @@ public Mono> solve( var solution = new Solution<>(this); var processResult = context - .getBean(PythonProcessRunner.class, scriptPath) + .getBean(PythonProcessRunner.class, scriptPath, venv) .withArguments( - "--lkh-instance", solverBinary, + "--lkh-instance", binaryPath, ProcessRunner.INPUT_FILE_PATH, "--output-file", ProcessRunner.OUTPUT_FILE_PATH ) diff --git a/src/main/java/edu/kit/provideq/toolbox/vrp/solvers/QrispVrpSolver.java b/src/main/java/edu/kit/provideq/toolbox/vrp/solvers/QrispVrpSolver.java index 37d7b534..7be00951 100644 --- a/src/main/java/edu/kit/provideq/toolbox/vrp/solvers/QrispVrpSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/vrp/solvers/QrispVrpSolver.java @@ -18,13 +18,16 @@ @Component public class QrispVrpSolver extends VrpSolver { private final String scriptPath; + private final String venv; private final ApplicationContext context; @Autowired public QrispVrpSolver( - @Value("${qrisp.script.vrp}") String scriptPath, + @Value("${path.qrisp.vrp}") String scriptPath, + @Value("${venv.qrisp.vrp}") String venv, ApplicationContext context) { this.scriptPath = scriptPath; + this.venv = venv; this.context = context; } @@ -47,7 +50,7 @@ public Mono> solve( var solution = new Solution<>(this); var processResult = context - .getBean(PythonProcessRunner.class, scriptPath) + .getBean(PythonProcessRunner.class, scriptPath, venv) .withArguments( ProcessRunner.INPUT_FILE_PATH, "--output-file", ProcessRunner.OUTPUT_FILE_PATH, diff --git a/src/main/resources/application-linux.properties b/src/main/resources/application-linux.properties index 2d535095..555f8643 100644 --- a/src/main/resources/application-linux.properties +++ b/src/main/resources/application-linux.properties @@ -1,8 +1,8 @@ # linux-specific Binary for the Berger-Vrp pipeline: -custom.binary.berger-vrp=${custom.directory.berger-vrp}/bin/pipeline-linux-gnu +path.custom.berger-vrp=${path.custom}/${name.custom.berger-vrp}/bin/pipeline-linux-gnu # linux-specific Binary for the LKH solver: -custom.binary.lkh=${custom.directory.lkh.directory}/bin/LKH-linux +path.custom.lkh.binary=${path.custom}/${name.custom.lkh}/bin/LKH-linux # linux specific Binary for the ganak sharp-sat solver: -custom.binary.ganak-sat=${custom.directory.sharp-sat.directory}/ganak/bin/ganak-linux +path.custom.sharp-sat-ganak=${path.custom}/${name.custom.sharp-sat-ganak}/bin/ganak-linux diff --git a/src/main/resources/application-mac.properties b/src/main/resources/application-mac.properties index 4d7ac164..3e7a167c 100644 --- a/src/main/resources/application-mac.properties +++ b/src/main/resources/application-mac.properties @@ -1,8 +1,8 @@ # Mac-specific Binary for the Berger-Vrp pipeline: -custom.binary.berger-vrp=${custom.directory.berger-vrp}/bin/pipeline-mac +path.custom.berger-vrp=${path.custom}/${name.custom.berger-vrp}/bin/pipeline-mac # Mac-specific Binary for the LKH solver: -custom.binary.lkh=${custom.directory.lkh.directory}/bin/LKH-mac +path.custom.lkh.binary=${path.custom}/${name.custom.lkh}/bin/LKH-mac # Mac-specific Binary for the ganak sharp-sat solver: -custom.binary.ganak-sat=${custom.directory.sharp-sat.directory}/ganak/bin/ganak-mac +path.custom.sharp-sat-ganak=${path.custom}/${name.custom.sharp-sat-ganak}/bin/ganak-mac diff --git a/src/main/resources/application-windows.properties b/src/main/resources/application-windows.properties index c23d0f9a..a016b1e6 100644 --- a/src/main/resources/application-windows.properties +++ b/src/main/resources/application-windows.properties @@ -1,8 +1,8 @@ # windows-specific Binary for the Berger-Vrp pipeline: -custom.binary.berger-vrp=${custom.directory.berger-vrp}/bin/pipeline-windows.exe +path.custom.berger-vrp=${path.custom}/${name.custom.berger-vrp}/bin/pipeline-windows.exe # windows-specific Binary for the LKH solver: -custom.binary.lkh=${custom.directory.lkh.directory}/bin/LKH-windows.exe +path.custom.lkh.binary=${path.custom}/${name.custom.lkh}/bin/LKH-windows.exe # Empty path - this solver is not available on Windows -custom.binary.ganak-sat= +path.custom.sharp-sat-ganak= diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f3659bb8..bd646f28 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,49 +1 @@ -# default spring profile, correct one will be set during runtime (see ToolboxServerApplication.java) -# options: mac, windows, linux -spring.profiles.active=linux -springdoc.swagger-ui.operationsSorter=alpha -springdoc.swagger-ui.tagsSorter=alpha - -working.directory=jobs -examples.directory=examples -springdoc.swagger-ui.path=/ - -# Solvers -solvers.directory=solvers - -# Non OS-specific solvers: (typically GAMS and Python) -gams.directory=${solvers.directory}/gams -gams.script.max-cut=${gams.directory}/max-cut/maxcut.gms -gams.script.sat=${gams.directory}/sat/sat.gms - -qiskit.directory=${solvers.directory}/qiskit -qiskit.script.max-cut=${qiskit.directory}/max-cut/maxCut_qiskit.py -qiskit.script.qubo=${qiskit.directory}/qubo/qubo_qiskit.py -qiskit.script.knapsack=${qiskit.directory}/knapsack/knapsack_qiskit.py - -cirq.directory=${solvers.directory}/cirq -cirq.script.max-cut=${cirq.directory}/max-cut/max_cut_cirq.py - -qrisp.directory=${solvers.directory}/qrisp -qrisp.script.vrp=${qrisp.directory}/vrp/grover.py -qrisp.script.qubo=${qrisp.directory}/qubo/qaoa.py -qrisp.script.sat=${qrisp.directory}/sat/grover.py -qrisp.script.exact-sat=${qrisp.directory}/sat/exact_grover.py - -dwave.directory=${solvers.directory}/dwave -dwave.script.qubo=${dwave.directory}/qubo/main.py - -# Non OS-specific custom solvers: (solvers that are not part of a framework) -custom.directory=${solvers.directory}/custom -custom.script.hs_knapsack=${custom.directory}/hs-knapsack/knapsack.py -custom.directory.lkh.directory=${custom.directory}/lkh -custom.script.lkh=${custom.directory.lkh.directory}/vrp_lkh.py -custom.directory.berger-vrp=${custom.directory}/berger-vrp -custom.directory.sharp-sat.directory=${custom.directory}/sharp-sat -custom.script.bruteforce-sat=${custom.directory.sharp-sat.directory}/bruteforce/exact-solution-counter.py - -# Demonstrators -demonstrators.directory=demonstrators - -cplex.directory=${demonstrators.directory}/cplex -cplex.directory.mip=${cplex.directory}/mip-solver/mip-solver.py +# default spring profile, correct one will be set during runtime (see ToolboxServerApplication.java) # options: mac, windows, linux spring.profiles.active=linux springdoc.swagger-ui.operationsSorter=alpha springdoc.swagger-ui.tagsSorter=alpha working.directory=jobs examples.directory=examples springdoc.swagger-ui.path=/ # Solvers name.solvers=solvers # Non OS-specific solvers: (typically GAMS and Python) name.gams=gams path.gams=${name.solvers}/${name.gams} name.gams.max-cut=max-cut path.gams.max-cut=${path.gams}/${name.gams.max-cut}/maxcut.gms name.gams.sat=sat path.gams.sat=${path.gams}/${name.gams.sat}/sat.gms name.qiskit=qiskit path.qiskit=${name.solvers}/${name.qiskit} name.qiskit.knapsack=knapsack path.qiskit.knapsack=${path.qiskit}/${name.qiskit.knapsack}/knapsack_qiskit.py venv.qiskit.knapsack=${name.solvers}_${name.qiskit}_${name.qiskit.knapsack} name.qiskit.max-cut=max-cut path.qiskit.max-cut=${path.qiskit}/${name.qiskit.max-cut}/maxCut_qiskit.py venv.qiskit.max-cut=${name.solvers}_${name.qiskit}_${name.qiskit.max-cut} name.qiskit.qubo=qubo path.qiskit.qubo=${path.qiskit}/${name.qiskit.qubo}/qubo_qiskit.py venv.qiskit.qubo=${name.solvers}_${name.qiskit}_${name.qiskit.qubo} name.cirq=cirq path.cirq=${name.solvers}/${name.cirq} name.cirq.max-cut=max-cut path.cirq.max-cut=${path.cirq}/${name.cirq.max-cut}/max_cut_cirq.py venv.cirq.max-cut=${name.solvers}_${name.cirq}_${name.cirq.max-cut} name.qrisp=qrisp path.qrisp=${name.solvers}/${name.qrisp} name.qrisp.vrp=vrp path.qrisp.vrp=${path.qrisp}/${name.qrisp.vrp}/grover.py venv.qrisp.vrp=${name.solvers}_${name.qrisp}_${name.qrisp.vrp} name.qrisp.qubo=qubo path.qrisp.qubo=${path.qrisp}/${name.qrisp.qubo}/qaoa.py venv.qrisp.qubo=${name.solvers}_${name.qrisp}_${name.qrisp.qubo} name.qrisp.sat=sat path.qrisp.sat.grover=${path.qrisp}/${name.qrisp.sat}/grover.py path.qrisp.sat.exact=${path.qrisp}/${name.qrisp.sat}/exact_grover.py venv.qrisp.sat=${name.solvers}_${name.qrisp}_${name.qrisp.sat} name.dwave=dwave path.dwave=${name.solvers}/${name.dwave} name.dwave.qubo=qubo path.dwave.qubo=${path.dwave}/${name.dwave.qubo}/main.py venv.dwave.qubo=${name.solvers}_${name.dwave}_${name.dwave.qubo} # Non OS-specific custom solvers: (solvers that are not part of a framework) name.custom=custom path.custom=${name.solvers}/${name.custom} name.custom.hs-knapsack=hs-knapsack path.custom.hs-knapsack=${path.custom}/${name.custom.hs-knapsack}/knapsack.py venv.custom.hs-knapsack=${name.solvers}_${name.custom}_${name.custom.hs-knapsack} name.custom.lkh=lkh path.custom.lkh=${path.custom}/${name.custom.lkh}/vrp_lkh.py venv.custom.lkh=${name.solvers}_${name.custom}_${name.custom.lkh} name.custom.berger-vrp=berger-vrp name.custom.sharp-sat-bruteforce=sharp-sat-bruteforce path.custom.sharp-sat-bruteforce=${path.custom}/${name.custom.sharp-sat-bruteforce}/exact-solution-counter.py venv.custom.sharp-sat-bruteforce=${name.solvers}_${name.custom}_${name.custom.sharp-sat-bruteforce} name.custom.sharp-sat-ganak=sharp-sat-ganak venv.custom.sharp-sat-ganak=${name.solvers}_${name.custom}_${name.custom.sharp-sat-ganak} # Demonstrators name.demonstrators=demonstrators name.cplex=cplex path.cplex=${name.demonstrators}/${name.cplex} name.cplex.mip=mip-solver path.cplex.mip=${path.cplex}/${name.cplex.mip}/mip-solver.py venv.cplex.mip=${name.demonstrators}_${name.cplex}_${name.cplex.mip} \ No newline at end of file From 7dad51fc3949d1b20fd9c18f5e9ca70da0a00566 Mon Sep 17 00:00:00 2001 From: Elscrux Date: Tue, 18 Mar 2025 22:41:17 +0100 Subject: [PATCH 07/39] chore: Update miniconda version --- scripts/setup-gams.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/setup-gams.sh b/scripts/setup-gams.sh index c0e28ddd..a4384e2b 100755 --- a/scripts/setup-gams.sh +++ b/scripts/setup-gams.sh @@ -46,9 +46,9 @@ cd "$GAMS_PATH" &&\ # === Install conda === # download installer, verify it and make it executable -curl --show-error --output /opt/conda-installer/install.sh --create-dirs "https://repo.anaconda.com/miniconda/Miniconda3-py310_23.1.0-1-Linux-x86_64.sh" +curl --show-error --output /opt/conda-installer/install.sh --create-dirs "https://repo.anaconda.com/miniconda/Miniconda3-py310_25.1.1-1-Linux-x86_64.sh" cd /opt/conda-installer -echo "32d73e1bc33fda089d7cd9ef4c1be542616bd8e437d1f77afeeaf7afdb019787 install.sh" | sha256sum --check +echo "585972959914f1f9be463284d477717eb10f7306bda63f2ec3c4c86047b9dd72 install.sh" | sha256sum --check chmod +x ./install.sh # Install python (with python -> python3 alias) and pip from miniconda From f365a5306036c9f9822ce5faa99c0b0f290aa9f6 Mon Sep 17 00:00:00 2001 From: Elscrux Date: Tue, 18 Mar 2025 22:41:43 +0100 Subject: [PATCH 08/39] debug --- .../java/edu/kit/provideq/toolbox/process/ProcessRunner.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java b/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java index 1f80221b..01e0f71b 100644 --- a/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java +++ b/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java @@ -294,6 +294,9 @@ protected ProcessRunnerExecutor getExecutor( String processError; int processExitCode; try { + processBuilder.directory(new File(System.getProperty("user.dir"))); + String command = processBuilder.command().stream().reduce("", (a, b) -> a + " |break| " + b); + System.out.println("ProcessBuilder command: " + command); Process process = processBuilder.start(); processOutput = resourceProvider.readStream(process.inputReader()); From 49db2e6dfe877697a90235e0f474d85174230bda Mon Sep 17 00:00:00 2001 From: Elscrux Date: Tue, 18 Mar 2025 22:46:34 +0100 Subject: [PATCH 09/39] feat: Make api token setting required --- .../edu/kit/provideq/toolbox/qubo/solvers/KipuQuboSolver.java | 1 + .../kit/provideq/toolbox/qubo/solvers/QuantagoniaQuboSolver.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/KipuQuboSolver.java b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/KipuQuboSolver.java index aa7ae48a..060c01f1 100644 --- a/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/KipuQuboSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/KipuQuboSolver.java @@ -46,6 +46,7 @@ public String getDescription() { public List getSolverSettings() { return List.of( new TextSetting( + true, SETTING_PLANQK_TOKEN, "Create access token as shown in docs: https://docs.planqk.de/services/applications.html" ) diff --git a/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QuantagoniaQuboSolver.java b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QuantagoniaQuboSolver.java index 40cf327a..5862a833 100644 --- a/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QuantagoniaQuboSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QuantagoniaQuboSolver.java @@ -44,6 +44,7 @@ public String getDescription() { public List getSolverSettings() { return List.of( new TextSetting( + true, SETTING_PLANQK_TOKEN, "Create access token as shown in docs: https://docs.planqk.de/services/applications.html" ) From c8458e72daee1fcc86ab9a3b8a2363c58bc556be Mon Sep 17 00:00:00 2001 From: ekulos-code Date: Wed, 19 Mar 2025 17:29:27 +0100 Subject: [PATCH 10/39] Implement suggestions --- .../projectq-executor/projectq_executor.py | 17 ----------------- solvers/circuitprocessing/requirements.txt | 2 -- .../solver/executor/ExecutionSolver.java | 2 +- .../solver/optimization/OptimizationSolver.java | 5 +++-- 4 files changed, 4 insertions(+), 22 deletions(-) delete mode 100644 solvers/circuitprocessing/projectq-executor/projectq_executor.py diff --git a/solvers/circuitprocessing/projectq-executor/projectq_executor.py b/solvers/circuitprocessing/projectq-executor/projectq_executor.py deleted file mode 100644 index 8600c2bd..00000000 --- a/solvers/circuitprocessing/projectq-executor/projectq_executor.py +++ /dev/null @@ -1,17 +0,0 @@ -import sys -from pytket.qasm import circuit_from_qasm_str -from pytket.extensions.projectq import ProjectQBackend - -input_circuit = sys.argv[1] -shots = int(sys.argv[2]) - -try: - circuit = circuit_from_qasm_str(input_circuit) -except Exception as e: - print("Was not able to convert to OpenQASM: ", e) - sys.exit(1) - -backend = ProjectQBackend() -handle = backend.process_circuit(circuit, n_shots=shots) -result = backend.get_result(handle) -print(result.get_shots()) \ No newline at end of file diff --git a/solvers/circuitprocessing/requirements.txt b/solvers/circuitprocessing/requirements.txt index 40a709cf..4fde5da3 100644 --- a/solvers/circuitprocessing/requirements.txt +++ b/solvers/circuitprocessing/requirements.txt @@ -1,5 +1,3 @@ pytket pytket-qiskit -pytket-pyquil -pytket-projectq pytket-qulacs \ No newline at end of file diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java index 58ed0aeb..754967fe 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java @@ -53,7 +53,7 @@ public List getSolverSettings() { SETTING_NUMBER_OF_SHOTS, "The number of shots to run", 1, - 10000, + 1000000, DEFAULT_NUMBER_OF_SHOTS), new SelectSetting<>( SETTING_SELECT_SIMULATOR, diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java index 8c883e00..ebd8dced 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java @@ -37,12 +37,13 @@ public OptimizationSolver( @Override public String getName() { - return "Optimize OpenQASM circuit"; + return "Apply Tket Optimization Pass"; } @Override public String getDescription() { - return "Run optimization algorithms on an OpenQASM circuit"; + return "Transform the given circuit into an optimized but equivalent circuit using" + + "Tket compilation passes (e.g. removing redundancies)."; } @Override From a765973d8728c979897f2c13c3b65b3d576e5a19 Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Tue, 25 Mar 2025 15:13:23 +0100 Subject: [PATCH 11/39] fix: changed cirq version because the defined one was not available on macos --- solvers/cirq/max-cut/requirements.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/solvers/cirq/max-cut/requirements.txt b/solvers/cirq/max-cut/requirements.txt index 746a80ce..ef2aec1e 100644 --- a/solvers/cirq/max-cut/requirements.txt +++ b/solvers/cirq/max-cut/requirements.txt @@ -1,7 +1,8 @@ # This file describes the python package requirements for the Cirq MaxCut solver matplotlib -cirq==1.5.0.dev20241009204224 +cirq networkx pandas + sympy -numpy \ No newline at end of file +numpy From 7b9277c7d5518e51f6db789e340b1c5fc100aa69 Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Tue, 25 Mar 2025 15:17:00 +0100 Subject: [PATCH 12/39] fix: checkstyle issues --- .../toolbox/process/ProcessRunner.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java b/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java index 01e0f71b..4e936b29 100644 --- a/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java +++ b/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java @@ -43,12 +43,10 @@ public class ProcessRunner { private static final String OUTPUT_FILE_NAME = "output"; protected final ProcessBuilder processBuilder; - protected ResourceProvider resourceProvider; - protected final List, UUID, Optional>> preProcessors; protected final List, UUID, Optional>> postProcessors; protected final List> argumentTransformers; - + protected ResourceProvider resourceProvider; /** * The directory of the problem that is being solved. * Only set when the run method is called. @@ -60,7 +58,8 @@ public ProcessRunner(ProcessBuilder processBuilder) { this.preProcessors = new ArrayList<>(); this.postProcessors = new ArrayList<>(); this.argumentTransformers = new ArrayList<>(); - argumentTransformers.add(x -> x.replace(PROBLEM_DIRECTORY_PATH, problemDirectory)); + argumentTransformers.add(x -> + x.replace(PROBLEM_DIRECTORY_PATH, problemDirectory)); } protected static ProcessBuilder createGenericProcessBuilder( @@ -94,7 +93,7 @@ public ProcessRunner writeInputFile(String inputData) { /** * Writes the input data to a specific input file. * - * @param inputData The input data to be written to the input file. + * @param inputData The input data to be written to the input file. * @param inputFileName The name of the file to write the input data to. * @return ProcessRunner instance for chaining. */ @@ -162,7 +161,7 @@ public ProcessRunnerExecutor readOutputFile(String outputFileName) { * Reads the output data from a default output file using a custom reader. * * @param reader The reader to use to read the output data. - * @param The type of the output data. + * @param The type of the output data. * @return ProcessRunner instance for chaining. */ public ProcessRunnerExecutor readOutputFile(ProcessResultReader reader) { @@ -173,8 +172,8 @@ public ProcessRunnerExecutor readOutputFile(ProcessResultReader reader * Reads the output data from a specific output file using a custom reader. * * @param outputFileName The name of the file to read the output data from. - * @param reader The reader to use to read the output data. - * @param The type of the output data. + * @param reader The reader to use to read the output data. + * @param The type of the output data. * @return ProcessRunner instance for chaining. */ public ProcessRunnerExecutor readOutputFile(String outputFileName, @@ -215,7 +214,7 @@ public ProcessRunnerExecutor readOutputFile(String outputFileName, /** * Adds an environment variable to the process. * - * @param key The key of the environment variable. + * @param key The key of the environment variable. * @param value The value of the environment variable. * @return ProcessRunner instance for chaining. */ @@ -295,7 +294,8 @@ protected ProcessRunnerExecutor getExecutor( int processExitCode; try { processBuilder.directory(new File(System.getProperty("user.dir"))); - String command = processBuilder.command().stream().reduce("", (a, b) -> a + " |break| " + b); + String command = + processBuilder.command().stream().reduce("", (a, b) -> a + " |break| " + b); System.out.println("ProcessBuilder command: " + command); Process process = processBuilder.start(); From 383b9d671d065cebb8992f72649a3f6b8624e0d1 Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Tue, 25 Mar 2025 15:46:11 +0100 Subject: [PATCH 13/39] fix: another checkstyle error --- .../edu/kit/provideq/toolbox/process/PythonProcessRunner.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java b/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java index 82b7f2da..76f38ae7 100644 --- a/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java +++ b/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java @@ -58,7 +58,8 @@ public ProcessRunner withArguments(String... arguments) { processBuilder.command(argument); } else { List existingCommands = processBuilder.command(); - System.out.println(String.format("Adding argument %s to existing commands %s", argument, String.join(" ", existingCommands))); + System.out.println(String.format("Adding argument %s to existing commands %s", argument, + String.join(" ", existingCommands))); int lastIndex = existingCommands.size() - 1; String lastCommand = existingCommands.get(lastIndex); existingCommands.remove(lastIndex); From be29e7cdb14c1fd6a20de4468744641e7886cd70 Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Tue, 1 Apr 2025 15:49:21 +0200 Subject: [PATCH 14/39] fix: added command to Dockerfile to ensure that ganak binaries are executable --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index 1bc8bacd..b0397b6f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -51,6 +51,8 @@ ENV PATH="${PATH}:/opt/java/bin" COPY solvers solvers COPY demonstrators demonstrators RUN scripts/ci-setup-solvers.sh +RUN chmod +x solvers/custom/sharp-sat-ganak/bin/ganak-linux +RUN chmod +x solvers/custom/sharp-sat-ganak/bin/ganak-mac COPY --from=builder /app/build/libs/toolbox-server-*.jar toolbox-server.jar # Run the toolbox server on dokku's default port From 6a4fa5db8053eb1acbe864855ae6ed0c1e2a7ec5 Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Wed, 2 Apr 2025 15:26:47 +0200 Subject: [PATCH 15/39] fix: testing new GAMS version --- scripts/setup-gams.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/setup-gams.sh b/scripts/setup-gams.sh index a4384e2b..79aa9f36 100755 --- a/scripts/setup-gams.sh +++ b/scripts/setup-gams.sh @@ -19,7 +19,7 @@ apt-get install curl --yes # iisaa/gams-docker (https://github.com/iiasa/gams-docker/blob/master/Dockerfile, GPL-3.0 licensed) # Configure the GAMS version here -GAMS_VERSION_RELEASE_MAJOR=42.1 +GAMS_VERSION_RELEASE_MAJOR=49.3 GAMS_VERSION_HOTFIX=0 # download the self-extracting archive to /opt/gams/gams.exe and run/extract it From 771e17cf3fc5fe89f8ec03058203f7a0efca9b53 Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Wed, 2 Apr 2025 18:12:14 +0200 Subject: [PATCH 16/39] fix: removed chmod from dockerfile and applied it directly to solvers --- Dockerfile | 2 -- solvers/custom/sharp-sat-ganak/bin/ganak-linux | Bin solvers/custom/sharp-sat-ganak/bin/ganak-mac | Bin 3 files changed, 2 deletions(-) mode change 100644 => 100755 solvers/custom/sharp-sat-ganak/bin/ganak-linux mode change 100644 => 100755 solvers/custom/sharp-sat-ganak/bin/ganak-mac diff --git a/Dockerfile b/Dockerfile index b0397b6f..1bc8bacd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -51,8 +51,6 @@ ENV PATH="${PATH}:/opt/java/bin" COPY solvers solvers COPY demonstrators demonstrators RUN scripts/ci-setup-solvers.sh -RUN chmod +x solvers/custom/sharp-sat-ganak/bin/ganak-linux -RUN chmod +x solvers/custom/sharp-sat-ganak/bin/ganak-mac COPY --from=builder /app/build/libs/toolbox-server-*.jar toolbox-server.jar # Run the toolbox server on dokku's default port diff --git a/solvers/custom/sharp-sat-ganak/bin/ganak-linux b/solvers/custom/sharp-sat-ganak/bin/ganak-linux old mode 100644 new mode 100755 diff --git a/solvers/custom/sharp-sat-ganak/bin/ganak-mac b/solvers/custom/sharp-sat-ganak/bin/ganak-mac old mode 100644 new mode 100755 From b5cd8840970c543b3e84064d56aa232d018f6f53 Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Wed, 2 Apr 2025 19:30:08 +0200 Subject: [PATCH 17/39] fix: improved error messages for testing / only print problem states when something goes wrong --- .../toolbox/process/ProcessRunner.java | 1 - .../toolbox/process/PythonProcessRunner.java | 2 -- .../provideq/toolbox/api/ApiTestHelper.java | 18 +++++++++++++----- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java b/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java index 4e936b29..21314223 100644 --- a/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java +++ b/src/main/java/edu/kit/provideq/toolbox/process/ProcessRunner.java @@ -296,7 +296,6 @@ protected ProcessRunnerExecutor getExecutor( processBuilder.directory(new File(System.getProperty("user.dir"))); String command = processBuilder.command().stream().reduce("", (a, b) -> a + " |break| " + b); - System.out.println("ProcessBuilder command: " + command); Process process = processBuilder.start(); processOutput = resourceProvider.readStream(process.inputReader()); diff --git a/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java b/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java index 76f38ae7..212317f1 100644 --- a/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java +++ b/src/main/java/edu/kit/provideq/toolbox/process/PythonProcessRunner.java @@ -58,8 +58,6 @@ public ProcessRunner withArguments(String... arguments) { processBuilder.command(argument); } else { List existingCommands = processBuilder.command(); - System.out.println(String.format("Adding argument %s to existing commands %s", argument, - String.join(" ", existingCommands))); int lastIndex = existingCommands.size() - 1; String lastCommand = existingCommands.get(lastIndex); existingCommands.remove(lastIndex); diff --git a/src/test/java/edu/kit/provideq/toolbox/api/ApiTestHelper.java b/src/test/java/edu/kit/provideq/toolbox/api/ApiTestHelper.java index cb2c9e99..c9618c18 100644 --- a/src/test/java/edu/kit/provideq/toolbox/api/ApiTestHelper.java +++ b/src/test/java/edu/kit/provideq/toolbox/api/ApiTestHelper.java @@ -141,9 +141,11 @@ public static ProblemDto trySolveFor( // Wait for problem 10 times long waitMilliseconds = seconds * 1000 / 10; + StringBuilder builder = new StringBuilder(); + ProblemDto problemDto; while (true) { - System.out.println("Checking if problem is solved..."); + builder.append("Checking if problem is solved...\n"); problemDto = client.get() .uri("/problems/" + problemType.getId() + "/" + problemId) .exchange() @@ -152,7 +154,7 @@ public static ProblemDto trySolveFor( }) .returnResult() .getResponseBody(); - System.out.println("Fetched problem: " + problemDto); + builder.append("Fetched problem: " + problemDto + "\n"); assertNotNull(problemDto); @@ -171,13 +173,13 @@ public static ProblemDto trySolveFor( }) .returnResult() .getResponseBody(); - System.out.println("Fetched sub problem: " + subProblemDto); + builder.append("Fetched sub problem: " + subProblemDto + "\n"); assertNotNull(subProblemDto); } } - System.out.println("Problem not solved yet. Waiting 5 seconds..."); + builder.append("Problem not solved yet. Waiting 5 seconds...\n"); try { Thread.sleep(waitMilliseconds); @@ -190,8 +192,14 @@ public static ProblemDto trySolveFor( } } + // print error output if something went wrong + if (problemDto.getState() != ProblemState.SOLVED + || problemDto.getSolution().getStatus() != SolutionStatus.SOLVED) { + System.out.println(builder); + } + assertEquals(ProblemState.SOLVED, problemDto.getState()); - Assertions.assertEquals(SolutionStatus.SOLVED, problemDto.getSolution().getStatus()); + assertEquals(SolutionStatus.SOLVED, problemDto.getSolution().getStatus()); return problemDto; } From cf64b9ac614ab7faaa794756895fad7bd1ff2dec Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Thu, 3 Apr 2025 13:44:19 +0200 Subject: [PATCH 18/39] fix: checkstyle issue --- .../provideq/toolbox/api/ApiTestHelper.java | 117 +++++++++--------- 1 file changed, 58 insertions(+), 59 deletions(-) diff --git a/src/test/java/edu/kit/provideq/toolbox/api/ApiTestHelper.java b/src/test/java/edu/kit/provideq/toolbox/api/ApiTestHelper.java index c9618c18..53511624 100644 --- a/src/test/java/edu/kit/provideq/toolbox/api/ApiTestHelper.java +++ b/src/test/java/edu/kit/provideq/toolbox/api/ApiTestHelper.java @@ -17,7 +17,6 @@ import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Stream; -import org.junit.jupiter.api.Assertions; import org.mockito.Mockito; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.MediaType; @@ -26,23 +25,23 @@ public class ApiTestHelper { public static Stream> getAllArgumentCombinations( - ProblemManager problemManager) { + ProblemManager problemManager) { return getAllArgumentCombinations(problemManager, List.of()); } public static Stream> getAllArgumentCombinations( - ProblemManager problemManager, - List... lists) { + ProblemManager problemManager, + List... lists) { // Get all solvers var solvers = problemManager.getSolvers().stream().toList(); // Get all example inputs var problems = problemManager.getExampleInstances() - .stream() - .map(Problem::getInput) - .filter(Optional::isPresent) - .map(Optional::get) - .toList(); + .stream() + .map(Problem::getInput) + .filter(Optional::isPresent) + .map(Optional::get) + .toList(); List> arguments = new ArrayList<>(List.of(solvers, problems)); for (List list : lists) { @@ -70,10 +69,10 @@ public static Stream concatAll(Stream... streams) { } public static ProblemDto createProblem( - WebTestClient client, - ProblemSolver solver, - InputT input, - ProblemType problemType) { + WebTestClient client, + ProblemSolver solver, + InputT input, + ProblemType problemType) { // Initialize mock solver var problemDtoMock = Mockito.mock(ProblemDto.class); Mockito.when(problemDtoMock.getSolverId()).thenReturn(solver.getId()); @@ -81,15 +80,15 @@ public static ProblemDto createProblem( Mockito.when(problemDtoMock.getState()).thenReturn(ProblemState.SOLVING); var problem = client.post() - .uri("/problems/" + problemType.getId()) - .contentType(MediaType.APPLICATION_JSON) - .bodyValue(problemDtoMock) - .exchange() - .expectStatus().isOk() - .expectBody(new ParameterizedTypeReference>() { - }) - .returnResult() - .getResponseBody(); + .uri("/problems/" + problemType.getId()) + .contentType(MediaType.APPLICATION_JSON) + .bodyValue(problemDtoMock) + .exchange() + .expectStatus().isOk() + .expectBody(new ParameterizedTypeReference>() { + }) + .returnResult() + .getResponseBody(); assertNotNull(problem); assertEquals(input, problem.getInput()); @@ -98,25 +97,25 @@ public static ProblemDto createProblem( } public static ProblemDto setProblemSolver( - WebTestClient client, - ProblemSolver solver, - String problemId, - String problemTypeId) { + WebTestClient client, + ProblemSolver solver, + String problemId, + String problemTypeId) { // Set subroutine solver and state var problemDtoMock = Mockito.mock(ProblemDto.class); Mockito.when(problemDtoMock.getSolverId()).thenReturn(solver.getId()); Mockito.when(problemDtoMock.getState()).thenReturn(ProblemState.SOLVING); var problem = client.patch() - .uri("/problems/" + problemTypeId + "/" + problemId) - .contentType(MediaType.APPLICATION_JSON) - .bodyValue(problemDtoMock) - .exchange() - .expectStatus().isOk() - .expectBody(new ParameterizedTypeReference>() { - }) - .returnResult() - .getResponseBody(); + .uri("/problems/" + problemTypeId + "/" + problemId) + .contentType(MediaType.APPLICATION_JSON) + .bodyValue(problemDtoMock) + .exchange() + .expectStatus().isOk() + .expectBody(new ParameterizedTypeReference>() { + }) + .returnResult() + .getResponseBody(); assertNotNull(problem); @@ -125,18 +124,18 @@ public static ProblemDto setProblemSolver( @SuppressWarnings("BusyWait") public static ProblemDto trySolveFor( - long seconds, - WebTestClient client, - String problemId, - ProblemType problemType) { + long seconds, + WebTestClient client, + String problemId, + ProblemType problemType) { AtomicBoolean hasTimeout = new AtomicBoolean(false); // Timeout throwing exception in x seconds Mono.delay(Duration.ofSeconds(seconds)) - .flux() - .doOnNext(x -> { - hasTimeout.set(true); - }) - .subscribe(); + .flux() + .doOnNext(x -> { + hasTimeout.set(true); + }) + .subscribe(); // Wait for problem 10 times long waitMilliseconds = seconds * 1000 / 10; @@ -147,13 +146,13 @@ public static ProblemDto trySolveFor( while (true) { builder.append("Checking if problem is solved...\n"); problemDto = client.get() - .uri("/problems/" + problemType.getId() + "/" + problemId) - .exchange() - .expectStatus().isOk() - .expectBody(new ParameterizedTypeReference>() { - }) - .returnResult() - .getResponseBody(); + .uri("/problems/" + problemType.getId() + "/" + problemId) + .exchange() + .expectStatus().isOk() + .expectBody(new ParameterizedTypeReference>() { + }) + .returnResult() + .getResponseBody(); builder.append("Fetched problem: " + problemDto + "\n"); assertNotNull(problemDto); @@ -166,13 +165,13 @@ public static ProblemDto trySolveFor( String subProblemTypeId = subProblem.getSubRoutine().getTypeId(); for (String subProblemId : subProblem.getSubProblemIds()) { var subProblemDto = client.get() - .uri("/problems/" + subProblemTypeId + "/" + subProblemId) - .exchange() - .expectStatus().isOk() - .expectBody(new ParameterizedTypeReference>() { - }) - .returnResult() - .getResponseBody(); + .uri("/problems/" + subProblemTypeId + "/" + subProblemId) + .exchange() + .expectStatus().isOk() + .expectBody(new ParameterizedTypeReference>() { + }) + .returnResult() + .getResponseBody(); builder.append("Fetched sub problem: " + subProblemDto + "\n"); assertNotNull(subProblemDto); @@ -194,7 +193,7 @@ public static ProblemDto trySolveFor( // print error output if something went wrong if (problemDto.getState() != ProblemState.SOLVED - || problemDto.getSolution().getStatus() != SolutionStatus.SOLVED) { + || problemDto.getSolution().getStatus() != SolutionStatus.SOLVED) { System.out.println(builder); } From 56febe6a81d2b79d4d35b02d5a7b7ff02d4089e6 Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Thu, 3 Apr 2025 16:27:33 +0200 Subject: [PATCH 19/39] fix: mentioned qiskit version explicitly because qiskit 2.0 does not support SamplerV1 anymore --- solvers/qiskit/knapsack/requirements.txt | 2 ++ solvers/qiskit/max-cut/requirements.txt | 3 ++- solvers/qiskit/qubo/requirements.txt | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/solvers/qiskit/knapsack/requirements.txt b/solvers/qiskit/knapsack/requirements.txt index e0471f77..3f34f649 100644 --- a/solvers/qiskit/knapsack/requirements.txt +++ b/solvers/qiskit/knapsack/requirements.txt @@ -1,2 +1,4 @@ # This file describes the python package requirements for the Qiskit Knapsack solver +qiskit == 1.4.2 qiskit-optimization == 0.6.1 + diff --git a/solvers/qiskit/max-cut/requirements.txt b/solvers/qiskit/max-cut/requirements.txt index ce8fc4e2..7823972c 100644 --- a/solvers/qiskit/max-cut/requirements.txt +++ b/solvers/qiskit/max-cut/requirements.txt @@ -1,5 +1,6 @@ # This file describes the python package requirements for the Qiskit Max-Cut solver pygmlparser == 1.0.1 +qiskit == 1.4.2 qiskit-optimization == 0.6.1 numpy -networkx \ No newline at end of file +networkx diff --git a/solvers/qiskit/qubo/requirements.txt b/solvers/qiskit/qubo/requirements.txt index dbf99f32..04bd3e61 100644 --- a/solvers/qiskit/qubo/requirements.txt +++ b/solvers/qiskit/qubo/requirements.txt @@ -1,2 +1,3 @@ # This file describes the python package requirements for the Qiskit QUBO solver +qiskit == 1.4.2 qiskit-optimization == 0.6.1 From 5ee7eb6d442332db6197ce6205294de447b3ea2e Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Thu, 3 Apr 2025 16:53:23 +0200 Subject: [PATCH 20/39] fix: added networkx python dependency to gams setup, removed gams requirement.txt files because they dont use our custom venv setup --- scripts/setup-gams.sh | 1 + solvers/gams/max-cut/requirements.txt | 3 --- solvers/gams/sat/requirements.txt | 2 -- 3 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 solvers/gams/max-cut/requirements.txt delete mode 100644 solvers/gams/sat/requirements.txt diff --git a/scripts/setup-gams.sh b/scripts/setup-gams.sh index 79aa9f36..8ce91fca 100755 --- a/scripts/setup-gams.sh +++ b/scripts/setup-gams.sh @@ -73,6 +73,7 @@ source /opt/conda/bin/activate gams # install GAMS links for python pip install gamsapi[core,connect] --find-links /opt/gams/gams${GAMS_VERSION_RELEASE_MAJOR}_linux_x64_64_sfx/api/python/bdist +pip install networkx # make GAMS use our python version echo "export GMSPYTHONLIB=/opt/conda/envs/gams/lib/libpython3.10.so" >> ~/.bashrc diff --git a/solvers/gams/max-cut/requirements.txt b/solvers/gams/max-cut/requirements.txt deleted file mode 100644 index a134aa9a..00000000 --- a/solvers/gams/max-cut/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -# This file describes the python package requirements for the GAMS Max-Cut solver -networkx -gamsapi[core,connect] \ No newline at end of file diff --git a/solvers/gams/sat/requirements.txt b/solvers/gams/sat/requirements.txt deleted file mode 100644 index b05a3184..00000000 --- a/solvers/gams/sat/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -# This file describes the python package requirements for the GAMS SAT solver -gamsapi[core,connect] \ No newline at end of file From b5f70d19e171206b6aea7a64264bf4345807bed6 Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Mon, 7 Apr 2025 13:56:44 +0200 Subject: [PATCH 21/39] fix: updated gams-maxcut cholesky transformation calls --- solvers/gams/max-cut/maxcut.gms | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solvers/gams/max-cut/maxcut.gms b/solvers/gams/max-cut/maxcut.gms index 71360a5e..4c8ebb28 100644 --- a/solvers/gams/max-cut/maxcut.gms +++ b/solvers/gams/max-cut/maxcut.gms @@ -133,7 +133,7 @@ $set LSYM L execute_unload 'csdpin.gdx' n = m, n, c, F, F0; execute.checkErrorLevel 'gams runcsdp.inc lo=%gams.lo% --strict=1' execute_load 'csdpout.gdx' Y; -$libInclude linalg cholesky n Y L +$callTool linalg.cholesky n Y L SDPRelaxation = 0.5*sum(e, w(e)*(1 - Y(e))); @@ -155,7 +155,7 @@ Solve sdp min sdpobj using lp; Parameter Yl(i,j) 'level values of Y as parameter'; Yl(i,j) = Y.l(i,j); -$libInclude linalg cholesky n Yl L +$callTool linalg.cholesky n Yl L SDPRelaxation = 0.5*sum(e, w(e)*(1 - Y.l(e))); From dc765c8aab8e50efa512d2adea21ef115fcaa850 Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Wed, 9 Apr 2025 10:24:30 +0200 Subject: [PATCH 22/39] fix: trying some minor changes in maxcut gams script --- solvers/gams/max-cut/maxcut.gms | 42 ++++++++++++--------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/solvers/gams/max-cut/maxcut.gms b/solvers/gams/max-cut/maxcut.gms index 4c8ebb28..8c3d43e3 100644 --- a/solvers/gams/max-cut/maxcut.gms +++ b/solvers/gams/max-cut/maxcut.gms @@ -9,27 +9,10 @@ defined to be sum of weights of the edges crossing the cut. This model presents a simple MIP formulation of the problem that is seeded with a solution from the Goemans/Williamson randomized approximation algorithm based on a semidefinite programming -relaxation. By default CSDP is used to solve the SDP. -Use --SDPSOLVER=MOSEK to switch to Mosek. - -The MaxCut instance tg20_7777 is available from the Biq Mac Library -and comes from applications in statistical physics. - - -Wiegele A., Biq Mac Library - Binary Quadratic and Max Cut Library. -http://biqmac.uni-klu.ac.at/biqmaclib.html - -Goemans M.X., and Williamson, D.P., Improved Approximation Algorithms -for Maximum Cut and Satisfiability Problems Using Semidefinite -Programming. Journal of the ACM 42 (1995), 1115-1145. -http://www-math.mit.edu/~goemans/PAPERS/maxcut-jacm.pdf - -Keywords: mixed integer linear programming, approximation algorithms, - convex optimization, randomized algorithms, maximum cut problem, - mathematics +relaxation. The model uses MOSEK to solve the SDP. $offText -$if not set INPUT $abort Please provide an input file via --INPUT= +$if not set INPUT $abort Please provide an input file via --INPUT= $if not set TARGETATTRIBUTE $set TARGETATTRIBUTE weight $if not set SOLVESDP $set SOLVESDP 1 $if not set SOLVEMIP $set SOLVEMIP 0 @@ -58,7 +41,6 @@ parameter rep(*) / 'value of cut' -inf 'value of best known bound' +inf 'relative gap' NA /; - $ onembeddedCode Python: import networkx as nx graph = nx.read_gml("%INPUT%", label=None) @@ -72,7 +54,6 @@ w(e(i,j)) = w(i,j) + w(j,i); w(i,j)$(not e(i,j)) = 0; option e < w; -*option e:0:0:1, w:8:0:1; display n,e,w; * Simple MIP model Variable @@ -155,12 +136,20 @@ Solve sdp min sdpobj using lp; Parameter Yl(i,j) 'level values of Y as parameter'; Yl(i,j) = Y.l(i,j); -$callTool linalg.cholesky n Yl L +executeTool.checkErrorLevel 'linalg.cholesky n Yl L'; +* Symbol L has been loaded implicitly by executeTool.checkErrorLevel. The compiler instruction +* in the next line supresses errors about presumably unassigned symbols +$onImplicitAssign + +* Check if Cholesky factorization is correct +Parameter Y_, Ydiff; +Y_(i,j) = sum(n, L(i,n)*L(j,n)); +Ydiff(i,j) = round(Y.l(i,j) - Y_(i,j),1e-6); +option Ydiff:8:0:1; +abort$card(Ydiff) Ydiff; SDPRelaxation = 0.5*sum(e, w(e)*(1 - Y.l(e))); -$endif.sdpsolver - display SDPRelaxation; * Now do the random hyperplane r @@ -195,10 +184,10 @@ put_utility 'log' / '### Value of cut: ' rep('value of cut'):0:4; put_utility 'log' / '### Value of best known bound: ' rep('value of best known bound'):0:4; put_utility 'log' / '### Relative gap: ' rep('relative gap'):0:16; - * use computed feasible solution as starting point for MIP solve x.l(bestS) = 1; cut.l(e(i,j)) = x.l(i) xor x.l(j); +$endif.sdpsolver $endif.solvesdp $ifthene.solvemip %SOLVEMIP%==1 @@ -343,5 +332,4 @@ with open("%OUTPUT%", 'w') as fout: strEdge += " ]" fout.write(strEdge + '\n') fout.write("]") -endembeddedCode - +endembeddedCode \ No newline at end of file From 6e5940b8daf7ba7d2b5cfc019fe546bb9fefce43 Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Wed, 9 Apr 2025 12:05:27 +0200 Subject: [PATCH 23/39] fix: added exit to script to enforce ci pipeline failure when venv setup goes wrong --- scripts/install-python-dependencies.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/install-python-dependencies.py b/scripts/install-python-dependencies.py index f175b7fe..215af013 100644 --- a/scripts/install-python-dependencies.py +++ b/scripts/install-python-dependencies.py @@ -9,6 +9,7 @@ os.path.join(root_dir, 'solvers'), ] +exitCode = 0 for base_dir in base_dirs: for root, dirs, files in os.walk(base_dir): # Iterate over framework directory (cirq, gams, qiskit, etc.) @@ -32,3 +33,7 @@ subprocess.run([pip_executable, 'install', '-r', req_file], check=True) except subprocess.CalledProcessError as e: print(f"Error setting up virtual environment for {solver_dir}: {e}") + exitCode = 1 + +# let pipeline fail if there was an error in the venv setup. +exit(exitCode) \ No newline at end of file From c238a4d678671429a0b8e048373267a62beb03db Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Wed, 9 Apr 2025 12:33:05 +0200 Subject: [PATCH 24/39] add: caching for gradle and venv dependencies --- .github/workflows/ci-cd-develop.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/ci-cd-develop.yml b/.github/workflows/ci-cd-develop.yml index de72f01e..5ed3788e 100644 --- a/.github/workflows/ci-cd-develop.yml +++ b/.github/workflows/ci-cd-develop.yml @@ -13,11 +13,13 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + - name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' + - name: Set up GAMS shell: bash # required for the source command env: @@ -27,6 +29,26 @@ jobs: echo "/opt/conda/bin" >> "$GITHUB_PATH" echo "$GAMS_PATH" >> "$GITHUB_PATH" echo "GMSPYTHONLIB=/opt/conda/envs/gams/lib/libpython3.10.so" >> "$GITHUB_ENV" + + - name: Cache Venv Dependencies + uses: actions/cache@v4 + with: + path: ~/venv + # update venv when setup script or any solver has changed: + key: venv-${{ runner.os }}-${{ hashFiles('scripts/ci-setup-solvers.sh', 'solvers/**') }} + restore-keys: | + venv-${{ runner.os }}- + + - name: Cache Gradle Dependencies + uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + gradle-${{ runner.os }}- + - name: Install solver dependencies run: ./scripts/ci-setup-solvers.sh - name: Run checks @@ -34,12 +56,14 @@ jobs: run: | source /opt/conda/bin/activate gams ./gradlew check --info + - name: Archive test reports if: always() uses: actions/upload-artifact@v4 with: name: test-report path: build/reports/tests/test/ + - name: Archive style reports if: always() uses: actions/upload-artifact@v4 From 1e2a83998cd27867dd448ac570a9fbe1dd37978b Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Wed, 9 Apr 2025 12:47:57 +0200 Subject: [PATCH 25/39] fix: fixed paths in caching jobs, removed unnecessary debug output --- .github/workflows/ci-cd-develop.yml | 10 +++++----- .../edu/kit/provideq/toolbox/api/QuboSolverTest.java | 6 ------ 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci-cd-develop.yml b/.github/workflows/ci-cd-develop.yml index 5ed3788e..2d435ba4 100644 --- a/.github/workflows/ci-cd-develop.yml +++ b/.github/workflows/ci-cd-develop.yml @@ -33,7 +33,7 @@ jobs: - name: Cache Venv Dependencies uses: actions/cache@v4 with: - path: ~/venv + path: ${{ github.workspace }}/venv # update venv when setup script or any solver has changed: key: venv-${{ runner.os }}-${{ hashFiles('scripts/ci-setup-solvers.sh', 'solvers/**') }} restore-keys: | @@ -43,8 +43,8 @@ jobs: uses: actions/cache@v4 with: path: | - ~/.gradle/caches - ~/.gradle/wrapper + ${{ github.workspace }}/.gradle/caches + ${{ github.workspace }}/.gradle/wrapper key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | gradle-${{ runner.os }}- @@ -53,9 +53,9 @@ jobs: run: ./scripts/ci-setup-solvers.sh - name: Run checks shell: bash # required for the source command - run: | + run: | # change to "./gradlew check --info" for more debugging output. source /opt/conda/bin/activate gams - ./gradlew check --info + ./gradlew check - name: Archive test reports if: always() diff --git a/src/test/java/edu/kit/provideq/toolbox/api/QuboSolverTest.java b/src/test/java/edu/kit/provideq/toolbox/api/QuboSolverTest.java index 45bd33b2..5cdcad08 100644 --- a/src/test/java/edu/kit/provideq/toolbox/api/QuboSolverTest.java +++ b/src/test/java/edu/kit/provideq/toolbox/api/QuboSolverTest.java @@ -52,13 +52,7 @@ Stream provideArguments() { @ParameterizedTest @MethodSource("provideArguments") void testQuboSolvers(ProblemSolver solver, String input) { - System.out.println("Testing Solver: " + solver.getName()); var problemDto = ApiTestHelper.createProblem(client, solver, input, QUBO); ApiTestHelper.testSolution(problemDto); - - if (problemDto.getSolution().getStatus() != SolutionStatus.SOLVED) { - System.out.println("Test Failed, Input was: " + problemDto.getInput()); - System.out.println("Error Message: " + problemDto.getSolution().getDebugData()); - } } } From ad3af913e258d43deaf6ebb2a388dc85b7e58cca Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Wed, 9 Apr 2025 13:59:36 +0200 Subject: [PATCH 26/39] fix: gradle path for caching --- .github/workflows/ci-cd-develop.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-cd-develop.yml b/.github/workflows/ci-cd-develop.yml index 2d435ba4..74de523f 100644 --- a/.github/workflows/ci-cd-develop.yml +++ b/.github/workflows/ci-cd-develop.yml @@ -30,7 +30,7 @@ jobs: echo "$GAMS_PATH" >> "$GITHUB_PATH" echo "GMSPYTHONLIB=/opt/conda/envs/gams/lib/libpython3.10.so" >> "$GITHUB_ENV" - - name: Cache Venv Dependencies + - name: Cache Venv dependencies uses: actions/cache@v4 with: path: ${{ github.workspace }}/venv @@ -39,12 +39,12 @@ jobs: restore-keys: | venv-${{ runner.os }}- - - name: Cache Gradle Dependencies + - name: Cache Gradle dependencies uses: actions/cache@v4 with: path: | - ${{ github.workspace }}/.gradle/caches - ${{ github.workspace }}/.gradle/wrapper + root/.gradle/caches + root/.gradle/wrapper key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | gradle-${{ runner.os }}- From 5b6b878a5e61695cf27de4706717d403343ff7c1 Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Wed, 9 Apr 2025 14:11:09 +0200 Subject: [PATCH 27/39] fix: removed gradle caching for now --- .github/workflows/ci-cd-develop.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/ci-cd-develop.yml b/.github/workflows/ci-cd-develop.yml index 74de523f..5906b611 100644 --- a/.github/workflows/ci-cd-develop.yml +++ b/.github/workflows/ci-cd-develop.yml @@ -39,16 +39,6 @@ jobs: restore-keys: | venv-${{ runner.os }}- - - name: Cache Gradle dependencies - uses: actions/cache@v4 - with: - path: | - root/.gradle/caches - root/.gradle/wrapper - key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - gradle-${{ runner.os }}- - - name: Install solver dependencies run: ./scripts/ci-setup-solvers.sh - name: Run checks From 89acbe96be3032568f1d90c98501fc1c304305e5 Mon Sep 17 00:00:00 2001 From: Elscrux Date: Tue, 18 Mar 2025 22:46:34 +0100 Subject: [PATCH 28/39] feat: Make api token setting required --- .../edu/kit/provideq/toolbox/qubo/solvers/KipuQuboSolver.java | 1 + .../kit/provideq/toolbox/qubo/solvers/QuantagoniaQuboSolver.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/KipuQuboSolver.java b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/KipuQuboSolver.java index aa7ae48a..060c01f1 100644 --- a/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/KipuQuboSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/KipuQuboSolver.java @@ -46,6 +46,7 @@ public String getDescription() { public List getSolverSettings() { return List.of( new TextSetting( + true, SETTING_PLANQK_TOKEN, "Create access token as shown in docs: https://docs.planqk.de/services/applications.html" ) diff --git a/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QuantagoniaQuboSolver.java b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QuantagoniaQuboSolver.java index 40cf327a..5862a833 100644 --- a/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QuantagoniaQuboSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/qubo/solvers/QuantagoniaQuboSolver.java @@ -44,6 +44,7 @@ public String getDescription() { public List getSolverSettings() { return List.of( new TextSetting( + true, SETTING_PLANQK_TOKEN, "Create access token as shown in docs: https://docs.planqk.de/services/applications.html" ) From 3b6a0499db43a9144709e3268d6cbe4fb6f163dc Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Tue, 15 Apr 2025 13:25:37 +0200 Subject: [PATCH 29/39] chore: adjusted readme for new venv installation, added python install as extra step to pipeline --- .github/workflows/ci-cd-develop.yml | 24 ++++++++++++++--------- README.md | 22 ++++++--------------- solvers/custom/berger-vrp/HOW_TO_BUILD.md | 8 ++++++++ solvers/custom/lkh/HOW_TO_BUILD.md | 5 +++++ solvers/gams/python/requirements.txt | 3 +++ 5 files changed, 37 insertions(+), 25 deletions(-) create mode 100644 solvers/custom/berger-vrp/HOW_TO_BUILD.md create mode 100644 solvers/custom/lkh/HOW_TO_BUILD.md create mode 100644 solvers/gams/python/requirements.txt diff --git a/.github/workflows/ci-cd-develop.yml b/.github/workflows/ci-cd-develop.yml index 5906b611..e82eb564 100644 --- a/.github/workflows/ci-cd-develop.yml +++ b/.github/workflows/ci-cd-develop.yml @@ -20,15 +20,10 @@ jobs: java-version: '17' distribution: 'temurin' - - name: Set up GAMS - shell: bash # required for the source command - env: - GAMS_LICENSE: ${{ secrets.GAMS_LICENSE }} - run: | - source ./scripts/setup-gams.sh - echo "/opt/conda/bin" >> "$GITHUB_PATH" - echo "$GAMS_PATH" >> "$GITHUB_PATH" - echo "GMSPYTHONLIB=/opt/conda/envs/gams/lib/libpython3.10.so" >> "$GITHUB_ENV" + - name: Set up Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: 3.10 - name: Cache Venv dependencies uses: actions/cache@v4 @@ -41,6 +36,17 @@ jobs: - name: Install solver dependencies run: ./scripts/ci-setup-solvers.sh + + - name: Set up GAMS + shell: bash # required for the source command + env: + GAMS_LICENSE: ${{ secrets.GAMS_LICENSE }} + run: | + source ./scripts/setup-gams.sh + echo "/opt/conda/bin" >> "$GITHUB_PATH" + echo "$GAMS_PATH" >> "$GITHUB_PATH" + echo "GMSPYTHONLIB=/opt/conda/envs/gams/lib/libpython3.10.so" >> "$GITHUB_ENV" + - name: Run checks shell: bash # required for the source command run: | # change to "./gradlew check --info" for more debugging output. diff --git a/README.md b/README.md index 49482e95..be07e65a 100644 --- a/README.md +++ b/README.md @@ -13,22 +13,12 @@ A web-based user interface can be found in our 1. Python-based Solvers (Qiskit, Cirq, Dwave, Qrisp) 1. Install Python 2. Install Python dependencies by running `python scripts/install-python-dependencies.py`
- Alternatively, run `pip install -r requirements.txt` on all requirement.txt files in the /solvers directory. + **Note:** Ensure that you execute the script from the root directory! Otherwise the created venv/ directory might be created at the wrong path. 2. Compiled Solvers (e.g. used for VRP and TSP) - 1. Solvers implemented in compiled languages must be executed via binaries that are compiled for your operating system. For those types of solvers we usually include pre-compiled binaries for windows, mac (only arm), and unix. - * General Note: Solvers might be programmed in different languages. E.g., LKH-3 is implemented in C. Make sure that the solver-specific language is installed on your system. - 2. In case the pre-compiled versions do not work on your machine: re-compile them: - * LKH-3: - 1. Build LKH-3 using the offical guide: http://webhotel4.ruc.dk/~keld/research/LKH-3/ - 2. Put the build binary in `solvers/lkh/bin`, replace the binary that matches your OS. - * VRP-Pipeline (used for K-means, Two Phase Clustering, VRP to QUBO convertion): - 1. Install Rust: https://www.rust-lang.org/tools/install - 2. Install a specific Rust nightly build (needed cause the solver uses experimental features): `rustup install nightly-2023-07-01` - 3. Check how the nightly build is called on your machine (this is shown when running the install command, on Mac it is called *nightly-2023-07-01-aarch64-apple-darwin*) - 4. Set the nightly build as default: `rustup default nightly-2023-07-01(... specific version name on machine)` - 5. Download source code of the VRP-Pipeline: https://github.com/ProvideQ/hybrid-vrp-solver - 6. build the source code using `cargo build` - 7. Put the build binary in `solvers/berger-vrp/bin`, replace the binary that matches your OS. + 1. Solvers implemented in compiled languages must be executed via binaries that are compiled for your operating system. + For those types of solvers we usually include pre-compiled binaries for windows, mac (only arm), and unix. + 2. In case the pre-compiled versions do not work on your machine: re-compile them. + Detailed compliation guides can be found in the *solvers/custom/[solver-name]* directory. 3. GAMS (multiple solvers are build on this): 1. Install a python env that works with GAMS (skip this step if you don't need GAMS) 2. Install GAMS. (https://www.gams.com/download/) @@ -42,7 +32,7 @@ A web-based user interface can be found in our `pip install gams[core,connect] --find-links /api/python/bdist` * If you get an error building `psycopg2`, try to install these postgres packages: `sudo apt-get install postgresql libpq-dev` and run the `pip install ...` command again - 8. Install the python dependencies we use in our python packages: `pip install -r gams/requirements.txt` + 8. Install the python dependencies we use in our python packages: `pip install -r gams/python/requirements.txt` 4. Run the server using `./gradlew bootRun` ## Deployment diff --git a/solvers/custom/berger-vrp/HOW_TO_BUILD.md b/solvers/custom/berger-vrp/HOW_TO_BUILD.md new file mode 100644 index 00000000..5d550483 --- /dev/null +++ b/solvers/custom/berger-vrp/HOW_TO_BUILD.md @@ -0,0 +1,8 @@ +Install Guide for the VRP-Pipeline (used for K-means, Two Phase Clustering, VRP to QUBO convertion): +1. Install Rust: https://www.rust-lang.org/tools/install +2. Install a specific Rust nightly build (needed cause the solver uses experimental features): `rustup install nightly-2023-07-01` +3. Check how the nightly build is called on your machine (this is shown when running the install command, on Mac it is called *nightly-2023-07-01-aarch64-apple-darwin*) +4. Set the nightly build as default: `rustup default nightly-2023-07-01(... specific version name on machine)` +5. Download source code of the VRP-Pipeline: https://github.com/ProvideQ/hybrid-vrp-solver +6. build the source code using `cargo build` +7. Put the build binary in `solvers/berger-vrp/bin`, replace the binary that matches your OS. diff --git a/solvers/custom/lkh/HOW_TO_BUILD.md b/solvers/custom/lkh/HOW_TO_BUILD.md new file mode 100644 index 00000000..b51dc685 --- /dev/null +++ b/solvers/custom/lkh/HOW_TO_BUILD.md @@ -0,0 +1,5 @@ +The following steps explain how build the binaries of the LKH-3 solvers that are placed in solvers/custom/lkh/bin. +The binaries are called via the vrp_lkh.py wrapper. + +1. Build LKH-3 using the offical guide: http://webhotel4.ruc.dk/~keld/research/LKH-3/ +2. Put the build binary in `solvers/lkh/bin`, replace the binary that matches your OS. diff --git a/solvers/gams/python/requirements.txt b/solvers/gams/python/requirements.txt new file mode 100644 index 00000000..b1b37424 --- /dev/null +++ b/solvers/gams/python/requirements.txt @@ -0,0 +1,3 @@ +# This file describes the python package requirements for all GAMS solvers. +# We only build one venv for all of GAMS, not for every GAMS solver. +networkx From 3c47662acd3d5a71f99d4c8a48f00057dcfe982b Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Tue, 15 Apr 2025 13:28:36 +0200 Subject: [PATCH 30/39] fix: changed python version naming --- .github/workflows/ci-cd-develop.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd-develop.yml b/.github/workflows/ci-cd-develop.yml index e82eb564..08037278 100644 --- a/.github/workflows/ci-cd-develop.yml +++ b/.github/workflows/ci-cd-develop.yml @@ -23,7 +23,7 @@ jobs: - name: Set up Python 3.10 uses: actions/setup-python@v4 with: - python-version: 3.10 + python-version: 3.10.17 - name: Cache Venv dependencies uses: actions/cache@v4 From 600ff25e8d5840c5feaf31a51cb9e676ce5fb5c9 Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Tue, 15 Apr 2025 13:31:12 +0200 Subject: [PATCH 31/39] fix: reverted ci pipeline change --- .github/workflows/ci-cd-develop.yml | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci-cd-develop.yml b/.github/workflows/ci-cd-develop.yml index 08037278..da4d67d9 100644 --- a/.github/workflows/ci-cd-develop.yml +++ b/.github/workflows/ci-cd-develop.yml @@ -20,10 +20,15 @@ jobs: java-version: '17' distribution: 'temurin' - - name: Set up Python 3.10 - uses: actions/setup-python@v4 - with: - python-version: 3.10.17 + - name: Set up GAMS + shell: bash # required for the source command + env: + GAMS_LICENSE: ${{ secrets.GAMS_LICENSE }} + run: | + source ./scripts/setup-gams.sh + echo "/opt/conda/bin" >> "$GITHUB_PATH" + echo "$GAMS_PATH" >> "$GITHUB_PATH" + echo "GMSPYTHONLIB=/opt/conda/envs/gams/lib/libpython3.10.so" >> "$GITHUB_ENV" - name: Cache Venv dependencies uses: actions/cache@v4 @@ -37,16 +42,6 @@ jobs: - name: Install solver dependencies run: ./scripts/ci-setup-solvers.sh - - name: Set up GAMS - shell: bash # required for the source command - env: - GAMS_LICENSE: ${{ secrets.GAMS_LICENSE }} - run: | - source ./scripts/setup-gams.sh - echo "/opt/conda/bin" >> "$GITHUB_PATH" - echo "$GAMS_PATH" >> "$GITHUB_PATH" - echo "GMSPYTHONLIB=/opt/conda/envs/gams/lib/libpython3.10.so" >> "$GITHUB_ENV" - - name: Run checks shell: bash # required for the source command run: | # change to "./gradlew check --info" for more debugging output. From ab60556a12eda3fab0bf7e5bbb1533f187ae5193 Mon Sep 17 00:00:00 2001 From: Elscrux Date: Tue, 22 Apr 2025 11:17:22 +0200 Subject: [PATCH 32/39] docs: Update path --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index be07e65a..1c896dfc 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ A web-based user interface can be found in our `pip install gams[core,connect] --find-links /api/python/bdist` * If you get an error building `psycopg2`, try to install these postgres packages: `sudo apt-get install postgresql libpq-dev` and run the `pip install ...` command again - 8. Install the python dependencies we use in our python packages: `pip install -r gams/python/requirements.txt` + 8. Install the python dependencies we use in our python packages: `pip install -r ./solvers/gams/python/requirements.txt` 4. Run the server using `./gradlew bootRun` ## Deployment From 4873ec2424c36d956f999ef62e4cce063c62aa01 Mon Sep 17 00:00:00 2001 From: Elscrux Date: Tue, 22 Apr 2025 11:59:39 +0200 Subject: [PATCH 33/39] refactor: Use demonstrator specific application property names for cplex mip demonstrator --- .../provideq/toolbox/demonstrators/CplexMipDemonstrator.java | 4 ++-- src/main/resources/application.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/edu/kit/provideq/toolbox/demonstrators/CplexMipDemonstrator.java b/src/main/java/edu/kit/provideq/toolbox/demonstrators/CplexMipDemonstrator.java index d3f8269a..821356f2 100644 --- a/src/main/java/edu/kit/provideq/toolbox/demonstrators/CplexMipDemonstrator.java +++ b/src/main/java/edu/kit/provideq/toolbox/demonstrators/CplexMipDemonstrator.java @@ -28,8 +28,8 @@ public class CplexMipDemonstrator implements Demonstrator { @Autowired public CplexMipDemonstrator( - @Value("${path.cplex.mip}") String scriptPath, - @Value("${venv.cplex.mip}") String venv, + @Value("${path.demonstrators.cplex.mip}") String scriptPath, + @Value("${venv.demonstrators.cplex.mip}") String venv, ApplicationContext context) { this.scriptPath = scriptPath; this.venv = venv; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index bd646f28..86d54fb5 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1 @@ -# default spring profile, correct one will be set during runtime (see ToolboxServerApplication.java) # options: mac, windows, linux spring.profiles.active=linux springdoc.swagger-ui.operationsSorter=alpha springdoc.swagger-ui.tagsSorter=alpha working.directory=jobs examples.directory=examples springdoc.swagger-ui.path=/ # Solvers name.solvers=solvers # Non OS-specific solvers: (typically GAMS and Python) name.gams=gams path.gams=${name.solvers}/${name.gams} name.gams.max-cut=max-cut path.gams.max-cut=${path.gams}/${name.gams.max-cut}/maxcut.gms name.gams.sat=sat path.gams.sat=${path.gams}/${name.gams.sat}/sat.gms name.qiskit=qiskit path.qiskit=${name.solvers}/${name.qiskit} name.qiskit.knapsack=knapsack path.qiskit.knapsack=${path.qiskit}/${name.qiskit.knapsack}/knapsack_qiskit.py venv.qiskit.knapsack=${name.solvers}_${name.qiskit}_${name.qiskit.knapsack} name.qiskit.max-cut=max-cut path.qiskit.max-cut=${path.qiskit}/${name.qiskit.max-cut}/maxCut_qiskit.py venv.qiskit.max-cut=${name.solvers}_${name.qiskit}_${name.qiskit.max-cut} name.qiskit.qubo=qubo path.qiskit.qubo=${path.qiskit}/${name.qiskit.qubo}/qubo_qiskit.py venv.qiskit.qubo=${name.solvers}_${name.qiskit}_${name.qiskit.qubo} name.cirq=cirq path.cirq=${name.solvers}/${name.cirq} name.cirq.max-cut=max-cut path.cirq.max-cut=${path.cirq}/${name.cirq.max-cut}/max_cut_cirq.py venv.cirq.max-cut=${name.solvers}_${name.cirq}_${name.cirq.max-cut} name.qrisp=qrisp path.qrisp=${name.solvers}/${name.qrisp} name.qrisp.vrp=vrp path.qrisp.vrp=${path.qrisp}/${name.qrisp.vrp}/grover.py venv.qrisp.vrp=${name.solvers}_${name.qrisp}_${name.qrisp.vrp} name.qrisp.qubo=qubo path.qrisp.qubo=${path.qrisp}/${name.qrisp.qubo}/qaoa.py venv.qrisp.qubo=${name.solvers}_${name.qrisp}_${name.qrisp.qubo} name.qrisp.sat=sat path.qrisp.sat.grover=${path.qrisp}/${name.qrisp.sat}/grover.py path.qrisp.sat.exact=${path.qrisp}/${name.qrisp.sat}/exact_grover.py venv.qrisp.sat=${name.solvers}_${name.qrisp}_${name.qrisp.sat} name.dwave=dwave path.dwave=${name.solvers}/${name.dwave} name.dwave.qubo=qubo path.dwave.qubo=${path.dwave}/${name.dwave.qubo}/main.py venv.dwave.qubo=${name.solvers}_${name.dwave}_${name.dwave.qubo} # Non OS-specific custom solvers: (solvers that are not part of a framework) name.custom=custom path.custom=${name.solvers}/${name.custom} name.custom.hs-knapsack=hs-knapsack path.custom.hs-knapsack=${path.custom}/${name.custom.hs-knapsack}/knapsack.py venv.custom.hs-knapsack=${name.solvers}_${name.custom}_${name.custom.hs-knapsack} name.custom.lkh=lkh path.custom.lkh=${path.custom}/${name.custom.lkh}/vrp_lkh.py venv.custom.lkh=${name.solvers}_${name.custom}_${name.custom.lkh} name.custom.berger-vrp=berger-vrp name.custom.sharp-sat-bruteforce=sharp-sat-bruteforce path.custom.sharp-sat-bruteforce=${path.custom}/${name.custom.sharp-sat-bruteforce}/exact-solution-counter.py venv.custom.sharp-sat-bruteforce=${name.solvers}_${name.custom}_${name.custom.sharp-sat-bruteforce} name.custom.sharp-sat-ganak=sharp-sat-ganak venv.custom.sharp-sat-ganak=${name.solvers}_${name.custom}_${name.custom.sharp-sat-ganak} # Demonstrators name.demonstrators=demonstrators name.cplex=cplex path.cplex=${name.demonstrators}/${name.cplex} name.cplex.mip=mip-solver path.cplex.mip=${path.cplex}/${name.cplex.mip}/mip-solver.py venv.cplex.mip=${name.demonstrators}_${name.cplex}_${name.cplex.mip} \ No newline at end of file +# default spring profile, correct one will be set during runtime (see ToolboxServerApplication.java) # options: mac, windows, linux spring.profiles.active=linux springdoc.swagger-ui.operationsSorter=alpha springdoc.swagger-ui.tagsSorter=alpha working.directory=jobs examples.directory=examples springdoc.swagger-ui.path=/ # Solvers name.solvers=solvers # Non OS-specific solvers: (typically GAMS and Python) name.gams=gams path.gams=${name.solvers}/${name.gams} name.gams.max-cut=max-cut path.gams.max-cut=${path.gams}/${name.gams.max-cut}/maxcut.gms name.gams.sat=sat path.gams.sat=${path.gams}/${name.gams.sat}/sat.gms name.qiskit=qiskit path.qiskit=${name.solvers}/${name.qiskit} name.qiskit.knapsack=knapsack path.qiskit.knapsack=${path.qiskit}/${name.qiskit.knapsack}/knapsack_qiskit.py venv.qiskit.knapsack=${name.solvers}_${name.qiskit}_${name.qiskit.knapsack} name.qiskit.max-cut=max-cut path.qiskit.max-cut=${path.qiskit}/${name.qiskit.max-cut}/maxCut_qiskit.py venv.qiskit.max-cut=${name.solvers}_${name.qiskit}_${name.qiskit.max-cut} name.qiskit.qubo=qubo path.qiskit.qubo=${path.qiskit}/${name.qiskit.qubo}/qubo_qiskit.py venv.qiskit.qubo=${name.solvers}_${name.qiskit}_${name.qiskit.qubo} name.cirq=cirq path.cirq=${name.solvers}/${name.cirq} name.cirq.max-cut=max-cut path.cirq.max-cut=${path.cirq}/${name.cirq.max-cut}/max_cut_cirq.py venv.cirq.max-cut=${name.solvers}_${name.cirq}_${name.cirq.max-cut} name.qrisp=qrisp path.qrisp=${name.solvers}/${name.qrisp} name.qrisp.vrp=vrp path.qrisp.vrp=${path.qrisp}/${name.qrisp.vrp}/grover.py venv.qrisp.vrp=${name.solvers}_${name.qrisp}_${name.qrisp.vrp} name.qrisp.qubo=qubo path.qrisp.qubo=${path.qrisp}/${name.qrisp.qubo}/qaoa.py venv.qrisp.qubo=${name.solvers}_${name.qrisp}_${name.qrisp.qubo} name.qrisp.sat=sat path.qrisp.sat.grover=${path.qrisp}/${name.qrisp.sat}/grover.py path.qrisp.sat.exact=${path.qrisp}/${name.qrisp.sat}/exact_grover.py venv.qrisp.sat=${name.solvers}_${name.qrisp}_${name.qrisp.sat} name.dwave=dwave path.dwave=${name.solvers}/${name.dwave} name.dwave.qubo=qubo path.dwave.qubo=${path.dwave}/${name.dwave.qubo}/main.py venv.dwave.qubo=${name.solvers}_${name.dwave}_${name.dwave.qubo} # Non OS-specific custom solvers: (solvers that are not part of a framework) name.custom=custom path.custom=${name.solvers}/${name.custom} name.custom.hs-knapsack=hs-knapsack path.custom.hs-knapsack=${path.custom}/${name.custom.hs-knapsack}/knapsack.py venv.custom.hs-knapsack=${name.solvers}_${name.custom}_${name.custom.hs-knapsack} name.custom.lkh=lkh path.custom.lkh=${path.custom}/${name.custom.lkh}/vrp_lkh.py venv.custom.lkh=${name.solvers}_${name.custom}_${name.custom.lkh} name.custom.berger-vrp=berger-vrp name.custom.sharp-sat-bruteforce=sharp-sat-bruteforce path.custom.sharp-sat-bruteforce=${path.custom}/${name.custom.sharp-sat-bruteforce}/exact-solution-counter.py venv.custom.sharp-sat-bruteforce=${name.solvers}_${name.custom}_${name.custom.sharp-sat-bruteforce} name.custom.sharp-sat-ganak=sharp-sat-ganak venv.custom.sharp-sat-ganak=${name.solvers}_${name.custom}_${name.custom.sharp-sat-ganak} # Demonstrators name.demonstrators=demonstrators name.demonstrators.cplex=cplex path.demonstrators.cplex=${name.demonstrators}/${name.demonstrators.cplex} name.demonstrators.cplex.mip=mip-solver path.demonstrators.cplex.mip=${path.demonstrators.cplex}/${name.demonstrators.cplex.mip}/mip-solver.py venv.demonstrators.cplex.mip=${name.demonstrators}_${name.demonstrators.cplex}_${name.demonstrators.cplex.mip} \ No newline at end of file From 53aa6c8aa94d2e4a3a27a4d92d349e5dbd5bce6b Mon Sep 17 00:00:00 2001 From: Domenik Eichhorn Date: Wed, 7 May 2025 16:12:04 +0200 Subject: [PATCH 34/39] updated release version --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7c999150..dcad0d47 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } group = 'edu.kit.provideq' -version = '0.4.0' +version = '0.4.1' sourceCompatibility = '17' repositories { From 6f632d7b11b96d56cf610d8d302fa1cdba97c4c4 Mon Sep 17 00:00:00 2001 From: ekulos-code Date: Wed, 29 Jan 2025 15:15:59 +0100 Subject: [PATCH 35/39] Add basic structure for OpenQASM processing --- .../CircuitProcessingConfiguration.java | 39 +++++++++++++ .../solver/CircuitProcessingSolver.java | 12 ++++ .../solver/MoveToExecutionSolver.java | 58 +++++++++++++++++++ .../solver/MoveToMitigationSolver.java | 44 ++++++++++++++ .../solver/MoveToOptimizationSolver.java | 44 ++++++++++++++ .../solver/executor/ExecutionResult.java | 13 +++++ .../solver/executor/ExecutionSolver.java | 36 ++++++++++++ .../executor/ExecutorConfiguration.java | 32 ++++++++++ .../ErrorMitigationConfiguration.java | 34 +++++++++++ .../mitigation/ErrorMitigationSolver.java | 35 +++++++++++ .../OptimizationConfiguration.java | 32 ++++++++++ .../optimization/OptimizationSolver.java | 35 +++++++++++ 12 files changed, 414 insertions(+) create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionResult.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java create mode 100644 src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java new file mode 100644 index 00000000..193657ce --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java @@ -0,0 +1,39 @@ +package edu.kit.provideq.toolbox.circuit.processing; + +import edu.kit.provideq.toolbox.circuit.processing.solver.MoveToExecutionSolver; +import edu.kit.provideq.toolbox.circuit.processing.solver.MoveToMitigationSolver; +import edu.kit.provideq.toolbox.circuit.processing.solver.MoveToOptimizationSolver; +import edu.kit.provideq.toolbox.meta.Problem; +import edu.kit.provideq.toolbox.meta.ProblemManager; +import edu.kit.provideq.toolbox.meta.ProblemType; +import java.util.Set; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class CircuitProcessingConfiguration { + public static final ProblemType CIRCUIT_PROCESSING = new ProblemType<>( + "circuit-processing", + String.class, + String.class, + null + ); + + @Bean + ProblemManager getCircuitProcessingManager( + MoveToExecutionSolver moveToExecutionSolver, + MoveToOptimizationSolver moveToOptimizationSolver, + MoveToMitigationSolver moveToMitigationSolver + ) { + return new ProblemManager<>( + CIRCUIT_PROCESSING, + Set.of( + moveToExecutionSolver, + moveToOptimizationSolver, + moveToMitigationSolver + ), + // TODO: dummy problem + Set.of(new Problem<>(CIRCUIT_PROCESSING)) + ); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java new file mode 100644 index 00000000..7c978ad2 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java @@ -0,0 +1,12 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver; + +import edu.kit.provideq.toolbox.circuit.processing.CircuitProcessingConfiguration; +import edu.kit.provideq.toolbox.meta.ProblemSolver; +import edu.kit.provideq.toolbox.meta.ProblemType; + +public abstract class CircuitProcessingSolver implements ProblemSolver { + @Override + public ProblemType getProblemType() { + return CircuitProcessingConfiguration.CIRCUIT_PROCESSING; + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java new file mode 100644 index 00000000..19d555c8 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java @@ -0,0 +1,58 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver; + +import edu.kit.provideq.toolbox.Solution; +import edu.kit.provideq.toolbox.SolutionStatus; +import edu.kit.provideq.toolbox.circuit.processing.solver.executor.ExecutionResult; +import edu.kit.provideq.toolbox.circuit.processing.solver.executor.ExecutorConfiguration; +import edu.kit.provideq.toolbox.meta.SolvingProperties; +import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; +import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import java.util.List; + +@Component +public class MoveToExecutionSolver extends CircuitProcessingSolver { + private static final SubRoutineDefinition EXECUTOR_SUBROUTINE = + new SubRoutineDefinition<>( + ExecutorConfiguration.EXECUTOR_CONFIG, + "Creates a execution solver" + ); + + @Override + public String getName() { + return "Execute QASM Code"; + } + + @Override + public String getDescription() { + return "Move QASM input to the executors"; + } + + @Override + public List> getSubRoutines() { + return List.of(EXECUTOR_SUBROUTINE); + } + + @Override + public Mono> solve( + String input, + SubRoutineResolver subRoutineResolver, + SolvingProperties properties + ) { + return subRoutineResolver.runSubRoutine(EXECUTOR_SUBROUTINE, input) + .map(executionResultSolution -> { + Solution solution = new Solution<>(this); + SolutionStatus status = executionResultSolution.getStatus(); + if (status == SolutionStatus.ERROR) { + solution.fail(); + solution.setDebugData("An error occurred while executing the circuit"); + return solution; + } + solution.complete(); + solution.setSolutionData(executionResultSolution.getSolutionData().toString()); + return solution; + }); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java new file mode 100644 index 00000000..4c70a353 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java @@ -0,0 +1,44 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver; + +import edu.kit.provideq.toolbox.Solution; +import edu.kit.provideq.toolbox.circuit.processing.solver.mitigation.ErrorMitigationConfiguration; +import edu.kit.provideq.toolbox.meta.SolvingProperties; +import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; +import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import java.util.List; + +@Component +public class MoveToMitigationSolver extends CircuitProcessingSolver { + private static final SubRoutineDefinition MITIGATOR_SUBROUTINE = + new SubRoutineDefinition<>( + ErrorMitigationConfiguration.MITIGATION_CONFIG, + "Creates a mitigation solver" + ); + + @Override + public String getName() { + return "Mitigate QASM Code Errors"; + } + + @Override + public String getDescription() { + return "Move QASM input to the error mitigators"; + } + + @Override + public List> getSubRoutines() { + return List.of(MITIGATOR_SUBROUTINE); + } + + @Override + public Mono> solve( + String input, + SubRoutineResolver subRoutineResolver, + SolvingProperties properties + ) { + return subRoutineResolver.runSubRoutine(MITIGATOR_SUBROUTINE, input); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java new file mode 100644 index 00000000..a6d938f6 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java @@ -0,0 +1,44 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver; + +import edu.kit.provideq.toolbox.Solution; +import edu.kit.provideq.toolbox.circuit.processing.solver.optimization.OptimizationConfiguration; +import edu.kit.provideq.toolbox.meta.SolvingProperties; +import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; +import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import java.util.List; + +@Component +public class MoveToOptimizationSolver extends CircuitProcessingSolver { + private static final SubRoutineDefinition OPTIMIZER_SUBROUTINE = + new SubRoutineDefinition<>( + OptimizationConfiguration.OPTIMIZATION_CONFIG, + "Creates a optimization solver" + ); + + @Override + public String getName() { + return "Optimize QASM Code"; + } + + @Override + public String getDescription() { + return "Move QASM input to the optimizers"; + } + + @Override + public List> getSubRoutines() { + return List.of(OPTIMIZER_SUBROUTINE); + } + + @Override + public Mono> solve( + String input, + SubRoutineResolver subRoutineResolver, + SolvingProperties properties + ) { + return subRoutineResolver.runSubRoutine(OPTIMIZER_SUBROUTINE, input); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionResult.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionResult.java new file mode 100644 index 00000000..4751c2b7 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionResult.java @@ -0,0 +1,13 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver.executor; + +import java.util.Optional; + +public record ExecutionResult(Optional resultString, Optional circuit) { + public boolean hasResult() { + return resultString.isPresent(); + } + + public boolean hasCircuit() { + return circuit.isPresent(); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java new file mode 100644 index 00000000..9043bdea --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java @@ -0,0 +1,36 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver.executor; + +import edu.kit.provideq.toolbox.Solution; +import edu.kit.provideq.toolbox.meta.ProblemSolver; +import edu.kit.provideq.toolbox.meta.ProblemType; +import edu.kit.provideq.toolbox.meta.SolvingProperties; +import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import java.util.Optional; + +@Component +public class ExecutionSolver implements ProblemSolver { + @Override + public String getName() { + return "Execute OpenQASM circuit"; + } + + @Override + public String getDescription() { + return "Execute an OpenQASM circuit"; + } + + @Override + public Mono> solve(String input, SubRoutineResolver subRoutineResolver, SolvingProperties properties) { + var solution = new Solution<>(this); + solution.setSolutionData(new ExecutionResult(Optional.of(input), Optional.empty())); + return Mono.just(solution); + } + + @Override + public ProblemType getProblemType() { + return ExecutorConfiguration.EXECUTOR_CONFIG; + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java new file mode 100644 index 00000000..d93390f2 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java @@ -0,0 +1,32 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver.executor; + +import edu.kit.provideq.toolbox.meta.Problem; +import edu.kit.provideq.toolbox.meta.ProblemManager; +import edu.kit.provideq.toolbox.meta.ProblemType; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Set; + +@Configuration +public class ExecutorConfiguration { + public static final ProblemType EXECUTOR_CONFIG = new ProblemType<>( + "circuit-processing-executor", + String.class, + ExecutionResult.class, + null + ); + + @Bean + ProblemManager getExecutorProblemManager( + ExecutionSolver executionSolver + ) { + return new ProblemManager<>( + EXECUTOR_CONFIG, + Set.of( + executionSolver + ), + Set.of(new Problem<>(EXECUTOR_CONFIG)) + ); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java new file mode 100644 index 00000000..953efc12 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java @@ -0,0 +1,34 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver.mitigation; + +import edu.kit.provideq.toolbox.circuit.processing.solver.executor.ExecutionResult; +import edu.kit.provideq.toolbox.circuit.processing.solver.executor.ExecutionSolver; +import edu.kit.provideq.toolbox.meta.Problem; +import edu.kit.provideq.toolbox.meta.ProblemManager; +import edu.kit.provideq.toolbox.meta.ProblemType; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Set; + +@Configuration +public class ErrorMitigationConfiguration { + public static final ProblemType MITIGATION_CONFIG = new ProblemType<>( + "circuit-processing-mitigation", + String.class, + String.class, + null + ); + + @Bean + ProblemManager getMitigationProblemManager( + ErrorMitigationSolver errorMitigationSolver + ) { + return new ProblemManager<>( + MITIGATION_CONFIG, + Set.of( + errorMitigationSolver + ), + Set.of(new Problem<>(MITIGATION_CONFIG)) + ); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java new file mode 100644 index 00000000..5c70686a --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java @@ -0,0 +1,35 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver.mitigation; + +import edu.kit.provideq.toolbox.Solution; +import edu.kit.provideq.toolbox.meta.ProblemSolver; +import edu.kit.provideq.toolbox.meta.ProblemType; +import edu.kit.provideq.toolbox.meta.SolvingProperties; +import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +@Component +public class ErrorMitigationSolver implements ProblemSolver { + + @Override + public String getName() { + return "Mitigate Errors for OpenQASM"; + } + + @Override + public String getDescription() { + return "Run error mitigation strategies on an OpenQASM circuit"; + } + + @Override + public Mono> solve(String input, SubRoutineResolver subRoutineResolver, SolvingProperties properties) { + var solution = new Solution<>(this); + solution.setSolutionData(input); + return Mono.just(solution); + } + + @Override + public ProblemType getProblemType() { + return ErrorMitigationConfiguration.MITIGATION_CONFIG; + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java new file mode 100644 index 00000000..78dfbbfd --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java @@ -0,0 +1,32 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver.optimization; + +import edu.kit.provideq.toolbox.meta.Problem; +import edu.kit.provideq.toolbox.meta.ProblemManager; +import edu.kit.provideq.toolbox.meta.ProblemType; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Set; + +@Configuration +public class OptimizationConfiguration { + public static final ProblemType OPTIMIZATION_CONFIG = new ProblemType<>( + "circuit-processing-optimization", + String.class, + String.class, + null + ); + + @Bean + ProblemManager getOptimizationProblemManager( + OptimizationSolver optimizationSolver + ) { + return new ProblemManager<>( + OPTIMIZATION_CONFIG, + Set.of( + optimizationSolver + ), + Set.of(new Problem<>(OPTIMIZATION_CONFIG)) + ); + } +} diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java new file mode 100644 index 00000000..fcf51939 --- /dev/null +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java @@ -0,0 +1,35 @@ +package edu.kit.provideq.toolbox.circuit.processing.solver.optimization; + +import edu.kit.provideq.toolbox.Solution; +import edu.kit.provideq.toolbox.meta.ProblemSolver; +import edu.kit.provideq.toolbox.meta.ProblemType; +import edu.kit.provideq.toolbox.meta.SolvingProperties; +import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +@Component +public class OptimizationSolver implements ProblemSolver { + + @Override + public String getName() { + return "Optimize OpenQASM circuit"; + } + + @Override + public String getDescription() { + return "Run optimization algorithms on an OpenQASM circuit"; + } + + @Override + public Mono> solve(String input, SubRoutineResolver subRoutineResolver, SolvingProperties properties) { + var solution = new Solution<>(this); + solution.setSolutionData(input); + return Mono.just(solution); + } + + @Override + public ProblemType getProblemType() { + return OptimizationConfiguration.OPTIMIZATION_CONFIG; + } +} From d36e66fa09406f76ef0b39148c2a8886496f9c2d Mon Sep 17 00:00:00 2001 From: ekulos-code Date: Mon, 10 Mar 2025 12:27:27 +0100 Subject: [PATCH 36/39] Add execution and optimization solvers --- .../decompose_multi_cx_optimizer.py | 19 ++++ .../remove_redundancies_optimizer.py | 19 ++++ .../aer-noisy/aer_noisy_executor.py | 27 +++++ .../default-executor/default_executor.py | 18 +++ .../projectq-executor/projectq_executor.py | 17 +++ .../qulacs-executor/qulacs_executor.py | 18 +++ solvers/circuitprocessing/requirements.txt | 5 + .../CircuitProcessingConfiguration.java | 21 +++- .../solver/CircuitProcessingSolver.java | 7 ++ .../solver/MoveToExecutionSolver.java | 2 +- .../solver/executor/ExecutionSolver.java | 100 +++++++++++++++- .../optimization/OptimizationSolver.java | 107 +++++++++++++++++- src/main/resources/application.properties | 2 +- 13 files changed, 351 insertions(+), 11 deletions(-) create mode 100644 solvers/circuitoptimizing/decompose-multi-cx/decompose_multi_cx_optimizer.py create mode 100644 solvers/circuitoptimizing/remove-redundancies/remove_redundancies_optimizer.py create mode 100644 solvers/circuitprocessing/aer-noisy/aer_noisy_executor.py create mode 100644 solvers/circuitprocessing/default-executor/default_executor.py create mode 100644 solvers/circuitprocessing/projectq-executor/projectq_executor.py create mode 100644 solvers/circuitprocessing/qulacs-executor/qulacs_executor.py create mode 100644 solvers/circuitprocessing/requirements.txt diff --git a/solvers/circuitoptimizing/decompose-multi-cx/decompose_multi_cx_optimizer.py b/solvers/circuitoptimizing/decompose-multi-cx/decompose_multi_cx_optimizer.py new file mode 100644 index 00000000..3d62f964 --- /dev/null +++ b/solvers/circuitoptimizing/decompose-multi-cx/decompose_multi_cx_optimizer.py @@ -0,0 +1,19 @@ +import sys +from pytket.qasm import circuit_from_qasm_str, circuit_to_qasm_str +from pytket.predicates import CompilationUnit +from pytket.passes import DecomposeMultiQubitsCX + + +input_circuit = sys.argv[1] + +try: + circuit = circuit_from_qasm_str(input_circuit) +except Exception as e: + print("Was not able to convert to OpenQASM: ", e) + sys.exit(1) + +pass1 = DecomposeMultiQubitsCX() +cu = CompilationUnit(circuit) +pass1.apply(cu) + +print(circuit_to_qasm_str(cu.circuit)) \ No newline at end of file diff --git a/solvers/circuitoptimizing/remove-redundancies/remove_redundancies_optimizer.py b/solvers/circuitoptimizing/remove-redundancies/remove_redundancies_optimizer.py new file mode 100644 index 00000000..58b57e68 --- /dev/null +++ b/solvers/circuitoptimizing/remove-redundancies/remove_redundancies_optimizer.py @@ -0,0 +1,19 @@ +import sys +from pytket.qasm import circuit_from_qasm_str, circuit_to_qasm_str +from pytket.predicates import CompilationUnit +from pytket.passes import RemoveRedundancies + + +input_circuit = sys.argv[1] + +try: + circuit = circuit_from_qasm_str(input_circuit) +except Exception as e: + print("Was not able to convert to OpenQASM: ", e) + sys.exit(1) + +pass1 = RemoveRedundancies() +cu = CompilationUnit(circuit) +pass1.apply(cu) + +print(circuit_to_qasm_str(cu.circuit)) \ No newline at end of file diff --git a/solvers/circuitprocessing/aer-noisy/aer_noisy_executor.py b/solvers/circuitprocessing/aer-noisy/aer_noisy_executor.py new file mode 100644 index 00000000..9db4439b --- /dev/null +++ b/solvers/circuitprocessing/aer-noisy/aer_noisy_executor.py @@ -0,0 +1,27 @@ +import sys +from pytket.qasm import circuit_from_qasm_str +from pytket.extensions.qiskit import AerBackend + +from qiskit_aer.noise import NoiseModel +from qiskit_aer.noise.errors import depolarizing_error + +input_circuit = sys.argv[1] +shots = sys.argv[2] + +try: + circuit = circuit_from_qasm_str(input_circuit) +except Exception as e: + print("Was not able to convert to OpenQASM: ", e) + sys.exit(1) + +# https://docs.quantinuum.com/tket/user-guide/manual/manual_noise.html +noise_model = NoiseModel() +noise_model.add_readout_error([[0.9, 0.1],[0.1, 0.9]], [0]) +noise_model.add_readout_error([[0.95, 0.05],[0.05, 0.95]], [1]) +noise_model.add_quantum_error(depolarizing_error(0.1, 2), ["cx"], [0, 1]) + +backend = AerBackend(noise_model) +c = backend.get_compiled_circuit(circuit) +handle = backend.process_circuit(c, n_shots=int(shots)) +counts = backend.get_result(handle).get_counts() +print(counts) \ No newline at end of file diff --git a/solvers/circuitprocessing/default-executor/default_executor.py b/solvers/circuitprocessing/default-executor/default_executor.py new file mode 100644 index 00000000..9ce98997 --- /dev/null +++ b/solvers/circuitprocessing/default-executor/default_executor.py @@ -0,0 +1,18 @@ +import sys +from pytket.qasm import circuit_from_qasm_str +from pytket.extensions.qiskit import AerBackend + +input_circuit = sys.argv[1] +shots = int(sys.argv[2]) + +try: + circuit = circuit_from_qasm_str(input_circuit) +except Exception as e: + print("Was not able to convert to OpenQASM: ", e) + sys.exit(1) + +backend = AerBackend() +c = backend.get_compiled_circuit(circuit) +handle = backend.process_circuit(c, n_shots=shots) +counts = backend.get_result(handle).get_counts() +print(counts) \ No newline at end of file diff --git a/solvers/circuitprocessing/projectq-executor/projectq_executor.py b/solvers/circuitprocessing/projectq-executor/projectq_executor.py new file mode 100644 index 00000000..8600c2bd --- /dev/null +++ b/solvers/circuitprocessing/projectq-executor/projectq_executor.py @@ -0,0 +1,17 @@ +import sys +from pytket.qasm import circuit_from_qasm_str +from pytket.extensions.projectq import ProjectQBackend + +input_circuit = sys.argv[1] +shots = int(sys.argv[2]) + +try: + circuit = circuit_from_qasm_str(input_circuit) +except Exception as e: + print("Was not able to convert to OpenQASM: ", e) + sys.exit(1) + +backend = ProjectQBackend() +handle = backend.process_circuit(circuit, n_shots=shots) +result = backend.get_result(handle) +print(result.get_shots()) \ No newline at end of file diff --git a/solvers/circuitprocessing/qulacs-executor/qulacs_executor.py b/solvers/circuitprocessing/qulacs-executor/qulacs_executor.py new file mode 100644 index 00000000..9652f6b0 --- /dev/null +++ b/solvers/circuitprocessing/qulacs-executor/qulacs_executor.py @@ -0,0 +1,18 @@ +import sys +from pytket.qasm import circuit_from_qasm_str +from pytket.extensions.qulacs import QulacsBackend + +input_circuit = sys.argv[1] +shots = int(sys.argv[2]) + +try: + circuit = circuit_from_qasm_str(input_circuit) +except Exception as e: + print("Was not able to convert to OpenQASM: ", e) + sys.exit(1) + +backend = QulacsBackend() +c = backend.get_compiled_circuit(circuit) +handle = backend.process_circuit(c, n_shots=shots) +counts = backend.get_result(handle).get_counts() +print(counts) \ No newline at end of file diff --git a/solvers/circuitprocessing/requirements.txt b/solvers/circuitprocessing/requirements.txt new file mode 100644 index 00000000..40a709cf --- /dev/null +++ b/solvers/circuitprocessing/requirements.txt @@ -0,0 +1,5 @@ +pytket +pytket-qiskit +pytket-pyquil +pytket-projectq +pytket-qulacs \ No newline at end of file diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java index 193657ce..2a72d788 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java @@ -25,6 +25,24 @@ ProblemManager getCircuitProcessingManager( MoveToOptimizationSolver moveToOptimizationSolver, MoveToMitigationSolver moveToMitigationSolver ) { + Problem demo = new Problem<>(CIRCUIT_PROCESSING); + demo.setInput(""" + OPENQASM 2.0; + include "qelib1.inc"; + qreg q[2]; + creg c[2]; + h q[0]; + cx q[0],q[1]; + measure q[0] -> c[0]; + measure q[1] -> c[1];"""); + Problem secondDemo = new Problem<>(CIRCUIT_PROCESSING); + secondDemo.setInput(""" + OPENQASM 2.0; + include "qelib1.inc"; + qreg q[3]; + crz(0.5) q[0], q[1]; + t q[2]; + cswap q[2], q[0], q[1];"""); return new ProblemManager<>( CIRCUIT_PROCESSING, Set.of( @@ -32,8 +50,7 @@ ProblemManager getCircuitProcessingManager( moveToOptimizationSolver, moveToMitigationSolver ), - // TODO: dummy problem - Set.of(new Problem<>(CIRCUIT_PROCESSING)) + Set.of(demo, secondDemo) ); } } diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java index 7c978ad2..507ce9c6 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/CircuitProcessingSolver.java @@ -3,8 +3,15 @@ import edu.kit.provideq.toolbox.circuit.processing.CircuitProcessingConfiguration; import edu.kit.provideq.toolbox.meta.ProblemSolver; import edu.kit.provideq.toolbox.meta.ProblemType; +import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; public abstract class CircuitProcessingSolver implements ProblemSolver { + public static final SubRoutineDefinition CIRCUIT_PROCESSING_SUBROUTINE = + new SubRoutineDefinition<>( + CircuitProcessingConfiguration.CIRCUIT_PROCESSING, + "Creates a circuit processing solver" + ); + @Override public ProblemType getProblemType() { return CircuitProcessingConfiguration.CIRCUIT_PROCESSING; diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java index 19d555c8..8d919d7c 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java @@ -47,7 +47,7 @@ public Mono> solve( SolutionStatus status = executionResultSolution.getStatus(); if (status == SolutionStatus.ERROR) { solution.fail(); - solution.setDebugData("An error occurred while executing the circuit"); + solution.setDebugData(executionResultSolution.getDebugData()); return solution; } solution.complete(); diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java index 9043bdea..c96df7f1 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java @@ -5,13 +5,38 @@ import edu.kit.provideq.toolbox.meta.ProblemType; import edu.kit.provideq.toolbox.meta.SolvingProperties; import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import edu.kit.provideq.toolbox.meta.setting.SolverSetting; +import edu.kit.provideq.toolbox.meta.setting.basic.IntegerSetting; +import edu.kit.provideq.toolbox.meta.setting.basic.SelectSetting; +import edu.kit.provideq.toolbox.process.PythonProcessRunner; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; +import java.util.List; import java.util.Optional; @Component public class ExecutionSolver implements ProblemSolver { + private static final String SETTING_NUMBER_OF_SHOTS = "Number of shots"; + private static final String SETTING_SELECT_SIMULATOR = "Selected Simulator"; + private static final int DEFAULT_NUMBER_OF_SHOTS = 1024; + private static final QuantumSimulator DEFAULT_SIMULATOR = QuantumSimulator.AER; + + private final String scriptPath; + private final ApplicationContext context; + + @Autowired + public ExecutionSolver( + @Value("${circuitprocessing.base.directory}") String scriptPath, + ApplicationContext context + ) { + this.context = context; + this.scriptPath = scriptPath; + } + @Override public String getName() { return "Execute OpenQASM circuit"; @@ -22,10 +47,51 @@ public String getDescription() { return "Execute an OpenQASM circuit"; } + @Override + public List getSolverSettings() { + return List.of( + new IntegerSetting( + SETTING_NUMBER_OF_SHOTS, + "The number of shots to run", + 1, + 10000, + DEFAULT_NUMBER_OF_SHOTS), + new SelectSetting<>( + SETTING_SELECT_SIMULATOR, + "The simulator to run the code with", + List.of(QuantumSimulator.values()), + QuantumSimulator.AER, + QuantumSimulator::getValue + ) + ); + } + @Override public Mono> solve(String input, SubRoutineResolver subRoutineResolver, SolvingProperties properties) { var solution = new Solution<>(this); - solution.setSolutionData(new ExecutionResult(Optional.of(input), Optional.empty())); + + int shotNumber = properties.getSetting(SETTING_NUMBER_OF_SHOTS) + .map(IntegerSetting::getValue) + .orElse(DEFAULT_NUMBER_OF_SHOTS); + + QuantumSimulator selectedSimulator = properties + .>getSetting(SETTING_SELECT_SIMULATOR) + .map(s -> s.getSelectedOptionT(QuantumSimulator::fromValue)) + .orElse(DEFAULT_SIMULATOR); + + var processResult = context + .getBean(PythonProcessRunner.class, scriptPath + selectedSimulator.getScriptPath()) + .withArguments(input, String.valueOf(shotNumber)) + .readOutputString() + .run(getProblemType(), solution.getId()); + + if (processResult.success()) { + solution.complete(); + solution.setSolutionData(new ExecutionResult(processResult.output(), Optional.of(input))); + return Mono.just(solution); + } + solution.fail(); + processResult.errorOutput().ifPresent(solution::setDebugData); return Mono.just(solution); } @@ -33,4 +99,36 @@ public Mono> solve(String input, SubRoutineResolver su public ProblemType getProblemType() { return ExecutorConfiguration.EXECUTOR_CONFIG; } + + enum QuantumSimulator { + AER("AerBackend", "default-executor/default_executor.py"), + // PROJECTQ("ProjectQBackend", "projectq-executor/projectq_executor.py"), + QULACS("QulacsBackend", "qulacs-executor/qulacs_executor.py"), + AER_NOISY("Aer Noisy Backend (max. 2 qubits)", "aer-noisy/aer_noisy_executor.py"); + + private final String value; + private final String scriptPath; + + QuantumSimulator(String value, String scriptPath) { + this.value = value; + this.scriptPath = scriptPath; + } + + public String getValue() { + return value; + } + + public String getScriptPath() { + return scriptPath; + } + + public static QuantumSimulator fromValue(String value) { + for (QuantumSimulator simulator : values()) { + if (simulator.value.equals(value)) { + return simulator; + } + } + throw new IllegalArgumentException("Unknown value: " + value); + } + } } diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java index fcf51939..846fad84 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java @@ -1,15 +1,36 @@ package edu.kit.provideq.toolbox.circuit.processing.solver.optimization; import edu.kit.provideq.toolbox.Solution; -import edu.kit.provideq.toolbox.meta.ProblemSolver; -import edu.kit.provideq.toolbox.meta.ProblemType; -import edu.kit.provideq.toolbox.meta.SolvingProperties; -import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import edu.kit.provideq.toolbox.circuit.processing.solver.CircuitProcessingSolver; +import edu.kit.provideq.toolbox.meta.*; +import edu.kit.provideq.toolbox.meta.setting.SolverSetting; +import edu.kit.provideq.toolbox.meta.setting.basic.SelectSetting; +import edu.kit.provideq.toolbox.process.PythonProcessRunner; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; +import java.util.List; + @Component public class OptimizationSolver implements ProblemSolver { + private static final String SETTING_SELECT_OPTIMIZER = "Selected Optimization Pass"; + private static final OptimizationSolver.QuantumOptimizer DEFAULT_OPTIMIZER = + QuantumOptimizer.DECOMPOSE_MULTI_CX; + + private final String scriptPath; + private final ApplicationContext context; + + @Autowired + public OptimizationSolver( + @Value("${circuitoptimizing.base.directory}") String scriptPath, + ApplicationContext context + ) { + this.scriptPath = scriptPath; + this.context = context; + } @Override public String getName() { @@ -22,9 +43,51 @@ public String getDescription() { } @Override - public Mono> solve(String input, SubRoutineResolver subRoutineResolver, SolvingProperties properties) { + public List> getSubRoutines() { + return List.of(CircuitProcessingSolver.CIRCUIT_PROCESSING_SUBROUTINE); + } + + @Override + public List getSolverSettings() { + return List.of( + new SelectSetting<>( + SETTING_SELECT_OPTIMIZER, + "The optimization pass to refactor the code with", + List.of(OptimizationSolver.QuantumOptimizer.values()), + QuantumOptimizer.DECOMPOSE_MULTI_CX, + OptimizationSolver.QuantumOptimizer::getValue + ) + ); + } + + @Override + public Mono> solve( + String input, + SubRoutineResolver subRoutineResolver, + SolvingProperties properties + ) { var solution = new Solution<>(this); - solution.setSolutionData(input); + + OptimizationSolver.QuantumOptimizer selectedOptimizer = properties + .>getSetting(SETTING_SELECT_OPTIMIZER) + .map(s -> s.getSelectedOptionT(OptimizationSolver.QuantumOptimizer::fromValue)) + .orElse(DEFAULT_OPTIMIZER); + + var processResult = context + .getBean(PythonProcessRunner.class, scriptPath + selectedOptimizer.getScriptPath()) + .withArguments(input) + .readOutputString() + .run(getProblemType(), solution.getId()); + + if (processResult.success() && processResult.output().isPresent()) { + solution.complete(); + solution.setSolutionData(processResult.output().get()); + return subRoutineResolver + .runSubRoutine(CircuitProcessingSolver.CIRCUIT_PROCESSING_SUBROUTINE, + processResult.output().get()); + } + solution.fail(); + processResult.errorOutput().ifPresent(solution::setDebugData); return Mono.just(solution); } @@ -32,4 +95,36 @@ public Mono> solve(String input, SubRoutineResolver subRoutineR public ProblemType getProblemType() { return OptimizationConfiguration.OPTIMIZATION_CONFIG; } + + enum QuantumOptimizer { + DECOMPOSE_MULTI_CX("DecomposeMultiQubitsCX", + "decompose-multi-cx/decompose_multi_cx_optimizer.py"), + REMOVE_REDUNDANCIES("RemoveRedundancies", + "remove-redundancies/remove_redundancies_optimizer.py"); + + private final String value; + private final String scriptPath; + + QuantumOptimizer(String value, String scriptPath) { + this.value = value; + this.scriptPath = scriptPath; + } + + public String getValue() { + return value; + } + + public String getScriptPath() { + return scriptPath; + } + + public static OptimizationSolver.QuantumOptimizer fromValue(String value) { + for (OptimizationSolver.QuantumOptimizer simulator : values()) { + if (simulator.value.equals(value)) { + return simulator; + } + } + throw new IllegalArgumentException("Unknown value: " + value); + } + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 86d54fb5..0cc876d0 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1 @@ -# default spring profile, correct one will be set during runtime (see ToolboxServerApplication.java) # options: mac, windows, linux spring.profiles.active=linux springdoc.swagger-ui.operationsSorter=alpha springdoc.swagger-ui.tagsSorter=alpha working.directory=jobs examples.directory=examples springdoc.swagger-ui.path=/ # Solvers name.solvers=solvers # Non OS-specific solvers: (typically GAMS and Python) name.gams=gams path.gams=${name.solvers}/${name.gams} name.gams.max-cut=max-cut path.gams.max-cut=${path.gams}/${name.gams.max-cut}/maxcut.gms name.gams.sat=sat path.gams.sat=${path.gams}/${name.gams.sat}/sat.gms name.qiskit=qiskit path.qiskit=${name.solvers}/${name.qiskit} name.qiskit.knapsack=knapsack path.qiskit.knapsack=${path.qiskit}/${name.qiskit.knapsack}/knapsack_qiskit.py venv.qiskit.knapsack=${name.solvers}_${name.qiskit}_${name.qiskit.knapsack} name.qiskit.max-cut=max-cut path.qiskit.max-cut=${path.qiskit}/${name.qiskit.max-cut}/maxCut_qiskit.py venv.qiskit.max-cut=${name.solvers}_${name.qiskit}_${name.qiskit.max-cut} name.qiskit.qubo=qubo path.qiskit.qubo=${path.qiskit}/${name.qiskit.qubo}/qubo_qiskit.py venv.qiskit.qubo=${name.solvers}_${name.qiskit}_${name.qiskit.qubo} name.cirq=cirq path.cirq=${name.solvers}/${name.cirq} name.cirq.max-cut=max-cut path.cirq.max-cut=${path.cirq}/${name.cirq.max-cut}/max_cut_cirq.py venv.cirq.max-cut=${name.solvers}_${name.cirq}_${name.cirq.max-cut} name.qrisp=qrisp path.qrisp=${name.solvers}/${name.qrisp} name.qrisp.vrp=vrp path.qrisp.vrp=${path.qrisp}/${name.qrisp.vrp}/grover.py venv.qrisp.vrp=${name.solvers}_${name.qrisp}_${name.qrisp.vrp} name.qrisp.qubo=qubo path.qrisp.qubo=${path.qrisp}/${name.qrisp.qubo}/qaoa.py venv.qrisp.qubo=${name.solvers}_${name.qrisp}_${name.qrisp.qubo} name.qrisp.sat=sat path.qrisp.sat.grover=${path.qrisp}/${name.qrisp.sat}/grover.py path.qrisp.sat.exact=${path.qrisp}/${name.qrisp.sat}/exact_grover.py venv.qrisp.sat=${name.solvers}_${name.qrisp}_${name.qrisp.sat} name.dwave=dwave path.dwave=${name.solvers}/${name.dwave} name.dwave.qubo=qubo path.dwave.qubo=${path.dwave}/${name.dwave.qubo}/main.py venv.dwave.qubo=${name.solvers}_${name.dwave}_${name.dwave.qubo} # Non OS-specific custom solvers: (solvers that are not part of a framework) name.custom=custom path.custom=${name.solvers}/${name.custom} name.custom.hs-knapsack=hs-knapsack path.custom.hs-knapsack=${path.custom}/${name.custom.hs-knapsack}/knapsack.py venv.custom.hs-knapsack=${name.solvers}_${name.custom}_${name.custom.hs-knapsack} name.custom.lkh=lkh path.custom.lkh=${path.custom}/${name.custom.lkh}/vrp_lkh.py venv.custom.lkh=${name.solvers}_${name.custom}_${name.custom.lkh} name.custom.berger-vrp=berger-vrp name.custom.sharp-sat-bruteforce=sharp-sat-bruteforce path.custom.sharp-sat-bruteforce=${path.custom}/${name.custom.sharp-sat-bruteforce}/exact-solution-counter.py venv.custom.sharp-sat-bruteforce=${name.solvers}_${name.custom}_${name.custom.sharp-sat-bruteforce} name.custom.sharp-sat-ganak=sharp-sat-ganak venv.custom.sharp-sat-ganak=${name.solvers}_${name.custom}_${name.custom.sharp-sat-ganak} # Demonstrators name.demonstrators=demonstrators name.demonstrators.cplex=cplex path.demonstrators.cplex=${name.demonstrators}/${name.demonstrators.cplex} name.demonstrators.cplex.mip=mip-solver path.demonstrators.cplex.mip=${path.demonstrators.cplex}/${name.demonstrators.cplex.mip}/mip-solver.py venv.demonstrators.cplex.mip=${name.demonstrators}_${name.demonstrators.cplex}_${name.demonstrators.cplex.mip} \ No newline at end of file +# default spring profile, correct one will be set during runtime (see ToolboxServerApplication.java) # options: mac, windows, linux spring.profiles.active=linux springdoc.swagger-ui.operationsSorter=alpha springdoc.swagger-ui.tagsSorter=alpha working.directory=jobs examples.directory=examples springdoc.swagger-ui.path=/ # Solvers name.solvers=solvers # Non OS-specific solvers: (typically GAMS and Python) name.gams=gams path.gams=${name.solvers}/${name.gams} name.gams.max-cut=max-cut path.gams.max-cut=${path.gams}/${name.gams.max-cut}/maxcut.gms name.gams.sat=sat path.gams.sat=${path.gams}/${name.gams.sat}/sat.gms name.qiskit=qiskit path.qiskit=${name.solvers}/${name.qiskit} name.qiskit.knapsack=knapsack path.qiskit.knapsack=${path.qiskit}/${name.qiskit.knapsack}/knapsack_qiskit.py venv.qiskit.knapsack=${name.solvers}_${name.qiskit}_${name.qiskit.knapsack} name.qiskit.max-cut=max-cut path.qiskit.max-cut=${path.qiskit}/${name.qiskit.max-cut}/maxCut_qiskit.py venv.qiskit.max-cut=${name.solvers}_${name.qiskit}_${name.qiskit.max-cut} name.qiskit.qubo=qubo path.qiskit.qubo=${path.qiskit}/${name.qiskit.qubo}/qubo_qiskit.py venv.qiskit.qubo=${name.solvers}_${name.qiskit}_${name.qiskit.qubo} name.cirq=cirq path.cirq=${name.solvers}/${name.cirq} name.cirq.max-cut=max-cut path.cirq.max-cut=${path.cirq}/${name.cirq.max-cut}/max_cut_cirq.py venv.cirq.max-cut=${name.solvers}_${name.cirq}_${name.cirq.max-cut} name.qrisp=qrisp path.qrisp=${name.solvers}/${name.qrisp} name.qrisp.vrp=vrp path.qrisp.vrp=${path.qrisp}/${name.qrisp.vrp}/grover.py venv.qrisp.vrp=${name.solvers}_${name.qrisp}_${name.qrisp.vrp} name.qrisp.qubo=qubo path.qrisp.qubo=${path.qrisp}/${name.qrisp.qubo}/qaoa.py venv.qrisp.qubo=${name.solvers}_${name.qrisp}_${name.qrisp.qubo} name.qrisp.sat=sat path.qrisp.sat.grover=${path.qrisp}/${name.qrisp.sat}/grover.py path.qrisp.sat.exact=${path.qrisp}/${name.qrisp.sat}/exact_grover.py venv.qrisp.sat=${name.solvers}_${name.qrisp}_${name.qrisp.sat} name.dwave=dwave path.dwave=${name.solvers}/${name.dwave} name.dwave.qubo=qubo path.dwave.qubo=${path.dwave}/${name.dwave.qubo}/main.py venv.dwave.qubo=${name.solvers}_${name.dwave}_${name.dwave.qubo} # Non OS-specific custom solvers: (solvers that are not part of a framework) name.custom=custom path.custom=${name.solvers}/${name.custom} name.custom.hs-knapsack=hs-knapsack path.custom.hs-knapsack=${path.custom}/${name.custom.hs-knapsack}/knapsack.py venv.custom.hs-knapsack=${name.solvers}_${name.custom}_${name.custom.hs-knapsack} name.custom.lkh=lkh path.custom.lkh=${path.custom}/${name.custom.lkh}/vrp_lkh.py venv.custom.lkh=${name.solvers}_${name.custom}_${name.custom.lkh} name.custom.berger-vrp=berger-vrp name.custom.sharp-sat-bruteforce=sharp-sat-bruteforce path.custom.sharp-sat-bruteforce=${path.custom}/${name.custom.sharp-sat-bruteforce}/exact-solution-counter.py venv.custom.sharp-sat-bruteforce=${name.solvers}_${name.custom}_${name.custom.sharp-sat-bruteforce} name.custom.sharp-sat-ganak=sharp-sat-ganak venv.custom.sharp-sat-ganak=${name.solvers}_${name.custom}_${name.custom.sharp-sat-ganak} # Demonstrators name.demonstrators=demonstrators name.demonstrators.cplex=cplex path.demonstrators.cplex=${name.demonstrators}/${name.demonstrators.cplex} name.demonstrators.cplex.mip=mip-solver path.demonstrators.cplex.mip=${path.demonstrators.cplex}/${name.demonstrators.cplex.mip}/mip-solver.py venv.demonstrators.cplex.mip=${name.demonstrators}_${name.demonstrators.cplex}_${name.demonstrators.cplex.mip} circuitprocessing.base.directory=${solvers.directory}/circuitprocessing/ circuitoptimizing.base.directory=${solvers.directory}/circuitoptimizing/ \ No newline at end of file From 0cb9b380c4a35a3fbd786755c44808fcc6d8837d Mon Sep 17 00:00:00 2001 From: ekulos-code Date: Mon, 10 Mar 2025 13:28:22 +0100 Subject: [PATCH 37/39] Merge dev, account for checkstyle errors --- .../processing/CircuitProcessingConfiguration.java | 3 +-- .../processing/solver/MoveToExecutionSolver.java | 3 +-- .../processing/solver/MoveToMitigationSolver.java | 3 +-- .../processing/solver/MoveToOptimizationSolver.java | 3 +-- .../processing/solver/executor/ExecutionSolver.java | 11 +++++++---- .../solver/executor/ExecutorConfiguration.java | 6 ++---- .../mitigation/ErrorMitigationConfiguration.java | 8 ++------ .../solver/mitigation/ErrorMitigationSolver.java | 6 +++++- .../optimization/OptimizationConfiguration.java | 6 ++---- .../solver/optimization/OptimizationSolver.java | 9 ++++++--- 10 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java index 2a72d788..c0092195 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/CircuitProcessingConfiguration.java @@ -15,8 +15,7 @@ public class CircuitProcessingConfiguration { public static final ProblemType CIRCUIT_PROCESSING = new ProblemType<>( "circuit-processing", String.class, - String.class, - null + String.class ); @Bean diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java index 8d919d7c..8d1d6b60 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToExecutionSolver.java @@ -7,11 +7,10 @@ import edu.kit.provideq.toolbox.meta.SolvingProperties; import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import java.util.List; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; -import java.util.List; - @Component public class MoveToExecutionSolver extends CircuitProcessingSolver { private static final SubRoutineDefinition EXECUTOR_SUBROUTINE = diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java index 4c70a353..56e68fcd 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToMitigationSolver.java @@ -5,11 +5,10 @@ import edu.kit.provideq.toolbox.meta.SolvingProperties; import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import java.util.List; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; -import java.util.List; - @Component public class MoveToMitigationSolver extends CircuitProcessingSolver { private static final SubRoutineDefinition MITIGATOR_SUBROUTINE = diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java index a6d938f6..d213b4ec 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/MoveToOptimizationSolver.java @@ -5,11 +5,10 @@ import edu.kit.provideq.toolbox.meta.SolvingProperties; import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; import edu.kit.provideq.toolbox.meta.SubRoutineResolver; +import java.util.List; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; -import java.util.List; - @Component public class MoveToOptimizationSolver extends CircuitProcessingSolver { private static final SubRoutineDefinition OPTIMIZER_SUBROUTINE = diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java index c96df7f1..58ed0aeb 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java @@ -9,15 +9,14 @@ import edu.kit.provideq.toolbox.meta.setting.basic.IntegerSetting; import edu.kit.provideq.toolbox.meta.setting.basic.SelectSetting; import edu.kit.provideq.toolbox.process.PythonProcessRunner; +import java.util.List; +import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; -import java.util.List; -import java.util.Optional; - @Component public class ExecutionSolver implements ProblemSolver { private static final String SETTING_NUMBER_OF_SHOTS = "Number of shots"; @@ -67,7 +66,11 @@ public List getSolverSettings() { } @Override - public Mono> solve(String input, SubRoutineResolver subRoutineResolver, SolvingProperties properties) { + public Mono> solve( + String input, + SubRoutineResolver subRoutineResolver, + SolvingProperties properties + ) { var solution = new Solution<>(this); int shotNumber = properties.getSetting(SETTING_NUMBER_OF_SHOTS) diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java index d93390f2..7701bc1a 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutorConfiguration.java @@ -3,18 +3,16 @@ import edu.kit.provideq.toolbox.meta.Problem; import edu.kit.provideq.toolbox.meta.ProblemManager; import edu.kit.provideq.toolbox.meta.ProblemType; +import java.util.Set; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.util.Set; - @Configuration public class ExecutorConfiguration { public static final ProblemType EXECUTOR_CONFIG = new ProblemType<>( "circuit-processing-executor", String.class, - ExecutionResult.class, - null + ExecutionResult.class ); @Bean diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java index 953efc12..26afe47f 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationConfiguration.java @@ -1,22 +1,18 @@ package edu.kit.provideq.toolbox.circuit.processing.solver.mitigation; -import edu.kit.provideq.toolbox.circuit.processing.solver.executor.ExecutionResult; -import edu.kit.provideq.toolbox.circuit.processing.solver.executor.ExecutionSolver; import edu.kit.provideq.toolbox.meta.Problem; import edu.kit.provideq.toolbox.meta.ProblemManager; import edu.kit.provideq.toolbox.meta.ProblemType; +import java.util.Set; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.util.Set; - @Configuration public class ErrorMitigationConfiguration { public static final ProblemType MITIGATION_CONFIG = new ProblemType<>( "circuit-processing-mitigation", String.class, - String.class, - null + String.class ); @Bean diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java index 5c70686a..5f6c3f87 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/mitigation/ErrorMitigationSolver.java @@ -22,7 +22,11 @@ public String getDescription() { } @Override - public Mono> solve(String input, SubRoutineResolver subRoutineResolver, SolvingProperties properties) { + public Mono> solve( + String input, + SubRoutineResolver subRoutineResolver, + SolvingProperties properties + ) { var solution = new Solution<>(this); solution.setSolutionData(input); return Mono.just(solution); diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java index 78dfbbfd..bfbe3f17 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationConfiguration.java @@ -3,18 +3,16 @@ import edu.kit.provideq.toolbox.meta.Problem; import edu.kit.provideq.toolbox.meta.ProblemManager; import edu.kit.provideq.toolbox.meta.ProblemType; +import java.util.Set; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.util.Set; - @Configuration public class OptimizationConfiguration { public static final ProblemType OPTIMIZATION_CONFIG = new ProblemType<>( "circuit-processing-optimization", String.class, - String.class, - null + String.class ); @Bean diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java index 846fad84..8c883e00 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java @@ -2,18 +2,21 @@ import edu.kit.provideq.toolbox.Solution; import edu.kit.provideq.toolbox.circuit.processing.solver.CircuitProcessingSolver; -import edu.kit.provideq.toolbox.meta.*; +import edu.kit.provideq.toolbox.meta.ProblemSolver; +import edu.kit.provideq.toolbox.meta.ProblemType; +import edu.kit.provideq.toolbox.meta.SolvingProperties; +import edu.kit.provideq.toolbox.meta.SubRoutineDefinition; +import edu.kit.provideq.toolbox.meta.SubRoutineResolver; import edu.kit.provideq.toolbox.meta.setting.SolverSetting; import edu.kit.provideq.toolbox.meta.setting.basic.SelectSetting; import edu.kit.provideq.toolbox.process.PythonProcessRunner; +import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; -import java.util.List; - @Component public class OptimizationSolver implements ProblemSolver { private static final String SETTING_SELECT_OPTIMIZER = "Selected Optimization Pass"; From 347d7be3c02a4026cf350d6803f885e18f5031ea Mon Sep 17 00:00:00 2001 From: ekulos-code Date: Wed, 19 Mar 2025 17:29:27 +0100 Subject: [PATCH 38/39] Implement suggestions --- .../projectq-executor/projectq_executor.py | 17 ----------------- solvers/circuitprocessing/requirements.txt | 2 -- .../solver/executor/ExecutionSolver.java | 2 +- .../solver/optimization/OptimizationSolver.java | 5 +++-- 4 files changed, 4 insertions(+), 22 deletions(-) delete mode 100644 solvers/circuitprocessing/projectq-executor/projectq_executor.py diff --git a/solvers/circuitprocessing/projectq-executor/projectq_executor.py b/solvers/circuitprocessing/projectq-executor/projectq_executor.py deleted file mode 100644 index 8600c2bd..00000000 --- a/solvers/circuitprocessing/projectq-executor/projectq_executor.py +++ /dev/null @@ -1,17 +0,0 @@ -import sys -from pytket.qasm import circuit_from_qasm_str -from pytket.extensions.projectq import ProjectQBackend - -input_circuit = sys.argv[1] -shots = int(sys.argv[2]) - -try: - circuit = circuit_from_qasm_str(input_circuit) -except Exception as e: - print("Was not able to convert to OpenQASM: ", e) - sys.exit(1) - -backend = ProjectQBackend() -handle = backend.process_circuit(circuit, n_shots=shots) -result = backend.get_result(handle) -print(result.get_shots()) \ No newline at end of file diff --git a/solvers/circuitprocessing/requirements.txt b/solvers/circuitprocessing/requirements.txt index 40a709cf..4fde5da3 100644 --- a/solvers/circuitprocessing/requirements.txt +++ b/solvers/circuitprocessing/requirements.txt @@ -1,5 +1,3 @@ pytket pytket-qiskit -pytket-pyquil -pytket-projectq pytket-qulacs \ No newline at end of file diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java index 58ed0aeb..754967fe 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java @@ -53,7 +53,7 @@ public List getSolverSettings() { SETTING_NUMBER_OF_SHOTS, "The number of shots to run", 1, - 10000, + 1000000, DEFAULT_NUMBER_OF_SHOTS), new SelectSetting<>( SETTING_SELECT_SIMULATOR, diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java index 8c883e00..ebd8dced 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java @@ -37,12 +37,13 @@ public OptimizationSolver( @Override public String getName() { - return "Optimize OpenQASM circuit"; + return "Apply Tket Optimization Pass"; } @Override public String getDescription() { - return "Run optimization algorithms on an OpenQASM circuit"; + return "Transform the given circuit into an optimized but equivalent circuit using" + + "Tket compilation passes (e.g. removing redundancies)."; } @Override From 0ca1d22f8376c75af20b9b1f1c40863c143171f6 Mon Sep 17 00:00:00 2001 From: ekulos-code Date: Mon, 26 May 2025 13:52:30 +0200 Subject: [PATCH 39/39] Preliminary migration for circuit processing to venvs --- .../aer-noisy/aer_noisy_executor.py | 11 +++++++++-- .../default-executor/default_executor.py | 11 +++++++++-- .../qulacs-executor/qulacs_executor.py | 11 +++++++++-- .../{ => circuitexecution}/requirements.txt | 0 .../decompose_multi_cx_optimizer.py | 10 ++++++++-- .../remove_redundancies_optimizer.py | 7 ++++++- .../circuitoptimizing/requirements.txt | 1 + .../solver/executor/ExecutionSolver.java | 14 +++++++++++--- .../solver/optimization/OptimizationSolver.java | 14 +++++++++++--- src/main/resources/application.properties | 2 +- 10 files changed, 65 insertions(+), 16 deletions(-) rename solvers/circuitprocessing/{ => circuitexecution}/aer-noisy/aer_noisy_executor.py (82%) rename solvers/circuitprocessing/{ => circuitexecution}/default-executor/default_executor.py (70%) rename solvers/circuitprocessing/{ => circuitexecution}/qulacs-executor/qulacs_executor.py (70%) rename solvers/circuitprocessing/{ => circuitexecution}/requirements.txt (100%) rename solvers/{ => circuitprocessing}/circuitoptimizing/decompose-multi-cx/decompose_multi_cx_optimizer.py (69%) rename solvers/{ => circuitprocessing}/circuitoptimizing/remove-redundancies/remove_redundancies_optimizer.py (75%) create mode 100644 solvers/circuitprocessing/circuitoptimizing/requirements.txt diff --git a/solvers/circuitprocessing/aer-noisy/aer_noisy_executor.py b/solvers/circuitprocessing/circuitexecution/aer-noisy/aer_noisy_executor.py similarity index 82% rename from solvers/circuitprocessing/aer-noisy/aer_noisy_executor.py rename to solvers/circuitprocessing/circuitexecution/aer-noisy/aer_noisy_executor.py index 9db4439b..c63a4388 100644 --- a/solvers/circuitprocessing/aer-noisy/aer_noisy_executor.py +++ b/solvers/circuitprocessing/circuitexecution/aer-noisy/aer_noisy_executor.py @@ -5,8 +5,15 @@ from qiskit_aer.noise import NoiseModel from qiskit_aer.noise.errors import depolarizing_error -input_circuit = sys.argv[1] -shots = sys.argv[2] +input_path = sys.argv[1] +num_runs = sys.argv[2] + +# read input from file +with open(input_path, 'r') as input_file: + text = input_file.read() + +input_circuit = text +shots = num_runs try: circuit = circuit_from_qasm_str(input_circuit) diff --git a/solvers/circuitprocessing/default-executor/default_executor.py b/solvers/circuitprocessing/circuitexecution/default-executor/default_executor.py similarity index 70% rename from solvers/circuitprocessing/default-executor/default_executor.py rename to solvers/circuitprocessing/circuitexecution/default-executor/default_executor.py index 9ce98997..c5a43bde 100644 --- a/solvers/circuitprocessing/default-executor/default_executor.py +++ b/solvers/circuitprocessing/circuitexecution/default-executor/default_executor.py @@ -2,8 +2,15 @@ from pytket.qasm import circuit_from_qasm_str from pytket.extensions.qiskit import AerBackend -input_circuit = sys.argv[1] -shots = int(sys.argv[2]) +input_path = sys.argv[1] +num_runs = sys.argv[2] + +# read input from file +with open(input_path, 'r') as input_file: + text = input_file.read() + +input_circuit = text +shots = num_runs try: circuit = circuit_from_qasm_str(input_circuit) diff --git a/solvers/circuitprocessing/qulacs-executor/qulacs_executor.py b/solvers/circuitprocessing/circuitexecution/qulacs-executor/qulacs_executor.py similarity index 70% rename from solvers/circuitprocessing/qulacs-executor/qulacs_executor.py rename to solvers/circuitprocessing/circuitexecution/qulacs-executor/qulacs_executor.py index 9652f6b0..71963c62 100644 --- a/solvers/circuitprocessing/qulacs-executor/qulacs_executor.py +++ b/solvers/circuitprocessing/circuitexecution/qulacs-executor/qulacs_executor.py @@ -2,8 +2,15 @@ from pytket.qasm import circuit_from_qasm_str from pytket.extensions.qulacs import QulacsBackend -input_circuit = sys.argv[1] -shots = int(sys.argv[2]) +input_path = sys.argv[1] +num_runs = sys.argv[2] + +# read input from file +with open(input_path, 'r') as input_file: + text = input_file.read() + +input_circuit = text +shots = num_runs try: circuit = circuit_from_qasm_str(input_circuit) diff --git a/solvers/circuitprocessing/requirements.txt b/solvers/circuitprocessing/circuitexecution/requirements.txt similarity index 100% rename from solvers/circuitprocessing/requirements.txt rename to solvers/circuitprocessing/circuitexecution/requirements.txt diff --git a/solvers/circuitoptimizing/decompose-multi-cx/decompose_multi_cx_optimizer.py b/solvers/circuitprocessing/circuitoptimizing/decompose-multi-cx/decompose_multi_cx_optimizer.py similarity index 69% rename from solvers/circuitoptimizing/decompose-multi-cx/decompose_multi_cx_optimizer.py rename to solvers/circuitprocessing/circuitoptimizing/decompose-multi-cx/decompose_multi_cx_optimizer.py index 3d62f964..3378a019 100644 --- a/solvers/circuitoptimizing/decompose-multi-cx/decompose_multi_cx_optimizer.py +++ b/solvers/circuitprocessing/circuitoptimizing/decompose-multi-cx/decompose_multi_cx_optimizer.py @@ -3,8 +3,13 @@ from pytket.predicates import CompilationUnit from pytket.passes import DecomposeMultiQubitsCX +input_path = sys.argv[1] -input_circuit = sys.argv[1] +# read input from file +with open(input_path, 'r') as input_file: + text = input_file.read() + +input_circuit = text try: circuit = circuit_from_qasm_str(input_circuit) @@ -16,4 +21,5 @@ cu = CompilationUnit(circuit) pass1.apply(cu) -print(circuit_to_qasm_str(cu.circuit)) \ No newline at end of file +print(circuit_to_qasm_str(cu.circuit)) + diff --git a/solvers/circuitoptimizing/remove-redundancies/remove_redundancies_optimizer.py b/solvers/circuitprocessing/circuitoptimizing/remove-redundancies/remove_redundancies_optimizer.py similarity index 75% rename from solvers/circuitoptimizing/remove-redundancies/remove_redundancies_optimizer.py rename to solvers/circuitprocessing/circuitoptimizing/remove-redundancies/remove_redundancies_optimizer.py index 58b57e68..a238a84a 100644 --- a/solvers/circuitoptimizing/remove-redundancies/remove_redundancies_optimizer.py +++ b/solvers/circuitprocessing/circuitoptimizing/remove-redundancies/remove_redundancies_optimizer.py @@ -3,8 +3,13 @@ from pytket.predicates import CompilationUnit from pytket.passes import RemoveRedundancies +input_path = sys.argv[1] -input_circuit = sys.argv[1] +# read input from file +with open(input_path, 'r') as input_file: + text = input_file.read() + +input_circuit = text try: circuit = circuit_from_qasm_str(input_circuit) diff --git a/solvers/circuitprocessing/circuitoptimizing/requirements.txt b/solvers/circuitprocessing/circuitoptimizing/requirements.txt new file mode 100644 index 00000000..f32bd3e4 --- /dev/null +++ b/solvers/circuitprocessing/circuitoptimizing/requirements.txt @@ -0,0 +1 @@ +pytket \ No newline at end of file diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java index 754967fe..9cca644d 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/executor/ExecutionSolver.java @@ -8,6 +8,7 @@ import edu.kit.provideq.toolbox.meta.setting.SolverSetting; import edu.kit.provideq.toolbox.meta.setting.basic.IntegerSetting; import edu.kit.provideq.toolbox.meta.setting.basic.SelectSetting; +import edu.kit.provideq.toolbox.process.ProcessRunner; import edu.kit.provideq.toolbox.process.PythonProcessRunner; import java.util.List; import java.util.Optional; @@ -25,14 +26,17 @@ public class ExecutionSolver implements ProblemSolver { private static final QuantumSimulator DEFAULT_SIMULATOR = QuantumSimulator.AER; private final String scriptPath; + private final String venv; private final ApplicationContext context; @Autowired public ExecutionSolver( - @Value("${circuitprocessing.base.directory}") String scriptPath, + @Value("${path.circuitprocessing.circuitexecution}") String scriptPath, + @Value("${venv.circuitprocessing.circuitexecution}") String venv, ApplicationContext context ) { this.context = context; + this.venv = venv; this.scriptPath = scriptPath; } @@ -83,8 +87,12 @@ public Mono> solve( .orElse(DEFAULT_SIMULATOR); var processResult = context - .getBean(PythonProcessRunner.class, scriptPath + selectedSimulator.getScriptPath()) - .withArguments(input, String.valueOf(shotNumber)) + .getBean(PythonProcessRunner.class, scriptPath + selectedSimulator.getScriptPath(), venv) + .withArguments( + ProcessRunner.INPUT_FILE_PATH, + String.valueOf(shotNumber) + ) + .writeInputFile(input) .readOutputString() .run(getProblemType(), solution.getId()); diff --git a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java index ebd8dced..be8d1b4d 100644 --- a/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java +++ b/src/main/java/edu/kit/provideq/toolbox/circuit/processing/solver/optimization/OptimizationSolver.java @@ -9,6 +9,7 @@ import edu.kit.provideq.toolbox.meta.SubRoutineResolver; import edu.kit.provideq.toolbox.meta.setting.SolverSetting; import edu.kit.provideq.toolbox.meta.setting.basic.SelectSetting; +import edu.kit.provideq.toolbox.process.ProcessRunner; import edu.kit.provideq.toolbox.process.PythonProcessRunner; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; @@ -24,14 +25,17 @@ public class OptimizationSolver implements ProblemSolver { QuantumOptimizer.DECOMPOSE_MULTI_CX; private final String scriptPath; + private final String venv; private final ApplicationContext context; @Autowired public OptimizationSolver( - @Value("${circuitoptimizing.base.directory}") String scriptPath, + @Value("${path.circuitprocessing.circuitoptimization}") String scriptPath, + @Value("${venv.circuitprocessing.circuitoptimization}") String venv, ApplicationContext context ) { this.scriptPath = scriptPath; + this.venv = venv; this.context = context; } @@ -77,9 +81,13 @@ public Mono> solve( .map(s -> s.getSelectedOptionT(OptimizationSolver.QuantumOptimizer::fromValue)) .orElse(DEFAULT_OPTIMIZER); + //String[] inputArray = new String[]{input}; var processResult = context - .getBean(PythonProcessRunner.class, scriptPath + selectedOptimizer.getScriptPath()) - .withArguments(input) + .getBean(PythonProcessRunner.class, scriptPath + selectedOptimizer.getScriptPath(), venv) + .withArguments( + ProcessRunner.INPUT_FILE_PATH + ) + .writeInputFile(input) .readOutputString() .run(getProblemType(), solution.getId()); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 0cc876d0..d749ff2d 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1 @@ -# default spring profile, correct one will be set during runtime (see ToolboxServerApplication.java) # options: mac, windows, linux spring.profiles.active=linux springdoc.swagger-ui.operationsSorter=alpha springdoc.swagger-ui.tagsSorter=alpha working.directory=jobs examples.directory=examples springdoc.swagger-ui.path=/ # Solvers name.solvers=solvers # Non OS-specific solvers: (typically GAMS and Python) name.gams=gams path.gams=${name.solvers}/${name.gams} name.gams.max-cut=max-cut path.gams.max-cut=${path.gams}/${name.gams.max-cut}/maxcut.gms name.gams.sat=sat path.gams.sat=${path.gams}/${name.gams.sat}/sat.gms name.qiskit=qiskit path.qiskit=${name.solvers}/${name.qiskit} name.qiskit.knapsack=knapsack path.qiskit.knapsack=${path.qiskit}/${name.qiskit.knapsack}/knapsack_qiskit.py venv.qiskit.knapsack=${name.solvers}_${name.qiskit}_${name.qiskit.knapsack} name.qiskit.max-cut=max-cut path.qiskit.max-cut=${path.qiskit}/${name.qiskit.max-cut}/maxCut_qiskit.py venv.qiskit.max-cut=${name.solvers}_${name.qiskit}_${name.qiskit.max-cut} name.qiskit.qubo=qubo path.qiskit.qubo=${path.qiskit}/${name.qiskit.qubo}/qubo_qiskit.py venv.qiskit.qubo=${name.solvers}_${name.qiskit}_${name.qiskit.qubo} name.cirq=cirq path.cirq=${name.solvers}/${name.cirq} name.cirq.max-cut=max-cut path.cirq.max-cut=${path.cirq}/${name.cirq.max-cut}/max_cut_cirq.py venv.cirq.max-cut=${name.solvers}_${name.cirq}_${name.cirq.max-cut} name.qrisp=qrisp path.qrisp=${name.solvers}/${name.qrisp} name.qrisp.vrp=vrp path.qrisp.vrp=${path.qrisp}/${name.qrisp.vrp}/grover.py venv.qrisp.vrp=${name.solvers}_${name.qrisp}_${name.qrisp.vrp} name.qrisp.qubo=qubo path.qrisp.qubo=${path.qrisp}/${name.qrisp.qubo}/qaoa.py venv.qrisp.qubo=${name.solvers}_${name.qrisp}_${name.qrisp.qubo} name.qrisp.sat=sat path.qrisp.sat.grover=${path.qrisp}/${name.qrisp.sat}/grover.py path.qrisp.sat.exact=${path.qrisp}/${name.qrisp.sat}/exact_grover.py venv.qrisp.sat=${name.solvers}_${name.qrisp}_${name.qrisp.sat} name.dwave=dwave path.dwave=${name.solvers}/${name.dwave} name.dwave.qubo=qubo path.dwave.qubo=${path.dwave}/${name.dwave.qubo}/main.py venv.dwave.qubo=${name.solvers}_${name.dwave}_${name.dwave.qubo} # Non OS-specific custom solvers: (solvers that are not part of a framework) name.custom=custom path.custom=${name.solvers}/${name.custom} name.custom.hs-knapsack=hs-knapsack path.custom.hs-knapsack=${path.custom}/${name.custom.hs-knapsack}/knapsack.py venv.custom.hs-knapsack=${name.solvers}_${name.custom}_${name.custom.hs-knapsack} name.custom.lkh=lkh path.custom.lkh=${path.custom}/${name.custom.lkh}/vrp_lkh.py venv.custom.lkh=${name.solvers}_${name.custom}_${name.custom.lkh} name.custom.berger-vrp=berger-vrp name.custom.sharp-sat-bruteforce=sharp-sat-bruteforce path.custom.sharp-sat-bruteforce=${path.custom}/${name.custom.sharp-sat-bruteforce}/exact-solution-counter.py venv.custom.sharp-sat-bruteforce=${name.solvers}_${name.custom}_${name.custom.sharp-sat-bruteforce} name.custom.sharp-sat-ganak=sharp-sat-ganak venv.custom.sharp-sat-ganak=${name.solvers}_${name.custom}_${name.custom.sharp-sat-ganak} # Demonstrators name.demonstrators=demonstrators name.demonstrators.cplex=cplex path.demonstrators.cplex=${name.demonstrators}/${name.demonstrators.cplex} name.demonstrators.cplex.mip=mip-solver path.demonstrators.cplex.mip=${path.demonstrators.cplex}/${name.demonstrators.cplex.mip}/mip-solver.py venv.demonstrators.cplex.mip=${name.demonstrators}_${name.demonstrators.cplex}_${name.demonstrators.cplex.mip} circuitprocessing.base.directory=${solvers.directory}/circuitprocessing/ circuitoptimizing.base.directory=${solvers.directory}/circuitoptimizing/ \ No newline at end of file +# default spring profile, correct one will be set during runtime (see ToolboxServerApplication.java) # options: mac, windows, linux spring.profiles.active=linux springdoc.swagger-ui.operationsSorter=alpha springdoc.swagger-ui.tagsSorter=alpha working.directory=jobs examples.directory=examples springdoc.swagger-ui.path=/ # Solvers name.solvers=solvers # Non OS-specific solvers: (typically GAMS and Python) name.gams=gams path.gams=${name.solvers}/${name.gams} name.gams.max-cut=max-cut path.gams.max-cut=${path.gams}/${name.gams.max-cut}/maxcut.gms name.gams.sat=sat path.gams.sat=${path.gams}/${name.gams.sat}/sat.gms name.qiskit=qiskit path.qiskit=${name.solvers}/${name.qiskit} name.qiskit.knapsack=knapsack path.qiskit.knapsack=${path.qiskit}/${name.qiskit.knapsack}/knapsack_qiskit.py venv.qiskit.knapsack=${name.solvers}_${name.qiskit}_${name.qiskit.knapsack} name.qiskit.max-cut=max-cut path.qiskit.max-cut=${path.qiskit}/${name.qiskit.max-cut}/maxCut_qiskit.py venv.qiskit.max-cut=${name.solvers}_${name.qiskit}_${name.qiskit.max-cut} name.qiskit.qubo=qubo path.qiskit.qubo=${path.qiskit}/${name.qiskit.qubo}/qubo_qiskit.py venv.qiskit.qubo=${name.solvers}_${name.qiskit}_${name.qiskit.qubo} name.cirq=cirq path.cirq=${name.solvers}/${name.cirq} name.cirq.max-cut=max-cut path.cirq.max-cut=${path.cirq}/${name.cirq.max-cut}/max_cut_cirq.py venv.cirq.max-cut=${name.solvers}_${name.cirq}_${name.cirq.max-cut} name.qrisp=qrisp path.qrisp=${name.solvers}/${name.qrisp} name.qrisp.vrp=vrp path.qrisp.vrp=${path.qrisp}/${name.qrisp.vrp}/grover.py venv.qrisp.vrp=${name.solvers}_${name.qrisp}_${name.qrisp.vrp} name.qrisp.qubo=qubo path.qrisp.qubo=${path.qrisp}/${name.qrisp.qubo}/qaoa.py venv.qrisp.qubo=${name.solvers}_${name.qrisp}_${name.qrisp.qubo} name.qrisp.sat=sat path.qrisp.sat.grover=${path.qrisp}/${name.qrisp.sat}/grover.py path.qrisp.sat.exact=${path.qrisp}/${name.qrisp.sat}/exact_grover.py venv.qrisp.sat=${name.solvers}_${name.qrisp}_${name.qrisp.sat} name.dwave=dwave path.dwave=${name.solvers}/${name.dwave} name.dwave.qubo=qubo path.dwave.qubo=${path.dwave}/${name.dwave.qubo}/main.py venv.dwave.qubo=${name.solvers}_${name.dwave}_${name.dwave.qubo} # Non OS-specific custom solvers: (solvers that are not part of a framework) name.custom=custom path.custom=${name.solvers}/${name.custom} name.custom.hs-knapsack=hs-knapsack path.custom.hs-knapsack=${path.custom}/${name.custom.hs-knapsack}/knapsack.py venv.custom.hs-knapsack=${name.solvers}_${name.custom}_${name.custom.hs-knapsack} name.custom.lkh=lkh path.custom.lkh=${path.custom}/${name.custom.lkh}/vrp_lkh.py venv.custom.lkh=${name.solvers}_${name.custom}_${name.custom.lkh} name.custom.berger-vrp=berger-vrp name.custom.sharp-sat-bruteforce=sharp-sat-bruteforce path.custom.sharp-sat-bruteforce=${path.custom}/${name.custom.sharp-sat-bruteforce}/exact-solution-counter.py venv.custom.sharp-sat-bruteforce=${name.solvers}_${name.custom}_${name.custom.sharp-sat-bruteforce} name.custom.sharp-sat-ganak=sharp-sat-ganak venv.custom.sharp-sat-ganak=${name.solvers}_${name.custom}_${name.custom.sharp-sat-ganak} # Demonstrators name.demonstrators=demonstrators name.demonstrators.cplex=cplex path.demonstrators.cplex=${name.demonstrators}/${name.demonstrators.cplex} name.demonstrators.cplex.mip=mip-solver path.demonstrators.cplex.mip=${path.demonstrators.cplex}/${name.demonstrators.cplex.mip}/mip-solver.py venv.demonstrators.cplex.mip=${name.demonstrators}_${name.demonstrators.cplex}_${name.demonstrators.cplex.mip} # Circuit Processing name.circuitprocessing=circuitprocessing path.circuitprocessing=${name.solvers}/${name.circuitprocessing} name.circuitprocessing.circuitexecution=circuitexecution path.circuitprocessing.circuitexecution=${path.circuitprocessing}/${name.circuitprocessing.circuitexecution}/ venv.circuitprocessing.circuitexecution=${name.solvers}_${name.circuitprocessing}_${name.circuitprocessing.circuitexecution}/ name.circuitprocessing.circuitoptimization=circuitoptimizing path.circuitprocessing.circuitoptimization=${path.circuitprocessing}/${name.circuitprocessing.circuitoptimization}/ venv.circuitprocessing.circuitoptimization=${name.solvers}_${name.circuitprocessing}_${name.circuitprocessing.circuitoptimization} circuitprocessing.optimize.decompmultipath = decompose-multi-cx/decompose_multi_cx_optimizer.py \ No newline at end of file