食事プランの最適化 PuLP

食事プランの最適化

最適化問題の例として食事プランの最適化問題を考えてみます。

この問題では、1週間の食事プランを最適化し、必要な栄養素をバランスよく摂取しながら、予算内で食材を購入することを目的とします。

以下は、PuLPを使用してこの問題を解くためのソースコードです。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from pulp import *

# 問題の定義
prob = LpProblem("Meal Planning", LpMinimize)

# 変数の定義
chicken = LpVariable("Chicken", lowBound=0.1)
beef = LpVariable("Beef", lowBound=0.1)
fish = LpVariable("Fish", lowBound=0.1)

# 制約条件の設定
prob += 3 * chicken + 4 * beef + 2 * fish >= 7.5
prob += 2 * chicken + 3 * beef + 1.5 * fish >= 6
prob += 0.5 * chicken + beef + 0.3 * fish >= 1.5
prob += 3 * chicken + 4 * beef + 2 * fish <= 30
prob += 2 * chicken + 3 * beef + 1.5 * fish <= 25
prob += 0.5 * chicken + beef + 0.3 * fish <= 5

# 目的関数の設定
prob += 5 * chicken + 7 * beef + 6 * fish

# 問題の解法
status = prob.solve()

# 結果の出力
print("Status:", LpStatus[status])
print("Optimal Solution:")
for var in prob.variables():
print(var.name, "=", var.varValue)
print("Total Cost of Ingredients = ", value(prob.objective))

上記のコードでは、変数 chicken、beef、fish はそれぞれ、鶏肉、牛肉、魚介類の購入量を表しています。


prob += 式 不等号 式で制約条件を、prob += 式 で目的関数を設定しています。

制約条件目的関数の違いは、不等号があるかどうかです。


制約条件は、それぞれ栄養素のバランスを保つための条件です。

例えば、4つ目の制約条件は、タンパク質の摂取量が30グラム以下であることを表しています。

目的関数は、食材の総額を最小化することを目的としています。


最後に、prob.solve() で問題を解き、結果を出力しています。

結果は、各変数(食材)の最適値と、食材の総額です。


このコードを実行すると、以下のような結果が得られます。

[実行結果]

Status: Optimal
Optimal Solution:
Beef = 1.8833333
Chicken = 0.1
Fish = 0.1
Total Cost of Ingredients =  14.2833331

これは、最適な食事プランが、牛肉1.88ポンド、鶏肉0.1ポンド、魚介類0.1ポンドであることを示しています。

また、このプランの食材の総額は14.28ドルであることがわかります。

スケジューリング最適化 PuLP

スケジューリング最適化

スケジューリング最適化の例題を考えます。

複数のジョブを複数のマシンで実行する場合のスケジューリングを最適化する問題です。

各ジョブには処理を実行するために必要な時間があり、各マシンには同時に実行できるジョブの数に制限があります。

目的は、すべてのジョブを完了するのに必要な最小時間を見つけることです。

例えば、4つのジョブ2つのマシンがあり、以下のような情報が与えられたとします。

ジョブ時間必要なマシン数
A21
B31
C22
D42

解き方・ソースコード

この問題をPuLPで解くには、以下のようなソースコードになります。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import pulp

# ①問題を定義する
problem = pulp.LpProblem("Job Scheduling", pulp.LpMinimize)

# ②各ジョブをどのマシンで実行するかを決定する変数を作成する
# ジョブAをマシン1で実行する場合、変数A_1の値は1になる
# ジョブAをマシン2で実行する場合、変数A_2の値は1になる
A_1 = pulp.LpVariable("A_1", lowBound=0, cat='Binary')
A_2 = pulp.LpVariable("A_2", lowBound=0, cat='Binary')
B_1 = pulp.LpVariable("B_1", lowBound=0, cat='Binary')
B_2 = pulp.LpVariable("B_2", lowBound=0, cat='Binary')
C_1 = pulp.LpVariable("C_1", lowBound=0, cat='Binary')
C_2 = pulp.LpVariable("C_2", lowBound=0, cat='Binary')
D_1 = pulp.LpVariable("D_1", lowBound=0, cat='Binary')
D_2 = pulp.LpVariable("D_2", lowBound=0, cat='Binary')

