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