LoginSignup
1
3

More than 5 years have passed since last update.

ナップザック問題を貪欲法で解いたメモ

Last updated at Posted at 2017-07-13

ナップザック問題を貪欲法で解いた際のメモです。

貪欲法の方針

容積あたりの価値が大きいものを先にナップザックに入れて、入り切ったものが解!
というのが、ナップザック問題の貪欲法における方針です。
例えば、過酷なサバイバルの準備のために、どちらも容積がほとんど同じである「うま〇棒」と「〇本満足バー」を好きなだけナップザックに詰めて持っていけるのなら、ナップザックいっぱいに「〇本満足バー」だけを詰め込むでしょう。そういうヒューリスティックに基づいています。

実装についてのメモ

1つの品物に1つのタプル(品物,価値,容積)を割り当て、それをリストで保持する方法が個人的に便利だと思います。
つまり、リストは次のような具合になります。

tuples = [
(品物,価値,容積),
(品物,価値,容積),
    :
(品物,価値,容積)
]

リスト内のタプルの要素にアクセスするとき、例えば、

品物"3"の"容積"

にアクセスするときは

tuples[2][2]

で値を取得できます。

コード

knapsack_greedy.py
import numpy as np

C = 2             #ナップザックの大きさ
len = 10          #品物の数
tuples = []       #(インデックス、価値、重さ、価値/重さ)を保持するリスト

#貪欲法の解とその初期化
sol = np.zeros(10)

#価値と重さの初期化
values = np.random.rand(len)
costs = np.random.rand(len)


#(インデックス、価値、容積、価値/容積)
for i in range(len):
    tuples.append((i,values[i],costs[i],float(values[i]/costs[i])))

#ソート後のタプル
tuples_sorted = []

#価値/容積の順で、ソートする
for x,y,z,w in sorted(tuples,key=lambda x:x[3],reverse = True):
    tuples_sorted.append((x,y,z,w))

sum = 0         #代入用変数    

for i in range(len):
    #容積あたりの価値が大きい物からナップザックに入れていく
    sum+=tuples_sorted[i][2]
    if(sum < C):
        sol[tuples_sorted[i][0]]=1         #容量オーバーしないなら入れる
    else:
        sol[tuples_sorted[i][0]]=0         #容量オーバーするので入れない

print("ナップザックの大きさ"+str(C))
print("価値")
print(np.round(values,3))
print("重さ")
print(np.round(costs,3))
print("選んだ品物")
print(sol)

sum_ = 0
for i in range(len):
    sum_ += sol[i]*costs[i]

print("選んだ品物の総容量")
print(str(sum_))

出力

ナップザックの大きさ2
価値
[ 0.631  0.543  0.668  0.337  0.011  0.454  0.536  0.527  0.434  0.833]
重さ
[ 0.823  0.546  0.759  0.028  0.005  0.638  0.694  0.468  0.474  0.351]
選んだ品物
[ 0.  1.  0.  1.  1.  0.  0.  1.  1.  1.]
選んだ品物の総容量
1.87266067297
1
3
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3