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