首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OptaPlanner 7.32.0.Final版本彩蛋 - SolverManager之异步求解

OptaPlanner 7.32.0.Final版本彩蛋 - SolverManager之异步求解

原创
作者头像
Kent Zhang
修改2020-02-26 08:50:58
7630
修改2020-02-26 08:50:58
举报

因为工作和其它原因,很长一段时间没有出新的、关于OptaPlanner的文章了,但工余时间并没有停止对该引擎的学习。与此同时Geoffrey大神带领的KIE项目团队并没有闲下来,尽管在工业可用性、易用性和使用门槛方面,OptaPlanner相对传统的求解器已经做得相当出色;特别是在规划过程交互、和各种操作接口方面,更是目前最为容易使用的规划求解器。

以第7版一系列子版本中,OptaPlanner很多子版只作了细微的更新,如优化规划性能,改善Business Center集成水平等。而在作为OptaPlanner直接使用者的我们而言,第7版的所有子版本中,目前本人认为最大最有意义的更新有2个。一个是7.9.0版本提供内了置的多线程规划,从而实现了规划过程中的多CPU同时对同一问题进行运算,大大地发挥了多CPU(核)服务器的并行运算能力。而今天本文需要详解的新增接口SolverManager则是在系统集成方面的另一次重大创新。SolverManager接口在7.32.0版本中发布。

规划服务的常见场景与异步服务

OptaPlanner的核心是一个运筹优化求解器,可以对各领域的规划问题(NPC, NP-Hard问题)进行规划求解,寻找出问题的近似最优解。OptaPlanner规划组件提供了相当完善的求解运算功能。但在实际的规划系统设计中,除了设计相应的规划模型,还需要考虑规划程序部署问题,便于与现有系统集成。这类部署问题并非OptaPlanner求解器自身的功能焦点。因此,对于我们软件开发、工程人员而言,还需要设计好相应的架构系统,才能实现规划程序与现有信息系统之间良好数据交互。

通常情况下规划运算需要使用大量的运算资源,也即CPU运算能力。我们会把基于OptaPlanner的规划程序部署成独立的规划服务,以接口方式与外界系统进行数据通讯。部署成独立的服务除了有利于降低系统模块间低耦合外,另一个重要原因是有利于运算资源的扩展。当问题规划增大时,程序所需的CPU运算能力也会大副提升;独立存在的规划服务更有利于硬件资源的更新。当然,需要在Client端进行即时规划的场景(例如手机导航软件)除外。

因为规划服务大多数情况下,需要一定的运算周期才能得到可行、且相对最优方案。若根据上述的场景需求,在常见的项目中,可以把规划程序做成一个轻量级的Jar包,再过Web和应用服务器,以Web服务的方式对外提供服务。例如使用Spring Boot进行封装,对外提供Web API服务。通过使Spring Boot的Controller与规划程序包在进程上相互独立,从而实现规划服务的异步性。当然也可以通过在Spring Boot程序中通过多线程方式实现异常调用的特性。不同的实现方法视实际需要而定。

SolverManager特性解决异步问题

对于上述场景,OptaPlanner是否可提供Out-Of-The-Box的解决方案呢?在7.32.0.Final版本之前,求解器规划问题时的接口方法是Solver.solve(),这个方法是同步的,需要规划完成后才能返回。若需要实现异步功能,就需要自己想办法实现了,例如上面提到的将服务进程与规划进程相互独立,或使用不同的线程来响应服务和启动规划,实现起来对软件架构设计需要有一定的经验才能做得相对完善。很幸运,在7.32.0.Final版本中,终于从OptaPlanner内置功能上实现了此特性,这个就是SolverManager。SolverManager是7.32.0.Final版本提供的新接口,通过此接口我们可以在调用规划核心程序进行问题求解时,调用线程即时返回,从而实现调用线程与规划线程异步执行。具体访求是:通过SolverManager.solve()方法可以启动一个异步规划方法,调用方可以即时返回,通过轮询的方式调用SolverManager的其它方法来查询规划状态(SolverManger.getSolverStatus)并获取结果(SoverJob.getFinalBestSolution)。SolverManager的基本用法如下:

CloudBalance problem1 = ...;
UUID problemId = UUID.randomUUID();
// Returns immediately
SolverJob<CloudBalance, UUID> solverJob = solverManager.solve(problemId, problem1);
...
CloudBalance solution1;
try {
    // Returns only after solving terminates
    solution1 = solverJob.getFinalBestSolution();
} catch (InterruptedException | ExecutionException e) {
    throw ...;
}

可以看出,使用SolverManager 对一个问题进行求解时,与Solver对象的solve方法有以下区别:

  1. 异步执行,当solve方法被调用后,方法会马上返回,而不待引擎运行结果。调用者需要通过轮询或回调方法(bestSolutionChanged事件)获取运行结果。
  2. 每个问题对应一个ID,因为SolverManager会启动线程池同一时间对多个问题进行求解,因此每个问题需要有一个唯一的标识做识别,在下一篇文章中的SolverManger批量求解中将会详解。

因此,在7.32.0.Final版本中,SolverManager的出现,将会在进行求解服务的设计过程中,大大简化引擎与服务的设计复杂度。希望在未来的应用过让OptaPlanner在工业场景的可能性上更胜一筹。

关于SolverManager接口的详细介绍见以下使用说明:

https://docs.optaplanner.org/7.33.0.Final/optaplanner-docs/html_single/index.html#solverManager​docs.optaplanner.org

原创不易,如果觉得文章对你有帮助,欢迎点赞、评论。文章有疏漏之处,欢迎批评指正。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 规划服务的常见场景与异步服务
  • SolverManager特性解决异步问题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档