Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 61 additions & 4 deletions src/main/java/edu/kit/provideq/toolbox/api/ComparisonDto.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,68 @@
package edu.kit.provideq.toolbox.api;

import edu.kit.provideq.toolbox.BoundWithInfo;
import edu.kit.provideq.toolbox.Solution;

public record ComparisonDto(float comparison, BoundWithInfo bound, Solution<?> solution) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice if you included an JavaDoc for this class

/**
* 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);
}

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);
}

/**
* 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;
}

public void setBound(BoundDto bound) {
this.bound = bound;
}

public void setBound(BoundWithInfo bound) {
this.bound = new BoundDto(bound);
}

public boolean hasBound() {
return bound != null;
}

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;
}

}
22 changes: 7 additions & 15 deletions src/main/java/edu/kit/provideq/toolbox/api/EstimationRouter.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ private <InputT, ResultT> Mono<ServerResponse> handleGet(
Mono<BoundDto> 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());
}
Expand All @@ -114,22 +114,14 @@ private <InputT, ResultT> Mono<ServerResponse> 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<>() {
});
}
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/edu/kit/provideq/toolbox/api/ProblemDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ public class ProblemDto<InputT, ResultT> {
private String typeId;
private InputT input;
private Solution<ResultT> solution;
private BoundWithInfo bound;
private ProblemState state;
private ComparisonDto boundWithComparison;
private String solverId;
private List<SolverSetting> solverSettings;
private List<SubProblemReferenceDto> subProblems;
Expand All @@ -40,7 +40,7 @@ public static <InputT, ResultT> ProblemDto<InputT, ResultT> 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)
Expand Down Expand Up @@ -70,8 +70,8 @@ public Solution<ResultT> getSolution() {
return solution;
}

public BoundWithInfo getBound() {
return bound;
public ComparisonDto getBoundWithComparison() {
return boundWithComparison;
}

public ProblemState getState() {
Expand Down Expand Up @@ -107,7 +107,7 @@ public String toString() {
+ ", solverId=" + solverId
+ ", input=" + input
+ ", solution=" + solution
+ ", value=" + bound
+ ", boundWithComparison=" + boundWithComparison
+ ", solverSettings=" + solverSettings
+ ", subProblems=" + subProblems
+ '}';
Expand Down
53 changes: 49 additions & 4 deletions src/main/java/edu/kit/provideq/toolbox/meta/Problem.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -30,7 +33,7 @@ public class Problem<InputT, ResultT> {

private InputT input;
private Solution<ResultT> solution;
private BoundWithInfo bound;
private final ComparisonDto boundWithComparison = new ComparisonDto();
private ProblemState state;
private ProblemSolver<InputT, ResultT> solver;
private List<SolverSetting> solverSettings;
Expand Down Expand Up @@ -84,6 +87,10 @@ public Mono<Solution<ResultT>> 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!");
Expand All @@ -93,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();
Expand All @@ -101,7 +109,28 @@ public void estimateBound() {
long finish = System.currentTimeMillis();
var executionTime = finish - start;

this.bound = new BoundWithInfo(estimatedBound, executionTime);
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) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we outsource this check to BoundWithInfo or ComparisonDto? It would be nice if we would have an indicator by a method call from the class which signalizes that the bound may not be set - isBoundSet() for instance?

throw new IllegalStateException("Cannot compare bound without solution!");
}
if (!this.boundWithComparison.hasBound()) {
throw new IllegalStateException("Cannot compare bound without bound!");
}

var bound = this.boundWithComparison.getBound();
var solutionData = this.solution.getSolutionData();

float solutionValue = getSolutionValue(solutionData);

var comparison = bound.boundType().compare(bound.bound(), solutionValue);

this.boundWithComparison.setComparison(comparison);
}

public UUID getId() {
Expand Down Expand Up @@ -231,7 +260,23 @@ public String toString() {
+ '}';
}

public Optional<BoundWithInfo> getBound() {
return Optional.ofNullable(bound);
public Optional<BoundDto> getBound() {
return Optional.ofNullable(boundWithComparison.getBound());
}

public Optional<ComparisonDto> 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;
}
}
Loading