Scippy

GCG

Branch-and-Price & Column Generation for Everyone

main.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 main.c
29  * @brief Main file for C compilation
30  * @author Gerald Gamrath
31  * @author Martin Bergner
32  * @author Christian Puchert
33  */
34 
35 /*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
36 #include <string.h>
37 
38 #include "scip/scip.h"
39 #include "scip/scipdefplugins.h"
40 #include "scip/scipshell.h"
41 #include "gcgplugins.h"
42 #include "cons_decomp.h"
43 
44 #include "relax_gcg.h"
45 #include "cons_decomp.h"
46 #include "gcg.h"
47 
48 #if SCIP_VERSION < 700
49 #error GCG 3.1.0 can only be compiled with SCIP version 7.0.0 or higher
50 #endif
51 
52 
53 /** read in parameter file
54  * @returns SCIP return code */
55 static
56 SCIP_RETCODE readParams(
57  SCIP* scip, /**< SCIP data structure */
58  const char* filename /**< parameter file name */
59  )
60 {
61  if( SCIPfileExists(filename) )
62  {
63  SCIPinfoMessage(scip, NULL, "reading user parameter file <%s>\n", filename);
64  SCIP_CALL( SCIPreadParams(scip, filename) );
65  }
66  else
67  SCIPinfoMessage(scip, NULL, "user parameter file <%s> not found - using default parameters\n", filename);
68 
69  return SCIP_OKAY;
70 }
71 
72 /** runs GCG from the command line
73  * @returns SCIPreturn code */
74 static
75 SCIP_RETCODE fromCommandLine(
76  SCIP* scip, /**< SCIP data structure */
77  const char* filename, /**< input file name */
78  const char* decname /**< decomposition file name (or NULL) */
79  )
80 {
81  SCIP_RESULT result = SCIP_DIDNOTRUN;
82  /********************
83  * Problem Creation *
84  ********************/
85 
86  SCIPinfoMessage(scip, NULL, "\nread problem <%s>\n", filename);
87  SCIPinfoMessage(scip, NULL, "============\n\n");
88  SCIP_CALL( SCIPreadProb(scip, filename, NULL) );
89 
90  SCIP_CALL( GCGtransformProb(scip) );
91 
92  if( decname != NULL )
93  {
94  SCIPinfoMessage(scip, NULL, "\nread decomposition <%s>\n", decname);
95  SCIPinfoMessage(scip, NULL, "==================\n\n");
96  SCIP_CALL( SCIPreadProb(scip, decname, NULL) );
97  }
98 
99  /*******************
100  * Problem Solving *
101  *******************/
102  SCIPinfoMessage(scip, NULL, "\nsolve problem\n");
103  SCIPinfoMessage(scip, NULL, "=============\n\n");
104 
105  SCIP_CALL( GCGsolve(scip) );
106 
107  SCIPinfoMessage(scip, NULL, "\nprimal solution:\n");
108  SCIPinfoMessage(scip, NULL, "================\n\n");
109  SCIP_CALL( SCIPprintBestSol(scip, NULL, FALSE) );
110 
111  /**************
112  * Statistics *
113  **************/
114 
115  SCIPinfoMessage(scip, NULL, "\nStatistics\n");
116  SCIPinfoMessage(scip, NULL, "==========\n");
117 
118  SCIP_CALL( GCGprintStatistics(scip, NULL) );
119 
120  return SCIP_OKAY;
121 }
122 
123 /** evaluates command line parameters and runs GCG appropriately in the given SCIP instance
124  * @returns SCIP return code */
125 static
127  SCIP* scip, /**< SCIP data structure */
128  int argc, /**< number of shell parameters */
129  char** argv, /**< array with shell parameters */
130  const char* defaultsetname /**< name of default settings file */
131  )
132 { /*lint --e{850}*/
133  char* probname = NULL;
134  char* decname = NULL;
135  char* settingsname = NULL;
136  char* mastersetname = NULL;
137  char* logname = NULL;
138  SCIP_Bool quiet;
139  SCIP_Bool paramerror;
140  SCIP_Bool interactive;
141  SCIP_Real primalreference = SCIP_UNKNOWN;
142  SCIP_Real dualreference = SCIP_UNKNOWN;
143  const char* dualrefstring;
144  const char* primalrefstring;
145  int i;
146 
147 
148  /********************
149  * Parse parameters *
150  ********************/
151 
152  quiet = FALSE;
153  paramerror = FALSE;
154  interactive = FALSE;
155  primalrefstring = NULL;
156  dualrefstring = NULL;
157  for( i = 1; i < argc; ++i )
158  {
159  if( strcmp(argv[i], "-l") == 0 )
160  {
161  i++;
162  if( i < argc )
163  logname = argv[i];
164  else
165  {
166  SCIPinfoMessage(scip, NULL, "missing log filename after parameter '-l'\n");
167  paramerror = TRUE;
168  }
169  }
170  else if( strcmp(argv[i], "-q") == 0 )
171  quiet = TRUE;
172  else if( strcmp(argv[i], "-s") == 0 )
173  {
174  i++;
175  if( i < argc )
176  settingsname = argv[i];
177  else
178  {
179  SCIPinfoMessage(scip, NULL, "missing settings filename after parameter '-s'\n");
180  paramerror = TRUE;
181  }
182  }
183  else if( strcmp(argv[i], "-m") == 0 )
184  {
185  i++;
186  if( i < argc )
187  mastersetname = argv[i];
188  else
189  {
190  SCIPinfoMessage(scip, NULL, "missing settings filename for master program after parameter '-m'\n");
191  paramerror = TRUE;
192  }
193  }
194  else if( strcmp(argv[i], "-f") == 0 )
195  {
196  i++;
197  if( i < argc )
198  probname = argv[i];
199  else
200  {
201  SCIPinfoMessage(scip, NULL, "missing problem filename after parameter '-f'\n");
202  paramerror = TRUE;
203  }
204  }
205  else if( strcmp(argv[i], "-d") == 0 )
206  {
207  i++;
208  if( i < argc )
209  decname = argv[i];
210  else
211  {
212  SCIPinfoMessage(scip, NULL, "missing decomposition filename after parameter '-d'\n");
213  paramerror = TRUE;
214  }
215  }
216  else if( strcmp(argv[i], "-c") == 0 )
217  {
218  i++;
219  if( i < argc )
220  {
221  SCIP_CALL( SCIPaddDialogInputLine(scip, argv[i]) );
222  interactive = TRUE;
223  }
224  else
225  {
226  SCIPinfoMessage(scip, NULL, "missing command line after parameter '-c'\n");
227  paramerror = TRUE;
228  }
229  }
230  else if( strcmp(argv[i], "-b") == 0 )
231  {
232  i++;
233  if( i < argc )
234  {
235  SCIP_FILE* file;
236 
237  file = SCIPfopen(argv[i], "r");
238  if( file == NULL )
239  {
240  SCIPinfoMessage(scip, NULL, "cannot read command batch file <%s>\n", argv[i]);
241  SCIPprintSysError(argv[i]);
242  paramerror = TRUE;
243  }
244  else
245  {
246  while( !SCIPfeof(file) )
247  {
248  char buffer[SCIP_MAXSTRLEN];
249 
250  (void)SCIPfgets(buffer, SCIP_MAXSTRLEN, file);
251  if( buffer[0] != '\0' )
252  {
253  SCIP_CALL( SCIPaddDialogInputLine(scip, buffer) );
254  }
255  }
256  SCIPfclose(file);
257  interactive = TRUE;
258  }
259  }
260  else
261  {
262  SCIPinfoMessage(scip, NULL, "missing command batch filename after parameter '-b'\n");
263  paramerror = TRUE;
264  }
265  }
266  else if( strcmp(argv[i], "-o") == 0 )
267  {
268  if( i >= argc - 2 )
269  {
270  printf("wrong usage of reference objective parameter '-o': -o <primref> <dualref>\n");
271  paramerror = TRUE;
272  }
273  else
274  {
275  /* do not parse the strings directly, the settings could still influence the value of +-infinity */
276  primalrefstring = argv[i + 1];
277  dualrefstring = argv[i+2];
278  }
279  i += 2;
280  }
281  else
282  {
283  SCIPinfoMessage(scip, NULL, "invalid parameter <%s>\n", argv[i]);
284  paramerror = TRUE;
285  }
286  }
287  if( interactive && probname != NULL )
288  {
289  SCIPinfoMessage(scip, NULL, "cannot mix batch mode '-c' and '-b' with file mode '-f'\n");
290  paramerror = TRUE;
291  }
292  if( probname == NULL && decname != NULL )
293  {
294  SCIPinfoMessage(scip, NULL, "cannot read decomposition file without given problem\n");
295  paramerror = TRUE;
296  }
297 
298  if( !paramerror )
299  {
300 
301  /***********************************
302  * create log file message handler *
303  ***********************************/
304 
305  if( quiet )
306  {
307  SCIPsetMessagehdlrQuiet(scip, quiet);
308  }
309 
310  if( logname != NULL )
311  {
312  SCIPsetMessagehdlrLogfile(scip, logname);
313  }
314 
315 
316  /***********************************
317  * Version and library information *
318  ***********************************/
319 
320  SCIPprintVersion(scip, NULL);
321  SCIPinfoMessage(scip, NULL, "\n");
322 
323  SCIPprintExternalCodes(scip, NULL);
324  SCIPinfoMessage(scip, NULL, "\n");
325 
326  /*****************
327  * Load settings *
328  *****************/
329 
330  if( settingsname != NULL )
331  {
332  SCIP_CALL( readParams(scip, settingsname) );
333  }
334  else if( defaultsetname != NULL )
335  {
336  SCIP_CALL( readParams(scip, defaultsetname) );
337  }
338 
339  if( mastersetname != NULL )
340  {
341  SCIP_CALL( readParams(GCGgetMasterprob(scip), mastersetname) );
342  }
343 
344  /**************
345  * Start SCIP *
346  **************/
347 
348  if( probname != NULL )
349  {
350  SCIP_Bool validatesolve = FALSE;
351 
352  if( primalrefstring != NULL && dualrefstring != NULL )
353  {
354  char *endptr;
355  if( ! SCIPparseReal(scip, primalrefstring, &primalreference, &endptr) ||
356  ! SCIPparseReal(scip, dualrefstring, &dualreference, &endptr) )
357  {
358  printf("error parsing primal and dual reference values for validation: %s %s\n", primalrefstring, dualrefstring);
359  return SCIP_ERROR;
360  }
361  else
362  validatesolve = TRUE;
363  }
364  SCIP_CALL( fromCommandLine(scip, probname, decname) );
365 
366  /* validate the solve */
367  if( validatesolve )
368  {
369  SCIP_CALL( SCIPvalidateSolve(scip, primalreference, dualreference, SCIPfeastol(scip), FALSE, NULL, NULL, NULL) );
370  }
371  }
372  else
373  {
374  SCIPinfoMessage(scip, NULL, "\n");
375  SCIP_CALL( SCIPstartInteraction(scip) );
376  }
377  }
378  else
379  {
380  SCIPinfoMessage(scip, NULL, "\nsyntax: %s [-l <logfile>] [-q] [-s <settings>] [-f <problem>] [-m <mastersettings>] [-d <decomposition>] [-b <batchfile>] [-c \"command\"]\n"
381  " -l <logfile> : copy output into log file\n"
382  " -q : suppress screen messages\n"
383  " -s <settings> : load parameter settings (.set) file\n"
384  " -m <mastersettings> : load parameter settings for master program (.set) file\n",
385  argv[0]);
386  SCIPinfoMessage(scip, NULL, " -f <problem> : load and solve problem file\n"
387  " -d <decomposition> : load decomposition file\n"
388  " -o <primref> <dualref> : pass primal and dual objective reference values for validation at the end of the solve\n"
389  " -b <batchfile> : load and execute dialog command batch file (can be used multiple times)\n"
390  " -c \"command\" : execute single line of dialog commands (can be used multiple times)\n\n");
391  }
392 
393  return SCIP_OKAY;
394 }
395 
396 /** runs the interactive shell
397  * @returns SCIP return code */
398 static
399 SCIP_RETCODE SCIPrunGCGShell(
400  int argc, /**< number of shell parameters */
401  char** argv, /**< array with shell parameters */
402  const char* defaultsetname /**< name of default settings file */
403  )
404 {
405  SCIP* scip = NULL;
406 
407  /*********
408  * Setup *
409  *********/
410 
411  /* initialize SCIP */
412  SCIP_CALL( SCIPcreate(&scip) );
413  GCGprintVersion(scip, NULL);
414 
415 
416  /* include coloring plugins */
417  SCIP_CALL( SCIPincludeGcgPlugins(scip) );
418 
419  /**********************************
420  * Process command line arguments *
421  **********************************/
422  SCIP_CALL( SCIPprocessGCGShellArguments(scip, argc, argv, defaultsetname) );
423 
424 
425  /********************
426  * Deinitialization *
427  ********************/
428 
429  SCIP_CALL( SCIPfree(&scip) );
430 
431  BMScheckEmptyMemory();
432 
433  return SCIP_OKAY;
434 }
435 
436 /** main function called first
437  * @returns 0 if success, -1 otherwise */
438 int
440  int argc, /**< number of arguments */
441  char** argv /**< array of arguments */
442  )
443 {
444  SCIP_RETCODE retcode;
445 
446  retcode = SCIPrunGCGShell(argc, argv, "gcg.set");
447 
448  if( retcode != SCIP_OKAY )
449  {
450  SCIPprintError(retcode);
451  return -1;
452  }
453 
454  return 0;
455 }
GCG interface methods.
SCIP_RETCODE SCIPincludeGcgPlugins(SCIP *scip)
Definition: gcgplugins.c:290
constraint handler for structure detection
SCIP_RETCODE GCGsolve(SCIP *scip)
Definition: relax_gcg.c:5341
SCIP_RETCODE GCGprintStatistics(SCIP *scip, FILE *file)
Definition: misc.c:685
int main(int argc, char **argv)
Definition: main.c:439
SCIP_RETCODE GCGtransformProb(SCIP *scip)
Definition: relax_gcg.c:5199
void GCGprintVersion(SCIP *scip, FILE *file)
Definition: gcg_general.c:78
SCIP * GCGgetMasterprob(SCIP *scip)
Definition: relax_gcg.c:3920
static SCIP_RETCODE fromCommandLine(SCIP *scip, const char *filename, const char *decname)
Definition: main.c:75
static SCIP_RETCODE SCIPprocessGCGShellArguments(SCIP *scip, int argc, char **argv, const char *defaultsetname)
Definition: main.c:126
SCIP plugins for generic column generation.
GCG relaxator.
static SCIP_RETCODE SCIPrunGCGShell(int argc, char **argv, const char *defaultsetname)
Definition: main.c:399
static SCIP_RETCODE readParams(SCIP *scip, const char *filename)
Definition: main.c:56