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-2018 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not 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 
1190  SCIPgetNVarsLinear(scip, cons), SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons),
1191  0, NULL, NULL, NULL,
1192  SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons),
1196 
1197  SCIP_CALL( SCIPreleaseCons(scip, &conss[considx]) ); /*lint !e613*/
1198 
1199  conss[considx] = cons; /*lint !e613*/
1200  constypes[considx] = QUADRATIC; /*lint !e613*/
1201  }
1202  else
1203  {
1204  cons = conss[considx]; /*lint !e613*/
1205  assert(constypes[considx] == QUADRATIC); /*lint !e613*/
1206  }
1207 
1208  SCIP_CALL( SCIPaddBilinTermQuadratic(scip, cons, vars[varidx1], vars[varidx2], coef) ); /*lint !e613*/
1209  }
1210 
1211  if( count != nqterms )
1212  {
1213  SCIPerrorMessage("Got only %d quadratic terms under <quadraticCoefficients> node, but expected %d many.\n", count, nqterms);
1214  *doingfine = FALSE;
1215  return SCIP_OKAY;
1216  }
1217 
1218  return SCIP_OKAY;
1219 }
1220 
1221 /** transforms OSnL expression tree into SCIP expression */
1222 static
1224  SCIP* scip, /**< SCIP data structure */
1225  SCIP_EXPR** expr, /**< buffer to store pointer to created expression */
1226  const XML_NODE* node, /**< root node of expression to be read */
1227  int* exprvaridx, /**< array with index of problem variables in expression graph */
1228  int* nexprvars, /**< number of variables in currently processed expression so far */
1229  int nvars, /**< total number of variables in problem (and length of exprvaridx array) */
1230  SCIP_Bool* doingfine /**< buffer to indicate whether no errors occurred */
1231  )
1232 {
1233  const char* exprname;
1234 
1235  assert(scip != NULL);
1236  assert(expr != NULL);
1237  assert(node != NULL);
1238  assert(exprvaridx != NULL || nvars == 0);
1239  assert(nexprvars != NULL);
1240  assert(doingfine != NULL);
1241 
1242  exprname = xmlGetName(node);
1243  assert(exprname != NULL);
1244 
1245  *expr = NULL;
1246 
1247  /* zero argument operands */
1248  if( strcmp(exprname, "variable") == 0 )
1249  {
1250  const char* attrval;
1251  SCIP_Real coef;
1252  int idx;
1253 
1254  /* read variable index */
1255  attrval = xmlGetAttrval(node, "idx");
1256  if( attrval == NULL )
1257  {
1258  SCIPerrorMessage("Attribute \"idx\" required for <variable> node in nonlinear expression\n");
1259  *doingfine = FALSE;
1260  return SCIP_OKAY;
1261  }
1262 
1263  idx = (int)strtol(attrval, (char**)&attrval, 10);
1264  if( *attrval != '\0' || idx < 0 || idx >= nvars )
1265  {
1266  SCIPerrorMessage("Invalid value '%s' in \"idx\" attribute of <variable> node in nonlinear expression.\n", xmlGetAttrval(node, "idx"));
1267  *doingfine = FALSE;
1268  return SCIP_OKAY;
1269  }
1270 
1271  /* read variable coefficient */
1272  attrval = xmlGetAttrval(node, "coef");
1273  if( attrval != NULL )
1274  {
1275  coef = strtod(attrval, (char**)&attrval);
1276  if( *attrval != '\0' || !SCIPisFinite(coef) )
1277  {
1278  SCIPerrorMessage("Invalid value '%s' in \"coef\" attribute of <variable> node in nonlinear expression.\n", xmlGetAttrval(node, "coef"));
1279  *doingfine = FALSE;
1280  return SCIP_OKAY;
1281  }
1282  }
1283  else
1284  {
1285  coef = 1.0;
1286  }
1287 
1288  /* assign index to variable, if we see it the first time */
1289  if( exprvaridx[idx] == -1 ) /*lint !e613*/
1290  {
1291  exprvaridx[idx] = *nexprvars; /*lint !e613*/
1292  ++*nexprvars;
1293  }
1294 
1295  /* create VARIDX expression, put into LINEAR expression if we have coefficient != 1 */
1296  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_VARIDX, exprvaridx[idx]) ); /*lint !e613*/
1297  if( coef != 1.0 )
1298  {
1299  SCIP_CALL( SCIPexprCreateLinear(SCIPblkmem(scip), expr, 1, expr, &coef, 0.0) );
1300  }
1301 
1302  return SCIP_OKAY;
1303  }
1304 
1305  if( strcmp(exprname, "number") == 0 )
1306  {
1307  const char* attrval;
1308  SCIP_Real val;
1309 
1310  attrval = xmlGetAttrval(node, "type");
1311  if( attrval != NULL && (strcmp(attrval, "real") != 0) )
1312  {
1313  SCIPerrorMessage("Type '%s' for <number> node in nonlinear expression not supported.\n", attrval);
1314  *doingfine = FALSE;
1315  return SCIP_OKAY;
1316  }
1317 
1318  attrval = xmlGetAttrval(node, "value");
1319  if( attrval != NULL )
1320  {
1321  val = strtod(attrval, (char**)&attrval);
1322  if( *attrval != '\0' || !SCIPisFinite(val) )
1323  {
1324  SCIPerrorMessage("Invalid value '%s' in \"value\" attribute of <number> node in nonlinear expression.\n", xmlGetAttrval(node, "value"));
1325  *doingfine = FALSE;
1326  return SCIP_OKAY;
1327  }
1328  }
1329  else
1330  {
1331  /* according to OSnL.xsd, the value attribute is optional
1332  * I guess the default is the empty string, which should correspond to 0.0
1333  */
1334  val = 0.0;
1335  }
1336 
1337  /* create CONST expression */
1338  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_CONST, val) );
1339 
1340  return SCIP_OKAY;
1341  }
1342 
1343  if( strcmp(exprname, "PI") == 0 )
1344  {
1345  /* create CONST expression with PI value*/
1347 
1348  return SCIP_OKAY;
1349  }
1350 
1351  if( strcmp(exprname, "E") == 0 )
1352  {
1353  /* create CONST expression with E value*/
1354  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_CONST, M_E) );
1355 
1356  return SCIP_OKAY;
1357  }
1358 
1359  /* single argument operands */
1360  if( strcmp(exprname, "negate") == 0 ||
1361  strcmp(exprname, "abs") == 0 ||
1362  strcmp(exprname, "squareRoot") == 0 ||
1363  strcmp(exprname, "sqrt") == 0 ||
1364  strcmp(exprname, "square") == 0 ||
1365  strcmp(exprname, "exp") == 0 ||
1366  strcmp(exprname, "ln") == 0 ||
1367  strcmp(exprname, "log10") == 0
1368  )
1369  {
1370  SCIP_EXPR* arg;
1371 
1372  /* check number of children */
1373  if( xmlFirstChild(node) == NULL || xmlNextSibl(xmlFirstChild(node)) != NULL )
1374  {
1375  SCIPerrorMessage("Expected exactly one child in <%s> node in nonlinear expression\n", exprname);
1376  *doingfine = FALSE;
1377  return SCIP_OKAY;
1378  }
1379 
1380  /* read child expression */
1381  SCIP_CALL( readExpression(scip, &arg, xmlFirstChild(node), exprvaridx, nexprvars, nvars, doingfine) );
1382  if( !*doingfine )
1383  return SCIP_OKAY;
1384 
1385  /* create SCIP expression according to expression name */
1386  if( strcmp(exprname, "negate") == 0 )
1387  {
1388  SCIP_Real minusone;
1389 
1390  minusone = -1.0;
1391  SCIP_CALL( SCIPexprCreateLinear(SCIPblkmem(scip), expr, 1, &arg, &minusone, 0.0) );
1392  }
1393  else if( strcmp(exprname, "abs") == 0 )
1394  {
1395  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_ABS, arg) );
1396  }
1397  else if( strcmp(exprname, "squareRoot") == 0 || strcmp(exprname, "sqrt") == 0 )
1398  {
1399  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_SQRT, arg) );
1400  }
1401  else if( strcmp(exprname, "square") == 0 )
1402  {
1403  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_SQUARE, arg) );
1404  }
1405  else if( strcmp(exprname, "exp") == 0 )
1406  {
1407  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_EXP, arg) );
1408  }
1409  else if( strcmp(exprname, "ln") == 0 )
1410  {
1411  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_LOG, arg) );
1412  }
1413  else /* if( strcmp(exprname, "log10") == 0 ) */
1414  {
1415  /* log10(expr) = ln(expr)*1/ln(10) */
1416  SCIP_EXPR* tmp;
1417 
1418  assert(strcmp(exprname, "log10") == 0);
1419 
1420  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &tmp, SCIP_EXPR_CONST, 1.0/log(10.0)) );
1421  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &arg, SCIP_EXPR_LOG, arg) );
1422  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_MUL, arg, tmp) );
1423  }
1424 
1425  return SCIP_OKAY;
1426  }
1427 
1428  /* two argument operands */
1429  if( strcmp(exprname, "plus") == 0 ||
1430  strcmp(exprname, "minus") == 0 ||
1431  strcmp(exprname, "times") == 0 ||
1432  strcmp(exprname, "divide") == 0 ||
1433  strcmp(exprname, "power") == 0 ||
1434  strcmp(exprname, "log") == 0
1435  )
1436  {
1437  SCIP_EXPR* arg1;
1438  SCIP_EXPR* arg2;
1439 
1440  /* check number of children */
1441  if( xmlFirstChild(node) == NULL ||
1442  xmlNextSibl(xmlFirstChild(node)) == NULL ||
1444  {
1445  SCIPerrorMessage("Expected exactly two children in <%s> node in nonlinear expression.\n", exprname);
1446  *doingfine = FALSE;
1447  return SCIP_OKAY;
1448  }
1449 
1450  /* read first child expression */
1451  SCIP_CALL( readExpression(scip, &arg1, xmlFirstChild(node), exprvaridx, nexprvars, nvars, doingfine) );
1452  if( !*doingfine )
1453  return SCIP_OKAY;
1454 
1455  /* read second child expression */
1456  SCIP_CALL( readExpression(scip, &arg2, xmlNextSibl(xmlFirstChild(node)), exprvaridx, nexprvars, nvars, doingfine) );
1457  if( !*doingfine )
1458  {
1459  SCIPexprFreeDeep(SCIPblkmem(scip), &arg1);
1460  return SCIP_OKAY;
1461  }
1462 
1463  if( strcmp(exprname, "plus") == 0 )
1464  {
1465  SCIP_CALL( SCIPexprAdd(SCIPblkmem(scip), expr, 1.0, arg1, 1.0, arg2, 0.0) );
1466  /* SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_PLUS, arg1, arg2) ); */
1467  }
1468  else if( strcmp(exprname, "minus") == 0 )
1469  {
1470  SCIP_CALL( SCIPexprAdd(SCIPblkmem(scip), expr, 1.0, arg1, -1.0, arg2, 0.0) );
1471  /* SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_MINUS, arg1, arg2) ); */
1472  }
1473  else if( strcmp(exprname, "times") == 0 )
1474  {
1475  if( SCIPexprGetOperator(arg1) == SCIP_EXPR_CONST )
1476  {
1477  SCIP_CALL( SCIPexprMulConstant(SCIPblkmem(scip), expr, arg2, SCIPexprGetOpReal(arg1)) );
1478  SCIPexprFreeDeep(SCIPblkmem(scip), &arg1);
1479  }
1480  else if( SCIPexprGetOperator(arg2) == SCIP_EXPR_CONST )
1481  {
1482  SCIP_CALL( SCIPexprMulConstant(SCIPblkmem(scip), expr, arg1, SCIPexprGetOpReal(arg2)) );
1483  SCIPexprFreeDeep(SCIPblkmem(scip), &arg2);
1484  }
1485  else
1486  {
1487  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_MUL, arg1, arg2) );
1488  }
1489  }
1490  else if( strcmp(exprname, "divide") == 0 )
1491  {
1492  if( SCIPexprGetOperator(arg2) == SCIP_EXPR_CONST )
1493  {
1494  assert(SCIPexprGetOpReal(arg2) != 0.0);
1495  SCIP_CALL( SCIPexprMulConstant(SCIPblkmem(scip), expr, arg1, 1.0/SCIPexprGetOpReal(arg2)) );
1496  SCIPexprFreeDeep(SCIPblkmem(scip), &arg2);
1497  }
1498  else
1499  {
1500  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_DIV, arg1, arg2) );
1501  }
1502  }
1503  else if( strcmp(exprname, "power") == 0 )
1504  {
1505  if( SCIPexprGetOperator(arg2) == SCIP_EXPR_CONST )
1506  {
1507  /* expr^number is intpower or realpower */
1508  if( SCIPisIntegral(scip, SCIPexprGetOpReal(arg2)) )
1509  {
1510  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_INTPOWER, arg1, (int)SCIPround(scip, SCIPexprGetOpReal(arg2))) );
1511  }
1512  else
1513  {
1515  }
1516  SCIPexprFreeDeep(SCIPblkmem(scip), &arg2);
1517  }
1518  else if( SCIPexprGetOperator(arg1) == SCIP_EXPR_CONST )
1519  {
1520  /* number^arg2 is exp(arg2 * ln(number)) */
1521  if( SCIPexprGetOpReal(arg1) < 0.0 )
1522  {
1523  SCIPerrorMessage("Negative base in <power> node with nonconstant exponent not allowed in nonlinear expression.\n");
1524  SCIPexprFreeDeep(SCIPblkmem(scip), &arg1);
1525  SCIPexprFreeDeep(SCIPblkmem(scip), &arg2);
1526  *doingfine = FALSE;
1527  return SCIP_OKAY;
1528  }
1529  else
1530  {
1531  SCIP_EXPR* tmp;
1532 
1534  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &tmp, SCIP_EXPR_MUL, tmp, arg2) );
1535  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_EXP, tmp) );
1536  SCIPexprFreeDeep(SCIPblkmem(scip), &arg1);
1537  }
1538  }
1539  else
1540  {
1541  /* arg1^arg2 is exp(arg2 * ln(arg1)) */
1542  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &arg1, SCIP_EXPR_LOG, arg1) );
1543  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &arg2, SCIP_EXPR_MUL, arg1, arg2) );
1544  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_EXP, arg2) );
1545  }
1546  }
1547  else if( strcmp(exprname, "log") == 0 )
1548  {
1549  /* logarithm of arg2 w.r.t. base arg1 = ln(arg2) / ln(arg1) */
1550  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &arg1, SCIP_EXPR_LOG, arg1) );
1551  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &arg2, SCIP_EXPR_LOG, arg2) );
1552  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_DIV, arg2, arg1) );
1553  }
1554  else if( strcmp(exprname, "min") == 0 )
1555  {
1556  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_MIN, arg1, arg2) );
1557  }
1558  else /* if( strcmp(exprname, "max") == 0 ) */
1559  {
1560  assert(strcmp(exprname, "max") == 0);
1561 
1562  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_MAX, arg1, arg2) );
1563  }
1564 
1565  return SCIP_OKAY;
1566  }
1567 
1568  /* arbitrary argument operands */
1569  if( strcmp(exprname, "sum") == 0 || strcmp(exprname, "product") == 0 )
1570  {
1571  const XML_NODE* argnode;
1572  SCIP_EXPR** args;
1573  int nargs;
1574  int argssize;
1575 
1576  /* a sum or product w.r.t. 0 arguments is constant */
1577  if( xmlFirstChild(node) == NULL )
1578  {
1579  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_CONST, (strcmp(exprname, "sum") == 0) ? 0.0 : 1.0) );
1580 
1581  return SCIP_OKAY;
1582  }
1583 
1584  /* read all child expressions */
1585  argssize = 5;
1586  SCIP_CALL( SCIPallocBufferArray(scip, &args, argssize) );
1587 
1588  nargs = 0;
1589  for( argnode = xmlFirstChild(node); argnode != NULL; argnode = xmlNextSibl(argnode), ++nargs )
1590  {
1591  if( nargs >= argssize )
1592  {
1593  argssize = SCIPcalcMemGrowSize(scip, nargs + 1);
1594  SCIP_CALL( SCIPreallocBufferArray(scip, &args, argssize) );
1595  }
1596  assert(nargs < argssize);
1597 
1598  SCIP_CALL( readExpression(scip, &args[nargs], argnode, exprvaridx, nexprvars, nvars, doingfine) );
1599  if( !*doingfine )
1600  {
1601  assert(args[nargs] == NULL);
1602  break;
1603  }
1604  }
1605 
1606  if( *doingfine )
1607  {
1608  switch( nargs )
1609  {
1610  case 0:
1611  {
1612  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_CONST, (strcmp(exprname, "sum") == 0) ? 0.0 : 1.0) );
1613  break;
1614  }
1615  case 1:
1616  {
1617  *expr = args[0];
1618  break;
1619  }
1620  case 2:
1621  {
1622  if( strcmp(exprname, "sum") == 0 )
1623  {
1624  SCIP_CALL( SCIPexprAdd(SCIPblkmem(scip), expr, 1.0, args[0], 1.0, args[1], 0.0) );
1625  }
1626  else
1627  {
1628  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, SCIP_EXPR_MUL, args[0], args[1]) );
1629  }
1630  break;
1631  }
1632  default:
1633  {
1634  /* create sum or product expression */
1635  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, (strcmp(exprname, "sum") == 0) ? SCIP_EXPR_SUM : SCIP_EXPR_PRODUCT, nargs, args) );
1636  break;
1637  }
1638  }
1639  }
1640  else
1641  {
1642  /* cleanup if parsing error */
1643  for( ; nargs > 0; --nargs )
1644  SCIPexprFreeDeep(SCIPblkmem(scip), &args[nargs-1]);
1645  }
1646 
1647  SCIPfreeBufferArray(scip, &args);
1648 
1649  return SCIP_OKAY;
1650  }
1651 
1652  if( strcmp(exprname, "min") == 0 || strcmp(exprname, "max") == 0 )
1653  {
1654  const XML_NODE* argnode;
1655  SCIP_EXPROP exprop;
1656  SCIP_EXPR* arg2;
1657 
1658  /* check that we have children */
1659  if( xmlFirstChild(node) == NULL )
1660  {
1661  SCIPerrorMessage("Expected at least one child in <%s> node of nonlinear expression.\n", exprname);
1662  *doingfine = FALSE;
1663  return SCIP_OKAY;
1664  }
1665 
1666  /* read expression corresponding to first child and store in expr */
1667  argnode = xmlFirstChild(node);
1668  SCIP_CALL( readExpression(scip, expr, argnode, exprvaridx, nexprvars, nvars, doingfine) );
1669  if( !*doingfine )
1670  {
1671  assert(*expr == NULL);
1672  return SCIP_OKAY;
1673  }
1674  arg2 = NULL;
1675 
1676  exprop = (strcmp(exprname, "min") == 0) ? SCIP_EXPR_MIN : SCIP_EXPR_MAX;
1677 
1678  /* read expressions corresponding to other children in arg and store exprop(expr, arg) in expr */
1679  for( argnode = xmlNextSibl(argnode); argnode != NULL; argnode = xmlNextSibl(argnode) )
1680  {
1681  assert(arg2 == NULL);
1682  SCIP_CALL( readExpression(scip, &arg2, argnode, exprvaridx, nexprvars, nvars, doingfine) );
1683  if( !*doingfine )
1684  {
1685  assert(arg2 == NULL);
1686  break;
1687  }
1688 
1689  assert(*expr != NULL);
1690  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), expr, exprop, *expr, arg2) );
1691  arg2 = NULL;
1692  }
1693 
1694  if( !*doingfine )
1695  {
1696  /* cleanup if failure */
1697  SCIPexprFreeDeep(SCIPblkmem(scip), expr);
1698  }
1699  assert(arg2 == NULL);
1700 
1701  return SCIP_OKAY;
1702  }
1703 
1704  if( strcmp(exprname, "quadratic") == 0 )
1705  {
1706  const char* attrval;
1707  const XML_NODE* qterm;
1708  SCIP_QUADELEM* quadelems;
1709  int nquadelems;
1710  int quadelemssize;
1711  int* quadvarsidxs;
1712  int nquadvars;
1713  int i;
1714 
1715  quadelemssize = 5;
1716  SCIP_CALL( SCIPallocBufferArray(scip, &quadelems, quadelemssize) );
1717  nquadelems = 0;
1718 
1719  SCIP_CALL( SCIPallocBufferArray(scip, &quadvarsidxs, nvars) );
1720  for( i = 0; i < nvars; ++i )
1721  quadvarsidxs[i] = -1;
1722  nquadvars = 0;
1723 
1724  /* read quadratic terms */
1725  for( qterm = xmlFirstChild(node); qterm != NULL; qterm = xmlNextSibl(qterm), ++nquadelems )
1726  {
1727  /* check for qpTerm node */
1728  if( strcmp(xmlGetName(qterm), "qpTerm") != 0 )
1729  {
1730  SCIPerrorMessage("Unexpected <%s> node under <quadratic> node in nonlinear expression, expected <qpTerm>.\n", xmlGetName(qterm));
1731  *doingfine = FALSE;
1732  break;
1733  }
1734 
1735  if( nquadelems >= quadelemssize )
1736  {
1737  quadelemssize = SCIPcalcMemGrowSize(scip, nquadelems + 1);
1738  SCIP_CALL( SCIPreallocBufferArray(scip, &quadelems, quadelemssize) );
1739  }
1740  assert(quadelemssize > nquadelems);
1741 
1742  /* get index of first variable */
1743  attrval = xmlGetAttrval(qterm, "idxOne");
1744  if( attrval == NULL )
1745  {
1746  SCIPerrorMessage("Missing \"idxOne\" attribute in %d'th <qpTerm> node under <quadratic> node in nonlinear expression.\n", nquadelems);
1747  *doingfine = FALSE;
1748  break;
1749  }
1750 
1751  quadelems[nquadelems].idx1 = (int)strtol(attrval, (char**)&attrval, 10);
1752  if( *attrval != '\0' || quadelems[nquadelems].idx1 < 0 || quadelems[nquadelems].idx1 >= nvars )
1753  {
1754  SCIPerrorMessage("Invalid value '%s' for \"idxOne\" attribute of %d'th <qpTerm> node under <quadratic> node in nonlinear expression.\n", xmlGetAttrval(qterm, "idxOne"), nquadelems);
1755  *doingfine = FALSE;
1756  break;
1757  }
1758 
1759  /* get index of second variable */
1760  attrval = xmlGetAttrval(qterm, "idxTwo");
1761  if( attrval == NULL )
1762  {
1763  SCIPerrorMessage("Missing \"idxTwo\" attribute in %d'th <qpTerm> node under <quadratic> node in nonlinear expression.\n", nquadelems);
1764  *doingfine = FALSE;
1765  break;
1766  }
1767 
1768  quadelems[nquadelems].idx2 = (int)strtol(attrval, (char**)&attrval, 10);
1769  if( *attrval != '\0' || quadelems[nquadelems].idx2 < 0 || quadelems[nquadelems].idx2 >= nvars )
1770  {
1771  SCIPerrorMessage("Invalid value '%s' for \"idxTwo\" attribute of %d'th <qpTerm> node under <quadratic> node in nonlinear expression.\n", xmlGetAttrval(qterm, "idxTwo"), nquadelems);
1772  *doingfine = FALSE;
1773  break;
1774  }
1775 
1776  /* get coefficient */
1777  attrval = xmlGetAttrval(qterm, "coef");
1778  if( attrval != NULL )
1779  {
1780  quadelems[nquadelems].coef = strtod(attrval, (char**)&attrval);
1781  if( *attrval != '\0' || (quadelems[nquadelems].coef != quadelems[nquadelems].coef) ) /*lint !e777*/
1782  {
1783  SCIPerrorMessage("Invalid value '%s' for \"coef\" attribute of %d'th <qpTerm> node under <quadratic> node in nonlinear expression.\n", xmlGetAttrval(qterm, "coef"), nquadelems);
1784  *doingfine = FALSE;
1785  break;
1786  }
1787  }
1788  else
1789  {
1790  quadelems[nquadelems].coef = 1.0;
1791  }
1792 
1793  /* get index for first variable in quadratic element */
1794  if( quadvarsidxs[quadelems[nquadelems].idx1] < 0 )
1795  {
1796  quadvarsidxs[quadelems[nquadelems].idx1] = nquadvars;
1797  quadelems[nquadelems].idx1 = nquadvars;
1798 
1799  ++nquadvars;
1800  }
1801  else
1802  {
1803  quadelems[nquadelems].idx1 = quadvarsidxs[quadelems[nquadelems].idx1];
1804  }
1805 
1806  /* get index for second variable in quadratic element */
1807  if( quadvarsidxs[quadelems[nquadelems].idx2] < 0 )
1808  {
1809  quadvarsidxs[quadelems[nquadelems].idx2] = nquadvars;
1810  quadelems[nquadelems].idx2 = nquadvars;
1811 
1812  ++nquadvars;
1813  }
1814  else
1815  {
1816  quadelems[nquadelems].idx2 = quadvarsidxs[quadelems[nquadelems].idx2];
1817  }
1818 
1819  /* swap indices if in wrong order */
1820  if( quadelems[nquadelems].idx1 > quadelems[nquadelems].idx2 )
1821  {
1822  int tmp;
1823 
1824  tmp = quadelems[nquadelems].idx1;
1825  quadelems[nquadelems].idx1 = quadelems[nquadelems].idx2;
1826  quadelems[nquadelems].idx2 = tmp;
1827  }
1828  }
1829 
1830  if( *doingfine )
1831  {
1832  SCIP_EXPR** children;
1833 
1834  /* setup array with children expressions corresponding to variables */
1835  SCIP_CALL( SCIPallocBufferArray(scip, &children, nquadvars) );
1836  for( i = 0; i < nvars; ++i )
1837  {
1838  if( quadvarsidxs[i] == -1 )
1839  continue;
1840 
1841  /* assign new index to variable, if we see it the first time in this exprtree */
1842  if( exprvaridx[i] == -1 ) /*lint !e613*/
1843  {
1844  exprvaridx[i] = *nexprvars; /*lint !e613*/
1845  ++*nexprvars;
1846  }
1847 
1848  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &children[quadvarsidxs[i]], SCIP_EXPR_VARIDX, exprvaridx[i]) ); /*lint !e613*/
1849  }
1850 
1851  /* create quadratic expression */
1852  SCIP_CALL( SCIPexprCreateQuadratic(SCIPblkmem(scip), expr, nquadvars, children, 0.0, NULL, nquadelems, quadelems) );
1853 
1854  SCIPfreeBufferArray(scip, &children);
1855  }
1856 
1857  SCIPfreeBufferArray(scip, &quadelems);
1858  SCIPfreeBufferArray(scip, &quadvarsidxs);
1859  }
1860 
1861  SCIPerrorMessage("Expression operand <%s> in nonlinear expression not supported by SCIP so far.\n", exprname);
1862  *doingfine = FALSE;
1863 
1864  return SCIP_OKAY;
1865 }
1866 
1867 
1868 /** read nonlinear expressions of constraints and objective */
1869 static
1871  SCIP* scip, /**< SCIP data structure */
1872  const XML_NODE* datanode, /**< XML root node for instance data */
1873  SCIP_VAR** vars, /**< variables in order of OSiL indices */
1874  int nvars, /**< number of variables */
1875  SCIP_CONS** conss, /**< constraints in order of OSiL indices */
1876  CONSTYPE* constypes, /**< type of constraints (assumed to be LINEAR) */
1877  int nconss, /**< number of constraints */
1878  SCIP_CONS** objcons, /**< buffer to store constraint for nonlinear part of objective function, or to add to if already existing */
1879  CONSTYPE* objconstype, /**< buffer to store type of objective constraint, if created (should be QUADRATIC) */
1880  SCIP_Bool* doingfine /**< buffer to indicate whether no errors occurred */
1881  )
1882 {
1883  const XML_NODE* nlexprs;
1884  const XML_NODE* nlexpr;
1885  const char* attrval;
1886  SCIP_EXPRTREE* exprtree;
1887  SCIP_EXPR* expr;
1888  SCIP_VAR** exprvars;
1889  int* exprvaridx;
1890  SCIP_RETCODE retcode;
1891  int nexprvars;
1892  int nnlexprs;
1893  int count;
1894  int considx;
1895  int i;
1896 
1897  assert(scip != NULL);
1898  assert(datanode != NULL);
1899  assert(vars != NULL || nvars == 0);
1900  assert(conss != NULL || nconss == 0);
1901  assert(constypes != NULL || nconss == 0);
1902  assert(objcons != NULL);
1903  assert(doingfine != NULL);
1904 
1905  retcode = SCIP_OKAY;
1906 
1907  nlexprs = xmlFindNodeMaxdepth(datanode, "nonlinearExpressions", 0, 1);
1908 
1909  if( nlexprs == NULL )
1910  return SCIP_OKAY;
1911 
1912  /* get number of nonlinear expressions */
1913  attrval = xmlGetAttrval(nlexprs, "numberOfNonlinearExpressions");
1914  if( attrval == NULL )
1915  {
1916  SCIPerrorMessage("Attribute \"numberOfNonlinearExpressions\" in <nonlinearExpressions> node not found.\n");
1917  *doingfine = FALSE;
1918  return SCIP_OKAY;
1919  }
1920 
1921  nnlexprs = (int)strtol(attrval, (char**)&attrval, 10);
1922  if( *attrval != '\0' || nnlexprs < 0 )
1923  {
1924  SCIPerrorMessage("Invalid value '%s' for \"numberOfNonlinearExpressions\" attribute in <nonlinearExpressions>.\n", xmlGetAttrval(nlexprs, "numberOfNonlinearExpressions"));
1925  *doingfine = FALSE;
1926  return SCIP_OKAY;
1927  }
1928  assert(nnlexprs >= 0);
1929 
1930  /* buffer array to store index of variable in expression graph, or -1 if not present */
1931  SCIP_CALL( SCIPallocBufferArray(scip, &exprvaridx, nvars) );
1932  SCIP_CALL( SCIPallocBufferArray(scip, &exprvars, nvars) );
1933 
1934  /* read nonlinear expressions and store in constraints */
1935  count = 0;
1936  for( nlexpr = xmlFirstChild(nlexprs); nlexpr != NULL; nlexpr = xmlNextSibl(nlexpr), ++count )
1937  {
1938  if( strcmp(xmlGetName(nlexpr), "nl") != 0 )
1939  {
1940  SCIPerrorMessage("Expected <nl> node under <nonlinearExpressions> node, but got '%s'.\n", xmlGetName(nlexpr));
1941  *doingfine = FALSE;
1942  break;
1943  }
1944  if( count >= nnlexprs )
1945  {
1946  SCIPerrorMessage("Too many nonlinear expressions under <nonlinearExpressions> node, expected %d many, but got at least %d.\n", nnlexprs, count + 1);
1947  *doingfine = FALSE;
1948  break;
1949  }
1950 
1951  /* treat empty expression as 0.0 and continue */
1952  if( xmlFirstChild(nlexprs) == NULL )
1953  continue;
1954 
1955  /* get constraint index, or -1 for objective */
1956  attrval = xmlGetAttrval(nlexpr, "idx");
1957  if( attrval == NULL )
1958  {
1959  SCIPerrorMessage("Missing \"idx\" attribute in %d'th <nl> node under <nonlinearExpressions> node.\n", count);
1960  *doingfine = FALSE;
1961  break;
1962  }
1963 
1964  considx = (int)strtol(attrval, (char**)&attrval, 10);
1965  if( *attrval != '\0' || considx < -1 || considx >= nconss )
1966  {
1967  SCIPerrorMessage("Invalid value '%s' in \"idx\" attribute of %d'th <nl> node under <nonlinearExpressions> node.\n", xmlGetAttrval(nlexpr, "idx"), count);
1968  *doingfine = FALSE;
1969  break;
1970  }
1971 
1972  expr = NULL;
1973  nexprvars = 0;
1974  for( i = 0; i < nvars; ++i )
1975  exprvaridx[i] = -1;
1976 
1977  /* turn OSiL expression into SCIP expression and assign indices to variables */
1978  SCIP_CALL( readExpression(scip, &expr, xmlFirstChild(nlexpr), exprvaridx, &nexprvars, nvars, doingfine) );
1979  if( !*doingfine )
1980  {
1981  assert(expr == NULL);
1982  break;
1983  }
1984 
1985  /* assemble array with SCIP_VAR*'s */
1986  for( i = 0; i < nvars; ++i )
1987  {
1988  assert(exprvaridx[i] < nexprvars );
1989 
1990  if( exprvaridx[i] >= 0 )
1991  exprvars[exprvaridx[i]] = vars[i]; /*lint !e613*/
1992  }
1993 
1994  /* create expression tree */
1995  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), &exprtree, expr, nexprvars, 0, NULL) );
1996  SCIP_CALL( SCIPexprtreeSetVars(exprtree, nexprvars, exprvars) );
1997 
1998  /* add expression tree to objective or constraint */
1999  if( considx == -1 && *objcons == NULL )
2000  {
2001  /* create constraint to hold nonlinear part of objective; note that
2002  * reading/{initialconss,dynamicconss,dynamicrows,dynamiccols} apply only to model constraints and variables,
2003  * not to an auxiliary objective constraint (otherwise it can happen that an auxiliary objective variable is
2004  * loose with infinite best bound, triggering the problem that an LP that is unbounded because of loose
2005  * variables with infinite best bound cannot be solved)
2006  */
2007 
2008  SCIP_VAR* objvar;
2009  SCIP_Real minusone;
2010  SCIP_Real one;
2011 
2012  SCIP_CALL( SCIPcreateVar(scip, &objvar, "objvar", -SCIPinfinity(scip), SCIPinfinity(scip), 1.0,
2014  SCIP_CALL( SCIPaddVar(scip, objvar) );
2015 
2016  minusone = -1.0;
2017  one = 1.0;
2018  SCIP_CALL_TERMINATE( retcode, SCIPcreateConsNonlinear(scip, objcons, "objcons", 1, &objvar, &minusone, 1, &exprtree, &one,
2019  SCIPgetObjsense(scip) == SCIP_OBJSENSE_MINIMIZE ? -SCIPinfinity(scip) : 0.0,
2020  SCIPgetObjsense(scip) == SCIP_OBJSENSE_MAXIMIZE ? SCIPinfinity(scip) : 0.0,
2021  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE), TERMINATE );
2022  *objconstype = NONLINEAR;
2023 
2024  SCIP_CALL( SCIPreleaseVar(scip, &objvar) );
2025  }
2026  else
2027  {
2028  SCIP_CONS** cons;
2029  SCIP_CONS* oldcons;
2030  CONSTYPE* constype;
2031 
2032  if( considx == -1 )
2033  {
2034  cons = objcons;
2035  constype = objconstype;
2036  }
2037  else
2038  {
2039  cons = &conss[considx]; /*lint !e613*/
2040  constype = &constypes[considx]; /*lint !e613*/
2041  }
2042  oldcons = *cons;
2043 
2044  /* replace cons by nonlinear constraint or add to already existing nonlinear constraint */
2045  switch( *constype )
2046  {
2047  case LINEAR:
2048  {
2049  SCIP_Real one;
2050 
2051  one = 1.0;
2052  SCIP_CALL_TERMINATE( retcode, SCIPcreateConsNonlinear(scip, cons, SCIPconsGetName(*cons),
2053  SCIPgetNVarsLinear(scip, *cons), SCIPgetVarsLinear(scip, *cons), SCIPgetValsLinear(scip, *cons),
2054  1, &exprtree, &one,
2055  SCIPgetLhsLinear(scip, *cons), SCIPgetRhsLinear(scip, *cons),
2059  SCIPconsIsStickingAtNode(*cons)), TERMINATE );
2060 
2061  SCIP_CALL( SCIPreleaseCons(scip, &oldcons) );
2062 
2063  break;
2064  }
2065 
2066  case QUADRATIC:
2067  {
2068  SCIP_EXPRTREE* exprtrees[2];
2069  SCIP_Real exprcoefs[2];
2070 
2071  SCIP_EXPR* quadexpr;
2072  SCIP_QUADELEM* quadelems;
2073  SCIP_Real* lincoefs;
2074  SCIP_EXPR** children;
2075  SCIP_QUADVARTERM* quadvarterms;
2076  SCIP_BILINTERM* bilinterms;
2077  int nquadelems;
2078  int nquadvars;
2079  int nbilin;
2080  int j;
2081 
2082  exprtrees[0] = exprtree;
2083  exprcoefs[0] = 1.0;
2084 
2085  /* turn quadratic part into expression tree */
2086  SCIP_CALL( SCIPsortQuadVarTermsQuadratic(scip, *cons) );
2087 
2088  quadvarterms = SCIPgetQuadVarTermsQuadratic(scip, *cons);
2089  nquadvars = SCIPgetNQuadVarTermsQuadratic(scip, *cons);
2090  bilinterms = SCIPgetBilinTermsQuadratic(scip, *cons);
2091  nbilin = SCIPgetNBilinTermsQuadratic(scip, *cons);
2092 
2093  SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nquadvars) );
2094  SCIP_CALL( SCIPallocBufferArray(scip, &children, nquadvars) );
2095  SCIP_CALL( SCIPallocBufferArray(scip, &quadelems, nbilin + nquadvars) );
2096  nquadelems = 0;
2097 
2098  for( i = 0; i < nquadvars; ++i )
2099  {
2100  lincoefs[i] = quadvarterms[i].lincoef;
2101  exprvars[i] = quadvarterms[i].var;
2102 
2103  if( quadvarterms[i].sqrcoef != 0.0 )
2104  {
2105  quadelems[nquadelems].idx1 = i;
2106  quadelems[nquadelems].idx2 = i;
2107  quadelems[nquadelems].coef = quadvarterms[i].sqrcoef;
2108  ++nquadelems;
2109  }
2110 
2111  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &children[i], SCIP_EXPR_VARIDX, i) );
2112 
2113  for( j = 0; j < quadvarterms[i].nadjbilin; ++j )
2114  {
2115  if( bilinterms[quadvarterms[i].adjbilin[j]].var1 == quadvarterms[i].var )
2116  {
2117  int otheridx;
2118 
2119  assert(bilinterms[quadvarterms[i].adjbilin[j]].var2 != quadvarterms[i].var);
2120 
2121  SCIP_CALL( SCIPfindQuadVarTermQuadratic(scip, *cons, bilinterms[quadvarterms[i].adjbilin[j]].var2, &otheridx) );
2122  assert(otheridx >= 0);
2123  assert(otheridx < nquadvars);
2124 
2125  quadelems[nquadelems].idx1 = MIN(i, otheridx);
2126  quadelems[nquadelems].idx2 = MAX(i, otheridx);
2127  quadelems[nquadelems].coef = bilinterms[quadvarterms[i].adjbilin[j]].coef;
2128  ++nquadelems;
2129  }
2130  }
2131  }
2132 
2133  SCIP_CALL( SCIPexprCreateQuadratic(SCIPblkmem(scip), &quadexpr, nquadvars, children, 0.0, lincoefs, nquadelems, quadelems) );
2134  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), &exprtrees[1], quadexpr, nquadvars, 0, NULL) );
2135  SCIP_CALL( SCIPexprtreeSetVars(exprtrees[1], nquadvars, exprvars) );
2136  exprcoefs[1] = 1.0;
2137 
2138  SCIPfreeBufferArray(scip, &lincoefs);
2139  SCIPfreeBufferArray(scip, &children);
2140  SCIPfreeBufferArray(scip, &quadelems);
2141 
2142  SCIP_CALL_TERMINATE( retcode, SCIPcreateConsNonlinear(scip, cons, SCIPconsGetName(*cons),
2143  SCIPgetNLinearVarsNonlinear(scip, *cons), SCIPgetLinearVarsNonlinear(scip, *cons),
2144  SCIPgetLinearCoefsNonlinear(scip, *cons), 2, exprtrees, exprcoefs,
2145  SCIPgetLhsNonlinear(scip, *cons), SCIPgetRhsNonlinear(scip, *cons),
2149  SCIPconsIsStickingAtNode(*cons)), TERMINATE );
2150 
2151  SCIP_CALL( SCIPreleaseCons(scip, &oldcons) );
2152 
2153  break;
2154  }
2155 
2156  case NONLINEAR:
2157  {
2158  SCIP_Real one;
2159 
2160  one = 1.0;
2161  SCIP_CALL( SCIPaddExprtreesNonlinear(scip, *cons, 1, &exprtree, &one) );
2162  break;
2163  }
2164  }
2165 
2166  *constype = NONLINEAR;
2167  }
2168 
2169  TERMINATE:
2170  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
2171 
2172  if( retcode != SCIP_OKAY )
2173  break;
2174  }
2175 
2176  SCIPfreeBufferArray(scip, &exprvars);
2177  SCIPfreeBufferArray(scip, &exprvaridx);
2178 
2179  SCIP_CALL( retcode );
2180 
2181  return SCIP_OKAY;
2182 }
2183 
2184 
2185 /** read sos1 and sos2 constraints
2186  *
2187  * sos constraints are expected to be given as a node of <instanceData> in the following way:
2188  * @code
2189  * <specialOrderedSets numberOfSpecialOrderedSets="1">
2190  * <sos numberOfVar="2" order="2">
2191  * <var idx="1"></var>
2192  * <var idx="2"></var>
2193  * </sos>
2194  * </specialOrderedSets>
2195  * @endcode
2196  * Weights are determined by the order in which the variables are given
2197  *
2198  */
2199 static
2201  SCIP* scip, /**< SCIP data structure */
2202  const XML_NODE* datanode, /**< XML root node for instance data */
2203  SCIP_VAR** vars, /**< variables in order of OSiL indices */
2204  int nvars, /**< number of variables */
2205  SCIP_Bool initialconss, /**< should model constraints be marked as initial? */
2206  SCIP_Bool dynamicconss, /**< should model constraints be subject to aging? */
2207  SCIP_Bool dynamicrows, /**< should rows be added and removed dynamically to the LP? */
2208  SCIP_Bool* doingfine /**< buffer to indicate whether no errors occurred */
2209  )
2210 {
2211  const XML_NODE* soscons;
2212  const XML_NODE* sosvar;
2213  const char* attrval;
2214  int nsoscons;
2215  int nsosvars;
2216  int sosorder;
2217  int type;
2218  int count;
2219  int varcount;
2220  int idx;
2221  SCIP_Bool initial;
2222  SCIP_Bool separate;
2223  SCIP_Bool enforce;
2224  SCIP_Bool check;
2225  SCIP_Bool propagate;
2226  SCIP_Bool local;
2227  SCIP_Bool dynamic;
2228  SCIP_Bool removable;
2229  char name[SCIP_MAXSTRLEN];
2230 
2231  /* standard settings for SOS constraints: */
2232  initial = initialconss;
2233  separate = TRUE;
2234  enforce = TRUE;
2235  check = TRUE;
2236  propagate = TRUE;
2237  local = FALSE;
2238  dynamic = dynamicconss;
2239  removable = dynamicrows;
2240 
2241  soscons= xmlFindNodeMaxdepth(datanode, "specialOrderedSets", 0, 1);
2242 
2243  if( soscons== NULL )
2244  return SCIP_OKAY;
2245 
2246  /* get number of sos constraints */
2247  attrval = xmlGetAttrval(soscons, "numberOfSOS");
2248  if( attrval == NULL )
2249  {
2250  SCIPerrorMessage("Attribute \"numberOfSOS in <specialOrderedSets> node not found.\n");
2251  *doingfine = FALSE;
2252  return SCIP_OKAY;
2253  }
2254 
2255  nsoscons = (int)strtol(attrval, (char**)&attrval, 10);
2256  if( *attrval != '\0' || nsoscons < 0 )
2257  {
2258  SCIPerrorMessage("Invalid value '%s' for \"numberOfSOS\" attribute in <specialOrderedSets>.\n", xmlGetAttrval(soscons, "numberOfSOS"));
2259  *doingfine = FALSE;
2260  return SCIP_OKAY;
2261  }
2262  assert(nsoscons >= 0);
2263 
2264  /* read sos constraints and create corresponding constraint */
2265  count = 0;
2266  for( soscons = xmlFirstChild(soscons); soscons != NULL; soscons = xmlNextSibl(soscons), ++count )
2267  {
2268  SCIP_CONS* cons;
2269 
2270  /* Make sure we get a sos node and not more then announced*/
2271  if( strcmp(xmlGetName(soscons), "sos") != 0 )
2272  {
2273  SCIPerrorMessage("Expected <sos> node under <specialOrderedSet> node, but got '%s'.\n", xmlGetName(soscons));
2274  *doingfine = FALSE;
2275  break;
2276  }
2277 
2278  if( count >= nsoscons)
2279  {
2280  SCIPerrorMessage("Too many sos under <specialOrderedSets> node, expected %d many, but got at least %d.\n", nsoscons, count + 1);
2281  *doingfine = FALSE;
2282  break;
2283  }
2284 
2285  /* get number of variables in this sos constraint */
2286  attrval = xmlGetAttrval(soscons, "numberOfVar");
2287  if( attrval == NULL )
2288  {
2289  SCIPerrorMessage("Attribute \"numberOfVar in <sos> node not found.\n");
2290  *doingfine = FALSE;
2291  return SCIP_OKAY;
2292  }
2293 
2294  nsosvars = (int)strtol(attrval, (char**)&attrval, 10);
2295  if( *attrval != '\0' || nsosvars < 0 )
2296  {
2297  SCIPerrorMessage("Invalid value '%s' for \"numberOfVar\" attribute in <sos>.\n", xmlGetAttrval(soscons, "numberOfVar"));
2298  *doingfine = FALSE;
2299  return SCIP_OKAY;
2300  }
2301  assert(nsosvars >= 0);
2302 
2303  /* get order of this sos constraint */
2304  attrval = xmlGetAttrval(soscons, "type");
2305  if( attrval == NULL )
2306  {
2307  SCIPerrorMessage("Attribute \"order\" in <sos> node not found.\n");
2308  *doingfine = FALSE;
2309  return SCIP_OKAY;
2310  }
2311 
2312  sosorder = (int)strtol(attrval, (char**)&attrval, 10);
2313  if( *attrval != '\0' || sosorder < 0 || sosorder > 2 )
2314  {
2315  SCIPerrorMessage("Invalid/unsupported value '%s' for \"order\" attribute in <sos>.\n", xmlGetAttrval(soscons, "order"));
2316  *doingfine = FALSE;
2317  return SCIP_OKAY;
2318  }
2319  assert(sosorder == 1 || sosorder == 2);
2320  type = sosorder;
2321 
2322  /* set artificial name for sos constraint*/
2323  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "SOS%d_%d", type, count);
2324 
2325  /* Create sos constraint */
2326  switch( type )
2327  {
2328  case 1:
2329  SCIP_CALL( SCIPcreateConsSOS1(scip, &cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate,
2330  local, dynamic, removable, FALSE) );
2331  break;
2332  case 2:
2333  SCIP_CALL( SCIPcreateConsSOS2(scip, &cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate,
2334  local, dynamic, removable, FALSE) );
2335  break;
2336  default:
2337  SCIPerrorMessage("unknown SOS type: <%d>\n", type); /* should not happen */
2338  SCIPABORT();
2339  return SCIP_INVALIDDATA; /*lint !e527*/
2340  }
2341 
2342  varcount = 0;
2343  for( sosvar = xmlFirstChild(soscons); sosvar!= NULL; sosvar = xmlNextSibl(sosvar), ++varcount )
2344  {
2345  /* get variable id*/
2346  attrval = xmlGetAttrval(sosvar, "idx");
2347  if( attrval == NULL )
2348  {
2349  SCIPerrorMessage("Attribute \"idx\" in <var> node below <specialOrderedSets> node not found.\n");
2350  *doingfine = FALSE;
2351  return SCIP_OKAY;
2352  }
2353 
2354  idx = (int)strtol(attrval, (char**)&attrval, 10);
2355  if( *attrval != '\0' || idx < 0 || idx > nvars - 1 )
2356  {
2357  SCIPerrorMessage("Invalid value '%s' for \"idx\" attribute in <var>.\n", xmlGetAttrval(sosvar, "idx"));
2358  *doingfine = FALSE;
2359  return SCIP_OKAY;
2360  }
2361  assert(idx >= 0);
2362 
2363  /* we now know that we have a variable/weight pair -> add variable*/
2364  switch( type )
2365  {
2366  case 1:
2367  SCIP_CALL( SCIPaddVarSOS1(scip, cons, vars[idx], (SCIP_Real) (nsosvars - varcount)) );
2368  break;
2369  case 2:
2370  SCIP_CALL( SCIPaddVarSOS2(scip, cons, vars[idx], (SCIP_Real) (nsosvars - varcount)) );
2371  break;
2372  default:
2373  SCIPerrorMessage("unknown SOS type: <%d>\n", type); /* should not happen */
2374  SCIPABORT();
2375  return SCIP_INVALIDDATA; /*lint !e527*/
2376  }
2377  } /* Close loop over variables in sos constraint */
2378 
2379  /* add the SOS constraint */
2380  SCIP_CALL( SCIPaddCons(scip, cons) );
2381  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
2382  }
2383 
2384  return SCIP_OKAY;
2385 }
2386 
2387  /*
2388  * Callback methods of reader
2389  */
2390 
2391 
2392 /** copy method for reader plugins (called when SCIP copies plugins) */
2393 static
2394 SCIP_DECL_READERCOPY(readerCopyOsil)
2395 { /*lint --e{715}*/
2396  assert(scip != NULL);
2397 
2399 
2400  return SCIP_OKAY;
2401 }
2402 
2403 /** problem reading method of reader */
2404 static
2405 SCIP_DECL_READERREAD(readerReadOsil)
2406 { /*lint --e{715}*/
2407  const char* name;
2408  XML_NODE* start;
2409  const XML_NODE* header;
2410  const XML_NODE* data;
2411  SCIP_RETCODE retcode;
2412  SCIP_Bool doingfine;
2413  SCIP_Bool initialconss;
2414  SCIP_Bool dynamicconss;
2415  SCIP_Bool dynamiccols;
2416  SCIP_Bool dynamicrows;
2417  SCIP_VAR** vars;
2418  int nvars;
2419  SCIP_CONS** conss;
2420  CONSTYPE* constypes;
2421  int nconss;
2422  SCIP_CONS* objcons;
2423  CONSTYPE objconstype;
2424  int i;
2425 
2426  assert(scip != NULL);
2427  assert(reader != NULL);
2428  assert(result != NULL);
2429  assert(filename != NULL);
2430 
2431  *result = SCIP_DIDNOTRUN;
2432  retcode = SCIP_READERROR;
2433  doingfine = TRUE;
2434  vars = NULL;
2435  nvars = 0;
2436  conss = NULL;
2437  constypes = NULL;
2438  nconss = 0;
2439  objcons = NULL;
2440 
2441  /* read OSiL xml file */
2442  start = xmlProcess(filename);
2443 
2444  if( start == NULL )
2445  {
2446  SCIPerrorMessage("Some error occurred when parsing the OSiL XML file '%s'.\n", filename);
2447  goto CLEANUP;
2448  }
2449 
2450  SCIPdebug( xmlShowNode(start) );
2451 
2452  /* parse header to get problem name */
2453  name = filename;
2454  header = xmlFindNodeMaxdepth(start, "instanceHeader", 0, 2);
2455  if( header != NULL )
2456  {
2457  const XML_NODE* namenode;
2458 
2459  namenode = xmlFindNodeMaxdepth(header, "name", 0, 2);
2460 
2461  if( namenode != NULL && xmlFirstChild(namenode) != NULL )
2462  name = xmlGetData(xmlFirstChild(namenode));
2463  else
2464  {
2465  namenode = xmlFindNodeMaxdepth(header, "description", 0, 2);
2466 
2467  if( namenode != NULL && xmlFirstChild(namenode) != NULL )
2468  name = xmlGetData(xmlFirstChild(namenode));
2469  }
2470  }
2471 
2472  /* create SCIP problem */
2474 
2475  /* process instance data */
2476  data = xmlFindNodeMaxdepth(start, "instanceData", 0, 2);
2477  if( data == NULL )
2478  {
2479  SCIPerrorMessage("Node <instanceData> not found.\n");
2480  goto CLEANUP;
2481  }
2482 
2483  SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &initialconss) );
2484  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &dynamicconss) );
2485  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &dynamiccols) );
2486  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &dynamicrows) );
2487 
2488  /* read variables */
2489  SCIP_CALL_TERMINATE( retcode, readVariables(scip, data, &vars, &nvars, initialconss, dynamicconss, dynamiccols, dynamicrows, &doingfine), CLEANUP );
2490  if( !doingfine )
2491  goto CLEANUP;
2492  assert(vars != NULL || nvars == 0);
2493 
2494  /* read objective sense, coefficient, and constant */
2495  SCIP_CALL_TERMINATE( retcode, readObjective(scip, data, vars, nvars, dynamiccols, &doingfine), CLEANUP );
2496  if( !doingfine )
2497  goto CLEANUP;
2498 
2499  /* read constraint data (names, constants, lhs/rhs) */
2500  SCIP_CALL_TERMINATE( retcode, readConstraints(scip, data, &conss, &constypes, &nconss, initialconss, dynamicconss, dynamicrows, &doingfine), CLEANUP );
2501  if( !doingfine )
2502  goto CLEANUP;
2503  assert(conss != NULL || nconss == 0);
2504 
2505  /* read linear coefficients matrix */
2506  SCIP_CALL_TERMINATE( retcode, readLinearCoefs(scip, data, vars, nvars, conss, constypes, nconss, &doingfine), CLEANUP );
2507  if( !doingfine )
2508  goto CLEANUP;
2509 
2510  /* read quadratic coefficients (turns linear constraints into quadratic ones, may create objcons) */
2511  SCIP_CALL_TERMINATE( retcode, readQuadraticCoefs(scip, data, vars, nvars, conss, constypes, nconss, &objcons, &objconstype, &doingfine), CLEANUP );
2512  if( !doingfine )
2513  goto CLEANUP;
2514 
2515  /* read nonlinear expressions (turns constraints into nonlinear ones, may create objcons) */
2516  SCIP_CALL_TERMINATE( retcode, readNonlinearExprs(scip, data, vars, nvars, conss, constypes, nconss, &objcons, &objconstype, &doingfine), CLEANUP );
2517  if( !doingfine )
2518  goto CLEANUP;
2519 
2520  /* add constraints to problem */
2521  for( i = 0; i < nconss; ++i )
2522  {
2523  assert(conss[i] != NULL); /*lint !e613*/
2524  SCIP_CALL( SCIPaddCons(scip, conss[i]) ); /*lint !e613*/
2525  }
2526  if( objcons != NULL )
2527  {
2528  SCIP_CALL( SCIPaddCons(scip, objcons) );
2529  }
2530 
2531  /* read sos2 constraints and add to problem*/
2532  SCIP_CALL_TERMINATE( retcode, readSOScons(scip, data, vars, nvars, initialconss, dynamicconss, dynamicrows, &doingfine), CLEANUP );
2533  if( !doingfine )
2534  goto CLEANUP;
2535 
2536  *result = SCIP_SUCCESS;
2537  retcode = SCIP_OKAY;
2538 
2539  CLEANUP:
2540  /* free xml data */
2541  if( start != NULL )
2542  xmlFreeNode(start);
2543 
2544  /* free variables */
2545  for( i = 0; i < nvars; ++i )
2546  {
2547  SCIP_CALL( SCIPreleaseVar(scip, &vars[i]) ); /*lint !e613*/
2548  }
2549  SCIPfreeBufferArrayNull(scip, &vars);
2550 
2551  /* free constraints */
2552  for( i = 0; i < nconss; ++i )
2553  {
2554  SCIP_CALL( SCIPreleaseCons(scip, &conss[i]) ); /*lint !e613*/
2555  }
2556  SCIPfreeBufferArrayNull(scip, &conss);
2557  SCIPfreeBufferArrayNull(scip, &constypes);
2558 
2559  if( objcons != NULL )
2560  {
2561  SCIP_CALL( SCIPreleaseCons(scip, &objcons) );
2562  }
2563 
2564  /* return read error retcode if something went wrong */
2565  if( !doingfine )
2566  return SCIP_READERROR;
2567 
2568  if( retcode == SCIP_PLUGINNOTFOUND )
2569  retcode = SCIP_READERROR;
2570 
2571  SCIP_CALL( retcode );
2572 
2573  return SCIP_OKAY;
2574 }
2575 
2576 /*
2577  * reader specific interface methods
2578  */
2579 
2580 /** includes the osil file reader in SCIP */
2582  SCIP* scip /**< SCIP data structure */
2583  )
2584 {
2585  SCIP_READER* reader;
2586 
2587  /* include osil reader */
2589 
2590  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyOsil) );
2591  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadOsil) );
2592 
2593  return SCIP_OKAY;
2594 }
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
void SCIPexprFreeDeep(BMS_BLKMEM *blkmem, SCIP_EXPR **expr)
Definition: expr.c:6183
#define NULL
Definition: def.h:239
public methods for SCIP parameter handling
#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:1870
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8335
#define READER_NAME
Definition: reader_osil.c:50
static SCIP_DECL_READERCOPY(readerCopyOsil)
Definition: reader_osil.c:2394
public methods for memory management
SCIP_EXPROP SCIPexprGetOperator(SCIP_EXPR *expr)
Definition: expr.c:5693
#define SCIP_MAXSTRLEN
Definition: def.h:260
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:162
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:210
SCIP_RETCODE SCIPaddVarSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real weight)
Definition: cons_sos2.c:2416
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1251
CONSTYPE
Definition: reader_osil.c:59
#define FALSE
Definition: def.h:65
SCIP_Real * SCIPgetLinearCoefsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPinfinity(SCIP *scip)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10017
#define TRUE
Definition: def.h:64
#define SCIPdebug(x)
Definition: pub_message.h:74
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8355
SCIP_Real SCIPgetRhsNonlinear(SCIP *scip, SCIP_CONS *cons)
public methods for problem variables
SCIP_RETCODE SCIPexprtreeSetVars(SCIP_EXPRTREE *tree, int nvars, SCIP_VAR **vars)
Definition: nlp.c:112
XML_NODE * xmlProcess(const char *filename)
Definition: xmlparse.c:1072
OS instance language (OSiL) format file reader.
const XML_NODE * xmlFirstChild(const XML_NODE *node)
Definition: xmlparse.c:1456
const char * xmlGetData(const XML_NODE *node)
Definition: xmlparse.c:1496
SCIP_RETCODE SCIPexprtreeCreate(BMS_BLKMEM *blkmem, SCIP_EXPRTREE **tree, SCIP_EXPR *root, int nvars, int nparams, SCIP_Real *params)
Definition: expr.c:8771
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:142
public methods for SCIP variables
SCIP_RETCODE SCIPaddExprtreesNonlinear(SCIP *scip, SCIP_CONS *cons, int nexprtrees, SCIP_EXPRTREE **exprtrees, SCIP_Real *coefs)
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8345
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:2200
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_RETCODE SCIPcreateConsQuadratic(SCIP *scip, SCIP_CONS **cons, const char *name, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int nquadterms, SCIP_VAR **quadvars1, SCIP_VAR **quadvars2, SCIP_Real *quadcoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable)
public methods for numerical tolerances
int SCIPgetNQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
public methods for expressions, expression trees, expression graphs, and related stuff ...
int SCIPgetNBilinTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
void xmlShowNode(const XML_NODE *root)
Definition: xmlparse.c:1296
SCIP_Real coef
Definition: type_expr.h:104
public methods for managing constraints
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition: scip_prob.c:1298
#define READER_DESC
Definition: reader_osil.c:51
static SCIP_DECL_READERREAD(readerReadOsil)
Definition: reader_osil.c:2405
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:6584
SCIP_RETCODE SCIPfindQuadVarTermQuadratic(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, int *pos)
#define SCIPerrorMessage
Definition: pub_message.h:45
enum SCIP_ExprOp SCIP_EXPROP
Definition: type_expr.h:91
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2822
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:1223
struct XML_NODE_struct XML_NODE
Definition: xml.h:41
SCIP_RETCODE SCIPaddVarSOS1(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real weight)
Definition: cons_sos1.c:10504
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip_mem.h:143
const XML_NODE * xmlFindNodeMaxdepth(const XML_NODE *node, const char *name, int depth, int maxdepth)
Definition: xmlparse.c:1406
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:128
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8076
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8295
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16729
constraint handler for quadratic constraints
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip_param.c:322
#define SCIP_CALL(x)
Definition: def.h:351
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8315
SCIP_BILINTERM * SCIPgetBilinTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPexprMulConstant(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, SCIP_EXPR *term, SCIP_Real factor)
Definition: expr.c:6404
public methods for constraint handler plugins and constraints
public methods for NLP management
SCIP_RETCODE SCIPincludeReaderOsil(SCIP *scip)
Definition: reader_osil.c:2581
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_var.c:4450
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:6246
SCIP_RETCODE SCIPaddBilinTermQuadratic(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var1, SCIP_VAR *var2, SCIP_Real coef)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:130
public data structures and miscellaneous methods
#define SCIP_Bool
Definition: def.h:62
SCIP_RETCODE SCIPincludeReaderBasic(SCIP *scip, SCIP_READER **readerptr, const char *name, const char *desc, const char *extension, SCIP_READERDATA *readerdata)
Definition: scip_reader.c:180
SCIP_Real SCIPgetLhsNonlinear(SCIP *scip, SCIP_CONS *cons)
constraint handler for nonlinear constraints
static SCIP_RETCODE readLinearCoefs(SCIP *scip, const XML_NODE *datanode, SCIP_VAR **vars, int nvars, SCIP_CONS **conss, CONSTYPE *constypes, int nconss, SCIP_Bool *doingfine)
Definition: reader_osil.c:669
#define MIN(x, y)
Definition: def.h:209
SCIP_RETCODE SCIPexprCreate(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, SCIP_EXPROP op,...)
Definition: expr.c:5973
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8275
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8245
SCIP_RETCODE SCIPexprtreeFree(SCIP_EXPRTREE **tree)
Definition: expr.c:8852
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
SCIPInterval log(const SCIPInterval &x)
Constraint handler for linear constraints in their most general form, .
const char * xmlGetName(const XML_NODE *node)
Definition: xmlparse.c:1476
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
Definition: scip_reader.c:218
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_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
static void readMultIncr(const XML_NODE *node, int *mult, int *incrint, SCIP_Real *incrreal, SCIP_Bool *doingfine)
Definition: reader_osil.c:603
#define MAX(x, y)
Definition: def.h:208
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
int SCIPgetNLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1724
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPexprGetOpReal(SCIP_EXPR *expr)
Definition: expr.c:5734
const char * xmlGetAttrval(const XML_NODE *node, const char *name)
Definition: xmlparse.c:1324
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1187
public methods for message output
SCIP_RETCODE SCIPsortQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE readQuadraticCoefs(SCIP *scip, const XML_NODE *datanode, SCIP_VAR **vars, int nvars, SCIP_CONS **conss, CONSTYPE *constypes, int nconss, SCIP_CONS **objcons, CONSTYPE *objconstype, SCIP_Bool *doingfine)
Definition: reader_osil.c:1009
#define SCIP_Real
Definition: def.h:150
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8325
SCIP_VAR ** SCIPgetLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:372
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
SCIP_RETCODE SCIPcreateConsNonlinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int nexprtrees, SCIP_EXPRTREE **exprtrees, SCIP_Real *nonlincoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8265
#define SCIP_INVALID
Definition: def.h:170
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8255
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip_reader.c:266
#define SCIPisFinite(x)
Definition: pub_misc.h:1769
declarations for XML parsing
SCIP_OBJSENSE SCIPgetObjsense(SCIP *scip)
Definition: scip_prob.c:1281
SCIP_RETCODE SCIPcreateConsBounddisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsSOS1(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *weights, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_sos1.c:10367
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:60
constraint handler for SOS type 2 constraints
SCIP_RETCODE SCIPcreateConsSOS2(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *weights, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_sos2.c:2317
void xmlFreeNode(XML_NODE *node)
Definition: xmlparse.c:1262
SCIP_QUADVARTERM * SCIPgetQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPexprCreateLinear(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real *coefs, SCIP_Real constant)
Definition: expr.c:6502
constraint handler for bound disjunction constraints
public methods for reader plugins
#define SCIPABORT()
Definition: def.h:323
public methods for global and local (sub)problems
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
const XML_NODE * xmlNextSibl(const XML_NODE *node)
Definition: xmlparse.c:1436
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:134
memory allocation routines