baoshiwei
2026-04-01 81b0ad0124847f083990d574dc8d20961ec6e713
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
import streamlit as st
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
import numpy as np
import joblib
import os
from datetime import datetime
from sklearn.preprocessing import MinMaxScaler
 
# 页面函数定义
def show_optimized_parameter_adjustment():
    # 页面标题
    st.title("优化版挤出机参数调节建议")
    
    # 添加操作指引
    with st.expander("📖 操作指引", expanded=True):
        st.markdown("""
        欢迎使用优化版挤出机参数调节建议功能!本功能基于多目标优化算法,根据您输入的米重数据和当前参数,为您提供科学合理的参数调整建议。
        
        **操作步骤:**
        1. 选择一个已训练好的模型
        2. 输入米重标准值、上下限和当前挤出机参数
        3. 输入当前实际米重测量值
        4. 调整优化参数(可选)
        5. 点击"计算优化调节建议"按钮
        6. 查看系统生成的参数调整建议
        
        **注意事项:**
        - 请确保输入的参数值在设备允许的范围内
        - 优化算法会平衡米重偏差和调整幅度
        - 历史调节记录可在页面底部查看
        """)
    
    # 初始化会话状态
    if 'optimized_adjustment_history' not in st.session_state:
        st.session_state['optimized_adjustment_history'] = []
    
    # 1. 模型选择区域
    with st.expander("🔍 模型选择", expanded=True):
        # 创建模型目录(如果不存在)
        model_dir = "saved_models"
        os.makedirs(model_dir, exist_ok=True)
        
        # 获取所有已保存的模型文件
        model_files = [f for f in os.listdir(model_dir) if f.endswith('.joblib')]
        model_files.sort(reverse=True)  # 最新的模型排在前面
        
        if not model_files:
            st.warning("尚未保存任何模型,请先训练模型并保存。")
            return
        
        # 模型选择下拉框
        selected_model_file = st.selectbox(
            "选择已保存的模型",
            options=model_files,
            help="选择要用于预测的模型文件"
        )
        
        # 加载并显示模型信息
        if selected_model_file:
            model_path = os.path.join(model_dir, selected_model_file)
            model_info = joblib.load(model_path)
            
            # 显示模型基本信息
            st.subheader("📊 模型信息")
            info_cols = st.columns(2)
            
            with info_cols[0]:
                st.metric("模型类型", model_info['model_type'])
                st.metric("创建时间", model_info['created_at'].strftime('%Y-%m-%d %H:%M:%S'))
                st.metric("使用稳态数据", "是" if model_info.get('use_steady_data', False) else "否")
            
            with info_cols[1]:
                st.metric("R² 得分", f"{model_info['r2_score']:.4f}")
                st.metric("均方误差 (MSE)", f"{model_info['mse']:.6f}")
                st.metric("均方根误差 (RMSE)", f"{model_info['rmse']:.6f}")
            
            # 显示模型特征
            st.write("🔑 模型使用的特征:")
            st.code(", ".join(model_info['features']))
            
            # 如果是深度学习模型,显示序列长度
            if 'sequence_length' in model_info:
                st.metric("序列长度", model_info['sequence_length'])
            
            # 保存模型信息到会话状态
            st.session_state['selected_model'] = model_info
            st.session_state['selected_model_file'] = selected_model_file
    
    # 2. 参数输入区域
    st.subheader("📝 参数输入")
    
    # 2.1 米重标准值、上下限输入
    with st.expander("⚖️ 米重标准与上下限", expanded=True):
        weight_cols = st.columns(3)
        
        with weight_cols[0]:
            standard_weight = st.number_input(
                "标准米重",
                key="standard_weight",
                value=5.20,
                min_value=0.01,
                max_value=10.0,
                step=0.0001,
                format="%.4f",
                help="输入目标米重标准值"
            )
            st.caption("单位: Kg/m")
        
        with weight_cols[1]:
            upper_limit = st.number_input(
                "米重上限",
                key="upper_limit",
                value=5.46,
                min_value=standard_weight,
                max_value=10.0,
                step=0.0001,
                format="%.4f",
                help="输入米重允许的上限值"
            )
            st.caption("单位: Kg/m")
        
        with weight_cols[2]:
            lower_limit = st.number_input(
                "米重下限",
                key="lower_limit",
                value=5.02,
                min_value=0.01,
                max_value=standard_weight,
                step=0.0001,
                format="%.4f",
                help="输入米重允许的下限值"
            )
            st.caption("单位: Kg/m")
    
    # 2.2 挤出机当前参数输入
    with st.expander("🔧 挤出机当前参数", expanded=True):
        param_cols = st.columns(3)
        
        with param_cols[0]:
            current_screw_speed = st.number_input(
                "螺杆转速",
                key="current_screw_speed",
                value=230.0,
                min_value=0.0,
                max_value=500.0,
                step=0.1,
                help="输入当前螺杆转速"
            )
            st.caption("单位: rpm")
            
            current_head_pressure = st.number_input(
                "机头压力",
                key="current_head_pressure",
                value=0.26,
                min_value=0.0,
                max_value=500.0,
                format="%.4f",
                step=1.0,
                help="输入当前机头压力"
            )
            st.caption("单位: bar")
            
            current_process_speed = st.number_input(
                "流程主速",
                key="current_process_speed",
                value=6.6,
                min_value=0.0,
                max_value=300.0,
                step=0.1,
                help="输入当前流程主速"
            )
            st.caption("单位: m/min")
        
        with param_cols[1]:
            current_screw_temperature = st.number_input(
                "螺杆温度",
                key="current_screw_temperature",
                value=79.9,
                min_value=0.0,
                max_value=300.0,
                step=1.0,
                help="输入当前螺杆温度"
            )
            st.caption("单位: °C")
            
            current_rear_barrel_temperature = st.number_input(
                "后机筒温度",
                key="current_rear_barrel_temperature",
                value=79.9,
                min_value=0.0,
                max_value=300.0,
                step=1.0,
                help="输入当前后机筒温度"
            )
            st.caption("单位: °C")
        
        with param_cols[2]:
            current_front_barrel_temperature = st.number_input(
                "前机筒温度",
                key="current_front_barrel_temperature",
                value=80.1,
                min_value=0.0,
                max_value=300.0,
                step=1.0,
                help="输入当前前机筒温度"
            )
            st.caption("单位: °C")
            
            current_head_temperature = st.number_input(
                "机头温度",
                key="current_head_temperature",
                value=95.1,
                min_value=0.0,
                max_value=300.0,
                step=1.0,
                help="输入当前机头温度"
            )
            st.caption("单位: °C")
    
    # 2.3 当前实际米重测量值输入
    with st.expander("📏 当前实际米重", expanded=True):
        actual_weight = st.number_input(
            "当前实际米重",
            key="actual_weight",
            value=5.115,
            min_value=0.01,
            max_value=10.0,
            step=0.0001,
            format="%.4f",
            help="输入当前实际测量的米重值"
        )
        st.caption("单位: Kg/m")
    
    # 3. 优化参数设置
    st.subheader("⚙️ 优化参数设置")
    
    with st.expander("🎯 多目标优化参数", expanded=True):
        # 目标权重设置
        st.write("### 目标权重")
        st.markdown("调整以下权重来平衡米重偏差和调整幅度的重要性:")
        weight_cols = st.columns(2)
        
        with weight_cols[0]:
            weight_deviation = st.slider(
                "米重偏差权重",
                min_value=0.1,
                max_value=1.0,
                value=0.8,
                step=0.1,
                help="权重越高,越优先考虑减少米重偏差"
            )
        
        with weight_cols[1]:
            weight_adjustment = st.slider(
                "调整幅度权重",
                min_value=0.1,
                max_value=1.0,
                value=0.2,
                step=0.1,
                help="权重越高,越优先考虑减少调整幅度"
            )
        
        # 调整权重,确保总和为1
        total_weight = weight_deviation + weight_adjustment
        weight_deviation = weight_deviation / total_weight
        weight_adjustment = weight_adjustment / total_weight
        
        st.write(f"### 调整后权重(总和为1)")
        st.write(f"- 米重偏差权重: {weight_deviation:.2f}")
        st.write(f"- 调整幅度权重: {weight_adjustment:.2f}")
        
        # 参数调整约束
        st.write("### 参数调整约束")
        constraint_cols = st.columns(2)
        
        with constraint_cols[0]:
            max_screw_speed_adjust = st.slider(
                "螺杆转速最大调整幅度(%)",
                min_value=5.0,
                max_value=20.0,
                value=15.0,
                step=1.0,
                help="单次调整的最大百分比"
            )
        
        with constraint_cols[1]:
            max_process_speed_adjust = st.slider(
                "流程主速最大调整幅度(%)",
                min_value=3.0,
                max_value=15.0,
                value=10.0,
                step=1.0,
                help="单次调整的最大百分比"
            )
    
    # 4. 计算优化调节建议
    st.subheader("🚀 计算优化调节建议")
    
    if st.button("📊 计算优化调节建议", key="calculate_optimized_adjustment"):
        # 参数验证
        validation_errors = []
        
        if standard_weight <= 0:
            validation_errors.append("标准米重必须大于0")
        
        if upper_limit <= standard_weight:
            validation_errors.append("米重上限必须大于标准米重")
        
        if lower_limit >= standard_weight:
            validation_errors.append("米重下限必须小于标准米重")
        
        if current_screw_speed <= 0:
            validation_errors.append("螺杆转速必须大于0")
        
        if current_process_speed <= 0:
            validation_errors.append("流程主速必须大于0")
        
        if actual_weight <= 0:
            validation_errors.append("实际米重必须大于0")
        
        if validation_errors:
            st.error("参数输入错误:")
            for error in validation_errors:
                st.error(f"- {error}")
        else:
            with st.spinner("正在计算优化调节建议..."):
                # 获取选中的模型
                if 'selected_model' not in st.session_state:
                    st.error("请先选择一个模型")
                    return
                
                model_info = st.session_state['selected_model']
                model = model_info['model']
                
                # 检查是否有缩放器
                has_scalers = ('scaler_X' in model_info and model_info['scaler_X'] is not None and 
                              'scaler_y' in model_info and model_info['scaler_y'] is not None)
                if has_scalers:
                    scaler_X = model_info['scaler_X']
                    scaler_y = model_info['scaler_y']
                
                features = model_info['features']
                
                # 多目标优化算法 - 粒子群优化
                def predict_weight(screw_speed, process_speed):
                    """使用模型预测米重"""
                    # 准备输入数据
                    input_data = {
                        '螺杆转速': screw_speed,
                        '机头压力': current_head_pressure,
                        '流程主速': process_speed,
                        '螺杆温度': current_screw_temperature,
                        '后机筒温度': current_rear_barrel_temperature,
                        '前机筒温度': current_front_barrel_temperature,
                        '机头温度': current_head_temperature
                    }
                    
                    # 根据模型特征创建输入DataFrame
                    input_df = pd.DataFrame([input_data])[features]
                    
                    if model_info['model_type'] in ['LSTM', 'GRU', 'BiLSTM']:
                        # 深度学习模型处理逻辑
                        import torch
                        
                        # 检查是否有缩放器
                        if has_scalers:
                            scaled_input = scaler_X.transform(input_df)
                        else:
                            scaled_input = input_df.values
                        
                        # 获取序列长度
                        sequence_length = model_info.get('sequence_length', 10)
                        
                        # 创建序列数据
                        input_seq = np.tile(scaled_input, (sequence_length, 1)).reshape(1, sequence_length, -1)
                        
                        # 转换为PyTorch张量
                        device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
                        input_tensor = torch.tensor(input_seq, dtype=torch.float32).to(device)
                        
                        # 预测
                        model.eval()
                        with torch.no_grad():
                            y_pred_scaled_tensor = model(input_tensor)
                            y_pred_scaled = y_pred_scaled_tensor.cpu().numpy().ravel()[0]
                            
                            if has_scalers:
                                # 反缩放预测结果
                                predicted_weight = scaler_y.inverse_transform(np.array([[y_pred_scaled]]))[0][0]
                            else:
                                predicted_weight = y_pred_scaled
                    
                    elif has_scalers:
                        # 特征缩放
                        scaled_input = scaler_X.transform(input_df)
                        
                        # 模型预测
                        scaled_prediction = model.predict(scaled_input)[0]
                        
                        # 反缩放预测结果
                        predicted_weight = scaler_y.inverse_transform(np.array([[scaled_prediction]]))[0][0]
                    
                    else:
                        # 直接预测,不使用缩放器
                        predicted_weight = model.predict(input_df)[0]
                    
                    return predicted_weight
                
                def objective_function(params):
                    """多目标目标函数"""
                    screw_speed_val, process_speed_val = params
                    
                    # 预测米重
                    predicted_weight_val = predict_weight(screw_speed_val, process_speed_val)
                    
                    # 计算目标1:米重偏差
                    deviation_val = abs(predicted_weight_val - standard_weight)
                    deviation_percent_val = abs((predicted_weight_val - standard_weight) / standard_weight * 100)
                    
                    # 计算目标2:调整幅度
                    screw_speed_adjustment_val = abs(screw_speed_val - current_screw_speed)
                    process_speed_adjustment_val = abs(process_speed_val - current_process_speed)
                    
                    screw_speed_adjustment_percent_val = abs((screw_speed_val - current_screw_speed) / current_screw_speed * 100)
                    process_speed_adjustment_percent_val = abs((process_speed_val - current_process_speed) / current_process_speed * 100)
                    
                    # 加权目标函数
                    objective_val = (weight_deviation * deviation_percent_val + 
                                    weight_adjustment * (screw_speed_adjustment_percent_val + process_speed_adjustment_percent_val) / 2)
                    
                    return objective_val, predicted_weight_val, deviation_percent_val, \
                           screw_speed_adjustment_percent_val, process_speed_adjustment_percent_val
                
                # 参数约束
                def is_within_constraints(params):
                    """检查参数是否在约束范围内"""
                    screw_speed, process_speed = params
                    
                    # 螺杆转速约束
                    if not (30 <= screw_speed <= 500):
                        return False
                    
                    # 流程主速约束
                    if not (0 <= process_speed <= 200):
                        return False
                    
                    # 单次调整幅度约束
                    screw_speed_adjustment_percent = abs((screw_speed - current_screw_speed) / current_screw_speed * 100)
                    if screw_speed_adjustment_percent > max_screw_speed_adjust:
                        return False
                    
                    process_speed_adjustment_percent = abs((process_speed - current_process_speed) / current_process_speed * 100)
                    if process_speed_adjustment_percent > max_process_speed_adjust:
                        return False
                    
                    return True
                
                # 粒子群优化算法
                def particle_swarm_optimization(objective, constraints, bounds, n_particles=30, n_iterations=50):
                    """粒子群优化算法"""
                    # 初始化粒子
                    particles = []
                    velocities = []
                    best_positions = []
                    best_scores = []
                    
                    # 边界
                    (screw_speed_min, screw_speed_max), (process_speed_min, process_speed_max) = bounds
                    
                    for _ in range(n_particles):
                        # 随机初始化位置
                        while True:
                            screw_speed = np.random.uniform(screw_speed_min, screw_speed_max)
                            process_speed = np.random.uniform(process_speed_min, process_speed_max)
                            pos = [screw_speed, process_speed]
                            if constraints(pos):
                                break
                        
                        particles.append(pos)
                        velocities.append([0.0, 0.0])
                        best_positions.append(pos.copy())
                        
                        # 计算初始得分
                        score, _, _, _, _ = objective(pos)
                        best_scores.append(score)
                    
                    # 全局最优
                    global_best_idx = np.argmin(best_scores)
                    global_best_position = best_positions[global_best_idx].copy()
                    global_best_score = best_scores[global_best_idx]
                    
                    # PSO参数
                    w = 0.5  # 惯性权重
                    c1 = 1.5  # 认知系数
                    c2 = 1.5  # 社会系数
                    
                    # 迭代优化
                    for _ in range(n_iterations):
                        for i in range(n_particles):
                            # 更新速度
                            r1, r2 = np.random.rand(), np.random.rand()
                            velocities[i][0] = (w * velocities[i][0] +
                                              c1 * r1 * (best_positions[i][0] - particles[i][0]) +
                                              c2 * r2 * (global_best_position[0] - particles[i][0]))
                            velocities[i][1] = (w * velocities[i][1] +
                                              c1 * r1 * (best_positions[i][1] - particles[i][1]) +
                                              c2 * r2 * (global_best_position[1] - particles[i][1]))
                            
                            # 更新位置
                            new_pos = [
                                particles[i][0] + velocities[i][0],
                                particles[i][1] + velocities[i][1]
                            ]
                            
                            # 检查约束
                            if constraints(new_pos):
                                particles[i] = new_pos
                                
                                # 更新个体最优
                                current_score, _, _, _, _ = objective(new_pos)
                                if current_score < best_scores[i]:
                                    best_scores[i] = current_score
                                    best_positions[i] = new_pos.copy()
                                    
                                    # 更新全局最优
                                    if current_score < global_best_score:
                                        global_best_score = current_score
                                        global_best_position = new_pos.copy()
                    
                    return global_best_position, global_best_score
                
                # 设置参数边界
                screw_speed_bounds = [
                    current_screw_speed * (1 - max_screw_speed_adjust / 100),
                    current_screw_speed * (1 + max_screw_speed_adjust / 100)
                ]
                
                process_speed_bounds = [
                    current_process_speed * (1 - max_process_speed_adjust / 100),
                    current_process_speed * (1 + max_process_speed_adjust / 100)
                ]
                
                # 执行优化
                best_params, best_score = particle_swarm_optimization(
                    objective_function,
                    is_within_constraints,
                    [(screw_speed_bounds[0], screw_speed_bounds[1]), 
                     (process_speed_bounds[0], process_speed_bounds[1])]
                )
                
                # 获取最优参数的详细信息
                best_screw_speed, best_process_speed = best_params
                best_objective, best_predicted_weight, best_deviation_percent, \
                best_screw_adjust_percent, best_process_adjust_percent = objective_function(best_params)
                
                # 计算当前参数的预测结果
                current_predicted_weight = predict_weight(current_screw_speed, current_process_speed)
                current_deviation_percent = abs((current_predicted_weight - standard_weight) / standard_weight * 100)
                
                # 生成调整建议文本
                def generate_recommendation():
                    """生成调整建议文本"""
                    screw_speed_change = "提高" if best_screw_speed > current_screw_speed else "降低"
                    process_speed_change = "提高" if best_process_speed > current_process_speed else "降低"
                    
                    recommendation = f"米重偏差 {current_deviation_percent:.2f}%,建议调整:\n"
                    recommendation += f"1. 将螺杆转速从 {current_screw_speed:.1f} rpm {screw_speed_change} 至 {best_screw_speed:.1f} rpm "
                    recommendation += f"( {screw_speed_change} {abs(best_screw_adjust_percent):.2f}% )\n"
                    recommendation += f"2. 将流程主速从 {current_process_speed:.1f} m/min {process_speed_change} 至 {best_process_speed:.1f} m/min "
                    recommendation += f"( {process_speed_change} {abs(best_process_adjust_percent):.2f}% )\n"
                    recommendation += f"\n预期效果:米重偏差将降至 {best_deviation_percent:.2f}%"
                    
                    return recommendation
                
                recommendation = generate_recommendation()
                
                # 构建调整结果
                adjustment_result = {
                    'status': '正常范围' if best_predicted_weight >= lower_limit and best_predicted_weight <= upper_limit else \
                              '超上限' if best_predicted_weight > upper_limit else '超下限',
                    'real_time_weight': actual_weight,
                    'standard_weight': standard_weight,
                    'upper_limit': upper_limit,
                    'lower_limit': lower_limit,
                    'current_screw_speed': current_screw_speed,
                    'current_process_speed': current_process_speed,
                    'new_screw_speed': best_screw_speed,
                    'new_process_speed': best_process_speed,
                    'predicted_weight': best_predicted_weight,
                    'current_predicted_weight': current_predicted_weight,
                    'deviation_percentage': (actual_weight - standard_weight) / standard_weight * 100,
                    'current_predicted_deviation_percent': current_deviation_percent,
                    'predicted_deviation_percent': best_deviation_percent,
                    'screw_speed_adjustment': best_screw_speed - current_screw_speed,
                    'process_speed_adjustment': best_process_speed - current_process_speed,
                    'screw_speed_adjust_percent': best_screw_adjust_percent,
                    'process_speed_adjust_percent': best_process_adjust_percent,
                    'recommendation': recommendation,
                    'weight_deviation': weight_deviation,
                    'weight_adjustment': weight_adjustment,
                    'best_objective_score': best_score
                }
                
                # 保存到历史记录
                history_record = {
                    'timestamp': datetime.now(),
                    'model_file': st.session_state.get('selected_model_file', '未知模型'),
                    'standard_weight': standard_weight,
                    'upper_limit': upper_limit,
                    'lower_limit': lower_limit,
                    'actual_weight': actual_weight,
                    'current_screw_speed': current_screw_speed,
                    'current_process_speed': current_process_speed,
                    'adjustment_result': adjustment_result
                }
                
                # 添加到会话状态的历史记录
                st.session_state['optimized_adjustment_history'].append(history_record)
                
                # 限制历史记录数量
                if len(st.session_state['optimized_adjustment_history']) > 100:
                    st.session_state['optimized_adjustment_history'] = st.session_state['optimized_adjustment_history'][-100:]
                
                # 5. 结果展示
                st.success("优化调节建议计算完成!")
                
                st.subheader("📋 优化调节建议结果")
                
                # 5.1 米重状态
                if adjustment_result['status'] == "正常范围":
                    st.success(f"米重状态: {adjustment_result['status']}")
                else:
                    st.warning(f"米重状态: {adjustment_result['status']}")
                
                # 5.2 偏差信息
                st.markdown("### 📊 偏差信息")
                info_cols = st.columns(3)
                info_cols[0].metric("实时米重", f"{adjustment_result['real_time_weight']:.4f} Kg/m")
                info_cols[1].metric("标准米重", f"{adjustment_result['standard_weight']:.4f} Kg/m")
                info_cols[2].metric("偏差百分比", f"{adjustment_result['deviation_percentage']:.2f}%")
                
                # 5.3 预测结果对比
                st.markdown("### 📈 预测结果对比")
                pred_cols = st.columns(3)
                pred_cols[0].metric("当前参数预测米重", f"{adjustment_result['current_predicted_weight']:.4f} Kg/m")
                pred_cols[1].metric("优化后预测米重", f"{adjustment_result['predicted_weight']:.4f} Kg/m")
                pred_cols[2].metric("预测偏差改善", f"{adjustment_result['current_predicted_deviation_percent'] - adjustment_result['predicted_deviation_percent']:.2f}%")
                
                # 5.4 关键调整建议
                st.markdown("### 🔑 关键调整建议")
                st.info(adjustment_result['recommendation'])
                
                # 5.5 参数调整对比
                st.markdown("### 📊 参数调整对比")
                
                param_compare_df = pd.DataFrame({
                    '参数名称': ['螺杆转速', '流程主速'],
                    '当前值': [adjustment_result['current_screw_speed'], adjustment_result['current_process_speed']],
                    '优化建议值': [adjustment_result['new_screw_speed'], adjustment_result['new_process_speed']],
                    '调整幅度': [f"{adjustment_result['screw_speed_adjust_percent']:.2f}%",
                               f"{adjustment_result['process_speed_adjust_percent']:.2f}%"]
                })
                
                # 高亮显示调整幅度
                def highlight_adjustment(val):
                    if isinstance(val, str) and '%' in val:
                        try:
                            percent = float(val.strip('%'))
                            if percent > 0:
                                return 'background-color: #90EE90'  # 绿色表示增加
                            elif percent < 0:
                                return 'background-color: #FFB6C1'  # 红色表示减少
                        except:
                            pass
                    return ''
                
                styled_df = param_compare_df.style.applymap(highlight_adjustment, subset=['调整幅度'])
                st.dataframe(styled_df, use_container_width=True, hide_index=True)
                
                # 5.6 可视化对比
                fig = go.Figure()
                fig.add_trace(go.Bar(
                    x=param_compare_df['参数名称'],
                    y=param_compare_df['当前值'],
                    name='当前值',
                    marker_color='blue'
                ))
                fig.add_trace(go.Bar(
                    x=param_compare_df['参数名称'],
                    y=param_compare_df['优化建议值'],
                    name='优化建议值',
                    marker_color='green'
                ))
                
                fig.update_layout(
                    barmode='group',
                    title='参数调整对比',
                    yaxis_title='数值',
                    height=400
                )
                
                st.plotly_chart(fig, use_container_width=True)
                
                # 5.7 优化效果可视化
                st.markdown("### 📉 优化效果")
                
                # 目标函数值对比
                fig_objective = go.Figure()
                fig_objective.add_trace(go.Bar(
                    x=['当前参数', '优化后参数'],
                    y=[
                        weight_deviation * current_deviation_percent + weight_adjustment * 0,
                        weight_deviation * best_deviation_percent + weight_adjustment * \
                        (abs(best_screw_adjust_percent) + abs(best_process_adjust_percent)) / 2
                    ],
                    marker_color=['red', 'green']
                ))
                fig_objective.update_layout(
                    title='多目标优化函数值对比',
                    yaxis_title='目标函数值(越小越好)',
                    height=300
                )
                st.plotly_chart(fig_objective, use_container_width=True)
    
    # 6. 历史记录展示
    st.subheader("📚 历史调节记录")
    
    if 'optimized_adjustment_history' in st.session_state and st.session_state['optimized_adjustment_history']:
        # 显示历史记录数量
        st.write(f"共 {len(st.session_state['optimized_adjustment_history'])} 条历史记录")
        
        # 分页显示
        page_size = 10
        total_pages = (len(st.session_state['optimized_adjustment_history']) + page_size - 1) // page_size
        
        page = st.selectbox(
            "选择页码",
            options=range(1, total_pages + 1),
            key="history_page"
        )
        
        start_idx = (page - 1) * page_size
        end_idx = start_idx + page_size
        paginated_history = st.session_state['optimized_adjustment_history'][start_idx:end_idx]
        
        # 反向显示,最新记录在前面
        for record in reversed(paginated_history):
            with st.expander(f"记录时间: {record['timestamp'].strftime('%Y-%m-%d %H:%M:%S')} | 模型: {record['model_file']}"):
                history_cols = st.columns(3)
                
                with history_cols[0]:
                    st.write("**米重参数**")
                    st.write(f"- 标准米重: {record['standard_weight']:.4f} Kg/m")
                    st.write(f"- 米重上限: {record['upper_limit']:.4f} Kg/m")
                    st.write(f"- 米重下限: {record['lower_limit']:.4f} Kg/m")
                    st.write(f"- 实际米重: {record['actual_weight']:.4f} Kg/m")
                
                with history_cols[1]:
                    st.write("**速度参数**")
                    st.write(f"- 当前螺杆转速: {record['current_screw_speed']:.1f} rpm")
                    st.write(f"- 当前流程主速: {record['current_process_speed']:.1f} m/min")
                    st.write(f"- 建议螺杆转速: {record['adjustment_result']['new_screw_speed']:.1f} rpm")
                    st.write(f"- 建议流程主速: {record['adjustment_result']['new_process_speed']:.1f} m/min")
                
                with history_cols[2]:
                    st.write("**预测结果**")
                    st.write(f"- 当前预测米重: {record['adjustment_result']['current_predicted_weight']:.4f} Kg/m")
                    st.write(f"- 优化后预测米重: {record['adjustment_result']['predicted_weight']:.4f} Kg/m")
                    st.write(f"- 当前预测偏差: {record['adjustment_result']['current_predicted_deviation_percent']:.2f}%")
                    st.write(f"- 优化后预测偏差: {record['adjustment_result']['predicted_deviation_percent']:.2f}%")
                
                st.write("**调整建议**")
                st.write(record['adjustment_result']['recommendation'])
    else:
        st.info("暂无历史调节记录")
    
    # 7. 帮助说明
    with st.expander("❓ 帮助说明"):
        st.markdown("""
        ### 功能说明
        本功能模块基于多目标优化算法,根据当前米重测量值和挤出机参数,为用户提供科学合理的参数调整建议。
        
        ### 优化算法
        - **算法类型**: 粒子群优化算法(PSO)
        - **优化目标**: 
          1. 最小化米重偏差
          2. 最小化参数调整幅度
        - **约束条件**: 
          - 螺杆转速和流程主速上下限
          - 单次最大调整幅度
        
        ### 结果解读
        - **米重状态**: 显示优化后预测米重是否在允许范围内
        - **偏差信息**: 当前米重与标准米重的偏差
        - **预测结果对比**: 当前参数和优化后参数的预测米重对比
        - **调整建议**: 详细的参数调整建议
        - **参数对比**: 直观展示参数调整幅度
        - **优化效果**: 多目标优化函数值对比
        
        ### 注意事项
        1. 请确保输入的参数值准确反映设备当前状态
        2. 优化建议仅供参考,实际操作时请结合现场经验
        3. 建议在调整参数后密切观察米重变化
        4. 定期更新模型以提高建议的准确性
        """)
 
# 页面入口
if __name__ == "__main__":
    show_optimized_parameter_adjustment()