車輪を再発明する前に: LP 用の DSL を既に提供している優れたライブラリを誰か知っていますか?
いいえ、 Microsoft SolverFoundation自体のODSL以外は知りません。
そうでなければ、F# でそのような DSL をどのように構築しますか?
言語の構文を決定します。内部 DSL を構築したいのですが、言語で何が許可され、何が表現できないかを決定する必要があります。
F# 引用符を使用して AST を取得します。なぜ反省が必要なの?まず、一連の変数を作成し、それらを float 定数と組み合わせて線形制約を形成します。後で、これらの変数に適切な値を入力します。リフレクションを使用すると、プレースホルダーを作成して、後で結果を計算できます。
AST を CLP の線形プログラムに変換して解決します。CLP には .NET API がないようです。コマンド ライン経由でソルバーと通信することはできますが、あまり便利ではなく、堅牢ではありません。DSL を作成する前に、低レベル API の構築を開始することをお勧めします。
(オプション) F# 3.0 では、DSL のクエリ構文を作成できます。説得力のある例、組み込みクエリ式を見ることができます。
Microsoft Solver Foundation は廃止されたため、独自の DSL を作成するための代替手段または合理的な方法を見つけようとしています。
いずれにせよ、MSF はあなたの仕事に貴重な例を提供します。このコードベースでODSL ソース コードを参照できます。実際、コードベースから、ODSL が 3 つの最初のステップを完了したことがわかります。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 の例を翻訳しました。