00001 /* MTgomory "multi tableau gomory cut" provides an implementation for gomory 00002 * cuts derived from multiple tableau rows in the spirit of the work of 00003 * Andersen et al (IPCO 2007), Cornuejols (es presented in George Nemhauser 00004 * Birthday Conference in Atlanta 2007) and Gomory (presented in the same 00005 * conference). 00006 * 00007 * Copyright (C) 2007 Daniel Espinoza. 00008 * 00009 * This library is free software; you can redistribute it and/or modify it 00010 * under the terms of the GNU Lesser General Public License as published by the 00011 * Free Software Foundation; either version 2.1 of the License, or (at your 00012 * option) any later version. 00013 * 00014 * This library is distributed in the hope that it will be useful, but 00015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 00016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 00017 * License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public License 00020 * along with this library; if not, write to the Free Software Foundation, 00021 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00022 * */ 00023 /* ========================================================================= */ 00024 #ifndef __MT_CPLEX_CBK_H__ 00025 #define __MT_CPLEX_CBK_H__ 00026 #include "cplex.h" 00027 #include "EGlib.h" 00028 #include "mt_types.h" 00029 #include "mt_cutpool.h" 00030 /** @file 00031 * @ingroup MTgomory */ 00032 /** @addtogroup MTgomory */ 00033 /** @{ */ 00034 /* ========================================================================= */ 00035 /** @brief Minimum violation for a cut to be added. Note that we scale the cut 00036 * in such a way that the maximum absolute value of a non-zero coefficient is 00037 * one. */ 00038 #define MT_CCBK_MIN_VIO 0x1p-10 00039 /* ========================================================================= */ 00040 /** @brief Minimum fractionality required for a tableau to be considered, i.e. 00041 * if abs(x-round(x))< min_frac we discard the asociated tableau */ 00042 #define MT_CCBK_MIN_FRAC 0x1p-12 00043 /* ========================================================================= */ 00044 /** @brief Maximum allowed cut ratio. The cut ratio is defined as the ratio 00045 * between the maximum absolute value and minimum absolute value for the 00046 * non-zero coefficients. It is importatn because is a measure of the error 00047 * inducing capabilities of the inequality */ 00048 #define MT_CCBK_MAX_RATIO 0x1p15 00049 /* ========================================================================= */ 00050 /** @brief Minimum tableau row ratio. This is defined as minabsval/maxabsval 00051 * for a tableau row. Tableau rows that have a ratio bellow the given threshold 00052 * will not be considered at the moment of cut genweration */ 00053 #define MT_CCBK_MIN_TABLEAU_RATIO 0x1p-12 00054 /* ========================================================================= */ 00055 /** @brief internal error string for cplex */ 00056 extern char __mt_cplex_errbuf[4096]; 00057 00058 /* ========================================================================= */ 00059 /** @brief if se to one, use real variable names while displaying cut/tableau 00060 * information */ 00061 #define MT_CCBK_USE_NAMES 1 00062 /* ========================================================================= */ 00063 /** @brief internal debugging information for CPLEX 00064 * @param __rval cplex return value (zero means success) 00065 * @param env as returned by CPXopenCPLEX function. 00066 * @param where to jump if an error is found. 00067 * */ 00068 #define MTcplexCHECKRVALG(__env,__rval,__where) do{\ 00069 if(__rval)\ 00070 {\ 00071 CPXgeterrorstring(__env, __rval, __mt_cplex_errbuf);\ 00072 fprintf(stderr,__mt_cplex_errbuf);\ 00073 __EG_PRINTLOC__;\ 00074 goto __where;\ 00075 }\ 00076 }while(0) 00077 /* ========================================================================= */ 00078 /** @brief display a compress tableau into the given file 00079 * @param file where to write the tableau. 00080 * @param lp all LP-related information (including length of the tableau) 00081 * @param matval values of the compresed tableau 00082 * @param matind indices of the non-zeros in the tableau 00083 * @param length of the compresed tableau 00084 * @note The function support compressed tableau with logical variables 00085 * @note Also, the function would prefix a ~ for all variables that are at its 00086 * upper bound. 00087 * */ 00088 void MTcplex_display_compress_tableau(FILE* file, 00089 const MTlp_t*const lp, 00090 const double*const matval, 00091 const int*const matind, 00092 const int nz); 00093 /* ========================================================================= */ 00094 /** @brief display a tableau into the given file 00095 * @param file where to write the tableau. 00096 * @param lp all LP-related information (including length of the tableau) 00097 * @param tableau actual values of the tableau. 00098 * */ 00099 void MTcplex_display_tableau( FILE* file, 00100 const MTlp_t*const lp, 00101 const double*const tableau); 00102 /* ========================================================================= */ 00103 /** @brief initialize an #MTlp_t structure 00104 * @param __lp pointer to an #MTlp_t structure. 00105 * */ 00106 #define MTlp_init(__lp) memset((__lp),0,sizeof(MTlp_t)) 00107 /* ========================================================================= */ 00108 /** @brief free any internally allocated memory inside an #MTlp_t structure. 00109 * @param MTlp pointer to an #MTlp_t structure. 00110 * */ 00111 void MTlp_clear(MTlp_t*const MTlp); 00112 /* ========================================================================= */ 00113 /** @brief Given an LP problem pointer, load it into an 00114 * (initialized) #MTlp_t structure. 00115 * @param lp pointer to an #MTlp_t structure. 00116 * @param CPXlp pointer to a CPLEX LP problem 00117 * @param env as returned by CPXopenCPLEX function. 00118 * @param cbdata A pointer passed from the optimization routine to the 00119 * user-written callback that identifies the problem being optimized. The only 00120 * purpose of this pointer is to pass it to the callback information routines. 00121 * @param wherefrom An integer value indicating where in the optimization this 00122 * function was called. It has the value CPX_CALLBACK_MIP_CUT. 00123 * @return zero on success. 00124 * */ 00125 int MTlp_load_problem(CPXCENVptr env, 00126 MTlp_t*const lp, 00127 CPXLPptr CPXlp, 00128 void*cbdata, 00129 int wherefrom); 00130 /* ========================================================================= */ 00131 /** @brief Initialize an #MTrowmatrix_t structure too an empty matrix 00132 * @param __mt matrix to initialize */ 00133 #define MTrowmatrix_init(__mt) memset((__mt),0,sizeof(MTrowmatrix_t)) 00134 /* ========================================================================= */ 00135 /** @brief resize a #MTrowmatrix_t structure 00136 * @param MTrm rowmatrix to resize 00137 * @param MTrsz new row-space (it will only grow). 00138 * @param MTnsz new non-zero space (it will only grow). 00139 * */ 00140 void MTrowmatrix_rsz(MTrowmatrix_t*const MTrm, 00141 const int MTrsz, 00142 const int MTnsz); 00143 /* ========================================================================= */ 00144 /** @brief free any internally allocated memory inside an #MTrowmatrix_t 00145 * structure. 00146 * @param MTrm rowmatrix to clear */ 00147 void MTrowmatrix_clear(MTrowmatrix_t*const MTrm); 00148 /* ========================================================================= */ 00149 /** @brief initialize a #MTsol_t structure */ 00150 #define MTsol_init(__sol) memset(__sol,0,sizeof(MTsol_t)) 00151 /* ========================================================================= */ 00152 /** @brief resize a solution structure 00153 * @param MTsol solution to resize 00154 * @param cnz new column space 00155 * @param rnz new row space 00156 * */ 00157 void MTsol_rsz( MTsol_t*const MTsol, 00158 const int cnz, 00159 const int rnz); 00160 /* ========================================================================= */ 00161 /** @brief clear any internal memory asociated with an #MTsol_t structure 00162 * @param MTsol structure to clear */ 00163 void MTsol_clear(MTsol_t*const MTsol); 00164 /* ========================================================================= */ 00165 /** @name #MTccbk_info_t set/get functions */ 00166 /*@{*/ 00167 #define MTcbkiSetCutsAtRoot(__cbki,__val) ((__cbki)->root_only=(__val)) 00168 #define MTcbkiSetCuts(__cbki,__val) ((__cbki)->use_cuts=(__val)) 00169 #define MTcbkiSetMaxRows(__cbki,__val) ((__cbki)->max_rows=(__val)) 00170 #define MTcbkiSetMaxNodeCuts(__cbki,__val) ((__cbki)->max_cuts=(size_t)(__val)) 00171 #define MTcbkiSetMaxRoundCuts(__cbki,__val) ((__cbki)->max_cpr=(__val)) 00172 #define MTcbkiSetCutStyle(__cbki,__val) ((__cbki)->cut_style=(__val)) 00173 /*@}*/ 00174 /* ========================================================================= */ 00175 /** @brief initialize an #MTccbk_info_t structure */ 00176 #define MTccbk_info_init(__cbinf) memset(__cbinf,0,sizeof(MTccbk_info_t)) 00177 /* ========================================================================= */ 00178 /** @brief display callback info */ 00179 void MTccbk_info_display(const MTccbk_info_t*const info,FILE*out); 00180 /* ========================================================================= */ 00181 /** @brief test if we should proceed with the cuting process, and update 00182 * information 00183 * @param info calllback info to use. 00184 * @param env as returned by CPXopenCPLEX function. 00185 * @param cbdata A pointer passed from the optimization routine to the 00186 * user-written callback that identifies the problem being optimized. The only 00187 * purpose of this pointer is to pass it to the callback information routines. 00188 * @param wherefrom An integer value indicating where in the optimization this 00189 * function was called. It has the value CPX_CALLBACK_MIP_CUT. 00190 * @param action pointer to an integer where we return action, zero to 00191 * continue cutting, non-zero to stop. 00192 * @return zero on succsess, non-zero otherwise. */ 00193 int MTccbk_info_process(MTccbk_info_t*const info, 00194 CPXCENVptr env, 00195 void*cbdata, 00196 int wherefrom, 00197 int*const action); 00198 /* ========================================================================= */ 00199 /** @name Profiling information for the cuts */ 00200 /*@{*/ 00201 /* @brief number of tableau rows discarded because they have a small ratio 00202 * between minabs and maxabs, thus possible inducing bad numericall issues */ 00203 extern int MTccbk_fail_tableau_ratio; 00204 /** @brief Number of discarded cuts because tableaus has wrong number 00205 * of basic variables. */ 00206 extern int MTccbk_fail_tableau_nbasic; 00207 /** @brief Number of discarded cuts because tableaus has wrong coefficient for 00208 * basic variable. */ 00209 extern int MTccbk_fail_tableau_coeff; 00210 /** @brief Number of discarded cuts because fraction is too small. */ 00211 extern int MTccbk_fail_tableau_frac; 00212 /** @brief Type of basic variable for tableau is not integer */ 00213 extern int MTccbk_fail_tableau_btype; 00214 /** @brief Number of discarded cuts because high ratio */ 00215 extern int MTccbk_fail_ratio; 00216 /** @brief minimum ratio of discarded inequality */ 00217 extern double MTccbk_discarded_ratio; 00218 /** @brief Number of discarded cuts because low violation */ 00219 extern int MTccbk_fail_violation; 00220 /** @brief maximum violation of discarded inequality */ 00221 extern double MTccbk_discarded_violation; 00222 /** @brief display summary information for the call-back calls 00223 * @param __fout where to write the sumary */ 00224 #define MTccbk_display_sumary(__fout) do{\ 00225 fprintf(__fout,"MTccbk sumary:\n");\ 00226 fprintf(__fout,"\tDiscarded tableau rows: %4d (coeff %d, nbasic %d,"\ 00227 " ratio %d, type %d, fraction %d)\n", MTccbk_fail_tableau_nbasic + \ 00228 MTccbk_fail_tableau_coeff + MTccbk_fail_tableau_ratio + \ 00229 MTccbk_fail_tableau_btype + MTccbk_fail_tableau_frac,\ 00230 MTccbk_fail_tableau_coeff, MTccbk_fail_tableau_nbasic, \ 00231 MTccbk_fail_tableau_ratio, MTccbk_fail_tableau_btype, \ 00232 MTccbk_fail_tableau_frac);\ 00233 fprintf(__fout,"\tDiscarded by ratio: %4d (next %.5lg)\n",\ 00234 MTccbk_fail_ratio, MTccbk_discarded_ratio);\ 00235 fprintf(__fout,"\tDiscarded by violation: %4d (next %.5lg)\n",\ 00236 MTccbk_fail_violation, MTccbk_discarded_violation);\ 00237 }while(0) 00238 /*@}*/ 00239 /* ========================================================================= */ 00240 /** @name #MTgomory_ccbk_t set/get functions */ 00241 /*@{*/ 00242 #define MTccbkSetCutDominance(__cbdata,__val) MTcutHeapSetDominance((&((__cbdata)->cuth)),__val) 00243 #define MTccbkSetCutSel(__cbdata,__val) MTcutHeapSetCS((&((__cbdata)->cuth)),__val) 00244 #define MTccbkSetCutsAtRoot(__cbdata,__val) MTcbkiSetCutsAtRoot((&((__cbdata)->info)),__val) 00245 #define MTccbkSetCuts(__cbdata,__val) MTcbkiSetCuts((&((__cbdata)->info)),__val) 00246 #define MTccbkSetCutStyle(__cbdata,__val) MTcbkiSetCutStyle((&((__cbdata)->info)),__val) 00247 #define MTccbkSetMaxRows(__cbdata,__val) MTcbkiSetMaxRows((&((__cbdata)->info)),__val) 00248 #define MTccbkSetMaxNodeCuts(__cbdata,__val) MTcbkiSetMaxNodeCuts((&((__cbdata)->info)),__val) 00249 #define MTccbkSetMaxRoundCuts(__cbdata,__val) do{\ 00250 MTgomory_ccbk_t*const __MTcbdata = (__cbdata);\ 00251 MTcbkiSetMaxRoundCuts((&(__MTcbdata->info)),__val);\ 00252 MTcutHeapClear(&(__MTcbdata->cuth));\ 00253 MTcutHeapInit(&(__MTcbdata->cuth),((size_t)(__MTcbdata->info.max_cpr)));}while(0) 00254 /*@}*/ 00255 /* ========================================================================= */ 00256 /** @brief initialize an #MTgomory_ccbk_t structure. 00257 * @param __cbdata pointer to an #MTgomory_ccbk_t structure. 00258 * */ 00259 #define MTgomory_ccbk_init(__cbdata) do{\ 00260 MTgomory_ccbk_t*const __MTcbdata = (__cbdata);\ 00261 memset((__MTcbdata),0,sizeof(MTgomory_ccbk_t));\ 00262 MTccbk_info_init(&(__MTcbdata->info));\ 00263 MTsol_init(&(__MTcbdata->sol));\ 00264 MTcut_init(&(__MTcbdata->cut));\ 00265 MTrowmatrix_init(&(__MTcbdata->tb));\ 00266 MTcutHeapInit(&(__MTcbdata->cuth),((size_t)(__MTcbdata->info.max_cpr)));\ 00267 MTlp_init(&(__MTcbdata->lp));}while(0) 00268 /* ========================================================================= */ 00269 /** @brief if required (i.e. __nrowsz > nrowsz || __ncolsz > colsz || 00270 * __ntbsz > tbsz) , resize an #MTgomory_ccbk_t structure 00271 * @param __cbdata pointer to an #MTgomory_ccbk_t structure. 00272 * @param __nrowsz new row-size for the structure. 00273 * @param __ncolsz new col-size for the structure. 00274 * @param __ntbsz new tableau-size for the structure. 00275 * @note When we resize the structure, all previous contents are lost. 00276 * */ 00277 #define MTgomory_ccbk_rsz(__cbdata,__nrowsz,__ncolsz,__ntbsz) do{\ 00278 MTgomory_ccbk_t*const __ccbk = (__cbdata);\ 00279 const int __ccbk_rsz = (__nrowsz);\ 00280 const int __ccbk_csz = (__ncolsz);\ 00281 const int __ccbk_tsz = (__ntbsz);\ 00282 MTrowmatrix_rsz(&(__ccbk->tb),__ccbk_rsz,__ccbk_tsz);\ 00283 MTsol_rsz(&(__ccbk->sol),__ccbk_csz,__ccbk_rsz);\ 00284 MTcut_rsz(&(__ccbk->cut),__ccbk_csz);\ 00285 if(__ccbk->colsz < __ccbk_csz){\ 00286 __ccbk->colsz = __ccbk_csz;\ 00287 EGfree(__ccbk->work);\ 00288 EGfree(__ccbk->extcut);\ 00289 __ccbk->work = EGsMalloc(double,(__ccbk_csz+1));\ 00290 __ccbk->extcut = EGsMalloc(double,__ccbk_csz);}\ 00291 if(__ccbk->rowsz < __ccbk_rsz){\ 00292 __ccbk->rowsz = __ccbk_rsz;\ 00293 EGfree(__ccbk->base);\ 00294 EGfree(__ccbk->f);\ 00295 __ccbk->base = EGsMalloc(double,__ccbk_rsz);\ 00296 __ccbk->f = EGsMalloc(double,__ccbk_rsz);}\ 00297 }while(0) 00298 /* ========================================================================= */ 00299 /** @brief free any internally allocated memory inside an #MTgomory_ccbk_t 00300 * structure. 00301 * @param __cbdata pointer to an #MTgomory_ccbk_t structure. 00302 * */ 00303 #define MTgomory_ccbk_clear(__cbdata) do{\ 00304 MTgomory_ccbk_t*const __ccbk = (__cbdata);\ 00305 EGfree(__ccbk->work);\ 00306 EGfree(__ccbk->extcut);\ 00307 EGfree(__ccbk->base);\ 00308 EGfree(__ccbk->f);\ 00309 __ccbk->rowsz = __ccbk->colsz = 0;\ 00310 MTsol_clear(&(__ccbk->sol));\ 00311 MTcut_clear(&(__ccbk->cut));\ 00312 MTrowmatrix_clear(&(__ccbk->tb));\ 00313 MTcutHeapClear(&(__ccbk->cuth));\ 00314 MTlp_clear(&(__ccbk->lp));}while(0) 00315 /* ========================================================================= */ 00316 /** @brief Interface for the CPLEX-callback for the #MTgomoryCut function. 00317 * @param env as returned by CPXopenCPLEX function. 00318 * @param cbdata A pointer passed from the optimization routine to the 00319 * user-written callback that identifies the problem being optimized. The only 00320 * purpose of this pointer is to pass it to the callback information routines. 00321 * @param wherefrom An integer value indicating where in the optimization this 00322 * function was called. It has the value CPX_CALLBACK_MIP_CUT. 00323 * @param cbhandle A pointer to user private data. 00324 * @param useraction_p A pointer to an integer indicating the action for ILOG 00325 * CPLEX to take at the completion 00326 * of the user callback. The table summarizes possible actions. 00327 * - 0 CPX_CALLBACK_DEFAULT Use cuts as added 00328 * - 1 CPX_CALLBACK_FAIL Exit optimization 00329 * - 2 CPX_CALLBACK_SET Use cuts as added 00330 * */ 00331 int MTgomory_ccbk(CPXCENVptr env, 00332 void*cbdata, 00333 int wherefrom, 00334 void*cbhandle, 00335 int*useraction_p); 00336 /* ========================================================================= */ 00337 /** @brief read optionfile and set parameter to CPLEX 00338 * @param env pointer to the CPLEX environment structure. 00339 * @param inputfile pointer to the optionfile.*/ 00340 int MTread_cplex_options(CPXENVptr env, FILE * inputfile); 00341 /* ========================================================================= */ 00342 /** @brief given an LP desvription, and CPLEX binvrow, compute the 00343 * actual tableau (including logicals, which are in position i+ncols of 00344 * the tableau for the i-th logical/slack variable, but we force that 00345 * the coefficient of equality logicals is zero) 00346 * @param lp pointer to an #MTlp_t structure. 00347 * @param binvrow as returned by cplex (length = lp->nrows); 00348 * @param tableau where to write the tableau (length lp->nrows + 00349 * lp->ncols). 00350 * @return zero on success, non-zero otherwise 00351 * */ 00352 int MTcplex_binv_to_tableau(const MTlp_t*const lp, 00353 const double*const binvrow, 00354 double*const tableau); 00355 /* ========================================================================= */ 00356 /** @brief test if a given cut is valid to the given cplex LP 00357 * @param cut cut to be tested 00358 * @param lp pointer to the asociated #MTlp_t structure. 00359 * @return zero on success, non-zero otherwise. 00360 * */ 00361 int MTcplex_test_cut( const MTcut_t*const cut, 00362 const MTlp_t*const lp); 00363 /* ========================================================================= */ 00364 /** @brief compute ax = f for a tableau 00365 * @param lp pointer to an #MTlp_t structure. 00366 * @param tableau where to write the tableau (length lp->nrows + 00367 * @param x structural variables values 00368 * @param slack logical variables values 00369 * @param f where to store ax = f 00370 * */ 00371 void MTcompute_f(const MTlp_t*const lp, 00372 const double*const tableau, 00373 const double*const x, 00374 const double*const slack, 00375 double*const f); 00376 /* ========================================================================= */ 00377 /** @brief display an LP to the given file 00378 * @param lp pointer to an #MTlp_t structure 00379 * @param sol asociated solution to the LP 00380 * @param stream file where to write the LP 00381 * */ 00382 void MTdisplay_lp(const MTlp_t*const lp, 00383 const MTsol_t*const sol, 00384 FILE*stream); 00385 /* ========================================================================= */ 00386 /** @brief get the indices of fractional (structural) variables 00387 * @param lp pointer to an #MTlp_t structure 00388 * @param x current LP x-value 00389 * @param fracvars array of length (at least) #MTlp_t::nrows 00390 * @param nfrac pointer to an integer where the number of fractional variables 00391 * is returned. 00392 * @param minitgap minimum distance to closest integer for a variable to be 00393 * considered fractional 00394 * @return zero on success, non-zero otherwise 00395 * */ 00396 int MTcompute_fractional_vars(const MTlp_t*const lp, 00397 const double*const x, 00398 int*const fracvars, 00399 int*const nfrac, 00400 const double minitgap); 00401 /* ========================================================================= */ 00402 /** @brief get the indices of (almost) integer variables 00403 * @param lp pointer to an #MTlp_t structure 00404 * @param x current LP x-value 00405 * @param intvars array of length (at least) #MTlp_t::nrows 00406 * @param nint pointer to an integer where the number of fractional variables 00407 * is returned. 00408 * @param intgap integrality gap allowd for a variable to be considered integer 00409 * @return zero on success, non-zero otherwise 00410 * */ 00411 int MTcompute_integer_vars(const MTlp_t*const lp, 00412 const double*const x, 00413 int*const intvars, 00414 int*const nint, 00415 const double intgap); 00416 /* ========================================================================= */ 00417 /** @brief Get the best K tableau (asociated to fractional variables), note 00418 * that we check for wrongly computed tableau. 00419 * Note that we compute Z = f + 0.5+Ax, where A is the tableau and f the 00420 * fractional value (displaced by 1/2), moreover, all basic variables have zero 00421 * coefficient in the resulting tableau, and all variables are complemented to 00422 * their bounds. 00423 * @param lp pointer to an #MTlp_t structure 00424 * @param sol asociated node solution 00425 * @patam tb pointer to an #MTrowmap_t structure 00426 * @param f fractional value for each tableau. 00427 * @param max_tableau maximum number of tableaus to consider. 00428 * used to select the set of best fractional tableau rows. 00429 * @param env Cplex environment pointer. 00430 * @param CPXlp cplex lp pointer. 00431 * @return zero on success, non-zero otherwise. 00432 * */ 00433 int MTget_best_k_tableau_rows(const MTlp_t*const lp, 00434 const MTsol_t*const sol, 00435 const int max_tableau, 00436 CPXCENVptr env, 00437 CPXLPptr CPXlp, 00438 MTrowmatrix_t*const tb, 00439 double*const f); 00440 /* ========================================================================= */ 00441 /** @brief Get the best K tableau (asociated to integer basic variables), note 00442 * that we check for wrongly computed tableau. 00443 * Note that we compute Z = f + 0.5+Ax, where A is the tableau and f the 00444 * fractional value (displaced by 1/2), moreover, all basic variables have zero 00445 * coefficient in the resulting tableau, and all variables are complemented to 00446 * their bounds. 00447 * @param lp pointer to an #MTlp_t structure 00448 * @param sol asociated node solution 00449 * @patam tb pointer to an #MTrowmap_t structure 00450 * @param f fractional value for each tableau. 00451 * @param max_tableau maximum number of tableaus to consider. 00452 * used to select the set of best integer tableau rows. 00453 * @param env Cplex environment pointer. 00454 * @param CPXlp cplex lp pointer. 00455 * @return zero on success, non-zero otherwise. 00456 * */ 00457 int MTget_best_k_integer_tableau_rows(const MTlp_t*const lp, 00458 const MTsol_t*const sol, 00459 const int max_tableau, 00460 CPXCENVptr env, 00461 CPXLPptr CPXlp, 00462 MTrowmatrix_t*const tb, 00463 double*const f); 00464 /* ========================================================================= */ 00465 /** @brief transform an uncomplemented cut to a complemented form. 00466 * Note that we expect no coefficient for basic variables in the cut. 00467 * @param cut pointer to an #MTcut_t structure, we will complement the cut. 00468 * @param sol asociated node solution 00469 * @param lp pointer to the related #MTlp_t structure 00470 * @return zero on success, non-zero otherwise. 00471 * */ 00472 int MTuncomplemented_to_complemented_cut( const MTlp_t*const lp, 00473 const MTsol_t*const sol, 00474 MTcut_t*const cut); 00475 /* ========================================================================= */ 00476 /** @brief transform an extened non-complemented cut to a compresed and 00477 * complemented form. We assume the extended cut is of the form ax >= 1. 00478 * Note that we expect no coefficient for basic variables in the cut, moreover, 00479 * the rhs of the inequality is assumed to be 1 (in raw format). 00480 * @note The parameter extended WILL CHANGE ITS CONTENTS 00481 * @param cut pointer to an #MTcut_t structure, we will store the compresed cut 00482 * here. 00483 * @param sol asociated node solution 00484 * @param extended extended cut (length #MTlp_t::nrows + #MTlp_t::ncols), note 00485 * that this informnation will be modified, and will contain the complemented 00486 * cut in extended form. 00487 * @param lp pointer to the related #MTlp_t structure 00488 * @return zero on success, non-zero otherwise. 00489 * */ 00490 int MTraw_to_complemented_cut( 00491 const MTlp_t*const lp, 00492 const MTsol_t*const sol, 00493 double*const extended, 00494 MTcut_t*const cut); 00495 /* ========================================================================= */ 00496 /** @brief transform an extened non-complemented cut to a compresed for. We 00497 * assume the extended cut is of the form ax >= 1.m 00498 * Note that we expect no coefficient for basic variables in the cut. 00499 * @note The parameter extended WILL NOT CHANGE ITS CONTENTS 00500 * @param cut pointer to an #MTcut_t structure, we will store the compresed cut 00501 * here. 00502 * @param extended extended cut (length #MTlp_t::nrows + #MTlp_t::ncols), note 00503 * that this informnation will be modified, and will contain the complemented 00504 * cut in extended form. 00505 * @param nactive length of array active 00506 * @param active if not null, it should store the positions of possibly active 00507 * positions in extended; all positions outside it are assumed to be zero. 00508 * @param lp pointer to the related #MTlp_t structure 00509 * @param status if status is zero, the cut should be stored, otherwise, it 00510 * should be discarded. 00511 * @return zero on success, non-zero otherwise. 00512 * */ 00513 int MTraw_to_uncomplemented_cut( 00514 const MTlp_t*const lp, 00515 const double*const extended, 00516 const int nactive, 00517 const int*const active, 00518 MTcut_t*const cut, 00519 int*const status); 00520 /* ========================================================================= */ 00521 /** @brief obtain a solution to the current node LP 00522 * @param lp pointer to an #MTlp_t structure 00523 * @param env Cplex environment pointer. 00524 * @param CPXlp cplex lp pointer. 00525 * @param sol where to store the solution 00526 * @param CPLEX callback cbdata. 00527 * @param wherefrom CPLEX callback wherefrom parameter. 00528 * @return zero on success, non-zero otherwise 00529 * */ 00530 int MTget_sol(const MTlp_t*const lp, 00531 CPXCENVptr env, 00532 CPXLPptr CPXlp, 00533 void*cbdata, 00534 int wherefrom, 00535 MTsol_t*const sol); 00536 /* ========================================================================= */ 00537 /** @biref if we have CPLEX 11 or later, we use sense as 'g' instead of 'G', 00538 * because, in theory, it enables cutpool management, we will see */ 00539 #if CPX_VERSION >= 1100 00540 #define MT_CPLEX_SENSE 'g' 00541 #else 00542 #define MT_CPLEX_SENSE 'G' 00543 #endif 00544 /* ========================================================================= */ 00545 /** @brief initialize an #MTns_ccbk_t structure */ 00546 #define MTns_ccbk_init(__ns_ccbk) do{\ 00547 MTns_ccbk_t*const __MTns_ccbk = (__ns_ccbk);\ 00548 memset(__MTns_ccbk,0,sizeof(MTns_ccbk_t));}while(0) 00549 /* ========================================================================= */ 00550 /** @brief resize node-solve arrays */ 00551 #define MTns_ccbk_rsz(__ns_ccbk,__ncsz,__nrsz) do{\ 00552 MTns_ccbk_t*const __MTns_ccbk = (__ns_ccbk);\ 00553 const size_t __MTns_ncsz = (size_t)(__ncsz);\ 00554 const size_t __MTns_nrsz = (size_t)(__nrsz);\ 00555 if( __MTns_ccbk->rsz < __MTns_nrsz){\ 00556 __MTns_ccbk->rsz = __MTns_nrsz;\ 00557 __MTns_ccbk->rfix = EGrealloc(__MTns_ccbk->rfix,sizeof(char)*__MTns_nrsz);\ 00558 __MTns_ccbk->rstat = EGrealloc(__MTns_ccbk->rstat,sizeof(int)*__MTns_nrsz);\ 00559 __MTns_ccbk->sense = EGrealloc(__MTns_ccbk->sense,sizeof(char)*__MTns_nrsz);\ 00560 __MTns_ccbk->pi = EGrealloc(__MTns_ccbk->pi,sizeof(double)*__MTns_nrsz);}\ 00561 if( __MTns_ccbk->csz < __MTns_ncsz){\ 00562 __MTns_ccbk->csz = __MTns_ncsz;\ 00563 __MTns_ccbk->oobj = EGrealloc(__MTns_ccbk->oobj,sizeof(double)*__MTns_ncsz);\ 00564 __MTns_ccbk->lb = EGrealloc(__MTns_ccbk->lb,sizeof(double)*__MTns_ncsz);\ 00565 __MTns_ccbk->ub = EGrealloc(__MTns_ccbk->ub,sizeof(double)*__MTns_ncsz);\ 00566 __MTns_ccbk->x0 = EGrealloc(__MTns_ccbk->x0,sizeof(double)*__MTns_ncsz);\ 00567 __MTns_ccbk->x1 = EGrealloc(__MTns_ccbk->x1,sizeof(double)*__MTns_ncsz);\ 00568 __MTns_ccbk->cfix = EGrealloc(__MTns_ccbk->cfix,sizeof(char)*__MTns_ncsz);\ 00569 __MTns_ccbk->cstat = EGrealloc(__MTns_ccbk->cstat,sizeof(int)*__MTns_ncsz);\ 00570 __MTns_ccbk->matind = EGrealloc(__MTns_ccbk->matind,sizeof(int)*__MTns_ncsz);\ 00571 __MTns_ccbk->matval = EGrealloc(__MTns_ccbk->matval,sizeof(double)*__MTns_ncsz);\ 00572 __MTns_ccbk->dj = EGrealloc(__MTns_ccbk->dj,sizeof(double)*__MTns_ncsz);\ 00573 }\ 00574 }while(0) 00575 /* ========================================================================= */ 00576 /** @brief clear any internally allocated memory within an #MTns_ccbk_t 00577 * structure. */ 00578 #define MTns_ccbk_clear(__ns_ccbk) do{\ 00579 MTns_ccbk_t*const __MTns_ccbk = (__ns_ccbk);\ 00580 EGfree(__MTns_ccbk->rfix);\ 00581 EGfree(__MTns_ccbk->pi);\ 00582 EGfree(__MTns_ccbk->cfix);\ 00583 EGfree(__MTns_ccbk->dj);\ 00584 EGfree(__MTns_ccbk->rstat);\ 00585 EGfree(__MTns_ccbk->sense);\ 00586 EGfree(__MTns_ccbk->oobj);\ 00587 EGfree(__MTns_ccbk->lb);\ 00588 EGfree(__MTns_ccbk->ub);\ 00589 EGfree(__MTns_ccbk->x1);\ 00590 EGfree(__MTns_ccbk->x0);\ 00591 EGfree(__MTns_ccbk->matind);\ 00592 EGfree(__MTns_ccbk->matval);\ 00593 EGfree(__MTns_ccbk->cstat);}while(0) 00594 /* ========================================================================= */ 00595 /** @brief Display stats in the given #MTns_ccbk_t structure */ 00596 #define MTns_ccbk_display(__ns_ccbk) do{\ 00597 const MTns_ccbk_t*const __MTns = (__ns_ccbk);\ 00598 const double __MTd = ((double)(__MTns->nzrd))/((double)__MTns->ncalls);\ 00599 const double __MTd2 = ((double)(__MTns->loops))/((double)__MTns->ncalls);\ 00600 fprintf(stderr,"\tAverage solution difference %.7le in %zd calls\n",__MTns->xdiff/((double)__MTns->ncalls),__MTns->ncalls);\ 00601 fprintf(stderr,"\tAverage Primal degenerancy %.4lf in %zd calls\n",__MTd,__MTns->ncalls);\ 00602 fprintf(stderr,"\tAverage Reoptimization steps %.4lf in %zd calls\n",__MTd2,__MTns->ncalls);}while(0) 00603 /* ========================================================================= */ 00604 /** @brief simple node solve callback, we use it to count primal degenerancy, 00605 * i.e. the number of variables with zero reduced cost, this should indicate 00606 * posibility of doing nested objective funcions to avoid primal degenerancy */ 00607 int MTnode_solve( CPXCENVptr env, 00608 void*cbdata, 00609 int wherefrom, 00610 void*cbhandle, 00611 int*useraction_p); 00612 /* ========================================================================= */ 00613 /** @brief given a tableau in extended notation, verify that it is indeed a 00614 * numerically stable and correct tableau. 00615 * @param tableau table to check 00616 * @param lp Internal LP description 00617 * @param status on return zero fi everything is OK, non-zero otherwise. 00618 * @param ratio if status==0, store the ratio for the tableau. 00619 * @param etnz if status == 0, store the number of non-zeros in the tableau 00620 * @return 0 on success, non-zero otherwise 00621 * */ 00622 int MTcheckTabrow( 00623 const MTlp_t*const lp, 00624 const double*tableau, 00625 int*const status, 00626 double*const ratio, 00627 int*const etnz); 00628 /* ========================================================================= */ 00629 /** @brief given a tableau row in extended format, store it as a compresed form, it include setting row to row - integer_part[row] and updating the rhs. 00630 * @param lp internal LP description, 00631 * @param sol current optimal solution. 00632 * @param rowval on input extended row description, on output, non-zeros 00633 * coefficients 00634 * @param rowind array of length ncols where we will store the indices of 00635 * non-zero coefficients in the row 00636 * @param nz on output, non-zeros found 00637 * @return zero on success, non-zero otherwise */ 00638 int MTcompressTabRow( 00639 const MTlp_t*const lp, 00640 const MTsol_t*const sol, 00641 double*rowval, 00642 int*rowind, 00643 double*const rhs, 00644 int*const nz); 00645 /* ========================================================================= */ 00646 /** @} */ 00647 /* end of mt_cplex_cbk.h */ 00648 #endif