# ③目的関数を定義する(すべてのジョブが完了するのに必要な時間を最小化する)
problem += 2*A_1 + 2*A_2 + 3*B_1 + 3*B_2 + 2*C_1 + 2*C_2 + 4*D_1 + 4*D_2

# ④制約条件(1)を定義する(各ジョブは1つのマシンで実行されなければならない)
problem += A_1 + A_2 == 1
problem += B_1 + B_2 == 1
problem += C_1 + C_2 == 1
problem += D_1 + D_2 == 1

# ⑤制約条件(2)を定義する(各マシンは同時に実行できるジョブの数に制限がある)
problem += A_1 + B_1 + C_1 + D_1 <= 2
problem += A_2 + B_2 + C_2 + D_2 <= 2

# ⑥問題を解く
status = problem.solve()

# ⑦結果を表示する
print("Status:", pulp.LpStatus[status])
print("Minimum Time:", pulp.value(problem.objective))
print("A_1:", pulp.value(A_1))
print("A_2:", pulp.value(A_2))
print("B_1:", pulp.value(B_1))
print("B_2:", pulp.value(B_2))
print("C_1:", pulp.value(C_1))
print("C_2:", pulp.value(C_2))
print("D_1:", pulp.value(D_1))
print("D_2:", pulp.value(D_2))

problemオブジェクトを作成し、最小化問題であることを示します。

②各ジョブをどのマシンで実行するかを決定する変数を作成します。
 各変数は、0または1の2値をとります。

目的関数を定義します。
 すべてのジョブが完了するのに必要な時間を最小化するように設定しています。

制約条件(1)を定義します。
 各ジョブは1つのマシンで実行されなければならず、各マシンは同時に実行できます。

制約条件(2)を定義します。
 ジョブの数に制限があることを示します。

⑥問題を解きます。

⑦結果を表示します。
 最適なスケジュールを決定するための変数の値と、最小化された時間を表示します。


このコードを実行すると、以下のような結果が得られます。

[実行結果]

Status: Optimal

Minimum Time: 11.0

A_1: 1.0

A_2: 0.0

B_1: 1.0

B_2: 0.0

C_1: 0.0

C_2: 1.0

D_1: 0.0

D_2: 1.0

この結果から、最小時間は11であり、次のようなスケジュールが最適であることがわかります。

🔹ジョブAをマシン1で、ジョブBをマシン1で、ジョブCをマシン2で、ジョブDをマシン2で実行する。

マーケティング最適化問題 PuLP

マーケティング最適化問題

簡単なマーケティング最適化問題を考えます。

この問題では、広告費用を最小限に抑えつつ、与えられた広告予算内で最大の利益を得るために、どの製品にどの程度の広告予算を割り当てるかを決定する必要があります。

例:

ある企業が3つの製品を販売しています。

各製品には、それぞれ異なる利益と広告費用があります。

企業は、合計で10,000ドルの広告予算を持っています。

どの製品にどの程度の広告予算を割り当てるべきかを決定して、利益を最大化する必要があります。

各製品の利益広告費用は以下のとおりです。

製品利益広告費用
A3002000
B2001500
C1501000

解き方・ソースコード

この問題をPuLPを使って解決するには、以下のようなスソースコードになります。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import pulp

# ①問題を初期化
problem = pulp.LpProblem("マーケティング最適化問題", pulp.LpMaximize)

# ②変数を定義
a = pulp.LpVariable("Aの広告費用", lowBound=0)
b = pulp.LpVariable("Bの広告費用", lowBound=0)
c = pulp.LpVariable("Cの広告費用", lowBound=0)

# ③目的関数を定義
problem += 300*a + 200*b + 150*c, "利益の合計"

# ④制約条件を定義
problem += a + b + c <= 10000, "広告予算の合計"
problem += a <= 2000, "Aの広告費用の上限"
problem += b <= 1500, "Bの広告費用の上限"
problem += c <= 1000, "Cの広告費用の上限"

# ⑤問題を解く
status = problem.solve()

# ⑥結果を出力
print(f"ステータス: {pulp.LpStatus[status]}")
print(f"最大利益: {problem.objective.value()}")
print(f"Aの広告費用: {a.value()}")
print(f"Bの広告費用: {b.value()}")
print(f"Cの広告費用: {c.value()}")

