Skip to content

Commit dc30167

Browse files
authored
Merge branch 'develop' into feat/problems-endpoint
2 parents ec56469 + 5e14f64 commit dc30167

7 files changed

Lines changed: 152 additions & 44 deletions

File tree

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package edu.kit.provideq.toolbox.api;
2+
3+
import edu.kit.provideq.toolbox.BoundWithInfo;
4+
5+
/**
6+
* A DTO for a comparison between a bound and a solution.
7+
*/
8+
public class BoundComparisonDto {
9+
private BoundDto bound;
10+
private float comparison;
11+
12+
/**
13+
* Creates a new comparison DTO out of a comparison value and a bound.
14+
*
15+
* @param comparison the comparison value, e.g., the ratio of the solution to the bound
16+
* @param bound a bound
17+
*/
18+
public BoundComparisonDto(float comparison, BoundWithInfo bound) {
19+
this.comparison = comparison;
20+
this.bound = new BoundDto(bound);
21+
}
22+
23+
/**
24+
* Creates a new comparison DTO out of a bound and with an uninitialized comparison value.
25+
*
26+
* @param bound a bound
27+
*/
28+
public BoundComparisonDto(BoundWithInfo bound) {
29+
this.comparison = -1;
30+
this.bound = new BoundDto(bound);
31+
}
32+
33+
public BoundComparisonDto() {
34+
this.comparison = -1;
35+
this.bound = null;
36+
}
37+
38+
@Override public String toString() {
39+
return "Comparison{bound=%s, comparison=%f}"
40+
.formatted(bound, comparison);
41+
}
42+
43+
/**
44+
* Gets the bound of the comparison as a BoundDto.
45+
*
46+
* @return the bound of the comparison, e.g., the best known solution or the optimal solution
47+
*/
48+
public BoundDto getBound() {
49+
return bound;
50+
}
51+
52+
public void setBound(BoundWithInfo bound) {
53+
this.bound = new BoundDto(bound);
54+
}
55+
56+
public boolean hasBound() {
57+
return bound != null;
58+
}
59+
60+
/**
61+
* Gets the comparison value of the comparison.
62+
*
63+
* @return the comparison value, e.g., the ratio of the solution to the bound.
64+
*/
65+
public float getComparison() {
66+
return comparison;
67+
}
68+
69+
public void setComparison(float comparison) {
70+
this.comparison = comparison;
71+
}
72+
73+
}

src/main/java/edu/kit/provideq/toolbox/api/BoundDto.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,8 @@ public BoundDto(BoundWithInfo boundWithInfo) {
1010
boundWithInfo.bound().boundType(),
1111
boundWithInfo.executionTime());
1212
}
13+
14+
public BoundDto() {
15+
this(-1, BoundType.LOWER, -1);
16+
}
1317
}

src/main/java/edu/kit/provideq/toolbox/api/ComparisonDto.java

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/main/java/edu/kit/provideq/toolbox/api/EstimationRouter.java

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import io.swagger.v3.oas.annotations.enums.ParameterIn;
1919
import java.util.NoSuchElementException;
2020
import java.util.UUID;
21-
import java.util.regex.Pattern;
2221
import org.springdoc.core.fn.builders.operation.Builder;
2322
import org.springframework.beans.factory.annotation.Autowired;
2423
import org.springframework.context.annotation.Bean;
@@ -90,7 +89,7 @@ private <InputT, ResultT> Mono<ServerResponse> handleGet(
9089
Mono<BoundDto> bound;
9190
try {
9291
problem.estimateBound();
93-
bound = Mono.just(new BoundDto(problem.getBound().orElseThrow()));
92+
bound = Mono.just(problem.getBound().orElseThrow());
9493
} catch (IllegalStateException | NoSuchElementException e) {
9594
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage());
9695
}
@@ -114,22 +113,14 @@ private <InputT, ResultT> Mono<ServerResponse> handleCompare(
114113
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Bound not estimated yet!");
115114
}
116115

117-
float bound = problem.getBound().get().bound().value();
118-
var pattern = Pattern.compile(manager.getType().getSolutionPattern());
119-
var solutionMatcher = pattern.matcher(problem.getSolution().get().getSolutionData().toString());
120-
float solutionValue;
121-
if (solutionMatcher.find()) {
122-
solutionValue = Float.parseFloat(solutionMatcher.group(1));
123-
} else {
124-
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Could not parse solution value!");
116+
try {
117+
problem.compareBound();
118+
} catch (IllegalStateException | NoSuchElementException e) {
119+
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage());
125120
}
126121

