F# Or-Tools Sat 求解器
F# Or-Tools Sat Solver
我正在试验 F#,想在我使用 Or-Tools 的地方进行一些约束编程。我以前曾将此包与 Python 一起使用,但我无法使其与 F# 一起使用。
我遵循 C# 示例:https://developers.google.com/optimization/cp/cp_solver#c_5
但是在尝试添加约束时出现错误:
所以这有点烦人,但这就是在 C# 中从 F# 重载的消耗运算符的工作原理。
你不能像这样使用!=
的原因是:
- 运算符
!=
在 C# 中作为 LinearExpr
class. 上的静态运算符重载(这很不寻常)
- 运算符
!=
编译为 op_Inequality
,但 F# 中的 op_Inequality
是 <>
,而不是 !=
- F# 已经将
<>
定义为通用运算符,它接受满足 equality
约束的任何成员,而 LinearExpr
- 定义的运算符
<>
正确解析,并生成 bool
,这与 model.Add
不兼容,因为它不期望 bool
解决方案是明确限定您对运算符的访问权限,如下所示:
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)
那么您可以改用这些运算符。另一个烦恼是 +
和 -
和 *
似乎工作得很好,因为 F# 类型不会产生像 bool
.[=33= 这样的不同类型]
简而言之,这个特殊的 API 在 F# 中使用有点烦人。
我正在试验 F#,想在我使用 Or-Tools 的地方进行一些约束编程。我以前曾将此包与 Python 一起使用,但我无法使其与 F# 一起使用。
我遵循 C# 示例:https://developers.google.com/optimization/cp/cp_solver#c_5
但是在尝试添加约束时出现错误:
所以这有点烦人,但这就是在 C# 中从 F# 重载的消耗运算符的工作原理。
你不能像这样使用!=
的原因是:
- 运算符
!=
在 C# 中作为LinearExpr
class. 上的静态运算符重载(这很不寻常)
- 运算符
!=
编译为op_Inequality
,但 F# 中的op_Inequality
是<>
,而不是!=
- F# 已经将
<>
定义为通用运算符,它接受满足equality
约束的任何成员,而LinearExpr
- 定义的运算符
<>
正确解析,并生成bool
,这与model.Add
不兼容,因为它不期望bool
解决方案是明确限定您对运算符的访问权限,如下所示:
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)
那么您可以改用这些运算符。另一个烦恼是 +
和 -
和 *
似乎工作得很好,因为 F# 类型不会产生像 bool
.[=33= 这样的不同类型]
简而言之,这个特殊的 API 在 F# 中使用有点烦人。