国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

非線性最優(yōu)化問題求解器Ipopt介紹

這篇具有很好參考價值的文章主要介紹了非線性最優(yōu)化問題求解器Ipopt介紹。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

Ipopt(Interior Point OPTimizer)是求解大規(guī)模非線性最優(yōu)化問題的求解軟件??梢郧蠼馊缦滦问降淖顑?yōu)化問題的(局部)最優(yōu)解。
m i n ? x ∈ R n ??? f ( x ) s . t . g L ≤ g ( x ) ≤ g U x L ≤ x ≤ x U (0) \underbrace{min}_ {x \in R?} \, \, \, f(x) \\ s.t. g_L ≤ g(x) ≤ g_U \\ x_L ≤ x ≤ x_U \tag{0} xRn min??f(x)s.t.gL?g(x)gU?xL?xxU?(0)
其中, f ( x ) : R n → R f(x): R^n \rightarrow R f(x):RnR是優(yōu)化目標函數(shù), g ( x ) : R n → R m g(x):R^n \rightarrow R^m g(x):RnRm是約束函數(shù), f ( x ) , g ( x ) f(x),g(x) f(x),g(x)可以是非線性和非凸的,但是需要是二階微分連續(xù)的。

為了求解最優(yōu)化問題,Ipopt需要更多的信息,如下:

  1. 優(yōu)化問題的維度
    1. 優(yōu)化變量 x x x的數(shù)目;
    2. 約束函數(shù) g ( x ) g(x) g(x)的數(shù)目;
  2. 優(yōu)化變量的邊界
    1. 優(yōu)化變量 x x x的邊界;
    2. 約束函數(shù) g ( x ) g(x) g(x)的邊界;
  3. 優(yōu)化問題的初始迭代點:
    1. 優(yōu)化變量 x x x的初始值;
    2. 拉格朗日乘子的初始值(僅僅是在warm start的時候需要);
  4. 優(yōu)化問題的數(shù)據(jù)結構(Structure):
    1. 約束函數(shù) g ( x ) g(x) g(x)的雅可比矩陣的非零元素的數(shù)目;
    2. 拉格朗日函數(shù)的黑森矩陣的非零元素的數(shù)目;
    3. 約束函數(shù) g ( x ) g(x) g(x)的雅可比稀疏矩陣的非零元素的行索引和列索引(sparsity structure,row and column indices of each of the nonzero entries );
    4. 拉格朗日函數(shù)的黑森稀疏矩陣的非零元素的行索引和列索引(sparsity structure,row and column indices of each of the nonzero entries );
  5. 優(yōu)化問題函數(shù)的值:
    1. 優(yōu)化目標函數(shù) f ( x ) f(x) f(x)
    2. 優(yōu)化目標函數(shù)的梯度函數(shù) c c c;
    3. 約束函數(shù) g ( x ) g(x) g(x);
    4. 約束函數(shù)的雅可比矩陣 ? g ( x ) T \nabla g(x) ^T ?g(x)T;
    5. 拉格朗日函數(shù)的黑森矩陣 σ f ? 2 f ( x ) + ∑ i = 1 m λ i ? 2 g i ( x ) \sigma_f \nabla ^2 f(x) + \sum_{i=1}^m \lambda_i \nabla ^2 g_i(x) σf??2f(x)+i=1m?λi??2gi?(x),如果使用擬牛頓法(quasi-Newton options )則不需要此矩陣;

優(yōu)化問題的維度和邊界約束可以直接獲得,并且來自于問題定義。初始迭代點會影響優(yōu)化問題的是否收斂或者是否收斂到(局部)最優(yōu)解,不同的初始值可能會導致收斂到不同的局部最優(yōu)解。計算微分矩陣(雅可比矩陣和黑森矩陣)可能有一點復雜,Ipopt需要提供約束函數(shù)的雅可比矩陣和拉格朗日函數(shù)的黑森矩陣的非零元素以及他們所在的行索引和列索引,并且標準接口是下三角矩陣(黑森矩陣是對稱矩陣)。矩陣的非零元素確定后,在整個求解過程中是不可變的,因此,非零元素不可以僅僅包含在初始值條件下,還需要包括在求解過程中會不為零的元素。

1. Example

f = x 1 x 4 ( x 1 + x 2 + x 3 ) + x 3 s . t . ?????? x 1 x 2 x 3 x 4 ≥ 25 x 1 2 + x 2 2 + x 3 2 + x 4 2 = 40 1 ≤ x 1 , x 2 , x 3 , x 4 ≤ 5 x 0 = ( 1 , 5 , 5 , 1 ) (1-1) f = x_1 x_4 (x_1 + x_2 + x_3) + x_3 \\ s.t. \,\,\,\,\,\, x_1 x_2 x_3 x_4 \geq 25 \\ x^2_1 + x^2_2 + x^2_3 + x^2_4 = 40 \\ 1 \leq x_1, x_2, x_3, x_4 \leq 5 \\ x_0 = (1,5,5,1) \tag{1-1} f=x1?x4?(x1?+x2?+x3?)+x3?s.t.x1?x2?x3?x4?25x12?+x22?+x32?+x42?=401x1?,x2?,x3?,x4?5x0?=(1,5,5,1)(1-1)

