LP DSL for F#,Clp 作为求解器



由于Microsoft求解器基础已被弃用,我正在尝试寻找一种替代或合理的方法来创建我自己的DSL。

我正在寻找的是必不可少的DSL来描述F#中的LP,使用Clp解决它并评估结果。

在我重新发明轮子之前:有人知道一个已经为 LP 提供 DSL 的好库吗?

否则,您将如何在 F# 中构建这样的 DSL?从本质上讲,我希望能够写出类似的东西

let xs = createVars 100 in 0..1
let ys = [| 1 .. 100 |]
let f i x = i*x
let lp = 
    minimize sumprod(xs, ys) subjectTo [
      xs.[0] + xs.[1] = 1
      sum(xs) <= 1
      sum({for i in 1..100 -> f i xs.[i]}) <= 100
      // ...
    ]
let solver = Clp()
let result = solver.solve lp

在我重新发明轮子之前:有人知道一个已经为 LP 提供 DSL 的好库吗?

不,除了来自 SolverFoundation 本身Microsoft ODSL 之外,我不知道任何内容。

否则,您将如何在 F# 中构建这样的 DSL?

  1. 确定语言的语法。虽然你想建立一个内部DSL,但你必须决定在你的语言中允许什么和什么不能表达。

  2. 使用 F# 引号获取 AST。你为什么需要反思?首先,创建一堆变量并将它们与浮点常量组合以形成线性约束。稍后,您将用适当的值填充这些变量。反射允许您创建占位符并在以后计算结果。

  3. 在 CLP 中将 AST 转换为线性程序并求解。CLP似乎没有.NET API;您可以通过命令行与求解器进行通信,但它不是很方便和健壮。最好在创建 DSL 之前开始构建低级 API。

  4. (可选)在 F# 3.0 中,可以为 DSL 创建查询语法。您可以查看一个令人信服的示例,即内置查询表达式。

由于Microsoft求解器基础已被弃用,我正在尝试寻找一种替代或合理的方法来创建我自己的 DSL。

論如何,無國界醫生將為你的工作提供寶貴的例子。您可以浏览此代码库中的 ODSL 源代码。实际上,从代码库中您可以看到ODSL已经完成了三个前步骤。我正在 ODSL 之上构建一种优化查询语言(步骤 4),并且只完成了表面语法。例如,这个原始示例

<@
        let sa = var<Barrel/Day>()
        let vz = var<Barrel/Day>()
        minimise (20.0<Dollar/Barrel> * sa + 15.0<Dollar/Barrel> * vz)
        where
            [
                0.3 * sa + 0.4 * vz >= 2000.<Barrel/Day>;
                0.4 * sa + 0.2 * vz >= 1500.<Barrel/Day>;
                0.2 * sa + 0.3 * vz >= 500.<Barrel/Day>;
                sa <= 9000.<Barrel/Day>;
                vz <= 6000.<Barrel/Day>;
                sa >= 0.<Barrel/Day>;
                vz >= 0.<Barrel/Day>  
            ]
    @>

将转换为

opt { let! sa = var<Barrel/Day>()
      let! vz = var<_>()
      assume (0.3 * sa + 0.4 * vz >= 2000.<_>)
      assume (0.4 * sa + 0.2 * vz >= 1500.<_>)
      assume (0.2 * sa + 0.3 * vz >= 500.<_>)
      assume (sa <= 9000.<_> && sa >= 0.<_>)
      assume (vz <= 6000.<_> && vz >= 0.<_>)   
      minimise (20.0<Dollar/Barrel> * sa + 15.0<_> * vz)
    }
我还

在这里翻译了一些DSL示例,以防您感兴趣。

相关内容

  • 没有找到相关文章

最新更新