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_cutpool.h"
00025
00026
00027
00028
00029
00030 void MTcutHeapInit(MTcutHeap_t*const cuth,size_t sz)
00031 {
00032 register int i;
00033 MTcutHeapCn_t*chcn;
00034 memset(cuth,0,sizeof(MTcutHeap_t));
00035 i = ((int)(cuth->all_sz = sz+1));
00036 dbl_EGeHeapInit(&(cuth->heap));
00037 dbl_EGeHeapChangeD(&(cuth->heap),2);
00038 dbl_EGeHeapResize(&(cuth->heap),cuth->all_sz);
00039 cuth->all_cn = EGsMalloc(MTcutHeapCn_t,cuth->all_sz);
00040 EGeListInit(&(cuth->free_cn));
00041 for( ; i-- ; ){
00042 MTcutHeapCnInit(cuth->all_cn+i);
00043 EGeListAddAfter(&(cuth->all_cn[i].lcn),&(cuth->free_cn));
00044 }
00045 chcn = EGcontainerOf(cuth->free_cn.next,MTcutHeapCn_t,lcn);
00046 cuth->next_free = &(chcn->cut);
00047 EGeListDel(cuth->free_cn.next);
00048 cuth->control.cut_score = MTcsDefault;
00049 return;
00050 }
00051
00052 void MTcutHeapClear(MTcutHeap_t*const cuth)
00053 {
00054 register int i = (int)(cuth->all_sz);
00055 dbl_EGeHeapResize(&(cuth->heap),0);
00056 dbl_EGeHeapClear(&(cuth->heap));
00057 for(;i--;) MTcutHeapCnClear(cuth->all_cn+i);
00058 EGfree(cuth->all_cn);
00059 memset(cuth,0,sizeof(MTcutHeap_t));
00060 return;
00061 }
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 static int MTcutHeapCn_compute_val( MTcutHeap_t*const cuth,
00072 MTcutHeapCn_t*const chcn)
00073 {
00074 register int i;
00075 double val = 0;
00076 int rval = 0;
00077 switch(cuth->control.cut_score)
00078 {
00079 case MTcsRAW:
00080 chcn->hcn.val = chcn->cut.score;
00081 break;
00082 case MTcsVIOL:
00083 chcn->hcn.val = chcn->cut.violation;
00084 break;
00085 case MTcsINVLINF:
00086 switch(chcn->cut.sense)
00087 {
00088 case 'L':
00089 case 'l':
00090 chcn->hcn.val = -chcn->cut.rhs/chcn->cut.max_abs;
00091 break;
00092 case 'G':
00093 case 'g':
00094 chcn->hcn.val = chcn->cut.rhs/chcn->cut.max_abs;
00095 break;
00096 default:
00097 FTESTG((rval=1),CLEANUP,"unexpected sense %c",chcn->cut.sense);
00098 break;
00099 }
00100 break;
00101 case MTcsINVL2:
00102 for( i = chcn->cut.nz ; i-- ; )
00103 val += chcn->cut.cutval[i]*chcn->cut.cutval[i];
00104 switch(chcn->cut.sense)
00105 {
00106 case 'L':
00107 case 'l':
00108 chcn->hcn.val = -chcn->cut.rhs*chcn->cut.rhs/val;
00109 break;
00110 case 'G':
00111 case 'g':
00112 chcn->hcn.val = chcn->cut.rhs*chcn->cut.rhs/val;
00113 break;
00114 default:
00115 FTESTG((rval=1),CLEANUP,"unexpected sense %c",chcn->cut.sense);
00116 break;
00117 }
00118 break;
00119 default:
00120 FTESTG((rval=1), CLEANUP, "Unknown function selection criteria %d",
00121 cuth->control.cut_score);
00122 break;
00123 }
00124 CLEANUP:
00125 return rval;
00126 }
00127
00128
00129 void MTintPermSort( const int sz,
00130 int*const perm,
00131 const int*const elem)
00132 {
00133 int i, j, temp;
00134 int t;
00135 if (sz <= 1)
00136 return;
00137
00138 EGswap (perm[0], perm[(sz - 1) / 2], temp);
00139 i = 0;
00140 j = sz;
00141 t = elem[perm[0]];
00142 for (;;)
00143 {
00144 do
00145 i++;
00146 while (i < sz && (elem[perm[i]] < t));
00147 do
00148 j--;
00149 while (t < elem[perm[j]]);
00150 if (j < i)
00151 break;
00152 EGswap (perm[i], perm[j], temp);
00153 }
00154 EGswap (perm[0], perm[j], temp);
00155 MTintPermSort (j, perm, elem);
00156 MTintPermSort (sz - i, perm + i, elem);
00157 }
00158
00159
00160 static int* MTcut1_nz = 0;
00161 static int* MTcut2_nz = 0;
00162 void MTcutNzAlloc(void) __attribute__ ((constructor));
00163 void MTcutNzAlloc(void)
00164 {
00165 MTcut1_nz = int_EGlpNumAllocArray(100);
00166 MTcut2_nz = int_EGlpNumAllocArray(100);
00167 }
00168 void MTcutNzFree(void) __attribute__ ((destructor));
00169 void MTcutNzFree(void)
00170 {
00171 int_EGlpNumFreeArray(MTcut1_nz);
00172 int_EGlpNumFreeArray(MTcut2_nz);
00173 }
00174
00175
00176 #define __MT_DOM do{\
00177 if(v2 + MT_ZERO_TOL < v1) \
00178 {\
00179 if(domset && dom != -1) return 0;\
00180 domset=1;\
00181 dom=-1;\
00182 equal = 0; \
00183 }\
00184 else if( v1 + MT_ZERO_TOL < v2)\
00185 {\
00186 if(domset && dom != 1) return 0;\
00187 domset=1;\
00188 dom=1;\
00189 equal = 0;\
00190 }\
00191 }while(0)
00192
00193 int MTcut_check_dominance(const MTcut_t*const cut1, const MTcut_t*const cut2)
00194 {
00195
00196 const size_t c1nz = ((size_t)(cut1->nz));
00197 const size_t c2nz = ((size_t)(cut2->nz));
00198 const int sense1 = (cut1->sense == 'l' || cut1->sense == 'L') ? -1 : 1;
00199 const int sense2 = (cut2->sense == 'l' || cut2->sense == 'L') ? -1 : 1;
00200 int dom=0,domset=0,equal=1,p1,p2,c1,c2;
00201 register int i,j;
00202 double v1,v2;
00203
00204 if( cut1->sense == 'e' || cut1->sense == 'E' ||
00205 cut2->sense == 'e' || cut2->sense == 'E') return 0;
00206
00207 if(__EGlpNumArraySize(MTcut1_nz) < c1nz)
00208 MTcut1_nz = int_EGlpNumReallocArray( &MTcut1_nz, c1nz);
00209 if(__EGlpNumArraySize(MTcut2_nz) < c2nz)
00210 MTcut2_nz = int_EGlpNumReallocArray( &MTcut2_nz, c2nz);
00211
00212 for( i = cut1->nz ; i-- ; ) MTcut1_nz[i] = i;
00213 for( i = cut2->nz ; i-- ; ) MTcut2_nz[i] = i;
00214 MTintPermSort(cut1->nz, MTcut1_nz, cut1->cutind);
00215 MTintPermSort(cut2->nz, MTcut2_nz, cut2->cutind);
00216
00217 v1 = -1*sense1*cut1->rhs;
00218 v2 = -1*sense2*cut2->rhs;
00219 __MT_DOM;
00220
00221 i = j = 0;
00222 while( i < cut1->nz || j < cut2->nz)
00223 {
00224
00225 if( i < cut1->nz)
00226 {
00227 p1 = MTcut1_nz[i];
00228 c1 = cut1->cutind[p1];
00229 v1 = sense1*cut1->cutval[p1];
00230 }
00231 else
00232 {
00233 p1 = INT_MAX;
00234 c1 = INT_MAX;
00235 v1 = 0.0;
00236 }
00237 if( j < cut2->nz)
00238 {
00239 p2 = MTcut2_nz[j];
00240 c2 = cut2->cutind[p2];
00241 v2 = sense2*cut2->cutval[p2];
00242 }
00243 else
00244 {
00245 c2 = INT_MAX;
00246 p2 = INT_MAX;
00247 v2 = 0.0;
00248 }
00249 if(c1 < c2)
00250 {
00251 v2 = 0.0;
00252 j--;
00253 }
00254 else if(c1 > c2)
00255 {
00256 v1 = 0.0;
00257 i--;
00258 }
00259 i++;
00260 j++;
00261
00262 __MT_DOM;
00263 }
00264
00265 if(equal) dom=-1;
00266 return dom;
00267 }
00268
00269 void MTcut_copy(MTcut_t*const dest,const MTcut_t*const src)
00270 {
00271 register int i = src->nz;
00272 dest->rhs = src->rhs;
00273 dest->violation = src->violation;
00274 dest->min_abs = src->min_abs;
00275 dest->max_abs = src->max_abs;
00276 dest->nz = src->nz;
00277 dest->sense = src->sense;
00278 dest->form = src->form;
00279 if(dest->nzspace < dest->nz)
00280 MTcut_rsz(dest,dest->nz);
00281 while(i--)
00282 {
00283 dest->cutind[i] = src->cutind[i];
00284 dest->cutval[i] = src->cutval[i];
00285 }
00286 }
00287
00288 int MTcutHeap_add_cut(const MTlp_t*const lp, MTcutHeap_t*const cuth)
00289 {
00290 int rval = 0;
00291 register int i = ((int)(cuth->heap.sz));
00292 MTcutHeapCn_t*chcn = EGcontainerOf(cuth->next_free,MTcutHeapCn_t,cut);
00293 dbl_EGeHeapCn_t*ccn;
00294 MTcut_t *cut1 = &(chcn->cut),*cut2;
00295
00296 rval = MTcutHeapCn_compute_val(cuth,chcn);
00297 CHECKRVALG(rval, CLEANUP);
00298
00299 if(cuth->control.dominance_check)
00300 {
00301 for( ;i--;)
00302 {
00303 cut2 = &((EGcontainerOf(cuth->heap.cn[i], MTcutHeapCn_t,hcn))->cut);
00304 rval = MTcut_check_dominance(cut1,cut2);
00305 switch(rval)
00306 {
00307 case -1:
00308 MESSAGE(MT_VERB_LVL, "incomming cut is dominated, "
00309 "score 1 %lf scrore 2 %lf",chcn->hcn.val,
00310 cuth->heap.cn[i]->val);
00311 rval = 0;
00312 goto CLEANUP;
00313 break;
00314 case 0:
00315 break;
00316 case 1:
00317 MTcut_copy(cut2,cut1);
00318 dbl_EGeHeapChangeVal(&(cuth->heap),cuth->heap.cn[i],chcn->hcn.val);
00319 MESSAGE(MT_VERB_LVL, "incomming cut dominate, "
00320 "score 1 %lf scrore 2 %lf",chcn->hcn.val,
00321 cuth->heap.cn[i]->val);
00322 rval = 0;
00323 goto CLEANUP;
00324 break;
00325 }
00326 rval = 0;
00327 }
00328 }
00329
00330 rval = dbl_EGeHeapAdd(&(cuth->heap),&(chcn->hcn));
00331 CHECKRVALG(rval, CLEANUP);
00332 MESSAGE(MT_VERB_LVL, "Adding cut %p with score %lf",(void*)(&(chcn->cut)),
00333 chcn->hcn.val);
00334
00335 if(EGeListIsEmpty(&(cuth->free_cn)))
00336 {
00337 ccn = dbl_EGeHeapGetMin(&(cuth->heap));
00338 TESTG((rval = !ccn),CLEANUP,"Unexpected NULL pointer");
00339 dbl_EGeHeapDel(&(cuth->heap),ccn);
00340 chcn = EGcontainerOf(ccn,MTcutHeapCn_t,hcn);
00341 MESSAGE(MT_VERB_LVL, "Removing cut %p with score %lf",(void*)(&(chcn->cut)),
00342 ccn->val);
00343 EGeListAddAfter(&(chcn->lcn),&(cuth->free_cn));
00344 if((MT_VERB_LVL+3 <= DEBUG) && (&(chcn->cut) != cut1))
00345 {
00346 fprintf(stderr,"Adding new MTcut (compress+complemented): ");
00347 MTcplex_display_compress_tableau(stderr,lp,cut1->cutval, cut1->cutind, cut1->nz);
00348 fprintf(stderr,">=1\n");
00349 }
00350 }
00351 else if(MT_VERB_LVL+3 <= DEBUG)
00352 {
00353 fprintf(stderr,"Adding new MTcut (compress+complemented): ");
00354 MTcplex_display_compress_tableau(stderr,lp,cut1->cutval, cut1->cutind, cut1->nz);
00355 fprintf(stderr,">=1\n");
00356 }
00357 chcn = EGcontainerOf(cuth->free_cn.next,MTcutHeapCn_t,lcn);
00358 cuth->next_free = &(chcn->cut);
00359 EGeListDel(cuth->free_cn.next);
00360 CLEANUP:
00361 return rval;
00362 }
00363
00364 MTcut_t* MTcutHeap_pop_cut(MTcutHeap_t*const cuth)
00365 {
00366 MTcutHeapCn_t*chcn=0;
00367 MTcut_t* cut=0;
00368 dbl_EGeHeapCn_t*ccn=0;
00369 ccn = dbl_EGeHeapGetMin(&(cuth->heap));
00370 if(ccn)
00371 {
00372 chcn = EGcontainerOf(ccn,MTcutHeapCn_t,hcn);
00373 cut = &(chcn->cut);
00374 dbl_EGeHeapDel(&(cuth->heap),ccn);
00375 EGeListAddAfter(&(chcn->lcn),&(cuth->free_cn));
00376 }
00377 return cut;
00378 }
00379
00380 void MTcut_rsz(MTcut_t*const MTcut,
00381 const int MTnsz)
00382 {
00383 if(MTcut->nzspace < MTnsz)
00384 {
00385 MTcut->nzspace = MTnsz;
00386 MTcut->cutind = EGrealloc(MTcut->cutind, sizeof(int)*((size_t)MTnsz));
00387 MTcut->cutval = EGrealloc(MTcut->cutval, sizeof(double)*((size_t)MTnsz));
00388 }
00389 return;
00390 }
00391
00392 void MTcut_clear(MTcut_t*const MTcut)
00393 {
00394 EGfree(MTcut->cutval);
00395 EGfree(MTcut->cutind);
00396 memset(MTcut,0,sizeof(MTcut_t));
00397 return;
00398 }
00399
00400
00401
00402
00403