Skip to content

Commit b48458d

Browse files
smokeyrobotpivovarit
authored andcommitted
Bael 801 (eugenp#5150)
* BAEL-801 A Guide to OptaPlanner * BAEL-801 Optaplanner per Editor Review * BAEL-801 Fixed parent pom merge issue * BAEL-801 Fixed parent pom merge issue * BAEL-801 Added logback to suppress debug logging causing build failures * BAEL-801 Updated per editor review * BAEL-801 Removed static variables * BAEL-801 - Updated per Senior Editor review. Moved classes to Drools module. * BAEL-801 - Updated per Senior Editor review. Moved classes to Drools module. * BAEL-801 - Deleted duplicate class.
1 parent 3dcdc30 commit b48458d

File tree

8 files changed

+218
-0
lines changed

8 files changed

+218
-0
lines changed

drools/pom.xml

+6
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,18 @@
4848
<artifactId>poi-ooxml</artifactId>
4949
<version>${apache-poi-version}</version>
5050
</dependency>
51+
<dependency>
52+
<groupId>org.optaplanner</groupId>
53+
<artifactId>optaplanner-core</artifactId>
54+
<version>${opta-planner-version}</version>
55+
</dependency>
5156
</dependencies>
5257

5358
<properties>
5459
<http-component-version>4.4.6</http-component-version>
5560
<drools-version>7.4.1.Final</drools-version>
5661
<apache-poi-version>3.13</apache-poi-version>
62+
<opta-planner-version>7.10.0.Final</opta-planner-version>
5763
</properties>
5864

5965
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.baeldung.drools.optaplanner;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty;
7+
import org.optaplanner.core.api.domain.solution.PlanningScore;
8+
import org.optaplanner.core.api.domain.solution.PlanningSolution;
9+
import org.optaplanner.core.api.domain.solution.drools.ProblemFactCollectionProperty;
10+
import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider;
11+
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
12+
import org.slf4j.Logger;
13+
import org.slf4j.LoggerFactory;
14+
15+
@PlanningSolution
16+
public class CourseSchedule {
17+
18+
Logger logger = LoggerFactory.getLogger("CourseSchedule");
19+
20+
private List<Integer> roomList;
21+
private List<Integer> periodList;
22+
private List<Lecture> lectureList;
23+
private HardSoftScore score;
24+
25+
public CourseSchedule(){
26+
roomList = new ArrayList<>();
27+
periodList = new ArrayList<>();
28+
lectureList = new ArrayList<>();
29+
}
30+
31+
@ValueRangeProvider(id = "availableRooms")
32+
@ProblemFactCollectionProperty
33+
public List<Integer> getRoomList() {
34+
return roomList;
35+
}
36+
37+
@ValueRangeProvider(id = "availablePeriods")
38+
@ProblemFactCollectionProperty
39+
public List<Integer> getPeriodList() {
40+
return periodList;
41+
}
42+
43+
@PlanningEntityCollectionProperty
44+
public List<Lecture> getLectureList() {
45+
return lectureList;
46+
}
47+
48+
@PlanningScore
49+
public HardSoftScore getScore() {
50+
return score;
51+
}
52+
53+
public void setScore(HardSoftScore score) {
54+
this.score = score;
55+
}
56+
57+
public void printCourseSchedule() {
58+
lectureList.stream()
59+
.map(c -> "Lecture in Room " + c.getRoomNumber().toString() + " during Period " + c.getPeriod().toString())
60+
.forEach(k -> logger.info(k));
61+
}
62+
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.baeldung.drools.optaplanner;
2+
3+
import org.optaplanner.core.api.domain.entity.PlanningEntity;
4+
import org.optaplanner.core.api.domain.variable.PlanningVariable;
5+
6+
@PlanningEntity
7+
public class Lecture {
8+
9+
private Integer roomNumber;
10+
private Integer period;
11+
12+
@PlanningVariable(valueRangeProviderRefs = {"availablePeriods"})
13+
public Integer getPeriod() {
14+
return period;
15+
}
16+
17+
@PlanningVariable(valueRangeProviderRefs = {"availableRooms"})
18+
public Integer getRoomNumber() {
19+
return roomNumber;
20+
}
21+
22+
public void setPeriod(Integer period) {
23+
this.period = period;
24+
}
25+
26+
public void setRoomNumber(Integer roomNumber) {
27+
this.roomNumber = roomNumber;
28+
}
29+
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.baeldung.drools.optaplanner;
2+
3+
import java.util.HashSet;
4+
5+
import org.optaplanner.core.api.score.Score;
6+
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
7+
import org.optaplanner.core.impl.score.director.easy.EasyScoreCalculator;
8+
9+
public class ScoreCalculator implements EasyScoreCalculator<CourseSchedule> {
10+
11+
@Override
12+
public Score calculateScore(CourseSchedule courseSchedule) {
13+
int hardScore = 0;
14+
int softScore = 0;
15+
16+
HashSet<String> occupiedRooms = new HashSet<>();
17+
for (Lecture lecture : courseSchedule.getLectureList()) {
18+
if(lecture.getPeriod() != null && lecture.getRoomNumber() != null) {
19+
String roomInUse = lecture.getPeriod().toString() + ":" + lecture.getRoomNumber().toString();
20+
if (occupiedRooms.contains(roomInUse)) {
21+
hardScore += -1;
22+
} else {
23+
occupiedRooms.add(roomInUse);
24+
}
25+
} else {
26+
hardScore += -1;
27+
}
28+
}
29+
30+
return HardSoftScore.valueOf(hardScore, softScore);
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.baeldung.drools.optaplanner
2+
3+
import com.baeldung.drools.optaplanner.Lecture;
4+
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder;
5+
6+
global HardSoftScoreHolder scoreHolder;
7+
8+
rule "noNullRoomPeriod"
9+
when
10+
Lecture( roomNumber == null );
11+
Lecture( period == null );
12+
then
13+
scoreHolder.addHardConstraintMatch(kcontext, -1);
14+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<solver>
3+
<scanAnnotatedClasses/>
4+
5+
<scoreDirectorFactory>
6+
<scoreDrl>courseSchedule.drl</scoreDrl>
7+
</scoreDirectorFactory>
8+
9+
<termination>
10+
<secondsSpentLimit>10</secondsSpentLimit>
11+
</termination>
12+
</solver>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<solver>
3+
<scanAnnotatedClasses/>
4+
5+
<scoreDirectorFactory>
6+
<easyScoreCalculatorClass>com.baeldung.drools.optaplanner.ScoreCalculator</easyScoreCalculatorClass>
7+
</scoreDirectorFactory>
8+
9+
<termination>
10+
<secondsSpentLimit>10</secondsSpentLimit>
11+
</termination>
12+
</solver>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.baeldung.drools.optaplanner;
2+
3+
import java.util.Arrays;
4+
5+
import org.junit.Assert;
6+
import org.junit.jupiter.api.BeforeAll;
7+
import org.junit.jupiter.api.Test;
8+
import org.optaplanner.core.api.solver.Solver;
9+
import org.optaplanner.core.api.solver.SolverFactory;
10+
11+
public class OptaPlannerUnitTest {
12+
13+
static CourseSchedule unsolvedCourseSchedule;
14+
15+
@BeforeAll
16+
public static void setUp() {
17+
18+
unsolvedCourseSchedule = new CourseSchedule();
19+
20+
for(int i = 0; i < 10; i++){
21+
unsolvedCourseSchedule.getLectureList().add(new Lecture());
22+
}
23+
24+
unsolvedCourseSchedule.getPeriodList().addAll(Arrays.asList(new Integer[] { 1, 2, 3 }));
25+
unsolvedCourseSchedule.getRoomList().addAll(Arrays.asList(new Integer[] { 1, 2 }));
26+
}
27+
28+
@Test
29+
public void test_whenCustomJavaSolver() {
30+
31+
SolverFactory<CourseSchedule> solverFactory = SolverFactory.createFromXmlResource("courseScheduleSolverConfiguration.xml");
32+
Solver<CourseSchedule> solver = solverFactory.buildSolver();
33+
CourseSchedule solvedCourseSchedule = solver.solve(unsolvedCourseSchedule);
34+
35+
Assert.assertNotNull(solvedCourseSchedule.getScore());
36+
Assert.assertEquals(-4, solvedCourseSchedule.getScore().getHardScore());
37+
}
38+
39+
@Test
40+
public void test_whenDroolsSolver() {
41+
42+
SolverFactory<CourseSchedule> solverFactory = SolverFactory.createFromXmlResource("courseScheduleSolverConfigDrools.xml");
43+
Solver<CourseSchedule> solver = solverFactory.buildSolver();
44+
CourseSchedule solvedCourseSchedule = solver.solve(unsolvedCourseSchedule);
45+
46+
Assert.assertNotNull(solvedCourseSchedule.getScore());
47+
Assert.assertEquals(0, solvedCourseSchedule.getScore().getHardScore());
48+
}
49+
}

0 commit comments

Comments
 (0)