用于F#的LP DSL,其中Clp作为解算器

Chr*_*nos 2 clr dsl f# linear-programming clp

由于Microsoft Solver Foundation已被弃用,我试图找到一种替代或合理的方法来创建自己的DSL.

我正在寻找的是在F#中描述LP的DSL必不可少的,用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
Run Code Online (Sandbox Code Playgroud)

pad*_*pad 6

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

不,除了Microsoft SolverFoundation本身的ODSL之外我什么都不知道.

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

  1. 确定语言的语法.虽然您想构建一个内部DSL,但您必须决定允许哪些内容以及您的语言中无法表达的内容.

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

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

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

由于Microsoft Solver Foundation已被弃用,我试图找到一种替代或合理的方法来创建自己的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>  
            ]
    @>
Run Code Online (Sandbox Code Playgroud)

会变成

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)
    }
Run Code Online (Sandbox Code Playgroud)

我还翻译了大量的DSL的例子在这里如果你有兴趣.