①問題を初期化

pulp.LpProblemを使って問題の名前を指定し、最大化問題であることを指定します。

②変数を定義

pulp.LpVariableを使って各製品の広告費用を表す変数a、b、cを定義します。

また、lowBound引数を使って変数の下限を0に設定します。

③目的関数を定義

各製品の利益を表す定数と広告費用を表す変数をかけた値を足し合わせて、最大化したい利益の合計を定義します。

④制約条件を定義

各制約条件を表す不等式をproblem +=で連結していきます。

制約条件は、広告予算の合計が10000ドル以下、各製品の広告費用が上限に収まることです。

⑤問題解決

problem.solve()を使って問題を解きます。

⑥結果出力

解のステータスや各製品の広告費用最大利益を出力します。

pulp.LpStatus[status]を使って、解のステータスをテキストで表示します。

また、各変数の値はvalue()を使って取得できます。

最大利益はproblem.objective.value()で取得できます。

[実行結果]

ステータス: Optimal

最大利益: 1050000.0

Aの広告費用: 2000.0

Bの広告費用: 1500.0

Cの広告費用: 1000.0

この結果から、最大利益は1050000ドルであり、A製品には広告費用2000ドル、B製品には広告費用1500ドル、C製品には広告費用1000ドルを割り当てることが最適であることがわかります。

また、制約条件がすべて満たされていることも確認できます。

建設プロジェクトのスケジューリング問題の最適化 PuLP

建設プロジェクトのスケジューリング問題の最適化

建設プロジェクトのスケジューリング問題を考えてみます。

ある建設プロジェクトにおいて、以下の6つの作業が必要です。

🔹作業A: 2週間かかる
🔹作業B: 3週間かかる
🔹作業C: 4週間かかる
🔹作業D: 2週間かかる
🔹作業E: 3週間かかる
🔹作業F: 4週間かかる

作業が開始されたら中断することはできません。さらに、以下の制約があります。

🔹作業A, B, Cは同時に開始することができます。
🔹作業Bが完了した後、作業Dを開始することができます。
🔹作業Cが完了した後、作業Eを開始することができます。
🔹作業DとEは同時に開始するることができます。
🔹作業DとEが完了した後、作業Fを開始できます。

解き方・ソースコード

この問題をPuLPで解いてみます。

問題の設定や解法の詳細はコメントを確認して下さい。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# 必要なライブラリをインポートする
import pulp

# 問題を定義する
problem = pulp.LpProblem('Construction Project', pulp.LpMinimize)

# 変数を定義する
a = pulp.LpVariable('a', lowBound=0, cat='Continuous')
b = pulp.LpVariable('b', lowBound=0, cat='Continuous')
c = pulp.LpVariable('c', lowBound=0, cat='Continuous')
d = pulp.LpVariable('d', lowBound=0, cat='Continuous')
e = pulp.LpVariable('e', lowBound=0, cat='Continuous')
f = pulp.LpVariable('f', lowBound=0, cat='Continuous')

# 制約式を定義する

# 各作業の所要日数
problem += a >= 2
problem += b >= 3
problem += c >= 4
problem += d >= 2
problem += e >= 3
problem += f >= 4

# 作業A, B, Cは同時に開始することができる
# a + 2 <= dは、作業Dを開始する前に、作業Aが完了している必要があることを表している
# b + 3 <= cは、作業Cを開始する前に、作業Bが完了している必要があることを表している
problem += a + 2 <= d
problem += b + 3 <= c

# 作業Cが完了した後、作業Eを開始する
# c + 4 <= eは、作業Eを開始する前に、作業Cが完了している必要があることを表している
problem += c + 4 <= e

# 作業DとEは同時に開始することができる
# d + 2 <= fは、作業Fを開始する前に、作業Dが完了している必要があることを表している
# e + 3 <= fは、作業Fを開始する前に、作業Eが完了している必要があることを表している
problem += d + 2 <= f
problem += e + 3 <= f

# 目的関数を定義する
problem += f

# 問題を解く
status = problem.solve()

