在R

时间:2016-02-03 05:13:50

标签: r mathematical-optimization knapsack-problem

对于模糊的标题,我们很抱歉,但是设置如下:

我有一份零件清单,每份都有制造商,成本和利润。我将添加一个片段,但这将是一个很长的列表(数十个制造商,数百个部分)。

Manufacturer    Part Name   Cost    Profit
Cohiba          Behike 54   10.95   5.05
Rocky Patel     Edge        13.99   8.01
Acid            Liquid      8.49    3.51

我有一个代码,对每个独特的制造商进行抽样,为每个制造商随机选择一个零件,然后计算总和成本和利润。

ind <- sapply (unique( data$Manufacturer ) , function(x)
  sample( which(data$Manufacturer==x) , 1 ) )

Sampler <- data[ ind, ]

sum(Sampler$Profit)

sum(SamplerX$Cost)

我觉得必须要有一个更聪明的方法,让它能够找到每个制造商的一个独特零件的最佳清单,以便以最低的成本获得最高的利润。谁能给我一些见解?

2 个答案:

答案 0 :(得分:1)

为了完整性:

背包问题是强盗想要最大限度地提高被盗物品的价格,同时保持重量等于或低于其容量。 adagio包具有解决它的功能。

library(adagio)
# create some random data:
set.seed(1)
weights <- sample(1:100,30,FALSE)
prices <- sample(1:10000,30,FALSE)

# find what is the total weight
sum(weights)
[1] 1383

# Solve the problem, allowing a capacity of about 10% the total weight:
a <- knapsack(w=weights, p=prices, cap=138)

# See what a returns:
a
$capacity
[1] 138

$profit
[1] 50928

$indices
[1]  1  5 10 11 12 19 22 27

# validate results:
sum(weights[a$indices])
[1] 138

请注意,如果你的矢量很大,你需要很多容量。

#######编辑添加#######

考虑到您希望在保持成本低于特定限制的同时实现利润最大化, AND 不超过特定数量的制造商(在您的问题中一个),这是一个二维背包问题,我没有找到解决它的任何功能或包。

备选方案:

  1. 自己编码:一个好的开始是adagio::knapsack(没有括号,所以你可以看到代码),以及谷歌搜索“二维背包”。伪代码中有很多算法,所以你不能从一张白纸开始。
  2. 解决方法:如果您的输出向量不是很大,您可以使用adagio::knapsack() 忽略制造商并找到近似解决方案。然后你必须手动找到制造商在结果向量中重复的项目,然后找到一个尽可能接近 要替换的项目的成本且属于不同的项目,尚未使用的制造商,可能获得最高利润。 请注意,这不一定会产生最佳解决方案,即最佳解决方案(问题是NP难,所以无论如何它可能不会),但这将是一个很好的近似。

答案 1 :(得分:0)

我必须完全赞赏PavoDive帮助我解决这个问题。他使用“背包问题”这句话让我的头脑旋转起来,因为我从中学开始就没有听过背包谜语的版本。

一旦他这么说,我能够快速连接点,并且实际上发现已经存在一个包来解决这个确切设置的背包问题:

http://www.inside-r.org/packages/cran/adagio/docs/knapsack

我需要的答案就在那里。分享这个以防其他人需要解决这个问题。