127-
float comparison = problem.getBound().get().bound().boundType().compare(bound, solutionValue);
128-
ComparisonDto comparisonDto = new ComparisonDto(
129-
comparison,
130-
problem.getBound().get(),
131-
problem.getSolution().get()
132-
);
122+
var comparisonDto = problem.getBoundWithComparison();
123+
133124
return ok().body(Mono.just(comparisonDto), new ParameterizedTypeReference<>() {
134125
});
135126
}
@@ -176,7 +167,7 @@ private static org.springdoc.core.fn.builders.content.Builder getOkResponseConte
176167
private static org.springdoc.core.fn.builders.content.Builder comparisonOkResponseContent() {
177168
return contentBuilder()
178169
.mediaType(APPLICATION_JSON_VALUE)
179-
.schema(schemaBuilder().implementation(ComparisonDto.class));
170+
.schema(schemaBuilder().implementation(BoundComparisonDto.class));
180171
}
181172

182173
private <InputT, ResultT> Problem<InputT, ResultT> findProblemOrThrow(

src/main/java/edu/kit/provideq/toolbox/api/ProblemDto.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package edu.kit.provideq.toolbox.api;
22

3-
import edu.kit.provideq.toolbox.BoundWithInfo;
43
import edu.kit.provideq.toolbox.Solution;
54
import edu.kit.provideq.toolbox.meta.Problem;
65
import edu.kit.provideq.toolbox.meta.ProblemSolver;
@@ -17,8 +16,8 @@ public class ProblemDto<InputT, ResultT> {
1716
private String typeId;
1817
private InputT input;
1918
private Solution<ResultT> solution;
20-
private BoundWithInfo bound;
2119
private ProblemState state;
20+
private BoundComparisonDto boundWithComparison;
2221
private String solverId;
2322
private List<SolverSetting> solverSettings;
2423
private List<SubProblemReferenceDto> subProblems;
@@ -40,7 +39,7 @@ public static <InputT, ResultT> ProblemDto<InputT, ResultT> fromProblem(
4039
dto.typeId = problem.getType().getId();
4140
dto.input = problem.getInput().orElse(null);
4241
dto.solution = problem.getSolution().orElse(null);
43-
dto.bound = problem.getBound().orElse(null);
42+
dto.boundWithComparison = problem.getBoundWithComparison().orElse(null);
4443
dto.state = problem.getState();
4544
dto.solverId = problem.getSolver()
4645
.map(ProblemSolver::getId)
@@ -70,8 +69,8 @@ public Solution<ResultT> getSolution() {
7069
return solution;
7170
}
7271

73-
public BoundWithInfo getBound() {
74-
return bound;
72+
public BoundComparisonDto getBoundWithComparison() {
73+
return boundWithComparison;
7574
}
7675

7776
public ProblemState getState() {
@@ -107,7 +106,7 @@ public String toString() {
107106
+ ", solverId=" + solverId
108107
+ ", input=" + input
109108
+ ", solution=" + solution
110-
+ ", value=" + bound
109+
+ ", boundWithComparison=" + boundWithComparison
111110
+ ", solverSettings=" + solverSettings
112111
+ ", subProblems=" + subProblems
113112
+ '}';

src/main/java/edu/kit/provideq/toolbox/meta/Problem.java

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import edu.kit.provideq.toolbox.BoundWithInfo;
44
import edu.kit.provideq.toolbox.Solution;
5+
import edu.kit.provideq.toolbox.api.BoundComparisonDto;
6+
import edu.kit.provideq.toolbox.api.BoundDto;
57
import edu.kit.provideq.toolbox.meta.setting.SolverSetting;
68
import java.util.Collections;
79
import java.util.HashSet;
@@ -10,6 +12,7 @@
1012
import java.util.Set;
1113
import java.util.UUID;
1214
import java.util.function.Consumer;
15+
import java.util.regex.Pattern;
1316
import java.util.stream.Collectors;
1417
import reactor.core.publisher.Mono;
1518

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

3134
private InputT input;
3235
private Solution<ResultT> solution;
33-
private BoundWithInfo bound;
36+
private BoundComparisonDto boundWithComparison;
3437
private ProblemState state;
3538
private ProblemSolver<InputT, ResultT> solver;
3639
private List<SolverSetting> solverSettings;
@@ -84,6 +87,10 @@ public Mono<Solution<ResultT>> solve() {
8487
});
8588
}
8689

90+
/**
91+
* Estimates a bound for the problem's solution. Uses the estimator provided by the problem type.
92+
* Also sets the execution time of the estimation in the boundWithComparison object.
93+
*/
8794
public void estimateBound() {
8895
if (this.input == null) {
8996
throw new IllegalStateException("Cannot estimate value without input!");
@@ -93,6 +100,7 @@ public void estimateBound() {
93100
if (optionalEstimator.isEmpty()) {
94101
throw new IllegalStateException("Cannot estimate value without an estimator!");
95102
}
103+
96104
var estimator = optionalEstimator.get();
97105

98106
long start = System.currentTimeMillis();
@@ -101,7 +109,29 @@ public void estimateBound() {
101109
long finish = System.currentTimeMillis();
102110
var executionTime = finish - start;
103111

104-
this.bound = new BoundWithInfo(estimatedBound, executionTime);
112+
this.boundWithComparison =
113+
new BoundComparisonDto(new BoundWithInfo(estimatedBound, executionTime));
114+
}
115+
116+
/**
117+
* Compares the current solution with the bound according to the bound type.
118+
*/
119+
public void compareBound() {
120+
if (this.solution == null) {
121+
throw new IllegalStateException("Cannot compare bound without solution!");
122+
}
123+
if (this.boundWithComparison == null || !this.boundWithComparison.hasBound()) {
124+
throw new IllegalStateException("Cannot compare bound without bound!");
125+
}
126+
127+
var bound = this.boundWithComparison.getBound();
128+
var solutionData = this.solution.getSolutionData();
129+
130+
float solutionValue = getSolutionValue(solutionData);
131+
132+
var comparison = bound.boundType().compare(bound.bound(), solutionValue);
133+
134+
this.boundWithComparison.setComparison(comparison);
105135
}
106136

107137
public UUID getId() {
@@ -231,7 +261,27 @@ public String toString() {
231261
+ '}';
232262
}
233263

234-
public Optional<BoundWithInfo> getBound() {
235-
return Optional.ofNullable(bound);
264+
public Optional<BoundDto> getBound() {
265+
if (boundWithComparison == null) {
266+
return Optional.empty();
267+
}
268+
269+
return Optional.ofNullable(boundWithComparison.getBound());
270+
}
271+
272+
public Optional<BoundComparisonDto> getBoundWithComparison() {
273+
return Optional.ofNullable(boundWithComparison);
274+
}
275+
276+
private float getSolutionValue(ResultT solutionData) {
277+
var pattern = Pattern.compile(this.type.getSolutionPattern());
278+
var solutionMatcher = pattern.matcher(solutionData.toString());
279+
float solutionValue;
280+
if (solutionMatcher.find()) {
281+
solutionValue = Float.parseFloat(solutionMatcher.group(1));
282+
} else {
283+
throw new IllegalStateException("Solution does not match the expected pattern!");
284+
}
285+
return solutionValue;
236286
}
237287
}

src/main/java/edu/kit/provideq/toolbox/meta/ProblemType.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ public class ProblemType<InputT, ResultT> {
2020
/**
2121
* Defines a new problem type.
2222
*
23-
* @param id a unique string identifier for this type of problem.
24-
* @param description a description of the problem type.
25-
* @param inputClass the Java class object corresponding to the {@link InputT} type parameter.
26-
* @param resultClass the Java class object corresponding to the {@link ResultT} type parameter.
27-
* @param estimator the bound estimator for this problem type.
28-
* null if estimation is not supported.
23+
* @param id a unique string identifier for this type of problem.
24+
* @param inputClass the Java class object matching the {@link InputT} type parameter.
25+
* @param resultClass the Java class object matching the {@link ResultT} type parameter.
26+
* @param estimator the bound estimator for this problem type,
27+
* null if estimation is not supported.
28+
* @param solutionPattern a regex pattern describing the format of valid solutions
29+
* needs to contain one group to match a float number describing
30+
* the problem quality if estimation is supported, null otherwise.
2931
*/
3032
public ProblemType(
3133
String id,

0 commit comments

Comments
 (0)