我正在解决一个带有'SLSQP‘和SCIPY优化驱动程序的dymos问题,我的问题由于’LSQ子问题中超过3^n次迭代‘而失败。我一直在试图理解这个错误究竟意味着什么,以确定在我的模型中我应该从哪里开始调试,但是我没有在这个主题上找到任何有用的资源。你们都提供了关于如何调试其他优化器错误的有用反馈,所以我想,也许你们都对这个错误也有一些建议。
请注意,我的变量缩放非常好。另外,如果我关闭优化变量opt=False,让优化器收敛轨迹,那么优化就完成了。然后,如果我启用优化变量opt=True和温暖启动问题,那么优化也是收敛的。虽然这样做有效,但我必须解决许多不同的问题,并找到一个温暖的开始解决每一个问题是不现实的。我还感到奇怪的是,LSQ子问题如此依赖于最初的猜测。
发布于 2022-08-05 14:05:36
如果没有更多的细节,很难做到非常具体。然而,一般的优化,特别是基于psuedo谱方法的最优控制优化,对初始值高度敏感的情况并不少见。以下不是作为解决方案的建议,甚至也不是所有dymos案例的一般推荐的最佳实践。但是,对于你发现你需要一个更好的初步猜测的问题,这是一个很好的起点:
import openmdao.api as om
import dymos as dm
from dymos.examples.plotting import plot_results
from dymos.examples.brachistochrone import BrachistochroneODE
import matplotlib.pyplot as plt
#
# Initialize the Problem and the optimization driver
#
p = om.Problem(model=om.Group())
p.driver = om.ScipyOptimizeDriver()
# p.driver.options['tol'] = 1e-9
p.driver.declare_coloring()
#
# Create a trajectory and add a phase to it
#
traj = p.model.add_subsystem('traj', dm.Trajectory())
phase = traj.add_phase('phase0',
dm.Phase(ode_class=BrachistochroneODE,
transcription=dm.GaussLobatto(num_segments=10)))
#
# Set the variables
#
phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10))
phase.add_state('x', fix_initial=True, fix_final=True)
phase.add_state('y', fix_initial=True, fix_final=True)
phase.add_state('v', fix_initial=True, fix_final=False)
phase.add_control('theta', continuity=True, rate_continuity=True,
units='deg', lower=0.01, upper=179.9)
phase.add_parameter('g', units='m/s**2', val=9.80665)
#
# Minimize time at the end of the phase
#
phase.add_objective('time', loc='final', scaler=10)
p.model.linear_solver = om.DirectSolver()
#
# Setup the Problem
#
p.setup()
# intial guesses for times and controls are important before running a sim
p['traj.phase0.t_initial'] = 0.0
p['traj.phase0.t_duration'] = 2.0
p.set_val('traj.phase0.controls:theta', phase.interp('theta', ys=[5, 100.5]))
# need this to set initial conditions for x,y,v so simulate starts from the right condition
p.set_val('traj.phase0.states:x', phase.interp('x', ys=[0, 10]))
p.set_val('traj.phase0.states:y', phase.interp('y', ys=[10, 5]))
p.set_val('traj.phase0.states:v', phase.interp('v', ys=[0, 9.9]))
# Run a simulation to get physically valid initial guesses
p.run_model()
exp_out = traj.simulate()
# extract the initial values out of the sim result
x_sim = exp_out.get_val('traj.phase0.timeseries.states:x')
y_sim = exp_out.get_val('traj.phase0.timeseries.states:y')
v_sim = exp_out.get_val('traj.phase0.timeseries.states:v')
t_sim = exp_out.get_val('traj.phase0.timeseries.time')
# need to manually reset the last value to the correct BCs for states where fix_final=True
# but the initial values will be correct because we set them above before sim
x_sim[-1] = 10
y_sim[-1] = 5
# set initial guesses based on initial sim into the model
# (Dymos will re-interpolate them onto the collocation grid)
# comment/uncomment these three lines to see the effect of the initial guess
p.set_val('traj.phase0.states:x', phase.interp('x', xs=t_sim, ys=x_sim))
p.set_val('traj.phase0.states:y', phase.interp('y', xs=t_sim, ys=y_sim))
p.set_val('traj.phase0.states:v', phase.interp('v', xs=t_sim, ys=v_sim))
#
# Solve for the optimal trajectory
#
dm.run_problem(p)
# Check the results
print(p.get_val('traj.phase0.timeseries.time')[-1])在没有初始猜测的情况下运行时,我得到:
Full total jacobian was computed 3 times, taking 0.019553 seconds.
Total jacobian shape: (40, 50)
Jacobian shape: (40, 50) (19.95% nonzero)
FWD solves: 13 REV solves: 0
Total colors vs. total size: 13 vs 50 (74.0% improvement)
Sparsity computed using tolerance: 1e-25
Time to compute sparsity: 0.019553 sec.
Time to compute coloring: 0.028856 sec.
Memory to compute coloring: 0.000000 MB.
Optimization terminated successfully (Exit mode 0)
Current function value: [18.0161673]
Iterations: 24
Function evaluations: 24
Gradient evaluations: 24
Optimization Complete
-----------------------------------
[1.80161673]当我用最初的猜测运行时,我得到:
Full total jacobian was computed 3 times, taking 0.020724 seconds.
Total jacobian shape: (40, 50)
Jacobian shape: (40, 50) (19.95% nonzero)
FWD solves: 13 REV solves: 0
Total colors vs. total size: 13 vs 50 (74.0% improvement)
Sparsity computed using tolerance: 1e-25
Time to compute sparsity: 0.020724 sec.
Time to compute coloring: 0.029557 sec.
Memory to compute coloring: 0.000000 MB.
Optimization terminated successfully (Exit mode 0)
Current function value: [18.01657396]
Iterations: 11
Function evaluations: 11
Gradient evaluations: 11
Optimization Complete
-----------------------------------
[1.8016574]所以你可以看到,这里的最初猜测有助于更快地融合事物。我要再次强调,情况并非总是如此。如果我最后一次改变最初的猜测(这是优化的一部分-因为目标是尽量减少旅行时间!)从2到10,那么最初的模拟是对最终解的更差的近似。
P‘traj.phase0.t_ 10.0’=10.0
然后我得到这个作为标准的初步猜测:
Optimization terminated successfully (Exit mode 0)
Current function value: [18.01612053]
Iterations: 39
Function evaluations: 39
Gradient evaluations: 39
Optimization Complete
-----------------------------------
[1.80161205]这是模拟的初步猜测:
Optimization terminated successfully (Exit mode 0)
Current function value: [18.01677452]
Iterations: 43
Function evaluations: 44
Gradient evaluations: 43
Optimization Complete
-----------------------------------
[1.80167745]因此,这次模拟猜测进行了几次迭代(尽管它仍然找到了正确的答案)。您可以直观地看到为什么这里是这样的,因为我将对持续时间的最初估计从2秒(接近最优1.801)更改为10秒(远远不是最优),因此最初的模拟对最优解的估计要差得多。因此,更普遍地说,您为非状态值(即时间、控件)提供合理的起始值的能力将影响您从模拟中最初猜测的效果。
即使是“坏”的模拟,最初的猜测,你仍然可以得到更好的稳定性,尽管你的优化。
还有一点要注意:尽管我在这里手动输入猜测是为了教学目的,dymos确实有一个助手函数,可以从案例数据库重新加载猜测。请参见restart参数到run_problem method。
https://stackoverflow.com/questions/73239002
复制相似问题