# 結果を表示する
print(f"Status: {pulp.LpStatus[status]}")
print(f"Optimal Solution:")
print(f"\ta: {a.value():.2f}")
print(f"\tb: {b.value():.2f}")
print(f"\tc: {c.value():.2f}")
print(f"\td: {d.value():.2f}")
print(f"\te: {e.value():.2f}")
print(f"\tf: {f.value():.2f}")

# それぞれの作業の開始時期を計算する
start_a = a.value()
start_b = b.value()
start_c = c.value()
start_d = d.value()
start_e = e.value()
start_f = f.value()

# 結果を表示する
print("Task Schedule:")
print(f"\tTask A starts at day {start_a:.2f}")
print(f"\tTask B starts at day {start_b:.2f}")
print(f"\tTask C starts at day {start_c:.2f}")
print(f"\tTask D starts at day {start_d:.2f}")
print(f"\tTask E starts at day {start_e:.2f}")
print(f"\tTask F starts at day {start_f:.2f}")

[実行結果]

Status: Optimal

Optimal Solution:

    a: 2.00

    b: 3.00

    c: 6.00

    d: 11.00

    e: 10.00

    f: 13.00

Task Schedule:

    Task A starts at day 2.00

    Task B starts at day 3.00

    Task C starts at day 6.00

    Task D starts at day 11.00

    Task E starts at day 10.00

    Task F starts at day 13.00

最適解は、作業の完了までの日数を最小化するようにスケジュールが設定された結果であり、最適なスケジュールでの各タスクの開始日を示しています。

都市最適化問題 PuLP

都市最適化問題

都市最適化問題の例として、以下の問題を考えてみましょう。

ある都市には5つの工場があり、それぞれが製品を生産しています。

各工場は、それぞれの製品を販売するための市場に製品を供給する必要があります。

この問題は、工場と市場をどのように結びつけるかを決定する問題となります。

解き方・ソースコード

この問題を解くために、PuLPを使用して以下のようにモデル化します。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 必要なライブラリをインポート
import pulp

# 問題を初期化
problem = pulp.LpProblem("Factory Market Problem", pulp.LpMinimize)

# 工場と市場の数
factories = ["Factory 1", "Factory 2", "Factory 3", "Factory 4", "Factory 5"]
markets = ["Market 1", "Market 2", "Market 3", "Market 4", "Market 5"]

# 各工場の製品の生産量(変数)
production = pulp.LpVariable.dicts("Production", factories, lowBound=0)

# 各市場に必要な製品の量(定数)
demand = {"Market 1": 20, "Market 2": 25, "Market 3": 30, "Market 4": 20, "Market 5": 15}

# 各工場が各市場に供給する製品の量(変数)
shipments = pulp.LpVariable.dicts("Shipments", (factories, markets), lowBound=0)

# 目的関数を設定
problem += pulp.lpSum([500 * production[i] for i in factories]) + pulp.lpSum([300 * shipments[i][j] for i in factories for j in markets])

# 制約条件を追加
for j in markets:
problem += pulp.lpSum([shipments[i][j] for i in factories]) == demand[j]

for i in factories:
problem += pulp.lpSum([shipments[i][j] for j in markets]) <= production[i]

# 問題を解く
problem.solve()

# 結果を表示
for i in factories:
for j in markets:
if shipments[i][j].value() > 0:
print(f"{i} から {j}{shipments[i][j].value()} だけ製品を供給します。")

この例では、5つの工場5つの市場があり、各市場に必要な製品の量が設定されています。

それぞれの工場の生産量と、各工場が各市場に供給する製品の量が決まっており、目的関数には生産コスト出荷コストが含まれています。

制約条件では、各市場に必要な製品の量が供給されていることと、各工場が生産した製品の量を超えて製品を出荷していないことを設定しています。


このモデルを実行すると、各工場が各市場に供給する製品の量が計算されます。

例えば、”Factory 2”から”Market 3”には30個の製品が供給され、”Factory 3”から”Market 2”には25個の製品が供給されるなど、全ての製品の供給量が計算されます。

このように、PuLPを使用して都市最適化問題を解くことができます。

実際の都市最適化問題では、工場や市場の数がより大きく、制約条件が複雑であることがありますが、PuLPはそれらの問題にも対応できます。