可以得到優(yōu)化目標的梯度為:
? f ( x ) = [ x 1 x 4 + x 4 ( x 1 + x 2 + x 3 ) x 1 x 4 x 1 x 4 + 1 x 1 ( x 1 + x 2 + x 3 ) ] (1-2) \nabla f(x) = \begin{bmatrix} x_1 x_4 + x_4(x_1 + x_2 + x_3) \\ x_1 x_4 \\ x_1 x_4 + 1 \\ x_1 (x_1 + x_2 + x_3) \end{bmatrix} \tag{1-2} ?f(x)=? ??x1?x4?+x4?(x1?+x2?+x3?)x1?x4?x1?x4?+1x1?(x1?+x2?+x3?)?? ??(1-2)
可以得到約束函數(shù)的雅可比矩陣為:
? g ( x ) = [ x 2 x 3 x 4 x 1 x 3 x 4 x 1 x 2 x 4 x 1 x 2 x 3 2 x 1 2 x 2 2 x 3 2 x 4 ] (1-3) \nabla g(x) = \begin{bmatrix} x_2 x_3 x_4 & x_1 x_3 x_4 & x_1 x_2 x_4 & x_1 x_2 x_3 \\ 2 x_1 & 2 x_2 & 2 x_3 & 2 x_4 \end{bmatrix} \tag{1-3} ?g(x)=[x2?x3?x4?2x1??x1?x3?x4?2x2??x1?x2?x4?2x3??x1?x2?x3?2x4??](1-3)
需要計算拉格朗日函數(shù)的黑森矩陣,如果使用擬牛頓法來近似二階微分,則不需要提供黑森矩陣。但是黑森矩陣可以是計算有更好的魯棒性和更快的收斂速度。NLP的拉格朗日函數(shù)定義為 f ( x ) + g ( x ) T λ f(x) + g(x)^T \lambda f(x)+g(x)Tλ,黑森矩陣定義為 ? 2 f ( x ) + ∑ i = 1 m λ i ? 2 g i ( x ) \nabla ^2 f(x) + \sum_{i=1}^m \lambda_i \nabla ^2 g_i(x) ?2f(x)+i=1m?λi??2gi?(x),然而在Ipopt中引入 σ f \sigma_f σf?使Ipopt可以分別確定優(yōu)化目標函數(shù)和約束函數(shù)的黑森矩陣,因此Ipopt的黑森矩陣為 σ f ? 2 f ( x ) + ∑ i = 1 m λ i ? 2 g i ( x ) \sigma_f \nabla ^2 f(x) + \sum_{i=1}^m \lambda_i \nabla ^2 g_i(x) σf??2f(x)+i=1m?λi??2gi?(x)??梢缘玫絻?yōu)化問題 ( 1 ? 1 ) (1-1) (1?1)的黑森矩陣為:
σ f [ 2 x 4 x 4 x 4 2 x 1 + x 2 + x 3 x 4 0 0 x 1 x 4 0 0 x 1 2 x 1 + x 2 + x 3 x 1 x 1 0 ] + λ 1 [ 0 x 3 x 4 x 2 x 4 x 2 x 3 x 3 x 4 0 x 1 x 4 x 1 x 3 x 2 x 4 x 1 x 4 0 x 1 x 2 x 2 x 3 x 1 x 3 x 1 x 2 0 ] + λ 2 [ 2 0 0 0 0 2 0 0 0 0 2 0 0 0 0 2 ] (1-4) \sigma_f \begin{bmatrix} 2 x_4 & x_4 & x_4 & 2 x_1 + x_2 + x_3 \\ x_4 & 0 & 0 & x_1 \\ x_4 & 0 & 0 & x_1 \\ 2 x_1 + x_2 + x_3 & x_1 & x_1 & 0 \end{bmatrix}+ \lambda_1 \begin{bmatrix} 0 & x_3 x_4 & x_2 x_4 & x_2 x_3 \\ x_3 x_4 & 0 & x_1 x_4 & x_1 x_3 \\ x_2 x_4 & x_1 x_4 & 0 & x_1 x_2 \\ x_2 x_3 & x_1 x_3 & x_1 x_2 & 0 \end{bmatrix}+ \lambda_2 \begin{bmatrix} 2 & 0 & 0 & 0 \\ 0 & 2 & 0 & 0 \\ 0 & 0 & 2 & 0 \\ 0 & 0 & 0 & 2 \end{bmatrix} \tag{1-4} σf?? ??2x4?x4?x4?2x1?+x2?+x3??x4?00x1??x4?00x1??2x1?+x2?+x3?x1?x1?0?? ??+λ1?? ??0x3?x4?x2?x4?x2?x3??x3?x4?0x1?x4?x1?x3??x2?x4?x1?x4?0x1?x2??x2?x3?x1?x3?x1?x2?0?? ??+λ2?? ??2000?0200?0020?0002?? ??(1-4)
其中,第一項是優(yōu)化目標函數(shù)的黑森矩陣,第二項和第三項是約束函數(shù)的黑森矩陣, λ 1 , λ 2 \lambda_1,\lambda_2 λ1?,λ2?是約束函數(shù)的拉格朗日乘子。

