Scippy

SCIP

Solving Constraint Integer Programs

reader_mps.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2014 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file reader_mps.c
17  * @brief (extended) MPS file reader
18  * @author Thorsten Koch
19  * @author Tobias Achterberg
20  * @author Marc Pfetsch
21  * @author Stefan Heinz
22  * @author Stefan Vigerske
23  * @author Michael Winkler
24  *
25  * This reader/writer handles MPS files in extended MPS format, as it
26  * is used by CPLEX. In the extended format the limits on variable
27  * name lengths and coefficients are considerably relaxed. The columns
28  * in the format are then separated by whitespaces.
29  *
30  * @todo Check whether constructing the names for aggregated constraint yields name clashes (aggrXXX).
31  */
32 
33 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
34 
35 #include <assert.h>
36 #include <string.h>
37 #include <ctype.h>
38 
39 #include "scip/reader_mps.h"
40 #include "scip/cons_knapsack.h"
41 #include "scip/cons_indicator.h"
42 #include "scip/cons_linear.h"
43 #include "scip/cons_logicor.h"
44 #include "scip/cons_setppc.h"
45 #include "scip/cons_varbound.h"
46 #include "scip/cons_and.h"
47 #include "scip/cons_sos1.h"
48 #include "scip/cons_sos2.h"
49 #include "scip/cons_quadratic.h"
50 #include "scip/cons_soc.h"
52 #include "scip/pub_misc.h"
53 
54 #define READER_NAME "mpsreader"
55 #define READER_DESC "file reader for MIQPs in IBM's Mathematical Programming System format"
56 #define READER_EXTENSION "mps"
57 
58 #define DEFAULT_LINEARIZE_ANDS TRUE /**< should possible \"and\" constraint be linearized when writing the mps
59  * file? */
60 #define DEFAULT_AGGRLINEARIZATION_ANDS TRUE /**< should an aggregated linearization for and constraints be used? */
61 
62 /*
63  * mps reader internal methods
64  */
65 
66 #define MPS_MAX_LINELEN 1024
67 #define MPS_MAX_NAMELEN 256
68 #define MPS_MAX_VALUELEN 26
69 #define MPS_MAX_FIELDLEN 20
70 
71 #define PATCH_CHAR '_'
72 #define BLANK ' '
73 
74 /** MPS reading data */
75 struct SCIP_ReaderData
76 {
77  SCIP_Bool linearizeands;
78  SCIP_Bool aggrlinearizationands;
79 };
80 
81 /** enum containing all mps sections */
83 {
100 };
101 typedef enum MpsSection MPSSECTION;
102 
103 /** mps input structure */
104 struct MpsInput
105 {
106  MPSSECTION section;
107  SCIP_FILE* fp;
108  int lineno;
109  SCIP_OBJSENSE objsense;
110  SCIP_Bool haserror;
111  char buf[MPS_MAX_LINELEN];
112  const char* f0;
113  const char* f1;
114  const char* f2;
115  const char* f3;
116  const char* f4;
117  const char* f5;
118  char probname[MPS_MAX_NAMELEN];
119  char objname [MPS_MAX_NAMELEN];
120  SCIP_Bool initialconss; /**< should model constraints be marked as initial? */
121  SCIP_Bool dynamicconss; /**< should model constraints be subject to aging? */
122  SCIP_Bool dynamiccols; /**< should columns be added and removed dynamically to the LP? */
123  SCIP_Bool dynamicrows; /**< should rows be added and removed dynamically to the LP? */
124  SCIP_Bool isinteger;
125  SCIP_Bool isnewformat;
126 };
127 typedef struct MpsInput MPSINPUT;
128 
129 /** sparse matrix representation */
130 struct SparseMatrix
131 {
132  SCIP_Real* values; /**< matrix element */
133  SCIP_VAR** columns; /**< corresponding variables */
134  const char** rows; /**< corresponding constraint names */
135  int nentries; /**< number of elements in the arrays */
136  int sentries; /**< number of slots in the arrays */
137 };
138 typedef struct SparseMatrix SPARSEMATRIX;
139 
140 /** creates the mps input structure */
141 static
143  SCIP* scip, /**< SCIP data structure */
144  MPSINPUT** mpsi, /**< mps input structure */
145  SCIP_FILE* fp /**< file object for the input file */
146  )
147 {
148  assert(mpsi != NULL);
149  assert(fp != NULL);
150 
151  SCIP_CALL( SCIPallocMemory(scip, mpsi) );
152 
153  (*mpsi)->section = MPS_NAME;
154  (*mpsi)->fp = fp;
155  (*mpsi)->lineno = 0;
156  (*mpsi)->objsense = SCIP_OBJSENSE_MINIMIZE;
157  (*mpsi)->haserror = FALSE;
158  (*mpsi)->isinteger = FALSE;
159  (*mpsi)->isnewformat = FALSE;
160  (*mpsi)->buf [0] = '\0';
161  (*mpsi)->probname[0] = '\0';
162  (*mpsi)->objname [0] = '\0';
163  (*mpsi)->f0 = NULL;
164  (*mpsi)->f1 = NULL;
165  (*mpsi)->f2 = NULL;
166  (*mpsi)->f3 = NULL;
167  (*mpsi)->f4 = NULL;
168  (*mpsi)->f5 = NULL;
169 
170  SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &((*mpsi)->initialconss)) );
171  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &((*mpsi)->dynamicconss)) );
172  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &((*mpsi)->dynamiccols)) );
173  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &((*mpsi)->dynamicrows)) );
174 
175  return SCIP_OKAY;
176 }
177 
178 /** free the mps input structure */
179 static
181  SCIP* scip, /**< SCIP data structure */
182  MPSINPUT** mpsi /**< mps input structure */
183  )
184 {
185  SCIPfreeMemory(scip, mpsi);
186 }
187 
188 /** returns the current section */
189 static
191  const MPSINPUT* mpsi /**< mps input structure */
192  )
193 {
194  assert(mpsi != NULL);
195 
196  return mpsi->section;
197 }
198 
199 /** return the current value of field 0 */
200 static
201 const char* mpsinputField0(
202  const MPSINPUT* mpsi /**< mps input structure */
203  )
204 {
205  assert(mpsi != NULL);
206 
207  return mpsi->f0;
208 }
209 
210 /** return the current value of field 1 */
211 static
212 const char* mpsinputField1(
213  const MPSINPUT* mpsi /**< mps input structure */
214  )
215 {
216  assert(mpsi != NULL);
217 
218  return mpsi->f1;
219 }
220 
221 /** return the current value of field 2 */
222 static
223 const char* mpsinputField2(
224  const MPSINPUT* mpsi /**< mps input structure */
225  )
226 {
227  assert(mpsi != NULL);
228 
229  return mpsi->f2;
230 }
231 
232 /** return the current value of field 3 */
233 static
234 const char* mpsinputField3(
235  const MPSINPUT* mpsi /**< mps input structure */
236  )
237 {
238  assert(mpsi != NULL);
239 
240  return mpsi->f3;
241 }
242 
243 /** return the current value of field 4 */
244 static
245 const char* mpsinputField4(
246  const MPSINPUT* mpsi /**< mps input structure */
247  )
248 {
249  assert(mpsi != NULL);
250 
251  return mpsi->f4;
252 }
253 
254 /** return the current value of field 5 */
255 static
256 const char* mpsinputField5(
257  const MPSINPUT* mpsi /**< mps input structure */
258  )
259 {
260  assert(mpsi != NULL);
261 
262  return mpsi->f5;
263 }
264 
265 #if 0
266 /** returns the problem name */
267 static
268 const char* mpsinputProbname(
269  const MPSINPUT* mpsi /**< mps input structure */
270  )
271 {
272  assert(mpsi != NULL);
273 
274  return mpsi->probname;
275 }
276 #endif
277 
278 /** returns the objective name */
279 static
280 const char* mpsinputObjname(
281  const MPSINPUT* mpsi /**< mps input structure */
282  )
283 {
284  assert(mpsi != NULL);
285 
286  return mpsi->objname;
287 }
288 
289 /** returns the objective sense */
290 static
292  const MPSINPUT* mpsi /**< mps input structure */
293  )
294 {
295  assert(mpsi != NULL);
296 
297  return mpsi->objsense;
298 }
299 
300 /** returns if an error was detected */
301 static
303  const MPSINPUT* mpsi /**< mps input structure */
304  )
305 {
306  assert(mpsi != NULL);
307 
308  return mpsi->haserror;
309 }
310 
311 /** returns the value of the Bool "is integer" in the mps input */
312 static
314  const MPSINPUT* mpsi /**< mps input structure */
315  )
316 {
317  assert(mpsi != NULL);
318 
319  return mpsi->isinteger;
320 }
321 
322 /** set the section in the mps input structure to given section */
323 static
325  MPSINPUT* mpsi, /**< mps input structure */
326  MPSSECTION section /**< section that is set */
327  )
328 {
329  assert(mpsi != NULL);
330 
331  mpsi->section = section;
332 }
333 
334 /** set the problem name in the mps input structure to given problem name */
335 static
337  MPSINPUT* mpsi, /**< mps input structure */
338  const char* probname /**< name of the problem to set */
339  )
340 {
341  assert(mpsi != NULL);
342  assert(probname != NULL);
343  assert(strlen(probname) < sizeof(mpsi->probname));
344 
345  (void)SCIPmemccpy(mpsi->probname, probname, '\0', MPS_MAX_NAMELEN - 1);
346 }
347 
348 /** set the objective name in the mps input structure to given objective name */
349 static
351  MPSINPUT* mpsi, /**< mps input structure */
352  const char* objname /**< name of the objective function to set */
353  )
354 {
355  assert(mpsi != NULL);
356  assert(objname != NULL);
357  assert(strlen(objname) < sizeof(mpsi->objname));
358 
359  (void)SCIPmemccpy(mpsi->objname, objname, '\0', MPS_MAX_NAMELEN - 1);
360 }
361 
362 /** set the objective sense in the mps input structure to given objective sense */
363 static
365  MPSINPUT* mpsi, /**< mps input structure */
366  SCIP_OBJSENSE sense /**< sense of the objective function */
367  )
368 {
369  assert(mpsi != NULL);
370 
371  mpsi->objsense = sense;
372 }
373 
374 static
376  MPSINPUT* mpsi /**< mps input structure */
377  )
378 {
379  assert(mpsi != NULL);
380 
381  SCIPerrorMessage("Syntax error in line %d\n", mpsi->lineno);
382  mpsi->section = MPS_ENDATA;
383  mpsi->haserror = TRUE;
384 }
385 
386 /** method post a ignore message */
387 static
389  SCIP* scip, /**< SCIP data structure */
390  MPSINPUT* mpsi, /**< mps input structure */
391  const char* what, /**< what get ignored */
392  const char* what_name, /**< name of that object */
393  const char* entity, /**< entity */
394  const char* entity_name, /**< entity name */
395  SCIP_VERBLEVEL verblevel /**< SCIP verblevel for this message */
396  )
397 {
398  assert(mpsi != NULL);
399  assert(what != NULL);
400  assert(what_name != NULL);
401  assert(entity != NULL);
402  assert(entity_name != NULL);
403 
404  SCIPverbMessage(scip, verblevel, NULL,
405  "Warning line %d: %s \"%s\" for %s \"%s\" ignored\n", mpsi->lineno, what, what_name, entity, entity_name);
406 }
407 
408 /** fill the line from \p pos up to column 80 with blanks. */
409 static
411  char* buf, /**< buffer to clear */
412  unsigned int pos /**< position to start the clearing process */
413  )
414 {
415  unsigned int i;
416 
417  for(i = pos; i < 80; i++)
418  buf[i] = BLANK;
419  buf[80] = '\0';
420 }
421 
422 /** change all blanks inside a field to #PATCH_CHAR. */
423 static
425  char* buf, /**< buffer to patch */
426  int beg, /**< position to begin */
427  int end /**< position to end */
428  )
429 {
430  int i;
431 
432  while( (beg <= end) && (buf[end] == BLANK) )
433  end--;
434 
435  while( (beg <= end) && (buf[beg] == BLANK) )
436  beg++;
437 
438  for( i = beg; i <= end; i++ )
439  if( buf[i] == BLANK )
440  buf[i] = PATCH_CHAR;
441 }
442 
443 /** read a mps format data line and parse the fields. */
444 static
446  MPSINPUT* mpsi /**< mps input structure */
447  )
448 {
449  unsigned int len;
450  unsigned int i;
451  int space;
452  char* s;
453  SCIP_Bool is_marker;
454  SCIP_Bool is_empty;
455  char* nexttok;
456 
457  do
458  {
459  mpsi->f0 = mpsi->f1 = mpsi->f2 = mpsi->f3 = mpsi->f4 = mpsi->f5 = 0;
460  is_marker = FALSE;
461 
462  /* Read until we have not a comment line. */
463  do
464  {
465  mpsi->buf[MPS_MAX_LINELEN-1] = '\0';
466  if( NULL == SCIPfgets(mpsi->buf, (int) sizeof(mpsi->buf), mpsi->fp) )
467  return FALSE;
468  mpsi->lineno++;
469  }
470  while( *mpsi->buf == '*' );
471 
472  /* Normalize line */
473  len = (unsigned int) strlen(mpsi->buf);
474 
475  for( i = 0; i < len; i++ )
476  if( (mpsi->buf[i] == '\t') || (mpsi->buf[i] == '\n') || (mpsi->buf[i] == '\r') )
477  mpsi->buf[i] = BLANK;
478 
479  if( len < 80 )
480  clearFrom(mpsi->buf, len);
481 
482  SCIPdebugMessage("line %d: <%s>\n", mpsi->lineno, mpsi->buf);
483 
484  assert(strlen(mpsi->buf) >= 80);
485 
486  /* Look for new section */
487  if( *mpsi->buf != BLANK )
488  {
489  mpsi->f0 = SCIPstrtok(&mpsi->buf[0], " ", &nexttok);
490 
491  assert(mpsi->f0 != 0);
492 
493  mpsi->f1 = SCIPstrtok(NULL, " ", &nexttok);
494 
495  return TRUE;
496  }
497 
498  /* If we decide to use the new format we never revert this decision */
499  if( !mpsi->isnewformat )
500  {
501  /* Test for fixed format comments */
502  if( (mpsi->buf[14] == '$') && (mpsi->buf[13] == ' ') )
503  clearFrom(mpsi->buf, 14);
504  else if( (mpsi->buf[39] == '$') && (mpsi->buf[38] == ' ') )
505  clearFrom(mpsi->buf, 39);
506 
507  /* Test for fixed format */
508  space = mpsi->buf[12] | mpsi->buf[13]
509  | mpsi->buf[22] | mpsi->buf[23]
510  | mpsi->buf[36] | mpsi->buf[37] | mpsi->buf[38]
511  | mpsi->buf[47] | mpsi->buf[48]
512  | mpsi->buf[61] | mpsi->buf[62] | mpsi->buf[63];
513 
514  if( space == BLANK )
515  {
516  /* Now we have space at the right positions.
517  * But are there also the non space where they
518  * should be ?
519  */
520  SCIP_Bool number;
521 
522  number = isdigit((unsigned char)mpsi->buf[24]) || isdigit((unsigned char)mpsi->buf[25])
523  || isdigit((unsigned char)mpsi->buf[26]) || isdigit((unsigned char)mpsi->buf[27])
524  || isdigit((unsigned char)mpsi->buf[28]) || isdigit((unsigned char)mpsi->buf[29])
525  || isdigit((unsigned char)mpsi->buf[30]) || isdigit((unsigned char)mpsi->buf[31])
526  || isdigit((unsigned char)mpsi->buf[32]) || isdigit((unsigned char)mpsi->buf[33])
527  || isdigit((unsigned char)mpsi->buf[34]) || isdigit((unsigned char)mpsi->buf[35]);
528 
529  /* len < 14 is handle ROW lines with embedded spaces
530  * in the names correctly
531  */
532  if( number || len < 14 )
533  {
534  /* We assume fixed format, so we patch possible embedded spaces. */
535  patchField(mpsi->buf, 4, 12);
536  patchField(mpsi->buf, 14, 22);
537  patchField(mpsi->buf, 39, 47);
538  }
539  else
540  {
541  if( mpsi->section == MPS_COLUMNS || mpsi->section == MPS_RHS
542  || mpsi->section == MPS_RANGES || mpsi->section == MPS_BOUNDS )
543  mpsi->isnewformat = TRUE;
544  }
545  }
546  else
547  {
548  mpsi->isnewformat = TRUE;
549  }
550  }
551  s = &mpsi->buf[1];
552 
553  /* At this point it is not clear if we have a indicator field.
554  * If there is none (e.g. empty) f1 will be the first name field.
555  * If there is one, f2 will be the first name field.
556  *
557  * Initially comment marks '$' are only allowed in the beginning
558  * of the 2nd and 3rd name field. We test all fields but the first.
559  * This makes no difference, since if the $ is at the start of a value
560  * field, the line will be erroneous anyway.
561  */
562  do
563  {
564  if( NULL == (mpsi->f1 = SCIPstrtok(s, " ", &nexttok)) )
565  break;
566 
567  if( (NULL == (mpsi->f2 = SCIPstrtok(NULL, " ", &nexttok))) || (*mpsi->f2 == '$') )
568  {
569  mpsi->f2 = 0;
570  break;
571  }
572  if( !strcmp(mpsi->f2, "'MARKER'") )
573  is_marker = TRUE;
574 
575  if( (NULL == (mpsi->f3 = SCIPstrtok(NULL, " ", &nexttok))) || (*mpsi->f3 == '$') )
576  {
577  mpsi->f3 = 0;
578  break;
579  }
580  if( is_marker )
581  {
582  if( !strcmp(mpsi->f3, "'INTORG'") )
583  mpsi->isinteger = TRUE;
584  else if( !strcmp(mpsi->f3, "'INTEND'") )
585  mpsi->isinteger = FALSE;
586  else
587  break; /* unknown marker */
588  }
589  if( !strcmp(mpsi->f3, "'MARKER'") )
590  is_marker = TRUE;
591 
592  if( (NULL == (mpsi->f4 = SCIPstrtok(NULL, " ", &nexttok))) || (*mpsi->f4 == '$') )
593  {
594  mpsi->f4 = 0;
595  break;
596  }
597  if( is_marker )
598  {
599  if( !strcmp(mpsi->f4, "'INTORG'") )
600  mpsi->isinteger = TRUE;
601  else if( !strcmp(mpsi->f4, "'INTEND'") )
602  mpsi->isinteger = FALSE;
603  else
604  break; /* unknown marker */
605  }
606  if( (NULL == (mpsi->f5 = SCIPstrtok(NULL, " ", &nexttok))) || (*mpsi->f5 == '$') )
607  mpsi->f5 = 0;
608  }
609  while( FALSE );
610 
611  /* check for empty lines */
612  is_empty = (mpsi->f0 == NULL && mpsi->f1 == NULL);
613  }
614  while( is_marker || is_empty );
615 
616  return TRUE;
617 }
618 
619 /** Insert \p str as field 4 and shift all other fields up. */
620 static
622  MPSINPUT* mpsi, /**< mps input structure */
623  const char* str /**< str to insert */
624  )
625 {
626  assert(mpsi != NULL);
627  assert(str != NULL);
628 
629  mpsi->f5 = mpsi->f4;
630  mpsi->f4 = str;
631 }
632 
633 /** Insert \p name as field 1 or 2 and shift all other fields up. */
634 static
636  MPSINPUT* mpsi, /**< mps input structure */
637  const char* name, /**< name to insert */
638  SCIP_Bool second /**< insert as second field? */
639  )
640 {
641  assert(mpsi != NULL);
642  assert(name != NULL);
643 
644  mpsi->f5 = mpsi->f4;
645  mpsi->f4 = mpsi->f3;
646  mpsi->f3 = mpsi->f2;
647 
648  if( second )
649  mpsi->f2 = name;
650  else
651  {
652  mpsi->f2 = mpsi->f1;
653  mpsi->f1 = name;
654  }
655 }
656 
657 /** Process NAME section. */
658 static
660  SCIP* scip, /**< SCIP data structure */
661  MPSINPUT* mpsi /**< mps input structure */
662  )
663 {
664  assert(mpsi != NULL);
665 
666  SCIPdebugMessage("read problem name\n");
667 
668  /* This has to be the Line with the NAME section. */
669  if( !mpsinputReadLine(mpsi) || mpsinputField0(mpsi) == NULL || strcmp(mpsinputField0(mpsi), "NAME") )
670  {
671  mpsinputSyntaxerror(mpsi);
672  return SCIP_OKAY;
673  }
674 
675  /* Sometimes the name is omitted. */
676  mpsinputSetProbname(mpsi, (mpsinputField1(mpsi) == 0) ? "_MPS_" : mpsinputField1(mpsi));
677 
678  /* This hat to be a new section */
679  if( !mpsinputReadLine(mpsi) || (mpsinputField0(mpsi) == NULL) )
680  {
681  mpsinputSyntaxerror(mpsi);
682  return SCIP_OKAY;
683  }
684 
685  if( !strncmp(mpsinputField0(mpsi), "ROWS", 4) )
687  else if( !strncmp(mpsinputField0(mpsi), "USERCUTS", 8) )
689  else if( !strncmp(mpsinputField0(mpsi), "LAZYCONS", 8) )
691  else if( !strncmp(mpsinputField0(mpsi), "OBJSEN", 6) )
693  else if( !strncmp(mpsinputField0(mpsi), "OBJNAME", 7) )
695  else
696  {
697  mpsinputSyntaxerror(mpsi);
698  return SCIP_OKAY;
699  }
700 
701  return SCIP_OKAY;
702 }
703 
704 /** Process OBJSEN section. This Section is a CPLEX extension. */
705 static
707  SCIP* scip, /**< SCIP data structure */
708  MPSINPUT* mpsi /**< mps input structure */
709  )
710 {
711  assert(mpsi != NULL);
712 
713  SCIPdebugMessage("read objective sense\n");
714 
715  /* This has to be the Line with MIN or MAX. */
716  if( !mpsinputReadLine(mpsi) || (mpsinputField1(mpsi) == NULL) )
717  {
718  mpsinputSyntaxerror(mpsi);
719  return SCIP_OKAY;
720  }
721 
722  if( !strncmp(mpsinputField1(mpsi), "MIN", 3) )
724  else if( !strncmp(mpsinputField1(mpsi), "MAX", 3) )
726  else
727  {
728  mpsinputSyntaxerror(mpsi);
729  return SCIP_OKAY;
730  }
731 
732  /* Look for ROWS, USERCUTS, LAZYCONS, or OBJNAME Section */
733  if( !mpsinputReadLine(mpsi) || mpsinputField0(mpsi) == NULL )
734  {
735  mpsinputSyntaxerror(mpsi);
736  return SCIP_OKAY;
737  }
738 
739  if( !strcmp(mpsinputField0(mpsi), "ROWS") )
741  else if( !strcmp(mpsinputField0(mpsi), "USERCUTS") )
743  else if( !strcmp(mpsinputField0(mpsi), "LAZYCONS") )
745  else if( !strcmp(mpsinputField0(mpsi), "OBJNAME") )
747  else
748  {
749  mpsinputSyntaxerror(mpsi);
750  return SCIP_OKAY;
751  }
752 
753  return SCIP_OKAY;
754 }
755 
756 /** Process OBJNAME section. This Section is a CPLEX extension. */
757 static
759  SCIP* scip, /**< SCIP data structure */
760  MPSINPUT* mpsi /**< mps input structure */
761  )
762 {
763  assert(mpsi != NULL);
764 
765  SCIPdebugMessage("read objective name\n");
766 
767  /* This has to be the Line with the name. */
768  if( !mpsinputReadLine(mpsi) || mpsinputField1(mpsi) == NULL )
769  {
770  mpsinputSyntaxerror(mpsi);
771  return SCIP_OKAY;
772  }
773 
774  mpsinputSetObjname(mpsi, mpsinputField1(mpsi));
775 
776  /* Look for ROWS, USERCUTS, or LAZYCONS Section */
777  if( !mpsinputReadLine(mpsi) || mpsinputField0(mpsi) == NULL )
778  {
779  mpsinputSyntaxerror(mpsi);
780  return SCIP_OKAY;
781  }
782  if( !strcmp(mpsinputField0(mpsi), "ROWS") )
784  else if( !strcmp(mpsinputField0(mpsi), "USERCUTS") )
786  else if( !strcmp(mpsinputField0(mpsi), "LAZYCONS") )
788  else
789  mpsinputSyntaxerror(mpsi);
790 
791  return SCIP_OKAY;
792 }
793 
794 /** Process ROWS, USERCUTS, or LAZYCONS section. */
795 static
797  MPSINPUT* mpsi, /**< mps input structure */
798  SCIP* scip /**< SCIP data structure */
799  )
800 {
801  SCIPdebugMessage("read rows\n");
802 
803  while( mpsinputReadLine(mpsi) )
804  {
805  if( mpsinputField0(mpsi) != NULL )
806  {
807  if( !strcmp(mpsinputField0(mpsi), "ROWS") )
809  else if( !strcmp(mpsinputField0(mpsi), "USERCUTS") )
811  else if( !strcmp(mpsinputField0(mpsi), "LAZYCONS") )
813  else if( !strcmp(mpsinputField0(mpsi), "COLUMNS") )
815  else
816  mpsinputSyntaxerror(mpsi);
817 
818  return SCIP_OKAY;
819  }
820 
821  if( *mpsinputField1(mpsi) == 'N' )
822  {
823  if( *mpsinputObjname(mpsi) == '\0' )
824  mpsinputSetObjname(mpsi, mpsinputField2(mpsi));
825  else
826  mpsinputEntryIgnored(scip, mpsi, "row", mpsinputField2(mpsi), "objective function", "N", SCIP_VERBLEVEL_NORMAL);
827  }
828  else
829  {
830  SCIP_CONS* cons;
831  SCIP_Bool initial;
832  SCIP_Bool separate;
833  SCIP_Bool enforce;
834  SCIP_Bool check;
835  SCIP_Bool propagate;
836  SCIP_Bool local;
837  SCIP_Bool modifiable;
838  SCIP_Bool dynamic;
839  SCIP_Bool removable;
840 
841  cons = SCIPfindCons(scip, mpsinputField2(mpsi));
842  if( cons != NULL )
843  break;
844 
845  initial = mpsi->initialconss && (mpsinputSection(mpsi) == MPS_ROWS);
846  separate = TRUE;
847  enforce = (mpsinputSection(mpsi) != MPS_USERCUTS);
848  check = (mpsinputSection(mpsi) != MPS_USERCUTS);
849  propagate = TRUE;
850  local = FALSE;
851  modifiable = FALSE;
852  dynamic = mpsi->dynamicconss;
853  removable = mpsi->dynamicrows || (mpsinputSection(mpsi) == MPS_USERCUTS);
854 
855  switch(*mpsinputField1(mpsi))
856  {
857  case 'G' :
858  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, mpsinputField2(mpsi), 0, NULL, NULL, 0.0, SCIPinfinity(scip),
859  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE) );
860  break;
861  case 'E' :
862  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, mpsinputField2(mpsi), 0, NULL, NULL, 0.0, 0.0,
863  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE) );
864  break;
865  case 'L' :
866  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, mpsinputField2(mpsi), 0, NULL, NULL, -SCIPinfinity(scip), 0.0,
867  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE) );
868  break;
869  default :
870  mpsinputSyntaxerror(mpsi);
871  return SCIP_OKAY;
872  }
873  SCIP_CALL( SCIPaddCons(scip, cons) );
874  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
875  }
876  }
877  mpsinputSyntaxerror(mpsi);
878 
879  return SCIP_OKAY;
880 }
881 
882 /** Process COLUMNS section. */
883 static
885  MPSINPUT* mpsi, /**< mps input structure */
886  SCIP* scip /**< SCIP data structure */
887  )
888 {
889  char colname[MPS_MAX_NAMELEN] = { '\0' };
890  SCIP_CONS* cons;
891  SCIP_VAR* var;
892  SCIP_Real val;
893 
894  SCIPdebugMessage("read columns\n");
895 
896  var = NULL;
897  while( mpsinputReadLine(mpsi) )
898  {
899  if( mpsinputField0(mpsi) != 0 )
900  {
901  if( strcmp(mpsinputField0(mpsi), "RHS") )
902  break;
903 
904  /* add the last variable to the problem */
905  if( var != NULL )
906  {
907  SCIP_CALL( SCIPaddVar(scip, var) );
908  SCIP_CALL( SCIPreleaseVar(scip, &var) );
909  }
910  assert(var == NULL);
911 
913  return SCIP_OKAY;
914  }
915  if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
916  break;
917 
918  /* new column? */
919  if( strcmp(colname, mpsinputField1(mpsi)) )
920  {
921  /* add the last variable to the problem */
922  if( var != NULL )
923  {
924  SCIP_CALL( SCIPaddVar(scip, var) );
925  SCIP_CALL( SCIPreleaseVar(scip, &var) );
926  }
927  assert(var == NULL);
928 
929  (void)SCIPmemccpy(colname, mpsinputField1(mpsi), '\0', MPS_MAX_NAMELEN - 1);
930 
931  if( mpsinputIsInteger(mpsi) )
932  {
933  /* for integer variables, default bounds are 0 <= x < 1(not +infinity, like it is for continuous variables), and default cost is 0 */
934  SCIP_CALL( SCIPcreateVar(scip, &var, colname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY,
935  !mpsi->dynamiccols, mpsi->dynamiccols, NULL, NULL, NULL, NULL, NULL) );
936  }
937  else
938  {
939  /* for continuous variables, default bounds are 0 <= x, and default cost is 0 */
940  SCIP_CALL( SCIPcreateVar(scip, &var, colname, 0.0, SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS,
941  !mpsi->dynamiccols, mpsi->dynamiccols, NULL, NULL, NULL, NULL, NULL) );
942  }
943  }
944  assert(var != NULL);
945 
946  val = atof(mpsinputField3(mpsi));
947 
948  if( !strcmp(mpsinputField2(mpsi), mpsinputObjname(mpsi)) )
949  {
950  SCIP_CALL( SCIPchgVarObj(scip, var, val) );
951  }
952  else
953  {
954  cons = SCIPfindCons(scip, mpsinputField2(mpsi));
955  if( cons == NULL )
956  mpsinputEntryIgnored(scip, mpsi, "Column", mpsinputField1(mpsi), "row", mpsinputField2(mpsi), SCIP_VERBLEVEL_FULL);
957  else if( !SCIPisZero(scip, val) )
958  {
959  SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
960  }
961  }
962  if( mpsinputField5(mpsi) != NULL )
963  {
964  assert(mpsinputField4(mpsi) != NULL);
965 
966  val = atof(mpsinputField5(mpsi));
967 
968  if( !strcmp(mpsinputField4(mpsi), mpsinputObjname(mpsi)) )
969  {
970  SCIP_CALL( SCIPchgVarObj(scip, var, val) );
971  }
972  else
973  {
974  cons = SCIPfindCons(scip, mpsinputField4(mpsi));
975  if( cons == NULL )
976  mpsinputEntryIgnored(scip, mpsi, "Column", mpsinputField1(mpsi), "row", mpsinputField4(mpsi), SCIP_VERBLEVEL_FULL);
977  else if( !SCIPisZero(scip, val) )
978  {
979  SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
980  }
981  }
982  }
983  }
984  mpsinputSyntaxerror(mpsi);
985 
986  return SCIP_OKAY;
987 }
988 
989 /** Process RHS section. */
990 static
992  MPSINPUT* mpsi, /**< mps input structure */
993  SCIP* scip /**< SCIP data structure */
994  )
995 {
996  char rhsname[MPS_MAX_NAMELEN] = { '\0' };
997  SCIP_CONS* cons;
998  SCIP_Real lhs;
999  SCIP_Real rhs;
1000  SCIP_Real val;
1001 
1002  SCIPdebugMessage("read right hand sides\n");
1003 
1004  while( mpsinputReadLine(mpsi) )
1005  {
1006  if( mpsinputField0(mpsi) != NULL )
1007  {
1008  if( !strcmp(mpsinputField0(mpsi), "RANGES") )
1010  else if( !strcmp(mpsinputField0(mpsi), "BOUNDS") )
1012  else if( !strcmp(mpsinputField0(mpsi), "SOS") )
1013  mpsinputSetSection(mpsi, MPS_SOS);
1014  else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
1016  else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
1018  else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
1020  else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
1022  else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
1024  else
1025  break;
1026  return SCIP_OKAY;
1027  }
1028  if( (mpsinputField2(mpsi) != NULL && mpsinputField3(mpsi) == NULL)
1029  || (mpsinputField4(mpsi) != NULL && mpsinputField5(mpsi) == NULL) )
1030  {
1031  SCIPwarningMessage(scip, "reading rhs section, a field is missing, assuming that the vector name is the missing one(, row identfier <%s>)\n", mpsinputField2(mpsi));
1032 
1033  mpsinputInsertName(mpsi, "_RHS_", FALSE);
1034  }
1035 
1036  if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
1037  break;
1038 
1039  if( *rhsname == '\0' )
1040  (void)SCIPmemccpy(rhsname, mpsinputField1(mpsi), '\0', MPS_MAX_NAMELEN - 1);
1041 
1042  if( !strcmp(rhsname, mpsinputField1(mpsi)) )
1043  {
1044  cons = SCIPfindCons(scip, mpsinputField2(mpsi));
1045  if( cons == NULL )
1046  mpsinputEntryIgnored(scip, mpsi, "RHS", mpsinputField1(mpsi), "row", mpsinputField2(mpsi), SCIP_VERBLEVEL_NORMAL);
1047  else
1048  {
1049  val = atof(mpsinputField3(mpsi));
1050 
1051  /* find out the row sense */
1052  lhs = SCIPgetLhsLinear(scip, cons);
1053  rhs = SCIPgetRhsLinear(scip, cons);
1054  if( SCIPisInfinity(scip, -lhs) )
1055  {
1056  /* lhs = -infinity -> lower or equal */
1057  assert(SCIPisZero(scip, rhs));
1058  SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) );
1059  }
1060  else if( SCIPisInfinity(scip, rhs) )
1061  {
1062  /* rhs = +infinity -> greater or equal */
1063  assert(SCIPisZero(scip, lhs));
1064  SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) );
1065  }
1066  else
1067  {
1068  /* lhs > -infinity, rhs < infinity -> equality */
1069  assert(SCIPisZero(scip, lhs));
1070  assert(SCIPisZero(scip, rhs));
1071  SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) );
1072  SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) );
1073  }
1074  SCIPdebugMessage("RHS <%s> lhs: %g rhs: %g val: <%22.12g>\n", mpsinputField2(mpsi), lhs, rhs, val);
1075  }
1076  if( mpsinputField5(mpsi) != NULL )
1077  {
1078  cons = SCIPfindCons(scip, mpsinputField4(mpsi));
1079  if( cons == NULL )
1080  mpsinputEntryIgnored(scip, mpsi, "RHS", mpsinputField1(mpsi), "row", mpsinputField4(mpsi), SCIP_VERBLEVEL_NORMAL);
1081  else
1082  {
1083  val = atof(mpsinputField5(mpsi));
1084 
1085  /* find out the row sense */
1086  lhs = SCIPgetLhsLinear(scip, cons);
1087  rhs = SCIPgetRhsLinear(scip, cons);
1088  if( SCIPisInfinity(scip, -lhs) )
1089  {
1090  /* lhs = -infinity -> lower or equal */
1091  assert(SCIPisZero(scip, rhs));
1092  SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) );
1093  }
1094  else if( SCIPisInfinity(scip, rhs) )
1095  {
1096  /* rhs = +infinity -> greater or equal */
1097  assert(SCIPisZero(scip, lhs));
1098  SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) );
1099  }
1100  else
1101  {
1102  /* lhs > -infinity, rhs < infinity -> equality */
1103  assert(SCIPisZero(scip, lhs));
1104  assert(SCIPisZero(scip, rhs));
1105  SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) );
1106  SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) );
1107  }
1108  SCIPdebugMessage("RHS <%s> lhs: %g rhs: %g val: <%22.12g>\n", mpsinputField4(mpsi), lhs, rhs, val);
1109  }
1110  }
1111  }
1112  }
1113  mpsinputSyntaxerror(mpsi);
1114 
1115  return SCIP_OKAY;
1116 }
1117 
1118 /** Process RANGES section */
1119 static
1121  MPSINPUT* mpsi, /**< mps input structure */
1122  SCIP* scip /**< SCIP data structure */
1123  )
1124 {
1125  char rngname[MPS_MAX_NAMELEN] = { '\0' };
1126  SCIP_CONS* cons;
1127  SCIP_Real lhs;
1128  SCIP_Real rhs;
1129  SCIP_Real val;
1130 
1131  SCIPdebugMessage("read ranges\n");
1132 
1133  while( mpsinputReadLine(mpsi) )
1134  {
1135  if( mpsinputField0(mpsi) != NULL )
1136  {
1137  if( !strcmp(mpsinputField0(mpsi), "BOUNDS") )
1139  else if( !strcmp(mpsinputField0(mpsi), "SOS") )
1140  mpsinputSetSection(mpsi, MPS_SOS);
1141  else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
1143  else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
1145  else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
1147  else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
1149  else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
1151  else
1152  break;
1153  return SCIP_OKAY;
1154  }
1155  if( (mpsinputField2(mpsi) != NULL && mpsinputField3(mpsi) == NULL)
1156  || (mpsinputField4(mpsi) != NULL && mpsinputField5(mpsi) == NULL) )
1157  {
1158  SCIPwarningMessage(scip, "reading ranged section, a field is missing, assuming that the vector name is the missing one(, row identfier <%s>)\n", mpsinputField2(mpsi));
1159 
1160  mpsinputInsertName(mpsi, "_RNG_", FALSE);
1161  }
1162 
1163  if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
1164  break;
1165 
1166  if( *rngname == '\0' )
1167  (void)SCIPmemccpy(rngname, mpsinputField1(mpsi), '\0', MPS_MAX_NAMELEN - 1);
1168 
1169  /* The rules are:
1170  * Row Sign LHS RHS
1171  * ----------------------------------------
1172  * G +/- rhs rhs + |range|
1173  * L +/- rhs - |range| rhs
1174  * E + rhs rhs + range
1175  * E - rhs + range rhs
1176  * ----------------------------------------
1177  */
1178  if( !strcmp(rngname, mpsinputField1(mpsi)) )
1179  {
1180  cons = SCIPfindCons(scip, mpsinputField2(mpsi));
1181  if( cons == NULL )
1182  mpsinputEntryIgnored(scip, mpsi, "Range", mpsinputField1(mpsi), "row", mpsinputField2(mpsi), SCIP_VERBLEVEL_NORMAL);
1183  else
1184  {
1185  val = atof(mpsinputField3(mpsi));
1186 
1187  /* find out the row sense */
1188  lhs = SCIPgetLhsLinear(scip, cons);
1189  rhs = SCIPgetRhsLinear(scip, cons);
1190  if( SCIPisInfinity(scip, -lhs) )
1191  {
1192  /* lhs = -infinity -> lower or equal */
1193  SCIP_CALL( SCIPchgLhsLinear(scip, cons, rhs - REALABS(val)) );
1194  }
1195  else if( SCIPisInfinity(scip, rhs) )
1196  {
1197  /* rhs = +infinity -> greater or equal */
1198  SCIP_CALL( SCIPchgRhsLinear(scip, cons, lhs + REALABS(val)) );
1199  }
1200  else
1201  {
1202  /* lhs > -infinity, rhs < infinity -> equality */
1203  assert(SCIPisEQ(scip, lhs, rhs));
1204  if( val >= 0.0 )
1205  {
1206  SCIP_CALL( SCIPchgRhsLinear(scip, cons, rhs + val) );
1207  }
1208  else
1209  {
1210  SCIP_CALL( SCIPchgLhsLinear(scip, cons, lhs + val) );
1211  }
1212  }
1213  }
1214  if( mpsinputField5(mpsi) != NULL )
1215  {
1216  cons = SCIPfindCons(scip, mpsinputField4(mpsi));
1217  if( cons == NULL )
1218  mpsinputEntryIgnored(scip, mpsi, "Range", mpsinputField1(mpsi), "row", mpsinputField4(mpsi), SCIP_VERBLEVEL_NORMAL);
1219  else
1220  {
1221  val = atof(mpsinputField5(mpsi));
1222 
1223  /* find out the row sense */
1224  lhs = SCIPgetLhsLinear(scip, cons);
1225  rhs = SCIPgetRhsLinear(scip, cons);
1226  if( SCIPisInfinity(scip, -lhs) )
1227  {
1228  /* lhs = -infinity -> lower or equal */
1229  SCIP_CALL( SCIPchgLhsLinear(scip, cons, rhs - REALABS(val)) );
1230  }
1231  else if( SCIPisInfinity(scip, rhs) )
1232  {
1233  /* rhs = +infinity -> greater or equal */
1234  SCIP_CALL( SCIPchgRhsLinear(scip, cons, lhs + REALABS(val)) );
1235  }
1236  else
1237  {
1238  /* lhs > -infinity, rhs < infinity -> equality */
1239  assert(SCIPisEQ(scip, lhs, rhs));
1240  if( val >= 0.0 )
1241  {
1242  SCIP_CALL( SCIPchgRhsLinear(scip, cons, rhs + val) );
1243  }
1244  else
1245  {
1246  SCIP_CALL( SCIPchgLhsLinear(scip, cons, lhs + val) );
1247  }
1248  }
1249  }
1250  }
1251  }
1252  }
1253  mpsinputSyntaxerror(mpsi);
1254 
1255  return SCIP_OKAY;
1256 }
1257 
1258 /** Process BOUNDS section. */
1259 static
1261  MPSINPUT* mpsi, /**< mps input structure */
1262  SCIP* scip /**< SCIP data structure */
1263  )
1264 {
1265  char bndname[MPS_MAX_NAMELEN] = { '\0' };
1266  SCIP_VAR* var;
1267  SCIP_Real val;
1268  SCIP_Bool shifted;
1269 
1270  SCIP_VAR** semicont;
1271  int nsemicont;
1272  int semicontsize;
1273 
1274  semicont = NULL;
1275  nsemicont = 0;
1276  semicontsize = 0;
1277 
1278  SCIPdebugMessage("read bounds\n");
1279 
1280  while( mpsinputReadLine(mpsi) )
1281  {
1282  if( mpsinputField0(mpsi) != 0 )
1283  {
1284  if( !strcmp(mpsinputField0(mpsi), "SOS") )
1285  mpsinputSetSection(mpsi, MPS_SOS);
1286  else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
1288  else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
1290  else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
1292  else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
1294  else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
1296  else
1297  break;
1298  goto READBOUNDS_FINISH;
1299  }
1300 
1301  shifted = FALSE;
1302 
1303  /* Is the value field used ? */
1304  if( !strcmp(mpsinputField1(mpsi), "LO") /* lower bound given in field 4 */
1305  || !strcmp(mpsinputField1(mpsi), "UP") /* upper bound given in field 4 */
1306  || !strcmp(mpsinputField1(mpsi), "FX") /* fixed value given in field 4 */
1307  || !strcmp(mpsinputField1(mpsi), "LI") /* CPLEX extension: lower bound of integer variable given in field 4 */
1308  || !strcmp(mpsinputField1(mpsi), "UI") /* CPLEX extension: upper bound of integer variable given in field 4 */
1309  || !strcmp(mpsinputField1(mpsi), "SC") )/* CPLEX extension: semi continuous variable, upper bound given in field 4 */
1310  {
1311  if( mpsinputField3(mpsi) != NULL && mpsinputField4(mpsi) == NULL )
1312  {
1313  int l;
1314 
1315  /* check what might be missing, if field 3 is a number the bound name might be missing */
1316  for( l = (int) strlen(mpsinputField3(mpsi)) - 1; l >= 0; --l )
1317  {
1318  if( mpsinputField3(mpsi)[l] != '.' && !isdigit(mpsinputField3(mpsi)[l]) )
1319  break;
1320  }
1321 
1322  /* the bound name?! is missing */
1323  if( l < 0 )
1324  {
1325  SCIPwarningMessage(scip, "in bound section a name for value <%s> might be missing\n", mpsinputField3(mpsi));
1326 
1327  mpsinputInsertName(mpsi, "_BND_", TRUE);
1328  shifted = TRUE;
1329  }
1330  /* the bound is be missing */
1331  else
1332  {
1333  SCIPwarningMessage(scip, "in bound section a value for column <%s> is missing, assuming 0.0\n", mpsinputField3(mpsi));
1334 
1335  mpsinputInsertField4(mpsi, "0.0");
1336  shifted = TRUE;
1337  }
1338  }
1339  }
1340  else if( !strcmp(mpsinputField1(mpsi), "FR") /* free variable */
1341  || !strcmp(mpsinputField1(mpsi), "MI") /* lower bound is minus infinity */
1342  || !strcmp(mpsinputField1(mpsi), "PL") /* upper bound is plus infinity */
1343  || !strcmp(mpsinputField1(mpsi), "BV") ) /* CPLEX extension: binary variable */
1344  {
1345  if( mpsinputField2(mpsi) != NULL && mpsinputField3(mpsi) == NULL )
1346  {
1347  SCIPwarningMessage(scip, "in bound section a name for a column is missing\n");
1348 
1349  mpsinputInsertName(mpsi, "_BND_", TRUE);
1350  shifted = TRUE;
1351  }
1352  }
1353  else
1354  {
1355  mpsinputSyntaxerror(mpsi);
1356  return SCIP_OKAY;
1357  }
1358 
1359  if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
1360  break;
1361 
1362  if( *bndname == '\0' )
1363  (void)SCIPmemccpy(bndname, mpsinputField2(mpsi), '\0', MPS_MAX_NAMELEN - 1);
1364 
1365  /* Only read the first Bound in section */
1366  if( !strcmp(bndname, mpsinputField2(mpsi)) )
1367  {
1368  SCIP_VARTYPE oldvartype;
1369  SCIP_Bool infeasible;
1370 
1371  var = SCIPfindVar(scip, mpsinputField3(mpsi));
1372  /* if variable did not appear in columns section before, then it may still come in later sections (QCMATRIX, QMATRIX, SOS, ...)
1373  * thus add it as continuous variables, which has default bounds 0.0 <= x, and default cost 0.0 */
1374  if( var == NULL )
1375  {
1376  SCIP_VAR* varcpy;
1377 
1378  SCIP_CALL( SCIPcreateVar(scip, &var, mpsinputField3(mpsi), 0.0, SCIPinfinity(scip), 0.0,
1379  SCIP_VARTYPE_CONTINUOUS, !mpsi->dynamiccols, mpsi->dynamiccols, NULL, NULL, NULL, NULL, NULL) );
1380 
1381  SCIP_CALL( SCIPaddVar(scip, var) );
1382  varcpy = var;
1383  SCIP_CALL( SCIPreleaseVar(scip, &varcpy) );
1384  /* mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField3(mpsi), "bound", bndname, SCIP_VERBLEVEL_NORMAL); */
1385  }
1386  assert(var != NULL);
1387 
1388  if( mpsinputField4(mpsi) == NULL )
1389  val = 0.0;
1390  else
1391  val = atof(mpsinputField4(mpsi));
1392 
1393  /* remember variable type */
1394  oldvartype = SCIPvarGetType(var);
1395 
1396  /* if a bound of a binary variable is given, the variable is converted into an integer variable
1397  * with default bounds 0 <= x <= infinity
1398  */
1399  if( oldvartype == SCIP_VARTYPE_BINARY )
1400  {
1401  if( (mpsinputField1(mpsi)[1] == 'I') /* CPLEX extension (Integer Bound) */
1402  || (!(mpsinputField1(mpsi)[0] == 'L' && SCIPisFeasEQ(scip, val, 0.0))
1403  && !(mpsinputField1(mpsi)[0] == 'U' && SCIPisFeasEQ(scip, val, 1.0))) )
1404  {
1405  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) );
1406  assert(!infeasible);
1407 
1408  oldvartype = SCIP_VARTYPE_INTEGER;
1409  SCIP_CALL( SCIPchgVarUb(scip, var, SCIPinfinity(scip)) );
1410  }
1411  }
1412 
1413  /* switch variable type to continuous before applying the bound, this is necessary for stupid non-integral
1414  * bounds on general variables, which even might lead to infeasibility
1415  */
1416  if( oldvartype != SCIP_VARTYPE_CONTINUOUS )
1417  {
1420  /* relaxing variable type */
1421  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_CONTINUOUS, &infeasible) );
1422  }
1423  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
1424 
1425  switch( mpsinputField1(mpsi)[0] )
1426  {
1427  case 'L':
1428  if( !SCIPisZero(scip, SCIPvarGetLbGlobal(var)) && SCIPisLT(scip, val, SCIPvarGetLbGlobal(var)) )
1429  {
1430  SCIPwarningMessage(scip, "Relaxing already defined lower bound %g of variable <%s> to %g not allowed.\n", SCIPvarGetLbGlobal(var), SCIPvarGetName(var), val);
1431  }
1432 
1433  SCIP_CALL( SCIPchgVarLb(scip, var, val) );
1434 
1435  if( mpsinputField1(mpsi)[1] == 'I' ) /* CPLEX extension (Integer Bound) */
1436  {
1437  if( !SCIPisFeasIntegral(scip, val) )
1438  {
1439  SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral lower bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val);
1440  }
1441  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) );
1442  /* don't assert feasibility here because the presolver will and should detect a infeasibility */
1443  }
1444  else if( oldvartype < SCIP_VARTYPE_CONTINUOUS )
1445  {
1446  if( !SCIPisFeasIntegral(scip, val) )
1447  {
1448  SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral lower bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val);
1449  }
1450  }
1451 
1452  break;
1453  case 'U':
1454  if( SCIPisGT(scip, val, SCIPvarGetUbGlobal(var)) )
1455  {
1456  SCIPwarningMessage(scip, "Relaxing already defined upper bound %g of variable <%s> to %g not allowed.\n", SCIPvarGetUbGlobal(var), SCIPvarGetName(var), val);
1457  }
1458 
1459  SCIP_CALL( SCIPchgVarUb(scip, var, val) );
1460  if( mpsinputField1(mpsi)[1] == 'I' ) /* CPLEX extension (Integer Bound) */
1461  {
1462  if( !SCIPisFeasIntegral(scip, val) )
1463  {
1464  SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral upper bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val);
1465  }
1466 
1467  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) );
1468  /* don't assert feasibility here because the presolver will and should detect an infeasibility */
1469  }
1470  else if( oldvartype < SCIP_VARTYPE_CONTINUOUS )
1471  {
1472  if( !SCIPisFeasIntegral(scip, val) )
1473  {
1474  SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral upper bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val);
1475  }
1476  }
1477  break;
1478  case 'S':
1479  assert(mpsinputField1(mpsi)[1] == 'C'); /* CPLEX extension (Semi-Continuous) */
1480  /* remember that variable is semi-continuous */
1481  if( semicontsize <= nsemicont )
1482  {
1483  semicontsize = SCIPcalcMemGrowSize(scip, nsemicont+1);
1484  if( semicont == NULL )
1485  {
1486  SCIP_CALL( SCIPallocBufferArray(scip, &semicont, semicontsize) );
1487  }
1488  else
1489  {
1490  SCIP_CALL( SCIPreallocBufferArray(scip, &semicont, semicontsize) );
1491  }
1492  }
1493  assert(semicont != NULL);
1494  semicont[nsemicont] = var;
1495  ++nsemicont;
1496 
1497  if( SCIPisGT(scip, val, SCIPvarGetUbGlobal(var)) )
1498  {
1499  SCIPwarningMessage(scip, "Relaxing already defined upper bound %g of variable <%s> to %g not allowed.\n", SCIPvarGetUbGlobal(var), SCIPvarGetName(var), val);
1500  }
1501 
1502  SCIP_CALL( SCIPchgVarUb(scip, var, val) );
1503  break;
1504  case 'F':
1505  if( mpsinputField1(mpsi)[1] == 'X' )
1506  {
1507  SCIP_CALL( SCIPchgVarLb(scip, var, val) );
1508  SCIP_CALL( SCIPchgVarUb(scip, var, val) );
1509  }
1510  else
1511  {
1512  SCIP_CALL( SCIPchgVarLb(scip, var, -SCIPinfinity(scip)) );
1513  SCIP_CALL( SCIPchgVarUb(scip, var, +SCIPinfinity(scip)) );
1514  }
1515  break;
1516  case 'M':
1517  SCIP_CALL( SCIPchgVarLb(scip, var, -SCIPinfinity(scip)) );
1518  break;
1519  case 'P':
1520  SCIP_CALL( SCIPchgVarUb(scip, var, +SCIPinfinity(scip)) );
1521  break;
1522  case 'B' : /* CPLEX extension (Binary) */
1523  SCIP_CALL( SCIPchgVarLb(scip, var, 0.0) );
1524  SCIP_CALL( SCIPchgVarUb(scip, var, 1.0) );
1525  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
1526  /* don't assert feasibility here because the presolver will and should detect a infeasibility */
1527  break;
1528  default:
1529  mpsinputSyntaxerror(mpsi);
1530  return SCIP_OKAY;
1531  }
1532 
1533  /* switch variable type back to old type if necessary */
1534  if( oldvartype < SCIPvarGetType(var) )
1535  {
1536  SCIP_CALL( SCIPchgVarType(scip, var, oldvartype, &infeasible) );
1537  }
1538  }
1539  else
1540  {
1541  /* check for syntax error */
1542  assert(*bndname != '\0');
1543  if( strcmp(bndname, mpsinputField3(mpsi)) == 0 && shifted )
1544  {
1545  mpsinputSyntaxerror(mpsi);
1546  return SCIP_OKAY;
1547  }
1548 
1549  mpsinputEntryIgnored(scip, mpsi, "bound", mpsinputField2(mpsi), "variable", mpsinputField3(mpsi), SCIP_VERBLEVEL_NORMAL);
1550  }
1551  }
1552  mpsinputSyntaxerror(mpsi);
1553 
1554 
1555  READBOUNDS_FINISH:
1556  if( nsemicont > 0 )
1557  {
1558  int i;
1559  SCIP_Real oldlb;
1560  char name[SCIP_MAXSTRLEN];
1561  SCIP_CONS* cons;
1562 
1563  SCIP_VAR* vars[2];
1564  SCIP_BOUNDTYPE boundtypes[2];
1565  SCIP_Real bounds[2];
1566 
1567  assert(semicont != NULL);
1568 
1569  /* add bound disjunction constraints for semi-continuous variables */
1570  for( i = 0; i < nsemicont; ++i )
1571  {
1572  var = semicont[i];
1573 
1574  oldlb = SCIPvarGetLbGlobal(var);
1575  /* if no bound was specified (which we assume if we see lower bound 0.0),
1576  * then the default lower bound for a semi-continuous variable is 1.0 */
1577  if( oldlb == 0.0 )
1578  oldlb = 1.0;
1579 
1580  /* change the lower bound to 0.0 */
1581  SCIP_CALL( SCIPchgVarLb(scip, var, 0.0) );
1582 
1583  /* add a bound disjunction constraint to say var <= 0.0 or var >= oldlb */
1584  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "semicont_%s", SCIPvarGetName(var));
1585 
1586  vars[0] = var;
1587  vars[1] = var;
1588  boundtypes[0] = SCIP_BOUNDTYPE_UPPER;
1589  boundtypes[1] = SCIP_BOUNDTYPE_LOWER;
1590  bounds[0] = 0.0;
1591  bounds[1] = oldlb;
1592 
1593  SCIP_CALL( SCIPcreateConsBounddisjunction(scip, &cons, name, 2, vars, boundtypes, bounds,
1594  !mpsi->dynamiccols, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, mpsi->dynamicconss, mpsi->dynamiccols, FALSE) );
1595  SCIP_CALL( SCIPaddCons(scip, cons) );
1596 
1597  SCIPdebugMessage("add bound disjunction constraint for semi-continuity of <%s>:\n\t", SCIPvarGetName(var));
1598  SCIPdebugPrintCons(scip, cons, NULL);
1599 
1600  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1601  }
1602  }
1603 
1604  SCIPfreeBufferArrayNull(scip, &semicont);
1605 
1606  return SCIP_OKAY;
1607 }
1608 
1609 
1610 /** Process SOS section.
1611  *
1612  * We read the SOS section, which is a nonstandard section introduced by CPLEX.
1613  *
1614  * @note Currently we do not support the standard way of specifying SOS constraints via markers.
1615  */
1616 static
1618  MPSINPUT* mpsi, /**< mps input structure */
1619  SCIP* scip /**< SCIP data structure */
1620  )
1621 {
1622  SCIP_Bool initial;
1623  SCIP_Bool separate;
1624  SCIP_Bool enforce;
1625  SCIP_Bool check;
1626  SCIP_Bool propagate;
1627  SCIP_Bool local;
1628  SCIP_Bool modifiable;
1629  SCIP_Bool dynamic;
1630  SCIP_Bool removable;
1631  char name[MPS_MAX_NAMELEN] = { '\0' };
1632  SCIP_CONS* cons = NULL;
1633  int consType = -1;
1634  int cnt = 0;
1635 
1636  SCIPdebugMessage("read SOS constraints\n");
1637 
1638  /* standard settings for SOS constraints: */
1639  initial = mpsi->initialconss;
1640  separate = FALSE;
1641  enforce = TRUE;
1642  check = TRUE;
1643  propagate = TRUE;
1644  local = FALSE;
1645  modifiable = FALSE;
1646  dynamic = mpsi->dynamicconss;
1647  removable = mpsi->dynamicrows;
1648 
1649  /* loop through section */
1650  while( mpsinputReadLine(mpsi) )
1651  {
1652  int type = -1;
1653 
1654  /* check if next section is found */
1655  if( mpsinputField0(mpsi) != NULL )
1656  {
1657  if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
1659  else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
1661  else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
1663  else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
1665  else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
1667  break;
1668  }
1669  if( mpsinputField1(mpsi) == NULL )
1670  {
1671  SCIPerrorMessage("empty data in a non-comment line.\n");
1672  mpsinputSyntaxerror(mpsi);
1673  return SCIP_OKAY;
1674  }
1675 
1676  /* check for new SOS set */
1677  if( strcmp(mpsinputField1(mpsi), "S1") == 0 )
1678  type = 1;
1679  if( strcmp(mpsinputField1(mpsi), "S2") == 0 )
1680  type = 2;
1681 
1682  /* add last constraint and create a new one */
1683  if( type > 0 )
1684  {
1685  assert( type == 1 || type == 2 );
1686  if( cons != NULL )
1687  {
1688  /* add last constraint */
1689  SCIP_CALL( SCIPaddCons(scip, cons) );
1690  SCIPdebugMessage("(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons));
1691  SCIPdebugPrintCons(scip, cons, NULL);
1692  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1693  }
1694 
1695  /* check name */
1696  if( mpsinputField2(mpsi) != NULL )
1697  (void)SCIPmemccpy(name, mpsinputField2(mpsi), '\0', MPS_MAX_NAMELEN - 1);
1698  else
1699  {
1700  /* create new name */
1701  (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "SOS%d", ++cnt);
1702  }
1703 
1704  /* create new SOS constraint */
1705  if( type == 1 )
1706  {
1707  /* we do not know the name of the constraint */
1708  SCIP_CALL( SCIPcreateConsSOS1(scip, &cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate,
1709  local, modifiable, dynamic, removable) );
1710  }
1711  else
1712  {
1713  assert( type == 2 );
1714  SCIP_CALL( SCIPcreateConsSOS2(scip, &cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate,
1715  local, modifiable, dynamic, removable) );
1716  }
1717  consType = type;
1718  SCIPdebugMessage("created constraint <%s> of type %d.\n", name, type);
1719  /* note: we ignore the priorities! */
1720  }
1721  else
1722  {
1723  /* otherwise we are in the section given variables */
1724  SCIP_VAR* var;
1725  SCIP_Real weight;
1726  char* endptr;
1727 
1728  if( consType != 1 && consType != 2 )
1729  {
1730  SCIPerrorMessage("missing SOS type specification.\n");
1731  mpsinputSyntaxerror(mpsi);
1732  return SCIP_OKAY;
1733  }
1734 
1735  /* get variable */
1736  var = SCIPfindVar(scip, mpsinputField1(mpsi));
1737  if( var == NULL )
1738  {
1739  /* ignore unknown variables - we would not know the type anyway */
1740  mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField1(mpsi), "SOS", name, SCIP_VERBLEVEL_NORMAL);
1741  }
1742  else
1743  {
1744  /* get weight */
1745  weight = strtod(mpsinputField2(mpsi), &endptr);
1746  if( endptr == mpsinputField2(mpsi) || *endptr != '\0' )
1747  {
1748  SCIPerrorMessage("weight for variable <%s> not specified.\n", mpsinputField1(mpsi));
1749  mpsinputSyntaxerror(mpsi);
1750  return SCIP_OKAY;
1751  }
1752 
1753  /* add variable and weight */
1754  assert( consType == 1 || consType == 2 );
1755  switch( consType )
1756  {
1757  case 1:
1758  SCIP_CALL( SCIPaddVarSOS1(scip, cons, var, weight) );
1759  break;
1760  case 2:
1761  SCIP_CALL( SCIPaddVarSOS2(scip, cons, var, weight) );
1762  break;
1763  default:
1764  SCIPerrorMessage("unknown SOS type: <%d>\n", type); /* should not happen */
1765  SCIPABORT();
1766  return SCIP_INVALIDDATA; /*lint !e527*/
1767  }
1768  SCIPdebugMessage("added variable <%s> with weight %g.\n", SCIPvarGetName(var), weight);
1769  }
1770  /* check other fields */
1771  if( (mpsinputField3(mpsi) != NULL && *mpsinputField3(mpsi) != '\0' ) ||
1772  (mpsinputField4(mpsi) != NULL && *mpsinputField4(mpsi) != '\0' ) ||
1773  (mpsinputField5(mpsi) != NULL && *mpsinputField5(mpsi) != '\0' ) )
1774  {
1775  SCIPwarningMessage(scip, "ignoring data in fields 3-5 <%s> <%s> <%s>.\n",
1776  mpsinputField3(mpsi), mpsinputField4(mpsi), mpsinputField5(mpsi));
1777  }
1778  }
1779  }
1780 
1781  if( cons != NULL )
1782  {
1783  /* add last constraint */
1784  SCIP_CALL( SCIPaddCons(scip, cons) );
1785  SCIPdebugMessage("(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons));
1786  SCIPdebugPrintCons(scip, cons, NULL);
1787  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1788  }
1789 
1790  return SCIP_OKAY;
1791 }
1792 
1793 
1794 /** Process QMATRIX or QUADOBJ section.
1795  *
1796  * - We read the QMATRIX or QUADOBJ section, which is a nonstandard section introduced by CPLEX.
1797  * - We create a quadratic constraint for this matrix and add a variable to the objective to
1798  * represent the value of the QMATRIX.
1799  * - For a QMATRIX, we expect that both lower and upper diagonal elements are given and every
1800  * coefficient has to be divided by 2.0.
1801  * - For a QUADOBJ, we expect that only the upper diagonal elements are given and thus only
1802  * coefficients on the diagonal have to be divided by 2.0.
1803  */
1804 static
1806  MPSINPUT* mpsi, /**< mps input structure */
1807  SCIP_Bool isQuadObj, /**< whether we actually read a QUADOBJ section */
1808  SCIP* scip /**< SCIP data structure */
1809  )
1810 {
1811  SCIP_VAR** quadvars1;
1812  SCIP_VAR** quadvars2;
1813  SCIP_Real* quadcoefs;
1814  int cnt = 0; /* number of qmatrix elements processed so far */
1815  int size; /* size of quad* arrays */
1816 
1817  SCIPdebugMessage("read %s objective\n", isQuadObj ? "QUADOBJ" : "QMATRIX");
1818 
1819  size = 1;
1820  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars1, size) );
1821  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars2, size) );
1822  SCIP_CALL( SCIPallocBufferArray(scip, &quadcoefs, size) );
1823 
1824  /* loop through section */
1825  while( mpsinputReadLine(mpsi) )
1826  {
1827  /* otherwise we are in the section given variables */
1828  SCIP_VAR* var1;
1829  SCIP_VAR* var2;
1830  SCIP_Real coef;
1831 
1832  /* check if next section is found */
1833  if( mpsinputField0(mpsi) != NULL )
1834  {
1835  if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
1837  else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
1839  else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
1841  break;
1842  }
1843  if( mpsinputField1(mpsi) == NULL && mpsinputField2(mpsi) == NULL )
1844  {
1845  SCIPerrorMessage("empty data in a non-comment line.\n");
1846  mpsinputSyntaxerror(mpsi);
1847  SCIPfreeBufferArray(scip, &quadvars1);
1848  SCIPfreeBufferArray(scip, &quadvars2);
1849  SCIPfreeBufferArray(scip, &quadcoefs);
1850  return SCIP_OKAY;
1851  }
1852 
1853  /* get first variable */
1854  var1 = SCIPfindVar(scip, mpsinputField1(mpsi));
1855  if( var1 == NULL )
1856  {
1857  /* ignore unknown variables - we would not know the type anyway */
1858  mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField1(mpsi), "QMatrix", "QMATRIX", SCIP_VERBLEVEL_NORMAL);
1859  }
1860  else
1861  {
1862  int k;
1863  for( k = 1; k <= 2; ++k )
1864  {
1865  /* get second variable */
1866  var2 = SCIPfindVar(scip, k == 1 ? mpsinputField2(mpsi) : mpsinputField4(mpsi));
1867  if( var2 == NULL )
1868  {
1869  /* ignore unknown variables - we would not know the type anyway */
1870  mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField2(mpsi), "QMatrix", "QMATRIX", SCIP_VERBLEVEL_NORMAL);
1871  }
1872  else
1873  {
1874  const char* field;
1875  char* endptr;
1876 
1877  /* get coefficient */
1878  field = (k == 1 ? mpsinputField3(mpsi) : mpsinputField5(mpsi));
1879  coef = strtod(field, &endptr);
1880  if( endptr == field || *endptr != '\0' )
1881  {
1882  SCIPerrorMessage("coefficient of term <%s>*<%s> not specified.\n", SCIPvarGetName(var1), SCIPvarGetName(var2));
1883  mpsinputSyntaxerror(mpsi);
1884  SCIPfreeBufferArray(scip, &quadvars1);
1885  SCIPfreeBufferArray(scip, &quadvars2);
1886  SCIPfreeBufferArray(scip, &quadcoefs);
1887  return SCIP_OKAY;
1888  }
1889 
1890  /* store variables and coefficient */
1891  if( cnt >= size )
1892  {
1893  int newsize = SCIPcalcMemGrowSize(scip, size+1);
1894  assert(newsize > size);
1895  SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars1, newsize) );
1896  SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars2, newsize) );
1897  SCIP_CALL( SCIPreallocBufferArray(scip, &quadcoefs, newsize) );
1898  size = newsize;
1899  }
1900  assert(cnt < size);
1901  quadvars1[cnt] = var1;
1902  quadvars2[cnt] = var2;
1903  quadcoefs[cnt] = coef;
1904 
1905  /* diagonal elements have to be divided by 2.0
1906  * in a QMATRIX section also off-diagonal have to be divided by 2.0, since both lower and upper diagonal elements are given
1907  */
1908  if( var1 == var2 || !isQuadObj )
1909  quadcoefs[cnt] /= 2.0;
1910  ++cnt;
1911 
1912  SCIPdebugMessage("stored term %g*<%s>*<%s>.\n", coef, SCIPvarGetName(var1), SCIPvarGetName(var2));
1913  }
1914 
1915  if( mpsinputField4(mpsi) == NULL || *mpsinputField4(mpsi) == '\0' )
1916  break;
1917 
1918  if( mpsinputField5(mpsi) == NULL || *mpsinputField5(mpsi) == '\0' )
1919  {
1920  /* ignore unknown variables - we would not know the type anyway */
1921  mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField4(mpsi), "QMatrix", "QMATRIX", SCIP_VERBLEVEL_NORMAL);
1922  break;
1923  }
1924  }
1925  }
1926  }
1927 
1928  /* add constraint */
1929  if( cnt )
1930  {
1931  SCIP_Bool initial, separate, enforce, check, propagate;
1932  SCIP_Bool local, modifiable, dynamic, removable;
1933  SCIP_CONS* cons = NULL;
1934  SCIP_VAR* qmatrixvar = NULL;
1935  SCIP_Real lhs, rhs;
1936  SCIP_Real minusone = -1.0;
1937 
1938  /* determine settings; note that reading/{initialconss,dynamicconss,dynamicrows,dynamiccols} apply only to model
1939  * constraints and variables, not to an auxiliary objective constraint (otherwise it can happen that an auxiliary
1940  * objective variable is loose with infinite best bound, triggering the problem that an LP that is unbounded
1941  * because of loose variables with infinite best bound cannot be solved)
1942  */
1943  initial = TRUE;
1944  separate = TRUE;
1945  enforce = TRUE;
1946  check = TRUE;
1947  propagate = TRUE;
1948  local = FALSE;
1949  modifiable = FALSE;
1950  dynamic = FALSE;
1951  removable = FALSE;
1952 
1953  SCIP_CALL( SCIPcreateVar(scip, &qmatrixvar, "qmatrixvar", -SCIPinfinity(scip), SCIPinfinity(scip), 1.0,
1955  SCIP_CALL( SCIPaddVar(scip, qmatrixvar) );
1956 
1958  {
1959  lhs = -SCIPinfinity(scip);
1960  rhs = 0.0;
1961  }
1962  else
1963  {
1964  lhs = 0.0;
1965  rhs = SCIPinfinity(scip);
1966  }
1967 
1968  SCIP_CALL( SCIPcreateConsQuadratic(scip, &cons, "qmatrix", 1, &qmatrixvar, &minusone, cnt, quadvars1, quadvars2, quadcoefs, lhs, rhs,
1969  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable) );
1970 
1971  SCIP_CALL( SCIPaddCons(scip, cons) );
1972  SCIPdebugMessage("(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons));
1973  SCIPdebugPrintCons(scip, cons, NULL);
1974 
1975  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1976  SCIP_CALL( SCIPreleaseVar(scip, &qmatrixvar) );
1977  }
1978  else
1979  {
1980  SCIPwarningMessage(scip, "%s section has no entries.\n", isQuadObj ? "QUADOBJ" : "QMATRIX");
1981  }
1982 
1983  SCIPfreeBufferArray(scip, &quadvars1);
1984  SCIPfreeBufferArray(scip, &quadvars2);
1985  SCIPfreeBufferArray(scip, &quadcoefs);
1986 
1987  return SCIP_OKAY;
1988 }
1989 
1990 
1991 /** Process QCMATRIX section.
1992  *
1993  * We read the QCMATRIX section, which is a nonstandard section introduced by CPLEX.
1994  *
1995  * We replace the corresponding linear constraint by a quadratic constraint which contains the
1996  * original linear constraint plus the quadratic part specified in the QCMATRIX.
1997  */
1998 static
2000  MPSINPUT* mpsi, /**< mps input structure */
2001  SCIP* scip /**< SCIP data structure */
2002  )
2003 {
2004  SCIP_CONS* lincons; /* the linear constraint that was added for the corresponding row */
2005  SCIP_VAR** quadvars1;
2006  SCIP_VAR** quadvars2;
2007  SCIP_Real* quadcoefs;
2008  int cnt = 0; /* number of qcmatrix elements processed so far */
2009  int size; /* size of quad* arrays */
2010 
2011  if( mpsinputField1(mpsi) == NULL )
2012  {
2013  SCIPerrorMessage("no row name in QCMATRIX line.\n");
2014  mpsinputSyntaxerror(mpsi);
2015  return SCIP_OKAY;
2016  }
2017 
2018  SCIPdebugMessage("read QCMATRIX section for row <%s>\n", mpsinputField1(mpsi));
2019 
2020  lincons = SCIPfindCons(scip, mpsinputField1(mpsi));
2021  if( lincons == NULL )
2022  {
2023  SCIPerrorMessage("no row under name <%s> processed so far.\n");
2024  mpsinputSyntaxerror(mpsi);
2025  return SCIP_OKAY;
2026  }
2027 
2028  size = 1;
2029  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars1, size) );
2030  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars2, size) );
2031  SCIP_CALL( SCIPallocBufferArray(scip, &quadcoefs, size) );
2032 
2033  /* loop through section */
2034  while( mpsinputReadLine(mpsi) )
2035  {
2036  /* otherwise we are in the section given variables */
2037  SCIP_VAR* var1;
2038  SCIP_VAR* var2;
2039  SCIP_Real coef;
2040 
2041  /* check if next section is found */
2042  if( mpsinputField0(mpsi) != NULL )
2043  {
2044  if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
2046  else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
2048  else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
2050  else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
2052  else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
2054  break;
2055  }
2056  if( mpsinputField1(mpsi) == NULL && mpsinputField2(mpsi) == NULL )
2057  {
2058  SCIPerrorMessage("empty data in a non-comment line.\n");
2059  mpsinputSyntaxerror(mpsi);
2060  SCIPfreeBufferArray(scip, &quadvars1);
2061  SCIPfreeBufferArray(scip, &quadvars2);
2062  SCIPfreeBufferArray(scip, &quadcoefs);
2063  return SCIP_OKAY;
2064  }
2065 
2066  /* get first variable */
2067  var1 = SCIPfindVar(scip, mpsinputField1(mpsi));
2068  if( var1 == NULL )
2069  {
2070  /* ignore unknown variables - we would not know the type anyway */
2071  mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField1(mpsi), "QCMatrix", SCIPconsGetName(lincons), SCIP_VERBLEVEL_NORMAL);
2072  }
2073  else
2074  {
2075  /* get second variable */
2076  var2 = SCIPfindVar(scip, mpsinputField2(mpsi));
2077  if( var2 == NULL )
2078  {
2079  /* ignore unknown variables - we would not know the type anyway */
2080  mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField2(mpsi), "QCMatrix", SCIPconsGetName(lincons), SCIP_VERBLEVEL_NORMAL);
2081  }
2082  else
2083  {
2084  char* endptr;
2085  /* get coefficient */
2086  coef = strtod(mpsinputField3(mpsi), &endptr);
2087  if( endptr == mpsinputField3(mpsi) || *endptr != '\0' )
2088  {
2089  SCIPerrorMessage("coefficient of term <%s>*<%s> not specified.\n", mpsinputField1(mpsi), mpsinputField2(mpsi));
2090  mpsinputSyntaxerror(mpsi);
2091  SCIPfreeBufferArray(scip, &quadvars1);
2092  SCIPfreeBufferArray(scip, &quadvars2);
2093  SCIPfreeBufferArray(scip, &quadcoefs);
2094  return SCIP_OKAY;
2095  }
2096 
2097  /* store variables and coefficient */
2098  if( cnt >= size )
2099  {
2100  int newsize = SCIPcalcMemGrowSize(scip, size+1);
2101  assert(newsize > size);
2102  SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars1, newsize) );
2103  SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars2, newsize) );
2104  SCIP_CALL( SCIPreallocBufferArray(scip, &quadcoefs, newsize) );
2105  size = newsize;
2106  }
2107  assert(cnt < size);
2108  quadvars1[cnt] = var1;
2109  quadvars2[cnt] = var2;
2110  quadcoefs[cnt] = coef;
2111  ++cnt;
2112 
2113  SCIPdebugMessage("stored term %g*<%s>*<%s>.\n", coef, SCIPvarGetName(var1), SCIPvarGetName(var2));
2114 
2115  /* check other fields */
2116  if( (mpsinputField4(mpsi) != NULL && *mpsinputField4(mpsi) != '\0' ) ||
2117  (mpsinputField5(mpsi) != NULL && *mpsinputField5(mpsi) != '\0' ) )
2118  {
2119  SCIPwarningMessage(scip, "ignoring data in fields 4 and 5 <%s> <%s>.\n", mpsinputField4(mpsi), mpsinputField5(mpsi));
2120  }
2121  }
2122  }
2123  }
2124 
2125  /* replace linear constraint by quadratic constraint */
2126  if( cnt )
2127  {
2128  SCIP_CONS* cons = NULL;
2129 
2130  SCIP_CALL( SCIPcreateConsQuadratic(scip, &cons, SCIPconsGetName(lincons),
2131  SCIPgetNVarsLinear(scip, lincons), SCIPgetVarsLinear(scip, lincons), SCIPgetValsLinear(scip, lincons),
2132  cnt, quadvars1, quadvars2, quadcoefs, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons),
2133  SCIPconsIsInitial(lincons), SCIPconsIsSeparated(lincons), SCIPconsIsEnforced(lincons), SCIPconsIsChecked(lincons),
2134  SCIPconsIsPropagated(lincons), SCIPconsIsLocal(lincons), SCIPconsIsModifiable(lincons), SCIPconsIsDynamic(lincons),
2135  SCIPconsIsRemovable(lincons)) );
2136 
2137  SCIP_CALL( SCIPaddCons(scip, cons) );
2138  SCIPdebugMessage("(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons));
2139  SCIPdebugPrintCons(scip, cons, NULL);
2140 
2141  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
2142 
2143  SCIP_CALL( SCIPdelCons(scip, lincons) );
2144  }
2145  else
2146  {
2147  SCIPwarningMessage(scip, "QCMATRIX section has no entries.\n");
2148  }
2149 
2150  SCIPfreeBufferArray(scip, &quadvars1);
2151  SCIPfreeBufferArray(scip, &quadvars2);
2152  SCIPfreeBufferArray(scip, &quadcoefs);
2153 
2154  return SCIP_OKAY;
2155 }
2156 
2157 
2158 /** Process INDICATORS section.
2159  *
2160  * We read the INDICATORS section, which is a nonstandard section introduced by CPLEX.
2161  *
2162  * The section has to come after the QMATRIX* sections.
2163  */
2164 static
2166  MPSINPUT* mpsi, /**< mps input structure */
2167  SCIP* scip /**< SCIP data structure */
2168  )
2169 {
2170  SCIP_Bool initial;
2171  SCIP_Bool separate;
2172  SCIP_Bool enforce;
2173  SCIP_Bool check;
2174  SCIP_Bool propagate;
2175  SCIP_Bool local;
2176  SCIP_Bool dynamic;
2177  SCIP_Bool removable;
2178  SCIP_Bool stickingatnode;
2179  char name[MPS_MAX_NAMELEN] = { '\0' };
2180 
2181  SCIPdebugMessage("read INDICATORS constraints\n");
2182 
2183  /* standard settings for indicator constraints: */
2184  initial = mpsi->initialconss;
2185  separate = TRUE;
2186  enforce = TRUE;
2187  check = TRUE;
2188  propagate = TRUE;
2189  local = FALSE;
2190  dynamic = mpsi->dynamicconss;
2191  removable = mpsi->dynamicrows;
2192  stickingatnode = FALSE;
2193 
2194  /* loop through section */
2195  while( mpsinputReadLine(mpsi) )
2196  {
2197  SCIP_CONSHDLR* conshdlr;
2198  SCIP_VARTYPE slackvartype;
2199  SCIP_CONS* cons;
2200  SCIP_CONS* lincons;
2201  SCIP_VAR* binvar;
2202  SCIP_VAR* slackvar;
2203  SCIP_Real lhs;
2204  SCIP_Real rhs;
2205  SCIP_Real sign;
2206  SCIP_VAR** linvars;
2207  SCIP_Real* linvals;
2208  int nlinvars;
2209  int i;
2210 
2211  /* check if next section is found */
2212  if( mpsinputField0(mpsi) != NULL )
2213  {
2214  if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
2216  break;
2217  }
2218  if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL )
2219  {
2220  SCIPerrorMessage("empty data in a non-comment line.\n");
2221  mpsinputSyntaxerror(mpsi);
2222  return SCIP_OKAY;
2223  }
2224 
2225  /* check for new indicator constraint */
2226  if( strcmp(mpsinputField1(mpsi), "IF") != 0 )
2227  {
2228  SCIPerrorMessage("Indicator constraints need to be introduced by 'IF' in column 1.\n");
2229  mpsinputSyntaxerror(mpsi);
2230  return SCIP_OKAY;
2231  }
2232 
2233  /* get linear constraint (row) */
2234  lincons = SCIPfindCons(scip, mpsinputField2(mpsi));
2235  if( lincons == NULL )
2236  {
2237  SCIPerrorMessage("row <%s> does not exist.\n", mpsinputField2(mpsi));
2238  mpsinputSyntaxerror(mpsi);
2239  return SCIP_OKAY;
2240  }
2241 
2242  /* check whether constraint is really linear */
2243  conshdlr = SCIPconsGetHdlr(lincons);
2244  if( strcmp(SCIPconshdlrGetName(conshdlr), "linear") != 0 )
2245  {
2246  SCIPerrorMessage("constraint <%s> is not linear.\n", mpsinputField2(mpsi));
2247  mpsinputSyntaxerror(mpsi);
2248  return SCIP_OKAY;
2249  }
2250 
2251  /* get binary variable */
2252  binvar = SCIPfindVar(scip, mpsinputField3(mpsi));
2253  if( binvar == NULL )
2254  {
2255  SCIPerrorMessage("binary variable <%s> does not exist.\n", mpsinputField3(mpsi));
2256  mpsinputSyntaxerror(mpsi);
2257  return SCIP_OKAY;
2258  }
2259 
2260  /* check type */
2261  if( SCIPvarGetType(binvar) != SCIP_VARTYPE_BINARY )
2262  {
2263  SCIPerrorMessage("variable <%s> is not binary.\n", mpsinputField3(mpsi));
2264  mpsinputSyntaxerror(mpsi);
2265  return SCIP_OKAY;
2266  }
2267 
2268  /* check whether we need the negated variable */
2269  if( mpsinputField4(mpsi) != NULL )
2270  {
2271  if( *mpsinputField4(mpsi) == '0' )
2272  {
2273  SCIP_VAR* var;
2274  SCIP_CALL( SCIPgetNegatedVar(scip, binvar, &var) );
2275  binvar = var;
2276  assert( binvar != NULL );
2277  }
2278  else
2279  {
2280  if( *mpsinputField4(mpsi) != '1' )
2281  {
2282  SCIPerrorMessage("binary variable <%s> can only take values 0/1 (%s).\n", mpsinputField3(mpsi), mpsinputField4(mpsi));
2283  mpsinputSyntaxerror(mpsi);
2284  return SCIP_OKAY;
2285  }
2286  }
2287  }
2288 
2289  /* check lhs/rhs */
2290  lhs = SCIPgetLhsLinear(scip, lincons);
2291  rhs = SCIPgetRhsLinear(scip, lincons);
2292  nlinvars = SCIPgetNVarsLinear(scip, lincons);
2293  linvars = SCIPgetVarsLinear(scip, lincons);
2294  linvals = SCIPgetValsLinear(scip, lincons);
2295 
2296  sign = -1.0;
2297  if( !SCIPisInfinity(scip, -lhs) )
2298  {
2299  if( SCIPisInfinity(scip, rhs) )
2300  sign = 1.0;
2301  else
2302  {
2303  if( !SCIPisEQ(scip, lhs, rhs) )
2304  {
2305  SCIPerrorMessage("ranged row <%s> is not allowed in indicator constraints.\n", mpsinputField2(mpsi));
2306  mpsinputSyntaxerror(mpsi);
2307  return SCIP_OKAY;
2308  }
2309  else
2310  {
2311  /* create second indicator constraint */
2312  SCIP_VAR** vars;
2313  SCIP_Real* vals;
2314 
2315  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nlinvars) );
2316  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nlinvars) );
2317  for( i = 0; i < nlinvars; ++i )
2318  {
2319  vars[i] = linvars[i];
2320  vals[i] = -linvals[i];
2321  }
2322 
2323  /* create new name */
2324  (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "indlhs_%s", SCIPconsGetName(lincons));
2325 
2326  /* create indicator constraint */
2327  SCIP_CALL( SCIPcreateConsIndicator(scip, &cons, name, binvar, nlinvars, vars, vals, -lhs,
2328  initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
2329  SCIP_CALL( SCIPaddCons(scip, cons) );
2330  SCIPdebugMessage("created indicator constraint <%s>\n", mpsinputField2(mpsi));
2331  SCIPdebugPrintCons(scip, cons, NULL);
2332  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
2333 
2334  SCIPfreeBufferArray(scip, &vals);
2335  SCIPfreeBufferArray(scip, &vars);
2336  }
2337  }
2338  }
2339 
2340  /* check if slack variable can be made implicitly integer */
2341  slackvartype = SCIP_VARTYPE_IMPLINT;
2342  for( i = 0; i < nlinvars; ++i )
2343  {
2344  if( !SCIPvarIsIntegral(linvars[i]) || ! SCIPisIntegral(scip, linvals[i]) )
2345  {
2346  slackvartype = SCIP_VARTYPE_CONTINUOUS;
2347  break;
2348  }
2349  }
2350 
2351  /* create slack variable */
2352  (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "indslack_%s", SCIPconsGetName(lincons));
2353  SCIP_CALL( SCIPcreateVar(scip, &slackvar, name, 0.0, SCIPinfinity(scip), 0.0, slackvartype, TRUE, FALSE,
2354  NULL, NULL, NULL, NULL, NULL) );
2355 
2356  /* add slack variable */
2357  SCIP_CALL( SCIPaddVar(scip, slackvar) );
2358  SCIP_CALL( SCIPaddCoefLinear(scip, lincons, slackvar, sign) );
2359 
2360  /* create new name */
2361  if ( SCIPisEQ(scip, lhs, rhs) )
2362  (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "indrhs_%s", SCIPconsGetName(lincons));
2363  else
2364  (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "ind_%s", SCIPconsGetName(lincons));
2365 
2366  /* create indicator constraint */
2367  SCIP_CALL( SCIPcreateConsIndicatorLinCons(scip, &cons, name, binvar, lincons, slackvar,
2368  initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
2369 
2370  SCIP_CALL( SCIPaddCons(scip, cons) );
2371  SCIPdebugMessage("created indicator constraint <%s>", mpsinputField2(mpsi));
2372  SCIPdebugPrintCons(scip, cons, NULL);
2373  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
2374  }
2375 
2376  return SCIP_OKAY;
2377 }
2378 
2379 
2380 /** Read LP in "MPS File Format".
2381  *
2382  * A specification of the MPS format can be found at
2383  *
2384  * http://plato.asu.edu/ftp/mps_format.txt,
2385  * ftp://ftp.caam.rice.edu/pub/people/bixby/miplib/mps_format,
2386  *
2387  * and in the
2388  *
2389  * CPLEX Reference Manual
2390  *
2391  * This routine should read all valid MPS format files.
2392  * What it will not do, is to find all cases where a file is ill formed.
2393  * If this happens it may complain and read nothing or read "something".
2394  */
2395 static
2397  SCIP* scip, /**< SCIP data structure */
2398  const char* filename /**< name of the input file */
2399  )
2400 {
2401  SCIP_FILE* fp;
2402  MPSINPUT* mpsi;
2403  SCIP_Bool error;
2404 
2405  assert(scip != NULL);
2406  assert(filename != NULL);
2407 
2408  fp = SCIPfopen(filename, "r");
2409  if( fp == NULL )
2410  {
2411  SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
2412  SCIPprintSysError(filename);
2413  return SCIP_NOFILE;
2414  }
2415 
2416  SCIP_CALL( mpsinputCreate(scip, &mpsi, fp) );
2417 
2418  SCIP_CALL( readName(scip, mpsi) );
2419 
2420  SCIP_CALL( SCIPcreateProb(scip, mpsi->probname, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
2421 
2422  if( mpsinputSection(mpsi) == MPS_OBJSEN )
2423  {
2424  SCIP_CALL( readObjsen(scip, mpsi) );
2425  }
2426  if( mpsinputSection(mpsi) == MPS_OBJNAME )
2427  {
2428  SCIP_CALL( readObjname(scip, mpsi) );
2429  }
2430  while( mpsinputSection(mpsi) == MPS_ROWS
2431  || mpsinputSection(mpsi) == MPS_USERCUTS
2432  || mpsinputSection(mpsi) == MPS_LAZYCONS )
2433  {
2434  SCIP_CALL( readRows(mpsi, scip) );
2435  }
2436  if( mpsinputSection(mpsi) == MPS_COLUMNS )
2437  {
2438  SCIP_CALL( readCols(mpsi, scip) );
2439  }
2440  if( mpsinputSection(mpsi) == MPS_RHS )
2441  {
2442  SCIP_CALL( readRhs(mpsi, scip) );
2443  }
2444  if( mpsinputSection(mpsi) == MPS_RANGES )
2445  {
2446  SCIP_CALL( readRanges(mpsi, scip) );
2447  }
2448  if( mpsinputSection(mpsi) == MPS_BOUNDS )
2449  {
2450  SCIP_CALL( readBounds(mpsi, scip) );
2451  }
2452  if( mpsinputSection(mpsi) == MPS_SOS )
2453  {
2454  SCIP_CALL( readSOS(mpsi, scip) );
2455  }
2456  while( mpsinputSection(mpsi) == MPS_QCMATRIX )
2457  {
2458  SCIP_CALL( readQCMatrix(mpsi, scip) );
2459  }
2460  if( mpsinputSection(mpsi) == MPS_QMATRIX )
2461  {
2462  SCIP_CALL( readQMatrix(mpsi, FALSE, scip) );
2463  }
2464  if( mpsinputSection(mpsi) == MPS_QUADOBJ )
2465  {
2466  SCIP_CALL( readQMatrix(mpsi, TRUE, scip) );
2467  }
2468  while( mpsinputSection(mpsi) == MPS_QCMATRIX )
2469  {
2470  SCIP_CALL( readQCMatrix(mpsi, scip) );
2471  }
2472  if( mpsinputSection(mpsi) == MPS_INDICATORS )
2473  {
2474  SCIP_CALL( readIndicators(mpsi, scip) );
2475  }
2476  if( mpsinputSection(mpsi) != MPS_ENDATA )
2477  mpsinputSyntaxerror(mpsi);
2478 
2479  SCIPfclose(fp);
2480 
2481  error = mpsinputHasError(mpsi);
2482 
2483  if( !error )
2484  {
2485  SCIP_CALL( SCIPsetObjsense(scip, mpsinputObjsense(mpsi)) );
2486  }
2487  mpsinputFree(scip, &mpsi);
2488 
2489  if( error )
2490  return SCIP_READERROR;
2491  else
2492  return SCIP_OKAY;
2493 }
2494 
2495 /*
2496  * local methods for writing problem
2497  */
2498 
2499 /** hash key retrieval function for variables */
2500 static
2501 SCIP_DECL_HASHGETKEY(hashGetKeyVar)
2502 { /*lint --e{715}*/
2503  return elem;
2504 }
2505 
2506 /** returns TRUE iff the indices of both variables are equal */
2507 static
2508 SCIP_DECL_HASHKEYEQ(hashKeyEqVar)
2509 { /*lint --e{715}*/
2510  if( key1 == key2 )
2511  return TRUE;
2512  return FALSE;
2513 }
2514 
2515 /** returns the hash value of the key */
2516 static
2517 SCIP_DECL_HASHKEYVAL(hashKeyValVar)
2518 { /*lint --e{715}*/
2519  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
2520  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
2521 }
2522 
2523 
2524 /** computes the field width such that the output file is nicely arranged */
2525 static
2526 unsigned int computeFieldWidth(
2527  unsigned int width /**< required width */
2528  )
2529 {
2530  width = MAX(8u, width);
2531  return MIN(MPS_MAX_FIELDLEN, width);
2532 }
2533 
2534 
2535 /** output two strings in columns 1 and 2 with computed widths */
2536 static
2538  SCIP* scip, /**< SCIP data structure */
2539  FILE* file, /**< output file (or NULL for standard output) */
2540  const char* col1, /**< column 1 */
2541  const char* col2, /**< column 2 */
2542  unsigned int maxnamelen /**< maximum name length */
2543  )
2544 {
2545  unsigned int fieldwidth;
2546  char format[32];
2547 
2548  assert( scip != NULL );
2549  assert( col1 != NULL );
2550  assert( col2 != NULL );
2551  assert( strlen(col1) < MPS_MAX_NAMELEN );
2552  assert( strlen(col2) < MPS_MAX_VALUELEN );
2553  assert( maxnamelen > 0 );
2554 
2555  fieldwidth = computeFieldWidth(maxnamelen);
2556  (void) SCIPsnprintf(format, 32," %%-%ds %%%ds ", fieldwidth, MPS_MAX_VALUELEN - 1);
2557 
2558  SCIPinfoMessage(scip, file, (const char *)format, col1, col2);
2559 }
2560 
2561 /** output two strings in columns 1 (width 2) and 2 (width 8) */
2562 static
2564  SCIP* scip, /**< SCIP data structure */
2565  FILE* file, /**< output file (or NULL for standard output) */
2566  const char* col1, /**< column 1 */
2567  const char* col2, /**< column 2 */
2568  int maxnamelen /**< maximum name length (-1 if irrelevant) */
2569  )
2570 {
2571  unsigned int fieldwidth;
2572  char format[32];
2573 
2574  assert( scip != NULL );
2575  assert( col1 != NULL );
2576  assert( col2 != NULL );
2577  assert( strlen(col1) <= 2 );
2578  assert( strlen(col2) < MPS_MAX_NAMELEN );
2579  assert( maxnamelen == -1 || maxnamelen > 0 );
2580 
2581  if( maxnamelen < 0 )
2582  {
2583  /* format does not matter */
2584  (void) SCIPsnprintf(format, 32, " %%-2.2s %%-s ");
2585  }
2586  else
2587  {
2588  fieldwidth = computeFieldWidth((unsigned int) maxnamelen);
2589  (void) SCIPsnprintf(format, 32, " %%-2.2s %%-%ds ", fieldwidth);
2590  }
2591 
2592  SCIPinfoMessage(scip, file, (const char*)format, col1, col2);
2593 }
2594 
2595 /** prints the given data as column entry */
2596 static
2598  SCIP* scip, /**< SCIP data structure */
2599  FILE* file, /**< output file (or NULL for standard output) */
2600  const char* varname, /**< variable name */
2601  const char* consname, /**< constraint name */
2602  SCIP_Real value, /**< value to display */
2603  int* recordcnt, /**< pointer to store the number of records per line */
2604  unsigned int maxnamelen /**< maximum name length */
2605  )
2606 {
2607  char valuestr[MPS_MAX_VALUELEN] = { '\0' };
2608 
2609  assert( scip != NULL );
2610  assert( recordcnt != NULL );
2611  assert( *recordcnt >= 0 && *recordcnt < 2 );
2612 
2613  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", value);
2614 
2615  if( *recordcnt == 0 )
2616  {
2617  /* start new line with an empty first column and the variable name in the second column */
2618  printStart(scip, file, "", varname, (int) maxnamelen);
2619  *recordcnt = 0;
2620  }
2621 
2622  printRecord(scip, file, consname, valuestr, maxnamelen);
2623  (*recordcnt)++;
2624 
2625  if( *recordcnt == 2 )
2626  {
2627  /* each line can have at most two records */
2628  SCIPinfoMessage(scip, file, "\n");
2629  *recordcnt = 0;
2630  }
2631 }
2632 
2633 /** prints the constraint type to file stream */
2634 static
2636  SCIP* scip, /**< SCIP data structure */
2637  FILE* file, /**< output file (or NULL for standard output) */
2638  SCIP_Real lhs, /**< left hand side */
2639  SCIP_Real rhs, /**< right hand side */
2640  const char* name /**< constraint name */
2641  )
2642 {
2643  char rowtype[2];
2644  assert( scip != NULL );
2645 
2646  assert( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) );
2647  assert( SCIPisGT(scip, rhs, lhs) || SCIPisEQ(scip, lhs, rhs) );
2648  assert( name != NULL );
2649 
2650 
2651  if( SCIPisEQ(scip, lhs, rhs) )
2652  (void) SCIPsnprintf(rowtype, 2, "%s", "E");
2653  else
2654  {
2655  /* in case the right hand side and the left hand side are not infinity we print a
2656  * less or equal constraint and put the right hand side in the RHS section and the
2657  * left hand side (hidden) in the RANGE section */
2658  if( !SCIPisInfinity(scip, rhs) )
2659  (void) SCIPsnprintf(rowtype, 2, "%s", "L");
2660  else
2661  {
2662  assert( !SCIPisInfinity(scip, -lhs) );
2663  (void) SCIPsnprintf(rowtype, 2, "%s", "G");
2664  }
2665  }
2666 
2667  printStart(scip, file, rowtype, name, -1);
2668  SCIPinfoMessage(scip, file, "\n");
2669 }
2670 
2671 
2672 /** initializes the sparse matrix */
2673 static
2675  SCIP* scip, /**< SCIP data structure */
2676  SPARSEMATRIX** matrix, /**< pointer to sparse matrix containing the entries */
2677  int slots /**< number of slots */
2678  )
2679 {
2680  SCIP_CALL( SCIPallocBuffer(scip, matrix) );
2681  (*matrix)->nentries = 0;
2682  (*matrix)->sentries = slots;
2683  SCIP_CALL( SCIPallocBufferArray(scip, &(*matrix)->values, (*matrix)->sentries) );
2684  SCIP_CALL( SCIPallocBufferArray(scip, &(*matrix)->columns, (*matrix)->sentries) );
2685  SCIP_CALL( SCIPallocBufferArray(scip, &(*matrix)->rows, (*matrix)->sentries) );
2686 
2687  return SCIP_OKAY;
2688 }
2689 
2690 /** this method takes care that the required capacity is available in the sparse matrix */
2691 static
2693  SCIP* scip, /**< SCIP data structure */
2694  SPARSEMATRIX* matrix, /**< sparse matrix for storing the coefficient */
2695  int capacity /**< needed capacity */
2696  )
2697 {
2698  if( matrix->nentries + capacity >= matrix->sentries )
2699  {
2700  matrix->sentries = matrix->sentries * 2 + capacity;
2701  SCIP_CALL( SCIPreallocBufferArray(scip, &matrix->values, matrix->sentries) );
2702  SCIP_CALL( SCIPreallocBufferArray(scip, &matrix->columns, matrix->sentries) );
2703  SCIP_CALL( SCIPreallocBufferArray(scip, &matrix->rows, matrix->sentries) );
2704  }
2705  return SCIP_OKAY;
2706 }
2707 
2708 /** frees the sparse matrix */
2709 static
2711  SCIP* scip, /**< SCIP data structure */
2712  SPARSEMATRIX* matrix /**< sparse matrix to free */
2713  )
2714 {
2715  SCIPfreeBufferArray(scip, &matrix->rows);
2716  SCIPfreeBufferArray(scip, &matrix->columns);
2717  SCIPfreeBufferArray(scip, &matrix->values);
2718 
2719  SCIPfreeBuffer(scip, &matrix);
2720 }
2721 
2722 
2723 /** computes the coefficient for the given variables and linear constraint information */
2724 static
2726  SCIP* scip, /**< SCIP data structure */
2727  const char* consname, /**< name of the constraint */
2728  SCIP_VAR** vars, /**< array of variables */
2729  SCIP_Real* vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
2730  int nvars, /**< number of variables */
2731  SCIP_Bool transformed, /**< transformed constraint? */
2732  SPARSEMATRIX* matrix, /**< sparse matrix for storing the coefficient */
2733  SCIP_Real* rhs /**< pointer to right hand side */
2734  )
2735 {
2736  SCIP_VAR** activevars;
2737  SCIP_Real* activevals;
2738  SCIP_Real activeconstant = 0.0;
2739 
2740  int nactivevars;
2741  int requiredsize;
2742  int v;
2743 
2744  assert( scip != NULL );
2745  assert( nvars == 0 || vars != NULL );
2746  assert( !SCIPisInfinity(scip, *rhs) );
2747  assert( matrix != NULL );
2748 
2749  /* if the variables array contains no variables, then return without
2750  * doing any thing; The MPS format and LP format do not forbid this
2751  * situation */
2752  if( nvars == 0 )
2753  return SCIP_OKAY;
2754 
2755  /* duplicate variable and value array */
2756  nactivevars = nvars;
2757  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) );
2758 
2759  if( vals != NULL )
2760  {
2761  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) );
2762  }
2763  else
2764  {
2765  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2766 
2767  for( v = 0; v < nactivevars; ++v )
2768  activevals[v] = 1.0;
2769  }
2770 
2771  /* retransform given variables to active variables */
2772  if( transformed )
2773  {
2774  SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activevals, &nactivevars, nactivevars, &activeconstant, &requiredsize, TRUE) );
2775 
2776  if( requiredsize > nactivevars )
2777  {
2778  SCIP_CALL( SCIPreallocBufferArray(scip, &activevars, requiredsize) );
2779  SCIP_CALL( SCIPreallocBufferArray(scip, &activevals, requiredsize) );
2780 
2781  SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activevals, &nactivevars, requiredsize, &activeconstant, &requiredsize, TRUE) );
2782  assert( requiredsize <= nactivevars );
2783  }
2784  }
2785  else
2786  {
2787  for( v = 0; v < nactivevars; ++v )
2788  {
2789  SCIP_CALL( SCIPvarGetOrigvarSum(&activevars[v], &activevals[v], &activeconstant) );
2790  }
2791  }
2792 
2793  /* copy the (matrix) row into the sparse matrix */
2794  SCIP_CALL( checkSparseMatrixCapacity(scip, matrix, nactivevars) );
2795  assert( matrix->nentries + nactivevars < matrix->sentries );
2796 
2797  for( v = 0; v < nactivevars; ++v )
2798  {
2799  matrix->values[matrix->nentries] = activevals[v];
2800  matrix->columns[matrix->nentries] = activevars[v];
2801  matrix->rows[matrix->nentries] = consname;
2802  matrix->nentries++;
2803  }
2804 
2805  /* adjust right hand side */
2806  (*rhs) -= activeconstant;
2807 
2808  /* free buffer arrays */
2809  SCIPfreeBufferArray(scip, &activevals);
2810  SCIPfreeBufferArray(scip, &activevars);
2811 
2812  return SCIP_OKAY;
2813 }
2814 
2815 
2816 /** check whether given variables are aggregated and put them into an array without duplication */
2817 static
2819  SCIP* scip, /**< SCIP data structure */
2820  SCIP_VAR** vars, /**< variable array */
2821  int nvars, /**< number of active variables in the problem */
2822  SCIP_VAR*** aggvars, /**< pointer to array storing the aggregated variables on output */
2823  int* naggvars, /**< pointer to number of aggregated variables on output */
2824  int* saggvars, /**< pointer to number of slots in aggvars array */
2825  SCIP_HASHTABLE* varAggregated /**< hashtable for checking duplicates */
2826  )
2827 {
2828  int v;
2829 
2830  assert( scip != NULL );
2831  assert( aggvars != NULL );
2832  assert( naggvars != NULL );
2833  assert( saggvars != NULL );
2834 
2835  /* check variables */
2836  for( v = 0; v < nvars; ++v )
2837  {
2838  SCIP_VARSTATUS status;
2839  SCIP_VAR* var;
2840 
2841  var = vars[v];
2842  status = SCIPvarGetStatus(var);
2843 
2844  /* collect aggregated variables in a list */
2845  if( status >= SCIP_VARSTATUS_AGGREGATED )
2846  {
2847  assert( status == SCIP_VARSTATUS_AGGREGATED || status == SCIP_VARSTATUS_MULTAGGR || status == SCIP_VARSTATUS_NEGATED );
2848  assert( varAggregated != NULL );
2849 
2850  if( ! SCIPhashtableExists(varAggregated, (void*) var) )
2851  {
2852  /* possibly enlarge array */
2853  if ( *saggvars <= *naggvars )
2854  {
2855  int newsize;
2856  newsize = SCIPcalcMemGrowSize(scip, *naggvars + 1);
2857  assert( newsize > *saggvars );
2858  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &aggvars, *saggvars, newsize) );
2859  *saggvars = newsize;
2860  }
2861 
2862  (*aggvars)[*naggvars] = var;
2863  (*naggvars)++;
2864  SCIP_CALL( SCIPhashtableInsert(varAggregated, (void*) var) );
2865  assert( *naggvars <= *saggvars );
2866  }
2867  }
2868  }
2869  return SCIP_OKAY;
2870 }
2871 
2872 
2873 /** method check if the variable names are not longer than MPS_MAX_NAMELEN - 1*/
2874 static
2876  SCIP* scip, /**< SCIP data structure */
2877  SCIP_VAR** vars, /**< array of variables */
2878  int nvars, /**< number of variables */
2879  unsigned int* maxnamelen, /**< pointer to store the maximum name length */
2880  const char*** varnames, /**< pointer to array of variable names */
2881  SCIP_HASHMAP** varnameHashmap /**< pointer to hash map storing variable, variable name mapping */
2882  )
2883 {
2884  int v;
2885  int faulty;
2886  char* varname;
2887  SCIP_VAR* var;
2888 
2889  assert( scip != NULL );
2890  assert( vars != NULL );
2891  assert( maxnamelen != NULL );
2892 
2893  faulty = 0;
2894 
2895  /* allocate memory */
2896  SCIP_CALL( SCIPhashmapCreate(varnameHashmap, SCIPblkmem(scip), SCIPcalcHashtableSize(5 * nvars)) );
2897  SCIP_CALL( SCIPallocBufferArray(scip, varnames, nvars) );
2898 
2899  /* check if the variable names are not to long */
2900  for( v = 0; v < nvars; ++v )
2901  {
2902  size_t l;
2903 
2904  var = vars[v];
2905  assert( var != NULL );
2906 
2907  l = strlen(SCIPvarGetName(var));
2908 
2909  if( l >= MPS_MAX_NAMELEN )
2910  {
2911  faulty++;
2912  (*maxnamelen) = MPS_MAX_NAMELEN - 1;
2913  }
2914  else
2915  {
2916  (*maxnamelen) = MAX(*maxnamelen, (unsigned int) l);
2917  }
2918 
2919  SCIP_CALL( SCIPallocBufferArray(scip, &varname, (int) *maxnamelen + 1) );
2920  (void) SCIPsnprintf(varname, (int)(*maxnamelen) + 1, "%s", SCIPvarGetName(var) );
2921 
2922  /* insert variable with variable name into hash map */
2923  assert( !SCIPhashmapExists(*varnameHashmap, var) );
2924  SCIP_CALL( SCIPhashmapInsert(*varnameHashmap, var, (void*) (size_t) varname) );
2925 
2926  (*varnames)[v] = varname;
2927  }
2928 
2929  if( faulty > 0 )
2930  {
2931  SCIPwarningMessage(scip, "there are %d variable names which have to be cut down to %d characters; LP might be corrupted\n",
2932  faulty, MPS_MAX_NAMELEN - 1);
2933  }
2934  return SCIP_OKAY;
2935 }
2936 
2937 /** method check if the constraint names are not longer than MPS_MAX_NAMELEN - 1 */
2938 static
2940  SCIP* scip, /**< SCIP data structure */
2941  SCIP_CONS** conss, /**< array of all constraints */
2942  int nconss, /**< number of all constraints */
2943  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
2944  unsigned int* maxnamelen, /**< pointer to store the maximum name length */
2945  const char*** consnames, /**< pointer to array of constraint names */
2946  SCIP_Bool* error /**< pointer to store whether all constraint names exist */
2947  )
2948 {
2949  SCIP_CONS* cons;
2950  char* consname;
2951  int faulty;
2952  int i;
2953 
2954  assert(scip != NULL);
2955  assert(maxnamelen != NULL);
2956 
2957  faulty = 0;
2958  *error = FALSE;
2959 
2960  /* allocate memory */
2961  SCIP_CALL( SCIPallocBufferArray(scip, consnames, nconss) );
2962 
2963  for( i = 0; i < nconss; ++i )
2964  {
2965  size_t l;
2966 
2967  cons = conss[i];
2968  assert( cons != NULL );
2969 
2970  /* in case the transformed problem is written, only constraints are posted which are enabled in the current node */
2971  assert(!transformed || SCIPconsIsEnabled(cons));
2972 
2973  l = strlen(SCIPconsGetName(cons));
2974 
2975  if( l >= MPS_MAX_NAMELEN )
2976  {
2977  faulty++;
2978  l = MPS_MAX_NAMELEN - 1;
2979  }
2980 
2981  if( l == 0 )
2982  {
2983  SCIPwarningMessage(scip, "At least one name of a constraint is empty, so file will be written with generic names.\n");
2984 
2985  --i; /*lint !e445*/
2986  for( ; i >= 0; --i) /*lint !e445*/
2987  {
2988  SCIPfreeBufferArray(scip, &((*consnames)[i]));
2989  }
2990  SCIPfreeBufferArray(scip, consnames);
2991 
2992  *error = TRUE;
2993 
2994  return SCIP_OKAY;
2995  }
2996 
2997  (*maxnamelen) = MAX(*maxnamelen, (unsigned int) l);
2998 
2999  SCIP_CALL( SCIPallocBufferArray(scip, &consname, (int) l + 1) );
3000  (void) SCIPsnprintf(consname, (int)l + 1, "%s", SCIPconsGetName(cons) );
3001 
3002  (*consnames)[i] = consname;
3003  }
3004 
3005  if( faulty > 0 )
3006  {
3007  SCIPwarningMessage(scip, "there are %d constraint names which have to be cut down to %d characters; MPS file might be corrupted\n",
3008  faulty, MPS_MAX_NAMELEN - 1);
3009  }
3010 
3011  return SCIP_OKAY;
3012 }
3013 
3014 
3015 /** outputs the COLUMNS section of the MPS format */
3016 static
3018  SCIP* scip, /**< SCIP data structure */
3019  FILE* file, /**< output file, or NULL if standard output should be used */
3020  SPARSEMATRIX* matrix, /**< sparse matrix containing the entries */
3021  SCIP_HASHMAP* varnameHashmap, /**< map from SCIP_VAR* to variable name */
3022  SCIP_HASHTABLE* indicatorSlackHash, /**< hashtable containing slack variables from indicators (or NULL) */
3023  unsigned int maxnamelen /**< maximum name length */
3024  )
3025 {
3026  SCIP_Bool intSection;
3027  SCIP_VAR* var;
3028  const char* varname;
3029  SCIP_Real value;
3030  int v;
3031  int recordcnt;
3032 
3033  /* sort sparse matrix w.r.t. the variable indices */
3034  SCIPsortPtrPtrReal((void**) matrix->columns, (void**) matrix->rows, matrix->values, SCIPvarComp, matrix->nentries);
3035 
3036  /* print COLUMNS section */
3037  SCIPinfoMessage(scip, file, "COLUMNS\n");
3038 
3039  intSection = FALSE;
3040 
3041  for( v = 0; v < matrix->nentries; )
3042  {
3043  var = matrix->columns[v];
3044  assert( var != NULL );
3045 
3046  /* skip slack variables in output */
3047  if( indicatorSlackHash != NULL && SCIPhashtableExists(indicatorSlackHash, var) )
3048  {
3049  ++v;
3050  continue;
3051  }
3052 
3053  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS && intSection )
3054  {
3055  /* end integer section in MPS format */
3056  printStart(scip, file, "", "INTEND", (int) maxnamelen);
3057  printRecord(scip, file, "'MARKER'", "", maxnamelen);
3058  printRecord(scip, file, "'INTEND'", "", maxnamelen);
3059  SCIPinfoMessage(scip, file, "\n", maxnamelen);
3060  intSection = FALSE;
3061  }
3062  else if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !intSection )
3063  {
3064  /* start integer section in MPS format */
3065  printStart(scip, file, "", "INTSTART", (int) maxnamelen);
3066  printRecord(scip, file, "'MARKER'", "", maxnamelen);
3067  printRecord(scip, file, "'INTORG'", "", maxnamelen);
3068  SCIPinfoMessage(scip, file, "\n");
3069  intSection = TRUE;
3070  }
3071 
3072  SCIPdebugMessage("create entries for variable <%s>\n", SCIPvarGetName(var));
3073 
3074  /* record count; there are at most two records per line */
3075  recordcnt = 0;
3076 
3077  /* get variable name */
3078  assert ( SCIPhashmapExists(varnameHashmap, var) );
3079  varname = (const char*) (size_t) SCIPhashmapGetImage(varnameHashmap, var);
3080 
3081  /* output all entries of the same variable */
3082  do
3083  {
3084  value = matrix->values[v];
3085 
3086  /* print record to file */
3087  printEntry( scip, file, varname, matrix->rows[v], value, &recordcnt, maxnamelen );
3088  v++;
3089  }
3090  while( v < matrix->nentries && var == matrix->columns[v] );
3091 
3092  if( recordcnt == 1 )
3093  SCIPinfoMessage(scip, file, "\n");
3094  }
3095  /* end integer section, if the columns sections ends with integer variables */
3096  if( intSection )
3097  {
3098  /* end integer section in MPS format */
3099  printStart(scip, file, "", "INTEND", (int) maxnamelen);
3100  printRecord(scip, file, "'MARKER'", "", maxnamelen);
3101  printRecord(scip, file, "'INTEND'", "", maxnamelen);
3102  SCIPinfoMessage(scip, file, "\n", maxnamelen);
3103  }
3104 }
3105 
3106 
3107 /** outputs the right hand side section */
3108 static
3110  SCIP* scip, /**< SCIP data structure */
3111  FILE* file, /**< output file, or NULL if standard output should be used */
3112  int nconss, /**< number of constraints */
3113  const char** consnames, /**< constraint names */
3114  SCIP_Real* rhss, /**< right hand side array */
3115  unsigned int maxnamelen /**< maximum name length */
3116  )
3117 {
3118  int recordcnt;
3119  int c;
3120 
3121  assert( rhss != NULL );
3122 
3123  SCIPinfoMessage(scip, file, "RHS\n");
3124  SCIPdebugMessage("start printing RHS section\n");
3125 
3126  recordcnt = 0;
3127 
3128  /* take care of the linear constraints */
3129  for( c = 0; c < nconss; ++c )
3130  {
3131  /* skip all constraints which have a right hand side of infinity */
3132  if( SCIPisInfinity(scip, rhss[c]) )
3133  continue;
3134 
3135  assert(consnames[c] != NULL);
3136 
3137  printEntry( scip, file, "RHS", consnames[c], rhss[c], &recordcnt, maxnamelen );
3138  }
3139 
3140  if( recordcnt == 1 )
3141  SCIPinfoMessage(scip, file, "\n");
3142 }
3143 
3144 
3145 /** outputs the range section */
3146 static
3148  SCIP* scip, /**< SCIP data structure */
3149  FILE* file, /**< output file, or NULL if standard output should be used */
3150  SCIP_CONS** conss, /**< constraint array */
3151  int nconss, /**< number of constraints */
3152  const char** consnames, /**< constraint names */
3153  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
3154  unsigned int maxnamelen /**< maximum name length */
3155  )
3156 {
3157  int c;
3158  int recordcnt;
3159 
3160  SCIP_CONSHDLR* conshdlr;
3161  const char* conshdlrname;
3162 
3163  SCIP_CONS* cons;
3164  SCIP_Real lhs;
3165  SCIP_Real rhs;
3166 
3167 
3168  SCIPinfoMessage(scip, file, "RANGES\n");
3169  SCIPdebugMessage("start printing RANGES section\n");
3170 
3171  recordcnt = 0;
3172 
3173  for( c = 0; c < nconss; ++c )
3174  {
3175  cons = conss[c];
3176  assert( cons != NULL);
3177 
3178  /* in case the transformed problems is written only constraint are posted which are enabled in the current node;
3179  * the conss array should only contain relevant constraints
3180  */
3181  assert( !transformed || SCIPconsIsEnabled(cons) );
3182 
3183  assert( consnames[c] != NULL );
3184 
3185  conshdlr = SCIPconsGetHdlr(cons);
3186  assert( conshdlr != NULL );
3187 
3188  conshdlrname = SCIPconshdlrGetName(conshdlr);
3189 
3190  if( strcmp(conshdlrname, "linear") == 0 )
3191  {
3192  lhs = SCIPgetLhsLinear(scip, cons);
3193  rhs = SCIPgetRhsLinear(scip, cons);
3194  }
3195  else if( strcmp(conshdlrname, "varbound") == 0 )
3196  {
3197  lhs = SCIPgetLhsVarbound(scip, cons);
3198  rhs = SCIPgetRhsVarbound(scip, cons);
3199  }
3200  else
3201  continue;
3202 
3203  if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, rhs, lhs) )
3204  {
3205  assert( SCIPisGT(scip, rhs, lhs) );
3206  printEntry( scip, file, "RANGE", consnames[c], rhs - lhs, &recordcnt, maxnamelen );
3207  }
3208  }
3209  if(recordcnt == 1 )
3210  SCIPinfoMessage(scip, file, "\n");
3211 }
3212 
3213 /** print bound section name */
3214 static
3216  SCIP* scip, /**< SCIP data structure */
3217  FILE* file /**< output file, or NULL if standard output should be used */
3218  )
3219 {
3220  SCIPinfoMessage(scip, file, "BOUNDS\n");
3221  SCIPdebugMessage("start printing BOUNDS section\n");
3222 }
3223 
3224 /** output bound section */
3225 static
3227  SCIP* scip, /**< SCIP data structure */
3228  FILE* file, /**< output file, or NULL if standard output should be used */
3229  SCIP_VAR** vars, /**< active variables */
3230  int nvars, /**< number of active variables */
3231  SCIP_VAR** aggvars, /**< needed aggregated variables */
3232  int naggvars, /**< number of aggregated variables */
3233  SCIP_VAR** fixvars, /**< all fixed variables */
3234  int nfixvars, /**< number of fixed variables */
3235  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
3236  const char** varnames, /**< array with variable names */
3237  SCIP_HASHTABLE* indicatorSlackHash, /**< hashtable containing slack variables from indicators (or NULL) */
3238  unsigned int maxnamelen /**< maximum name length */
3239  )
3240 {
3241  int v;
3242  SCIP_VAR* var;
3243  SCIP_Real lb;
3244  SCIP_Real ub;
3245  SCIP_Bool sectionName;
3246  const char* varname;
3247  char valuestr[MPS_MAX_VALUELEN] = { '\0' };
3248 
3249  assert( scip != NULL );
3250  assert( vars != NULL );
3251 
3252  sectionName = FALSE;
3253 
3254  /* output the active variables */
3255  for( v = 0; v < nvars; ++v )
3256  {
3257  var = vars[v];
3258  assert( var != NULL );
3259 
3260  /* skip slack variables in output */
3261  if( indicatorSlackHash != NULL && SCIPhashtableExists(indicatorSlackHash, var) )
3262  continue;
3263 
3264  /* get variable name */
3265  varname = varnames[v];
3266  assert(strncmp(varname, SCIPvarGetName(var), maxnamelen) == 0);
3267 
3268  if( transformed )
3269  {
3270  /* in case the transformed is written only local bounds are posted
3271  * which are valid in the current node */
3272  lb = SCIPvarGetLbLocal(var);
3273  ub = SCIPvarGetUbLocal(var);
3274  }
3275  else
3276  {
3277  lb = SCIPvarGetLbOriginal(var);
3278  ub = SCIPvarGetUbOriginal(var);
3279  }
3280 
3281  /* take care of binary variables */
3282  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
3283  {
3284  if( !sectionName )
3285  {
3286  printBoundSectionName(scip, file);
3287  sectionName = TRUE;
3288  }
3289 
3290  if( !SCIPisFeasZero(scip, lb) || !SCIPisFeasEQ(scip, ub, 1.0) )
3291  {
3292  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb);
3293  printStart(scip, file, "LO", "Bound", (int) maxnamelen);
3294  printRecord(scip, file, varname, valuestr, maxnamelen);
3295  SCIPinfoMessage(scip, file, "\n");
3296 
3297  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", ub);
3298  printStart(scip, file, "UP", "Bound", (int) maxnamelen);
3299  printRecord(scip, file, varname, valuestr, maxnamelen);
3300  }
3301  else
3302  {
3303  printStart(scip, file, "BV", "Bound", (int) maxnamelen);
3304  printRecord(scip, file, varname, "", maxnamelen);
3305  }
3306  SCIPinfoMessage(scip, file, "\n");
3307 
3308  continue;
3309  }
3310 
3311  /* take care of free variables */
3312  if( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) )
3313  {
3314  if( !sectionName )
3315  {
3316  printBoundSectionName(scip, file);
3317  sectionName = TRUE;
3318  }
3319 
3320  /* variable is free */
3321  printStart(scip, file, "FR", "Bound", (int) maxnamelen);
3322  printRecord(scip, file, varname, "", maxnamelen);
3323  SCIPinfoMessage(scip, file, "\n");
3324  continue;
3325  }
3326 
3327  /* take care of fixed variables */
3328  if( SCIPisEQ(scip, lb, ub) )
3329  {
3330  if( !sectionName )
3331  {
3332  printBoundSectionName(scip, file);
3333  sectionName = TRUE;
3334  }
3335 
3336  /* variable is fixed */
3337  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb);
3338  printStart(scip, file, "FX", "Bound", (int) maxnamelen);
3339  printRecord(scip, file, varname, valuestr, maxnamelen);
3340  SCIPinfoMessage(scip, file, "\n");
3341  continue;
3342  }
3343 
3344  /* print lower bound */
3345  if( SCIPisInfinity(scip, -lb) )
3346  {
3347  if( !sectionName )
3348  {
3349  printBoundSectionName(scip, file);
3350  sectionName = TRUE;
3351  }
3352 
3353  /* the free variables are processed above */
3354  assert( !SCIPisInfinity(scip, ub) );
3355  printStart(scip, file, "MI", "Bound", (int) maxnamelen);
3356  printRecord(scip, file, varname, "", maxnamelen);
3357  SCIPinfoMessage(scip, file, "\n");
3358  }
3359  else
3360  {
3361  if( SCIPisZero(scip, lb) )
3362  {
3363  lb = 0.0;
3364  }
3365  else
3366  {
3367  if( !sectionName )
3368  {
3369  printBoundSectionName(scip, file);
3370  sectionName = TRUE;
3371  }
3372 
3373  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb);
3374  printStart(scip, file, "LO", "Bound", (int) maxnamelen);
3375  printRecord(scip, file, varname, valuestr, maxnamelen);
3376  SCIPinfoMessage(scip, file, "\n");
3377  }
3378  }
3379 
3380  /* print upper bound, infinity has to be printed for integer (!) variables, because during
3381  * reading an mps file no upper bound of an integer variable means that the upper bound will
3382  * be set to 1 instead of +infinity (like it is for continuous variables) */
3383  if( SCIPisInfinity(scip, ub) )
3384  {
3385  if( !sectionName )
3386  {
3387  printBoundSectionName(scip, file);
3388  sectionName = TRUE;
3389  }
3390 
3391  /* the free variables are processed above */
3392  assert( !SCIPisInfinity(scip, -lb) );
3393  printStart(scip, file, "PL", "Bound", (int) maxnamelen);
3394  printRecord(scip, file, varname, "", maxnamelen);
3395  SCIPinfoMessage(scip, file, "\n");
3396  }
3397  else
3398  {
3399  if( !sectionName )
3400  {
3401  printBoundSectionName(scip, file);
3402  sectionName = TRUE;
3403  }
3404 
3405  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", ub);
3406  printStart(scip, file, "UP", "Bound", (int) maxnamelen);
3407  printRecord(scip, file, varname, valuestr, maxnamelen);
3408  SCIPinfoMessage(scip, file, "\n");
3409  }
3410  }
3411 
3412  /* output aggregated variables as 'free', except if they are binary */
3413  for( v = 0; v < naggvars; ++v )
3414  {
3415  if( !sectionName )
3416  {
3417  printBoundSectionName(scip, file);
3418  sectionName = TRUE;
3419  }
3420 
3421  var = aggvars[v];
3422  assert( var != NULL );
3423 
3424  /* get variable name */
3425  varname = varnames[nvars + v];
3426  assert(strncmp(varname, SCIPvarGetName(var), maxnamelen) == 0);
3427 
3428  /* take care of binary variables */
3429  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
3430  {
3431  printStart(scip, file, "BV", "Bound", (int) maxnamelen);
3432  printRecord(scip, file, varname, "", maxnamelen);
3433  SCIPinfoMessage(scip, file, "\n");
3434  }
3435  else
3436  {
3437  /* variable is free */
3438  printStart(scip, file, "FR", "Bound", (int) maxnamelen);
3439  printRecord(scip, file, varname, "", maxnamelen);
3440  SCIPinfoMessage(scip, file, "\n");
3441  }
3442  }
3443 
3444  /* output all fixed variables */
3445  for( v = 0; v < nfixvars; ++v )
3446  {
3447  /* we should print the transformed problem, otherwise no fixed variable should exists */
3448  assert(transformed);
3449  assert(fixvars != NULL);
3450 
3451  var = fixvars[v];
3452  assert(var != NULL);
3453  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
3454 
3455  /* get variable name */
3456  varname = varnames[nvars + naggvars + v];
3457  assert(strncmp(varname, SCIPvarGetName(var), maxnamelen) == 0);
3458 
3459  /* only local bounds are posted which are valid in the current node */
3460  lb = SCIPvarGetLbLocal(var);
3461  ub = SCIPvarGetUbLocal(var);
3462  assert(SCIPisEQ(scip, lb, ub));
3463 
3464  if( !sectionName )
3465  {
3466  printBoundSectionName(scip, file);
3467  sectionName = TRUE;
3468  }
3469 
3470  /* print fixed variable */
3471  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb);
3472  printStart(scip, file, "FX", "Bound", (int) maxnamelen);
3473  printRecord(scip, file, varname, valuestr, maxnamelen);
3474  SCIPinfoMessage(scip, file, "\n");
3475  }
3476 }
3477 
3478 
3479 /*
3480  * Callback methods of reader
3481  */
3482 
3483 /** copy method for reader plugins (called when SCIP copies plugins) */
3484 static
3485 SCIP_DECL_READERCOPY(readerCopyMps)
3486 { /*lint --e{715}*/
3487  assert(scip != NULL);
3488  assert(reader != NULL);
3489  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
3490 
3491  /* call inclusion method of reader */
3493 
3494  return SCIP_OKAY;
3495 }
3496 
3497 /** destructor of reader to free user data (called when SCIP is exiting) */
3498 static
3499 SCIP_DECL_READERFREE(readerFreeMps)
3500 {
3501  SCIP_READERDATA* readerdata;
3502 
3503  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
3504  readerdata = SCIPreaderGetData(reader);
3505  assert(readerdata != NULL);
3506  SCIPfreeMemory(scip, &readerdata);
3507 
3508  return SCIP_OKAY;
3509 }
3510 
3511 /** problem reading method of reader */
3512 static
3513 SCIP_DECL_READERREAD(readerReadMps)
3514 { /*lint --e{715}*/
3515  SCIP_RETCODE retcode;
3516 
3517  assert(reader != NULL);
3518  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
3519  assert(scip != NULL);
3520  assert(result != NULL);
3521 
3522  retcode = readMps(scip, filename);
3523 
3524  if( retcode == SCIP_NOFILE || retcode == SCIP_READERROR )
3525  return retcode;
3526 
3527  SCIP_CALL( retcode );
3528 
3529  *result = SCIP_SUCCESS;
3530 
3531  return SCIP_OKAY;
3532 }
3533 
3534 
3535 /** problem writing method of reader */
3536 static
3537 SCIP_DECL_READERWRITE(readerWriteMps)
3538 { /*lint --e{715}*/
3539  SCIP_READERDATA* readerdata;
3540  int naddrows;
3541  int faulty = 0;
3542  int c;
3543  int v;
3544  int k;
3545  char* namestr;
3546 
3547  SCIP_CONS* cons = NULL;
3548  const char* consname;
3549  const char** consnames;
3550 
3551  SCIP_CONSHDLR* conshdlr;
3552  const char* conshdlrname;
3553 
3554  SCIP_Real lhs;
3555  SCIP_Real rhs;
3556  SCIP_Real* rhss;
3557  SCIP_Real value;
3558 
3559  SCIP_VAR* var = NULL;
3560  const char* varname;
3561  const char** varnames;
3562 
3563  char valuestr[MPS_MAX_VALUELEN] = { '\0' };
3564 
3565  SCIP_CONS** consIndicator;
3566  SCIP_CONS** consSOS1;
3567  SCIP_CONS** consSOS2;
3568  SCIP_CONS** consQuadratic;
3569  SCIP_CONS** consSOC;
3570  int nConsIndicator;
3571  int nConsSOS1;
3572  int nConsSOS2;
3573  int nConsQuadratic;
3574  int nConsSOC;
3575 
3576  SCIP_HASHMAP* varnameHashmap; /* hash map from SCIP_VAR* to variable name */
3577  SPARSEMATRIX* matrix;
3578 
3579  SCIP_VAR** aggvars;
3580  int naggvars = 0;
3581  int saggvars;
3582  SCIP_HASHTABLE* varFixedHash;
3583  SCIP_HASHTABLE* indicatorSlackHash;
3584 
3585  SCIP_VAR** fixvars = NULL;
3586  int nfixvars = 0;
3587 
3588  SCIP_VAR** consvars;
3589  int nconsvars;
3590  SCIP_Real* vals;
3591  SCIP_Longint* weights;
3592 
3593  SCIP_Bool needRANGES;
3594  unsigned int maxnamelen;
3595 
3596  SCIP_Bool error;
3597 
3598  assert(reader != NULL);
3599  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
3600  assert(scip != NULL);
3601  assert(result != NULL);
3602 
3603  needRANGES = FALSE;
3604  maxnamelen = 0;
3605  nConsSOS1 = 0;
3606  nConsSOS2 = 0;
3607  nConsQuadratic = 0;
3608  nConsSOC = 0;
3609  nConsIndicator = 0;
3610 
3611  /* check if the constraint names are too long and build the constraint names */
3612  SCIP_CALL( checkConsnames(scip, conss, nconss, transformed, &maxnamelen, &consnames, &error) );
3613  if( error )
3614  {
3615  /* call writing with generic names */
3616  if( transformed )
3617  {
3618  SCIPwarningMessage(scip, "write transformed problem with generic variable and constraint names\n");
3619  SCIP_CALL( SCIPprintTransProblem(scip, file, "mps", TRUE) );
3620  }
3621  else
3622  {
3623  SCIPwarningMessage(scip, "write original problem with generic variable and constraint names\n");
3624  SCIP_CALL( SCIPprintOrigProblem(scip, file, "mps", TRUE) );
3625  }
3626  *result = SCIP_SUCCESS;
3627 
3628  return SCIP_OKAY;
3629  }
3630 
3631  /* check if the variable names are not too long and build the "variable" -> "variable name" hash map */
3632  SCIP_CALL( checkVarnames(scip, vars, nvars, &maxnamelen, &varnames, &varnameHashmap) );
3633 
3634  /* collect SOS, quadratic, and indicator constraints in array for later output */
3635  SCIP_CALL( SCIPallocBufferArray(scip, &consSOS1, nconss) );
3636  SCIP_CALL( SCIPallocBufferArray(scip, &consSOS2, nconss) );
3637  SCIP_CALL( SCIPallocBufferArray(scip, &consQuadratic, nconss) );
3638  SCIP_CALL( SCIPallocBufferArray(scip, &consSOC, nconss) );
3639  SCIP_CALL( SCIPallocBufferArray(scip, &consIndicator, nconss) );
3640 
3641  /* nfixedvars counts all variables with status SCIP_VARSTATUS_FIXED, SCIP_VARSTATUS_AGGREGATED, SCIP_VARSTATUS_MULTAGGR, but not SCIP_VARSTATUS_NEGATED */
3642  saggvars = nfixedvars;
3643  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &aggvars, saggvars) );
3644 
3645  /* create hashtable for storing aggregated variables */
3646  if( nfixedvars > 0 )
3647  {
3648  SCIP_CALL( SCIPhashtableCreate(&varFixedHash, SCIPblkmem(scip), 5 * nfixedvars, hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) );
3649  }
3650  else
3651  varFixedHash = NULL;
3652 
3653  if( nvars > 0 )
3654  {
3655  SCIP_CALL( SCIPhashtableCreate(&indicatorSlackHash, SCIPblkmem(scip), 5 * nvars, hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) );
3656  }
3657  else
3658  indicatorSlackHash = NULL;
3659 
3660  /* initialize sparse matrix */
3661  SCIP_CALL( initializeMatrix(scip, &matrix, (nvars * 2 + nfixedvars)) );
3662  assert( matrix->sentries >= nvars );
3663 
3664  readerdata = SCIPreaderGetData(reader);
3665  assert(readerdata != NULL);
3666 
3667  naddrows = 0;
3668 
3669  /* determine and-constraints and printing format to resize necessary arrays */
3670  if( readerdata->linearizeands )
3671  {
3672  SCIP_CONSHDLR* andconshdlr = SCIPfindConshdlr(scip, "and");
3673 
3674  if( andconshdlr != NULL )
3675  {
3676  /* need to check for and-constraints, note that in the original problem you cannot get the number of
3677  * and-constraints by one call */
3678  for( c = nconss - 1; c >= 0; --c )
3679  {
3680  conshdlr = SCIPconsGetHdlr(conss[c]);
3681  assert(conshdlr != NULL);
3682 
3683  conshdlrname = SCIPconshdlrGetName(conshdlr);
3684 
3685  if( strcmp(conshdlrname, "and") == 0 )
3686  {
3687  if( readerdata->aggrlinearizationands )
3688  ++naddrows;
3689  else
3690  naddrows += SCIPgetNVarsAnd(scip, conss[c]);
3691  }
3692  }
3693  assert(naddrows >= 0);
3694 
3695  if( naddrows > 0 )
3696  {
3697  /* resize consnames vector */
3698  SCIP_CALL( SCIPreallocBufferArray(scip, &consnames, nconss + naddrows) );
3699  }
3700  }
3701  }
3702 
3703  /* initialize rhs vector */
3704  SCIP_CALL( SCIPallocBufferArray(scip, &rhss, nconss + naddrows) );
3705 
3706  /* print statistics as comment to file stream */
3707  SCIPinfoMessage(scip, file, "* SCIP STATISTICS\n");
3708  SCIPinfoMessage(scip, file, "* Problem name : %s\n", name);
3709  SCIPinfoMessage(scip, file, "* Variables : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
3710  nvars, nbinvars, nintvars, nimplvars, ncontvars);
3711  SCIPinfoMessage(scip, file, "* Constraints : %d\n", nconss);
3712  SCIPinfoMessage(scip, file, "* Obj. scale : %.15g\n", objscale);
3713  SCIPinfoMessage(scip, file, "* Obj. offset : %.15g\n", objoffset);
3714 
3715  /* print NAME of the problem */
3716  SCIPinfoMessage(scip, file, "%-14s%s\n", "NAME", name);
3717 
3718  /* start ROWS section */
3719  SCIPinfoMessage(scip, file, "ROWS\n");
3720 
3721  /* print row type for the objective function */
3722  printStart(scip, file, "N", "Obj", -1);
3723  SCIPinfoMessage(scip, file, "\n");
3724 
3725  /* first fill the matrix with the objective coefficients */
3726  for( v = 0; v < nvars; ++v )
3727  {
3728  /* take care of the objective entry */
3729  var = vars[v];
3730  value = SCIPvarGetObj(var);
3731 
3732  /* we also want to add integer variables to the columns section, even if the objective value is 0, because it
3733  * might happen that they only exist in non-linear constraints, which leads to no other line in the column section
3734  * and therefore do not mark the variable as an integer
3735  */
3736  if( !SCIPisZero(scip, value) || SCIPvarGetType(var) < SCIP_VARTYPE_IMPLINT )
3737  {
3738  /* convert maximization problem into minimization since MPS format the objective is to minimize */
3739  if( objsense == SCIP_OBJSENSE_MAXIMIZE )
3740  value *= -1.0;
3741 
3742  assert( matrix->nentries < matrix->sentries );
3743 
3744  matrix->values[matrix->nentries] = value;
3745  matrix->columns[matrix->nentries] = var;
3746  matrix->rows[matrix->nentries] = "Obj";
3747  matrix->nentries++;
3748  }
3749  }
3750 
3751  /* loop over all constraints */
3752  k = nconss;
3753  for( c = 0; c < nconss; ++c )
3754  {
3755  cons = conss[c];
3756  assert( cons != NULL);
3757 
3758  /* in case the transformed problems is written only constraint are posted which are enabled in the current node;
3759  * the conss array should only contain relevant constraints
3760  */
3761  assert( !transformed || SCIPconsIsEnabled(cons) );
3762 
3763  conshdlr = SCIPconsGetHdlr(cons);
3764  assert( conshdlr != NULL );
3765 
3766  conshdlrname = SCIPconshdlrGetName(conshdlr);
3767 
3768  /* construct constraint name */
3769  consname = consnames[c];
3770  assert( 0 == strncmp(consname, SCIPconsGetName(cons), maxnamelen) );
3771 
3772  if( strcmp(conshdlrname, "linear") == 0 )
3773  {
3774  lhs = SCIPgetLhsLinear(scip, cons);
3775  rhs = SCIPgetRhsLinear(scip, cons);
3776 
3777  /* there is nothing to do if the left hand side is minus infinity and the right side is infinity */
3778  if( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) )
3779  {
3780  if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, lhs, rhs) )
3781  needRANGES = TRUE;
3782 
3783  /* print row entry */
3784  printRowType(scip, file, lhs, rhs, consname);
3785 
3786  if( SCIPisInfinity(scip, rhs) )
3787  rhss[c] = lhs;
3788  else
3789  rhss[c] = rhs;
3790 
3791  assert( !SCIPisInfinity(scip, rhss[c]) );
3792 
3793  /* compute column entries */
3794  SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons),
3795  SCIPgetNVarsLinear(scip, cons), transformed, matrix, &rhss[c]) );
3796  }
3797  }
3798  else if( strcmp(conshdlrname, "setppc") == 0 )
3799  {
3800  /* print row entry */
3801  switch( SCIPgetTypeSetppc(scip, cons) )
3802  {
3804  printRowType(scip, file, 1.0, 1.0, consname);
3805  break;
3807  printRowType(scip, file, -SCIPinfinity(scip), 1.0, consname);
3808  break;
3810  printRowType(scip, file, 1.0, SCIPinfinity(scip), consname);
3811  break;
3812  }
3813 
3814  rhss[c] = 1.0;
3815 
3816  /* compute column entries */
3817  SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetVarsSetppc(scip, cons), NULL, SCIPgetNVarsSetppc(scip, cons), transformed, matrix, &rhss[c]) );
3818  }
3819  else if( strcmp(conshdlrname, "logicor") == 0 )
3820  {
3821  /* print row entry */
3822  printRowType(scip, file, 1.0, SCIPinfinity(scip), consname);
3823 
3824  rhss[c] = 1.0;
3825 
3826  /* compute column entries */
3827  SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons), transformed, matrix, &rhss[c]) );
3828  }
3829  else if( strcmp(conshdlrname, "knapsack") == 0 )
3830  {
3831  int i;
3832 
3833  /* print row entry */
3834  printRowType(scip, file, -SCIPinfinity(scip), (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), consname);
3835 
3836  nconsvars = SCIPgetNVarsKnapsack(scip, cons);
3837  weights = SCIPgetWeightsKnapsack(scip, cons);
3838 
3839  /* copy Longint array to SCIP_Real array */
3840  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nconsvars ) );
3841  for( i = 0; i < nconsvars; ++i )
3842  vals[i] = (SCIP_Real)weights[i];
3843 
3844  rhss[c] = (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons);
3845 
3846  /* compute column entries */
3847  SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetVarsKnapsack(scip, cons), vals, nconsvars, transformed, matrix, &rhss[c]) );
3848 
3849  SCIPfreeBufferArray(scip, &vals);
3850  }
3851  else if( strcmp(conshdlrname, "varbound") == 0 )
3852  {
3853  lhs = SCIPgetLhsVarbound(scip, cons);
3854  rhs = SCIPgetRhsVarbound(scip, cons);
3855 
3856  /* there is nothing to do if the left hand side is minus infinity and the right side is infinity */
3857  if( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) )
3858  {
3859  if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, lhs, rhs) )
3860  needRANGES = TRUE;
3861 
3862  /* print row entry */
3863  printRowType(scip, file, lhs, rhs, consname);
3864 
3865  /* allocate memory */
3866  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
3867  SCIP_CALL( SCIPallocBufferArray(scip, &vals, 2) );
3868 
3869  consvars[0] = SCIPgetVarVarbound(scip, cons);
3870  consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
3871 
3872  vals[0] = 1.0;
3873  vals[1] = SCIPgetVbdcoefVarbound(scip, cons);
3874 
3875  if( SCIPisInfinity(scip, rhs) )
3876  rhss[c] = lhs;
3877  else
3878  rhss[c] = rhs;
3879 
3880  assert( !SCIPisInfinity(scip, rhss[c]) );
3881 
3882  /* compute column entries */
3883  SCIP_CALL( getLinearCoeffs(scip, consname, consvars, vals, 2, transformed, matrix, &rhss[c]) );
3884 
3885  SCIPfreeBufferArray(scip, &vals);
3886  SCIPfreeBufferArray(scip, &consvars);
3887  }
3888  }
3889  else if( strcmp(conshdlrname, "indicator") == 0 )
3890  {
3891  SCIP_VAR* slackvar;
3892  SCIP_VAR* binvar;
3893 
3894  /* store slack variable in hash */
3895  slackvar = SCIPgetSlackVarIndicator(cons);
3896  assert( slackvar != NULL );
3897  assert( indicatorSlackHash != NULL );
3898  assert( !SCIPhashtableExists(indicatorSlackHash, (void*) slackvar) );
3899  SCIP_CALL( SCIPhashtableInsert(indicatorSlackHash, (void*) slackvar) );
3900 
3901  /* if slackvariable is aggregated, we store it in the list of aggregated variables */
3902  if ( SCIPvarGetStatus(slackvar) == SCIP_VARSTATUS_AGGREGATED )
3903  {
3904  SCIP_CALL( collectAggregatedVars(scip, &slackvar, 1, &aggvars, &naggvars, &saggvars, varFixedHash) );
3905  }
3906 
3907  /* store aggregated variables */
3908  binvar = SCIPgetBinaryVarIndicator(cons);
3909  if( SCIPvarIsNegated(binvar) )
3910  binvar = SCIPvarGetNegatedVar(binvar);
3911  assert( binvar != NULL );
3912  SCIP_CALL( collectAggregatedVars(scip, &binvar, 1, &aggvars, &naggvars, &saggvars, varFixedHash) );
3913 
3914  /* indicator constraint do not have a right hand side; mark this with SCIPinfinity(scip) */
3915  rhss[c] = SCIPinfinity(scip);
3916 
3917  /* store constraint */
3918  consIndicator[nConsIndicator++] = cons;
3919  continue;
3920  }
3921  else if( strcmp(conshdlrname, "SOS1") == 0 )
3922  {
3923  /* store constraint */
3924  consSOS1[nConsSOS1++] = cons;
3925 
3926  /* check for aggregated variables in SOS1 constraints for later output
3927  * of aggregations as linear constraints */
3928  consvars = SCIPgetVarsSOS1(scip, cons);
3929  nconsvars = SCIPgetNVarsSOS1(scip, cons);
3930 
3931  /* SOS constraint do not have a right hand side; mark this with SCIPinfinity(scip) */
3932  rhss[c] = SCIPinfinity(scip);
3933 
3934  SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varFixedHash) );
3935  }
3936  else if( strcmp(conshdlrname, "SOS2") == 0 )
3937  {
3938  /* store constraint */
3939  consSOS2[nConsSOS2++] = cons;
3940 
3941  /* check for aggregated variables in SOS2 constraints for later output aggregations as linear constraints */
3942  consvars = SCIPgetVarsSOS2(scip, cons);
3943  nconsvars = SCIPgetNVarsSOS2(scip, cons);
3944 
3945  /* SOS constraint do not have a right hand side; mark this with SCIPinfinity(scip) */
3946  rhss[c] = SCIPinfinity(scip);
3947 
3948  SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varFixedHash) );
3949  }
3950  else if( strcmp(conshdlrname, "quadratic") == 0 )
3951  {
3952  SCIP_VAR** quadvars;
3953  SCIP_Real* quadvarlincoefs;
3954  int j;
3955 
3956  /* store constraint */
3957  consQuadratic[nConsQuadratic++] = cons;
3958 
3959  /* collect linear coefficients of quadratic part */
3960  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars, SCIPgetNQuadVarTermsQuadratic(scip, cons)) );
3961  SCIP_CALL( SCIPallocBufferArray(scip, &quadvarlincoefs, SCIPgetNQuadVarTermsQuadratic(scip, cons)) );
3962  for( j = 0; j < SCIPgetNQuadVarTermsQuadratic(scip, cons); ++j )
3963  {
3964  quadvars[j] = SCIPgetQuadVarTermsQuadratic(scip, cons)[j].var;
3965  quadvarlincoefs[j] = SCIPgetQuadVarTermsQuadratic(scip, cons)[j].lincoef;
3966  }
3967 
3968  lhs = SCIPgetLhsQuadratic(scip, cons);
3969  rhs = SCIPgetRhsQuadratic(scip, cons);
3970 
3971  /* there is nothing to do if the left hand side is minus infinity and the right side is infinity */
3972  if( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) )
3973  {
3974  if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, lhs, rhs) )
3975  needRANGES = TRUE;
3976 
3977  /* print row entry */
3978  printRowType(scip, file, lhs, rhs, consname);
3979 
3980  if( SCIPisInfinity(scip, rhs) )
3981  rhss[c] = lhs;
3982  else
3983  rhss[c] = rhs;
3984 
3985  assert( !SCIPisInfinity(scip, rhss[c]) );
3986 
3987  /* compute column entries for linear part */
3988  SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetLinearVarsQuadratic(scip, cons), SCIPgetCoefsLinearVarsQuadratic(scip, cons),
3989  SCIPgetNLinearVarsQuadratic(scip, cons), transformed, matrix, &rhss[c]) );
3990 
3991  /* compute column entries for linear part in quadratic part */
3992  SCIP_CALL( getLinearCoeffs(scip, consname, quadvars, quadvarlincoefs, SCIPgetNQuadVarTermsQuadratic(scip, cons),
3993  transformed, matrix, &rhss[c]) );
3994  }
3995 
3996  /* check for aggregated variables in quadratic part of quadratic constraints for later output of
3997  * aggregations as linear constraints */
3998  consvars = quadvars;
3999  nconsvars = SCIPgetNQuadVarTermsQuadratic(scip, cons);
4000 
4001  SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varFixedHash) );
4002 
4003  SCIPfreeBufferArray(scip, &quadvars);
4004  SCIPfreeBufferArray(scip, &quadvarlincoefs);
4005  }
4006  else if( strcmp(conshdlrname, "soc") == 0 )
4007  {
4008  /* SOC constraints are of the form lhsconstant + sum_i (lhscoef_i*(lhsvar_i+lhsoffset_i))^2 <= (rhscoef*(rhsvar+rhsoffset))^2 */
4009  SCIP_Real* lincoefs;
4010  SCIP_Real coef;
4011  SCIP_Real offset;
4012 
4013  /* store constraint */
4014  consSOC[nConsSOC++] = cons;
4015 
4016  consvars = SCIPgetLhsVarsSOC(scip, cons);
4017  nconsvars = SCIPgetNLhsVarsSOC(scip, cons);
4018 
4019  rhs = -SCIPgetLhsConstantSOC(scip, cons);
4020 
4021  /* offsets on lhs give linear coefficients that need to be processed here */
4022  SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nconsvars) );
4023 
4024  for( v = 0; v < nconsvars; ++v )
4025  {
4026  offset = SCIPgetLhsOffsetsSOC(scip, cons)[v];
4027  coef = SCIPgetLhsCoefsSOC(scip, cons)[v];
4028 
4029  lincoefs[v] = 2 * offset * coef * coef;
4030  rhs -= offset * offset * coef * coef;
4031  }
4032 
4033  SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetLhsVarsSOC(scip, cons), lincoefs, nconsvars, transformed, matrix, &rhs) );
4034 
4035  SCIPfreeBufferArray(scip, &lincoefs);
4036 
4037  /* if there is an offsets on rhs, then we have linear a coefficient that need to be processed here */
4038  if( SCIPgetRhsOffsetSOC(scip, cons) != 0.0 )
4039  {
4040  SCIP_VAR* rhsvar;
4041  SCIP_Real lincoef;
4042 
4043  coef = SCIPgetRhsCoefSOC(scip, cons);
4044  offset = SCIPgetRhsOffsetSOC(scip, cons);
4045  rhsvar = SCIPgetRhsVarSOC(scip, cons);
4046  lincoef = -2 * offset * coef * coef;
4047  rhs += offset * offset * coef * coef;
4048 
4049  SCIP_CALL( getLinearCoeffs(scip, consname, &rhsvar, &lincoef, 1, transformed, matrix, &rhs) );
4050  }
4051 
4052  assert(!SCIPisInfinity(scip, ABS(rhs)));
4053 
4054  /* print row entry */
4055  printRowType(scip, file, -SCIPinfinity(scip), rhs, consname);
4056 
4057  rhss[c] = rhs;
4058 
4059  /* check for aggregated variables in for later output of aggregations as linear constraints */
4060  SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varFixedHash) );
4061  var = SCIPgetRhsVarSOC(scip, cons);
4062  SCIP_CALL( collectAggregatedVars(scip, &var, 1, &aggvars, &naggvars, &saggvars, varFixedHash) );
4063  }
4064  else if( strcmp(conshdlrname, "and") == 0 )
4065  {
4066  if( readerdata->linearizeands )
4067  {
4068  SCIP_VAR** rowvars;
4069  SCIP_VAR** operands;
4070  SCIP_VAR* resultant;
4071  SCIP_Real* rowvals;
4072  char* rowname;
4073  int nrowvars;
4074  int l;
4075  int n;
4076 
4077  nrowvars = SCIPgetNVarsAnd(scip, cons);
4078  operands = SCIPgetVarsAnd(scip, cons);
4079  resultant = SCIPgetResultantAnd(scip, cons);
4080 
4081  /* allocate buffer array */
4082  SCIP_CALL( SCIPallocBufferArray(scip, &rowvars, nrowvars + 1) );
4083  SCIP_CALL( SCIPallocBufferArray(scip, &rowvals, nrowvars + 1) );
4084 
4085  /* get length of constraint name */
4086  l = (int) strlen(consname);
4087 
4088  /* the tight relaxtion, number of and-constraint operands rows */
4089  if( !readerdata->aggrlinearizationands )
4090  {
4091  rowvars[0] = resultant;
4092  rowvals[0] = 1.0;
4093  rowvals[1] = -1.0;
4094 
4095  /* compute maximal length for rowname */
4096  n = (int) log10((double)nrowvars) + 1 + l;
4097 
4098  /* assure maximal allowed value */
4099  if( n >= MPS_MAX_NAMELEN )
4100  n = MPS_MAX_NAMELEN - 1;
4101 
4102  /* update maxnamelen */
4103  maxnamelen = MAX(maxnamelen, (unsigned int) n);
4104 
4105  /* print operator rows */
4106  for( v = 0; v < nrowvars; ++v )
4107  {
4108  /* compute maximal length for rowname */
4109  if( v == 0 )
4110  n = 2;
4111  else
4112  n = (int) log10((double)v) + 2;
4113  n += l;;
4114 
4115  /* assure maximal allowed value */
4116  if( n >= MPS_MAX_NAMELEN )
4117  {
4118  n = MPS_MAX_NAMELEN - 1;
4119  ++faulty;
4120  }
4121 
4122  /* need memory for additional row */
4123  SCIP_CALL( SCIPallocBufferArray(scip, &rowname, n + 1) );
4124 
4125  assert(k < nconss + naddrows);
4126  consnames[k] = rowname;
4127 
4128  (void) SCIPsnprintf(rowname, n + 1, "%s_%d", consname, v);
4129  rowvars[1] = operands[v];
4130 
4131  /* print row entry */
4132  printRowType(scip, file, -SCIPinfinity(scip), 0.0, rowname);
4133 
4134  rhss[k] = 0.0;
4135 
4136  /* compute column entries */
4137  SCIP_CALL( getLinearCoeffs(scip, rowname, rowvars, rowvals, 2, transformed, matrix, &rhss[k]) );
4138  ++k;
4139  }
4140  }
4141 
4142  /* prepare for next row */
4143  for( v = nrowvars - 1; v >= 0; --v )
4144  {
4145  rowvars[v] = operands[v];
4146  rowvals[v] = -1.0;
4147  }
4148 
4149  rowvars[nrowvars] = resultant;
4150 
4151  /* the weak relaxtion, only one constraint */
4152  if( readerdata->aggrlinearizationands )
4153  {
4154  /* compute maximal length for rowname */
4155  n = l + 3;
4156 
4157  /* assure maximal allowed value */
4158  if( n >= MPS_MAX_NAMELEN )
4159  {
4160  n = MPS_MAX_NAMELEN - 1;
4161  ++faulty;
4162  }
4163 
4164  /* update maxnamelen */
4165  maxnamelen = MAX(maxnamelen, (unsigned int) n);
4166 
4167  /* need memory for additional row */
4168  SCIP_CALL( SCIPallocBufferArray(scip, &rowname, n + 1) );
4169 
4170  assert(k < nconss + naddrows);
4171  consnames[k] = rowname;
4172 
4173  /* adjust rowname of constraint */
4174  (void) SCIPsnprintf(rowname, n + 1, "%s_op", consname);
4175 
4176  rowvals[nrowvars] = (SCIP_Real) nrowvars;
4177 
4178  /* print row entry */
4179  printRowType(scip, file, -SCIPinfinity(scip), 0.0, rowname);
4180 
4181  rhss[k] = 0.0;
4182 
4183  /* compute column entries */
4184  SCIP_CALL( getLinearCoeffs(scip, rowname, rowvars, rowvals, nrowvars + 1, transformed, matrix, &rhss[k]) );
4185 
4186  printf("%g, %g\n", rowvals[1], rhss[k]);
4187  ++k;
4188  }
4189 
4190  rowvals[nrowvars] = 1.0;
4191 
4192  /* print row entry */
4193  printRowType(scip, file, -nrowvars + 1.0, SCIPinfinity(scip), consname);
4194 
4195  rhss[c] = -nrowvars + 1.0;
4196 
4197  /* compute column entries */
4198  SCIP_CALL( getLinearCoeffs(scip, consname, rowvars, rowvals, nrowvars + 1, transformed, matrix, &rhss[c]) );
4199 
4200  /* free buffer array */
4201  SCIPfreeBufferArray(scip, &rowvals);
4202  SCIPfreeBufferArray(scip, &rowvars);
4203  }
4204  else
4205  {
4206  /* and constraint printing not enabled; mark this with SCIPinfinity(scip) */
4207  rhss[c] = SCIPinfinity(scip);
4208 
4209  SCIPwarningMessage(scip, "change parameter \"reading/"READER_NAME"/linearize-and-constraints\" to TRUE to print and-constraints\n");
4210  }
4211  }
4212  else
4213  {
4214  /* unknown constraint type; mark this with SCIPinfinity(scip) */
4215  rhss[c] = SCIPinfinity(scip);
4216 
4217  SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
4218  }
4219  }
4220 
4221  if( faulty > 0 )
4222  {
4223  SCIPwarningMessage(scip, "there are %d and-constraint-rownames which have to be cut down to %d characters; MPS file might be corrupted\n",
4224  faulty, MPS_MAX_NAMELEN - 1);
4225  }
4226 
4227  /* free hash table */
4228  if( varFixedHash != NULL )
4229  SCIPhashtableFree(&varFixedHash);
4230 
4231  if( indicatorSlackHash != NULL && nConsIndicator == 0 )
4232  {
4233  SCIPhashtableFree(&indicatorSlackHash);
4234  assert( indicatorSlackHash == NULL );
4235  }
4236 
4237  if( naggvars > 0 )
4238  {
4239  /* construct variables name of the needed aggregated variables and the constraint names for the aggregation constraints */
4240 
4241  /* realloc memory */
4242  SCIP_CALL( SCIPreallocBufferArray(scip, &consnames, nconss + naddrows + naggvars) );
4243  SCIP_CALL( SCIPreallocBufferArray(scip, &rhss, nconss + naddrows + naggvars) );
4244  SCIP_CALL( SCIPreallocBufferArray(scip, &varnames, nvars + naggvars) );
4245 
4246  for( c = 0; c < naggvars; ++c )
4247  {
4248  size_t l;
4249 
4250  /* create variable name */
4251  var = aggvars[c];
4252 
4253  l = strlen(SCIPvarGetName(var));
4254  if( l >= MPS_MAX_NAMELEN )
4255  maxnamelen = MPS_MAX_NAMELEN - 1;
4256  else
4257  maxnamelen = MAX(maxnamelen, (unsigned int) l);
4258 
4259  SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) );
4260  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
4261 
4262  /* insert variable with variable name into hash map */
4263  varnames[nvars + c] = namestr;
4264  assert( !SCIPhashmapExists(varnameHashmap, var) );
4265  SCIP_CALL( SCIPhashmapInsert(varnameHashmap, var, (void*) (size_t) namestr) );
4266 
4267  /* output row type (it is an equation) */
4268  SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) ); /* note that namestr above is freed via varnames */
4269  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "aggr_%s", SCIPvarGetName(var));
4270  printRowType(scip, file, 1.0, 1.0, namestr);
4271 
4272  l = strlen(namestr);
4273  maxnamelen = MAX(maxnamelen, (unsigned int) l);
4274  consnames[nconss + naddrows + c] = namestr;
4275  rhss[nconss + naddrows + c] = 0.0;
4276 
4277  /* compute column entries */
4278  SCIP_CALL( getLinearCoeffs(scip, namestr, &(aggvars[c]), NULL, 1, transformed, matrix, &rhss[nconss + naddrows + c]) );
4279 
4280  /* add the aggregated variables to the sparse matrix */
4281  SCIP_CALL( checkSparseMatrixCapacity(scip, matrix, 1) );
4282  matrix->values[matrix->nentries] = -1.0;
4283  matrix->columns[matrix->nentries] = aggvars[c];
4284  matrix->rows[matrix->nentries] = namestr;
4285  matrix->nentries++;
4286  }
4287  }
4288 
4289  /* collect also fixed variables, because they might not be removed from all constraints */
4290  /* @todo only collect fixed variables in the non-linear constraint types, where they (could not be)/(were not) removed */
4291  if( nfixedvars > 0 )
4292  {
4293  int startpos = nvars + naggvars;
4294  /* construct variables name of fixed variables */
4295 
4296  /* realloc memory */
4297  SCIP_CALL( SCIPreallocBufferArray(scip, &varnames, startpos + nfixedvars) );
4298 
4299  /* allocate memory for fixed variables */
4300  SCIP_CALL( SCIPallocBufferArray(scip, &fixvars, nfixedvars) );
4301 
4302  for( v = nfixedvars - 1; v >= 0; --v )
4303  {
4304  /* create variable name */
4305  var = fixedvars[v];
4306 
4308  {
4309  size_t l;
4310  l = strlen(SCIPvarGetName(var));
4311  if( l >= MPS_MAX_NAMELEN )
4312  maxnamelen = MPS_MAX_NAMELEN - 1;
4313  else
4314  maxnamelen = MAX(maxnamelen, (unsigned int) l);
4315 
4316  SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) );
4317  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
4318 
4319  varnames[startpos + nfixvars] = namestr;
4320  fixvars[nfixvars] = var;
4321  ++nfixvars;
4322 
4323  /* insert variable with variable name into hash map */
4324  assert(!SCIPhashmapExists(varnameHashmap, var));
4325  SCIP_CALL( SCIPhashmapInsert(varnameHashmap, var, (void*) (size_t) namestr) );
4326 
4327  /* add the fixed variables to the sparse matrix, needed for columns section */
4328  SCIP_CALL( checkSparseMatrixCapacity(scip, matrix, 1) );
4329  matrix->values[matrix->nentries] = 0.0;
4330  matrix->columns[matrix->nentries] = var;
4331  matrix->rows[matrix->nentries] = "Obj";
4332  matrix->nentries++;
4333  }
4334  }
4335  }
4336 
4337  /* output COLUMNS section */
4338  printColumnSection(scip, file, matrix, varnameHashmap, indicatorSlackHash, maxnamelen);
4339 
4340  /* output RHS section */
4341  printRhsSection(scip, file, nconss + naddrows +naggvars, consnames, rhss, maxnamelen);
4342 
4343  /* output RANGES section */
4344  if( needRANGES )
4345  printRangeSection(scip, file, conss, nconss, consnames, transformed, maxnamelen);
4346 
4347  /* output BOUNDS section */
4348  printBoundSection(scip, file, vars, nvars, aggvars, naggvars, fixvars, nfixvars, transformed, varnames, indicatorSlackHash, maxnamelen);
4349 
4350  if( nfixedvars > 0 )
4351  {
4352  assert(fixvars != NULL);
4353  SCIPfreeBufferArray(scip, &fixvars);
4354  }
4355 
4356  /* print SOS section */
4357  if( nConsSOS1 > 0 || nConsSOS2 > 0 )
4358  {
4359  SCIP_Real* sosweights;
4360 
4361  SCIPinfoMessage(scip, file, "SOS\n");
4362  SCIPdebugMessage("start printing SOS section\n");
4363 
4364  SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) );
4365 
4366  /* first output SOS1 constraints */
4367  for( c = 0; c < nConsSOS1; ++c )
4368  {
4369  cons = consSOS1[c];
4370  consvars = SCIPgetVarsSOS1(scip, cons);
4371  nconsvars = SCIPgetNVarsSOS1(scip, cons);
4372  sosweights = SCIPgetWeightsSOS1(scip, cons);
4373  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPconsGetName(cons) );
4374 
4375  printStart(scip, file, "S1", namestr, -1);
4376  SCIPinfoMessage(scip, file, "\n");
4377 
4378  for( v = 0; v < nconsvars; ++v )
4379  {
4380  /* get variable name */
4381  assert ( SCIPhashmapExists(varnameHashmap, consvars[v]) );
4382  varname = (const char*) (size_t) SCIPhashmapGetImage(varnameHashmap, consvars[v]);
4383 
4384  printStart(scip, file, "", varname, (int) maxnamelen);
4385 
4386  if( sosweights != NULL )
4387  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", sosweights[v]);
4388  else
4389  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d ", v);
4390 
4391  SCIPinfoMessage(scip, file, "%25s\n", valuestr);
4392  }
4393  }
4394 
4395  /* next output SOS2 constraints */
4396  for( c = 0; c < nConsSOS2; ++c )
4397  {
4398  cons = consSOS2[c];
4399  consvars = SCIPgetVarsSOS2(scip, cons);
4400  nconsvars = SCIPgetNVarsSOS2(scip, cons);
4401  sosweights = SCIPgetWeightsSOS2(scip, cons);
4402  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPconsGetName(cons) );
4403 
4404  printStart(scip, file, "S2", namestr, -1);
4405  SCIPinfoMessage(scip, file, "\n");
4406 
4407  for( v = 0; v < nconsvars; ++v )
4408  {
4409  /* get variable name */
4410  assert ( SCIPhashmapExists(varnameHashmap, consvars[v]) );
4411  varname = (const char*) (size_t) SCIPhashmapGetImage(varnameHashmap, consvars[v]);
4412 
4413  printStart(scip, file, "", varname, (int) maxnamelen);
4414 
4415  if( sosweights != NULL )
4416  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", sosweights[v]);
4417  else
4418  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d ", v);
4419 
4420  SCIPinfoMessage(scip, file, "%25s\n", valuestr);
4421  }
4422  }
4423  SCIPfreeBufferArray(scip, &namestr);
4424  }
4425 
4426  /* print QCMATRIX sections for quadratic constraints
4427  * in difference to a quadratic term in the objective function, the quadratic part is not divided by 2 here
4428  */
4429  if( nConsQuadratic > 0 )
4430  {
4431  SCIP_QUADVARTERM* quadvarterms;
4432  SCIP_BILINTERM* bilinterms;
4433  const char* varname2;
4434  int nbilin;
4435 
4436  SCIPdebugMessage("start printing QCMATRIX sections for quadratic constraints\n");
4437  SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) );
4438 
4439  for( c = 0; c < nConsQuadratic; ++c )
4440  {
4441  cons = consQuadratic[c];
4442  nconsvars = SCIPgetNQuadVarTermsQuadratic(scip, cons);
4443  quadvarterms = SCIPgetQuadVarTermsQuadratic(scip, cons);
4444  bilinterms = SCIPgetBilinTermsQuadratic(scip, cons);
4445  nbilin = SCIPgetNBilinTermsQuadratic(scip, cons);
4446 
4447  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPconsGetName(cons) );
4448 
4449  SCIPinfoMessage(scip, file, "QCMATRIX %s\n", namestr);
4450 
4451  /* print x^2 terms */
4452  for( v = 0; v < nconsvars; ++v )
4453  {
4454  if( quadvarterms[v].sqrcoef == 0.0 )
4455  continue;
4456 
4457  /* get variable name */
4458  assert ( SCIPhashmapExists(varnameHashmap, quadvarterms[v].var) );
4459  varname = (const char*) (size_t) SCIPhashmapGetImage(varnameHashmap, quadvarterms[v].var);
4460 
4461  /* get coefficient as string */
4462  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", quadvarterms[v].sqrcoef);
4463 
4464  /* print "x x coeff" line */
4465  printStart(scip, file, "", varname, (int) maxnamelen);
4466  printRecord(scip, file, varname, valuestr, maxnamelen);
4467  SCIPinfoMessage(scip, file, "\n", valuestr);
4468  }
4469 
4470  /* print bilinear terms; CPLEX format expects a symmetric matrix with all coefficients specified,
4471  * i.e., we have to split bilinear coefficients into two off diagonal elements */
4472  for( v = 0; v < nbilin; ++v )
4473  {
4474  if( bilinterms[v].coef == 0.0 )
4475  continue;
4476 
4477  /* get name of first variable */
4478  assert ( SCIPhashmapExists(varnameHashmap, bilinterms[v].var1) );
4479  varname = (const char*) (size_t) SCIPhashmapGetImage(varnameHashmap, bilinterms[v].var1);
4480 
4481  /* get name of second variable */
4482  assert ( SCIPhashmapExists(varnameHashmap, bilinterms[v].var2) );
4483  varname2 = (const char*) (size_t) SCIPhashmapGetImage(varnameHashmap, bilinterms[v].var2);
4484 
4485  /* get coefficient as string */
4486  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", 0.5*bilinterms[v].coef);
4487 
4488  /* print "x y coeff/2" line */
4489  printStart(scip, file, "", varname, (int) maxnamelen);
4490  printRecord(scip, file, varname2, valuestr, maxnamelen);
4491  SCIPinfoMessage(scip, file, "\n", valuestr);
4492 
4493  /* print "y x coeff/2" line */
4494  printStart(scip, file, "", varname2, (int) maxnamelen);
4495  printRecord(scip, file, varname, valuestr, maxnamelen);
4496  SCIPinfoMessage(scip, file, "\n", valuestr);
4497  }
4498  }
4499 
4500  SCIPfreeBufferArray(scip, &namestr);
4501  }
4502 
4503 
4504  /* print QCMATRIX sections for second order cone constraints */
4505  if( nConsSOC > 0 )
4506  {
4507  SCIP_Real* coefs;
4508 
4509  SCIPdebugMessage("start printing QCMATRIX sections for soc constraints\n");
4510  SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) );
4511 
4512  for( c = 0; c < nConsSOC; ++c )
4513  {
4514  cons = consSOC[c];
4515  consvars = SCIPgetLhsVarsSOC(scip, cons);
4516  nconsvars = SCIPgetNLhsVarsSOC(scip, cons);
4517  coefs = SCIPgetLhsCoefsSOC(scip, cons);
4518 
4519  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPconsGetName(cons) );
4520  SCIPinfoMessage(scip, file, "QCMATRIX %s\n", namestr);
4521 
4522  /* print alpha_i^2 x_i^2 terms */
4523  for( v = 0; v < nconsvars; ++v )
4524  {
4525  if( coefs[v] == 0.0 )
4526  continue;
4527 
4528  /* get variable name */
4529  assert ( SCIPhashmapExists(varnameHashmap, consvars[v]) );
4530  varname = (const char*) (size_t) SCIPhashmapGetImage(varnameHashmap, consvars[v]);
4531 
4532  /* get coefficient^2 as string */
4533  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", coefs[v]*coefs[v]);
4534 
4535  /* print "x x coeff" line */
4536  printStart(scip, file, "", varname, (int) maxnamelen);
4537  printRecord(scip, file, varname, valuestr, maxnamelen);
4538  SCIPinfoMessage(scip, file, "\n", valuestr);
4539  }
4540 
4541  /* print -(alpha_{n+1} x_{n+1})^2 term */
4542 
4543  /* get variable name */
4544  var = SCIPgetRhsVarSOC(scip, cons);
4545  assert ( SCIPhashmapExists(varnameHashmap, var) );
4546  varname = (const char*) (size_t) SCIPhashmapGetImage(varnameHashmap, var);
4547 
4548  /* get -coefficient^2 as string */
4549  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", -SCIPgetRhsCoefSOC(scip, cons)*SCIPgetRhsCoefSOC(scip, cons));
4550 
4551  /* print "x x coeff" line */
4552  printStart(scip, file, "", varname, (int) maxnamelen);
4553  printRecord(scip, file, varname, valuestr, maxnamelen);
4554  SCIPinfoMessage(scip, file, "\n", valuestr);
4555  }
4556 
4557  SCIPfreeBufferArray(scip, &namestr);
4558  }
4559 
4560  /* print indicator section */
4561  if( nConsIndicator > 0 )
4562  {
4563  SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) );
4564 
4565  SCIPinfoMessage(scip, file, "INDICATORS\n");
4566  SCIPdebugMessage("start printing INDICATOR section\n");
4567 
4568  /* output each indicator constraint */
4569  for( c = 0; c < nConsIndicator; ++c )
4570  {
4571  SCIP_CONS* lincons;
4572  SCIP_VAR* slackvar;
4573  SCIP_VAR* binvar;
4574 
4575  cons = consIndicator[c];
4576  binvar = SCIPgetBinaryVarIndicator(cons);
4577  lincons = SCIPgetLinearConsIndicator(cons);
4578  slackvar = SCIPgetSlackVarIndicator(cons);
4579 
4580  /* create variable and value strings */
4581  if( SCIPvarIsNegated(binvar) )
4582  {
4583  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d", 0);
4584  assert( SCIPvarGetNegatedVar(binvar) != NULL );
4585  assert( SCIPhashmapExists(varnameHashmap, SCIPvarGetNegatedVar(binvar)) );
4586  varname = (const char*) (size_t) SCIPhashmapGetImage(varnameHashmap, SCIPvarGetNegatedVar(binvar));
4587  }
4588  else
4589  {
4590  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d", 1);
4591  assert ( SCIPhashmapExists(varnameHashmap, binvar) );
4592  varname = (const char*) (size_t) SCIPhashmapGetImage(varnameHashmap, binvar);
4593  }
4594 
4595  /* write records */
4596  if ( SCIPvarGetStatus(slackvar) == SCIP_VARSTATUS_AGGREGATED )
4597  {
4598  /* for aggregated variables output name of aggregating constraint */
4599  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "aggr_%s", SCIPvarGetName(slackvar));
4600  printStart(scip, file, "IF", namestr, (int) maxnamelen);
4601  printRecord(scip, file, varname, valuestr, maxnamelen);
4602  SCIPinfoMessage(scip, file, "\n");
4603  }
4604  else
4605  {
4606  printStart(scip, file, "IF", SCIPconsGetName(lincons), (int) maxnamelen);
4607  printRecord(scip, file, varname, valuestr, maxnamelen);
4608  SCIPinfoMessage(scip, file, "\n");
4609  }
4610  }
4611  SCIPfreeBufferArray(scip, &namestr);
4612  }
4613 
4614  /* free matrix data structure */
4615  freeMatrix(scip, matrix);
4616 
4617  /* free slackvar hashtable */
4618  if( indicatorSlackHash != NULL )
4619  SCIPhashtableFree(&indicatorSlackHash);
4620 
4621  /* free variable hashmap */
4622  SCIPhashmapFree(&varnameHashmap);
4623 
4624  SCIPfreeBlockMemoryArray(scip, &aggvars, saggvars);
4625  SCIPfreeBufferArray(scip, &rhss);
4626 
4627  /* free buffer arrays for SOS1, SOS2, and quadratic */
4628  SCIPfreeBufferArray(scip, &consIndicator);
4629  SCIPfreeBufferArray(scip, &consSOC);
4630  SCIPfreeBufferArray(scip, &consQuadratic);
4631  SCIPfreeBufferArray(scip, &consSOS2);
4632  SCIPfreeBufferArray(scip, &consSOS1);
4633 
4634  /* free variable and constraint name array */
4635  for( v = nvars + naggvars + nfixvars - 1; v >= 0; --v )
4636  SCIPfreeBufferArray(scip, &varnames[v]);
4637  SCIPfreeBufferArray(scip, &varnames);
4638 
4639  for( c = nconss + naddrows + naggvars - 1; c >= 0; --c )
4640  SCIPfreeBufferArray(scip, &consnames[c]);
4641  SCIPfreeBufferArray(scip, &consnames);
4642 
4643  /* print end of data line */
4644  SCIPinfoMessage(scip, file, "ENDATA");
4645 
4646  *result = SCIP_SUCCESS;
4647 
4648  return SCIP_OKAY;
4649 }
4650 
4651 
4652 /*
4653  * mps file reader specific interface methods
4654  */
4655 
4656 /** includes the mps file reader in SCIP */
4658  SCIP* scip /**< SCIP data structure */
4659  )
4660 {
4661  SCIP_READERDATA* readerdata;
4662  SCIP_READER* reader;
4663 
4664  /* create reader data */
4665  SCIP_CALL( SCIPallocMemory(scip, &readerdata) );
4666 
4667  /* include reader */
4668  SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, readerdata) );
4669 
4670  /* set non fundamental callbacks via setter functions */
4671  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyMps) );
4672  SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeMps) );
4673  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadMps) );
4674  SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteMps) );
4675 
4676  /* add lp-reader parameters */
4678  "reading/"READER_NAME"/linearize-and-constraints",
4679  "should possible \"and\" constraint be linearized when writing the mps file?",
4680  &readerdata->linearizeands, TRUE, DEFAULT_LINEARIZE_ANDS, NULL, NULL) );
4682  "reading/"READER_NAME"/aggrlinearization-ands",
4683  "should an aggregated linearization for and constraints be used?",
4684  &readerdata->aggrlinearizationands, TRUE, DEFAULT_AGGRLINEARIZATION_ANDS, NULL, NULL) );
4685 
4686  return SCIP_OKAY;
4687 }
4688