我想编写一个程序,它接受数学(优化)问题的描述,解析它,并生成解决它的紧凑,高效的C代码。我在python中有一个更小,更具体的问题的黑客攻击解决方案,但它很丑陋,只是依赖于模板化C代码 - 所以我有一堆乱七八糟的字符串看起来像
for (k = 0; k <= %s; k += %s) a[k] = v[k]/%s * a[i];
然后有一堆复杂的条件逻辑,在填写了正确的%s值后,上面的一行被写入solve_problem.c。
它实际上变得更加复杂,因为通常问题是通过具有某种结构的矩阵等参数化的,并且上述方法虽然可行,但在其自身重量下开始崩溃。
所以我想我正在寻找的是关于如何在代码中表示这些问题的高级建议,或者更确切地说只是解决了这个问题的其他项目的例子。有人告诉我使用OCaml或F#并查看FFTW,但更简单的东西将不胜感激。
我很抱歉这么说不好,但我甚至难以表达自己正在寻找的东西,我认为这是问题的根源。
答案 0 :(得分:8)
for (k = 0; k <= %s; k += %s) a[k] = v[k]/%s * a[i];
您正在寻找代表上述代码的方法。这可以用值表示:
For("k", Int 0, Leq(Var "k", a), Set("k", Add(Var "k", b)),
SetElt(Var "a", Var "k",
Mul(Div(GetElt(Var "v", Var "k"), c, GetElt(Var "a", Var "i")))))
给出这样的类型:
type Expr =
| Int of int
| Var of string
| Leq of Expr * Expr
| Mul of Expr * Expr
| Div of Expr * Expr
| Set of string * Expr
| SetElt of Expr * Expr * Expr
| GetElt of Expr * Expr
| For of string * Expr * Expr * Expr
我编写了一个非常简单的高级VM,称为HLVM,你可能会觉得很有启发性,因为它以一种简单的方式使用这种表示。定义是here,使用这些定义编写的一堆测试是here。
这种表示比字符串munging更强大,因为模式匹配编译器会为您执行详尽的冗余检查,从而可以轻松地在Expr
类型的值上编写函数,包括优化传递和代码生成器。
答案 1 :(得分:3)
您正在尝试实现编译器,这就是您应该如何解决问题的方法。有一种输入语言描述了您的优化问题,输出语言是C。
您可以将问题归结为以下任务(不一定按此顺序解决):
如果您不习惯实现语言和编译器,那么您将很想采用快捷方式。例如,您可以考虑使用正则表达式进行解析。或者您可能认为跳过抽象语法是个好主意,只是直接生成C源代码。我强烈建议不要这样做。抽象是你的朋友,因为它会让你的问题变得易于管理。
您应该仔细选择实施整个事物的语言。当然,像Ocaml这样的东西非常适合这项工作。但如果你不熟悉Ocaml,你应该坚持使用你最熟悉的语言。你不应该尝试手工实现解析器,那里有很多解析器生成器。值得学习一个。您可能会发现我的PL Zoo有帮助。
答案 2 :(得分:2)
我不知道你在优化方面有多少背景,但我怀疑你描述的路径是要走的路。具体来说,如果您能编写有效的C代码来解决优化问题,我会感到惊讶,除非您将自己局限于特定类别的问题。优化通常区分不同类型的问题(线性与非线性,整数与连续与混合整数编程),每种问题通常使用非常不同的算法来解决解决方案。
您可能需要查看Microsoft Solver Foundation的一些想法。本质上,MSF是一个通用API,它允许您以多种形式声明您的问题(OML,一种用于指定优化问题的声明性语言,还有C#和F#),然后根据性质将问题提供给适当的求解器问题。
答案 3 :(得分:1)
Dunno更简单。建议你看一下数学建模的现有工作。我不希望这很简单;解算器代码很难,生成它们更难。
您需要使用方法来指定问题的详细信息,并且可以组合由这些详细信息控制的答案部分。
我建议:
Sinapse,一个用于生成数学建模代码的系统;本文讨论了如何组织知识并支持有限差分码的生成,
和
Solving finite differencing equations,麻省理工学院的论文也是如此。
(我在初期开发过程中研究过Sinapse系统)。
答案 4 :(得分:1)