文章目錄
- 一、問題描述
- 二、數學推導
- 1. 目標函數處理
- 2. 約束條件處理
- 三、代碼編寫
一、問題描述
已知:
m i n ( x 1 ? 1 ) 2 + ( x 2 ? 2 ) 2 s . t . 0 ? x 1 ? 1.5 , 1 ? x 2 ? 2.5 min(x_1-1)^2+(x_2-2)^2 \qquad s.t. \ \ 0 \leqslant x_1 \leqslant 1.5,\ \ 1 \leqslant x_2 \leqslant 2.5 min(x1??1)2+(x2??2)2s.t.??0?x1??1.5,??1?x2??2.5
目標函數為二元二次函數,可行域為線性、凸集,此為二次規劃問題,可將其轉換成二次規劃表達式再進行求解。相關數學概念參考另一篇: 最優化問題基礎理論概述。
二、數學推導
1. 目標函數處理
f ( x 1 , x 2 ) = ( x 1 ? 1 ) 2 + ( x 2 ? 2 ) 2 = x 1 2 + x 2 2 ? 2 x 1 ? 4 x 2 + C f(x_1, x_2)=(x_1-1)^2+(x_2-2)^2 =x_1^2+x_2^2-2x_1-4x_2+C f(x1?,x2?)=(x1??1)2+(x2??2)2=x12?+x22??2x1??4x2?+C
其中,常數項用 C C C表示;
令, X = [ x 1 x 2 ] X=\left[ \begin{matrix} x_1 \\ x_2 \end{matrix} \right] X=[x1?x2??],則
f ( x 1 , x 2 ) = [ x 1 , x 2 ] [ x 1 , x 2 ] T + [ ? 2 , ? 4 ] [ x 1 , x 2 ] T = X T X + [ ? 2 , ? 4 ] X = 1 2 X T [ 2 0 0 2 ] X + [ ? 2 ? 4 ] T X = 1 2 X T P X + Q T X \begin{aligned} f(x_1, x_2) &= [x_1, x_2][x_1, x_2]^T+[-2, -4][x_1, x_2]^T \\[2ex] &= X^TX+[-2, -4]X \\[2ex] &=\frac{1}{2} X^T \left[\begin{matrix} 2 &0 \\ 0&2 \end{matrix} \right] X+\left[\begin{matrix} -2 \\ -4 \end{matrix} \right]^TX \\[2ex] &= \frac{1}{2} X^TPX+Q^TX \end{aligned} f(x1?,x2?)?=[x1?,x2?][x1?,x2?]T+[?2,?4][x1?,x2?]T=XTX+[?2,?4]X=21?XT[20?02?]X+[?2?4?]TX=21?XTPX+QTX?
其中, P = [ 2 0 0 2 ] ,? Q = [ ? 2 ? 4 ] P=\left[\begin{matrix} 2 &0 \\ 0&2 \end{matrix} \right],\ Q=\left[\begin{matrix} -2 \\ -4 \end{matrix} \right] P=[20?02?],?Q=[?2?4?]
?
關于為什么要寫成 1 2 X T P X \frac{1}{2} X^TPX 21?XTPX 形式,因為此時 P P P 為目標函數的海塞矩陣,具體參看 此鏈接。
2. 約束條件處理
{ 0 ? x 1 ? 1.5 1 ? x 2 ? 2.5 ? [ 0 1 ] ? [ x 1 x 2 ] ? [ 1.5 2.5 ] ? [ 0 1 ] ? [ 1 0 0 1 ] X ? [ 1.5 2.5 ] \begin{aligned} \left\{ \begin{array}{} 0 \leqslant x_1 \leqslant 1.5 \\ 1 \leqslant x_2 \leqslant 2.5 \\ \end{array} \right . \quad \Longleftrightarrow \quad \left[\begin{matrix}0 \\1\end{matrix} \right] \leqslant \left[\begin{matrix}x_1 \\x_2\end{matrix} \right] \leqslant \left[\begin{matrix}1.5 \\2.5\end{matrix} \right] \quad \Longleftrightarrow \quad \left[\begin{matrix}0 \\1\end{matrix} \right] \leqslant \left[\begin{matrix}1&0 \\0&1\end{matrix} \right]X \leqslant \left[\begin{matrix}1.5 \\2.5\end{matrix} \right] \end{aligned} {0?x1??1.51?x2??2.5??[01?]?[x1?x2??]?[1.52.5?]?[01?]?[10?01?]X?[1.52.5?]?
令 L B = [ 0 1 ] , A = [ 1 0 0 1 ] , U B = [ 1.5 2.5 ] L_B=\left[\begin{matrix}0 \\1\end{matrix} \right],\ A=\left[\begin{matrix}1&0 \\0&1\end{matrix} \right],\ U_B=\left[\begin{matrix}1.5 \\2.5\end{matrix} \right] LB?=[01?],?A=[10?01?],?UB?=[1.52.5?] ,整理得約束條件如下:
L B ? A X ? U B L_B \leqslant AX \leqslant U_B LB??AX?UB?
三、代碼編寫
??由步驟 二、數學推導 得到5個矩陣:
- P P P : 二次型矩陣(實對稱矩陣);
- Q Q Q : 一次項矩陣;
- U B U_B UB? : 上邊界矩陣;
- L B L_B LB? : 下邊界矩陣;
- A A A : 邊界系數矩陣;
??現在根據這5個矩陣進行代碼編寫,是使用osqp進行二次型規劃問題構建及求解。
代碼如下:
Eigen::SparseMatrix<double> P(2, 2); // P, 二次型矩陣
Eigen::VectorXd Q(2); // Q, 一次項向量
Eigen::SparseMatrix<double> A(2, 2); // 單位陣
Eigen::VectorXd lowerBound(2); // 下邊界向量
Eigen::VectorXd upperBound(2); // 上邊界向量P.insert(0, 0) = 2.0;
P.insert(1, 1) = 2.0;
std::cout << "\033[34m" << "P:" << std::endl<< P << "\033[0m" << std::endl;A.insert(0, 0) = 1.0;
A.insert(1, 1) = 1.0;
std::cout << "\033[34m" << "A:" << std::endl<< A << "\033[0m" << std::endl;Q << -2, -4;
std::cout << "\033[34m" << "Q:" << std::endl<< Q << "\033[0m" << std::endl;lowerBound << 0.0, 1.0;
upperBound << 1.5, 2.5;// Step 1: 創建求解器
OsqpEigen::Solver solver;
// Step 2: 設置(提升求解速度)
solver.settings()->setVerbosity(false);
solver.settings()->setWarmStart(true);// Step 3: 初始化(7部分)
solver.data()->setNumberOfVariables(2); // 變量數
solver.data()->setNumberOfConstraints(2); // 約束數
if (!solver.data()->setHessianMatrix(P)) // 海塞矩陣
{return;
}
if (!solver.data()->setGradient(Q)) // Q矩陣
{return;
}
if (!solver.data()->setLinearConstraintsMatrix(A)) // 線性約束矩陣A
{return;
}
if (!solver.data()->setLowerBound(lowerBound)) // 下邊界矩陣
{return;
}
if (!solver.data()->setUpperBound(upperBound)) // 上邊界矩陣
{return;
}if (!solver.initSolver())
{return;
}// Step 4:求解
Eigen::VectorXd QPSolution;
if (solver.solveProblem() != OsqpEigen::ErrorExitFlag::NoError)
{return;
}
QPSolution = solver.getSolution();
std::cout << "\033[1;32m" << "QPSolution:" << std::endl<< QPSolution << "\033[0m" << std::endl;
運行結果如下:
可見,當 x 1 = 1 , x 2 = 2 x_1=1,\ x_2=2 x1?=1,?x2?=2 時目標函數取得最小。