00001
00054
00055
00056
00057 #ifndef _QuadraticProgram_H_
00058 #define _QuadraticProgram_H_
00059
00060
00061 #include <SharkDefs.h>
00062 #include <ReClaM/Model.h>
00063 #include <ReClaM/KernelFunction.h>
00064 #include <Array/Array2D.h>
00065 #include <vector>
00066
00067
00069 class QPSolver
00070 {
00071 public:
00072 QPSolver();
00073 virtual ~QPSolver();
00074 };
00075
00076
00085 class QPMatrix
00086 {
00087 public:
00089 QPMatrix(unsigned int size);
00090
00092 virtual ~QPMatrix();
00093
00102 virtual float Entry(unsigned int i, unsigned int j) = 0;
00103
00115 virtual void FlipColumnsAndRows(unsigned int i, unsigned int j) = 0;
00116
00118 inline unsigned int getMatrixSize() const
00119 {
00120 return matrixsize;
00121 }
00122
00123 protected:
00125 unsigned int matrixsize;
00126 };
00127
00128
00135 class KernelMatrix : public QPMatrix
00136 {
00137 public:
00141 KernelMatrix(KernelFunction* kernelfunction,
00142 const Array<double>& data);
00143
00145 ~KernelMatrix();
00146
00148 float Entry(unsigned int i, unsigned int j);
00149
00151 void FlipColumnsAndRows(unsigned int i, unsigned int j);
00152
00153 protected:
00155 KernelFunction* kernel;
00156
00158 Array<ArrayReference<double>* > x;
00159 };
00160
00161
00169 class RegularizedKernelMatrix : public KernelMatrix
00170 {
00171 public:
00176 RegularizedKernelMatrix(KernelFunction* kernel,
00177 const Array<double>& data,
00178 const Array<double>& diagModification);
00179
00181 ~RegularizedKernelMatrix();
00182
00184 float Entry(unsigned int i, unsigned int j);
00185
00187 void FlipColumnsAndRows(unsigned int i, unsigned int j);
00188
00189 protected:
00191 Array<double> diagMod;
00192 };
00193
00194
00204 class QPMatrix2 : public QPMatrix
00205 {
00206 public:
00212 QPMatrix2(QPMatrix* base);
00213
00215 ~QPMatrix2();
00216
00218 float Entry(unsigned int i, unsigned int j);
00219
00221 void FlipColumnsAndRows(unsigned int i, unsigned int j);
00222
00223 protected:
00225 QPMatrix* baseMatrix;
00226
00228 Array<unsigned int> mapping;
00229 };
00230
00231
00239 class InputLabelMatrix : public QPMatrix
00240 {
00241 public:
00247 InputLabelMatrix(KernelFunction* kernelfunction,
00248 const Array<double>& input,
00249 const Array<double>& target,
00250 const Array<double>& prototypes);
00251
00253 ~InputLabelMatrix();
00254
00256 float Entry(unsigned int i, unsigned int j);
00257
00259 void FlipColumnsAndRows(unsigned int i, unsigned int j);
00260
00261 protected:
00263 KernelFunction* kernel;
00264
00266 Array<ArrayReference<double>* > x;
00267
00269 std::vector<unsigned int> y;
00270
00272 Array<double> prototypeProduct;
00273 };
00274
00275
00289 class CachedMatrix : public QPMatrix
00290 {
00291 public:
00295 CachedMatrix(QPMatrix* base, unsigned int cachesize = 0x4000000);
00296
00298 ~CachedMatrix();
00299
00312 float* Row(unsigned int k, unsigned int begin, unsigned int end, bool temp = false);
00313
00315 float Entry(unsigned int i, unsigned int j);
00316
00328 void FlipColumnsAndRows(unsigned int i, unsigned int j);
00329
00330 inline unsigned int getMaxCacheSize() const
00331 {
00332 return cacheMaxSize;
00333 }
00334
00335 inline unsigned int getCacheSize() const
00336 {
00337 return cacheSize;
00338 }
00339
00340 inline unsigned int getCacheRowSize(unsigned int k)
00341 {
00342 return cacheEntry[k].length;
00343 }
00344
00345 inline void Clear()
00346 { cacheClear(); }
00347
00348 void CacheRowResize(unsigned int k, unsigned int newsize);
00349 void CacheRowRelease(unsigned int k);
00350
00351 protected:
00353 QPMatrix* baseMatrix;
00354
00355
00356 unsigned int cacheSize;
00357 unsigned int cacheMaxSize;
00358 struct tCacheEntry
00359 {
00360 float* data;
00361 int length;
00362 int older;
00363 int newer;
00364 };
00365 std::vector<tCacheEntry> cacheEntry;
00366 std::vector<float> cacheTemp;
00367 int cacheNewest;
00368 int cacheOldest;
00369
00371 void cacheAppend(int var);
00372
00374 void cacheRemove(int var);
00375
00378 void cacheAdd(int var, unsigned int length);
00379
00381 void cacheDelete(int var);
00382
00384 void cacheResize(int var, unsigned int newlength);
00385
00387 void cacheClear();
00388 };
00389
00390
00447 class QpSvmCG : public QPSolver
00448 {
00449 public:
00456 static void Solve(const Array<double>& quadratic,
00457 const Array<double>& linear,
00458 const Array<double>& lower,
00459 const Array<double>& upper,
00460 Array<double>& point,
00461 double accuracy = 1e-10);
00462 };
00463
00464
00526 class QpSvmDecomp : public QPSolver
00527 {
00528 public:
00531 QpSvmDecomp(CachedMatrix& quadraticPart);
00532
00534 virtual ~QpSvmDecomp();
00535
00555 double Solve(const Array<double>& linearPart,
00556 const Array<double>& boxLower,
00557 const Array<double>& boxUpper,
00558 Array<double>& solutionVector,
00559 double eps = 0.001,
00560 double threshold = 1e100);
00561
00576 double ComputeInnerProduct(unsigned int index, const Array<double>& coeff);
00577
00582 void getGradient(Array<double>& grad);
00583
00585 inline void setVerbose(bool verbose = false)
00586 {
00587 printInfo = verbose;
00588 }
00589
00591 inline void setStrategy(const char* strategy = NULL)
00592 {
00593 WSS_Strategy = strategy;
00594 }
00595
00597 inline void setShrinking(bool shrinking = true)
00598 {
00599 useShrinking = shrinking;
00600 }
00601
00603 inline SharkInt64 iterations()
00604 {
00605 return iter;
00606 }
00607
00609 inline bool isOptimal()
00610 {
00611 return optimal;
00612 }
00613
00617 inline void setMaxIterations(SharkInt64 maxiter = -1)
00618 {
00619 this->maxIter = maxiter;
00620 }
00621
00625 inline void setMaxSeconds(int seconds = -1)
00626 {
00627 maxSeconds = seconds;
00628 }
00629
00630 protected:
00632 unsigned int dimension;
00633
00635 CachedMatrix& quadratic;
00636
00638 Array<double> linear;
00639
00641 Array<double> boxMin;
00642
00644 Array<double> boxMax;
00645
00647 SharkInt64 iter;
00648
00652 bool optimal;
00653
00655 SharkInt64 maxIter;
00656
00658 int maxSeconds;
00659
00661 bool printInfo;
00662
00664 const char* WSS_Strategy;
00665
00667 bool useShrinking;
00668
00670 bool(QpSvmDecomp::*currentWSS)(unsigned int&, unsigned int&);
00671
00673 unsigned int active;
00674
00676 Array<unsigned int> permutation;
00677
00680 Array<double> diagonal;
00681
00684 Array<double> gradient;
00685
00687 Array<double> alpha;
00688
00690 bool bFirst;
00691
00693 unsigned int old_i;
00694
00696 unsigned int old_j;
00697
00699 double epsilon;
00700
00706 bool MVP(unsigned int& i, unsigned int& j);
00707
00713 bool HMG(unsigned int& i, unsigned int& j);
00714
00720 bool Libsvm28(unsigned int& i, unsigned int& j);
00721
00729 virtual bool SelectWorkingSet(unsigned int& i, unsigned int& j);
00730
00732 void SelectWSS();
00733
00735 void Shrink();
00736
00738 void Unshrink(bool complete = false);
00739
00741 bool bUnshrinked;
00742
00744 void FlipCoordinates(unsigned int i, unsigned int j);
00745 };
00746
00747
00757 class QpBoxDecomp : public QPSolver
00758 {
00759 public:
00762 QpBoxDecomp(CachedMatrix& quadraticPart);
00763
00765 virtual ~QpBoxDecomp();
00766
00776 void Solve(const Array<double>& linearPart,
00777 const Array<double>& boxLower,
00778 const Array<double>& boxUpper,
00779 Array<double>& solutionVector,
00780 double eps = 0.001);
00781
00795 void Continue(const Array<double>& boxLower,
00796 const Array<double>& boxUpper,
00797 Array<double>& solutionVector);
00798
00813 void Continue(const Array<double>& gradientUpdate,
00814 Array<double>& solutionVector);
00815
00817 inline SharkInt64 iterations()
00818 {
00819 return iter;
00820 }
00821
00823 inline bool isOptimal()
00824 {
00825 return optimal;
00826 }
00827
00831 inline void setMaxIterations(SharkInt64 maxiter = -1)
00832 {
00833 this->maxIter = maxiter;
00834 }
00835
00836 protected:
00838 void SMO();
00839
00841 unsigned int dimension;
00842
00844 CachedMatrix& quadratic;
00845
00847 Array<double> linear;
00848
00850 Array<double> boxMin;
00851
00853 Array<double> boxMax;
00854
00856 unsigned int active;
00857
00859 Array<unsigned int> permutation;
00860
00863 Array<double> diagonal;
00864
00867 Array<double> gradient;
00868
00870 Array<double> alpha;
00871
00873 double epsilon;
00874
00875 virtual bool SelectWorkingSet(unsigned int& i);
00876
00878 void Shrink();
00879
00881 void Unshrink(bool complete = false);
00882
00884 bool bUnshrinked;
00885
00887 SharkInt64 iter;
00888
00892 bool optimal;
00893
00895 SharkInt64 maxIter;
00896
00898 void FlipCoordinates(unsigned int i, unsigned int j);
00899 };
00900
00901
00912 class QpBoxAllInOneDecomp : public QPSolver
00913 {
00914 public:
00918 QpBoxAllInOneDecomp(CachedMatrix& kernel);
00919
00921 virtual ~QpBoxAllInOneDecomp();
00922
00933 void Solve(unsigned int classes,
00934 const Array<double>& target,
00935 const Array<double>& prototypes,
00936 double C,
00937 Array<double>& solutionVector,
00938 double eps = 0.001);
00939
00957 void Continue(double largerC, Array<double>& solutionVector);
00958
00960 inline SharkInt64 iterations()
00961 {
00962 return iter;
00963 }
00964
00966 inline bool isOptimal()
00967 {
00968 return optimal;
00969 }
00970
00974 inline void setMaxIterations(SharkInt64 maxiter = -1)
00975 {
00976 this->maxIter = maxiter;
00977 }
00978
00979 protected:
00981 struct tExample
00982 {
00983 unsigned int index;
00984 unsigned int label;
00985 unsigned int active;
00986 unsigned int* variables;
00987 };
00988
00990 struct tVariable
00991 {
00992 unsigned int example;
00993 unsigned int index;
00994 unsigned int label;
00995 };
00996
00998 std::vector<tExample> example;
00999
01001 std::vector<tVariable> variable;
01002
01004 std::vector<unsigned int> storage;
01005
01006 unsigned int examples;
01007 unsigned int classes;
01008 unsigned int variables;
01009
01011 CachedMatrix& kernelMatrix;
01012
01014 Array<double> linear;
01015
01017 Array<double> boxMin;
01018
01020 Array<double> boxMax;
01021
01023 unsigned int activeEx;
01024
01026 unsigned int activeVar;
01027
01030 Array<double> diagonal;
01031
01034 Array<double> gradient;
01035
01037 Array<double> alpha;
01038
01040 double epsilon;
01041
01043 double Modifier(unsigned int v_i, unsigned int v_j, unsigned int y_i, unsigned int y_j);
01044
01046 bool SelectWorkingSet(unsigned int& i);
01047
01049 void Shrink();
01050
01052 void Unshrink(bool complete = false);
01053
01055 bool bUnshrinked;
01056
01058 void DeactivateVariable(unsigned int v);
01059
01061 void DeactivateExample(unsigned int e);
01062
01064 Array<double> m_prototypeProduct;
01065
01067 Array<double> m_prototypeLength;
01068
01070 SharkInt64 iter;
01071
01075 bool optimal;
01076
01078 SharkInt64 maxIter;
01079 };
01080
01081
01095 class QpCrammerSingerDecomp : public QPSolver
01096 {
01097 public:
01102 QpCrammerSingerDecomp(CachedMatrix& kernel, const Array<double>& y, unsigned int classes);
01103
01105 virtual ~QpCrammerSingerDecomp();
01106
01114 void Solve(Array<double>& solutionVector,
01115 double beta,
01116 double eps = 0.001);
01117
01119 inline SharkInt64 iterations()
01120 {
01121 return iter;
01122 }
01123
01125 inline bool isOptimal()
01126 {
01127 return optimal;
01128 }
01129
01133 inline void setMaxIterations(SharkInt64 maxiter = -1)
01134 {
01135 this->maxIter = maxiter;
01136 }
01137
01138 protected:
01140 struct tExample
01141 {
01142 unsigned int index;
01143 unsigned int label;
01144 unsigned int active;
01145 unsigned int* variables;
01146 };
01147
01149 struct tVariable
01150 {
01151 unsigned int example;
01152 unsigned int index;
01153 unsigned int label;
01154 };
01155
01157 std::vector<tExample> example;
01158
01160 std::vector<tVariable> variable;
01161
01163 std::vector<unsigned int> storage;
01164
01165 unsigned int examples;
01166 unsigned int classes;
01167 unsigned int variables;
01168
01170 CachedMatrix& kernelMatrix;
01171
01173 Array<double> linear;
01174
01176 Array<double> boxMin;
01177
01179 Array<double> boxMax;
01180
01182 unsigned int activeEx;
01183
01185 unsigned int activeVar;
01186
01189 Array<double> diagonal;
01190
01193 Array<double> gradient;
01194
01196 Array<double> alpha;
01197
01199 double epsilon;
01200
01201 double SelectWorkingSet(unsigned int& i, unsigned int& j);
01202
01204 void Shrink();
01205
01207 void Unshrink(bool complete = false);
01208
01210 bool bUnshrinked;
01211
01213 void DeactivateVariable(unsigned int v);
01214
01216 void DeactivateExample(unsigned int e);
01217
01219 SharkInt64 iter;
01220
01224 bool optimal;
01225
01227 SharkInt64 maxIter;
01228 };
01229
01230
01232 class QpBoxAndEqCG : public QPSolver
01233 {
01234 public:
01241 static void Solve(const Array<double>& quadratic,
01242 const Array<double>& linear,
01243 const Array<double>& boxMin,
01244 const Array<double>& boxMax,
01245 const Array<double>& eqMat,
01246 Array<double>& point,
01247 double accuracy = 1e-10);
01248
01249 protected:
01250 static void Orthogonalize(int oc, const Array<double>& ortho, const Array<bool>& active, ArrayReference<double> vec);
01251 static void Orthogonalize(Array<double>& eq, const Array<bool>& active);
01252 static void Project(const Array<bool>& active, Array<double>& eq, const Array<double>& gradient, Array<double>& direction);
01253 };
01254
01255
01257 class QpBoxAndEqDecomp : public QPSolver
01258 {
01259 public:
01266 static void Solve(const Array<double>& quadratic,
01267 const Array<double>& linear,
01268 const Array<double>& boxMin,
01269 const Array<double>& boxMax,
01270 const Array<double>& eqMat,
01271 Array<double>& point,
01272 double accuracy = 1e-3);
01273
01274 protected:
01275 static void Orthogonalize(Array<double>& eq);
01276 static void Project(const Array<double>& eq, const Array<double>& gradient, Array<double>& direction);
01277 };
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429 #endif
01430