[実行結果]

Factory 2 から Market 3 へ 30.0 だけ製品を供給します。

Factory 2 から Market 5 へ 15.0 だけ製品を供給します。

Factory 3 から Market 2 へ 25.0 だけ製品を供給します。

Factory 4 から Market 1 へ 20.0 だけ製品を供給します。

Factory 4 から Market 4 へ 20.0 だけ製品を供給します。

この結果から、各工場が各市場に供給する製品の量が計算され、各市場に必要な量が供給されていることがわかります。

経済最適化問題 PuLP

経済最適化問題

あなたは、小売店を経営しています。

あなたの店には、リンゴ、バナナ、オレンジといった果物があります。

あなたは、これらの果物を卸売業者から購入し、顧客に販売します。

各果物の単価、在庫、需要量は以下の通りです。

  • リンゴ:単価100円、在庫200個、需要量100個
  • バナナ:単価80円、在庫150個、需要量50個
  • オレンジ:単価120円、在庫100個、需要量75個

最大の利益を得るためには、どの果物を何個購入し販売すべきでしょうか。

解き方・ソースコード

3種類の果物(リンゴ、バナナ、オレンジ)の購入・販売数を最適化する方法を考えます。

目的は、最大利益を得ることであり、利益は各果物の単価と数量の積の総和となります。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from pulp import *

# ①各果物の単価、在庫、需要量を設定
prices = {"apple": 100, "banana": 80, "orange": 120}
inventory = {"apple": 200, "banana": 150, "orange": 100}
demand = {"apple": 100, "banana": 50, "orange": 75}

# ②変数
apple_qty = LpVariable("apple_qty", lowBound=0, cat='Integer')
banana_qty = LpVariable("banana_qty", lowBound=0, cat='Integer')
orange_qty = LpVariable("orange_qty", lowBound=0, cat='Integer')

# ③問題の定義
prob = LpProblem("Fruit Buying Problem", LpMaximize)

# ④目的関数
prob += prices["apple"] * apple_qty + prices["banana"] * banana_qty + prices["orange"] * orange_qty

# ⑤制約条件
prob += apple_qty <= inventory["apple"]
prob += banana_qty <= inventory["banana"]
prob += orange_qty <= inventory["orange"]
prob += apple_qty + banana_qty + orange_qty >= demand["apple"] + demand["banana"] + demand["orange"]
prob += apple_qty >= demand["apple"]
prob += banana_qty >= demand["banana"]
prob += orange_qty >= demand["orange"]

# ⑥最適化の実行
prob.solve()

# ⑦結果の表示
print("Apple quantity: ", apple_qty.value())
print("Banana quantity: ", banana_qty.value())
print("Orange quantity: ", orange_qty.value())
print("Maximum profit: ", value(prob.objective))

①まず、各果物の単価、在庫、需要量を辞書型データで設定します。

これらの情報は、問題を解決するための制約条件として使用されます。

例えば、リンゴの在庫量は200であり、需要量は100であることが設定されています。


②次に、PuLPを使用して変数を作成します。

LpVariableを使用して、リンゴ、バナナ、オレンジの数量を表す3つの変数を作成しています。

これらの変数は、それぞれapple_qty、banana_qty、orange_qtyという名前で定義され、lowBoundパラメータを使用して0以上の整数値であることが保証されています。


③PuLPを使用して問題を定義します。

LpProblemを使用して、問題のタイトル(Fruit Buying Problem)と目的(最大化)を指定します。

④目的関数は、各果物の数量と単価の積の総和であり、prob += prices[“apple”] * apple_qtyという形式で追加されます。

⑤リンゴ、バナナ、オレンジの数量に関する制約条件を追加します。

例えば、リンゴの在庫量は apple_qty <= inventory[“apple”] の制約条件で表されます。

その他の制約条件には、需要量の制約や、リンゴ、バナナ、オレンジの数量を合計した値の制約が含まれます。


⑥PuLPを使用して問題を解きます。

⑦各果物の数量と最大利益を表示しています。

[実行結果]

Apple quantity:  200.0

Banana quantity:  150.0

Orange quantity:  100.0

Maximum profit:  44000.0

この結果から、リンゴ200個、バナナ150個、オレンジ100個を購入し、最大利益は44,000円であることがわかります。

飛行機スケジュール最適化問題 PuLP

飛行機スケジュール最適化問題

飛行機スケジュール最適化問題は、与えられた制約条件の下で、最小限のコストまたは最大限の利益で運ぶように航空便をスケジュールする問題です。

この問題に対する一つのアプローチは、線形プログラミングを用いることです。

PuLPは、Pythonで線形プログラミング問題を解くためのオープンソースのライブラリです。


以下に、飛行機スケジュール最適化問題の例を示します。

例:

ある航空会社が、3つの都市(A、B、C)を結ぶ便を運航しています。

各都市の間には、以下のような航空路があります。

  • 都市Aから都市Bへの便
  • 都市Aから都市Cへの便
  • 都市Bから都市Cへの便

各都市への到着時刻出発時刻フライト時間最大搭乗可能人数が与えられています。

以下の制約条件を満たしながら、最大限の利益を得るために、どのようなスケジュールを立てるかを決定する必要があります。

  • 各便の発着は、出発地の時刻よりも遅れることはできない。
  • 各便の出発時刻は、前の便の到着時刻よりも遅れることはできない。
  • 各便の乗客数は、最大搭乗可能人数を超えてはなりません。

解き方・ソースコード

PuLPを使って飛行機スケジュール最適化問題を解決しています。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# ①pulpライブラリをインポート
import pulp

# ②制約条件を定義する
problem = pulp.LpProblem('Flight Schedule', pulp.LpMaximize)

# ③便ごとに決定変数を作成する
flight_AB = pulp.LpVariable('Flight_AB', lowBound=0, cat='Integer')
flight_AC = pulp.LpVariable('Flight_AC', lowBound=0, cat='Integer')
flight_BC = pulp.LpVariable('Flight_BC', lowBound=0, cat='Integer')

# ④目的関数を設定する
problem += 1000 * flight_AB + 1500 * flight_AC + 1200 * flight_BC

# ⑤制約条件を追加する
problem += flight_AB <= 50
problem += flight_AC <= 70
problem += flight_BC <= 80

problem += flight_AB <= 8
problem += flight_AC <= 11
problem += flight_BC <= 12

problem += flight_AB + flight_AC <= 70
problem += flight_AB + flight_BC <= 60
problem += flight_AC + flight_BC <= 75

# ⑥最適化を実行する
problem.solve()

# ⑦結果を表示する
print('Flight AB:', pulp.value(flight_AB))
print('Flight AC:', pulp.value(flight_AC))
print('Flight BC:', pulp.value(flight_BC))
print('Total profit:', pulp.value(problem.objective))

①PuLPライブラリをインポートしています。

②pulp.LpProblemを使用して、最適化問題を定義しています。

‘Flight Schedule’は問題の名前であり、pulp.LpMaximizeは目的関数を最大化することを示しています。

③各便に対して決定変数を作成します。

ここでは、都市Aと都市Bの間のフライトをflight_AB、都市Aと都市Cの間のフライトをflight_AC、都市Bと都市Cの間のフライトをflight_BCとしています。

各決定変数の値は、整数であることを指定し、0以上の値を取るように制限されています。

目的関数は、各便の利益の合計を設定します。

ここで、flight_AB、flight_AC、およびflight_BCは各便の数を表します。

制約条件を設定します。

これらの条件は、便の数に関する制限を設定するものです。

⑥problem.solve()で最適化問題を解きます。

⑦結果を表示しています。

pulp.valueを使用して、各便の数総利益を取得しています。

[実行結果]

Flight AB: 8.0

Flight AC: 11.0

Flight BC: 12.0

Total profit: 38900.0

この結果は、都市Aと都市Bの間に8便、都市Aと都市Cの間に11便、都市Bと都市Cの間に12便の便をスケジュールすることが最適であり、その結果、最大の利益である38900ドルを得ることができることを示しています。

クラウドコンピューティング最適化問題 PuLP

クラウドコンピューティング最適化問題

クラウドコンピューティングにおけるサーバー配置問題を例にして、PuLPを用いて解いていきます。

