Upload 2 files
Browse files- app.py +133 -0
- requirements.txt +75 -0
app.py
ADDED
@@ -0,0 +1,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 |
+
# Set up the button click event to call the calculator function
|
122 |
+
submit_btn.click(
|
123 |
+
bounded_knapsack_problem_solver,
|
124 |
+
inputs=[target, df],
|
125 |
+
outputs=[result],
|
126 |
+
)
|
127 |
+
|
128 |
+
# Launch the Gradio application
|
129 |
+
demo.queue(api_open=False)
|
130 |
+
demo.launch(max_threads=5, share=False)
|
131 |
+
|
132 |
+
if __name__ == "__main__":
|
133 |
+
demo.launch()
|
requirements.txt
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
aiofiles==23.2.1 ; python_version >= "3.10" and python_version < "4.0"
|
2 |
+
altair==5.3.0 ; python_version >= "3.10" and python_version < "4.0"
|
3 |
+
annotated-types==0.7.0 ; python_version >= "3.10" and python_version < "4.0"
|
4 |
+
anyio==4.4.0 ; python_version >= "3.10" and python_version < "4.0"
|
5 |
+
attrs==23.2.0 ; python_version >= "3.10" and python_version < "4.0"
|
6 |
+
certifi==2024.7.4 ; python_version >= "3.10" and python_version < "4.0"
|
7 |
+
charset-normalizer==3.3.2 ; python_version >= "3.10" and python_version < "4.0"
|
8 |
+
click==8.1.7 ; python_version >= "3.10" and python_version < "4.0"
|
9 |
+
colorama==0.4.6 ; python_version >= "3.10" and python_version < "4.0" and (platform_system == "Windows" or sys_platform == "win32")
|
10 |
+
contourpy==1.2.1 ; python_version >= "3.10" and python_version < "4.0"
|
11 |
+
cycler==0.12.1 ; python_version >= "3.10" and python_version < "4.0"
|
12 |
+
dnspython==2.6.1 ; python_version >= "3.10" and python_version < "4.0"
|
13 |
+
email-validator==2.2.0 ; python_version >= "3.10" and python_version < "4.0"
|
14 |
+
exceptiongroup==1.2.2 ; python_version >= "3.10" and python_version < "3.11"
|
15 |
+
fastapi-cli==0.0.4 ; python_version >= "3.10" and python_version < "4.0"
|
16 |
+
fastapi==0.111.1 ; python_version >= "3.10" and python_version < "4.0"
|
17 |
+
ffmpy==0.3.2 ; python_version >= "3.10" and python_version < "4.0"
|
18 |
+
filelock==3.15.4 ; python_version >= "3.10" and python_version < "4.0"
|
19 |
+
fonttools==4.53.1 ; python_version >= "3.10" and python_version < "4.0"
|
20 |
+
fsspec==2024.6.1 ; python_version >= "3.10" and python_version < "4.0"
|
21 |
+
gradio-client==0.16.3 ; python_version >= "3.10" and python_version < "4.0"
|
22 |
+
gradio==4.31.3 ; python_version >= "3.10" and python_version < "4.0"
|
23 |
+
h11==0.14.0 ; python_version >= "3.10" and python_version < "4.0"
|
24 |
+
httpcore==1.0.5 ; python_version >= "3.10" and python_version < "4.0"
|
25 |
+
httptools==0.6.1 ; python_version >= "3.10" and python_version < "4.0"
|
26 |
+
httpx==0.27.0 ; python_version >= "3.10" and python_version < "4.0"
|
27 |
+
huggingface-hub==0.23.4 ; python_version >= "3.10" and python_version < "4.0"
|
28 |
+
idna==3.7 ; python_version >= "3.10" and python_version < "4.0"
|
29 |
+
importlib-resources==6.4.0 ; python_version >= "3.10" and python_version < "4.0"
|
30 |
+
jinja2==3.1.4 ; python_version >= "3.10" and python_version < "4.0"
|
31 |
+
jsonschema-specifications==2023.12.1 ; python_version >= "3.10" and python_version < "4.0"
|
32 |
+
jsonschema==4.23.0 ; python_version >= "3.10" and python_version < "4.0"
|
33 |
+
kiwisolver==1.4.5 ; python_version >= "3.10" and python_version < "4.0"
|
34 |
+
markdown-it-py==3.0.0 ; python_version >= "3.10" and python_version < "4.0"
|
35 |
+
markupsafe==2.1.5 ; python_version >= "3.10" and python_version < "4.0"
|
36 |
+
matplotlib==3.9.1 ; python_version >= "3.10" and python_version < "4.0"
|
37 |
+
mdurl==0.1.2 ; python_version >= "3.10" and python_version < "4.0"
|
38 |
+
numpy==1.26.4 ; python_version >= "3.10" and python_version < "4.0"
|
39 |
+
orjson==3.10.6 ; python_version >= "3.10" and python_version < "4.0"
|
40 |
+
packaging==24.1 ; python_version >= "3.10" and python_version < "4.0"
|
41 |
+
pandas==2.2.2 ; python_version >= "3.10" and python_version < "4.0"
|
42 |
+
pillow==10.4.0 ; python_version >= "3.10" and python_version < "4.0"
|
43 |
+
pulp==2.9.0 ; python_version >= "3.10" and python_version < "4.0"
|
44 |
+
pydantic-core==2.20.1 ; python_version >= "3.10" and python_version < "4.0"
|
45 |
+
pydantic==2.8.2 ; python_version >= "3.10" and python_version < "4.0"
|
46 |
+
pydub==0.25.1 ; python_version >= "3.10" and python_version < "4.0"
|
47 |
+
pygments==2.18.0 ; python_version >= "3.10" and python_version < "4.0"
|
48 |
+
pyparsing==3.1.2 ; python_version >= "3.10" and python_version < "4.0"
|
49 |
+
python-dateutil==2.9.0.post0 ; python_version >= "3.10" and python_version < "4.0"
|
50 |
+
python-dotenv==1.0.1 ; python_version >= "3.10" and python_version < "4.0"
|
51 |
+
python-multipart==0.0.9 ; python_version >= "3.10" and python_version < "4.0"
|
52 |
+
pytz==2024.1 ; python_version >= "3.10" and python_version < "4.0"
|
53 |
+
pyyaml==6.0.1 ; python_version >= "3.10" and python_version < "4.0"
|
54 |
+
referencing==0.35.1 ; python_version >= "3.10" and python_version < "4.0"
|
55 |
+
requests==2.32.3 ; python_version >= "3.10" and python_version < "4.0"
|
56 |
+
rich==13.7.1 ; python_version >= "3.10" and python_version < "4.0"
|
57 |
+
rpds-py==0.19.0 ; python_version >= "3.10" and python_version < "4.0"
|
58 |
+
ruff==0.5.2 ; python_version >= "3.10" and python_version < "4.0" and sys_platform != "emscripten"
|
59 |
+
semantic-version==2.10.0 ; python_version >= "3.10" and python_version < "4.0"
|
60 |
+
shellingham==1.5.4 ; python_version >= "3.10" and python_version < "4.0"
|
61 |
+
six==1.16.0 ; python_version >= "3.10" and python_version < "4.0"
|
62 |
+
sniffio==1.3.1 ; python_version >= "3.10" and python_version < "4.0"
|
63 |
+
starlette==0.37.2 ; python_version >= "3.10" and python_version < "4.0"
|
64 |
+
tomlkit==0.12.0 ; python_version >= "3.10" and python_version < "4.0"
|
65 |
+
toolz==0.12.1 ; python_version >= "3.10" and python_version < "4.0"
|
66 |
+
tqdm==4.66.4 ; python_version >= "3.10" and python_version < "4.0"
|
67 |
+
typer==0.12.3 ; python_version >= "3.10" and python_version < "4.0"
|
68 |
+
typing-extensions==4.12.2 ; python_version >= "3.10" and python_version < "4.0"
|
69 |
+
tzdata==2024.1 ; python_version >= "3.10" and python_version < "4.0"
|
70 |
+
urllib3==2.2.2 ; python_version >= "3.10" and python_version < "4.0"
|
71 |
+
uvicorn==0.30.1 ; python_version >= "3.10" and python_version < "4.0" and sys_platform != "emscripten"
|
72 |
+
uvicorn[standard]==0.30.1 ; python_version >= "3.10" and python_version < "4.0"
|
73 |
+
uvloop==0.19.0 ; (sys_platform != "win32" and sys_platform != "cygwin") and platform_python_implementation != "PyPy" and python_version >= "3.10" and python_version < "4.0"
|
74 |
+
watchfiles==0.22.0 ; python_version >= "3.10" and python_version < "4.0"
|
75 |
+
websockets==11.0.3 ; python_version >= "3.10" and python_version < "4.0"
|