42 #define HEUR_NAME "relaxcolsel"
43 #define HEUR_DESC "column selection heuristic that tries to round a master LP solution in promising directions"
44 #define HEUR_DISPCHAR 'x'
45 #define HEUR_PRIORITY -100
47 #define HEUR_FREQOFS 0
48 #define HEUR_MAXDEPTH -1
49 #define HEUR_TIMING SCIP_HEURTIMING_AFTERLPNODE
50 #define HEUR_USESSUBSCIP FALSE
52 #define DEFAULT_MINCOLUMNS 200
98 SCIP_VAR** mastervars;
99 SCIP_Real* mastervals;
109 assert(origprob != NULL);
112 SCIP_CALL( SCIPgetVarsData(scip, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
113 assert(nmastervars >= 0);
117 assert( nblocks >= 0 );
120 SCIP_CALL( SCIPallocBufferArray(scip, &mastervals, nmastervars) );
121 SCIP_CALL( SCIPgetSolVals(scip, NULL, nmastervars, mastervars, mastervals) );
127 for( i = 0; i < nmastervars && *success; ++i )
130 SCIP_VARTYPE vartype;
140 mastervar = mastervars[i];
142 vartype = SCIPvarGetType(mastervar);
145 solval = mastervals[i];
146 roundval = SCIPfeasFloor(scip, solval);
147 frac = SCIPfeasFrac(scip, solval);
165 if( SCIPisFeasPositive(scip, roundval) )
167 SCIPdebugMessage(
" -> (block %d) select ray master variable %s (%d times)\n",
168 block, SCIPvarGetName(mastervar), (
int) roundval);
171 SCIP_CALL( SCIPsetSolVal(scip, mastersol, mastervar, roundval) );
174 for( j = 0; j < norigvars; ++j )
180 origvar = origvars[j];
181 origval = origvals[j];
184 if( SCIPisZero(scip, origval) )
187 assert(!SCIPisZero(scip, origval));
194 SCIP_CALL( SCIPincSolVal(scip, origsol, origvar, origval * roundval) );
198 if( !SCIPisFeasFracIntegral(scip, frac) )
200 mastercands[*nmastercands] = i;
201 candfracs[*nmastercands] = frac;
218 assert(norigvars == 1);
219 origvar = origvars[0];
221 assert(origvals[0] == 1.0);
223 assert(origblock == -2 || origblock == -1);
227 if( origblock == -2 )
232 if( (vartype == SCIP_VARTYPE_BINARY || vartype == SCIP_VARTYPE_INTEGER )
233 && !SCIPisFeasFracIntegral(scip, frac) )
235 SCIP_CALL( SCIPsetSolVal(scip, mastersol, mastervar, roundval) );
236 SCIP_CALL( SCIPsetSolVal(origprob, origsol, origvar, roundval) );
237 mastercands[*nmastercands] = i;
238 candfracs[*nmastercands] = frac;
243 SCIP_CALL( SCIPsetSolVal(scip, mastersol, mastervar, solval) );
244 SCIP_CALL( SCIPsetSolVal(origprob, origsol, origvar, solval) );
251 if( !SCIPisFeasZero(scip, roundval) )
254 SCIP_CALL( SCIPsetSolVal(scip, mastersol, mastervar, roundval) );
256 SCIPdebugMessage(
" -> (block %d) select master variable %s (%d times)\n",
257 block, SCIPvarGetName(mastervar), (
int) roundval);
259 for( j = 0; j < norigvars; ++j )
265 origvar = origvars[j];
266 origval = origvals[j];
270 if( SCIPisZero(scip, origval) )
278 SCIP_VAR** linkingpricingvars;
284 for( k = 0; k < nblocks; ++k )
285 if( linkingpricingvars[k] != NULL )
296 SCIP_VAR* linkingmastervar;
299 assert(linkingmastervar != NULL);
300 SCIP_CALL( SCIPsetSolVal(origprob, origsol, origvar, origval) );
301 SCIP_CALL( SCIPsetSolVal(scip, mastersol, linkingmastervar, origval) );
307 value = SCIPgetSolVal(origprob, origsol, origvar);
308 if( !SCIPisEQ(origprob, value, origval) )
310 SCIPdebugMessage(
" -> cannot use mastervar: origvar %s already has value %g in block %d, different to %g\n",
311 SCIPvarGetName(origvar), value, j, origval);
319 SCIP_VAR* pricingvar;
320 SCIP_VAR** origpricingvars;
322 int norigpricingvars;
329 assert(pricingvar != NULL);
339 for( k = 0; k < (int) roundval; ++k )
342 blockidx = blocknr[block] + k;
344 assert(blockidx < norigpricingvars);
346 SCIP_CALL( SCIPincSolVal(origprob, origsol, origpricingvars[blockidx], origval) );
352 blocknr[block] += (int) roundval;
356 if( !SCIPisFeasFracIntegral(scip, frac) )
358 mastercands[*nmastercands] = i;
359 candfracs[*nmastercands] = frac;
365 SCIPfreeBufferArray(scip, &mastervals);
376 SCIP_VAR** zeromastervar
379 SCIP_VAR** mastervars;
386 SCIP_CALL( SCIPgetVarsData(scip, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
388 *zeromastervar = NULL;
391 for( i = 0; i < nmastervars && *zeromastervar == NULL; ++i )
396 mastervar = mastervars[i];
409 for( j = 0; j < norigvars; ++j )
410 if( !SCIPisZero(scip, origvals[j]) )
415 *zeromastervar = mastervar;
427 SCIP_HEURDATA* heurdata,
429 SCIP_VAR** zeromastervar
434 if( heurdata->zerovars[block] == NULL )
437 *zeromastervar = heurdata->zerovars[block];
450 #define heurCopyRelaxcolsel NULL
456 SCIP_HEURDATA* heurdata;
458 assert(heur != NULL);
459 assert(scip != NULL);
462 heurdata = SCIPheurGetData(heur);
463 assert(heurdata != NULL);
466 SCIPfreeMemory(scip, &heurdata);
467 SCIPheurSetData(heur, NULL);
478 SCIP_HEURDATA* heurdata;
483 assert(heur != NULL);
484 assert(scip != NULL);
488 assert(origprob != NULL);
491 heurdata = SCIPheurGetData(heur);
492 assert(heurdata != NULL);
497 heurdata->lastncols = 0;
502 heurdata->maxzerovars = SCIPcalcMemGrowSize(scip, nblocks);
503 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->zerovars, heurdata->maxzerovars) );
506 for( i = 0; i < nblocks; ++i )
507 heurdata->zerovars[i] = NULL;
517 SCIP_HEURDATA* heurdata;
519 assert(heur != NULL);
520 assert(scip != NULL);
523 heurdata = SCIPheurGetData(heur);
524 assert(heurdata != NULL);
527 SCIPfreeBlockMemoryArrayNull(scip, &heurdata->zerovars, heurdata->maxzerovars);
534 #define heurInitsolRelaxcolsel NULL
538 #define heurExitsolRelaxcolsel NULL
546 SCIP_HEURDATA* heurdata;
549 SCIP_VAR** mastervars;
550 SCIP_Real* candfracs;
553 SCIP_Bool allblocksfull;
554 SCIP_Bool masterfeas;
565 assert(heur != NULL);
566 assert(scip != NULL);
567 assert(result != NULL);
571 assert(origprob != NULL);
574 heurdata = SCIPheurGetData(heur);
575 assert(heurdata != NULL);
577 *result = SCIP_DELAYED;
580 if( SCIPgetStage(scip) > SCIP_STAGE_SOLVING || SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
583 assert(SCIPhasCurrentNodeLP(scip));
586 SCIP_CALL( SCIPgetVarsData(scip, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
587 assert(mastervars != NULL);
588 assert(nmastervars >= 0);
592 minnewcols = heurdata->mincolumns * (int) (1.0 * ((1.0 + SCIPheurGetNCalls(heur)) / (1.0 + SCIPheurGetNBestSolsFound(heur))));
595 if( nmastervars - heurdata->lastncols < minnewcols )
598 *result = SCIP_DIDNOTFIND;
600 SCIPdebugMessage(
"Executing Relaxation Based Column Selection heuristic (nmastervars = %d) ...\n", nmastervars);
604 assert(nblocks >= 0);
607 SCIP_CALL( SCIPcreateSol(scip, &mastersol, heur) );
608 SCIP_CALL( SCIPcreateSol(origprob, &origsol, heur) );
609 SCIP_CALL( SCIPallocBufferArray(scip, &blocknr, nblocks) );
610 SCIP_CALL( SCIPallocBufferArray(scip, &mastercands, nmastervars) );
611 SCIP_CALL( SCIPallocBufferArray(scip, &candfracs, nmastervars) );
614 BMSclearMemoryArray(blocknr, nblocks);
615 BMSclearMemoryArray(candfracs, nmastervars);
616 allblocksfull = FALSE;
619 for( i = 0; i < nmastervars; ++i )
624 SCIPdebugMessage(
"initializing starting solution...\n");
626 mastercands, candfracs, &nmastercands, &success) );
630 SCIPdebugMessage(
" -> not successful.\n");
637 SCIPdebugMessage(
"trying to round up...\n");
640 while( !allblocksfull && !success )
645 SCIP_Bool compatible;
658 for( i = 0; i < nmastercands; ++i )
663 idx = mastercands[i];
664 tmpfrac = candfracs[i];
665 if( idx != -1 && SCIPisFeasGT(scip, tmpfrac, frac) )
669 tmpvar = mastervars[idx];
686 assert(mastervar == NULL);
691 assert(candidx >= 0 && candidx < nmastercands);
692 mastercands[candidx] = -1;
693 candfracs[candidx] = 0.0;
695 assert(mastervar != NULL);
698 SCIPdebugMessage(
" -> (block %d) selected master variable %s; frac=%g\n",
699 block, SCIPvarGetName(mastervar), frac);
707 SCIP_CALL( SCIPincSolVal(scip, mastersol, mastervar, 1.0) );
721 assert(norigvars == 1);
722 origvar = origvars[0];
724 assert(origvals[0] == 1.0);
727 assert(origblock == -1);
731 SCIP_CALL( SCIPincSolVal(origprob, origsol, origvar, 1.0) );
737 for( i = 0; i < norigvars; ++i )
742 origvar = origvars[i];
743 origval = origvals[i];
752 SCIP_VAR** linkingpricingvars;
758 for( j = 0; j < nblocks; ++j )
759 if( linkingpricingvars[j] != NULL )
770 SCIP_VAR* linkingmastervar;
773 assert(linkingmastervar != NULL);
774 SCIP_CALL( SCIPincSolVal(origprob, origsol, origvar, origval) );
775 SCIP_CALL( SCIPincSolVal(scip, mastersol, linkingmastervar, origval) );
781 value = SCIPgetSolVal(origprob, origsol, origvar);
782 if( !SCIPisEQ(origprob, value, origval) )
784 SCIPdebugMessage(
" -> cannot use mastervar: origvar %s already has value %g in block %d, different to %g\n",
785 SCIPvarGetName(origvar), value, j, origval);
793 SCIP_VAR* pricingvar;
794 SCIP_VAR** origpricingvars;
796 int norigpricingvars;
800 if( SCIPisZero(scip, origval) )
804 assert(pricingvar != NULL);
811 assert(blocknr[block] < norigpricingvars);
815 SCIP_CALL( SCIPincSolVal(origprob, origsol, origpricingvars[blocknr[block]], origval) );
823 SCIP_CALL( SCIPincSolVal(scip, mastersol, mastervar, -1.0) );
824 for( k = 0; k < i; ++k )
829 origvar = origvars[k];
830 origval = origvals[k];
834 SCIP_VAR** linkingpricingvars;
840 for( j = 0; j < nblocks; ++j )
841 if( linkingpricingvars[j] != NULL )
842 if( blocknr[j] > 0 && j != block )
851 SCIP_VAR* linkingmastervar;
854 SCIP_CALL( SCIPincSolVal(origprob, origsol, origvar, -origval) );
855 SCIP_CALL( SCIPincSolVal(scip, mastersol, linkingmastervar, -origval) );
860 SCIP_VAR* pricingvar;
861 SCIP_VAR** origpricingvars;
863 int norigpricingvars;
867 assert(pricingvar != NULL);
874 assert(blocknr[block] < norigpricingvars);
878 SCIP_CALL( SCIPincSolVal(origprob, origsol, origpricingvars[blocknr[block]], -origval) );
888 SCIP_CALL( SCIPtrySol(origprob, origsol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
891 allblocksfull = TRUE;
892 for( i = 0; i < nblocks && allblocksfull; ++i )
901 if( success && blocknr[i] < nidentblocks )
903 SCIP_VAR* zeromastervar;
906 zeromastervar = NULL;
908 if( zeromastervar != NULL )
910 SCIPdebugMessage(
" -> (block %d) selected zero master variable %s (%d times)\n",
911 i, SCIPvarGetName(zeromastervar), nidentblocks - blocknr[i]);
913 SCIP_CALL( SCIPincSolVal(scip, mastersol, zeromastervar,
914 (SCIP_Real) nidentblocks - blocknr[i]) );
915 blocknr[i] = nidentblocks;
920 if( !(blocknr[i] >= nidentblocks) )
921 allblocksfull = FALSE;
926 if( success && allblocksfull )
929 SCIP_CALL( SCIPtrySol(scip, mastersol, TRUE, TRUE, TRUE, TRUE, TRUE, &masterfeas) );
931 SCIP_CALL( SCIPtrySol(scip, mastersol, FALSE, FALSE, TRUE, TRUE, TRUE, &masterfeas) );
935 SCIPdebugMessage(
"WARNING: original solution feasible, but no solution has been added to master problem.\n");
942 *result = SCIP_FOUNDSOL;
943 SCIPdebugMessage(
" -> heuristic successful - feasible solution found.\n");
947 SCIPdebugMessage(
" -> no feasible solution found.\n");
951 SCIP_CALL( SCIPfreeSol(origprob, &origsol) );
952 SCIP_CALL( SCIPfreeSol(scip, &mastersol) );
953 SCIPfreeBufferArray(scip, &candfracs);
954 SCIPfreeBufferArray(scip, &mastercands);
955 SCIPfreeBufferArray(scip, &blocknr);
957 heurdata->lastncols = nmastervars;
974 SCIP_HEURDATA* heurdata;
977 SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
978 heurdata->zerovars = NULL;
979 heurdata->maxzerovars = 0;
989 SCIP_CALL( SCIPaddIntParam(scip,
"heuristics/relaxcolsel/mincolumns",
990 "minimum number of columns to regard in the master problem",