Scippy

SCIP

Solving Constraint Integer Programs

reader_osil.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-2017 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_osil.c
17  * @brief OS instance language (OSiL) format file reader
18  * @author Stefan Vigerske
19  * @author Ingmar Vierhaus
20  */
21 
22 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
23 
24 #define _USE_MATH_DEFINES /* to get M_PI and M_E on Windows */ /*lint !750 */
25 
26 #include <assert.h>
27 #include <string.h>
28 #include <math.h>
29 
30 #include "scip/reader_osil.h"
31 #include "scip/scip.h"
33 #include "scip/cons_linear.h"
34 #include "scip/cons_quadratic.h"
35 #include "scip/cons_nonlinear.h"
36 #include "scip/cons_sos1.h"
37 #include "scip/cons_sos2.h"
38 #include "xml/xml.h"
39 
40 
41 #define READER_NAME "osilreader"
42 #define READER_DESC "file reader for OS instance language (OSiL) format"
43 #define READER_EXTENSION "osil"
44 
45 /*
46  * Data structures
47  */
48 
49 /** type of constraint */
50 typedef enum
51 {
52  LINEAR, /**< linear constraint */
53  QUADRATIC, /**< quadratic constraint */
54  NONLINEAR /**< general nonlinear constraint */
55 } CONSTYPE;
56 
57 
58 /*
59  * Local methods
60  */
61 
62 /** create variables with bounds and type according to xml data */
63 static
65  SCIP* scip, /**< SCIP data structure */
66  const XML_NODE* datanode, /**< XML root node for instance data */
67  SCIP_VAR*** vars, /**< buffer to store pointer to variable array */
68  int* nvars, /**< buffer to store number of variables */
69  SCIP_Bool initialconss, /**< should model constraints be marked as initial? */
70  SCIP_Bool dynamicconss, /**< should model constraints be subject to aging? */
71  SCIP_Bool dynamiccols, /**< should columns be added and removed dynamically to the LP? */
72  SCIP_Bool dynamicrows, /**< should rows be added and removed dynamically to the LP? */
73  SCIP_Bool* doingfine /**< buffer to indicate whether no errors occured */
74  )
75 {
76  const XML_NODE* variables;
77  const XML_NODE* varnode;
78  const char* attrval;
79  int varssize;
80 
81  assert(scip != NULL);
82  assert(datanode != NULL);
83  assert(vars != NULL);
84  assert(nvars != NULL);
85  assert(doingfine != NULL);
86 
87  *vars = NULL;
88  *nvars = 0;
89 
90  variables = xmlFindNodeMaxdepth(datanode, "variables", 0, 1);
91 
92  if( variables == NULL )
93  {
94  /* no variables: strange but ok so far */
95  return SCIP_OKAY;
96  }
97 
98  /* get number of variables */
99  attrval = xmlGetAttrval(variables, "numberOfVariables");
100  if( attrval == NULL )
101  {
102  SCIPerrorMessage("Attribute \"numberOfVariables\" not found in <variables> node.\n");
103  *doingfine = FALSE;
104  return SCIP_OKAY;
105  }
106 
107  varssize = (int)strtol(attrval, (char**)&attrval, 10);
108  if( *attrval != '\0' || varssize < 0 )
109  {
110  SCIPerrorMessage("Invalid value '%s' for \"numberOfVariables\" attribute.\n", xmlGetAttrval(variables, "numberOfVariables"));
111  *doingfine = FALSE;
112  return SCIP_OKAY;
113  }
114  assert(varssize >= 0);
115 
116  SCIP_CALL( SCIPallocBufferArray(scip, vars, varssize) );
117 
118  /* parse variable nodes, create SCIP vars and add to problem
119  * create bounddisjunction constraints for semicontinuous/semiinteger variables
120  */
121  for( varnode = xmlFirstChild(variables); varnode != NULL; varnode = xmlNextSibl(varnode) )
122  {
123  const char* varname;
124  SCIP_VARTYPE vartype;
125  SCIP_Real varlb;
126  SCIP_Real varub;
127  SCIP_Real semibound;
128 
129  if( varssize == *nvars )
130  {
131  SCIPerrorMessage("Expected %d variables, got at least %d many.\n", varssize, *nvars+1);
132  *doingfine = FALSE;
133  return SCIP_OKAY;
134  }
135 
136  /* find variable name */
137  varname = xmlGetAttrval(varnode, "name");
138 
139  /* check for mult attribute */
140  attrval = xmlGetAttrval(varnode, "mult");
141  if( attrval != NULL && strcmp(attrval, "1") != 0 )
142  {
143  SCIPerrorMessage("Variable attribute 'mult' not supported (while parsing variable <%s>)\n", varname);
144  *doingfine = FALSE;
145  return SCIP_OKAY;
146  }
147 
148  /* find variable lower bound (default is 0.0 !) */
149  attrval = xmlGetAttrval(varnode, "lb");
150  if( attrval == NULL )
151  varlb = 0.0;
152  else if( strcmp(attrval, "-INF") == 0 )
153  varlb = -SCIPinfinity(scip);
154  else if( strcmp(attrval, "INF") == 0 )
155  varlb = SCIPinfinity(scip);
156  else
157  {
158  varlb = strtod(attrval, (char**)&attrval);
159  if( *attrval != '\0' )
160  {
161  SCIPerrorMessage("Error parsing variable lower bound '%s' for variable <%s>\n", attrval, varname);
162  *doingfine = FALSE;
163  return SCIP_OKAY;
164  }
165  }
166 
167  /* find variable upper bound (default is infinity) */
168  attrval = xmlGetAttrval(varnode, "ub");
169  if( attrval == NULL )
170  varub = SCIPinfinity(scip);
171  else if( strcmp(attrval, "-INF") == 0 )
172  varub = -SCIPinfinity(scip);
173  else if( strcmp(attrval, "INF") == 0 )
174  varub = SCIPinfinity(scip);
175  else
176  {
177  varub = strtod(attrval, (char**)&attrval);
178  if( *attrval != '\0' )
179  {
180  SCIPerrorMessage("Error parsing variable upper bound '%s' for variable <%s>\n", attrval, varname);
181  *doingfine = FALSE;
182  return SCIP_OKAY;
183  }
184  }
185 
186  semibound = SCIP_INVALID;
187 
188  /* find variable type (default is continuous)
189  * adjust variable lower bound for semicontinuous variables
190  */
191  attrval = xmlGetAttrval(varnode, "type");
192  if( attrval == NULL )
193  vartype = SCIP_VARTYPE_CONTINUOUS;
194  else switch( *attrval )
195  {
196  case 'C':
197  vartype = SCIP_VARTYPE_CONTINUOUS;
198  break;
199  case 'B':
200  vartype = SCIP_VARTYPE_BINARY;
201  if( varub > 1.0 )
202  varub = 1.0;
203  break;
204  case 'I':
205  vartype = SCIP_VARTYPE_INTEGER;
206  break;
207  case 'D':
208  vartype = SCIP_VARTYPE_CONTINUOUS;
209  if( varlb > 0.0 )
210  semibound = varlb;
211  varlb = 0.0;
212  break;
213  case 'J':
214  vartype = SCIP_VARTYPE_INTEGER;
215  if( varlb > 0.0 )
216  semibound = varlb;
217  varlb = 0.0;
218  break;
219  default:
220  SCIPerrorMessage("Unsupported variable type '%s' for variable <%s>\n", attrval, varname);
221  *doingfine = FALSE;
222  return SCIP_OKAY;
223  }
224 
225  if( vartype != SCIP_VARTYPE_CONTINUOUS )
226  {
227  varlb = SCIPceil(scip, varlb);
228  varub = SCIPfloor(scip, varub);
229  }
230 
231  /* create SCIP variable */
232  SCIP_CALL( SCIPcreateVar(scip, &(*vars)[*nvars], varname, varlb, varub, 0.0, vartype, !dynamiccols, dynamiccols, NULL, NULL, NULL, NULL, NULL) );
233  assert((*vars)[*nvars] != NULL);
234 
235  /* add variable to problem */
236  SCIP_CALL( SCIPaddVar(scip, (*vars)[*nvars]) );
237 
238  /* if variable is actually semicontinuous or semiintegral, create bounddisjunction constraint (var <= 0.0 || var >= semibound) */
239  if( semibound != SCIP_INVALID ) /*lint !e777*/
240  {
241  SCIP_CONS* cons;
242  SCIP_VAR* consvars[2];
243  SCIP_BOUNDTYPE boundtypes[2];
244  SCIP_Real bounds[2];
245  char name[SCIP_MAXSTRLEN];
246 
247  consvars[0] = (*vars)[*nvars];
248  consvars[1] = (*vars)[*nvars];
249 
250  boundtypes[0] = SCIP_BOUNDTYPE_UPPER;
251  boundtypes[1] = SCIP_BOUNDTYPE_LOWER;
252 
253  bounds[0] = 0.0;
254  bounds[1] = semibound;
255 
256  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_semibound", SCIPvarGetName((*vars)[*nvars]));
257 
258  SCIP_CALL( SCIPcreateConsBounddisjunction(scip, &cons, name, 2, consvars, boundtypes, bounds,
259  initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, dynamicconss, dynamicrows, FALSE) );
260  SCIP_CALL( SCIPaddCons(scip, cons) );
261  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
262  }
263 
264  ++*nvars;
265  }
266  if( *nvars < varssize )
267  {
268  SCIPerrorMessage("Expected %d variables, but got only %d many.\n", varssize, *nvars);
269  *doingfine = FALSE;
270  return SCIP_OKAY;
271  }
272 
273  return SCIP_OKAY;
274 }
275 
276 /** setup linear coefficients and constant of objective and objective sense */
277 static
279  SCIP* scip, /**< SCIP data structure */
280  const XML_NODE* datanode, /**< XML root node for instance data */
281  SCIP_VAR** vars, /**< variables in order of OSiL indices */
282  int nvars, /**< number of variables */
283  SCIP_Bool dynamiccols, /**< should columns be added and removed dynamically to the LP? */
284  SCIP_Bool* doingfine /**< buffer to indicate whether no errors occured */
285  )
286 {
287  const XML_NODE* objective;
288  const XML_NODE* coefnode;
289  const char* attrval;
290 
291  assert(scip != NULL);
292  assert(datanode != NULL);
293  assert(vars != NULL || nvars == 0);
294  assert(doingfine != NULL);
295 
296  /* check for first objective */
297  objective = xmlFindNodeMaxdepth(datanode, "obj", 0, 2);
298 
299  /* if no objective, then nothing to do here */
300  if( objective == NULL )
301  return SCIP_OKAY;
302 
303  /* check for mult attribute */
304  attrval = xmlGetAttrval(objective, "mult");
305  if( attrval != NULL && strcmp(attrval, "1") != 0 )
306  {
307  SCIPerrorMessage("Objective attribute 'mult' not supported.\n");
308  *doingfine = FALSE;
309  return SCIP_OKAY;
310  }
311 
312  /* objective sense */
313  attrval = xmlGetAttrval(objective, "maxOrMin");
314  if( attrval == NULL )
315  {
316  SCIPerrorMessage("Objective sense missing.\n");
317  *doingfine = FALSE;
318  return SCIP_OKAY;
319  }
320  else if( strcmp(attrval, "min") == 0 )
321  {
323  }
324  else if( strcmp(attrval, "max") == 0 )
325  {
327  }
328  else
329  {
330  SCIPerrorMessage("Cannot parse objective sense '%s'.\n", attrval);
331  *doingfine = FALSE;
332  return SCIP_OKAY;
333  }
334 
335  /* objective coefficients */
336  for( coefnode = xmlFirstChild(objective); coefnode != NULL; coefnode = xmlNextSibl(coefnode) )
337  {
338  SCIP_Real val;
339  int idx;
340 
341  /* get variable index */
342  attrval = xmlGetAttrval(coefnode, "idx");
343  if( attrval == NULL )
344  {
345  SCIPerrorMessage("Missing \"idx\" attribute in objective coefficient.\n");
346  *doingfine = FALSE;
347  return SCIP_OKAY;
348  }
349  idx = (int)strtol(attrval, (char**)&attrval, 10);
350  if( *attrval != '\0' )
351  {
352  SCIPerrorMessage("Error parsing variable index '%s' of objective coefficient.\n", xmlGetAttrval(coefnode, "idx"));
353  *doingfine = FALSE;
354  return SCIP_OKAY;
355  }
356 
357  if( idx < 0 || idx >= nvars )
358  {
359  SCIPerrorMessage("Invalid variable index '%d' of objective coefficient.\n", idx);
360  *doingfine = FALSE;
361  return SCIP_OKAY;
362  }
363 
364  /* get coefficient value */
365  if( xmlFirstChild(coefnode) == NULL || xmlGetData(xmlFirstChild(coefnode)) == NULL )
366  {
367  SCIPerrorMessage("No objective coefficient stored for %d'th variable (<%s>).\n", idx, SCIPvarGetName(vars[idx])); /*lint !e613*/
368  *doingfine = FALSE;
369  return SCIP_OKAY;
370  }
371 
372  attrval = xmlGetData(xmlFirstChild(coefnode));
373  val = strtod(attrval, (char**)&attrval);
374  if( *attrval != '\0' )
375  {
376  SCIPerrorMessage("Error parsing objective coefficient value '%s' for %d'th variable (<%s>).\n", xmlGetData(xmlFirstChild(coefnode)), idx, SCIPvarGetName(vars[idx])); /*lint !e613*/
377  *doingfine = FALSE;
378  return SCIP_OKAY;
379  }
380 
381  /* change objective coefficient of SCIP variable */
382  SCIP_CALL( SCIPchgVarObj(scip, vars[idx], val) ); /*lint !e613*/
383  }
384 
385  /* objective constant: model as fixed variable, if nonzero */
386  attrval = xmlGetAttrval(objective, "constant");
387  if( attrval != NULL )
388  {
389  SCIP_Real objconst;
390 
391  objconst = strtod(attrval, (char**)&attrval);
392  if( *attrval != '\0' )
393  {
394  SCIPerrorMessage("Error parsing objective constant '%s'\n", xmlGetAttrval(objective, "constant"));
395  *doingfine = FALSE;
396  return SCIP_OKAY;
397  }
398 
399  if( objconst != 0.0 )
400  {
401  SCIP_VAR* objconstvar;
402 
403  SCIP_CALL( SCIPcreateVar(scip, &objconstvar, "objconstvar", objconst, objconst, 1.0, SCIP_VARTYPE_CONTINUOUS, !dynamiccols, dynamiccols, NULL, NULL, NULL, NULL, NULL) );
404  SCIP_CALL( SCIPaddVar(scip, objconstvar) );
405  SCIP_CALL( SCIPreleaseVar(scip, &objconstvar) );
406  }
407  }
408 
409  if( xmlNextSibl(objective) != NULL )
410  {
411  SCIPerrorMessage("Multiple objectives not supported by SCIP.\n");
412  *doingfine = FALSE;
413  return SCIP_OKAY;
414  }
415 
416  return SCIP_OKAY;
417 }
418 
419 /** setup constraint sides as linear constraints
420  *
421  * constraints are not added to the problem yet
422  */
423 static
425  SCIP* scip, /**< SCIP data structure */
426  const XML_NODE* datanode, /**< XML root node for instance data */
427  SCIP_CONS*** conss, /**< buffer to store array of (linear) constraints */
428  CONSTYPE** constypes, /**< buffer to store type of constraints (will be all LINEAR) */
429  int* nconss, /**< buffer to store number of constraints */
430  SCIP_Bool initialconss, /**< should model constraints be marked as initial? */
431  SCIP_Bool dynamicconss, /**< should model constraints be subject to aging? */
432  SCIP_Bool dynamicrows, /**< should rows be added and removed dynamically to the LP? */
433  SCIP_Bool* doingfine /**< buffer to indicate whether no errors occured */
434  )
435 {
436  const XML_NODE* constraints;
437  const XML_NODE* consnode;
438  const char* attrval;
439  int consssize;
440  char name[20];
441 
442  assert(scip != NULL);
443  assert(datanode != NULL);
444  assert(conss != NULL);
445  assert(constypes != NULL);
446  assert(nconss != NULL);
447  assert(doingfine != NULL);
448 
449  *conss = NULL;
450  *constypes = NULL;
451  *nconss = 0;
452 
453  constraints = xmlFindNodeMaxdepth(datanode, "constraints", 0, 1);
454 
455  /* if no constraints, then nothing to do here */
456  if( constraints == NULL )
457  return SCIP_OKAY;
458 
459  /* read number of constraints */
460  attrval = xmlGetAttrval(constraints, "numberOfConstraints");
461  if( attrval == NULL )
462  {
463  SCIPerrorMessage("Attribute \"numberOfConstraints\" not found in <constraints> node.\n");
464  *doingfine = FALSE;
465  return SCIP_OKAY;
466  }
467 
468  consssize = (int)strtol(attrval, (char**)&attrval, 10);
469  if( *attrval != '\0' || consssize < 0 )
470  {
471  SCIPerrorMessage("Invalid value '%s' for \"numberOfConstraints\" attribute.\n", xmlGetAttrval(constraints, "numberOfConstraints"));
472  *doingfine = FALSE;
473  return SCIP_OKAY;
474  }
475  assert(consssize >= 0);
476 
477  SCIP_CALL( SCIPallocBufferArray(scip, conss, consssize) );
478  SCIP_CALL( SCIPallocBufferArray(scip, constypes, consssize) );
479 
480  /* read constraint names, lhs, rhs, constant */
481  for( consnode = xmlFirstChild(constraints); consnode != NULL; consnode = xmlNextSibl(consnode) )
482  {
483  const char* consname;
484  SCIP_Real conslhs;
485  SCIP_Real consrhs;
486 
487  if( consssize == *nconss )
488  {
489  SCIPerrorMessage("Expected %d constraints, but got at least %d many.\n", consssize, *nconss+1);
490  *doingfine = FALSE;
491  return SCIP_OKAY;
492  }
493 
494  /* find constraint name */
495  consname = xmlGetAttrval(consnode, "name");
496  if( consname == NULL )
497  {
498  (void) SCIPsnprintf(name, 20, "cons%d", *nconss);
499  consname = name;
500  }
501 
502  /* check for mult attribute */
503  attrval = xmlGetAttrval(consnode, "mult");
504  if( attrval != NULL && strcmp(attrval, "1") != 0 )
505  {
506  SCIPerrorMessage("Constraint attribute 'mult' not supported (while parsing constraint <%s>).\n", consname);
507  *doingfine = FALSE;
508  return SCIP_OKAY;
509  }
510 
511  /* find constraint lower bound (=lhs) (default is -infinity) */
512  attrval = xmlGetAttrval(consnode, "lb");
513  if( attrval == NULL )
514  conslhs = -SCIPinfinity(scip);
515  else if( strcmp(attrval, "-INF") == 0 )
516  conslhs = -SCIPinfinity(scip);
517  else if( strcmp(attrval, "INF") == 0 )
518  conslhs = SCIPinfinity(scip);
519  else
520  {
521  conslhs = strtod(attrval, (char**)&attrval);
522  if( *attrval != '\0' )
523  {
524  SCIPerrorMessage("Error parsing constraint lower bound '%s' for constraint <%s>.\n", attrval, consname);
525  *doingfine = FALSE;
526  return SCIP_OKAY;
527  }
528  }
529 
530  /* find constraint upper bound (=rhs) (default is +infinity) */
531  attrval = xmlGetAttrval(consnode, "ub");
532  if( attrval == NULL )
533  consrhs = SCIPinfinity(scip);
534  else if( strcmp(attrval, "-INF") == 0 )
535  consrhs = -SCIPinfinity(scip);
536  else if( strcmp(attrval, "INF") == 0 )
537  consrhs = SCIPinfinity(scip);
538  else
539  {
540  consrhs = strtod(attrval, (char**)&attrval);
541  if( *attrval != '\0' )
542  {
543  SCIPerrorMessage("Error parsing constraint upper bound '%s' for constraint <%s>.\n", attrval, consname);
544  *doingfine = FALSE;
545  return SCIP_OKAY;
546  }
547  }
548 
549  /* find constraint constant (default is 0.0) and substract from lhs/rhs */
550  attrval = xmlGetAttrval(consnode, "constant");
551  if( attrval != NULL )
552  {
553  SCIP_Real consconstant;
554 
555  consconstant = strtod(attrval, (char**)&attrval);
556  if( *attrval != '\0' )
557  {
558  SCIPerrorMessage("Error parsing constraint constant '%s' for constraint <%s>.\n", attrval, consname);
559  *doingfine = FALSE;
560  return SCIP_OKAY;
561  }
562  if( conslhs > -SCIPinfinity(scip) )
563  conslhs -= consconstant;
564  if( consrhs < SCIPinfinity(scip) )
565  consrhs -= consconstant;
566  }
567 
568  /* create SCIP linear constraint */
569  SCIP_CALL( SCIPcreateConsLinear(scip, &(*conss)[*nconss], consname, 0, NULL, NULL, conslhs, consrhs,
570  initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, dynamicconss, dynamicrows, FALSE) );
571  assert((*conss)[*nconss] != NULL);
572 
573  (*constypes)[*nconss] = LINEAR;
574 
575  ++*nconss;
576  }
577 
578  if( *nconss < consssize )
579  {
580  SCIPerrorMessage("Got %d constraints, but expected %d many.\n", *nconss, consssize);
581  *doingfine = FALSE;
582  return SCIP_OKAY;
583  }
584 
585  return SCIP_OKAY;
586 }
587 
588 /** reads mult and incr attributes of an OSiL node
589  *
590  * if mult attribute is not present, then returns mult=1
591  * if incr attribute is not present, then returns incrint=0 and incrreal=0
592  */
593 static
595  const XML_NODE* node, /**< XML node to read attributes from */
596  int* mult, /**< buffer to store mult */
597  int* incrint, /**< buffer to store incr as int, or NULL if no int expected */
598  SCIP_Real* incrreal, /**< buffer to store incr as real, or NULL if no real expected */
599  SCIP_Bool* doingfine /**< buffer to indicate whether no errors occured */
600  )
601 {
602  const char* attrval;
603 
604  assert(node != NULL);
605  assert(mult != NULL);
606  assert(doingfine != NULL);
607 
608  *mult = 1;
609  if( incrint != NULL )
610  *incrint = 0;
611  if( incrreal != NULL )
612  *incrreal = 0.0;
613 
614  attrval = xmlGetAttrval(node, "mult");
615  if( attrval == NULL )
616  return;
617 
618  /* read "mult" attribute */
619  *mult = (int)strtol(attrval, (char**)&attrval, 10);
620  if( *attrval != '\0' || *mult < 1 )
621  {
622  SCIPerrorMessage("Invalid value '%s' in \"mult\" attribute of node.\n", xmlGetAttrval(node, "mult"));
623  *doingfine = FALSE;
624  return;
625  }
626 
627  if( *mult == 1 )
628  return;
629 
630  /* read "incr" attribute */
631  attrval = xmlGetAttrval(node, "incr");
632  if( attrval == NULL )
633  return;
634 
635  if( incrint != NULL )
636  {
637  *incrint = (int)strtol(attrval, (char**)&attrval, 10);
638  if( *attrval != '\0' )
639  {
640  SCIPerrorMessage("Invalid value '%s' in \"incr\" attribute of node.\n", xmlGetAttrval(node, "incr"));
641  *doingfine = FALSE;
642  return;
643  }
644  }
645 
646  if( incrreal != NULL )
647  {
648  *incrreal = strtod(attrval, (char**)&attrval);
649  if( *attrval != '\0' || !SCIPisFinite(*incrreal) )
650  {
651  SCIPerrorMessage("Invalid value '%s' in \"incr\" attribute of node.\n", xmlGetAttrval(node, "incr"));
652  *doingfine = FALSE;
653  return;
654  }
655  }
656 }
657 
658 /** parse linear coefficients of constraints */
659 static
661  SCIP* scip, /**< SCIP data structure */
662  const XML_NODE* datanode, /**< XML root node for instance data */
663  SCIP_VAR** vars, /**< variables in order of OSiL indices */
664  int nvars, /**< number of variables */
665  SCIP_CONS** conss, /**< constraints in order of OSiL indices */
666  CONSTYPE* constypes, /**< type of constraints (assumed to be LINEAR) */
667  int nconss, /**< number of constraints */
668  SCIP_Bool* doingfine /**< buffer to indicate whether no errors occured */
669  )
670 {
671  const XML_NODE* lincoef;
672  const XML_NODE* startnode;
673  const XML_NODE* idxnode;
674  const XML_NODE* valnode;
675  const XML_NODE* elnode;
676  const char* attrval;
677  SCIP_Bool rowmajor;
678  int* start;
679  int* idx;
680  SCIP_Real* val;
681  int nnz;
682  int count;
683  int mult;
684  int incrint;
685  SCIP_Real incrreal;
686 
687  assert(scip != NULL);
688  assert(datanode != NULL);
689  assert(vars != NULL || nvars == 0);
690  assert(conss != NULL || nconss == 0);
691  assert(constypes != NULL || nconss == 0);
692  assert(doingfine != NULL);
693 
694  lincoef = xmlFindNodeMaxdepth(datanode, "linearConstraintCoefficients", 0, 1);
695 
696  if( lincoef == NULL )
697  return SCIP_OKAY;
698 
699  /* get number of linear constraint coefficients */
700  attrval = xmlGetAttrval(lincoef, "numberOfValues");
701  if( attrval == NULL )
702  {
703  SCIPerrorMessage("Attribute \"numberOfValues\" not found for <linearConstraintCoefficients> node.\n");
704  *doingfine = FALSE;
705  return SCIP_OKAY;
706  }
707 
708  nnz = (int)strtol(attrval, (char**)&attrval, 10);
709  if( *attrval != '\0' || nnz < 0 )
710  {
711  SCIPerrorMessage("Invalid value '%s' for \"numberOfValues\" attribute in <linearConstraintCoefficients> node.\n", xmlGetAttrval(lincoef, "numberOfValues"));
712  *doingfine = FALSE;
713  return SCIP_OKAY;
714  }
715  assert(nnz >= 0);
716 
717  /* check for start, rowIdx, colIdx, and value nodes */
718  startnode = xmlFindNodeMaxdepth(lincoef, "start", 0, 1);
719  if( startnode == NULL )
720  {
721  SCIPerrorMessage("Node <start> not found inside <linearConstraintCoefficients> node.\n");
722  *doingfine = FALSE;
723  return SCIP_OKAY;
724  }
725 
726  idxnode = xmlFindNodeMaxdepth(lincoef, "rowIdx", 0, 1);
727  if( idxnode != NULL )
728  {
729  if( xmlFindNodeMaxdepth(lincoef, "colIdx", 0, 1) != NULL )
730  {
731  SCIPerrorMessage("Both <rowIdx> and <colIdx> found under <linearConstraintCoefficients> node.\n");
732  *doingfine = FALSE;
733  return SCIP_OKAY;
734  }
735  rowmajor = FALSE;
736  }
737  else
738  {
739  idxnode = xmlFindNodeMaxdepth(lincoef, "colIdx", 0, 1);
740  if( idxnode == NULL )
741  {
742  SCIPerrorMessage("Both <rowIdx> and <colIdx> not found under <linearConstraintCoefficients> node.\n");
743  *doingfine = FALSE;
744  return SCIP_OKAY;
745  }
746  rowmajor = TRUE;
747  }
748 
749  valnode = xmlFindNodeMaxdepth(lincoef, "value", 0, 1);
750  if( valnode == NULL )
751  {
752  SCIPerrorMessage("<value> node not found under <linearConstraintCoefficients> node.\n");
753  *doingfine = FALSE;
754  return SCIP_OKAY;
755  }
756 
757  start = NULL;
758  idx = NULL;
759  val = NULL;
760 
761  /* read row or column start indices */
762  SCIP_CALL( SCIPallocBufferArray(scip, &start, (rowmajor ? nconss : nvars) + 1) );
763 
764  count = 0;
765  for( elnode = xmlFirstChild(startnode); elnode != NULL; elnode = xmlNextSibl(elnode), ++count )
766  {
767  /* check for <el> node and read it's data */
768  if( strcmp(xmlGetName(elnode), "el") != 0 )
769  {
770  SCIPerrorMessage("Expected <el> node under <start> node in <linearConstraintCoefficients>, but got '%s'.\n", xmlGetName(elnode));
771  *doingfine = FALSE;
772  goto CLEANUP;
773  }
774  if( count >= (rowmajor ? nconss : nvars) + 1 )
775  {
776  SCIPerrorMessage("Too many elements under <start> node in <linearConstraintCoefficients>, expected %d many, got at least %d.\n", (rowmajor ? nconss : nvars) + 1, count + 1);
777  *doingfine = FALSE;
778  goto CLEANUP;
779  }
780  if( xmlFirstChild(elnode) == NULL || xmlGetData(xmlFirstChild(elnode)) == NULL )
781  {
782  SCIPerrorMessage("No data in <el> node in <linearConstraintCoefficients>.\n");
783  *doingfine = FALSE;
784  goto CLEANUP;
785  }
786 
787  start[count] = (int)strtol(xmlGetData(xmlFirstChild(elnode)), (char**)&attrval, 10);
788 
789  if( *attrval != '\0' || start[count] < 0 || (start[count] > nnz) )
790  {
791  SCIPerrorMessage("Invalid value '%s' in <el> node under <start> node in <linearConstraintCoefficients>.\n", xmlGetData(elnode));
792  *doingfine = FALSE;
793  goto CLEANUP;
794  }
795 
796  /* add additional start-indices according to mult and incr attributes */
797  readMultIncr(elnode, &mult, &incrint, NULL, doingfine);
798  if( !*doingfine )
799  goto CLEANUP;
800 
801  for( --mult; mult > 0; --mult )
802  {
803  ++count;
804  if( count >= (rowmajor ? nconss : nvars) + 1 )
805  {
806  SCIPerrorMessage("Too many elements under <start> node in <linearConstraintCoefficients>, expected %d many, got at least %d.\n", (rowmajor ? nconss : nvars) + 1, count + 1);
807  *doingfine = FALSE;
808  goto CLEANUP;
809  }
810  start[count] = start[count-1] + incrint;
811  }
812  }
813  if( count != (rowmajor ? nconss : nvars) + 1 )
814  {
815  SCIPerrorMessage("Got only %d <start> entries in <linearConstraintCoefficients>, but expected %d many.\n", count, (rowmajor ? nconss : nvars) + 1);
816  *doingfine = FALSE;
817  goto CLEANUP;
818  }
819 
820  /* read row or column indices */
821  SCIP_CALL( SCIPallocBufferArray(scip, &idx, nnz) );
822 
823  count = 0;
824  for( elnode = xmlFirstChild(idxnode); elnode != NULL; elnode = xmlNextSibl(elnode), ++count )
825  {
826  /* check for <el> node and read it's data */
827  if( strcmp(xmlGetName(elnode), "el") != 0 )
828  {
829  SCIPerrorMessage("Expected <el> node under <%s> node in <linearConstraintCoefficients>, but got '%s'.\n", rowmajor ? "colIdx" : "rowIdx", xmlGetName(elnode));
830  *doingfine = FALSE;
831  goto CLEANUP;
832  }
833  if( count >= nnz )
834  {
835  SCIPerrorMessage("Too many elements under <%s> node in <linearConstraintCoefficients>, expected %d many, but got at least %d.\n", rowmajor ? "colIdx" : "rowIdx", nnz, count + 1);
836  *doingfine = FALSE;
837  goto CLEANUP;
838  }
839  if( xmlFirstChild(elnode) == NULL || xmlGetData(xmlFirstChild(elnode)) == NULL )
840  {
841  SCIPerrorMessage("No data in <el> node under <%s> node in <linearConstraintCoefficients>.\n", rowmajor ? "colIdx" : "rowIdx");
842  *doingfine = FALSE;
843  goto CLEANUP;
844  }
845 
846  idx[count] = (int)strtol(xmlGetData(xmlFirstChild(elnode)), (char**)&attrval, 10);
847 
848  if( *attrval != '\0' || idx[count] < 0 || (idx[count] >= (rowmajor ? nvars : nconss)) )
849  {
850  SCIPerrorMessage("Invalid value '%s' in <el> node under <%s> node in <linearConstraintCoefficients>.\n", xmlGetData(elnode), rowmajor ? "colIdx" : "rowIdx");
851  *doingfine = FALSE;
852  goto CLEANUP;
853  }
854 
855  /* add additional indices according to mult and incr attributes */
856  readMultIncr(elnode, &mult, &incrint, NULL, doingfine);
857  if( !*doingfine )
858  goto CLEANUP;
859 
860  for( --mult; mult > 0; --mult )
861  {
862  ++count;
863  if( count >= nnz )
864  {
865  SCIPerrorMessage("Too many elements under <%s> node in <linearConstraintCoefficients>, expected %d many, got at least %d.\n", rowmajor ? "colIdx" : "rowIdx", nnz, count + 1);
866  *doingfine = FALSE;
867  goto CLEANUP;
868  }
869  idx[count] = idx[count-1] + incrint;
870  }
871  }
872  if( count != nnz )
873  {
874  SCIPerrorMessage("Got only %d entries in <%s> node in <linearConstraintCoefficients>, expected %d many.\n", count, rowmajor ? "colIdx" : "rowIdx", nnz);
875  *doingfine = FALSE;
876  goto CLEANUP;
877  }
878 
879  /* read coefficient values */
880  SCIP_CALL( SCIPallocBufferArray(scip, &val, nnz) );
881 
882  count = 0;
883  for( elnode = xmlFirstChild(valnode); elnode != NULL; elnode = xmlNextSibl(elnode), ++count )
884  {
885  /* check for <el> node and read it's data */
886  if( strcmp(xmlGetName(elnode), "el") != 0 )
887  {
888  SCIPerrorMessage("Expected <el> node under <value> node in <linearConstraintCoefficients>, but got '%s'.\n", xmlGetName(elnode));
889  *doingfine = FALSE;
890  goto CLEANUP;
891  }
892  if( count >= nnz )
893  {
894  SCIPerrorMessage("Too many elements under <value> node in <linearConstraintCoefficients>, expected %d many, got at least %d.\n", nnz, count + 1);
895  *doingfine = FALSE;
896  goto CLEANUP;
897  }
898  if( xmlFirstChild(elnode) == NULL || xmlGetData(xmlFirstChild(elnode)) == NULL )
899  {
900  SCIPerrorMessage("No data in <el> node under <value> node in <linearConstraintCoefficients>.\n");
901  *doingfine = FALSE;
902  goto CLEANUP;
903  }
904 
905  val[count] = strtod(xmlGetData(xmlFirstChild(elnode)), (char**)&attrval);
906 
907  if( *attrval != '\0' || !SCIPisFinite(val[count]) )
908  {
909  SCIPerrorMessage("Invalid value '%s' in <el> node under <value> node in <linearConstraintCoefficients>.\n", xmlGetData(elnode));
910  *doingfine = FALSE;
911  goto CLEANUP;
912  }
913 
914  /* add additional values according to mult and incr attributes */
915  readMultIncr(elnode, &mult, NULL, &incrreal, doingfine);
916  if( !*doingfine )
917  goto CLEANUP;
918 
919  for( --mult; mult > 0; --mult )
920  {
921  ++count;
922  if( count >= nnz )
923  {
924  SCIPerrorMessage("Too many elements under <value> node in <linearConstraintCoefficients>, expected %d many, got at least %d.\n", nnz, count + 1);
925  *doingfine = FALSE;
926  goto CLEANUP;
927  }
928  val[count] = val[count-1] + incrreal;
929  }
930  }
931  if( count != nnz )
932  {
933  SCIPerrorMessage("Got only %d entries under <value> node in <linearConstraintCoefficients>, expected %d many.\n", count, nnz);
934  *doingfine = FALSE;
935  goto CLEANUP;
936  }
937 
938  /* add coefficients to linear constraints */
939  if( rowmajor )
940  {
941  int row;
942  int pos;
943  for( row = 0; row < nconss; ++row )
944  {
945  /* these asserts were checked above */
946  assert(start[row] >= 0);
947  assert(start[row+1] >= 0);
948  assert(start[row] <= nnz);
949  assert(start[row+1] <= nnz);
950  for( pos = start[row]; pos < start[row+1]; ++pos )
951  {
952  /* these asserts were checked above */
953  assert(pos >= 0);
954  assert(pos < nnz);
955  assert(idx[pos] >= 0);
956  assert(idx[pos] < nvars);
957 
958  assert(constypes[row] == LINEAR); /*lint !e613*/
959 
960  SCIP_CALL( SCIPaddCoefLinear(scip, conss[row], vars[idx[pos]], val[pos]) ); /*lint !e613*/
961  }
962  }
963  }
964  else
965  {
966  int col;
967  int pos;
968  for( col = 0; col < nvars; ++col )
969  {
970  /* these asserts were checked above */
971  assert(start[col] >= 0);
972  assert(start[col+1] >= 0);
973  assert(start[col] <= nnz);
974  assert(start[col+1] <= nnz);
975  for( pos = start[col]; pos < start[col+1]; ++pos )
976  {
977  /* these asserts were checked above */
978  assert(pos >= 0);
979  assert(pos < nnz);
980  assert(idx[pos] >= 0);
981  assert(idx[pos] < nconss);
982 
983  assert(constypes[idx[pos]] == LINEAR); /*lint !e613*/
984 
985  SCIP_CALL( SCIPaddCoefLinear(scip, conss[idx[pos]], vars[col], val[pos]) ); /*lint !e613*/
986  }
987  }
988  }
989 
990  CLEANUP:
991  SCIPfreeBufferArrayNull(scip, &val);
992  SCIPfreeBufferArrayNull(scip, &idx);
993  SCIPfreeBufferArrayNull(scip, &start);
994 
995  return SCIP_OKAY;
996 }
997 
998 /** read quadratic coefficients of constraints and objective */
999 static
1001  SCIP* scip, /**< SCIP data structure */
1002  const XML_NODE* datanode, /**< XML root node for instance data */
1003  SCIP_VAR** vars, /**< variables in order of OSiL indices */
1004  int nvars, /**< number of variables */
1005  SCIP_CONS** conss, /**< constraints in order of OSiL indices */
1006  CONSTYPE* constypes, /**< type of constraints (assumed to be LINEAR) */
1007  int nconss, /**< number of constraints */
1008  SCIP_CONS** objcons, /**< buffer to store constraint for nonlinear part of objective function, or to add to if already existing */
1009  CONSTYPE* objconstype, /**< buffer to store type of objective constraint, if created (should be QUADRATIC) */
1010  SCIP_Bool* doingfine /**< buffer to indicate whether no errors occured */
1011  )
1012 {
1013  const XML_NODE* quadcoef;
1014  const XML_NODE* qterm;
1015  const char* attrval;
1016  SCIP_CONS* cons;
1017  int nqterms;
1018  int count;
1019  int considx;
1020  int varidx1;
1021  int varidx2;
1022  SCIP_Real coef;
1023 
1024  assert(scip != NULL);
1025  assert(datanode != NULL);
1026  assert(vars != NULL || nvars == 0);
1027  assert(conss != NULL || nconss == 0);
1028  assert(constypes != NULL || nconss == 0);
1029  assert(objcons != NULL);
1030  assert(doingfine != NULL);
1031 
1032  quadcoef = xmlFindNodeMaxdepth(datanode, "quadraticCoefficients", 0, 1);
1033 
1034  if( quadcoef == NULL )
1035  return SCIP_OKAY;
1036 
1037  /* read number of quadratic terms */
1038  attrval = xmlGetAttrval(quadcoef, "numberOfQuadraticTerms");
1039  if( attrval == NULL )
1040  {
1041  SCIPerrorMessage("Attribute \"numberOfQuadraticTerms\" not found for <quadraticCoefficients> node.\n");
1042  *doingfine = FALSE;
1043  return SCIP_OKAY;
1044  }
1045 
1046  nqterms = (int)strtol(attrval, (char**)&attrval, 10);
1047  if( *attrval != '\0' || nqterms < 0 )
1048  {
1049  SCIPerrorMessage("Invalid value '%s' for \"numberOfQuadraticTerms\" attribute of <quadraticCoefficients> node.\n", xmlGetAttrval(quadcoef, "numberOfQuadraticTerms"));
1050  *doingfine = FALSE;
1051  return SCIP_OKAY;
1052  }
1053  assert(nqterms >= 0);
1054 
1055  count = 0;
1056  for( qterm = xmlFirstChild(quadcoef); qterm != NULL; qterm = xmlNextSibl(qterm), ++count )
1057  {
1058  /* check for qterm node */
1059  if( strcmp(xmlGetName(qterm), "qTerm") != 0 )
1060  {
1061  SCIPerrorMessage("Expected <qTerm> node under <quadraticCoefficients> node, but got <%s>\n", xmlGetName(qterm));
1062  *doingfine = FALSE;
1063  return SCIP_OKAY;
1064  }
1065  if( count >= nqterms )
1066  {
1067  SCIPerrorMessage("Too many quadratic terms under <quadraticCoefficients> node, expected %d many, but got at least %d.\n", nqterms, count + 1);
1068  *doingfine = FALSE;
1069  return SCIP_OKAY;
1070  }
1071 
1072  /* get constraint index, or -1 for objective */
1073  attrval = xmlGetAttrval(qterm, "idx");
1074  if( attrval == NULL )
1075  {
1076  SCIPerrorMessage("Missing \"idx\" attribute in %d'th <qTerm> node under <quadraticCoefficients> node.\n", count);
1077  *doingfine = FALSE;
1078  return SCIP_OKAY;
1079  }
1080 
1081  considx = (int)strtol(attrval, (char**)&attrval, 10);
1082  if( *attrval != '\0' || considx < -1 || considx >= nconss )
1083  {
1084  SCIPerrorMessage("Invalid value '%s' in \"idx\" attribute of %d'th <qTerm> node under <quadraticCoefficients> node.\n", xmlGetAttrval(qterm, "idx"), count);
1085  *doingfine = FALSE;
1086  return SCIP_OKAY;
1087  }
1088 
1089  /* get index of first variable */
1090  attrval = xmlGetAttrval(qterm, "idxOne");
1091  if( attrval == NULL )
1092  {
1093  SCIPerrorMessage("Missing \"idxOne\" attribute in %d'th <qTerm> node under <quadraticCoefficients> node.\n", count);
1094  *doingfine = FALSE;
1095  return SCIP_OKAY;
1096  }
1097 
1098  varidx1 = (int)strtol(attrval, (char**)&attrval, 10);
1099  if( *attrval != '\0' || varidx1 < 0 || varidx1 >= nvars )
1100  {
1101  SCIPerrorMessage("Invalid value '%s' in \"idxOne\" attribute of %d'th <qTerm> node under <quadraticCoefficients> node.\n", xmlGetAttrval(qterm, "idxOne"), count);
1102  *doingfine = FALSE;
1103  return SCIP_OKAY;
1104  }
1105 
1106  /* get index of second variable */
1107  attrval = xmlGetAttrval(qterm, "idxTwo");
1108  if( attrval == NULL )
1109  {
1110  SCIPerrorMessage("Missing \"idxTwo\" attribute in %d'th <qTerm> node under <quadraticCoefficients> node.\n", count);
1111  *doingfine = FALSE;
1112  return SCIP_OKAY;
1113  }
1114 
1115  varidx2 = (int)strtol(attrval, (char**)&attrval, 10);
1116  if( *attrval != '\0' || varidx2 < 0 || varidx2 >= nvars )
1117  {
1118  SCIPerrorMessage("Invalid value '%s' in \"idxTwo\" attribute of %d'th <qTerm> node under <quadraticCoefficients> node.\n", xmlGetAttrval(qterm, "idxTwo"), count);
1119  *doingfine = FALSE;
1120  return SCIP_OKAY;
1121  }
1122 
1123  /* get (optional) coefficient of quadratic term */
1124  attrval = xmlGetAttrval(qterm, "coef");
1125  if( attrval != NULL )
1126  {
1127  coef = strtod(attrval, (char**)&attrval);
1128  if( *attrval != '\0' || (coef != coef) ) /*lint !e777*/
1129  {
1130  SCIPerrorMessage("Invalid value '%s' in \"coef\" attribute of %d'th <qTerm> node under <quadraticCoefficients> node.\n", xmlGetAttrval(qterm, "coef"), count);
1131  *doingfine = FALSE;
1132  return SCIP_OKAY;
1133  }
1134  }
1135  else
1136  {
1137  /* default is 1.0 according to specification */
1138  coef = 1.0;
1139  }
1140 
1141  /* skip zero coefficients */
1142  if( coef == 0.0 )
1143  continue;
1144 
1145  if( considx == -1 )
1146  {
1147  if( *objcons == NULL )
1148  {
1149  /* create constraint to hold quadratic part of objective; note that
1150  * reading/{initialconss,dynamicconss,dynamicrows,dynamiccols} apply only to model constraints and
1151  * variables, not to an auxiliary objective constraint (otherwise it can happen that an auxiliary objective
1152  * variable is loose with infinite best bound, triggering the problem that an LP that is unbounded because
1153  * of loose variables with infinite best bound cannot be solved)
1154  */
1155 
1156  SCIP_VAR* objvar;
1157  SCIP_Real minusone;
1158 
1159  SCIP_CALL( SCIPcreateVar(scip, &objvar, "objvar", -SCIPinfinity(scip), SCIPinfinity(scip), 1.0,
1161  SCIP_CALL( SCIPaddVar(scip, objvar) );
1162 
1163  minusone = -1.0;
1164  SCIP_CALL( SCIPcreateConsQuadratic(scip, objcons, "objcons", 1, &objvar, &minusone, 0, NULL, NULL, NULL,
1165  SCIPgetObjsense(scip) == SCIP_OBJSENSE_MINIMIZE ? -SCIPinfinity(scip) : 0.0,
1166  SCIPgetObjsense(scip) == SCIP_OBJSENSE_MAXIMIZE ? SCIPinfinity(scip) : 0.0,
1167  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
1168  *objconstype = QUADRATIC;
1169 
1170  SCIP_CALL( SCIPreleaseVar(scip, &objvar) );
1171  }
1172  cons = *objcons;
1173  assert(*objconstype == QUADRATIC);
1174  }
1175  else if( constypes[considx] == LINEAR ) /*lint !e613*/
1176  {
1177  /* replace linear constraint by quadratic constraint */
1178  cons = conss[considx]; /*lint !e613*/
1179 
1181  SCIPgetNVarsLinear(scip, cons), SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons),
1182  0, NULL, NULL, NULL,
1183  SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons),
1187 
1188  SCIP_CALL( SCIPreleaseCons(scip, &conss[considx]) ); /*lint !e613*/
1189 
1190  conss[considx] = cons; /*lint !e613*/
1191  constypes[considx] = QUADRATIC; /*lint !e613*/
1192  }
1193  else
1194  {
1195  cons = conss[considx]; /*lint !e613*/
1196  assert(constypes[considx] == QUADRATIC); /*lint !e613*/
1197  }
1198 
1199  SCIP_CALL( SCIPaddBilinTermQuadratic(scip, cons, vars[varidx1], vars[varidx2], coef) ); /*lint !e613*/
1200  }
1201 
1202  if( count != nqterms )
1203  {
1204  SCIPerrorMessage("Got only %d quadratic terms under <quadraticCoefficients> node, but expected %d many.\n", count, nqterms);
1205  *doingfine = FALSE;
1206  return SCIP_OKAY;
1207  }
1208 
1209  return SCIP_OKAY;
1210 }
1211 
1212 /** transforms OSnL expression tree into SCIP expression */
1213 static
1215  SCIP* scip, /**< SCIP data structure */
1216  SCIP_EXPR** expr, /**< buffer to store pointer to created expression */
1217  const XML_NODE* node, /**< root node of expression to be read */
1218  int* exprvaridx, /**< array with index of problem variables in expression graph */
1219  int* nexprvars, /**< number of variables in currently processed expression so far */
1220  int nvars, /**< total number of variables in problem (and length of exprvaridx array) */
1221  SCIP_Bool* doingfine /**< buffer to indicate whether no errors occurred */
1222  )
1223 {
1224  const char* exprname;
1225 
1226  assert(scip != NULL);
1227  assert(expr != NULL);
1228  assert(node != NULL);
1229  assert(exprvaridx != NULL || nvars == 0);
1230  assert(nexprvars != NULL);
1231  assert(doingfine != NULL);
1232 
1233  exprname = xmlGetName(node);
1234  assert(exprname != NULL);
1235 
1236  *expr = NULL;
1237 
1238  /* zero argument operands */
1239  if( strcmp(exprname, "variable") == 0 )
1240  {
1241  const char* attrval;
1242  SCIP_Real coef;
1243  int idx;
1244 
1245  /* read variable index */
1246  attrval = xmlGetAttrval(node, "idx");
1247  if( attrval == NULL )
1248  {
1249  SCIPerrorMessage("Attribute \"idx\" required for <variable> node in nonlinear expression\n");
1250  *doingfine = FALSE;
1251  return SCIP_OKAY;
1252  }
1253 
1254  idx = (int)strtol(attrval, (char**)&attrval, 10);
1255  if( *attrval != '\0' || idx < 0 || idx >= nvars )
1256  {
1257  SCIPerrorMessage("Invalid value '%s' in \"idx\" attribute of <variable> node in nonlinear expression.\n", xmlGetAttrval(node, "idx"));
1258  *doingfine = FALSE;
1259  return SCIP_OKAY;
1260  }
1261 
1262  /* read variable coefficient */
1263  attrval = xmlGetAttrval(node, "coef");
1264  if( attrval != NULL )
1265  {
1266  coef = strtod(attrval, (char**)&attrval);
1267  if( *attrval != '\0' || !SCIPisFinite(coef) )
1268  {
1269  SCIPerrorMessage("Invalid value '%s' in \"coef\" attribute of <variable> node in nonlinear expression.\n", xmlGetAttrval(node, "coef"));
1270  *doingfine = FALSE;
1271  return SCIP_OKAY;
1272  }
1273  }
1274  else
1275  {
1276  coef = 1.0;
1277  }
1278 
1279  /* assign index to variable, if we see it the first time */
1280  if( exprvaridx[idx] == -1 ) /*lint !e613*/
1281  {
1282  exprvaridx[idx] = *nexprvars; /*lint !e613*/
1283  ++*nexprvars;
1284  }
1285 
1286  /* create VARIDX expression, put into LINEAR expression if we have coefficient != 1 */
1287  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_VARIDX, exprvaridx[idx]) ); /*lint !e613*/
1288  if( coef != 1.0 )
1289  {
1290  SCIP_CALL( SCIPexprCreateLinear(SCIPblkmem(scip), expr, 1, expr, &coef, 0.0) );
1291  }
1292 
1293  return SCIP_OKAY;
1294  }
1295 
1296  if( strcmp(exprname, "number") == 0 )
1297  {
1298  const char* attrval;
1299  SCIP_Real val;
1300 
1301  attrval = xmlGetAttrval(node, "type");
1302  if( attrval != NULL && (strcmp(attrval, "real") != 0) )
1303  {
1304  SCIPerrorMessage("Type '%s' for <number> node in nonlinear expression not supported.\n", attrval);
1305  *doingfine = FALSE;
1306  return SCIP_OKAY;
1307  }
1308 
1309  attrval = xmlGetAttrval(node, "value");
1310  if( attrval != NULL )
1311  {
1312  val = strtod(attrval, (char**)&attrval);
1313  if( *attrval != '\0' || !SCIPisFinite(val) )
1314  {
1315  SCIPerrorMessage("Invalid value '%s' in \"value\" attribute of <number> node in nonlinear expression.\n", xmlGetAttrval(node, "value"));
1316  *doingfine = FALSE;
1317  return SCIP_OKAY;
1318  }
1319  }
1320  else
1321  {
1322  /* according to OSnL.xsd, the value attribute is optional
1323  * I guess the default is the empty string, which should correspond to 0.0
1324  */
1325  val = 0.0;
1326  }
1327 
1328  /* create CONST expression */
1329  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_CONST, val) );
1330 
1331  return SCIP_OKAY;
1332  }
1333 
1334  if( strcmp(exprname, "PI") == 0 )
1335  {
1336  /* create CONST expression with PI value*/
1338 
1339  return SCIP_OKAY;
1340  }
1341 
1342  if( strcmp(exprname, "E") == 0 )
1343  {
1344  /* create CONST expression with E value*/
1345  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_CONST, M_E) );
1346 
1347  return SCIP_OKAY;
1348  }
1349 
1350 
1351  /* single argument operands */
1352  if( strcmp(exprname, "negate") == 0 ||
1353  strcmp(exprname, "abs") == 0 ||
1354  strcmp(exprname, "squareRoot") == 0 ||
1355  strcmp(exprname, "sqrt") == 0 ||
1356  strcmp(exprname, "square") == 0 ||
1357  strcmp(exprname, "exp") == 0 ||
1358  strcmp(exprname, "ln") == 0 ||
1359  strcmp(exprname, "log10") == 0
1360  )
1361  {
1362  SCIP_EXPR* arg;
1363 
1364  /* check number of children */
1365  if( xmlFirstChild(node) == NULL || xmlNextSibl(xmlFirstChild(node)) != NULL )
1366  {
1367  SCIPerrorMessage("Expected exactly one child in <%s> node in nonlinear expression\n", exprname);
1368  *doingfine = FALSE;
1369  return SCIP_OKAY;
1370  }
1371 
1372  /* read child expression */
1373  SCIP_CALL( readExpression(scip, &arg, xmlFirstChild(node), exprvaridx, nexprvars, nvars, doingfine) );
1374  if( !*doingfine )
1375  return SCIP_OKAY;
1376 
1377  /* create SCIP expression according to expression name */
1378  if( strcmp(exprname, "negate") == 0 )
1379  {
1380  SCIP_Real minusone;
1381 
1382  minusone = -1.0;
1383  SCIP_CALL( SCIPexprCreateLinear(SCIPblkmem(scip), expr, 1, &arg, &minusone, 0.0) );
1384  }
1385  else if( strcmp(exprname, "abs") == 0 )
1386  {
1387  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_ABS, arg) );
1388  }
1389  else if( strcmp(exprname, "squareRoot") == 0 || strcmp(exprname, "sqrt") == 0 )
1390  {
1391  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_SQRT, arg) );
1392  }
1393  else if( strcmp(exprname, "square") == 0 )
1394  {
1395  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_SQUARE, arg) );
1396  }
1397  else if( strcmp(exprname, "exp") == 0 )
1398  {
1399  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_EXP, arg) );
1400  }
1401  else if( strcmp(exprname, "ln") == 0 )
1402  {
1403  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_LOG, arg) );
1404  }
1405  else /* if( strcmp(exprname, "log10") == 0 ) */
1406  {
1407  /* log10(expr) = ln(expr)*1/ln(10) */
1408  SCIP_EXPR* tmp;
1409 
1410  assert(strcmp(exprname, "log10") == 0);
1411 
1412  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &tmp, SCIP_EXPR_CONST, 1.0/log(10.0)) );
1413  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &arg, SCIP_EXPR_LOG, arg) );
1414  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_MUL, arg, tmp) );
1415  }
1416 
1417  return SCIP_OKAY;
1418  }
1419 
1420  /* two argument operands */
1421  if( strcmp(exprname, "plus") == 0 ||
1422  strcmp(exprname, "minus") == 0 ||
1423  strcmp(exprname, "times") == 0 ||
1424  strcmp(exprname, "divide") == 0 ||
1425  strcmp(exprname, "power") == 0 ||
1426  strcmp(exprname, "log") == 0
1427  )
1428  {
1429  SCIP_EXPR* arg1;
1430  SCIP_EXPR* arg2;
1431 
1432  /* check number of children */
1433  if( xmlFirstChild(node) == NULL ||
1434  xmlNextSibl(xmlFirstChild(node)) == NULL ||
1436  {
1437  SCIPerrorMessage("Expected exactly two children in <%s> node in nonlinear expression.\n", exprname);
1438  *doingfine = FALSE;
1439  return SCIP_OKAY;
1440  }
1441 
1442  /* read first child expression */
1443  SCIP_CALL( readExpression(scip, &arg1, xmlFirstChild(node), exprvaridx, nexprvars, nvars, doingfine) );
1444  if( !*doingfine )
1445  return SCIP_OKAY;
1446 
1447  /* read second child expression */
1448  SCIP_CALL( readExpression(scip, &arg2, xmlNextSibl(xmlFirstChild(node)), exprvaridx, nexprvars, nvars, doingfine) );
1449  if( !*doingfine )
1450  {
1451  SCIPexprFreeDeep(SCIPblkmem(scip), &arg1);
1452  return SCIP_OKAY;
1453  }
1454 
1455  if( strcmp(exprname, "plus") == 0 )
1456  {
1457  SCIP_CALL( SCIPexprAdd(SCIPblkmem(scip), expr, 1.0, arg1, 1.0, arg2, 0.0) );
1458  /* SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_PLUS, arg1, arg2) ); */
1459  }
1460  else if( strcmp(exprname, "minus") == 0 )
1461  {
1462  SCIP_CALL( SCIPexprAdd(SCIPblkmem(scip), expr, 1.0, arg1, -1.0, arg2, 0.0) );
1463  /* SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_MINUS, arg1, arg2) ); */
1464  }
1465  else if( strcmp(exprname, "times") == 0 )
1466  {
1467  if( SCIPexprGetOperator(arg1) == SCIP_EXPR_CONST )
1468  {
1469  SCIP_CALL( SCIPexprMulConstant(SCIPblkmem(scip), expr, arg2, SCIPexprGetOpReal(arg1)) );
1470  SCIPexprFreeDeep(SCIPblkmem(scip), &arg1);
1471  }
1472  else if( SCIPexprGetOperator(arg2) == SCIP_EXPR_CONST )
1473  {
1474  SCIP_CALL( SCIPexprMulConstant(SCIPblkmem(scip), expr, arg1, SCIPexprGetOpReal(arg2)) );
1475  SCIPexprFreeDeep(SCIPblkmem(scip), &arg2);
1476  }
1477  else
1478  {
1479  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_MUL, arg1, arg2) );
1480  }
1481  }
1482  else if( strcmp(exprname, "divide") == 0 )
1483  {
1484  if( SCIPexprGetOperator(arg2) == SCIP_EXPR_CONST )
1485  {
1486  assert(SCIPexprGetOpReal(arg2) != 0.0);
1487  SCIP_CALL( SCIPexprMulConstant(SCIPblkmem(scip), expr, arg1, 1.0/SCIPexprGetOpReal(arg2)) );
1488  SCIPexprFreeDeep(SCIPblkmem(scip), &arg2);
1489  }
1490  else
1491  {
1492  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_DIV, arg1, arg2) );
1493  }
1494  }
1495  else if( strcmp(exprname, "power") == 0 )
1496  {
1497  if( SCIPexprGetOperator(arg2) == SCIP_EXPR_CONST )
1498  {
1499  /* expr^number is intpower or realpower */
1500  if( SCIPisIntegral(scip, SCIPexprGetOpReal(arg2)) )
1501  {
1502  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_INTPOWER, arg1, (int)SCIPround(scip, SCIPexprGetOpReal(arg2))) );
1503  }
1504  else
1505  {
1507  }
1508  SCIPexprFreeDeep(SCIPblkmem(scip), &arg2);
1509  }
1510  else if( SCIPexprGetOperator(arg1) == SCIP_EXPR_CONST )
1511  {
1512  /* number^arg2 is exp(arg2 * ln(number)) */
1513  if( SCIPexprGetOpReal(arg1) < 0.0 )
1514  {
1515  SCIPerrorMessage("Negative base in <power> node with nonconstant exponent not allowed in nonlinear expression.\n");
1516  SCIPexprFreeDeep(SCIPblkmem(scip), &arg1);
1517  SCIPexprFreeDeep(SCIPblkmem(scip), &arg2);
1518  *doingfine = FALSE;
1519  return SCIP_OKAY;
1520  }
1521  else
1522  {
1523  SCIP_EXPR* tmp;
1524 
1526  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &tmp, SCIP_EXPR_MUL, tmp, arg2) );
1527  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_EXP, tmp) );
1528  SCIPexprFreeDeep(SCIPblkmem(scip), &arg1);
1529  }
1530  }
1531  else
1532  {
1533  /* arg1^arg2 is exp(arg2 * ln(arg1)) */
1534  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &arg1, SCIP_EXPR_LOG, arg1) );
1535  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &arg2, SCIP_EXPR_MUL, arg1, arg2) );
1536  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_EXP, arg2) );
1537  }
1538  }
1539  else if( strcmp(exprname, "log") == 0 )
1540  {
1541  /* logarithm of arg2 w.r.t. base arg1 = ln(arg2) / ln(arg1) */
1542  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &arg1, SCIP_EXPR_LOG, arg1) );
1543  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &arg2, SCIP_EXPR_LOG, arg2) );
1544  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_DIV, arg2, arg1) );
1545  }
1546  else if( strcmp(exprname, "min") == 0 )
1547  {
1548  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_MIN, arg1, arg2) );
1549  }
1550  else /* if( strcmp(exprname, "max") == 0 ) */
1551  {
1552  assert(strcmp(exprname, "max") == 0);
1553 
1554  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_MAX, arg1, arg2) );
1555  }
1556 
1557  return SCIP_OKAY;
1558  }
1559 
1560  /* arbitrary argument operands */
1561  if( strcmp(exprname, "sum") == 0 || strcmp(exprname, "product") == 0 )
1562  {
1563  const XML_NODE* argnode;
1564  SCIP_EXPR** args;
1565  int nargs;
1566  int argssize;
1567 
1568  /* a sum or product w.r.t. 0 arguments is constant */
1569  if( xmlFirstChild(node) == NULL )
1570  {
1571  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_CONST, (strcmp(exprname, "sum") == 0) ? 0.0 : 1.0) );
1572 
1573  return SCIP_OKAY;
1574  }
1575 
1576  /* read all child expressions */
1577  argssize = 5;
1578  SCIP_CALL( SCIPallocBufferArray(scip, &args, argssize) );
1579 
1580  nargs = 0;
1581  for( argnode = xmlFirstChild(node); argnode != NULL; argnode = xmlNextSibl(argnode), ++nargs )
1582  {
1583  if( nargs >= argssize )
1584  {
1585  argssize = SCIPcalcMemGrowSize(scip, nargs + 1);
1586  SCIP_CALL( SCIPreallocBufferArray(scip, &args, argssize) );
1587  }
1588  assert(nargs < argssize);
1589 
1590  SCIP_CALL( readExpression(scip, &args[nargs], argnode, exprvaridx, nexprvars, nvars, doingfine) );
1591  if( !*doingfine )
1592  {
1593  assert(args[nargs] == NULL);
1594  break;
1595  }
1596  }
1597 
1598  if( *doingfine )
1599  {
1600  switch( nargs )
1601  {
1602  case 0:
1603  {
1604  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_CONST, (strcmp(exprname, "sum") == 0) ? 0.0 : 1.0) );
1605  break;
1606  }
1607  case 1:
1608  {
1609  *expr = args[0];
1610  break;
1611  }
1612  case 2:
1613  {
1614  if( strcmp(exprname, "sum") == 0 )
1615  {
1616  SCIP_CALL( SCIPexprAdd(SCIPblkmem(scip), expr, 1.0, args[0], 1.0, args[1], 0.0) );
1617  }
1618  else
1619  {
1620  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_MUL, args[0], args[1]) );
1621  }
1622  break;
1623  }
1624  default:
1625  {
1626  /* create sum or product expression */
1627  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, (strcmp(exprname, "sum") == 0) ? SCIP_EXPR_SUM : SCIP_EXPR_PRODUCT, nargs, args) );
1628  break;
1629  }
1630  }
1631  }
1632  else
1633  {
1634  /* cleanup if parsing error */
1635  for( ; nargs > 0; --nargs )
1636  SCIPexprFreeDeep(SCIPblkmem(scip), &args[nargs-1]);
1637  }
1638 
1639  SCIPfreeBufferArray(scip, &args);
1640 
1641  return SCIP_OKAY;
1642  }
1643 
1644  if( strcmp(exprname, "min") == 0 || strcmp(exprname, "max") == 0 )
1645  {
1646  const XML_NODE* argnode;
1647  SCIP_EXPROP exprop;
1648  SCIP_EXPR* arg2;
1649 
1650  /* check that we have children */
1651  if( xmlFirstChild(node) == NULL )
1652  {
1653  SCIPerrorMessage("Expected at least one child in <%s> node of nonlinear expression.\n", exprname);
1654  *doingfine = FALSE;
1655  return SCIP_OKAY;
1656  }
1657 
1658  /* read expression corresponding to first child and store in expr */
1659  argnode = xmlFirstChild(node);
1660  SCIP_CALL( readExpression(scip, expr, argnode, exprvaridx, nexprvars, nvars, doingfine) );
1661  if( !*doingfine )
1662  {
1663  assert(*expr == NULL);
1664  return SCIP_OKAY;
1665  }
1666  arg2 = NULL;
1667 
1668  exprop = (strcmp(exprname, "min") == 0) ? SCIP_EXPR_MIN : SCIP_EXPR_MAX;
1669 
1670  /* read expressions corresponding to other children in arg and store exprop(expr, arg) in expr */
1671  for( argnode = xmlNextSibl(argnode); argnode != NULL; argnode = xmlNextSibl(argnode) )
1672  {
1673  assert(arg2 == NULL);
1674  SCIP_CALL( readExpression(scip, &arg2, argnode, exprvaridx, nexprvars, nvars, doingfine) );
1675  if( !*doingfine )
1676  {
1677  assert(arg2 == NULL);
1678  break;
1679  }
1680 
1681  assert(*expr != NULL);
1682  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, exprop, *expr, arg2) );
1683  arg2 = NULL;
1684  }
1685 
1686  if( !*doingfine )
1687  {
1688  /* cleanup if failure */
1689  SCIPexprFreeDeep(SCIPblkmem(scip), expr);
1690  }
1691  assert(arg2 == NULL);
1692 
1693  return SCIP_OKAY;
1694  }
1695 
1696  if( strcmp(exprname, "quadratic") == 0 )
1697  {
1698  const char* attrval;
1699  const XML_NODE* qterm;
1700  SCIP_QUADELEM* quadelems;
1701  int nquadelems;
1702  int quadelemssize;
1703  int* quadvarsidxs;
1704  int nquadvars;
1705  int i;
1706 
1707  quadelemssize = 5;
1708  SCIP_CALL( SCIPallocBufferArray(scip, &quadelems, quadelemssize) );
1709  nquadelems = 0;
1710 
1711  SCIP_CALL( SCIPallocBufferArray(scip, &quadvarsidxs, nvars) );
1712  for( i = 0; i < nvars; ++i )
1713  quadvarsidxs[i] = -1;
1714  nquadvars = 0;
1715 
1716  /* read quadratic terms */
1717  for( qterm = xmlFirstChild(node); qterm != NULL; qterm = xmlNextSibl(qterm), ++nquadelems )
1718  {
1719  /* check for qpTerm node */
1720  if( strcmp(xmlGetName(qterm), "qpTerm") != 0 )
1721  {
1722  SCIPerrorMessage("Unexpected <%s> node under <quadratic> node in nonlinear expression, expected <qpTerm>.\n", xmlGetName(qterm));
1723  *doingfine = FALSE;
1724  break;
1725  }
1726 
1727  if( nquadelems >= quadelemssize )
1728  {
1729  quadelemssize = SCIPcalcMemGrowSize(scip, nquadelems + 1);
1730  SCIP_CALL( SCIPreallocBufferArray(scip, &quadelems, quadelemssize) );
1731  }
1732  assert(quadelemssize > nquadelems);
1733 
1734  /* get index of first variable */
1735  attrval = xmlGetAttrval(qterm, "idxOne");
1736  if( attrval == NULL )
1737  {
1738  SCIPerrorMessage("Missing \"idxOne\" attribute in %d'th <qpTerm> node under <quadratic> node in nonlinear expression.\n", nquadelems);
1739  *doingfine = FALSE;
1740  break;
1741  }
1742 
1743  quadelems[nquadelems].idx1 = (int)strtol(attrval, (char**)&attrval, 10);
1744  if( *attrval != '\0' || quadelems[nquadelems].idx1 < 0 || quadelems[nquadelems].idx1 >= nvars )
1745  {
1746  SCIPerrorMessage("Invalid value '%s' for \"idxOne\" attribute of %d'th <qpTerm> node under <quadratic> node in nonlinear expression.\n", xmlGetAttrval(qterm, "idxOne"), nquadelems);
1747  *doingfine = FALSE;
1748  break;
1749  }
1750 
1751  /* get index of second variable */
1752  attrval = xmlGetAttrval(qterm, "idxTwo");
1753  if( attrval == NULL )
1754  {
1755  SCIPerrorMessage("Missing \"idxTwo\" attribute in %d'th <qpTerm> node under <quadratic> node in nonlinear expression.\n", nquadelems);
1756  *doingfine = FALSE;
1757  break;
1758  }
1759 
1760  quadelems[nquadelems].idx2 = (int)strtol(attrval, (char**)&attrval, 10);
1761  if( *attrval != '\0' || quadelems[nquadelems].idx2 < 0 || quadelems[nquadelems].idx2 >= nvars )
1762  {
1763  SCIPerrorMessage("Invalid value '%s' for \"idxTwo\" attribute of %d'th <qpTerm> node under <quadratic> node in nonlinear expression.\n", xmlGetAttrval(qterm, "idxTwo"), nquadelems);
1764  *doingfine = FALSE;
1765  break;
1766  }
1767 
1768  /* get coefficient */
1769  attrval = xmlGetAttrval(qterm, "coef");
1770  if( attrval != NULL )
1771  {
1772  quadelems[nquadelems].coef = strtod(attrval, (char**)&attrval);
1773  if( *attrval != '\0' || (quadelems[nquadelems].coef != quadelems[nquadelems].coef) ) /*lint !e777*/
1774  {
1775  SCIPerrorMessage("Invalid value '%s' for \"coef\" attribute of %d'th <qpTerm> node under <quadratic> node in nonlinear expression.\n", xmlGetAttrval(qterm, "coef"), nquadelems);
1776  *doingfine = FALSE;
1777  break;
1778  }
1779  }
1780  else
1781  {
1782  quadelems[nquadelems].coef = 1.0;
1783  }
1784 
1785  /* get index for first variable in quadratic element */
1786  if( quadvarsidxs[quadelems[nquadelems].idx1] < 0 )
1787  {
1788  quadvarsidxs[quadelems[nquadelems].idx1] = nquadvars;
1789  quadelems[nquadelems].idx1 = nquadvars;
1790 
1791  ++nquadvars;
1792  }
1793  else
1794  {
1795  quadelems[nquadelems].idx1 = quadvarsidxs[quadelems[nquadelems].idx1];
1796  }
1797 
1798  /* get index for second variable in quadratic element */
1799  if( quadvarsidxs[quadelems[nquadelems].idx2] < 0 )
1800  {
1801  quadvarsidxs[quadelems[nquadelems].idx2] = nquadvars;
1802  quadelems[nquadelems].idx2 = nquadvars;
1803 
1804  ++nquadvars;
1805  }
1806  else
1807  {
1808  quadelems[nquadelems].idx2 = quadvarsidxs[quadelems[nquadelems].idx2];
1809  }
1810 
1811  /* swap indices if in wrong order */
1812  if( quadelems[nquadelems].idx1 > quadelems[nquadelems].idx2 )
1813  {
1814  int tmp;
1815 
1816  tmp = quadelems[nquadelems].idx1;
1817  quadelems[nquadelems].idx1 = quadelems[nquadelems].idx2;
1818  quadelems[nquadelems].idx2 = tmp;
1819  }
1820  }
1821 
1822  if( *doingfine )
1823  {
1824  SCIP_EXPR** children;
1825 
1826  /* setup array with children expressions corresponding to variables */
1827  SCIP_CALL( SCIPallocBufferArray(scip, &children, nquadvars) );
1828  for( i = 0; i < nvars; ++i )
1829  {
1830  if( quadvarsidxs[i] == -1 )
1831  continue;
1832 
1833  /* assign new index to variable, if we see it the first time in this exprtree */
1834  if( exprvaridx[i] == -1 ) /*lint !e613*/
1835  {
1836  exprvaridx[i] = *nexprvars; /*lint !e613*/
1837  ++*nexprvars;
1838  }
1839 
1840  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &children[quadvarsidxs[i]], SCIP_EXPR_VARIDX, exprvaridx[i]) ); /*lint !e613*/
1841  }
1842 
1843  /* create quadratic expression */
1844  SCIP_CALL( SCIPexprCreateQuadratic(SCIPblkmem(scip), expr, nquadvars, children, 0.0, NULL, nquadelems, quadelems) );
1845 
1846  SCIPfreeBufferArray(scip, &children);
1847  }
1848 
1849  SCIPfreeBufferArray(scip, &quadelems);
1850  SCIPfreeBufferArray(scip, &quadvarsidxs);
1851  }
1852 
1853 
1854  SCIPerrorMessage("Expression operand <%s> in nonlinear expression not supported by SCIP so far.\n", exprname);
1855  *doingfine = FALSE;
1856 
1857  return SCIP_OKAY;
1858 }
1859 
1860 
1861 /** read nonlinear expressions of constraints and objective */
1862 static
1864  SCIP* scip, /**< SCIP data structure */
1865  const XML_NODE* datanode, /**< XML root node for instance data */
1866  SCIP_VAR** vars, /**< variables in order of OSiL indices */
1867  int nvars, /**< number of variables */
1868  SCIP_CONS** conss, /**< constraints in order of OSiL indices */
1869  CONSTYPE* constypes, /**< type of constraints (assumed to be LINEAR) */
1870  int nconss, /**< number of constraints */
1871  SCIP_CONS** objcons, /**< buffer to store constraint for nonlinear part of objective function, or to add to if already existing */
1872  CONSTYPE* objconstype, /**< buffer to store type of objective constraint, if created (should be QUADRATIC) */
1873  SCIP_Bool* doingfine /**< buffer to indicate whether no errors occurred */
1874  )
1875 {
1876  const XML_NODE* nlexprs;
1877  const XML_NODE* nlexpr;
1878  const char* attrval;
1879  SCIP_EXPRTREE* exprtree;
1880  SCIP_EXPR* expr;
1881  SCIP_VAR** exprvars;
1882  int* exprvaridx;
1883  SCIP_RETCODE retcode;
1884  int nexprvars;
1885  int nnlexprs;
1886  int count;
1887  int considx;
1888  int i;
1889 
1890  assert(scip != NULL);
1891  assert(datanode != NULL);
1892  assert(vars != NULL || nvars == 0);
1893  assert(conss != NULL || nconss == 0);
1894  assert(constypes != NULL || nconss == 0);
1895  assert(objcons != NULL);
1896  assert(doingfine != NULL);
1897 
1898  retcode = SCIP_OKAY;
1899 
1900  nlexprs = xmlFindNodeMaxdepth(datanode, "nonlinearExpressions", 0, 1);
1901 
1902  if( nlexprs == NULL )
1903  return SCIP_OKAY;
1904 
1905  /* get number of nonlinear expressions */
1906  attrval = xmlGetAttrval(nlexprs, "numberOfNonlinearExpressions");
1907  if( attrval == NULL )
1908  {
1909  SCIPerrorMessage("Attribute \"numberOfNonlinearExpressions\" in <nonlinearExpressions> node not found.\n");
1910  *doingfine = FALSE;
1911  return SCIP_OKAY;
1912  }
1913 
1914  nnlexprs = (int)strtol(attrval, (char**)&attrval, 10);
1915  if( *attrval != '\0' || nnlexprs < 0 )
1916  {
1917  SCIPerrorMessage("Invalid value '%s' for \"numberOfNonlinearExpressions\" attribute in <nonlinearExpressions>.\n", xmlGetAttrval(nlexprs, "numberOfNonlinearExpressions"));
1918  *doingfine = FALSE;
1919  return SCIP_OKAY;
1920  }
1921  assert(nnlexprs >= 0);
1922 
1923  /* buffer array to store index of variable in expression graph, or -1 if not present */
1924  SCIP_CALL( SCIPallocBufferArray(scip, &exprvaridx, nvars) );
1925  SCIP_CALL( SCIPallocBufferArray(scip, &exprvars, nvars) );
1926 
1927  /* read nonlinear expressions and store in constraints */
1928  count = 0;
1929  for( nlexpr = xmlFirstChild(nlexprs); nlexpr != NULL; nlexpr = xmlNextSibl(nlexpr), ++count )
1930  {
1931  if( strcmp(xmlGetName(nlexpr), "nl") != 0 )
1932  {
1933  SCIPerrorMessage("Expected <nl> node under <nonlinearExpressions> node, but got '%s'.\n", xmlGetName(nlexpr));
1934  *doingfine = FALSE;
1935  break;
1936  }
1937  if( count >= nnlexprs )
1938  {
1939  SCIPerrorMessage("Too many nonlinear expressions under <nonlinearExpressions> node, expected %d many, but got at least %d.\n", nnlexprs, count + 1);
1940  *doingfine = FALSE;
1941  break;
1942  }
1943 
1944  /* treat empty expression as 0.0 and continue */
1945  if( xmlFirstChild(nlexprs) == NULL )
1946  continue;
1947 
1948  /* get constraint index, or -1 for objective */
1949  attrval = xmlGetAttrval(nlexpr, "idx");
1950  if( attrval == NULL )
1951  {
1952  SCIPerrorMessage("Missing \"idx\" attribute in %d'th <nl> node under <nonlinearExpressions> node.\n", count);
1953  *doingfine = FALSE;
1954  break;
1955  }
1956 
1957  considx = (int)strtol(attrval, (char**)&attrval, 10);
1958  if( *attrval != '\0' || considx < -1 || considx >= nconss )
1959  {
1960  SCIPerrorMessage("Invalid value '%s' in \"idx\" attribute of %d'th <nl> node under <nonlinearExpressions> node.\n", xmlGetAttrval(nlexpr, "idx"), count);
1961  *doingfine = FALSE;
1962  break;
1963  }
1964 
1965  expr = NULL;
1966  nexprvars = 0;
1967  for( i = 0; i < nvars; ++i )
1968  exprvaridx[i] = -1;
1969 
1970  /* turn OSiL expression into SCIP expression and assign indices to variables */
1971  SCIP_CALL( readExpression(scip, &expr, xmlFirstChild(nlexpr), exprvaridx, &nexprvars, nvars, doingfine) );
1972  if( !*doingfine )
1973  {
1974  assert(expr == NULL);
1975  break;
1976  }
1977 
1978  /* assemble array with SCIP_VAR*'s */
1979  for( i = 0; i < nvars; ++i )
1980  {
1981  assert(exprvaridx[i] < nexprvars );
1982 
1983  if( exprvaridx[i] >= 0 )
1984  exprvars[exprvaridx[i]] = vars[i]; /*lint !e613*/
1985  }
1986 
1987  /* create expression tree */
1988  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), &exprtree, expr, nexprvars, 0, NULL) );
1989  SCIP_CALL( SCIPexprtreeSetVars(exprtree, nexprvars, exprvars) );
1990 
1991  /* add expression tree to objective or constraint */
1992  if( considx == -1 && *objcons == NULL )
1993  {
1994  /* create constraint to hold nonlinear part of objective; note that
1995  * reading/{initialconss,dynamicconss,dynamicrows,dynamiccols} apply only to model constraints and variables,
1996  * not to an auxiliary objective constraint (otherwise it can happen that an auxiliary objective variable is
1997  * loose with infinite best bound, triggering the problem that an LP that is unbounded because of loose
1998  * variables with infinite best bound cannot be solved)
1999  */
2000 
2001  SCIP_VAR* objvar;
2002  SCIP_Real minusone;
2003  SCIP_Real one;
2004 
2005  SCIP_CALL( SCIPcreateVar(scip, &objvar, "objvar", -SCIPinfinity(scip), SCIPinfinity(scip), 1.0,
2007  SCIP_CALL( SCIPaddVar(scip, objvar) );
2008 
2009  minusone = -1.0;
2010  one = 1.0;
2011  SCIP_CALL_TERMINATE( retcode, SCIPcreateConsNonlinear(scip, objcons, "objcons", 1, &objvar, &minusone, 1, &exprtree, &one,
2012  SCIPgetObjsense(scip) == SCIP_OBJSENSE_MINIMIZE ? -SCIPinfinity(scip) : 0.0,
2013  SCIPgetObjsense(scip) == SCIP_OBJSENSE_MAXIMIZE ? SCIPinfinity(scip) : 0.0,
2014  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE), TERMINATE );
2015  *objconstype = NONLINEAR;
2016 
2017  SCIP_CALL( SCIPreleaseVar(scip, &objvar) );
2018  }
2019  else
2020  {
2021  SCIP_CONS** cons;
2022  SCIP_CONS* oldcons;
2023  CONSTYPE* constype;
2024 
2025  if( considx == -1 )
2026  {
2027  cons = objcons;
2028  constype = objconstype;
2029  }
2030  else
2031  {
2032  cons = &conss[considx]; /*lint !e613*/
2033  constype = &constypes[considx]; /*lint !e613*/
2034  }
2035  oldcons = *cons;
2036 
2037  /* replace cons by nonlinear constraint or add to already existing nonlinear constraint */
2038  switch( *constype )
2039  {
2040  case LINEAR:
2041  {
2042  SCIP_Real one;
2043 
2044  one = 1.0;
2045  SCIP_CALL_TERMINATE( retcode, SCIPcreateConsNonlinear(scip, cons, SCIPconsGetName(*cons),
2046  SCIPgetNVarsLinear(scip, *cons), SCIPgetVarsLinear(scip, *cons), SCIPgetValsLinear(scip, *cons),
2047  1, &exprtree, &one,
2048  SCIPgetLhsLinear(scip, *cons), SCIPgetRhsLinear(scip, *cons),
2052  SCIPconsIsStickingAtNode(*cons)), TERMINATE );
2053 
2054  SCIP_CALL( SCIPreleaseCons(scip, &oldcons) );
2055 
2056  break;
2057  }
2058 
2059  case QUADRATIC:
2060  {
2061  SCIP_EXPRTREE* exprtrees[2];
2062  SCIP_Real exprcoefs[2];
2063 
2064  SCIP_EXPR* quadexpr;
2065  SCIP_QUADELEM* quadelems;
2066  SCIP_Real* lincoefs;
2067  SCIP_EXPR** children;
2068  SCIP_QUADVARTERM* quadvarterms;
2069  SCIP_BILINTERM* bilinterms;
2070  int nquadelems;
2071  int nquadvars;
2072  int nbilin;
2073  int j;
2074 
2075  exprtrees[0] = exprtree;
2076  exprcoefs[0] = 1.0;
2077 
2078  /* turn quadratic part into expression tree */
2079  SCIP_CALL( SCIPsortQuadVarTermsQuadratic(scip, *cons) );
2080 
2081  quadvarterms = SCIPgetQuadVarTermsQuadratic(scip, *cons);
2082  nquadvars = SCIPgetNQuadVarTermsQuadratic(scip, *cons);
2083  bilinterms = SCIPgetBilinTermsQuadratic(scip, *cons);
2084  nbilin = SCIPgetNBilinTermsQuadratic(scip, *cons);
2085 
2086  SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nquadvars) );
2087  SCIP_CALL( SCIPallocBufferArray(scip, &children, nquadvars) );
2088  SCIP_CALL( SCIPallocBufferArray(scip, &quadelems, nbilin + nquadvars) );
2089  nquadelems = 0;
2090 
2091  for( i = 0; i < nquadvars; ++i )
2092  {
2093  lincoefs[i] = quadvarterms[i].lincoef;
2094  exprvars[i] = quadvarterms[i].var;
2095 
2096  if( quadvarterms[i].sqrcoef != 0.0 )
2097  {
2098  quadelems[nquadelems].idx1 = i;
2099  quadelems[nquadelems].idx2 = i;
2100  quadelems[nquadelems].coef = quadvarterms[i].sqrcoef;
2101  ++nquadelems;
2102  }
2103 
2104  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &children[i], SCIP_EXPR_VARIDX, i) );
2105 
2106  for( j = 0; j < quadvarterms[i].nadjbilin; ++j )
2107  {
2108  if( bilinterms[quadvarterms[i].adjbilin[j]].var1 == quadvarterms[i].var )
2109  {
2110  int otheridx;
2111 
2112  assert(bilinterms[quadvarterms[i].adjbilin[j]].var2 != quadvarterms[i].var);
2113 
2114  SCIP_CALL( SCIPfindQuadVarTermQuadratic(scip, *cons, bilinterms[quadvarterms[i].adjbilin[j]].var2, &otheridx) );
2115  assert(otheridx >= 0);
2116  assert(otheridx < nquadvars);
2117 
2118  quadelems[nquadelems].idx1 = MIN(i, otheridx);
2119  quadelems[nquadelems].idx2 = MAX(i, otheridx);
2120  quadelems[nquadelems].coef = bilinterms[quadvarterms[i].adjbilin[j]].coef;
2121  ++nquadelems;
2122  }
2123  }
2124  }
2125 
2126  SCIP_CALL( SCIPexprCreateQuadratic(SCIPblkmem(scip), &quadexpr, nquadvars, children, 0.0, lincoefs, nquadelems, quadelems) );
2127  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), &exprtrees[1], quadexpr, nquadvars, 0, NULL) );
2128  SCIP_CALL( SCIPexprtreeSetVars(exprtrees[1], nquadvars, exprvars) );
2129  exprcoefs[1] = 1.0;
2130 
2131  SCIPfreeBufferArray(scip, &lincoefs);
2132  SCIPfreeBufferArray(scip, &children);
2133  SCIPfreeBufferArray(scip, &quadelems);
2134 
2135  SCIP_CALL_TERMINATE( retcode, SCIPcreateConsNonlinear(scip, cons, SCIPconsGetName(*cons),
2136  SCIPgetNLinearVarsNonlinear(scip, *cons), SCIPgetLinearVarsNonlinear(scip, *cons),
2137  SCIPgetLinearCoefsNonlinear(scip, *cons), 2, exprtrees, exprcoefs,
2138  SCIPgetLhsNonlinear(scip, *cons), SCIPgetRhsNonlinear(scip, *cons),
2142  SCIPconsIsStickingAtNode(*cons)), TERMINATE );
2143 
2144  SCIP_CALL( SCIPreleaseCons(scip, &oldcons) );
2145 
2146  break;
2147  }
2148 
2149  case NONLINEAR:
2150  {
2151  SCIP_Real one;
2152 
2153  one = 1.0;
2154  SCIP_CALL( SCIPaddExprtreesNonlinear(scip, *cons, 1, &exprtree, &one) );
2155  break;
2156  }
2157  }
2158 
2159  *constype = NONLINEAR;
2160  }
2161  /* cppcheck-suppress unusedLabel */
2162  TERMINATE:
2163  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
2164 
2165  if( retcode != SCIP_OKAY )
2166  break;
2167  }
2168 
2169  SCIPfreeBufferArray(scip, &exprvars);
2170  SCIPfreeBufferArray(scip, &exprvaridx);
2171 
2172  SCIP_CALL( retcode );
2173 
2174  return SCIP_OKAY;
2175 }
2176 
2177 
2178 /** read sos1 and sos2 constraints
2179  *
2180  * sos constraints are expected to be given as a node of <instanceData> in the following way:
2181  * @code
2182  * <specialOrderedSets numberOfSpecialOrderedSets="1">
2183  * <sos numberOfVar="2" order="2">
2184  * <var idx="1"></var>
2185  * <var idx="2"></var>
2186  * </sos>
2187  * </specialOrderedSets>
2188  * @endcode
2189  * Weights are determined by the order in which the variables are given
2190  *
2191  */
2192 static
2194  SCIP* scip, /**< SCIP data structure */
2195  const XML_NODE* datanode, /**< XML root node for instance data */
2196  SCIP_VAR** vars, /**< variables in order of OSiL indices */
2197  int nvars, /**< number of variables */
2198  SCIP_Bool initialconss, /**< should model constraints be marked as initial? */
2199  SCIP_Bool dynamicconss, /**< should model constraints be subject to aging? */
2200  SCIP_Bool dynamicrows, /**< should rows be added and removed dynamically to the LP? */
2201  SCIP_Bool* doingfine /**< buffer to indicate whether no errors occurred */
2202  )
2203 {
2204  const XML_NODE* soscons;
2205  const XML_NODE* sosvar;
2206  const char* attrval;
2207  int nsoscons;
2208  int nsosvars;
2209  int sosorder;
2210  int type;
2211  int count;
2212  int varcount;
2213  int idx;
2214  SCIP_Bool initial;
2215  SCIP_Bool separate;
2216  SCIP_Bool enforce;
2217  SCIP_Bool check;
2218  SCIP_Bool propagate;
2219  SCIP_Bool local;
2220  SCIP_Bool modifiable;
2221  SCIP_Bool dynamic;
2222  SCIP_Bool removable;
2223  char name[SCIP_MAXSTRLEN];
2224 
2225  /* standard settings for SOS constraints: */
2226  initial = initialconss;
2227  separate = TRUE;
2228  enforce = TRUE;
2229  check = TRUE;
2230  propagate = TRUE;
2231  local = FALSE;
2232  modifiable = FALSE;
2233  dynamic = dynamicconss;
2234  removable = dynamicrows;
2235 
2236  soscons= xmlFindNodeMaxdepth(datanode, "specialOrderedSets", 0, 1);
2237 
2238  if( soscons== NULL )
2239  return SCIP_OKAY;
2240 
2241  /* get number of sos constraints */
2242  attrval = xmlGetAttrval(soscons, "numberOfSOS");
2243  if( attrval == NULL )
2244  {
2245  SCIPerrorMessage("Attribute \"numberOfSOS in <specialOrderedSets> node not found.\n");
2246  *doingfine = FALSE;
2247  return SCIP_OKAY;
2248  }
2249 
2250  nsoscons = (int)strtol(attrval, (char**)&attrval, 10);
2251  if( *attrval != '\0' || nsoscons < 0 )
2252  {
2253  SCIPerrorMessage("Invalid value '%s' for \"numberOfSOS\" attribute in <specialOrderedSets>.\n", xmlGetAttrval(soscons, "numberOfSOS"));
2254  *doingfine = FALSE;
2255  return SCIP_OKAY;
2256  }
2257  assert(nsoscons >= 0);
2258 
2259  /* read sos constraints and create corresponding constraint */
2260  count = 0;
2261  for( soscons = xmlFirstChild(soscons); soscons != NULL; soscons = xmlNextSibl(soscons), ++count )
2262  {
2263  SCIP_CONS* cons;
2264 
2265  /* Make sure we get a sos node and not more then announced*/
2266  if( strcmp(xmlGetName(soscons), "sos") != 0 )
2267  {
2268  SCIPerrorMessage("Expected <sos> node under <specialOrderedSet> node, but got '%s'.\n", xmlGetName(soscons));
2269  *doingfine = FALSE;
2270  break;
2271  }
2272 
2273  if( count >= nsoscons)
2274  {
2275  SCIPerrorMessage("Too many sos under <specialOrderedSets> node, expected %d many, but got at least %d.\n", nsoscons, count + 1);
2276  *doingfine = FALSE;
2277  break;
2278  }
2279 
2280  /* get number of variables in this sos constraint */
2281  attrval = xmlGetAttrval(soscons, "numberOfVar");
2282  if( attrval == NULL )
2283  {
2284  SCIPerrorMessage("Attribute \"numberOfVar in <sos> node not found.\n");
2285  *doingfine = FALSE;
2286  return SCIP_OKAY;
2287  }
2288 
2289  nsosvars = (int)strtol(attrval, (char**)&attrval, 10);
2290  if( *attrval != '\0' || nsosvars < 0 )
2291  {
2292  SCIPerrorMessage("Invalid value '%s' for \"numberOfVar\" attribute in <sos>.\n", xmlGetAttrval(soscons, "numberOfVar"));
2293  *doingfine = FALSE;
2294  return SCIP_OKAY;
2295  }
2296  assert(nsosvars >= 0);
2297 
2298  /* get order of this sos constraint */
2299  attrval = xmlGetAttrval(soscons, "type");
2300  if( attrval == NULL )
2301  {
2302  SCIPerrorMessage("Attribute \"order\" in <sos> node not found.\n");
2303  *doingfine = FALSE;
2304  return SCIP_OKAY;
2305  }
2306 
2307  sosorder = (int)strtol(attrval, (char**)&attrval, 10);
2308  if( *attrval != '\0' || sosorder < 0 || sosorder > 2 )
2309  {
2310  SCIPerrorMessage("Invalid/unsupported value '%s' for \"order\" attribute in <sos>.\n", xmlGetAttrval(soscons, "order"));
2311  *doingfine = FALSE;
2312  return SCIP_OKAY;
2313  }
2314  assert(sosorder == 1 || sosorder == 2);
2315  type = sosorder;
2316 
2317  /* set artificial name for sos constraint*/
2318  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "SOS%d_%d", type, count);
2319 
2320  /* Create sos constraint */
2321  switch( type )
2322  {
2323  case 1:
2324  SCIP_CALL( SCIPcreateConsSOS1(scip, &cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate,
2325  local, modifiable, dynamic, removable) );
2326  break;
2327  case 2:
2328  SCIP_CALL( SCIPcreateConsSOS2(scip, &cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate,
2329  local, modifiable, dynamic, removable) );
2330  break;
2331  default:
2332  SCIPerrorMessage("unknown SOS type: <%d>\n", type); /* should not happen */
2333  SCIPABORT();
2334  return SCIP_INVALIDDATA; /*lint !e527*/
2335  }
2336 
2337  varcount = 0;
2338  for( sosvar = xmlFirstChild(soscons); sosvar!= NULL; sosvar = xmlNextSibl(sosvar), ++varcount )
2339  {
2340  /* get variable id*/
2341  attrval = xmlGetAttrval(sosvar, "idx");
2342  if( attrval == NULL )
2343  {
2344  SCIPerrorMessage("Attribute \"idx\" in <var> node below <specialOrderedSets> node not found.\n");
2345  *doingfine = FALSE;
2346  return SCIP_OKAY;
2347  }
2348 
2349  idx = (int)strtol(attrval, (char**)&attrval, 10);
2350  if( *attrval != '\0' || idx < 0 || idx > nvars - 1 )
2351  {
2352  SCIPerrorMessage("Invalid value '%s' for \"idx\" attribute in <var>.\n", xmlGetAttrval(sosvar, "idx"));
2353  *doingfine = FALSE;
2354  return SCIP_OKAY;
2355  }
2356  assert(idx >= 0);
2357 
2358  /* we now know that we have a variable/weight pair -> add variable*/
2359  switch( type )
2360  {
2361  case 1:
2362  SCIP_CALL( SCIPaddVarSOS1(scip, cons, vars[idx], (SCIP_Real) (nsosvars - varcount)) );
2363  break;
2364  case 2:
2365  SCIP_CALL( SCIPaddVarSOS2(scip, cons, vars[idx], (SCIP_Real) (nsosvars - varcount)) );
2366  break;
2367  default:
2368  SCIPerrorMessage("unknown SOS type: <%d>\n", type); /* should not happen */
2369  SCIPABORT();
2370  return SCIP_INVALIDDATA; /*lint !e527*/
2371  }
2372  } /* Close loop over variables in sos constraint */
2373 
2374  /* add the SOS constraint */
2375  SCIP_CALL( SCIPaddCons(scip, cons) );
2376  }
2377 
2378  return SCIP_OKAY;
2379 }
2380 
2381  /*
2382  * Callback methods of reader
2383  */
2384 
2385 
2386 /** copy method for reader plugins (called when SCIP copies plugins) */
2387 static
2388 SCIP_DECL_READERCOPY(readerCopyOsil)
2389 { /*lint --e{715}*/
2390  assert(scip != NULL);
2391 
2393 
2394  return SCIP_OKAY;
2395 }
2396 
2397 /** problem reading method of reader */
2398 static
2399 SCIP_DECL_READERREAD(readerReadOsil)
2400 { /*lint --e{715}*/
2401  const char* name;
2402  XML_NODE* start;
2403  const XML_NODE* header;
2404  const XML_NODE* data;
2405  SCIP_RETCODE retcode;
2406  SCIP_Bool doingfine;
2407  SCIP_Bool initialconss;
2408  SCIP_Bool dynamicconss;
2409  SCIP_Bool dynamiccols;
2410  SCIP_Bool dynamicrows;
2411  SCIP_VAR** vars;
2412  int nvars;
2413  SCIP_CONS** conss;
2414  CONSTYPE* constypes;
2415  int nconss;
2416  SCIP_CONS* objcons;
2417  CONSTYPE objconstype;
2418  int i;
2419 
2420  assert(scip != NULL);
2421  assert(reader != NULL);
2422  assert(result != NULL);
2423  assert(filename != NULL);
2424 
2425  *result = SCIP_DIDNOTRUN;
2426  retcode = SCIP_READERROR;
2427  doingfine = TRUE;
2428  vars = NULL;
2429  nvars = 0;
2430  conss = NULL;
2431  constypes = NULL;
2432  nconss = 0;
2433  objcons = NULL;
2434 
2435  /* read OSiL xml file */
2436  start = xmlProcess(filename);
2437 
2438  if( start == NULL )
2439  {
2440  SCIPerrorMessage("Some error occurred when parsing the OSiL XML file '%s'.\n", filename);
2441  goto CLEANUP;
2442  }
2443 
2444  SCIPdebug( xmlShowNode(start) );
2445 
2446  /* parse header to get problem name */
2447  name = filename;
2448  header = xmlFindNodeMaxdepth(start, "instanceHeader", 0, 2);
2449  if( header != NULL )
2450  {
2451  const XML_NODE* namenode;
2452 
2453  namenode = xmlFindNodeMaxdepth(header, "name", 0, 2);
2454 
2455  if( namenode != NULL && xmlFirstChild(namenode) != NULL )
2456  name = xmlGetData(xmlFirstChild(namenode));
2457  else
2458  {
2459  namenode = xmlFindNodeMaxdepth(header, "description", 0, 2);
2460 
2461  if( namenode != NULL && xmlFirstChild(namenode) != NULL )
2462  name = xmlGetData(xmlFirstChild(namenode));
2463  }
2464  }
2465 
2466  /* create SCIP problem */
2468 
2469  /* process instance data */
2470  data = xmlFindNodeMaxdepth(start, "instanceData", 0, 2);
2471  if( data == NULL )
2472  {
2473  SCIPerrorMessage("Node <instanceData> not found.\n");
2474  goto CLEANUP;
2475  }
2476 
2477  SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &initialconss) );
2478  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &dynamicconss) );
2479  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &dynamiccols) );
2480  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &dynamicrows) );
2481 
2482  /* read variables */
2483  SCIP_CALL_TERMINATE( retcode, readVariables(scip, data, &vars, &nvars, initialconss, dynamicconss, dynamiccols, dynamicrows, &doingfine), CLEANUP );
2484  if( !doingfine )
2485  goto CLEANUP;
2486  assert(vars != NULL || nvars == 0);
2487 
2488  /* read objective sense, coefficient, and constant */
2489  SCIP_CALL_TERMINATE( retcode, readObjective(scip, data, vars, nvars, dynamiccols, &doingfine), CLEANUP );
2490  if( !doingfine )
2491  goto CLEANUP;
2492 
2493  /* read constraint data (names, constants, lhs/rhs) */
2494  SCIP_CALL_TERMINATE( retcode, readConstraints(scip, data, &conss, &constypes, &nconss, initialconss, dynamicconss, dynamicrows, &doingfine), CLEANUP );
2495  if( !doingfine )
2496  goto CLEANUP;
2497  assert(conss != NULL || nconss == 0);
2498 
2499  /* read linear coefficients matrix */
2500  SCIP_CALL_TERMINATE( retcode, readLinearCoefs(scip, data, vars, nvars, conss, constypes, nconss, &doingfine), CLEANUP );
2501  if( !doingfine )
2502  goto CLEANUP;
2503 
2504  /* read quadratic coefficients (turns linear constraints into quadratic ones, may create objcons) */
2505  SCIP_CALL_TERMINATE( retcode, readQuadraticCoefs(scip, data, vars, nvars, conss, constypes, nconss, &objcons, &objconstype, &doingfine), CLEANUP );
2506  if( !doingfine )
2507  goto CLEANUP;
2508 
2509  /* read nonlinear expressions (turns constraints into nonlinear ones, may create objcons) */
2510  SCIP_CALL_TERMINATE( retcode, readNonlinearExprs(scip, data, vars, nvars, conss, constypes, nconss, &objcons, &objconstype, &doingfine), CLEANUP );
2511  if( !doingfine )
2512  goto CLEANUP;
2513 
2514  /* add constraints to problem */
2515  for( i = 0; i < nconss; ++i )
2516  {
2517  assert(conss[i] != NULL); /*lint !e613*/
2518  SCIP_CALL( SCIPaddCons(scip, conss[i]) ); /*lint !e613*/
2519  }
2520  if( objcons != NULL )
2521  {
2522  SCIP_CALL( SCIPaddCons(scip, objcons) );
2523  }
2524 
2525  /* read sos2 constraints and add to problem*/
2526  SCIP_CALL_TERMINATE( retcode, readSOScons(scip, data, vars, nvars, initialconss, dynamicconss, dynamicrows, &doingfine), CLEANUP );
2527  if( !doingfine )
2528  goto CLEANUP;
2529 
2530 
2531  *result = SCIP_SUCCESS;
2532  retcode = SCIP_OKAY;
2533 
2534  CLEANUP:
2535  /* free xml data */
2536  if( start != NULL )
2537  xmlFreeNode(start);
2538 
2539  /* free variables */
2540  for( i = 0; i < nvars; ++i )
2541  {
2542  SCIP_CALL( SCIPreleaseVar(scip, &vars[i]) ); /*lint !e613*/
2543  }
2544  SCIPfreeBufferArrayNull(scip, &vars);
2545 
2546  /* free constraints */
2547  for( i = 0; i < nconss; ++i )
2548  {
2549  SCIP_CALL( SCIPreleaseCons(scip, &conss[i]) ); /*lint !e613*/
2550  }
2551  SCIPfreeBufferArrayNull(scip, &conss);
2552  SCIPfreeBufferArrayNull(scip, &constypes);
2553 
2554  if( objcons != NULL )
2555  {
2556  SCIP_CALL( SCIPreleaseCons(scip, &objcons) );
2557  }
2558 
2559  /* return read error retcode if something went wrong */
2560  if( !doingfine )
2561  return SCIP_READERROR;
2562 
2563  if( retcode == SCIP_PLUGINNOTFOUND )
2564  retcode = SCIP_READERROR;
2565 
2566  SCIP_CALL( retcode );
2567 
2568  return SCIP_OKAY;
2569 }
2570 
2571 /*
2572  * reader specific interface methods
2573  */
2574 
2575 /** includes the osil file reader in SCIP */
2577  SCIP* scip /**< SCIP data structure */
2578  )
2579 {
2580  SCIP_READER* reader;
2581 
2582  /* include osil reader */
2584 
2585  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyOsil) );
2586  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadOsil) );
2587 
2588  return SCIP_OKAY;
2589 }
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
void SCIPexprFreeDeep(BMS_BLKMEM *blkmem, SCIP_EXPR **expr)
Definition: expr.c:6142
#define READER_EXTENSION
Definition: reader_osil.c:43
static SCIP_RETCODE readNonlinearExprs(SCIP *scip, const XML_NODE *datanode, SCIP_VAR **vars, int nvars, SCIP_CONS **conss, CONSTYPE *constypes, int nconss, SCIP_CONS **objcons, CONSTYPE *objconstype, SCIP_Bool *doingfine)
Definition: reader_osil.c:1863
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8140
#define READER_NAME
Definition: reader_osil.c:41
static SCIP_DECL_READERCOPY(readerCopyOsil)
Definition: reader_osil.c:2388
SCIP_EXPROP SCIPexprGetOperator(SCIP_EXPR *expr)
Definition: expr.c:5654
#define SCIP_MAXSTRLEN
Definition: def.h:215
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:9778
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:45601
SCIP_RETCODE SCIPaddVarSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real weight)
Definition: cons_sos2.c:2388
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18384
CONSTYPE
Definition: reader_osil.c:50
#define FALSE
Definition: def.h:64
#define M_PI
Definition: string.c:42
SCIP_Real * SCIPgetLinearCoefsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:45816
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:9340
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8160
SCIP_Real SCIPgetRhsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPexprtreeSetVars(SCIP_EXPRTREE *tree, int nvars, SCIP_VAR **vars)
Definition: nlp.c:111
XML_NODE * xmlProcess(const char *filename)
Definition: xmlparse.c:1069
OS instance language (OSiL) format file reader.
const XML_NODE * xmlFirstChild(const XML_NODE *node)
Definition: xmlparse.c:1453
const char * xmlGetData(const XML_NODE *node)
Definition: xmlparse.c:1493
SCIP_RETCODE SCIPexprtreeCreate(BMS_BLKMEM *blkmem, SCIP_EXPRTREE **tree, SCIP_EXPR *root, int nvars, int nparams, SCIP_Real *params)
Definition: expr.c:8702
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:21937
SCIP_RETCODE SCIPaddExprtreesNonlinear(SCIP *scip, SCIP_CONS *cons, int nexprtrees, SCIP_EXPRTREE **exprtrees, SCIP_Real *coefs)
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8150
static SCIP_RETCODE readSOScons(SCIP *scip, const XML_NODE *datanode, SCIP_VAR **vars, int nvars, SCIP_Bool initialconss, SCIP_Bool dynamicconss, SCIP_Bool dynamicrows, SCIP_Bool *doingfine)
Definition: reader_osil.c:2193
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_RETCODE SCIPcreateConsQuadratic(SCIP *scip, SCIP_CONS **cons, const char *name, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int nquadterms, SCIP_VAR **quadvars1, SCIP_VAR **quadvars2, SCIP_Real *quadcoefs, 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)
int SCIPgetNQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNBilinTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
void xmlShowNode(const XML_NODE *root)
Definition: xmlparse.c:1293
SCIP_Real coef
Definition: type_expr.h:102
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition: scip.c:10898
#define READER_DESC
Definition: reader_osil.c:42
static SCIP_DECL_READERREAD(readerReadOsil)
Definition: reader_osil.c:2399
SCIP_RETCODE SCIPexprCreateQuadratic(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real constant, SCIP_Real *lincoefs, int nquadelems, SCIP_QUADELEM *quadelems)
Definition: expr.c:6543
SCIP_RETCODE SCIPfindQuadVarTermQuadratic(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, int *pos)
#define SCIPerrorMessage
Definition: pub_message.h:45
enum SCIP_ExprOp SCIP_EXPROP
Definition: type_expr.h:89
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12410
static SCIP_RETCODE readExpression(SCIP *scip, SCIP_EXPR **expr, const XML_NODE *node, int *exprvaridx, int *nexprvars, int nvars, SCIP_Bool *doingfine)
Definition: reader_osil.c:1214
struct XML_NODE_struct XML_NODE
Definition: xml.h:41
SCIP_RETCODE SCIPaddVarSOS1(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real weight)
Definition: cons_sos1.c:10459
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:21938
const XML_NODE * xmlFindNodeMaxdepth(const XML_NODE *node, const char *name, int depth, int maxdepth)
Definition: xmlparse.c:1403
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:45519
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7881
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8100
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16552
constraint handler for quadratic constraints
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip.c:4369
#define NULL
Definition: lpi_spx1.cpp:137
#define SCIP_CALL(x)
Definition: def.h:306
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8120
SCIP_BILINTERM * SCIPgetBilinTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPexprMulConstant(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, SCIP_EXPR *term, SCIP_Real factor)
Definition: expr.c:6363
SCIP_RETCODE SCIPincludeReaderOsil(SCIP *scip)
Definition: reader_osil.c:2576
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:21448
SCIP_RETCODE SCIPexprAdd(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, SCIP_Real coef1, SCIP_EXPR *term1, SCIP_Real coef2, SCIP_EXPR *term2, SCIP_Real constant)
Definition: expr.c:6205
SCIP_RETCODE SCIPaddBilinTermQuadratic(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var1, SCIP_VAR *var2, SCIP_Real coef)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:21925
#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:5201
SCIP_Real SCIPgetLhsNonlinear(SCIP *scip, SCIP_CONS *cons)
constraint handler for nonlinear constraints
static SCIP_RETCODE readLinearCoefs(SCIP *scip, const XML_NODE *datanode, SCIP_VAR **vars, int nvars, SCIP_CONS **conss, CONSTYPE *constypes, int nconss, SCIP_Bool *doingfine)
Definition: reader_osil.c:660
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_RETCODE SCIPexprCreate(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, SCIP_EXPROP op,...)
Definition: expr.c:5934
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8080
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8050
SCIP_RETCODE SCIPexprtreeFree(SCIP_EXPRTREE **tree)
Definition: expr.c:8783
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:17237
SCIPInterval log(const SCIPInterval &x)
Constraint handler for linear constraints in their most general form, .
const char * xmlGetName(const XML_NODE *node)
Definition: xmlparse.c:1473
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
Definition: scip.c:5239
static SCIP_RETCODE readConstraints(SCIP *scip, const XML_NODE *datanode, SCIP_CONS ***conss, CONSTYPE **constypes, int *nconss, SCIP_Bool initialconss, SCIP_Bool dynamicconss, SCIP_Bool dynamicrows, SCIP_Bool *doingfine)
Definition: reader_osil.c:424
static SCIP_RETCODE readObjective(SCIP *scip, const XML_NODE *datanode, SCIP_VAR **vars, int nvars, SCIP_Bool dynamiccols, SCIP_Bool *doingfine)
Definition: reader_osil.c:278
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 void readMultIncr(const XML_NODE *node, int *mult, int *incrint, SCIP_Real *incrreal, SCIP_Bool *doingfine)
Definition: reader_osil.c:594
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:45900
int SCIPgetNLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:11311
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPexprGetOpReal(SCIP_EXPR *expr)
Definition: expr.c:5695
const char * xmlGetAttrval(const XML_NODE *node, const char *name)
Definition: xmlparse.c:1321
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27323
SCIP_RETCODE SCIPsortQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE readQuadraticCoefs(SCIP *scip, const XML_NODE *datanode, SCIP_VAR **vars, int nvars, SCIP_CONS **conss, CONSTYPE *constypes, int nconss, SCIP_CONS **objcons, CONSTYPE *objconstype, SCIP_Bool *doingfine)
Definition: reader_osil.c:1000
#define SCIP_Real
Definition: def.h:135
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8130
SCIP_VAR ** SCIPgetLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
#define MIN(x, y)
Definition: memory.c:75
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:327
static SCIP_RETCODE readVariables(SCIP *scip, const XML_NODE *datanode, SCIP_VAR ***vars, int *nvars, SCIP_Bool initialconss, SCIP_Bool dynamicconss, SCIP_Bool dynamiccols, SCIP_Bool dynamicrows, SCIP_Bool *doingfine)
Definition: reader_osil.c:64
constraint handler for SOS type 1 constraints
SCIP_RETCODE SCIPcreateConsNonlinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int nexprtrees, SCIP_EXPRTREE **exprtrees, SCIP_Real *nonlincoefs, 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)
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8070
#define SCIP_INVALID
Definition: def.h:155
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8060
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip.c:5287
#define SCIPisFinite(x)
Definition: pub_misc.h:1601
declarations for XML parsing
SCIP_OBJSENSE SCIPgetObjsense(SCIP *scip)
Definition: scip.c:10881
SCIP_RETCODE SCIPcreateConsBounddisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds, 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_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsSOS1(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *weights, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_sos1.c:10322
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:60
constraint handler for SOS type 2 constraints
SCIP_RETCODE SCIPcreateConsSOS2(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *weights, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_sos2.c:2289
void xmlFreeNode(XML_NODE *node)
Definition: xmlparse.c:1259
SCIP_QUADVARTERM * SCIPgetQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
Definition: scip.c:45949
SCIP_RETCODE SCIPexprCreateLinear(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real *coefs, SCIP_Real constant)
Definition: expr.c:6461
constraint handler for bound disjunction constraints
#define SCIPABORT()
Definition: def.h:278
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
Definition: scip.c:45961
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:45937
const XML_NODE * xmlNextSibl(const XML_NODE *node)
Definition: xmlparse.c:1433
SCIP callable library.
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:21929