メインページ | ネームスペース一覧 | クラス階層 | 構成 | Directories | ファイル一覧 | ネームスペースメンバ | 構成メンバ | ファイルメンバ | 関連ページ

QuadProgram.h

00001 /***********************************************************************/
00002 /*                                                                     */
00003 /*  FILE        :qp_prog02.h                                           */
00004 /*  DATE        :2002/04/01                                            */
00005 /*  DESCRIPTION :Quadratic Programming (Active Set Method)             */
00006 /*                                                                     */
00007 /*  Katsuhito AKAHANE  (kakahane@hi.pi.titech.ac.jp)                   */
00008 /*                    modified by Shoichi HASEGAWA                     */
00009 /*                                                                     */
00010 /***********************************************************************/
00011 #ifndef QUADPROGRAM_H
00012 #define QUADPROGRAM_H
00013 #include <Base/TMatrix.h>
00014 using namespace PTM;
00015 /*
00016 二次計画法
00017                                                           2003/02/04 赤羽 克仁
00018 
00019 1.目的
00020     ボックス制約条件下(minX<=x<=maxX)で、次元が小規模の二次計画問題を解くプログラムです。
00021     SPIDAR用に開発されていますが、ボックス制約条件下ならば、一般の二次計画問題を解くこともできます。
00022     具体的には、以下の通り
00023     
00024     f(x) = (1/2)x'Qx - c'x   -> minimize
00025     minX <= x <= maxX
00026     
00027     を有効制約法(Active Set Strategy Methods)を用いて解いています。
00028 */
00029 /** Quadratic Programming (C++ template)
00030     @param MATNN    n行n列の行列型
00031     @param VECN     n行のベクトル型
00032     @param VEC2N    2n行のベクトル型
00033     @param VECNI    int型のn行のベクトル型  */
00034 template <typename MATNN, typename VECN, typename VEC2N, typename VECNI>
00035 class QuadProgramImp{
00036 public:
00037     MATNN matQ;             ///<    目的関数の2次の係数行列
00038     VECN vecC;              ///<    目的関数の1次の係数ベクトル
00039     VECN vecX;              ///<    解
00040     int Dim(){ return vecX.size(); }
00041     typedef TYPENAME VECN::element_type T;
00042 
00043 protected:
00044     MATNN matA;
00045     VECN minX;              
00046     VECN maxX;
00047 
00048     MATNN matR;
00049     VECN vecL;
00050 
00051     VEC2N vecXYNext;
00052     VECN vecD;
00053     VECNI isActiveSet;
00054 
00055 public:
00056     QuadProgramImp(){}
00057     ~QuadProgramImp(){}
00058 
00059     //
00060     // QP Initialize Function
00061     // minT <= T <= maxT
00062     void Init(VECN minT, VECN maxT){
00063         int i,j;
00064         minX = -minT;
00065         maxX = maxT;
00066 
00067         for(i=0; i<Dim(); i++){
00068             for(j=0;j<Dim();j++){
00069                 matA[i][j] = 0;
00070             }
00071             vecX[i] = minT[i];
00072             isActiveSet[i] = -1;
00073             matA[i][i] = 1;
00074         }
00075     }
00076 
00077     //
00078     // QP Main Function
00079     int Solve(){
00080         int i = 0;
00081         //while(1){
00082         for(;i<10;i++){
00083             MakeCalcMat();
00084             CalcMatRXL(matR,vecXYNext,vecL);
00085             if(isVecX_VecXNext()){
00086                 if(CalcLambda()) return i;
00087             }
00088             else{
00089                 CalcAlpha();
00090             }
00091             i++;
00092         }
00093         return -1;
00094     }
00095 
00096 protected:
00097     void MakeCalcMat(){
00098         int i,j;
00099         for(i=0;i<Dim();i++){
00100             vecL[i] = vecC[i];
00101             for(j=0;j<Dim();j++){
00102                 if(isActiveSet[j] > 0){
00103                     vecL[i] -= matQ[i][j] * maxX[i];
00104                     matR[i][j] = matA[i][j];
00105                 }
00106                 else if(isActiveSet[j] < 0){
00107                     vecL[i] += matQ[i][j] * minX[i];
00108                     matR[i][j] = -matA[i][j];
00109                 }
00110                 else{
00111                     matR[i][j] = matQ[i][j];
00112                 }
00113             }
00114         }
00115 
00116     }
00117 
00118     void CalcMatRXL(MATNN& a, VEC2N& x, VECN& b){
00119         int i,j,k;
00120         T p,q,s;
00121         // 連立1次方程式を解く
00122         //(ガウスの消去法 科学技術計算ハンドブックより)改善の余地あり
00123         for ( k=0 ; k<Dim()-1 ; ++k )
00124         {
00125             p=a[k][k];
00126             for ( j=k+1 ; j<Dim() ; ++j )
00127                 a[k][j]/=p;
00128             b[k]/=p;
00129             for ( i=k+1 ; i<Dim() ; ++i )
00130             {
00131                 q=a[i][k];
00132                 for ( j=k+1 ; j<Dim() ; ++j )
00133                     a[i][j]-=q*a[k][j];
00134                 b[i]-=q*b[k];
00135             } 
00136         } 
00137         x[Dim()-1]=b[Dim()-1]/a[(Dim()-1)][(Dim()-1)];
00138         for ( k=Dim()-2 ; k>=0 ; --k )
00139         {
00140             s=b[k];
00141             for ( j=k+1 ; j<Dim() ; ++j )
00142                 s-=a[k][j]*x[j];
00143             x[k]=s;
00144         }  
00145 
00146         // 結果を格納
00147         for(i=0;i<Dim();i++){
00148             if(isActiveSet[i] > 0){
00149                 x[Dim()+i] = x[i];
00150                 x[i] = maxX[i];
00151             }
00152             else if(isActiveSet[i] < 0){
00153                 x[Dim()+i] = x[i];
00154                 x[i] = -minX[i];
00155             }
00156             else{
00157                 x[Dim()+i] = 0.0f;
00158                 //xout[i] = x[i];
00159             }
00160         }
00161 
00162     }
00163 
00164     int isVecX_VecXNext(){
00165         int i;
00166         for(i=0;i<Dim();i++){
00167             if(vecX[i] != vecXYNext[i]) return 0;
00168         }
00169         return 1;
00170     }
00171 
00172     int CalcLambda(){
00173         int i,bval = 1;
00174         for(i=0;i<Dim();i++){
00175             if(isActiveSet[i]){
00176                 if(vecXYNext[Dim()+i] < 0){
00177                     isActiveSet[i] = 0;
00178                     bval = 0;
00179                 }
00180             }
00181         }
00182         return bval;
00183     }
00184 
00185     void CalcAlpha(){
00186         int i,minIndex = -1,bval;
00187         T val,alpha;
00188         T minAlpha = 1;
00189 
00190         for(i=0;i<Dim();i++){
00191             if(!isActiveSet[i]){
00192                 val = vecD[i] = vecXYNext[i] - vecX[i];
00193                 if(val < 0){
00194                     alpha = -(minX[i] + vecX[i]) / val;
00195                     if(alpha > 0 && minAlpha > alpha){
00196                         minAlpha = alpha;
00197                         minIndex = i;
00198                         bval = -1;
00199                     }
00200                     else if(alpha <= 0){
00201                         isActiveSet[i] = -1;
00202                     }
00203                 }
00204                 else if(val > 0){
00205                     alpha = (maxX[i] - vecX[i]) / val;
00206                     if(alpha > 0 && minAlpha > alpha){
00207                         minAlpha = alpha;
00208                         minIndex = i;
00209                         bval = 1;
00210                     }
00211                     else if(alpha <= 0){
00212                         isActiveSet[i] = 1;
00213                     }
00214                 }
00215             }
00216         }
00217         if(minIndex >= 0){
00218             isActiveSet[minIndex] = bval;
00219             for(i=0;i<Dim();i++){
00220                 if(!isActiveSet[i]){
00221                     vecX[i] += minAlpha * vecD[i];
00222                 }
00223             }
00224         }
00225         else{
00226             for(i=0;i<Dim();i++){
00227                 vecX[i] = vecXYNext[i];
00228             }
00229         }
00230     }
00231 };
00232 
00233 /** Quadratic Programming (C++ template)
00234     @param T    型名
00235     @param N    次元数                      */
00236 template <typename T, int N>
00237 class TQuadProgram:public QuadProgramImp< TMatrixRow<N, N, T>, TVector<N, T>, TVector<2*N, T>, TVector<N, int> >{
00238 };
00239 /** Quadratic Programming (C++ template)
00240     @param T    型名    */
00241 template <class T>
00242 class VQuadProgram:public QuadProgramImp< VMatrixRow<T>, VVector<T>, VVector<T>, VVector<int> >{
00243 public:
00244 #ifdef __GNUC__
00245     typedef typename VQuadProgram::T ET;
00246 #else
00247     typedef T ET;
00248 #endif
00249     typedef QuadProgramImp< VMatrixRow<ET>, VVector<ET>, VVector<ET>, VVector<int> > base_type;
00250     /// 次元を設定
00251     void SetDim(int n){
00252         matQ.resize(n,n);
00253         vecC.resize(n);
00254         vecX.resize(n);
00255         matA.resize(n, n);
00256         minX.resize(n); 
00257         maxX.resize(n);
00258 
00259         matR.resize(n, n);
00260         vecL.resize(n);
00261 
00262         vecXYNext.resize(2*n);
00263         vecD.resize(n);
00264         isActiveSet.resize(n);
00265     }
00266     /// 初期化,minTの次元で,次元を設定
00267     void Init(VVector<ET> minT, VVector<ET> maxT){
00268         SetDim(minT.size());
00269         base_type::Init(minT, maxT);
00270     }
00271 
00272     void SetOneRange(int num, ET max,ET min){
00273         minX[num] = -min;
00274         maxX[num] = max;
00275     }
00276 };
00277 
00278 
00279 #endif //QUADPROGRAM_H

Springheadに対してSun Apr 16 01:57:55 2006に生成されました。  doxygen 1.4.1