2. C++ Interface

需要繼承純虛基類Ipopt::TNLP來編寫自己的求解類,并且需要重載 9 9 9Ipopt::TNLP基類的虛函數(shù),Ipopt通過Ipopt::IpoptApplication類來求解最優(yōu)化問題。

2.1 Ipopt::TNLP::get_nlp_info

   virtual bool get_nlp_info(
      Index&          n,
      Index&          m,
      Index&          nnz_jac_g,
      Index&          nnz_h_lag,
      IndexStyleEnum& index_style
   ) = 0;

Ipopt使用這個函數(shù)來確定數(shù)組的內(nèi)存分配,這里如果發(fā)生問題,會引起內(nèi)存泄漏等問題,很難去debug

  • n:優(yōu)化變量 x x x的數(shù)目;
  • m:約束函數(shù) g ( x ) g(x) g(x)的數(shù)目;
  • nnz_jac_g:雅可比矩陣非零元素的數(shù)目;
  • nnz_h_lag:黑森矩陣非零元素的數(shù)目;
  • index_style:稀疏矩陣的索引使用C語言風格(從 0 0 0開始),還是使用Fortran語言風格(從 1 1 1開始);

上述例子中有 4 4 4個優(yōu)化變量, 2 2 2個約束函數(shù),雅可比矩陣中的非零元素個數(shù)為 8 8 8,黑森矩陣中非零元素的個數(shù)為 16 16 16,由于是對稱矩陣,因此下三角矩陣中非零元素個數(shù)為 10 10 10。

// returns the size of the problem
bool HS071_NLP::get_nlp_info(
   Index&          n,
   Index&          m,
   Index&          nnz_jac_g,
   Index&          nnz_h_lag,
   IndexStyleEnum& index_style
)
{
   // The problem described in HS071_NLP.hpp has 4 variables, x[0] through x[3]
   n = 4;
 
   // one equality constraint and one inequality constraint
   m = 2;
 
   // in this example the jacobian is dense and contains 8 nonzeros
   nnz_jac_g = 8;
 
   // the Hessian is also dense and has 16 total nonzeros, but we
   // only need the lower left corner (since it is symmetric)
   nnz_h_lag = 10;
 
   // use the C style indexing (0-based)
   index_style = TNLP::C_STYLE;
 
   return true;
}

2.2 Ipopt::TNLP::get_bounds_info

   virtual bool get_bounds_info(
      Index   n,
      Number* x_l,
      Number* x_u,
      Index   m,
      Number* g_l,
      Number* g_u
   ) = 0;

Ipopt使用這個函數(shù)來確定優(yōu)化變量 x x x的邊界和約束函數(shù) g ( x ) g(x) g(x)的邊界。

  • n:優(yōu)化變量 x x x的數(shù)目;
  • x_l:優(yōu)化變量 x x x的下邊界,數(shù)組;
  • x_u:優(yōu)化變量 x x x的上邊界,數(shù)組;
  • m:約束函數(shù) g ( x ) g(x) g(x)的數(shù)目;
  • g_l:約束函數(shù) g ( x ) g(x) g(x)的下邊界,數(shù)組;
  • g_u:約束函數(shù) g ( x ) g(x) g(x)的上邊界,數(shù)組;

Ipopt中默認設置邊界值需要在 ( ? 1 0 9 , 1 0 9 ) (-10^9, 10^9) (?109,109)范圍內(nèi),當不在此范圍時,則認為是無窮大或者無窮小。

// returns the variable bounds
bool HS071_NLP::get_bounds_info(
   Index   n,
   Number* x_l,
   Number* x_u,
   Index   m,
   Number* g_l,
   Number* g_u
)
{
   // here, the n and m we gave IPOPT in get_nlp_info are passed back to us.
   // If desired, we could assert to make sure they are what we think they are.
   assert(n == 4);
   assert(m == 2);
 
   // the variables have lower bounds of 1
   for( Index i = 0; i < 4; i++ )
   {
      x_l[i] = 1.0;
   }
 
   // the variables have upper bounds of 5
   for( Index i = 0; i < 4; i++ )
   {
      x_u[i] = 5.0;
   }
 
   // the first constraint g1 has a lower bound of 25
   g_l[0] = 25;
   // the first constraint g1 has NO upper bound, here we set it to 2e19.
   // Ipopt interprets any number greater than nlp_upper_bound_inf as
   // infinity. The default value of nlp_upper_bound_inf and nlp_lower_bound_inf
   // is 1e19 and can be changed through ipopt options.
   g_u[0] = 2e19;
 
   // the second constraint g2 is an equality constraint, so we set the
   // upper and lower bound to the same value
   g_l[1] = g_u[1] = 40.0;
 
   return true;
}	

