使用Clp作为解算器的F#LP DSL 自从微软解决方案基金会被弃用以来,我试图找到一种替代或合理的方法来创建自己的DSL。
我所寻找的是一个DSL,它可以用F#来描述LP,用Clp来解决它,并评估结果 在我重新发明轮子之前:有人知道一个已经为LPs提供DSL的好库吗 否则,您将如何在F#中构建这样的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]
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。