All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.optaplanner.examples.curriculumcourse.solver.curriculumCourseConstraints.drl Maven / Gradle / Ivy

Go to download

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.

There is a newer version: 9.44.0.Final
Show newest version
/*
 * 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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy