add examples
Browse files
app.py
CHANGED
@@ -1,133 +1,149 @@
|
|
1 |
-
import gradio as gr
|
2 |
-
import numpy as np
|
3 |
-
import pulp
|
4 |
-
|
5 |
-
|
6 |
-
def bounded_knapsack_problem_solver(target, df):
|
7 |
-
|
8 |
-
name_ls = []
|
9 |
-
for index, item in enumerate(df["name"]):
|
10 |
-
if item:
|
11 |
-
name_ls.append(item)
|
12 |
-
else:
|
13 |
-
name_ls.append(f"📦{str(index+1)}")
|
14 |
-
|
15 |
-
if len(name_ls) != len(set(name_ls)):
|
16 |
-
return "Please check for duplicate item names and try again."
|
17 |
-
|
18 |
-
items = np.array(name_ls) # 物品名称
|
19 |
-
prices = np.array([int(p) if p else 0 for p in df["value"]]) # 物品单价
|
20 |
-
stocks = np.array([int(c) if c else 0 for c in df["count"]]) # 物品数量
|
21 |
-
|
22 |
-
# 创建问题实例,最大化物品总价值
|
23 |
-
prob = pulp.LpProblem("Maximize_Value", pulp.LpMaximize)
|
24 |
-
|
25 |
-
# 决策变量,装入背包的物品物品组合,件数必须是整数
|
26 |
-
x = pulp.LpVariable.dicts("x", range(len(prices)), lowBound=0, cat="Integer")
|
27 |
-
|
28 |
-
# 遍历,设置决策变量的上界为库存量
|
29 |
-
for i in range(len(stocks)):
|
30 |
-
x[i].upBound = stocks[i]
|
31 |
-
|
32 |
-
# 目标函数:最大化物品总价值
|
33 |
-
prob += pulp.lpSum([prices[i] * x[i] for i in range(len(stocks))])
|
34 |
-
|
35 |
-
# 添加约束条件: 总价值小于等于目标值
|
36 |
-
prob += pulp.lpSum([prices[i] * x[i] for i in range(len(stocks))]) <= target
|
37 |
-
|
38 |
-
# 求解问题
|
39 |
-
# CBC(Coin-or Branch and Cut)求解器使用分支定界算法来寻找整数规划问题的最优解
|
40 |
-
solver = pulp.getSolver("PULP_CBC_CMD")
|
41 |
-
prob.solve(solver=solver)
|
42 |
-
|
43 |
-
if pulp.LpStatus[prob.status] == "Optimal":
|
44 |
-
|
45 |
-
value = 0
|
46 |
-
solution = []
|
47 |
-
for i, v in x.items():
|
48 |
-
if v.varValue:
|
49 |
-
if v.varValue > 0:
|
50 |
-
solution.append(f"{items[i]}(${prices[i]}): {int(v.varValue)}\n")
|
51 |
-
value += int(v.varValue) * prices[i]
|
52 |
-
if value == target:
|
53 |
-
return f"Optimal solution found:\n\n{''.join(solution)}\nTotal value: {value}\nGreat! Found a combination of items with a total value equal to the target value(${target}).😃"
|
54 |
-
|
55 |
-
else:
|
56 |
-
return f"Optimal solution found:\n\n{''.join(solution)}\nTotal value: {value}\n${target - value} short of the target value(${target}).😂"
|
57 |
-
|
58 |
-
|
59 |
-
# Create a Gradio interface with a column layout
|
60 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
61 |
-
gr.Markdown(
|
62 |
-
"""
|
63 |
-
<center><font size=8>📦Easy Bounded Knapsack Problem Solver📦</center>
|
64 |
-
|
65 |
-
### Given
|
66 |
-
|
67 |
-
- A set of items, each with:
|
68 |
-
- Value ( v_i )
|
69 |
-
- Maximum quantity ( q_i )
|
70 |
-
- A target value ( T )
|
71 |
-
|
72 |
-
### Objective
|
73 |
-
|
74 |
-
Find a combination of items such that the sum of the selected items' values equals ( T )
|
75 |
-
or maximizes the total value without exceeding ( T ).
|
76 |
-
Each item ( i ) can be selected up to ( q_i ) times.
|
77 |
-
"""
|
78 |
-
)
|
79 |
-
|
80 |
-
with gr.Column():
|
81 |
-
# Add a row for the target input
|
82 |
-
target = gr.Number(
|
83 |
-
label="Target",
|
84 |
-
info="number less than 50,000",
|
85 |
-
value=0,
|
86 |
-
precision=0,
|
87 |
-
minimum=0,
|
88 |
-
maximum=50000,
|
89 |
-
step=100,
|
90 |
-
)
|
91 |
-
|
92 |
-
df = gr.Dataframe(
|
93 |
-
headers=["name", "value", "count"],
|
94 |
-
datatype=["str", "number", "number"],
|
95 |
-
row_count=3,
|
96 |
-
col_count=(3, "fixed"),
|
97 |
-
label="Items",
|
98 |
-
)
|
99 |
-
|
100 |
-
# Add a radio selection for the strategy
|
101 |
-
# condition = gr.Radio(
|
102 |
-
# [
|
103 |
-
# ("最小化物品数量(优先选择高价物品)", "MinimizeCount"),
|
104 |
-
# ("最大化物品数量(优先选择低价物品)", "MaximizeCount"),
|
105 |
-
# ],
|
106 |
-
# value="MinimizeCount",
|
107 |
-
# label="Condition",
|
108 |
-
# )
|
109 |
-
|
110 |
-
# Add a row for the Clear and Calculate buttons
|
111 |
-
with gr.Row():
|
112 |
-
clear_btn = gr.ClearButton(df, size="sm", value="❌Clear")
|
113 |
-
|
114 |
-
# Add a button to trigger the calculation
|
115 |
-
submit_btn = gr.Button(value="🛠Calculate")
|
116 |
-
|
117 |
-
# Add a row for the result textbox
|
118 |
-
with gr.Row():
|
119 |
-
result = gr.Textbox(label="Output")
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import numpy as np
|
3 |
+
import pulp
|
4 |
+
|
5 |
+
|
6 |
+
def bounded_knapsack_problem_solver(target, df):
|
7 |
+
|
8 |
+
name_ls = []
|
9 |
+
for index, item in enumerate(df["name"]):
|
10 |
+
if item:
|
11 |
+
name_ls.append(item)
|
12 |
+
else:
|
13 |
+
name_ls.append(f"📦{str(index+1)}")
|
14 |
+
|
15 |
+
if len(name_ls) != len(set(name_ls)):
|
16 |
+
return "Please check for duplicate item names and try again."
|
17 |
+
|
18 |
+
items = np.array(name_ls) # 物品名称
|
19 |
+
prices = np.array([int(p) if p else 0 for p in df["value"]]) # 物品单价
|
20 |
+
stocks = np.array([int(c) if c else 0 for c in df["count"]]) # 物品数量
|
21 |
+
|
22 |
+
# 创建问题实例,最大化物品总价值
|
23 |
+
prob = pulp.LpProblem("Maximize_Value", pulp.LpMaximize)
|
24 |
+
|
25 |
+
# 决策变量,装入背包的物品物品组合,件数必须是整数
|
26 |
+
x = pulp.LpVariable.dicts("x", range(len(prices)), lowBound=0, cat="Integer")
|
27 |
+
|
28 |
+
# 遍历,设置决策变量的上界为库存量
|
29 |
+
for i in range(len(stocks)):
|
30 |
+
x[i].upBound = stocks[i]
|
31 |
+
|
32 |
+
# 目标函数:最大化物品总价值
|
33 |
+
prob += pulp.lpSum([prices[i] * x[i] for i in range(len(stocks))])
|
34 |
+
|
35 |
+
# 添加约束条件: 总价值小于等于目标值
|
36 |
+
prob += pulp.lpSum([prices[i] * x[i] for i in range(len(stocks))]) <= target
|
37 |
+
|
38 |
+
# 求解问题
|
39 |
+
# CBC(Coin-or Branch and Cut)求解器使用分支定界算法来寻找整数规划问题的最优解
|
40 |
+
solver = pulp.getSolver("PULP_CBC_CMD")
|
41 |
+
prob.solve(solver=solver)
|
42 |
+
|
43 |
+
if pulp.LpStatus[prob.status] == "Optimal":
|
44 |
+
|
45 |
+
value = 0
|
46 |
+
solution = []
|
47 |
+
for i, v in x.items():
|
48 |
+
if v.varValue:
|
49 |
+
if v.varValue > 0:
|
50 |
+
solution.append(f"{items[i]}(${prices[i]}): {int(v.varValue)}\n")
|
51 |
+
value += int(v.varValue) * prices[i]
|
52 |
+
if value == target:
|
53 |
+
return f"Optimal solution found:\n\n{''.join(solution)}\nTotal value: {value}\nGreat! Found a combination of items with a total value equal to the target value(${target}).😃"
|
54 |
+
|
55 |
+
else:
|
56 |
+
return f"Optimal solution found:\n\n{''.join(solution)}\nTotal value: {value}\n${target - value} short of the target value(${target}).😂"
|
57 |
+
|
58 |
+
|
59 |
+
# Create a Gradio interface with a column layout
|
60 |
+
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
61 |
+
gr.Markdown(
|
62 |
+
"""
|
63 |
+
<center><font size=8>📦Easy Bounded Knapsack Problem Solver📦</center>
|
64 |
+
|
65 |
+
### Given
|
66 |
+
|
67 |
+
- A set of items, each with:
|
68 |
+
- Value ( v_i )
|
69 |
+
- Maximum quantity ( q_i )
|
70 |
+
- A target value ( T )
|
71 |
+
|
72 |
+
### Objective
|
73 |
+
|
74 |
+
Find a combination of items such that the sum of the selected items' values equals ( T )
|
75 |
+
or maximizes the total value without exceeding ( T ).
|
76 |
+
Each item ( i ) can be selected up to ( q_i ) times.
|
77 |
+
"""
|
78 |
+
)
|
79 |
+
|
80 |
+
with gr.Column():
|
81 |
+
# Add a row for the target input
|
82 |
+
target = gr.Number(
|
83 |
+
label="Target",
|
84 |
+
info="number less than 50,000",
|
85 |
+
value=0,
|
86 |
+
precision=0,
|
87 |
+
minimum=0,
|
88 |
+
maximum=50000,
|
89 |
+
step=100,
|
90 |
+
)
|
91 |
+
|
92 |
+
df = gr.Dataframe(
|
93 |
+
headers=["name", "value", "count"],
|
94 |
+
datatype=["str", "number", "number"],
|
95 |
+
row_count=3,
|
96 |
+
col_count=(3, "fixed"),
|
97 |
+
label="Items",
|
98 |
+
)
|
99 |
+
|
100 |
+
# Add a radio selection for the strategy
|
101 |
+
# condition = gr.Radio(
|
102 |
+
# [
|
103 |
+
# ("最小化物品数量(优先选择高价物品)", "MinimizeCount"),
|
104 |
+
# ("最大化物品数量(优先选择低价物品)", "MaximizeCount"),
|
105 |
+
# ],
|
106 |
+
# value="MinimizeCount",
|
107 |
+
# label="Condition",
|
108 |
+
# )
|
109 |
+
|
110 |
+
# Add a row for the Clear and Calculate buttons
|
111 |
+
with gr.Row():
|
112 |
+
clear_btn = gr.ClearButton(df, size="sm", value="❌Clear")
|
113 |
+
|
114 |
+
# Add a button to trigger the calculation
|
115 |
+
submit_btn = gr.Button(value="🛠Calculate")
|
116 |
+
|
117 |
+
# Add a row for the result textbox
|
118 |
+
with gr.Row():
|
119 |
+
result = gr.Textbox(label="Output")
|
120 |
+
|
121 |
+
examples = gr.Examples(
|
122 |
+
examples=[
|
123 |
+
[150, [["", 12, 10], ["", 9, 5], ["", 8, 10]]],
|
124 |
+
[
|
125 |
+
500,
|
126 |
+
[
|
127 |
+
["pencil", 129, 1],
|
128 |
+
["magic keyboard", 349, 1],
|
129 |
+
["homepod", 299, 1],
|
130 |
+
["airpods max", 549, 1],
|
131 |
+
],
|
132 |
+
],
|
133 |
+
],
|
134 |
+
inputs=[target, df],
|
135 |
+
)
|
136 |
+
|
137 |
+
# Set up the button click event to call the calculator function
|
138 |
+
submit_btn.click(
|
139 |
+
bounded_knapsack_problem_solver,
|
140 |
+
inputs=[target, df],
|
141 |
+
outputs=[result],
|
142 |
+
)
|
143 |
+
|
144 |
+
# Launch the Gradio application
|
145 |
+
demo.queue(api_open=False)
|
146 |
+
demo.launch(max_threads=5, share=False)
|
147 |
+
|
148 |
+
if __name__ == "__main__":
|
149 |
+
demo.launch()
|