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_pip.c
26   	 * @ingroup DEFPLUGINS_READER
27   	 * @brief  file reader for polynomial mixed-integer programs in PIP format
28   	 * @author Stefan Vigerske
29   	 * @author Marc Pfetsch
30   	 */
31   	
32   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33   	
34   	#include <ctype.h>
35   	
36   	#include "blockmemshell/memory.h"
37   	#include "scip/reader_pip.h"
38   	#include "scip/cons_and.h"
39   	#include "scip/cons_nonlinear.h"
40   	#include "scip/cons_knapsack.h"
41   	#include "scip/cons_linear.h"
42   	#include "scip/cons_logicor.h"
43   	#include "scip/cons_setppc.h"
44   	#include "scip/cons_varbound.h"
45   	#include "scip/expr_sum.h"
46   	#include "scip/expr_var.h"
47   	#include "scip/pub_cons.h"
48   	#include "scip/pub_expr.h"
49   	#include "scip/pub_fileio.h"
50   	#include "scip/pub_message.h"
51   	#include "scip/pub_misc.h"
52   	#include "scip/pub_nlp.h"
53   	#include "scip/pub_reader.h"
54   	#include "scip/pub_var.h"
55   	#include "scip/scip_cons.h"
56   	#include "scip/scip_mem.h"
57   	#include "scip/scip_message.h"
58   	#include "scip/scip_numerics.h"
59   	#include "scip/scip_param.h"
60   	#include "scip/scip_prob.h"
61   	#include "scip/scip_reader.h"
62   	#include "scip/scip_var.h"
63   	#include <stdlib.h>
64   	#include <string.h>
65   	#include <ctype.h>
66   	
67   	#if !defined(_WIN32) && !defined(_WIN64)
68   	#include <strings.h> /*lint --e{766}*/ /* needed for strncasecmp() */
69   	#endif
70   	
71   	#define READER_NAME             "pipreader"
72   	#define READER_DESC             "file reader for polynomial mixed-integer programs in PIP format"
73   	#define READER_EXTENSION        "pip"
74   	
75   	
76   	/*
77   	 * Data structures
78   	 */
79   	#define PIP_MAX_LINELEN        65536
80   	#define PIP_MAX_PUSHEDTOKENS   2
81   	#define PIP_INIT_MONOMIALSSIZE 128
82   	#define PIP_INIT_FACTORSSIZE   16
83   	#define PIP_MAX_PRINTLEN       561       /**< the maximum length of any line is 560 + '\\0' = 561*/
84   	#define PIP_MAX_NAMELEN        256       /**< the maximum length for any name is 255 + '\\0' = 256 */
85   	#define PIP_PRINTLEN           100
86   	
87   	/** Section in PIP File */
88   	enum PipSection
89   	{
90   	   PIP_START,
91   	   PIP_OBJECTIVE,
92   	   PIP_CONSTRAINTS,
93   	   PIP_BOUNDS,
94   	   PIP_GENERALS,
95   	   PIP_BINARIES,
96   	   PIP_END
97   	};
98   	typedef enum PipSection PIPSECTION;
99   	
100  	enum PipExpType
101  	{
102  	   PIP_EXP_NONE,
103  	   PIP_EXP_UNSIGNED,
104  	   PIP_EXP_SIGNED
105  	};
106  	typedef enum PipExpType PIPEXPTYPE;
107  	
108  	enum PipSense
109  	{
110  	   PIP_SENSE_NOTHING,
111  	   PIP_SENSE_LE,
112  	   PIP_SENSE_GE,
113  	   PIP_SENSE_EQ
114  	};
115  	typedef enum PipSense PIPSENSE;
116  	
117  	/** PIP reading data */
118  	struct PipInput
119  	{
120  	   SCIP_FILE*            file;
121  	   char                  linebuf[PIP_MAX_LINELEN+1];
122  	   char                  probname[PIP_MAX_LINELEN];
123  	   char                  objname[PIP_MAX_LINELEN];
124  	   char*                 token;
125  	   char*                 tokenbuf;
126  	   char*                 pushedtokens[PIP_MAX_PUSHEDTOKENS];
127  	   int                   npushedtokens;
128  	   int                   linenumber;
129  	   int                   linepos;
130  	   PIPSECTION            section;
131  	   SCIP_OBJSENSE         objsense;
132  	   SCIP_Bool             initialconss;       /**< should model constraints be marked as initial? */
133  	   SCIP_Bool             dynamicconss;       /**< should model constraints be subject to aging? */
134  	   SCIP_Bool             dynamiccols;        /**< should columns be added and removed dynamically to the LP? */
135  	   SCIP_Bool             dynamicrows;        /**< should rows be added and removed dynamically to the LP? */
136  	   SCIP_Bool             haserror;
137  	};
138  	typedef struct PipInput PIPINPUT;
139  	
140  	static const char delimchars[] = " \f\n\r\t\v";
141  	static const char tokenchars[] = "-+:<>=*^";
142  	static const char commentchars[] = "\\";
143  	static const char namechars[] = "!#$%&;?@_";  /* and characters and numbers */
144  	
145  	
146  	/*
147  	 * Local methods (for reading)
148  	 */
149  	
150  	/** issues an error message and marks the PIP data to have errors */
151  	static
152  	void syntaxError(
153  	   SCIP*                 scip,               /**< SCIP data structure */
154  	   PIPINPUT*             pipinput,           /**< PIP reading data */
155  	   const char*           msg                 /**< error message */
156  	   )
157  	{
158  	   char formatstr[256];
159  	
160  	   assert(pipinput != NULL);
161  	
162  	   SCIPerrorMessage("Syntax error in line %d: %s ('%s')\n", pipinput->linenumber, msg, pipinput->token);
163  	   if( pipinput->linebuf[strlen(pipinput->linebuf)-1] == '\n' )
164  	   {
165  	      SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "  input: %s", pipinput->linebuf);
166  	   }
167  	   else
168  	   {
169  	      SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "  input: %s\n", pipinput->linebuf);
170  	   }
171  	   (void) SCIPsnprintf(formatstr, 256, "         %%%ds\n", pipinput->linepos);
172  	   SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, formatstr, "^");
173  	   pipinput->section  = PIP_END;
174  	   pipinput->haserror = TRUE;
175  	}
176  	
177  	/** returns whether a syntax error was detected */
178  	static
179  	SCIP_Bool hasError(
180  	   PIPINPUT*             pipinput            /**< PIP reading data */
181  	   )
182  	{
183  	   assert(pipinput != NULL);
184  	
185  	   return pipinput->haserror;
186  	}
187  	
188  	/** returns whether the given character is a token delimiter */
189  	static
190  	SCIP_Bool isDelimChar(
191  	   char                  c                   /**< input character */
192  	   )
193  	{
194  	   return (c == '\0') || (strchr(delimchars, c) != NULL);
195  	}
196  	
197  	/** returns whether the given character is a single token */
198  	static
199  	SCIP_Bool isTokenChar(
200  	   char                  c                   /**< input character */
201  	   )
202  	{
203  	   return (strchr(tokenchars, c) != NULL);
204  	}
205  	
206  	/** returns whether the current character is member of a value string */
207  	static
208  	SCIP_Bool isValueChar(
209  	   char                  c,                  /**< input character */
210  	   char                  nextc,              /**< next input character */
211  	   SCIP_Bool             firstchar,          /**< is the given character the first char of the token? */
212  	   SCIP_Bool*            hasdot,             /**< pointer to update the dot flag */
213  	   PIPEXPTYPE*           exptype             /**< pointer to update the exponent type */
214  	   )
215  	{
216  	   assert(hasdot != NULL);
217  	   assert(exptype != NULL);
218  	
219  	   if( isdigit((unsigned char)c) )
220  	      return TRUE;
221  	   else if( (*exptype == PIP_EXP_NONE) && !(*hasdot) && (c == '.') && isdigit((unsigned char)nextc) )
222  	   {
223  	      *hasdot = TRUE;
224  	      return TRUE;
225  	   }
226  	   else if( !firstchar && (*exptype == PIP_EXP_NONE) && (c == 'e' || c == 'E') )
227  	   {
228  	      if( nextc == '+' || nextc == '-' )
229  	      {
230  	         *exptype = PIP_EXP_SIGNED;
231  	         return TRUE;
232  	      }
233  	      else if( isdigit((unsigned char)nextc) )
234  	      {
235  	         *exptype = PIP_EXP_UNSIGNED;
236  	         return TRUE;
237  	      }
238  	   }
239  	   else if( (*exptype == PIP_EXP_SIGNED) && (c == '+' || c == '-') )
240  	   {
241  	      *exptype = PIP_EXP_UNSIGNED;
242  	      return TRUE;
243  	   }
244  	
245  	   return FALSE;
246  	}
247  	
248  	/** reads the next line from the input file into the line buffer; skips comments;
249  	 *  returns whether a line could be read
250  	 */
251  	static
252  	SCIP_Bool getNextLine(
253  	   SCIP*                 scip,               /**< SCIP data structure */
254  	   PIPINPUT*             pipinput            /**< PIP reading data */
255  	   )
256  	{
257  	   int i;
258  	
259  	   assert(scip != NULL);  /* for lint */
260  	   assert(pipinput != NULL);
261  	
262  	   /* clear the line */
263  	   BMSclearMemoryArray(pipinput->linebuf, PIP_MAX_LINELEN);
264  	
265  	   /* read next line */
266  	   pipinput->linepos = 0;
267  	   pipinput->linebuf[PIP_MAX_LINELEN-2] = '\0';
268  	   if( SCIPfgets(pipinput->linebuf, (int) sizeof(pipinput->linebuf), pipinput->file) == NULL )
269  	      return FALSE;
270  	   pipinput->linenumber++;
271  	   if( pipinput->linebuf[PIP_MAX_LINELEN-2] != '\0' )
272  	   {
273  	      SCIPerrorMessage("Error: line %d exceeds %d characters\n", pipinput->linenumber, PIP_MAX_LINELEN-2);
274  	      pipinput->haserror = TRUE;
275  	      return FALSE;
276  	   }
277  	   pipinput->linebuf[PIP_MAX_LINELEN-1] = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
278  	
279  	   /* skip characters after comment symbol */
280  	   for( i = 0; commentchars[i] != '\0'; ++i )
281  	   {
282  	      char* commentstart;
283  	
284  	      commentstart = strchr(pipinput->linebuf, commentchars[i]);
285  	      if( commentstart != NULL )
286  	      {
287  	         *commentstart = '\0';
288  	         *(commentstart+1) = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
289  	      }
290  	   }
291  	
292  	   return TRUE;
293  	}
294  	
295  	/** swaps the addresses of two pointers */
296  	static
297  	void swapPointers(
298  	   char**                pointer1,           /**< first pointer */
299  	   char**                pointer2            /**< second pointer */
300  	   )
301  	{
302  	   char* tmp;
303  	
304  	   tmp = *pointer1;
305  	   *pointer1 = *pointer2;
306  	   *pointer2 = tmp;
307  	}
308  	
309  	/** reads the next token from the input file into the token buffer; returns whether a token was read */
310  	static
311  	SCIP_Bool getNextToken(
312  	   SCIP*                 scip,               /**< SCIP data structure */
313  	   PIPINPUT*             pipinput            /**< PIP reading data */
314  	   )
315  	{
316  	   SCIP_Bool hasdot;
317  	   PIPEXPTYPE exptype;
318  	   char* buf;
319  	   int tokenlen;
320  	
321  	   assert(pipinput != NULL);
322  	   assert(pipinput->linepos < PIP_MAX_LINELEN);
323  	
324  	   /* check the token stack */
325  	   if( pipinput->npushedtokens > 0 )
326  	   {
327  	      swapPointers(&pipinput->token, &pipinput->pushedtokens[pipinput->npushedtokens-1]);
328  	      pipinput->npushedtokens--;
329  	      SCIPdebugMsg(scip, "(line %d) read token again: '%s'\n", pipinput->linenumber, pipinput->token);
330  	      return TRUE;
331  	   }
332  	
333  	   /* skip delimiters */
334  	   buf = pipinput->linebuf;
335  	   while( isDelimChar(buf[pipinput->linepos]) )
336  	   {
337  	      if( buf[pipinput->linepos] == '\0' )
338  	      {
339  	         if( !getNextLine(scip, pipinput) )
340  	         {
341  	            pipinput->section = PIP_END;
342  	            SCIPdebugMsg(scip, "(line %d) end of file\n", pipinput->linenumber);
343  	            return FALSE;
344  	         }
345  	         assert(pipinput->linepos == 0);
346  	      }
347  	      else
348  	         pipinput->linepos++;
349  	   }
350  	   assert(pipinput->linepos < PIP_MAX_LINELEN);
351  	   assert(!isDelimChar(buf[pipinput->linepos]));
352  	
353  	   /* check if the token is a value */
354  	   hasdot = FALSE;
355  	   exptype = PIP_EXP_NONE;
356  	   if( isValueChar(buf[pipinput->linepos], buf[pipinput->linepos+1], TRUE, &hasdot, &exptype) )
357  	   {
358  	      /* read value token */
359  	      tokenlen = 0;
360  	      do
361  	      {
362  	         assert(tokenlen < PIP_MAX_LINELEN);
363  	         assert(!isDelimChar(buf[pipinput->linepos]));
364  	         pipinput->token[tokenlen] = buf[pipinput->linepos];
365  	         tokenlen++;
366  	         pipinput->linepos++;
367  	      }
368  	      while( isValueChar(buf[pipinput->linepos], buf[pipinput->linepos+1], FALSE, &hasdot, &exptype) );
369  	   }
370  	   else
371  	   {
372  	      /* read non-value token */
373  	      tokenlen = 0;
374  	      do
375  	      {
376  	         assert(tokenlen < PIP_MAX_LINELEN);
377  	         pipinput->token[tokenlen] = buf[pipinput->linepos];
378  	         tokenlen++;
379  	         pipinput->linepos++;
380  	         if( tokenlen == 1 && isTokenChar(pipinput->token[0]) )
381  	            break;
382  	      }
383  	      while( !isDelimChar(buf[pipinput->linepos]) && !isTokenChar(buf[pipinput->linepos]) );
384  	
385  	      /* if the token is an equation sense '<', '>', or '=', skip a following '='
386  	       * if the token is an equality token '=' and the next character is a '<' or '>', replace the token by the inequality sense
387  	       */
388  	      if( tokenlen >= 1
389  	         && (pipinput->token[tokenlen-1] == '<' || pipinput->token[tokenlen-1] == '>' || pipinput->token[tokenlen-1] == '=')
390  	         && buf[pipinput->linepos] == '=' )
391  	      {
392  	         pipinput->linepos++;
393  	      }
394  	      else if( pipinput->token[tokenlen-1] == '=' && (buf[pipinput->linepos] == '<' || buf[pipinput->linepos] == '>') )
395  	      {
396  	         pipinput->token[tokenlen-1] = buf[pipinput->linepos];
397  	         pipinput->linepos++;
398  	      }
399  	   }
400  	   assert(tokenlen < PIP_MAX_LINELEN);
401  	   pipinput->token[tokenlen] = '\0';
402  	
403  	   SCIPdebugMsg(scip, "(line %d) read token: '%s'\n", pipinput->linenumber, pipinput->token);
404  	
405  	   return TRUE;
406  	}
407  	
408  	/** puts the current token on the token stack, such that it is read at the next call to getNextToken() */
409  	static
410  	void pushToken(
411  	   PIPINPUT*             pipinput            /**< PIP reading data */
412  	   )
413  	{
414  	   assert(pipinput != NULL);
415  	   assert(pipinput->npushedtokens < PIP_MAX_PUSHEDTOKENS);
416  	
417  	   swapPointers(&pipinput->pushedtokens[pipinput->npushedtokens], &pipinput->token);
418  	   pipinput->npushedtokens++;
419  	}
420  	
421  	/** puts the buffered token on the token stack, such that it is read at the next call to getNextToken() */
422  	static
423  	void pushBufferToken(
424  	   PIPINPUT*             pipinput            /**< PIP reading data */
425  	   )
426  	{
427  	   assert(pipinput != NULL);
428  	   assert(pipinput->npushedtokens < PIP_MAX_PUSHEDTOKENS);
429  	
430  	   swapPointers(&pipinput->pushedtokens[pipinput->npushedtokens], &pipinput->tokenbuf);
431  	   pipinput->npushedtokens++;
432  	}
433  	
434  	/** swaps the current token with the token buffer */
435  	static
436  	void swapTokenBuffer(
437  	   PIPINPUT*             pipinput            /**< PIP reading data */
438  	   )
439  	{
440  	   assert(pipinput != NULL);
441  	
442  	   swapPointers(&pipinput->token, &pipinput->tokenbuf);
443  	}
444  	
445  	/** checks whether the current token is a section identifier, and if yes, switches to the corresponding section */
446  	static
447  	SCIP_Bool isNewSection(
448  	   SCIP*                 scip,               /**< SCIP data structure */
449  	   PIPINPUT*             pipinput            /**< PIP reading data */
450  	   )
451  	{
452  	   SCIP_Bool iscolon;
453  	
454  	   assert(pipinput != NULL);
455  	
456  	   /* remember first token by swapping the token buffer */
457  	   swapTokenBuffer(pipinput);
458  	
459  	   /* look at next token: if this is a ':', the first token is a name and no section keyword */
460  	   iscolon = FALSE;
461  	   if( getNextToken(scip, pipinput) )
462  	   {
463  	      iscolon = (strcmp(pipinput->token, ":") == 0);
464  	      pushToken(pipinput);
465  	   }
466  	
467  	   /* reinstall the previous token by swapping back the token buffer */
468  	   swapTokenBuffer(pipinput);
469  	
470  	   /* check for ':' */
471  	   if( iscolon )
472  	      return FALSE;
473  	
474  	   if( strcasecmp(pipinput->token, "MINIMIZE") == 0
475  	      || strcasecmp(pipinput->token, "MINIMUM") == 0
476  	      || strcasecmp(pipinput->token, "MIN") == 0 )
477  	   {
478  	      SCIPdebugMsg(scip, "(line %d) new section: OBJECTIVE\n", pipinput->linenumber);
479  	      pipinput->section = PIP_OBJECTIVE;
480  	      pipinput->objsense = SCIP_OBJSENSE_MINIMIZE;
481  	      return TRUE;
482  	   }
483  	
484  	   if( strcasecmp(pipinput->token, "MAXIMIZE") == 0
485  	      || strcasecmp(pipinput->token, "MAXIMUM") == 0
486  	      || strcasecmp(pipinput->token, "MAX") == 0 )
487  	   {
488  	      SCIPdebugMsg(scip, "(line %d) new section: OBJECTIVE\n", pipinput->linenumber);
489  	      pipinput->section = PIP_OBJECTIVE;
490  	      pipinput->objsense = SCIP_OBJSENSE_MAXIMIZE;
491  	      return TRUE;
492  	   }
493  	
494  	   if( strcasecmp(pipinput->token, "SUBJECT") == 0 )
495  	   {
496  	      /* check if the next token is 'TO' */
497  	      swapTokenBuffer(pipinput);
498  	      if( getNextToken(scip, pipinput) )
499  	      {
500  	         if( strcasecmp(pipinput->token, "TO") == 0 )
501  	         {
502  	            SCIPdebugMsg(scip, "(line %d) new section: CONSTRAINTS\n", pipinput->linenumber);
503  	            pipinput->section = PIP_CONSTRAINTS;
504  	            return TRUE;
505  	         }
506  	         else
507  	            pushToken(pipinput);
508  	      }
509  	      swapTokenBuffer(pipinput);
510  	   }
511  	
512  	   if( strcasecmp(pipinput->token, "SUCH") == 0 )
513  	   {
514  	      /* check if the next token is 'THAT' */
515  	      swapTokenBuffer(pipinput);
516  	      if( getNextToken(scip, pipinput) )
517  	      {
518  	         if( strcasecmp(pipinput->token, "THAT") == 0 )
519  	         {
520  	            SCIPdebugMsg(scip, "(line %d) new section: CONSTRAINTS\n", pipinput->linenumber);
521  	            pipinput->section = PIP_CONSTRAINTS;
522  	            return TRUE;
523  	         }
524  	         else
525  	            pushToken(pipinput);
526  	      }
527  	      swapTokenBuffer(pipinput);
528  	   }
529  	
530  	   if( strcasecmp(pipinput->token, "st") == 0
531  	      || strcasecmp(pipinput->token, "S.T.") == 0
532  	      || strcasecmp(pipinput->token, "ST.") == 0 )
533  	   {
534  	      SCIPdebugMsg(scip, "(line %d) new section: CONSTRAINTS\n", pipinput->linenumber);
535  	      pipinput->section = PIP_CONSTRAINTS;
536  	      return TRUE;
537  	   }
538  	
539  	   if( strcasecmp(pipinput->token, "BOUNDS") == 0
540  	      || strcasecmp(pipinput->token, "BOUND") == 0 )
541  	   {
542  	      SCIPdebugMsg(scip, "(line %d) new section: BOUNDS\n", pipinput->linenumber);
543  	      pipinput->section = PIP_BOUNDS;
544  	      return TRUE;
545  	   }
546  	
547  	   if( strcasecmp(pipinput->token, "GENERAL") == 0
548  	      || strcasecmp(pipinput->token, "GENERALS") == 0
549  	      || strcasecmp(pipinput->token, "GEN") == 0
550  	      || strcasecmp(pipinput->token, "INTEGER") == 0
551  	      || strcasecmp(pipinput->token, "INTEGERS") == 0
552  	      || strcasecmp(pipinput->token, "INT") == 0 )
553  	   {
554  	      SCIPdebugMsg(scip, "(line %d) new section: GENERALS\n", pipinput->linenumber);
555  	      pipinput->section = PIP_GENERALS;
556  	      return TRUE;
557  	   }
558  	
559  	   if( strcasecmp(pipinput->token, "BINARY") == 0
560  	      || strcasecmp(pipinput->token, "BINARIES") == 0
561  	      || strcasecmp(pipinput->token, "BIN") == 0 )
562  	   {
563  	      SCIPdebugMsg(scip, "(line %d) new section: BINARIES\n", pipinput->linenumber);
564  	      pipinput->section = PIP_BINARIES;
565  	      return TRUE;
566  	   }
567  	
568  	   if( strcasecmp(pipinput->token, "END") == 0 )
569  	   {
570  	      SCIPdebugMsg(scip, "(line %d) new section: END\n", pipinput->linenumber);
571  	      pipinput->section = PIP_END;
572  	      return TRUE;
573  	   }
574  	
575  	   return FALSE;
576  	}
577  	
578  	/** returns whether the current token is a sign */
579  	static
580  	SCIP_Bool isSign(
581  	   PIPINPUT*             pipinput,           /**< PIP reading data */
582  	   int*                  sign                /**< pointer to update the sign */
583  	   )
584  	{
585  	   assert(pipinput != NULL);
586  	   assert(sign != NULL);
587  	   assert(*sign == +1 || *sign == -1);
588  	
589  	   if( pipinput->token[1] == '\0' )
590  	   {
591  	      if( *pipinput->token == '+' )
592  	         return TRUE;
593  	      else if( *pipinput->token == '-' )
594  	      {
595  	         *sign *= -1;
596  	         return TRUE;
597  	      }
598  	   }
599  	
600  	   return FALSE;
601  	}
602  	
603  	/** returns whether the current token is a value */
604  	static
605  	SCIP_Bool isValue(
606  	   SCIP*                 scip,               /**< SCIP data structure */
607  	   PIPINPUT*             pipinput,           /**< PIP reading data */
608  	   SCIP_Real*            value               /**< pointer to store the value (unchanged, if token is no value) */
609  	   )
610  	{
611  	   assert(pipinput != NULL);
612  	   assert(value != NULL);
613  	
614  	   if( strcasecmp(pipinput->token, "INFINITY") == 0 || strcasecmp(pipinput->token, "INF") == 0 )
615  	   {
616  	      *value = SCIPinfinity(scip);
617  	      return TRUE;
618  	   }
619  	   else
620  	   {
621  	      double val;
622  	      char* endptr;
623  	
624  	      val = strtod(pipinput->token, &endptr);
625  	      if( endptr != pipinput->token && *endptr == '\0' )
626  	      {
627  	         *value = val;
628  	         return TRUE;
629  	      }
630  	   }
631  	
632  	   return FALSE;
633  	}
634  	
635  	/** returns whether the current token is an equation sense */
636  	static
637  	SCIP_Bool isSense(
638  	   PIPINPUT*             pipinput,           /**< PIP reading data */
639  	   PIPSENSE*             sense               /**< pointer to store the equation sense, or NULL */
640  	   )
641  	{
642  	   assert(pipinput != NULL);
643  	
644  	   if( strcmp(pipinput->token, "<") == 0 )
645  	   {
646  	      if( sense != NULL )
647  	         *sense = PIP_SENSE_LE;
648  	      return TRUE;
649  	   }
650  	   else if( strcmp(pipinput->token, ">") == 0 )
651  	   {
652  	      if( sense != NULL )
653  	         *sense = PIP_SENSE_GE;
654  	      return TRUE;
655  	   }
656  	   else if( strcmp(pipinput->token, "=") == 0 )
657  	   {
658  	      if( sense != NULL )
659  	         *sense = PIP_SENSE_EQ;
660  	      return TRUE;
661  	   }
662  	
663  	   return FALSE;
664  	}
665  	
666  	/** returns the variable with the given name, or creates a new variable if it does not exist */
667  	static
668  	SCIP_RETCODE getVariable(
669  	   SCIP*                 scip,               /**< SCIP data structure */
670  	   char*                 name,               /**< name of the variable */
671  	   SCIP_Bool             dynamiccols,        /**< should columns be added and removed dynamically to the LP? */
672  	   SCIP_VAR**            var,                /**< pointer to store the variable */
673  	   SCIP_Bool*            created             /**< pointer to store whether a new variable was created, or NULL */
674  	   )
675  	{
676  	   assert(name != NULL);
677  	   assert(var != NULL);
678  	
679  	   *var = SCIPfindVar(scip, name);
680  	   if( *var == NULL )
681  	   {
682  	      SCIP_VAR* newvar;
683  	
684  	      /* create new variable of the given name */
685  	      SCIPdebugMsg(scip, "creating new variable: <%s>\n", name);
686  	      SCIP_CALL( SCIPcreateVar(scip, &newvar, name, 0.0, SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS,
687  	            !dynamiccols, dynamiccols, NULL, NULL, NULL, NULL, NULL) );
688  	      SCIP_CALL( SCIPaddVar(scip, newvar) );
689  	      *var = newvar;
690  	
691  	      /* because the variable was added to the problem, it is captured by SCIP and we can safely release it right now
692  	       * without making the returned *var invalid
693  	       */
694  	      SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
695  	
696  	      if( created != NULL )
697  	         *created = TRUE;
698  	   }
699  	   else if( created != NULL )
700  	      *created = FALSE;
701  	
702  	   return SCIP_OKAY;
703  	}
704  	
705  	/** reads the header of the file */
706  	static
707  	SCIP_RETCODE readStart(
708  	   SCIP*                 scip,               /**< SCIP data structure */
709  	   PIPINPUT*             pipinput            /**< PIP reading data */
710  	   )
711  	{
712  	   assert(pipinput != NULL);
713  	
714  	   /* everything before first section is treated as comment */
715  	   do
716  	   {
717  	      /* get token */
718  	      if( !getNextToken(scip, pipinput) )
719  	         return SCIP_OKAY;
720  	   }
721  	   while( !isNewSection(scip, pipinput) );
722  	
723  	   return SCIP_OKAY;
724  	}
725  	
726  	/** ensure that an array of monomials can hold a minimum number of entries */
727  	static
728  	SCIP_RETCODE ensureMonomialsSize(
729  	   SCIP*                 scip,               /**< SCIP data structure */
730  	   SCIP_EXPR***          monomials,          /**< pointer to current array of monomials */
731  	   SCIP_Real**           monomialscoef,      /**< pointer to current array of monomial coefficients */
732  	   int*                  monomialssize,      /**< current size of monomials array at input; new size at exit */
733  	   int                   minnmonomials       /**< required minimal size of monomials array */
734  	   )
735  	{
736  	   int newsize;
737  	
738  	   assert(scip != NULL);
739  	   assert(monomials != NULL);
740  	   assert(monomialscoef != NULL);
741  	   assert(monomialssize != NULL);
742  	   assert(*monomials != NULL || *monomialssize == 0);
743  	
744  	   if( minnmonomials <= *monomialssize )
745  	      return SCIP_OKAY;
746  	
747  	   newsize = SCIPcalcMemGrowSize(scip, minnmonomials);
748  	
749  	   if( *monomials != NULL )
750  	   {
751  	      SCIP_CALL( SCIPreallocBufferArray(scip, monomials, newsize) );
752  	   }
753  	   else
754  	   {
755  	      SCIP_CALL( SCIPallocBufferArray(scip, monomials, newsize) );
756  	   }
757  	   if( *monomialscoef != NULL )
758  	   {
759  	      SCIP_CALL( SCIPreallocBufferArray(scip, monomialscoef, newsize) );
760  	   }
761  	   else
762  	   {
763  	      SCIP_CALL( SCIPallocBufferArray(scip, monomialscoef, newsize) );
764  	   }
765  	   *monomialssize = newsize;
766  	
767  	   return SCIP_OKAY;
768  	}
769  	
770  	/** ensure that arrays of exponents and variable indices can hold a minimum number of entries */
771  	static
772  	SCIP_RETCODE ensureFactorsSize(
773  	   SCIP*                 scip,               /**< SCIP data structure */
774  	   SCIP_VAR***           vars,               /**< pointer to current array of variables */
775  	   SCIP_Real**           exponents,          /**< pointer to current array of exponents */
776  	   int*                  factorssize,        /**< current size of arrays at input; new size at exit */
777  	   int                   minnfactors         /**< required minimal size of arrays */
778  	   )
779  	{
780  	   int newsize;
781  	
782  	   assert(scip != NULL);
783  	   assert(vars != NULL);
784  	   assert(exponents != NULL);
785  	   assert(factorssize != NULL);
786  	   assert(*exponents != NULL || *factorssize == 0);
787  	   assert(*vars != NULL || *factorssize == 0);
788  	
789  	   if( minnfactors <= *factorssize )
790  	      return SCIP_OKAY;
791  	
792  	   newsize = SCIPcalcMemGrowSize(scip, minnfactors);
793  	
794  	   if( *exponents != NULL )
795  	   {
796  	      SCIP_CALL( SCIPreallocBufferArray(scip, exponents, newsize) );
797  	      SCIP_CALL( SCIPreallocBufferArray(scip, vars, newsize) );
798  	   }
799  	   else
800  	   {
801  	      SCIP_CALL( SCIPallocBufferArray(scip, exponents, newsize) );
802  	      SCIP_CALL( SCIPallocBufferArray(scip, vars, newsize) );
803  	   }
804  	   *factorssize = newsize;
805  	
806  	   return SCIP_OKAY;
807  	}
808  	
809  	/** reads an objective or constraint with name and coefficients */
810  	static
811  	SCIP_RETCODE readPolynomial(
812  	   SCIP*                 scip,               /**< SCIP data structure */
813  	   PIPINPUT*             pipinput,           /**< PIP reading data */
814  	   char*                 name,               /**< pointer to store the name of the line; must be at least of size
815  	                                              *   PIP_MAX_LINELEN */
816  	   SCIP_EXPR**           expr,               /**< pointer to store the constraint function as expression */
817  	   SCIP_Bool*            islinear,           /**< pointer to store polynomial is linear */
818  	   SCIP_Bool*            newsection          /**< pointer to store whether a new section was encountered */
819  	   )
820  	{
821  	   SCIP_Bool havesign;
822  	   SCIP_Bool havevalue;
823  	   SCIP_Real coef;
824  	   int coefsign;
825  	   int nextcoefsign;
826  	   int monomialdegree;
827  	   int i;
828  	
829  	   SCIP_VAR** vars;
830  	   SCIP_Real constant;
831  	
832  	   SCIP_EXPR** monomials;
833  	   SCIP_Real* monomialscoef;
834  	   int monomialssize;
835  	   int nmonomials;
836  	
837  	   int nfactors;
838  	   int factorssize;
839  	   SCIP_Real* exponents;
840  	
841  	   assert(scip != NULL);
842  	   assert(pipinput != NULL);
843  	   assert(name != NULL);
844  	   assert(expr != NULL);
845  	   assert(islinear != NULL);
846  	   assert(newsection != NULL);
847  	
848  	   *name = '\0';
849  	   *expr = NULL;
850  	   *islinear = TRUE;
851  	   *newsection = FALSE;
852  	
853  	   /* read the first token, which may be the name of the line */
854  	   if( getNextToken(scip, pipinput) )
855  	   {
856  	      /* check if we reached a new section */
857  	      if( isNewSection(scip, pipinput) )
858  	      {
859  	         *newsection = TRUE;
860  	         return SCIP_OKAY;
861  	      }
862  	
863  	      /* remember the token in the token buffer */
864  	      swapTokenBuffer(pipinput);
865  	
866  	      /* get the next token and check, whether it is a colon */
867  	      if( getNextToken(scip, pipinput) )
868  	      {
869  	         if( strcmp(pipinput->token, ":") == 0 )
870  	         {
871  	            /* the second token was a colon: the first token is the line name */
872  	            (void)SCIPstrncpy(name, pipinput->tokenbuf, PIP_MAX_LINELEN);
873  	            SCIPdebugMsg(scip, "(line %d) read constraint name: '%s'\n", pipinput->linenumber, name);
874  	         }
875  	         else
876  	         {
877  	            /* the second token was no colon: push the tokens back onto the token stack and parse them as coefficients */
878  	            pushToken(pipinput);
879  	            pushBufferToken(pipinput);
880  	         }
881  	      }
882  	      else
883  	      {
884  	         /* there was only one token left: push it back onto the token stack and parse it as coefficient */
885  	         pushBufferToken(pipinput);
886  	      }
887  	   }
888  	
889  	   /* initialize buffer for storing the monomials */
890  	   monomialssize = PIP_INIT_MONOMIALSSIZE;
891  	   SCIP_CALL( SCIPallocBufferArray(scip, &monomials, monomialssize) );
892  	   SCIP_CALL( SCIPallocBufferArray(scip, &monomialscoef, monomialssize) );
893  	
894  	   /* initialize buffer for storing the factors in a monomial */
895  	   factorssize = PIP_INIT_FACTORSSIZE;
896  	   SCIP_CALL( SCIPallocBufferArray(scip, &exponents, factorssize) );
897  	   SCIP_CALL( SCIPallocBufferArray(scip, &vars, factorssize) );
898  	
899  	   /* read the coefficients */
900  	   coefsign = +1;
901  	   nextcoefsign = +1;
902  	   coef = 1.0;
903  	   havesign = FALSE;
904  	   havevalue = FALSE;
905  	   nmonomials = 0;
906  	   nfactors = 0;
907  	   monomialdegree = 0;
908  	   constant = 0.0;
909  	   while( getNextToken(scip, pipinput) )
910  	   {
911  	      SCIP_VAR* var;
912  	      SCIP_Bool issense;
913  	      SCIP_Bool issign;
914  	      SCIP_Bool isnewsection;
915  	      SCIP_Real exponent;
916  	
917  	      issign = FALSE;   /* fix compiler warning */
918  	      issense = FALSE;  /* fix lint warning */
919  	      if( (isnewsection = isNewSection(scip, pipinput)) ||  /*lint !e820*/
920  	         (issense = isSense(pipinput, NULL))      ||  /*lint !e820*/
921  	         ((nfactors > 0 || havevalue) && (issign = isSign(pipinput, &nextcoefsign))) )  /*lint !e820*/
922  	      {
923  	         /* finish the current monomial */
924  	         if( nfactors > 0 )
925  	         {
926  	            if( coefsign * coef != 0.0 )
927  	            {
928  	               SCIP_CALL( ensureMonomialsSize(scip, &monomials, &monomialscoef, &monomialssize, nmonomials + 1) );
929  	               SCIP_CALL( SCIPcreateExprMonomial(scip, &monomials[nmonomials], nfactors, vars, exponents, NULL, NULL) );
930  	               monomialscoef[nmonomials] = coefsign * coef;
931  	               ++nmonomials;
932  	            }
933  	         }
934  	         else if( havevalue )
935  	         {
936  	            constant += coefsign * coef;
937  	         }
938  	
939  	         if( monomialdegree > 1 )
940  	            *islinear = FALSE;
941  	
942  	         /* reset variables */
943  	         nfactors = 0;
944  	         coef = 1.0;
945  	         coefsign = +1;
946  	         havesign = FALSE;
947  	         havevalue = FALSE;
948  	         monomialdegree = 0;
949  	
950  	         if( isnewsection )
951  	         {
952  	            *newsection = TRUE;
953  	            break;
954  	         }
955  	
956  	         if( issense )
957  	         {
958  	            /* put the sense back onto the token stack */
959  	            pushToken(pipinput);
960  	            break;
961  	         }
962  	
963  	         if( issign )
964  	         {
965  	            coefsign = nextcoefsign;
966  	            SCIPdebugMsg(scip, "(line %d) read coefficient sign: %+d\n", pipinput->linenumber, coefsign);
967  	            havesign = TRUE;
968  	            nextcoefsign = +1;
969  	            continue;
970  	         }
971  	      }
972  	
973  	      /* check if we read a sign */
974  	      if( isSign(pipinput, &coefsign) )
975  	      {
976  	         SCIPdebugMsg(scip, "(line %d) read coefficient sign: %+d\n", pipinput->linenumber, coefsign);
977  	
978  	         if( nfactors > 0 || havevalue )
979  	         {
980  	            syntaxError(scip, pipinput, "sign can only be at beginning of monomial");
981  	            goto TERMINATE_READPOLYNOMIAL;
982  	         }
983  	
984  	         havesign = TRUE;
985  	         continue;
986  	      }
987  	
988  	      /* check if we are in between factors of a monomial */
989  	      if( strcmp(pipinput->token, "*") == 0 )
990  	      {
991  	         if( nfactors == 0 )
992  	         {
993  	            syntaxError(scip, pipinput, "cannot have '*' before first variable in monomial");
994  	            goto TERMINATE_READPOLYNOMIAL;
995  	         }
996  	
997  	         continue;
998  	      }
999  	
1000 	      /* all but the first monomial need a sign */
1001 	      if( nmonomials > 0 && !havesign )
1002 	      {
1003 	         syntaxError(scip, pipinput, "expected sign ('+' or '-') or sense ('<' or '>')");
1004 	         goto TERMINATE_READPOLYNOMIAL;
1005 	      }
1006 	
1007 	      /* check if we are at an exponent for the last variable */
1008 	      if( strcmp(pipinput->token, "^") == 0 )
1009 	      {
1010 	         if( !getNextToken(scip, pipinput) || !isValue(scip, pipinput, &exponent) )
1011 	         {
1012 	            syntaxError(scip, pipinput, "expected exponent value after '^'");
1013 	            goto TERMINATE_READPOLYNOMIAL;
1014 	         }
1015 	         if( nfactors == 0 )
1016 	         {
1017 	            syntaxError(scip, pipinput, "cannot have '^' before first variable in monomial");
1018 	            goto TERMINATE_READPOLYNOMIAL;
1019 	         }
1020 	         exponents[nfactors-1] = exponent;  /*lint !e530*/
1021 	         if( SCIPisIntegral(scip, exponent) && exponent > 0.0 ) /*lint !e530*/
1022 	            monomialdegree += (int)exponent - 1; /*lint !e530*//* -1, because we added +1 when we put the variable into varidxs */
1023 	         else
1024 	            *islinear = FALSE;
1025 	
1026 	         SCIPdebugMsg(scip, "(line %d) read exponent value %g for variable %s\n", pipinput->linenumber, exponent,
1027 	            SCIPvarGetName(vars[nfactors-1]));
1028 	         continue;
1029 	      }
1030 	
1031 	      /* check if we read a value */
1032 	      if( isValue(scip, pipinput, &coef) )
1033 	      {
1034 	         SCIPdebugMsg(scip, "(line %d) read coefficient value: %g with sign %+d\n", pipinput->linenumber, coef, coefsign);
1035 	
1036 	         if( havevalue )
1037 	         {
1038 	            syntaxError(scip, pipinput, "two consecutive values");
1039 	            goto TERMINATE_READPOLYNOMIAL;
1040 	         }
1041 	
1042 	         if( nfactors > 0 )
1043 	         {
1044 	            syntaxError(scip, pipinput, "coefficients can only be at the beginning of a monomial");
1045 	            goto TERMINATE_READPOLYNOMIAL;
1046 	         }
1047 	
1048 	         havevalue = TRUE;
1049 	         continue;
1050 	      }
1051 	
1052 	      /* the token is a variable name: get the corresponding variable (or create a new one) */
1053 	      SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, NULL) );
1054 	
1055 	      /* ensure that there is enough memory to store all factors */
1056 	      SCIP_CALL( ensureFactorsSize(scip, &vars, &exponents, &factorssize, nfactors + 1) );
1057 	
1058 	      /* create and store corresponding variable expression */
1059 	      vars[nfactors] = var;
1060 	      exponents[nfactors] = 1.0;
1061 	      ++nfactors;
1062 	      ++monomialdegree;
1063 	   }
1064 	
1065 	   if( nfactors > 0 )
1066 	   {
1067 	      syntaxError(scip, pipinput, "string ended before monomial has finished");
1068 	      goto TERMINATE_READPOLYNOMIAL;
1069 	   }
1070 	
1071 	   /* create sum expression consisting of all monomial expressions */
1072 	   SCIP_CALL( SCIPcreateExprSum(scip, expr, nmonomials, monomials, monomialscoef, constant, NULL, NULL) );
1073 	
1074 	   /* release monomial expressions */
1075 	   for( i = 0; i < nmonomials; ++i )
1076 	   {
1077 	      assert(monomials[i] != NULL);
1078 	      SCIP_CALL( SCIPreleaseExpr(scip, &monomials[i]) );
1079 	   }
1080 	
1081 	#ifdef SCIP_DEBUG
1082 	   SCIPdebugMsg(scip, "read polynomial: ");
1083 	   SCIP_CALL( SCIPprintExpr(scip, *expr, NULL) );
1084 	   SCIPinfoMessage(scip, NULL, "\n");
1085 	#endif
1086 	
1087 	 TERMINATE_READPOLYNOMIAL:
1088 	   SCIPfreeBufferArray(scip, &vars);
1089 	   SCIPfreeBufferArray(scip, &exponents);
1090 	   SCIPfreeBufferArray(scip, &monomialscoef);
1091 	   SCIPfreeBufferArray(scip, &monomials);
1092 	
1093 	   return SCIP_OKAY;
1094 	}
1095 	
1096 	/** reads the objective section */
1097 	static
1098 	SCIP_RETCODE readObjective(
1099 	   SCIP*                 scip,               /**< SCIP data structure */
1100 	   PIPINPUT*             pipinput            /**< PIP reading data */
1101 	   )
1102 	{
1103 	   char name[PIP_MAX_LINELEN];
1104 	   SCIP_EXPR* expr;
1105 	   SCIP_Bool linear;
1106 	   SCIP_Bool newsection;
1107 	   SCIP_Bool initial;
1108 	   SCIP_Bool separate;
1109 	   SCIP_Bool enforce;
1110 	   SCIP_Bool check;
1111 	   SCIP_Bool propagate;
1112 	   SCIP_Bool local;
1113 	   SCIP_Bool modifiable;
1114 	   SCIP_Bool dynamic;
1115 	   SCIP_Bool removable;
1116 	
1117 	   assert(pipinput != NULL);
1118 	
1119 	   /* determine settings; note that reading/{initialconss,dynamicconss,dynamicrows,dynamiccols} apply only to model
1120 	    * constraints and variables, not to an auxiliary objective constraint (otherwise it can happen that an auxiliary
1121 	    * objective variable is loose with infinite best bound, triggering the problem that an LP that is unbounded because
1122 	    * of loose variables with infinite best bound cannot be solved)
1123 	    */
1124 	   initial = TRUE;
1125 	   separate = TRUE;
1126 	   enforce = TRUE;
1127 	   check = TRUE;
1128 	   propagate = TRUE;
1129 	   local = FALSE;
1130 	   modifiable = FALSE;
1131 	   dynamic = FALSE;
1132 	   removable = FALSE;
1133 	
1134 	   /* read the objective coefficients */
1135 	   SCIP_CALL( readPolynomial(scip, pipinput, name, &expr, &linear, &newsection) );
1136 	   if( !hasError(pipinput) && expr != NULL )
1137 	   {
1138 	      SCIP_Real constant = SCIPgetConstantExprSum(expr);
1139 	
1140 	      /* always create a variable that represents the constant; otherwise, this might lead to numerical issues on
1141 	       * instances with a relatively large constant, e.g., popdynm* instances
1142 	       */
1143 	      if( constant != 0.0 )
1144 	      {
1145 	         SCIP_VAR* objconst;
1146 	         SCIP_CALL( SCIPcreateVarBasic(scip, &objconst, "objconst", 1.0, 1.0, constant, SCIP_VARTYPE_CONTINUOUS) );
1147 	         SCIP_CALL( SCIPaddVar(scip, objconst) );
1148 	         SCIP_CALL( SCIPreleaseVar(scip, &objconst) );
1149 	
1150 	         /* remove the constant of the sum expression */
1151 	         SCIPsetConstantExprSum(expr, 0.0);
1152 	      }
1153 	
1154 	      if( linear )
1155 	      {
1156 	         int i;
1157 	
1158 	         /* set objective coefficients of variables */
1159 	         for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
1160 	         {
1161 	            SCIP_EXPR* child;
1162 	            SCIP_VAR* var;
1163 	            SCIP_Real coef;
1164 	
1165 	            child = SCIPexprGetChildren(expr)[i];
1166 	            assert(child != NULL);
1167 	            assert(SCIPisExprVar(scip, child));
1168 	
1169 	            /* child has to be a variable expression, see SCIPcreateExprMonomial() */
1170 	            var = SCIPgetVarExprVar(child);
1171 	            assert(var != NULL);
1172 	            coef = SCIPgetCoefsExprSum(expr)[i];
1173 	
1174 	            /* adjust the objective coefficient */
1175 	            SCIP_CALL( SCIPchgVarObj(scip, var, SCIPvarGetObj(var) + coef) );
1176 	         }
1177 	      }
1178 	      else /* insert dummy variable and constraint to represent the nonlinear objective */
1179 	      {
1180 	         SCIP_EXPR* nonlinobjvarexpr;
1181 	         SCIP_VAR*  nonlinobjvar;
1182 	         SCIP_CONS* nonlinobjcons;
1183 	         SCIP_Real lhs;
1184 	         SCIP_Real rhs;
1185 	
1186 	         SCIP_CALL( SCIPcreateVar(scip, &nonlinobjvar, "nonlinobjvar", -SCIPinfinity(scip), SCIPinfinity(scip), 1.0,
1187 	            SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
1188 	         SCIP_CALL( SCIPaddVar(scip, nonlinobjvar) );
1189 	
1190 	         if ( pipinput->objsense == SCIP_OBJSENSE_MINIMIZE )
1191 	         {
1192 	            lhs = -SCIPinfinity(scip);
1193 	            rhs = 0.0;
1194 	         }
1195 	         else
1196 	         {
1197 	            lhs = 0.0;
1198 	            rhs = SCIPinfinity(scip);
1199 	         }
1200 	
1201 	         /* add created objective variable */
1202 	         SCIP_CALL( SCIPcreateExprVar(scip, &nonlinobjvarexpr, nonlinobjvar, NULL, NULL) );
1203 	         SCIP_CALL( SCIPappendExprSumExpr(scip, expr, nonlinobjvarexpr, -1.0) );
1204 	         SCIP_CALL( SCIPreleaseExpr(scip, &nonlinobjvarexpr) );
1205 	
1206 	         /* create nonlinear constraint */
1207 	         SCIP_CALL( SCIPcreateConsNonlinear(scip, &nonlinobjcons, "nonlinobj", expr, lhs, rhs, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable) );
1208 	
1209 	         SCIP_CALL( SCIPaddCons(scip, nonlinobjcons) );
1210 	         SCIPdebugMsg(scip, "(line %d) added constraint <%s> to represent nonlinear objective: ", pipinput->linenumber, SCIPconsGetName(nonlinobjcons));
1211 	         SCIPdebugPrintCons(scip, nonlinobjcons, NULL);
1212 	
1213 	         SCIP_CALL( SCIPreleaseCons(scip, &nonlinobjcons) );
1214 	         SCIP_CALL( SCIPreleaseVar(scip, &nonlinobjvar) );
1215 	      }
1216 	   }
1217 	
1218 	   /* release expression */
1219 	   if( expr != NULL )
1220 	   {
1221 	      SCIP_CALL( SCIPreleaseExpr(scip, &expr) );
1222 	   }
1223 	
1224 	   return SCIP_OKAY;
1225 	}
1226 	
1227 	/** reads the constraints section */
1228 	static
1229 	SCIP_RETCODE readConstraints(
1230 	   SCIP*                 scip,               /**< SCIP data structure */
1231 	   PIPINPUT*             pipinput            /**< PIP reading data */
1232 	   )
1233 	{
1234 	   char name[PIP_MAX_LINELEN];
1235 	   SCIP_EXPR* expr;
1236 	   SCIP_CONS* cons = NULL;
1237 	   SCIP_Bool linear;
1238 	
1239 	   PIPSENSE sense;
1240 	   SCIP_Real sidevalue;
1241 	   SCIP_Real lhs;
1242 	   SCIP_Real rhs;
1243 	   SCIP_Bool newsection;
1244 	   SCIP_Bool initial;
1245 	   SCIP_Bool separate;
1246 	   SCIP_Bool enforce;
1247 	   SCIP_Bool check;
1248 	   SCIP_Bool propagate;
1249 	   SCIP_Bool local;
1250 	   SCIP_Bool modifiable;
1251 	   SCIP_Bool dynamic;
1252 	   SCIP_Bool removable;
1253 	   int sidesign;
1254 	
1255 	   assert(pipinput != NULL);
1256 	
1257 	   /* read polynomial */
1258 	   SCIP_CALL( readPolynomial(scip, pipinput, name, &expr, &linear, &newsection) );
1259 	   if ( hasError(pipinput) )
1260 	      return SCIP_READERROR;
1261 	   if ( newsection )
1262 	   {
1263 	      if ( expr != NULL )
1264 	         syntaxError(scip, pipinput, "expected constraint sense '<=', '=', or '>='");
1265 	      return SCIP_OKAY;
1266 	   }
1267 	
1268 	   /* read the constraint sense */
1269 	   if ( !getNextToken(scip, pipinput) )
1270 	   {
1271 	      syntaxError(scip, pipinput, "expected constraint sense.");
1272 	      return SCIP_READERROR;
1273 	   }
1274 	   if ( !isSense(pipinput, &sense) )
1275 	   {
1276 	      syntaxError(scip, pipinput, "expected constraint sense '<=', '=', or '>='");
1277 	      return SCIP_READERROR;
1278 	   }
1279 	
1280 	   /* read the right hand side */
1281 	   sidesign = +1;
1282 	   if ( !getNextToken(scip, pipinput) )
1283 	   {
1284 	      syntaxError(scip, pipinput, "missing right hand side");
1285 	      return SCIP_READERROR;
1286 	   }
1287 	   if ( isSign(pipinput, &sidesign) )
1288 	   {
1289 	      if( !getNextToken(scip, pipinput) )
1290 	      {
1291 	         syntaxError(scip, pipinput, "missing value of right hand side");
1292 	         return SCIP_READERROR;
1293 	      }
1294 	   }
1295 	   if ( !isValue(scip, pipinput, &sidevalue) )
1296 	   {
1297 	      syntaxError(scip, pipinput, "expected value as right hand side");
1298 	      return SCIP_READERROR;
1299 	   }
1300 	   sidevalue *= sidesign;
1301 	
1302 	   /* determine settings */
1303 	   initial = pipinput->initialconss;
1304 	   separate = TRUE;
1305 	   enforce = TRUE;
1306 	   check = TRUE;
1307 	   propagate = TRUE;
1308 	   local = FALSE;
1309 	   modifiable = FALSE;
1310 	   dynamic = pipinput->dynamicconss;
1311 	   removable = pipinput->dynamicrows;
1312 	
1313 	   /* assign the left and right hand side, depending on the constraint sense */
1314 	   switch ( sense )  /*lint !e530*/
1315 	   {
1316 	   case PIP_SENSE_GE:
1317 	      lhs = sidevalue;
1318 	      rhs = SCIPinfinity(scip);
1319 	      break;
1320 	   case PIP_SENSE_LE:
1321 	      lhs = -SCIPinfinity(scip);
1322 	      rhs = sidevalue;
1323 	      break;
1324 	   case PIP_SENSE_EQ:
1325 	      lhs = sidevalue;
1326 	      rhs = sidevalue;
1327 	      break;
1328 	   case PIP_SENSE_NOTHING:
1329 	   default:
1330 	      SCIPerrorMessage("invalid constraint sense <%d>\n", sense);
1331 	      return SCIP_INVALIDDATA;
1332 	   }
1333 	
1334 	   /* linear constraint function */
1335 	   if( linear )
1336 	   {
1337 	      SCIP_VAR** vars;
1338 	      SCIP_Real* coefs;
1339 	      SCIP_Real constant;
1340 	      int nchildren;
1341 	      int i;
1342 	
1343 	      nchildren = SCIPexprGetNChildren(expr);
1344 	      constant = SCIPgetConstantExprSum(expr);
1345 	      coefs = SCIPgetCoefsExprSum(expr);
1346 	
1347 	      /* allocate memory to store variables */
1348 	      SCIP_CALL( SCIPallocBufferArray(scip, &vars, nchildren) );
1349 	
1350 	      /* collect variables */
1351 	      for( i = 0; i < nchildren; ++i )
1352 	      {
1353 	         SCIP_EXPR* child = SCIPexprGetChildren(expr)[i];
1354 	         assert(child != NULL);
1355 	         assert(SCIPisExprVar(scip, child));
1356 	
1357 	         vars[i] = SCIPgetVarExprVar(child);
1358 	         assert(vars[i] != NULL);
1359 	      }
1360 	
1361 	      /* adjust lhs and rhs */
1362 	      if( !SCIPisInfinity(scip, -lhs) )
1363 	         lhs -= constant;
1364 	      if( !SCIPisInfinity(scip, rhs) )
1365 	         rhs -= constant;
1366 	
1367 	      /* create linear constraint */
1368 	      SCIP_CALL( SCIPcreateConsLinear(scip, &cons, name, nchildren, vars, coefs, lhs, rhs, initial, separate, enforce,
1369 	         check, propagate, local, modifiable, dynamic, removable, FALSE) );
1370 	
1371 	      /* free memory */
1372 	      SCIPfreeBufferArray(scip, &vars);
1373 	   }
1374 	   else /* nonlinear constraint function */
1375 	   {
1376 	      SCIP_CALL( SCIPcreateConsNonlinear(scip, &cons, name, expr, lhs, rhs, initial, separate, enforce, check, propagate,
1377 	      local, modifiable, dynamic, removable) );
1378 	   }
1379 	
1380 	   /* add and release constraint */
1381 	   assert(cons != NULL);
1382 	   SCIP_CALL( SCIPaddCons(scip, cons) );
1383 	   SCIPdebugMsg(scip, "(line %d) created constraint: ", pipinput->linenumber);
1384 	   SCIPdebugPrintCons(scip, cons, NULL);
1385 	   SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1386 	
1387 	   /* release expression */
1388 	   if( expr != NULL )
1389 	   {
1390 	      SCIP_CALL( SCIPreleaseExpr(scip, &expr) );
1391 	   }
1392 	
1393 	   return SCIP_OKAY;
1394 	}
1395 	
1396 	/** reads the bounds section */
1397 	static
1398 	SCIP_RETCODE readBounds(
1399 	   SCIP*                 scip,               /**< SCIP data structure */
1400 	   PIPINPUT*             pipinput            /**< PIP reading data */
1401 	   )
1402 	{
1403 	   assert(pipinput != NULL);
1404 	
1405 	   while( getNextToken(scip, pipinput) )
1406 	   {
1407 	      SCIP_VAR* var;
1408 	      SCIP_Real value;
1409 	      SCIP_Real lb;
1410 	      SCIP_Real ub;
1411 	      int sign;
1412 	      SCIP_Bool hassign;
1413 	      PIPSENSE leftsense;
1414 	
1415 	      /* check if we reached a new section */
1416 	      if( isNewSection(scip, pipinput) )
1417 	         return SCIP_OKAY;
1418 	
1419 	      /* default bounds are [0,+inf] */
1420 	      lb = 0.0;
1421 	      ub = SCIPinfinity(scip);
1422 	      leftsense = PIP_SENSE_NOTHING;
1423 	
1424 	      /* check if the first token is a sign */
1425 	      sign = +1;
1426 	      hassign = isSign(pipinput, &sign);
1427 	      if( hassign && !getNextToken(scip, pipinput) )
1428 	      {
1429 	         syntaxError(scip, pipinput, "expected value");
1430 	         return SCIP_OKAY;
1431 	      }
1432 	
1433 	      /* the first token must be either a value or a variable name */
1434 	      if( isValue(scip, pipinput, &value) )
1435 	      {
1436 	         /* first token is a value: the second token must be a sense */
1437 	         if( !getNextToken(scip, pipinput) || !isSense(pipinput, &leftsense) )
1438 	         {
1439 	            syntaxError(scip, pipinput, "expected bound sense '<=', '=', or '>='");
1440 	            return SCIP_OKAY;
1441 	         }
1442 	
1443 	         /* update the bound corresponding to the sense */
1444 	         switch( leftsense )
1445 	         {
1446 	         case PIP_SENSE_GE:
1447 	            ub = sign * value;
1448 	            break;
1449 	         case PIP_SENSE_LE:
1450 	            lb = sign * value;
1451 	            break;
1452 	         case PIP_SENSE_EQ:
1453 	            lb = sign * value;
1454 	            ub = sign * value;
1455 	            break;
1456 	         case PIP_SENSE_NOTHING:
1457 	         default:
1458 	            SCIPerrorMessage("invalid bound sense <%d>\n", leftsense);
1459 	            return SCIP_INVALIDDATA;
1460 	         }
1461 	      }
1462 	      else if( hassign )
1463 	      {
1464 	         syntaxError(scip, pipinput, "expected value");
1465 	         return SCIP_OKAY;
1466 	      }
1467 	      else
1468 	         pushToken(pipinput);
1469 	
1470 	      /* the next token must be a variable name */
1471 	      if( !getNextToken(scip, pipinput) )
1472 	      {
1473 	         syntaxError(scip, pipinput, "expected variable name");
1474 	         return SCIP_OKAY;
1475 	      }
1476 	      SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, NULL) );
1477 	
1478 	      /* the next token might be another sense, or the word "free" */
1479 	      if( getNextToken(scip, pipinput) )
1480 	      {
1481 	         PIPSENSE rightsense;
1482 	
1483 	         if( isSense(pipinput, &rightsense) )
1484 	         {
1485 	            /* check, if the senses fit */
1486 	            if( leftsense == PIP_SENSE_NOTHING
1487 	               || (leftsense == PIP_SENSE_LE && rightsense == PIP_SENSE_LE)
1488 	               || (leftsense == PIP_SENSE_GE && rightsense == PIP_SENSE_GE) )
1489 	            {
1490 	               if( !getNextToken(scip, pipinput) )
1491 	               {
1492 	                  syntaxError(scip, pipinput, "expected value or sign");
1493 	                  return SCIP_OKAY;
1494 	               }
1495 	
1496 	               /* check if the next token is a sign */
1497 	               sign = +1;
1498 	               hassign = isSign(pipinput, &sign);
1499 	               if( hassign && !getNextToken(scip, pipinput) )
1500 	               {
1501 	                  syntaxError(scip, pipinput, "expected value");
1502 	                  return SCIP_OKAY;
1503 	               }
1504 	
1505 	               /* the next token must be a value */
1506 	               if( !isValue(scip, pipinput, &value) )
1507 	               {
1508 	                  syntaxError(scip, pipinput, "expected value");
1509 	                  return SCIP_OKAY;
1510 	               }
1511 	
1512 	               /* update the bound corresponding to the sense */
1513 	               switch( rightsense )
1514 	               {
1515 	               case PIP_SENSE_GE:
1516 	                  lb = sign * value;
1517 	                  break;
1518 	               case PIP_SENSE_LE:
1519 	                  ub = sign * value;
1520 	                  break;
1521 	               case PIP_SENSE_EQ:
1522 	                  lb = sign * value;
1523 	                  ub = sign * value;
1524 	                  break;
1525 	               case PIP_SENSE_NOTHING:
1526 	               default:
1527 	                  SCIPerrorMessage("invalid bound sense <%d>\n", leftsense);
1528 	                  return SCIP_INVALIDDATA;
1529 	               }
1530 	            }
1531 	            else
1532 	            {
1533 	               syntaxError(scip, pipinput, "the two bound senses do not fit");
1534 	               return SCIP_OKAY;
1535 	            }
1536 	         }
1537 	         else if( strcasecmp(pipinput->token, "FREE") == 0 )
1538 	         {
1539 	            if( leftsense != PIP_SENSE_NOTHING )
1540 	            {
1541 	               syntaxError(scip, pipinput, "variable with bound is marked as 'free'");
1542 	               return SCIP_OKAY;
1543 	            }
1544 	            lb = -SCIPinfinity(scip);
1545 	            ub = SCIPinfinity(scip);
1546 	         }
1547 	         else
1548 	         {
1549 	            /* the token was no sense: push it back to the token stack */
1550 	            pushToken(pipinput);
1551 	         }
1552 	      }
1553 	
1554 	      /* change the bounds of the variable if bounds have been given (do not destroy earlier specification of bounds) */
1555 	      if ( lb != 0.0 )
1556 	         SCIP_CALL( SCIPchgVarLb(scip, var, lb) );
1557 	      /*lint --e{777}*/
1558 	      if ( ub != SCIPinfinity(scip) )
1559 	         SCIP_CALL( SCIPchgVarUb(scip, var, ub) );
1560 	      SCIPdebugMsg(scip, "(line %d) new bounds: <%s>[%g,%g]\n", pipinput->linenumber, SCIPvarGetName(var),
1561 	         SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var));
1562 	   }
1563 	
1564 	   return SCIP_OKAY;
1565 	}
1566 	
1567 	/** reads the generals section */
1568 	static
1569 	SCIP_RETCODE readGenerals(
1570 	   SCIP*                 scip,               /**< SCIP data structure */
1571 	   PIPINPUT*             pipinput            /**< PIP reading data */
1572 	   )
1573 	{
1574 	   assert(pipinput != NULL);
1575 	
1576 	   while( getNextToken(scip, pipinput) )
1577 	   {
1578 	      SCIP_VAR* var;
1579 	      SCIP_Bool created;
1580 	      SCIP_Bool infeasible;
1581 	
1582 	      /* check if we reached a new section */
1583 	      if( isNewSection(scip, pipinput) )
1584 	         return SCIP_OKAY;
1585 	
1586 	      /* the token must be the name of an existing variable */
1587 	      SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, &created) );
1588 	      if( created )
1589 	      {
1590 	         syntaxError(scip, pipinput, "unknown variable in generals section");
1591 	         return SCIP_OKAY;
1592 	      }
1593 	
1594 	      /* mark the variable to be integral */
1595 	      SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) );
1596 	      /* don't assert feasibility here because the presolver will and should detect a infeasibility */
1597 	   }
1598 	
1599 	   return SCIP_OKAY;
1600 	}
1601 	
1602 	/** reads the binaries section */
1603 	static
1604 	SCIP_RETCODE readBinaries(
1605 	   SCIP*                 scip,               /**< SCIP data structure */
1606 	   PIPINPUT*             pipinput            /**< PIP reading data */
1607 	   )
1608 	{
1609 	   assert(pipinput != NULL);
1610 	
1611 	   while( getNextToken(scip, pipinput) )
1612 	   {
1613 	      SCIP_VAR* var;
1614 	      SCIP_Bool created;
1615 	      SCIP_Bool infeasible;
1616 	
1617 	      /* check if we reached a new section */
1618 	      if( isNewSection(scip, pipinput) )
1619 	         return SCIP_OKAY;
1620 	
1621 	      /* the token must be the name of an existing variable */
1622 	      SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, &created) );
1623 	      if( created )
1624 	      {
1625 	         syntaxError(scip, pipinput, "unknown variable in binaries section");
1626 	         return SCIP_OKAY;
1627 	      }
1628 	
1629 	      /* mark the variable to be binary and change its bounds appropriately */
1630 	      if( SCIPvarGetLbGlobal(var) < 0.0 )
1631 	      {
1632 	         SCIP_CALL( SCIPchgVarLb(scip, var, 0.0) );
1633 	      }
1634 	      if( SCIPvarGetUbGlobal(var) > 1.0 )
1635 	      {
1636 	         SCIP_CALL( SCIPchgVarUb(scip, var, 1.0) );
1637 	      }
1638 	      SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
1639 	      /* don't assert feasibility here because the presolver will and should detect a infeasibility */
1640 	   }
1641 	
1642 	   return SCIP_OKAY;
1643 	}
1644 	
1645 	/** reads a PIP file
1646 	 */
1647 	static
1648 	SCIP_RETCODE readPIPFile(
1649 	   SCIP*                 scip,               /**< SCIP data structure */
1650 	   PIPINPUT*             pipinput,           /**< PIP reading data */
1651 	   const char*           filename            /**< name of the input file */
1652 	   )
1653 	{
1654 	   assert(pipinput != NULL);
1655 	
1656 	   /* open file */
1657 	   pipinput->file = SCIPfopen(filename, "r");
1658 	   if( pipinput->file == NULL )
1659 	   {
1660 	      SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
1661 	      SCIPprintSysError(filename);
1662 	      return SCIP_NOFILE;
1663 	   }
1664 	
1665 	   /* create problem */
1666 	   SCIP_CALL( SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
1667 	
1668 	   /* parse the file */
1669 	   pipinput->section = PIP_START;
1670 	   while( pipinput->section != PIP_END && !hasError(pipinput) )
1671 	   {
1672 	      switch( pipinput->section )
1673 	      {
1674 	      case PIP_START:
1675 	         SCIP_CALL( readStart(scip, pipinput) );
1676 	         break;
1677 	
1678 	      case PIP_OBJECTIVE:
1679 	         SCIP_CALL( readObjective(scip, pipinput) );
1680 	         break;
1681 	
1682 	      case PIP_CONSTRAINTS:
1683 	         SCIP_CALL( readConstraints(scip, pipinput) );
1684 	         break;
1685 	
1686 	      case PIP_BOUNDS:
1687 	         SCIP_CALL( readBounds(scip, pipinput) );
1688 	         break;
1689 	
1690 	      case PIP_GENERALS:
1691 	         SCIP_CALL( readGenerals(scip, pipinput) );
1692 	         break;
1693 	
1694 	      case PIP_BINARIES:
1695 	         SCIP_CALL( readBinaries(scip, pipinput) );
1696 	         break;
1697 	
1698 	      case PIP_END: /* this is already handled in the while() loop */
1699 	      default:
1700 	         SCIPerrorMessage("invalid PIP file section <%d>\n", pipinput->section);
1701 	         return SCIP_INVALIDDATA;
1702 	      }
1703 	   }
1704 	
1705 	   /* close file */
1706 	   SCIPfclose(pipinput->file);
1707 	
1708 	   return SCIP_OKAY;
1709 	}
1710 	
1711 	
1712 	/*
1713 	 * Local methods (for writing)
1714 	 */
1715 	
1716 	/** hash key retrieval function for variables */
1717 	static
1718 	SCIP_DECL_HASHGETKEY(hashGetKeyVar)
1719 	{  /*lint --e{715}*/
1720 	   return elem;
1721 	}
1722 	
1723 	/** returns TRUE iff the indices of both variables are equal */
1724 	static
1725 	SCIP_DECL_HASHKEYEQ(hashKeyEqVar)
1726 	{  /*lint --e{715}*/
1727 	   if ( key1 == key2 )
1728 	      return TRUE;
1729 	   return FALSE;
1730 	}
1731 	
1732 	/** returns the hash value of the key */
1733 	static
1734 	SCIP_DECL_HASHKEYVAL(hashKeyValVar)
1735 	{  /*lint --e{715}*/
1736 	   assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
1737 	   return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
1738 	}
1739 	
1740 	/** transforms given variables, scalars, and constant to the corresponding active variables, scalars, and constant */
1741 	static
1742 	SCIP_RETCODE getActiveVariables(
1743 	   SCIP*                 scip,               /**< SCIP data structure */
1744 	   SCIP_VAR***           vars,               /**< pointer to vars array to get active variables for */
1745 	   SCIP_Real**           scalars,            /**< pointer to scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
1746 	   int*                  nvars,              /**< pointer to number of variables and values in vars and vals array */
1747 	   SCIP_Real*            constant,           /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c  */
1748 	   SCIP_Bool             transformed         /**< transformed constraint? */
1749 	   )
1750 	{
1751 	   int requiredsize;
1752 	   int v;
1753 	
1754 	   assert(scip != NULL);
1755 	   assert(vars != NULL);
1756 	   assert(scalars != NULL);
1757 	   assert(nvars != NULL);
1758 	   assert(*vars != NULL || *nvars == 0);
1759 	   assert(*scalars != NULL || *nvars == 0);
1760 	   assert(constant != NULL);
1761 	
1762 	   if( transformed )
1763 	   {
1764 	      SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *nvars, constant, &requiredsize, TRUE) );
1765 	
1766 	      if( requiredsize > *nvars )
1767 	      {
1768 	         SCIP_CALL( SCIPreallocBufferArray(scip, vars, requiredsize) );
1769 	         SCIP_CALL( SCIPreallocBufferArray(scip, scalars, requiredsize) );
1770 	
1771 	         SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, requiredsize, constant, &requiredsize, TRUE) );
1772 	         assert( requiredsize <= *nvars );
1773 	      }
1774 	   }
1775 	   else
1776 	   {
1777 	      if( *nvars > 0 && ( *vars == NULL || *scalars == NULL ) ) /*lint !e774 !e845*/
1778 	      {
1779 	         SCIPerrorMessage("Null pointer in PIP reader\n"); /* should not happen */
1780 	         SCIPABORT();
1781 	         return SCIP_INVALIDDATA;  /*lint !e527*/
1782 	      }
1783 	
1784 	      for( v = 0; v < *nvars; ++v )
1785 	      {
1786 	         SCIP_CALL( SCIPvarGetOrigvarSum(&(*vars)[v], &(*scalars)[v], constant) );
1787 	
1788 	         /* negated variables with an original counterpart may also be returned by SCIPvarGetOrigvarSum();
1789 	          * make sure we get the original variable in that case
1790 	          */
1791 	         if( SCIPvarGetStatus((*vars)[v]) == SCIP_VARSTATUS_NEGATED )
1792 	         {
1793 	            (*vars)[v] = SCIPvarGetNegatedVar((*vars)[v]);
1794 	            *constant += (*scalars)[v];
1795 	            (*scalars)[v] *= -1.0;
1796 	         }
1797 	      }
1798 	   }
1799 	   return SCIP_OKAY;
1800 	}
1801 	
1802 	/** checks whether a given expression is a signomial
1803 	 *
1804 	 * assumes simplified expression
1805 	 */
1806 	static
1807 	SCIP_Bool isExprSignomial(
1808 	   SCIP*                 scip,               /**< SCIP data structure */
1809 	   SCIP_EXPR*            expr                /**< expression */
1810 	   )
1811 	{
1812 	   assert(scip != NULL);
1813 	   assert(expr != NULL);
1814 	
1815 	   if( SCIPisExprVar(scip, expr) || SCIPisExprValue(scip, expr) )
1816 	      return TRUE;
1817 	
1818 	   if( SCIPisExprPower(scip, expr) && SCIPisExprVar(scip, SCIPexprGetChildren(expr)[0]) )
1819 	      return TRUE;
1820 	
1821 	   if( SCIPisExprProduct(scip, expr) )
1822 	   {
1823 	      SCIP_EXPR* child;
1824 	      int c;
1825 	
1826 	      for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
1827 	      {
1828 	         child = SCIPexprGetChildren(expr)[c];
1829 	
1830 	         if( SCIPisExprVar(scip, child) )
1831 	            continue;
1832 	
1833 	         if( SCIPisExprPower(scip, child) && SCIPisExprVar(scip, SCIPexprGetChildren(child)[0]) )
1834 	            continue;
1835 	
1836 	         /* the pip format does not allow constants here */
1837 	
1838 	         return FALSE;
1839 	      }
1840 	
1841 	      return TRUE;
1842 	   }
1843 	
1844 	   return FALSE;
1845 	}
1846 	
1847 	/** checks whether a given expression is a sum of signomials (i.e., like a polynomial, but negative and fractional exponents allowed)
1848 	 *
1849 	 * assumes simplified expression;
1850 	 * does not check whether variables in powers with fractional exponent are nonnegative;
1851 	 * does not check whether variables in powers with negative exponent are bounded away from zero (the format specification does not require that, too)
1852 	 */
1853 	static
1854 	SCIP_Bool isExprPolynomial(
1855 	   SCIP*                 scip,               /**< SCIP data structure */
1856 	   SCIP_EXPR*            expr                /**< expression */
1857 	   )
1858 	{
1859 	   int c;
1860 	
1861 	   assert(scip != NULL);
1862 	   assert(expr != NULL);
1863 	
1864 	   if( !SCIPisExprSum(scip, expr) )
1865 	      return isExprSignomial(scip, expr);
1866 	
1867 	   /* check whether every term of sum is signomial */
1868 	   for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
1869 	      if( !isExprSignomial(scip, SCIPexprGetChildren(expr)[c]) )
1870 	         return FALSE;
1871 	
1872 	   return TRUE;
1873 	}
1874 	
1875 	/** clears the given line buffer */
1876 	static
1877 	void clearLine(
1878 	   char*                 linebuffer,         /**< line */
1879 	   int*                  linecnt             /**< number of characters in line */
1880 	   )
1881 	{
1882 	   assert( linebuffer != NULL );
1883 	   assert( linecnt != NULL );
1884 	
1885 	   (*linecnt) = 0;
1886 	   linebuffer[0] = '\0';
1887 	}
1888 	
1889 	/** ends the given line with '\\0' and prints it to the given file stream */
1890 	static
1891 	void endLine(
1892 	   SCIP*                 scip,               /**< SCIP data structure */
1893 	   FILE*                 file,               /**< output file (or NULL for standard output) */
1894 	   char*                 linebuffer,         /**< line */
1895 	   int*                  linecnt             /**< number of characters in line */
1896 	   )
1897 	{
1898 	   assert( scip != NULL );
1899 	   assert( linebuffer != NULL );
1900 	   assert( linecnt != NULL );
1901 	   assert( 0 <= *linecnt && *linecnt < PIP_MAX_PRINTLEN );
1902 	
1903 	   if( (*linecnt) > 0 )
1904 	   {
1905 	      linebuffer[(*linecnt)] = '\0';
1906 	      SCIPinfoMessage(scip, file, "%s\n", linebuffer);
1907 	      clearLine(linebuffer, linecnt);
1908 	   }
1909 	}
1910 	
1911 	/** appends extension to line and prints it to the give file stream if the
1912 	 *  line exceeded the length given in the define PIP_PRINTLEN */
1913 	static
1914 	void appendLine(
1915 	   SCIP*                 scip,               /**< SCIP data structure */
1916 	   FILE*                 file,               /**< output file (or NULL for standard output) */
1917 	   char*                 linebuffer,         /**< line */
1918 	   int*                  linecnt,            /**< number of characters in line */
1919 	   const char*           extension           /**< string to extent the line */
1920 	   )
1921 	{
1922 	   assert( scip != NULL );
1923 	   assert( linebuffer != NULL );
1924 	   assert( linecnt != NULL );
1925 	   assert( extension != NULL );
1926 	   assert( strlen(linebuffer) + strlen(extension) < PIP_MAX_PRINTLEN );
1927 	
1928 	   /* NOTE: avoid
1929 	    *   sprintf(linebuffer, "%s%s", linebuffer, extension);
1930 	    * because of overlapping memory areas in memcpy used in sprintf.
1931 	    */
1932 	   (void) strncat(linebuffer, extension, PIP_MAX_PRINTLEN - strlen(linebuffer));
1933 	
1934 	   (*linecnt) += (int) strlen(extension);
1935 	
1936 	   SCIPdebugMsg(scip, "linebuffer <%s>, length = %lu\n", linebuffer, (unsigned long)strlen(linebuffer));
1937 	
1938 	   if( (*linecnt) > PIP_PRINTLEN )
1939 	      endLine(scip, file, linebuffer, linecnt);
1940 	}
1941 	
1942 	
1943 	/** print linear or quadratic row in PIP format to file stream */
1944 	static
1945 	SCIP_RETCODE printRow(
1946 	   SCIP*                 scip,               /**< SCIP data structure */
1947 	   FILE*                 file,               /**< output file (or NULL for standard output) */
1948 	   const char*           rowname,            /**< row name */
1949 	   const char*           rownameextension,   /**< row name extension */
1950 	   const char*           type,               /**< row type ("=", "<=", or ">=") */
1951 	   SCIP_VAR**            linvars,            /**< array of linear variables */
1952 	   SCIP_Real*            linvals,            /**< array of linear coefficient values */
1953 	   int                   nlinvars,           /**< number of linear variables */
1954 	   SCIP_EXPR*            quadexpr,           /**< quadratic expression */
1955 	   SCIP_Real             rhs,                /**< right hand side */
1956 	   SCIP_Bool             transformed         /**< transformed constraint? */
1957 	   )
1958 	{
1959 	   int v;
1960 	   char linebuffer[PIP_MAX_PRINTLEN+1] = { '\0' };
1961 	   int linecnt;
1962 	
1963 	   char varname[PIP_MAX_NAMELEN];
1964 	   char varname2[PIP_MAX_NAMELEN];
1965 	   char consname[PIP_MAX_NAMELEN + 1]; /* an extra character for ':' */
1966 	   char buffer[PIP_MAX_PRINTLEN];
1967 	
1968 	   assert( scip != NULL );
1969 	   assert( strcmp(type, "=") == 0 || strcmp(type, "<=") == 0 || strcmp(type, ">=") == 0 );
1970 	   assert( nlinvars == 0 || (linvars != NULL && linvals != NULL) );
1971 	
1972 	   clearLine(linebuffer, &linecnt);
1973 	
1974 	   /* start each line with a space */
1975 	   appendLine(scip, file, linebuffer, &linecnt, " ");
1976 	
1977 	   /* print row name */
1978 	   if ( strlen(rowname) > 0 || strlen(rownameextension) > 0 )
1979 	   {
1980 	      (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN + 1, "%s%s:", rowname, rownameextension);
1981 	      appendLine(scip, file, linebuffer, &linecnt, consname);
1982 	   }
1983 	
1984 	   /* print coefficients */
1985 	   for( v = 0; v < nlinvars; ++v )
1986 	   {
1987 	      SCIP_VAR* var;
1988 	
1989 	      assert(linvars != NULL);  /* for lint */
1990 	      assert(linvals != NULL);
1991 	
1992 	      var = linvars[v];
1993 	      assert( var != NULL );
1994 	
1995 	      /* we start a new line; therefore we tab this line */
1996 	      if ( linecnt == 0 )
1997 	         appendLine(scip, file, linebuffer, &linecnt, " ");
1998 	
1999 	      (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2000 	      (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", linvals[v], varname);
2001 	
2002 	      appendLine(scip, file, linebuffer, &linecnt, buffer);
2003 	   }
2004 	
2005 	   /* print quadratic part */
2006 	   if( quadexpr != NULL )
2007 	   {
2008 	      SCIP_EXPR** linexprs;
2009 	      SCIP_VAR** activevars;
2010 	      SCIP_Real* activevals;
2011 	      SCIP_Real* lincoefs;
2012 	      SCIP_Real constant;
2013 	      SCIP_Real activeconstant = 0.0;
2014 	      int nbilinexprterms;
2015 	      int nactivevars;
2016 	      int nquadexprs;
2017 	      int nlinexprs;
2018 	
2019 	      /* get data from the quadratic expression */
2020 	      SCIPexprGetQuadraticData(quadexpr, &constant, &nlinexprs, &linexprs, &lincoefs, &nquadexprs, &nbilinexprterms,
2021 	            NULL, NULL);
2022 	
2023 	      /* allocate memory to store active linear variables */
2024 	      SCIP_CALL( SCIPallocBufferArray(scip, &activevars, nlinexprs) );
2025 	      SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, lincoefs, nlinexprs) );
2026 	      nactivevars = nlinexprs;
2027 	
2028 	      for( v = 0; v < nlinexprs; ++v )
2029 	      {
2030 	         assert(linexprs != NULL && linexprs[v] != NULL);
2031 	         assert(SCIPisExprVar(scip, linexprs[v]));
2032 	
2033 	         activevars[v] = SCIPgetVarExprVar(linexprs[v]);
2034 	         assert(activevars[v] != NULL);
2035 	      }
2036 	
2037 	      /* get active variables */
2038 	      SCIP_CALL( getActiveVariables(scip, &activevars, &activevals, &nactivevars, &activeconstant, transformed) );
2039 	      constant += activeconstant;
2040 	
2041 	      /* print linear coefficients of linear variables */
2042 	      for( v = 0; v < nactivevars; ++v )
2043 	      {
2044 	         SCIP_VAR* var;
2045 	
2046 	         assert(activevars != NULL);  /* for lint */
2047 	         assert(activevals != NULL);
2048 	
2049 	         var = activevars[v];
2050 	         assert( var != NULL );
2051 	
2052 	         /* we start a new line; therefore we tab this line */
2053 	         if( linecnt == 0 )
2054 	            appendLine(scip, file, linebuffer, &linecnt, " ");
2055 	
2056 	         (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2057 	         (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", activevals[v], varname);
2058 	
2059 	         appendLine(scip, file, linebuffer, &linecnt, buffer);
2060 	      }
2061 	
2062 	      /* free memory for active linear variables */
2063 	      SCIPfreeBufferArray(scip, &activevals);
2064 	      SCIPfreeBufferArray(scip, &activevars);
2065 	
2066 	      /* adjust rhs if there is a constant */
2067 	      if( constant != 0.0 && !SCIPisInfinity(scip, rhs) )
2068 	         rhs -= constant;
2069 	
2070 	      /* print linear coefficients of quadratic variables */
2071 	      for( v = 0; v < nquadexprs; ++v )
2072 	      {
2073 	         SCIP_EXPR* expr;
2074 	         SCIP_VAR* var;
2075 	         SCIP_Real lincoef;
2076 	
2077 	         /* get linear coefficient and variable of quadratic term */
2078 	         SCIPexprGetQuadraticQuadTerm(quadexpr, v, &expr, &lincoef, NULL, NULL, NULL, NULL);
2079 	         assert(expr != NULL);
2080 	         assert(SCIPisExprVar(scip, expr));
2081 	
2082 	         var = SCIPgetVarExprVar(expr);
2083 	         assert(var != NULL);
2084 	
2085 	         if( lincoef == 0.0 )
2086 	            continue;
2087 	
2088 	         /* we start a new line; therefore we tab this line */
2089 	         if( linecnt == 0 )
2090 	            appendLine(scip, file, linebuffer, &linecnt, " ");
2091 	
2092 	         (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2093 	         (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", lincoef, varname);
2094 	
2095 	         appendLine(scip, file, linebuffer, &linecnt, buffer);
2096 	      }
2097 	
2098 	      /* print square terms */
2099 	      for( v = 0; v < nquadexprs; ++v )
2100 	      {
2101 	         SCIP_EXPR* expr;
2102 	         SCIP_VAR* var;
2103 	         SCIP_Real sqrcoef;
2104 	
2105 	         /* get square coefficient and variable of quadratic term */
2106 	         SCIPexprGetQuadraticQuadTerm(quadexpr, v, &expr, NULL, &sqrcoef, NULL, NULL, NULL);
2107 	         assert(expr != NULL);
2108 	         assert(SCIPisExprVar(scip, expr));
2109 	
2110 	         var = SCIPgetVarExprVar(expr);
2111 	         assert(var != NULL);
2112 	
2113 	         if( sqrcoef == 0.0 )
2114 	            continue;
2115 	
2116 	         /* we start a new line; therefore we tab this line */
2117 	         if( linecnt == 0 )
2118 	            appendLine(scip, file, linebuffer, &linecnt, " ");
2119 	
2120 	         (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2121 	         (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^2", sqrcoef, varname);
2122 	
2123 	         appendLine(scip, file, linebuffer, &linecnt, buffer);
2124 	      }
2125 	
2126 	      /* print bilinear terms */
2127 	      for( v = 0; v < nbilinexprterms; ++v )
2128 	      {
2129 	         SCIP_EXPR* expr1;
2130 	         SCIP_EXPR* expr2;
2131 	         SCIP_VAR* var1;
2132 	         SCIP_VAR* var2;
2133 	         SCIP_Real bilincoef;
2134 	
2135 	         /* get coefficient and variables of bilinear */
2136 	         SCIPexprGetQuadraticBilinTerm(quadexpr, v, &expr1, &expr2, &bilincoef, NULL, NULL);
2137 	         assert(expr1 != NULL);
2138 	         assert(SCIPisExprVar(scip, expr1));
2139 	         assert(expr2 != NULL);
2140 	         assert(SCIPisExprVar(scip, expr2));
2141 	
2142 	         var1 = SCIPgetVarExprVar(expr1);
2143 	         assert(var1 != NULL);
2144 	         var2 = SCIPgetVarExprVar(expr2);
2145 	         assert(var2 != NULL);
2146 	
2147 	         /* we start a new line; therefore we tab this line */
2148 	         if( linecnt == 0 )
2149 	            appendLine(scip, file, linebuffer, &linecnt, " ");
2150 	
2151 	         (void) SCIPsnprintf(varname,  PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var1));
2152 	         (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var2));
2153 	         (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s * %s", bilincoef, varname, varname2);
2154 	
2155 	         appendLine(scip, file, linebuffer, &linecnt, buffer);
2156 	      }
2157 	   }
2158 	
2159 	   /* print right hand side */
2160 	   if( SCIPisZero(scip, rhs) )
2161 	      rhs = 0.0;
2162 	
2163 	   (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s %+.15g", type, rhs);
2164 	
2165 	   /* we start a new line; therefore we tab this line */
2166 	   if (linecnt == 0 )
2167 	      appendLine(scip, file, linebuffer, &linecnt, " ");
2168 	   appendLine(scip, file, linebuffer, &linecnt, buffer);
2169 	
2170 	   endLine(scip, file, linebuffer, &linecnt);
2171 	
2172 	   return SCIP_OKAY;
2173 	}
2174 	
2175 	/** print signomial in PIP format to file stream */
2176 	static
2177 	void printSignomial(
2178 	   SCIP*                 scip,               /**< SCIP data structure */
2179 	   FILE*                 file,               /**< output file (or NULL for standard output) */
2180 	   char*                 linebuffer,         /**< line buffer to append to */
2181 	   int*                  linecnt,            /**< count on line buffer use */
2182 	   SCIP_EXPR*            expr,               /**< sigomial expression */
2183 	   SCIP_Real             coef,               /**< coefficient */
2184 	   SCIP_Bool             needsign            /**< whether a sign needs to be ensured */
2185 	   )
2186 	{
2187 	   char buffer[PIP_MAX_PRINTLEN];
2188 	   SCIP_EXPR* child;
2189 	   int c;
2190 	
2191 	   assert(isExprSignomial(scip, expr));
2192 	
2193 	   if( SCIPisExprProduct(scip, expr) )
2194 	      coef *= SCIPgetCoefExprProduct(expr);
2195 	
2196 	   if( SCIPisExprValue(scip, expr) )
2197 	      coef *= SCIPgetValueExprValue(expr);
2198 	
2199 	   if( REALABS(coef) != 1.0 )
2200 	   {
2201 	      (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, needsign ? " %+.15g " : " %.15g ", coef);
2202 	      appendLine(scip, file, linebuffer, linecnt, buffer);
2203 	   }
2204 	   else if( coef == 1.0 && needsign )
2205 	   {
2206 	      appendLine(scip, file, linebuffer, linecnt, " + ");
2207 	   }
2208 	   else if( coef == -1.0 )
2209 	   {
2210 	      appendLine(scip, file, linebuffer, linecnt, " - ");
2211 	   }
2212 	   else
2213 	   {
2214 	      appendLine(scip, file, linebuffer, linecnt, " ");
2215 	   }
2216 	
2217 	   if( SCIPisExprVar(scip, expr) )
2218 	   {
2219 	      appendLine(scip, file, linebuffer, linecnt, SCIPvarGetName(SCIPgetVarExprVar(expr)));
2220 	      return;
2221 	   }
2222 	
2223 	   if( SCIPisExprValue(scip, expr) )
2224 	   {
2225 	      if( REALABS(coef) == 1.0 )
2226 	      {
2227 	         /* in this case, we will have printed only a sign or space above, so print also a 1.0 */
2228 	         appendLine(scip, file, linebuffer, linecnt, "1.0");
2229 	      }
2230 	      return;
2231 	   }
2232 	
2233 	   if( SCIPisExprPower(scip, expr) )
2234 	   {
2235 	      assert(SCIPisExprVar(scip, SCIPexprGetChildren(expr)[0]));
2236 	
2237 	      (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, "%s^%.15g", SCIPvarGetName(SCIPgetVarExprVar(SCIPexprGetChildren(expr)[0])), SCIPgetExponentExprPow(expr));
2238 	      appendLine(scip, file, linebuffer, linecnt, buffer);
2239 	
2240 	      return;
2241 	   }
2242 	
2243 	   assert(SCIPisExprProduct(scip, expr));
2244 	   for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
2245 	   {
2246 	      child = SCIPexprGetChildren(expr)[c];
2247 	
2248 	      if( c > 0 )
2249 	         appendLine(scip, file, linebuffer, linecnt, " ");
2250 	
2251 	      if( SCIPisExprVar(scip, child) )
2252 	      {
2253 	         appendLine(scip, file, linebuffer, linecnt, SCIPvarGetName(SCIPgetVarExprVar(child)));
2254 	         continue;
2255 	      }
2256 	
2257 	      assert(SCIPisExprPower(scip, child));
2258 	      assert(SCIPisExprVar(scip, SCIPexprGetChildren(child)[0]));
2259 	
2260 	      (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, "%s^%.15g", SCIPvarGetName(SCIPgetVarExprVar(SCIPexprGetChildren(child)[0])), SCIPgetExponentExprPow(child));
2261 	      appendLine(scip, file, linebuffer, linecnt, buffer);
2262 	   }
2263 	}
2264 	
2265 	/** print polynomial row in PIP format to file stream */
2266 	static
2267 	void printRowNl(
2268 	   SCIP*                 scip,               /**< SCIP data structure */
2269 	   FILE*                 file,               /**< output file (or NULL for standard output) */
2270 	   const char*           rowname,            /**< row name */
2271 	   const char*           rownameextension,   /**< row name extension */
2272 	   const char*           type,               /**< row type ("=", "<=", or ">=") */
2273 	   SCIP_EXPR*            expr,               /**< polynomial expression */
2274 	   SCIP_Real             rhs                 /**< right hand side */
2275 	   )
2276 	{
2277 	   char consname[PIP_MAX_NAMELEN + 1]; /* an extra character for ':' */
2278 	   char buffer[PIP_MAX_PRINTLEN];
2279 	   char linebuffer[PIP_MAX_PRINTLEN+1] = { '\0' };
2280 	   int linecnt;
2281 	
2282 	   assert(scip != NULL);
2283 	   assert(strcmp(type, "=") == 0 || strcmp(type, "<=") == 0 || strcmp(type, ">=") == 0);
2284 	   assert(expr != NULL);
2285 	
2286 	   clearLine(linebuffer, &linecnt);
2287 	
2288 	   /* start each line with a space */
2289 	   appendLine(scip, file, linebuffer, &linecnt, " ");
2290 	
2291 	   /* print row name */
2292 	   if( strlen(rowname) > 0 || strlen(rownameextension) > 0 )
2293 	   {
2294 	      (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN + 1, "%s%s:", rowname, rownameextension);
2295 	      appendLine(scip, file, linebuffer, &linecnt, consname);
2296 	   }
2297 	
2298 	   if( SCIPisExprSum(scip, expr) )
2299 	   {
2300 	      int c;
2301 	      SCIP_Bool needsign = FALSE;
2302 	
2303 	      if( SCIPgetConstantExprSum(expr) != 0.0 )
2304 	      {
2305 	         (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", SCIPgetConstantExprSum(expr));
2306 	         appendLine(scip, file, linebuffer, &linecnt, buffer);
2307 	
2308 	         needsign = TRUE;
2309 	      }
2310 	
2311 	      for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
2312 	      {
2313 	         printSignomial(scip, file, linebuffer, &linecnt, SCIPexprGetChildren(expr)[c], SCIPgetCoefsExprSum(expr)[c], needsign);
2314 	         needsign = TRUE;
2315 	      }
2316 	   }
2317 	   else
2318 	   {
2319 	      printSignomial(scip, file, linebuffer, &linecnt, expr, 1.0, FALSE);
2320 	   }
2321 	
2322 	   /* print right hand side */
2323 	   (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s %+.15g", type, rhs);
2324 	
2325 	   /* we start a new line; therefore we tab this line */
2326 	   if( linecnt == 0 )
2327 	      appendLine(scip, file, linebuffer, &linecnt, " ");
2328 	   appendLine(scip, file, linebuffer, &linecnt, buffer);
2329 	
2330 	   endLine(scip, file, linebuffer, &linecnt);
2331 	}
2332 	
2333 	/** print "and" constraint as row in PIP format to file stream */
2334 	static
2335 	void printRowAnd(
2336 	   SCIP*                 scip,               /**< SCIP data structure */
2337 	   FILE*                 file,               /**< output file (or NULL for standard output) */
2338 	   const char*           rowname,            /**< row name */
2339 	   SCIP_CONS*            cons                /**< "and" constraint */
2340 	   )
2341 	{
2342 	   char linebuffer[PIP_MAX_PRINTLEN+1] = { '\0' };
2343 	   int linecnt;
2344 	   int i;
2345 	
2346 	   assert(scip != NULL);
2347 	   assert(rowname != NULL);
2348 	   assert(cons != NULL);
2349 	
2350 	   clearLine(linebuffer, &linecnt);
2351 	
2352 	   /* start each line with a space */
2353 	   appendLine(scip, file, linebuffer, &linecnt, " ");
2354 	
2355 	   /* print row name */
2356 	   if( strlen(rowname) > 0 )
2357 	   {
2358 	      appendLine(scip, file, linebuffer, &linecnt, rowname);
2359 	      appendLine(scip, file, linebuffer, &linecnt, ":");
2360 	   }
2361 	
2362 	   for( i = 0; i < SCIPgetNVarsAnd(scip, cons); ++i )
2363 	   {
2364 	      appendLine(scip, file, linebuffer, &linecnt, " ");
2365 	      appendLine(scip, file, linebuffer, &linecnt, SCIPvarGetName(SCIPgetVarsAnd(scip, cons)[i]));
2366 	   }
2367 	
2368 	   appendLine(scip, file, linebuffer, &linecnt, " - ");
2369 	   appendLine(scip, file, linebuffer, &linecnt, SCIPvarGetName(SCIPgetResultantAnd(scip, cons)));
2370 	
2371 	   /* we start a new line; therefore we tab this line */
2372 	   if( linecnt == 0 )
2373 	      appendLine(scip, file, linebuffer, &linecnt, " ");
2374 	
2375 	   /* print right hand side */
2376 	   appendLine(scip, file, linebuffer, &linecnt, " = 0");
2377 	
2378 	   endLine(scip, file, linebuffer, &linecnt);
2379 	}
2380 	
2381 	/** prints given (linear or) quadratic constraint information in LP format to file stream */
2382 	static
2383 	SCIP_RETCODE printQuadraticCons(
2384 	   SCIP*                 scip,               /**< SCIP data structure */
2385 	   FILE*                 file,               /**< output file (or NULL for standard output) */
2386 	   const char*           rowname,            /**< name of the row */
2387 	   SCIP_VAR**            linvars,            /**< array of linear variables */
2388 	   SCIP_Real*            linvals,            /**< array of linear coefficients values (or NULL if all linear coefficient values are 1) */
2389 	   int                   nlinvars,           /**< number of linear variables */
2390 	   SCIP_EXPR*            quadexpr,           /**< quadratic expression (or NULL if nlinvars > 0) */
2391 	   SCIP_Real             lhs,                /**< left hand side */
2392 	   SCIP_Real             rhs,                /**< right hand side */
2393 	   SCIP_Bool             transformed         /**< transformed constraint? */
2394 	   )
2395 	{
2396 	   int v;
2397 	   SCIP_VAR** activevars = NULL;
2398 	   SCIP_Real* activevals = NULL;
2399 	   int nactivevars;
2400 	   SCIP_Real activeconstant = 0.0;
2401 	
2402 	   assert( scip != NULL );
2403 	   assert( rowname != NULL );
2404 	
2405 	   assert( nlinvars == 0 || linvars != NULL );
2406 	   assert( quadexpr == NULL || nlinvars == 0);
2407 	   assert( lhs <= rhs );
2408 	
2409 	   if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2410 	      return SCIP_OKAY;
2411 	
2412 	   nactivevars = nlinvars;
2413 	   if( nlinvars > 0 )
2414 	   {
2415 	      /* duplicate variable and value array */
2416 	      SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, linvars, nactivevars ) );
2417 	      if( linvals != NULL )
2418 	      {
2419 	         SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, linvals, nactivevars ) );
2420 	      }
2421 	      else
2422 	      {
2423 	         SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2424 	
2425 	         for( v = 0; v < nactivevars; ++v )
2426 	            activevals[v] = 1.0;
2427 	      }
2428 	
2429 	      /* retransform given variables to active variables */
2430 	      SCIP_CALL( getActiveVariables(scip, &activevars, &activevals, &nactivevars, &activeconstant, transformed) );
2431 	   }
2432 	
2433 	   /* print row(s) in LP format */
2434 	   if( SCIPisEQ(scip, lhs, rhs) )
2435 	   {
2436 	      assert( !SCIPisInfinity(scip, rhs) );
2437 	
2438 	      /* equal constraint */
2439 	      SCIP_CALL( printRow(scip, file, rowname, "", "=", activevars, activevals, nactivevars, quadexpr,
2440 	         rhs - activeconstant, transformed) );
2441 	   }
2442 	   else
2443 	   {
2444 	      if( !SCIPisInfinity(scip, -lhs) )
2445 	      {
2446 	         /* print inequality ">=" */
2447 	         SCIP_CALL( printRow(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", ">=", activevars,
2448 	            activevals, nactivevars, quadexpr, lhs - activeconstant, transformed) );
2449 	      }
2450 	      if( !SCIPisInfinity(scip, rhs) )
2451 	      {
2452 	         /* print inequality "<=" */
2453 	         SCIP_CALL( printRow(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "<=", activevars,
2454 	            activevals, nactivevars, quadexpr, rhs - activeconstant, transformed) );
2455 	      }
2456 	   }
2457 	
2458 	   if( nlinvars > 0 )
2459 	   {
2460 	      /* free buffer arrays */
2461 	      SCIPfreeBufferArray(scip, &activevars);
2462 	      SCIPfreeBufferArray(scip, &activevals);
2463 	   }
2464 	
2465 	   return SCIP_OKAY;
2466 	}
2467 	
2468 	/** prints given nonlinear constraint information in LP format to file stream */
2469 	static
2470 	SCIP_RETCODE printNonlinearCons(
2471 	   SCIP*                 scip,               /**< SCIP data structure */
2472 	   FILE*                 file,               /**< output file (or NULL for standard output) */
2473 	   const char*           rowname,            /**< name of the row */
2474 	   SCIP_EXPR*            expr,               /**< polynomial expression */
2475 	   SCIP_Real             lhs,                /**< left hand side */
2476 	   SCIP_Real             rhs                 /**< right hand side */
2477 	   )
2478 	{
2479 	   assert(scip != NULL);
2480 	   assert(rowname != NULL);
2481 	   assert(expr != NULL);
2482 	   assert(lhs <= rhs);
2483 	
2484 	   if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2485 	      return SCIP_OKAY;
2486 	
2487 	   /* print row(s) in LP format */
2488 	   if( SCIPisEQ(scip, lhs, rhs) )
2489 	   {
2490 	      assert( !SCIPisInfinity(scip, rhs) );
2491 	
2492 	      /* equal constraint */
2493 	      printRowNl(scip, file, rowname, "", "=", expr, rhs);
2494 	   }
2495 	   else
2496 	   {
2497 	      if( !SCIPisInfinity(scip, -lhs) )
2498 	      {
2499 	         /* print inequality ">=" */
2500 	         printRowNl(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", ">=", expr, lhs);
2501 	      }
2502 	      if( !SCIPisInfinity(scip, rhs) )
2503 	      {
2504 	         /* print inequality "<=" */
2505 	         printRowNl(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "<=", expr, rhs);
2506 	      }
2507 	   }
2508 	
2509 	   return SCIP_OKAY;
2510 	}
2511 	
2512 	/** check whether given variables are aggregated and put them into an array without duplication */
2513 	static
2514 	SCIP_RETCODE collectAggregatedVars(
2515 	   int                   nvars,              /**< number of active variables in the problem */
2516 	   SCIP_VAR**            vars,               /**< variable array */
2517 	   int*                  nAggregatedVars,    /**< number of aggregated variables on output */
2518 	   SCIP_VAR***           aggregatedVars,     /**< array storing the aggregated variables on output */
2519 	   SCIP_HASHTABLE**      varAggregated       /**< hashtable for checking duplicates */
2520 	   )
2521 	{
2522 	   int j;
2523 	
2524 	   /* check variables */
2525 	   for (j = 0; j < nvars; ++j)
2526 	   {
2527 	      SCIP_VARSTATUS status;
2528 	      SCIP_VAR* var;
2529 	
2530 	      var = vars[j];
2531 	      status = SCIPvarGetStatus(var);
2532 	
2533 	      /* collect aggregated variables in a list */
2534 	      if( status >= SCIP_VARSTATUS_AGGREGATED )
2535 	      {
2536 	         assert( status == SCIP_VARSTATUS_AGGREGATED ||
2537 	            status == SCIP_VARSTATUS_MULTAGGR ||
2538 	            status == SCIP_VARSTATUS_NEGATED );
2539 	
2540 	         if ( ! SCIPhashtableExists(*varAggregated, (void*) var) )
2541 	         {
2542 	            (*aggregatedVars)[(*nAggregatedVars)++] = var;
2543 	            SCIP_CALL( SCIPhashtableInsert(*varAggregated, (void*) var) );
2544 	         }
2545 	      }
2546 	   }
2547 	
2548 	   return SCIP_OKAY;
2549 	}
2550 	
2551 	
2552 	/** print aggregated variable-constraints */
2553 	static
2554 	SCIP_RETCODE printAggregatedCons(
2555 	   SCIP*                 scip,               /**< SCIP data structure */
2556 	   FILE*                 file,               /**< output file (or NULL for standard output) */
2557 	   SCIP_Bool             transformed,        /**< TRUE iff problem is the transformed problem */
2558 	   int                   nvars,              /**< number of active variables in the problem */
2559 	   int                   nAggregatedVars,    /**< number of aggregated variables */
2560 	   SCIP_VAR**            aggregatedVars      /**< array storing the aggregated variables */
2561 	   )
2562 	{
2563 	   int j;
2564 	
2565 	   SCIP_VAR** activevars;
2566 	   SCIP_Real* activevals;
2567 	   int nactivevars;
2568 	   SCIP_Real activeconstant = 0.0;
2569 	   char consname[PIP_MAX_NAMELEN];
2570 	
2571 	   assert( scip != NULL );
2572 	
2573 	   /* write aggregation constraints */
2574 	   SCIP_CALL( SCIPallocBufferArray(scip, &activevars, nvars) );
2575 	   SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nvars) );
2576 	
2577 	   for (j = 0; j < nAggregatedVars; ++j)
2578 	   {
2579 	      /* set up list to obtain substitution variables */
2580 	      nactivevars = 1;
2581 	
2582 	      activevars[0] = aggregatedVars[j];
2583 	      activevals[0] = 1.0;
2584 	      activeconstant = 0.0;
2585 	
2586 	      /* retransform given variables to active variables */
2587 	      SCIP_CALL( getActiveVariables(scip, &activevars, &activevals, &nactivevars, &activeconstant, transformed) );
2588 	
2589 	      activevals[nactivevars] = -1.0;
2590 	      activevars[nactivevars] = aggregatedVars[j];
2591 	      ++nactivevars;
2592 	
2593 	      /* output constraint */
2594 	      (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN, "aggr_%s", SCIPvarGetName(aggregatedVars[j]));
2595 	      SCIP_CALL( printRow(scip, file, consname, "", "=", activevars, activevals, nactivevars, NULL, - activeconstant,
2596 	         transformed) );
2597 	   }
2598 	
2599 	   /* free buffer arrays */
2600 	   SCIPfreeBufferArray(scip, &activevars);
2601 	   SCIPfreeBufferArray(scip, &activevals);
2602 	
2603 	   return SCIP_OKAY;
2604 	}
2605 	
2606 	/** returns whether name is valid according to PIP specification
2607 	 *
2608 	 * Checks these two conditions from http://polip.zib.de/pipformat.php:
2609 	 * - Names/labels can contain at most 255 characters.
2610 	 * - Name/labels have to consist of the following characters: a-z, A-Z, 0-9, "!", "#", "$", "%", "&", ";", "?", "@", "_". They cannot start with a number.
2611 	 *
2612 	 * In addition checks that the length is not zero.
2613 	 */
2614 	static
2615 	SCIP_Bool isNameValid(
2616 	   const char*           name                /**< name to check */
2617 	   )
2618 	{
2619 	   size_t len;
2620 	   size_t i;
2621 	
2622 	   assert(name != NULL);
2623 	
2624 	   len = strlen(name);  /*lint !e613*/
2625 	   if( len > (size_t) PIP_MAX_NAMELEN || len == 0 )
2626 	      return FALSE;
2627 	
2628 	   /* names cannot start with a number */
2629 	   if( isdigit(name[0]) )
2630 	      return FALSE;
2631 	
2632 	   for( i = 0; i < len; ++i )
2633 	   {
2634 	      /* a-z, A-Z, 0-9 are ok */
2635 	      if( isalnum(name[i]) )
2636 	         continue;
2637 	
2638 	      /* characters in namechars are ok, too */
2639 	      if( strchr(namechars, name[i]) != NULL )
2640 	         continue;
2641 	
2642 	      return FALSE;
2643 	   }
2644 	
2645 	   return TRUE;
2646 	}
2647 	
2648 	
2649 	/** method check if the variable names are valid according to PIP specification */
2650 	static
2651 	void checkVarnames(
2652 	   SCIP*                 scip,               /**< SCIP data structure */
2653 	   SCIP_VAR**            vars,               /**< array of variables */
2654 	   int                   nvars               /**< number of variables */
2655 	   )
2656 	{
2657 	   int v;
2658 	
2659 	   assert(scip != NULL);
2660 	   assert(vars != NULL || nvars == 0);
2661 	
2662 	   /* check if the variable names are not too long and have only characters allowed by PIP */
2663 	   for( v = 0; v < nvars; ++v )
2664 	   {
2665 	      if( !isNameValid(SCIPvarGetName(vars[v])) )
2666 	      {
2667 	         SCIPwarningMessage(scip, "variable name <%s> is not valid (too long or disallowed characters); PIP might be corrupted\n", SCIPvarGetName(vars[v]));
2668 	         return;
2669 	      }
2670 	   }
2671 	}
2672 	
2673 	/** method check if the constraint names are valid according to PIP specification */
2674 	static
2675 	void checkConsnames(
2676 	   SCIP*                 scip,               /**< SCIP data structure */
2677 	   SCIP_CONS**           conss,              /**< array of constraints */
2678 	   int                   nconss,             /**< number of constraints */
2679 	   SCIP_Bool             transformed         /**< TRUE iff problem is the transformed problem */
2680 	   )
2681 	{
2682 	   int c;
2683 	   SCIP_CONS* cons;
2684 	   SCIP_CONSHDLR* conshdlr;
2685 	   const char* conshdlrname;
2686 	
2687 	   assert( scip != NULL );
2688 	   assert( conss != NULL || nconss == 0 );
2689 	
2690 	   for( c = 0; c < nconss; ++c )
2691 	   {
2692 	      assert(conss != NULL); /* for lint */
2693 	      cons = conss[c];
2694 	      assert(cons != NULL );
2695 	
2696 	      /* in case the transformed is written only constraints are posted which are enabled in the current node */
2697 	      assert(!transformed || SCIPconsIsEnabled(cons));
2698 	
2699 	      conshdlr = SCIPconsGetHdlr(cons);
2700 	      assert( conshdlr != NULL );
2701 	
2702 	      conshdlrname = SCIPconshdlrGetName(conshdlr);
2703 	      assert( transformed == SCIPconsIsTransformed(cons) );
2704 	
2705 	      if( !isNameValid(SCIPconsGetName(cons)) )
2706 	      {
2707 	         SCIPwarningMessage(scip, "constraint name <%s> is not valid (too long or unallowed characters); PIP might be corrupted\n", SCIPconsGetName(cons));
2708 	         return;
2709 	      }
2710 	
2711 	      if( strcmp(conshdlrname, "linear") == 0 )
2712 	      {
2713 	         SCIP_Real lhs = SCIPgetLhsLinear(scip, cons);
2714 	         SCIP_Real rhs = SCIPgetRhsLinear(scip, cons);
2715 	
2716 	         /* for ranged constraints, we need to be able to append _lhs and _rhs to the constraint name, so need additional 4 characters */
2717 	         if( !SCIPisEQ(scip, lhs, rhs) && strlen(SCIPconsGetName(conss[c])) > (size_t) PIP_MAX_NAMELEN -  4 )
2718 	         {
2719 	            SCIPwarningMessage(scip, "name of ranged constraint <%s> has to be cut down to %d characters;\n", SCIPconsGetName(conss[c]),
2720 	               PIP_MAX_NAMELEN  - 1);
2721 	            return;
2722 	         }
2723 	      }
2724 	   }
2725 	}
2726 	
2727 	/** writes problem to file
2728 	 * @todo add writing cons_pseudoboolean
2729 	 */
2730 	SCIP_RETCODE SCIPwritePip(
2731 	   SCIP*                 scip,               /**< SCIP data structure */
2732 	   FILE*                 file,               /**< output file, or NULL if standard output should be used */
2733 	   const char*           name,               /**< problem name */
2734 	   SCIP_Bool             transformed,        /**< TRUE iff problem is the transformed problem */
2735 	   SCIP_OBJSENSE         objsense,           /**< objective sense */
2736 	   SCIP_Real             objscale,           /**< scalar applied to objective function; external objective value is
2737 	                                              *   extobj = objsense * objscale * (intobj + objoffset) */
2738 	   SCIP_Real             objoffset,          /**< objective offset from bound shifting and fixing */
2739 	   SCIP_VAR**            vars,               /**< array with active variables ordered binary, integer, implicit, continuous */
2740 	   int                   nvars,              /**< number of active variables in the problem */
2741 	   int                   nbinvars,           /**< number of binary variables */
2742 	   int                   nintvars,           /**< number of general integer variables */
2743 	   int                   nimplvars,          /**< number of implicit integer variables */
2744 	   int                   ncontvars,          /**< number of continuous variables */
2745 	   SCIP_CONS**           conss,              /**< array with constraints of the problem */
2746 	   int                   nconss,             /**< number of constraints in the problem */
2747 	   SCIP_RESULT*          result              /**< pointer to store the result of the file writing call */
2748 	   )
2749 	{
2750 	   int c;
2751 	   int v;
2752 	
2753 	   int linecnt;
2754 	   char linebuffer[PIP_MAX_PRINTLEN+1];
2755 	
2756 	   char varname[PIP_MAX_NAMELEN];
2757 	   char buffer[PIP_MAX_PRINTLEN];
2758 	
2759 	   SCIP_CONSHDLR* conshdlr;
2760 	   const char* conshdlrname;
2761 	   SCIP_CONS* cons;
2762 	   SCIP_CONS** consNonlinear;
2763 	   int nConsNonlinear;
2764 	   SCIP_CONS** consAnd;
2765 	   int nConsAnd;
2766 	   char consname[PIP_MAX_NAMELEN];
2767 	
2768 	   SCIP_VAR** aggregatedVars;
2769 	   int nAggregatedVars;
2770 	   SCIP_HASHTABLE* varAggregated;
2771 	
2772 	   SCIP_VAR** tmpvars;
2773 	   int tmpvarssize;
2774 	
2775 	   SCIP_VAR** consvars;
2776 	   SCIP_Real* consvals;
2777 	   int nconsvars;
2778 	
2779 	   SCIP_VAR* var;
2780 	   SCIP_Real lb;
2781 	   SCIP_Real ub;
2782 	
2783 	   assert( scip != NULL );
2784 	
2785 	   nAggregatedVars = 0;
2786 	   nConsNonlinear = 0;
2787 	   nConsAnd = 0;
2788 	
2789 	   /* check if the variable names are not to long */
2790 	   checkVarnames(scip, vars, nvars);
2791 	
2792 	   /* check if the constraint names are to long */
2793 	   checkConsnames(scip, conss, nconss, transformed);
2794 	
2795 	   /* print statistics as comment to file */
2796 	   SCIPinfoMessage(scip, file, "\\ SCIP STATISTICS\n");
2797 	   SCIPinfoMessage(scip, file, "\\   Problem name     : %s\n", name);
2798 	   SCIPinfoMessage(scip, file, "\\   Variables        : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
2799 	      nvars, nbinvars, nintvars, nimplvars, ncontvars);
2800 	   SCIPinfoMessage(scip, file, "\\   Constraints      : %d\n", nconss);
2801 	
2802 	   /* print objective sense */
2803 	   SCIPinfoMessage(scip, file, "%s\n", objsense == SCIP_OBJSENSE_MINIMIZE ? "Minimize" : "Maximize");
2804 	
2805 	   clearLine(linebuffer, &linecnt);
2806 	   appendLine(scip, file, linebuffer, &linecnt, " Obj:");
2807 	
2808 	   for (v = 0; v < nvars; ++v)
2809 	   {
2810 	      var = vars[v];
2811 	
2812 	#ifndef NDEBUG
2813 	      /* in case the original problem has to be posted the variables have to be either "original" or "negated" */
2814 	      if ( !transformed )
2815 	         assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL || SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED );
2816 	#endif
2817 	
2818 	      if ( SCIPisZero(scip, SCIPvarGetObj(var)) )
2819 	         continue;
2820 	
2821 	      /* we start a new line; therefore we tab this line */
2822 	      if ( linecnt == 0 )
2823 	         appendLine(scip, file, linebuffer, &linecnt, "     ");
2824 	
2825 	      (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2826 	      (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", objscale * SCIPvarGetObj(var), varname );
2827 	
2828 	      appendLine(scip, file, linebuffer, &linecnt, buffer);
2829 	   }
2830 	
2831 	   if( ! SCIPisZero(scip, objoffset) )
2832 	   {
2833 	      (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", objscale * objoffset);
2834 	      appendLine(scip, file, linebuffer, &linecnt, buffer);
2835 	   }
2836 	
2837 	   endLine(scip, file, linebuffer, &linecnt);
2838 	
2839 	   /* print "Subject to" section */
2840 	   SCIPinfoMessage(scip, file, "Subject to\n");
2841 	
2842 	   /* collect quadratic, nonlinear, absolute power, and, and bivariate constraints in arrays */
2843 	   SCIP_CALL( SCIPallocBufferArray(scip, &consNonlinear, nconss) );
2844 	   SCIP_CALL( SCIPallocBufferArray(scip, &consAnd, nconss) );
2845 	
2846 	   tmpvarssize = SCIPgetNTotalVars(scip);
2847 	   SCIP_CALL( SCIPallocBufferArray(scip, &tmpvars, tmpvarssize) );
2848 	
2849 	   for (c = 0; c < nconss; ++c)
2850 	   {
2851 	      cons = conss[c];
2852 	      assert( cons != NULL);
2853 	
2854 	      /* in case the transformed is written only constraints are posted which are enabled in the current node */
2855 	      assert(!transformed || SCIPconsIsEnabled(cons));
2856 	
2857 	      conshdlr = SCIPconsGetHdlr(cons);
2858 	      assert( conshdlr != NULL );
2859 	
2860 	      (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN, "%s", SCIPconsGetName(cons));
2861 	      conshdlrname = SCIPconshdlrGetName(conshdlr);
2862 	      assert( transformed == SCIPconsIsTransformed(cons) );
2863 	
2864 	      if( strcmp(conshdlrname, "linear") == 0 )
2865 	      {
2866 	         SCIP_CALL( printQuadraticCons(scip, file, consname,
2867 	               SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons), SCIPgetNVarsLinear(scip, cons),
2868 	               NULL, SCIPgetLhsLinear(scip, cons),  SCIPgetRhsLinear(scip, cons), transformed) );
2869 	      }
2870 	      else if( strcmp(conshdlrname, "setppc") == 0 )
2871 	      {
2872 	         consvars = SCIPgetVarsSetppc(scip, cons);
2873 	         nconsvars = SCIPgetNVarsSetppc(scip, cons);
2874 	
2875 	         switch( SCIPgetTypeSetppc(scip, cons) )
2876 	         {
2877 	         case SCIP_SETPPCTYPE_PARTITIONING :
2878 	            SCIP_CALL( printQuadraticCons(scip, file, consname,
2879 	                  consvars, NULL, nconsvars, NULL, 1.0, 1.0, transformed) );
2880 	            break;
2881 	         case SCIP_SETPPCTYPE_PACKING :
2882 	            SCIP_CALL( printQuadraticCons(scip, file, consname,
2883 	                  consvars, NULL, nconsvars, NULL, -SCIPinfinity(scip), 1.0, transformed) );
2884 	            break;
2885 	         case SCIP_SETPPCTYPE_COVERING :
2886 	            SCIP_CALL( printQuadraticCons(scip, file, consname,
2887 	                  consvars, NULL, nconsvars, NULL, 1.0, SCIPinfinity(scip), transformed) );
2888 	            break;
2889 	         }
2890 	      }
2891 	      else if ( strcmp(conshdlrname, "logicor") == 0 )
2892 	      {
2893 	         SCIP_CALL( printQuadraticCons(scip, file, consname,
2894 	               SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons),
2895 	               NULL, 1.0, SCIPinfinity(scip), transformed) );
2896 	      }
2897 	      else if ( strcmp(conshdlrname, "knapsack") == 0 )
2898 	      {
2899 	         SCIP_Longint* weights;
2900 	
2901 	         consvars = SCIPgetVarsKnapsack(scip, cons);
2902 	         nconsvars = SCIPgetNVarsKnapsack(scip, cons);
2903 	
2904 	         /* copy Longint array to SCIP_Real array */
2905 	         weights = SCIPgetWeightsKnapsack(scip, cons);
2906 	         SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
2907 	         for( v = 0; v < nconsvars; ++v )
2908 	            consvals[v] = (SCIP_Real)weights[v];
2909 	
2910 	         SCIP_CALL( printQuadraticCons(scip, file, consname, consvars, consvals, nconsvars,
2911 	               NULL, -SCIPinfinity(scip), (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), transformed) );
2912 	
2913 	         SCIPfreeBufferArray(scip, &consvals);
2914 	      }
2915 	      else if ( strcmp(conshdlrname, "varbound") == 0 )
2916 	      {
2917 	         SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
2918 	         SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
2919 	
2920 	         consvars[0] = SCIPgetVarVarbound(scip, cons);
2921 	         consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
2922 	
2923 	         consvals[0] = 1.0;
2924 	         consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
2925 	
2926 	         SCIP_CALL( printQuadraticCons(scip, file, consname, consvars, consvals, 2, NULL,
2927 	            SCIPgetLhsVarbound(scip, cons), SCIPgetRhsVarbound(scip, cons), transformed) );
2928 	
2929 	         SCIPfreeBufferArray(scip, &consvars);
2930 	         SCIPfreeBufferArray(scip, &consvals);
2931 	      }
2932 	      else if( strcmp(conshdlrname, "nonlinear") == 0 )
2933 	      {
2934 	         SCIP_Bool ispolynomial;
2935 	         SCIP_Bool isquadratic;
2936 	         SCIP_EXPR* simplifiedexpr = NULL;
2937 	
2938 	         ispolynomial = isExprPolynomial(scip, SCIPgetExprNonlinear(cons));
2939 	         if( !ispolynomial )
2940 	         {
2941 	            /* simplify expression and check again if polynomial
2942 	             * simplifying the expr owned by the cons can have undesired sideffects onto the consdata (the varhashmap can get messed up), so we copy first
2943 	             */
2944 	            SCIP_EXPR* exprcopy;
2945 	            SCIP_Bool changed;
2946 	            SCIP_Bool infeasible;
2947 	
2948 	            SCIP_CALL( SCIPduplicateExpr(scip, SCIPgetExprNonlinear(cons), &exprcopy, NULL, NULL, NULL, NULL) );
2949 	            SCIP_CALL( SCIPsimplifyExpr(scip, exprcopy, &simplifiedexpr, &changed, &infeasible, NULL, NULL) );
2950 	            SCIP_CALL( SCIPreleaseExpr(scip, &exprcopy) );
2951 	
2952 	            ispolynomial = isExprPolynomial(scip, simplifiedexpr);
2953 	         }
2954 	
2955 	         /* nonlinear constraints that are not polynomial cannot be printed as PIP */
2956 	         if( !ispolynomial )
2957 	         {
2958 	            SCIPwarningMessage(scip, "nonlinear constraint <%s> is not polynomial\n", SCIPconsGetName(cons));
2959 	            SCIPinfoMessage(scip, file, "\\ ");
2960 	            SCIP_CALL( SCIPprintCons(scip, cons, file) );
2961 	            SCIPinfoMessage(scip, file, ";\n");
2962 	
2963 	            SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedexpr) );
2964 	            return SCIP_OKAY;
2965 	         }
2966 	
2967 	         /* check whether constraint is even quadratic
2968 	          * (we could also skip this and print as polynomial, but the code exists already)
2969 	          */
2970 	         SCIP_CALL( SCIPcheckExprQuadratic(scip, simplifiedexpr != NULL ? simplifiedexpr : SCIPgetExprNonlinear(cons), &isquadratic) );
2971 	         if( isquadratic )
2972 	            isquadratic = SCIPexprAreQuadraticExprsVariables(simplifiedexpr != NULL ? simplifiedexpr : SCIPgetExprNonlinear(cons));
2973 	
2974 	         if( isquadratic )
2975 	         {
2976 	            SCIP_CALL( printQuadraticCons(scip, file, consname, NULL, NULL, 0, simplifiedexpr != NULL ? simplifiedexpr : SCIPgetExprNonlinear(cons),
2977 	               SCIPgetLhsNonlinear(cons), SCIPgetRhsNonlinear(cons), transformed) );
2978 	         }
2979 	         else
2980 	         {
2981 	            SCIP_CALL( printNonlinearCons(scip, file, consname, simplifiedexpr != NULL ? simplifiedexpr : SCIPgetExprNonlinear(cons), SCIPgetLhsNonlinear(cons), SCIPgetRhsNonlinear(cons)) );
2982 	         }
2983 	
2984 	         consNonlinear[nConsNonlinear++] = cons;
2985 	
2986 	         if( simplifiedexpr != NULL )
2987 	         {
2988 	            SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedexpr) );
2989 	         }
2990 	      }
2991 	      else if( strcmp(conshdlrname, "and") == 0 )
2992 	      {
2993 	         printRowAnd(scip, file, consname, cons);
2994 	
2995 	         consAnd[nConsAnd++] = cons;
2996 	      }
2997 	      else
2998 	      {
2999 	         SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
3000 	         SCIPinfoMessage(scip, file, "\\ ");
3001 	         SCIP_CALL( SCIPprintCons(scip, cons, file) );
3002 	         SCIPinfoMessage(scip, file, ";\n");
3003 	      }
3004 	   }
3005 	
3006 	   /* create hashtable for storing aggregated variables */
3007 	   SCIP_CALL( SCIPallocBufferArray(scip, &aggregatedVars, nvars) );
3008 	   SCIP_CALL( SCIPhashtableCreate(&varAggregated, SCIPblkmem(scip), nvars/10, hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) );
3009 	
3010 	   /* check for aggregated variables in nonlinear constraints and output aggregations as linear constraints */
3011 	   for( c = 0; c < nConsNonlinear; ++c )
3012 	   {
3013 	      SCIP_Bool success;
3014 	      int ntmpvars;
3015 	
3016 	      /* get variables of the nonlinear constraint */
3017 	      SCIP_CALL( SCIPgetConsNVars(scip, consNonlinear[c], &ntmpvars, &success) );
3018 	      assert(success);
3019 	      if( ntmpvars > tmpvarssize )
3020 	      {
3021 	         tmpvarssize = SCIPcalcMemGrowSize(scip, ntmpvars);
3022 	         SCIP_CALL( SCIPreallocBufferArray(scip, &tmpvars, tmpvarssize) );
3023 	      }
3024 	      SCIP_CALL( SCIPgetConsVars(scip, consNonlinear[c], tmpvars, tmpvarssize, &success) );
3025 	      assert(success);
3026 	
3027 	      SCIP_CALL( collectAggregatedVars(ntmpvars, tmpvars, &nAggregatedVars, &aggregatedVars, &varAggregated) );
3028 	   }
3029 	
3030 	   /* check for aggregated variables in and constraints and output aggregations as linear constraints */
3031 	   for (c = 0; c < nConsAnd; ++c)
3032 	   {
3033 	      SCIP_VAR* resultant;
3034 	
3035 	      cons = consAnd[c];
3036 	
3037 	      SCIP_CALL( collectAggregatedVars(SCIPgetNVarsAnd(scip, cons), SCIPgetVarsAnd(scip, cons), &nAggregatedVars, &aggregatedVars, &varAggregated) );
3038 	
3039 	      resultant = SCIPgetResultantAnd(scip, cons);
3040 	      SCIP_CALL( collectAggregatedVars(1, &resultant, &nAggregatedVars, &aggregatedVars, &varAggregated) );
3041 	   }
3042 	
3043 	   /* print aggregation constraints */
3044 	   SCIP_CALL( printAggregatedCons(scip, file, transformed, nvars, nAggregatedVars, aggregatedVars) );
3045 	
3046 	   /* print "Bounds" section */
3047 	   SCIPinfoMessage(scip, file, "Bounds\n");
3048 	   for (v = 0; v < nvars; ++v)
3049 	   {
3050 	      var = vars[v];
3051 	      assert( var != NULL );
3052 	      (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3053 	
3054 	      if( transformed )
3055 	      {
3056 	         /* in case the transformed is written only local bounds are posted which are valid in the current node */
3057 	         lb = SCIPvarGetLbLocal(var);
3058 	         ub = SCIPvarGetUbLocal(var);
3059 	      }
3060 	      else
3061 	      {
3062 	         lb = SCIPvarGetLbOriginal(var);
3063 	         ub = SCIPvarGetUbOriginal(var);
3064 	      }
3065 	
3066 	      if ( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) )
3067 	         SCIPinfoMessage(scip, file, " %s free\n", varname);
3068 	      else
3069 	      {
3070 	         /* print lower bound */
3071 	         if ( SCIPisInfinity(scip, -lb) )
3072 	            SCIPinfoMessage(scip, file, " -inf <= ");
3073 	         else
3074 	         {
3075 	            if ( SCIPisZero(scip, lb) )
3076 	            {
3077 	               /* variables are nonnegative by default - so we skip these variables */
3078 	               if ( SCIPisInfinity(scip, ub) )
3079 	                  continue;
3080 	               lb = 0.0;
3081 	            }
3082 	
3083 	            SCIPinfoMessage(scip, file, " %.15g <= ", lb);
3084 	         }
3085 	         /* print variable name */
3086 	         SCIPinfoMessage(scip, file, "%s", varname);
3087 	
3088 	         /* print upper bound as far this one is not infinity */
3089 	         if( !SCIPisInfinity(scip, ub) )
3090 	            SCIPinfoMessage(scip, file, " <= %.15g", ub);
3091 	
3092 	         SCIPinfoMessage(scip, file, "\n");
3093 	      }
3094 	   }
3095 	
3096 	   /* output aggregated variables as 'free' */
3097 	   for (v = 0; v < nAggregatedVars; ++v)
3098 	   {
3099 	      var = aggregatedVars[v];
3100 	      assert( var != NULL );
3101 	      (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3102 	
3103 	      SCIPinfoMessage(scip, file, " %s free\n", varname);
3104 	   }
3105 	
3106 	   /* free space */
3107 	   SCIPfreeBufferArray(scip, &aggregatedVars);
3108 	   SCIPhashtableFree(&varAggregated);
3109 	
3110 	   /* print binaries section */
3111 	   if ( nbinvars > 0 )
3112 	   {
3113 	      SCIPinfoMessage(scip, file, "Binaries\n");
3114 	
3115 	      clearLine(linebuffer, &linecnt);
3116 	
3117 	      for (v = 0; v < nvars; ++v)
3118 	      {
3119 	         var = vars[v];
3120 	         assert( var != NULL );
3121 	
3122 	         if ( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
3123 	         {
3124 	            (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3125 	            (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s", varname);
3126 	            appendLine(scip, file, linebuffer, &linecnt, buffer);
3127 	         }
3128 	      }
3129 	
3130 	      endLine(scip, file, linebuffer, &linecnt);
3131 	   }
3132 	
3133 	   /* print generals section */
3134 	   if ( nintvars > 0 )
3135 	   {
3136 	      SCIPinfoMessage(scip, file, "Generals\n");
3137 	
3138 	      for (v = 0; v < nvars; ++v)
3139 	      {
3140 	         var = vars[v];
3141 	         assert( var != NULL );
3142 	
3143 	         if ( SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER )
3144 	         {
3145 	            (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3146 	            (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s", varname);
3147 	            appendLine(scip, file, linebuffer, &linecnt, buffer);
3148 	         }
3149 	      }
3150 	      endLine(scip, file, linebuffer, &linecnt);
3151 	   }
3152 	
3153 	   /* free space */
3154 	   SCIPfreeBufferArray(scip, &tmpvars);
3155 	   SCIPfreeBufferArray(scip, &consNonlinear);
3156 	   SCIPfreeBufferArray(scip, &consAnd);
3157 	
3158 	   /* end of lp format */
3159 	   SCIPinfoMessage(scip, file, "%s\n", "End");
3160 	
3161 	   *result = SCIP_SUCCESS;
3162 	
3163 	   return SCIP_OKAY;
3164 	}
3165 	
3166 	/*
3167 	 * Callback methods of reader
3168 	 */
3169 	
3170 	/** copy method for reader plugins (called when SCIP copies plugins) */
3171 	static
3172 	SCIP_DECL_READERCOPY(readerCopyPip)
3173 	{  /*lint --e{715}*/
3174 	   assert(scip != NULL);
3175 	   assert(reader != NULL);
3176 	   assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
3177 	
3178 	   /* call inclusion method of reader */
3179 	   SCIP_CALL( SCIPincludeReaderPip(scip) );
3180 	
3181 	   return SCIP_OKAY;
3182 	}
3183 	
3184 	
3185 	/** problem reading method of reader */
3186 	static
3187 	SCIP_DECL_READERREAD(readerReadPip)
3188 	{  /*lint --e{715}*/
3189 	
3190 	   SCIP_CALL( SCIPreadPip(scip, reader, filename, result) );
3191 	
3192 	   return SCIP_OKAY;
3193 	}
3194 	
3195 	
3196 	/** problem writing method of reader */
3197 	static
3198 	SCIP_DECL_READERWRITE(readerWritePip)
3199 	{  /*lint --e{715}*/
3200 	   SCIP_CALL( SCIPwritePip(scip, file, name, transformed, objsense, objscale, objoffset, vars,
3201 	         nvars, nbinvars, nintvars, nimplvars, ncontvars, conss, nconss, result) );
3202 	
3203 	   return SCIP_OKAY;
3204 	}
3205 	
3206 	
3207 	/*
3208 	 * reader specific interface methods
3209 	 */
3210 	
3211 	/** includes the pip file reader in SCIP */
3212 	SCIP_RETCODE SCIPincludeReaderPip(
3213 	   SCIP*                 scip                /**< SCIP data structure */
3214 	   )
3215 	{
3216 	   SCIP_READER* reader;
3217 	
3218 	   /* include reader */
3219 	   SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, NULL) );
3220 	
3221 	   /* set non fundamental callbacks via setter functions */
3222 	   SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyPip) );
3223 	   SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadPip) );
3224 	   SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWritePip) );
3225 	
3226 	   return SCIP_OKAY;
3227 	}
3228 	
3229 	
3230 	/** reads problem from file */
3231 	SCIP_RETCODE SCIPreadPip(
3232 	   SCIP*                 scip,               /**< SCIP data structure */
3233 	   SCIP_READER*          reader,             /**< the file reader itself */
3234 	   const char*           filename,           /**< full path and name of file to read, or NULL if stdin should be used */
3235 	   SCIP_RESULT*          result              /**< pointer to store the result of the file reading call */
3236 	   )
3237 	{  /*lint --e{715}*/
3238 	   PIPINPUT pipinput;
3239 	   SCIP_RETCODE retcode;
3240 	   int i;
3241 	
3242 	   assert(scip != NULL);  /* for lint */
3243 	   assert(reader != NULL);
3244 	
3245 	   /* initialize PIP input data */
3246 	   pipinput.file = NULL;
3247 	   pipinput.linebuf[0] = '\0';
3248 	   pipinput.probname[0] = '\0';
3249 	   pipinput.objname[0] = '\0';
3250 	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, &pipinput.token, PIP_MAX_LINELEN) ); /*lint !e506*/
3251 	   pipinput.token[0] = '\0';
3252 	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, &pipinput.tokenbuf, PIP_MAX_LINELEN) ); /*lint !e506*/
3253 	   pipinput.tokenbuf[0] = '\0';
3254 	   for( i = 0; i < PIP_MAX_PUSHEDTOKENS; ++i )
3255 	   {
3256 	      SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((pipinput.pushedtokens)[i]), PIP_MAX_LINELEN) ); /*lint !e866 !e506*/
3257 	   }
3258 	
3259 	   pipinput.npushedtokens = 0;
3260 	   pipinput.linenumber = 0;
3261 	   pipinput.linepos = 0;
3262 	   pipinput.section = PIP_START;
3263 	   pipinput.objsense = SCIP_OBJSENSE_MINIMIZE;
3264 	   pipinput.haserror = FALSE;
3265 	
3266 	   SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &(pipinput.initialconss)) );
3267 	   SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &(pipinput.dynamicconss)) );
3268 	   SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &(pipinput.dynamiccols)) );
3269 	   SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &(pipinput.dynamicrows)) );
3270 	
3271 	   /* read the file */
3272 	   retcode = readPIPFile(scip, &pipinput, filename);
3273 	
3274 	   /* free dynamically allocated memory */
3275 	   for( i = PIP_MAX_PUSHEDTOKENS - 1; i >= 0 ; --i )
3276 	   {
3277 	      SCIPfreeBlockMemoryArray(scip, &pipinput.pushedtokens[i], PIP_MAX_LINELEN);
3278 	   }
3279 	   SCIPfreeBlockMemoryArray(scip, &pipinput.tokenbuf, PIP_MAX_LINELEN);
3280 	   SCIPfreeBlockMemoryArray(scip, &pipinput.token, PIP_MAX_LINELEN);
3281 	
3282 	   if( retcode == SCIP_PLUGINNOTFOUND )
3283 	      retcode = SCIP_READERROR;
3284 	
3285 	   /* evaluate the result */
3286 	   if( pipinput.haserror )
3287 	      retcode = SCIP_READERROR;
3288 	   else
3289 	   {
3290 	      /* set objective sense */
3291 	      SCIP_CALL( SCIPsetObjsense(scip, pipinput.objsense) );
3292 	      *result = SCIP_SUCCESS;
3293 	   }
3294 	
3295 	   SCIP_CALL( retcode );
3296 	
3297 	   return SCIP_OKAY;
3298 	}
3299