2.3 Ipopt::TNLP::get_starting_point

   virtual bool get_starting_point(
      Index   n,
      bool    init_x,
      Number* x,
      bool    init_z,
      Number* z_L,
      Number* z_U,
      Index   m,
      bool    init_lambda,
      Number* lambda
   ) = 0;

Ipopt使用這個函數(shù)來確定迭代優(yōu)化的起點。

  • n:優(yōu)化變量 x x x的數(shù)目;
  • init_x:如果是ture,則需要提供優(yōu)化變量 x x x的初始值;
  • x:優(yōu)化變量 x x x的初始值;

其他為dual variables的初始值,一般不用設置。在Ipopt中默認是需要設置 x x x的初始值。

// returns the initial point for the problem
bool HS071_NLP::get_starting_point(
   Index   n,
   bool    init_x,
   Number* x,
   bool    init_z,
   Number* z_L,
   Number* z_U,
   Index   m,
   bool    init_lambda,
   Number* lambda
)
{
   // Here, we assume we only have starting values for x, if you code
   // your own NLP, you can provide starting values for the dual variables
   // if you wish
   assert(init_x == true);
   assert(init_z == false);
   assert(init_lambda == false);
 
   // initialize to the given starting point
   x[0] = 1.0;
   x[1] = 5.0;
   x[2] = 5.0;
   x[3] = 1.0;
 
   return true;
}

2.4 Ipopt::TNLP::eval_f

   virtual bool eval_f(
      Index         n,
      const Number* x,
      bool          new_x,
      Number&       obj_value
   ) = 0;

Ipopt使用這個函數(shù)來確定優(yōu)化目標函數(shù)。

  • n:優(yōu)化變量 x x x的數(shù)目;
  • x:優(yōu)化變量 x x x的值,用來計算 f ( x ) f(x) f(x)
  • new_x:在此之前調(diào)用的eval_*函數(shù)是否有錯誤發(fā)生,可以忽略;
  • obj_value f ( x ) f(x) f(x);
// returns the value of the objective function
bool HS071_NLP::eval_f(
   Index         n,
   const Number* x,
   bool          new_x,
   Number&       obj_value
)
{
   assert(n == 4);
 
   obj_value = x[0] * x[3] * (x[0] + x[1] + x[2]) + x[2];
 
   return true;
}

2.5 Ipopt::TNLP::eval_grad_f

   virtual bool eval_grad_f(
      Index         n,
      const Number* x,
      bool          new_x,
      Number*       grad_f
   ) = 0;

Ipopt使用這個函數(shù)來確定優(yōu)化目標函數(shù)的梯度。

  • n:優(yōu)化變量 x x x的數(shù)目;
  • x:優(yōu)化變量 x x x的值,用來計算 ? f ( x ) \nabla f(x) ?f(x);
  • new_x:在此之前調(diào)用的eval_*函數(shù)是否有錯誤發(fā)生,可以忽略;
  • obj_value ? f ( x ) \nabla f(x) ?f(x),數(shù)組的大小和 x x x的數(shù)組大小一致;
// return the gradient of the objective function grad_{x} f(x)
bool HS071_NLP::eval_grad_f(
   Index         n,
   const Number* x,
   bool          new_x,
   Number*       grad_f
)
{
   assert(n == 4);
 
   grad_f[0] = x[0] * x[3] + x[3] * (x[0] + x[1] + x[2]);
   grad_f[1] = x[0] * x[3];
   grad_f[2] = x[0] * x[3] + 1;
   grad_f[3] = x[0] * (x[0] + x[1] + x[2]);
 
   return true;
}

2.6 Ipopt::TNLP::eval_g

   virtual bool eval_g(
      Index         n,
      const Number* x,
      bool          new_x,
      Index         m,
      Number*       g
   ) = 0;

Ipopt使用這個函數(shù)來確定約束函數(shù) g ( x ) g(x) g(x)

  • n:優(yōu)化變量 x x x的數(shù)目;
  • x:優(yōu)化變量 x x x的值,用來計算 ? f ( x ) \nabla f(x) ?f(x)
  • new_x:在此之前調(diào)用的eval_*函數(shù)是否有錯誤發(fā)生,可以忽略;
  • m:約束函數(shù) g ( x ) g(x) g(x)的數(shù)目;
  • g: g ( x ) g(x) g(x),數(shù)組的大小和 m m m一致;
// return the value of the constraints: g(x)
bool HS071_NLP::eval_g(
   Index         n,
   const Number* x,
   bool          new_x,
   Index         m,
   Number*       g
)
{
   assert(n == 4);
   assert(m == 2);
 
   g[0] = x[0] * x[1] * x[2] * x[3];
   g[1] = x[0] * x[0] + x[1] * x[1] + x[2] * x[2] + x[3] * x[3];
 
   return true;
}

