Scippy

GCG

Branch-and-Price & Column Generation for Everyone

event_bestsol.c
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 event_bestsol.c
29  * @brief eventhdlr to record the best primal bound for each heuristic
30  * @author Christian Puchert
31  */
32 
33 /*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
34 
35 #include <string.h>
36 #include "event_bestsol.h"
37 
38 #ifdef SCIP_STATISTIC
39 #define EVENTHDLR_NAME "bestsol"
40 #define EVENTHDLR_DESC "event handler to record the best primal bound for each heuristic"
41 
42 /*
43  * Data structures
44  */
45 
46 /** event handler data */
47 struct SCIP_EventhdlrData
48 {
49  SCIP_HEUR** heurs; /**< heuristics known to this event handler */
50  SCIP_Real* bestprimalbd; /**< array to store best primal bounds for each heuristic */
51 };
52 
53 /*
54  * Callback methods of event handler
55  */
56 
57 /** destructor of event handler to free user data (called when SCIP is exiting) */
58 static
59 SCIP_DECL_EVENTFREE(eventFreeBestsol)
60 { /*lint --e{715}*/
61  SCIP_EVENTHDLRDATA* eventhdlrdata;
62 
63  assert(scip != NULL);
64  assert(eventhdlr != NULL);
65 
66  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
67  assert(eventhdlrdata != NULL);
68 
69  SCIPfreeMemory(scip, &eventhdlrdata);
70 
71  return SCIP_OKAY;
72 }
73 
74 /** initialization method of event handler (called after problem was transformed) */
75 static
76 SCIP_DECL_EVENTINIT(eventInitBestsol)
77 { /*lint --e{715}*/
78  SCIP_EVENTHDLRDATA* eventhdlrdata;
79  int nheurs;
80  int i;
81 
82  assert(scip != NULL);
83  assert(eventhdlr != NULL);
84  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
85 
86  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
87  assert(eventhdlrdata != NULL);
88 
89  nheurs = SCIPgetNHeurs(scip);
90 
91  /* allocate memory */
92  SCIP_CALL( SCIPduplicateMemoryArray(scip, &eventhdlrdata->heurs, SCIPgetHeurs(scip), nheurs) );
93  SCIP_CALL( SCIPallocMemoryArray(scip, &eventhdlrdata->bestprimalbd, nheurs) );
94 
95  for( i = 0; i < nheurs; ++i )
96  eventhdlrdata->bestprimalbd[i] = SCIPinfinity(scip);
97 
98  /* notify SCIP that your event handler wants to react on the event types best solution found and node solved */
99  SCIP_CALL( SCIPcatchEvent(scip, SCIP_EVENTTYPE_SOLFOUND, eventhdlr, NULL, NULL) );
100 
101  return SCIP_OKAY;
102 }
103 
104 /** deinitialization method of event handler (called before transformed problem is freed) */
105 static
106 SCIP_DECL_EVENTEXIT(eventExitBestsol)
107 { /*lint --e{715}*/
108  SCIP_EVENTHDLRDATA* eventhdlrdata;
109 
110  assert(scip != NULL);
111  assert(eventhdlr != NULL);
112  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
113 
114  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
115  assert(eventhdlrdata != NULL);
116 
117  /* free memory */
118  SCIPfreeMemoryArray(scip, &eventhdlrdata->heurs);
119  SCIPfreeMemoryArray(scip, &eventhdlrdata->bestprimalbd);
120 
121  /* notify SCIP that your event handler wants to drop the event types best solution found and node solved */
122  SCIP_CALL( SCIPdropEvent(scip, SCIP_EVENTTYPE_SOLFOUND, eventhdlr, NULL, -1) );
123 
124  return SCIP_OKAY;
125 }
126 
127 /** solving process deinitialization method of event handler (called before branch and bound process data is freed) */
128 static
129 SCIP_DECL_EVENTEXITSOL(eventExitsolBestsol)
130 { /*lint --e{715}*/
131  SCIP_EVENTHDLRDATA* eventhdlrdata;
132  const char* probname;
133  int nheurs;
134  int i;
135 
136  assert(scip != NULL);
137  assert(eventhdlr != NULL);
138  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
139 
140  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
141  assert(eventhdlrdata != NULL);
142 
143  nheurs = SCIPgetNHeurs(scip);
144  probname = SCIPgetProbName(scip);
145 
146  /* output statistics */
147  for( i = 0; i < nheurs; ++i )
148  {
149  SCIPstatisticPrintf("Heuristic statistics (%s) -- %s : bestprimalbound = %13.6e\n",
150  strncmp(probname, "master", 6) == 0 ? "master" : "original",
151  SCIPheurGetName(eventhdlrdata->heurs[i]), eventhdlrdata->bestprimalbd[i]);
152  }
153 
154  return SCIP_OKAY;
155 }
156 
157 /** execution method of event handler */
158 static
159 SCIP_DECL_EVENTEXEC(eventExecBestsol)
160 { /*lint --e{715}*/
161  SCIP_EVENTHDLRDATA* eventhdlrdata;
162  int nheurs;
163  SCIP_SOL* sol;
164  SCIP_HEUR* solheur;
165  SCIP_Real obj;
166  int i;
167 
168  assert(scip != NULL);
169  assert(eventhdlr != NULL);
170  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
171 
172  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
173  assert(eventhdlrdata != NULL);
174 
175  nheurs = SCIPgetNHeurs(scip);
176 
177  /* get new primal solution */
178  sol = SCIPeventGetSol(event);
179  assert(sol != NULL);
180 
181  /* get the heuristic that found the solution */
182  solheur = SCIPgetSolHeur(scip, sol);
183 
184  /* get the objective value */
185  obj = SCIPgetSolTransObj(scip, sol);
186 
187  /* if the solution was found by a relaxation, there is nothing to do */
188  if( solheur == NULL )
189  return SCIP_OKAY;
190 
191  /* search the heuristic that found the solution */
192  for( i = 0; i < nheurs && eventhdlrdata->heurs[i] != solheur; ++i ) ;
193 
194  /* if the heuristic was not found in the problem, then the solution comes
195  * from another problem; in that case, no statistics are collected here
196  */
197  if( i == nheurs )
198  return SCIP_OKAY;
199 
200  /* update the best objective value for that heuristic */
201  if( obj < eventhdlrdata->bestprimalbd[i] )
202  eventhdlrdata->bestprimalbd[i] = obj;
203 
204  return SCIP_OKAY;
205 }
206 #endif
207 
208 /** creates event handler for bestsol event */
210  SCIP* scip /**< SCIP data structure */
211  )
212 {
213 #ifdef SCIP_STATISTIC
214  SCIP_EVENTHDLRDATA* eventhdlrdata;
215  SCIP_EVENTHDLR* eventhdlr;
216 
217  /* create bestsol event handler data */
218  eventhdlrdata = NULL;
219  SCIP_CALL( SCIPallocMemory(scip, &eventhdlrdata) );
220  assert(eventhdlrdata != NULL);
221 
222  eventhdlr = NULL;
223 
224  /* include event handler into SCIP */
225  SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC,
226  eventExecBestsol, eventhdlrdata) );
227  assert(eventhdlr != NULL);
228 
229  /* set non fundamental callbacks via setter functions */
230  SCIP_CALL( SCIPsetEventhdlrFree(scip, eventhdlr, eventFreeBestsol) );
231  SCIP_CALL( SCIPsetEventhdlrInit(scip, eventhdlr, eventInitBestsol) );
232  SCIP_CALL( SCIPsetEventhdlrExit(scip, eventhdlr, eventExitBestsol) );
233  SCIP_CALL( SCIPsetEventhdlrExitsol(scip, eventhdlr, eventExitsolBestsol) );
234 #endif
235 
236  return SCIP_OKAY;
237 }
static SCIP_DECL_EVENTEXIT(eventExitMastersol)
static SCIP_DECL_EVENTFREE(eventFreeMastersol)
#define EVENTHDLR_DESC
static SCIP_DECL_EVENTEXITSOL(eventExitsolGenericbranchvaradd)
static SCIP_DECL_EVENTINIT(eventInitMastersol)
#define EVENTHDLR_NAME
SCIP_RETCODE SCIPincludeEventHdlrBestsol(SCIP *scip)
static SCIP_DECL_EVENTEXEC(eventExecGenericbranchvaradd)
eventhdlr to record the best primal bound for each heuristic