【问题标题】:Best practice to solve large number of similar knapsack instances解决大量类似背包实例的最佳实践
【发布时间】:2018-05-28 23:18:10
【问题描述】:

我正在开展一个项目,我需要解决数千个类似背包问题的从小到大的“简单”实例。我所有的实例都具有相同的结构,相同的约束,但项目的数量(因此变量)有所不同。可以为所有实例固定域。

我已经成功地将 minizinc 集成到一个工作流中

  1. 从数据库中提取相关数据,
  2. 生成.mzn模型(包括初始变量赋值)
  3. 调用 CBC 求解器的 minizinc 驱动程序,
  4. 解析和解释解决方案。

我现在在大型实例的扁平化阶段遇到了性能瓶颈(参见详细扁平化统计信息)。展平最多需要 30 秒,而求解最优需要不到 1 秒。

我尝试禁用“优化展平”无济于事,我还尝试拆分工具链(mzn2fzn 然后 mzn-cbc);最后尝试将模型和数据定义分开,但没有观察到任何显着的改进。

如果有帮助,我已经确定了导致问​​题的一组约束:

...
array[1..num_items] of int: item_label= [1,12,81,12, [10 000 more ints between 1..82], 53 ];

int: num_label = 82;
array[1..num_label] of var 0..num_items: cluster_distribution;
constraint forall(i in 1..num_label)(cluster_distribution[i]==sum(j in 1..num_items)(item_indicator[j] /\ item_label[j]==i));
var 1..num_label: nz_label;
constraint non_zero_label = sum(i in 1..num_label) (cluster_distribution[i]>0);
....

基本上,5000 个项目中的每一个都有一个标签(大约 100 个可能的标签),我尝试(在其他目标中)最大化不同标签的数量(non_zero_label var)。我尝试了各种配方,但这个似乎是最有效的。

谁能给我一些关于如何加速这个扁平化阶段的指导?您将如何处理解决数千个“相似”实例的任务?

直接生成MPS文件,然后原生调用CBC会有好处吗?我希望 minizinc 在编译 MPS 文件时非常有效,但也许我可以通过利用实例的重复结构来加快速度?然而,我担心这或多或少会归结为重新编写一个写得不好的半生不熟的伪定制版 minizinc,这感觉不对。

谢谢!

我的系统信息:Os X 和 Ubuntu,mnz 2.1.7。

Compiling instance-2905-gd.mzn
MiniZinc to FlatZinc converter, version 2.1.7
Copyright (C) 2014-2018   Monash University, NICTA, Data61
Parsing file(s) 'instance-2905-gd.mzn' ...
processing file '../share/minizinc/std/stdlib.mzn'
processing file '../share/minizinc/std/builtins.mzn'
processing file '../share/minizinc/std/redefinitions-2.1.1.mzn'
processing file '../share/minizinc/std/redefinitions-2.1.mzn'
processing file '../share/minizinc/linear/redefinitions-2.0.2.mzn'
processing file '../share/minizinc/linear/redefinitions-2.0.mzn'
processing file '../share/minizinc/linear/redefinitions.mzn'
processing file '../share/minizinc/std/nosets.mzn'
processing file '../share/minizinc/linear/redefs_lin_halfreifs.mzn'
processing file '../share/minizinc/linear/redefs_lin_reifs.mzn'
processing file '../share/minizinc/linear/domain_encodings.mzn'
processing file '../share/minizinc/linear/redefs_bool_reifs.mzn'
processing file '../share/minizinc/linear/options.mzn'
processing file '../share/minizinc/std/flatzinc_builtins.mzn'
processing file 'instance-2905-gd.mzn'
 done parsing (70 ms)
Typechecking ... done (13 ms)
Flattening ... done (16504 ms), max stack depth 14
MIP domains ...82 POSTs [ 82,0,0,0,0,0,0,0,0,0, ], LINEQ [ 0,0,0,0,0,0,0,0,82, ], 82 / 82 vars, 82 cliques, 2 / 2 / 2 NSubIntv m/a/m, 0 / 127.085 / 20322 SubIntvSize m/a/m, 0 clq eq_encoded  ...  done (28 ms)
Optimizing ... done (8 ms)
Converting to old FlatZinc ... done (37 ms)
Generated FlatZinc statistics:
Variables: 21258 int, 20928 float
Constraints: 416 int, 20929 float
    This is a minimization problem.
Printing FlatZinc to '/var/folders/99/0zvzbfcj3h16g04d07w38wrw0000gn/T/MiniZinc IDE (bundled)-RzF4wk/instance-2905-gd.fzn' ... done (316 ms)
Printing .ozn to '/var/folders/99/0zvzbfcj3h16g04d07w38wrw0000gn/T/MiniZinc IDE (bundled)-RzF4wk/instance-2905-gd.ozn' ... done (111 ms)
Maximum memory 318 Mbytes.
  Flattening done, 17.09 s

【问题讨论】:

  • 我希望每次执行 minizinc 都会增加一些开销。问题很简单,能不能不直接调用CBC API?这比通过 MPS 文件要快。

标签: knapsack-problem constraint-programming minizinc


【解决方案1】:

如果您要解决同一问题类的多个实例化并且遇到较大的展平时间,那么您可以采用两种通用方法:优化 MiniZinc 以最小化展平时间,或者您可以在直接求解器 API。

如果您想保持求解器之间的通用性,第一个选项是最好的。为了优化展平时间,您要消除的主要内容是“临时”变量:创建然后丢弃的变量。扁平化模型的很多时间都用于解决不必要的变量。这是为了在求解时最小化搜索空间。临时变量可能在理解、循环、let 表达式和具体化中生成。对于您的特定模型Gleb posted,对约束中的 for 循环进行优化:

constraint forall(i in 1..num_label)(cluster_distribution[i]==sum(j in 1..num_items where item_label[j]==i)(item_indicator[j]));

如果您想将模型集成到软件产品中,则另一个选项可能是最好的,因为您可以提供与求解器的直接交互。您将不得不手动“展平”您的模型/数据,但您可以以更有限的方式仅针对您的目的进行操作。因为它不是通用的,所以它可以非常快。可以通过查看针对不同实例生成的 FlatZinc 来找到模型的提示。

【讨论】:

  • 感谢 Dekker(还有 Gleb),这无疑减少了扁平化阶段所需的时间。
猜你喜欢
  • 2011-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-17
  • 2015-06-18
  • 2021-11-08
  • 2010-10-04
  • 2013-01-08
相关资源
最近更新 更多