当前位置: 首页 > 知识库问答 >
问题:

Optaplanner中的公平性,但用小时代替轮班

韩峰
2023-03-14

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

  • 周内的偶数班次。
  • 总计偶数班次。
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

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

共有1个答案

拓拔弘亮
2023-03-14

看一下网球的例子,特别是这一行。

rule "fairAssignmentCountPerTeam"
    when
        accumulate(
            $t : Team()
            and accumulate(
                TeamAssignment(team == $t);
                $assignmentCount : count() // This could be a sum of hours too
            );
            $result : loadBalance($assignmentCount)
        )
    then
        scoreHolder.addMediumConstraintMatch(kcontext, - (int) $result.getMeanDeviationSquaredSumRootMillis());
end
 类似资料:
  • 如何使用约束流api计算员工的公平性。 https://www.optaplanner.org/blog/2017/02/03/FormulaForMeasuringUnfairness.html 我在网球求解器示例中看到了上述流口水的实现。 https://github.com/kiegroup/optaplanner/blob/581d10fb8140f37b7491d06b2bab8d5ac

  • 我有几个属性文件(application.properties),其中包含类路径下的自定义和Spring配置,我想根据系统变量加载这些属性。我使用加载属性如下。 但它未能覆盖Spring配置(Spring配置添加在application.properties),我想覆盖这些文件后Spring选择application.properties文件。想法是以编程方式覆盖Spring配置。如何实现?

  • 我已经通过接受了公平和非公平纪律的测试。我写了一个模拟哲学家吃饭的小程序。 每个哲学家都有左右叉子,分别是s。我模拟了1000次思考和进食行为: 在哪里 没什么意思,只是睡了一段时间而已。下面是eat的

  • 问题内容: py2exe很棒,每当我想打包一个要在Windows系统上运行的python程序时,我都会使用py2exe。 我的问题是,是否可以使用等效工具在Windows上打包程序,但是可以在Linux上运行? 问题答案: 好的,我已经做到了。这有点hacky,但是对于我的用例来说效果很好。 要点是使用ModuleFinder查找所有导入的模块,过滤掉所有系统模块,编译并压缩它们。 不幸的是,我的

  • 我是OptaPlanner的新手,尝试根据自己的需要修改现有VRP示例。 我的问题是:我想要无容量限制的VRP,如示例tutorial/test/tutorial-01-uncapacitated中所示。vrp。在实际实现中,优化器大多只使用一辆车,因为它只考虑最小化总数据量。我想改变软约束,使最大行程最小化。我的目标是平等利用车辆。 以下是实现的drools软约束: 我试图计算每辆车的距离,并为

  • 在B. Goetz的Java实践中的并发,第13.5节说: 在Java5.0中,读锁的行为更像是一个信号量而不是锁,只维护活动读卡器的数量,而不是它们的身份。Java 6中的行为已更改,以跟踪哪些线程已被授予读锁6。 6这种变化的一个原因是,在java 5.0下,锁实现不能区分第一次请求读锁的线程和重入锁请求,这将使公平读写锁容易死锁。 我的问题是公平有什么问题?为什么不公平的读写锁会被死锁屏蔽?