HowardZhangdqs commited on
Commit
f2a4894
·
1 Parent(s): efbecf0

feat: main features

Browse files
Files changed (2) hide show
  1. app.py +237 -0
  2. style.css +7 -0
app.py ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+ import numpy as np
3
+ import gradio as gr
4
+ import pandas as pd
5
+ from deap import base, creator, tools
6
+
7
+ # 全局变量存储优化状态
8
+ state = {
9
+ "toolbox": None,
10
+ "population": None,
11
+ "current_idx": 0,
12
+ "current_gen": 0,
13
+ "history": [],
14
+ "best_ind": None,
15
+ "running": False,
16
+ "params": {}
17
+ }
18
+
19
+
20
+ def create_individual(min_max):
21
+ return [
22
+ random.uniform(min_max["kp_min"], min_max["kp_max"]),
23
+ random.uniform(min_max["ki_min"], min_max["ki_max"]),
24
+ random.uniform(min_max["kd_min"], min_max["kd_max"])
25
+ ]
26
+
27
+
28
+ def init_toolbox(min_max):
29
+ if "FitnessMax" in creator.__dict__:
30
+ del creator.FitnessMax
31
+ if "Individual" in creator.__dict__:
32
+ del creator.Individual
33
+
34
+ creator.create("FitnessMax", base.Fitness, weights=(1.0,))
35
+ creator.create("Individual", list, fitness=creator.FitnessMax)
36
+
37
+ toolbox = base.Toolbox()
38
+ toolbox.register("individual", tools.initIterate, creator.Individual,
39
+ lambda: create_individual(min_max))
40
+ toolbox.register("population", tools.initRepeat, list, toolbox.individual)
41
+ toolbox.register("mate", tools.cxBlend, alpha=0.5)
42
+ toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=0.1, indpb=0.2)
43
+ toolbox.register("select", tools.selTournament, tournsize=3)
44
+ return toolbox
45
+
46
+
47
+ def start_optimization(kp_min, kp_max, ki_min, ki_max, kd_min, kd_max,
48
+ pop_size, max_gen, cx_prob, mut_prob):
49
+ state.update({
50
+ "params": {
51
+ "kp_range": (kp_min, kp_max),
52
+ "ki_range": (ki_min, ki_max),
53
+ "kd_range": (kd_min, kd_max),
54
+ "pop_size": pop_size,
55
+ "max_gen": max_gen,
56
+ "cx_prob": cx_prob,
57
+ "mut_prob": mut_prob
58
+ },
59
+ "current_gen": 0,
60
+ "history": [],
61
+ "best_ind": None,
62
+ "running": True
63
+ })
64
+
65
+ min_max = {
66
+ "kp_min": kp_min, "kp_max": kp_max,
67
+ "ki_min": ki_min, "ki_max": ki_max,
68
+ "kd_min": kd_min, "kd_max": kd_max
69
+ }
70
+
71
+ toolbox = init_toolbox(min_max)
72
+ population = toolbox.population(n=pop_size)
73
+
74
+ state.update({
75
+ "toolbox": toolbox,
76
+ "population": population,
77
+ "current_idx": 0
78
+ })
79
+
80
+ first_ind = population[0]
81
+ return {
82
+ current_params: f"Kp: {first_ind[0]:.4f}, Ki: {first_ind[1]:.4f}, Kd: {first_ind[2]:.4f}",
83
+ fitness_input: "",
84
+ history_output: pd.DataFrame(columns=["Kp", "Ki", "Kd", "Fitness"]),
85
+ best_output: "最佳参数:尚未找到"
86
+ }
87
+
88
+
89
+ def submit_fitness(fitness):
90
+ if not state["running"]:
91
+ return {current_params: "优化未运行"}
92
+
93
+ population = state["population"]
94
+ idx = state["current_idx"]
95
+ ind = population[idx]
96
+
97
+ # 记录适应度
98
+ ind.fitness.values = (float(fitness),)
99
+ state["history"].append({
100
+ "Kp": ind[0], "Ki": ind[1], "Kd": ind[2], "Fitness": float(fitness)
101
+ })
102
+
103
+ # 更新最佳个体
104
+ if state["best_ind"] is None or ind.fitness > state["best_ind"].fitness:
105
+ state["best_ind"] = ind
106
+
107
+ # 移动到下一个个体
108
+ state["current_idx"] += 1
109
+
110
+ # 检查是否完成当前种群评估
111
+ if state["current_idx"] >= len(population):
112
+ evolve_population()
113
+ state["current_idx"] = 0
114
+ state["current_gen"] += 1
115
+
116
+ # 检查终止条件
117
+ if state["current_gen"] >= state["params"]["max_gen"]:
118
+ state["running"] = False
119
+ return {
120
+ current_params: "优化完成!",
121
+ best_output: format_best(state["best_ind"])
122
+ }
123
+
124
+ next_ind = population[state["current_idx"]]
125
+ return {
126
+ current_params: f"Kp: {next_ind[0]:.4f}, Ki: {next_ind[1]:.4f}, Kd: {next_ind[2]:.4f}",
127
+ fitness_input: "",
128
+ history_output: pd.DataFrame(state["history"]),
129
+ best_output: format_best(state["best_ind"])
130
+ }
131
+
132
+
133
+ def evolve_population():
134
+ params = state["params"]
135
+ toolbox = state["toolbox"]
136
+ population = state["population"]
137
+
138
+ # 选择
139
+ offspring = toolbox.select(population, len(population))
140
+ offspring = list(map(toolbox.clone, offspring))
141
+
142
+ # 交叉
143
+ for child1, child2 in zip(offspring[::2], offspring[1::2]):
144
+ if random.random() < params["cx_prob"]:
145
+ toolbox.mate(child1, child2)
146
+ del child1.fitness.values
147
+ del child2.fitness.values
148
+
149
+ # 变异
150
+ for mutant in offspring:
151
+ if random.random() < params["mut_prob"]:
152
+ toolbox.mutate(mutant)
153
+ # 参数裁剪
154
+ mutant[0] = np.clip(mutant[0], *params["kp_range"])
155
+ mutant[1] = np.clip(mutant[1], *params["ki_range"])
156
+ mutant[2] = np.clip(mutant[2], *params["kd_range"])
157
+ del mutant.fitness.values
158
+
159
+ state["population"] = offspring
160
+
161
+
162
+ def stop_optimization():
163
+ state["running"] = False
164
+ return {
165
+ current_params: "优化已终止",
166
+ fitness_input: ""
167
+ }
168
+
169
+
170
+ def format_best(ind):
171
+ if ind is None:
172
+ return "最佳参数:尚未找到"
173
+ return f"最佳参数:Kp={ind[0]:.4f}, Ki={ind[1]:.4f}, Kd={ind[2]:.4f} 适应度={ind.fitness.values[0]:.4f}"
174
+
175
+
176
+ with gr.Blocks(title="青云调参", css_paths="./style.css") as demo:
177
+ gr.HTML("<h1 style='text-align: center;'>青云调参</h1><div style='text-align: center;'>适者存千代竞逐,精微处三昧调弦</div>")
178
+
179
+ with gr.Row():
180
+ with gr.Column(scale=1):
181
+ with gr.Row():
182
+ start_btn = gr.Button("开始优化", variant="primary")
183
+ stop_btn = gr.Button("终止优化")
184
+
185
+ with gr.Row():
186
+ kp_min = gr.Number(label="Kp最小值", value=0.0)
187
+ kp_max = gr.Number(label="Kp最大值", value=10.0)
188
+
189
+ with gr.Row():
190
+ ki_min = gr.Number(label="Ki最小值", value=0.0)
191
+ ki_max = gr.Number(label="Ki最大值", value=10.0)
192
+
193
+ with gr.Row():
194
+ kd_min = gr.Number(label="Kd最小值", value=0.0)
195
+ kd_max = gr.Number(label="Kd最大值", value=10.0)
196
+
197
+ pop_size = gr.Slider(2, 50, value=5, step=1, label="种群大小")
198
+ max_gen = gr.Slider(1, 50, value=10, step=1, label="迭代次数")
199
+ cx_prob = gr.Slider(0.0, 1.0, value=0.7, step=0.05, label="交叉概率")
200
+ mut_prob = gr.Slider(0.0, 1.0, value=0.2, step=0.05, label="变异概率")
201
+
202
+ with gr.Column(scale=2):
203
+ current_params = gr.Textbox(label="当前参数组合", interactive=False)
204
+ with gr.Row():
205
+ fitness_input = gr.Number(label="输入适应度值")
206
+ submit_btn = gr.Button("提交适应度")
207
+
208
+ gr.Markdown("## 最佳参数")
209
+ best_output = gr.Textbox(label="当前最佳参数", interactive=False)
210
+
211
+ gr.Markdown("## 优化历史")
212
+ history_output = gr.Dataframe(
213
+ headers=["Kp", "Ki", "Kd", "Fitness"],
214
+ datatype=["number", "number", "number", "number"],
215
+ interactive=False
216
+ )
217
+
218
+ start_btn.click(
219
+ start_optimization,
220
+ inputs=[kp_min, kp_max, ki_min, ki_max, kd_min, kd_max,
221
+ pop_size, max_gen, cx_prob, mut_prob],
222
+ outputs=[current_params, fitness_input, history_output, best_output]
223
+ )
224
+
225
+ submit_btn.click(
226
+ submit_fitness,
227
+ inputs=fitness_input,
228
+ outputs=[current_params, fitness_input, history_output, best_output]
229
+ )
230
+
231
+ stop_btn.click(
232
+ stop_optimization,
233
+ outputs=[current_params, fitness_input]
234
+ )
235
+
236
+ if __name__ == "__main__":
237
+ demo.launch()
style.css ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ textarea {
2
+ font-family: var(--font-mono);
3
+ }
4
+
5
+ footer {
6
+ display: none !important;
7
+ }