1 个不稳定版本
0.1.0 | 2016年9月10日 |
---|
2355 在 算法 中
59KB
1K SLoC
铜
约束规划求解器。
求解器是一个声明性框架,其中组合问题用决策变量和绑定约束来描述。用于找到可行解或最小化表达式的算法被抽象化,用户无需关心。专注于问题定义,建立变量之间的关系,铜将负责执行实际的搜索。
用法
以下是对 背包问题 的公式化。它最大化存储在具有固定最大重量的包中的物品价值。
// Extension trait, used here to scale decision variables by a constant (`times` method)
use copper::views::ViewExt;
// Problem parameters
let item_weights = [10, 60, 30, 40, 30, 20, 20, 2];
let item_values = [1, 10, 15, 40, 60, 90, 100, 15];
let weight_max = 102;
// Model object, used to declare decision variables and constraints
let mut m = copper::Model::default();
// Binary decision variables: for each item, do I put it in the bag?
let xs: Vec<_> = m.new_vars_binary(item_weights.len()).collect();
// Sum of the weights of the selected items
let weight = m.sum_iter(xs.iter().zip(item_weights).map(|(x, w)| x.times(w)));
// Ensure the bag does not exceed its maximum weight
m.less_than_or_equals(weight, weight_max);
// Sum the value of the selected items
let value = m.sum_iter(xs.iter().zip(item_values).map(|(x, v)| x.times(v)));
// Find the selection of items that maximizes the bag's value
let solution = m.maximize(value).unwrap();
// Extract assignment for each decision variable: is this item in the optimal bag?
let is_item_in_bag = solution.get_values_binary(&xs);
assert_eq!(is_item_in_bag, vec![false, false, true, false, true, true, true, true]);
assert_eq!(solution[weight], 102);
assert_eq!(solution[value], 280);
您可以在 Model 结构 的文档中找到类似问题的逐步指南。
约束规划或线性求解器?
大多数整数规划求解器,无论是 开源 还是 商业,都限于线性约束。这解锁了性能良好的方法,如 单纯形算法,这使得它们在处理线性问题时比约束规划求解器快得多。
然而,它要求用户用线性方程的形式来表达他们的约束。这种限制可能导致 尴尬的线性化、可疑的近似 或 存在的恐惧。
约束规划不对决策变量之间的关系施加此类限制。复杂的非线性约束甚至可以帮助传播引擎进一步剪枝搜索空间,从而提高整体性能。
为什么选择铜?
- 直截了当且严格的 API:对开发者体验的关注使铜易于上手,而 Rust 的健壮的类型系统使我们能够公开严格的 API,这些 API 难以误用。
- 宽松的许可证:铜在 MIT 许可证 下开发,对最终用户施加的限制很少。免费如同啤酒 和 话语。
为什么不选择铜?
- 性能:铜(Copper)仍处于早期开发阶段,无法与成熟求解器如 Gecode 或 or-tools 相媲美。尽管它是用Rust编写的,但还不是 ⚡️ 非常快 ™⚡️(目前还不是)。
- 特性:目前,铜(Copper)仅支持有限数量的变量类型和约束。您可以自己扩展其引擎,但其他求解器将提供更多现成的功能。
免责声明
铜(Copper)正处于积极开发中。一些暴露的API可能会发生变化,包括与自定义传播器和分支策略相关的API。
依赖关系
~15KB