2.7 Ipopt::TNLP::eval_jac_g

   virtual bool eval_jac_g(
      Index         n,
      const Number* x,
      bool          new_x,
      Index         m,
      Index         nele_jac,
      Index*        iRow,
      Index*        jCol,
      Number*       values
   ) = 0;

Ipopt使用這個函數(shù)來確定約束函數(shù) g ( x ) g(x) g(x)的雅可比矩陣的非零元素的值,以及其在稀疏矩陣中的行索引值和列索引值。雅可比矩陣中的第 i i i行和第 j j j列的元素值是 g i ( x ) g_i(x) gi?(x) x j x_j xj?的導數(shù)。

  • n:優(yōu)化變量 x x x的數(shù)目;
  • x:優(yōu)化變量 x x x的值,用來計算 ? g ( x ) T \nabla g(x)^T ?g(x)T;
  • new_x:在此之前調(diào)用的eval_*函數(shù)是否有錯誤發(fā)生,可以忽略;
  • m:約束函數(shù) g ( x ) g(x) g(x)的數(shù)目;
  • nele_jac:雅可比矩陣非零元素的數(shù)目;
  • iRow:存儲雅可比矩陣非零元素在矩陣中的行索引值,如果是C語言風格,雅可比矩陣索引值從 0 0 0開始;
  • jCol:存儲雅可比矩陣非零元素在矩陣中的列索引值,如果是C語言風格,雅可比矩陣索引值從 0 0 0開始;
  • values:存儲雅可比矩陣中的非零元素;

需要注意的是:①iRow、jColvalues三個數(shù)組的大小是一致的,并且其儲存的值應該和雅可比矩陣非零元素的行索引值、列索引值和非零元素值相對應;②數(shù)組iRowjCol只需要被填寫一次,即第一次調(diào)用此函數(shù)時填寫iRowjCol,第一次調(diào)用時xvalues都是null,當Ipopt需要values的值時,傳遞iRowjCol將會是null,此時對values的值進行填寫。

// return the structure or values of the Jacobian
bool HS071_NLP::eval_jac_g(
   Index         n,
   const Number* x,
   bool          new_x,
   Index         m,
   Index         nele_jac,
   Index*        iRow,
   Index*        jCol,
   Number*       values
)
{
   assert(n == 4);
   assert(m == 2);
 
   if( values == NULL )
   {
      // return the structure of the Jacobian
 
      // this particular Jacobian is dense
      iRow[0] = 0;
      jCol[0] = 0;
      iRow[1] = 0;
      jCol[1] = 1;
      iRow[2] = 0;
      jCol[2] = 2;
      iRow[3] = 0;
      jCol[3] = 3;
      iRow[4] = 1;
      jCol[4] = 0;
      iRow[5] = 1;
      jCol[5] = 1;
      iRow[6] = 1;
      jCol[6] = 2;
      iRow[7] = 1;
      jCol[7] = 3;
   }
   else
   {
      // return the values of the Jacobian of the constraints
 
      values[0] = x[1] * x[2] * x[3]; // 0,0
      values[1] = x[0] * x[2] * x[3]; // 0,1
      values[2] = x[0] * x[1] * x[3]; // 0,2
      values[3] = x[0] * x[1] * x[2]; // 0,3
 
      values[4] = 2 * x[0]; // 1,0
      values[5] = 2 * x[1]; // 1,1
      values[6] = 2 * x[2]; // 1,2
      values[7] = 2 * x[3]; // 1,3
   }
 
   return true;
}

2.8 Ipopt::TNLP::eval_h

   virtual bool eval_h(
      Index         n,
      const Number* x,
      bool          new_x,
      Number        obj_factor,
      Index         m,
      const Number* lambda,
      bool          new_lambda,
      Index         nele_hess,
      Index*        iRow,
      Index*        jCol,
      Number*       values
   )

Ipopt使用這個函數(shù)來確定拉格朗日函數(shù)黑森矩陣的非零元素的值,以及其在稀疏矩陣中的行索引值和列索引值。

  • n:優(yōu)化變量 x x x的數(shù)目;
  • x:優(yōu)化變量 x x x的值,用來計算 ? g ( x ) T \nabla g(x)^T ?g(x)T;
  • new_x:在此之前調(diào)用的eval_*函數(shù)是否有錯誤發(fā)生,可以忽略;
  • obj_factor σ f \sigma_f σf?
  • m:約束函數(shù) g ( x ) g(x) g(x)的數(shù)目;
  • lambda:拉格朗日乘子 λ \lambda λ
  • new_lambda:如果之前調(diào)用的函數(shù)使用相同的 λ \lambda λ則為false,一般忽略;
  • nele_hess:黑森矩陣非零元素的個數(shù)(下三角矩陣);
  • iRow:存儲黑森矩陣非零元素在矩陣中的行索引值,如果是C語言風格,黑森矩陣索引值從 0 0 0開始;
  • jCol:存儲黑森矩陣非零元素在矩陣中的列索引值,如果是C語言風格,黑森矩陣索引值從 0 0 0開始;
  • values:存儲黑森矩陣中的非零元素的值;

