From 23dd65e12152fa278370bfb4fce5ce799dacd196 Mon Sep 17 00:00:00 2001 From: zaibod Date: Mon, 17 Feb 2025 09:30:16 +0100 Subject: [PATCH 1/3] refactor: problem bound structure --- .../provideq/toolbox/api/ComparisonDto.java | 41 +++++++++++++++++-- .../toolbox/api/EstimationRouter.java | 22 ++++------ .../kit/provideq/toolbox/api/ProblemDto.java | 10 ++--- .../kit/provideq/toolbox/meta/Problem.java | 40 ++++++++++++++++-- 4 files changed, 86 insertions(+), 27 deletions(-) diff --git a/src/main/java/edu/kit/provideq/toolbox/api/ComparisonDto.java b/src/main/java/edu/kit/provideq/toolbox/api/ComparisonDto.java index ad2d4ed2..4488a45a 100644 --- a/src/main/java/edu/kit/provideq/toolbox/api/ComparisonDto.java +++ b/src/main/java/edu/kit/provideq/toolbox/api/ComparisonDto.java @@ -3,9 +3,44 @@ import edu.kit.provideq.toolbox.BoundWithInfo; import edu.kit.provideq.toolbox.Solution; -public record ComparisonDto(float comparison, BoundWithInfo bound, Solution solution) { +public class ComparisonDto { + private BoundDto bound; + private float comparison; + + public ComparisonDto(float comparison, BoundWithInfo bound) { + this.comparison = comparison; + this.bound = new BoundDto(bound); + } + + public ComparisonDto() { + this.comparison = -1; + this.bound = null; + } + + @Override public String toString() { - return "Comparison{comparison=%f, bound=%s, solution=%s}" - .formatted(comparison, bound, solution); + return "Comparison{bound=%s, comparison=%f}" + .formatted(bound, comparison); + } + + public BoundDto getBound() { + return bound; } + + public void setBound(BoundDto bound) { + this.bound = bound; + } + + public void setBound(BoundWithInfo bound) { + this.bound = new BoundDto(bound); + } + + public void setComparison(float comparison) { + this.comparison = comparison; + } + + public float getComparison() { + return comparison; + } + } diff --git a/src/main/java/edu/kit/provideq/toolbox/api/EstimationRouter.java b/src/main/java/edu/kit/provideq/toolbox/api/EstimationRouter.java index 71fd772f..fdf6bc09 100644 --- a/src/main/java/edu/kit/provideq/toolbox/api/EstimationRouter.java +++ b/src/main/java/edu/kit/provideq/toolbox/api/EstimationRouter.java @@ -90,7 +90,7 @@ private Mono handleGet( Mono bound; try { problem.estimateBound(); - bound = Mono.just(new BoundDto(problem.getBound().orElseThrow())); + bound = Mono.just(problem.getBound().orElseThrow()); } catch (IllegalStateException | NoSuchElementException e) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage()); } @@ -114,22 +114,14 @@ private Mono handleCompare( throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Bound not estimated yet!"); } - float bound = problem.getBound().get().bound().value(); - var pattern = Pattern.compile(manager.getType().getSolutionPattern()); - var solutionMatcher = pattern.matcher(problem.getSolution().get().getSolutionData().toString()); - float solutionValue; - if (solutionMatcher.find()) { - solutionValue = Float.parseFloat(solutionMatcher.group(1)); - } else { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Could not parse solution value!"); + try { + problem.compareBound(); + } catch (IllegalStateException | NoSuchElementException e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage()); } - float comparison = problem.getBound().get().bound().boundType().compare(bound, solutionValue); - ComparisonDto comparisonDto = new ComparisonDto( - comparison, - problem.getBound().get(), - problem.getSolution().get() - ); + var comparisonDto = problem.getBoundWithComparison(); + return ok().body(Mono.just(comparisonDto), new ParameterizedTypeReference<>() { }); } diff --git a/src/main/java/edu/kit/provideq/toolbox/api/ProblemDto.java b/src/main/java/edu/kit/provideq/toolbox/api/ProblemDto.java index 954e2f0c..23de41e3 100644 --- a/src/main/java/edu/kit/provideq/toolbox/api/ProblemDto.java +++ b/src/main/java/edu/kit/provideq/toolbox/api/ProblemDto.java @@ -17,8 +17,8 @@ public class ProblemDto { private String typeId; private InputT input; private Solution solution; - private BoundWithInfo bound; private ProblemState state; + private ComparisonDto boundWithComparison; private String solverId; private List solverSettings; private List subProblems; @@ -40,7 +40,7 @@ public static ProblemDto fromProblem( dto.typeId = problem.getType().getId(); dto.input = problem.getInput().orElse(null); dto.solution = problem.getSolution().orElse(null); - dto.bound = problem.getBound().orElse(null); + dto.boundWithComparison = problem.getBoundWithComparison().orElse(null); dto.state = problem.getState(); dto.solverId = problem.getSolver() .map(ProblemSolver::getId) @@ -70,8 +70,8 @@ public Solution getSolution() { return solution; } - public BoundWithInfo getBound() { - return bound; + public ComparisonDto getBoundWithComparison() { + return boundWithComparison; } public ProblemState getState() { @@ -107,7 +107,7 @@ public String toString() { + ", solverId=" + solverId + ", input=" + input + ", solution=" + solution - + ", value=" + bound + + ", boundWithComparison=" + boundWithComparison + ", solverSettings=" + solverSettings + ", subProblems=" + subProblems + '}'; diff --git a/src/main/java/edu/kit/provideq/toolbox/meta/Problem.java b/src/main/java/edu/kit/provideq/toolbox/meta/Problem.java index 2b8791ae..1ea2171d 100644 --- a/src/main/java/edu/kit/provideq/toolbox/meta/Problem.java +++ b/src/main/java/edu/kit/provideq/toolbox/meta/Problem.java @@ -2,6 +2,8 @@ import edu.kit.provideq.toolbox.BoundWithInfo; import edu.kit.provideq.toolbox.Solution; +import edu.kit.provideq.toolbox.api.BoundDto; +import edu.kit.provideq.toolbox.api.ComparisonDto; import edu.kit.provideq.toolbox.meta.setting.SolverSetting; import java.util.Collections; import java.util.HashSet; @@ -10,6 +12,7 @@ import java.util.Set; import java.util.UUID; import java.util.function.Consumer; +import java.util.regex.Pattern; import java.util.stream.Collectors; import reactor.core.publisher.Mono; @@ -30,7 +33,7 @@ public class Problem { private InputT input; private Solution solution; - private BoundWithInfo bound; + private final ComparisonDto boundWithComparison = new ComparisonDto(); private ProblemState state; private ProblemSolver solver; private List solverSettings; @@ -101,7 +104,32 @@ public void estimateBound() { long finish = System.currentTimeMillis(); var executionTime = finish - start; - this.bound = new BoundWithInfo(estimatedBound, executionTime); + this.boundWithComparison.setBound(new BoundWithInfo(estimatedBound, executionTime)); + } + + public void compareBound() { + if (this.solution == null) { + throw new IllegalStateException("Cannot compare bound without solution!"); + } + if (this.boundWithComparison.getBound() == null) { + throw new IllegalStateException("Cannot compare bound without bound!"); + } + + var bound = this.boundWithComparison.getBound(); + var solution = this.solution.getSolutionData(); + + var pattern = Pattern.compile(this.type.getSolutionPattern()); + var solutionMatcher = pattern.matcher(solution.toString()); + float solutionValue; + if (solutionMatcher.find()) { + solutionValue = Float.parseFloat(solutionMatcher.group(1)); + } else { + throw new IllegalStateException("Solution does not match the expected pattern!"); + } + + var comparison = bound.boundType().compare(bound.bound(), solutionValue); + + this.boundWithComparison.setComparison(comparison); } public UUID getId() { @@ -231,7 +259,11 @@ public String toString() { + '}'; } - public Optional getBound() { - return Optional.ofNullable(bound); + public Optional getBound() { + return Optional.ofNullable(boundWithComparison.getBound()); + } + + public Optional getBoundWithComparison() { + return Optional.of(boundWithComparison); } } From ba9d2198261e8f62fdd8e1b3be11e3a6c10fce9c Mon Sep 17 00:00:00 2001 From: zaibod <92274292+zaibod@users.noreply.github.com> Date: Mon, 30 Jun 2025 18:05:39 +0200 Subject: [PATCH 2/3] refactor: added docs and small refactors --- .../provideq/toolbox/api/ComparisonDto.java | 20 +++++++++++- .../kit/provideq/toolbox/meta/Problem.java | 31 +++++++++++++------ 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/main/java/edu/kit/provideq/toolbox/api/ComparisonDto.java b/src/main/java/edu/kit/provideq/toolbox/api/ComparisonDto.java index 4488a45a..8367f891 100644 --- a/src/main/java/edu/kit/provideq/toolbox/api/ComparisonDto.java +++ b/src/main/java/edu/kit/provideq/toolbox/api/ComparisonDto.java @@ -1,12 +1,20 @@ package edu.kit.provideq.toolbox.api; import edu.kit.provideq.toolbox.BoundWithInfo; -import edu.kit.provideq.toolbox.Solution; +/** + * A DTO for a comparison between a bound and a solution. + */ public class ComparisonDto { private BoundDto bound; private float comparison; + /** + * Creates a new comparison DTO out of a comparison value and a bound. + * + * @param comparison the comparison value, e.g., the ratio of the solution to the bound + * @param bound a bound + */ public ComparisonDto(float comparison, BoundWithInfo bound) { this.comparison = comparison; this.bound = new BoundDto(bound); @@ -23,6 +31,11 @@ public ComparisonDto() { .formatted(bound, comparison); } + /** + * Gets the bound of the comparison as a BoundDto. + * + * @return the bound of the comparison, e.g., the best known solution or the optimal solution + */ public BoundDto getBound() { return bound; } @@ -39,6 +52,11 @@ public void setComparison(float comparison) { this.comparison = comparison; } + /** + * Gets the comparison value of the comparison. + * + * @return the comparison value, e.g., the ratio of the solution to the bound. + */ public float getComparison() { return comparison; } diff --git a/src/main/java/edu/kit/provideq/toolbox/meta/Problem.java b/src/main/java/edu/kit/provideq/toolbox/meta/Problem.java index 1ea2171d..47043a71 100644 --- a/src/main/java/edu/kit/provideq/toolbox/meta/Problem.java +++ b/src/main/java/edu/kit/provideq/toolbox/meta/Problem.java @@ -87,6 +87,10 @@ public Mono> solve() { }); } + /** + * Estimates a bound for the problem's solution. Uses the estimator provided by the problem type. + * Also sets the execution time of the estimation in the boundWithComparison object. + */ public void estimateBound() { if (this.input == null) { throw new IllegalStateException("Cannot estimate value without input!"); @@ -96,6 +100,7 @@ public void estimateBound() { if (optionalEstimator.isEmpty()) { throw new IllegalStateException("Cannot estimate value without an estimator!"); } + var estimator = optionalEstimator.get(); long start = System.currentTimeMillis(); @@ -107,6 +112,9 @@ public void estimateBound() { this.boundWithComparison.setBound(new BoundWithInfo(estimatedBound, executionTime)); } + /** + * Compares the current solution with the bound according to the bound type. + */ public void compareBound() { if (this.solution == null) { throw new IllegalStateException("Cannot compare bound without solution!"); @@ -116,16 +124,9 @@ public void compareBound() { } var bound = this.boundWithComparison.getBound(); - var solution = this.solution.getSolutionData(); + var solutionData = this.solution.getSolutionData(); - var pattern = Pattern.compile(this.type.getSolutionPattern()); - var solutionMatcher = pattern.matcher(solution.toString()); - float solutionValue; - if (solutionMatcher.find()) { - solutionValue = Float.parseFloat(solutionMatcher.group(1)); - } else { - throw new IllegalStateException("Solution does not match the expected pattern!"); - } + float solutionValue = getSolutionValue(solutionData); var comparison = bound.boundType().compare(bound.bound(), solutionValue); @@ -266,4 +267,16 @@ public Optional getBound() { public Optional getBoundWithComparison() { return Optional.of(boundWithComparison); } + + private float getSolutionValue(ResultT solutionData) { + var pattern = Pattern.compile(this.type.getSolutionPattern()); + var solutionMatcher = pattern.matcher(solutionData.toString()); + float solutionValue; + if (solutionMatcher.find()) { + solutionValue = Float.parseFloat(solutionMatcher.group(1)); + } else { + throw new IllegalStateException("Solution does not match the expected pattern!"); + } + return solutionValue; + } } From 0a4921f319d588958ce72b131382ed3b9c6b820b Mon Sep 17 00:00:00 2001 From: zaibod Date: Mon, 30 Jun 2025 18:08:13 +0200 Subject: [PATCH 3/3] refactor: add hasBound method to ComparisonDto Introduced a hasBound() method in ComparisonDto to check for the presence of a bound. Updated Problem to use hasBound() instead of directly checking for null --- src/main/java/edu/kit/provideq/toolbox/api/ComparisonDto.java | 4 ++++ src/main/java/edu/kit/provideq/toolbox/meta/Problem.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/kit/provideq/toolbox/api/ComparisonDto.java b/src/main/java/edu/kit/provideq/toolbox/api/ComparisonDto.java index 4488a45a..539e29bf 100644 --- a/src/main/java/edu/kit/provideq/toolbox/api/ComparisonDto.java +++ b/src/main/java/edu/kit/provideq/toolbox/api/ComparisonDto.java @@ -35,6 +35,10 @@ public void setBound(BoundWithInfo bound) { this.bound = new BoundDto(bound); } + public boolean hasBound() { + return bound != null; + } + public void setComparison(float comparison) { this.comparison = comparison; } diff --git a/src/main/java/edu/kit/provideq/toolbox/meta/Problem.java b/src/main/java/edu/kit/provideq/toolbox/meta/Problem.java index 1ea2171d..9adabb29 100644 --- a/src/main/java/edu/kit/provideq/toolbox/meta/Problem.java +++ b/src/main/java/edu/kit/provideq/toolbox/meta/Problem.java @@ -111,7 +111,7 @@ public void compareBound() { if (this.solution == null) { throw new IllegalStateException("Cannot compare bound without solution!"); } - if (this.boundWithComparison.getBound() == null) { + if (!this.boundWithComparison.hasBound()) { throw new IllegalStateException("Cannot compare bound without bound!"); }