Scippy

SCIP

Solving Constraint Integer Programs

reader_cnf.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2018 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file reader_cnf.c
17  * @brief CNF file reader
18  * @author Thorsten Koch
19  * @author Tobias Achterberg
20  *
21  * The DIMACS CNF (conjunctive normal form) is a file format used for example for SAT problems. For a detailed description of
22  * this format see http://people.sc.fsu.edu/~jburkardt/data/cnf/cnf.html .
23  */
24 
25 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
26 
27 #include <assert.h>
28 #include <string.h>
29 
30 #include "scip/reader_cnf.h"
31 #include "scip/cons_linear.h"
32 #include "scip/cons_logicor.h"
33 #include "scip/cons_setppc.h"
34 #include "scip/pub_misc.h"
35 
36 
37 #define READER_NAME "cnfreader"
38 #define READER_DESC "file reader for SAT problems in conjunctive normal form"
39 #define READER_EXTENSION "cnf"
40 
41 #define MAXLINELEN 65536
42 
43 
44 /*
45  * cnf reader internal methods
46  */
47 
48 static
49 void readError(
50  SCIP* scip, /**< SCIP data structure */
51  int linecount, /**< line number of error */
52  const char* errormsg /**< error message */
53  )
54 {
55  SCIPerrorMessage("read error in line <%d>: %s\n", linecount, errormsg);
56 }
57 
58 static
60  SCIP* scip, /**< SCIP data structure */
61  int linecount, /**< line number of error */
62  const char* warningmsg /**< warning message */
63  )
64 {
65  SCIPwarningMessage(scip, "Line <%d>: %s\n", linecount, warningmsg);
66 }
67 
68 /** reads the next non-empty non-comment line of a cnf file */
69 static
71  SCIP* scip, /**< SCIP data structure */
72  SCIP_FILE* file, /**< input file */
73  char* buffer, /**< buffer for storing the input line */
74  int size, /**< size of the buffer */
75  int* linecount /**< pointer to the line number counter */
76  )
77 {
78  char* line;
79  int linelen;
80 
81  assert(file != NULL);
82  assert(buffer != NULL);
83  assert(size >= 2);
84  assert(linecount != NULL);
85 
86  do
87  {
88  (*linecount)++;
89  line = SCIPfgets(buffer, size, file);
90  if( line != NULL )
91  {
92  linelen = (int)strlen(line);
93  if( linelen == size-1 )
94  {
95  char s[SCIP_MAXSTRLEN];
96  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "line too long (exceeds %d characters)", size-2);
97  readError(scip, *linecount, s);
98  return SCIP_READERROR;
99  }
100  }
101  else
102  linelen = 0;
103  }
104  while( line != NULL && (*line == 'c' || *line == '\n') );
105 
106  if( line != NULL && linelen >= 2 && line[linelen-2] == '\n' )
107  line[linelen-2] = '\0';
108  else if( linelen == 0 )
109  *buffer = '\0';
110 
111  assert((line == NULL) == (*buffer == '\0'));
112 
113  return SCIP_OKAY;
114 }
115 
116 /* Read SAT formula in "CNF File Format".
117  *
118  * The specification is taken from the
119  *
120  * Satisfiability Suggested Format
121  *
122  * Online available at http://www.intellektik.informatik.tu-darmstadt.de/SATLIB/Benchmarks/SAT/satformat.ps
123  *
124  * The method reads all files of CNF format. Other formats (SAT, SATX, SATE) are not supported.
125  */
126 static
128  SCIP* scip, /**< SCIP data structure */
129  SCIP_FILE* file /**< input file */
130  )
131 {
132  SCIP_RETCODE retcode;
133  SCIP_VAR** vars;
134  SCIP_VAR** clausevars;
135  SCIP_CONS* cons;
136  int* varsign;
137  char* tok;
138  char* nexttok;
139  char line[MAXLINELEN];
140  char format[SCIP_MAXSTRLEN];
141  char varname[SCIP_MAXSTRLEN];
142  char s[SCIP_MAXSTRLEN];
143  SCIP_Bool initialconss;
144  SCIP_Bool dynamicconss;
145  SCIP_Bool dynamiccols;
146  SCIP_Bool dynamicrows;
147  SCIP_Bool useobj;
148  int linecount;
149  int clauselen;
150  int clausenum;
151  int nvars;
152  int nclauses;
153  int varnum;
154  int v;
155 
156  assert(scip != NULL);
157  assert(file != NULL);
158 
159  linecount = 0;
160 
161  /* read header */
162  SCIP_CALL( readCnfLine(scip, file, line, (int) sizeof(line), &linecount) );
163  if( *line != 'p' )
164  {
165  readError(scip, linecount, "problem declaration line expected");
166  return SCIP_READERROR;
167  }
168  /* cppcheck-suppress invalidScanfFormatWidth_smaller */
169  if( sscanf(line, "p %8s %d %d", format, &nvars, &nclauses) != 3 )
170  {
171  readError(scip, linecount, "invalid problem declaration (must be 'p cnf <nvars> <nclauses>')");
172  return SCIP_READERROR;
173  }
174  if( strcmp(format, "cnf") != 0 )
175  {
176  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "invalid format tag <%s> (must be 'cnf')", format);
177  readError(scip, linecount, s);
178  return SCIP_READERROR;
179  }
180  if( nvars <= 0 )
181  {
182  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "invalid number of variables <%d> (must be positive)", nvars);
183  readError(scip, linecount, s);
184  return SCIP_READERROR;
185  }
186  if( nclauses <= 0 )
187  {
188  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "invalid number of clauses <%d> (must be positive)", nclauses);
189  readError(scip, linecount, s);
190  return SCIP_READERROR;
191  }
192 
193  /* get parameter values */
194  SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &initialconss) );
195  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &dynamicconss) );
196  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &dynamiccols) );
197  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &dynamicrows) );
198  SCIP_CALL( SCIPgetBoolParam(scip, "reading/cnfreader/useobj", &useobj) );
199 
200  /* get temporary memory */
201  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
202  SCIP_CALL( SCIPallocBufferArray(scip, &clausevars, nvars) );
203  SCIP_CALL( SCIPallocBufferArray(scip, &varsign, nvars) );
204 
205  /* create the variables */
206  for( v = 0; v < nvars; ++v )
207  {
208  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "x%d", v+1);
209  SCIP_CALL( SCIPcreateVar(scip, &vars[v], varname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY, !dynamiccols, dynamiccols,
210  NULL, NULL, NULL, NULL, NULL) );
211  SCIP_CALL( SCIPaddVar(scip, vars[v]) );
212  varsign[v] = 0;
213  }
214 
215  /* read clauses */
216  clausenum = 0;
217  clauselen = 0;
218  do
219  {
220  retcode = readCnfLine(scip, file, line, (int) sizeof(line), &linecount);
221  if( retcode != SCIP_OKAY )
222  goto TERMINATE;
223 
224  if( *line != '\0' && *line != '%' )
225  {
226  tok = SCIPstrtok(line, " \f\n\r\t", &nexttok);
227  while( tok != NULL )
228  {
229  /* parse literal and check for errors */
230  if( sscanf(tok, "%d", &v) != 1 )
231  {
232  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "invalid literal <%s>", tok);
233  readError(scip, linecount, s);
234  retcode = SCIP_READERROR;
235  goto TERMINATE;
236  }
237 
238  /* interpret literal number: v == 0: end of clause, v < 0: negated literal, v > 0: positive literal */
239  if( v == 0 )
240  {
241  /* end of clause: construct clause and add it to SCIP */
242  if( clauselen == 0 )
243  readWarning(scip, linecount, "empty clause detected in line -- problem infeasible");
244 
245  clausenum++;
246  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "c%d", clausenum);
247 
248  if( SCIPfindConshdlr(scip, "logicor") != NULL )
249  {
250  /* if the constraint handler logicor exit create a logicor constraint */
251  SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, s, clauselen, clausevars,
252  initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, dynamicconss, dynamicrows, FALSE) );
253  }
254  else if( SCIPfindConshdlr(scip, "setppc") != NULL )
255  {
256  /* if the constraint handler logicor does not exit but constraint
257  * handler setppc create a setppc constraint */
258  SCIP_CALL( SCIPcreateConsSetcover(scip, &cons, s, clauselen, clausevars,
259  initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, dynamicconss, dynamicrows, FALSE) );
260  }
261  else
262  {
263  /* if none of the previous constraint handler exits create a linear
264  * constraint */
265  SCIP_Real* vals;
266  int i;
267 
268  SCIP_CALL( SCIPallocBufferArray(scip, &vals, clauselen) );
269 
270  for( i = 0; i < clauselen; ++i )
271  vals[i] = 1.0;
272 
273  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, s, clauselen, clausevars, vals, 1.0, SCIPinfinity(scip),
274  initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, dynamicconss, dynamicrows, FALSE) );
275 
276  SCIPfreeBufferArray(scip, &vals);
277  }
278 
279  SCIP_CALL( SCIPaddCons(scip, cons) );
280  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
281  clauselen = 0;
282  }
283  else if( v >= -nvars && v <= nvars )
284  {
285  if( clauselen >= nvars )
286  {
287  readError(scip, linecount, "too many literals in clause");
288  retcode = SCIP_READERROR;
289  goto TERMINATE;
290  }
291 
292  /* add literal to clause */
293  varnum = ABS(v)-1;
294  if( v < 0 )
295  {
296  SCIP_CALL( SCIPgetNegatedVar(scip, vars[varnum], &clausevars[clauselen]) );
297  varsign[varnum]--;
298  }
299  else
300  {
301  clausevars[clauselen] = vars[varnum];
302  varsign[varnum]++;
303  }
304  clauselen++;
305  }
306  else
307  {
308  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "invalid variable number <%d>", ABS(v));
309  readError(scip, linecount, s);
310  retcode = SCIP_READERROR;
311  goto TERMINATE;
312  }
313 
314  /* get next token */
315  tok = SCIPstrtok(NULL, " \f\n\r\t", &nexttok);
316  }
317  }
318  }
319  while( *line != '\0' && *line != '%' );
320 
321  /* check for additional literals */
322  if( clauselen > 0 )
323  {
324  SCIPwarningMessage(scip, "found %d additional literals after last clause\n", clauselen);
325  }
326 
327  /* check number of clauses */
328  if( clausenum != nclauses )
329  {
330  SCIPwarningMessage(scip, "expected %d clauses, but found %d\n", nclauses, clausenum);
331  }
332 
333  TERMINATE:
334  /* change objective values and release variables */
336  for( v = 0; v < nvars; ++v )
337  {
338  if( useobj )
339  {
340  SCIP_CALL( SCIPchgVarObj(scip, vars[v], (SCIP_Real)varsign[v]) );
341  }
342  SCIP_CALL( SCIPreleaseVar(scip, &vars[v]) );
343  }
344 
345  /* free temporary memory */
346  SCIPfreeBufferArray(scip, &varsign);
347  SCIPfreeBufferArray(scip, &clausevars);
348  SCIPfreeBufferArray(scip, &vars);
349 
350  return retcode;
351 }
352 
353 
354 /*
355  * Callback methods
356  */
357 
358 /** copy method for reader plugins (called when SCIP copies plugins) */
359 static
360 SCIP_DECL_READERCOPY(readerCopyCnf)
361 { /*lint --e{715}*/
362  assert(scip != NULL);
363  assert(reader != NULL);
364  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
365 
366  /* call inclusion method of reader */
368 
369  return SCIP_OKAY;
370 }
371 
372 
373 /** problem reading method of reader */
374 static
375 SCIP_DECL_READERREAD(readerReadCnf)
376 { /*lint --e{715}*/
377  SCIP_FILE* f;
378  SCIP_RETCODE retcode;
379 
380  assert(reader != NULL);
381  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
382  assert(filename != NULL);
383  assert(result != NULL);
384 
385  /* open file */
386  f = SCIPfopen(filename, "r");
387  if( f == NULL )
388  {
389  SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
390  SCIPprintSysError(filename);
391  return SCIP_NOFILE;
392  }
393 
394  /* create problem */
395  SCIP_CALL( SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
396 
397  /* read cnf file */
398  retcode = readCnf(scip, f);
399 
400  /* close file */
401  SCIPfclose(f);
402 
403  *result = SCIP_SUCCESS;
404 
405  return retcode;
406 }
407 
408 
409 /*
410  * cnf file reader specific interface methods
411  */
412 
413 /** includes the cnf file reader in SCIP */
415  SCIP* scip /**< SCIP data structure */
416  )
417 {
418  SCIP_READER* reader;
419 
420  /* include reader */
422 
423  /* set non fundamental callbacks via setter functions */
424  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyCnf) );
425  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadCnf) );
426 
427  /* add cnf reader parameters */
429  "reading/cnfreader/useobj", "should an artificial objective, depending on the number of clauses a variable appears in, be used?",
430  NULL, FALSE, FALSE, NULL, NULL) );
431 
432  return SCIP_OKAY;
433 }
434 
static void readWarning(SCIP *scip, int linecount, const char *warningmsg)
Definition: reader_cnf.c:59
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6604
CNF file reader.
static SCIP_DECL_READERCOPY(readerCopyCnf)
Definition: reader_cnf.c:360
#define SCIP_MAXSTRLEN
Definition: def.h:259
SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
Definition: scip.c:9936
static SCIP_RETCODE readCnfLine(SCIP *scip, SCIP_FILE *file, char *buffer, int size, int *linecount)
Definition: reader_cnf.c:70
SCIP_RETCODE SCIPcreateConsSetcover(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_setppc.c:9151
const char * SCIPreaderGetName(SCIP_READER *reader)
Definition: reader.c:515
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18766
#define FALSE
Definition: def.h:64
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:47028
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10011
#define TRUE
Definition: def.h:63
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
static SCIP_RETCODE readCnf(SCIP *scip, SCIP_FILE *file)
Definition: reader_cnf.c:127
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22632
Constraint handler for the set partitioning / packing / covering constraints .
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1267
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:140
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition: scip.c:11066
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12591
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
struct SCIP_File SCIP_FILE
Definition: pub_fileio.h:34
char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
Definition: fileio.c:187
#define READER_DESC
Definition: reader_cnf.c:38
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip.c:4432
#define SCIP_CALL(x)
Definition: def.h:350
#define READER_EXTENSION
Definition: reader_cnf.c:39
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:21853
SCIP_RETCODE SCIPincludeReaderCnf(SCIP *scip)
Definition: reader_cnf.c:414
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:22620
public data structures and miscellaneous methods
#define READER_NAME
Definition: reader_cnf.c:37
#define SCIP_Bool
Definition: def.h:61
SCIP_RETCODE SCIPincludeReaderBasic(SCIP *scip, SCIP_READER **readerptr, const char *name, const char *desc, const char *extension, SCIP_READERDATA *readerdata)
Definition: scip.c:5264
void SCIPprintSysError(const char *message)
Definition: misc.c:9920
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip.c:17619
Constraint handler for linear constraints in their most general form, .
SCIP_RETCODE SCIPcreateConsLogicor(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
Definition: scip.c:5302
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
static SCIP_DECL_READERREAD(readerReadCnf)
Definition: reader_cnf.c:375
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:11492
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27761
#define MAXLINELEN
Definition: reader_cnf.c:41
#define SCIP_Real
Definition: def.h:149
static void readError(SCIP *scip, int linecount, const char *errormsg)
Definition: reader_cnf.c:49
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip.c:5350
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:219
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition: misc.c:9969
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip.c:19045
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4239