【发布时间】:2020-03-21 21:12:36
【问题描述】:
我正在尝试在 Anylogic 中构建一个模型,以优化我的资源池的开始和结束时间以满足需求。有没有办法将计划的开始时间和结束时间作为参数输入到优化模型中。我目前的班次为 8-5 班,30 天内满足需求,但优化模型可能会说 6-6 班(我们加班)将在 15 天内满足需求。开始和结束时间会有最小值和最大值。
【问题讨论】:
我正在尝试在 Anylogic 中构建一个模型,以优化我的资源池的开始和结束时间以满足需求。有没有办法将计划的开始时间和结束时间作为参数输入到优化模型中。我目前的班次为 8-5 班,30 天内满足需求,但优化模型可能会说 6-6 班(我们加班)将在 15 天内满足需求。开始和结束时间会有最小值和最大值。
【问题讨论】:
不幸的是,这并不简单。
当您以可视方式创建 Schedule 对象时,您必须“硬编码”开始和结束时间。因此,要使它们可变(由模型参数驱动),您必须以编程方式创建调度,并确保资源池容量由它驱动。
如果您在帮助中看到 AnyLogic 帮助 > 函数、表函数和计划 > 计划 > 计划 API,说明了用于创建计划的编程接口 (API) 并包含示例模型。不过
该示例根据动态创建的计划动态设置源块到达计划。对于资源池,您不能这样做。 (不允许动态更改容量定义。)因此您需要设置一些 AnyLogic 事件来更改计划中的资源池容量。 (您可以随时动态更改资源池的容量。)事实上,当您为资源池块设置容量计划时,这就是资源池块在内部所做的事情......
该示例用于速率计划,没有记录任何代码,并且帮助中存在一些错误/缺乏正确解释。 (特别是,setPeriod 采用您在 setTimeUnit 中指定的时间单位,不是毫秒。)
假设您的班次是周一至周五,并且您想改变开始/结束时间(以及,为了更好地衡量,班次大小)。所以我们为这些添加(类型int)模型参数,以及一个名为workers的资源池。
我们使用整数调度来定义资源池容量,因此我们定义一个变量(类型Schedule<Integer>)来保存它(最初是null)。我们还定义了一个动态事件ShiftChange:我们将启动这些事件的“链”,其中每个事件在下一个计划更改时间触发并相应地更改资源池容量(使用图片调色板中的动画时钟来帮助我们可以更清楚地看到正在发生的事情;您也可以使用开发人员面板中显示的时间)。
动态事件需要有一个参数shiftSize(类型int):它需要知道将资源池容量更改为所需的班次大小。
所以Main 看起来像这样:
在Main的启动动作中,我们设置了动态调度和动态事件的第一个实例:
dynamicSchedule = new Schedule<Integer>();
dynamicSchedule.setOwner(this);
dynamicSchedule.setCalendarType(true);
dynamicSchedule.setFirstDayOfWeek(MONDAY);
dynamicSchedule.setTimeUnits(TIME_UNIT_WEEK);
dynamicSchedule.setPeriod(1); // Repeats every 1 time unit (week)
dynamicSchedule.setGlueIntervals(true);
dynamicSchedule.setDefaultValue(0); // Default schedule value (0)
// Add intervals for Mon-Fri (day 1-5) from the given start to the end hour with the given shift size
for (int i = 1; i <=5; i++) {
dynamicSchedule.addInterval(1, // startWeek
i, // startDayOfWeek,
startHour, //startHour
0, // startMinute
0, // startSecond
1, // endWeek
i, // endDayOfWeek
endHour, //endHour
0, // endMinute
0, // endSecond
shiftSize); //value
}
dynamicSchedule.initialize(); // Needed to 'take' the changes
// Can't do the below: can't change a ResourcePool's capacity definition dynamically
//workers.set_capacityDefinitionType(CapacityDefinitionType.CAPACITY_SCHEDULE);
//workers.set_capacitySchedule(dynamicSchedule);
// Instead we create a chain of dynamic events to change the Resource Pool capacity as per the schedule
create_ShiftChange(dynamicSchedule.getTimeoutToNextValue(), dynamicSchedule.getNextValue());
(有关动态事件的详细信息,请参阅此帮助主题:AnyLogic 帮助 > 定义行为。事件和状态图 > 事件 > 动态事件。我还包含注释掉的代码,这些代码对于尝试在资源池中动态设置容量调度。)
动态事件操作代码如下所示(连同一个漂亮的控制台消息,帮助我们检查它是否正常工作):
traceln(format(date()) + ": changing shift size to " + shiftSize);
workers.set_capacity(shiftSize); // Dynamically change the resource pool's capacity
// Set up the next dynamic event in the chain
create_ShiftChange(dynamicSchedule.getTimeoutToNextValue(), dynamicSchedule.getNextValue());
在我的例子中,我使用了开始时间 1、结束时间 3 和班次大小 5 的默认值。如果我在星期一日期启动模型,我会得到以下输出(您可以看到资源池容量发生变化...... ..):
Nov 25, 2019, 1:00:00 AM: changing shift size to 5
Nov 25, 2019, 3:00:00 AM: changing shift size to 0
Nov 26, 2019, 1:00:00 AM: changing shift size to 5
Nov 26, 2019, 3:00:00 AM: changing shift size to 0
Nov 27, 2019, 1:00:00 AM: changing shift size to 5
Nov 27, 2019, 3:00:00 AM: changing shift size to 0
Nov 28, 2019, 1:00:00 AM: changing shift size to 5
Nov 28, 2019, 3:00:00 AM: changing shift size to 0
Nov 29, 2019, 1:00:00 AM: changing shift size to 5
Nov 29, 2019, 3:00:00 AM: changing shift size to 0
Dec 2, 2019, 1:00:00 AM: changing shift size to 5
Dec 2, 2019, 3:00:00 AM: changing shift size to 0
[...]
现在您的优化可以根据需要(通过整数模型参数)改变开始/结束时间和班次大小,根据需要设置最大/最小值。
【讨论】:
当然可以,但您需要在模型开始时(即在 Main 启动时)动态创建计划对象,而不是像目前那样通过拖放对象静态创建。
查看AnyLogic API,了解如何使用代码创建计划。作为其中的一部分,您应该能够根据参数动态定义班次开始和结束时间(优化实验每次都设置不同的参数)。
【讨论】: