第 11 章 Red Hat build of OptaPlanner with Java solvers:一个云平衡快速启动指南
本指南指导您完成创建带有 OptaPlanner 约束(AI)的 Java solvers 的过程。
11.1. Java solvers 入门:云供应商示例 复制链接链接已复制到粘贴板!
例如,使用 Java 代码开发基本红帽构建的 OptaPlanner 可解决器。
假设您的公司拥有多个云计算机,需要在这些计算机上运行多个进程。您必须将每个进程分配到计算机。
必须满足以下硬限制:
每个计算机都必须能够处理进程总和的最低硬件要求:
- CPU 容量 :计算机的 CPU 能力必须至少是分配给该计算机的进程所需的 CPU 电源总和。
- 内存容量 :计算机的 RAM 内存必须至少是分配给该计算机的进程所需的 RAM 内存总和。
- 网络容量 :计算机的网络带宽必须至少是分配给该计算机的进程所需的网络带宽总和。
应优化以下软限制:
每个分配了一个或多个进程的计算机都会产生维护成本,每个计算机会修复它。
- 成本 :最小化维护成本。
此问题是 bin 打包 的形式。在以下简化的示例中,我们使用简单算法为两台限制(CPU 和 RAM)为两台计算机分配四个进程:
此处使用的简单算法是第一个 Fit Decreasing 算法,它会首先 分配较大的进程,并将较小的进程分配给剩余的空间。看不到,它不是最佳的,因为它没有足够的空间来分配黄色进程 D
。
OptaPlanner 使用额外的智能算法找到更最佳的解决方案。它还扩展:在数据(更多进程、更多计算机)和限制(更多硬件要求、其他限制)中。
以下概述适用于本例,以及 第 4.7 节 “机器重新分配(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 |
11.1.1. 域模型设计 复制链接链接已复制到粘贴板!
使用 域模型 有助于确定哪些类正在规划实体及其属性计划变量。它还有助于简化约束、提高性能并提高未来需求的灵活性。
11.1.1.1. 设计域模型 复制链接链接已复制到粘贴板!
要创建域模型,请定义代表问题的输入数据的所有对象。在本例中,对象是进程和计算机。
域模型中的单独的对象必须代表一组问题,其中包含输入数据和解决方案。在本例中,此对象包含计算机列表和进程列表。每个进程分配到一个计算机;计算机之间的进程分布是解决方案。
流程
- 绘制域模型的类图。
- 将其规范化以删除重复的数据。
为每个类编写 一些示例实例。示例实例是与规划目的相关的实体属性。
计算机
:代表具有特定硬件和维护成本的计算机。在本例中,
计算机
类的示例实例为cpuPower
、内存
、networkBandwidth
,成本
为。进程
:代表具有需求的进程。需要由 Planner 分配给计算机
。Process
实例示例是必需的CpuPower
、RequireMemory
和requiredNetworkBandwidth
。CloudBalance
:代表计算机之间进程分布。包含特定数据集
和流程。的每个
计算机对于代表完整数据集和解决方案的对象,必须存在包含 分数 的示例实例。OptaPlanner 可以计算和比较不同解决方案的分数;具有最高分数的解决方案是最佳解决方案。因此,
CloudBalance
的示例实例分数
为。
在规划过程中确定哪些关系(或字段)变化:
规划实体 : OptaPlanner 的类(或类)在技术期间可能会改变。在本例中,它是类
进程
,因为我们可以将进程移到不同的计算机。- 代表 OptaPlanner 无法更改的输入数据的类被称为 问题事实。
-
规划变量 :计划实体类的属性(或属性),这些类在技术期间发生了变化。在本例中,这是类
进程
的属性计算机
。 -
规划解决方案 :代表问题解决方案的类。此类必须代表完整的数据集,并包含所有规划实体。在本例中,是类
CloudBalance
。
在以下 UML 类图中,OptaPlanner 概念已被注解:
您可以在 examples/sources/src/main/java/org/optaplanner/examples/cloudbalancing/domain
目录中找到本例的类定义。
11.1.1.2. 计算机 类 复制链接链接已复制到粘贴板!
Computer
类是一种 Java 对象,它存储数据,有时被称为 POJO (旧 Java 对象)。通常,您将拥有许多带有输入数据的类。
例 11.1. CloudComputer.java
11.1.1.3. 进程 类 复制链接链接已复制到粘贴板!
Process
类是参与期间修改的类。
我们需要告诉 OptaPlanner,它可以更改属性 计算机
。为此,可使用 @PlanningEntity
注解类,并使用 @PlanningVariable
注解 getComputer ()
getter。
课程,属性 计算机还需要
设置者,因此 OptaPlanner 可在公司期间更改它。
例 11.2. CloudProcess.java
OptaPlanner 需要知道它可以选择哪些值分配给属性 计算机
。这些值从规划解决方案上的方法 CloudBalance.getComputerList ()
检索,后者返回当前数据集中的所有计算机的列表。
CloudProcess.getComputer ()
上的 @PlanningVariable
'svalueRangeProviderRefs
参数需要与 CloudBalance.getComputerList ()
上的 @ValueRangeProvider
'sid
匹配。
您还可以在字段而不是 getters 上使用注解。
11.1.1.4. CloudBalance 类 复制链接链接已复制到粘贴板!
CloudBalance
类具有 @PlanningSolution 注释。
此类包含所有计算机和进程的列表。它代表了规划问题,以及(如果被初始化)规划解决方案。
CloudBalance
类有以下关键属性:
它包含 OptaPlanner 可能会更改的进程集合。我们使用
@PlanningEntityCollectionProperty
注解 gettergetProcessList ()
,以便 OptaPlanner 能够检索它可以更改的进程。要保存解决方案,OptaPlanner 使用更改的进程列表初始化类的新实例。-
它还有一个
@PlanningScore
注解的属性分数
,这是该解决方案处于当前状态的分数
。OptaPlanner 会在计算解决方案实例的Score
时自动更新它,因此此属性需要 setter。 -
特别是使用 Drools 进行分数计算,属性
computerList
需要用@ProblemFactCollectionProperty
注解,以便 OptaPlanner 能够检索计算机列表(虚拟化事实)并使其提供给决策引擎。
-
它还有一个
例 11.3. CloudBalance.java
11.1.2. 运行 Cloud balancing Hello World 应用程序 复制链接链接已复制到粘贴板!
您可以运行示例 Hello World 应用程序来演示解析器。
流程
- 下载并配置您首选的 IDE 中的示例。有关在 IDE 中下载和配置示例的步骤,请参考 第 5.2 节 “在 IDE 中运行红帽构建的 OptaPlanner 示例(IntelliJ、Ecli 或 Netbeans)”。
使用以下主类创建运行配置:
org.optaplanner.examples.cloudbalancing.app.CloudBalancingHelloWorld
默认情况下,Cloud Balancing Hello World 配置为运行 120 秒。
结果
应用程序执行以下代码:
例 11.4. CloudBalancingHelloWorld.java
代码示例执行以下操作:
根据
解析器
配置构建 Solver (本例中为 XML 文件cloudBalancingSolverConfig.xml
)。构建
Solver
是此流程中最复杂的部分。如需了解更多详细信息,请参阅 第 11.1.3 节 “solver 配置”。SolverFactory<CloudBalance> solverFactory = SolverFactory.createFromXmlResource( "org/optaplanner/examples/cloudbalancing/solver/cloudBalancingSolverConfig.xml"); Solver solver<CloudBalance> = solverFactory.buildSolver();
SolverFactory<CloudBalance> solverFactory = SolverFactory.createFromXmlResource( "org/optaplanner/examples/cloudbalancing/solver/cloudBalancingSolverConfig.xml"); Solver solver<CloudBalance> = solverFactory.buildSolver();
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 加载问题。
CloudBalancingGenerator
生成一个随机问题:您将替换为加载实际问题的类,例如从数据库中。CloudBalance unsolvedCloudBalance = new CloudBalancingGenerator().createCloudBalance(400, 1200);
CloudBalance unsolvedCloudBalance = new CloudBalancingGenerator().createCloudBalance(400, 1200);
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 解决问题。
CloudBalance solvedCloudBalance = solver.solve(unsolvedCloudBalance);
CloudBalance solvedCloudBalance = solver.solve(unsolvedCloudBalance);
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 显示结果。
System.out.println("\nSolved cloudBalance with 400 computers and 1200 processes:\n" + toDisplayString(solvedCloudBalance));
System.out.println("\nSolved cloudBalance with 400 computers and 1200 processes:\n" + toDisplayString(solvedCloudBalance));
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
11.1.3. solver 配置 复制链接链接已复制到粘贴板!
solver 配置文件决定了参与过程的工作方式;它被视为代码的一部分。该文件命名为 example /sources/src/main/resources/org/optaplanner/examples/cloudbalancing/solver/cloudBalancingSolverConfig.xml
。
例 11.5. cloudBalancingSolverConfig.xml
这个 resolver 配置由三个部分组成:
域模型配置 :OptaPlanner 可以更改什么?
我们需要让 OptaPlanner 了解我们的域类。在此配置中,它将自动扫描类路径中的所有类(对于
@PlanningEntity
或@PlanningSolution
注解):<scanAnnotatedClasses/>
<scanAnnotatedClasses/>
Copy to Clipboard Copied! Toggle word wrap Toggle overflow score configuration:OptaPlanner 应优化规划变量?我们的目标是什么?
由于我们存在硬和软限制,因此我们使用一个
HardSoftScore
。但我们需要根据我们的业务需求告知 OptaPlanner 如何计算分数。此外,我们将查看两种替代方法来计算分数:使用基本的 Java 实施和使用 droolL。<scoreDirectorFactory> <easyScoreCalculatorClass>org.optaplanner.examples.cloudbalancing.optional.score.CloudBalancingEasyScoreCalculator</easyScoreCalculatorClass> <!--<scoreDrl>org/optaplanner/examples/cloudbalancing/solver/cloudBalancingScoreRules.drl</scoreDrl>--> </scoreDirectorFactory>
<scoreDirectorFactory> <easyScoreCalculatorClass>org.optaplanner.examples.cloudbalancing.optional.score.CloudBalancingEasyScoreCalculator</easyScoreCalculatorClass> <!--<scoreDrl>org/optaplanner/examples/cloudbalancing/solver/cloudBalancingScoreRules.drl</scoreDrl>--> </scoreDirectorFactory>
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 优化算法配置 :OptaPlanner 应如何优化它?在这种情况下,我们使用默认的优化算法(因为没有配置显式优化算法) 30 秒:
<termination> <secondsSpentLimit>30</secondsSpentLimit> </termination>
<termination> <secondsSpentLimit>30</secondsSpentLimit> </termination>
Copy to Clipboard Copied! Toggle word wrap Toggle overflow OptaPlanner 应该会得到很好的结果(如果使用实时规划功能,则结果少于 15 毫秒),但其结果越好,则结果越好。高级用例可能会使用与硬时间限制不同的终止标准。
默认算法将容易使用人工规划器和大多数内部实施。您可以使用高级基准测试程序功能来更好地获得更好的结果。
11.1.4. 分数配置 复制链接链接已复制到粘贴板!
OptaPlanner 将搜索具有最高 分数的解决方案
。这个示例使用
Hard SoftScore
,这意味着 OptaPlanner 将查找没有硬约束(需要满足硬件要求)的解决方案,并尽量少的软约束问题(降低维护成本)。
您可以使用普通 Java、Jrools 或 OptaPlanner ConstraintStream API 来定义限制。有关 ConstraintStream API 的详情,请参考 第 10.3 节 “定义约束并计算分数”。
11.1.4.1. 使用 Java 配置分数计算 复制链接链接已复制到粘贴板!
定义分数功能的一种方法是以普通 Java 实施接口 EasyScoreCalculator
。
流程
在 Cloud
BalancingSolverConfig.xml
文件中,添加或取消注释设置:<scoreDirectorFactory> <easyScoreCalculatorClass>org.optaplanner.examples.cloudbalancing.optional.score.CloudBalancingEasyScoreCalculator</easyScoreCalculatorClass> </scoreDirectorFactory>
<scoreDirectorFactory> <easyScoreCalculatorClass>org.optaplanner.examples.cloudbalancing.optional.score.CloudBalancingEasyScoreCalculator</easyScoreCalculatorClass> </scoreDirectorFactory>
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 实施 compute
Score (Solution)
方法,以返回Hard SoftScore
实例。例 11.6. CloudBalancingEasyScoreCalculator.java
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
即使我们优化了上述代码以使用 Map
s 来迭代 processList
一次,它仍然会很慢,因为它不会进行增量分数计算。
要修复这个问题,可以使用增量 Java 分数计算或 drools 分数计算。本指南中不涵盖增量 Java 分数计算。
11.1.4.2. 使用 drools 配置分数计算 复制链接链接已复制到粘贴板!
您可以使用 dols 规则语言(DRL)来定义限制。dols 分数计算使用增量计算,每个分数约束都会写成一个或多个分数规则。
通过使用决策引擎进行分数计算,您可以与其他 dols 技术集成,如分区表(基于 XLS 或 Web)、Business Central 和其他支持的功能。
流程
在 classpath 中添加
scoreDrl
资源,以使用决策引擎作为分数功能。在 CloudBalancingSolverConfig.xml
文件中,添加或取消注释设置:<scoreDirectorFactory> <scoreDrl>org/optaplanner/examples/cloudbalancing/solver/cloudBalancingScoreRules.drl</scoreDrl> </scoreDirectorFactory>
<scoreDirectorFactory> <scoreDrl>org/optaplanner/examples/cloudbalancing/solver/cloudBalancingScoreRules.drl</scoreDrl> </scoreDirectorFactory>
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 创建硬限制。这些限制可确保所有计算机有足够的 CPU、RAM 和网络带宽来支持其所有进程:
例 11.7. cloudBalancingScoreRules.drl - Hard Constraints
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 创建软约束。此约束可最小化维护成本。只有在满足硬限制时才会应用它:
例 11.8. cloudBalancingScoreRules.drl - Soft Constraints
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
11.1.5. 进一步开发问题 复制链接链接已复制到粘贴板!
现在,本示例可以正常工作,您可以尝试进一步开发它。例如,您可以增强域模型并添加额外的限制,例如:
-
每个进程都
属于一个服务
。计算机可能会崩溃,因此运行同一服务的进程应该(或必须)分配给不同的计算机。 -
每个计算机
都位于一个构建中
。构建可能会刻录,因此应(或必须)将同一服务的进程分配给不同构建中的计算机。