import pandas as pd
import numpy as np
import re
from typing import Tuple
def curve_score(
value: float,
spec_range: Tuple[float, float],
weight: float,
min_score: float = 0.0,
base_curvature: float = 2.0,
narrow_range_coeff: float = 5.0
) -> float:
lower, upper = spec_range
if lower <= value <= upper:
return 1.0
# 计算规格宽度和边界
if lower == -np.inf and upper == np.inf:
return 1.0
elif lower == -np.inf:
spec_width = abs(upper) * 2 if upper != 0 else 1
bound = upper
elif upper == np.inf:
spec_width = abs(lower) * 2 if lower != 0 else 1
bound = lower
else:
spec_width = upper - lower
bound = lower if value < lower else upper
# 标准化距离
distance = abs(value - bound)
if spec_width == 0:
distance_ratio = distance / (abs(bound) + 1e-6)
else:
distance_ratio = distance / spec_width
# 动态曲率(基础曲率×权重×窄化系数)
if spec_width > 0:
narrow_coeff = 1 + narrow_range_coeff / (spec_width + 1)
else:
narrow_coeff = 1 + narrow_range_coeff
dynamic_curvature = base_curvature * weight * narrow_coeff
# 严重偏离额外惩罚
if distance_ratio > 0.5:
distance_ratio = distance_ratio ** 1.5
return max(min_score, np.exp(-dynamic_curvature * distance_ratio))
def dynamic_filter_sort(predictedDF, target_spec, weights):
mask = pd.Series(True, index=predictedDF.index)
filtered_df = predictedDF[mask].copy()
score = pd.Series(0.0, index=filtered_df.index)
for col, cond in target_spec.items():
col_values = filtered_df[col].astype(float)
weight = weights.get(col, 1.0)
# 给窄范围spec加隐性权重(可选,根据需求开启)
if '-' in cond:
low, high = map(float, re.fullmatch(r'^(-?\d+\.?\d*)-(-?\d+\.?\d*)$', cond).groups())
spec_width = high - low
if spec_width < 10: # 范围宽度<10判定为窄范围
weight *= 1.2 # 隐性权重系数
# 条件处理
if '-' in cond:
spec = (low, high)
normalized = col_values.apply(lambda x: curve_score(x, spec, weight=weight))
score += normalized * weight
elif cond.startswith('lt('):
ceiling = float(cond[3:-1])
spec = (-np.inf, ceiling)
normalized = col_values.apply(lambda x: curve_score(x, spec, weight=weight))
score += normalized * weight
elif cond.startswith('gt('):
floor = float(cond[3:-1])
spec = (floor, np.inf)
normalized = col_values.apply(lambda x: curve_score(x, spec, weight=weight))
score += normalized * weight
else:
try:
target_val = float(cond)
except ValueError:
target_val = cond
spec = (target_val, target_val)
normalized = col_values.apply(lambda x: curve_score(x, spec, weight=weight))
score += normalized * weight
filtered_df['score#'] = round(score, 3)
return filtered_df.sort_values('score#', ascending=False)
# 业务代码(无需修改,直接使用)
data_df = pd.DataFrame(
np.array(result['specMatrix'])[recipe_index,:].reshape(1,-1),
columns=result['maxMatrix'].keys()
)
target_spec = {
'Depth': '1100-1300',
'SOCremain': '0-500',
'SiNSWA': '86-89',
'TCD': '21-22',
'doubleslope': '0-1',
'maskremain': '2201.8-2833.7'
}
weights = {
'Depth': 3,
'SOCremain': 1,
'SiNSWA': 1,
'TCD': 3, # 可根据需要调整为3.5
'doubleslope': 2,
'maskremain': 1
}
data_df = (-dynamic_filter_sort(data_df, target_spec, weights)['score#'].values[:]).tolist()