F#Or-ToolsSat求解器
f#
我正在试验 F# 并希望在使用 Or-Tools 的地方进行一些约束编程。我之前曾将该包与 Python 一起使用,但我无法让它与 F# 一起使用。
我遵循 C# 示例:https : //developers.google.com/optimization/cp/cp_solver#c_5
但是在尝试添加约束时出现错误:
回答
所以这有点烦人,但这就是在 C# 中从 F# 重载的消耗运算符的工作原理。
你不能这样使用的原因!=是:
- 运算符
!=在 C# 中作为LinearExpr类上的静态运算符重载(这是不寻常的)。 - 运算符
!=编译为op_Inequality,但op_Inequality在 F# 中为<>,而不是!= - F# 已经定义
<>为一个泛型运算符,它接受任何满足equality约束的成员,它LinearExpr不会 - 定义的运算符
<>正确解析,并产生 abool,这是不兼容的,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 有点烦人。