サーバー配置問題とは、複数のクラウドサービスを提供するために必要なサーバーを、最小限のコストで配置する問題です。

ここでは、各サーバーのスペックと利用料金が既知であると仮定します。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from pulp import *

# 問題設定
servers = ["Server1", "Server2", "Server3"]
spec = {"Server1": {"CPU": 4, "Memory": 16, "Storage": 500},
"Server2": {"CPU": 2, "Memory": 8, "Storage": 250},
"Server3": {"CPU": 8, "Memory": 32, "Storage": 1000}}
costs = {"Server1": 100, "Server2": 50, "Server3": 200}
demands = {"CPU": 10, "Memory": 32, "Storage": 800}

# モデル定義
prob = LpProblem("Server Allocation Problem", LpMinimize)

# 変数定義
servers_vars = LpVariable.dicts("Server", servers, lowBound=0, upBound=None, cat="Integer")

# 目的関数
prob += lpSum([costs[s] * servers_vars[s] for s in servers])

# 制約条件
for r in spec["Server1"].keys():
prob += lpSum([spec[s][r] * servers_vars[s] for s in servers]) >= demands[r]

# 解法
prob.solve()

# 結果出力
print("Total cost: {}".format(value(prob.objective)))
for s in servers:
print("{}: {}".format(s, value(servers_vars[s])))

このコードでは、各サーバーのスペックをspec、利用料金をcosts、要求スペックをdemandsとして定義し、PuLPを用いてモデルを定義しています。

変数として各サーバーの割り当てをservers_varsと定義し、目的関数と制約条件を設定した後にprob.solve()を実行することで最適解を求め、結果を出力しています。

[実行結果]

Total cost: 250.0

Server1: 0.0

Server2: 1.0

Server3: 1.0

この結果から、サーバー2サーバー3それぞれ1台使用することで、最小のコストで要求スペックを満たすことができることがわかります。

また、この最適解においてかかるコストは250となります。

医療最適化問題 PuLP

医療最適化問題

ある病院における輸血の最適化問題を考えてみましょう。

具患者に輸血を行う場合、その輸血に使用する血液の種類によって、患者に不適切な血液を投与してしまうリスクがあります。

このため、輸血に使用する血液の種類を適切に選択することが重要です。

この問題をPuLPを使って解くためには、以下のような手順を踏みます。

  1. 必要なパッケージをインポートします。

    1
    from pulp import *
  2. 問題を定義します。

    1
    2
    # 問題を定義
    prob = LpProblem('Blood_Transfusion', LpMinimize)
  3. 変数を定義します。

    1
    2
    3
    4
    # 変数を定義
    blood_type_A = LpVariable('Blood_Type_A', lowBound=0, cat='Integer')
    blood_type_B = LpVariable('Blood_Type_B', lowBound=0, cat='Integer')
    blood_type_O = LpVariable('Blood_Type_O', lowBound=0, cat='Integer')
  4. 目的関数を定義します。

    1
    2
    # 目的関数を定義
    prob += 10 * blood_type_A + 20 * blood_type_B + 30 * blood_type_O

各血液の種類について、そのコストを10, 20, 30としました。

血液の種類がAの場合には10のコスト、Bの場合には20のコスト、Oの場合には30のコストがかかるということになります。

  1. 制約条件を定義します。
    1
    2
    3
    4
    5
    # 制約条件を定義
    prob += blood_type_A + blood_type_B + blood_type_O >= 100
    prob += blood_type_A >= 20
    prob += blood_type_B >= 30
    prob += blood_type_O >= 40

病院で必要な総血液量が100であること、血液の種類Aが20以上必要であること、血液の種類Bが30以上必要であること、血液の種類Oが40以上必要であることを制約条件として定義しています。

  1. 最適化を実行します。

    1
    2
    # 最適化を実行
    prob.solve()
  2. 結果を表示します。

    1
    2
    3
    4
    5
    # 結果を表示
    print('Blood Type A: ', blood_type_A.value())
    print('Blood Type B: ', blood_type_B.value())
    print('Blood Type O: ', blood_type_O.value())
    print('Total Cost: ', value(prob.objective))

完全なソースコード

以上の手順をすべて組み合わせた完全なコードは次のようになります。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from pulp import *

