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