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