This commit is contained in:
Jonathan Cook
2019-10-23 15:01:44 +02:00
parent db85c8f275
commit 684ec0d2e3
20486 changed files with 1642483 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
## OptaPlanner
This module contains articles about OptaPlanner.
### Relevant articles
- [A Guide to OptaPlanner](https://www.baeldung.com/opta-planner)
+27
View File
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>optaplanner</artifactId>
<name>optaplanner</name>
<parent>
<artifactId>parent-modules</artifactId>
<groupId>com.baeldung</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.optaplanner</groupId>
<artifactId>optaplanner-core</artifactId>
<version>${optaplanner-core.version}</version>
</dependency>
</dependencies>
<properties>
<optaplanner-core.version>7.9.0.Final</optaplanner-core.version>
</properties>
</project>
@@ -0,0 +1,63 @@
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.valuerange.ValueRangeProvider;
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@PlanningSolution
public class CourseSchedule {
Logger logger = LoggerFactory.getLogger("CourseSchedule");
private List<Integer> roomList;
private List<Integer> periodList;
private List<Lecture> lectureList;
private HardSoftScore score;
public CourseSchedule(){
roomList = new ArrayList<>();
periodList = new ArrayList<>();
lectureList = new ArrayList<>();
}
@ValueRangeProvider(id = "availableRooms")
@ProblemFactCollectionProperty
public List<Integer> getRoomList() {
return roomList;
}
@ValueRangeProvider(id = "availablePeriods")
@ProblemFactCollectionProperty
public List<Integer> getPeriodList() {
return periodList;
}
@PlanningEntityCollectionProperty
public List<Lecture> getLectureList() {
return lectureList;
}
@PlanningScore
public HardSoftScore getScore() {
return score;
}
public void setScore(HardSoftScore score) {
this.score = score;
}
public void printCourseSchedule() {
lectureList.stream()
.map(c -> "Lecture in Room " + c.getRoomNumber().toString() + " during Period " + c.getPeriod().toString())
.forEach(k -> logger.info(k));
}
}
@@ -0,0 +1,30 @@
package com.baeldung.optaplanner;
import org.optaplanner.core.api.domain.entity.PlanningEntity;
import org.optaplanner.core.api.domain.variable.PlanningVariable;
@PlanningEntity
public class Lecture {
private Integer roomNumber;
private Integer period;
@PlanningVariable(valueRangeProviderRefs = {"availablePeriods"})
public Integer getPeriod() {
return period;
}
@PlanningVariable(valueRangeProviderRefs = {"availableRooms"})
public Integer getRoomNumber() {
return roomNumber;
}
public void setPeriod(Integer period) {
this.period = period;
}
public void setRoomNumber(Integer roomNumber) {
this.roomNumber = roomNumber;
}
}
@@ -0,0 +1,32 @@
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 java.util.HashSet;
public class ScoreCalculator implements EasyScoreCalculator<CourseSchedule> {
@Override
public Score calculateScore(CourseSchedule courseSchedule) {
int hardScore = 0;
int softScore = 0;
HashSet<String> occupiedRooms = new HashSet<>();
for (Lecture lecture : courseSchedule.getLectureList()) {
if(lecture.getPeriod() != null && lecture.getRoomNumber() != null) {
String roomInUse = lecture.getPeriod().toString() + ":" + lecture.getRoomNumber().toString();
if (occupiedRooms.contains(roomInUse)) {
hardScore += -1;
} else {
occupiedRooms.add(roomInUse);
}
} else {
hardScore += -1;
}
}
return HardSoftScore.valueOf(hardScore, softScore);
}
}
@@ -0,0 +1,14 @@
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
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<solver>
<scanAnnotatedClasses/>
<scoreDirectorFactory>
<scoreDrl>courseSchedule.drl</scoreDrl>
</scoreDirectorFactory>
<termination>
<secondsSpentLimit>10</secondsSpentLimit>
</termination>
</solver>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<solver>
<scanAnnotatedClasses/>
<scoreDirectorFactory>
<easyScoreCalculatorClass>com.baeldung.optaplanner.ScoreCalculator</easyScoreCalculatorClass>
</scoreDirectorFactory>
<termination>
<secondsSpentLimit>10</secondsSpentLimit>
</termination>
</solver>
@@ -0,0 +1,3 @@
<configuration>
<logger name="org.optaplanner" level="info"/>
</configuration>
@@ -0,0 +1,50 @@
package com.baeldung.optaplanner.test;
import com.baeldung.optaplanner.CourseSchedule;
import com.baeldung.optaplanner.Lecture;
import org.junit.Assert;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.optaplanner.core.api.solver.Solver;
import org.optaplanner.core.api.solver.SolverFactory;
import java.util.Arrays;
public class OptaPlannerUnitTest {
static CourseSchedule unsolvedCourseSchedule;
@BeforeAll
public static void setUp() {
unsolvedCourseSchedule = new CourseSchedule();
for(int i = 0; i < 10; i++){
unsolvedCourseSchedule.getLectureList().add(new Lecture());
}
unsolvedCourseSchedule.getPeriodList().addAll(Arrays.asList(new Integer[] { 1, 2, 3 }));
unsolvedCourseSchedule.getRoomList().addAll(Arrays.asList(new Integer[] { 1, 2 }));
}
@Test
public void test_whenCustomJavaSolver() {
SolverFactory<CourseSchedule> solverFactory = SolverFactory.createFromXmlResource("courseScheduleSolverConfiguration.xml");
Solver<CourseSchedule> solver = solverFactory.buildSolver();
CourseSchedule solvedCourseSchedule = solver.solve(unsolvedCourseSchedule);
Assert.assertNotNull(solvedCourseSchedule.getScore());
Assert.assertEquals(-4, solvedCourseSchedule.getScore().getHardScore());
}
@Test
public void test_whenDroolsSolver() {
SolverFactory<CourseSchedule> solverFactory = SolverFactory.createFromXmlResource("courseScheduleSolverConfigDrools.xml");
Solver<CourseSchedule> solver = solverFactory.buildSolver();
CourseSchedule solvedCourseSchedule = solver.solve(unsolvedCourseSchedule);
Assert.assertNotNull(solvedCourseSchedule.getScore());
Assert.assertEquals(0, solvedCourseSchedule.getScore().getHardScore());
}
}