Add main project files
Browse files- app.py +143 -0
- plants.csv +53 -0
- requirements.txt +0 -0
app.py
ADDED
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import pandas as pd
|
3 |
+
import pulp
|
4 |
+
import numpy as np
|
5 |
+
|
6 |
+
LANGUAGE = "en"
|
7 |
+
|
8 |
+
# Define the quality tiers and names for the plants
|
9 |
+
PLANTS_TIERS = {
|
10 |
+
"radiant": "金品质",
|
11 |
+
"flourishing": "紫品质",
|
12 |
+
"hardy": "蓝品质",
|
13 |
+
"feeble": "白品质",
|
14 |
+
}
|
15 |
+
|
16 |
+
PLANTS_I18N = {
|
17 |
+
"fanged_geranium": "毒牙天竺葵",
|
18 |
+
"gillyweed": "鳃囊草",
|
19 |
+
"rose": "玫瑰",
|
20 |
+
"puffapod": "泡泡豆荚",
|
21 |
+
"nifflers_fancy": "嗅幻草",
|
22 |
+
"ladys_mantle": "羽衣草",
|
23 |
+
"mandrake": "曼德拉草",
|
24 |
+
"chinese_chomping_cabbage": "中国咬人甘蓝",
|
25 |
+
"peony": "牡丹",
|
26 |
+
"begonia": "秋海棠",
|
27 |
+
"mayflower": "五月花",
|
28 |
+
"hydrangea": "绣球",
|
29 |
+
"daffodil": "水仙",
|
30 |
+
}
|
31 |
+
|
32 |
+
# Import and process plant data
|
33 |
+
df = pd.read_csv("plants.csv")
|
34 |
+
|
35 |
+
# Convert columns to Categorical type and remove rows with NaN in 'gold' column
|
36 |
+
df["species"] = pd.Categorical(df["species"])
|
37 |
+
df["tier"] = pd.Categorical(df["tier"])
|
38 |
+
df = df.dropna(subset=["gold"])
|
39 |
+
df = df.astype(
|
40 |
+
{
|
41 |
+
"gold": int,
|
42 |
+
"gems": int,
|
43 |
+
}
|
44 |
+
)
|
45 |
+
|
46 |
+
|
47 |
+
def calculator(*args):
|
48 |
+
"""
|
49 |
+
Calculate the optimal solution of plant sales based on the given budget
|
50 |
+
and inventory constraints.
|
51 |
+
|
52 |
+
Args:
|
53 |
+
*args (tuple): A tuple where the first element is Gabby's gold budget,
|
54 |
+
and the subsequent elements represent the stock levels of
|
55 |
+
each plant type.
|
56 |
+
|
57 |
+
Returns:
|
58 |
+
str: A description of the optimal solution, including which plants to sell,
|
59 |
+
the total gold earned, and the remaining inventory.
|
60 |
+
"""
|
61 |
+
budget = args[0] # 葭碧预算
|
62 |
+
stocks = np.array(args[1:]) # 植物库存
|
63 |
+
|
64 |
+
# 植物名称列表
|
65 |
+
plants_en = [f"{row['tier']}_{row['species']}" for index, row in df.iterrows()]
|
66 |
+
|
67 |
+
gold = np.array(df["gold"]) # 植物单价
|
68 |
+
|
69 |
+
# 创建问题实例,目标是最大化存货数量
|
70 |
+
prob = pulp.LpProblem("Maximize_Sale", pulp.LpMaximize)
|
71 |
+
|
72 |
+
# 决策变量,售出每种植物的件数,必须是整数
|
73 |
+
x = pulp.LpVariable.dicts("x", range(len(stocks)), lowBound=0, cat="Integer")
|
74 |
+
|
75 |
+
# 遍历,设置决策变量的上界为库存量
|
76 |
+
for i in range(len(stocks)):
|
77 |
+
x[i].upBound = stocks[i]
|
78 |
+
|
79 |
+
# 目标函数:最大化总的存货数量
|
80 |
+
prob += pulp.lpSum([stocks[i] - x[i] for i in range(len(stocks))])
|
81 |
+
|
82 |
+
# 约束条件:每类产品售出数量乘以单价之和等于总价格
|
83 |
+
prob += pulp.lpSum([gold[i] * x[i] for i in range(len(stocks))]) == budget
|
84 |
+
|
85 |
+
# 求解问题
|
86 |
+
# CBC(Coin-or Branch and Cut)求解器使用分支定界算法来寻找整数规划问题的最优解
|
87 |
+
solver = pulp.getSolver("PULP_CBC_CMD")
|
88 |
+
prob.solve(solver=solver)
|
89 |
+
|
90 |
+
if pulp.LpStatus[prob.status] == "Optimal":
|
91 |
+
|
92 |
+
sold = 0
|
93 |
+
solution = []
|
94 |
+
for i, v in x.items():
|
95 |
+
if v.varValue:
|
96 |
+
if v.varValue > 0:
|
97 |
+
solution.append(f"{plants_en[i]}: {int(v.varValue)}\n")
|
98 |
+
sold += int(v.varValue) * gold[i]
|
99 |
+
|
100 |
+
return f"Optimal solution found:\n\n{''.join(solution)}\nTotal price: {sold}\nStock: {pulp.value(prob.objective)}"
|
101 |
+
else:
|
102 |
+
return "No solution found."
|
103 |
+
|
104 |
+
|
105 |
+
# Create a Gradio interface with a column layout
|
106 |
+
with gr.Blocks() as demo:
|
107 |
+
with gr.Column():
|
108 |
+
# Add a row for the budget input
|
109 |
+
with gr.Row():
|
110 |
+
budget = gr.Number(
|
111 |
+
label="Gold Budget", value=0, minimum=0, maximum=15000, step=100
|
112 |
+
)
|
113 |
+
|
114 |
+
# Add a row for the plant inventory inputs
|
115 |
+
with gr.Row():
|
116 |
+
inventory = {}
|
117 |
+
for index, row in df.iterrows():
|
118 |
+
inventory[f"{row['tier']}_{row['species']}"] = gr.Number(
|
119 |
+
label=f"{row['tier']}_{row['species']}",
|
120 |
+
value=0,
|
121 |
+
minimum=0,
|
122 |
+
maximum=500,
|
123 |
+
step=10,
|
124 |
+
)
|
125 |
+
|
126 |
+
# Add a button to trigger the calculation
|
127 |
+
submit_btn = gr.Button(value="Calculate")
|
128 |
+
|
129 |
+
# Add a row for the result textbox
|
130 |
+
with gr.Row():
|
131 |
+
result = gr.Textbox()
|
132 |
+
|
133 |
+
# Set up the button click event to call the calculator function
|
134 |
+
submit_btn.click(
|
135 |
+
calculator,
|
136 |
+
inputs=[budget] + list(inventory.values()),
|
137 |
+
outputs=[result],
|
138 |
+
api_name=False,
|
139 |
+
)
|
140 |
+
|
141 |
+
# Launch the Gradio application
|
142 |
+
if __name__ == "__main__":
|
143 |
+
demo.launch(show_api=False)
|
plants.csv
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
gold,gems,species,tier,amount
|
2 |
+
12,0,fanged_geranium,radiant,0
|
3 |
+
9,0,fanged_geranium,flourishing,0
|
4 |
+
8,0,fanged_geranium,hardy,0
|
5 |
+
1,0,fanged_geranium,feeble,0
|
6 |
+
6,0,gillyweed,radiant,0
|
7 |
+
4,0,gillyweed,flourishing,0
|
8 |
+
3,0,gillyweed,hardy,0
|
9 |
+
1,0,gillyweed,feeble,0
|
10 |
+
42,0,rose,radiant,0
|
11 |
+
34,0,rose,flourishing,0
|
12 |
+
30,0,rose,hardy,0
|
13 |
+
,0,rose,feeble,0
|
14 |
+
85,0,puffapod,radiant,0
|
15 |
+
62,0,puffapod,flourishing,0
|
16 |
+
55,0,puffapod,hardy,0
|
17 |
+
,0,puffapod,feeble,0
|
18 |
+
0,5,nifflers_fancy,radiant,0
|
19 |
+
260,0,nifflers_fancy,flourishing,0
|
20 |
+
234,0,nifflers_fancy,hardy,0
|
21 |
+
1,0,nifflers_fancy,feeble,0
|
22 |
+
105,0,ladys_mantle,radiant,0
|
23 |
+
96,0,ladys_mantle,flourishing,0
|
24 |
+
76,0,ladys_mantle,hardy,0
|
25 |
+
,0,ladys_mantle,feeble,0
|
26 |
+
24,0,mandrake,radiant,0
|
27 |
+
22,0,mandrake,flourishing,0
|
28 |
+
15,0,mandrake,hardy,0
|
29 |
+
,0,mandrake,feeble,0
|
30 |
+
57,0,chinese_chomping_cabbage,radiant,0
|
31 |
+
40,0,chinese_chomping_cabbage,flourishing,0
|
32 |
+
36,0,chinese_chomping_cabbage,hardy,0
|
33 |
+
,0,chinese_chomping_cabbage,feeble,0
|
34 |
+
0,2,peony,radiant,0
|
35 |
+
58,0,peony,flourishing,0
|
36 |
+
45,0,peony,hardy,0
|
37 |
+
1,0,peony,feeble,0
|
38 |
+
72,0,begonia,radiant,0
|
39 |
+
58,0,begonia,flourishing,0
|
40 |
+
,0,begonia,hardy,0
|
41 |
+
,0,begonia,feeble,0
|
42 |
+
186,0,mayflower,radiant,0
|
43 |
+
,0,mayflower,flourishing,0
|
44 |
+
,0,mayflower,hardy,0
|
45 |
+
,0,mayflower,feeble,0
|
46 |
+
215,0,hydrangea,radiant,0
|
47 |
+
,0,hydrangea,flourishing,0
|
48 |
+
,0,hydrangea,hardy,0
|
49 |
+
,0,hydrangea,feeble,0
|
50 |
+
0,2,daffodil,radiant,0
|
51 |
+
,0,daffodil,flourishing,0
|
52 |
+
,0,daffodil,hardy,0
|
53 |
+
,0,daffodil,feeble,0
|
requirements.txt
ADDED
Binary file (2.72 kB). View file
|
|