本指南指导您完成创建带有 OptaPlanner 约束智能(AI)的红帽构建的 Quarkus 应用程序的过程。您将构建 REST 应用程序,该应用程序针对领导和专业者进行了优化。
OptaPlanner timetable 项目的目标是将每个小项分配到一个时间插槽和房间。要做到这一点,添加三个类: Timeslot
、init
on 和 Room,如下图所示:
一个时间插槽没有日期,因为每周计划只重复一次。不需要 持续规划。timeslot 被称为 问题事实,因为公司不会更改 Timeslot
实例。此类类不需要任何特定于 OptaPlanner 的注解。
空间
实例在竞争过程中不会改变,因此 Room
也是 问题事实。
在 OptaPlanner 期间,OptaPlanner 会更改周一类的 timeslot
和 room
字段,以将每个小时间分配给一个时间插槽和房间。
因为 OptaPlanner 更改这些字段,因此 Apple
on 是一个 规划实体 :
上图中的大部分字段都包含输入数据,但 orange 字段除外。在输入数据中取消分配较少的 timeslot
和 room
字段,并在输出数据中分配(而非 null
)。OptaPlanner 在参与过程中会更改这些字段。此类字段称为 规划变量。为了使 OptaPlanner 能够识别它们,timeslot
和 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;
}
}
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;
}
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
请注意,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;
}
}
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;
}
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
创建 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;
}
}
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;
}
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
bring on
类有一个 @PlanningEntity
注释,因此 OptaPlanner 知道该类在周五期间发生了变化,因为它包含一个或多个规划变量。
timeslot
字段有一个 @PlanningVariable
注释,因此 OptaPlanner 知道它可以更改其值。要查找分配给此字段的潜在 Timeslot
实例,OptaPlanner 使用 valueRangeProviderRefs
属性连接到提供 List<Timeslot>
; 的值范围供应商。有关值范围供应商的详情,请查看 第 9.3 节 “在计划解决方案中收集域对象”。
由于同样原因,room
字段也有一个 @PlanningVariable
注释。