Optaplanner的公平性,但有几个小时而不是轮班

时间:2017-12-14 17:05:11

标签: java optaplanner

我在公平约束方面遇到了一些麻烦,我想确保员工得到:

  • 几周内换班。
  • 总共有多少班次。

基本上我想避免公平只是检查几周(因此,如果有两个额外的轮班,那么两个员工每周都会得到这些,可能不会相同)

我想避免公平性只检查总数(这样一个员工可能会在一周内获得更多的轮班,然后没有更多的轮班,但总体而言,他们仍然可以获得更多的工作时间)

所以我试着遵循Optaplanner关于公平约束的文档,并对此做了两个限制,但与使用班次的文档预览不同,我需要在几个小时内估算我...所以现在,我的代码:

public int accumulateFairnessInHoursPerEmployeePerWeek(Week week)
    {
        //System.out.println("WEEK FAIRNESS CONSTRAINT:");
        int actualWorkload = 0;
        int totalAssignmentsDuringWeek = 0;
        for(Employee emp : getEmployees())
        {
            List<Assignment> assignmentsForEmployeeDuringWeek = new ArrayList<>();
            for(Assignment currentAss : getAssignmentsForSpecificWeek(week))
            {
                if(currentAss.getEmployee() == emp)
                {
                    assignmentsForEmployeeDuringWeek.add(currentAss);
                }
            }
            totalAssignmentsDuringWeek += getDurationForAssignments(assignmentsForEmployeeDuringWeek)/3600;
            actualWorkload += (int) Math.pow(getDurationForAssignments(assignmentsForEmployeeDuringWeek)/3600, 2);
            //System.out.println(emp.getName() + " has " + getDurationForAssignments(assignmentsForEmployeeDuringWeek)/3600 + " hours. Score: " + actualWorkload + " total: " + actualWorkload + " " + ass.getShift().getStartDate());
         }
        int idealWorkLoad = (int) Math.pow(totalAssignmentsDuringWeek, 2)/getEmployees().size();
        //System.out.println("IDEAL: " + idealWorkLoad + " ACTUAL: " + actualWorkload + " FAIRNESS: " + (actualWorkload -idealWorkLoad));
        return (actualWorkload - idealWorkLoad);
    }

    public int accumulateFairnessInHoursPerEmployeeInTotal()
    {
        System.out.println("TOTAL FAIRNESS CONSTRAINT:");
        int actualWorkload = 0;
        int totalDuration = 0;
        for(Employee emp : getEmployees())
        {
            List<Assignment> assignmentsForEmployee = new ArrayList<>();
            for(Assignment currentAss : getAssignments())
            {
                if(currentAss.getEmployee() == emp)
                {
                    assignmentsForEmployee.add(currentAss);
                }
            }
            totalDuration += getDurationForAssignments(assignmentsForEmployee)/3600;
            actualWorkload += (int) Math.pow(getDurationForAssignments(assignmentsForEmployee)/3600, 2);
            System.out.println(emp.getName() + " has " + getDurationForAssignments(assignmentsForEmployee)/3600 + " hours. Score: " + actualWorkload);
        }
        int idealWorkLoad = (int) Math.pow(totalDuration, 2)/getEmployees().size();
        System.out.println("IDEAL: " + idealWorkLoad + " ACTUAL: " + actualWorkload + " FAIRNESS: " + (actualWorkload - idealWorkLoad));
        return (actualWorkload - idealWorkLoad);
    }

这是流口水:

rule "EvenWorkloadPerEmployeeTotal"
    when
        $service : Service
        (
            $service.accumulateFairnessInHoursPerEmployeeInTotal() != 0
        )

    then
        if(isDroolActivated(kcontext.getRule().getName(), $service))
        {
            setDroolRating(scoreHolder, kcontext, $service.getDroolStrength(drools), $service.accumulateFairnessInHoursPerEmployeeInTotal());
        }
end

rule "EvenWorkloadPerEmployeePerWeek"
    when
        $week : Week()
        $service : Service
        (
            $service.accumulateFairnessInHoursPerEmployeePerWeek($week) != 0
        )

    then
        if(isDroolActivated(kcontext.getRule().getName(), $service))
        {
            setDroolRating(scoreHolder, kcontext, $service.getDroolStrength(drools), $service.accumulateFairnessInHoursPerEmployeePerWeek($week));
        }
end

它似乎在大多数时间都有效,特别是在较小的数据集中...但是,当我使用更大的数据集时...... 这是我的结果:

  • A有76.0小时。得分:5776
  • B有118.0小时。得分:19700
  • C有76.0小时。得分:25476
  • D有83.0小时。得分:32365
  • E有88.0小时。得分:40109
  • F有72.0小时。得分:45293
  • G有68.0小时。得分:49917
  • H有64.0小时。得分:54013
  • 我有96.0小时。得分:63229
  • J有94.0小时。得分:72065
  • K有92.0小时。得分:80529
  • L有67.0小时。得分:85018
  • M有98.0小时。得分:94622
  • N有95.0小时。得分:103647
  • O有101.0小时。得分:113848
  • P有90.0小时。得分:121948
  • Q有93.0小时。得分:130597
  • R有108.0小时。得分:142261
  • S有124.0小时。得分:157637
  • T有116.0小时。得分:171093

IDEAL:157560 ACTUAL:171093 FAIRNESS:13533

数字相当高...... 而且我怀疑有人认为G和H只有64-68小时是公平的,但S必须工作124小时 我想知道在使用时间而不是轮班计算公平性时,是否有另一种/更好的方法来估计公平性?

编辑:可能值得注意的是,我也尝试了几天,但是使用这些数字似乎太小了,就像它对一个员工相比另一个人一天不太关心。

我同时使用这些约束,但没有涉及其他约束

1 个答案:

答案 0 :(得分:0)

看看网球示例,特别是this line

func showNotification(title: String, informativeText: String) -> NSUserNotification {
    let notification = NSUserNotification()
    notification.title = title
    notification.informativeText = informativeText
    NSUserNotificationCenter.default.deliver(notification)
    return notification
}