结构健康监测仿真-主题038-结构健康监测中的优化算法技术
结构健康监测仿真-主题038-结构健康监测中的优化算法技术
目录


引言
1.1 优化在结构健康监测中的重要性
结构健康监测(SHM)涉及大量的优化问题,从传感器布置优化到损伤识别,从模型修正到维护决策,优化算法贯穿整个SHM流程。优化算法的性能直接影响监测系统的效率和准确性。
SHM中的典型优化问题:
- 传感器布置优化:在有限资源下确定最优传感器数量和位置
- 损伤识别优化:通过优化算法识别损伤的位置和程度
- 模型修正优化:调整有限元模型参数使其与实测数据吻合
- 维护策略优化:制定最优的检测和维护计划
- 信号处理优化:优化滤波器参数、特征提取方法等
1.2 优化问题的数学描述
一个典型的优化问题可以表示为:
最小化:f(x)
约束条件:
g_i(x) ≤ 0, i = 1, 2, ..., m (不等式约束)
h_j(x) = 0, j = 1, 2, ..., p (等式约束)
x_L ≤ x ≤ x_U (边界约束)
其中:
- x = [x₁, x₂, …, xₙ]ᵀ 是设计变量向量
- f(x) 是目标函数
- g_i(x) 是不等式约束函数
- h_j(x) 是等式约束函数
- x_L 和 x_U 是设计变量的下界和上界
1.3 优化问题的分类
按目标函数数量分类:
- 单目标优化:只有一个目标函数
- 多目标优化:多个冲突的目标函数需要同时优化
按约束条件分类:
- 无约束优化:没有任何约束条件
- 等式约束优化:只有等式约束
- 不等式约束优化:只有不等式约束
- 混合约束优化:同时包含等式和不等式约束
按问题特性分类:
- 线性规划:目标函数和约束都是线性的
- 非线性规划:目标函数或约束是非线性的
- 整数规划:设计变量必须是整数
- 混合整数规划:部分变量连续,部分变量离散
- 凸优化:目标函数是凸函数,可行域是凸集
按搜索空间特性分类:
- 连续优化:设计变量在连续空间取值
- 离散优化/组合优化:设计变量在离散空间取值
- 混合优化:同时包含连续和离散变量
优化算法基础理论
2.1 最优性条件
局部最优与全局最优:
- 局部最优解:在解的某个邻域内,没有其他解比它更优
- 全局最优解:在整个可行域内,没有其他解比它更优
一阶必要条件(KKT条件):
对于约束优化问题,若x*是局部最优解,且满足一定的正则性条件,则存在拉格朗日乘子λ和μ,使得:
∇f(x*) + Σλ_i∇g_i(x*) + Σμ_j∇h_j(x*) = 0 (平稳性)
g_i(x*) ≤ 0, λ_i ≥ 0, λ_i·g_i(x*) = 0 (互补松弛性)
h_j(x*) = 0 (可行性)
二阶充分条件:
在KKT点处,如果Hessian矩阵在切空间上正定,则该点是严格局部最优解。
2.2 优化算法的收敛性
收敛性定义:
- 弱收敛:算法产生的序列有子序列收敛到最优解
- 强收敛:算法产生的序列本身收敛到最优解
- 线性收敛:‖x_{k+1} - x*‖ ≤ c‖x_k - x*‖, 0 < c < 1
- 超线性收敛:lim ‖x_{k+1} - x*‖ / ‖x_k - x*‖ = 0
- 二次收敛:‖x_{k+1} - x*‖ ≤ c‖x_k - x*‖²
2.3 计算复杂度
时间复杂度:
- 多项式时间算法:O(n^k),k为常数
- 指数时间算法:O(2^n)或O(n!)
- NP-hard问题:没有已知的多项式时间算法
空间复杂度:
算法运行所需的内存空间随问题规模的增长关系。
传统优化算法
3.1 梯度下降法
基本思想:
沿着目标函数的负梯度方向进行搜索,逐步逼近最优解。
算法步骤:
1. 初始化:选择初始点x₀,设置收敛阈值ε
2. 计算梯度:g_k = ∇f(x_k)
3. 检查收敛:如果‖g_k‖ < ε,停止
4. 确定步长:通过线搜索确定α_k
5. 更新:x_{k+1} = x_k - α_k·g_k
6. 返回步骤2
步长选择策略:
- 固定步长:α_k = α(常数)
- 精确线搜索:α_k = argmin f(x_k - α·g_k)
- Armijo准则:确保充分下降
- Wolfe条件:结合Armijo条件和曲率条件
优缺点:
- 优点:简单易实现,收敛速度快(对于强凸函数)
- 缺点:可能收敛到局部最优,对初始点敏感,对病态问题收敛慢
Python实现:
def gradient_descent(f, grad_f, x0, alpha=0.01, max_iter=1000, tol=1e-6):
"""
梯度下降法
参数:
f: 目标函数
grad_f: 梯度函数
x0: 初始点
alpha: 步长
max_iter: 最大迭代次数
tol: 收敛阈值
返回:
x: 最优解
history: 迭代历史
"""
x = x0.copy()
history = {'x': [x.copy()], 'f': [f(x)], 'grad_norm': []}
for i in range(max_iter):
grad = grad_f(x)
grad_norm = np.linalg.norm(grad)
history['grad_norm'].append(grad_norm)
if grad_norm < tol:
break
x = x - alpha * grad
history['x'].append(x.copy())
history['f'].append(f(x))
return x, history
3.2 牛顿法
基本思想:
利用目标函数的二阶信息(Hessian矩阵)来确定搜索方向,具有二次收敛速度。
算法公式:
x_{k+1} = x_k - [∇²f(x_k)]⁻¹·∇f(x_k)
算法步骤:
1. 初始化:选择初始点x₀
2. 计算梯度和Hessian:g_k = ∇f(x_k), H_k = ∇²f(x_k)
3. 求解线性方程组:H_k·d_k = -g_k
4. 更新:x_{k+1} = x_k + d_k
5. 检查收敛,否则返回步骤2
优缺点:
- 优点:收敛速度快(二次收敛),精度高
- 缺点:需要计算和存储Hessian矩阵,计算量大,可能收敛到鞍点
拟牛顿法(BFGS):
用近似矩阵代替Hessian矩阵,避免直接计算二阶导数。
def bfgs(f, grad_f, x0, max_iter=1000, tol=1e-6):
"""
BFGS拟牛顿法
"""
n = len(x0)
x = x0.copy()
H = np.eye(n) # 初始Hessian近似为单位矩阵
history = {'x': [x.copy()], 'f': [f(x)]}
for i in range(max_iter):
grad = grad_f(x)
if np.linalg.norm(grad) < tol:
break
# 搜索方向
d = -H @ grad
# 线搜索确定步长
alpha = line_search(f, grad_f, x, d)
# 更新
x_new = x + alpha * d
grad_new = grad_f(x_new)
s = x_new - x
y = grad_new - grad
# BFGS更新公式
rho = 1.0 / (y @ s)
H = (np.eye(n) - rho * np.outer(s, y)) @ H @ (np.eye(n) - rho * np.outer(y, s)) + rho * np.outer(s, s)
x = x_new
history['x'].append(x.copy())
history['f'].append(f(x))
return x, history
3.3 共轭梯度法
基本思想:
结合梯度下降法的简单性和牛顿法的快速收敛性,通过构造共轭方向来加速收敛。
共轭方向定义:
两个方向d_i和d_j关于对称正定矩阵A共轭,如果:
d_iᵀ·A·d_j = 0, i ≠ j
算法步骤(Fletcher-Reeves公式):
1. 初始化:x₀, d₀ = -∇f(x₀)
2. 线搜索:α_k = argmin f(x_k + α·d_k)
3. 更新:x_{k+1} = x_k + α_k·d_k
4. 计算β_{k+1} = ‖∇f(x_{k+1})‖² / ‖∇f(x_k)‖²
5. 更新方向:d_{k+1} = -∇f(x_{k+1}) + β_{k+1}·d_k
6. 检查收敛,否则返回步骤2
优缺点:
- 优点:收敛速度快,存储需求小,适合大规模问题
- 缺点:对于非凸问题可能不稳定
3.4 最小二乘法
线性最小二乘:
对于超定线性方程组Ax ≈ b,最小二乘解为:
x* = (AᵀA)⁻¹Aᵀb
非线性最小二乘(高斯-牛顿法):
用于求解min ‖r(x)‖²,其中r(x)是残差向量。
x_{k+1} = x_k - (J_kᵀJ_k)⁻¹J_kᵀr_k
其中J是残差的Jacobian矩阵。
Levenberg-Marquardt算法:
结合高斯-牛顿法和梯度下降法的优点:
x_{k+1} = x_k - (J_kᵀJ_k + λI)⁻¹J_kᵀr_k
当λ→0时接近高斯-牛顿法,当λ很大时接近梯度下降法。
进化优化算法
4.1 遗传算法(GA)
基本思想:
模拟生物进化过程,通过选择、交叉、变异等遗传操作来搜索最优解。
算法流程:
1. 初始化:随机生成N个个体构成初始种群
2. 评估:计算每个个体的适应度
3. 选择:根据适应度选择父代个体
4. 交叉:以概率Pc进行交叉操作产生子代
5. 变异:以概率Pm进行变异操作
6. 替换:用子代替换父代形成新种群
7. 检查终止条件,否则返回步骤2
关键操作:
选择操作:
- 轮盘赌选择:按适应度比例选择
- 锦标赛选择:随机选择k个个体,取最优
- 排序选择:按适应度排序后选择
交叉操作:
- 单点交叉:随机选择交叉点,交换片段
- 多点交叉:多个交叉点
- 均匀交叉:每个基因独立决定是否交换
- 算术交叉:x’ = α·x₁ + (1-α)·x₂
变异操作:
- 位变异:二进制编码中翻转某些位
- 高斯变异:实数编码中添加高斯噪声
- 多项式变异:使用多项式分布进行变异
Python实现:
class GeneticAlgorithm:
"""遗传算法"""
def __init__(self, pop_size=100, n_generations=200,
crossover_prob=0.8, mutation_prob=0.1):
self.pop_size = pop_size
self.n_generations = n_generations
self.crossover_prob = crossover_prob
self.mutation_prob = mutation_prob
def initialize_population(self, n_vars, bounds):
"""初始化种群"""
pop = np.random.rand(self.pop_size, n_vars)
for i in range(n_vars):
pop[:, i] = bounds[i][0] + pop[:, i] * (bounds[i][1] - bounds[i][0])
return pop
def tournament_selection(self, fitness, tournament_size=3):
"""锦标赛选择"""
selected = []
for _ in range(self.pop_size):
idx = np.random.choice(len(fitness), tournament_size, replace=False)
winner = idx[np.argmin(fitness[idx])] # 最小化问题
selected.append(winner)
return selected
def crossover(self, parent1, parent2):
"""模拟二进制交叉(SBX)"""
if np.random.random() > self.crossover_prob:
return parent1.copy(), parent2.copy()
eta = 20 # 分布指数
child1, child2 = parent1.copy(), parent2.copy()
for i in range(len(parent1)):
if np.random.random() <= 0.5:
if abs(parent1[i] - parent2[i]) > 1e-14:
if parent1[i] < parent2[i]:
y1, y2 = parent1[i], parent2[i]
else:
y1, y2 = parent2[i], parent1[i]
beta = 1.0 + (2.0 * (y1 - 0) / (y2 - y1))
alpha = 2.0 - beta ** (-(eta + 1))
rand = np.random.random()
if rand <= 1.0 / alpha:
beta_q = (rand * alpha) ** (1.0 / (eta + 1))
else:
beta_q = (1.0 / (2.0 - rand * alpha)) ** (1.0 / (eta + 1))
c1 = 0.5 * ((y1 + y2) - beta_q * (y2 - y1))
beta = 1.0 + (2.0 * (1 - y2) / (y2 - y1))
alpha = 2.0 - beta ** (-(eta + 1))
if rand <= 1.0 / alpha:
beta_q = (rand * alpha) ** (1.0 / (eta + 1))
else:
beta_q = (1.0 / (2.0 - rand * alpha)) ** (1.0 / (eta + 1))
c2 = 0.5 * ((y1 + y2) + beta_q * (y2 - y1))
child1[i], child2[i] = c1, c2
return child1, child2
def mutate(self, individual, bounds):
"""多项式变异"""
eta_m = 20
mutant = individual.copy()
for i in range(len(individual)):
if np.random.random() <= self.mutation_prob:
y = individual[i]
yl, yu = bounds[i]
delta1 = (y - yl) / (yu - yl)
delta2 = (yu - y) / (yu - yl)
rand = np.random.random()
mut_pow = 1.0 / (eta_m + 1.0)
if rand <= 0.5:
xy = 1.0 - delta1
val = 2.0 * rand + (1.0 - 2.0 * rand) * (xy ** (eta_m + 1))
delta_q = val ** mut_pow - 1.0
else:
xy = 1.0 - delta2
val = 2.0 * (1.0 - rand) + 2.0 * (rand - 0.5) * (xy ** (eta_m + 1))
delta_q = 1.0 - val ** mut_pow
y = y + delta_q * (yu - yl)
mutant[i] = np.clip(y, yl, yu)
return mutant
def optimize(self, objective_func, n_vars, bounds):
"""优化主函数"""
# 初始化
population = self.initialize_population(n_vars, bounds)
fitness = np.array([objective_func(ind) for ind in population])
best_history = []
for gen in range(self.n_generations):
# 选择
selected_idx = self.tournament_selection(fitness)
# 交叉和变异
offspring = []
for i in range(0, self.pop_size, 2):
p1_idx = selected_idx[i]
p2_idx = selected_idx[(i + 1) % self.pop_size]
child1, child2 = self.crossover(population[p1_idx], population[p2_idx])
child1 = self.mutate(child1, bounds)
child2 = self.mutate(child2, bounds)
offspring.extend([child1, child2])
offspring = np.array(offspring[:self.pop_size])
offspring_fitness = np.array([objective_func(ind) for ind in offspring])
# 精英保留
combined = np.vstack([population, offspring])
combined_fitness = np.concatenate([fitness, offspring_fitness])
best_idx = np.argsort(combined_fitness)[:self.pop_size]
population = combined[best_idx]
fitness = combined_fitness[best_idx]
best_history.append(fitness[0])
best_idx = np.argmin(fitness)
return population[best_idx], fitness[best_idx], best_history
4.2 差分进化(DE)
基本思想:
通过个体间的差分向量来引导搜索方向,具有全局搜索能力强、参数少、易于实现等优点。
算法流程:
1. 初始化:随机生成N个个体
2. 对于每个个体x_i(目标向量):
a. 变异:v_i = x_{r1} + F·(x_{r2} - x_{r3})
b. 交叉:将v_i与x_i交叉生成试验向量u_i
c. 选择:如果f(u_i) < f(x_i),则x_i = u_i
3. 检查终止条件,否则返回步骤2
变异策略:
- DE/rand/1:v = x_{r1} + F·(x_{r2} - x_{r3})
- DE/best/1:v = x_{best} + F·(x_{r1} - x_{r2})
- DE/current-to-best/1:v = x_i + F·(x_{best} - x_i) + F·(x_{r1} - x_{r2})
参数设置:
- 种群大小N:通常5D~10D(D为维度)
- 缩放因子F:通常0.4~1.0
- 交叉概率CR:通常0.1~1.0
4.3 进化策略(ES)
基本思想:
强调自适应性,通过进化机制调整搜索步长。
主要类型:
- (μ+λ)-ES:从μ个父代和λ个子代中选择最好的μ个
- (μ,λ)-ES:只从λ个子代中选择(μ < λ)
自适应机制:
- 1/5成功规则:根据成功变异的比例调整步长
- 自适应协方差矩阵:学习变量间的相关性
群智能优化算法
5.1 粒子群优化(PSO)
基本思想:
模拟鸟群觅食行为,每个粒子根据自身经验和群体经验调整飞行方向和速度。
算法公式:
v_i(t+1) = w·v_i(t) + c1·r1·(pbest_i - x_i(t)) + c2·r2·(gbest - x_i(t))
x_i(t+1) = x_i(t) + v_i(t+1)
其中:
- w:惯性权重
- c1, c2:学习因子
- r1, r2:[0,1]区间的随机数
- pbest_i:粒子i的历史最优位置
- gbest:群体历史最优位置
参数设置:
- 惯性权重w:通常0.4~0.9,可线性递减
- 学习因子c1, c2:通常都取2.0
- 种群大小:20~50
Python实现:
class ParticleSwarmOptimization:
"""粒子群优化算法"""
def __init__(self, n_particles=30, max_iter=100, w=0.7, c1=2.0, c2=2.0):
self.n_particles = n_particles
self.max_iter = max_iter
self.w = w
self.c1 = c1
self.c2 = c2
def optimize(self, objective_func, n_vars, bounds):
"""优化主函数"""
# 初始化粒子位置和速度
particles = np.random.rand(self.n_particles, n_vars)
for i in range(n_vars):
particles[:, i] = bounds[i][0] + particles[:, i] * (bounds[i][1] - bounds[i][0])
velocities = np.zeros((self.n_particles, n_vars))
# 初始化个体最优和全局最优
pbest = particles.copy()
pbest_fitness = np.array([objective_func(p) for p in particles])
gbest_idx = np.argmin(pbest_fitness)
gbest = pbest[gbest_idx].copy()
gbest_fitness = pbest_fitness[gbest_idx]
history = [gbest_fitness]
for iter in range(self.max_iter):
# 线性递减惯性权重
w = self.w - (self.w - 0.4) * iter / self.max_iter
for i in range(self.n_particles):
r1, r2 = np.random.rand(2)
# 更新速度
velocities[i] = (w * velocities[i] +
self.c1 * r1 * (pbest[i] - particles[i]) +
self.c2 * r2 * (gbest - particles[i]))
# 限制速度
for j in range(n_vars):
vmax = (bounds[j][1] - bounds[j][0]) * 0.5
velocities[i, j] = np.clip(velocities[i, j], -vmax, vmax)
# 更新位置
particles[i] = particles[i] + velocities[i]
# 边界处理
for j in range(n_vars):
particles[i, j] = np.clip(particles[i, j], bounds[j][0], bounds[j][1])
# 评估新位置
fitness = objective_func(particles[i])
# 更新个体最优
if fitness < pbest_fitness[i]:
pbest[i] = particles[i].copy()
pbest_fitness[i] = fitness
# 更新全局最优
if fitness < gbest_fitness:
gbest = particles[i].copy()
gbest_fitness = fitness
history.append(gbest_fitness)
return gbest, gbest_fitness, history
5.2 蚁群优化(ACO)
基本思想:
模拟蚂蚁觅食行为,通过信息素的正反馈机制寻找最优路径。
算法流程:
1. 初始化:设置信息素浓度τ_ij = τ₀
2. 对于每只蚂蚁:
a. 根据信息素和启发信息选择下一个节点
b. 完成路径构造
3. 计算每条路径的长度
4. 更新信息素:
τ_ij = (1-ρ)·τ_ij + Δτ_ij
5. 检查终止条件,否则返回步骤2
状态转移概率:
P(i,j) = [τ(i,j)]^α · [η(i,j)]^β / Σ[τ(i,k)]^α · [η(i,k)]^β
其中:
- τ(i,j):边(i,j)上的信息素浓度
- η(i,j):启发信息(通常是距离的倒数)
- α, β:控制信息素和启发信息的相对重要性
信息素更新:
Δτ(i,j) = Σ(1/L_k) 如果边(i,j)在蚂蚁k的路径上
其中L_k是蚂蚁k的路径长度。
5.3 人工蜂群算法(ABC)
基本思想:
模拟蜜蜂的采蜜行为,包括雇佣蜂、观察蜂和侦查蜂三种角色。
算法流程:
1. 初始化:随机生成SN个食物源(解)
2. 雇佣蜂阶段:
对每个食物源x_i,在其邻域搜索产生新解v_i
如果f(v_i) < f(x_i),则替换
3. 计算选择概率:
P_i = fitness_i / Σfitness_j
4. 观察蜂阶段:
根据概率选择食物源,在其邻域搜索
5. 侦查蜂阶段:
如果某个食物源limit次未改进,则随机产生新解
6. 记录最优解,检查终止条件
邻域搜索:
v_i = x_i + φ·(x_i - x_k)
其中k是随机选择的不同于i的食物源,φ∈[-1,1]是随机数。
5.4 灰狼优化(GWO)
基本思想:
模拟灰狼的社会等级和狩猎行为,包括包围、狩猎和攻击猎物三个阶段。
社会等级:
- α狼:最优解
- β狼:次优解
- δ狼:第三优解
- ω狼:其他解
位置更新:
D_α = |C₁·X_α - X|
D_β = |C₂·X_β - X|
D_δ = |C₃·X_δ - X|
X₁ = X_α - A₁·D_α
X₂ = X_β - A₂·D_β
X₃ = X_δ - A₃·D_δ
X(t+1) = (X₁ + X₂ + X₃) / 3
其中:
- A = 2a·r₁ - a(线性递减从2到0)
- C = 2·r₂
- r₁, r₂:[0,1]区间的随机向量
5.5 鲸鱼优化算法(WOA)
基本思想:
模拟座头鲸的 bubble-net 狩猎行为,包括包围猎物、气泡网攻击和搜索猎物三个阶段。
包围猎物:
D = |C·X*(t) - X(t)|
X(t+1) = X*(t) - A·D
气泡网攻击(螺旋更新):
X(t+1) = D'·e^(bl)·cos(2πl) + X*(t)
其中D’ = |X*(t) - X(t)|,b是常数,l∈[-1,1]是随机数。
搜索猎物(随机选择个体):
D = |C·X_rand - X|
X(t+1) = X_rand - A·D
概率选择:
- 如果|A| < 1且p < 0.5:包围猎物
- 如果|A| < 1且p ≥ 0.5:螺旋更新
- 如果|A| ≥ 1:搜索猎物
多目标优化
6.1 多目标优化基础
问题描述:
最小化:F(x) = [f₁(x), f₂(x), ..., f_m(x)]ᵀ
约束条件:x ∈ Ω
Pareto支配:
解x₁支配x₂(记为x₁ ≺ x₂),当且仅当:
- ∀i: f_i(x₁) ≤ f_i(x₂)
- ∃j: f_j(x₁) < f_j(x₂)
Pareto最优解:
如果不存在其他解支配它,则该解是Pareto最优解。
Pareto前沿:
所有Pareto最优解在目标空间中的映射。
6.2 NSGA-II算法
基本思想:
非支配排序遗传算法II,通过快速非支配排序和拥挤度距离来维护解的多样性。
算法流程:
1. 初始化种群P₀
2. 非支配排序,计算拥挤度
3. 选择、交叉、变异产生子代Q₀
4. 对于每代t:
a. R_t = P_t ∪ Q_t(合并父代和子代)
b. 对R_t进行非支配排序
c. 按 fronts 选择N个个体形成P_{t+1}
d. 对P_{t+1}进行遗传操作产生Q_{t+1}
5. 返回Pareto前沿
快速非支配排序:
- 计算每个解的支配数(被多少解支配)
- 计算每个解支配的解集合
- 按支配数分层
拥挤度距离:
d_i = Σ(f_{i+1}^k - f_{i-1}^k) / (f_max^k - f_min^k)
用于维护解的多样性,优先选择拥挤度大的解。
Python实现:
class NSGA2:
"""NSGA-II多目标优化算法"""
def __init__(self, pop_size=100, n_generations=200,
crossover_prob=0.9, mutation_prob=0.1):
self.pop_size = pop_size
self.n_generations = n_generations
self.crossover_prob = crossover_prob
self.mutation_prob = mutation_prob
def non_dominated_sort(self, objectives):
"""快速非支配排序"""
n = len(objectives)
S = [[] for _ in range(n)] # 支配的解
n_dominated = [0] * n # 被支配数
ranks = [0] * n
fronts = [[]]
for p in range(n):
for q in range(n):
if p != q:
if self.dominates(objectives[p], objectives[q]):
S[p].append(q)
elif self.dominates(objectives[q], objectives[p]):
n_dominated[p] += 1
if n_dominated[p] == 0:
ranks[p] = 0
fronts[0].append(p)
i = 0
while len(fronts[i]) > 0:
Q = []
for p in fronts[i]:
for q in S[p]:
n_dominated[q] -= 1
if n_dominated[q] == 0:
ranks[q] = i + 1
Q.append(q)
i += 1
fronts.append(Q)
return ranks, fronts[:-1]
def dominates(self, obj1, obj2):
"""判断obj1是否支配obj2"""
return np.all(obj1 <= obj2) and np.any(obj1 < obj2)
def crowding_distance(self, objectives):
"""计算拥挤度距离"""
n, m = objectives.shape
if n <= 2:
return np.full(n, np.inf)
distances = np.zeros(n)
for i in range(m):
idx = np.argsort(objectives[:, i])
f_max = objectives[idx[-1], i]
f_min = objectives[idx[0], i]
distances[idx[0]] = distances[idx[-1]] = np.inf
for j in range(1, n - 1):
distances[idx[j]] += (objectives[idx[j+1], i] - objectives[idx[j-1], i]) / (f_max - f_min + 1e-10)
return distances
def optimize(self, objective_funcs, n_vars, bounds):
"""优化主函数"""
n_objs = len(objective_funcs)
# 初始化
pop = np.random.rand(self.pop_size, n_vars)
for i in range(n_vars):
pop[:, i] = bounds[i][0] + pop[:, i] * (bounds[i][1] - bounds[i][0])
# 评估
objectives = np.array([[f(ind) for f in objective_funcs] for ind in pop])
for gen in range(self.n_generations):
# 非支配排序
ranks, fronts = self.non_dominated_sort(objectives)
# 计算拥挤度
crowding_dist = np.zeros(self.pop_size)
for front in fronts:
if len(front) > 0:
crowding_dist[front] = self.crowding_distance(objectives[front])
# 遗传操作产生子代
offspring = self.create_offspring(pop, ranks, crowding_dist, bounds)
offspring_objs = np.array([[f(ind) for f in objective_funcs] for ind in offspring])
# 合并父代和子代
combined_pop = np.vstack([pop, offspring])
combined_objs = np.vstack([objectives, offspring_objs])
# 环境选择
pop, objectives = self.environmental_selection(combined_pop, combined_objs)
# 返回Pareto前沿
ranks, fronts = self.non_dominated_sort(objectives)
pareto_front = objectives[fronts[0]]
pareto_solutions = pop[fronts[0]]
return pareto_solutions, pareto_front
def create_offspring(self, pop, ranks, crowding_dist, bounds):
"""产生子代"""
offspring = []
while len(offspring) < self.pop_size:
# 锦标赛选择
p1 = self.tournament_selection(ranks, crowding_dist)
p2 = self.tournament_selection(ranks, crowding_dist)
# 交叉
if np.random.random() < self.crossover_prob:
child1, child2 = self.sbx_crossover(pop[p1], pop[p2], bounds)
else:
child1, child2 = pop[p1].copy(), pop[p2].copy()
# 变异
child1 = self.polynomial_mutation(child1, bounds)
child2 = self.polynomial_mutation(child2, bounds)
offspring.extend([child1, child2])
return np.array(offspring[:self.pop_size])
def tournament_selection(self, ranks, crowding_dist, tournament_size=2):
"""锦标赛选择"""
candidates = np.random.choice(len(ranks), tournament_size, replace=False)
best = candidates[0]
for c in candidates[1:]:
if ranks[c] < ranks[best]:
best = c
elif ranks[c] == ranks[best] and crowding_dist[c] > crowding_dist[best]:
best = c
return best
def environmental_selection(self, pop, objectives):
"""环境选择"""
ranks, fronts = self.non_dominated_sort(objectives)
selected = []
for front in fronts:
if len(selected) + len(front) <= self.pop_size:
selected.extend(front)
else:
# 按拥挤度排序选择
crowding = self.crowding_distance(objectives[front])
idx = np.argsort(-crowding)
remaining = self.pop_size - len(selected)
selected.extend([front[i] for i in idx[:remaining]])
break
return pop[selected], objectives[selected]
6.3 性能指标
收敛性指标:
- Generational Distance (GD):Pareto前沿到真实前沿的平均距离
- Inverted Generational Distance (IGD):真实前沿到Pareto前沿的平均距离
多样性指标:
- Spacing (SP):解之间的均匀程度
- Maximum Spread (MS):Pareto前沿的覆盖范围
综合性指标:
- Hypervolume (HV):Pareto前沿与参考点围成的超体积
约束优化处理
7.1 惩罚函数法
基本思想:
将约束违反度以惩罚项的形式加入目标函数,将约束优化转化为无约束优化。
静态惩罚:
F(x) = f(x) + Σr_i·max(0, g_i(x))² + Σc_j·h_j(x)²
动态惩罚:
惩罚系数随迭代增加:
r(t) = (2t)^α
自适应惩罚:
根据种群中可行解的比例调整惩罚系数。
7.2 修复法
基本思想:
将不可行解投影到可行域内。
常用方法:
- 投影法:将解投影到最近的边界
- 反射法:将解反射回可行域
- 截断法:将超出边界的分量设为边界值
7.3 特殊编码和处理
解码器法:
设计特殊的编码方式,保证生成的解总是可行的。
分离法:
分别处理可行解和不可行解,优先保留可行解。
7.4 多目标化处理
将约束优化转化为多目标优化:
最小化:[f(x), CV(x)]
其中CV(x)是约束违反度。
Python仿真实现
8.1 传感器布置优化
问题描述:
在结构上选择最优的传感器位置,使得损伤识别能力最大化。
目标函数:
- 最大化模态置信准则(MAC)矩阵的非对角元最小值
- 最小化Fisher信息矩阵的条件数
def sensor_placement_objective(sensor_positions, mode_shapes, n_sensors):
"""
传感器布置优化目标函数
参数:
sensor_positions: 传感器位置(二进制编码)
mode_shapes: 模态振型矩阵
n_sensors: 传感器数量
返回:
目标函数值(越小越好)
"""
# 选择传感器位置的模态振型
selected_modes = mode_shapes[sensor_positions == 1, :]
if np.sum(sensor_positions) != n_sensors:
return 1e10 # 惩罚不满足约束的解
# 计算MAC矩阵
n_modes = mode_shapes.shape[1]
MAC = np.zeros((n_modes, n_modes))
for i in range(n_modes):
for j in range(n_modes):
phi_i = selected_modes[:, i]
phi_j = selected_modes[:, j]
MAC[i, j] = (phi_i @ phi_j) ** 2 / ((phi_i @ phi_i) * (phi_j @ phi_j))
# 目标:最大化非对角元的差异(最小化最大非对角元)
off_diag = MAC - np.diag(np.diag(MAC))
max_off_diag = np.max(off_diag)
return max_off_diag
8.2 损伤识别优化
问题描述:
通过优化算法识别结构损伤的位置和程度。
目标函数(最小化残差):
def damage_identification_objective(damage_params, measured_frequencies,
measured_modes, model_func):
"""
损伤识别目标函数
参数:
damage_params: 损伤参数(位置和程度)
measured_frequencies: 实测频率
measured_modes: 实测模态
model_func: 结构模型函数
返回:
残差平方和
"""
# 解析损伤参数
n_elements = len(damage_params) // 2
damage_locations = damage_params[:n_elements].astype(int)
damage_severities = damage_params[n_elements:]
# 计算预测响应
pred_frequencies, pred_modes = model_func(damage_locations, damage_severities)
# 频率残差
freq_residual = np.sum((measured_frequencies - pred_frequencies) ** 2 / measured_frequencies ** 2)
# 模态残差(MAC)
mode_residual = 0
for i in range(len(measured_frequencies)):
mac = calculate_mac(measured_modes[:, i], pred_modes[:, i])
mode_residual += (1 - mac) ** 2
return freq_residual + mode_residual
8.3 模型修正优化
问题描述:
调整有限元模型的参数,使其与实测数据吻合。
def model_updating_objective(params, measured_data, fem_model):
"""
模型修正目标函数
参数:
params: 待修正参数(弹性模量、密度等)
measured_data: 实测数据
fem_model: 有限元模型
返回:
残差
"""
# 更新模型参数
E, rho, damping = params[0], params[1], params[2]
fem_model.update_material(E, rho, damping)
# 计算模型响应
pred_frequencies, pred_modes = fem_model.modal_analysis()
# 计算残差
residual = 0
# 频率残差
for i, (pred, meas) in enumerate(zip(pred_frequencies, measured_data['frequencies'])):
residual += ((pred - meas) / meas) ** 2
# 模态残差
for i in range(len(measured_data['frequencies'])):
mac = calculate_mac(pred_modes[:, i], measured_data['modes'][:, i])
residual += (1 - mac) ** 2
return residual
案例分析
9.1 案例一:简支梁传感器优化布置
问题描述:
在20个单元的简支梁上选择5个最优传感器位置。
优化设置:
- 算法:遗传算法
- 种群大小:50
- 迭代次数:100
- 编码:二进制编码(20位,1表示有传感器)
结果分析:
- 最优布置位置:第3、7、12、16、19单元
- MAC矩阵最大非对角元:0.05
- 传感器均匀分布在梁上,避免聚集
9.2 案例二:桁架结构损伤识别
问题描述:
识别10杆桁架中可能存在的损伤杆件及其损伤程度。
损伤模型:
E_damaged = (1 - α)·E_healthy
其中α是损伤程度(0~1)。
优化设置:
- 算法:差分进化
- 种群大小:60
- 迭代次数:200
- 变量:10个损伤程度参数(连续变量)
结果分析:
- 成功识别出第3杆和第7杆存在损伤
- 识别损伤程度:第3杆28%,第7杆15%
- 真实损伤程度:第3杆30%,第7杆20%
- 识别误差在可接受范围内
9.3 案例三:多目标维护决策优化
问题描述:
在有限预算下,优化桥梁检测和维护计划。
目标函数:
- 目标1:最小化结构失效风险
- 目标2:最小化维护成本
- 目标3:最小化交通中断时间
约束条件:
- 总预算不超过限额
- 检测频率符合规范要求
- 维护活动不冲突
优化设置:
- 算法:NSGA-II
- 种群大小:100
- 迭代次数:300
结果分析:
- 获得Pareto前沿,包含多种权衡方案
- 推荐方案:风险降低65%,成本增加40%
- 为决策者提供量化依据
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)