1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*  Copyright (c) 2002-2023 Zuse Institute Berlin (ZIB)                      */
7    	/*                                                                           */
8    	/*  Licensed under the Apache License, Version 2.0 (the "License");          */
9    	/*  you may not use this file except in compliance with the License.         */
10   	/*  You may obtain a copy of the License at                                  */
11   	/*                                                                           */
12   	/*      http://www.apache.org/licenses/LICENSE-2.0                           */
13   	/*                                                                           */
14   	/*  Unless required by applicable law or agreed to in writing, software      */
15   	/*  distributed under the License is distributed on an "AS IS" BASIS,        */
16   	/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17   	/*  See the License for the specific language governing permissions and      */
18   	/*  limitations under the License.                                           */
19   	/*                                                                           */
20   	/*  You should have received a copy of the Apache-2.0 license                */
21   	/*  along with SCIP; see the file LICENSE. If not visit scipopt.org.         */
22   	/*                                                                           */
23   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24   	
25   	/**@file   reader_pbm.c
26   	 * @ingroup DEFPLUGINS_READER
27   	 * @brief  file writer for portable bitmap file format (PBM), open with common graphic viewer programs (e.g. xview)
28   	 * @author Alexandra Kraft
29   	 *
30   	 */
31   	
32   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33   	
34   	#include "blockmemshell/memory.h"
35   	#include "scip/cons_knapsack.h"
36   	#include "scip/cons_linear.h"
37   	#include "scip/cons_logicor.h"
38   	#include "scip/cons_setppc.h"
39   	#include "scip/cons_varbound.h"
40   	#include "scip/pub_cons.h"
41   	#include "scip/pub_message.h"
42   	#include "scip/pub_reader.h"
43   	#include "scip/pub_var.h"
44   	#include "scip/reader_pbm.h"
45   	#include "scip/scip_cons.h"
46   	#include "scip/scip_mem.h"
47   	#include "scip/scip_message.h"
48   	#include "scip/scip_param.h"
49   	#include "scip/scip_reader.h"
50   	#include "scip/scip_var.h"
51   	#include <string.h>
52   	
53   	#define READER_NAME             "pbmreader"
54   	#define READER_DESC             "file writer for portable bitmap file format (PBM), open with common graphic viewer programs (e.g. xview)"
55   	#define READER_EXTENSION        "pbm"
56   	
57   	/*
58   	 * Data structures
59   	 */
60   	#define PBM_MAX_LINELEN               71      /**< the maximum length of any line is 70 + '\\0' = 71*/
61   	#define DEFAULT_PBM_BINARY            TRUE    /**< binary is the default format for PBM */
62   	#define DEFAULT_PBM_MAXROWS           1000    /**< allowed maximum of pixel-rows int the picture */
63   	#define DEFAULT_PBM_MAXCOLS           1000    /**< allowed maximum of pixel-columns in the picture */
64   	
65   	/** LP reading data */
66   	struct SCIP_ReaderData
67   	{
68   	   SCIP_Bool             binary;             /**< binary is the default format for PBM */
69   	   int                   maxrows;            /**< allowed maximum of pixel-rows int the picture */
70   	   int                   maxcols;            /**< allowed maximum of pixel-columns in the picture */
71   	};
72   	
73   	/*
74   	 * Local methods (for writing)
75   	 */
76   	
77   	/** transforms given variables, scalars, and constant to the corresponding active variables, scalars, and constant */
78   	static
79   	SCIP_RETCODE getActiveVariables(
80   	   SCIP*                 scip,               /**< SCIP data structure */
81   	   SCIP_VAR**            vars,               /**< vars array to get active variables for */
82   	   SCIP_Real*            scalars,            /**< scalars a_1, ..., a_n in sum a_1*x_1 + ... + a_n*x_n + c */
83   	   int*                  nvars,              /**< pointer to number of variables and values in vars and vals array */
84   	   SCIP_Real*            constant,           /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c  */
85   	   SCIP_Bool             transformed         /**< transformed constraint? */
86   	   )
87   	{
88   	   int requiredsize;
89   	   int v;
90   	
91   	   assert(scip != NULL);
92   	   assert(vars != NULL);
93   	   assert(scalars != NULL);
94   	   assert(nvars != NULL);
95   	   assert(constant != NULL);
96   	
97   	   if( transformed )
98   	   {
99   	      SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize, TRUE) );
100  	
101  	      if( requiredsize > *nvars )
102  	      {
103  	         SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
104  	         SCIP_CALL( SCIPreallocBufferArray(scip, &scalars, requiredsize) );
105  	
106  	         SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize, TRUE) );
107  	         assert(requiredsize <= *nvars);
108  	      }
109  	   }
110  	   else
111  	   {
112  	      for( v = 0; v < *nvars; ++v )
113  	      {
114  	         SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalars[v], constant) );
115  	      }
116  	   }
117  	
118  	   return SCIP_OKAY;
119  	}
120  	
121  	/** transforms given variables to the corresponding active variables */
122  	static
123  	SCIP_RETCODE getActiveVariables2(
124  	   SCIP*                 scip,               /**< SCIP data structure */
125  	   SCIP_VAR**            vars,               /**< vars array to get active variables for */
126  	   int*                  nvars,              /**< pointer to number of variables and values in vars and vals array */
127  	   SCIP_Bool             transformed         /**< transformed constraint? */
128  	   )
129  	{
130  	   int requiredsize;
131  	   int v;
132  	
133  	   assert(scip != NULL);
134  	   assert(vars != NULL);
135  	   assert(nvars != NULL);
136  	
137  	   if( transformed )
138  	   {
139  	      SCIP_CALL( SCIPgetActiveVars(scip, vars, nvars, *nvars, &requiredsize) );
140  	
141  	      if( requiredsize > *nvars )
142  	      {
143  	         SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
144  	
145  	         SCIP_CALL( SCIPgetActiveVars(scip, vars, nvars, requiredsize, &requiredsize) );
146  	         assert(requiredsize <= *nvars);
147  	      }
148  	   }
149  	   else
150  	   {
151  	      SCIP_Real scalar;
152  	      SCIP_Real constant;
153  	      for( v = 0; v < *nvars; ++v )
154  	      {
155  	         scalar = 1.0;
156  	         constant = 0.0;
157  	         SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalar, &constant) );
158  	      }
159  	   }
160  	
161  	   return SCIP_OKAY;
162  	}
163  	
164  	/** clears the given line buffer */
165  	static
166  	void clearLine(
167  	   char*                 linebuffer,         /**< line */
168  	   int*                  linecnt             /**< number of characters in line */
169  	   )
170  	{
171  	   assert(linebuffer != NULL);
172  	   assert(linecnt != NULL);
173  	
174  	   (*linecnt) = 0;
175  	   linebuffer[0] = '\0';
176  	}
177  	
178  	
179  	/** appends a bit to buffer and prints it to the give file stream if we've gather a whole byte */
180  	static
181  	void flushBits(
182  	   SCIP*                 scip,               /**< SCIP data structure */
183  	   FILE*                 file,               /**< output file (or NULL for standard output) */
184  	   unsigned char*        bitcnt,             /**< counts bits until whole byte is gathered */
185  	   unsigned char*        bitbuffer           /**< bit buffer */
186  	   )
187  	{
188  	   assert(scip != NULL);
189  	
190  	   if( *bitcnt == 0 )
191  	      return;
192  	
193  	   assert(bitbuffer != NULL);
194  	   assert(*bitcnt > 0 && *bitcnt <= 8);
195  	
196  	   (*bitbuffer) <<= (8 - *bitcnt); /*lint !e701 !e734*/
197  	
198  	   fputc(*bitbuffer, file);
199  	
200  	   *bitcnt = 0;
201  	   *bitbuffer = 0;
202  	}
203  	
204  	
205  	/** appends a bit to buffer and prints it to the given file stream if we've gathered a whole byte */
206  	static
207  	void appendBit(
208  	   SCIP*                 scip,               /**< SCIP data structure */
209  	   FILE*                 file,               /**< output file (or NULL for standard output) */
210  	   unsigned char         bit,                /**< bit to append */
211  	   unsigned char*        bitcnt,             /**< counts bits until whole byte is gathered */
212  	   unsigned char*        bitbuffer           /**< bit buffer */
213  	   )
214  	{
215  	   assert(scip != NULL);
216  	   assert(*bitcnt < 8);
217  	   assert(bitbuffer != NULL);
218  	
219  	   (*bitbuffer) = ((*bitbuffer)<<1)|(bit&1); /*lint !e734*/
220  	   *bitcnt += 1;
221  	
222  	   if( *bitcnt == 8 )
223  	      flushBits(scip, file, bitcnt, bitbuffer);
224  	}
225  	
226  	/** calculates the size of the quadratic matrix, which will correspond to one pixel in the picture */
227  	static
228  	int getSubmatrixSize(
229  	   SCIP_READERDATA*      readerdata,         /**< information for reader */
230  	   int                   nvars,              /**< number of variables */
231  	   int                   nconss              /**< number of constraints */
232  	   )
233  	{
234  	   int sizev;
235  	   int sizeh;
236  	   int res;
237  	
238  	   assert(readerdata->maxrows != 0 && readerdata->maxcols != 0);
239  	
240  	   if( readerdata->maxrows > nconss )
241  	      readerdata->maxrows = nconss;
242  	
243  	   if( readerdata->maxcols > nvars )
244  	      readerdata->maxcols = nvars;
245  	
246  	   sizev = (nconss + readerdata->maxrows - 1) / readerdata->maxrows;
247  	   sizeh = (nvars + readerdata->maxcols - 1) / readerdata->maxcols;
248  	
249  	   /* both defined with -1 */
250  	   if( readerdata->maxrows == -1 && readerdata->maxcols == -1 )
251  	      res = 1;
252  	
253  	   /* only width is defined */
254  	   else if( readerdata->maxrows == -1 && readerdata->maxcols > 0 )
255  	      res = sizeh;
256  	
257  	   /* only height is defined */
258  	   else if( readerdata->maxrows > 0 && readerdata->maxcols == -1 )
259  	      res = sizev;
260  	
261  	   /* both are defined, use smaller scaling factor */
262  	   else if( sizev > sizeh )
263  	      res = sizev;
264  	   else
265  	      res = sizeh;
266  	
267  	   readerdata->maxrows = (nconss + res - 1) / res;
268  	   readerdata->maxcols = (nvars + res - 1) / res;
269  	
270  	   return res;
271  	}
272  	
273  	
274  	/** print row in PBM format to file stream */
275  	static
276  	void printRow(
277  	   SCIP*                 scip,               /**< SCIP data structure */
278  	   SCIP_READERDATA*      readerdata,         /**< information for reader */
279  	   SCIP_VAR**            vars,               /**< array of constraint variables */
280  	   int                   conscnt,            /**< current constraint */
281  	   int                   nvars,              /**< number of constraint variables */
282  	   int                   submatrixsize,      /**< size of the submatrices */
283  	   int*                  scaledimage         /**< array of ints that count variables in every submatrix */
284  	   )
285  	{
286  	   int v;
287  	   int i;
288  	   const int y = conscnt / submatrixsize;
289  	   int x;
290  	
291  	   assert(scip != NULL);
292  	   assert(nvars > 0);
293  	   assert(readerdata != NULL);
294  	
295  	   for( i = 0; i < nvars; ++i )
296  	   {
297  	      assert(vars != NULL); /* for lint */
298  	
299  	      v = SCIPvarGetProbindex(vars[i]);
300  	      if( v != -1 )
301  	      {
302  	         x = v / submatrixsize;
303  	         ++(scaledimage[y * readerdata->maxcols + x]);
304  	      }
305  	   }
306  	
307  	   return;
308  	}
309  	
310  	/** prints given linear constraint information in PBM format to file stream */
311  	static
312  	SCIP_RETCODE printLinearCons(
313  	   SCIP*                 scip,               /**< SCIP data structure */
314  	   SCIP_READERDATA*      readerdata,         /**< information for reader */
315  	   SCIP_VAR**            vars,               /**< array of variables */
316  	   SCIP_Real*            vals,               /**< array of coefficients values (or NULL if all coefficient values are 1) */
317  	   int                   nvars,              /**< current constraint */
318  	   int                   conscnt,            /**< counts variables in the constraint */
319  	   SCIP_Bool             transformed,        /**< transformed constraint? */
320  	   int                   submatrixsize,      /**< size of the submatrices */
321  	   int*                  scaledimage         /**< array of ints that count variables in every submatrix */
322  	   )
323  	{
324  	   SCIP_VAR** activevars;
325  	   SCIP_Real* activevals;
326  	   SCIP_Real activeconstant = 0.0;
327  	   int nactivevars;
328  	   int v;
329  	
330  	   assert(scip != NULL);
331  	   assert(vars != NULL);
332  	   assert(nvars > 0);
333  	   assert(conscnt >= 0);
334  	   assert(readerdata != NULL);
335  	
336  	   /* duplicate variable and value array */
337  	   nactivevars = nvars;
338  	   SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) );
339  	   if( vals != NULL )
340  	   {
341  	      SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) );
342  	   }
343  	   else
344  	   {
345  	      SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
346  	
347  	      for( v = 0; v < nactivevars; ++v )
348  	         activevals[v] = 1.0;
349  	   }
350  	
351  	   /* retransform given variables to active variables */
352  	   SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
353  	
354  	   /* print constraint */
355  	   printRow(scip, readerdata, activevars, conscnt, nactivevars, submatrixsize, scaledimage);
356  	
357  	   /* free buffer arrays */
358  	   SCIPfreeBufferArray(scip, &activevars);
359  	   SCIPfreeBufferArray(scip, &activevals);
360  	
361  	   return SCIP_OKAY;
362  	}
363  	
364  	/* draws the scaled image */
365  	static
366  	void drawScaledImage(
367  	   SCIP*                 scip,               /**< SCIP data structure */
368  	   FILE*                 file,               /**< output file, or NULL if standard output should be used */
369  	   SCIP_READERDATA*      readerdata,         /**< information for reader */
370  	   int*                  scaledimage         /**< array of ints that count variables in every submatrix */
371  	   )
372  	{
373  	   int y;
374  	   int x;
375  	   unsigned char bitcnt = 0;
376  	   unsigned char bitbuffer = '\0';
377  	
378  	   assert(scip != NULL);
379  	   assert(readerdata != NULL);
380  	
381  	   for( y = 0; y < readerdata->maxrows; y++ )
382  	   {
383  	      for( x = 0; x < readerdata->maxcols; x++ )
384  	      {
385  	         unsigned char v = 0;
386  	         if( scaledimage[y*readerdata->maxcols+x] >= 1 )
387  	         {
388  	            v = 1;
389  	         }
390  	         appendBit(scip, file, v, &bitcnt, &bitbuffer);
391  	      }
392  	      flushBits(scip, file, &bitcnt, &bitbuffer);
393  	   }
394  	}
395  	
396  	
397  	/*
398  	 * Callback methods of reader
399  	 */
400  	
401  	/** copy method for reader plugins (called when SCIP copies plugins) */
402  	static
403  	SCIP_DECL_READERCOPY(readerCopyPbm)
404  	{  /*lint --e{715}*/
405  	   assert(scip != NULL);
406  	   assert(reader != NULL);
407  	   assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
408  	
409  	   /* call inclusion method of reader */
410  	   SCIP_CALL( SCIPincludeReaderPbm(scip) );
411  	
412  	   return SCIP_OKAY;
413  	}
414  	
415  	/** destructor of reader to free user data (called when SCIP is exiting) */
416  	static
417  	SCIP_DECL_READERFREE(readerFreePbm)
418  	{
419  	   SCIP_READERDATA* readerdata;
420  	
421  	   assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
422  	
423  	   readerdata = SCIPreaderGetData(reader);
424  	   assert(readerdata != NULL);
425  	
426  	   SCIPfreeBlockMemory(scip, &readerdata);
427  	
428  	   return SCIP_OKAY;
429  	}
430  	
431  	/** problem reading method of reader */
432  	#define readerReadPbm NULL
433  	
434  	/** problem writing method of reader */
435  	static
436  	SCIP_DECL_READERWRITE(readerWritePbm)
437  	{  /*lint --e{715}*/
438  	   SCIP_READERDATA* readerdata;
439  	
440  	   assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
441  	
442  	   readerdata = SCIPreaderGetData(reader);
443  	   assert(readerdata != NULL);
444  	
445  	   SCIP_CALL( SCIPwritePbm(scip, file, name, readerdata, transformed, nvars, conss, nconss, result) );
446  	
447  	   return SCIP_OKAY;
448  	}
449  	
450  	/*
451  	 * reader specific interface methods
452  	 */
453  	
454  	/** includes the pbm file reader in SCIP */
455  	SCIP_RETCODE SCIPincludeReaderPbm(
456  	   SCIP*                 scip                /**< SCIP data structure */
457  	   )
458  	{
459  	   SCIP_READERDATA* readerdata;
460  	
461  	   /* create pbm reader data */
462  	   SCIP_CALL( SCIPallocBlockMemory(scip, &readerdata) );
463  	
464  	   /* include pbm reader */
465  	   SCIP_CALL( SCIPincludeReader(scip, READER_NAME, READER_DESC, READER_EXTENSION,
466  	         readerCopyPbm, readerFreePbm, readerReadPbm, readerWritePbm, readerdata) );
467  	
468  	   /* add pbm reader parameters */
469  	   SCIP_CALL( SCIPaddBoolParam(scip,
470  	         "reading/pbmreader/binary", "should the output format be binary(P4) (otherwise plain(P1) format)",
471  	         &readerdata->binary, FALSE, DEFAULT_PBM_BINARY, NULL, NULL) );
472  	   SCIP_CALL( SCIPaddIntParam(scip,
473  	         "reading/pbmreader/maxrows", "maximum number of rows in the scaled picture (-1 for no limit)",
474  	         &readerdata->maxrows, FALSE, DEFAULT_PBM_MAXROWS, -1, INT_MAX, NULL, NULL) );
475  	   SCIP_CALL( SCIPaddIntParam(scip,
476  	         "reading/pbmreader/maxcols", "maximum number of columns in the scaled picture (-1 for no limit)",
477  	         &readerdata->maxcols, FALSE, DEFAULT_PBM_MAXCOLS, -1, INT_MAX, NULL, NULL) );
478  	
479  	   return SCIP_OKAY;
480  	}
481  	
482  	/* writes picture of matrix structure to file */
483  	SCIP_RETCODE SCIPwritePbm(
484  	   SCIP*                 scip,               /**< SCIP data structure */
485  	   FILE*                 file,               /**< output file, or NULL if standard output should be used */
486  	   const char*           name,               /**< problem name */
487  	   SCIP_READERDATA*      readerdata,         /**< information for reader */
488  	   SCIP_Bool             transformed,        /**< TRUE iff problem is the transformed problem */
489  	   int                   nvars,              /**< number of active variables in the problem */
490  	   SCIP_CONS**           conss,              /**< array with constraints of the problem */
491  	   int                   nconss,             /**< number of constraints in the problem */
492  	   SCIP_RESULT*          result              /**< pointer to store the result of the file writing call */
493  	   )
494  	{
495  	   SCIP_CONSHDLR* conshdlr;
496  	   SCIP_CONS* cons;
497  	   SCIP_VAR** consvars;
498  	   SCIP_Real* consvals;
499  	   SCIP_READERDATA readerdata_copy;
500  	   char linebuffer[PBM_MAX_LINELEN];
501  	   const char* conshdlrname;
502  	   int* scaledimage;
503  	   int submatrixsize;
504  	   int nconsvars;
505  	   int linecnt;
506  	   int c;
507  	   int v;
508  	
509  	   assert(scip != NULL);
510  	   assert(readerdata != NULL);
511  	   assert(conss != NULL);
512  	
513  	   readerdata_copy = *readerdata;
514  	   submatrixsize = getSubmatrixSize(&readerdata_copy, nvars, nconss);
515  	   readerdata = &readerdata_copy;
516  	
517  	   SCIP_CALL( SCIPallocBufferArray(scip, &scaledimage, readerdata_copy.maxrows * readerdata_copy.maxcols) );
518  	   assert(scaledimage != NULL);
519  	   BMSclearMemoryArray(scaledimage, readerdata->maxrows * readerdata->maxcols);
520  	
521  	   /* print statistics as comment to file */
522  	   if( readerdata->binary )
523  	      SCIPinfoMessage(scip, file, "P4\n");
524  	   else
525  	      SCIPinfoMessage(scip, file, "P1\n");
526  	
527  	   SCIPinfoMessage(scip, file, "# %s\n", name);
528  	   SCIPinfoMessage(scip, file, "%d %d\n", readerdata->maxcols, readerdata->maxrows);
529  	
530  	   clearLine(linebuffer, &linecnt);
531  	
532  	   for( c = 0; c < nconss; ++c )
533  	   {
534  	      cons = conss[c];
535  	      assert(cons != NULL);
536  	
537  	      /* in case the transformed is written only constraint are posted which are enabled in the current node */
538  	      assert(!transformed || SCIPconsIsEnabled(cons));
539  	
540  	      conshdlr = SCIPconsGetHdlr(cons);
541  	      assert(conshdlr != NULL);
542  	
543  	      conshdlrname = SCIPconshdlrGetName(conshdlr);
544  	      assert(transformed == SCIPconsIsTransformed(cons));
545  	
546  	      if( strcmp(conshdlrname, "linear") == 0 )
547  	      {
548  	         consvars = SCIPgetVarsLinear(scip, cons);
549  	         nconsvars = SCIPgetNVarsLinear(scip, cons);
550  	         assert(consvars != NULL || nconsvars == 0);
551  	
552  	         if( nconsvars > 0 )
553  	         {
554  	            SCIP_CALL( printLinearCons(scip, readerdata, consvars, SCIPgetValsLinear(scip, cons),
555  	                  nconsvars, c, transformed, submatrixsize, scaledimage) );
556  	         }
557  	      }
558  	      else if( strcmp(conshdlrname, "setppc") == 0 )
559  	      {
560  	         consvars = SCIPgetVarsSetppc(scip, cons);
561  	         nconsvars = SCIPgetNVarsSetppc(scip, cons);
562  	         assert(consvars != NULL || nconsvars == 0);
563  	
564  	         if( nconsvars > 0 )
565  	         {
566  	            SCIP_CALL( printLinearCons(scip, readerdata, consvars, NULL,
567  	                  nconsvars, c, transformed, submatrixsize, scaledimage) );
568  	         }
569  	      }
570  	      else if( strcmp(conshdlrname, "logicor") == 0 )
571  	      {
572  	         consvars = SCIPgetVarsLogicor(scip, cons);
573  	         nconsvars = SCIPgetNVarsLogicor(scip, cons);
574  	         assert(consvars != NULL || nconsvars == 0);
575  	
576  	         if( nconsvars > 0 )
577  	         {
578  	            SCIP_CALL( printLinearCons(scip, readerdata, consvars, NULL,
579  	                  nconsvars, c, transformed, submatrixsize, scaledimage) );
580  	         }
581  	      }
582  	      else if( strcmp(conshdlrname, "knapsack") == 0 )
583  	      {
584  	         SCIP_Longint* weights;
585  	
586  	         consvars = SCIPgetVarsKnapsack(scip, cons);
587  	         nconsvars = SCIPgetNVarsKnapsack(scip, cons);
588  	         assert(consvars != NULL || nconsvars == 0);
589  	
590  	         /* copy Longint array to SCIP_Real array */
591  	         weights = SCIPgetWeightsKnapsack(scip, cons);
592  	         SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
593  	         for( v = 0; v < nconsvars; ++v )
594  	            consvals[v] = weights[v];
595  	
596  	         if( nconsvars > 0 )
597  	         {
598  	            SCIP_CALL( printLinearCons(scip, readerdata, consvars, consvals, nconsvars, c, transformed,
599  	                  submatrixsize, scaledimage) );
600  	         }
601  	
602  	         SCIPfreeBufferArray(scip, &consvals);
603  	      }
604  	      else if( strcmp(conshdlrname, "varbound") == 0 )
605  	      {
606  	         SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
607  	         SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
608  	
609  	         consvars[0] = SCIPgetVarVarbound(scip, cons);
610  	         consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
611  	
612  	         consvals[0] = 1.0;
613  	         consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
614  	
615  	         SCIP_CALL( printLinearCons(scip, readerdata, consvars, consvals, 2, c, transformed,
616  	               submatrixsize, scaledimage) );
617  	
618  	         SCIPfreeBufferArray(scip, &consvars);
619  	         SCIPfreeBufferArray(scip, &consvals);
620  	      }
621  	      else
622  	      {
623  	         SCIP_Bool success;
624  	
625  	         consvars = NULL;
626  	         SCIP_CALL( SCIPgetConsNVars(scip, cons, &nconsvars, &success) );
627  	
628  	         if( success )
629  	         {
630  	            SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
631  	
632  	            SCIP_CALL( SCIPgetConsVars(scip, cons, consvars, nconsvars, &success) );
633  	         }
634  	
635  	         if( success )
636  	         {
637  	            /* retransform given variables to active variables */
638  	            SCIP_CALL( getActiveVariables2(scip, consvars, &nconsvars, transformed) );
639  	
640  	            printRow(scip, readerdata, consvars, c, nconsvars, submatrixsize, scaledimage);
641  	         }
642  	         else
643  	         {
644  	            SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
645  	            SCIPinfoMessage(scip, file, "\\ ");
646  	            SCIP_CALL( SCIPprintCons(scip, cons, file) );
647  	         }
648  	
649  	         SCIPfreeBufferArrayNull(scip, &consvars);
650  	      }
651  	   }
652  	
653  	   drawScaledImage(scip, file, readerdata, scaledimage);
654  	
655  	   SCIPfreeBufferArray(scip, &scaledimage);
656  	
657  	   *result = SCIP_SUCCESS;
658  	
659  	   return SCIP_OKAY; /*lint !e438*/
660  	}
661