LOCAL SOLVER数学求解器两大新功能-JSON模块 、Modeler API
随着LocalSolver 10.0的发布,我们想要推进的一个关键特性就是将LSP程序集成到完全生产性的应用程序中。JSON模块和Modeler API都是为了方便LSP程序对内对外的数据处理而引入的。在本文中,我们将通过一些小示例来展示这些特性。如果您不熟悉LSP,我们建议您查看LOCAL SOLVER的语言参考。
让我们以示例教程中的背包LSP程序为例,了解一下这些特性是如何帮助我们的。
// 背包问题的LSP模型
function model() {
// 0-1 decisions
x[i in 0..nbItems-1] <- bool();
// weight constraint
knapsackWeight <- sum[i in 0..nbItems-1](weights[i] * x[i]);
constraint knapsackWeight <= knapsackBound;
// maximize value
knapsackValue <- sum[i in 0..nbItems-1](prices[i] * x[i]);
maximize knapsackValue;
}
JSON模块
新添加的JSON模块允许将JSON数据解析为LSP值。它可以方便地读取某个问题的输入数据,然后导出其解决方案。看看我们的程序,我们可以看到model函数需要初始化一些变量才能执行。具体来说,需要设置变量nbItems、weights、prices和knapsackBound。我们可以采用以下形式的JSON数据文件:
{
"nbItems": 5,
"weights": [5, 3, 2, 1, 3],
"prices": [10, 9, 5, 6, 3],
"knapsackBound": 10
}
由于使用了parse方法,该文件可以转换为LSP值。下面的代码将正确初始化model函数所需的变量。
use json;
function input() {
data = json.parse("data.json");
nbItems = data["nbItems"];
weights = data["weights"];
prices = data["prices"];
knapsackBound = data["knapsackBound"];
}
问题解决后,可以使用dump方法导出解决方案数据。
function output() {
out = {
"value": knapsackValue.value,
"decisions": map[i in 0..nbItems-1](x[i].value)
};
json.dump(out, "out.json");
}
有关模块和解析选项的更多信息,请查看参考引用.
Modeler API(建模器应用程序接口)
建模器API允许您与虚拟机交互,从而为LSP语言提供了动力:使用LSP编写的原型开发人员现在能够完全将它们集成到Python、java、C++和C++环境中。例如,使用这些新绑定,您可以:
将现有LSP文件加载到模块中并执行它们。
与模块中包含的函数和变量交互。
将用您选择的语言开发的方法作为LSP函数公开。
因此,现在可以在Python环境中集成背包问题LSP程序。首先,我们需要实例化API的主类LSPModeler,它将使我们能够与模块(modules)、映射(maps)和函数(functions)进行交互。鉴于上述模型在一个knapsack.lsp程序中,我们可以使用以下代码片段将模块加载到modeler中:
from localsolver.modeler import *
with LSPModeler() as modeler:
knapsack_module = modeler.load_module("knapsack.lsp")
这使得包含在knapsack.lsp中的所有变量和函数可以通过背包模块对象knapsack_module获得(请参阅LSPModule参考)。它还使我们能够执行这个模块,这意味着运行model函数并启动解析过程。如前所述,我们需要预先初始化几个变量。
为整型变量如 nbItems and knapsackBound 设定数值的话,我们可以做如下操作:
# 声名一个变量名为`nbItems`并将数值设为5.
knapsack_module["nbItems"] = 5
接下来,我们需要输入重量和价格。它们都是数字的集合,所以它们应该是LSPMap类型的对象
# `weights_data` 是我们需要输入的数据.
weights_data = [5, 4, 6, 3, 1]
# `weights_map`是在LSP程序中存储数值的LSPMap对象.
weights_map = modeler.create_map()
for value in weights_data:
weights_map.append(value)
knapsack_module["weights"] = weights_map
设置好所有变量后,我们可以通过调用knapsack_module.run()执行模块. 这个方法复制了通过从命令行执行模块得到的行为,我们可以传递lsTimeLimit之类的参数。
knapsack_module.run("lsTimeLimit=10")
一旦解析过程完成,我们就可以提取解决方案数据:
# 首先,我们提取在LSP程序中创建的LSExpression
obj_expression = knapsack_module["knapsackValue"]
# 然后,我们可以使用常规的LocalSolver Python API提取目标值.
obj_value = obj_expression.value
使用建模器API,您可以从LSP中建模的简易性获益,同时仍然能够在Python、java、C++、C++应用程序中集成模型。
将所有的程序整合在一起
下面是如何将LSP模型集成到Flask web应用程序的示例。它包含一个端点,该端点将JSON数据作为输入,在LSPModule中设置正确的变量,并以JSON格式输出最终的目标值和决策。
from flask import Flask, request, jsonify
from localsolver.modeler import *
app = Flask(__name__)
def create_map(modeler, data):
map_ = modeler.create_map()
for val in data:
map_.append(val)
return map_
@app.route("/", methods=["POST"])
def index():
data = request.json
with LSPModeler() as modeler:
module = modeler.load_module("knapsack.lsp")
module["nbItems"] = data["nbItems"]
module["knapsackBound"] = data["knapsackBound"]
module["weights"] = create_map(modeler, data["weights"])
module["prices"] = create_map(modeler, data["prices"])
module.run()
return jsonify({
"value": module["knapsackValue"].value,
"decisions": [x_i.value for _, x_i in module["x"]]
})
我们随时随您一起探索LocalSolver数学规划求解器。只要在这里注册就可以申请免费的Local Solver试用许可证。同时,请随时与我们联系以获取更多信息或支持。更多问题请联系LocalSolver大规模数学规划优化器独家代理商无锡迅合信息科技有限公司开发人员。
————————————————