第 29 章 Java solvers 入门:云供应商示例
示例演示了使用 Java 代码的基本红帽业务优化器的开发。
假设您的公司拥有多个云计算机,需要在这些计算机上运行多个进程。您必须将每个进程分配到计算机。
必须满足以下硬限制:
每个计算机都必须能够处理进程总和的最低硬件要求:
- CPU 容量 :计算机的 CPU 能力必须至少是分配给该计算机的进程所需的 CPU 电源总和。
- 内存容量 :计算机的 RAM 内存必须至少是分配给该计算机的进程所需的 RAM 内存总和。
- 网络容量 :计算机的网络带宽必须至少是分配给该计算机的进程所需的网络带宽总和。
应优化以下软限制:
每个分配了一个或多个进程的计算机都会产生维护成本(每计算机可修复)。
- 成本 :最小化维护成本。
此问题是 bin 打包 的形式。在以下简化的示例中,我们使用简单算法为两台限制(CPU 和 RAM)为两台计算机分配四个进程:
此处使用的简单算法是第一个 Fit Decreasing 算法,它会首先 分配较大的进程,并将较小的进程分配给剩余的空间。如看到的那样,这不是最佳选择,因为它没有足够的空间来分配黄色进程 D。
商业优化器通过使用其他智能算法找到更最佳的解决方案。它还扩展:在数据(更多进程、更多计算机)和限制(更多硬件要求、其他限制)中。
以下概述适用于本例,以及 第 30.10 节 “机器重新分配(Google ROADEF 2012)” 中描述的更多限制的高级实现:
| 问题大小 | 计算机 | Process | 搜索空间 |
|---|---|---|---|
| 2computers-6processes | 2 | 6 | 64 |
| 3computers-9processes | 3 | 9 | 10^4 |
| 4computers-012processes | 4 | 12 | 10^7 |
| 100computers-300processes | 100 | 300 | 10^600 |
| 200computers-600processes | 200 | 600 | 10^1380 |
| 400computers-1200processes | 400 | 1200 | 10^3122 |
| 800computers-2400processes | 800 | 2400 | 10^6967 |
29.1. 域模型设计 复制链接链接已复制到粘贴板!
使用 域模型 有助于确定哪些类正在规划实体及其属性计划变量。它还有助于简化约束、提高性能并提高未来需求的灵活性。
29.1.1. 设计域模型 复制链接链接已复制到粘贴板!
要创建域模型,请定义代表问题的输入数据的所有对象。在本例中,对象是进程和计算机。
域模型中的单独的对象必须代表一组问题,其中包含输入数据和解决方案。在本例中,此对象包含计算机列表和进程列表。每个进程分配到一个计算机;计算机之间的进程分布是解决方案。
流程
- 绘制域模型的类图。
- 将其规范化以删除重复的数据。
为每个类编写 一些示例实例。示例实例是与规划目的相关的实体属性。
计算机:代表具有特定硬件和维护成本的计算机。在本例中,
计算机类的示例实例为cpuPower、内存、networkBandwidth,成本为。进程:代表具有需求的进程。需要由 Planner 分配给计算机。Process实例示例是必需的CpuPower、RequireMemory和requiredNetworkBandwidth。CloudBalance:代表计算机之间进程分布。包含特定数据集和流程。的每个计算机对于代表完整数据集和解决方案的对象,必须存在包含 分数 的示例实例。企业优化器可以计算和比较不同解决方案的分数;解决方案与最高分数是最佳解决方案。因此,
CloudBalance的示例实例分数为。
在规划过程中确定哪些关系(或字段)变化:
规划实体 :业务优化器在公司期间可能会改变的类(或类)。在本例中,它是类
进程,因为我们可以将进程移到不同的计算机。- 代表业务优化器无法更改的输入数据的类称为 问题事实。
-
规划变量 :计划实体类的属性(或属性),这些类在技术期间发生了变化。在本例中,这是类
进程的属性计算机。 -
规划解决方案 :代表问题解决方案的类。此类必须代表完整的数据集,并包含所有规划实体。在本例中,是类
CloudBalance。
在以下 UML 类图中,vmim Optimizer 概念已被注解:
您可以在 examples/sources/src/main/java/org/optaplanner/examples/cloudbalancing/domain 目录中找到本例的类定义。
29.1.2. 计算机 类 复制链接链接已复制到粘贴板!
Computer 类是一种 Java 对象,它存储数据,有时被称为 POJO (旧 Java 对象)。通常,您将拥有许多带有输入数据的类。
例 29.1. CloudComputer.java
public class CloudComputer ... {
private int cpuPower;
private int memory;
private int networkBandwidth;
private int cost;
... // getters
}
29.1.3. 进程 类 复制链接链接已复制到粘贴板!
Process 类是参与期间修改的类。
我们需要告诉 Business Optimizer,它可以更改属性 计算机。为此,可使用 @PlanningEntity 注解类,并使用 @PlanningVariable 注解 getComputer () getter。
课程,属性 计算机还需要 设置者,因此业务优化器可以在技术期间更改它。
例 29.2. CloudProcess.java
@PlanningEntity(...)
public class CloudProcess ... {
private int requiredCpuPower;
private int requiredMemory;
private int requiredNetworkBandwidth;
private CloudComputer computer;
... // getters
@PlanningVariable(valueRangeProviderRefs = {"computerRange"})
public CloudComputer getComputer() {
return computer;
}
public void setComputer(CloudComputer computer) {
computer = computer;
}
// ************************************************************************
// Complex methods
// ************************************************************************
...
}
Business Optimizer 需要知道它可以选择将哪些值分配给属性 计算机。这些值从规划解决方案上的方法 CloudBalance.getComputerList () 检索,后者返回当前数据集中的所有计算机的列表。
CloudProcess.getComputer () 上的 @PlanningVariable 'svalueRangeProviderRefs 参数需要与 CloudBalance.getComputerList () 上的 @ValueRangeProvider 'sid 匹配。
您还可以在字段而不是 getters 上使用注解。
29.1.4. CloudBalance 类 复制链接链接已复制到粘贴板!
CloudBalance 类具有 @PlanningSolution 注释。
此类包含所有计算机和进程的列表。它代表了规划问题,以及(如果被初始化)规划解决方案。
CloudBalance 类有以下关键属性:
它包含一组业务优化器可以更改的进程集合。我们使用
@PlanningEntityCollectionProperty注解 gettergetProcessList (),以便 Business Optimizer 能够检索它可以更改的进程。为保存解决方案,BUSINESS Optimizer 使用更改的进程列表初始化类的新实例。-
它还有一个
@PlanningScore注解的属性分数,这是该解决方案处于当前状态的分数。当为解决方案实例计算Score时,业务优化器会自动更新它,因此此属性需要一个 setter。 -
特别是使用 Drools 进行分数计算,属性
computerList需要用@ProblemFactCollectionProperty注解,以便业务优化器可以检索计算机(虚拟化事实)列表,并使其可供决策引擎使用。
-
它还有一个
例 29.3. CloudBalance.java
@PlanningSolution
public class CloudBalance ... {
private List<CloudComputer> computerList;
private List<CloudProcess> processList;
private HardSoftScore score;
@ValueRangeProvider(id = "computerRange")
@ProblemFactCollectionProperty
public List<CloudComputer> getComputerList() {
return computerList;
}
@PlanningEntityCollectionProperty
public List<CloudProcess> getProcessList() {
return processList;
}
@PlanningScore
public HardSoftScore getScore() {
return score;
}
public void setScore(HardSoftScore score) {
this.score = score;
}
...
}