需要注意的是:①iRowjColvalues三個數(shù)組的大小是一致的,并且其儲存的值應該和黑森矩陣非零元素的行索引值、列索引值和非零元素值相對應;②數(shù)組iRowjCol只需要被填寫一次,即第一次調(diào)用此函數(shù)時填寫iRowjCol,第一次調(diào)用時x、lambdavalues都是null,當Ipopt需要values的值時,傳遞iRowjCol將會是null,此時對values的值進行填寫;③由于黑森矩陣是對稱陣,Ipopt使用下三角矩陣;④Ipopt默認是需要黑森矩陣的,當使用擬牛頓法時,則不需要黑森矩陣。

在此例中,黑森矩陣是稠密的,但是仍然使用稀疏矩陣來表示。

//return the structure or values of the Hessian
bool HS071_NLP::eval_h(
   Index         n,
   const Number* x,
   bool          new_x,
   Number        obj_factor,
   Index         m,
   const Number* lambda,
   bool          new_lambda,
   Index         nele_hess,
   Index*        iRow,
   Index*        jCol,
   Number*       values
)
{
   assert(n == 4);
   assert(m == 2);
 
   if( values == NULL )
   {
      // return the structure. This is a symmetric matrix, fill the lower left
      // triangle only.
 
      // the hessian for this problem is actually dense
      Index idx = 0;
      for( Index row = 0; row < 4; row++ )
      {
         for( Index col = 0; col <= row; col++ )
         {
            iRow[idx] = row;
            jCol[idx] = col;
            idx++;
         }
      }
 
      assert(idx == nele_hess);
   }
   else
   {
      // return the values. This is a symmetric matrix, fill the lower left
      // triangle only
 
      // fill the objective portion
      values[0] = obj_factor * (2 * x[3]); // 0,0
 
      values[1] = obj_factor * (x[3]);     // 1,0
      values[2] = 0.;                      // 1,1
 
      values[3] = obj_factor * (x[3]);     // 2,0
      values[4] = 0.;                      // 2,1
      values[5] = 0.;                      // 2,2
 
      values[6] = obj_factor * (2 * x[0] + x[1] + x[2]); // 3,0
      values[7] = obj_factor * (x[0]);                   // 3,1
      values[8] = obj_factor * (x[0]);                   // 3,2
      values[9] = 0.;                                    // 3,3
 
      // add the portion for the first constraint
      values[1] += lambda[0] * (x[2] * x[3]); // 1,0
 
      values[3] += lambda[0] * (x[1] * x[3]); // 2,0
      values[4] += lambda[0] * (x[0] * x[3]); // 2,1
 
      values[6] += lambda[0] * (x[1] * x[2]); // 3,0
      values[7] += lambda[0] * (x[0] * x[2]); // 3,1
      values[8] += lambda[0] * (x[0] * x[1]); // 3,2
 
      // add the portion for the second constraint
      values[0] += lambda[1] * 2; // 0,0
 
      values[2] += lambda[1] * 2; // 1,1
 
      values[5] += lambda[1] * 2; // 2,2
 
      values[9] += lambda[1] * 2; // 3,3
   }
 
   return true;
}

2.9 Ipopt::TNLP::finalize_solution

   virtual void finalize_solution(
      SolverReturn               status,
      Index                      n,
      const Number*              x,
      const Number*              z_L,
      const Number*              z_U,
      Index                      m,
      const Number*              g,
      const Number*              lambda,
      Number                     obj_value,
      const IpoptData*           ip_data,
      IpoptCalculatedQuantities* ip_cq
   ) = 0;

Ipopt使用這個函數(shù)來得到最優(yōu)化問題的求解結果,對其重要的值進行介紹。

  • status:求解器的狀態(tài);
    • SUCCESS:在滿足收斂條件的情況下,找到局部最優(yōu)解;
    • MAXITER_EXCEEDED:超出最大迭代次數(shù);
    • CPUTIME_EXCEEDED:超出最大求解時間;
    • STOP_AT_ACCEPTABLE_POINT:求解收斂在某點,不滿足期望的容差,但是在可接受范圍內(nèi);
    • LOCAL_INFEASIBILITY:在可行域內(nèi)找不到最優(yōu)解,一般是由于bounds和約束設置不合理導致的;
  • x:優(yōu)化變量 x x x的局部最優(yōu)解的值;
