解决大量类似背包实例的最佳实践

时间:2018-05-28 23:18:10

标签: knapsack-problem constraint-programming minizinc

我正在开展一个项目,我需要解决成千上万的从小到大的问题"简单"像背包一样的问题。我的所有实例都具有相同的结构,相同的约束,但项目数量(因此变量)不同。可以为所有实例修复域。

我已成功将minizinc整合到工作流程中

  1. 从数据库中提取相关数据
  2. 生成.mzn模型(包括初始变量赋值)
  3. 调用minizinc驱动程序获取CBC解算器,
  4. 解析并解释解决方案。
  5. 我现在在大型实例的展平阶段遇到了性能瓶颈(参见详细的展平统计数据)。展平最多需要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
    

1 个答案:

答案 0 :(得分:3)

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

如果您想保持求解器之间的一般性,那么第一个选项是最好的。为了优化展平时间,您想要消除的主要内容是“临时”变量:创建然后丢弃的变量。扁平化模型的大部分时间都用于解决不必要的变量。这是为了在解决时最小化搜索空间。可以在理解,循环,let-expressions和reifications中生成临时变量。对于您的特定模型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,可以找到模型的提示。