第 10 章 Red Hat build of OptaPlanner on the Red Hat build of Quarkus platform: a IANA timetable quick Start guide
本指南指导您使用红帽构建的 OptaPlanner 约束创建 Red Hat build of Quarkus 应用程序的过程。您将构建 REST 应用程序,该应用程序针对领导和专业者进行了优化。
您的服务将通过 AI 遵循以下硬和软 调度限制,自动将附件实例分配给 Timeslot 和 Room 实例:
- 空间最多可以同时有一个小时间。
- 一个架构师可以同时参与一个小时间。
- 每天最多可同时参与一个小时间。
- 交互式人员更喜欢在单个房间参与。
- 指导人员更喜欢参与较少的活动,并排解少量间的差距。
mathematly 认为是 NP 硬性问题。这意味着难以扩展。只需将所有可能的组合与括号一起进行迭代,可以在非平量数据集中使用数百万年,即使在超级计算器上也是如此。AI 的约束程序(如红帽构建的 OptaPlanner)具有以合理的时间提供接近优化解决方案的高级算法。认为是合理的时间,这取决于您的问题的目标。
先决条件
- 已安装 OpenJDK 11 或更高版本。Red Hat build of Open JDK 位于红帽客户门户网站中的 Software Downloads 页面中(需要登录)。
- 已安装 Apache Maven 3.8 或更高版本。Maven 可从 Apache Maven 项目网站 获得。
- 提供了 IDE,如 IntelliJ IDEA、VSCode 或 Eclipse。
- 红帽构建的 OptaPlanner Red Hat build of Quarkus 项目可用。有关创建 Red Hat Build of OptaPlanner Red Hat build of Quarkus 项目的说明,请参阅 红帽构建的 OptaPlanner 和 Quarkus 部分中的 " OptaPlanner 和 Quarkus"。
10.1. 对域对象建模 复制链接链接已复制到粘贴板!
红帽构建的 OptaPlanner 时间项目的目标是将每项分配给一个时间插槽和房间。要做到这一点,添加三个类: Timeslot、init on 和 Room,如下图所示:
timeslot
Timeslot 类代表当减少活动为过期的时间间隔时,例如,Monday 10:30 - 11:30 或 Tuesday 13:30 - 14:30。在这个示例中,所有时间段都有相同的持续时间,在 lunch 或其他中断过程中没有时间插槽。
一个时间插槽没有日期,因为每周计划只重复一次。不需要 持续规划。timeslot 被称为 问题事实,因为公司不会更改 Timeslot 实例。此类类不需要任何特定于 OptaPlanner 的注解。
房间
Room 类代表更小活动的位置,例如 Room A 或 Room B。在本例中,所有房间都没有容量限制,它们可以容纳所有定义。
空间 实例在竞争过程中不会改变,因此 Room 也是 问题事实。
lesson
在小时间中,由周一类代表,受一组参与者代表的规定,例如,A.Turing for 9th rating 或 Chemistry by M.Curie 代表第 10 等级。如果一个主题是按同一站组相同的每周的多次,则有多个仅可通过 id 区分的实例。例如,第 9 等级每周有六个数学。
在 OptaPlanner 期间,OptaPlanner 会更改周一类的 timeslot 和 room 字段,以将每个小时间分配给一个时间插槽和房间。因为 OptaPlanner 更改这些字段,因此 Apple on 是一个 规划实体 :
上图中的大部分字段都包含输入数据,但 orange 字段除外。在输入数据中取消分配较少的 timeslot 和 room 字段,并在输出数据中分配(而非 )。OptaPlanner 在参与过程中会更改这些字段。此类字段称为 规划变量。为了使 OptaPlanner 能够识别它们,nulltimeslot 和 room 字段都需要 @PlanningVariable 注释。它们包含类属性需要 @PlanningEntity 注释。
流程
创建
src/main/java/com/example/domain/Timeslot.java类:package com.example.domain; import java.time.DayOfWeek; import java.time.LocalTime; public class Timeslot { private DayOfWeek dayOfWeek; private LocalTime startTime; private LocalTime endTime; private Timeslot() { } public Timeslot(DayOfWeek dayOfWeek, LocalTime startTime, LocalTime endTime) { this.dayOfWeek = dayOfWeek; this.startTime = startTime; this.endTime = endTime; } @Override public String toString() { return dayOfWeek + " " + startTime.toString(); } // ******************************** // Getters and setters // ******************************** public DayOfWeek getDayOfWeek() { return dayOfWeek; } public LocalTime getStartTime() { return startTime; } public LocalTime getEndTime() { return endTime; } }请注意,
toString ()方法保留输出短,因此更易于阅读 OptaPlanner 的DEBUG或TRACE日志,如稍后所示。创建
src/main/java/com/example/domain/Room.java类:package com.example.domain; public class Room { private String name; private Room() { } public Room(String name) { this.name = name; } @Override public String toString() { return name; } // ******************************** // Getters and setters // ******************************** public String getName() { return name; } }创建
src/main/java/com/example/domain/Lesson.java类:package com.example.domain; import org.optaplanner.core.api.domain.entity.PlanningEntity; import org.optaplanner.core.api.domain.variable.PlanningVariable; @PlanningEntity public class Lesson { private Long id; private String subject; private String teacher; private String studentGroup; @PlanningVariable(valueRangeProviderRefs = "timeslotRange") private Timeslot timeslot; @PlanningVariable(valueRangeProviderRefs = "roomRange") private Room room; private Lesson() { } public Lesson(Long id, String subject, String teacher, String studentGroup) { this.id = id; this.subject = subject; this.teacher = teacher; this.studentGroup = studentGroup; } @Override public String toString() { return subject + "(" + id + ")"; } // ******************************** // Getters and setters // ******************************** public Long getId() { return id; } public String getSubject() { return subject; } public String getTeacher() { return teacher; } public String getStudentGroup() { return studentGroup; } public Timeslot getTimeslot() { return timeslot; } public void setTimeslot(Timeslot timeslot) { this.timeslot = timeslot; } public Room getRoom() { return room; } public void setRoom(Room room) { this.room = room; } }bring
on类有一个@PlanningEntity注释,因此 OptaPlanner 知道该类在周五期间发生了变化,因为它包含一个或多个规划变量。timeslot字段有一个@PlanningVariable注释,因此 OptaPlanner 知道它可以更改其值。要查找分配给此字段的潜在Timeslot实例,OptaPlanner 使用valueRangeProviderRefs属性连接到提供List<Timeslot> 的值范围供应商。有关值范围供应商的详情,请查看 第 10.3 节 “在计划解决方案中收集域对象”。由于同样原因,
room字段也有一个@PlanningVariable注释。