void HS071_NLP::finalize_solution(
   SolverReturn               status,
   Index                      n,
   const Number*              x,
   const Number*              z_L,
   const Number*              z_U,
   Index                      m,
   const Number*              g,
   const Number*              lambda,
   Number                     obj_value,
   const IpoptData*           ip_data,
   IpoptCalculatedQuantities* ip_cq
)
{
   // here is where we would store the solution to variables, or write to a file, etc
   // so we could use the solution.
 
   // For this example, we write the solution to the console
   std::cout << std::endl << std::endl << "Solution of the primal variables, x" << std::endl;
   for( Index i = 0; i < n; i++ )
   {
      std::cout << "x[" << i << "] = " << x[i] << std::endl;
   }
 
   std::cout << std::endl << std::endl << "Solution of the bound multipliers, z_L and z_U" << std::endl;
   for( Index i = 0; i < n; i++ )
   {
      std::cout << "z_L[" << i << "] = " << z_L[i] << std::endl;
   }
   for( Index i = 0; i < n; i++ )
   {
      std::cout << "z_U[" << i << "] = " << z_U[i] << std::endl;
   }
 
   std::cout << std::endl << std::endl << "Objective value" << std::endl;
   std::cout << "f(x*) = " << obj_value << std::endl;
 
   std::cout << std::endl << "Final value of the constraints:" << std::endl;
   for( Index i = 0; i < m; i++ )
   {
      std::cout << "g(" << i << ") = " << g[i] << std::endl;
   }
}

2.10 main function

上述對Ipopt::TNLP的函數(shù)進行了重載,但是需要編寫調(diào)用Ipopt的函數(shù)來執(zhí)行求解。文章來源地址http://www.zghlxwxcb.cn/news/detail-808294.html

#include "IpIpoptApplication.hpp"
#include "hs071_nlp.hpp"
 
#include <iostream>
 
using namespace Ipopt;
 
int main(
   int    /*argv*/,
   char** /*argc*/
)
{
   // Create a new instance of your nlp
   //  (use a SmartPtr, not raw)
   SmartPtr<TNLP> mynlp = new HS071_NLP();
 
   // Create a new instance of IpoptApplication
   //  (use a SmartPtr, not raw)
   // We are using the factory, since this allows us to compile this
   // example with an Ipopt Windows DLL
   SmartPtr<IpoptApplication> app = IpoptApplicationFactory();
 
   // Change some options
   // Note: The following choices are only examples, they might not be
   //       suitable for your optimization problem.
   app->Options()->SetNumericValue("tol", 3.82e-6);
   app->Options()->SetStringValue("mu_strategy", "adaptive");
   app->Options()->SetStringValue("output_file", "ipopt.out");
   // The following overwrites the default name (ipopt.opt) of the options file
   // app->Options()->SetStringValue("option_file_name", "hs071.opt");
 
   // Initialize the IpoptApplication and process the options
   ApplicationReturnStatus status;
   status = app->Initialize();
   if( status != Solve_Succeeded )
   {
      std::cout << std::endl << std::endl << "*** Error during initialization!" << std::endl;
      return (int) status;
   }
 
   // Ask Ipopt to solve the problem
   status = app->OptimizeTNLP(mynlp);
 
   if( status == Solve_Succeeded )
   {
      std::cout << std::endl << std::endl << "*** The problem solved!" << std::endl;
   }
   else
   {
      std::cout << std::endl << std::endl << "*** The problem FAILED!" << std::endl;
   }
 
   // As the SmartPtrs go out of scope, the reference count
   // will be decremented and the objects will automatically
   // be deleted.
 
   return (int) status;
}

到了這里,關于非線性最優(yōu)化問題求解器Ipopt介紹的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 二次規(guī)劃(QP)求解與序列二次規(guī)劃(SQP)求解非線性規(guī)劃問題

    二次規(guī)劃(QP)是求解一種特殊的數(shù)學優(yōu)化問題的過程——具體地說,是一個(線性約束)二次優(yōu)化問題,即優(yōu)化(最小化或最大化)多個變量的二次函數(shù),并服從于這些變量的線性約束。二次規(guī)劃是一種特殊的非線性規(guī)劃。? ? ? ? 序列二次規(guī)劃(SQP,Sequental Quadratic Programming)算法是

    2024年02月02日
    瀏覽(19)
  • 機器學習筆記之最優(yōu)化理論與方法(九)無約束優(yōu)化問題——常用求解方法(下)

    上一節(jié)介紹了 牛頓法、擬牛頓法 。本節(jié)將繼續(xù)以 擬牛頓法 為基礎,介紹 DFP , BFGS text{DFP},text{BFGS} DFP , BFGS 方法 。 經(jīng)典牛頓法缺陷與修正牛頓法 關于 經(jīng)典牛頓法 中關于 下降方向 D k ( k = 1 , 2 , ? ? , ∞ ) mathcal D_k(k=1,2,cdots,infty) D k ? ( k = 1 , 2 , ? , ∞ ) 的 數(shù)學符號 表

    2024年02月09日
    瀏覽(22)
  • 機器學習筆記之最優(yōu)化理論與方法(七)無約束優(yōu)化問題——常用求解方法(上)

    機器學習筆記之最優(yōu)化理論與方法(七)無約束優(yōu)化問題——常用求解方法(上)

    本節(jié)將介紹 無約束優(yōu)化問題 的常用求解方法,包括 坐標軸交替下降法、最速下降法 。 本節(jié)是對優(yōu)化算法(十~十七)最速下降法(梯度下降法)的理論補充,其中可能出現(xiàn)一些定理的 證明過程 這里不再贅述,并在相應位置 附加鏈接 。 從本節(jié)開始,將介紹 四大類 無約束優(yōu)化問

    2024年02月10日
    瀏覽(27)
  • 利用 MATLAB 編程實現(xiàn)乘子法求解約束最優(yōu)化問題。
