优化问题:* 仅用于上下文,并非严格需要。* 使用SciPy的“最小化”,该代码是在给定作用于船舶的环境力的情况下,将最佳控制力分配给船舶上的推进器(风、波浪和海流)在3个自由度中的纵荡、横荡和偏航,以保持船舶的位置 (对动力定位很重要).本船有4个推进器,1台定角推进器(隧道)和3个旋转推进器(方位角)。固定推进器在一个方向上有一个力(x1)和旋转推进器具有在两个方向x和y上的力,作为变量对实现(x2,x3),(x4,x5),(x6,x7)。* 例如,x2和x3分别是用于旋转推进器1的x和y方向上的力。* 对于3个DOF也存在3个松弛变量以确保解。
编程问题:我想通过对其中一个推进器实施不等式约束来限制它的力,但通过实施约束“ineq 1”,所有输出都最小化为零。该约束应限制x1,非常简单,如下所示:(x1〈x1_最大值)随访:“minimize”似乎忽略了约束字典中的第一个约束,不管它是等式约束还是不等式约束。但是,第二个约束仍然有效。
仅具有等式约束的输出:Correct output
中断不等式约束的输出:Incorrect output with inequality
"我所尝试的是"
- ...尝试不同的算法
- ...测试约束中的每个正/负组合
- 使用数组/向量A,如标准形式A*x〈B,而不仅仅是x[0]
- ...使用数字代替fmax[0]
- ...尝试了其他设计变量及其组合
代码:
在第42行中的“cons 1”和“cons 2”之间切换,查看不同的结果。
import numpy as np
from scipy.optimize import minimize
# Parameters
nf = 1 # No. of fixed thrusters
nr = 3 # No. of rotating thrusters
nt = nf + 2*nr # No. of actuators
ns = 3 # No. of slack variables (slacks)
n = nt + ns # Design variables
Lx = np.array([30.5, 22.25, -35.5, -35.5]) # Thruster position
W = np.diag([1, 1, 1, 1, 1, 1, 1]) # Weighting for thrusters
Q = np.diag([1, 1, 1])*5000 # Weighting for slacks
Te = np.array([[0,1,0,1,0,1,0], # Thrust config. matrix
[1,0,1,0,1,0,1],
[Lx[0],0,Lx[1],0,Lx[2],0,Lx[3]]])
fmax = np.array([ 50000, 60000, 75000, 75000])
tau = np.array([50000,35000,0]) # Environmental forces in surge, sway & yaw
x0 = np.zeros(n)
# Problem definition
def obj(x):
fe = x[:nt]
s = x[nt:]
return fe.transpose()@W@fe + s.transpose()@Q@s
def eqcon(x):
fe = x[:nt]
s = x[nt:]
return tau + s - Te@fe # = 0
def ineq1(x):
return fmax[0] - x[0] # > 0
cons1 = {'type': 'eq', 'fun': eqcon}
cons2 = {'type': 'eq', 'fun': eqcon,
'type': 'ineq', 'fun': ineq1}
# Computing
opt = {'disp': True}
res = minimize(obj, x0, method='SLSQP', constraints=cons2, options=opt)
# Debugging
print("Environmental forces (surge, sway & yaw): ", tau)
print("Forces: ", np.round(res.x[:nt],1))
print("Slacks: ", np.round(res.x[nt:],1))
print(f"Thruster 1 has angle 90.00 with force {res.x[0]/1000:0.2f} kN")
angles = np.zeros(nr)
ux = res.x[nf:nt][::2] # Every other force element in x for azimuth: ux2, ux3, ...
uy = res.x[nf:nt][1:][::2] # uy2, uy3, ...
for i in range(nr):
angles[i] = np.arctan2(uy[i], ux[i]) * 180 / np.pi
print(f"Thruster {nf+i+1} has angle {angles[i]:0.2f} with force {np.sqrt(ux[i]**2+uy[i]**2)/1000:0.2f} kN")
有什么想法吗?
1条答案
按热度按时间ulmd4ohb1#
约束应为字典列表,因此使用
应该可以解决你的问题。也就是说,字典中的键应该是唯一的。否则,你就不能通过不明确的键来访问字典中的特定值。