SHOGUN
v3.2.0
|
00001 /* 00002 * This program is free software; you can redistribute it and/or modify 00003 * it under the terms of the GNU General Public License as published by 00004 * the Free Software Foundation; either version 3 of the License, or 00005 * (at your option) any later version. 00006 * 00007 * Written (W) 2009 Alexander Binder 00008 * Copyright (C) 2009 Fraunhofer Institute FIRST and Max-Planck-Society 00009 * 00010 * Update to patch 0.10.0 - thanks to Eric aka Yoo (thereisnoknife@gmail.com) 00011 * 00012 */ 00013 00014 #include <shogun/classifier/mkl/MKLMulticlassGLPK.h> 00015 #ifdef USE_GLPK 00016 #include <glpk.h> 00017 #endif 00018 00019 00020 using namespace shogun; 00021 00022 MKLMulticlassGLPK::MKLMulticlassGLPK() 00023 { 00024 numkernels = 0; 00025 #ifdef USE_GLPK 00026 //makes glpk quiet 00027 glp_term_out(GLP_OFF); 00028 linearproblem=NULL; 00029 #endif 00030 } 00031 MKLMulticlassGLPK::~MKLMulticlassGLPK() 00032 { 00033 #if defined(USE_GLPK) 00034 if (linearproblem) 00035 { 00036 glp_delete_prob((glp_prob*) linearproblem); 00037 linearproblem=NULL; 00038 } 00039 00040 #endif 00041 } 00042 00043 MKLMulticlassGLPK MKLMulticlassGLPK::operator=(MKLMulticlassGLPK & gl) 00044 { 00045 SG_ERROR( 00046 " MKLMulticlassGLPK MKLMulticlassGLPK::operator=(...): must " 00047 "not be called, glpk structure is currently not copyable"); 00048 return (*this); 00049 00050 } 00051 MKLMulticlassGLPK::MKLMulticlassGLPK(MKLMulticlassGLPK & gl) 00052 { 00053 SG_ERROR( 00054 " MKLMulticlassGLPK::MKLMulticlassGLPK(MKLMulticlassGLPK & gl):" 00055 " must not be called, glpk structure is currently not copyable"); 00056 00057 } 00058 00059 void MKLMulticlassGLPK::setup(const int32_t numkernels2) 00060 { 00061 #if defined(USE_GLPK) 00062 numkernels=numkernels2; 00063 if (numkernels<=1) 00064 { 00065 SG_ERROR("void glpkwrapper::setup(const int32_tnumkernels): input " 00066 "numkernels out of bounds: %d\n",numkernels); 00067 } 00068 00069 if (!linearproblem) 00070 { 00071 linearproblem=glp_create_prob(); 00072 } 00073 00074 glp_set_obj_dir((glp_prob*)linearproblem, GLP_MAX); 00075 00076 glp_add_cols((glp_prob*)linearproblem,1+numkernels); 00077 00078 //set up theta 00079 glp_set_col_bnds((glp_prob*)linearproblem,1,GLP_FR,0.0,0.0); 00080 glp_set_obj_coef((glp_prob*)linearproblem,1,1.0); 00081 00082 //set up betas 00083 int32_t offset=2; 00084 for (int32_t i=0; i<numkernels;++i) 00085 { 00086 glp_set_col_bnds((glp_prob*)linearproblem,offset+i,GLP_DB,0.0,1.0); 00087 glp_set_obj_coef((glp_prob*)linearproblem,offset+i,0.0); 00088 } 00089 00090 //set sumupconstraint32_t/sum_l \beta_l=1 00091 glp_add_rows((glp_prob*)linearproblem,1); 00092 00093 int32_t*betainds(NULL); 00094 betainds=SG_MALLOC(int, 1+numkernels); 00095 for (int32_t i=0; i<numkernels;++i) 00096 { 00097 betainds[1+i]=2+i; // coefficient for theta stays zero, therefore 00098 //start at 2 not at 1 ! 00099 } 00100 00101 float64_t *betacoeffs(NULL); 00102 betacoeffs=new float64_t[1+numkernels]; 00103 00104 for (int32_t i=0; i<numkernels;++i) 00105 { 00106 betacoeffs[1+i]=1; 00107 } 00108 00109 glp_set_mat_row((glp_prob*)linearproblem,1,numkernels, betainds,betacoeffs); 00110 glp_set_row_bnds((glp_prob*)linearproblem,1,GLP_FX,1.0,1.0); 00111 00112 SG_FREE(betainds); 00113 betainds=NULL; 00114 00115 SG_FREE(betacoeffs); 00116 betacoeffs=NULL; 00117 #else 00118 SG_ERROR( 00119 "glpk.h from GNU glpk not included at compile time necessary " 00120 "here\n"); 00121 #endif 00122 00123 } 00124 00125 void MKLMulticlassGLPK::addconstraint(const ::std::vector<float64_t> & normw2, 00126 const float64_t sumofpositivealphas) 00127 { 00128 #if defined(USE_GLPK) 00129 00130 ASSERT ((int)normw2.size()==numkernels) 00131 ASSERT (sumofpositivealphas>=0) 00132 00133 glp_add_rows((glp_prob*)linearproblem,1); 00134 00135 int32_t curconstraint=glp_get_num_rows((glp_prob*)linearproblem); 00136 00137 int32_t *betainds(NULL); 00138 betainds=SG_MALLOC(int, 1+1+numkernels); 00139 00140 betainds[1]=1; 00141 for (int32_t i=0; i<numkernels;++i) 00142 { 00143 betainds[2+i]=2+i; // coefficient for theta stays zero, therefore start 00144 //at 2 not at 1 ! 00145 } 00146 00147 float64_t *betacoeffs(NULL); 00148 betacoeffs=new float64_t[1+1+numkernels]; 00149 00150 betacoeffs[1]=-1; 00151 00152 for (int32_t i=0; i<numkernels;++i) 00153 { 00154 betacoeffs[2+i]=0.5*normw2[i]; 00155 } 00156 glp_set_mat_row((glp_prob*)linearproblem,curconstraint,1+numkernels, betainds, 00157 betacoeffs); 00158 glp_set_row_bnds((glp_prob*)linearproblem,curconstraint,GLP_LO,sumofpositivealphas, 00159 sumofpositivealphas); 00160 00161 SG_FREE(betainds); 00162 betainds=NULL; 00163 00164 SG_FREE(betacoeffs); 00165 betacoeffs=NULL; 00166 00167 #else 00168 SG_ERROR( 00169 "glpk.h from GNU glpk not included at compile time necessary " 00170 "here\n"); 00171 #endif 00172 } 00173 00174 void MKLMulticlassGLPK::computeweights(std::vector<float64_t> & weights2) 00175 { 00176 #if defined(USE_GLPK) 00177 weights2.resize(numkernels); 00178 00179 glp_simplex((glp_prob*) linearproblem,NULL); 00180 00181 float64_t sum=0; 00182 for (int32_t i=0; i< numkernels;++i) 00183 { 00184 weights2[i]=glp_get_col_prim((glp_prob*) linearproblem, i+2); 00185 weights2[i]= ::std::max(0.0, ::std::min(1.0,weights2[i])); 00186 sum+= weights2[i]; 00187 } 00188 00189 if (sum>0) 00190 { 00191 for (int32_t i=0; i< numkernels;++i) 00192 { 00193 weights2[i]/=sum; 00194 } 00195 } 00196 else 00197 SG_ERROR("void glpkwrapper::computeweights(std::vector<float64_t> & " 00198 "weights2): sum of weights nonpositive %f\n",sum); 00199 #else 00200 SG_ERROR( 00201 "glpk.h from GNU glpk not included at compile time necessary " 00202 "here\n"); 00203 #endif 00204 }