# 問題を定義
prob = LpProblem('Blood_Transfusion', LpMinimize)

# 変数を定義
blood_type_A = LpVariable('Blood_Type_A', lowBound=0, cat='Integer')
blood_type_B = LpVariable('Blood_Type_B', lowBound=0, cat='Integer')
blood_type_O = LpVariable('Blood_Type_O', lowBound=0, cat='Integer')

# 目的関数を定義
prob += 10 * blood_type_A + 20 * blood_type_B + 30 * blood_type_O

# 制約条件を定義
prob += blood_type_A + blood_type_B + blood_type_O >= 100
prob += blood_type_A >= 20
prob += blood_type_B >= 30
prob += blood_type_O >= 40

# 最適化を実行
prob.solve()

# 結果を表示
print('Blood Type A: ', blood_type_A.value())
print('Blood Type B: ', blood_type_B.value())
print('Blood Type O: ', blood_type_O.value())
print('Total Cost: ', value(prob.objective))

[実行結果]

Blood Type A:  30.0
Blood Type B:  30.0
Blood Type O:  40.0
Total Cost:  2100.0

この結果から、血液の種類Aが30、種類Bが30、種類Oが40必要であり、総コストが2100であることが確認できました。

音楽推薦最適化問題 PuLP

音楽推薦最適化問題

音楽推薦の最適化問題PuLPを用いて解く例題を以下に示します。

この問題では、複数の楽曲を聴取したユーザーが、各楽曲に対して評価を付けたデータを利用して、ユーザーに最適な楽曲の推薦リストを作成します。

推薦リストは、ユーザーが楽曲を聴取するためにかかる時間の合計を最小限に抑えるように決定します。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# PuLPをインポートする
from pulp import *

# データを定義する
users = ['User 1', 'User 2', 'User 3', 'User 4']
songs = ['Song 1', 'Song 2', 'Song 3', 'Song 4']
ratings = {
('User 1', 'Song 1'): 3,
('User 1', 'Song 2'): 4,
('User 1', 'Song 3'): 5,
('User 1', 'Song 4'): 2,
('User 2', 'Song 1'): 5,
('User 2', 'Song 2'): 4,
('User 2', 'Song 3'): 2,
('User 2', 'Song 4'): 3,
('User 3', 'Song 1'): 4,
('User 3', 'Song 2'): 5,
('User 3', 'Song 3'): 3,
('User 3', 'Song 4'): 4,
('User 4', 'Song 1'): 2,
('User 4', 'Song 2'): 3,
('User 4', 'Song 3'): 4,
('User 4', 'Song 4'): 5
}
time_limits = {
'User 1': 60,
'User 2': 90,
'User 3': 120,
'User 4': 60
}

# 問題を定義する
prob = LpProblem("Music Recommendation", LpMinimize)

# 変数を定義する
x = LpVariable.dicts('x', [(u, s) for u in users for s in songs], cat='Binary')

# 目的関数を定義する
prob += lpSum([x[(u, s)] * ratings[(u, s)] for u in users for s in songs])

# 制約条件を追加する
for u in users:
prob += lpSum([x[(u, s)] for s in songs]) <= len(songs) // 2, f"User {u} - Song count"
prob += lpSum([x[(u, s)] * ratings[(u, s)] for s in songs]) >= 3, f"User {u} - Minimum rating"
prob += lpSum([x[(u, s)] * ratings[(u, s)] for s in songs]) <= 5, f"User {u} - Maximum rating"
prob += lpSum([x[(u, s)] * ratings[(u, s)] for s in songs]) * 5 <= time_limits[u], f"User

[実行結果]

Status: Optimal

Total rating: 12.0

User 1 recommendations: ['Song 1']

User 2 recommendations: ['Song 4']

User 3 recommendations: ['Song 3']

User 4 recommendations: ['Song 2']

この結果から、各ユーザーにおすすめする曲を決定することができます。

たとえば、User 1 には ‘Song 1’ をおすすめすることができます。

また、最適化問題の総合評価が 12 であることから、ユーザーが評価する曲の総合的な評価を最大化しつつ、制約条件を満たす最適な曲の選択を行っていることがわかります。