擬 Newton 法

    利用 MATLAB 編程實現(xiàn)乘子法求解約束最優(yōu)化問題。 擬 Newton 法

    1、畫出 PH 法的算法流程圖; 2、MATLAB 編寫 PH 法求解約束優(yōu)化問題的函數(shù),無約束子問題用精確一 維搜索的擬 Newton 法((函數(shù)式 M 文件,精度設為 epson 可調(diào));編寫程序(命 令式 M 文件),調(diào)用 PH 法,求解如下問題: ? 初始點?。?0,10),按教材 P217,例 12 取不同的參

    2024年02月11日
    瀏覽(66)
  • 最小二乘問題和非線性優(yōu)化

    最小二乘問題和非線性優(yōu)化

    轉(zhuǎn)載自此處,修正了一點小錯誤。 在求解 SLAM 中的最優(yōu)狀態(tài)估計問題時,我們一般會得到兩個變量,一個是由傳感器獲得的實際觀測值 z boldsymbol{z} z ,一個是根據(jù)目前估計的狀態(tài)量和觀測模型計算出來的預測值 h ( x ) h(boldsymbol{x}) h ( x ) 。求解最優(yōu)狀態(tài)估計問題時通常我們

    2024年02月13日
    瀏覽(21)
  • 機器視覺【3】非線性求解相機幾何參數(shù)

    機器視覺【3】非線性求解相機幾何參數(shù)

    上一章節(jié)介紹學習了(DLT)線性求解相機幾何參數(shù),了解到線性求解法當中比較明顯的缺點: 沒有考慮到鏡頭畸變的影響 不能引入更多的約束條件融入到DLT算法當中優(yōu)化 最關鍵的是,代數(shù)距離并不是計算相機矩陣的最佳距離函數(shù) 基于以上問題點,提出非線性求解方法。 將

    2024年02月21日
    瀏覽(23)
  • 高等工程數(shù)學 —— 第五章 (2)非線性規(guī)劃的最優(yōu)條件

    高等工程數(shù)學 —— 第五章 (2)非線性規(guī)劃的最優(yōu)條件

    無約束規(guī)劃問題的最優(yōu)性條件 簡單說就是先用一階必要條件求駐點,再用二階充分條件來驗證。 其實就是一階導數(shù)為0然后解未知量的值 這里的Hesse矩陣如下: 再簡單說說判斷矩陣是否正定的兩種方法: 求出A的所有特征值。若A的特征值均為正數(shù),則A是正定的;若A的特征值

    2024年02月03日
    瀏覽(19)
  • 【算法系列】非線性最小二乘求解-梯度下降法

    【算法系列】非線性最小二乘求解-梯度下降法

    ·【算法系列】卡爾曼濾波算法 ·【算法系列】非線性最小二乘求解-直接求解法 ·【算法系列】非線性最小二乘求解-梯度下降法 ·【算法系列】非線性最小二乘-高斯牛頓法? ·【算法系列】非線性最小二乘-列文伯格馬夸爾和狗腿算法? 文章目錄 系列文章 文章目錄 前言 一、

    2024年02月16日
    瀏覽(18)
  • 【數(shù)學建?!縋ython+Gurobi求解非線性規(guī)劃模型

    目錄 1 概述 2 算例? 2.1 算例 2.2 參數(shù)設置 2.3 Python代碼實現(xiàn) 2.4 求解結果 如果目標函數(shù)或約束條件中包含非線性函數(shù),就稱這種規(guī)劃問題為非線性規(guī)劃問題。 參考:(非線性規(guī)劃Python)計及動態(tài)約束及節(jié)能減排環(huán)保要求的經(jīng)濟調(diào)度 2.1 算例 2.2 參數(shù)設置 求解NLP/非凸問題時,

    2024年02月09日
    瀏覽(20)
  • matlab實現(xiàn)牛頓迭代法求解非線性方程

    非線性方程是指含有未知數(shù)的方程,且方程中至少有一個未知數(shù)的次數(shù)大于一或者含有非一次冪的函數(shù)(如指數(shù)、對數(shù)、三角函數(shù)等)。例如,$f(x) = x^3 - 2x - 5 = 0$就是一個非線性方程。非線性方程通常沒有顯式的解析解,因此需要使用數(shù)值方法來近似求解。 牛頓迭代法(N

    2024年02月11日
    瀏覽(36)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包