我一直在尝试创建Drools文件来进行时间表设置,但是即使实体数量很少(少于400个),OptaPlanner仍需要花费很长时间才能运行。

默认的后期接受策略可以非常快速地减少硬约束,同时将软约束保持在较高水平,但是会在达到可行性之前达到性能极限。禁忌搜索会降低两个分数,但比延迟验收要慢得多,而且比延迟验收要早,在可行性之前就碰壁了。

我想知道某些指数或群体评估者的写作是否错误或效率低下?我在给所有人带来尴尬的语法错误时遇到了麻烦,声称无法匹配ObjectType。

import data.Module
import data.Session
import data.Slot
import data.Program
import data.Staffer
import data.SessionAlternativeGroup
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder
import enums.SessionType

import java.util.Collections

import data.Constants

global HardSoftScoreHolder scoreHolder;

// Check for one tutor overused in the same slot
rule "staffClash"
    when
        $s1 : Session($tutors : tutors, $id : ID)
        $tutor : Staffer() from $tutors
        accumulate($s2 : Session($s2.overlaps($s1)); $tuse1 : sum($s2.getTutorWeeks($tutor)))
        eval($tuse1 > 12)
    then
        scoreHolder.addHardConstraintMatch(kcontext,-1);
end

// Room used for one module cannot be used for others at the same time
// (But it could be used for the same type of session on the same module)
rule "moduleRoomClash"
    when
        $s1 : Session($mod : module, $typ : type, $room : room, $id : ID)
        $s2 : Session(module != $mod, type != $typ, room == $room, $s2.overlaps($s1))
    then
        scoreHolder.addHardConstraintMatch(kcontext,-1);
end

// Apply badness of time slots
rule "timeBadness"
    when
        Session($slots : allSlots, $count : students)
        Slot ($bad : badness) from $slots
    then
        scoreHolder.addSoftConstraintMatch(kcontext,0-($bad * $count));
end

// Apply staff dislike of time slots
rule "staffDislikedTime"
    when
        $s : Session($staff : tutors, $slots : allSlots, $count : students)
        $st : Staffer($slot : dislikeSlots) from $staff
        eval($slots.contains($slot))
    then
        scoreHolder.addSoftConstraintMatch(kcontext,0-
          (Constants.BADNESS_STAFFER_DISLIKES_SLOT) * $count * ($s.getTutorWeeks($st)));
end

// Non computer sessions can be in computer rooms, but it's better not to
rule "unnecessaryComputerRoom"
    when
        $s : Session(!needsComputer, room!.isComputer, $count : students)
    then
        scoreHolder.addSoftConstraintMatch(kcontext,0-
          (Constants.BADNESS_UNNECESSARY_COMPUTER_ROOM) * $count);
end


// COMPULSORY, MANDATORY sessions must not clash with ANY other mandatory session on that
// program (if they did, it would be impossible to take that module)
rule "CompulsoryMandatoryClash"
    when
        Program( $comp : compulsories, $all : all )
        $s1 : Session( module memberOf $comp, $ID : ID, mandatory == true )
        Session( module memberOf $all, ID > $ID, mandatory == true, overlaps($s1) )
    then
        scoreHolder.addHardConstraintMatch(kcontext,-1);
end

// COMPULSORY, MANDATORY sessions must have at least ONE session in each altgroup on that
// programme that they do not clash with
rule "ProgrammeCompulsoryPracticalWipeout"
    when
        Program( $comp : compulsories, $all : all )
        $s1 : Session(module memberOf $comp, $ID : ID, mandatory)
        SessionAlternativeGroup(module memberOf $all, $sessions : sessions)
        forall ($s2 : Session(overlaps($s1)) from $sessions)
    then
        scoreHolder.addHardConstraintMatch(kcontext,-1);
end

// It's bad for elective modules on a programme to clash.
rule "ProgrammeElectiveLectureClash"
    when
        Program( $el : electives )
        $s1 : Session( module memberOf $el, $ID : ID, mandatory == true )
        Session( module memberOf $el, ID > $ID, mandatory == true, overlaps($s1) )
    then
        scoreHolder.addSoftConstraintMatch(kcontext,0-Constants.BADNESS_ELECTIVE_CLASH);
end

// Lectures should be earlier in the week than practicals
rule "LecturesBeforePracticals"
    when
        Session ($module : module, isLecture, $lecslot : slot)
        Session (module == $module, !isLecture, (slot!.ordinal) < ($lecslot!.ordinal))
    then
        scoreHolder.addHardConstraintMatch(kcontext,-1);
end

// Mandatory sessions shouldn't overlap any sessions on the same module
// (practicals CAN overlap each other, and normally would)
rule "PracticalOverLecture"
    when
        $s1 : Session ($mod : module, $ID : ID, mandatory)
        $s2 : Session (module == $mod, ID > $ID, $s1.overlaps($s2))
    then
        scoreHolder.addHardConstraintMatch(kcontext,-1);
end

// Elective sessions of different types on the same module
// shouldn't completely overlap each other
rule "MultipleTypesOverlap"
    when
        $s1 : Session ($mod : module, $ID : ID, $type : type, !mandatory)
        $ag : SessionAlternativeGroup($mod == module, type == $type, $s2s : sessions)
        forall ($s2 : Session(overlaps($s1)) from $s2s);
    then
        scoreHolder.addHardConstraintMatch(kcontext,-1);
end



// Sessions on a module should be as close as possible to each other
rule "PracticalsNearLectures"
    when
        $lec : Session (lastSlot != null, $mod : module, $ID : ID)
        $prac : Session (slot != null, module == $mod, $count : students, ID > $ID)
    then
        scoreHolder.addSoftConstraintMatch(kcontext,
               $count * (Math.min(0,0-($prac.getSlot().ordinal - ($lec.getLastSlot().ordinal+1)))));
end

// 12pm or 1pm slot should be free for staff for lunch
rule "NoLunchForYouStaffer"
       when
           Session($tutors : tutors, $day : slot.day, containsDayOrdinal(4))
           $tutor : Staffer() from $tutors
           Session(tutors contains $tutor, slot.day == $day, containsDayOrdinal(5))
       then
           scoreHolder.addHardConstraintMatch(kcontext,-1);
end

// 12pm or 1pm slot should be free for students, for lunch
rule "NoLunchForYouStudent"
   when
       Program ($comp : compulsories)
       Session($day : slot.day, $comp contains module, containsDayOrdinal(4))
       Session(slot.day == $day, $comp contains module, containsDayOrdinal(5))
   then
       scoreHolder.addHardConstraintMatch(kcontext,-1);
end

// Number of days staff members are in should be fairly distributed
rule "StaffInDaysFairness"
     when
         $s : Staffer(isAL == false)
         accumulate(Session(tutors contains $s, $day : slot!.day); $days1 : count($day))
     then
         scoreHolder.addSoftConstraintMatch(kcontext,(int)-(($days1 ^ 2)));
end

// Staff should have a clear day
rule "StaffClearDay"
     when
         $s : Staffer(isAL == false)
         accumulate(Session(tutors contains $s, $day : slot!.day != 2); $days1 : count($day))
         eval(($days1 > 3))
     then
         scoreHolder.addHardConstraintMatch(kcontext,-1);
end

最佳答案

INFO日志记录输出分数计算速度。基准测试程序(甚至更好)甚至在图形中显示它。越高越好。

运行40秒,注释部分规则,并观察分数计算速度,以查找瓶颈规则。

07-24 09:27