feat: 优化回路数计算逻辑,提升报表准确性

This commit is contained in:
dmy
2026-01-07 16:55:11 +08:00
parent 87cea6ed86
commit f2a960e789
3 changed files with 59 additions and 54 deletions

16
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,16 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Current File with Arguments",
"type": "debugpy",
"request": "launch",
"program": "main.py",
"console": "integratedTerminal",
"args": "--excel abc.xlsx"
},
]
}

10
gui.py
View File

@@ -781,8 +781,12 @@ def index():
total_length_m = sum(d["length"] for d in res["eval"]["details"]) total_length_m = sum(d["length"] for d in res["eval"]["details"])
total_length_km = total_length_m / 1000 total_length_km = total_length_m / 1000
# 获取回路数 (通过统计从升压站发出的连接)
n_circuits = sum(1 for d in res["eval"]["details"] if d["source"] == "substation" or d["target"] == "substation")
row_dict = { row_dict = {
"name": name_display, "name": name_display,
"n_circuits": n_circuits,
"cost_wan": f"{res['cost'] / 10000:.2f}", "cost_wan": f"{res['cost'] / 10000:.2f}",
"loss_kw": f"{res['loss']:.2f}", "loss_kw": f"{res['loss']:.2f}",
"total_length": f"{total_length_km:.2f}", "total_length": f"{total_length_km:.2f}",
@@ -938,6 +942,12 @@ def index():
"required": True, "required": True,
"align": "left", "align": "left",
}, },
{
"name": "n_circuits",
"label": "回路数",
"field": "n_circuits",
"sortable": True,
},
{ {
"name": "cost_wan", "name": "cost_wan",
"label": "总投资 (万元)", "label": "总投资 (万元)",

87
main.py
View File

@@ -655,38 +655,20 @@ def design_with_rotational_sweep(
return final_connections, turbines return final_connections, turbines
def get_max_cable_capacity_mw( # 4. 获取电缆最大容量(MW)
cable_specs=None, voltage=VOLTAGE_LEVEL, power_factor=POWER_FACTOR def get_max_cable_capacity_mw(cable_specs, voltage=VOLTAGE_LEVEL, power_factor=POWER_FACTOR):
):
""" """
计算给定电缆规格中能够承载的最大功率 (单位: MW)。 根据电缆规格计算最大承载功率
:param cable_specs: 电缆规格列表 list of tuples或者直接是最大功率数值(MW)
基于提供的电缆规格列表,选取最大载流量,结合系统电压和功率因数计算理论最大传输功率。
参数:
cable_specs (list, optional): 电缆规格列表。每个元素应包含 (截面积, 额定电流, 单价, 损耗系数)。
voltage (float): 系统电压 (V), 默认 66000
power_factor (float): 功率因数, 默认 0.95
返回:
float: 最大功率承载能力 (MW)。
异常:
Exception: 当未提供 cable_specs 时抛出,提示截面不满足。
""" """
if cable_specs is None: # 如果传入的已经是数值,直接返回
# Default cable specs if not provided (same as in evaluate_design) if isinstance(cable_specs, (int, float, np.number)):
cable_specs = [ return float(cable_specs)
(35, 150, 0.524, 80),
(70, 215, 0.268, 120), # 兼容性检查:如果列表为空
(95, 260, 0.193, 150), if not cable_specs:
(120, 295, 0.153, 180), print("Warning: 没有可用的电缆规格,使用默认最大容量 100MW")
(150, 330, 0.124, 220), return 100.0
(185, 370, 0.0991, 270),
(240, 425, 0.0754, 350),
(300, 500, 0.0601, 450),
(400, 580, 0.0470, 600),
]
# 从所有电缆规格中找到最大的额定电流容量 # 从所有电缆规格中找到最大的额定电流容量
max_current_capacity = max(spec[1] for spec in cable_specs) max_current_capacity = max(spec[1] for spec in cable_specs)
@@ -1009,10 +991,12 @@ def export_to_excel(connections_details, filename):
df = pd.DataFrame(data) df = pd.DataFrame(data)
# 汇总统计 # 汇总统计
n_circuits = sum(1 for conn in connections_details if conn["source"] == "substation" or conn["target"] == "substation")
summary = { summary = {
"Total Cost (¥)": df["Cost (¥)"].sum(), "Total Cost (¥)": df["Cost (¥)"].sum(),
"Total Effective Length (m)": df["Effective Length (m)"].sum(), "Total Effective Length (m)": df["Effective Length (m)"].sum(),
"Total Vertical Length (m)": df["Vertical Length (m)"].sum(), "Total Vertical Length (m)": df["Vertical Length (m)"].sum(),
"Number of Circuits": n_circuits,
} }
summary_df = pd.DataFrame([summary]) summary_df = pd.DataFrame([summary])
@@ -1038,15 +1022,14 @@ def export_all_scenarios_to_excel(results, filename):
# 1. 总览 Sheet # 1. 总览 Sheet
summary_data = [] summary_data = []
for res in results: for res in results:
# 获取回路数 # 获取回路数 (通过统计从升压站发出的连接)
n_circuits = 0 n_circuits = sum(1 for conn in res["eval"]["details"] if conn["source"] == "substation" or conn["target"] == "substation")
if "turbines" in res and "cluster" in res["turbines"].columns:
n_circuits = res["turbines"]["cluster"].nunique()
summary_data.append( summary_data.append(
{ {
"Scenario": res["name"], "Scenario": res["name"],
"Total Cost (¥)": res["cost"], "Total Cost (¥)": res["cost"],
"总费用(万元)": res.get("total_cost_npv", res["cost"]) / 10000,
"Total Loss (kW)": res["loss"], "Total Loss (kW)": res["loss"],
"Num Circuits": n_circuits, "Num Circuits": n_circuits,
# 计算电缆统计 # 计算电缆统计
@@ -1413,14 +1396,10 @@ def compare_design_methods(
print(f" 最大电缆容量: {max_cable_mw:.2f} MW") print(f" 最大电缆容量: {max_cable_mw:.2f} MW")
# --- Run 1: Base Algorithm (Capacitated Sweep) --- # --- Run 1: Base Sector Sweep ---
base_name = f"{name} (Base)" base_name = f"{name} (Base)"
conns_base, turbines_base = design_with_capacitated_sweep( conns_base, turbines_base = design_with_capacitated_sweep(
turbines.copy(), turbines.copy(), substation, max_cable_mw, voltage=voltage
substation,
cable_specs=current_specs,
voltage=voltage,
power_factor=power_factor,
) )
eval_base = evaluate_design( eval_base = evaluate_design(
turbines, turbines,
@@ -1432,7 +1411,7 @@ def compare_design_methods(
voltage=voltage, voltage=voltage,
power_factor=power_factor, power_factor=power_factor,
) )
n_circuits_base = sum(1 for d in eval_base["details"] if d["source"] == "substation" or d["target"] == "substation")
comparison_results.append( comparison_results.append(
{ {
"name": base_name, "name": base_name,
@@ -1444,17 +1423,13 @@ def compare_design_methods(
} }
) )
print( print(
f" [Base] Cost: ¥{eval_base['total_cost']:,.2f} | Loss: {eval_base['total_loss']:.2f} kW" f" [Base] Cost: ¥{eval_base['total_cost']:,.2f} | Loss: {eval_base['total_loss']:.2f} kW | Circuits: {n_circuits_base}"
) )
# --- Run 2: Rotational Algorithm (Optimization) --- # --- Run 2: Rotational Sweep (Optimization) ---
rot_name = f"{name} (Rotational)" rot_name = f"{name} (Rotational)"
conns_rot, turbines_rot = design_with_rotational_sweep( conns_rot, turbines_rot = design_with_rotational_sweep(
turbines.copy(), turbines.copy(), substation, max_cable_mw, voltage=voltage
substation,
cable_specs=current_specs,
voltage=voltage,
power_factor=power_factor,
) )
eval_rot = evaluate_design( eval_rot = evaluate_design(
turbines, turbines,
@@ -1466,7 +1441,7 @@ def compare_design_methods(
voltage=voltage, voltage=voltage,
power_factor=power_factor, power_factor=power_factor,
) )
n_circuits_rot = sum(1 for d in eval_rot["details"] if d["source"] == "substation" or d["target"] == "substation")
comparison_results.append( comparison_results.append(
{ {
"name": rot_name, "name": rot_name,
@@ -1478,7 +1453,7 @@ def compare_design_methods(
} }
) )
print( print(
f" [Rotational] Cost: ¥{eval_rot['total_cost']:,.2f} | Loss: {eval_rot['total_loss']:.2f} kW" f" [Rotational] Cost: ¥{eval_rot['total_cost']:,.2f} | Loss: {eval_rot['total_loss']:.2f} kW | Circuits: {n_circuits_rot}"
) )
# --- Run 3: Esau-Williams Algorithm --- # --- Run 3: Esau-Williams Algorithm ---
@@ -1496,7 +1471,7 @@ def compare_design_methods(
voltage=voltage, voltage=voltage,
power_factor=power_factor, power_factor=power_factor,
) )
n_circuits_ew = sum(1 for d in eval_ew["details"] if d["source"] == "substation" or d["target"] == "substation")
comparison_results.append( comparison_results.append(
{ {
"name": ew_name, "name": ew_name,
@@ -1508,7 +1483,7 @@ def compare_design_methods(
} }
) )
print( print(
f" [Esau-Williams] Cost: ¥{eval_ew['total_cost']:,.2f} | Loss: {eval_ew['total_loss']:.2f} kW" f" [Esau-Williams] Cost: ¥{eval_ew['total_cost']:,.2f} | Loss: {eval_ew['total_loss']:.2f} kW | Circuits: {n_circuits_ew}"
) )
# 记录最佳 # 记录最佳
@@ -1525,7 +1500,7 @@ def compare_design_methods(
# 可视化 (只画 Base 版本) # 可视化 (只画 Base 版本)
ax_idx = i + 1 ax_idx = i + 1
if plot_results and ax_idx < 4: if plot_results and ax_idx < 4:
n_circuits = turbines_base["cluster"].nunique() n_circuits = sum(1 for d in eval_base["details"] if d["source"] == "substation" or d["target"] == "substation")
title = f"{base_name} ({n_circuits} circuits)\nCost: ¥{eval_base['total_cost'] / 10000:.2f}" title = f"{base_name} ({n_circuits} circuits)\nCost: ¥{eval_base['total_cost'] / 10000:.2f}"
visualize_design( visualize_design(
turbines_base, substation, eval_base["details"], title, ax=axes[ax_idx] turbines_base, substation, eval_base["details"], title, ax=axes[ax_idx]
@@ -1565,7 +1540,11 @@ def compare_design_methods(
for i, res in enumerate(comparison_results): for i, res in enumerate(comparison_results):
if res["cost"] < comparison_results[best_idx]["cost"]: if res["cost"] < comparison_results[best_idx]["cost"]:
best_idx = i best_idx = i
print(f" {i + 1}. {res['name']} - Cost: ¥{res['cost']:,.2f}")
# 获取回路数 (通过统计从升压站发出的连接)
n_circuits = sum(1 for conn in res["eval"]["details"] if conn["source"] == "substation" or conn["target"] == "substation")
print(f" {i + 1}. {res['name']} - Cost: ¥{res['cost']:,.2f} | Circuits: {n_circuits}")
print(f"推荐方案: {comparison_results[best_idx]['name']} (默认)") print(f"推荐方案: {comparison_results[best_idx]['name']} (默认)")