diff --git a/optaplanner/pom.xml b/optaplanner/pom.xml
index 0e5fa9050e..e1653fd749 100644
--- a/optaplanner/pom.xml
+++ b/optaplanner/pom.xml
@@ -18,10 +18,16 @@
optaplanner-core
${optaplanner-core.version}
+
+ org.optaplanner
+ optaplanner-test
+ ${optaplanner-core.version}
+ test
+
- 7.9.0.Final
+ 8.24.0.Final
\ No newline at end of file
diff --git a/optaplanner/src/main/java/com/baeldung/optaplanner/CourseSchedule.java b/optaplanner/src/main/java/com/baeldung/optaplanner/CourseSchedule.java
index 8a820ab56e..357dfe809f 100644
--- a/optaplanner/src/main/java/com/baeldung/optaplanner/CourseSchedule.java
+++ b/optaplanner/src/main/java/com/baeldung/optaplanner/CourseSchedule.java
@@ -3,7 +3,7 @@ package com.baeldung.optaplanner;
import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty;
import org.optaplanner.core.api.domain.solution.PlanningScore;
import org.optaplanner.core.api.domain.solution.PlanningSolution;
-import org.optaplanner.core.api.domain.solution.drools.ProblemFactCollectionProperty;
+import org.optaplanner.core.api.domain.solution.ProblemFactCollectionProperty;
import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider;
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
import org.slf4j.Logger;
@@ -16,36 +16,36 @@ import java.util.List;
public class CourseSchedule {
Logger logger = LoggerFactory.getLogger("CourseSchedule");
-
+ @ValueRangeProvider(id = "availableRooms")
+ @ProblemFactCollectionProperty
private List roomList;
+ @ValueRangeProvider(id = "availablePeriods")
+ @ProblemFactCollectionProperty
private List periodList;
+ @PlanningEntityCollectionProperty
private List lectureList;
+ @PlanningScore
private HardSoftScore score;
+
public CourseSchedule(){
roomList = new ArrayList<>();
periodList = new ArrayList<>();
lectureList = new ArrayList<>();
}
- @ValueRangeProvider(id = "availableRooms")
- @ProblemFactCollectionProperty
public List getRoomList() {
return roomList;
}
- @ValueRangeProvider(id = "availablePeriods")
- @ProblemFactCollectionProperty
public List getPeriodList() {
return periodList;
}
- @PlanningEntityCollectionProperty
public List getLectureList() {
return lectureList;
}
- @PlanningScore
public HardSoftScore getScore() {
return score;
}
@@ -54,6 +54,18 @@ public class CourseSchedule {
this.score = score;
}
+ public void setRoomList(List roomList) {
+ this.roomList = roomList;
+ }
+
+ public void setPeriodList(List periodList) {
+ this.periodList = periodList;
+ }
+
+ public void setLectureList(List lectureList) {
+ this.lectureList = lectureList;
+ }
+
public void printCourseSchedule() {
lectureList.stream()
.map(c -> "Lecture in Room " + c.getRoomNumber().toString() + " during Period " + c.getPeriod().toString())
diff --git a/optaplanner/src/main/java/com/baeldung/optaplanner/CourseScheduleConstraintProvider.java b/optaplanner/src/main/java/com/baeldung/optaplanner/CourseScheduleConstraintProvider.java
new file mode 100644
index 0000000000..2733806d16
--- /dev/null
+++ b/optaplanner/src/main/java/com/baeldung/optaplanner/CourseScheduleConstraintProvider.java
@@ -0,0 +1,24 @@
+package com.baeldung.optaplanner;
+
+import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
+import org.optaplanner.core.api.score.stream.Constraint;
+import org.optaplanner.core.api.score.stream.ConstraintFactory;
+import org.optaplanner.core.api.score.stream.ConstraintProvider;
+import org.optaplanner.core.api.score.stream.Joiners;
+
+public class CourseScheduleConstraintProvider implements ConstraintProvider {
+
+ @Override
+ public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
+ return new Constraint[]{
+ roomConflict(constraintFactory)
+ };
+ }
+
+ public Constraint roomConflict(ConstraintFactory constraintFactory){
+ return constraintFactory
+ .forEachUniquePair(Lecture.class,
+ Joiners.equal(Lecture::getRoomNumber), Joiners.equal(Lecture::getPeriod))
+ .penalize("Room conflict", HardSoftScore.ONE_HARD);
+ }
+}
diff --git a/optaplanner/src/main/java/com/baeldung/optaplanner/Lecture.java b/optaplanner/src/main/java/com/baeldung/optaplanner/Lecture.java
index 48af4e89d1..b63bd21030 100644
--- a/optaplanner/src/main/java/com/baeldung/optaplanner/Lecture.java
+++ b/optaplanner/src/main/java/com/baeldung/optaplanner/Lecture.java
@@ -1,14 +1,24 @@
package com.baeldung.optaplanner;
import org.optaplanner.core.api.domain.entity.PlanningEntity;
+import org.optaplanner.core.api.domain.lookup.PlanningId;
import org.optaplanner.core.api.domain.variable.PlanningVariable;
@PlanningEntity
public class Lecture {
+ @PlanningId
+ private Long id;
private Integer roomNumber;
private Integer period;
+ public Lecture(Long i) {
+ this.id = i;
+ }
+
+ public Lecture() {
+ }
+
@PlanningVariable(valueRangeProviderRefs = {"availablePeriods"})
public Integer getPeriod() {
return period;
diff --git a/optaplanner/src/main/java/com/baeldung/optaplanner/ScoreCalculator.java b/optaplanner/src/main/java/com/baeldung/optaplanner/ScoreCalculator.java
index 11e5e4a5be..3e3747f764 100644
--- a/optaplanner/src/main/java/com/baeldung/optaplanner/ScoreCalculator.java
+++ b/optaplanner/src/main/java/com/baeldung/optaplanner/ScoreCalculator.java
@@ -1,15 +1,14 @@
package com.baeldung.optaplanner;
-import org.optaplanner.core.api.score.Score;
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
-import org.optaplanner.core.impl.score.director.easy.EasyScoreCalculator;
+import org.optaplanner.core.api.score.calculator.EasyScoreCalculator;
import java.util.HashSet;
-public class ScoreCalculator implements EasyScoreCalculator {
+public class ScoreCalculator implements EasyScoreCalculator {
@Override
- public Score calculateScore(CourseSchedule courseSchedule) {
+ public HardSoftScore calculateScore(CourseSchedule courseSchedule) {
int hardScore = 0;
int softScore = 0;
@@ -27,6 +26,6 @@ public class ScoreCalculator implements EasyScoreCalculator {
}
}
- return HardSoftScore.valueOf(hardScore, softScore);
+ return HardSoftScore.of(hardScore, softScore);
}
}
diff --git a/optaplanner/src/main/resources/courseSchedule.drl b/optaplanner/src/main/resources/courseSchedule.drl
deleted file mode 100644
index 9372a24976..0000000000
--- a/optaplanner/src/main/resources/courseSchedule.drl
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.baeldung.optaplanner
-
-import com.baeldung.optaplanner.Lecture;
-import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder;
-
-global HardSoftScoreHolder scoreHolder;
-
-rule "noNullRoomPeriod"
- when
- Lecture( roomNumber == null );
- Lecture( period == null );
- then
- scoreHolder.addHardConstraintMatch(kcontext, -1);
-end
\ No newline at end of file
diff --git a/optaplanner/src/main/resources/courseScheduleSolverConfigDrools.xml b/optaplanner/src/main/resources/courseScheduleSolverConfigDrools.xml
deleted file mode 100644
index 7cf95fdcd3..0000000000
--- a/optaplanner/src/main/resources/courseScheduleSolverConfigDrools.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
- courseSchedule.drl
-
-
-
- 10
-
-
\ No newline at end of file
diff --git a/optaplanner/src/main/resources/courseScheduleSolverConfiguration.xml b/optaplanner/src/main/resources/courseScheduleSolverConfiguration.xml
deleted file mode 100644
index 0ad2264dcd..0000000000
--- a/optaplanner/src/main/resources/courseScheduleSolverConfiguration.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
- com.baeldung.optaplanner.ScoreCalculator
-
-
-
- 10
-
-
\ No newline at end of file
diff --git a/optaplanner/src/main/resources/logback.xml b/optaplanner/src/main/resources/logback.xml
index c109aa19e2..34da901079 100644
--- a/optaplanner/src/main/resources/logback.xml
+++ b/optaplanner/src/main/resources/logback.xml
@@ -1,3 +1,16 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%-12.12t] %-5p %m%n
+
+
+
-
\ No newline at end of file
+
+
+
+
+
+
diff --git a/optaplanner/src/test/java/com/baeldung/optaplanner/test/CourseScheduleConstraintProviderUnitTest.java b/optaplanner/src/test/java/com/baeldung/optaplanner/test/CourseScheduleConstraintProviderUnitTest.java
new file mode 100644
index 0000000000..22de095ce9
--- /dev/null
+++ b/optaplanner/src/test/java/com/baeldung/optaplanner/test/CourseScheduleConstraintProviderUnitTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.optaplanner.test;
+
+import com.baeldung.optaplanner.CourseSchedule;
+import com.baeldung.optaplanner.CourseScheduleConstraintProvider;
+import com.baeldung.optaplanner.Lecture;
+import org.junit.jupiter.api.Test;
+import org.optaplanner.test.api.score.stream.ConstraintVerifier;
+
+public class CourseScheduleConstraintProviderUnitTest {
+
+ private final ConstraintVerifier constraintVerifier =
+ ConstraintVerifier.build(new CourseScheduleConstraintProvider(), CourseSchedule.class, Lecture.class);
+
+ @Test
+ public void testCourseScheduleConstraint() {
+
+ Lecture lecture = new Lecture(0L);
+ lecture.setPeriod(1);
+ lecture.setRoomNumber(1);
+ Lecture conflictedLecture = new Lecture(1L);
+ conflictedLecture.setPeriod(1);
+ conflictedLecture.setRoomNumber(1);
+
+ constraintVerifier.verifyThat(CourseScheduleConstraintProvider::roomConflict)
+ .given(lecture, conflictedLecture)
+ .penalizesBy(1);
+ }
+}
diff --git a/optaplanner/src/test/java/com/baeldung/optaplanner/test/OptaPlannerUnitTest.java b/optaplanner/src/test/java/com/baeldung/optaplanner/test/OptaPlannerUnitTest.java
index 2847a233a5..2b72765074 100644
--- a/optaplanner/src/test/java/com/baeldung/optaplanner/test/OptaPlannerUnitTest.java
+++ b/optaplanner/src/test/java/com/baeldung/optaplanner/test/OptaPlannerUnitTest.java
@@ -1,16 +1,26 @@
package com.baeldung.optaplanner.test;
import com.baeldung.optaplanner.CourseSchedule;
+import com.baeldung.optaplanner.CourseScheduleConstraintProvider;
import com.baeldung.optaplanner.Lecture;
+import com.baeldung.optaplanner.ScoreCalculator;
import org.junit.Assert;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.optaplanner.core.api.score.ScoreManager;
import org.optaplanner.core.api.solver.Solver;
import org.optaplanner.core.api.solver.SolverFactory;
+import org.optaplanner.core.config.solver.SolverConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.Duration;
import java.util.Arrays;
public class OptaPlannerUnitTest {
+ Logger logger = LoggerFactory.getLogger("OptaPlannerUnitTest");
+
static CourseSchedule unsolvedCourseSchedule;
@BeforeAll
@@ -18,8 +28,8 @@ public class OptaPlannerUnitTest {
unsolvedCourseSchedule = new CourseSchedule();
- for(int i = 0; i < 10; i++){
- unsolvedCourseSchedule.getLectureList().add(new Lecture());
+ for(long i = 0; i < 10; i++) {
+ unsolvedCourseSchedule.getLectureList().add(new Lecture(i));
}
unsolvedCourseSchedule.getPeriodList().addAll(Arrays.asList(new Integer[] { 1, 2, 3 }));
@@ -29,7 +39,12 @@ public class OptaPlannerUnitTest {
@Test
public void test_whenCustomJavaSolver() {
- SolverFactory solverFactory = SolverFactory.createFromXmlResource("courseScheduleSolverConfiguration.xml");
+ SolverFactory solverFactory = SolverFactory.create(new SolverConfig()
+ .withSolutionClass(CourseSchedule.class)
+ .withEntityClasses(Lecture.class)
+ .withEasyScoreCalculatorClass(ScoreCalculator.class)
+ .withTerminationSpentLimit(Duration.ofSeconds(1)));
+
Solver solver = solverFactory.buildSolver();
CourseSchedule solvedCourseSchedule = solver.solve(unsolvedCourseSchedule);
@@ -38,13 +53,22 @@ public class OptaPlannerUnitTest {
}
@Test
- public void test_whenDroolsSolver() {
+ public void test_whenConstraintStreamSolver() {
+
+ SolverFactory solverFactory = SolverFactory.create(new SolverConfig()
+ .withSolutionClass(CourseSchedule.class)
+ .withEntityClasses(Lecture.class)
+ .withConstraintProviderClass(CourseScheduleConstraintProvider.class)
+ .withTerminationSpentLimit(Duration.ofSeconds(1)));
- SolverFactory solverFactory = SolverFactory.createFromXmlResource("courseScheduleSolverConfigDrools.xml");
Solver solver = solverFactory.buildSolver();
CourseSchedule solvedCourseSchedule = solver.solve(unsolvedCourseSchedule);
+ logger.info(ScoreManager.create(solverFactory).explainScore(solvedCourseSchedule).getSummary());
+
Assert.assertNotNull(solvedCourseSchedule.getScore());
- Assert.assertEquals(0, solvedCourseSchedule.getScore().getHardScore());
+ Assert.assertEquals(-4, solvedCourseSchedule.getScore().getHardScore());
+
}
+
}
diff --git a/pom.xml b/pom.xml
index 3918250d85..da9a18bd3d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -492,7 +492,6 @@
open-liberty
oauth2-framework-impl
- optaplanner
orika
osgi
@@ -926,7 +925,6 @@
open-liberty
oauth2-framework-impl
- optaplanner
orika
osgi
@@ -1248,6 +1246,7 @@
apache-httpclient-2
libraries-concurrency
maven-modules/multimodulemavenproject
+ optaplanner
persistence-modules/sirix
persistence-modules/spring-data-cassandra-2
quarkus-modules/quarkus-vs-springboot
@@ -1317,6 +1316,7 @@
apache-httpclient-2
libraries-concurrency
maven-modules/multimodulemavenproject
+ optaplanner
persistence-modules/sirix
persistence-modules/spring-data-cassandra-2
quarkus-modules/quarkus-vs-springboot