使用Clp作为解算器的F#LP DSL 自从微软解决方案基金会被弃用以来,我试图找到一种替代或合理的方法来创建自己的DSL。

使用Clp作为解算器的F#LP DSL 自从微软解决方案基金会被弃用以来,我试图找到一种替代或合理的方法来创建自己的DSL。,f#,clr,dsl,linear-programming,clp,F#,Clr,Dsl,Linear Programming,Clp,我所寻找的是一个DSL,它可以用F#来描述LP,用Clp来解决它,并评估结果 在我重新发明轮子之前:有人知道一个已经为LPs提供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]

我所寻找的是一个DSL,它可以用F#来描述LP,用Clp来解决它,并评估结果

在我重新发明轮子之前:有人知道一个已经为LPs提供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
让xs=createVars 100在0..1中
设ys=[1..100]
设f i x=i*x
设lp=
最小化sumprod(xs,ys)受[
xs.[0]+xs.[1]=1
总和(xs)f i xs.[i]}
在我重新发明轮子之前:有人知道一个已经为LPs提供DSL的好库吗

不,除了它自己,我什么都不知道

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

  • 决定语言的语法。虽然你想建立一个内部DSL,但你必须决定什么是允许的,什么是不能用你的语言表达的

  • 用于获取AST。为什么需要反射?首先,创建一组变量并将其与浮点常量组合以形成线性约束。稍后,您将使用适当的值填充这些变量。反射允许您稍后创建占位符并计算结果

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

  • (可选)在F#3.0中,您可以为您的DSL创建查询语法

  • 自从微软解决方案基金会被弃用以来,我试图找到一种替代或合理的方法来创建自己的DSL。

    无论如何,MSF将为您的工作提供有价值的示例。您可以浏览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>  
                ]
        @>
    
    =2000。;
    0.4*sa+0.2*vz>=1500。;
    0.2*sa+0.3*vz>=500。;
    sa=0。
    ]
    @>
    
    将转变为

    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)
        }
    
    opt{let!sa=var()
    让!vz=var()
    假设(0.3*sa+0.4*vz>=2000。)
    假设(0.4*sa+0.2*vz>=1500。)
    假设(0.2*sa+0.3*vz>=500。)
    假设(sa=0。)
    假设(vz=0。)
    最小化(20.0*sa+15.0*vz)
    }
    

    如果您感兴趣,我还翻译了许多DSL示例。

    谢谢!还发现你在F#中关于DSL的博客文章和备忘非常有用。我已经习惯了哈斯克尔和斯卡拉,也不得不习惯F。