F#Or-ToolsSat求解器

f#

我正在试验 F# 并希望在使用 Or-Tools 的地方进行一些约束编程。我之前曾将该包与 Python 一起使用,但我无法让它与 F# 一起使用。

我遵循 C# 示例:https : //developers.google.com/optimization/cp/cp_solver#c_5

但是在尝试添加约束时出现错误:

回答

所以这有点烦人,但这就是在 C# 中从 F# 重载的消耗运算符的工作原理。

你不能这样使用的原因!=是:

  1. 运算符!=在 C# 中作为LinearExpr类上的静态运算符重载(这是不寻常的)。
  2. 运算符!=编译为op_Inequality,但op_Inequality在 F# 中为<>,而不是!=
  3. F# 已经定义<>为一个泛型运算符,它接受任何满足equality约束的成员,它LinearExpr不会
  4. 定义的运算符<>正确解析,并产生 a bool,这是不兼容的,model.Add因为它不期望 abool

解决方案是明确限定您对运算符的访问权限,如下所示:

LinearExpr.(<>) (x, y)

请注意,因为它在定义中采用元组参数,所以您还必须对参数进行元组处理,并且不能像“普通”运算符一样使用它。

这是完整的 F# 解决方案,并进行了一些小调整以使其符合习惯:

#r "nuget: Google.OrTools"

open Google.OrTools.Sat

let model = CpModel()

// Creates the variables.
let num_vals = 3L;

let x = model.NewIntVar(0L, num_vals - 1L, "x")
let y = model.NewIntVar(0L, num_vals - 1L, "y")
let z = model.NewIntVar(0L, num_vals - 1L, "z")

// Creates the constraints.
model.Add(LinearExpr.(<>) (x, y))

// Creates a solver and solves the model.
let solver = CpSolver();
let status = solver.Solve(model)

if status = CpSolverStatus.Optimal then
    printfn $"x = {solver.Value(x)}"
    printfn $"y = {solver.Value(y)}"
    printfn $"z = {solver.Value(z)}"

一种让 F# 变得更好的方法是定义一个运算符模块,这些运算符映射到LinearExpr运算符,如下所示:

module LinearExprOperators =
    let ( ^<> ) (x: LinearExpr) (y: LinearExpr) = LinearExpr.(<>) (x, y)
    let ( ^= ) (x: LinearExpr) (y: LinearExpr) = LinearExpr.(=) (x, y)

然后您可以改用这些运算符。另一个烦恼是,+and 和-and似乎*工作得很好,因为 F# 类型不会产生不同的类型,如bool.

简而言之,从 F# 使用这个特定的 API 有点烦人。


以上是F#Or-ToolsSat求解器的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>