GLPK Mathprog组

时间:2013-05-01 19:42:55

标签: linear-programming solver knapsack-problem ampl mathprog

我正在尝试编写一个可以解决多选择背包问题(MCKP)的模型,如涉及维度,需求和多个的背包问题中所述 选择约束:概括和转换 配方(找到here,见图8和9)。您可以找到基本背包问题here的示例GMPL模型。对于想要快速解释背包问题的人,请阅读以下插图:

你是一个冒险家,偶然发现了一个宝库。有数以百计的精彩物品'我',每个物品都有一个重量'w'和一个利润'p'。假设您有一个重量为“c”的背包,并且您希望在不过量填充背包的情况下获得最大利润。什么是最佳的项目组合,以便您获得最大的利润?

在代码中:

maximize obj :
sum{(i,w,p) in I} p*x[i];

其中'I'是项目的篮子,x [i]是二进制变量(0 =未选择,1 =选择)

我遇到问题的问题是增加了多个组。 MCKP只需要从每个组中选择一个项目。因此,例如,假设我们有三个组可供选择。它们可以表示如下(忽略实际值):

# Items: index, weight, profit
set ONE :=
1 10 10
2 10 10
3 15 15
4 20 20
5 20 20
6 24 24
7 24 24
8 50 50;

# Items: index, weight, profit
set TWO :=
1 10 10
2 10 10
3 15 15
4 20 20
5 20 20
6 24 24
7 24 24
8 50 50;

# Items: index, weight, profit
set THREE :=
1 10 10
2 10 10
3 15 15
4 20 20
5 20 20
6 24 24
7 24 24
8 50 50;

我对如何迭代每个组以及如何定义变量x感到困惑。我认为它看起来像:

var x{i,j} binary;

其中i是j组中的项目索引。这假设我定义了一组集:

set Groups{ONE,TWO,THREE}

然后我会迭代这些项目组:

sum{j in Groups, (i,w,p) in Groups[j]} p*x[i,j];

但我很担心,因为我认为GMPL不支持有序集。我看过this相关问题,答案建议在集合中定义一个集合。但是,我不确定它在这种特定情况下会如何应用。

我的主要问题,要明确:在GMPL中,我如何迭代多组集合(在这种情况下是一组每组具有一组项目的组)?

2 个答案:

答案 0 :(得分:2)

AMPL不同,GMPL不支持集合。以下是在AMPL中执行此操作的方法:

set Groups;
set Items{Groups} dimen 3;

# define x and additional constraints
# ...

maximize obj: sum{g in Groups, (i,w,p) in Items[g]} p*x[i];

data;

set Groups := ONE TWO THREE;

# Items: index, weight, profit
set Items[ONE] :=
1 10 10
2 10 10
3 15 15
4 20 20
5 20 20
6 24 24
7 24 24
8 50 50;

# Items: index, weight, profit
set Items[TWO] :=
1 10 10
2 10 10
3 15 15
4 20 20
5 20 20
6 24 24
7 24 24
8 50 50;

# Items: index, weight, profit
set Items[THREE] :=
1 10 10
2 10 10
3 15 15
4 20 20
5 20 20
6 24 24
7 24 24
8 50 50;

如果您的变量不超过300个,则可以使用free student version of AMPL和解算器(例如CPLEX或Gurobi)。

答案 1 :(得分:2)

基于此gnu mailing list thread,我相信GMPL / MathProg支持您想要做的事情。这是他们的榜样:

set WORKERS;
param number_of_shifts, integer, >= 1;
set WORKER_CLIQUE{1..number_of_shifts}, within WORKERS;

data;
set WORKERS := Jack Kate Sawyer Sun Juliet Richard Desmond Hugo;
param number_of_shifts := 2;
set WORKER_CLIQUE[1] := Sawyer, Juliet;
set WORKER_CLIQUE[2] := Jack, Kate, Hugo;

在您的示例中,我假设您使用set Items{1..3}, within Groups;之类的内容与来自@ vitaut的答案的数据块。