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