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