如何通过抬高桥腿实现多座桥梁在相邻中点处衔接的算法求解
解决方案
问题本质梳理
你遇到的问题本质是带边界约束的线性等式求解问题,不需要用通用非线性优化器求解,推导线性约束后用线性规划/二次规划就能快速得到全局最优解。
变量定义
设第i个桥腿的抬高量为d_i,满足0 ≤ d_i ≤ 10,调整后的桥腿总高度为h_i = y_i + d_i。
约束推导
- 单座桥梁k的桥面是经过两个支撑桥腿
(x_{2k}, h_{2k})、(x_{2k+1}, h_{2k+1})的直线,任意x位置的桥面高度为:
f_k(x) = h_{2k} + (h_{2k+1} - h_{2k}) * (x - x_{2k}) / (x_{2k+1} - x_{2k})
- 相邻桥梁k和k+1的衔接中点为
x_m = (x_{2k+1} + x_{2k+2})/2,衔接要求为f_k(x_m) = f_{k+1}(x_m),展开后是关于d_i的线性等式。
具体求解方案
示例参数约束
针对你给出的示例,展开后得到两个线性等式约束:
- 桥1和桥2衔接约束:
-d0 +5d1 -5d2 +d3 = 22 - 桥2和桥3衔接约束:
-d2 +5d3 -5d4 +d5 = -6
求解实现(Python)
你可以选择以下两种目标之一求解:
- 最小化总抬高量(线性规划):
import numpy as np from scipy.optimize import linprog # 目标:最小化所有d_i的和 c = np.ones(6) # 等式约束 A_eq = np.array([ [-1, 5, -5, 1, 0, 0], [0, 0, -1, 5, -5, 1] ]) b_eq = np.array([22, -6]) # 边界约束 bounds = [(0, 10) for _ in range(6)] # 求解 res = linprog(c, A_eq=A_eq, b_eq=b_eq, bounds=bounds, method='highs') # 输出结果 print("各桥腿抬高量:", np.round(res.x, 2))
运行后得到的结果与你给出的示例一致,d1≈4、d4≈1,其余抬高量为0。
2. 最小化抬高量平方和(二次规划):
如果希望抬高量尽可能均匀分布,可以用SLSQP求解器实现:
from scipy.optimize import minimize def objective(d): return np.sum(d**2) cons = [{'type': 'eq', 'fun': lambda d: -d[0] +5*d[1] -5*d[2] +d[3] -22}, {'type': 'eq', 'fun': lambda d: -d[2] +5*d[3] -5*d[4] +d[5] +6}] x0 = np.zeros(6) res = minimize(objective, x0, method='SLSQP', bounds=bounds, constraints=cons)
原优化方案失败原因
你之前用scipy.optimize.minimize未得到有效结果,大概率是两个原因:
- 没有显式传入线性约束,仅将高度差加入目标函数,容易陷入局部最优
- 选择了不支持带约束求解的优化器
扩展场景处理
如果后续桥梁数量增加,只需要按上述推导方式批量生成线性约束即可,求解复杂度不会明显上升。如果线性约束无解,可将目标改为最小化衔接点高度差的平方和,属于凸优化问题,同样存在全局最优解。
内容的提问来源于stack exchange,提问作者FluxSwirl
相关产品推荐
相关产品推荐

