00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef QUADPROGRAM_H
00012 #define QUADPROGRAM_H
00013 #include <Base/TMatrix.h>
00014 using namespace PTM;
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 template <typename MATNN, typename VECN, typename VEC2N, typename VECNI>
00035 class QuadProgramImp{
00036 public:
00037 MATNN matQ;
00038 VECN vecC;
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
00061
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
00079 int Solve(){
00080 int i = 0;
00081
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
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
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
00234
00235
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
00240
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
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