Scippy

SCIP

Solving Constraint Integer Programs

reader_gms.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2014 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file reader_gms.c
17  * @brief GAMS file writer
18  * @author Ambros Gleixner
19  * @author Stefan Vigerske
20  *
21  * @todo Check for words reserved for GAMS.
22  */
23 
24 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
25 
26 #include <stdlib.h>
27 #include <assert.h>
28 #include <string.h>
29 
30 #ifdef WITH_GAMS
31 #include <sys/stat.h>
32 
33 #include "gmomcc.h"
34 #include "gevmcc.h"
35 
36 #include "reader_gmo.h"
37 #endif
38 
39 #include "scip/reader_gms.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_soc.h"
45 #include "scip/cons_sos1.h"
46 #include "scip/cons_sos2.h"
47 #include "scip/cons_setppc.h"
48 #include "scip/cons_varbound.h"
49 #include "scip/cons_indicator.h"
50 #include "scip/cons_abspower.h"
51 #include "scip/cons_nonlinear.h"
52 #include "scip/cons_bivariate.h"
53 #include "scip/pub_misc.h"
54 
55 #define READER_NAME "gmsreader"
56 #define READER_DESC "file writer for MI(NL)(SOC)Ps in GAMS file format"
57 #define READER_EXTENSION "gms"
58 
59 
60 #define GMS_MAX_LINELEN 256
61 #define GMS_MAX_PRINTLEN 256 /**< the maximum length of any line is 255 + '\\0' = 256*/
62 #define GMS_MAX_NAMELEN 64 /**< the maximum length for any name is 63 + '\\0' = 64 */
63 #define GMS_PRINTLEN 100
64 #define GMS_DEFAULT_BIGM 1e+6
65 #define GMS_DEFAULT_INDICATORREFORM 's'
66 #define GMS_DEFAULT_SIGNPOWER FALSE
67 
68 /*
69  * Local methods (for writing)
70  */
71 
72 static const char badchars[] = "#*+/-@$";
73 
74 /** transforms given variables, scalars, and constant to the corresponding active variables, scalars, and constant */
75 static
77  SCIP* scip, /**< SCIP data structure */
78  SCIP_VAR** vars, /**< vars array to get active variables for */
79  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
80  int* nvars, /**< pointer to number of variables and values in vars and vals array */
81  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
82  SCIP_Bool transformed /**< transformed constraint? */
83  )
84 {
85  int requiredsize;
86  int v;
87 
88  assert( scip != NULL );
89  assert( vars != NULL );
90  assert( scalars != NULL );
91  assert( nvars != NULL );
92  assert( constant != NULL );
93 
94  if( transformed )
95  {
96  SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize, TRUE) );
97 
98  if( requiredsize > *nvars )
99  {
100  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
101  SCIP_CALL( SCIPreallocBufferArray(scip, &scalars, requiredsize) );
102 
103  SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize, TRUE) );
104  assert( requiredsize <= *nvars );
105  }
106  }
107  else
108  {
109  for( v = 0; v < *nvars; ++v )
110  {
111  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalars[v], constant) );
112  }
113  }
114  return SCIP_OKAY;
115 }
116 
117 /** clears the given line buffer */
118 static
120  char* linebuffer, /**< line */
121  int* linecnt /**< number of characters in line */
122  )
123 {
124  assert( linebuffer != NULL );
125  assert( linecnt != NULL );
126 
127  (*linecnt) = 0;
128  linebuffer[0] = '\0';
129 }
130 
131 /** ends the given line with '\\0' and prints it to the given file stream */
132 static
133 void endLine(
134  SCIP* scip, /**< SCIP data structure */
135  FILE* file, /**< output file (or NULL for standard output) */
136  char* linebuffer, /**< line */
137  int* linecnt /**< number of characters in line */
138  )
139 {
140  assert( scip != NULL );
141  assert( linebuffer != NULL );
142  assert( linecnt != NULL );
143 
144  if( (*linecnt) > 0 )
145  {
146  linebuffer[(*linecnt)] = '\0';
147  SCIPinfoMessage(scip, file, "%s\n", linebuffer);
148  clearLine(linebuffer, linecnt);
149  }
150 }
151 
152 /** appends extension to line and prints it to the give file stream if the
153  * line exceeded the length given in the define GMS_PRINTLEN */
154 static
156  SCIP* scip, /**< SCIP data structure */
157  FILE* file, /**< output file (or NULL for standard output) */
158  char* linebuffer, /**< line */
159  int* linecnt, /**< number of characters in line */
160  const char* extension /**< string to extend the line */
161  )
162 {
163  size_t len;
164  assert( scip != NULL );
165  assert( linebuffer != NULL );
166  assert( linecnt != NULL );
167  assert( extension != NULL );
168  assert( strlen(linebuffer) + strlen(extension) < GMS_MAX_PRINTLEN );
169 
170  /* NOTE: avoid
171  * sprintf(linebuffer, "%s%s", linebuffer, extension);
172  * because of overlapping memory areas in memcpy used in sprintf.
173  */
174  len = strlen(linebuffer);
175  strncat(linebuffer, extension, GMS_MAX_PRINTLEN - len);
176 
177  (*linecnt) += (int) strlen(extension);
178 
179  SCIPdebugMessage("linebuffer <%s>, length = %lu\n", linebuffer, (unsigned long)len);
180 
181  if( (*linecnt) > GMS_PRINTLEN )
182  endLine(scip, file, linebuffer, linecnt);
183 }
184 
185 /** appends extension to line and prints it to the give file stream if the
186  * line exceeded the length given in the define GMS_PRINTLEN
187  * indents the line by some spaces if it is a new line */
188 static
190  SCIP* scip, /**< SCIP data structure */
191  FILE* file, /**< output file (or NULL for standard output) */
192  char* linebuffer, /**< line */
193  int* linecnt, /**< number of characters in line */
194  const char* extension /**< string to extend the line */
195  )
196 {
197  if( *linecnt == 0 )
198  /* we start a new line; therefore we indent line */
199  appendLine(scip, file, linebuffer, linecnt, " ");
200 
201  appendLine(scip, file, linebuffer, linecnt, extension);
202 }
203 
204 /** checks string for occurences of '#', '*', '+', '/', and '-' and replaces those by '_' */
205 static
207  char* name /**< string to adjust */
208  )
209 {
210  const char* badchar;
211 
212  assert( name != NULL );
213 
214  for( badchar = badchars; *badchar; ++badchar )
215  {
216  char* c = strchr(name, *badchar);
217 
218  while( c != NULL )
219  {
220  assert( *c == *badchar );
221 
222  *c = '_';
223  c = strchr(c, *badchar);
224  }
225  }
226 }
227 
228 /* print first len-1 characters of name to string s and replace '#', '*', '+', '/', and '-' by '_' if necessary */
229 static
231  SCIP* scip, /**< SCIP data structure */
232  char* t, /**< target string */
233  int len, /**< length of t */
234  const char* name /**< source string or format string */
235  )
236 {
237  SCIP_Bool replaceforbiddenchars;
238 
239  assert( t != NULL );
240  assert( len > 0 );
241 
242  SCIP_CALL( SCIPgetBoolParam(scip, "reading/gmsreader/replaceforbiddenchars", &replaceforbiddenchars) );
243 
244  (void) SCIPsnprintf(t, len, "%s", name);
245 
246  if( replaceforbiddenchars )
247  conformName(t);
248 
249  return SCIP_OKAY;
250 }
251 
252 
253 /* retransform to active variables and print in GAMS format to file stream with surrounding bracket, pre- and suffix */
254 static
256  SCIP* scip, /**< SCIP data structure */
257  FILE* file, /**< output file (or NULL for standard output) */
258  char* linebuffer, /**< line */
259  int* linecnt, /**< number of characters in line */
260  const char* prefix, /**< prefix (maybe NULL) */
261  const char* suffix, /**< suffix (maybe NULL) */
262  int nvars, /**< number of variables */
263  SCIP_VAR** vars, /**< array of variables */
264  SCIP_Real* vals, /**< array of values (or NULL if all ones) */
265  SCIP_Bool transformed /**< transformed constraint? */
266  )
267 {
268  int v;
269  int closingbracket;
270 
271  SCIP_VAR* var;
272  char varname[GMS_MAX_NAMELEN];
273  char buffer[GMS_MAX_PRINTLEN];
274  char ext[GMS_MAX_PRINTLEN];
275 
276  SCIP_VAR** activevars = NULL;
277  SCIP_Real* activevals = NULL;
278  int nactivevars;
279  SCIP_Real activeconstant = 0.0;
280 
281  assert( scip != NULL );
282  assert( vars != NULL || nvars == 0 );
283 
284 
285  if( *linecnt == 0 )
286  /* we start a new line; therefore we tab this line */
287  appendLine(scip, file, linebuffer, linecnt, " ");
288 
289  if( nvars == 0 )
290  {
291  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%s(0)%s", prefix != NULL ? prefix : "", suffix != NULL ? suffix : "");
292 
293  appendLine(scip, file, linebuffer, linecnt, buffer);
294  }
295  else
296  {
297  nactivevars = nvars;
298 
299  /* duplicate variable and value array */
300  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars) );
301  if( vals != NULL )
302  {
303  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars) );
304  }
305  else
306  {
307  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
308 
309  for( v = 0; v < nactivevars; ++v )
310  activevals[v] = 1.0;
311  }
312 
313  /* retransform given variables to active variables */
314  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
315 
316  assert( nactivevars == 0 || activevals != NULL );
317 
318  if( nactivevars == 0 && SCIPisZero(scip, activeconstant) )
319  {
320  if( *linecnt == 0 )
321  /* we start a new line; therefore we tab this line */
322  appendLine(scip, file, linebuffer, linecnt, " ");
323 
324  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%s(0)%s", prefix != NULL ? prefix : "", suffix != NULL ? suffix : "");
325 
326  appendLine(scip, file, linebuffer, linecnt, buffer);
327  }
328  else
329  {
330  /* buffer prefix */
331  (void) SCIPsnprintf(ext, GMS_MAX_PRINTLEN, "%s(", prefix != NULL ? prefix : "");
332 
333  /* find position of closing bracket */
334  closingbracket = nactivevars;
335  if( SCIPisZero(scip, activeconstant) )
336  {
337  do
338  --closingbracket;
339  while( SCIPisZero(scip, activevals[closingbracket]) && closingbracket > 0 );
340  }
341 
342  /* print active variables */
343  for( v = 0; v < nactivevars; ++v )
344  {
345  var = activevars[v];
346  assert( var != NULL );
347 
348  if( !SCIPisZero(scip, activevals[v]) )
349  {
350  if( *linecnt == 0 )
351  /* we start a new line; therefore we tab this line */
352  appendLine(scip, file, linebuffer, linecnt, " ");
353 
354  SCIP_CALL( printConformName(scip, varname, GMS_MAX_NAMELEN, SCIPvarGetName(var)) );
355 
356  if( SCIPisEQ(scip, activevals[v], 1.0) )
357  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%s%s%s%s%s", ext, strchr(ext, '(') == NULL ? "+" : "",
358  varname, (v == closingbracket) ? ")" : "", (v == closingbracket && suffix) ? suffix : "");
359  else if( SCIPisEQ(scip, activevals[v], -1.0) )
360  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%s-%s%s%s", ext,
361  varname, (v == closingbracket) ? ")" : "", (v == closingbracket && suffix) ? suffix : "");
362  else if( strchr(ext, '(') != NULL )
363  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%s%.15g*%s%s%s", ext,
364  activevals[v], varname, (v == closingbracket) ? ")" : "", (v == closingbracket && suffix) ? suffix : "");
365  else
366  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%s%+.15g*%s%s%s", ext,
367  activevals[v], varname, (v == closingbracket) ? ")" : "", (v == closingbracket && suffix) ? suffix : "");
368 
369  appendLine(scip, file, linebuffer, linecnt, buffer);
370 
371  (void) SCIPsnprintf(ext, GMS_MAX_PRINTLEN, (*linecnt == 0) ? "" : " ");
372  }
373  }
374 
375  /* print active constant */
376  if( !SCIPisZero(scip, activeconstant) )
377  {
378  if( *linecnt == 0 )
379  /* we start a new line; therefore we tab this line */
380  appendLine(scip, file, linebuffer, linecnt, " ");
381 
382  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%s%+.15g)%s", ext, activeconstant, suffix ? suffix : "");
383 
384  appendLine(scip, file, linebuffer, linecnt, buffer);
385  }
386  /* nothing has been printed, yet */
387  else if( strchr(ext, '(') != NULL )
388  {
389  if( *linecnt == 0 )
390  /* we start a new line; therefore we tab this line */
391  appendLine(scip, file, linebuffer, linecnt, " ");
392 
393  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%s(0)%s", prefix ? prefix : "", suffix ? suffix : "");
394 
395  appendLine(scip, file, linebuffer, linecnt, buffer);
396  }
397  }
398 
399  /* free buffer arrays */
400  SCIPfreeBufferArray(scip, &activevars);
401  SCIPfreeBufferArray(scip, &activevals);
402  }
403 
404  return SCIP_OKAY;
405 }
406 
407 
408 /* print linear row in GAMS format to file stream (without retransformation to active variables) */
409 static
411  SCIP* scip, /**< SCIP data structure */
412  FILE* file, /**< output file (or NULL for standard output) */
413  const char* rowname, /**< row name */
414  const char* rownameextension, /**< row name extension */
415  const char* type, /**< row type ("=e=", "=l=", or "=g=") */
416  int nvars, /**< number of variables */
417  SCIP_VAR** vars, /**< array of variables */
418  SCIP_Real* vals, /**< array of values */
419  SCIP_Real rhs /**< right hand side */
420  )
421 {
422  int v;
423  char linebuffer[GMS_MAX_PRINTLEN] = { '\0' };
424  int linecnt;
425 
426  SCIP_VAR* var;
427  char varname[GMS_MAX_NAMELEN];
428  char consname[GMS_MAX_NAMELEN + 3]; /* four extra characters for ' ..' */
429  char buffer[GMS_MAX_PRINTLEN];
430 
431  assert( scip != NULL );
432  assert( strcmp(type, "=e=") == 0 || strcmp(type, "=l=") == 0 || strcmp(type, "=g=") == 0);
433  assert( nvars == 0 || (vars != NULL && vals != NULL) );
434 
435  clearLine(linebuffer, &linecnt);
436 
437  /* start each line with a space */
438  appendLine(scip, file, linebuffer, &linecnt, " ");
439 
440  /* print row name */
441  if( strlen(rowname) > 0 || strlen(rownameextension) > 0 )
442  {
443  (void) SCIPsnprintf(buffer, GMS_MAX_NAMELEN + 3, "%s%s ..", rowname, rownameextension);
444  SCIP_CALL( printConformName(scip, consname, GMS_MAX_NAMELEN + 3, buffer) );
445  appendLine(scip, file, linebuffer, &linecnt, consname);
446  }
447 
448  /* print coefficients */
449  if( nvars == 0 )
450  {
451  /* we start a new line; therefore we tab this line */
452  if( linecnt == 0 )
453  appendLine(scip, file, linebuffer, &linecnt, " ");
454 
455  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " 0");
456 
457  appendLine(scip, file, linebuffer, &linecnt, buffer);
458  }
459 
460  for( v = 0; v < nvars; ++v )
461  {
462  var = vars[v];
463  assert( var != NULL );
464 
465  /* we start a new line; therefore we tab this line */
466  if( linecnt == 0 )
467  appendLine(scip, file, linebuffer, &linecnt, " ");
468 
469  SCIP_CALL( printConformName(scip, varname, GMS_MAX_NAMELEN, SCIPvarGetName(var)) );
470  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " %+.15g*%s", vals[v], varname);
471 
472  appendLine(scip, file, linebuffer, &linecnt, buffer);
473  }
474 
475  /* print right hand side */
476  if( SCIPisZero(scip, rhs) )
477  rhs = 0.0;
478 
479  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " %s %.15g;", type, rhs);
480 
481  /* we start a new line; therefore we tab this line */
482  if( linecnt == 0 )
483  appendLine(scip, file, linebuffer, &linecnt, " ");
484  appendLine(scip, file, linebuffer, &linecnt, buffer);
485 
486  endLine(scip, file, linebuffer, &linecnt);
487 
488  return SCIP_OKAY;
489 }
490 
491 
492 /** prints given linear constraint information in GAMS format to file stream */
493 static
495  SCIP* scip, /**< SCIP data structure */
496  FILE* file, /**< output file (or NULL for standard output) */
497  const char* rowname, /**< name of the row */
498  int nvars, /**< number of variables */
499  SCIP_VAR** vars, /**< array of variables */
500  SCIP_Real* vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
501  SCIP_Real lhs, /**< left hand side */
502  SCIP_Real rhs, /**< right hand side */
503  SCIP_Bool transformed /**< transformed constraint? */
504  )
505 {
506  int v;
507  SCIP_VAR** activevars = NULL;
508  SCIP_Real* activevals = NULL;
509  int nactivevars;
510  SCIP_Real activeconstant = 0.0;
511 
512  assert( scip != NULL );
513  assert( rowname != NULL );
514 
515  /* The GAMS format does not forbid that the variable array is empty */
516  assert( nvars == 0 || vars != NULL );
517 
518  assert( lhs <= rhs );
519 
520  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
521  return SCIP_OKAY;
522 
523  nactivevars = nvars;
524  if( nvars > 0 )
525  {
526  /* duplicate variable and value array */
527  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars) );
528  if( vals != NULL )
529  {
530  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars) );
531  }
532  else
533  {
534  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
535 
536  for( v = 0; v < nactivevars; ++v )
537  activevals[v] = 1.0;
538  }
539 
540  /* retransform given variables to active variables */
541  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
542  }
543 
544  /* print row(s) in GAMS format */
545  if( SCIPisEQ(scip, lhs, rhs) )
546  {
547  assert( !SCIPisInfinity(scip, rhs) );
548 
549  /* print equality constraint */
550  SCIP_CALL( printLinearRow(scip, file, rowname, "", "=e=",
551  nactivevars, activevars, activevals, rhs - activeconstant) );
552  }
553  else
554  {
555  if( !SCIPisInfinity(scip, -lhs) )
556  {
557  /* print inequality ">=" */
558  SCIP_CALL( printLinearRow(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", "=g=",
559  nactivevars, activevars, activevals, lhs - activeconstant) );
560  }
561  if( !SCIPisInfinity(scip, rhs) )
562  {
563  /* print inequality "<=" */
564  SCIP_CALL( printLinearRow(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "=l=",
565  nactivevars, activevars, activevals, rhs - activeconstant) );
566  }
567  }
568 
569  if( nvars > 0 )
570  {
571  /* free buffer arrays */
572  SCIPfreeBufferArray(scip, &activevars);
573  SCIPfreeBufferArray(scip, &activevals);
574  }
575 
576  return SCIP_OKAY;
577 }
578 
579 
580 /* print quadratic row in GAMS format to file stream (performing retransformation to active variables) */
581 static
583  SCIP* scip, /**< SCIP data structure */
584  FILE* file, /**< output file (or NULL for standard output) */
585  const char* rowname, /**< row name */
586  const char* rownameextension, /**< row name extension */
587  const char* type, /**< row type ("=e=", "=l=", or "=g=") */
588  int nlinvars, /**< number of linear terms */
589  SCIP_VAR** linvars, /**< variables in linear part */
590  SCIP_Real* lincoeffs, /**< coefficients of variables in linear part */
591  int nquadvarterms, /**< number of quadratic variable terms */
592  SCIP_QUADVARTERM* quadvarterms, /**< quadratic variable terms */
593  int nbilinterms, /**< number of bilinear terms */
594  SCIP_BILINTERM* bilinterms, /**< bilinear terms */
595  SCIP_Real rhs, /**< right hand side */
596  SCIP_Bool transformed /**< transformed constraint? */
597  )
598 {
599  int t;
600  char linebuffer[GMS_MAX_PRINTLEN] = { '\0' };
601  int linecnt;
602 
603  SCIP_VAR* var;
604  char consname[GMS_MAX_NAMELEN + 3]; /* four extra characters for ' ..' */
605  char buffer[GMS_MAX_PRINTLEN];
606 
607  assert( scip != NULL );
608  assert( strlen(rowname) > 0 || strlen(rownameextension) > 0 );
609  assert( strcmp(type, "=e=") == 0 || strcmp(type, "=l=") == 0 || strcmp(type, "=g=") == 0 );
610  assert( nlinvars == 0 || (linvars != NULL && lincoeffs != NULL) );
611  assert( nquadvarterms == 0 || quadvarterms != NULL );
612  assert( nbilinterms == 0 || bilinterms != NULL );
613  assert( nquadvarterms > 0 || nbilinterms == 0 );
614 
615  clearLine(linebuffer, &linecnt);
616 
617  /* start each line with a space */
618  appendLine(scip, file, linebuffer, &linecnt, " ");
619 
620  /* print row name */
621  (void) SCIPsnprintf(buffer, GMS_MAX_NAMELEN + 3, "%s%s ..", rowname, rownameextension);
622  SCIP_CALL( printConformName(scip, consname, GMS_MAX_NAMELEN + 3, buffer) );
623 
624  appendLine(scip, file, linebuffer, &linecnt, consname);
625 
626  /* print linear terms */
627  if( nlinvars > 0 )
628  {
629  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "+", " ", nlinvars, linvars, lincoeffs, transformed) );
630  }
631 
632  /* print linear coefficients of quadratic terms */
633  for( t = 0; t < nquadvarterms; ++t )
634  {
635  var = quadvarterms[t].var;
636  assert( var != NULL );
637 
638  if( !SCIPisZero(scip, quadvarterms[t].lincoef) )
639  {
640  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%+.15g*", quadvarterms[t].lincoef);
641 
642  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, buffer, NULL, 1, &var, NULL, transformed) );
643  }
644  }
645 
646  /* print square coefficients of quadratic terms */
647  for( t = 0; t < nquadvarterms; ++t )
648  {
649  var = quadvarterms[t].var;
650  assert( var != NULL );
651 
652  if( !SCIPisZero(scip, quadvarterms[t].sqrcoef) )
653  {
654  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%+.15g*sqr", quadvarterms[t].sqrcoef);
655 
656  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, buffer, NULL, 1, &var, NULL, transformed) );
657  }
658  }
659 
660  /* print bilinear terms */
661  for( t = 0; t < nbilinterms; ++t )
662  {
663  if( !SCIPisZero(scip, bilinterms[t].coef) )
664  {
665  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%+.15g*", bilinterms[t].coef);
666 
667  /* print first variable (retransformed to active variables) */
668  var = bilinterms[t].var1;
669  assert( var != NULL );
670 
671  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, buffer, "", 1, &var, NULL, transformed) );
672 
673  /* print second variable (retransformed to active variables) */
674  var = bilinterms[t].var2;
675  assert( var != NULL );
676 
677  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "*", " ", 1, &var, NULL, transformed) );
678  }
679  }
680 
681  /* print right hand side */
682  if( linecnt == 0 )
683  /* we start a new line; therefore we tab this line */
684  appendLine(scip, file, linebuffer, &linecnt, " ");
685 
686  if( SCIPisZero(scip, rhs) )
687  rhs = 0.0;
688 
689  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%s%s %.15g;", (nlinvars == 0 && nquadvarterms == 0) ? "0 " : "", type, rhs);
690 
691  appendLine(scip, file, linebuffer, &linecnt, buffer);
692 
693  endLine(scip, file, linebuffer, &linecnt);
694 
695  return SCIP_OKAY;
696 }
697 
698 
699 /** prints given quadratic constraint information in GAMS format to file stream */
700 static
702  SCIP* scip, /**< SCIP data structure */
703  FILE* file, /**< output file (or NULL for standard output) */
704  const char* rowname, /**< name of the row */
705  int nlinvars, /**< number of linear terms */
706  SCIP_VAR** linvars, /**< variables in linear part */
707  SCIP_Real* lincoeffs, /**< coefficients of variables in linear part */
708  int nquadvarterms, /**< number of quadratic variable terms */
709  SCIP_QUADVARTERM* quadvarterms, /**< quadratic variable terms */
710  int nbilinterms, /**< number of bilinear terms */
711  SCIP_BILINTERM* bilinterms, /**< bilinear terms */
712  SCIP_Real lhs, /**< left hand side */
713  SCIP_Real rhs, /**< right hand side */
714  SCIP_Bool transformed /**< transformed constraint? */
715  )
716 {
717  assert( scip != NULL );
718  assert( rowname != NULL );
719  assert( nlinvars == 0 || (linvars != NULL && lincoeffs != NULL) );
720  assert( nquadvarterms == 0 || quadvarterms != NULL );
721  assert( nbilinterms == 0 || bilinterms != NULL );
722  assert( nquadvarterms > 0 || nbilinterms == 0 );
723  assert( lhs <= rhs );
724 
725  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
726  return SCIP_OKAY;
727 
728  /* print row(s) in GAMS format */
729  if( SCIPisEQ(scip, lhs, rhs) )
730  {
731  assert( !SCIPisInfinity(scip, rhs) );
732 
733  /* print equality constraint */
734  SCIP_CALL( printQuadraticRow(scip, file, rowname, "", "=e=",
735  nlinvars, linvars, lincoeffs,
736  nquadvarterms, quadvarterms,
737  nbilinterms, bilinterms, rhs, transformed) );
738  }
739  else
740  {
741  if( !SCIPisInfinity(scip, -lhs) )
742  {
743  /* print inequality ">=" */
744  SCIP_CALL( printQuadraticRow(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", "=g=",
745  nlinvars, linvars, lincoeffs,
746  nquadvarterms, quadvarterms,
747  nbilinterms, bilinterms, lhs, transformed) );
748  }
749  if( !SCIPisInfinity(scip, rhs) )
750  {
751  /* print inequality "<=" */
752  SCIP_CALL( printQuadraticRow(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "=l=",
753  nlinvars, linvars, lincoeffs,
754  nquadvarterms, quadvarterms,
755  nbilinterms, bilinterms, rhs, transformed) );
756  }
757  }
758 
759  return SCIP_OKAY;
760 }
761 
762 /** check GAMS limitations on SOC constraints
763  * returns true of constraint can be written as conic equation in GAMS (using equation type =C=)
764  */
765 static
767  int nlhsvars, /**< number of variables on left hand side */
768  SCIP_VAR** lhsvars, /**< variables on left hand side */
769  SCIP_Real* lhscoeffs, /**< coefficients of variables on left hand side, or NULL if == 1.0 */
770  SCIP_Real* lhsoffsets, /**< offsets of variables on left hand side, or NULL if == 0.0 */
771  SCIP_Real lhsconstant, /**< constant on left hand side */
772  SCIP_VAR* rhsvar, /**< variable on right hand side */
773  SCIP_Real rhscoef, /**< coefficient of variable on right hand side */
774  SCIP_Real rhsoffset /**< offset of variable on right hand side */
775  )
776 {
777  int i;
778 
779  assert(nlhsvars == 0 || lhsvars != NULL);
780 
781  if( rhscoef != 1.0 )
782  return FALSE;
783 
784  if( rhsoffset != 0.0 )
785  return FALSE;
786 
787  if( rhsvar == NULL )
788  return FALSE;
789 
790  if( !SCIPvarIsActive(rhsvar) )
791  return FALSE;
792 
793  if( lhsconstant != 0.0 )
794  return FALSE;
795 
796  if( nlhsvars < 2 )
797  return FALSE;
798 
799  for( i = 0; i < nlhsvars; ++i )
800  {
801  if( lhscoeffs [i] != 1.0 )
802  return FALSE;
803 
804  if( lhsoffsets[i] != 0.0 )
805  return FALSE;
806 
807  if( !SCIPvarIsActive(lhsvars[i]) )
808  return FALSE;
809  }
810 
811  return TRUE;
812 }
813 
814 /* print second order cone row in GAMS format to file stream (performing retransformation to active variables)
815  * The constraints are of the following form:
816  * \f[
817  * \left\{ x \;:\; \sqrt{\gamma + \sum_{i=1}^{n} (\alpha_i\, (x_i + \beta_i))^2} \leq \alpha_{n+1}\, (x_{n+1}+\beta_{n+1}) \right\}.
818  * \f]
819  * */
820 static
822  SCIP* scip, /**< SCIP data structure */
823  FILE* file, /**< output file (or NULL for standard output) */
824  const char* rowname, /**< row name */
825  int nlhsvars, /**< number of variables on left hand side */
826  SCIP_VAR** lhsvars, /**< variables on left hand side */
827  SCIP_Real* lhscoeffs, /**< coefficients of variables on left hand side, or NULL if == 1.0 */
828  SCIP_Real* lhsoffsets, /**< offsets of variables on left hand side, or NULL if == 0.0 */
829  SCIP_Real lhsconstant, /**< constant on left hand side */
830  SCIP_VAR* rhsvar, /**< variable on right hand side */
831  SCIP_Real rhscoef, /**< coefficient of variable on right hand side */
832  SCIP_Real rhsoffset, /**< offset of variable on right hand side */
833  SCIP_Bool transformed /**< transformed constraint? */
834  )
835 {
836  char linebuffer[GMS_MAX_PRINTLEN] = { '\0' };
837  int linecnt;
838 
839  char consname[GMS_MAX_NAMELEN + 3]; /* four extra characters for ' ..' */
840  char buffer[GMS_MAX_PRINTLEN];
841 
842  assert( scip != NULL );
843  assert( strlen(rowname) > 0 );
844  assert( nlhsvars == 0 || lhsvars != NULL );
845 
846  clearLine(linebuffer, &linecnt);
847 
848  /* start each line with a space */
849  appendLine(scip, file, linebuffer, &linecnt, " ");
850 
851  /* print row name */
852  (void) SCIPsnprintf(buffer, GMS_MAX_NAMELEN + 3, "%s ..", rowname);
853  SCIP_CALL( printConformName(scip, consname, GMS_MAX_NAMELEN + 3, buffer) );
854 
855  appendLine(scip, file, linebuffer, &linecnt, consname);
856 
857  if( !isGAMSprintableSOC(nlhsvars, lhsvars, lhscoeffs, lhsoffsets, lhsconstant, rhsvar, rhscoef, rhsoffset) )
858  {
859  int t;
860 
861  /* print right-hand side on left */
862  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "sqr(%.15g +", rhsoffset);
863 
864  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, buffer, ")", 1, &rhsvar, &rhscoef, transformed) );
865 
866  appendLine(scip, file, linebuffer, &linecnt, " =g= ");
867 
868  /* print left-hand side on right */
869 
870  if( lhsconstant != 0.0 )
871  {
872  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%.15g", lhsconstant);
873 
874  appendLine(scip, file, linebuffer, &linecnt, buffer);
875  }
876 
877  for( t = 0; t < nlhsvars; ++t )
878  {
879  assert( lhsvars[t] != NULL );
880 
881  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "+ sqr(%.15g * (%.15g + ", lhscoeffs ? lhscoeffs[t] : 1.0, lhsoffsets ? lhsoffsets[t] : 0.0);
882 
883  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, buffer, "))", 1, &lhsvars[t], NULL, transformed) );
884  }
885  }
886  else
887  {
888  /* print right-hand side on left */
889  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "+", " ", 1, &rhsvar, &rhscoef, transformed) );
890 
891  appendLine(scip, file, linebuffer, &linecnt, " =c= ");
892 
893  /* print left-hand side on right */
894  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "+", " ", nlhsvars, lhsvars, lhscoeffs, transformed) );
895  }
896 
897  appendLine(scip, file, linebuffer, &linecnt, ";");
898 
899  endLine(scip, file, linebuffer, &linecnt);
900 
901  return SCIP_OKAY;
902 }
903 
904 /* print indicator constraint in some GAMS format to file stream (performing retransformation to active variables)
905  * The constraints are of the following form:
906  * \f[
907  * z = 1 -> s = 0
908  * \f]
909  * */
910 static
912  SCIP* scip, /**< SCIP data structure */
913  FILE* file, /**< output file (or NULL for standard output) */
914  const char* rowname, /**< row name */
915  SCIP_VAR* z, /**< indicating variable (binary) */
916  SCIP_VAR* s, /**< slack variable */
917  SCIP_Bool* sossetdeclr, /**< buffer to store whether we declared the SOS set for indicator reform */
918  SCIP_Bool transformed /**< transformed constraint? */
919  )
920 {
921  char linebuffer[GMS_MAX_PRINTLEN] = { '\0' };
922  int linecnt;
923  SCIP_Real coef;
924  char indicatorform;
925 
926  char consname[GMS_MAX_NAMELEN + 30];
927  char buffer[GMS_MAX_PRINTLEN];
928 
929  assert( scip != NULL );
930  assert( strlen(rowname) > 0 );
931  assert( z != NULL );
932  assert( s != NULL );
933  assert( SCIPvarIsBinary(z) );
934  assert( sossetdeclr != NULL );
935 
936  clearLine(linebuffer, &linecnt);
937 
938  /* start each line with a space */
939  appendLine(scip, file, linebuffer, &linecnt, " ");
940 
941  SCIP_CALL( SCIPgetCharParam(scip, "reading/gmsreader/indicatorreform", &indicatorform) );
942 
943  switch( indicatorform )
944  {
945  case 'b':
946  {
947  /* print row name */
948  (void) SCIPsnprintf(buffer, GMS_MAX_NAMELEN + 3, "%s ..", rowname);
949  SCIP_CALL( printConformName(scip, consname, GMS_MAX_NAMELEN + 3, buffer) );
950 
951  appendLine(scip, file, linebuffer, &linecnt, consname);
952 
953  /* write as s <= upperbound(s)*(1-z) */
954  coef = 1.0;
955  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, NULL, " =l= ", 1, &s, &coef, transformed) );
956 
957  coef = SCIPvarGetUbGlobal(s);
958  if( SCIPisInfinity(scip, coef) )
959  {
960  SCIP_CALL( SCIPgetRealParam(scip, "reading/gmsreader/bigmdefault", &coef) );
961 
962  SCIPwarningMessage(scip, "do not have upper bound on slack variable <%s> in indicator constraint <%s>, will use M = %g.\n",
963  SCIPvarGetName(s), rowname, coef);
964  }
965 
966  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%.15g + ", coef);
967 
968  coef = -coef;
969  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, buffer, ";", 1, &z, &coef, transformed) );
970 
971  break;
972  }
973 
974  case 's':
975  {
976  /* write as
977  * sos1 Variable name_sos(sosset);
978  * name_soseq(sosset).. name_sos(sosset) =e= s$(sameas(sosset,'slack') + z$(sameas(sosset,'bin'));
979  */
980  coef = 1.0;
981  SCIP_CALL( printConformName(scip, consname, GMS_MAX_NAMELEN, rowname) );
982 
983  /* declare set for SOS1 declarations from reformulation of indicator, if needed */
984  if( !*sossetdeclr )
985  {
986  SCIPinfoMessage(scip, file, " Set sosset / slack, bin /;\n");
987  *sossetdeclr = TRUE;
988  }
989 
990  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "sos1 Variable %s_sos(sosset);", consname);
991  appendLine(scip, file, linebuffer, &linecnt, buffer);
992  endLine(scip, file, linebuffer, &linecnt);
993 
994  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " %s(sosset).. %s_sos(sosset) =e= ", consname, consname);
995  appendLine(scip, file, linebuffer, &linecnt, buffer);
996  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, NULL, "$sameas(sosset,'slack')", 1, &s, &coef, transformed) );
997  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, " + ", "$sameas(sosset,'bin');", 1, &z, &coef, transformed) );
998  endLine(scip, file, linebuffer, &linecnt);
999 
1000  break;
1001  }
1002 
1003  default:
1004  SCIPerrorMessage("wrong value '%c' for parameter reading/gmsreader/indicatorreform\n", indicatorform);
1005  return SCIP_ERROR;
1006  }
1007 
1008  endLine(scip, file, linebuffer, &linecnt);
1009 
1010  return SCIP_OKAY;
1011 }
1012 
1013 /* print SOS constraint in some GAMS format to file stream (performing retransformation to active variables)
1014  *
1015  * write as
1016  * Set name_sosset /1*nvars/;
1017  * SOS1/2 Variable name_sosvar(name_sosset);
1018  * Equation name_sosequ(e1_sosset);
1019  * name_sosequ(name_sosset).. name_sosvar(e1_sosset) =e=
1020  * vars[0]$sameas(name_sosset, '1') + vars[1]$sameas(name_sosset, '2') + ... + vars[nvars-1]$sameas(name_sosset, nvars);
1021  */
1022 static
1024  SCIP* scip, /**< SCIP data structure */
1025  FILE* file, /**< output file (or NULL for standard output) */
1026  const char* rowname, /**< row name */
1027  int nvars, /**< number of variables in SOS */
1028  SCIP_VAR** vars, /**< variables in SOS */
1029  int sostype, /**< type of SOS: 1 or 2 */
1030  SCIP_Bool transformed /**< transformed constraint? */
1031  )
1032 {
1033  char linebuffer[GMS_MAX_PRINTLEN] = { '\0' };
1034  int linecnt;
1035  SCIP_Real coef;
1036  int v;
1037 
1038  char consname[GMS_MAX_NAMELEN + 30];
1039  char buffer[GMS_MAX_PRINTLEN];
1040 
1041  assert( scip != NULL );
1042  assert( strlen(rowname) > 0 );
1043  assert( vars != NULL || nvars == 0 );
1044  assert( sostype == 1 || sostype == 2 );
1045 
1046  clearLine(linebuffer, &linecnt);
1047 
1048  /* start each line with a space */
1049  appendLine(scip, file, linebuffer, &linecnt, " ");
1050 
1051  SCIP_CALL( printConformName(scip, consname, GMS_MAX_NAMELEN, rowname) );
1052 
1053  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "Set %s_sosset /1*%d/;", consname, nvars);
1054  appendLine(scip, file, linebuffer, &linecnt, buffer);
1055  endLine(scip, file, linebuffer, &linecnt);
1056 
1057  /* explicitly set lower bound of SOS variables to -inf, as GAMS default is 0.0 */
1058  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " SOS%d Variable %s_sosvar(%s_sosset); %s_sosvar.lo(%s_sosset) = -inf;", sostype, consname, consname, consname, consname);
1059  appendLine(scip, file, linebuffer, &linecnt, buffer);
1060  endLine(scip, file, linebuffer, &linecnt);
1061 
1062  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " %s(%s_sosset).. %s_sosvar(%s_sosset) =e= ", consname, consname, consname, consname);
1063  appendLine(scip, file, linebuffer, &linecnt, buffer);
1064  endLine(scip, file, linebuffer, &linecnt);
1065 
1066  coef = 1.0;
1067  for( v = 0; v < nvars; ++v )
1068  {
1069  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "$sameas(%s_sosset,'%d')", consname, v+1);
1070  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, v > 0 ? " + " : NULL, buffer, 1, &vars[v], &coef, transformed) ); /*lint !e613*/
1071  }
1072  appendLine(scip, file, linebuffer, &linecnt, ";");
1073  endLine(scip, file, linebuffer, &linecnt);
1074 
1075  return SCIP_OKAY;
1076 }
1077 
1078 /* print signpower row in GAMS format to file stream (performing retransformation to active variables) */
1079 static
1081  SCIP* scip, /**< SCIP data structure */
1082  FILE* file, /**< output file (or NULL for standard output) */
1083  const char* rowname, /**< row name */
1084  const char* rownameextension, /**< row name extension */
1085  const char* type, /**< row type ("=e=", "=l=", or "=g=") */
1086  SCIP_VAR* nonlinvar, /**< nonlinear variable */
1087  SCIP_VAR* linvar, /**< linear variable, may be NULL */
1088  SCIP_Real exponent, /**< exponent of nonlinear variable */
1089  SCIP_Real offset, /**< offset of nonlinear variable */
1090  SCIP_Real coeflinear, /**< coefficient of linear variable */
1091  SCIP_Real rhs, /**< right hand side */
1092  SCIP_Bool transformed, /**< transformed constraint? */
1093  SCIP_Bool signpowerallowed, /**< allowed to use signpower operator in GAMS? */
1094  SCIP_Bool* nsmooth /**< buffer to store whether we printed a nonsmooth function */
1095  )
1096 {
1097  char linebuffer[GMS_MAX_PRINTLEN] = { '\0' };
1098  int linecnt;
1099  SCIP_Bool nisoddint;
1100  SCIP_Bool fixedsign;
1101 
1102  char consname[GMS_MAX_NAMELEN + 3]; /* four extra characters for ' ..' */
1103  char buffer[GMS_MAX_PRINTLEN];
1104 
1105  assert( scip != NULL );
1106  assert( strlen(rowname) > 0 || strlen(rownameextension) > 0 );
1107  assert( strcmp(type, "=e=") == 0 || strcmp(type, "=l=") == 0 || strcmp(type, "=g=") == 0 );
1108  assert( nonlinvar != NULL );
1109  assert( exponent > 1.0 );
1110  assert( nsmooth != NULL );
1111 
1112  clearLine(linebuffer, &linecnt);
1113 
1114  /* start each line with a space */
1115  appendLine(scip, file, linebuffer, &linecnt, " ");
1116 
1117  /* print row name */
1118  (void) SCIPsnprintf(buffer, GMS_MAX_NAMELEN + 3, "%s%s ..", rowname, rownameextension);
1119  SCIP_CALL( printConformName(scip, consname, GMS_MAX_NAMELEN + 3, buffer) );
1120 
1121  appendLine(scip, file, linebuffer, &linecnt, consname);
1122 
1123  /* print nonlinear term
1124  * if not signpowerallowed, then signpow(x,n) is printed as x*abs(x) if n == 2, x*(abs(x)**(n-1)) if n is not 2 and not an odd integer, and as power(x,n) if n is an odd integer
1125  * if signpowerallowed, then signpow(x,n) is printed as power(x,n) if n is an odd integer and as signpower(x,n) otherwiser
1126  */
1127  nisoddint = SCIPisIntegral(scip, exponent) && ((int)SCIPfloor(scip, exponent+0.5))%2 == 1;
1128  fixedsign = !SCIPisNegative(scip, SCIPvarGetLbGlobal(nonlinvar)) || !SCIPisPositive(scip, SCIPvarGetUbGlobal(nonlinvar));
1129  if( !nisoddint && !fixedsign )
1130  {
1131  if( signpowerallowed )
1132  {
1133  if( offset != 0.0 )
1134  {
1135  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "signpower(%g ", offset);
1136  appendLine(scip, file, linebuffer, &linecnt, buffer);
1137  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "+", ",", 1, &nonlinvar, NULL, transformed) );
1138  }
1139  else
1140  {
1141  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "signpower(", ",", 1, &nonlinvar, NULL, transformed) );
1142  }
1143  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%g)", exponent);
1144  appendLine(scip, file, linebuffer, &linecnt, buffer);
1145  }
1146  else
1147  {
1148  if( offset != 0.0 )
1149  {
1150  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "(%g ", offset);
1151  appendLine(scip, file, linebuffer, &linecnt, buffer);
1152  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "+", ") * ", 1, &nonlinvar, NULL, transformed) );
1153  }
1154  else
1155  {
1156  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, NULL, " * ", 1, &nonlinvar, NULL, transformed) );
1157  }
1158 
1159  if( exponent == 2.0)
1160  {
1161  if( offset != 0.0 )
1162  {
1163  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "abs(%g ", offset);
1164  appendLine(scip, file, linebuffer, &linecnt, buffer);
1165  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "+", ")", 1, &nonlinvar, NULL, transformed) );
1166  }
1167  else
1168  {
1169  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "abs", NULL, 1, &nonlinvar, NULL, transformed) );
1170  }
1171  }
1172  else
1173  {
1174  if( offset != 0.0 )
1175  {
1176  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "abs(%g ", offset);
1177  appendLine(scip, file, linebuffer, &linecnt, buffer);
1178  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "+", ")", 1, &nonlinvar, NULL, transformed) );
1179  }
1180  else
1181  {
1182  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "abs", NULL, 1, &nonlinvar, NULL, transformed) );
1183  }
1184  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "**%g", exponent-1.0);
1185  appendLine(scip, file, linebuffer, &linecnt, buffer);
1186  }
1187  }
1188  *nsmooth = TRUE;
1189  }
1190  else if( nisoddint || !SCIPisNegative(scip, SCIPvarGetLbGlobal(nonlinvar)) )
1191  {
1192  if( exponent == 2.0 )
1193  {
1194  if( offset != 0.0 )
1195  {
1196  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "sqr(%g ", offset);
1197  appendLine(scip, file, linebuffer, &linecnt, buffer);
1198  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "+", ")", 1, &nonlinvar, NULL, transformed) );
1199  }
1200  else
1201  {
1202  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "sqr", NULL, 1, &nonlinvar, NULL, transformed) );
1203  }
1204  }
1205  else
1206  {
1207  if( offset != 0.0 )
1208  {
1209  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "power(%g ", offset);
1210  appendLine(scip, file, linebuffer, &linecnt, buffer);
1211  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "+", ",", 1, &nonlinvar, NULL, transformed) );
1212  }
1213  else
1214  {
1215  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "power(", ",", 1, &nonlinvar, NULL, transformed) );
1216  }
1217  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%g)", exponent);
1218  appendLine(scip, file, linebuffer, &linecnt, buffer);
1219  }
1220  }
1221  else
1222  {
1223  assert(fixedsign && !SCIPisPositive(scip, SCIPvarGetUbGlobal(nonlinvar)));
1224  if( exponent == 2.0 )
1225  {
1226  if( offset != 0.0 )
1227  {
1228  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "-sqr(%g ", -offset);
1229  appendLine(scip, file, linebuffer, &linecnt, buffer);
1230  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "-", ")", 1, &nonlinvar, NULL, transformed) );
1231  }
1232  else
1233  {
1234  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "-sqr(-", ")", 1, &nonlinvar, NULL, transformed) );
1235  }
1236  }
1237  else
1238  {
1239  if( offset != 0.0 )
1240  {
1241  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "-power(%g ", -offset);
1242  appendLine(scip, file, linebuffer, &linecnt, buffer);
1243  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "-", ",", 1, &nonlinvar, NULL, transformed) );
1244  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%g)", exponent);
1245  appendLine(scip, file, linebuffer, &linecnt, buffer);
1246  }
1247  else
1248  {
1249  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "-power(-", ",", 1, &nonlinvar, NULL, transformed) );
1250  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%g)", exponent);
1251  appendLine(scip, file, linebuffer, &linecnt, buffer);
1252  }
1253  }
1254  }
1255 
1256  /* print linear term */
1257  if( linvar != NULL )
1258  {
1259  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, " +", "", 1, &linvar, &coeflinear, transformed) );
1260  }
1261 
1262  /* print right hand side */
1263  if( linecnt == 0 )
1264  {
1265  /* we start a new line; therefore we tab this line */
1266  appendLine(scip, file, linebuffer, &linecnt, " ");
1267  }
1268 
1269  if( SCIPisZero(scip, rhs) )
1270  rhs = 0.0;
1271 
1272  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%s %.15g;", type, rhs);
1273 
1274  appendLine(scip, file, linebuffer, &linecnt, buffer);
1275 
1276  endLine(scip, file, linebuffer, &linecnt);
1277 
1278  return SCIP_OKAY;
1279 }
1280 
1281 /* print signpower cons in GAMS format to file stream (performing retransformation to active variables)
1282  */
1283 static
1285  SCIP* scip, /**< SCIP data structure */
1286  FILE* file, /**< output file (or NULL for standard output) */
1287  const char* rowname, /**< row name */
1288  SCIP_VAR* nonlinvar, /**< nonlinear variable */
1289  SCIP_VAR* linvar, /**< linear variable, may be NULL */
1290  SCIP_Real exponent, /**< exponent of nonlinear variable */
1291  SCIP_Real offset, /**< offset of nonlinear variable */
1292  SCIP_Real coeflinear, /**< coefficient of linear variable */
1293  SCIP_Real lhs, /**< left hand side */
1294  SCIP_Real rhs, /**< right hand side */
1295  SCIP_Bool transformed, /**< transformed constraint? */
1296  SCIP_Bool signpowerallowed, /**< allowed to use signpower operator in GAMS? */
1297  SCIP_Bool* nsmooth /**< buffer to store whether we printed a nonsmooth function */
1298  )
1299 {
1300  assert( scip != NULL );
1301  assert( strlen(rowname) > 0 );
1302 
1303  /* print row(s) in GAMS format */
1304  if( SCIPisEQ(scip, lhs, rhs) )
1305  {
1306  assert( !SCIPisInfinity(scip, rhs) );
1307 
1308  /* print equality constraint */
1309  SCIP_CALL( printSignpowerRow(scip, file, rowname, "", "=e=",
1310  nonlinvar, linvar, exponent, offset, coeflinear, rhs, transformed, signpowerallowed, nsmooth) );
1311  }
1312  else
1313  {
1314  if( !SCIPisInfinity(scip, -lhs) )
1315  {
1316  /* print inequality ">=" */
1317  SCIP_CALL( printSignpowerRow(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", "=g=",
1318  nonlinvar, linvar, exponent, offset, coeflinear, lhs, transformed, signpowerallowed, nsmooth) );
1319  }
1320  if( !SCIPisInfinity(scip, rhs) )
1321  {
1322  /* print inequality "<=" */
1323  SCIP_CALL( printSignpowerRow(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "=l=",
1324  nonlinvar, linvar, exponent, offset, coeflinear, rhs, transformed, signpowerallowed, nsmooth) );
1325  }
1326  }
1327 
1328  return SCIP_OKAY;
1329 }
1330 
1331 /* prints expression in GAMS format to file stream */
1332 static
1334  SCIP* scip, /**< SCIP data structure */
1335  FILE* file, /**< output file (or NULL for standard output) */
1336  char* linebuffer, /**< line buffer of length GMS_MAX_PRINTLEN */
1337  int* linecnt, /**< number of characters in line so far */
1338  SCIP_Bool* nsmooth, /**< buffer to store whether we printed a nonsmooth function */
1339  SCIP_Bool transformed, /**< expression belongs to transformed constraint? */
1340  SCIP_EXPR* expr, /**< expression to print */
1341  SCIP_VAR** exprvars /**< variables of expression */
1342 )
1343 {
1344  char buffer[GMS_MAX_PRINTLEN];
1345 
1346  assert(scip != NULL);
1347  assert(linebuffer != NULL);
1348  assert(linecnt != NULL);
1349  assert(expr != NULL);
1350  assert(nsmooth != NULL);
1351 
1352  switch( SCIPexprGetOperator(expr) )
1353  {
1354  case SCIP_EXPR_VARIDX:
1355  {
1356  SCIP_Real one;
1357 
1358  assert(exprvars != NULL);
1359 
1360  one = 1.0;
1361  SCIP_CALL( printActiveVariables(scip, file, linebuffer, linecnt, "", "", 1, &exprvars[SCIPexprGetOpIndex(expr)], &one, transformed) );
1362 
1363  break;
1364  }
1365 
1366  case SCIP_EXPR_PARAM:
1367  {
1368  SCIPwarningMessage(scip, "parameterized expression in GAMS writer. GAMS file will not compile.\n");
1369 
1370  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "param%d", SCIPexprGetOpIndex(expr));
1371  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1372 
1373  break;
1374  }
1375 
1376  case SCIP_EXPR_CONST:
1377  {
1378  if( SCIPexprGetOpReal(expr) < 0.0 )
1379  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "(%.15g)", SCIPexprGetOpReal(expr));
1380  else
1381  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%.15g", SCIPexprGetOpReal(expr));
1382  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1383 
1384  break;
1385  }
1386 
1387  case SCIP_EXPR_PLUS:
1388  {
1389  appendLineWithIndent(scip, file, linebuffer, linecnt, "(");
1390  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[0], exprvars) );
1391  appendLineWithIndent(scip, file, linebuffer, linecnt, " + ");
1392  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[1], exprvars) );
1393  appendLineWithIndent(scip, file, linebuffer, linecnt, ")");
1394  break;
1395  }
1396 
1397  case SCIP_EXPR_MINUS:
1398  {
1399  appendLineWithIndent(scip, file, linebuffer, linecnt, "(");
1400  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[0], exprvars) );
1401  appendLineWithIndent(scip, file, linebuffer, linecnt, " - ");
1402  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[1], exprvars) );
1403  appendLineWithIndent(scip, file, linebuffer, linecnt, ")");
1404  break;
1405  }
1406 
1407  case SCIP_EXPR_MUL:
1408  {
1409  appendLineWithIndent(scip, file, linebuffer, linecnt, "(");
1410  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[0], exprvars) );
1411  appendLineWithIndent(scip, file, linebuffer, linecnt, " * ");
1412  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[1], exprvars) );
1413  appendLineWithIndent(scip, file, linebuffer, linecnt, ")");
1414  break;
1415  }
1416 
1417  case SCIP_EXPR_DIV:
1418  {
1419  appendLineWithIndent(scip, file, linebuffer, linecnt, "(");
1420  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[0], exprvars) );
1421  appendLineWithIndent(scip, file, linebuffer, linecnt, " / ");
1422  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[1], exprvars) );
1423  appendLineWithIndent(scip, file, linebuffer, linecnt, ")");
1424  break;
1425  }
1426 
1427  case SCIP_EXPR_REALPOWER:
1428  {
1429  appendLineWithIndent(scip, file, linebuffer, linecnt, "(");
1430  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[0], exprvars) );
1431  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, ")**(%.15g)", SCIPexprGetRealPowerExponent(expr));
1432  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1433  break;
1434  }
1435 
1436  case SCIP_EXPR_INTPOWER:
1437  {
1438  appendLineWithIndent(scip, file, linebuffer, linecnt, "power(");
1439  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[0], exprvars) );
1440  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, ", %d)", SCIPexprGetIntPowerExponent(expr));
1441  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1442  break;
1443  }
1444 
1445  case SCIP_EXPR_SIGNPOWER:
1446  {
1447  SCIP_Real exponent;
1448  SCIP_Bool nisoddint;
1449 
1450  /* signpow(x,y) is printed as x*abs(x) if y == 2, x*(abs(x) ** (y-1)) if y is not 2 and not an odd integer, and as intpower(x,y) if y is an odd integer
1451  * but if reading/gmsreader/signpower is TRUE, then we print as signpower(x,y), unless y is odd integer
1452  */
1453  exponent = SCIPexprGetSignPowerExponent(expr);
1454  nisoddint = (((SCIP_Real)((int)exponent)) == exponent) && (((int)exponent)%2 == 1);
1455 
1456  if( !nisoddint )
1457  {
1458  SCIP_Bool signpowerallowed;
1459 
1460  SCIP_CALL( SCIPgetBoolParam(scip, "reading/gmsreader/signpower", &signpowerallowed) );
1461 
1462  if( signpowerallowed )
1463  {
1464  appendLineWithIndent(scip, file, linebuffer, linecnt, " * signpower(");
1465  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[0], exprvars) );
1466  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, ", %.15g)", exponent);
1467  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1468  }
1469  else
1470  {
1471  appendLineWithIndent(scip, file, linebuffer, linecnt, "(");
1472  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[0], exprvars) );
1473  appendLineWithIndent(scip, file, linebuffer, linecnt, ")");
1474 
1475  if( exponent == 2.0)
1476  {
1477  appendLineWithIndent(scip, file, linebuffer, linecnt, " * abs(");
1478  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[0], exprvars) );
1479  appendLineWithIndent(scip, file, linebuffer, linecnt, ")");
1480  }
1481  else
1482  {
1483  appendLineWithIndent(scip, file, linebuffer, linecnt, " * abs(");
1484  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[0], exprvars) );
1485  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, ")**(%g)", SCIPexprGetRealPowerExponent(expr)-1.0);
1486  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1487  }
1488  }
1489  *nsmooth = TRUE;
1490  }
1491  else
1492  {
1493  appendLineWithIndent(scip, file, linebuffer, linecnt, " * power(");
1494  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[0], exprvars) );
1495  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, ", %.15g)", exponent);
1496  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1497  }
1498 
1499  break;
1500  }
1501 
1502  case SCIP_EXPR_ABS:
1503  case SCIP_EXPR_SIGN:
1504  *nsmooth = TRUE; /*lint -fallthrough*/
1505  case SCIP_EXPR_SQUARE:
1506  case SCIP_EXPR_SQRT:
1507  case SCIP_EXPR_EXP:
1508  case SCIP_EXPR_LOG:
1509  case SCIP_EXPR_SIN:
1510  case SCIP_EXPR_COS:
1511  case SCIP_EXPR_TAN:
1512  /* case SCIP_EXPR_ERF: */
1513  /* case SCIP_EXPR_ERFI: */
1514  case SCIP_EXPR_MIN:
1515  case SCIP_EXPR_MAX:
1516  {
1517  int i;
1518 
1519  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%s(", SCIPexpropGetName(SCIPexprGetOperator(expr)));
1520  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1521 
1522  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
1523  {
1524  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[i], exprvars) );
1525  if( i + 1 < SCIPexprGetNChildren(expr) )
1526  appendLineWithIndent(scip, file, linebuffer, linecnt, ", ");
1527  }
1528 
1529  appendLineWithIndent(scip, file, linebuffer, linecnt, ")");
1530  break;
1531  }
1532 
1533  case SCIP_EXPR_SUM:
1534  case SCIP_EXPR_PRODUCT:
1535  {
1536  switch( SCIPexprGetNChildren(expr) )
1537  {
1538  case 0:
1539  {
1540  appendLineWithIndent(scip, file, linebuffer, linecnt, SCIPexprGetOperator(expr) == SCIP_EXPR_SUM ? "0" : "1");
1541  break;
1542  }
1543  case 1:
1544  {
1545  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[0], exprvars) );
1546  break;
1547  }
1548  default:
1549  {
1550  int i;
1551  const char* opstr = SCIPexprGetOperator(expr) == SCIP_EXPR_SUM ? " + " : " * ";
1552 
1553  appendLineWithIndent(scip, file, linebuffer, linecnt, "(");
1554  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
1555  {
1556  if( i > 0 )
1557  {
1558  appendLineWithIndent(scip, file, linebuffer, linecnt, opstr);
1559  }
1560  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[i], exprvars) );
1561  }
1562  appendLineWithIndent(scip, file, linebuffer, linecnt, ")");
1563  }
1564  }
1565  break;
1566  }
1567 
1568  case SCIP_EXPR_LINEAR:
1569  {
1570  SCIP_Real constant;
1571  int i;
1572 
1573  constant = SCIPexprGetLinearConstant(expr);
1574 
1575  if( SCIPexprGetNChildren(expr) == 0 )
1576  {
1577  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%.15g", constant);
1578  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1579  break;
1580  }
1581 
1582  appendLineWithIndent(scip, file, linebuffer, linecnt, "(");
1583 
1584  if( constant != 0.0 )
1585  {
1586  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%.15g", constant);
1587  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1588  }
1589 
1590  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
1591  {
1592  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " %+.15g * ", SCIPexprGetLinearCoefs(expr)[i]);
1593  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1594  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[i], exprvars) );
1595  }
1596 
1597  appendLineWithIndent(scip, file, linebuffer, linecnt, ")");
1598  break;
1599  }
1600 
1601  case SCIP_EXPR_QUADRATIC:
1602  {
1603  SCIP_Real constant;
1604  int i;
1605  SCIP_QUADELEM* quadelems;
1606  SCIP_Real* lincoefs;
1607 
1608  constant = SCIPexprGetQuadConstant(expr);
1609 
1610  if( SCIPexprGetNChildren(expr) == 0 )
1611  {
1612  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%.15g", constant);
1613  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1614  break;
1615  }
1616 
1617  appendLineWithIndent(scip, file, linebuffer, linecnt, "(");
1618 
1619  if( constant != 0.0 )
1620  {
1621  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%.15g", constant);
1622  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1623  }
1624 
1625  lincoefs = SCIPexprGetQuadLinearCoefs(expr);
1626  if( lincoefs != NULL )
1627  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
1628  {
1629  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " %+.15g * ", lincoefs[i]);
1630  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1631  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[i], exprvars) );
1632  }
1633 
1634  quadelems = SCIPexprGetQuadElements(expr);
1635  for( i = 0; i < SCIPexprGetNQuadElements(expr); ++i )
1636  {
1637  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " %+.15g * ", quadelems[i].coef);
1638  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1639 
1640  if( quadelems[i].idx1 == quadelems[i].idx2 )
1641  {
1642  appendLineWithIndent(scip, file, linebuffer, linecnt, "sqr(");
1643  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[quadelems[i].idx1], exprvars) );
1644  appendLineWithIndent(scip, file, linebuffer, linecnt, ")");
1645  }
1646  else
1647  {
1648  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[quadelems[i].idx1], exprvars) );
1649  appendLineWithIndent(scip, file, linebuffer, linecnt, " * ");
1650  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[quadelems[i].idx2], exprvars) );
1651  }
1652  }
1653 
1654  appendLineWithIndent(scip, file, linebuffer, linecnt, ")");
1655  break;
1656  }
1657 
1658  case SCIP_EXPR_POLYNOMIAL:
1659  {
1660  SCIP_EXPRDATA_MONOMIAL* monomdata;
1661  SCIP_Real exponent;
1662  int i;
1663  int j;
1664 
1665  appendLineWithIndent(scip, file, linebuffer, linecnt, "(");
1666 
1667  if( SCIPexprGetPolynomialConstant(expr) != 0.0 || SCIPexprGetNMonomials(expr) == 0 )
1668  {
1669  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%.15g", SCIPexprGetPolynomialConstant(expr));
1670  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1671  }
1672 
1673  for( i = 0; i < SCIPexprGetNMonomials(expr); ++i )
1674  {
1675  monomdata = SCIPexprGetMonomials(expr)[i];
1676  assert(monomdata != NULL);
1677 
1678  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " %+.15g", SCIPexprGetMonomialCoef(monomdata));
1679  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1680 
1681  for( j = 0; j < SCIPexprGetMonomialNFactors(monomdata); ++j )
1682  {
1683  appendLineWithIndent(scip, file, linebuffer, linecnt, "*");
1684 
1685  exponent = SCIPexprGetMonomialExponents(monomdata)[j];
1686  if( exponent == 1.0 )
1687  {
1688  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[SCIPexprGetMonomialChildIndices(monomdata)[j]], exprvars) );
1689  }
1690  else if( exponent == 2.0 )
1691  {
1692  appendLineWithIndent(scip, file, linebuffer, linecnt, "sqr(");
1693  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[SCIPexprGetMonomialChildIndices(monomdata)[j]], exprvars) );
1694  appendLineWithIndent(scip, file, linebuffer, linecnt, ")");
1695  }
1696  else if( exponent == 0.5 )
1697  {
1698  appendLineWithIndent(scip, file, linebuffer, linecnt, "sqrt(");
1699  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[SCIPexprGetMonomialChildIndices(monomdata)[j]], exprvars) );
1700  appendLineWithIndent(scip, file, linebuffer, linecnt, ")");
1701  }
1702  else if( ((SCIP_Real)((int)exponent)) == exponent )
1703  {
1704  appendLineWithIndent(scip, file, linebuffer, linecnt, "power(");
1705  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[SCIPexprGetMonomialChildIndices(monomdata)[j]], exprvars) );
1706  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, ", %d)", (int)SCIPround(scip, exponent));
1707  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1708  }
1709  else
1710  {
1711  SCIP_CALL( printExpr(scip, file, linebuffer, linecnt, nsmooth, transformed, SCIPexprGetChildren(expr)[SCIPexprGetMonomialChildIndices(monomdata)[j]], exprvars) );
1712  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " ** %.15g", exponent);
1713  appendLineWithIndent(scip, file, linebuffer, linecnt, buffer);
1714  }
1715  }
1716  }
1717 
1718  appendLineWithIndent(scip, file, linebuffer, linecnt, ")");
1719  break;
1720  }
1721 
1722  default:
1723  SCIPerrorMessage("unexpected operand %d in expression\n", SCIPexprGetOperator(expr));
1724  return SCIP_OKAY;
1725  } /*lint !e788*/
1726 
1727  return SCIP_OKAY;
1728 }
1729 
1730 /* print nonlinear row in GAMS format to file stream */
1731 static
1733  SCIP* scip, /**< SCIP data structure */
1734  FILE* file, /**< output file (or NULL for standard output) */
1735  const char* rowname, /**< row name */
1736  const char* rownameextension, /**< row name extension */
1737  const char* type, /**< row type ("=e=", "=l=", or "=g=") */
1738  int nlinvars, /**< number of linear terms */
1739  SCIP_VAR** linvars, /**< variables in linear part */
1740  SCIP_Real* lincoeffs, /**< coefficients of variables in linear part */
1741  int nexprtrees, /**< number of expression trees */
1742  SCIP_EXPRTREE** exprtrees, /**< expression trees */
1743  SCIP_Real* exprtreecoefs, /**< expression tree coefficients */
1744  SCIP_Real rhs, /**< right hand side */
1745  SCIP_Bool transformed, /**< transformed constraint? */
1746  SCIP_Bool* nsmooth /**< buffer to store whether we printed a nonsmooth function */
1747  )
1748 {
1749  char linebuffer[GMS_MAX_PRINTLEN] = { '\0' };
1750  int linecnt;
1751 
1752  char consname[GMS_MAX_NAMELEN + 3]; /* four extra characters for ' ..' */
1753  char buffer[GMS_MAX_PRINTLEN];
1754 
1755  int i;
1756 
1757  assert( scip != NULL );
1758  assert( strlen(rowname) > 0 || strlen(rownameextension) > 0 );
1759  assert( strcmp(type, "=e=") == 0 || strcmp(type, "=l=") == 0 || strcmp(type, "=g=") == 0 );
1760 
1761  clearLine(linebuffer, &linecnt);
1762 
1763  /* start each line with a space */
1764  appendLine(scip, file, linebuffer, &linecnt, " ");
1765 
1766  /* print row name */
1767  (void) SCIPsnprintf(buffer, GMS_MAX_NAMELEN + 3, "%s%s ..", rowname, rownameextension);
1768  SCIP_CALL( printConformName(scip, consname, GMS_MAX_NAMELEN + 3, buffer) );
1769 
1770  appendLine(scip, file, linebuffer, &linecnt, consname);
1771 
1772  /* print nonlinear terms
1773  */
1774  for( i = 0; i < nexprtrees; ++i )
1775  {
1776  assert(exprtrees[i] != NULL);
1777  if( exprtreecoefs[i] != 0.0 )
1778  {
1779  (void) SCIPsnprintf(buffer, GMS_MAX_NAMELEN + 3, "%+g * (", exprtreecoefs[i]);
1780  appendLineWithIndent(scip, file, linebuffer, &linecnt, buffer);
1781  SCIP_CALL( printExpr(scip, file, linebuffer, &linecnt, nsmooth, transformed, SCIPexprtreeGetRoot(exprtrees[i]), SCIPexprtreeGetVars(exprtrees[i])) );
1782  appendLineWithIndent(scip, file, linebuffer, &linecnt, ")");
1783  }
1784  }
1785 
1786  /* print linear terms, do after nonlinear since nonlinear may not print sign in beginning */
1787  if( nlinvars > 0 )
1788  {
1789  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "+", " ", nlinvars, linvars, lincoeffs, transformed) );
1790  }
1791 
1792  /* print right hand side */
1793  if( linecnt == 0 )
1794  /* we start a new line; therefore we tab this line */
1795  appendLine(scip, file, linebuffer, &linecnt, " ");
1796 
1797  if( SCIPisZero(scip, rhs) )
1798  rhs = 0.0;
1799 
1800  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%s %.15g;", type, rhs);
1801 
1802  appendLine(scip, file, linebuffer, &linecnt, buffer);
1803 
1804  endLine(scip, file, linebuffer, &linecnt);
1805 
1806  return SCIP_OKAY;
1807 }
1808 
1809 /* print nonlinear row in GAMS format to file stream (performing retransformation to active linear variables)
1810  * */
1811 static
1813  SCIP* scip, /**< SCIP data structure */
1814  FILE* file, /**< output file (or NULL for standard output) */
1815  const char* rowname, /**< row name */
1816  int nlinvars, /**< number of linear terms */
1817  SCIP_VAR** linvars, /**< variables in linear part */
1818  SCIP_Real* lincoeffs, /**< coefficients of variables in linear part */
1819  int nexprtrees, /**< number of expression trees */
1820  SCIP_EXPRTREE** exprtrees, /**< expression trees */
1821  SCIP_Real* exprtreecoefs, /**< expression tree coefficients */
1822  SCIP_Real lhs, /**< left hand side */
1823  SCIP_Real rhs, /**< right hand side */
1824  SCIP_Bool transformed, /**< transformed constraint? */
1825  SCIP_Bool* nsmooth /**< buffer to store whether we printed a nonsmooth function */
1826  )
1827 {
1828  assert( scip != NULL );
1829  assert( strlen(rowname) > 0 );
1830 
1831  /* print row(s) in GAMS format */
1832  if( SCIPisEQ(scip, lhs, rhs) )
1833  {
1834  assert( !SCIPisInfinity(scip, rhs) );
1835 
1836  /* print equality constraint */
1837  SCIP_CALL( printNonlinearRow(scip, file, rowname, "", "=e=",
1838  nlinvars, linvars, lincoeffs, nexprtrees, exprtrees, exprtreecoefs, rhs, transformed, nsmooth) );
1839  }
1840  else
1841  {
1842  if( !SCIPisInfinity(scip, -lhs) )
1843  {
1844  /* print inequality ">=" */
1845  SCIP_CALL( printNonlinearRow(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", "=g=",
1846  nlinvars, linvars, lincoeffs, nexprtrees, exprtrees, exprtreecoefs, lhs, transformed, nsmooth) );
1847  }
1848  if( !SCIPisInfinity(scip, rhs) )
1849  {
1850  /* print inequality "<=" */
1851  SCIP_CALL( printNonlinearRow(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "=l=",
1852  nlinvars, linvars, lincoeffs, nexprtrees, exprtrees, exprtreecoefs, rhs, transformed, nsmooth) );
1853  }
1854  }
1855 
1856  return SCIP_OKAY;
1857 }
1858 
1859 /** method check if the variable names are not longer than GMS_MAX_NAMELEN */
1860 static
1862  SCIP* scip, /**< SCIP data structure */
1863  SCIP_VAR** vars, /**< array of variables */
1864  int nvars /**< number of variables */
1865  )
1866 {
1867  int v;
1868  SCIP_VAR* var;
1869  SCIP_Bool replaceforbiddenchars;
1870  const char* badchar;
1871 
1872  assert( scip != NULL );
1873  assert( vars != NULL );
1874 
1875  SCIP_CALL( SCIPgetBoolParam(scip, "reading/gmsreader/replaceforbiddenchars", &replaceforbiddenchars) );
1876 
1877  /* check if the variable names contain the symbols '#', '*', '+', '/', '-', or '@' */
1878  for( badchar = badchars; *badchar; ++badchar )
1879  {
1880  for( v = 0; v < nvars; ++v )
1881  {
1882  var = vars[v];
1883  assert( var != NULL );
1884 
1885  if( strchr(SCIPvarGetName(var), *badchar) != NULL )
1886  {
1887  if( replaceforbiddenchars )
1888  {
1889  SCIPinfoMessage(scip, NULL, "there is a variable name with symbol '%c', not allowed in GAMS format; all '%c' replaced by '_' (consider using 'write genproblem'/'write gentransproblem').\n", *badchar, *badchar);
1890  }
1891  else
1892  {
1893  SCIPwarningMessage(scip, "there is a variable name with symbol '%c', not allowed in GAMS format; use 'write genproblem'/'write gentransproblem', or set 'reading/gmsreader/replaceforbiddenchars' to TRUE and risk duplicate variable names.\n", *badchar);
1894  }
1895 
1896  break;
1897  }
1898  }
1899  }
1900 
1901  /* check if the variable names are too long */
1902  for( v = 0; v < nvars; ++v )
1903  {
1904  var = vars[v];
1905  assert( var != NULL );
1906 
1907  if( strlen(SCIPvarGetName(var)) > GMS_MAX_NAMELEN )
1908  {
1909  SCIPwarningMessage(scip, "there is a variable name which has to be cut down to %d characters; GAMS model might be corrupted.\n",
1910  GMS_MAX_NAMELEN - 1);
1911  break;
1912  }
1913  }
1914 
1915  return SCIP_OKAY;
1916 }
1917 
1918 /** method check if the constraint names are not longer than GMS_MAX_NAMELEN */
1919 static
1921  SCIP* scip, /**< SCIP data structure */
1922  SCIP_CONS** conss, /**< array of constraints */
1923  int nconss, /**< number of constraints */
1924  SCIP_Bool transformed /**< TRUE iff problem is the transformed problem */
1925  )
1926 {
1927  int c;
1928  SCIP_CONS* cons;
1929  SCIP_CONSHDLR* conshdlr;
1930  const char* conshdlrname;
1931  SCIP_Bool replaceforbiddenchars;
1932  const char* badchar;
1933 
1934  assert( scip != NULL );
1935  assert( conss != NULL );
1936 
1937  SCIP_CALL( SCIPgetBoolParam(scip, "reading/gmsreader/replaceforbiddenchars", &replaceforbiddenchars) );
1938 
1939  /* check if the constraint names contain the symbol '#', '*', '+', '/', '-', or '@' */
1940  for( badchar = badchars; *badchar; ++badchar )
1941  {
1942  for( c = 0; c < nconss; ++c )
1943  {
1944  cons = conss[c];
1945  assert( cons != NULL );
1946 
1947  if( strchr(SCIPconsGetName(cons), *badchar) != NULL )
1948  {
1949  if( replaceforbiddenchars )
1950  {
1951  SCIPinfoMessage(scip, NULL, "there is a constraint name with symbol '%c', not allowed in GAMS format; all '%c' replaced by '_' (consider using 'write genproblem'/'write gentransproblem').\n", *badchar, *badchar);
1952  }
1953  else
1954  {
1955  SCIPwarningMessage(scip, "there is a constraint name with symbol '%c', not allowed in GAMS format; use 'write genproblem'/'write gentransproblem', or set 'reading/gmsreader/replaceforbiddenchars' to TRUE and risk duplicate variable names.\n", *badchar);
1956  }
1957 
1958  break;
1959  }
1960  }
1961  }
1962 
1963  /* check if the constraint names are too long */
1964  for( c = 0; c < nconss; ++c )
1965  {
1966  cons = conss[c];
1967  assert( cons != NULL );
1968 
1969  /* in case the transformed is written, only constraints are posted which are enabled in the current node */
1970  assert(!transformed || SCIPconsIsEnabled(cons));
1971 
1972  conshdlr = SCIPconsGetHdlr(cons);
1973  assert( conshdlr != NULL );
1974 
1975  conshdlrname = SCIPconshdlrGetName(conshdlr);
1976  assert( transformed == SCIPconsIsTransformed(cons) );
1977 
1978  if( strcmp(conshdlrname, "linear") == 0 || strcmp(conshdlrname, "quadratic") == 0 )
1979  {
1980  SCIP_Real lhs = strcmp(conshdlrname, "linear") == 0 ? SCIPgetLhsLinear(scip, cons) : SCIPgetLhsQuadratic(scip, cons);
1981  SCIP_Real rhs = strcmp(conshdlrname, "linear") == 0 ? SCIPgetLhsLinear(scip, cons) : SCIPgetRhsQuadratic(scip, cons);
1982 
1983  if( SCIPisEQ(scip, lhs, rhs) && strlen(SCIPconsGetName(conss[c])) > GMS_MAX_NAMELEN )
1984  {
1985  SCIPwarningMessage(scip, "there is a constraint name which has to be cut down to %d characters;\n",
1986  GMS_MAX_NAMELEN - 1);
1987  break;
1988  }
1989  else if( !SCIPisEQ(scip, lhs, rhs) && strlen(SCIPconsGetName(conss[c])) > GMS_MAX_NAMELEN - 4 )
1990  {
1991  SCIPwarningMessage(scip, "there is a constraint name which has to be cut down to %d characters;\n",
1992  GMS_MAX_NAMELEN - 5);
1993  break;
1994  }
1995  }
1996  else if( strlen(SCIPconsGetName(conss[c])) > GMS_MAX_NAMELEN )
1997  {
1998  SCIPwarningMessage(scip, "there is a constraint name which has to be cut down to %d characters;\n",
1999  GMS_MAX_NAMELEN - 1);
2000  break;
2001  }
2002  }
2003  return SCIP_OKAY;
2004 }
2005 
2006 
2007 /*
2008  * Callback methods of reader
2009  */
2010 
2011 /** copy method for reader plugins (called when SCIP copies plugins) */
2012 static
2013 SCIP_DECL_READERCOPY(readerCopyGms)
2014 { /*lint --e{715}*/
2015  assert(scip != NULL);
2016  assert(reader != NULL);
2017  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
2018 
2019  /* call inclusion method of reader */
2021 
2022  return SCIP_OKAY;
2023 }
2024 
2025 #ifdef WITH_GAMS
2026 /** problem reading method of reader */
2027 static
2028 SCIP_DECL_READERREAD(readerReadGms)
2029 {
2030  SCIP_RETCODE ret;
2031  FILE* convertdopt;
2032  char gamscall[SCIP_MAXSTRLEN];
2033  char buffer[GMS_SSSIZE];
2034  int rc;
2035  gmoHandle_t gmo = NULL;
2036  gevHandle_t gev = NULL;
2037 
2038  assert(scip != NULL);
2039  assert(reader != NULL);
2040  assert(filename != NULL);
2041  assert(result != NULL);
2042 
2043  *result = SCIP_DIDNOTRUN;
2044  ret = SCIP_ERROR;
2045 
2046  /* create temporary directory */
2047  mkdir("loadgms.tmp", S_IRWXU);
2048 
2049  /* create empty convertd options file */
2050  convertdopt = fopen("loadgms.tmp/convertd.opt", "w");
2051  if( convertdopt == NULL )
2052  {
2053  SCIPerrorMessage("Could not create convertd options file. Do you have write permissions in execution directory?\n");
2054  goto TERMINATE;
2055  }
2056  fputs(" ", convertdopt);
2057  fclose(convertdopt);
2058 
2059  /* call GAMS with convertd solver to get compiled model instance in temporary directory */
2060  SCIPsnprintf(gamscall, SCIP_MAXSTRLEN, WITH_GAMS "/gams %s LP=CONVERTD RMIP=CONVERTD QCP=CONVERTD RMIQCP=CONVERTD NLP=CONVERTD DNLP=CONVERTD RMINLP=CONVERTD CNS=CONVERTD MIP=CONVERTD MIQCP=CONVERTD MINLP=CONVERTD MCP=CONVERTD MPEC=CONVERTD RMPEC=CONVERTD SCRDIR=loadgms.tmp output=loadgms.tmp/listing optdir=loadgms.tmp optfile=1 pf4=0 solprint=0 limcol=0 limrow=0 pc=2 lo=%d",
2061  filename, SCIPgetVerbLevel(scip) == SCIP_VERBLEVEL_FULL ? 3 : 0);
2062  SCIPdebugMessage(gamscall);
2063  rc = system(gamscall);
2064  if( rc != 0 )
2065  {
2066  SCIPerrorMessage("GAMS call returned with code %d, check loadgms.tmp/listing for details.\n", rc);
2067  /* likely the GAMS model could not be compiled, which we could report as a readerror */
2068  ret = SCIP_READERROR;
2069  goto TERMINATE;
2070  }
2071 
2072  /* initialize GEV library and create GEV */
2073  if( !gevCreateDD(&gev, WITH_GAMS, buffer, sizeof(buffer)) )
2074  {
2075  SCIPerrorMessage(buffer);
2076  goto TERMINATE;
2077  }
2078 
2079  /* initialize GMO library and create GMO */
2080  if( !gmoCreateDD(&gmo, WITH_GAMS, buffer, sizeof(buffer)) )
2081  {
2082  SCIPerrorMessage(buffer);
2083  goto TERMINATE;
2084  }
2085 
2086  /* load control file */
2087  if( gevInitEnvironmentLegacy(gev, "loadgms.tmp/gamscntr.dat") )
2088  {
2089  SCIPerrorMessage("Could not load control file loadgms.tmp/gamscntr.dat\n");
2090  goto TERMINATE;
2091  }
2092 
2093  /* tell GMO about GEV */
2094  if( gmoRegisterEnvironment(gmo, gev, buffer) )
2095  {
2096  SCIPerrorMessage("Error registering GAMS Environment: %s\n", buffer);
2097  goto TERMINATE;
2098  }
2099 
2100  /* load GAMS model instance into GMO */
2101  if( gmoLoadDataLegacy(gmo, buffer) )
2102  {
2103  SCIPerrorMessage("Could not load model data.\n");
2104  goto TERMINATE;
2105  }
2106 
2107  /* create SCIP problem out of GMO, using the magic from reader_gmo in interfaces/gams */
2108  SCIP_CALL( SCIPcreateProblemReaderGmo(scip, gmo, NULL, FALSE) );
2109  *result = SCIP_SUCCESS;
2110 
2111  ret = SCIP_OKAY;
2112 
2113 TERMINATE:
2114  if( gmo != NULL )
2115  gmoFree(&gmo);
2116  if( gev != NULL )
2117  gevFree(&gev);
2118 
2119  /* remove temporary directory content (should have only files and directory itself) */
2120  if( ret != SCIP_READERROR )
2121  system("rm loadgms.tmp/* && rmdir loadgms.tmp");
2122 
2123  return ret;
2124 }
2125 #endif
2126 
2127 /** problem writing method of reader */
2128 static
2129 SCIP_DECL_READERWRITE(readerWriteGms)
2130 { /*lint --e{715}*/
2131  SCIP_CALL( SCIPwriteGms(scip, file, name, transformed, objsense, objscale, objoffset, vars,
2132  nvars, nbinvars, nintvars, nimplvars, ncontvars, conss, nconss, result) );
2133 
2134  return SCIP_OKAY;
2135 }
2136 
2137 #ifdef WITH_GAMS
2138 /** destructor of reader to free user data (called when SCIP is exiting) */
2139 static
2140 SCIP_DECL_READERFREE(readerFreeGms)
2141 {
2142  if( gmoLibraryLoaded() )
2143  gmoLibraryUnload();
2144  if( gevLibraryLoaded() )
2145  gevLibraryUnload();
2146 
2147  return SCIP_OKAY;
2148 }
2149 #endif
2150 
2151 /*
2152  * reader specific interface methods
2153  */
2154 
2155 /** includes the gms file reader in SCIP */
2157  SCIP* scip /**< SCIP data structure */
2158  )
2159 {
2160  SCIP_READERDATA* readerdata;
2161  SCIP_READER* reader;
2162 
2163  /* create reader data */
2164  readerdata = NULL;
2165 
2166  /* include reader */
2167  SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, readerdata) );
2168 
2169  /* set non fundamental callbacks via setter functions */
2170  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyGms) );
2171 #ifdef WITH_GAMS
2172  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadGms) );
2173  SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeGms) );
2174 #endif
2175  SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteGms) );
2176 
2177  /* add gms reader parameters for writing routines*/
2179  "reading/gmsreader/freeints", "have integer variables no upper bound by default (depending on GAMS version)?",
2180  NULL, FALSE, FALSE, NULL, NULL) );
2181 
2183  "reading/gmsreader/replaceforbiddenchars", "shall characters '#', '*', '+', '/', and '-' in variable and constraint names be replaced by '_'?",
2184  NULL, FALSE, FALSE, NULL, NULL) );
2185 
2187  "reading/gmsreader/bigmdefault", "default M value for big-M reformulation of indicator constraints in case no bound on slack variable is given",
2189 
2191  "reading/gmsreader/indicatorreform", "which reformulation to use for indicator constraints: 'b'ig-M, 's'os1",
2193 
2195  "reading/gmsreader/signpower", "is it allowed to use the gams function signpower(x,a)?",
2197 
2198  return SCIP_OKAY;
2199 }
2200 
2201 
2202 /** writes problem to gms file */
2204  SCIP* scip, /**< SCIP data structure */
2205  FILE* file, /**< output file, or NULL if standard output should be used */
2206  const char* name, /**< problem name */
2207  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
2208  SCIP_OBJSENSE objsense, /**< objective sense */
2209  SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
2210  * extobj = objsense * objscale * (intobj + objoffset) */
2211  SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
2212  SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
2213  int nvars, /**< number of active variables in the problem */
2214  int nbinvars, /**< number of binary variables */
2215  int nintvars, /**< number of general integer variables */
2216  int nimplvars, /**< number of implicit integer variables */
2217  int ncontvars, /**< number of continuous variables */
2218  SCIP_CONS** conss, /**< array with constraints of the problem */
2219  int nconss, /**< number of constraints in the problem */
2220  SCIP_RESULT* result /**< pointer to store the result of the file writing call */
2221  )
2222 {
2223  int c;
2224  int v;
2225  int linecnt;
2226  char linebuffer[GMS_MAX_PRINTLEN];
2227 
2228  char varname[GMS_MAX_NAMELEN];
2229  char buffer[GMS_MAX_PRINTLEN];
2230 
2231  SCIP_Real* objcoeffs;
2232 
2233  SCIP_CONSHDLR* conshdlr;
2234  const char* conshdlrname;
2235  SCIP_CONS* cons;
2236 
2237  char consname[GMS_MAX_NAMELEN];
2238 
2239  SCIP_VAR** consvars;
2240  SCIP_Real* consvals;
2241  int nconsvars;
2242 
2243  SCIP_VAR* var;
2244  SCIP_VAR* objvar;
2245  SCIP_Real lb;
2246  SCIP_Real ub;
2247  SCIP_Bool freeints;
2248  SCIP_Bool nondefbounds;
2249  SCIP_Bool nlcons;
2250  SCIP_Bool nqcons;
2251  SCIP_Bool nsmooth;
2252  SCIP_Bool discrete;
2253  SCIP_Bool rangedrow;
2254  SCIP_Bool indicatorsosdef;
2255  SCIP_Bool signpowerallowed;
2256  SCIP_Bool needcomma;
2257 
2258  assert( scip != NULL );
2259  assert( vars != NULL || nvars == 0 );
2260 
2261  /* check if the variable names are not too long */
2262  SCIP_CALL( checkVarnames(scip, vars, nvars) );
2263  /* check if the constraint names are too long */
2264  SCIP_CALL( checkConsnames(scip, conss, nconss, transformed) );
2265 
2266  SCIP_CALL( SCIPgetBoolParam(scip, "reading/gmsreader/signpower", &signpowerallowed) );
2267 
2268  /* check if the objective is a single continuous variable, so we would not have to introduce an auxiliary variable
2269  * for GAMS
2270  */
2271  objvar = NULL;
2272  if( objscale == 1.0 && objoffset == 0.0 )
2273  {
2274  for( v = 0; v < nvars; ++v )
2275  {
2276  if( SCIPvarGetObj(vars[v]) == 0.0 ) /*lint !e613*/
2277  continue;
2278 
2279  if( objvar == NULL )
2280  {
2281  /* first variable with nonzero obj coefficient
2282  * if not active or having coefficient != 1.0, or being binary/integer, then give up
2283  */
2284  if( !SCIPvarIsActive(vars[v]) || SCIPvarGetObj(vars[v]) != 1.0 ||
2285  SCIPvarGetType(vars[v]) < SCIP_VARTYPE_IMPLINT ) /*lint !e613*/
2286  break;
2287 
2288  objvar = vars[v]; /*lint !e613*/
2289  }
2290  else
2291  {
2292  /* second variable with nonzero obj coefficient -> give up */
2293  objvar = NULL;
2294  break;
2295  }
2296  }
2297  }
2298 
2299  /* print statistics as comment to file */
2300  SCIPinfoMessage(scip, file, "$OFFLISTING\n");
2301  SCIPinfoMessage(scip, file, "* SCIP STATISTICS\n");
2302  SCIPinfoMessage(scip, file, "* Problem name : %s\n", name);
2303  SCIPinfoMessage(scip, file, "* Variables : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
2304  nvars, nbinvars, nintvars, nimplvars, ncontvars);
2305  SCIPinfoMessage(scip, file, "* Constraints : %d\n\n", nconss);
2306 
2307  /* print flags */
2308  SCIPinfoMessage(scip, file, "$MAXCOL %d\n", GMS_MAX_LINELEN - 1);
2309  SCIPinfoMessage(scip, file, "$OFFDIGIT\n\n");
2310 
2311  /* print variable section */
2312  SCIPinfoMessage(scip, file, "Variables\n");
2313  clearLine(linebuffer, &linecnt);
2314 
2315  if( objvar == NULL )
2316  {
2317  /* auxiliary objective variable */
2318  SCIPinfoMessage(scip, file, " objvar%c", nvars > 0 ? ',' : ';');
2319  }
2320 
2321  /* "model" variables */
2322  for( v = 0; v < nvars; ++v )
2323  {
2324  var = vars[v]; /*lint !e613*/
2325  assert( var != NULL );
2326 
2327  SCIP_CALL( printConformName(scip, varname, GMS_MAX_NAMELEN, SCIPvarGetName(var)) );
2328  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " %s%c", varname, (v < nvars - 1) ? ',' : ';');
2329  appendLine(scip, file, linebuffer, &linecnt, buffer);
2330 
2331  if( (linecnt > 0 && (v == nbinvars - 1 || v == nbinvars + nintvars - 1 ||
2332  v == nbinvars + nintvars + nimplvars - 1)) || v == nvars - 1 )
2333  {
2334  endLine(scip, file, linebuffer, &linecnt);
2335  clearLine(linebuffer, &linecnt);
2336  }
2337  }
2338 
2339  SCIPinfoMessage(scip, file, "\n");
2340 
2341  /* declare binary variables if present */
2342  if( nbinvars > 0 )
2343  {
2344  SCIPinfoMessage(scip, file, "Binary variables\n");
2345  clearLine(linebuffer, &linecnt);
2346 
2347  for( v = 0; v < nbinvars; ++v )
2348  {
2349  var = vars[v]; /*lint !e613*/
2350 
2351  SCIP_CALL( printConformName(scip, varname, GMS_MAX_NAMELEN, SCIPvarGetName(var)) );
2352  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " %s%s", varname, (v < nbinvars - 1) ? "," : ";");
2353 
2354  appendLine(scip, file, linebuffer, &linecnt, buffer);
2355  }
2356 
2357  endLine(scip, file, linebuffer, &linecnt);
2358  SCIPinfoMessage(scip, file, "\n");
2359  }
2360 
2361  /* declare integer variables if present */
2362  if( nintvars > 0 )
2363  {
2364  SCIPinfoMessage(scip, file, "Integer variables\n");
2365  clearLine(linebuffer, &linecnt);
2366 
2367  for( v = 0; v < nintvars; ++v )
2368  {
2369  var = vars[nbinvars + v]; /*lint !e613*/
2370 
2371  SCIP_CALL( printConformName(scip, varname, GMS_MAX_NAMELEN, SCIPvarGetName(var)) );
2372  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " %s%s", varname, (v < nintvars - 1) ? "," : ";");
2373 
2374  appendLine(scip, file, linebuffer, &linecnt, buffer);
2375  }
2376  endLine(scip, file, linebuffer, &linecnt);
2377  SCIPinfoMessage(scip, file, "\n");
2378  }
2379 
2380  /* print variable bounds */
2381  SCIPinfoMessage(scip, file, "* Variable bounds\n");
2382  SCIP_CALL( SCIPgetBoolParam(scip, "reading/gmsreader/freeints", &freeints) );
2383  nondefbounds = FALSE;
2384 
2385  for( v = 0; v < nvars; ++v )
2386  {
2387  var = vars[v]; /*lint !e613*/
2388  assert( var != NULL );
2389 
2390  SCIP_CALL( printConformName(scip, varname, GMS_MAX_NAMELEN, SCIPvarGetName(var)) );
2391 
2392  if( transformed )
2393  {
2394  /* in case the transformed is written only local bounds are posted which are valid in the current node */
2395  lb = SCIPvarGetLbLocal(var);
2396  ub = SCIPvarGetUbLocal(var);
2397  }
2398  else
2399  {
2400  lb = SCIPvarGetLbOriginal(var);
2401  ub = SCIPvarGetUbOriginal(var);
2402  }
2403  assert( lb <= ub );
2404 
2405  /* fixed */
2406  if( SCIPisEQ(scip, lb, ub) )
2407  {
2408  if( v < nintvars )
2409  SCIPinfoMessage(scip, file, " %s.fx = %g;\n", varname, SCIPfloor(scip, lb + 0.5));
2410  else
2411  SCIPinfoMessage(scip, file, " %s.fx = %.15g;\n", varname, lb);
2412  nondefbounds = TRUE;
2413 
2414  /* no need to write lower and upper bounds additionally */
2415  continue;
2416  }
2417 
2418  /* lower bound */
2419  if( v < nbinvars + nintvars )
2420  {
2421  /* default lower bound of binaries and integers is 0 (also in recent gams versions if pf4=0 is given) */
2422  if( !SCIPisZero(scip, lb) )
2423  {
2424  if( !SCIPisInfinity(scip, -lb) )
2425  SCIPinfoMessage(scip, file, " %s.lo = %g;\n", varname, SCIPceil(scip, lb));
2426  else if( freeints )
2427  SCIPinfoMessage(scip, file, " %s.lo = -inf;\n", varname); /* -inf is allowed when running gams with pf4=0, which we assume if freeints is TRUE */
2428  else
2429  SCIPinfoMessage(scip, file, " %s.lo = %g;\n", varname, -SCIPinfinity(scip)); /* sorry, -inf not allowed in gams file here */
2430  nondefbounds = TRUE;
2431  }
2432  }
2433  else if( v >= nbinvars + nintvars && !SCIPisInfinity(scip, -lb) )
2434  {
2435  /* continuous variables are free by default */
2436  SCIPinfoMessage(scip, file, " %s.lo = %.15g;\n", varname, lb);
2437  nondefbounds = TRUE;
2438  }
2439 
2440  /* upper bound */
2441  if( v < nbinvars )
2442  {
2443  if( !SCIPisFeasEQ(scip, ub, 1.0) )
2444  {
2445  SCIPinfoMessage(scip, file, " %s.up = %g;\n", varname, SCIPfeasFloor(scip, ub));
2446  nondefbounds = TRUE;
2447  }
2448  }
2449  else if( v < nbinvars + nintvars && !freeints )
2450  {
2451  /* freeints == FALSE: integer variables have upper bound 100 by default */
2452  if( !SCIPisFeasEQ(scip, ub, 100.0) )
2453  {
2454  if( !SCIPisInfinity(scip, ub) )
2455  SCIPinfoMessage(scip, file, " %s.up = %g;\n", varname, SCIPfeasFloor(scip, ub));
2456  else
2457  SCIPinfoMessage(scip, file, " %s.up = %g;\n", varname, SCIPinfinity(scip)); /* sorry, +inf not allowed in gams file here (unless pf4=0) */
2458  nondefbounds = TRUE;
2459  }
2460  }
2461  else if( v < nbinvars + nintvars && !SCIPisInfinity(scip, ub) )
2462  {
2463  /* freeints == TRUE: integer variables have no upper bound by default */
2464  SCIPinfoMessage(scip, file, " %s.up = %g;\n", varname, SCIPfloor(scip, ub));
2465  nondefbounds = TRUE;
2466  }
2467  else if( v >= nbinvars + nintvars && !SCIPisInfinity(scip, ub) )
2468  {
2469  /* continuous variables are free by default */
2470  SCIPinfoMessage(scip, file, " %s.up = %.15g;\n", varname, ub);
2471  nondefbounds = TRUE;
2472  }
2473  }
2474 
2475  if( !nondefbounds )
2476  SCIPinfoMessage(scip, file, "* (All other bounds at default value: binary [0,1], integer [%s], continuous [-inf,+inf].)\n", freeints ? "0,+inf" : "0,100");
2477  SCIPinfoMessage(scip, file, "\n");
2478 
2479  /* print equations section */
2480  if( nconss > 0 || objvar == NULL )
2481  {
2482  SCIPinfoMessage(scip, file, "Equations\n");
2483  clearLine(linebuffer, &linecnt);
2484  }
2485  needcomma = FALSE;
2486 
2487  if( objvar == NULL )
2488  {
2489  SCIPinfoMessage(scip, file, " objequ");
2490  needcomma = TRUE;
2491  }
2492 
2493  /* declare equations */
2494  for( c = 0; c < nconss; ++c )
2495  {
2496  cons = conss[c];
2497  assert( cons != NULL );
2498 
2499  conshdlr = SCIPconsGetHdlr(cons);
2500  assert( conshdlr != NULL );
2501 
2502  SCIP_CALL( printConformName(scip, consname, GMS_MAX_NAMELEN, SCIPconsGetName(cons)) );
2503  conshdlrname = SCIPconshdlrGetName(conshdlr);
2504  assert( transformed == SCIPconsIsTransformed(cons) );
2505 
2506  rangedrow = strcmp(conshdlrname, "linear") == 0
2507  && !SCIPisInfinity(scip, -SCIPgetLhsLinear(scip, cons)) && !SCIPisInfinity(scip, SCIPgetRhsLinear(scip, cons))
2508  && !SCIPisEQ(scip, SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons));
2509  rangedrow = rangedrow || (strcmp(conshdlrname, "quadratic") == 0
2510  && !SCIPisInfinity(scip, -SCIPgetLhsQuadratic(scip, cons)) && !SCIPisInfinity(scip, SCIPgetRhsQuadratic(scip, cons))
2511  && !SCIPisEQ(scip, SCIPgetLhsQuadratic(scip, cons), SCIPgetRhsQuadratic(scip, cons)));
2512  rangedrow = rangedrow || (strcmp(conshdlrname, "nonlinear") == 0
2513  && !SCIPisInfinity(scip, -SCIPgetLhsNonlinear(scip, cons)) && !SCIPisInfinity(scip, SCIPgetRhsNonlinear(scip, cons))
2514  && !SCIPisEQ(scip, SCIPgetLhsNonlinear(scip, cons), SCIPgetRhsNonlinear(scip, cons)));
2515  rangedrow = rangedrow || (strcmp(conshdlrname, "abspower") == 0
2516  && !SCIPisInfinity(scip, -SCIPgetLhsAbspower(scip, cons)) && !SCIPisInfinity(scip, SCIPgetRhsAbspower(scip, cons))
2517  && !SCIPisEQ(scip, SCIPgetLhsAbspower(scip, cons), SCIPgetRhsAbspower(scip, cons)));
2518  rangedrow = rangedrow || (strcmp(conshdlrname, "bivariate") == 0
2519  && !SCIPisInfinity(scip, -SCIPgetLhsBivariate(scip, cons)) && !SCIPisInfinity(scip, SCIPgetRhsBivariate(scip, cons))
2520  && !SCIPisEQ(scip, SCIPgetLhsBivariate(scip, cons), SCIPgetRhsBivariate(scip, cons)));
2521  rangedrow = rangedrow || (strcmp(conshdlrname, "varbound") == 0
2522  && !SCIPisInfinity(scip, -SCIPgetLhsVarbound(scip, cons)) && !SCIPisInfinity(scip, SCIPgetRhsVarbound(scip, cons))
2523  && !SCIPisEQ(scip, SCIPgetLhsVarbound(scip, cons), SCIPgetRhsVarbound(scip, cons)));
2524 
2525  /* we declare only those constraints which we can print in GAMS format */
2526  if( strcmp(conshdlrname, "knapsack") != 0 && strcmp(conshdlrname, "logicor") != 0 && strcmp(conshdlrname, "setppc") != 0
2527  && strcmp(conshdlrname, "linear") != 0 && strcmp(conshdlrname, "quadratic") != 0 && strcmp(conshdlrname, "varbound") != 0
2528  && strcmp(conshdlrname, "soc") != 0 && strcmp(conshdlrname, "abspower") != 0 && strcmp(conshdlrname, "bivariate") != 0
2529  && strcmp(conshdlrname, "nonlinear") != 0 && strcmp(conshdlrname, "SOS1") != 0 && strcmp(conshdlrname, "SOS2") != 0
2530  && strcmp(conshdlrname, "indicator") != 0 )
2531  {
2532  SCIPwarningMessage(scip, "Constraint type <%s> not supported. Skip writing constraint <%s>.\n", conshdlrname, SCIPconsGetName(cons));
2533  continue;
2534  }
2535 
2536  if( needcomma )
2537  appendLine(scip, file, linebuffer, &linecnt, ",");
2538 
2539  SCIP_CALL( printConformName(scip, consname, GMS_MAX_NAMELEN, SCIPconsGetName(cons)) );
2540  if( rangedrow )
2541  {
2542  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " %s%s%s%s", consname, "_lhs, ", consname, "_rhs");
2543  appendLine(scip, file, linebuffer, &linecnt, buffer);
2544  }
2545  else
2546  {
2547  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " %s", consname);
2548  appendLine(scip, file, linebuffer, &linecnt, buffer);
2549  }
2550  needcomma = TRUE;
2551  }
2552 
2553  if( nconss > 0 || objvar == NULL )
2554  {
2555  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, ";");
2556  appendLine(scip, file, linebuffer, &linecnt, buffer);
2557 
2558  endLine(scip, file, linebuffer, &linecnt);
2559  SCIPinfoMessage(scip, file, "\n");
2560  }
2561 
2562  if( objvar == NULL )
2563  {
2564  /* print objective function equation */
2565  clearLine(linebuffer, &linecnt);
2566  if( objoffset != 0.0 )
2567  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " objequ .. objvar =e= %.15g + ", objscale * objoffset);
2568  else
2569  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, " objequ .. objvar =e= ");
2570  appendLine(scip, file, linebuffer, &linecnt, buffer);
2571 
2572  SCIP_CALL( SCIPallocBufferArray(scip, &objcoeffs, nvars) );
2573 
2574  for( v = 0; v < nvars; ++v )
2575  {
2576  var = vars[v]; /*lint !e613*/
2577  assert( var != NULL );
2578 
2579  /* in case the original problem has to be posted the variables have to be either "original" or "negated" */
2580  assert( transformed || SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL || SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED );
2581 
2582  objcoeffs[v] = SCIPisZero(scip, SCIPvarGetObj(var)) ? 0.0 : objscale * SCIPvarGetObj(var);
2583  }
2584 
2585  SCIP_CALL( printActiveVariables(scip, file, linebuffer, &linecnt, "", ";", nvars, vars, objcoeffs, transformed) );
2586 
2587  SCIPfreeBufferArray(scip, &objcoeffs);
2588  endLine(scip, file, linebuffer, &linecnt);
2589  SCIPinfoMessage(scip, file, "\n");
2590  }
2591 
2592  /* print constraints */
2593  nlcons = FALSE;
2594  nqcons = FALSE;
2595  nsmooth = FALSE;
2596  discrete = nbinvars > 0 || nintvars > 0;
2597  indicatorsosdef = FALSE;
2598  for( c = 0; c < nconss; ++c )
2599  {
2600  cons = conss[c];
2601  assert( cons != NULL );
2602 
2603  /* in case the transformed is written, only constraints are posted which are enabled in the current node */
2604  assert(!transformed || SCIPconsIsEnabled(cons));
2605 
2606  conshdlr = SCIPconsGetHdlr(cons);
2607  assert( conshdlr != NULL );
2608 
2609  SCIP_CALL( printConformName(scip, consname, GMS_MAX_NAMELEN, SCIPconsGetName(cons)) );
2610  conshdlrname = SCIPconshdlrGetName(conshdlr);
2611  assert( transformed == SCIPconsIsTransformed(cons) );
2612 
2613  if( strcmp(conshdlrname, "knapsack") == 0 )
2614  {
2615  SCIP_Longint* weights;
2616 
2617  consvars = SCIPgetVarsKnapsack(scip, cons);
2618  nconsvars = SCIPgetNVarsKnapsack(scip, cons);
2619 
2620  /* copy Longint array to SCIP_Real array */
2621  weights = SCIPgetWeightsKnapsack(scip, cons);
2622  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
2623  for( v = 0; v < nconsvars; ++v )
2624  consvals[v] = (SCIP_Real)weights[v];
2625 
2626  SCIP_CALL( printLinearCons(scip, file, consname, nconsvars, consvars, consvals,
2627  -SCIPinfinity(scip), (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), transformed) );
2628 
2629  SCIPfreeBufferArray(scip, &consvals);
2630  }
2631  else if( strcmp(conshdlrname, "linear") == 0 )
2632  {
2633  SCIP_CALL( printLinearCons(scip, file, consname,
2634  SCIPgetNVarsLinear(scip, cons), SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons),
2635  SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), transformed) );
2636  }
2637  else if( strcmp(conshdlrname, "logicor") == 0 )
2638  {
2639  SCIP_CALL( printLinearCons(scip, file, consname,
2640  SCIPgetNVarsLogicor(scip, cons), SCIPgetVarsLogicor(scip, cons), NULL,
2641  1.0, SCIPinfinity(scip), transformed) );
2642  }
2643  else if( strcmp(conshdlrname, "quadratic") == 0 )
2644  {
2645  SCIP_CALL( printQuadraticCons(scip, file, consname,
2649  SCIPgetLhsQuadratic(scip, cons), SCIPgetRhsQuadratic(scip, cons), transformed) );
2650 
2651  nlcons = TRUE;
2652  }
2653  else if( strcmp(conshdlrname, "nonlinear") == 0 )
2654  {
2655  /* cons_nonlinear does not have exprtree's at hand during presolve */
2657  && SCIPgetExprgraphNonlinear(scip,conshdlr) != NULL )
2658  {
2659  SCIP_EXPRTREE* exprtree;
2660  SCIP_Real coef;
2661 
2663  coef = 1.0;
2664  SCIP_CALL( printNonlinearCons(scip, file, consname,
2666  1, &exprtree, &coef,
2667  SCIPgetLhsNonlinear(scip, cons), SCIPgetRhsNonlinear(scip, cons), transformed, &nsmooth) );
2668 
2669  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
2670  }
2671  else
2672  {
2673  SCIP_CALL( printNonlinearCons(scip, file, consname,
2676  SCIPgetLhsNonlinear(scip, cons), SCIPgetRhsNonlinear(scip, cons), transformed, &nsmooth) );
2677  }
2678  nlcons = TRUE;
2679  nqcons = TRUE;
2680  }
2681  else if( strcmp(conshdlrname, "bivariate") == 0 )
2682  {
2683  SCIP_EXPRTREE* exprtree;
2684  SCIP_VAR* linvar;
2685  SCIP_Real lincoef;
2686  int exprdegree;
2687  SCIP_Real one;
2688 
2689  exprtree = SCIPgetExprtreeBivariate(scip, cons);
2690  assert(exprtree != NULL);
2691 
2692  linvar = SCIPgetLinearVarBivariate(scip, cons);
2693  lincoef = SCIPgetLinearCoefBivariate(scip, cons);
2694  one = 1.0;
2695  SCIP_CALL( printNonlinearCons(scip, file, consname,
2696  linvar == NULL ? 0 : 1, &linvar, &lincoef,
2697  1, &exprtree, &one,
2698  SCIPgetLhsBivariate(scip, cons), SCIPgetRhsBivariate(scip, cons), transformed, &nsmooth) );
2699 
2700  SCIP_CALL( SCIPexprtreeGetMaxDegree(exprtree, &exprdegree) );
2701  if( exprdegree > 1 )
2702  nlcons = TRUE;
2703  if( exprdegree > 2)
2704  nqcons = TRUE;
2705  }
2706  else if( strcmp(conshdlrname, "setppc") == 0 )
2707  {
2708  consvars = SCIPgetVarsSetppc(scip, cons);
2709  nconsvars = SCIPgetNVarsSetppc(scip, cons);
2710 
2711  switch( SCIPgetTypeSetppc(scip, cons) )
2712  {
2714  SCIP_CALL( printLinearCons(scip, file, consname,
2715  nconsvars, consvars, NULL, 1.0, 1.0, transformed) );
2716  break;
2718  SCIP_CALL( printLinearCons(scip, file, consname,
2719  nconsvars, consvars, NULL, -SCIPinfinity(scip), 1.0, transformed) );
2720  break;
2722  SCIP_CALL( printLinearCons(scip, file, consname,
2723  nconsvars, consvars, NULL, 1.0, SCIPinfinity(scip), transformed) );
2724  break;
2725  }
2726  }
2727  else if( strcmp(conshdlrname, "varbound") == 0 )
2728  {
2729  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
2730  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
2731 
2732  consvars[0] = SCIPgetVarVarbound(scip, cons);
2733  consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
2734 
2735  consvals[0] = 1.0;
2736  consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
2737 
2738  SCIP_CALL( printLinearCons(scip, file, consname,
2739  2, consvars, consvals,
2740  SCIPgetLhsVarbound(scip, cons), SCIPgetRhsVarbound(scip, cons), transformed) );
2741 
2742  SCIPfreeBufferArray(scip, &consvars);
2743  SCIPfreeBufferArray(scip, &consvals);
2744  }
2745  else if( strcmp(conshdlrname, "soc") == 0 )
2746  {
2747  SCIP_CALL( printSOCCons(scip, file, consname,
2748  SCIPgetNLhsVarsSOC(scip, cons), SCIPgetLhsVarsSOC(scip, cons), SCIPgetLhsCoefsSOC(scip, cons), SCIPgetLhsOffsetsSOC(scip, cons), SCIPgetLhsConstantSOC(scip, cons),
2749  SCIPgetRhsVarSOC(scip, cons), SCIPgetRhsCoefSOC(scip, cons), SCIPgetRhsOffsetSOC(scip, cons), transformed) );
2750 
2751  nlcons = nlcons || !isGAMSprintableSOC(SCIPgetNLhsVarsSOC(scip, cons), SCIPgetLhsVarsSOC(scip, cons), SCIPgetLhsCoefsSOC(scip, cons), SCIPgetLhsOffsetsSOC(scip, cons), SCIPgetLhsConstantSOC(scip, cons),
2752  SCIPgetRhsVarSOC(scip, cons), SCIPgetRhsCoefSOC(scip, cons), SCIPgetRhsOffsetSOC(scip, cons));
2753  }
2754  else if( strcmp(conshdlrname, "indicator") == 0 )
2755  {
2756  SCIP_CALL( printIndicatorCons(scip, file, consname,
2757  SCIPgetBinaryVarIndicator(cons), SCIPgetSlackVarIndicator(cons), &indicatorsosdef,
2758  transformed) );
2759  }
2760  else if( strcmp(conshdlrname, "abspower") == 0 )
2761  {
2762  SCIP_CALL( printSignpowerCons(scip, file, consname,
2763  SCIPgetNonlinearVarAbspower(scip, cons), SCIPgetLinearVarAbspower(scip, cons),
2764  SCIPgetExponentAbspower(scip, cons), SCIPgetOffsetAbspower(scip, cons), SCIPgetCoefLinearAbspower(scip, cons),
2765  SCIPgetLhsAbspower(scip, cons), SCIPgetRhsAbspower(scip, cons), transformed, signpowerallowed, &nsmooth) );
2766 
2767  nlcons = TRUE;
2768  nqcons = TRUE;
2769  }
2770  else if( strcmp(conshdlrname, "SOS1") == 0 )
2771  {
2772  SCIP_CALL( printSOSCons(scip, file, consname,
2773  SCIPgetNVarsSOS1(scip, cons), SCIPgetVarsSOS1(scip, cons), 1,
2774  transformed) );
2775  discrete = TRUE;
2776  }
2777  else if( strcmp(conshdlrname, "SOS2") == 0 )
2778  {
2779  SCIP_CALL( printSOSCons(scip, file, consname,
2780  SCIPgetNVarsSOS2(scip, cons), SCIPgetVarsSOS2(scip, cons), 2,
2781  transformed) );
2782  discrete = TRUE;
2783  }
2784  else
2785  {
2786  SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
2787  SCIPinfoMessage(scip, file, "* ");
2788  SCIP_CALL( SCIPprintCons(scip, cons, file) );
2789  SCIPinfoMessage(scip, file, ";\n");
2790  }
2791 
2792  SCIPinfoMessage(scip, file, "\n");
2793  }
2794  /* if at most quadratic, then cannot have nonsmooth functions */
2795  assert(nlcons || !nsmooth);
2796 
2797  /* print model creation */
2798  SCIPinfoMessage(scip, file, "Model m / all /;\n\n");
2799 
2800  /* set some options to reduce listing file size */
2801  SCIPinfoMessage(scip, file, "option limrow = 0;\n");
2802  SCIPinfoMessage(scip, file, "option limcol = 0;\n\n");
2803 
2804  /* print solve command */
2805  (void) SCIPsnprintf(buffer, GMS_MAX_PRINTLEN, "%s%s",
2806  discrete ? "MI" : "", nlcons ? (nqcons ? ((nsmooth && !discrete) ? "DNLP" : "NLP") : "QCP") : (discrete > 0 ? "P" : "LP"));
2807 
2808  if( objvar != NULL )
2809  {
2810  SCIP_CALL( printConformName(scip, varname, GMS_MAX_NAMELEN, SCIPvarGetName(objvar)) );
2811  }
2812 
2813  SCIPinfoMessage(scip, file, "$if not set %s $set %s %s\n", buffer, buffer, buffer);
2814  SCIPinfoMessage(scip, file, "Solve m using %%%s%% %simizing %s;\n",
2815  buffer, objsense == SCIP_OBJSENSE_MINIMIZE ? "min" : "max", objvar != NULL ? varname : "objvar");
2816 
2817  *result = SCIP_SUCCESS;
2818 
2819  return SCIP_OKAY;
2820 }
2821