org.optaplanner.examples.curriculumcourse.solver.curriculumCourseConstraints.drl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of optaplanner-examples Show documentation
Show all versions of optaplanner-examples Show documentation
OptaPlanner solves planning problems.
This lightweight, embeddable planning engine implements powerful and scalable algorithms
to optimize business resource scheduling and planning.
This module contains the examples which demonstrate how to use it in a normal Java application.
/*
* Copyright 2010 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.optaplanner.examples.curriculumcourse.solver;
dialect "java"
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder;
import org.optaplanner.examples.curriculumcourse.domain.Course;
import org.optaplanner.examples.curriculumcourse.domain.Curriculum;
import org.optaplanner.examples.curriculumcourse.domain.CourseSchedule;
import org.optaplanner.examples.curriculumcourse.domain.Day;
import org.optaplanner.examples.curriculumcourse.domain.Lecture;
import org.optaplanner.examples.curriculumcourse.domain.Period;
import org.optaplanner.examples.curriculumcourse.domain.Room;
import org.optaplanner.examples.curriculumcourse.domain.Teacher;
import org.optaplanner.examples.curriculumcourse.domain.Timeslot;
import org.optaplanner.examples.curriculumcourse.domain.UnavailablePeriodPenalty;
import org.optaplanner.examples.curriculumcourse.domain.solver.CourseConflict;
global HardSoftScoreHolder scoreHolder;
// ############################################################################
// Hard constraints
// ############################################################################
// Lectures: A missing or extra lecture of a course.
// This hard constraint is built-in: the correct number of Lecture's is created
// Conflicts: Two conflicting lectures in the same period.
// Three conflicting lectures count as 3 violations: one for each pair.
rule "conflictingLecturesDifferentCourseInSamePeriod"
when
$courseConflict : CourseConflict($leftCourse : leftCourse, $rightCourse : rightCourse)
$leftLecture : Lecture(course == $leftCourse, $period : period, period != null)
$rightLecture : Lecture(course == $rightCourse, period == $period, this != $leftLecture)
then
scoreHolder.addHardConstraintMatch(kcontext, - $courseConflict.getConflictCount());
end
rule "conflictingLecturesSameCourseInSamePeriod"
when
Lecture($leftId : id, $leftCourse : course, $period : period, period != null)
Lecture(course == $leftCourse, period == $period, id > $leftId)
then
scoreHolder.addHardConstraintMatch(kcontext, - (1 + $leftCourse.getCurriculumList().size()));
end
// RoomOccupancy: Two lectures in the same room at the same period.
// Any extra lecture in the same period and room counts as one more violation.
rule "roomOccupancy"
when
Lecture($leftId : id, period != null, $period : period, room != null, $room : room)
// $leftLecture has lowest id of the period+room combo
not Lecture(period == $period, room == $room, id < $leftId)
// rightLecture has the same period
Lecture(period == $period, room == $room, id > $leftId, $rightId : id)
then
scoreHolder.addHardConstraintMatch(kcontext, -1);
end
// Availabilities: Each lecture in a period unavailable for that course.
rule "unavailablePeriodPenalty"
when
UnavailablePeriodPenalty($course : course, $period : period)
Lecture(course == $course, period == $period)
then
scoreHolder.addHardConstraintMatch(kcontext, -10);
end
// ############################################################################
// Soft constraints
// ############################################################################
// RoomCapacity: For each lecture, the number of students that attend the course should be less or equal
// than the number of seats of all the rooms that host its lectures.
// Each student above the capacity counts as 1 point of penalty.
rule "roomCapacity"
when
$lecture : Lecture(room != null, studentSize > getRoom().getCapacity())
then
scoreHolder.addSoftConstraintMatch(kcontext, ($lecture.getRoom().getCapacity() - $lecture.getStudentSize()));
end
// MinimumWorkingDays: The lectures of each course should be spread into a minimum number of days.
// Each day below the minimum counts as 5 points of penalty.
rule "minimumWorkingDays"
when
$course : Course($minWorkingDaySize : minWorkingDaySize)
accumulate(
$day : Day()
and exists Lecture(course == $course, day == $day);
$dayCount : count($day);
$dayCount < $minWorkingDaySize
)
// An uninitialized schedule should have no constraints broken
exists Lecture(course == $course, period != null)
then
scoreHolder.addSoftConstraintMatch(kcontext, (($dayCount.intValue() - $minWorkingDaySize) * 5));
end
// CurriculumCompactness: Lectures belonging to a curriculum should be adjacent
// to each other (i.e., in consecutive periods).
// For a given curriculum we account for a violation every time there is one lecture not adjacent
// to any other lecture within the same day.
// Each isolated lecture in a curriculum counts as 2 points of penalty.
rule "curriculumCompactness"
when
$curriculum : Curriculum()
Lecture(curriculumList contains $curriculum,
$day : day, $timeslotIndex : timeslotIndex, period != null
)
not Lecture(curriculumList contains $curriculum,
day == $day, timeslotIndex == ($timeslotIndex - 1)
)
not Lecture(curriculumList contains $curriculum,
day == $day, timeslotIndex == ($timeslotIndex + 1)
)
then
scoreHolder.addSoftConstraintMatch(kcontext, -2);
end
// RoomStability: All lectures of a course should be given in the same room.
// Each distinct room used for the lectures of a course, but the first, counts as 1 point of penalty.
rule "roomStability"
when
$course : Course()
accumulate(
$room : Room()
and exists Lecture(course == $course, room == $room);
$roomCount : count($room);
$roomCount > 1
)
then
scoreHolder.addSoftConstraintMatch(kcontext, -($roomCount.intValue() - 1));
end