Scippy

GCG

Branch-and-Price & Column Generation for Everyone

dec_neighborhoodmaster.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program */
4 /* GCG --- Generic Column Generation */
5 /* a Dantzig-Wolfe decomposition based extension */
6 /* of the branch-cut-and-price framework */
7 /* SCIP --- Solving Constraint Integer Programs */
8 /* */
9 /* Copyright (C) 2010-2021 Operations Research, RWTH Aachen University */
10 /* Zuse Institute Berlin (ZIB) */
11 /* */
12 /* This program is free software; you can redistribute it and/or */
13 /* modify it under the terms of the GNU Lesser General Public License */
14 /* as published by the Free Software Foundation; either version 3 */
15 /* of the License, or (at your option) any later version. */
16 /* */
17 /* This program is distributed in the hope that it will be useful, */
18 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
19 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
20 /* GNU Lesser General Public License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with this program; if not, write to the Free Software */
24 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
25 /* */
26 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
27 
28 /**@file dec_neighborhoodmaster.cpp
29  * @ingroup DETECTORS
30  * @brief detector neighborhoodmaster (This detector calculates cons-cons adjacency (if not already done), sorts constraints according size of neighborhood. Searching two consecutive constraints with largest size difference (according neighborhood size) in sorted constraints. All constraints having a larger neighborhood than the second one are assigned to the master)
31  * @author Michael Bastubbe
32  */
33 
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35 
36 #include "dec_neighborhoodmaster.h"
37 #include "cons_decomp.h"
38 #include "class_partialdecomp.h"
39 #include "class_detprobdata.h"
40 #include "gcg.h"
41 #include "scip/cons_setppc.h"
42 #include "scip/scip.h"
43 #include "scip_misc.h"
44 #include "scip/clock.h"
45 
46 #include <sstream>
47 
48 #include <iostream>
49 #include <algorithm>
50 
51 /**
52 This detector calculates cons-cons adjacency (if not already done), and sorts constraints according size of neighborhood. Searching two consecutive constraints with largest size difference (according neighborhood size) in sorted constraints. All constraints having a larger neighborhood than the second one are assigned to the master
53 */
54 
55 /* constraint handler properties */
56 #define DEC_DETECTORNAME "neighborhoodmaster" /**< name of detector */
57 #define DEC_DESC "detector neighborhoodmaster" /**< description of detector*/
58 #define DEC_FREQCALLROUND 1 /** frequency the detector gets called in detection loop ,ie it is called in round r if and only if minCallRound <= r <= maxCallRound AND (r - minCallRound) mod freqCallRound == 0 */
59 #define DEC_MAXCALLROUND 0 /** last round the detector gets called */
60 #define DEC_MINCALLROUND 0 /** first round the detector gets called */
61 #define DEC_FREQCALLROUNDORIGINAL 1 /** frequency the detector gets called in detection loop while detecting the original problem */
62 #define DEC_MAXCALLROUNDORIGINAL INT_MAX /** last round the detector gets called while detecting the original problem */
63 #define DEC_MINCALLROUNDORIGINAL 0 /** first round the detector gets called while detecting the original problem */
64 #define DEC_PRIORITY 0 /**< priority of the constraint handler for separation */
65 #define DEC_DECCHAR 'n' /**< display character of detector */
66 #define DEC_ENABLED TRUE /**< should the detection be enabled */
67 #define DEC_ENABLEDFINISHING FALSE /**< should the detection be enabled */
68 #define DEC_ENABLEDPOSTPROCESSING FALSE /**< should the postprocessing be enabled */
69 #define DEC_SKIP FALSE /**< should detector be skipped if other detectors found decompositions */
70 #define DEC_USEFULRECALL FALSE /**< is it useful to call this detector on a descendant of the propagated partialdec */
71 
72 #define DEFAULT_MAXRATIO 0.2
73 
74 /*
75  * Data structures
76  */
77 
78 /** detector handler data */
79 struct DEC_DetectorData
80 {
81  SCIP_Real maxratio;
82 };
83 
84 /*
85  * Local methods
86  */
87 
88 struct sort_pred {
89  bool operator()(const std::pair<int,int> &left, const std::pair<int,int> &right) {
90  return left.first > right.first;
91  }
92 };
93 
94 /* put your local methods here, and declare them static */
95 
96 /*
97  * detector callback methods
98  */
99 
100 /** destructor of detector to free user data (called when GCG is exiting) */
101 DEC_DECL_FREEDETECTOR(freeNeighborhoodmaster)
102 { /*lint --e{715}*/
103 
104  DEC_DETECTORDATA *detectordata;
105 
106  assert(scip != NULL);
107  assert(detector != NULL);
108 
109  assert(strcmp(DECdetectorGetName(detector), DEC_DETECTORNAME) == 0);
110 
111  detectordata = DECdetectorGetData(detector);
112  assert(detectordata != NULL);
113 
114  SCIPfreeMemory(scip, &detectordata);
115 
116  return SCIP_OKAY;
117 }
118 
119 /** destructor of detector to free detector data (called before the solving process begins) */
120 #define exitNeighborhoodmaster NULL
121 
122 /** detection initialization function of detector (called before solving is about to begin) */
123 #define initNeighborhoodmaster NULL
124 
125 #define finishPartialdecNeighborhoodmaster NULL
126 
127 static DEC_DECL_PROPAGATEPARTIALDEC(propagatePartialdecNeighborhoodmaster)
128 {
129  *result = SCIP_DIDNOTFIND;
130  char decinfo[SCIP_MAXSTRLEN];
131  SCIP_CLOCK* temporaryClock;
132  gcg::DETPROBDATA* detprobdata;
133  gcg::PARTIALDECOMP* partialdec;
134  DEC_DetectorData* detectorData = DECdetectorGetData(detector);
135  std::stringstream decdesc;
136  int maxdiff = -1;
137  int maxdiffindex = -1;
138  int lastindex = -1;
139 
140  detprobdata = partialdecdetectiondata->detprobdata;
141  partialdec = partialdecdetectiondata->workonpartialdec;
142 
143  if ( !detprobdata->isConssAdjInitialized() )
144  detprobdata->createConssAdjacency();
145 
146  SCIP_CALL_ABORT( SCIPcreateClock(scip, &temporaryClock) );
147  SCIP_CALL_ABORT( SCIPstartClock(scip, temporaryClock) );
148 
149  lastindex = (int) (detectorData->maxratio * partialdec->getNOpenconss());
150 
151  /** fix open conss that have a) type of the current subset or b) decomp info ONLY_MASTER as master conss */
152  std::vector<std::pair<int,int>> neighborhoodsize;
153  neighborhoodsize.reserve(partialdec->getNOpenconss());
154  for( int opencons : partialdec->getOpenconssVec() )
155  {
156  neighborhoodsize.emplace_back(std::pair<int,int>(detprobdata->getNConssForCons(opencons), opencons));
157  }
158 
159  std::sort(neighborhoodsize.begin(), neighborhoodsize.end(), sort_pred() );
160 
161  for( int i = 0; i < lastindex && i < (int) neighborhoodsize.size() - 1; ++i )
162  {
163  if( maxdiff < neighborhoodsize[i].first - neighborhoodsize[i+1].first )
164  {
165  maxdiff = neighborhoodsize[i].first - neighborhoodsize[i+1].first;
166  maxdiffindex = i;
167  }
168  }
169 
170  for( int i = 0; i <= maxdiffindex; ++i )
171  {
172  partialdec->fixConsToMaster(neighborhoodsize[i].second);
173  }
174 
175  decdesc << "neighborhoodmaster" << "\\_" << maxdiffindex ;
176 
177  partialdec->sort();
178  (void) SCIPsnprintf(decinfo, SCIP_MAXSTRLEN, decdesc.str().c_str());
179  partialdec->addDetectorChainInfo(decinfo);
180 
181  SCIP_CALL_ABORT( SCIPstopClock(scip, temporaryClock ) );
182 
183  partialdecdetectiondata->detectiontime = SCIPgetClockTime(scip, temporaryClock);
184 
185  SCIP_CALL( SCIPallocMemoryArray(scip, &(partialdecdetectiondata->newpartialdecs), 1) );
186  partialdecdetectiondata->nnewpartialdecs = 1;
187  partialdecdetectiondata->newpartialdecs[0] = partialdec;
188  partialdecdetectiondata->newpartialdecs[0]->addClockTime(SCIPgetClockTime(scip, temporaryClock));
189  // we used the provided partialdec -> prevent deletion
190  partialdecdetectiondata->workonpartialdec = NULL;
191 
192  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "dec_neighborhoodmaster found %d new partialdec \n", partialdecdetectiondata->nnewpartialdecs );
193 
194  SCIP_CALL_ABORT(SCIPfreeClock(scip, &temporaryClock) );
195 
196  *result = SCIP_SUCCESS;
197 
198  return SCIP_OKAY;
199 }
200 
201 #define detectorPostprocessPartialdecNeighborhoodmaster NULL
202 
203 static
204 DEC_DECL_SETPARAMAGGRESSIVE(setParamAggressiveNeighborhoodmaster)
205 {
206  char setstr[SCIP_MAXSTRLEN];
207  const char* name = DECdetectorGetName(detector);
208 
209  (void) SCIPsnprintf(setstr, SCIP_MAXSTRLEN, "detection/detectors/%s/enabled", name);
210  SCIP_CALL( SCIPsetBoolParam(scip, setstr, TRUE) );
211 
212  (void) SCIPsnprintf(setstr, SCIP_MAXSTRLEN, "detection/detectors/%s/finishingenabled", name);
213  SCIP_CALL( SCIPsetBoolParam(scip, setstr, FALSE ) );
214 
215  return SCIP_OKAY;
216 }
217 
218 
219 static
220 DEC_DECL_SETPARAMDEFAULT(setParamDefaultNeighborhoodmaster)
221 {
222  char setstr[SCIP_MAXSTRLEN];
223  const char* name = DECdetectorGetName(detector);
224 
225  (void) SCIPsnprintf(setstr, SCIP_MAXSTRLEN, "detection/detectors/%s/enabled", name);
226  SCIP_CALL( SCIPsetBoolParam(scip, setstr, DEC_ENABLED) );
227 
228  (void) SCIPsnprintf(setstr, SCIP_MAXSTRLEN, "detection/detectors/%s/finishingenabled", name);
229  SCIP_CALL( SCIPsetBoolParam(scip, setstr, DEC_ENABLEDFINISHING ) );
230 
231  return SCIP_OKAY;
232 }
233 
234 static
235 DEC_DECL_SETPARAMFAST(setParamFastNeighborhoodmaster)
236 {
237  char setstr[SCIP_MAXSTRLEN];
238  const char* name = DECdetectorGetName(detector);
239 
240  (void) SCIPsnprintf(setstr, SCIP_MAXSTRLEN, "detection/detectors/%s/enabled", name);
241  SCIP_CALL( SCIPsetBoolParam(scip, setstr, FALSE) );
242 
243  (void) SCIPsnprintf(setstr, SCIP_MAXSTRLEN, "detection/detectors/%s/finishingenabled", name);
244  SCIP_CALL( SCIPsetBoolParam(scip, setstr, FALSE ) );
245 
246  return SCIP_OKAY;
247 }
248 
249 
250 
251 /*
252  * detector specific interface methods
253  */
254 
255 /** creates the handler for neighborhoodmaster detector and includes it in SCIP */
256 SCIP_RETCODE SCIPincludeDetectorNeighborhoodmaster(SCIP* scip /**< SCIP data structure */
257 )
258 {
259  DEC_DETECTORDATA* detectordata;
260 
261  detectordata = NULL;
262 
263  SCIP_CALL( SCIPallocMemory(scip, &detectordata) );
264  assert(detectordata != NULL);
265 
266  SCIP_CALL(
270  detectordata, freeNeighborhoodmaster, initNeighborhoodmaster,
271  exitNeighborhoodmaster, propagatePartialdecNeighborhoodmaster, finishPartialdecNeighborhoodmaster,
272  detectorPostprocessPartialdecNeighborhoodmaster, setParamAggressiveNeighborhoodmaster,
273  setParamDefaultNeighborhoodmaster, setParamFastNeighborhoodmaster));
274 
275  SCIP_CALL( SCIPaddRealParam(scip, "detection/detectors/neighborhoodmaster/maxratio",
276  "the maximal ratio of open constraints that are assigned to the master problem",
277  &detectordata->maxratio, FALSE, DEFAULT_MAXRATIO, 0.0, 1.0, NULL, NULL ) );
278 
279  return SCIP_OKAY;
280 }
void addClockTime(SCIP_Real clocktime)
adds detection time of one detector
const char * DECdetectorGetName(DEC_DETECTOR *detector)
returns the name of the provided detector
#define DEC_DECCHAR
GCG interface methods.
#define DEFAULT_MAXRATIO
std::vector< int >::const_iterator fixConsToMaster(std::vector< int >::const_iterator itr)
fixes a constraint to the master constraints
void addDetectorChainInfo(const char *decinfo)
add information about the detector chain
#define DEC_MAXCALLROUNDORIGINAL
#define DEC_DESC
std::vector< int > & getOpenconssVec()
Gets a vector containing constraint ids not assigned yet as vector.
constraint handler for structure detection
#define DEC_DETECTORNAME
bool operator()(const std::pair< int, int > &left, const std::pair< int, int > &right)
#define DEC_ENABLED
#define exitNeighborhoodmaster
DEC_DECL_FREEDETECTOR(freeNeighborhoodmaster)
#define DEC_FREQCALLROUNDORIGINAL
#define DEC_USEFULRECALL
various SCIP helper methods
static DEC_DECL_SETPARAMFAST(setParamFastNeighborhoodmaster)
#define DEC_ENABLEDFINISHING
static DEC_DECL_SETPARAMDEFAULT(setParamDefaultNeighborhoodmaster)
#define detectorPostprocessPartialdecNeighborhoodmaster
static DEC_DECL_PROPAGATEPARTIALDEC(propagatePartialdecNeighborhoodmaster)
DEC_DETECTORDATA * DECdetectorGetData(DEC_DETECTOR *detector)
returns the data of the provided detector
bool sort()
sorts the vars and conss data structures by their indices
#define DEC_ENABLEDPOSTPROCESSING
#define finishPartialdecNeighborhoodmaster
int getNConssForCons(int consIndex)
returns the number of constraints for a given constraint
void createConssAdjacency()
create the constraint adjacency datastructure that is used (if created) for some methods to faster ac...
static DEC_DECL_SETPARAMAGGRESSIVE(setParamAggressiveNeighborhoodmaster)
class to manage partial decompositions
#define DEC_FREQCALLROUND
neighborhoodmaster detector
SCIP_RETCODE DECincludeDetector(SCIP *scip, const char *name, const char decchar, const char *description, int freqCallRound, int maxCallRound, int minCallRound, int freqCallRoundOriginal, int maxCallRoundOriginal, int minCallRoundOriginal, int priority, SCIP_Bool enabled, SCIP_Bool enabledFinishing, SCIP_Bool enabledPostprocessing, SCIP_Bool skip, SCIP_Bool usefulRecall, DEC_DETECTORDATA *detectordata, DEC_DECL_FREEDETECTOR((*freeDetector)), DEC_DECL_INITDETECTOR((*initDetector)), DEC_DECL_EXITDETECTOR((*exitDetector)), DEC_DECL_PROPAGATEPARTIALDEC((*propagatePartialdecDetector)), DEC_DECL_FINISHPARTIALDEC((*finishPartialdecDetector)), DEC_DECL_POSTPROCESSPARTIALDEC((*postprocessPartialdecDetector)), DEC_DECL_SETPARAMAGGRESSIVE((*setParamAggressiveDetector)), DEC_DECL_SETPARAMDEFAULT((*setParamDefaultDetector)),)
SCIP_Bool isConssAdjInitialized()
determines whether or not the constraint-constraint adjacency data structure is initilized
int getNOpenconss()
Gets size of vector containing constraints not assigned yet.
#define DEC_MINCALLROUND
#define initNeighborhoodmaster
class storing (potentially incomplete) decompositions
#define DEC_MINCALLROUNDORIGINAL
SCIP_RETCODE SCIPincludeDetectorNeighborhoodmaster(SCIP *scip)
#define DEC_MAXCALLROUND
class storing partialdecs and the problem matrix
#define DEC_PRIORITY
#define DEC_SKIP