773 lines
28 KiB
Python
773 lines
28 KiB
Python
"""爆管定位主模块。"""
|
||
|
||
import copy
|
||
import math
|
||
import os
|
||
import sys
|
||
from datetime import datetime
|
||
from time import perf_counter
|
||
|
||
import networkx as nx
|
||
import numpy as np
|
||
import pandas as pd
|
||
|
||
from .leak_simulator import cal_signature_pipe_multi_pf
|
||
from .network_partitioner import (
|
||
cal_group_num,
|
||
metis_grouping_pipe_weight,
|
||
visualize_metis_partition,
|
||
)
|
||
from .similarity_calculator import (
|
||
adjust_ratio,
|
||
cal_similarity_all_multi_new_sq_improve_double_lzr,
|
||
decode_mode,
|
||
extra_judge,
|
||
update_similarity,
|
||
)
|
||
|
||
|
||
def _ensure_signatures_for_centers(
|
||
wn,
|
||
wn_inp_path,
|
||
center_list, # 本轮要用到的中心(list[str])
|
||
pressure_leak_all,
|
||
flow_leak_all, # 全量缓存(可为空 DF)
|
||
timestep_list, # 你现有的时序列表
|
||
pressure_monitor,
|
||
flow_monitor, # 用来推断传感器列名
|
||
leak_mag,
|
||
n_workers=1,
|
||
):
|
||
"""
|
||
只为缺失的中心补算 SLF(调用你现有的 cal_signature_pipe_multi_pf),
|
||
并把补算结果并回缓存。返回:
|
||
pressure_leak_subset, flow_leak_subset, pressure_leak_all_new, flow_leak_all_new
|
||
其中 subset 只包含 center_list 的行(顺序与 center_list 保持一致)。
|
||
"""
|
||
|
||
center_list = _dedupe_preserve_order(center_list)
|
||
|
||
# 1) 推断传感器列名(与现有数据保持一致)
|
||
sensor_name_all = list(pressure_monitor.columns)
|
||
sensor_f_name_all = (
|
||
list(flow_monitor.columns)
|
||
if (flow_monitor is not None and hasattr(flow_monitor, "columns"))
|
||
else []
|
||
)
|
||
|
||
# 2) 取出缓存里已经有的中心(考虑 MultiIndex 的第 0 层为 pipe)
|
||
def _existing_pipes(df):
|
||
if df is None or len(df) == 0:
|
||
return set()
|
||
idx = df.index
|
||
if isinstance(idx, pd.MultiIndex):
|
||
return set(idx.get_level_values(0))
|
||
else:
|
||
return set(idx)
|
||
|
||
exist_p = _existing_pipes(pressure_leak_all)
|
||
need = [p for p in center_list if p not in exist_p]
|
||
|
||
# 3) 若有缺失中心,仅为这些中心补算一次
|
||
if len(need) > 0:
|
||
p_new, _ = cal_signature_pipe_multi_pf(
|
||
wn,
|
||
leak_mag,
|
||
need,
|
||
timestep_list,
|
||
sensor_name_all,
|
||
n_workers=n_workers,
|
||
wn_inp_path=wn_inp_path,
|
||
)
|
||
# 初始化空缓存时,做一次“同构化”
|
||
if pressure_leak_all is None or len(pressure_leak_all) == 0:
|
||
pressure_leak_all = p_new
|
||
else:
|
||
pressure_leak_all = pd.concat([pressure_leak_all, p_new], axis=0)
|
||
# if (flow_leak_all is None or len(flow_leak_all) == 0) and f_new is not None:
|
||
# flow_leak_all = f_new
|
||
# elif f_new is not None:
|
||
# flow_leak_all = pd.concat([flow_leak_all, f_new], axis=0)
|
||
|
||
# 去重(如果既有缓存里不小心有重复中心)
|
||
if isinstance(pressure_leak_all.index, pd.MultiIndex):
|
||
pressure_leak_all = pressure_leak_all[
|
||
~pressure_leak_all.index.duplicated(keep="last")
|
||
]
|
||
if flow_leak_all is not None and len(flow_leak_all) > 0:
|
||
flow_leak_all = flow_leak_all[
|
||
~flow_leak_all.index.duplicated(keep="last")
|
||
]
|
||
else:
|
||
pressure_leak_all = pressure_leak_all[
|
||
~pressure_leak_all.index.duplicated(keep="last")
|
||
]
|
||
if flow_leak_all is not None and len(flow_leak_all) > 0:
|
||
flow_leak_all = flow_leak_all[
|
||
~flow_leak_all.index.duplicated(keep="last")
|
||
]
|
||
|
||
# 4) 从更新后的缓存里,取出这轮需要的中心子集(顺序与 center_list 一致)
|
||
if isinstance(pressure_leak_all.index, pd.MultiIndex):
|
||
pressure_subset = pressure_leak_all.loc[center_list]
|
||
flow_subset = (
|
||
flow_leak_all.loc[center_list]
|
||
if (flow_leak_all is not None and len(flow_leak_all) > 0)
|
||
else None
|
||
)
|
||
else:
|
||
pressure_subset = pressure_leak_all.loc[center_list, :]
|
||
flow_subset = (
|
||
flow_leak_all.loc[center_list, :]
|
||
if (flow_leak_all is not None and len(flow_leak_all) > 0)
|
||
else None
|
||
)
|
||
|
||
return pressure_subset, flow_subset, pressure_leak_all, flow_leak_all
|
||
|
||
|
||
def area_output_num_ki_improve(
|
||
candidate_center,
|
||
candidate_group,
|
||
similarity,
|
||
new_all_node,
|
||
top_group_ratio,
|
||
top_pipe_num_max,
|
||
top_pipe_num_min,
|
||
cut_ratio,
|
||
):
|
||
final_area = []
|
||
final_center = []
|
||
all_node_iter = []
|
||
if similarity.index.is_unique == False:
|
||
total_center_num = len(set(similarity.index))
|
||
else:
|
||
total_center_num = len(similarity.index)
|
||
|
||
next_group_num = min(
|
||
total_center_num, math.ceil(total_center_num / cut_ratio * top_group_ratio)
|
||
)
|
||
|
||
for i in range(next_group_num):
|
||
top_center = similarity.index[i]
|
||
top_center_index = find_list_repeat(candidate_center, top_center)
|
||
for j in range(len(top_center_index)):
|
||
final_area = final_area + candidate_group[top_center_index[j]]
|
||
all_node_iter = all_node_iter + list(new_all_node[top_center_index[j]])
|
||
final_center.append(top_center)
|
||
final_area = sorted(set(final_area))
|
||
|
||
if len(final_area) > top_pipe_num_max:
|
||
if_end = 0
|
||
elif len(final_area) > top_pipe_num_min:
|
||
if_end = 1
|
||
elif total_center_num == next_group_num:
|
||
if_end = 1
|
||
else:
|
||
if_end = 1
|
||
for i in np.arange(next_group_num, total_center_num, 1):
|
||
|
||
before_list = copy.deepcopy(final_area)
|
||
top_center = similarity.index[i]
|
||
top_center_index = candidate_center.index(top_center)
|
||
temp_group = final_area + candidate_group[top_center_index]
|
||
temp_area = sorted(set(temp_group))
|
||
|
||
if len(temp_area) < top_pipe_num_min:
|
||
|
||
final_center.append(top_center)
|
||
all_node_iter = all_node_iter + list(new_all_node[top_center_index])
|
||
final_area = temp_area
|
||
|
||
elif len(temp_area) < top_pipe_num_max:
|
||
final_center.append(top_center)
|
||
all_node_iter = all_node_iter + list(new_all_node[top_center_index])
|
||
final_area = temp_area
|
||
break
|
||
else:
|
||
a = len(temp_area) - top_pipe_num_max
|
||
b = top_pipe_num_min - len(before_list)
|
||
|
||
if a >= b:
|
||
final_area = before_list
|
||
else:
|
||
final_center.append(top_center)
|
||
all_node_iter = all_node_iter + list(new_all_node[top_center_index])
|
||
final_area = temp_area
|
||
break
|
||
|
||
final_center = sorted(set(final_center))
|
||
all_node_iter = sorted(set(all_node_iter))
|
||
return final_area, final_center, all_node_iter, if_end
|
||
|
||
|
||
def find_list_repeat(candidate_center, target):
|
||
repeated_list = []
|
||
for index, nums in enumerate(candidate_center):
|
||
if nums == target:
|
||
repeated_list.append(index)
|
||
return repeated_list
|
||
|
||
|
||
def _dedupe_preserve_order(items):
|
||
seen = set()
|
||
output = []
|
||
for item in items:
|
||
if item in seen:
|
||
continue
|
||
seen.add(item)
|
||
output.append(item)
|
||
return output
|
||
|
||
|
||
def _accumulate_stage(stage_timing, stage_name, started_at):
|
||
stage_timing[stage_name] = stage_timing.get(stage_name, 0.0) + (
|
||
perf_counter() - started_at
|
||
)
|
||
|
||
|
||
def _write_last_round_candidates_csv(
|
||
csv_path,
|
||
exit_condition,
|
||
iteration_count,
|
||
similarity_mode,
|
||
candidate_details,
|
||
fallback_similarity,
|
||
):
|
||
if not csv_path:
|
||
return None
|
||
timestamp_suffix = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||
base_path, ext = os.path.splitext(csv_path)
|
||
ext = ext or ".csv"
|
||
output_path = f"{base_path}_{timestamp_suffix}{ext}"
|
||
if candidate_details is not None and len(candidate_details) > 0:
|
||
export_df = candidate_details.copy()
|
||
if export_df.index.name == "pipe_id":
|
||
export_df = export_df.reset_index()
|
||
else:
|
||
export_df = pd.DataFrame(
|
||
{
|
||
"pipe_id": [str(pipe_id) for pipe_id in fallback_similarity.index],
|
||
"final_similarity": [float(value) for value in fallback_similarity.values],
|
||
}
|
||
)
|
||
export_df["exit_condition"] = exit_condition
|
||
export_df["iterations"] = int(iteration_count)
|
||
export_df["similarity_mode"] = similarity_mode
|
||
parent_dir = os.path.dirname(output_path)
|
||
if parent_dir:
|
||
os.makedirs(parent_dir, exist_ok=True)
|
||
export_df.to_csv(output_path, index=False, encoding="utf-8-sig")
|
||
return output_path
|
||
|
||
|
||
def cal_DtoTop1(
|
||
G0, pipe_leak, located_pipe, pipe_start_node_all, pipe_end_node_all, pipe_length
|
||
):
|
||
if pipe_leak == located_pipe:
|
||
result_DtoTop1 = 0
|
||
result_DtoTop1_num = 0
|
||
else:
|
||
pipe_leak_start_node = pipe_start_node_all[pipe_leak]
|
||
pipe_leak_end_node = pipe_end_node_all[pipe_leak]
|
||
located_pipe_start_node = pipe_start_node_all[located_pipe]
|
||
located_pipe_end_node = pipe_end_node_all[located_pipe]
|
||
DtoTop1_series = pd.Series(dtype=object)
|
||
DtoTop1_num_series = pd.Series(dtype=object)
|
||
DtoTop1_series["ss"] = nx.shortest_path_length(
|
||
G0, pipe_leak_start_node, located_pipe_start_node, weight="weight"
|
||
)
|
||
DtoTop1_series["se"] = nx.shortest_path_length(
|
||
G0, pipe_leak_start_node, located_pipe_end_node, weight="weight"
|
||
)
|
||
DtoTop1_series["es"] = nx.shortest_path_length(
|
||
G0, pipe_leak_end_node, located_pipe_start_node, weight="weight"
|
||
)
|
||
DtoTop1_series["ee"] = nx.shortest_path_length(
|
||
G0, pipe_leak_end_node, located_pipe_end_node, weight="weight"
|
||
)
|
||
DtoTop1_num_series["ss"] = nx.shortest_path_length(
|
||
G0, pipe_leak_start_node, located_pipe_start_node
|
||
)
|
||
DtoTop1_num_series["se"] = nx.shortest_path_length(
|
||
G0, pipe_leak_start_node, located_pipe_end_node
|
||
)
|
||
DtoTop1_num_series["es"] = nx.shortest_path_length(
|
||
G0, pipe_leak_end_node, located_pipe_start_node
|
||
)
|
||
DtoTop1_num_series["ee"] = nx.shortest_path_length(
|
||
G0, pipe_leak_end_node, located_pipe_end_node
|
||
)
|
||
|
||
if DtoTop1_num_series.min() == 0:
|
||
result_DtoTop1_num = 1
|
||
result_DtoTop1 = DtoTop1_series.max() / 2
|
||
else:
|
||
result_DtoTop1_num = DtoTop1_num_series.min() + 1
|
||
DtoTop1_type = DtoTop1_series.argmin()
|
||
result_DtoTop1 = (
|
||
DtoTop1_series[DtoTop1_type]
|
||
+ (pipe_length[pipe_leak] + pipe_length[located_pipe]) / 2
|
||
)
|
||
return result_DtoTop1, result_DtoTop1_num
|
||
|
||
|
||
def cal_RR(located_pipe, similarity_sp):
|
||
if located_pipe in similarity_sp.index:
|
||
rank = similarity_sp.index.get_loc(located_pipe)
|
||
RR = rank / len(similarity_sp.index)
|
||
else:
|
||
RR = 1.1
|
||
return RR
|
||
|
||
|
||
def cal_cover(similarity, leak_pipe):
|
||
if leak_pipe in list(similarity.index):
|
||
cover = 1
|
||
else:
|
||
cover = 0
|
||
return cover
|
||
|
||
|
||
def cal_SD(located_pipe, real_pipe, pipe_x, pipe_y):
|
||
dx = pipe_x[located_pipe] - pipe_x[real_pipe]
|
||
dy = pipe_y[located_pipe] - pipe_y[real_pipe]
|
||
SD = math.sqrt(dx * dx + dy * dy)
|
||
return SD
|
||
|
||
|
||
def DN_search_multi_simple_add_flow_count_new(
|
||
wn,
|
||
wn_inp_path,
|
||
G0,
|
||
all_node,
|
||
node_x,
|
||
node_y,
|
||
pipe_start_node_all,
|
||
pipe_end_node_all,
|
||
pipe_diameter,
|
||
couple_node_length,
|
||
node_pipe_dic,
|
||
all_node_series,
|
||
top_group_ratio,
|
||
top_pipe_num_max,
|
||
top_pipe_num_min,
|
||
candidate_pipe_input_initial,
|
||
similarity_mode,
|
||
pressure_monitor,
|
||
pressure_predict,
|
||
pressure_normal,
|
||
pressure_leak_all,
|
||
flow_monitor,
|
||
flow_predict,
|
||
flow_normal,
|
||
flow_leak_all,
|
||
timestep_list,
|
||
max_flow,
|
||
group_basic_num,
|
||
Top_sensor_num,
|
||
if_gy,
|
||
pressure_threshold,
|
||
leak_mag,
|
||
n_workers=1,
|
||
stage_timing=None,
|
||
partition_on_full_graph=True,
|
||
visualize_partition=False,
|
||
visualize_pause_seconds=0.3,
|
||
final_candidates_csv_path=None,
|
||
):
|
||
if stage_timing is None:
|
||
stage_timing = {}
|
||
exit_condition = "unknown"
|
||
final_candidates_csv = None
|
||
iter_count = 0
|
||
all_node_iter = copy.deepcopy(all_node)
|
||
candidate_pipe_input = copy.deepcopy(candidate_pipe_input_initial) # 可能漏损管段
|
||
t1 = datetime.now()
|
||
if_flow, if_only_cos, if_only_flow = decode_mode(similarity_mode) # 定位方法
|
||
# threshold
|
||
if if_only_flow == 1:
|
||
dpressure = (flow_predict - flow_monitor).mean()
|
||
dpressure = dpressure.abs()
|
||
effective_sensor = list(dpressure.index)
|
||
|
||
else:
|
||
dpressure = (pressure_predict - pressure_monitor).mean()
|
||
dpressure = dpressure.abs()
|
||
dpressure = dpressure[dpressure > pressure_threshold]
|
||
effective_sensor = list(dpressure.index)
|
||
simulation_times = 0 # 模拟次数
|
||
if len(dpressure) > 0:
|
||
break_flag = 0
|
||
last_round_candidate_details = None
|
||
|
||
cos_h = 0
|
||
dis_h = 0
|
||
dis_f_h = 0
|
||
if_compalsive = 0
|
||
record_center_dataset = []
|
||
record_center_set = set()
|
||
# iter
|
||
while 1:
|
||
final_area = []
|
||
final_center = []
|
||
group_num = cal_group_num(candidate_pipe_input, group_basic_num)
|
||
partition_nodes = all_node if partition_on_full_graph else all_node_iter
|
||
|
||
# group 分组,得出候选漏损中心
|
||
stage_start = perf_counter()
|
||
(
|
||
candidate_center_list,
|
||
candidate_group_list,
|
||
new_all_node,
|
||
candidate_center_candidates,
|
||
) = (
|
||
metis_grouping_pipe_weight(
|
||
G0,
|
||
wn,
|
||
partition_nodes,
|
||
candidate_pipe_input,
|
||
group_num,
|
||
node_x,
|
||
node_y,
|
||
pipe_start_node_all,
|
||
pipe_end_node_all,
|
||
node_pipe_dic,
|
||
all_node_series,
|
||
couple_node_length,
|
||
pipe_diameter,
|
||
)
|
||
)
|
||
_accumulate_stage(stage_timing, "group_partitioning", stage_start)
|
||
if visualize_partition:
|
||
visualize_metis_partition(
|
||
G0,
|
||
candidate_center_list,
|
||
candidate_group_list,
|
||
node_x,
|
||
node_y,
|
||
pipe_start_node_all,
|
||
pipe_end_node_all,
|
||
title=(
|
||
f"METIS Partition Iteration {iter_count + 1} | "
|
||
f"candidate pipes={len(candidate_pipe_input)} "
|
||
f"groups={len(candidate_group_list)}"
|
||
),
|
||
block=False,
|
||
pause_seconds=visualize_pause_seconds,
|
||
)
|
||
simulation_times = simulation_times + len(candidate_center_list)
|
||
# pick_pressure_leak
|
||
# pressure_leak = pressure_leak_all.loc[candidate_center_list].loc[:, :]
|
||
# flow_leak = flow_leak_all.loc[candidate_center_list].loc[:, :]
|
||
# —— 新增泄漏量(保持你现在的一致,或从外部传入)——
|
||
# —— 只为缺失中心补算,然后取本轮需要的中心子集 ——
|
||
stage_start = perf_counter()
|
||
pressure_leak, flow_leak, pressure_leak_all, flow_leak_all = (
|
||
_ensure_signatures_for_centers(
|
||
wn=wn,
|
||
wn_inp_path=wn_inp_path,
|
||
center_list=candidate_center_list,
|
||
pressure_leak_all=pressure_leak_all,
|
||
flow_leak_all=flow_leak_all,
|
||
timestep_list=timestep_list,
|
||
pressure_monitor=pressure_monitor,
|
||
flow_monitor=flow_monitor,
|
||
leak_mag=leak_mag,
|
||
n_workers=n_workers,
|
||
)
|
||
)
|
||
_accumulate_stage(stage_timing, "signature_for_candidates", stage_start)
|
||
|
||
# pressure_leak_f= pressure_leak.swaplevel()
|
||
|
||
# --------------------------------------------------------
|
||
|
||
add_center = []
|
||
leak_center_dict = dict()
|
||
for i in range(len(candidate_center_list)):
|
||
primary_center = candidate_center_list[i]
|
||
houxuan_center = [
|
||
center
|
||
for center in candidate_center_candidates[i]
|
||
if center != primary_center
|
||
]
|
||
candidate_group_set = set(candidate_group_list[i])
|
||
for each_center in record_center_dataset:
|
||
if (
|
||
each_center in candidate_group_set
|
||
and each_center != primary_center
|
||
):
|
||
houxuan_center.append(each_center)
|
||
add_center = add_center + houxuan_center
|
||
leak_center_dict[primary_center] = _dedupe_preserve_order(
|
||
houxuan_center + [primary_center]
|
||
)
|
||
add_center = _dedupe_preserve_order(add_center)
|
||
for each_group_centers in candidate_center_candidates:
|
||
for each_center in each_group_centers:
|
||
if each_center not in record_center_set:
|
||
record_center_dataset.append(each_center)
|
||
record_center_set.add(each_center)
|
||
for each_center in add_center:
|
||
if each_center not in record_center_set:
|
||
record_center_dataset.append(each_center)
|
||
record_center_set.add(each_center)
|
||
|
||
# --------------------------------------------------------
|
||
# --------------------------------------------------------
|
||
# if len(add_center) > 0:
|
||
# s3 = pressure_leak_all.loc[add_center]
|
||
# pressure_leak = pd.concat([pressure_leak, s3])
|
||
# s4 = flow_leak_all.loc[add_center]
|
||
# flow_leak = pd.concat([flow_leak, s4])
|
||
# --------------------------------------------------------
|
||
# 只为 add_center 里还没算过的中心补算,并与本轮中心合并
|
||
if len(add_center) > 0:
|
||
stage_start = perf_counter()
|
||
pressure_add, flow_add, pressure_leak_all, flow_leak_all = (
|
||
_ensure_signatures_for_centers(
|
||
wn=wn,
|
||
wn_inp_path=wn_inp_path,
|
||
center_list=add_center,
|
||
pressure_leak_all=pressure_leak_all,
|
||
flow_leak_all=flow_leak_all,
|
||
timestep_list=timestep_list,
|
||
pressure_monitor=pressure_monitor,
|
||
flow_monitor=flow_monitor,
|
||
leak_mag=leak_mag, # 与上面一致
|
||
n_workers=n_workers,
|
||
)
|
||
)
|
||
_accumulate_stage(
|
||
stage_timing, "signature_for_extra_centers", stage_start
|
||
)
|
||
pressure_leak = pd.concat([pressure_leak, pressure_add], axis=0)
|
||
if (flow_leak is not None) and (flow_add is not None):
|
||
flow_leak = pd.concat([flow_leak, flow_add], axis=0)
|
||
# --------------------------------------------------------
|
||
#
|
||
if len(candidate_pipe_input) < 1.2 * top_pipe_num_max / top_group_ratio:
|
||
if_compalsive = 1
|
||
cos_h, dis_h, dis_f_h = adjust_ratio(similarity_mode, cos_h, dis_h, dis_f_h)
|
||
candidate_center_list_sup = _dedupe_preserve_order(
|
||
candidate_center_list + add_center
|
||
)
|
||
stage_start = perf_counter()
|
||
similarity, cos_h, dis_h, dis_f_h, break_flag, similarity_details = (
|
||
cal_similarity_all_multi_new_sq_improve_double_lzr(
|
||
candidate_center_list_sup,
|
||
similarity_mode,
|
||
pressure_leak,
|
||
pressure_monitor,
|
||
pressure_predict,
|
||
pressure_normal,
|
||
if_flow,
|
||
if_only_cos,
|
||
if_only_flow,
|
||
flow_leak,
|
||
flow_monitor,
|
||
flow_predict,
|
||
flow_normal,
|
||
timestep_list,
|
||
Top_sensor_num,
|
||
if_gy,
|
||
effective_sensor,
|
||
cos_h,
|
||
dis_h,
|
||
dis_f_h,
|
||
if_compalsive,
|
||
max_flow,
|
||
)
|
||
)
|
||
last_round_candidate_details = similarity_details
|
||
_accumulate_stage(stage_timing, "similarity_ranking", stage_start)
|
||
if break_flag == 1:
|
||
exit_condition = "similarity_break_flag"
|
||
break
|
||
|
||
new_similarity = update_similarity(
|
||
candidate_center_list, similarity, leak_center_dict
|
||
)
|
||
if len(candidate_pipe_input) > top_pipe_num_max / top_group_ratio:
|
||
cut_ratio, new_similarity = extra_judge(new_similarity)
|
||
else:
|
||
cut_ratio = 1
|
||
stage_start = perf_counter()
|
||
final_area_t, final_center_t, all_node_new_1, if_end = (
|
||
area_output_num_ki_improve(
|
||
candidate_center_list,
|
||
candidate_group_list,
|
||
new_similarity,
|
||
new_all_node,
|
||
top_group_ratio,
|
||
top_pipe_num_max,
|
||
top_pipe_num_min,
|
||
cut_ratio,
|
||
)
|
||
)
|
||
_accumulate_stage(stage_timing, "candidate_area_selection", stage_start)
|
||
final_area = final_area + final_area_t
|
||
final_center = final_center + final_center_t
|
||
|
||
final_area = sorted(set(final_area))
|
||
final_center = sorted(set(final_center))
|
||
if if_end == 1:
|
||
exit_condition = "candidate_area_if_end"
|
||
break
|
||
elif len(candidate_pipe_input) == len(final_area):
|
||
exit_condition = "candidate_size_no_change"
|
||
break
|
||
else:
|
||
candidate_pipe_input = final_area
|
||
if not partition_on_full_graph:
|
||
all_node_iter = all_node_new_1
|
||
iter_count += 1
|
||
sys.stdout.write(
|
||
"\r"
|
||
+ "已经完成"
|
||
+ str(iter_count)
|
||
+ "次迭代计算"
|
||
+ "候选节点"
|
||
+ str(len(final_area))
|
||
+ "个"
|
||
)
|
||
# if break_flag == 0:
|
||
# final_area_pipe = copy.deepcopy(final_area)
|
||
# simulation_times = simulation_times + len(final_area)
|
||
# pressure_leak_sp = pressure_leak_all.loc[final_area_pipe].loc[:, :]
|
||
# flow_leak_sp = flow_leak_all.loc[final_area_pipe].loc[:, :]
|
||
# similarity_sp, cos_h, dis_h, dis_f_h, break_flag = cal_similarity_all_multi_new_sq_improve_double_lzr(
|
||
# final_area_pipe, similarity_mode, pressure_leak_sp,
|
||
# pressure_monitor, pressure_predict, pressure_normal, if_flow,
|
||
# if_only_cos, if_only_flow,
|
||
# flow_leak_sp, flow_monitor, flow_predict, flow_normal,
|
||
# timestep_list, Top_sensor_num, if_gy, effective_sensor, cos_h, dis_h, dis_f_h, if_compalsive, max_flow)
|
||
if break_flag == 0:
|
||
final_area_pipe = list(final_area) # 确保是 list
|
||
|
||
# 只为还没算过的管段补齐 SLF(按需计算)
|
||
stage_start = perf_counter()
|
||
pressure_leak_sp, flow_leak_sp, pressure_leak_all, flow_leak_all = (
|
||
_ensure_signatures_for_centers(
|
||
wn=wn,
|
||
wn_inp_path=wn_inp_path,
|
||
center_list=final_area_pipe, # 这次要用的“最终区域里的所有管段”
|
||
pressure_leak_all=pressure_leak_all, # 累积缓存(会被更新)
|
||
flow_leak_all=flow_leak_all,
|
||
timestep_list=timestep_list,
|
||
pressure_monitor=pressure_monitor,
|
||
flow_monitor=flow_monitor,
|
||
leak_mag=leak_mag,
|
||
n_workers=n_workers,
|
||
)
|
||
)
|
||
_accumulate_stage(stage_timing, "signature_for_final_area", stage_start)
|
||
|
||
# 如果你要精确统计模拟次数,这里可以加上“本次新补的数量”,
|
||
# 做法:让 _ensure_signatures_for_centers 额外返回 need_cnt,再 simulation_times += need_cnt
|
||
|
||
stage_start = perf_counter()
|
||
(
|
||
similarity_sp,
|
||
cos_h,
|
||
dis_h,
|
||
dis_f_h,
|
||
break_flag,
|
||
similarity_details,
|
||
) = (
|
||
cal_similarity_all_multi_new_sq_improve_double_lzr(
|
||
final_area_pipe,
|
||
similarity_mode,
|
||
pressure_leak_sp,
|
||
pressure_monitor,
|
||
pressure_predict,
|
||
pressure_normal,
|
||
if_flow,
|
||
if_only_cos,
|
||
if_only_flow,
|
||
flow_leak_sp,
|
||
flow_monitor,
|
||
flow_predict,
|
||
flow_normal,
|
||
timestep_list,
|
||
Top_sensor_num,
|
||
if_gy,
|
||
effective_sensor,
|
||
cos_h,
|
||
dis_h,
|
||
dis_f_h,
|
||
if_compalsive,
|
||
max_flow,
|
||
)
|
||
)
|
||
last_round_candidate_details = similarity_details
|
||
_accumulate_stage(stage_timing, "similarity_final", stage_start)
|
||
|
||
else:
|
||
dpressure = (pressure_predict - pressure_monitor).mean()
|
||
dpressure = dpressure.abs()
|
||
simulation_times = simulation_times + len(dpressure.index)
|
||
similarity_sp = pd.Series(dtype=float)
|
||
for each_node in dpressure.index:
|
||
pipe = node_pipe_dic[each_node][0]
|
||
similarity_sp.loc[pipe] = dpressure.loc[each_node]
|
||
similarity_sp = similarity_sp.sort_values(ascending=False, kind="mergesort")
|
||
t2 = datetime.now()
|
||
final_area_pipe = []
|
||
|
||
sys.stdout.write(
|
||
"\r"
|
||
+ "已经完成"
|
||
+ str(iter_count + 1)
|
||
+ "次迭代计算"
|
||
+ "候选节点"
|
||
+ str(len(final_area_pipe))
|
||
+ "个"
|
||
)
|
||
t2 = datetime.now()
|
||
dt = (t2 - t1).seconds
|
||
final_candidates_csv = _write_last_round_candidates_csv(
|
||
csv_path=final_candidates_csv_path,
|
||
exit_condition=exit_condition,
|
||
iteration_count=iter_count + 1,
|
||
similarity_mode=similarity_mode,
|
||
candidate_details=last_round_candidate_details,
|
||
fallback_similarity=similarity_sp,
|
||
)
|
||
else:
|
||
exit_condition = "no_effective_sensor_after_threshold"
|
||
dpressure = (pressure_predict - pressure_monitor).mean()
|
||
dpressure = dpressure.abs()
|
||
|
||
similarity_sp = pd.Series(dtype=float)
|
||
for each_node in dpressure.index:
|
||
pipe = node_pipe_dic[each_node][0]
|
||
similarity_sp.loc[pipe] = dpressure.loc[each_node]
|
||
similarity_sp = similarity_sp.sort_values(ascending=False, kind="mergesort")
|
||
t2 = datetime.now()
|
||
dt = (t2 - t1).seconds
|
||
final_candidates_csv = _write_last_round_candidates_csv(
|
||
csv_path=final_candidates_csv_path,
|
||
exit_condition=exit_condition,
|
||
iteration_count=0,
|
||
similarity_mode=similarity_mode,
|
||
candidate_details=None,
|
||
fallback_similarity=similarity_sp,
|
||
)
|
||
stage_timing["iterations"] = iter_count + 1 if len(dpressure) > 0 else 0
|
||
stage_timing["total_elapsed_seconds"] = float(dt)
|
||
stage_timing["exit_condition"] = exit_condition
|
||
stage_timing["final_candidates_csv"] = final_candidates_csv
|
||
return (
|
||
similarity_sp.index[0],
|
||
dt,
|
||
simulation_times,
|
||
wn,
|
||
similarity_sp,
|
||
exit_condition,
|
||
final_candidates_csv,
|
||
)
|
||
|
||
|