00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "mt_T2.h"
00025
00026
00027
00028
00029
00030 int MTt2Cut(const MTrowmatrix_t*const tb,
00031 MTlp_t*const lp,
00032 MTcutHeap_t*const cuth,
00033 const double*const f,
00034 double*const cutval,
00035 double*const work,
00036 const int cut_style)
00037 {
00038 const int nrows = tb->nrows;
00039 const int ncols = tb->ncols;
00040 const double*const rowval = tb->rowval;
00041 const int*const rowind = tb->rowind;
00042 const int*const rowbeg = tb->rowbeg;
00043 int rval=0,pos,sense,redo,redo2, cur_tabrows = nrows;
00044 double* ineq_val = EGsMalloc(double,(ncols+1)*(nrows+1));
00045 double* ineq = 0;
00046 const int*order = 0;
00047 const int*sign = 0;
00048 int*active = EGsMalloc(int,ncols);
00049 int nactive = 0, status;
00050 MTcut_t*cut;
00051 register int i,j,k;
00052 EGgcIt_t gc;
00053 EGpermIt_t prit;
00054 double ratio = 0;
00055 #if MT_DEBUG_LVL +5 <= DEBUG
00056 FILE* fout = EGsfopen("cur_tableau.txt","w+");
00057 rval = MTwriteRTableau(fout, nrows, ncols, rowval, rowind, rowbeg, f);
00058 CHECKRVALG(rval,CLEANUP);
00059 fclose(fout);
00060 #endif
00061
00062 if(MT_DEBUG_LVL <= DEBUG)
00063 {
00064 for(i = nrows ; i-- ; )
00065 {
00066 TESTG((rval=(f[i]<=(-0x1p-1+MT_ZERO_TOL))), CLEANUP,
00067 "%d-th fractional value is outside bounds %lf <= %lf",
00068 i, f[i], (-0x1p-1+MT_ZERO_TOL));
00069 TESTG((rval=(f[i]>=(0x1p-1-MT_ZERO_TOL))), CLEANUP,
00070 "%d-th fractional value is outside bounds %lf >= %lf",
00071 i, f[i], (0x1p-1-MT_ZERO_TOL));
00072 }
00073 }
00074
00075 REDO:
00076 EGgcItInit(&gc,cur_tabrows);
00077 EGpermItInit(&prit,cur_tabrows);
00078 order = EGpermItGetTuple(&prit);
00079 sign = EGgcItGetTuple(&gc);
00080
00081 memset(active,0,sizeof(int)*((size_t)ncols));
00082 for( i = rowbeg[cur_tabrows] ; i-- ;)
00083 active[rowind[i]] = 1;
00084 for(nactive=0, i = 0 ; i < ncols ; i++)
00085 if(active[i]) active[nactive++] = i;
00086 MESSAGE(MT_VERB_LVL,"Active cols %.3lf%%",100*((double)nactive)/ncols);
00087
00088 do
00089 {
00090
00091 EGgcItReset(&gc);
00092 if(MT_DEBUG_LVL + 10 <= DEBUG)
00093 {
00094 fprintf(stderr,"\rUsing Order ");
00095 for( i = 0 ; i<cur_tabrows ; i++ ) fprintf(stderr,"%d ",order[i]);
00096 fprintf(stderr,"\n");
00097 }
00098
00099
00100
00101
00102 memset(ineq_val,0,sizeof(double)*((size_t)((ncols+1)*(cur_tabrows+1))));
00103
00104 for( k = cur_tabrows ; k-- ; )
00105 ineq_val[k*(ncols+1)+ncols] = 0.5*((double)(k+1));
00106 ineq_val[cur_tabrows*(ncols+1)+ncols] = 0.5*((double)cur_tabrows);
00107
00108 for( j = cur_tabrows ; j-- ; )
00109 {
00110 sense = sign[j] ? -1:1;
00111 k = order[j];
00112 ineq_val[k*(ncols+1)+ncols] += sense*f[j];
00113 for( k++ ; k <= cur_tabrows ; k++)
00114 ineq_val[k*(ncols+1)+ncols] -= sense*f[j];
00115 for( i = rowbeg[j] ; i < rowbeg[j+1] ; i++)
00116 {
00117 k = order[j];
00118 ineq_val[k*(ncols+1)+rowind[i]] -= sense*rowval[i];
00119 for(k++ ; k <= cur_tabrows ; k++)
00120 ineq_val[k*(ncols+1)+rowind[i]] += sense*rowval[i];
00121 }
00122 }
00123
00124
00125 do
00126 {
00127 if(MT_DEBUG_LVL + 10 <= DEBUG)
00128 {
00129 fprintf(stderr,"\tUsing orientation ");
00130 for( i = 0 ; i<cur_tabrows ; i++ ) fprintf(stderr,"%d ",sign[i]);
00131 fprintf(stderr,"\n");
00132 }
00133
00134
00135 memset(cutval,0,sizeof(double)*((size_t)ncols));
00136 for( k = cur_tabrows+1 ; k-- ; )
00137 {
00138 ineq = ineq_val+k*(ncols+1);
00139 TESTG((rval = (ineq[ncols]<0)), CLEANUP,
00140 "Imposible rhs_k - const[perm]_k*\\sigma*f < 0!");
00141 for( i = nactive ; i-- ; )
00142 {
00143 pos = active[i];
00144 if(ineq[pos] < MT_ZERO_TOL) continue;
00145 ratio = ineq[pos]/ineq[ncols];
00146 if(cutval[pos] < ratio) cutval[pos] = ratio;
00147 }
00148 }
00149
00150
00151 cut = MTcutHeap_get_free_cut(cuth);
00152 for( i = ncols ; i-- ; ) work[i] = cutval[i];
00153 rval = MTraw_to_uncomplemented_cut( lp, work, nactive, active, cut, &status);
00154 CHECKRVALG(rval,CLEANUP);
00155 if(status) goto NEXT;
00156
00157 rval = MTcutHeap_add_cut(lp,cuth);
00158 CHECKRVALG(rval,CLEANUP);
00159
00160 NEXT:
00161
00162 redo = EGgcItNext(&gc);
00163 if(!redo) break;
00164 pos = EGgcItGetChange(&gc);
00165 sense = sign[pos] ? -1:1;
00166
00167 k = order[pos];
00168 ineq_val[k*(ncols+1)+ncols] += 2*sense*f[pos];
00169 for( k++ ; k<= cur_tabrows ; k++)
00170 ineq_val[k*(ncols+1)+ncols] -= 2*sense*f[pos];
00171 for( i = rowbeg[pos]; i < rowbeg[pos+1] ; i++)
00172 {
00173 k = order[pos];
00174 ineq_val[k*(ncols+1)+rowind[i]] -= 2*sense*rowval[i];
00175 for(k++ ; k <= cur_tabrows ; k++)
00176 ineq_val[k*(ncols+1)+rowind[i]] += 2*sense*rowval[i];
00177 }
00178 } while(1);
00179
00180 redo2 = EGpermItNext(&prit);
00181 if(!redo2) break;
00182 } while(1);
00183 if(cut_style && cur_tabrows > 2)
00184 {
00185 EGgcItClear(&gc);
00186 EGpermItClear(&prit);
00187 cur_tabrows--;
00188 goto REDO;
00189 }
00190
00191 CLEANUP:
00192 EGgcItClear(&gc);
00193 EGpermItClear(&prit);
00194 EGfree(ineq_val);
00195 EGfree(active);
00196 return rval;
00197 }
00198
00199 int MTt2_ccbk(CPXCENVptr env,
00200 void*cbdata,
00201 int wherefrom,
00202 void*cbhandle,
00203 int*useraction_p)
00204 {
00205 MTgomory_ccbk_t*const data=(MTgomory_ccbk_t*)cbhandle;
00206 MTcutHeap_t*const cuth = &(data->cuth);
00207 MTcut_t*cut=0;
00208 int rval = 0, action = 0;
00209 CPXLPptr lp = 0;
00210 int ncols,nrows;
00211 size_t ncpr=0;
00212
00213 MESSAGE(MT_VERB_LVL,"Entering");
00214 *useraction_p = CPX_CALLBACK_DEFAULT;
00215
00216 rval = MTccbk_info_process(&(data->info), env, cbdata, wherefrom, &action);
00217 CHECKRVALG(rval,CLEANUP);
00218 if(action) goto CLEANUP;
00219
00220 rval = CPXgetcallbacknodelp (env, cbdata, wherefrom, &lp);
00221 MTcplexCHECKRVALG(env,rval,CLEANUP);
00222
00223 if(MT_VERB_LVL +5 <= DEBUG)
00224 {
00225 rval = CPXwriteprob(env,lp,"node_lp.lp.gz","LP");
00226 MTcplexCHECKRVALG(env,rval,CLEANUP);
00227 }
00228
00229 rval = MTlp_load_problem(env, &(data->lp), lp, cbdata, wherefrom);
00230 CHECKRVALG(rval,CLEANUP);
00231
00232 ncols = CPXgetnumcols(env,lp);
00233 nrows = CPXgetnumrows(env,lp);
00234 MESSAGE(MT_VERB_LVL+3,"Problem has %d vars and %d constr",ncols,nrows);
00235
00236 rval = EGmax(nrows,ncols);
00237 MTgomory_ccbk_rsz(data,nrows,ncols+nrows,rval);
00238
00239 rval = MTget_sol(&(data->lp), env, lp, cbdata, wherefrom, &(data->sol));
00240 CHECKRVALG(rval,CLEANUP);
00241
00242 if(MT_VERB_LVL + 10 <= DEBUG)
00243 MTdisplay_lp(&(data->lp), &(data->sol), stderr);
00244
00245 rval = MTget_best_k_tableau_rows( &(data->lp), &(data->sol),
00246 data->info.max_rows, env, lp,
00247 &(data->tb), data->f);
00248 CHECKRVALG(rval,CLEANUP);
00249 if(!data->tb.nrows) goto CLEANUP;
00250
00251 rval = MTt2Cut( &(data->tb), &(data->lp), cuth, data->f,
00252 data->extcut, data->work, data->info.cut_style);
00253 CHECKRVALG(rval,CLEANUP);
00254
00255 ncpr = MTcutHeap_get_ncuts(cuth);
00256 data->info.added_cuts += ncpr;
00257 data->info.node_cuts += ncpr;
00258
00259 while((cut=MTcutHeap_pop_cut(cuth)))
00260 {
00261 rval = MTuncomplemented_to_complemented_cut(&(data->lp), &(data->sol), cut);
00262 CHECKRVALG(rval,CLEANUP);
00263
00264 if(MT_DEBUG_LVL + 10 <= DEBUG)
00265 {
00266 rval = MTcplex_test_cut(cut, &(data->lp));
00267 if(rval)
00268 {
00269 fprintf(stderr,"Failing cut was:");
00270 MTcplex_display_compress_tableau( stderr, &(data->lp), cut->cutval,
00271 cut->cutind, cut->nz);
00272 fprintf(stderr," >= %.3lf, max_abs %lf, min_abs %lf\n",cut->rhs,
00273 cut->max_abs, cut->min_abs);
00274 }
00275 CHECKRVALG(rval,CLEANUP);
00276 fprintf(stderr,"Adding cut with raw score %.7lg",cut->score);
00277 fprintf(stderr," MTcut: ");
00278 MTcplex_display_compress_tableau(stderr, &(data->lp), cut->cutval, cut->cutind, cut->nz);
00279 fprintf(stderr," >= %.4lf\n", cut->rhs);
00280 }
00281 rval = CPXcutcallbackaddlocal( env, cbdata, wherefrom, cut->nz, cut->rhs,
00282 cut->sense , cut->cutind, cut->cutval);
00283 MTcplexCHECKRVALG(env,rval,CLEANUP);
00284 MESSAGE(MT_VERB_LVL, "Node %zd LP:(%d,%d,%d) Constr: %d nz, %.2lf rhs,"
00285 " ratio %.2lf, violation (>0) %lf", data->info.node_cnt,
00286 data->lp.nrows, data->lp.ncols, data->lp.nz, cut->nz, cut->rhs,
00287 cut->max_abs/cut->min_abs, cut->violation);
00288 }
00289 CLEANUP:
00290 MESSAGE(MT_VERB_LVL,"Done, status %d, added %zd cuts",rval,ncpr);
00291 return rval;
00292 }
00293
00294
00295