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-2018 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 
969  SCIPdebugMsg(scip, "read columns\n");
970 
971  var = NULL;
972  while( mpsinputReadLine(mpsi) )
973  {
974  if( mpsinputField0(mpsi) != 0 )
975  {
976  if( strcmp(mpsinputField0(mpsi), "RHS") )
977  break;
978 
979  /* add the last variable to the problem */
980  if( var != NULL )
981  {
982  SCIP_CALL( SCIPaddVar(scip, var) );
983  SCIP_CALL( SCIPreleaseVar(scip, &var) );
984  }
985  assert(var == NULL);
986 
988  return SCIP_OKAY;
989  }
990  if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
991  break;
992 
993  /* new column? */
994  if( strcmp(colname, mpsinputField1(mpsi)) )
995  {
996  /* add the last variable to the problem */
997  if( var != NULL )
998  {
999  SCIP_CALL( SCIPaddVar(scip, var) );
1000  SCIP_CALL( SCIPreleaseVar(scip, &var) );
1001  }
1002  assert(var == NULL);
1003 
1004  (void)SCIPmemccpy(colname, mpsinputField1(mpsi), '\0', MPS_MAX_NAMELEN - 1);
1005 
1006  /* if the file type is a cor file, the the variable name must be stored */
1007  SCIP_CALL( addVarNameToStorage(scip, varnames, varnamessize, nvarnames, colname) );
1008 
1009  if( mpsinputIsInteger(mpsi) )
1010  {
1011  /* for integer variables, default bounds are 0 <= x < 1(not +infinity, like it is for continuous variables), and default cost is 0 */
1012  SCIP_CALL( SCIPcreateVar(scip, &var, colname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY,
1013  !mpsi->dynamiccols, mpsi->dynamiccols, NULL, NULL, NULL, NULL, NULL) );
1014  }
1015  else
1016  {
1017  /* for continuous variables, default bounds are 0 <= x, and default cost is 0 */
1018  SCIP_CALL( SCIPcreateVar(scip, &var, colname, 0.0, SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS,
1019  !mpsi->dynamiccols, mpsi->dynamiccols, NULL, NULL, NULL, NULL, NULL) );
1020  }
1021  }
1022  assert(var != NULL);
1023 
1024  val = atof(mpsinputField3(mpsi));
1025 
1026  if( !strcmp(mpsinputField2(mpsi), mpsinputObjname(mpsi)) )
1027  {
1028  SCIP_CALL( SCIPchgVarObj(scip, var, val) );
1029  }
1030  else
1031  {
1032  cons = SCIPfindCons(scip, mpsinputField2(mpsi));
1033  if( cons == NULL )
1034  mpsinputEntryIgnored(scip, mpsi, "Column", mpsinputField1(mpsi), "row", mpsinputField2(mpsi), SCIP_VERBLEVEL_FULL);
1035  else if( !SCIPisZero(scip, val) )
1036  {
1037  SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
1038  }
1039  }
1040  if( mpsinputField5(mpsi) != NULL )
1041  {
1042  assert(mpsinputField4(mpsi) != NULL);
1043 
1044  val = atof(mpsinputField5(mpsi));
1045 
1046  if( !strcmp(mpsinputField4(mpsi), mpsinputObjname(mpsi)) )
1047  {
1048  SCIP_CALL( SCIPchgVarObj(scip, var, val) );
1049  }
1050  else
1051  {
1052  cons = SCIPfindCons(scip, mpsinputField4(mpsi));
1053  if( cons == NULL )
1054  mpsinputEntryIgnored(scip, mpsi, "Column", mpsinputField1(mpsi), "row", mpsinputField4(mpsi), SCIP_VERBLEVEL_FULL);
1055  else if( !SCIPisZero(scip, val) )
1056  {
1057  SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
1058  }
1059  }
1060  }
1061  }
1062  mpsinputSyntaxerror(mpsi);
1063 
1064  return SCIP_OKAY;
1065 }
1066 
1067 /** Process RHS section. */
1068 static
1070  MPSINPUT* mpsi, /**< mps input structure */
1071  SCIP* scip /**< SCIP data structure */
1072  )
1073 {
1074  char rhsname[MPS_MAX_NAMELEN] = { '\0' };
1075  SCIP_CONS* cons;
1076  SCIP_Real lhs;
1077  SCIP_Real rhs;
1078  SCIP_Real val;
1079 
1080  SCIPdebugMsg(scip, "read right hand sides\n");
1081 
1082  while( mpsinputReadLine(mpsi) )
1083  {
1084  if( mpsinputField0(mpsi) != NULL )
1085  {
1086  if( !strcmp(mpsinputField0(mpsi), "RANGES") )
1088  else if( !strcmp(mpsinputField0(mpsi), "BOUNDS") )
1090  else if( !strcmp(mpsinputField0(mpsi), "SOS") )
1091  mpsinputSetSection(mpsi, MPS_SOS);
1092  else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
1094  else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
1096  else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
1098  else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
1100  else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
1102  else
1103  break;
1104  return SCIP_OKAY;
1105  }
1106  if( (mpsinputField2(mpsi) != NULL && mpsinputField3(mpsi) == NULL)
1107  || (mpsinputField4(mpsi) != NULL && mpsinputField5(mpsi) == NULL) )
1108  {
1109  SCIPwarningMessage(scip, "reading rhs section, a field is missing, assuming that the vector name is the missing one(, row identfier <%s>)\n", mpsinputField2(mpsi));
1110 
1111  mpsinputInsertName(mpsi, "_RHS_", FALSE);
1112  }
1113 
1114  if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
1115  break;
1116 
1117  if( *rhsname == '\0' )
1118  (void)SCIPmemccpy(rhsname, mpsinputField1(mpsi), '\0', MPS_MAX_NAMELEN - 1);
1119 
1120  if( !strcmp(rhsname, mpsinputField1(mpsi)) )
1121  {
1122  cons = SCIPfindCons(scip, mpsinputField2(mpsi));
1123  if( cons == NULL )
1124  {
1125  /* the rhs of the objective row is treated as objective constant */
1126  if( !strcmp(mpsinputField2(mpsi), mpsinputObjname(mpsi)) )
1127  {
1128  val = atof(mpsinputField3(mpsi));
1129  SCIP_CALL( SCIPaddOrigObjoffset(scip, -val) );
1130  }
1131  else
1132  mpsinputEntryIgnored(scip, mpsi, "RHS", mpsinputField1(mpsi), "row", mpsinputField2(mpsi), SCIP_VERBLEVEL_NORMAL);
1133  }
1134  else
1135  {
1136  val = atof(mpsinputField3(mpsi));
1137 
1138  /* find out the row sense */
1139  lhs = SCIPgetLhsLinear(scip, cons);
1140  rhs = SCIPgetRhsLinear(scip, cons);
1141  if( SCIPisInfinity(scip, -lhs) )
1142  {
1143  /* lhs = -infinity -> lower or equal */
1144  assert(SCIPisZero(scip, rhs));
1145  SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) );
1146  }
1147  else if( SCIPisInfinity(scip, rhs) )
1148  {
1149  /* rhs = +infinity -> greater or equal */
1150  assert(SCIPisZero(scip, lhs));
1151  SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) );
1152  }
1153  else
1154  {
1155  /* lhs > -infinity, rhs < infinity -> equality */
1156  assert(SCIPisZero(scip, lhs));
1157  assert(SCIPisZero(scip, rhs));
1158  SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) );
1159  SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) );
1160  }
1161  SCIPdebugMsg(scip, "RHS <%s> lhs: %g rhs: %g val: <%22.12g>\n", mpsinputField2(mpsi), lhs, rhs, val);
1162  }
1163  if( mpsinputField5(mpsi) != NULL )
1164  {
1165  cons = SCIPfindCons(scip, mpsinputField4(mpsi));
1166  if( cons == NULL )
1167  {
1168  /* the rhs of the objective row is treated as objective constant */
1169  if( !strcmp(mpsinputField2(mpsi), mpsinputObjname(mpsi)) )
1170  {
1171  val = atof(mpsinputField3(mpsi));
1172  SCIP_CALL( SCIPaddOrigObjoffset(scip, -val) );
1173  }
1174  else
1175  mpsinputEntryIgnored(scip, mpsi, "RHS", mpsinputField1(mpsi), "row", mpsinputField4(mpsi), SCIP_VERBLEVEL_NORMAL);
1176  }
1177  else
1178  {
1179  val = atof(mpsinputField5(mpsi));
1180 
1181  /* find out the row sense */
1182  lhs = SCIPgetLhsLinear(scip, cons);
1183  rhs = SCIPgetRhsLinear(scip, cons);
1184  if( SCIPisInfinity(scip, -lhs) )
1185  {
1186  /* lhs = -infinity -> lower or equal */
1187  assert(SCIPisZero(scip, rhs));
1188  SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) );
1189  }
1190  else if( SCIPisInfinity(scip, rhs) )
1191  {
1192  /* rhs = +infinity -> greater or equal */
1193  assert(SCIPisZero(scip, lhs));
1194  SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) );
1195  }
1196  else
1197  {
1198  /* lhs > -infinity, rhs < infinity -> equality */
1199  assert(SCIPisZero(scip, lhs));
1200  assert(SCIPisZero(scip, rhs));
1201  SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) );
1202  SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) );
1203  }
1204  SCIPdebugMsg(scip, "RHS <%s> lhs: %g rhs: %g val: <%22.12g>\n", mpsinputField4(mpsi), lhs, rhs, val);
1205  }
1206  }
1207  }
1208  }
1209  mpsinputSyntaxerror(mpsi);
1210 
1211  return SCIP_OKAY;
1212 }
1213 
1214 /** Process RANGES section */
1215 static
1217  MPSINPUT* mpsi, /**< mps input structure */
1218  SCIP* scip /**< SCIP data structure */
1219  )
1220 {
1221  char rngname[MPS_MAX_NAMELEN] = { '\0' };
1222  SCIP_CONS* cons;
1223  SCIP_Real lhs;
1224  SCIP_Real rhs;
1225  SCIP_Real val;
1226 
1227  SCIPdebugMsg(scip, "read ranges\n");
1228 
1229  while( mpsinputReadLine(mpsi) )
1230  {
1231  if( mpsinputField0(mpsi) != NULL )
1232  {
1233  if( !strcmp(mpsinputField0(mpsi), "BOUNDS") )
1235  else if( !strcmp(mpsinputField0(mpsi), "SOS") )
1236  mpsinputSetSection(mpsi, MPS_SOS);
1237  else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
1239  else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
1241  else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
1243  else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
1245  else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
1247  else
1248  break;
1249  return SCIP_OKAY;
1250  }
1251  if( (mpsinputField2(mpsi) != NULL && mpsinputField3(mpsi) == NULL)
1252  || (mpsinputField4(mpsi) != NULL && mpsinputField5(mpsi) == NULL) )
1253  {
1254  SCIPwarningMessage(scip, "reading ranged section, a field is missing, assuming that the vector name is the missing one(, row identfier <%s>)\n", mpsinputField2(mpsi));
1255 
1256  mpsinputInsertName(mpsi, "_RNG_", FALSE);
1257  }
1258 
1259  if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
1260  break;
1261 
1262  if( *rngname == '\0' )
1263  (void)SCIPmemccpy(rngname, mpsinputField1(mpsi), '\0', MPS_MAX_NAMELEN - 1);
1264 
1265  /* The rules are:
1266  * Row Sign LHS RHS
1267  * ----------------------------------------
1268  * G +/- rhs rhs + |range|
1269  * L +/- rhs - |range| rhs
1270  * E + rhs rhs + range
1271  * E - rhs + range rhs
1272  * ----------------------------------------
1273  */
1274  if( !strcmp(rngname, mpsinputField1(mpsi)) )
1275  {
1276  cons = SCIPfindCons(scip, mpsinputField2(mpsi));
1277  if( cons == NULL )
1278  mpsinputEntryIgnored(scip, mpsi, "Range", mpsinputField1(mpsi), "row", mpsinputField2(mpsi), SCIP_VERBLEVEL_NORMAL);
1279  else
1280  {
1281  val = atof(mpsinputField3(mpsi));
1282 
1283  /* find out the row sense */
1284  lhs = SCIPgetLhsLinear(scip, cons);
1285  rhs = SCIPgetRhsLinear(scip, cons);
1286  if( SCIPisInfinity(scip, -lhs) )
1287  {
1288  /* lhs = -infinity -> lower or equal */
1289  SCIP_CALL( SCIPchgLhsLinear(scip, cons, rhs - REALABS(val)) );
1290  }
1291  else if( SCIPisInfinity(scip, rhs) )
1292  {
1293  /* rhs = +infinity -> greater or equal */
1294  SCIP_CALL( SCIPchgRhsLinear(scip, cons, lhs + REALABS(val)) );
1295  }
1296  else
1297  {
1298  /* lhs > -infinity, rhs < infinity -> equality */
1299  assert(SCIPisEQ(scip, lhs, rhs));
1300  if( val >= 0.0 )
1301  {
1302  SCIP_CALL( SCIPchgRhsLinear(scip, cons, rhs + val) );
1303  }
1304  else
1305  {
1306  SCIP_CALL( SCIPchgLhsLinear(scip, cons, lhs + val) );
1307  }
1308  }
1309  }
1310  if( mpsinputField5(mpsi) != NULL )
1311  {
1312  cons = SCIPfindCons(scip, mpsinputField4(mpsi));
1313  if( cons == NULL )
1314  mpsinputEntryIgnored(scip, mpsi, "Range", mpsinputField1(mpsi), "row", mpsinputField4(mpsi), SCIP_VERBLEVEL_NORMAL);
1315  else
1316  {
1317  val = atof(mpsinputField5(mpsi));
1318 
1319  /* find out the row sense */
1320  lhs = SCIPgetLhsLinear(scip, cons);
1321  rhs = SCIPgetRhsLinear(scip, cons);
1322  if( SCIPisInfinity(scip, -lhs) )
1323  {
1324  /* lhs = -infinity -> lower or equal */
1325  SCIP_CALL( SCIPchgLhsLinear(scip, cons, rhs - REALABS(val)) );
1326  }
1327  else if( SCIPisInfinity(scip, rhs) )
1328  {
1329  /* rhs = +infinity -> greater or equal */
1330  SCIP_CALL( SCIPchgRhsLinear(scip, cons, lhs + REALABS(val)) );
1331  }
1332  else
1333  {
1334  /* lhs > -infinity, rhs < infinity -> equality */
1335  assert(SCIPisEQ(scip, lhs, rhs));
1336  if( val >= 0.0 )
1337  {
1338  SCIP_CALL( SCIPchgRhsLinear(scip, cons, rhs + val) );
1339  }
1340  else
1341  {
1342  SCIP_CALL( SCIPchgLhsLinear(scip, cons, lhs + val) );
1343  }
1344  }
1345  }
1346  }
1347  }
1348  }
1349  mpsinputSyntaxerror(mpsi);
1350 
1351  return SCIP_OKAY;
1352 }
1353 
1354 /** Process BOUNDS section. */
1355 static
1357  MPSINPUT* mpsi, /**< mps input structure */
1358  SCIP* scip /**< SCIP data structure */
1359  )
1360 {
1361  char bndname[MPS_MAX_NAMELEN] = { '\0' };
1362  SCIP_VAR* var;
1363  SCIP_RETCODE retcode;
1364  SCIP_Real val;
1365  SCIP_Bool shifted;
1366 
1367  SCIP_VAR** semicont;
1368  int nsemicont;
1369  int semicontsize;
1370 
1371  retcode = SCIP_OKAY;
1372 
1373  semicont = NULL;
1374  nsemicont = 0;
1375  semicontsize = 0;
1376 
1377  SCIPdebugMsg(scip, "read bounds\n");
1378 
1379  while( mpsinputReadLine(mpsi) )
1380  {
1381  if( mpsinputField0(mpsi) != 0 )
1382  {
1383  if( !strcmp(mpsinputField0(mpsi), "SOS") )
1384  mpsinputSetSection(mpsi, MPS_SOS);
1385  else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
1387  else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
1389  else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
1391  else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
1393  else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
1395  else
1396  break;
1397  goto READBOUNDS_FINISH;
1398  }
1399 
1400  shifted = FALSE;
1401 
1402  /* Is the value field used ? */
1403  if( !strcmp(mpsinputField1(mpsi), "LO") /* lower bound given in field 4 */
1404  || !strcmp(mpsinputField1(mpsi), "UP") /* upper bound given in field 4 */
1405  || !strcmp(mpsinputField1(mpsi), "FX") /* fixed value given in field 4 */
1406  || !strcmp(mpsinputField1(mpsi), "LI") /* CPLEX extension: lower bound of integer variable given in field 4 */
1407  || !strcmp(mpsinputField1(mpsi), "UI") /* CPLEX extension: upper bound of integer variable given in field 4 */
1408  || !strcmp(mpsinputField1(mpsi), "SC") /* CPLEX extension: semi-continuous variable, upper bound given in field 4 */
1409  || !strcmp(mpsinputField1(mpsi), "SI") )/* CPLEX extension: semi-integer variable, upper bound given in field 4 */
1410  {
1411  if( mpsinputField3(mpsi) != NULL && mpsinputField4(mpsi) == NULL )
1412  {
1413  int l;
1414 
1415  /* check what might be missing, if field 3 is a number the bound name might be missing */
1416  for( l = (int) strlen(mpsinputField3(mpsi)) - 1; l >= 0; --l )
1417  {
1418  if( mpsinputField3(mpsi)[l] != '.' && !isdigit(mpsinputField3(mpsi)[l]) )
1419  break;
1420  }
1421 
1422  /* the bound name?! is missing */
1423  if( l < 0 )
1424  {
1425  SCIPwarningMessage(scip, "in bound section a name for value <%s> might be missing\n", mpsinputField3(mpsi));
1426 
1427  mpsinputInsertName(mpsi, "_BND_", TRUE);
1428  shifted = TRUE;
1429  }
1430  /* the bound is be missing */
1431  else
1432  {
1433  SCIPwarningMessage(scip, "in bound section a value for column <%s> is missing, assuming 0.0\n", mpsinputField3(mpsi));
1434 
1435  mpsinputInsertField4(mpsi, "0.0");
1436  shifted = TRUE;
1437  }
1438  }
1439  }
1440  else if( !strcmp(mpsinputField1(mpsi), "FR") /* free variable */
1441  || !strcmp(mpsinputField1(mpsi), "MI") /* lower bound is minus infinity */
1442  || !strcmp(mpsinputField1(mpsi), "PL") /* upper bound is plus infinity */
1443  || !strcmp(mpsinputField1(mpsi), "BV") ) /* CPLEX extension: binary variable */
1444  {
1445  if( mpsinputField2(mpsi) != NULL && mpsinputField3(mpsi) == NULL )
1446  {
1447  SCIPwarningMessage(scip, "in bound section a name for a column is missing\n");
1448 
1449  mpsinputInsertName(mpsi, "_BND_", TRUE);
1450  shifted = TRUE;
1451  }
1452  }
1453  else
1454  {
1455  mpsinputSyntaxerror(mpsi);
1456  return SCIP_OKAY;
1457  }
1458 
1459  if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
1460  break;
1461 
1462  if( *bndname == '\0' )
1463  (void)SCIPmemccpy(bndname, mpsinputField2(mpsi), '\0', MPS_MAX_NAMELEN - 1);
1464 
1465  /* Only read the first Bound in section */
1466  if( !strcmp(bndname, mpsinputField2(mpsi)) )
1467  {
1468  SCIP_VARTYPE oldvartype;
1469  SCIP_Bool infeasible;
1470 
1471  var = SCIPfindVar(scip, mpsinputField3(mpsi));
1472  /* if variable did not appear in columns section before, then it may still come in later sections (QCMATRIX, QMATRIX, SOS, ...)
1473  * thus add it as continuous variables, which has default bounds 0.0 <= x, and default cost 0.0 */
1474  if( var == NULL )
1475  {
1476  SCIP_VAR* varcpy;
1477 
1478  SCIP_CALL( SCIPcreateVar(scip, &var, mpsinputField3(mpsi), 0.0, SCIPinfinity(scip), 0.0,
1479  SCIP_VARTYPE_CONTINUOUS, !mpsi->dynamiccols, mpsi->dynamiccols, NULL, NULL, NULL, NULL, NULL) );
1480 
1481  SCIP_CALL( SCIPaddVar(scip, var) );
1482  varcpy = var;
1483  SCIP_CALL( SCIPreleaseVar(scip, &varcpy) );
1484  /* mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField3(mpsi), "bound", bndname, SCIP_VERBLEVEL_NORMAL); */
1485  }
1486  assert(var != NULL);
1487 
1488  if( mpsinputField4(mpsi) == NULL )
1489  val = 0.0;
1490  else
1491  val = atof(mpsinputField4(mpsi));
1492 
1493  /* remember variable type */
1494  oldvartype = SCIPvarGetType(var);
1495 
1496  /* If a bound of a binary variable is given, the variable is converted into an integer variable
1497  * with default bounds 0 <= x <= infinity before applying the bound. Note that integer variables
1498  * are by default assumed to be binary, but an explicit lower bound of 0 turns them into integer variables.
1499  * Only if the upper bound is explicitly set to 1, we leave the variable as a binary one.
1500  */
1501  if( oldvartype == SCIP_VARTYPE_BINARY && !((mpsinputField1(mpsi)[0] == 'U' ||
1502  (mpsinputField1(mpsi)[0] == 'F' && mpsinputField1(mpsi)[1] == 'X')) && SCIPisFeasEQ(scip, val, 1.0))
1503  && !(mpsinputField1(mpsi)[0] == 'F' && mpsinputField1(mpsi)[1] == 'X'&& SCIPisFeasEQ(scip, val, 0.0)) )
1504  {
1505  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) );
1506  assert(!infeasible);
1507 
1508  oldvartype = SCIP_VARTYPE_INTEGER;
1509  SCIP_CALL( SCIPchgVarUb(scip, var, SCIPinfinity(scip)) );
1510  }
1511 
1512  /* switch variable type to continuous before applying the bound, this is necessary for stupid non-integral
1513  * bounds on general variables, which even might lead to infeasibility
1514  */
1515  if( oldvartype != SCIP_VARTYPE_CONTINUOUS )
1516  {
1519  /* relaxing variable type */
1520  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_CONTINUOUS, &infeasible) );
1521  }
1522  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
1523 
1524  switch( mpsinputField1(mpsi)[0] )
1525  {
1526  case 'L':
1527  if( !SCIPisZero(scip, SCIPvarGetLbGlobal(var)) && SCIPisLT(scip, val, SCIPvarGetLbGlobal(var)) )
1528  {
1529  SCIPwarningMessage(scip, "Relaxing already defined lower bound %g of variable <%s> to %g not allowed.\n", SCIPvarGetLbGlobal(var), SCIPvarGetName(var), val);
1530  }
1531 
1532  SCIP_CALL( SCIPchgVarLb(scip, var, val) );
1533 
1534  if( mpsinputField1(mpsi)[1] == 'I' ) /* CPLEX extension (Integer Bound) */
1535  {
1536  if( !SCIPisFeasIntegral(scip, val) )
1537  {
1538  SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral lower bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val);
1539  }
1540  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) );
1541  /* don't assert feasibility here because the presolver will and should detect a infeasibility */
1542  }
1543  else if( oldvartype < SCIP_VARTYPE_CONTINUOUS )
1544  {
1545  if( !SCIPisFeasIntegral(scip, val) )
1546  {
1547  SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral lower bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val);
1548  }
1549  }
1550 
1551  break;
1552  case 'U':
1553  if( SCIPisGT(scip, val, SCIPvarGetUbGlobal(var)) )
1554  {
1555  SCIPwarningMessage(scip, "Relaxing already defined upper bound %g of variable <%s> to %g not allowed.\n", SCIPvarGetUbGlobal(var), SCIPvarGetName(var), val);
1556  }
1557 
1558  SCIP_CALL( SCIPchgVarUb(scip, var, val) );
1559  if( mpsinputField1(mpsi)[1] == 'I' ) /* CPLEX extension (Integer Bound) */
1560  {
1561  if( !SCIPisFeasIntegral(scip, val) )
1562  {
1563  SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral upper bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val);
1564  }
1565 
1566  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) );
1567  /* don't assert feasibility here because the presolver will and should detect an infeasibility */
1568  }
1569  else if( oldvartype < SCIP_VARTYPE_CONTINUOUS )
1570  {
1571  if( !SCIPisFeasIntegral(scip, val) )
1572  {
1573  SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral upper bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val);
1574  }
1575  }
1576  break;
1577  case 'S':
1578  assert(mpsinputField1(mpsi)[1] == 'C' || mpsinputField1(mpsi)[1] == 'I'); /* semi-continuous or semi-integer (CPLEX extension) */
1579  /* remember that variable is semi-continuous/-integer */
1580  if( semicontsize <= nsemicont )
1581  {
1582  semicontsize = SCIPcalcMemGrowSize(scip, nsemicont+1);
1583  if( semicont == NULL )
1584  {
1585  SCIP_CALL( SCIPallocBufferArray(scip, &semicont, semicontsize) );
1586  }
1587  else
1588  {
1589  SCIP_CALL( SCIPreallocBufferArray(scip, &semicont, semicontsize) );
1590  }
1591  }
1592  assert(semicont != NULL);
1593  semicont[nsemicont] = var;
1594  ++nsemicont;
1595 
1596  if( mpsinputField1(mpsi)[1] == 'I' ) /* variable is semi-integer, hence change its type to integer (the "semi" part will be handled below) */
1597  {
1598  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) );
1599  /* don't assert feasibility here because the presolver will and should detect an infeasibility */
1600  }
1601 
1602  /* if both bounds are infinite anyway, we do not need to print a warning or change the bound */
1603  if( !SCIPisInfinity(scip, val) || !SCIPisInfinity(scip, SCIPvarGetUbGlobal(var)) )
1604  {
1605  if( SCIPisGT(scip, val, SCIPvarGetUbGlobal(var)) )
1606  {
1607  SCIPwarningMessage(scip, "Relaxing already defined upper bound %g of variable <%s> to %g not allowed.\n", SCIPvarGetUbGlobal(var), SCIPvarGetName(var), val);
1608  }
1609 
1610  SCIP_CALL( SCIPchgVarUb(scip, var, val) );
1611  }
1612  break;
1613  case 'F':
1614  if( mpsinputField1(mpsi)[1] == 'X' )
1615  {
1616  SCIP_CALL( SCIPchgVarLb(scip, var, val) );
1617  SCIP_CALL( SCIPchgVarUb(scip, var, val) );
1618  }
1619  else
1620  {
1621  SCIP_CALL( SCIPchgVarLb(scip, var, -SCIPinfinity(scip)) );
1622  SCIP_CALL( SCIPchgVarUb(scip, var, +SCIPinfinity(scip)) );
1623  }
1624  break;
1625  case 'M':
1626  SCIP_CALL( SCIPchgVarLb(scip, var, -SCIPinfinity(scip)) );
1627  break;
1628  case 'P':
1629  SCIP_CALL( SCIPchgVarUb(scip, var, +SCIPinfinity(scip)) );
1630  break;
1631  case 'B' : /* CPLEX extension (Binary) */
1632  SCIP_CALL( SCIPchgVarLb(scip, var, 0.0) );
1633  SCIP_CALL( SCIPchgVarUb(scip, var, 1.0) );
1634  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
1635  /* don't assert feasibility here because the presolver will and should detect a infeasibility */
1636  break;
1637  default:
1638  mpsinputSyntaxerror(mpsi);
1639  return SCIP_OKAY;
1640  }
1641 
1642  /* switch variable type back to old type if necessary */
1643  if( oldvartype < SCIPvarGetType(var) )
1644  {
1645  SCIP_CALL( SCIPchgVarType(scip, var, oldvartype, &infeasible) );
1646  }
1647  }
1648  else
1649  {
1650  /* check for syntax error */
1651  assert(*bndname != '\0');
1652  if( strcmp(bndname, mpsinputField3(mpsi)) == 0 && shifted )
1653  {
1654  mpsinputSyntaxerror(mpsi);
1655  return SCIP_OKAY;
1656  }
1657 
1658  mpsinputEntryIgnored(scip, mpsi, "bound", mpsinputField2(mpsi), "variable", mpsinputField3(mpsi), SCIP_VERBLEVEL_NORMAL);
1659  }
1660  }
1661  mpsinputSyntaxerror(mpsi);
1662 
1663  READBOUNDS_FINISH:
1664  if( nsemicont > 0 )
1665  {
1666  SCIP_CONS* cons;
1667  SCIP_VAR* vars[2];
1668  SCIP_BOUNDTYPE boundtypes[2];
1669  SCIP_Real bounds[2];
1670  char name[SCIP_MAXSTRLEN];
1671  SCIP_Real oldlb;
1672  int i;
1673 
1674  assert(semicont != NULL);
1675 
1676  /* add bound disjunction constraints for semi-continuous and semi-integer variables */
1677  for( i = 0; i < nsemicont; ++i )
1678  {
1679  var = semicont[i];
1681 
1682  oldlb = SCIPvarGetLbGlobal(var);
1683  assert(oldlb >= 0.0);
1684 
1685  /* if no bound was specified (which we assume if we see lower bound 0.0),
1686  * then the default lower bound for a semi-continuous variable is 1.0 */
1687  if( oldlb == 0.0 )
1688  oldlb = 1.0;
1689 
1690  /* change the lower bound to 0.0 */
1691  SCIP_CALL( SCIPchgVarLb(scip, var, 0.0) );
1692 
1693  /* add a bound disjunction constraint to say var <= 0.0 or var >= oldlb */
1694  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "semicont_%s", SCIPvarGetName(var));
1695 
1696  vars[0] = var;
1697  vars[1] = var;
1698  boundtypes[0] = SCIP_BOUNDTYPE_UPPER;
1699  boundtypes[1] = SCIP_BOUNDTYPE_LOWER;
1700  bounds[0] = 0.0;
1701  bounds[1] = oldlb;
1702 
1703  retcode = SCIPcreateConsBounddisjunction(scip, &cons, name, 2, vars, boundtypes, bounds,
1704  !mpsi->dynamiccols, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, mpsi->dynamicconss, mpsi->dynamiccols, FALSE);
1705 
1706  if( retcode != SCIP_OKAY )
1707  break;
1708 
1709  SCIP_CALL( SCIPaddCons(scip, cons) );
1710 
1711  SCIPdebugMsg(scip, "add bound disjunction constraint for semi-continuity/-integrality of <%s>:\n\t", SCIPvarGetName(var));
1712  SCIPdebugPrintCons(scip, cons, NULL);
1713 
1714  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1715  }
1716  }
1717 
1718  SCIPfreeBufferArrayNull(scip, &semicont);
1719 
1720  SCIP_CALL( retcode );
1721 
1722  return SCIP_OKAY;
1723 }
1724 
1725 
1726 /** Process SOS section.
1727  *
1728  * We read the SOS section, which is a nonstandard section introduced by CPLEX.
1729  *
1730  * @note Currently we do not support the standard way of specifying SOS constraints via markers.
1731  */
1732 static
1734  MPSINPUT* mpsi, /**< mps input structure */
1735  SCIP* scip /**< SCIP data structure */
1736  )
1737 {
1738  SCIP_Bool initial;
1739  SCIP_Bool separate;
1740  SCIP_Bool enforce;
1741  SCIP_Bool check;
1742  SCIP_Bool propagate;
1743  SCIP_Bool local;
1744  SCIP_Bool dynamic;
1745  SCIP_Bool removable;
1746  char name[MPS_MAX_NAMELEN] = { '\0' };
1747  SCIP_CONS* cons = NULL;
1748  int consType = -1;
1749  int cnt = 0;
1750 
1751  SCIPdebugMsg(scip, "read SOS constraints\n");
1752 
1753  /* standard settings for SOS constraints: */
1754  initial = mpsi->initialconss;
1755  separate = TRUE;
1756  enforce = TRUE;
1757  check = TRUE;
1758  propagate = TRUE;
1759  local = FALSE;
1760  dynamic = mpsi->dynamicconss;
1761  removable = mpsi->dynamicrows;
1762 
1763  /* loop through section */
1764  while( mpsinputReadLine(mpsi) )
1765  {
1766  int type = -1;
1767 
1768  /* check if next section is found */
1769  if( mpsinputField0(mpsi) != NULL )
1770  {
1771  if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
1773  else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
1775  else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
1777  else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
1779  else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
1781  break;
1782  }
1783  if( mpsinputField1(mpsi) == NULL )
1784  {
1785  SCIPerrorMessage("empty data in a non-comment line.\n");
1786  mpsinputSyntaxerror(mpsi);
1787  return SCIP_OKAY;
1788  }
1789 
1790  /* check for new SOS set */
1791  if( strcmp(mpsinputField1(mpsi), "S1") == 0 )
1792  type = 1;
1793  if( strcmp(mpsinputField1(mpsi), "S2") == 0 )
1794  type = 2;
1795 
1796  /* add last constraint and create a new one */
1797  if( type > 0 )
1798  {
1799  assert( type == 1 || type == 2 );
1800  if( cons != NULL )
1801  {
1802  /* add last constraint */
1803  SCIP_CALL( SCIPaddCons(scip, cons) );
1804  SCIPdebugMsg(scip, "(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons));
1805  SCIPdebugPrintCons(scip, cons, NULL);
1806  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1807  }
1808 
1809  /* check name */
1810  if( mpsinputField2(mpsi) != NULL )
1811  (void)SCIPmemccpy(name, mpsinputField2(mpsi), '\0', MPS_MAX_NAMELEN - 1);
1812  else
1813  {
1814  /* create new name */
1815  (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "SOS%d", ++cnt);
1816  }
1817 
1818  /* create new SOS constraint */
1819  if( type == 1 )
1820  {
1821  /* we do not know the name of the constraint */
1822  SCIP_CALL( SCIPcreateConsSOS1(scip, &cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate,
1823  local, dynamic, removable, FALSE) );
1824  }
1825  else
1826  {
1827  assert( type == 2 );
1828  SCIP_CALL( SCIPcreateConsSOS2(scip, &cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate,
1829  local, dynamic, removable, FALSE) );
1830  }
1831  consType = type;
1832  SCIPdebugMsg(scip, "created constraint <%s> of type %d.\n", name, type);
1833  /* note: we ignore the priorities! */
1834  }
1835  else
1836  {
1837  /* otherwise we are in the section given variables */
1838  SCIP_VAR* var;
1839  SCIP_Real weight;
1840  char* endptr;
1841 
1842  if( consType != 1 && consType != 2 )
1843  {
1844  SCIPerrorMessage("missing SOS type specification.\n");
1845  mpsinputSyntaxerror(mpsi);
1846  return SCIP_OKAY;
1847  }
1848 
1849  /* get variable */
1850  var = SCIPfindVar(scip, mpsinputField1(mpsi));
1851  if( var == NULL )
1852  {
1853  /* ignore unknown variables - we would not know the type anyway */
1854  mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField1(mpsi), "SOS", name, SCIP_VERBLEVEL_NORMAL);
1855  }
1856  else
1857  {
1858  /* get weight */
1859  if( NULL == mpsinputField2(mpsi) )
1860  {
1861  SCIPerrorMessage("weight for variable <%s> not specified.\n", mpsinputField1(mpsi));
1862  mpsinputSyntaxerror(mpsi);
1863  return SCIP_OKAY;
1864  }
1865 
1866  weight = strtod(mpsinputField2(mpsi), &endptr);
1867  if( endptr == mpsinputField2(mpsi) || *endptr != '\0' )
1868  {
1869  SCIPerrorMessage("weight for variable <%s> not specified.\n", mpsinputField1(mpsi));
1870  mpsinputSyntaxerror(mpsi);
1871  return SCIP_OKAY;
1872  }
1873 
1874  /* add variable and weight */
1875  assert( consType == 1 || consType == 2 );
1876  switch( consType )
1877  {
1878  case 1:
1879  SCIP_CALL( SCIPaddVarSOS1(scip, cons, var, weight) );
1880  break;
1881  case 2:
1882  SCIP_CALL( SCIPaddVarSOS2(scip, cons, var, weight) );
1883  break;
1884  default:
1885  SCIPerrorMessage("unknown SOS type: <%d>\n", type); /* should not happen */
1886  SCIPABORT();
1887  return SCIP_INVALIDDATA; /*lint !e527*/
1888  }
1889  SCIPdebugMsg(scip, "added variable <%s> with weight %g.\n", SCIPvarGetName(var), weight);
1890  }
1891  /* check other fields */
1892  if( (mpsinputField3(mpsi) != NULL && *mpsinputField3(mpsi) != '\0' ) ||
1893  (mpsinputField4(mpsi) != NULL && *mpsinputField4(mpsi) != '\0' ) ||
1894  (mpsinputField5(mpsi) != NULL && *mpsinputField5(mpsi) != '\0' ) )
1895  {
1896  SCIPwarningMessage(scip, "ignoring data in fields 3-5 <%s> <%s> <%s>.\n",
1897  mpsinputField3(mpsi), mpsinputField4(mpsi), mpsinputField5(mpsi));
1898  }
1899  }
1900  }
1901 
1902  if( cons != NULL )
1903  {
1904  /* add last constraint */
1905  SCIP_CALL( SCIPaddCons(scip, cons) );
1906  SCIPdebugMsg(scip, "(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons));
1907  SCIPdebugPrintCons(scip, cons, NULL);
1908  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1909  }
1910 
1911  return SCIP_OKAY;
1912 }
1913 
1914 
1915 /** Process QMATRIX or QUADOBJ section.
1916  *
1917  * - We read the QMATRIX or QUADOBJ section, which is a nonstandard section introduced by CPLEX.
1918  * - We create a quadratic constraint for this matrix and add a variable to the objective to
1919  * represent the value of the QMATRIX.
1920  * - For a QMATRIX, we expect that both lower and upper diagonal elements are given and every
1921  * coefficient has to be divided by 2.0.
1922  * - For a QUADOBJ, we expect that only the upper diagonal elements are given and thus only
1923  * coefficients on the diagonal have to be divided by 2.0.
1924  */
1925 static
1927  MPSINPUT* mpsi, /**< mps input structure */
1928  SCIP_Bool isQuadObj, /**< whether we actually read a QUADOBJ section */
1929  SCIP* scip /**< SCIP data structure */
1930  )
1931 {
1932  SCIP_VAR** quadvars1;
1933  SCIP_VAR** quadvars2;
1934  SCIP_Real* quadcoefs;
1935  SCIP_RETCODE retcode;
1936  int cnt = 0; /* number of qmatrix elements processed so far */
1937  int size; /* size of quad* arrays */
1938 
1939  SCIPdebugMsg(scip, "read %s objective\n", isQuadObj ? "QUADOBJ" : "QMATRIX");
1940 
1941  retcode = SCIP_OKAY;
1942 
1943  size = 1;
1944  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars1, size) );
1945  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars2, size) );
1946  SCIP_CALL( SCIPallocBufferArray(scip, &quadcoefs, size) );
1947 
1948  /* loop through section */
1949  while( mpsinputReadLine(mpsi) )
1950  {
1951  /* otherwise we are in the section given variables */
1952  SCIP_VAR* var1;
1953  SCIP_VAR* var2;
1954  SCIP_Real coef;
1955 
1956  /* check if next section is found */
1957  if( mpsinputField0(mpsi) != NULL )
1958  {
1959  if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
1961  else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
1963  else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
1965  break;
1966  }
1967  if( mpsinputField1(mpsi) == NULL && mpsinputField2(mpsi) == NULL )
1968  {
1969  SCIPerrorMessage("empty data in a non-comment line.\n");
1970  mpsinputSyntaxerror(mpsi);
1971  SCIPfreeBufferArray(scip, &quadvars1);
1972  SCIPfreeBufferArray(scip, &quadvars2);
1973  SCIPfreeBufferArray(scip, &quadcoefs);
1974  return SCIP_OKAY;
1975  }
1976 
1977  /* get first variable */
1978  var1 = SCIPfindVar(scip, mpsinputField1(mpsi));
1979  if( var1 == NULL )
1980  {
1981  /* ignore unknown variables - we would not know the type anyway */
1982  mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField1(mpsi), "QMatrix", "QMATRIX", SCIP_VERBLEVEL_NORMAL);
1983  }
1984  else
1985  {
1986  int k;
1987  for( k = 1; k <= 2; ++k )
1988  {
1989  /* get second variable */
1990  var2 = SCIPfindVar(scip, k == 1 ? mpsinputField2(mpsi) : mpsinputField4(mpsi));
1991  if( var2 == NULL )
1992  {
1993  /* ignore unknown variables - we would not know the type anyway */
1994  mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField2(mpsi), "QMatrix", "QMATRIX", SCIP_VERBLEVEL_NORMAL);
1995  }
1996  else
1997  {
1998  const char* field;
1999  char* endptr;
2000 
2001  /* get coefficient */
2002  field = (k == 1 ? mpsinputField3(mpsi) : mpsinputField5(mpsi));
2003  if( NULL == field )
2004  {
2005  SCIPerrorMessage("coefficient of term <%s>*<%s> not specified.\n", SCIPvarGetName(var1), SCIPvarGetName(var2));
2006  mpsinputSyntaxerror(mpsi);
2007  SCIPfreeBufferArray(scip, &quadvars1);
2008  SCIPfreeBufferArray(scip, &quadvars2);
2009  SCIPfreeBufferArray(scip, &quadcoefs);
2010  return SCIP_OKAY;
2011  }
2012 
2013  coef = strtod(field, &endptr);
2014  if( endptr == field || *endptr != '\0' )
2015  {
2016  SCIPerrorMessage("coefficient of term <%s>*<%s> not specified.\n", SCIPvarGetName(var1), SCIPvarGetName(var2));
2017  mpsinputSyntaxerror(mpsi);
2018  SCIPfreeBufferArray(scip, &quadvars1);
2019  SCIPfreeBufferArray(scip, &quadvars2);
2020  SCIPfreeBufferArray(scip, &quadcoefs);
2021  return SCIP_OKAY;
2022  }
2023 
2024  /* store variables and coefficient */
2025  if( cnt >= size )
2026  {
2027  int newsize = SCIPcalcMemGrowSize(scip, size+1);
2028  assert(newsize > size);
2029  SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars1, newsize) );
2030  SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars2, newsize) );
2031  SCIP_CALL( SCIPreallocBufferArray(scip, &quadcoefs, newsize) );
2032  size = newsize;
2033  }
2034  assert(cnt < size);
2035  quadvars1[cnt] = var1;
2036  quadvars2[cnt] = var2;
2037  quadcoefs[cnt] = coef;
2038 
2039  /* diagonal elements have to be divided by 2.0
2040  * in a QMATRIX section also off-diagonal have to be divided by 2.0, since both lower and upper diagonal elements are given
2041  */
2042  if( var1 == var2 || !isQuadObj )
2043  quadcoefs[cnt] /= 2.0;
2044  ++cnt;
2045 
2046  SCIPdebugMsg(scip, "stored term %g*<%s>*<%s>.\n", coef, SCIPvarGetName(var1), SCIPvarGetName(var2));
2047  }
2048 
2049  if( mpsinputField4(mpsi) == NULL || *mpsinputField4(mpsi) == '\0' )
2050  break;
2051 
2052  if( mpsinputField5(mpsi) == NULL || *mpsinputField5(mpsi) == '\0' )
2053  {
2054  /* ignore unknown variables - we would not know the type anyway */
2055  mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField4(mpsi), "QMatrix", "QMATRIX", SCIP_VERBLEVEL_NORMAL);
2056  break;
2057  }
2058  }
2059  }
2060  }
2061 
2062  /* add constraint */
2063  if( cnt )
2064  {
2065  SCIP_Bool initial, separate, enforce, check, propagate;
2066  SCIP_Bool local, modifiable, dynamic, removable;
2067  SCIP_CONS* cons = NULL;
2068  SCIP_VAR* qmatrixvar = NULL;
2069  SCIP_Real lhs, rhs;
2070  SCIP_Real minusone = -1.0;
2071 
2072  /* determine settings; note that reading/{initialconss,dynamicconss,dynamicrows,dynamiccols} apply only to model
2073  * constraints and variables, not to an auxiliary objective constraint (otherwise it can happen that an auxiliary
2074  * objective variable is loose with infinite best bound, triggering the problem that an LP that is unbounded
2075  * because of loose variables with infinite best bound cannot be solved)
2076  */
2077  initial = TRUE;
2078  separate = TRUE;
2079  enforce = TRUE;
2080  check = TRUE;
2081  propagate = TRUE;
2082  local = FALSE;
2083  modifiable = FALSE;
2084  dynamic = FALSE;
2085  removable = FALSE;
2086 
2087  SCIP_CALL( SCIPcreateVar(scip, &qmatrixvar, "qmatrixvar", -SCIPinfinity(scip), SCIPinfinity(scip), 1.0,
2089  SCIP_CALL( SCIPaddVar(scip, qmatrixvar) );
2090 
2092  {
2093  lhs = -SCIPinfinity(scip);
2094  rhs = 0.0;
2095  }
2096  else
2097  {
2098  lhs = 0.0;
2099  rhs = SCIPinfinity(scip);
2100  }
2101 
2102  retcode = SCIPcreateConsQuadratic(scip, &cons, "qmatrix", 1, &qmatrixvar, &minusone, cnt, quadvars1, quadvars2, quadcoefs, lhs, rhs,
2103  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable);
2104 
2105  if( retcode == SCIP_OKAY )
2106  {
2107  SCIP_CALL( SCIPaddCons(scip, cons) );
2108  SCIPdebugMsg(scip, "(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons));
2109  SCIPdebugPrintCons(scip, cons, NULL);
2110 
2111  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
2112  SCIP_CALL( SCIPreleaseVar(scip, &qmatrixvar) );
2113  }
2114  }
2115  else
2116  {
2117  SCIPwarningMessage(scip, "%s section has no entries.\n", isQuadObj ? "QUADOBJ" : "QMATRIX");
2118  }
2119 
2120  SCIPfreeBufferArray(scip, &quadvars1);
2121  SCIPfreeBufferArray(scip, &quadvars2);
2122  SCIPfreeBufferArray(scip, &quadcoefs);
2123 
2124  SCIP_CALL( retcode );
2125 
2126  return SCIP_OKAY;
2127 }
2128 
2129 
2130 /** Process QCMATRIX section.
2131  *
2132  * We read the QCMATRIX section, which is a nonstandard section introduced by CPLEX.
2133  *
2134  * We replace the corresponding linear constraint by a quadratic constraint which contains the
2135  * original linear constraint plus the quadratic part specified in the QCMATRIX.
2136  */
2137 static
2139  MPSINPUT* mpsi, /**< mps input structure */
2140  SCIP* scip /**< SCIP data structure */
2141  )
2142 {
2143  SCIP_CONS* lincons; /* the linear constraint that was added for the corresponding row */
2144  SCIP_VAR** quadvars1;
2145  SCIP_VAR** quadvars2;
2146  SCIP_Real* quadcoefs;
2147  SCIP_RETCODE retcode;
2148  int cnt = 0; /* number of qcmatrix elements processed so far */
2149  int size; /* size of quad* arrays */
2150 
2151  if( mpsinputField1(mpsi) == NULL )
2152  {
2153  SCIPerrorMessage("no row name in QCMATRIX line.\n");
2154  mpsinputSyntaxerror(mpsi);
2155  return SCIP_OKAY;
2156  }
2157 
2158  retcode = SCIP_OKAY;
2159 
2160  SCIPdebugMsg(scip, "read QCMATRIX section for row <%s>\n", mpsinputField1(mpsi));
2161 
2162  lincons = SCIPfindCons(scip, mpsinputField1(mpsi));
2163  if( lincons == NULL )
2164  {
2165  SCIPerrorMessage("no row under name <%s> processed so far.\n");
2166  mpsinputSyntaxerror(mpsi);
2167  return SCIP_OKAY;
2168  }
2169 
2170  size = 1;
2171  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars1, size) );
2172  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars2, size) );
2173  SCIP_CALL( SCIPallocBufferArray(scip, &quadcoefs, size) );
2174 
2175  /* loop through section */
2176  while( mpsinputReadLine(mpsi) )
2177  {
2178  /* otherwise we are in the section given variables */
2179  SCIP_VAR* var1;
2180  SCIP_VAR* var2;
2181  SCIP_Real coef;
2182 
2183  /* check if next section is found */
2184  if( mpsinputField0(mpsi) != NULL )
2185  {
2186  if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
2188  else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
2190  else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
2192  else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
2194  else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
2196  break;
2197  }
2198  if( mpsinputField1(mpsi) == NULL && mpsinputField2(mpsi) == NULL )
2199  {
2200  SCIPerrorMessage("empty data in a non-comment line.\n");
2201  mpsinputSyntaxerror(mpsi);
2202 
2203  goto TERMINATE;
2204  }
2205 
2206  /* get first variable */
2207  var1 = SCIPfindVar(scip, mpsinputField1(mpsi));
2208  if( var1 == NULL )
2209  {
2210  /* ignore unknown variables - we would not know the type anyway */
2211  mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField1(mpsi), "QCMatrix", SCIPconsGetName(lincons), SCIP_VERBLEVEL_NORMAL);
2212  }
2213  else
2214  {
2215  /* get second variable */
2216  var2 = SCIPfindVar(scip, mpsinputField2(mpsi));
2217  if( var2 == NULL )
2218  {
2219  /* ignore unknown variables - we would not know the type anyway */
2220  mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField2(mpsi), "QCMatrix", SCIPconsGetName(lincons), SCIP_VERBLEVEL_NORMAL);
2221  }
2222  else
2223  {
2224  char* endptr;
2225  if( mpsinputField3(mpsi) == NULL )
2226  {
2227  SCIPerrorMessage("coefficient of term <%s>*<%s> not specified.\n", mpsinputField1(mpsi), mpsinputField2(mpsi));
2228  mpsinputSyntaxerror(mpsi);
2229 
2230  goto TERMINATE;
2231  }
2232 
2233  /* get coefficient */
2234  coef = strtod(mpsinputField3(mpsi), &endptr);
2235  if( endptr == mpsinputField3(mpsi) || *endptr != '\0' )
2236  {
2237  SCIPerrorMessage("coefficient of term <%s>*<%s> not specified.\n", mpsinputField1(mpsi), mpsinputField2(mpsi));
2238  mpsinputSyntaxerror(mpsi);
2239 
2240  goto TERMINATE;
2241  }
2242 
2243  /* store variables and coefficient */
2244  if( cnt >= size )
2245  {
2246  int newsize = SCIPcalcMemGrowSize(scip, size+1);
2247  assert(newsize > size);
2248  SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars1, newsize) );
2249  SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars2, newsize) );
2250  SCIP_CALL( SCIPreallocBufferArray(scip, &quadcoefs, newsize) );
2251  size = newsize;
2252  }
2253  assert(cnt < size);
2254  quadvars1[cnt] = var1;
2255  quadvars2[cnt] = var2;
2256  quadcoefs[cnt] = coef;
2257  ++cnt;
2258 
2259  SCIPdebugMsg(scip, "stored term %g*<%s>*<%s>.\n", coef, SCIPvarGetName(var1), SCIPvarGetName(var2));
2260 
2261  /* check other fields */
2262  if( (mpsinputField4(mpsi) != NULL && *mpsinputField4(mpsi) != '\0' ) ||
2263  (mpsinputField5(mpsi) != NULL && *mpsinputField5(mpsi) != '\0' ) )
2264  {
2265  SCIPwarningMessage(scip, "ignoring data in fields 4 and 5 <%s> <%s>.\n", mpsinputField4(mpsi), mpsinputField5(mpsi));
2266  }
2267  }
2268  }
2269  }
2270 
2271  /* replace linear constraint by quadratic constraint */
2272  if( cnt )
2273  {
2274  SCIP_CONS* cons = NULL;
2275 
2276  retcode = SCIPcreateConsQuadratic(scip, &cons, SCIPconsGetName(lincons),
2277  SCIPgetNVarsLinear(scip, lincons), SCIPgetVarsLinear(scip, lincons), SCIPgetValsLinear(scip, lincons),
2278  cnt, quadvars1, quadvars2, quadcoefs, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons),
2279  SCIPconsIsInitial(lincons), SCIPconsIsSeparated(lincons), SCIPconsIsEnforced(lincons), SCIPconsIsChecked(lincons),
2280  SCIPconsIsPropagated(lincons), SCIPconsIsLocal(lincons), SCIPconsIsModifiable(lincons), SCIPconsIsDynamic(lincons),
2281  SCIPconsIsRemovable(lincons));
2282 
2283  if( retcode != SCIP_OKAY )
2284  goto TERMINATE;
2285 
2286  SCIP_CALL( SCIPaddCons(scip, cons) );
2287  SCIPdebugMsg(scip, "(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons));
2288  SCIPdebugPrintCons(scip, cons, NULL);
2289 
2290  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
2291 
2292  SCIP_CALL( SCIPdelCons(scip, lincons) );
2293  }
2294  else
2295  {
2296  SCIPwarningMessage(scip, "QCMATRIX section has no entries.\n");
2297  }
2298 
2299  TERMINATE:
2300  SCIPfreeBufferArray(scip, &quadcoefs);
2301  SCIPfreeBufferArray(scip, &quadvars2);
2302  SCIPfreeBufferArray(scip, &quadvars1);
2303 
2304  SCIP_CALL( retcode );
2305 
2306  return SCIP_OKAY;
2307 }
2308 
2309 
2310 /** Process INDICATORS section.
2311  *
2312  * We read the INDICATORS section, which is a nonstandard section introduced by CPLEX.
2313  * Note that CPLEX does not allow ranged rows.
2314  *
2315  * If the linear constraints are equations or ranged rows, we generate two indicator
2316  * constraints.
2317  *
2318  * The section has to come after the QMATRIX* sections.
2319  */
2320 static
2322  MPSINPUT* mpsi, /**< mps input structure */
2323  SCIP* scip /**< SCIP data structure */
2324  )
2325 {
2326  SCIP_Bool initial;
2327  SCIP_Bool separate;
2328  SCIP_Bool enforce;
2329  SCIP_Bool check;
2330  SCIP_Bool propagate;
2331  SCIP_Bool local;
2332  SCIP_Bool dynamic;
2333  SCIP_Bool removable;
2334  SCIP_Bool stickingatnode;
2335  char name[MPS_MAX_NAMELEN] = { '\0' };
2336 
2337  SCIPdebugMsg(scip, "read INDICATORS constraints\n");
2338 
2339  /* standard settings for indicator constraints: */
2340  initial = mpsi->initialconss;
2341  separate = TRUE;
2342  enforce = TRUE;
2343  check = TRUE;
2344  propagate = TRUE;
2345  local = FALSE;
2346  dynamic = mpsi->dynamicconss;
2347  removable = mpsi->dynamicrows;
2348  stickingatnode = FALSE;
2349 
2350  /* loop through section */
2351  while( mpsinputReadLine(mpsi) )
2352  {
2353  SCIP_CONSHDLR* conshdlr;
2354  SCIP_VARTYPE slackvartype;
2355  SCIP_CONS* cons;
2356  SCIP_CONS* lincons;
2357  SCIP_VAR* binvar;
2358  SCIP_VAR* slackvar;
2359  SCIP_Real lhs;
2360  SCIP_Real rhs;
2361  SCIP_Real sign;
2362  SCIP_VAR** linvars;
2363  SCIP_Real* linvals;
2364  int nlinvars;
2365  int i;
2366 
2367  /* check if next section is found */
2368  if( mpsinputField0(mpsi) != NULL )
2369  {
2370  if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
2372  break;
2373  }
2374  if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL )
2375  {
2376  SCIPerrorMessage("empty data in a non-comment line.\n");
2377  mpsinputSyntaxerror(mpsi);
2378  return SCIP_OKAY;
2379  }
2380 
2381  /* check for new indicator constraint */
2382  if( strcmp(mpsinputField1(mpsi), "IF") != 0 )
2383  {
2384  SCIPerrorMessage("Indicator constraints need to be introduced by 'IF' in column 1.\n");
2385  mpsinputSyntaxerror(mpsi);
2386  return SCIP_OKAY;
2387  }
2388 
2389  /* get linear constraint (row) */
2390  lincons = SCIPfindCons(scip, mpsinputField2(mpsi));
2391  if( lincons == NULL )
2392  {
2393  SCIPerrorMessage("row <%s> does not exist.\n", mpsinputField2(mpsi));
2394  mpsinputSyntaxerror(mpsi);
2395  return SCIP_OKAY;
2396  }
2397 
2398  /* check whether constraint is really linear */
2399  conshdlr = SCIPconsGetHdlr(lincons);
2400  if( strcmp(SCIPconshdlrGetName(conshdlr), "linear") != 0 )
2401  {
2402  SCIPerrorMessage("constraint <%s> is not linear.\n", mpsinputField2(mpsi));
2403  mpsinputSyntaxerror(mpsi);
2404  return SCIP_OKAY;
2405  }
2406 
2407  /* get binary variable */
2408  binvar = SCIPfindVar(scip, mpsinputField3(mpsi));
2409  if( binvar == NULL )
2410  {
2411  SCIPerrorMessage("binary variable <%s> does not exist.\n", mpsinputField3(mpsi));
2412  mpsinputSyntaxerror(mpsi);
2413  return SCIP_OKAY;
2414  }
2415 
2416  /* check type */
2417  if( SCIPvarGetType(binvar) != SCIP_VARTYPE_BINARY )
2418  {
2419  SCIPerrorMessage("variable <%s> is not binary.\n", mpsinputField3(mpsi));
2420  mpsinputSyntaxerror(mpsi);
2421  return SCIP_OKAY;
2422  }
2423 
2424  /* check whether we need the negated variable */
2425  if( mpsinputField4(mpsi) != NULL )
2426  {
2427  if( *mpsinputField4(mpsi) == '0' )
2428  {
2429  SCIP_VAR* var;
2430  SCIP_CALL( SCIPgetNegatedVar(scip, binvar, &var) );
2431  binvar = var;
2432  assert( binvar != NULL );
2433  }
2434  else
2435  {
2436  if( *mpsinputField4(mpsi) != '1' )
2437  {
2438  SCIPerrorMessage("binary variable <%s> can only take values 0/1 (%s).\n", mpsinputField3(mpsi), mpsinputField4(mpsi));
2439  mpsinputSyntaxerror(mpsi);
2440  return SCIP_OKAY;
2441  }
2442  }
2443  }
2444 
2445  /* check lhs/rhs */
2446  lhs = SCIPgetLhsLinear(scip, lincons);
2447  rhs = SCIPgetRhsLinear(scip, lincons);
2448  nlinvars = SCIPgetNVarsLinear(scip, lincons);
2449  linvars = SCIPgetVarsLinear(scip, lincons);
2450  linvals = SCIPgetValsLinear(scip, lincons);
2451 
2452  sign = -1.0;
2453  if( !SCIPisInfinity(scip, -lhs) )
2454  {
2455  if( SCIPisInfinity(scip, rhs) )
2456  sign = 1.0;
2457  else
2458  {
2459  /* create second indicator constraint */
2460  SCIP_VAR** vars;
2461  SCIP_Real* vals;
2462  SCIP_RETCODE retcode;
2463 
2464  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nlinvars) );
2465  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nlinvars) );
2466  for( i = 0; i < nlinvars; ++i )
2467  {
2468  vars[i] = linvars[i];
2469  vals[i] = -linvals[i];
2470  }
2471 
2472  /* create new name */
2473  (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "indlhs_%s", SCIPconsGetName(lincons));
2474 
2475  /* create indicator constraint */
2476  retcode = SCIPcreateConsIndicator(scip, &cons, name, binvar, nlinvars, vars, vals, -lhs,
2477  initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode);
2478 
2479  if( retcode == SCIP_OKAY )
2480  {
2481  SCIP_CALL( SCIPaddCons(scip, cons) );
2482  SCIPdebugMsg(scip, "created indicator constraint <%s>\n", mpsinputField2(mpsi));
2483  SCIPdebugPrintCons(scip, cons, NULL);
2484  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
2485  }
2486 
2487  SCIPfreeBufferArray(scip, &vals);
2488  SCIPfreeBufferArray(scip, &vars);
2489 
2490  SCIP_CALL( retcode );
2491  }
2492  }
2493 
2494  /* check if slack variable can be made implicitly integer */
2495  slackvartype = SCIP_VARTYPE_IMPLINT;
2496  for (i = 0; i < nlinvars; ++i)
2497  {
2498  if( ! SCIPvarIsIntegral(linvars[i]) || ! SCIPisIntegral(scip, linvals[i]) )
2499  {
2500  slackvartype = SCIP_VARTYPE_CONTINUOUS;
2501  break;
2502  }
2503  }
2504 
2505  /* create slack variable */
2506  if ( ! SCIPisInfinity(scip, -lhs) )
2507  (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "indslack_indrhs_%s", SCIPconsGetName(lincons));
2508  else
2509  (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "indslack_%s", SCIPconsGetName(lincons));
2510  SCIP_CALL( SCIPcreateVar(scip, &slackvar, name, 0.0, SCIPinfinity(scip), 0.0, slackvartype, TRUE, FALSE,
2511  NULL, NULL, NULL, NULL, NULL) );
2512 
2513  /* add slack variable */
2514  SCIP_CALL( SCIPaddVar(scip, slackvar) );
2515  SCIP_CALL( SCIPaddCoefLinear(scip, lincons, slackvar, sign) );
2516 
2517  /* correct linear constraint and create new name */
2518  if ( ! SCIPisInfinity(scip, -lhs) )
2519  {
2520  /* we have added lhs above and only need the rhs */
2521  SCIP_CALL( SCIPchgLhsLinear(scip, lincons, -SCIPinfinity(scip) ) );
2522  (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "indrhs_%s", SCIPconsGetName(lincons));
2523  }
2524  else
2525  (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "ind_%s", SCIPconsGetName(lincons));
2526 
2527  /* create indicator constraint */
2528  SCIP_CALL( SCIPcreateConsIndicatorLinCons(scip, &cons, name, binvar, lincons, slackvar,
2529  initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
2530 
2531  SCIP_CALL( SCIPaddCons(scip, cons) );
2532  SCIPdebugMsg(scip, "created indicator constraint <%s>", mpsinputField2(mpsi));
2533  SCIPdebugPrintCons(scip, cons, NULL);
2534  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
2535  SCIP_CALL( SCIPreleaseVar(scip, &slackvar) );
2536  }
2537 
2538  return SCIP_OKAY;
2539 }
2540 
2541 
2542 /** Read LP in "MPS File Format".
2543  *
2544  * A specification of the MPS format can be found at
2545  *
2546  * http://plato.asu.edu/ftp/mps_format.txt,
2547  * ftp://ftp.caam.rice.edu/pub/people/bixby/miplib/mps_format,
2548  *
2549  * and in the
2550  *
2551  * CPLEX Reference Manual
2552  *
2553  * This routine should read all valid MPS format files.
2554  * What it will not do, is to find all cases where a file is ill formed.
2555  * If this happens it may complain and read nothing or read "something".
2556  */
2557 static
2559  SCIP* scip, /**< SCIP data structure */
2560  const char* filename, /**< name of the input file */
2561  const char*** varnames, /**< storage for the variable names, or NULL */
2562  const char*** consnames, /**< storage for the constraint names, or NULL */
2563  int* varnamessize, /**< the size of the variable names storage, or NULL */
2564  int* consnamessize, /**< the size of the constraint names storage, or NULL */
2565  int* nvarnames, /**< the number of stored variable names, or NULL */
2566  int* nconsnames /**< the number of stored constraint names, or NULL */
2567  )
2568 {
2569  SCIP_FILE* fp;
2570  MPSINPUT* mpsi;
2571  SCIP_RETCODE retcode;
2572  SCIP_Bool error = TRUE;
2573 
2574  assert(scip != NULL);
2575  assert(filename != NULL);
2576 
2577  fp = SCIPfopen(filename, "r");
2578  if( fp == NULL )
2579  {
2580  SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
2581  SCIPprintSysError(filename);
2582  return SCIP_NOFILE;
2583  }
2584 
2585  SCIP_CALL( mpsinputCreate(scip, &mpsi, fp) );
2586 
2587  SCIP_CALL_TERMINATE( retcode, readName(scip, mpsi), TERMINATE );
2588 
2589  SCIP_CALL_TERMINATE( retcode, SCIPcreateProb(scip, mpsi->probname, NULL, NULL, NULL, NULL, NULL, NULL, NULL), TERMINATE );
2590 
2591  if( mpsinputSection(mpsi) == MPS_OBJSEN )
2592  {
2593  SCIP_CALL_TERMINATE( retcode, readObjsen(scip, mpsi), TERMINATE );
2594  }
2595  if( mpsinputSection(mpsi) == MPS_OBJNAME )
2596  {
2597  SCIP_CALL_TERMINATE( retcode, readObjname(scip, mpsi), TERMINATE );
2598  }
2599  while( mpsinputSection(mpsi) == MPS_ROWS
2600  || mpsinputSection(mpsi) == MPS_USERCUTS
2601  || mpsinputSection(mpsi) == MPS_LAZYCONS )
2602  {
2603  SCIP_CALL_TERMINATE( retcode, readRows(mpsi, scip, consnames, consnamessize, nconsnames), TERMINATE );
2604  }
2605  if( mpsinputSection(mpsi) == MPS_COLUMNS )
2606  {
2607  SCIP_CALL_TERMINATE( retcode, readCols(mpsi, scip, varnames, varnamessize, nvarnames), TERMINATE );
2608  }
2609  if( mpsinputSection(mpsi) == MPS_RHS )
2610  {
2611  SCIP_CALL_TERMINATE( retcode, readRhs(mpsi, scip), TERMINATE );
2612  }
2613  if( mpsinputSection(mpsi) == MPS_RANGES )
2614  {
2615  SCIP_CALL_TERMINATE( retcode, readRanges(mpsi, scip), TERMINATE );
2616  }
2617  if( mpsinputSection(mpsi) == MPS_BOUNDS )
2618  {
2619  SCIP_CALL_TERMINATE( retcode, readBounds(mpsi, scip), TERMINATE );
2620  }
2621  if( mpsinputSection(mpsi) == MPS_SOS )
2622  {
2623  SCIP_CALL_TERMINATE( retcode, readSOS(mpsi, scip), TERMINATE );
2624  }
2625  while( mpsinputSection(mpsi) == MPS_QCMATRIX )
2626  {
2627  SCIP_CALL_TERMINATE( retcode, readQCMatrix(mpsi, scip), TERMINATE );
2628  }
2629  if( mpsinputSection(mpsi) == MPS_QMATRIX )
2630  {
2631  SCIP_CALL_TERMINATE( retcode, readQMatrix(mpsi, FALSE, scip), TERMINATE );
2632  }
2633  if( mpsinputSection(mpsi) == MPS_QUADOBJ )
2634  {
2635  SCIP_CALL_TERMINATE( retcode, readQMatrix(mpsi, TRUE, scip), TERMINATE );
2636  }
2637  while( mpsinputSection(mpsi) == MPS_QCMATRIX )
2638  {
2639  SCIP_CALL_TERMINATE( retcode, readQCMatrix(mpsi, scip), TERMINATE );
2640  }
2641  if( mpsinputSection(mpsi) == MPS_INDICATORS )
2642  {
2643  SCIP_CALL_TERMINATE( retcode, readIndicators(mpsi, scip), TERMINATE );
2644  }
2645  if( mpsinputSection(mpsi) != MPS_ENDATA )
2646  mpsinputSyntaxerror(mpsi);
2647 
2648  SCIPfclose(fp);
2649 
2650  error = mpsinputHasError(mpsi);
2651 
2652  if( !error )
2653  {
2654  SCIP_CALL_TERMINATE( retcode, SCIPsetObjsense(scip, mpsinputObjsense(mpsi)), TERMINATE );
2655  }
2656 
2657  TERMINATE:
2658  mpsinputFree(scip, &mpsi);
2659 
2660  if( error )
2661  return SCIP_READERROR;
2662  else
2663  return SCIP_OKAY;
2664 }
2665 
2666 /*
2667  * local methods for writing problem
2668  */
2669 
2670 /** gets the key (i.e. the name) of the given namefreq */
2671 static
2672 SCIP_DECL_HASHGETKEY(hashGetKeyNamefreq)
2673 { /*lint --e{715}*/
2674  CONSNAMEFREQ* consnamefreq = (CONSNAMEFREQ*)elem;
2675 
2676  assert(consnamefreq != NULL);
2677  assert(consnamefreq->consname != NULL);
2678 
2679  return (void*)consnamefreq->consname;
2680 }
2681 
2682 /** returns TRUE iff both keys (i.e. strings) are equal up to max length*/
2683 static
2684 SCIP_DECL_HASHKEYEQ(hashKeyEqString)
2685 { /*lint --e{715}*/
2686  const char* string1 = (const char*)key1;
2687  const char* string2 = (const char*)key2;
2688 
2689  return (strncmp(string1, string2, MPS_MAX_NAMELEN - 1) == 0);
2690 }
2691 
2692 /** hash key retrieval function for variables */
2693 static
2694 SCIP_DECL_HASHGETKEY(hashGetKeyVar)
2695 { /*lint --e{715}*/
2696  return elem;
2697 }
2698 
2699 /** returns TRUE iff the indices of both variables are equal */
2700 static
2701 SCIP_DECL_HASHKEYEQ(hashKeyEqVar)
2702 { /*lint --e{715}*/
2703  if( key1 == key2 )
2704  return TRUE;
2705  return FALSE;
2706 }
2707 
2708 /** returns the hash value of the key */
2709 static
2710 SCIP_DECL_HASHKEYVAL(hashKeyValVar)
2711 { /*lint --e{715}*/
2712  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
2713  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
2714 }
2715 
2716 
2717 /** computes the field width such that the output file is nicely arranged */
2718 static
2719 unsigned int computeFieldWidth(
2720  unsigned int width /**< required width */
2721  )
2722 {
2723  width = MAX(8u, width);
2724  return MIN(MPS_MAX_FIELDLEN, width);
2725 }
2726 
2727 
2728 /** output two strings in columns 1 and 2 with computed widths */
2729 static
2731  SCIP* scip, /**< SCIP data structure */
2732  FILE* file, /**< output file (or NULL for standard output) */
2733  const char* col1, /**< column 1 */
2734  const char* col2, /**< column 2 */
2735  unsigned int maxnamelen /**< maximum name length */
2736  )
2737 {
2738  unsigned int fieldwidth;
2739  char format[32];
2740 
2741  assert( scip != NULL );
2742  assert( col1 != NULL );
2743  assert( col2 != NULL );
2744  assert( strlen(col1) < MPS_MAX_NAMELEN );
2745  assert( strlen(col2) < MPS_MAX_VALUELEN );
2746  assert( maxnamelen > 0 );
2747 
2748  fieldwidth = computeFieldWidth(maxnamelen);
2749  (void) SCIPsnprintf(format, 32," %%-%ds %%%ds ", fieldwidth, MPS_MAX_VALUELEN - 1);
2750 
2751  SCIPinfoMessage(scip, file, (const char *)format, col1, col2);
2752 }
2753 
2754 /** output two strings in columns 1 (width 2) and 2 (width 8) */
2755 static
2757  SCIP* scip, /**< SCIP data structure */
2758  FILE* file, /**< output file (or NULL for standard output) */
2759  const char* col1, /**< column 1 */
2760  const char* col2, /**< column 2 */
2761  int maxnamelen /**< maximum name length (-1 if irrelevant) */
2762  )
2763 {
2764  unsigned int fieldwidth;
2765  char format[32];
2766 
2767  assert( scip != NULL );
2768  assert( col1 != NULL );
2769  assert( col2 != NULL );
2770  assert( strlen(col1) <= 2 );
2771  assert( strlen(col2) < MPS_MAX_NAMELEN );
2772  assert( maxnamelen == -1 || maxnamelen > 0 );
2773 
2774  if( maxnamelen < 0 )
2775  {
2776  /* format does not matter */
2777  (void) SCIPsnprintf(format, 32, " %%-2.2s %%-s ");
2778  }
2779  else
2780  {
2781  fieldwidth = computeFieldWidth((unsigned int) maxnamelen);
2782  (void) SCIPsnprintf(format, 32, " %%-2.2s %%-%ds ", fieldwidth);
2783  }
2784 
2785  SCIPinfoMessage(scip, file, (const char*)format, col1, col2);
2786 }
2787 
2788 /** prints the given data as column entry */
2789 static
2791  SCIP* scip, /**< SCIP data structure */
2792  FILE* file, /**< output file (or NULL for standard output) */
2793  const char* varname, /**< variable name */
2794  const char* consname, /**< constraint name */
2795  SCIP_Real value, /**< value to display */
2796  int* recordcnt, /**< pointer to store the number of records per line */
2797  unsigned int maxnamelen /**< maximum name length */
2798  )
2799 {
2800  char valuestr[MPS_MAX_VALUELEN] = { '\0' };
2801 
2802  assert( scip != NULL );
2803  assert( recordcnt != NULL );
2804  assert( *recordcnt >= 0 && *recordcnt < 2 );
2805 
2806  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", value);
2807 
2808  if( *recordcnt == 0 )
2809  {
2810  /* start new line with an empty first column and the variable name in the second column */
2811  printStart(scip, file, "", varname, (int) maxnamelen);
2812  *recordcnt = 0;
2813  }
2814 
2815  printRecord(scip, file, consname, valuestr, maxnamelen);
2816  (*recordcnt)++;
2817 
2818  if( *recordcnt == 2 )
2819  {
2820  /* each line can have at most two records */
2821  SCIPinfoMessage(scip, file, "\n");
2822  *recordcnt = 0;
2823  }
2824 }
2825 
2826 /** prints the constraint type to file stream */
2827 static
2829  SCIP* scip, /**< SCIP data structure */
2830  FILE* file, /**< output file (or NULL for standard output) */
2831  SCIP_Real lhs, /**< left hand side */
2832  SCIP_Real rhs, /**< right hand side */
2833  const char* name /**< constraint name */
2834  )
2835 {
2836  char rowtype[2];
2837 
2838  assert( scip != NULL );
2839  assert( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) );
2840  assert( SCIPisGT(scip, rhs, lhs) || SCIPisEQ(scip, lhs, rhs) );
2841  assert( name != NULL );
2842 
2843  if( SCIPisEQ(scip, lhs, rhs) )
2844  (void) SCIPsnprintf(rowtype, 2, "%s", "E");
2845  else
2846  {
2847  /* in case the right hand side and the left hand side are not infinity we print a
2848  * less or equal constraint and put the right hand side in the RHS section and the
2849  * left hand side (hidden) in the RANGE section */
2850  if( !SCIPisInfinity(scip, rhs) )
2851  (void) SCIPsnprintf(rowtype, 2, "%s", "L");
2852  else
2853  {
2854  assert( !SCIPisInfinity(scip, -lhs) );
2855  (void) SCIPsnprintf(rowtype, 2, "%s", "G");
2856  }
2857  }
2858 
2859  printStart(scip, file, rowtype, name, -1);
2860  SCIPinfoMessage(scip, file, "\n");
2861 }
2862 
2863 
2864 /** initializes the sparse matrix */
2865 static
2867  SCIP* scip, /**< SCIP data structure */
2868  SPARSEMATRIX** matrix, /**< pointer to sparse matrix containing the entries */
2869  int slots /**< number of slots */
2870  )
2871 {
2872  SCIP_CALL( SCIPallocBuffer(scip, matrix) );
2873  (*matrix)->nentries = 0;
2874  (*matrix)->sentries = slots;
2875  SCIP_CALL( SCIPallocBufferArray(scip, &(*matrix)->values, (*matrix)->sentries) );
2876  SCIP_CALL( SCIPallocBufferArray(scip, &(*matrix)->columns, (*matrix)->sentries) );
2877  SCIP_CALL( SCIPallocBufferArray(scip, &(*matrix)->rows, (*matrix)->sentries) );
2878 
2879  return SCIP_OKAY;
2880 }
2881 
2882 /** this method takes care that the required capacity is available in the sparse matrix */
2883 static
2885  SCIP* scip, /**< SCIP data structure */
2886  SPARSEMATRIX* matrix, /**< sparse matrix for storing the coefficient */
2887  int capacity /**< needed capacity */
2888  )
2889 {
2890  if( matrix->nentries + capacity >= matrix->sentries )
2891  {
2892  matrix->sentries = matrix->sentries * 2 + capacity;
2893  SCIP_CALL( SCIPreallocBufferArray(scip, &matrix->values, matrix->sentries) );
2894  SCIP_CALL( SCIPreallocBufferArray(scip, &matrix->columns, matrix->sentries) );
2895  SCIP_CALL( SCIPreallocBufferArray(scip, &matrix->rows, matrix->sentries) );
2896  }
2897  return SCIP_OKAY;
2898 }
2899 
2900 /** frees the sparse matrix */
2901 static
2903  SCIP* scip, /**< SCIP data structure */
2904  SPARSEMATRIX* matrix /**< sparse matrix to free */
2905  )
2906 {
2907  SCIPfreeBufferArray(scip, &matrix->rows);
2908  SCIPfreeBufferArray(scip, &matrix->columns);
2909  SCIPfreeBufferArray(scip, &matrix->values);
2910 
2911  SCIPfreeBuffer(scip, &matrix);
2912 }
2913 
2914 
2915 /** computes the coefficient for the given variables and linear constraint information */
2916 static
2918  SCIP* scip, /**< SCIP data structure */
2919  const char* consname, /**< name of the constraint */
2920  SCIP_VAR** vars, /**< array of variables */
2921  SCIP_Real* vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
2922  int nvars, /**< number of variables */
2923  SCIP_Bool transformed, /**< transformed constraint? */
2924  SPARSEMATRIX* matrix, /**< sparse matrix for storing the coefficient */
2925  SCIP_Real* rhs /**< pointer to right hand side */
2926  )
2927 {
2928  SCIP_VAR** activevars;
2929  SCIP_Real* activevals;
2930  SCIP_Real activeconstant = 0.0;
2931 
2932  int nactivevars;
2933  int requiredsize;
2934  int v;
2935 
2936  assert( scip != NULL );
2937  assert( nvars == 0 || vars != NULL );
2938  assert( !SCIPisInfinity(scip, *rhs) );
2939  assert( matrix != NULL );
2940 
2941  /* if the variables array contains no variables, then return without
2942  * doing any thing; The MPS format and LP format do not forbid this
2943  * situation */
2944  if( nvars == 0 )
2945  return SCIP_OKAY;
2946 
2947  /* duplicate variable and value array */
2948  nactivevars = nvars;
2949  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) );
2950 
2951  if( vals != NULL )
2952  {
2953  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) );
2954  }
2955  else
2956  {
2957  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2958 
2959  for( v = 0; v < nactivevars; ++v )
2960  activevals[v] = 1.0;
2961  }
2962 
2963  /* retransform given variables to active variables */
2964  if( transformed )
2965  {
2966  SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activevals, &nactivevars, nactivevars, &activeconstant, &requiredsize, TRUE) );
2967 
2968  if( requiredsize > nactivevars )
2969  {
2970  SCIP_CALL( SCIPreallocBufferArray(scip, &activevars, requiredsize) );
2971  SCIP_CALL( SCIPreallocBufferArray(scip, &activevals, requiredsize) );
2972 
2973  SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activevals, &nactivevars, requiredsize, &activeconstant, &requiredsize, TRUE) );
2974  assert( requiredsize <= nactivevars );
2975  }
2976  }
2977  else
2978  {
2979  for( v = 0; v < nactivevars; ++v )
2980  {
2981  SCIP_CALL( SCIPvarGetOrigvarSum(&activevars[v], &activevals[v], &activeconstant) );
2982 
2983  /* negated variables with an original counterpart may also be returned by SCIPvarGetOrigvarSum();
2984  * make sure we get the original variable in that case
2985  */
2986  if( SCIPvarGetStatus(activevars[v]) == SCIP_VARSTATUS_NEGATED )
2987  {
2988  activevars[v] = SCIPvarGetNegatedVar(activevars[v]);
2989  activevals[v] *= -1.0;
2990  activeconstant += 1.0;
2991  }
2992  }
2993  }
2994 
2995  /* copy the (matrix) row into the sparse matrix */
2996  SCIP_CALL( checkSparseMatrixCapacity(scip, matrix, nactivevars) );
2997  assert( matrix->nentries + nactivevars < matrix->sentries );
2998 
2999  for( v = 0; v < nactivevars; ++v )
3000  {
3001  matrix->values[matrix->nentries] = activevals[v];
3002  matrix->columns[matrix->nentries] = activevars[v];
3003  matrix->rows[matrix->nentries] = consname;
3004  matrix->nentries++;
3005  }
3006 
3007  /* adjust right hand side */
3008  (*rhs) -= activeconstant;
3009 
3010  /* free buffer arrays */
3011  SCIPfreeBufferArray(scip, &activevals);
3012  SCIPfreeBufferArray(scip, &activevars);
3013 
3014  return SCIP_OKAY;
3015 }
3016 
3017 
3018 /** check whether given variables are aggregated and put them into an array without duplication */
3019 static
3021  SCIP* scip, /**< SCIP data structure */
3022  SCIP_VAR** vars, /**< variable array */
3023  int nvars, /**< number of active variables in the problem */
3024  SCIP_VAR*** aggvars, /**< pointer to array storing the aggregated variables on output */
3025  int* naggvars, /**< pointer to number of aggregated variables on output */
3026  int* saggvars, /**< pointer to number of slots in aggvars array */
3027  SCIP_HASHTABLE* varAggregated /**< hashtable for checking duplicates */
3028  )
3029 {
3030  int v;
3031 
3032  assert( scip != NULL );
3033  assert( aggvars != NULL );
3034  assert( naggvars != NULL );
3035  assert( saggvars != NULL );
3036 
3037  /* check variables */
3038  for( v = 0; v < nvars; ++v )
3039  {
3040  SCIP_VARSTATUS status;
3041  SCIP_VAR* var;
3042 
3043  var = vars[v];
3044  status = SCIPvarGetStatus(var);
3045 
3046  /* collect aggregated variables in a list */
3047  if( status >= SCIP_VARSTATUS_AGGREGATED )
3048  {
3049  assert( status == SCIP_VARSTATUS_AGGREGATED || status == SCIP_VARSTATUS_MULTAGGR || status == SCIP_VARSTATUS_NEGATED );
3050  assert( varAggregated != NULL );
3051 
3052  if( ! SCIPhashtableExists(varAggregated, (void*) var) )
3053  {
3054  /* possibly enlarge array */
3055  if ( *saggvars <= *naggvars )
3056  {
3057  int newsize;
3058  newsize = SCIPcalcMemGrowSize(scip, *naggvars + 1);
3059  assert( newsize > *saggvars );
3060  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &aggvars, *saggvars, newsize) );
3061  *saggvars = newsize;
3062  }
3063 
3064  (*aggvars)[*naggvars] = var;
3065  (*naggvars)++;
3066  SCIP_CALL( SCIPhashtableInsert(varAggregated, (void*) var) );
3067  assert( *naggvars <= *saggvars );
3068  }
3069  }
3070  }
3071  return SCIP_OKAY;
3072 }
3073 
3074 
3075 /** method check if the variable names are not longer than MPS_MAX_NAMELEN - 1*/
3076 static
3078  SCIP* scip, /**< SCIP data structure */
3079  SCIP_VAR** vars, /**< array of variables */
3080  int nvars, /**< number of variables */
3081  unsigned int* maxnamelen, /**< pointer to store the maximum name length */
3082  const char*** varnames, /**< pointer to array of variable names */
3083  SCIP_HASHMAP** varnameHashmap /**< pointer to hash map storing variable, variable name mapping */
3084  )
3085 {
3086  int v;
3087  int faulty;
3088  char* varname;
3089  SCIP_VAR* var;
3090 
3091  assert( scip != NULL );
3092  assert( vars != NULL );
3093  assert( maxnamelen != NULL );
3094 
3095  faulty = 0;
3096 
3097  /* allocate memory */
3098  SCIP_CALL( SCIPhashmapCreate(varnameHashmap, SCIPblkmem(scip), nvars) );
3099  SCIP_CALL( SCIPallocBufferArray(scip, varnames, nvars) );
3100 
3101  /* check if the variable names are not to long */
3102  for( v = 0; v < nvars; ++v )
3103  {
3104  size_t l;
3105 
3106  var = vars[v];
3107  assert( var != NULL );
3108 
3109  l = strlen(SCIPvarGetName(var));
3110 
3111  if( l >= MPS_MAX_NAMELEN )
3112  {
3113  faulty++;
3114  (*maxnamelen) = MPS_MAX_NAMELEN - 1;
3115  }
3116  else
3117  {
3118  (*maxnamelen) = MAX(*maxnamelen, (unsigned int) l);
3119  }
3120 
3121  SCIP_CALL( SCIPallocBufferArray(scip, &varname, (int) *maxnamelen + 1) );
3122  (void) SCIPsnprintf(varname, (int)(*maxnamelen) + 1, "%s", SCIPvarGetName(var) );
3123 
3124  /* insert variable with variable name into hash map */
3125  assert( !SCIPhashmapExists(*varnameHashmap, var) );
3126  SCIP_CALL( SCIPhashmapInsert(*varnameHashmap, var, (void*) varname) );
3127 
3128  (*varnames)[v] = varname;
3129  }
3130 
3131  if( faulty > 0 )
3132  {
3133  SCIPwarningMessage(scip, "there are %d variable names which have to be cut down to %d characters; LP might be corrupted\n",
3134  faulty, MPS_MAX_NAMELEN - 1);
3135  }
3136  return SCIP_OKAY;
3137 }
3138 
3139 /** method check if the constraint names are not longer than MPS_MAX_NAMELEN - 1 */
3140 static
3142  SCIP* scip, /**< SCIP data structure */
3143  SCIP_CONS** conss, /**< array of all constraints */
3144  int nconss, /**< number of all constraints */
3145  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
3146  unsigned int* maxnamelen, /**< pointer to store the maximum name length */
3147  const char*** consnames, /**< pointer to array of constraint names */
3148  SCIP_Bool* error /**< pointer to store whether all constraint names exist */
3149  )
3150 {
3151  SCIP_HASHTABLE* consfreq;
3152  CONSNAMEFREQ* consnamefreqs;
3153  SCIP_CONS* cons;
3154  char* consname;
3155  int i;
3156 
3157  assert(scip != NULL);
3158  assert(maxnamelen != NULL);
3159 
3160  *error = FALSE;
3161 
3162  /* allocate memory */
3163  SCIP_CALL( SCIPallocBufferArray(scip, &consnamefreqs, nconss) );
3164  SCIP_CALL( SCIPallocBufferArray(scip, consnames, nconss) );
3166  hashGetKeyNamefreq, hashKeyEqString, SCIPhashKeyValString, NULL) );
3167 
3168  for( i = 0; i < nconss; ++i )
3169  {
3170  CONSNAMEFREQ* consnamefreq;
3171  size_t l;
3172  int freq;
3173 
3174  cons = conss[i];
3175  assert( cons != NULL );
3176 
3177  /* in case the transformed problem is written, only constraints are posted which are enabled in the current node */
3178  assert(!transformed || SCIPconsIsEnabled(cons));
3179 
3180  l = strlen(SCIPconsGetName(cons));
3181 
3182  if( l == 0 )
3183  {
3184  SCIPwarningMessage(scip, "At least one name of a constraint is empty, so file will be written with generic names.\n");
3185  *error = TRUE;
3186 
3187  goto TERMINATE;
3188  }
3189 
3190  consnamefreqs[i].consname = SCIPconsGetName(cons);
3191  consnamefreqs[i].freq = 0;
3192  freq = 0;
3193 
3194  /* check for duplicate names */
3195  if( NULL != (consnamefreq = (CONSNAMEFREQ *)SCIPhashtableRetrieve(consfreq, (void*)SCIPconsGetName(cons))) )
3196  {
3197  consnamefreq->freq += 1;
3198  consnamefreqs[i] = *consnamefreq;
3199  freq = consnamefreq->freq;
3200  }
3201  SCIP_CALL( SCIPhashtableInsert(consfreq, (void*)(&consnamefreqs[i])) );
3202 
3203  /* the new length is the length of the old name + a '_' and the freq number which has floor(log10(freq)) + 1 characters */
3204  if( freq > 0 )
3205  l = l + 1 + (size_t)log10((SCIP_Real) freq) + 1;
3206 
3207  if( l >= MPS_MAX_NAMELEN )
3208  {
3209  SCIPwarningMessage(scip, "Constraints have duplicate name and are too long to fix, so file will be written with generic names.\n");
3210  *error = TRUE;
3211 
3212  goto TERMINATE;
3213  }
3214 
3215  (*maxnamelen) = MAX(*maxnamelen, (unsigned int) l);
3216 
3217  SCIP_CALL( SCIPallocBufferArray(scip, &consname, (int) l + 1) );
3218  if( freq > 0 )
3219  (void) SCIPsnprintf(consname, (int)l + 1, "%s_%d", SCIPconsGetName(cons), freq);
3220  else
3221  (void) SCIPsnprintf(consname, (int)l + 1, "%s", SCIPconsGetName(cons));
3222 
3223  (*consnames)[i] = consname;
3224  }
3225 
3226 TERMINATE:
3227  SCIPfreeBufferArray(scip, &consnamefreqs);
3228 
3229  if( *error )
3230  {
3231  --i; /*lint !e445*/
3232  for( ; i >= 0; --i) /*lint !e445*/
3233  {
3234  SCIPfreeBufferArray(scip, &((*consnames)[i]));
3235  }
3236  SCIPfreeBufferArray(scip, consnames);
3237  }
3238 
3239  SCIPhashtableFree(&consfreq);
3240 
3241  return SCIP_OKAY;
3242 }
3243 
3244 
3245 /** outputs the COLUMNS section of the MPS format */
3246 static
3248  SCIP* scip, /**< SCIP data structure */
3249  FILE* file, /**< output file, or NULL if standard output should be used */
3250  SPARSEMATRIX* matrix, /**< sparse matrix containing the entries */
3251  SCIP_HASHMAP* varnameHashmap, /**< map from SCIP_VAR* to variable name */
3252  SCIP_HASHTABLE* indicatorSlackHash, /**< hashtable containing slack variables from indicators (or NULL) */
3253  unsigned int maxnamelen /**< maximum name length */
3254  )
3255 {
3256  SCIP_Bool intSection;
3257  SCIP_VAR* var;
3258  const char* varname;
3259  SCIP_Real value;
3260  int v;
3261  int recordcnt;
3262 
3263  /* sort sparse matrix w.r.t. the variable indices */
3264  SCIPsortPtrPtrReal((void**) matrix->columns, (void**) matrix->rows, matrix->values, SCIPvarComp, matrix->nentries);
3265 
3266  /* print COLUMNS section */
3267  SCIPinfoMessage(scip, file, "COLUMNS\n");
3268 
3269  intSection = FALSE;
3270 
3271  for( v = 0; v < matrix->nentries; )
3272  {
3273  var = matrix->columns[v];
3274  assert( var != NULL );
3275 
3276  /* skip slack variables in output */
3277  if( indicatorSlackHash != NULL && SCIPhashtableExists(indicatorSlackHash, var) )
3278  {
3279  ++v;
3280  continue;
3281  }
3282 
3283  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS && intSection )
3284  {
3285  /* end integer section in MPS format */
3286  printStart(scip, file, "", "INTEND", (int) maxnamelen);
3287  printRecord(scip, file, "'MARKER'", "", maxnamelen);
3288  printRecord(scip, file, "'INTEND'", "", maxnamelen);
3289  SCIPinfoMessage(scip, file, "\n", maxnamelen);
3290  intSection = FALSE;
3291  }
3292  else if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !intSection )
3293  {
3294  /* start integer section in MPS format */
3295  printStart(scip, file, "", "INTSTART", (int) maxnamelen);
3296  printRecord(scip, file, "'MARKER'", "", maxnamelen);
3297  printRecord(scip, file, "'INTORG'", "", maxnamelen);
3298  SCIPinfoMessage(scip, file, "\n");
3299  intSection = TRUE;
3300  }
3301 
3302  SCIPdebugMsg(scip, "create entries for variable <%s>\n", SCIPvarGetName(var));
3303 
3304  /* record count; there are at most two records per line */
3305  recordcnt = 0;
3306 
3307  /* get variable name */
3308  assert ( SCIPhashmapExists(varnameHashmap, var) );
3309  varname = (const char*) SCIPhashmapGetImage(varnameHashmap, var);
3310 
3311  /* output all entries of the same variable */
3312  do
3313  {
3314  value = matrix->values[v];
3315 
3316  /* print record to file */
3317  printEntry(scip, file, varname, matrix->rows[v], value, &recordcnt, maxnamelen);
3318  v++;
3319  }
3320  while( v < matrix->nentries && var == matrix->columns[v] );
3321 
3322  if( recordcnt == 1 )
3323  SCIPinfoMessage(scip, file, "\n");
3324  }
3325  /* end integer section, if the columns sections ends with integer variables */
3326  if( intSection )
3327  {
3328  /* end integer section in MPS format */
3329  printStart(scip, file, "", "INTEND", (int) maxnamelen);
3330  printRecord(scip, file, "'MARKER'", "", maxnamelen);
3331  printRecord(scip, file, "'INTEND'", "", maxnamelen);
3332  SCIPinfoMessage(scip, file, "\n", maxnamelen);
3333  }
3334 }
3335 
3336 
3337 /** outputs the right hand side section */
3338 static
3340  SCIP* scip, /**< SCIP data structure */
3341  FILE* file, /**< output file, or NULL if standard output should be used */
3342  int nconss, /**< number of constraints */
3343  const char** consnames, /**< constraint names */
3344  SCIP_Real* rhss, /**< right hand side array */
3345  unsigned int maxnamelen /**< maximum name length */
3346  )
3347 {
3348  int recordcnt = 0;
3349  int c;
3350 
3351  assert( rhss != NULL );
3352 
3353  SCIPinfoMessage(scip, file, "RHS\n");
3354  SCIPdebugMsg(scip, "start printing RHS section\n");
3355 
3356  /* take care of the linear constraints */
3357  for( c = 0; c < nconss; ++c )
3358  {
3359  /* skip all constraints which have a right hand side of infinity */
3360  if( SCIPisInfinity(scip, rhss[c]) )
3361  continue;
3362 
3363  assert(consnames[c] != NULL);
3364 
3365  printEntry(scip, file, "RHS", consnames[c], rhss[c], &recordcnt, maxnamelen);
3366  }
3367 
3368  if( recordcnt == 1 )
3369  SCIPinfoMessage(scip, file, "\n");
3370 }
3371 
3372 
3373 /** outputs the range section */
3374 static
3376  SCIP* scip, /**< SCIP data structure */
3377  FILE* file, /**< output file, or NULL if standard output should be used */
3378  SCIP_CONS** conss, /**< constraint array */
3379  int nconss, /**< number of constraints */
3380  const char** consnames, /**< constraint names */
3381  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
3382  unsigned int maxnamelen /**< maximum name length */
3383  )
3384 {
3385  int c;
3386  int recordcnt = 0;
3387 
3388  SCIP_CONSHDLR* conshdlr;
3389  const char* conshdlrname;
3390 
3391  SCIP_CONS* cons;
3392  SCIP_Real lhs;
3393  SCIP_Real rhs;
3394 
3395  SCIPinfoMessage(scip, file, "RANGES\n");
3396  SCIPdebugMsg(scip, "start printing RANGES section\n");
3397 
3398  for( c = 0; c < nconss; ++c )
3399  {
3400  cons = conss[c];
3401  assert( cons != NULL);
3402 
3403  /* in case the transformed problems is written only constraint are posted which are enabled in the current node;
3404  * the conss array should only contain relevant constraints
3405  */
3406  assert( !transformed || SCIPconsIsEnabled(cons) );
3407 
3408  assert( consnames[c] != NULL );
3409 
3410  conshdlr = SCIPconsGetHdlr(cons);
3411  assert( conshdlr != NULL );
3412 
3413  conshdlrname = SCIPconshdlrGetName(conshdlr);
3414 
3415  if( strcmp(conshdlrname, "linear") == 0 )
3416  {
3417  lhs = SCIPgetLhsLinear(scip, cons);
3418  rhs = SCIPgetRhsLinear(scip, cons);
3419  }
3420  else if( strcmp(conshdlrname, "varbound") == 0 )
3421  {
3422  lhs = SCIPgetLhsVarbound(scip, cons);
3423  rhs = SCIPgetRhsVarbound(scip, cons);
3424  }
3425  else
3426  continue;
3427 
3428  if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, rhs, lhs) )
3429  {
3430  assert( SCIPisGT(scip, rhs, lhs) );
3431  printEntry(scip, file, "RANGE", consnames[c], rhs - lhs, &recordcnt, maxnamelen);
3432  }
3433  }
3434  if(recordcnt == 1 )
3435  SCIPinfoMessage(scip, file, "\n");
3436 }
3437 
3438 /** print bound section name */
3439 static
3441  SCIP* scip, /**< SCIP data structure */
3442  FILE* file /**< output file, or NULL if standard output should be used */
3443  )
3444 {
3445  SCIPinfoMessage(scip, file, "BOUNDS\n");
3446  SCIPdebugMsg(scip, "start printing BOUNDS section\n");
3447 }
3448 
3449 /** output bound section */
3450 static
3452  SCIP* scip, /**< SCIP data structure */
3453  FILE* file, /**< output file, or NULL if standard output should be used */
3454  SCIP_VAR** vars, /**< active variables */
3455  int nvars, /**< number of active variables */
3456  SCIP_VAR** aggvars, /**< needed aggregated variables */
3457  int naggvars, /**< number of aggregated variables */
3458  SCIP_VAR** fixvars, /**< all fixed variables (or NULL if nfixvars is 0) */
3459  int nfixvars, /**< number of fixed variables */
3460  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
3461  const char** varnames, /**< array with variable names */
3462  SCIP_HASHTABLE* indicatorSlackHash, /**< hashtable containing slack variables from indicators (or NULL) */
3463  unsigned int maxnamelen /**< maximum name length */
3464  )
3465 {
3466  int v;
3467  SCIP_VAR* var;
3468  SCIP_Real lb;
3469  SCIP_Real ub;
3470  SCIP_Bool sectionName;
3471  const char* varname;
3472  char valuestr[MPS_MAX_VALUELEN] = { '\0' };
3473 
3474  assert(scip != NULL);
3475  assert(vars != NULL);
3476  assert(nfixvars == 0 || fixvars != NULL);
3477 
3478  sectionName = FALSE;
3479 
3480  /* output the active variables */
3481  for( v = 0; v < nvars; ++v )
3482  {
3483  var = vars[v];
3484  assert( var != NULL );
3485 
3486  /* skip slack variables in output */
3487  if( indicatorSlackHash != NULL && SCIPhashtableExists(indicatorSlackHash, var) )
3488  continue;
3489 
3490  /* get variable name */
3491  varname = varnames[v];
3492  assert(strncmp(varname, SCIPvarGetName(var), maxnamelen) == 0);
3493 
3494  if( transformed )
3495  {
3496  /* in case the transformed is written only local bounds are posted
3497  * which are valid in the current node */
3498  lb = SCIPvarGetLbLocal(var);
3499  ub = SCIPvarGetUbLocal(var);
3500  }
3501  else
3502  {
3503  lb = SCIPvarGetLbOriginal(var);
3504  ub = SCIPvarGetUbOriginal(var);
3505  }
3506 
3507  /* take care of binary variables */
3508  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
3509  {
3510  if( !sectionName )
3511  {
3512  printBoundSectionName(scip, file);
3513  sectionName = TRUE;
3514  }
3515 
3516  if( !SCIPisFeasZero(scip, lb) || !SCIPisFeasEQ(scip, ub, 1.0) )
3517  {
3518  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb);
3519  printStart(scip, file, "LO", "Bound", (int) maxnamelen);
3520  printRecord(scip, file, varname, valuestr, maxnamelen);
3521  SCIPinfoMessage(scip, file, "\n");
3522 
3523  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", ub);
3524  printStart(scip, file, "UP", "Bound", (int) maxnamelen);
3525  printRecord(scip, file, varname, valuestr, maxnamelen);
3526  }
3527  else
3528  {
3529  printStart(scip, file, "BV", "Bound", (int) maxnamelen);
3530  printRecord(scip, file, varname, "", maxnamelen);
3531  }
3532  SCIPinfoMessage(scip, file, "\n");
3533 
3534  continue;
3535  }
3536 
3537  /* take care of free variables */
3538  if( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) )
3539  {
3540  if( !sectionName )
3541  {
3542  printBoundSectionName(scip, file);
3543  sectionName = TRUE;
3544  }
3545 
3546  /* variable is free */
3547  printStart(scip, file, "FR", "Bound", (int) maxnamelen);
3548  printRecord(scip, file, varname, "", maxnamelen);
3549  SCIPinfoMessage(scip, file, "\n");
3550  continue;
3551  }
3552 
3553  /* take care of fixed variables */
3554  if( SCIPisEQ(scip, lb, ub) )
3555  {
3556  if( !sectionName )
3557  {
3558  printBoundSectionName(scip, file);
3559  sectionName = TRUE;
3560  }
3561 
3562  /* variable is fixed */
3563  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb);
3564  printStart(scip, file, "FX", "Bound", (int) maxnamelen);
3565  printRecord(scip, file, varname, valuestr, maxnamelen);
3566  SCIPinfoMessage(scip, file, "\n");
3567  continue;
3568  }
3569 
3570  /* print lower bound */
3571  if( SCIPisInfinity(scip, -lb) )
3572  {
3573  if( !sectionName )
3574  {
3575  printBoundSectionName(scip, file);
3576  sectionName = TRUE;
3577  }
3578 
3579  /* the free variables are processed above */
3580  assert( !SCIPisInfinity(scip, ub) );
3581  printStart(scip, file, "MI", "Bound", (int) maxnamelen);
3582  printRecord(scip, file, varname, "", maxnamelen);
3583  SCIPinfoMessage(scip, file, "\n");
3584  }
3585  else
3586  {
3587  if( SCIPisZero(scip, lb) )
3588  {
3589  lb = 0.0;
3590  }
3591  else
3592  {
3593  if( !sectionName )
3594  {
3595  printBoundSectionName(scip, file);
3596  sectionName = TRUE;
3597  }
3598 
3599  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb);
3600  printStart(scip, file, "LO", "Bound", (int) maxnamelen);
3601  printRecord(scip, file, varname, valuestr, maxnamelen);
3602  SCIPinfoMessage(scip, file, "\n");
3603  }
3604  }
3605 
3606  /* print upper bound, infinity has to be printed for integer (!) variables, because during
3607  * reading an mps file no upper bound of an integer variable means that the upper bound will
3608  * be set to 1 instead of +infinity (like it is for continuous variables) */
3609  if( SCIPisInfinity(scip, ub) )
3610  {
3611  if( !sectionName )
3612  {
3613  printBoundSectionName(scip, file);
3614  sectionName = TRUE;
3615  }
3616 
3617  /* the free variables are processed above */
3618  assert( !SCIPisInfinity(scip, -lb) );
3619  printStart(scip, file, "PL", "Bound", (int) maxnamelen);
3620  printRecord(scip, file, varname, "", maxnamelen);
3621  SCIPinfoMessage(scip, file, "\n");
3622  }
3623  else
3624  {
3625  if( !sectionName )
3626  {
3627  printBoundSectionName(scip, file);
3628  sectionName = TRUE;
3629  }
3630 
3631  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", ub);
3632  printStart(scip, file, "UP", "Bound", (int) maxnamelen);
3633  printRecord(scip, file, varname, valuestr, maxnamelen);
3634  SCIPinfoMessage(scip, file, "\n");
3635  }
3636  }
3637 
3638  /* output aggregated variables as 'free', except if they are binary */
3639  for( v = 0; v < naggvars; ++v )
3640  {
3641  if( !sectionName )
3642  {
3643  printBoundSectionName(scip, file);
3644  sectionName = TRUE;
3645  }
3646 
3647  var = aggvars[v];
3648  assert( var != NULL );
3649 
3650  /* get variable name */
3651  varname = varnames[nvars + v];
3652  assert(strncmp(varname, SCIPvarGetName(var), maxnamelen) == 0);
3653 
3654  /* take care of binary variables */
3655  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
3656  {
3657  printStart(scip, file, "BV", "Bound", (int) maxnamelen);
3658  printRecord(scip, file, varname, "", maxnamelen);
3659  SCIPinfoMessage(scip, file, "\n");
3660  }
3661  else
3662  {
3663  /* variable is free */
3664  printStart(scip, file, "FR", "Bound", (int) maxnamelen);
3665  printRecord(scip, file, varname, "", maxnamelen);
3666  SCIPinfoMessage(scip, file, "\n");
3667  }
3668  }
3669 
3670  /* output all fixed variables */
3671  for( v = 0; v < nfixvars; ++v )
3672  {
3673  /* we should print the transformed problem, otherwise no fixed variable should exists */
3674  assert(transformed);
3675  assert(fixvars != NULL && fixvars[v] != NULL);
3676 
3677  /* cppcheck-suppress nullPointer */
3678  var = fixvars[v];
3679 
3680  assert(var != NULL);
3681  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
3682 
3683  /* get variable name */
3684  varname = varnames[nvars + naggvars + v];
3685  assert(strncmp(varname, SCIPvarGetName(var), maxnamelen) == 0);
3686 
3687  /* only local bounds are posted which are valid in the current node */
3688  lb = SCIPvarGetLbLocal(var);
3689  ub = SCIPvarGetUbLocal(var);
3690  assert(SCIPisEQ(scip, lb, ub));
3691 
3692  if( !sectionName )
3693  {
3694  printBoundSectionName(scip, file);
3695  sectionName = TRUE;
3696  }
3697 
3698  /* print fixed variable */
3699  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb);
3700  printStart(scip, file, "FX", "Bound", (int) maxnamelen);
3701  printRecord(scip, file, varname, valuestr, maxnamelen);
3702  SCIPinfoMessage(scip, file, "\n");
3703  }
3704 }
3705 
3706 
3707 /*
3708  * Callback methods of reader
3709  */
3710 
3711 /** copy method for reader plugins (called when SCIP copies plugins) */
3712 /**! [SnippetReaderCopyMps] */
3713 static
3714 SCIP_DECL_READERCOPY(readerCopyMps)
3715 { /*lint --e{715}*/
3716  assert(scip != NULL);
3717  assert(reader != NULL);
3718  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
3719 
3720  /* call inclusion method of reader */
3722 
3723  return SCIP_OKAY;
3724 }
3725 /**! [SnippetReaderCopyMps] */
3726 
3727 /** destructor of reader to free user data (called when SCIP is exiting) */
3728 /**! [SnippetReaderFreeMps] */
3729 static
3730 SCIP_DECL_READERFREE(readerFreeMps)
3731 {
3732  SCIP_READERDATA* readerdata;
3733 
3734  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
3735  readerdata = SCIPreaderGetData(reader);
3736  assert(readerdata != NULL);
3737  SCIPfreeBlockMemory(scip, &readerdata);
3738 
3739  return SCIP_OKAY;
3740 }
3741 /**! [SnippetReaderFreeMps] */
3742 
3743 /** problem reading method of reader */
3744 static
3745 SCIP_DECL_READERREAD(readerReadMps)
3746 { /*lint --e{715}*/
3747  assert(reader != NULL);
3748  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
3749 
3750  SCIP_CALL( SCIPreadMps(scip, reader, filename, result, NULL, NULL, NULL, NULL, NULL, NULL) );
3751 
3752  return SCIP_OKAY;
3753 }
3754 
3755 
3756 /** problem writing method of reader */
3757 static
3758 SCIP_DECL_READERWRITE(readerWriteMps)
3759 { /*lint --e{715}*/
3760  assert(reader != NULL);
3761  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
3762 
3763  SCIP_CALL( SCIPwriteMps(scip, reader, file, name, transformed, objsense, objscale, objoffset, vars,
3764  nvars, nbinvars, nintvars, nimplvars, ncontvars, fixedvars, nfixedvars, conss, nconss, result) );
3765 
3766  return SCIP_OKAY;
3767 }
3768 
3769 
3770 /*
3771  * mps file reader specific interface methods
3772  */
3773 
3774 /** includes the mps file reader in SCIP */
3776  SCIP* scip /**< SCIP data structure */
3777  )
3778 {
3779  SCIP_READERDATA* readerdata;
3780  SCIP_READER* reader;
3781 
3782  /* create reader data */
3783  SCIP_CALL( SCIPallocBlockMemory(scip, &readerdata) );
3784 
3785  /* include reader */
3786  SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, readerdata) );
3787 
3788  /* set non fundamental callbacks via setter functions */
3789  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyMps) );
3790  SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeMps) );
3791  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadMps) );
3792  SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteMps) );
3793 
3794  /* add lp-reader parameters */
3796  "reading/" READER_NAME "/linearize-and-constraints",
3797  "should possible \"and\" constraint be linearized when writing the mps file?",
3798  &readerdata->linearizeands, TRUE, DEFAULT_LINEARIZE_ANDS, NULL, NULL) );
3800  "reading/" READER_NAME "/aggrlinearization-ands",
3801  "should an aggregated linearization for and constraints be used?",
3802  &readerdata->aggrlinearizationands, TRUE, DEFAULT_AGGRLINEARIZATION_ANDS, NULL, NULL) );
3803 
3804  return SCIP_OKAY;
3805 }
3806 
3807 
3808 /** reads problem from file */
3810  SCIP* scip, /**< SCIP data structure */
3811  SCIP_READER* reader, /**< the file reader itself */
3812  const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
3813  SCIP_RESULT* result, /**< pointer to store the result of the file reading call */
3814  const char*** varnames, /**< storage for the variable names, or NULL */
3815  const char*** consnames, /**< storage for the constraint names, or NULL */
3816  int* varnamessize, /**< the size of the variable names storage, or NULL */
3817  int* consnamessize, /**< the size of the constraint names storage, or NULL */
3818  int* nvarnames, /**< the number of stored variable names, or NULL */
3819  int* nconsnames /**< the number of stored constraint names, or NULL */
3820  )
3821 {
3822  SCIP_RETCODE retcode;
3823 
3824  assert(reader != NULL);
3825  assert(scip != NULL);
3826  assert(result != NULL);
3827 
3828  retcode = readMps(scip, filename, varnames, consnames, varnamessize, consnamessize, nvarnames, nconsnames);
3829 
3830  if( retcode == SCIP_PLUGINNOTFOUND )
3831  retcode = SCIP_READERROR;
3832 
3833  if( retcode == SCIP_NOFILE || retcode == SCIP_READERROR )
3834  return retcode;
3835 
3836  SCIP_CALL( retcode );
3837 
3838  *result = SCIP_SUCCESS;
3839 
3840  return SCIP_OKAY;
3841 }
3842 
3843 
3844 /** writes problem to file */
3846  SCIP* scip, /**< SCIP data structure */
3847  SCIP_READER* reader, /**< the file reader itself */
3848  FILE* file, /**< output file, or NULL if standard output should be used */
3849  const char* name, /**< problem name */
3850  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
3851  SCIP_OBJSENSE objsense, /**< objective sense */
3852  SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
3853  * extobj = objsense * objscale * (intobj + objoffset) */
3854  SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
3855  SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
3856  int nvars, /**< number of active variables in the problem */
3857  int nbinvars, /**< number of binary variables */
3858  int nintvars, /**< number of general integer variables */
3859  int nimplvars, /**< number of implicit integer variables */
3860  int ncontvars, /**< number of continuous variables */
3861  SCIP_VAR** fixedvars, /**< array with fixed and aggregated variables */
3862  int nfixedvars, /**< number of fixed and aggregated variables in the problem */
3863  SCIP_CONS** conss, /**< array with constraints of the problem */
3864  int nconss, /**< number of constraints in the problem */
3865  SCIP_RESULT* result /**< pointer to store the result of the file writing call */
3866  )
3867 {
3868  SCIP_READERDATA* readerdata;
3869  int naddrows;
3870  int faulty = 0;
3871  int c;
3872  int v;
3873  int k;
3874  char* namestr;
3875 
3876  SCIP_CONS* cons = NULL;
3877  const char* consname;
3878  const char** consnames;
3879 
3880  SCIP_CONSHDLR* conshdlr;
3881  const char* conshdlrname;
3882 
3883  SCIP_Real lhs;
3884  SCIP_Real rhs;
3885  SCIP_Real* rhss;
3886  SCIP_Real value;
3887 
3888  SCIP_VAR* var = NULL;
3889  const char* varname;
3890  const char** varnames;
3891 
3892  char valuestr[MPS_MAX_VALUELEN] = { '\0' };
3893 
3894  SCIP_CONS** consIndicator;
3895  SCIP_CONS** consSOS1;
3896  SCIP_CONS** consSOS2;
3897  SCIP_CONS** consQuadratic;
3898  SCIP_CONS** consSOC;
3899  int nConsIndicator;
3900  int nConsSOS1;
3901  int nConsSOS2;
3902  int nConsQuadratic;
3903  int nConsSOC;
3904 
3905  SCIP_HASHMAP* varnameHashmap; /* hash map from SCIP_VAR* to variable name */
3906  SPARSEMATRIX* matrix;
3907 
3908  SCIP_VAR** aggvars;
3909  int naggvars = 0;
3910  int saggvars;
3911  SCIP_HASHTABLE* varFixedHash;
3912  SCIP_HASHTABLE* indicatorSlackHash;
3913 
3914  SCIP_VAR** fixvars = NULL;
3915  int nfixvars = 0;
3916 
3917  SCIP_VAR** consvars;
3918  int nconsvars;
3919  SCIP_Real* vals;
3920  SCIP_Longint* weights;
3921 
3922  SCIP_Bool needRANGES;
3923  unsigned int maxnamelen;
3924 
3925  SCIP_Bool error;
3926 
3927  assert(reader != NULL);
3928  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
3929  assert(scip != NULL);
3930  assert(result != NULL);
3931 
3932  needRANGES = FALSE;
3933  maxnamelen = 0;
3934  nConsSOS1 = 0;
3935  nConsSOS2 = 0;
3936  nConsQuadratic = 0;
3937  nConsSOC = 0;
3938  nConsIndicator = 0;
3939 
3940  /* check if the constraint names are too long and build the constraint names */
3941  SCIP_CALL( checkConsnames(scip, conss, nconss, transformed, &maxnamelen, &consnames, &error) );
3942  if( error )
3943  {
3944  /* call writing with generic names */
3945  if( transformed )
3946  {
3947  SCIPwarningMessage(scip, "write transformed problem with generic variable and constraint names\n");
3948  SCIP_CALL( SCIPprintTransProblem(scip, file, "mps", TRUE) );
3949  }
3950  else
3951  {
3952  SCIPwarningMessage(scip, "write original problem with generic variable and constraint names\n");
3953  SCIP_CALL( SCIPprintOrigProblem(scip, file, "mps", TRUE) );
3954  }
3955  *result = SCIP_SUCCESS;
3956 
3957  return SCIP_OKAY;
3958  }
3959 
3960  /* check if the variable names are not too long and build the "variable" -> "variable name" hash map */
3961  SCIP_CALL( checkVarnames(scip, vars, nvars, &maxnamelen, &varnames, &varnameHashmap) );
3962 
3963  /* collect SOS, quadratic, and indicator constraints in array for later output */
3964  SCIP_CALL( SCIPallocBufferArray(scip, &consSOS1, nconss) );
3965  SCIP_CALL( SCIPallocBufferArray(scip, &consSOS2, nconss) );
3966  SCIP_CALL( SCIPallocBufferArray(scip, &consQuadratic, nconss) );
3967  SCIP_CALL( SCIPallocBufferArray(scip, &consSOC, nconss) );
3968  SCIP_CALL( SCIPallocBufferArray(scip, &consIndicator, nconss) );
3969 
3970  /* nfixedvars counts all variables with status SCIP_VARSTATUS_FIXED, SCIP_VARSTATUS_AGGREGATED, SCIP_VARSTATUS_MULTAGGR, but not SCIP_VARSTATUS_NEGATED */
3971  saggvars = nfixedvars;
3972  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &aggvars, saggvars) );
3973 
3974  /* create hashtable for storing aggregated variables */
3975  if( nfixedvars > 0 )
3976  {
3977  SCIP_CALL( SCIPhashtableCreate(&varFixedHash, SCIPblkmem(scip), nfixedvars, hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) );
3978  }
3979  else
3980  varFixedHash = NULL;
3981 
3982  if( nvars > 0 )
3983  {
3984  SCIP_CALL( SCIPhashtableCreate(&indicatorSlackHash, SCIPblkmem(scip), nvars, hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) );
3985  }
3986  else
3987  indicatorSlackHash = NULL;
3988 
3989  /* initialize sparse matrix */
3990  SCIP_CALL( initializeMatrix(scip, &matrix, (nvars * 2 + nfixedvars)) );
3991  assert( matrix->sentries >= nvars );
3992 
3993  readerdata = SCIPreaderGetData(reader);
3994  assert(readerdata != NULL);
3995 
3996  naddrows = 0;
3997 
3998  /* determine and-constraints and printing format to resize necessary arrays */
3999  if( readerdata->linearizeands )
4000  {
4001  SCIP_CONSHDLR* andconshdlr = SCIPfindConshdlr(scip, "and");
4002 
4003  if( andconshdlr != NULL )
4004  {
4005  /* need to check for and-constraints, note that in the original problem you cannot get the number of
4006  * and-constraints by one call */
4007  for( c = nconss - 1; c >= 0; --c )
4008  {
4009  conshdlr = SCIPconsGetHdlr(conss[c]);
4010  assert(conshdlr != NULL);
4011 
4012  conshdlrname = SCIPconshdlrGetName(conshdlr);
4013 
4014  if( strcmp(conshdlrname, "and") == 0 )
4015  {
4016  if( readerdata->aggrlinearizationands )
4017  ++naddrows;
4018  else
4019  naddrows += SCIPgetNVarsAnd(scip, conss[c]);
4020  }
4021  }
4022  assert(naddrows >= 0);
4023 
4024  if( naddrows > 0 )
4025  {
4026  /* resize consnames vector */
4027  SCIP_CALL( SCIPreallocBufferArray(scip, &consnames, nconss + naddrows) );
4028  }
4029  }
4030  }
4031 
4032  /* initialize rhs vector */
4033  SCIP_CALL( SCIPallocBufferArray(scip, &rhss, nconss + naddrows) );
4034 
4035  /* print statistics as comment to file stream */
4036  SCIPinfoMessage(scip, file, "* SCIP STATISTICS\n");
4037  SCIPinfoMessage(scip, file, "* Problem name : %s\n", name);
4038  SCIPinfoMessage(scip, file, "* Variables : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
4039  nvars, nbinvars, nintvars, nimplvars, ncontvars);
4040  SCIPinfoMessage(scip, file, "* Constraints : %d\n", nconss);
4041  SCIPinfoMessage(scip, file, "* Obj. scale : %.15g\n", objscale);
4042  SCIPinfoMessage(scip, file, "* Obj. offset : %.15g\n", objoffset);
4043 
4044  /* print NAME of the problem */
4045  SCIPinfoMessage(scip, file, "%-14s%s\n", "NAME", name);
4046 
4047  /* print OBJSENSE of the problem */
4048  SCIPinfoMessage(scip, file, "OBJSENSE\n");
4049  SCIPinfoMessage(scip, file, "%s\n", objsense == SCIP_OBJSENSE_MAXIMIZE ? " MAX" : " MIN");
4050 
4051  /* start ROWS section */
4052  SCIPinfoMessage(scip, file, "ROWS\n");
4053 
4054  /* print row type for the objective function */
4055  printStart(scip, file, "N", "Obj", -1);
4056  SCIPinfoMessage(scip, file, "\n");
4057 
4058  /* first fill the matrix with the objective coefficients */
4059  for( v = 0; v < nvars; ++v )
4060  {
4061  /* take care of the objective entry */
4062  var = vars[v];
4063  value = SCIPvarGetObj(var);
4064 
4065  /* we also want to add integer variables to the columns section, even if the objective value is 0, because it
4066  * might happen that they only exist in non-linear constraints, which leads to no other line in the column section
4067  * and therefore do not mark the variable as an integer
4068  */
4069  if( !SCIPisZero(scip, value) || SCIPvarGetType(var) < SCIP_VARTYPE_IMPLINT
4071  && (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0)) )
4072  {
4073  assert( matrix->nentries < matrix->sentries );
4074 
4075  matrix->values[matrix->nentries] = value;
4076  matrix->columns[matrix->nentries] = var;
4077  matrix->rows[matrix->nentries] = "Obj";
4078  matrix->nentries++;
4079  }
4080  }
4081 
4082  /* loop over all constraints */
4083  k = nconss;
4084  for( c = 0; c < nconss; ++c )
4085  {
4086  cons = conss[c];
4087  assert( cons != NULL);
4088 
4089  /* in case the transformed problems is written only constraint are posted which are enabled in the current node;
4090  * the conss array should only contain relevant constraints
4091  */
4092  assert( !transformed || SCIPconsIsEnabled(cons) );
4093 
4094  conshdlr = SCIPconsGetHdlr(cons);
4095  assert( conshdlr != NULL );
4096 
4097  conshdlrname = SCIPconshdlrGetName(conshdlr);
4098 
4099  /* construct constraint name */
4100  consname = consnames[c];
4101 
4102  if( strcmp(conshdlrname, "linear") == 0 )
4103  {
4104  lhs = SCIPgetLhsLinear(scip, cons);
4105  rhs = SCIPgetRhsLinear(scip, cons);
4106 
4107  /* there is nothing to do if the left hand side is minus infinity and the right side is infinity */
4108  if( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) )
4109  {
4110  if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, lhs, rhs) )
4111  needRANGES = TRUE;
4112 
4113  /* print row entry */
4114  printRowType(scip, file, lhs, rhs, consname);
4115 
4116  if( SCIPisInfinity(scip, rhs) )
4117  rhss[c] = lhs;
4118  else
4119  rhss[c] = rhs;
4120 
4121  assert( !SCIPisInfinity(scip, rhss[c]) );
4122 
4123  /* compute column entries */
4124  SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons),
4125  SCIPgetNVarsLinear(scip, cons), transformed, matrix, &rhss[c]) );
4126  }
4127  }
4128  else if( strcmp(conshdlrname, "setppc") == 0 )
4129  {
4130  /* print row entry */
4131  switch( SCIPgetTypeSetppc(scip, cons) )
4132  {
4134  printRowType(scip, file, 1.0, 1.0, consname);
4135  break;
4137  printRowType(scip, file, -SCIPinfinity(scip), 1.0, consname);
4138  break;
4140  printRowType(scip, file, 1.0, SCIPinfinity(scip), consname);
4141  break;
4142  }
4143 
4144  rhss[c] = 1.0;
4145 
4146  /* compute column entries */
4147  SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetVarsSetppc(scip, cons), NULL, SCIPgetNVarsSetppc(scip, cons), transformed, matrix, &rhss[c]) );
4148  }
4149  else if( strcmp(conshdlrname, "logicor") == 0 )
4150  {
4151  /* print row entry */
4152  printRowType(scip, file, 1.0, SCIPinfinity(scip), consname);
4153 
4154  rhss[c] = 1.0;
4155 
4156  /* compute column entries */
4157  SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons), transformed, matrix, &rhss[c]) );
4158  }
4159  else if( strcmp(conshdlrname, "knapsack") == 0 )
4160  {
4161  int i;
4162 
4163  /* print row entry */
4164  printRowType(scip, file, -SCIPinfinity(scip), (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), consname);
4165 
4166  nconsvars = SCIPgetNVarsKnapsack(scip, cons);
4167  weights = SCIPgetWeightsKnapsack(scip, cons);
4168 
4169  /* copy Longint array to SCIP_Real array */
4170  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nconsvars ) );
4171  for( i = 0; i < nconsvars; ++i )
4172  vals[i] = (SCIP_Real)weights[i];
4173 
4174  rhss[c] = (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons);
4175 
4176  /* compute column entries */
4177  SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetVarsKnapsack(scip, cons), vals, nconsvars, transformed, matrix, &rhss[c]) );
4178 
4179  SCIPfreeBufferArray(scip, &vals);
4180  }
4181  else if( strcmp(conshdlrname, "varbound") == 0 )
4182  {
4183  lhs = SCIPgetLhsVarbound(scip, cons);
4184  rhs = SCIPgetRhsVarbound(scip, cons);
4185 
4186  /* there is nothing to do if the left hand side is minus infinity and the right side is infinity */
4187  if( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) )
4188  {
4189  if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, lhs, rhs) )
4190  needRANGES = TRUE;
4191 
4192  /* print row entry */
4193  printRowType(scip, file, lhs, rhs, consname);
4194 
4195  /* allocate memory */
4196  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
4197  SCIP_CALL( SCIPallocBufferArray(scip, &vals, 2) );
4198 
4199  consvars[0] = SCIPgetVarVarbound(scip, cons);
4200  consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
4201 
4202  vals[0] = 1.0;
4203  vals[1] = SCIPgetVbdcoefVarbound(scip, cons);
4204 
4205  if( SCIPisInfinity(scip, rhs) )
4206  rhss[c] = lhs;
4207  else
4208  rhss[c] = rhs;
4209 
4210  assert( !SCIPisInfinity(scip, rhss[c]) );
4211 
4212  /* compute column entries */
4213  SCIP_CALL( getLinearCoeffs(scip, consname, consvars, vals, 2, transformed, matrix, &rhss[c]) );
4214 
4215  SCIPfreeBufferArray(scip, &vals);
4216  SCIPfreeBufferArray(scip, &consvars);
4217  }
4218  }
4219  else if( strcmp(conshdlrname, "indicator") == 0 )
4220  {
4221  SCIP_VAR* slackvar;
4222  SCIP_VAR* binvar;
4223 
4224  /* store slack variable in hash */
4225  slackvar = SCIPgetSlackVarIndicator(cons);
4226  assert( slackvar != NULL );
4227  assert( indicatorSlackHash != NULL );
4228  assert( !SCIPhashtableExists(indicatorSlackHash, (void*) slackvar) );
4229  SCIP_CALL( SCIPhashtableInsert(indicatorSlackHash, (void*) slackvar) );
4230 
4231  /* if slackvariable is aggregated, we store it in the list of aggregated variables */
4232  if ( SCIPvarGetStatus(slackvar) == SCIP_VARSTATUS_AGGREGATED )
4233  {
4234  SCIP_CALL( collectAggregatedVars(scip, &slackvar, 1, &aggvars, &naggvars, &saggvars, varFixedHash) );
4235  }
4236 
4237  /* store aggregated variables */
4238  binvar = SCIPgetBinaryVarIndicator(cons);
4239  if( SCIPvarIsNegated(binvar) )
4240  binvar = SCIPvarGetNegatedVar(binvar);
4241  assert( binvar != NULL );
4242  SCIP_CALL( collectAggregatedVars(scip, &binvar, 1, &aggvars, &naggvars, &saggvars, varFixedHash) );
4243 
4244  /* indicator constraint do not have a right hand side; mark this with SCIPinfinity(scip) */
4245  rhss[c] = SCIPinfinity(scip);
4246 
4247  /* store constraint */
4248  consIndicator[nConsIndicator++] = cons;
4249  continue;
4250  }
4251  else if( strcmp(conshdlrname, "SOS1") == 0 )
4252  {
4253  /* store constraint */
4254  consSOS1[nConsSOS1++] = cons;
4255 
4256  /* check for aggregated variables in SOS1 constraints for later output
4257  * of aggregations as linear constraints */
4258  consvars = SCIPgetVarsSOS1(scip, cons);
4259  nconsvars = SCIPgetNVarsSOS1(scip, cons);
4260 
4261  /* SOS constraint do not have a right hand side; mark this with SCIPinfinity(scip) */
4262  rhss[c] = SCIPinfinity(scip);
4263 
4264  SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varFixedHash) );
4265  }
4266  else if( strcmp(conshdlrname, "SOS2") == 0 )
4267  {
4268  /* store constraint */
4269  consSOS2[nConsSOS2++] = cons;
4270 
4271  /* check for aggregated variables in SOS2 constraints for later output aggregations as linear constraints */
4272  consvars = SCIPgetVarsSOS2(scip, cons);
4273  nconsvars = SCIPgetNVarsSOS2(scip, cons);
4274 
4275  /* SOS constraint do not have a right hand side; mark this with SCIPinfinity(scip) */
4276  rhss[c] = SCIPinfinity(scip);
4277 
4278  SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varFixedHash) );
4279  }
4280  else if( strcmp(conshdlrname, "quadratic") == 0 )
4281  {
4282  SCIP_VAR** quadvars;
4283  SCIP_Real* quadvarlincoefs;
4284  int j;
4285 
4286  /* store constraint */
4287  consQuadratic[nConsQuadratic++] = cons;
4288 
4289  /* collect linear coefficients of quadratic part */
4290  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars, SCIPgetNQuadVarTermsQuadratic(scip, cons)) );
4291  SCIP_CALL( SCIPallocBufferArray(scip, &quadvarlincoefs, SCIPgetNQuadVarTermsQuadratic(scip, cons)) );
4292  for( j = 0; j < SCIPgetNQuadVarTermsQuadratic(scip, cons); ++j )
4293  {
4294  quadvars[j] = SCIPgetQuadVarTermsQuadratic(scip, cons)[j].var;
4295  quadvarlincoefs[j] = SCIPgetQuadVarTermsQuadratic(scip, cons)[j].lincoef;
4296  }
4297 
4298  lhs = SCIPgetLhsQuadratic(scip, cons);
4299  rhs = SCIPgetRhsQuadratic(scip, cons);
4300 
4301  /* there is nothing to do if the left hand side is minus infinity and the right side is infinity */
4302  if( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) )
4303  {
4304  if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, lhs, rhs) )
4305  needRANGES = TRUE;
4306 
4307  /* print row entry */
4308  printRowType(scip, file, lhs, rhs, consname);
4309 
4310  if( SCIPisInfinity(scip, rhs) )
4311  rhss[c] = lhs;
4312  else
4313  rhss[c] = rhs;
4314 
4315  assert( !SCIPisInfinity(scip, rhss[c]) );
4316 
4317  /* compute column entries for linear part */
4318  SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetLinearVarsQuadratic(scip, cons), SCIPgetCoefsLinearVarsQuadratic(scip, cons),
4319  SCIPgetNLinearVarsQuadratic(scip, cons), transformed, matrix, &rhss[c]) );
4320 
4321  /* compute column entries for linear part in quadratic part */
4322  SCIP_CALL( getLinearCoeffs(scip, consname, quadvars, quadvarlincoefs, SCIPgetNQuadVarTermsQuadratic(scip, cons),
4323  transformed, matrix, &rhss[c]) );
4324  }
4325 
4326  /* check for aggregated variables in quadratic part of quadratic constraints for later output of
4327  * aggregations as linear constraints */
4328  consvars = quadvars;
4329  nconsvars = SCIPgetNQuadVarTermsQuadratic(scip, cons);
4330 
4331  SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varFixedHash) );
4332 
4333  SCIPfreeBufferArray(scip, &quadvars);
4334  SCIPfreeBufferArray(scip, &quadvarlincoefs);
4335  }
4336  else if( strcmp(conshdlrname, "soc") == 0 )
4337  {
4338  /* SOC constraints are of the form lhsconstant + sum_i (lhscoef_i*(lhsvar_i+lhsoffset_i))^2 <= (rhscoef*(rhsvar+rhsoffset))^2 */
4339  SCIP_Real* lincoefs;
4340  SCIP_Real coef;
4341  SCIP_Real offset;
4342 
4343  /* store constraint */
4344  consSOC[nConsSOC++] = cons;
4345 
4346  consvars = SCIPgetLhsVarsSOC(scip, cons);
4347  nconsvars = SCIPgetNLhsVarsSOC(scip, cons);
4348 
4349  rhs = -SCIPgetLhsConstantSOC(scip, cons);
4350 
4351  /* offsets on lhs give linear coefficients that need to be processed here */
4352  SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nconsvars) );
4353 
4354  for( v = 0; v < nconsvars; ++v )
4355  {
4356  offset = SCIPgetLhsOffsetsSOC(scip, cons)[v];
4357  coef = SCIPgetLhsCoefsSOC(scip, cons)[v];
4358 
4359  lincoefs[v] = 2 * offset * coef * coef;
4360  rhs -= offset * offset * coef * coef;
4361  }
4362 
4363  SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetLhsVarsSOC(scip, cons), lincoefs, nconsvars, transformed, matrix, &rhs) );
4364 
4365  SCIPfreeBufferArray(scip, &lincoefs);
4366 
4367  /* if there is an offsets on rhs, then we have linear a coefficient that need to be processed here */
4368  if( SCIPgetRhsOffsetSOC(scip, cons) != 0.0 )
4369  {
4370  SCIP_VAR* rhsvar;
4371  SCIP_Real lincoef;
4372 
4373  coef = SCIPgetRhsCoefSOC(scip, cons);
4374  offset = SCIPgetRhsOffsetSOC(scip, cons);
4375  rhsvar = SCIPgetRhsVarSOC(scip, cons);
4376  lincoef = -2 * offset * coef * coef;
4377  rhs += offset * offset * coef * coef;
4378 
4379  SCIP_CALL( getLinearCoeffs(scip, consname, &rhsvar, &lincoef, 1, transformed, matrix, &rhs) );
4380  }
4381 
4382  assert(!SCIPisInfinity(scip, ABS(rhs)));
4383 
4384  /* print row entry */
4385  printRowType(scip, file, -SCIPinfinity(scip), rhs, consname);
4386 
4387  rhss[c] = rhs;
4388 
4389  /* check for aggregated variables in for later output of aggregations as linear constraints */
4390  SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varFixedHash) );
4391  var = SCIPgetRhsVarSOC(scip, cons);
4392  SCIP_CALL( collectAggregatedVars(scip, &var, 1, &aggvars, &naggvars, &saggvars, varFixedHash) );
4393  }
4394  else if( strcmp(conshdlrname, "and") == 0 )
4395  {
4396  if( readerdata->linearizeands )
4397  {
4398  SCIP_VAR** rowvars;
4399  SCIP_VAR** operands;
4400  SCIP_VAR* resultant;
4401  SCIP_Real* rowvals;
4402  char* rowname;
4403  int nrowvars;
4404  int l;
4405  int n;
4406 
4407  nrowvars = SCIPgetNVarsAnd(scip, cons);
4408  operands = SCIPgetVarsAnd(scip, cons);
4409  resultant = SCIPgetResultantAnd(scip, cons);
4410 
4411  /* allocate buffer array */
4412  SCIP_CALL( SCIPallocBufferArray(scip, &rowvars, nrowvars + 1) );
4413  SCIP_CALL( SCIPallocBufferArray(scip, &rowvals, nrowvars + 1) );
4414 
4415  /* get length of constraint name */
4416  l = (int) strlen(consname);
4417 
4418  /* the tight relaxtion, number of and-constraint operands rows */
4419  if( !readerdata->aggrlinearizationands )
4420  {
4421  rowvars[0] = resultant;
4422  rowvals[0] = 1.0;
4423  rowvals[1] = -1.0;
4424 
4425  /* compute maximal length for rowname */
4426  n = (int) log10((double)nrowvars) + 1 + l;
4427 
4428  /* assure maximal allowed value */
4429  if( n >= MPS_MAX_NAMELEN )
4430  n = MPS_MAX_NAMELEN - 1;
4431 
4432  /* update maxnamelen */
4433  maxnamelen = MAX(maxnamelen, (unsigned int) n);
4434 
4435  /* print operator rows */
4436  for( v = 0; v < nrowvars; ++v )
4437  {
4438  /* compute maximal length for rowname */
4439  if( v == 0 )
4440  n = 2;
4441  else
4442  n = (int) log10((double)v) + 2;
4443  n += l;
4444 
4445  /* assure maximal allowed value */
4446  if( n >= MPS_MAX_NAMELEN )
4447  {
4448  n = MPS_MAX_NAMELEN - 1;
4449  ++faulty;
4450  }
4451 
4452  /* need memory for additional row */
4453  SCIP_CALL( SCIPallocBufferArray(scip, &rowname, n + 1) );
4454 
4455  assert(k < nconss + naddrows);
4456  consnames[k] = rowname;
4457 
4458  (void) SCIPsnprintf(rowname, n + 1, "%s_%d", consname, v);
4459  rowvars[1] = operands[v];
4460 
4461  /* print row entry */
4462  printRowType(scip, file, -SCIPinfinity(scip), 0.0, rowname);
4463 
4464  rhss[k] = 0.0;
4465 
4466  /* compute column entries */
4467  SCIP_CALL( getLinearCoeffs(scip, rowname, rowvars, rowvals, 2, transformed, matrix, &rhss[k]) );
4468  ++k;
4469  }
4470  }
4471 
4472  /* prepare for next row */
4473  for( v = nrowvars - 1; v >= 0; --v )
4474  {
4475  rowvars[v] = operands[v];
4476  rowvals[v] = -1.0;
4477  }
4478 
4479  rowvars[nrowvars] = resultant;
4480 
4481  /* the weak relaxtion, only one constraint */
4482  if( readerdata->aggrlinearizationands )
4483  {
4484  /* compute maximal length for rowname */
4485  n = l + 3;
4486 
4487  /* assure maximal allowed value */
4488  if( n >= MPS_MAX_NAMELEN )
4489  {
4490  n = MPS_MAX_NAMELEN - 1;
4491  ++faulty;
4492  }
4493 
4494  /* update maxnamelen */
4495  maxnamelen = MAX(maxnamelen, (unsigned int) n);
4496 
4497  /* need memory for additional row */
4498  SCIP_CALL( SCIPallocBufferArray(scip, &rowname, n + 1) );
4499 
4500  assert(k < nconss + naddrows);
4501  consnames[k] = rowname;
4502 
4503  /* adjust rowname of constraint */
4504  (void) SCIPsnprintf(rowname, n + 1, "%s_op", consname);
4505 
4506  rowvals[nrowvars] = (SCIP_Real) nrowvars;
4507 
4508  /* print row entry */
4509  printRowType(scip, file, -SCIPinfinity(scip), 0.0, rowname);
4510 
4511  rhss[k] = 0.0;
4512 
4513  /* compute column entries */
4514  SCIP_CALL( getLinearCoeffs(scip, rowname, rowvars, rowvals, nrowvars + 1, transformed, matrix, &rhss[k]) );
4515 
4516  SCIPdebugMsg(scip, "%g, %g\n", rowvals[1], rhss[k]);
4517  ++k;
4518  }
4519 
4520  rowvals[nrowvars] = 1.0;
4521 
4522  /* print row entry */
4523  printRowType(scip, file, -nrowvars + 1.0, SCIPinfinity(scip), consname);
4524 
4525  rhss[c] = -nrowvars + 1.0;
4526 
4527  /* compute column entries */
4528  SCIP_CALL( getLinearCoeffs(scip, consname, rowvars, rowvals, nrowvars + 1, transformed, matrix, &rhss[c]) );
4529 
4530  /* free buffer array */
4531  SCIPfreeBufferArray(scip, &rowvals);
4532  SCIPfreeBufferArray(scip, &rowvars);
4533  }
4534  else
4535  {
4536  /* and constraint printing not enabled; mark this with SCIPinfinity(scip) */
4537  rhss[c] = SCIPinfinity(scip);
4538 
4539  SCIPwarningMessage(scip, "change parameter \"reading/" READER_NAME "/linearize-and-constraints\" to TRUE to print and-constraints\n");
4540  }
4541  }
4542  else
4543  {
4544  /* unknown constraint type; mark this with SCIPinfinity(scip) */
4545  rhss[c] = SCIPinfinity(scip);
4546 
4547  SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
4548  }
4549  }
4550 
4551  if( faulty > 0 )
4552  {
4553  SCIPwarningMessage(scip, "there are %d and-constraint-rownames which have to be cut down to %d characters; MPS file might be corrupted\n",
4554  faulty, MPS_MAX_NAMELEN - 1);
4555  }
4556 
4557  /* free hash table */
4558  if( varFixedHash != NULL )
4559  SCIPhashtableFree(&varFixedHash);
4560 
4561  if( indicatorSlackHash != NULL && nConsIndicator == 0 )
4562  {
4563  SCIPhashtableFree(&indicatorSlackHash);
4564  assert( indicatorSlackHash == NULL );
4565  }
4566 
4567  if( naggvars > 0 )
4568  {
4569  /* construct variables name of the needed aggregated variables and the constraint names for the aggregation constraints */
4570 
4571  /* realloc memory */
4572  SCIP_CALL( SCIPreallocBufferArray(scip, &consnames, nconss + naddrows + naggvars) );
4573  SCIP_CALL( SCIPreallocBufferArray(scip, &rhss, nconss + naddrows + naggvars) );
4574  SCIP_CALL( SCIPreallocBufferArray(scip, &varnames, nvars + naggvars) );
4575 
4576  for( c = 0; c < naggvars; ++c )
4577  {
4578  size_t l;
4579 
4580  /* create variable name */
4581  var = aggvars[c];
4582 
4583  l = strlen(SCIPvarGetName(var));
4584  if( l >= MPS_MAX_NAMELEN )
4585  maxnamelen = MPS_MAX_NAMELEN - 1;
4586  else
4587  maxnamelen = MAX(maxnamelen, (unsigned int) l);
4588 
4589  SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) );
4590  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
4591 
4592  /* insert variable with variable name into hash map */
4593  varnames[nvars + c] = namestr;
4594  assert( !SCIPhashmapExists(varnameHashmap, var) );
4595  SCIP_CALL( SCIPhashmapInsert(varnameHashmap, var, (void*) namestr) );
4596 
4597  /* output row type (it is an equation) */
4598  SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) ); /* note that namestr above is freed via varnames */
4599  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "aggr_%s", SCIPvarGetName(var));
4600  printRowType(scip, file, 1.0, 1.0, namestr);
4601 
4602  l = strlen(namestr);
4603  maxnamelen = MAX(maxnamelen, (unsigned int) l);
4604  consnames[nconss + naddrows + c] = namestr;
4605  rhss[nconss + naddrows + c] = 0.0;
4606 
4607  /* compute column entries */
4608  SCIP_CALL( getLinearCoeffs(scip, namestr, &(aggvars[c]), NULL, 1, transformed, matrix, &rhss[nconss + naddrows + c]) );
4609 
4610  /* add the aggregated variables to the sparse matrix */
4611  SCIP_CALL( checkSparseMatrixCapacity(scip, matrix, 1) );
4612  matrix->values[matrix->nentries] = -1.0;
4613  matrix->columns[matrix->nentries] = aggvars[c];
4614  matrix->rows[matrix->nentries] = namestr;
4615  matrix->nentries++;
4616  }
4617  }
4618 
4619  /* collect also fixed variables, because they might not be removed from all constraints */
4620  /* @todo only collect fixed variables in the non-linear constraint types, where they (could not be)/(were not) removed */
4621  if( nfixedvars > 0 )
4622  {
4623  int startpos = nvars + naggvars;
4624  /* construct variables name of fixed variables */
4625 
4626  /* realloc memory */
4627  SCIP_CALL( SCIPreallocBufferArray(scip, &varnames, startpos + nfixedvars) );
4628 
4629  /* allocate memory for fixed variables */
4630  SCIP_CALL( SCIPallocBufferArray(scip, &fixvars, nfixedvars) );
4631 
4632  for( v = nfixedvars - 1; v >= 0; --v )
4633  {
4634  /* create variable name */
4635  var = fixedvars[v];
4636 
4638  {
4639  size_t l;
4640  l = strlen(SCIPvarGetName(var));
4641  if( l >= MPS_MAX_NAMELEN )
4642  maxnamelen = MPS_MAX_NAMELEN - 1;
4643  else
4644  maxnamelen = MAX(maxnamelen, (unsigned int) l);
4645 
4646  SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) );
4647  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
4648 
4649  varnames[startpos + nfixvars] = namestr;
4650  fixvars[nfixvars] = var;
4651  ++nfixvars;
4652 
4653  /* insert variable with variable name into hash map */
4654  assert(!SCIPhashmapExists(varnameHashmap, var));
4655  SCIP_CALL( SCIPhashmapInsert(varnameHashmap, var, (void*) namestr) );
4656 
4657  /* add the fixed variables to the sparse matrix, needed for columns section */
4658  SCIP_CALL( checkSparseMatrixCapacity(scip, matrix, 1) );
4659  matrix->values[matrix->nentries] = 0.0;
4660  matrix->columns[matrix->nentries] = var;
4661  matrix->rows[matrix->nentries] = "Obj";
4662  matrix->nentries++;
4663  }
4664  }
4665  }
4666 
4667  /* output COLUMNS section */
4668  printColumnSection(scip, file, matrix, varnameHashmap, indicatorSlackHash, maxnamelen);
4669 
4670  /* output RHS section */
4671  printRhsSection(scip, file, nconss + naddrows +naggvars, consnames, rhss, maxnamelen);
4672 
4673  /* output RANGES section */
4674  if( needRANGES )
4675  printRangeSection(scip, file, conss, nconss, consnames, transformed, maxnamelen);
4676 
4677  /* output BOUNDS section */
4678  printBoundSection(scip, file, vars, nvars, aggvars, naggvars, fixvars, nfixvars, transformed, varnames, indicatorSlackHash, maxnamelen);
4679 
4680  if( nfixedvars > 0 )
4681  {
4682  SCIPfreeBufferArray(scip, &fixvars);
4683  }
4684 
4685  /* print SOS section */
4686  if( nConsSOS1 > 0 || nConsSOS2 > 0 )
4687  {
4688  SCIP_Real* sosweights;
4689 
4690  SCIPinfoMessage(scip, file, "SOS\n");
4691  SCIPdebugMsg(scip, "start printing SOS section\n");
4692 
4693  SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) );
4694 
4695  /* first output SOS1 constraints */
4696  for( c = 0; c < nConsSOS1; ++c )
4697  {
4698  cons = consSOS1[c];
4699  consvars = SCIPgetVarsSOS1(scip, cons);
4700  nconsvars = SCIPgetNVarsSOS1(scip, cons);
4701  sosweights = SCIPgetWeightsSOS1(scip, cons);
4702  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPconsGetName(cons) );
4703 
4704  printStart(scip, file, "S1", namestr, -1);
4705  SCIPinfoMessage(scip, file, "\n");
4706 
4707  for( v = 0; v < nconsvars; ++v )
4708  {
4709  /* get variable name */
4710  assert ( SCIPhashmapExists(varnameHashmap, consvars[v]) );
4711  varname = (const char*) SCIPhashmapGetImage(varnameHashmap, consvars[v]);
4712 
4713  printStart(scip, file, "", varname, (int) maxnamelen);
4714 
4715  if( sosweights != NULL )
4716  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", sosweights[v]);
4717  else
4718  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d ", v);
4719 
4720  SCIPinfoMessage(scip, file, "%25s\n", valuestr);
4721  }
4722  }
4723 
4724  /* next output SOS2 constraints */
4725  for( c = 0; c < nConsSOS2; ++c )
4726  {
4727  cons = consSOS2[c];
4728  consvars = SCIPgetVarsSOS2(scip, cons);
4729  nconsvars = SCIPgetNVarsSOS2(scip, cons);
4730  sosweights = SCIPgetWeightsSOS2(scip, cons);
4731  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPconsGetName(cons) );
4732 
4733  printStart(scip, file, "S2", namestr, -1);
4734  SCIPinfoMessage(scip, file, "\n");
4735 
4736  for( v = 0; v < nconsvars; ++v )
4737  {
4738  /* get variable name */
4739  assert ( SCIPhashmapExists(varnameHashmap, consvars[v]) );
4740  varname = (const char*) SCIPhashmapGetImage(varnameHashmap, consvars[v]);
4741 
4742  printStart(scip, file, "", varname, (int) maxnamelen);
4743 
4744  if( sosweights != NULL )
4745  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", sosweights[v]);
4746  else
4747  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d ", v);
4748 
4749  SCIPinfoMessage(scip, file, "%25s\n", valuestr);
4750  }
4751  }
4752  SCIPfreeBufferArray(scip, &namestr);
4753  }
4754 
4755  /* print QCMATRIX sections for quadratic constraints
4756  * in difference to a quadratic term in the objective function, the quadratic part is not divided by 2 here
4757  */
4758  if( nConsQuadratic > 0 )
4759  {
4760  SCIP_QUADVARTERM* quadvarterms;
4761  SCIP_BILINTERM* bilinterms;
4762  const char* varname2;
4763  int nbilin;
4764 
4765  SCIPdebugMsg(scip, "start printing QCMATRIX sections for quadratic constraints\n");
4766  SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) );
4767 
4768  for( c = 0; c < nConsQuadratic; ++c )
4769  {
4770  cons = consQuadratic[c];
4771  nconsvars = SCIPgetNQuadVarTermsQuadratic(scip, cons);
4772  quadvarterms = SCIPgetQuadVarTermsQuadratic(scip, cons);
4773  bilinterms = SCIPgetBilinTermsQuadratic(scip, cons);
4774  nbilin = SCIPgetNBilinTermsQuadratic(scip, cons);
4775 
4776  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPconsGetName(cons) );
4777 
4778  SCIPinfoMessage(scip, file, "QCMATRIX %s\n", namestr);
4779 
4780  /* print x^2 terms */
4781  for( v = 0; v < nconsvars; ++v )
4782  {
4783  if( quadvarterms[v].sqrcoef == 0.0 )
4784  continue;
4785 
4786  /* get variable name */
4787  assert ( SCIPhashmapExists(varnameHashmap, quadvarterms[v].var) );
4788  varname = (const char*) SCIPhashmapGetImage(varnameHashmap, quadvarterms[v].var);
4789 
4790  /* get coefficient as string */
4791  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", quadvarterms[v].sqrcoef);
4792 
4793  /* print "x x coeff" line */
4794  printStart(scip, file, "", varname, (int) maxnamelen);
4795  printRecord(scip, file, varname, valuestr, maxnamelen);
4796  SCIPinfoMessage(scip, file, "\n", valuestr);
4797  }
4798 
4799  /* print bilinear terms; CPLEX format expects a symmetric matrix with all coefficients specified,
4800  * i.e., we have to split bilinear coefficients into two off diagonal elements */
4801  for( v = 0; v < nbilin; ++v )
4802  {
4803  if( bilinterms[v].coef == 0.0 )
4804  continue;
4805 
4806  /* get name of first variable */
4807  assert ( SCIPhashmapExists(varnameHashmap, bilinterms[v].var1) );
4808  varname = (const char*) SCIPhashmapGetImage(varnameHashmap, bilinterms[v].var1);
4809 
4810  /* get name of second variable */
4811  assert ( SCIPhashmapExists(varnameHashmap, bilinterms[v].var2) );
4812  varname2 = (const char*) SCIPhashmapGetImage(varnameHashmap, bilinterms[v].var2);
4813 
4814  /* get coefficient as string */
4815  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", 0.5*bilinterms[v].coef);
4816 
4817  /* print "x y coeff/2" line */
4818  printStart(scip, file, "", varname, (int) maxnamelen);
4819  printRecord(scip, file, varname2, valuestr, maxnamelen);
4820  SCIPinfoMessage(scip, file, "\n", valuestr);
4821 
4822  /* print "y x coeff/2" line */
4823  printStart(scip, file, "", varname2, (int) maxnamelen);
4824  printRecord(scip, file, varname, valuestr, maxnamelen);
4825  SCIPinfoMessage(scip, file, "\n", valuestr);
4826  }
4827  }
4828 
4829  SCIPfreeBufferArray(scip, &namestr);
4830  }
4831 
4832  /* print QCMATRIX sections for second order cone constraints */
4833  if( nConsSOC > 0 )
4834  {
4835  SCIP_Real* coefs;
4836 
4837  SCIPdebugMsg(scip, "start printing QCMATRIX sections for soc constraints\n");
4838  SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) );
4839 
4840  for( c = 0; c < nConsSOC; ++c )
4841  {
4842  cons = consSOC[c];
4843  consvars = SCIPgetLhsVarsSOC(scip, cons);
4844  nconsvars = SCIPgetNLhsVarsSOC(scip, cons);
4845  coefs = SCIPgetLhsCoefsSOC(scip, cons);
4846 
4847  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPconsGetName(cons) );
4848  SCIPinfoMessage(scip, file, "QCMATRIX %s\n", namestr);
4849 
4850  /* print alpha_i^2 x_i^2 terms */
4851  for( v = 0; v < nconsvars; ++v )
4852  {
4853  if( coefs[v] == 0.0 )
4854  continue;
4855 
4856  /* get variable name */
4857  assert ( SCIPhashmapExists(varnameHashmap, consvars[v]) );
4858  varname = (const char*) SCIPhashmapGetImage(varnameHashmap, consvars[v]);
4859 
4860  /* get coefficient^2 as string */
4861  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", coefs[v]*coefs[v]);
4862 
4863  /* print "x x coeff" line */
4864  printStart(scip, file, "", varname, (int) maxnamelen);
4865  printRecord(scip, file, varname, valuestr, maxnamelen);
4866  SCIPinfoMessage(scip, file, "\n", valuestr);
4867  }
4868 
4869  /* print -(alpha_{n+1} x_{n+1})^2 term */
4870 
4871  /* get variable name */
4872  var = SCIPgetRhsVarSOC(scip, cons);
4873  assert ( SCIPhashmapExists(varnameHashmap, var) );
4874  varname = (const char*) SCIPhashmapGetImage(varnameHashmap, var);
4875 
4876  /* get -coefficient^2 as string */
4877  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", -SCIPgetRhsCoefSOC(scip, cons)*SCIPgetRhsCoefSOC(scip, cons));
4878 
4879  /* print "x x coeff" line */
4880  printStart(scip, file, "", varname, (int) maxnamelen);
4881  printRecord(scip, file, varname, valuestr, maxnamelen);
4882  SCIPinfoMessage(scip, file, "\n", valuestr);
4883  }
4884 
4885  SCIPfreeBufferArray(scip, &namestr);
4886  }
4887 
4888  /* print indicator section */
4889  if( nConsIndicator > 0 )
4890  {
4891  SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) );
4892 
4893  SCIPinfoMessage(scip, file, "INDICATORS\n");
4894  SCIPdebugMsg(scip, "start printing INDICATOR section\n");
4895 
4896  /* output each indicator constraint */
4897  for( c = 0; c < nConsIndicator; ++c )
4898  {
4899  SCIP_CONS* lincons;
4900  SCIP_VAR* slackvar;
4901  SCIP_VAR* binvar;
4902 
4903  cons = consIndicator[c];
4904  binvar = SCIPgetBinaryVarIndicator(cons);
4905  lincons = SCIPgetLinearConsIndicator(cons);
4906  slackvar = SCIPgetSlackVarIndicator(cons);
4907 
4908  /* linvars always contains slack variable, thus nlinvars >= 1 */
4909  if( SCIPgetNVarsLinear(scip, lincons) <= 1 || SCIPconsIsDeleted(lincons) )
4910  continue;
4911 
4912  /* create variable and value strings */
4913  if( SCIPvarIsNegated(binvar) )
4914  {
4915  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d", 0);
4916  assert( SCIPvarGetNegatedVar(binvar) != NULL );
4917  assert( SCIPhashmapExists(varnameHashmap, SCIPvarGetNegatedVar(binvar)) );
4918  varname = (const char*) SCIPhashmapGetImage(varnameHashmap, SCIPvarGetNegatedVar(binvar));
4919  }
4920  else
4921  {
4922  (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d", 1);
4923  assert ( SCIPhashmapExists(varnameHashmap, binvar) );
4924  varname = (const char*) SCIPhashmapGetImage(varnameHashmap, binvar);
4925  }
4926 
4927  /* write records */
4928  if ( SCIPvarGetStatus(slackvar) == SCIP_VARSTATUS_AGGREGATED )
4929  {
4930  /* for aggregated variables output name of aggregating constraint */
4931  (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "aggr_%s", SCIPvarGetName(slackvar));
4932  printStart(scip, file, "IF", namestr, (int) maxnamelen);
4933  printRecord(scip, file, varname, valuestr, maxnamelen);
4934  SCIPinfoMessage(scip, file, "\n");
4935  }
4936  else
4937  {
4938  printStart(scip, file, "IF", SCIPconsGetName(lincons), (int) maxnamelen);
4939  printRecord(scip, file, varname, valuestr, maxnamelen);
4940  SCIPinfoMessage(scip, file, "\n");
4941  }
4942  }
4943  SCIPfreeBufferArray(scip, &namestr);
4944  }
4945 
4946  /* free matrix data structure */
4947  freeMatrix(scip, matrix);
4948 
4949  /* free slackvar hashtable */
4950  if( indicatorSlackHash != NULL )
4951  SCIPhashtableFree(&indicatorSlackHash);
4952 
4953  /* free variable hashmap */
4954  SCIPhashmapFree(&varnameHashmap);
4955 
4956  SCIPfreeBlockMemoryArray(scip, &aggvars, saggvars);
4957  SCIPfreeBufferArray(scip, &rhss);
4958 
4959  /* free buffer arrays for SOS1, SOS2, and quadratic */
4960  SCIPfreeBufferArray(scip, &consIndicator);
4961  SCIPfreeBufferArray(scip, &consSOC);
4962  SCIPfreeBufferArray(scip, &consQuadratic);
4963  SCIPfreeBufferArray(scip, &consSOS2);
4964  SCIPfreeBufferArray(scip, &consSOS1);
4965 
4966  /* free variable and constraint name array */
4967  for( v = nvars + naggvars + nfixvars - 1; v >= 0; --v )
4968  SCIPfreeBufferArray(scip, &varnames[v]);
4969  SCIPfreeBufferArray(scip, &varnames);
4970 
4971  for( c = nconss + naddrows + naggvars - 1; c >= 0; --c )
4972  SCIPfreeBufferArray(scip, &consnames[c]);
4973  SCIPfreeBufferArray(scip, &consnames);
4974 
4975  /* print end of data line */
4976  SCIPinfoMessage(scip, file, "ENDATA");
4977 
4978  *result = SCIP_SUCCESS;
4979 
4980  return SCIP_OKAY;
4981 }
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:3020
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:5379
#define NULL
Definition: def.h:239
static SCIP_DECL_READERCOPY(readerCopyMps)
Definition: reader_mps.c:3714
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:9901
#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:2672
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:3375
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:10596
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2265
static SCIP_RETCODE readQMatrix(MPSINPUT *mpsi, SCIP_Bool isQuadObj, SCIP *scip)
Definition: reader_mps.c:1926
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:9250
#define READER_NAME
Definition: reader_mps.c:69
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17343
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:3451
#define SCIP_MAXSTRLEN
Definition: def.h:260
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:5403
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:2416
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17399
static SCIP_RETCODE checkSparseMatrixCapacity(SCIP *scip, SPARSEMATRIX *matrix, int capacity)
Definition: reader_mps.c:2884
SCIP_Real * SCIPgetWeightsSOS1(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sos1.c:10621
static SCIP_DECL_READERFREE(readerFreeMps)
Definition: reader_mps.c:3730
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:2710
static void printColumnSection(SCIP *scip, FILE *file, SPARSEMATRIX *matrix, SCIP_HASHMAP *varnameHashmap, SCIP_HASHTABLE *indicatorSlackHash, unsigned int maxnamelen)
Definition: reader_mps.c:3247
#define FALSE
Definition: def.h:65
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2793
SCIP_Real SCIPinfinity(SCIP *scip)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10017
#define TRUE
Definition: def.h:64
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:3845
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:2467
SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4613
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2931
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:2014
int SCIPgetNQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
public methods for querying solving statistics
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17159
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:3025
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:8072
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:17353
#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:5156
#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:2790
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:17289
SCIP_VAR * SCIPgetResultantAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5181
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:1069
SCIP_Real SCIPgetRhsVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR ** SCIPgetVarsSOS2(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sos2.c:2492
SCIP_RETCODE SCIPaddVarSOS1(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real weight)
Definition: cons_sos1.c:10504
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:17309
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:1356
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:4703
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:16729
#define DEFAULT_LINEARIZE_ANDS
Definition: reader_mps.c:73
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2826
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:174
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
#define SCIP_CALL(x)
Definition: def.h:351
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:5451
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:4450
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:62
int SCIPgetNLhsVarsSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5367
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:1733
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:9926
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:41
SCIP_VAR * SCIPgetRhsVarSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5427
static void printRecord(SCIP *scip, FILE *file, const char *col1, const char *col2, unsigned int maxnamelen)
Definition: reader_mps.c:2730
static const char * mpsinputField5(const MPSINPUT *mpsi)
Definition: reader_mps.c:278
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9292
SCIP_Real * SCIPgetWeightsSOS2(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sos2.c:2517
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:209
#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:17191
static SCIP_RETCODE readObjsen(SCIP *scip, MPSINPUT *mpsi)
Definition: reader_mps.c:772
int SCIPgetNVarsSOS1(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sos1.c:10571
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:3809
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:2828
static SCIP_RETCODE readIndicators(MPSINPUT *mpsi, SCIP *scip)
Definition: reader_mps.c:2321
Constraint handler for linear constraints in their most general form, .
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2326
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:12253
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:9271
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2064
#define SCIP_HASHSIZE_NAMES
Definition: def.h:270
static unsigned int computeFieldWidth(unsigned int width)
Definition: reader_mps.c:2719
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:208
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:3077
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:3758
static void freeMatrix(SCIP *scip, SPARSEMATRIX *matrix)
Definition: reader_mps.c:2902
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:5415
public methods for message output
SCIP_Real SCIPgetRhsCoefSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5439
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16848
static SCIP_RETCODE mpsinputCreate(SCIP *scip, MPSINPUT **mpsi, SCIP_FILE *fp)
Definition: reader_mps.c:164
#define SCIP_Real
Definition: def.h:150
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:372
int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5132
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:2866
public methods for message handling
static SCIP_RETCODE readRanges(MPSINPUT *mpsi, SCIP *scip)
Definition: reader_mps.c:1216
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8265
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8255
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip_reader.c:266
#define SCIP_Longint
Definition: def.h:135
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17026
static void printBoundSectionName(SCIP *scip, FILE *file)
Definition: reader_mps.c:3440
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16894
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2377
enum MpsSection MPSSECTION
Definition: reader_mps.c:115
SCIP_RETCODE SCIPcreateConsBounddisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
static SCIP_RETCODE checkConsnames(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool transformed, unsigned int *maxnamelen, const char ***consnames, SCIP_Bool *error)
Definition: reader_mps.c:3141
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsSOS1(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *weights, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_sos1.c:10367
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:60
constraint handler for SOS type 2 constraints
SCIP_RETCODE SCIPcreateConsSOS2(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *weights, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_sos2.c:2317
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
static const char * mpsinputField2(const MPSINPUT *mpsi)
Definition: reader_mps.c:245
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17409
static SCIP_DECL_HASHKEYEQ(hashKeyEqString)
Definition: reader_mps.c:2684
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
MpsSection
Definition: reader_mps.c:96
#define DEFAULT_AGGRLINEARIZATION_ANDS
Definition: reader_mps.c:74
#define READER_EXTENSION
Definition: reader_mps.c:71
static void printRhsSection(SCIP *scip, FILE *file, int nconss, const char **consnames, SCIP_Real *rhss, unsigned int maxnamelen)
Definition: reader_mps.c:3339
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2874
SCIP_QUADVARTERM * SCIPgetQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:219
static SCIP_RETCODE readObjname(SCIP *scip, MPSINPUT *mpsi)
Definition: reader_mps.c:824
constraint handler for bound disjunction constraints
static void printStart(SCIP *scip, FILE *file, const char *col1, const char *col2, int maxnamelen)
Definition: reader_mps.c:2756
SCIP_CONS * SCIPgetLinearConsIndicator(SCIP_CONS *cons)
SCIP_Longint * SCIPgetWeightsKnapsack(SCIP *scip, SCIP_CONS *cons)
public methods for reader plugins
SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
#define SCIPABORT()
Definition: def.h:323
public methods for global and local (sub)problems
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16920
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition: misc.c:9975
#define PATCH_CHAR
Definition: reader_mps.c:85
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real * SCIPgetLhsCoefsSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5391
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
#define ABS(x)
Definition: def.h:204
SCIP_RETCODE SCIPsetReaderFree(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERFREE((*readerfree)))
Definition: scip_reader.c:242
static SCIP_DECL_READERREAD(readerReadMps)
Definition: reader_mps.c:3745
SCIP_RETCODE SCIPincludeReaderMps(SCIP *scip)
Definition: reader_mps.c:3775
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip_var.c:1530
static SCIP_RETCODE getLinearCoeffs(SCIP *scip, const char *consname, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool transformed, SPARSEMATRIX *matrix, SCIP_Real *rhs)
Definition: reader_mps.c:2917
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:129
static SCIP_RETCODE readMps(SCIP *scip, const char *filename, const char ***varnames, const char ***consnames, int *varnamessize, int *consnamessize, int *nvarnames, int *nconsnames)
Definition: reader_mps.c:2558
(extended) MPS file reader
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16884
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:134
static SCIP_RETCODE readQCMatrix(MPSINPUT *mpsi, SCIP *scip)
Definition: reader_mps.c:2138
static SCIP_RETCODE readName(SCIP *scip, MPSINPUT *mpsi)
Definition: reader_mps.c:725
memory allocation routines