APPFS
Advanced practical programming for scientists
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
Data Structures | Macros | Enumerations | Functions | Variables
bip_enum.c File Reference

BIP Enumerator. More...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <stdbool.h>
#include <time.h>
#include <limits.h>
#include <math.h>
#include <errno.h>
#include <float.h>
#include <fenv.h>
#include "mshell.h"
#include "splitline.h"
#include "bip_enum.h"

Go to the source code of this file.

Data Structures

struct  binary_program
 

Macros

#define BIP_MAX_COLS   32
 
#define BIP_MAX_ROWS   32
 
#define MAX_LINE_LEN   512
 Maximum input line length. More...
 
#define GET_SEC(a, b)   ((b - a) / (double)CLOCKS_PER_SEC)
 

Enumerations

enum  LINE_MODE { READ_ERROR, READ_COLS, READ_ROWS, READ_COEF }
 
enum  Sense { LE = 0, GE = 1, EQ = 2 }
 

Functions

static bool bip_is_valid (const BIP *bip)
 Check whether BIP data structure is consistent. More...
 
void bip_init ()
 
void bip_free (BIP *bip)
 Deallocate BIP data structure. More...
 
static bool bip_can_overflow (const BIP *bip)
 
static LINE_MODE process_line (LINE_MODE mode, const LFS *lfs, const int lines, BIP *bip)
 
BIPbip_read (const char *filename)
 Read a bip file. More...
 
void bip_print (const BIP *bip, FILE *fp)
 Print Binary Program from BIP. More...
 
static void print_solu (FILE *fp, int vars, const double *x)
 Print solution vector. More...
 
static bool bip_is_feasible (const BIP *bip, const double *x)
 Check whether a particular vector is a feasible solution to a BIP. More...
 
int bip_enumerate (const BIP *bip, bool with_output)
 Enumerate all possible solution of a BIP. More...
 

Variables

static Numb max_coef_val
 
static Numb min_coef_val
 
static bool int_coef
 

Detailed Description

Author
Thorsten Koch
Date
20Nov2014

Definition in file bip_enum.c.

Macro Definition Documentation

#define BIP_MAX_COLS   32

Definition at line 37 of file bip_enum.c.

#define BIP_MAX_ROWS   32

Definition at line 38 of file bip_enum.c.

#define GET_SEC (   a,
 
)    ((b - a) / (double)CLOCKS_PER_SEC)

Definition at line 57 of file bip_enum.c.

#define MAX_LINE_LEN   512

Definition at line 55 of file bip_enum.c.

Enumeration Type Documentation

enum LINE_MODE
Enumerator
READ_ERROR 
READ_COLS 
READ_ROWS 
READ_COEF 

Definition at line 40 of file bip_enum.c.

enum Sense
Enumerator
LE 
GE 
EQ 

Definition at line 42 of file bip_enum.c.

42 { LE = 0, GE = 1, EQ = 2 } Sense;
Definition: bip_enum.c:42
Sense
Definition: bip_enum.c:42
Definition: bip_enum.c:42
Definition: bip_enum.c:42

Function Documentation

static bool bip_can_overflow ( const BIP bip)
static

Definition at line 142 of file bip_enum.c.

143 {
144  assert(bip_is_valid(bip));
145 
146  for(int r = 0; r < bip->rows; r++)
147  {
148  Numb row_max = 0;
149  Numb row_min = 0;
150 
151  for(int c = 0; c < bip->cols; c++)
152  {
153  Numb val = bip->a[r][c];
154 
155  if (val > 0)
156  {
157  if (row_max < max_coef_val - val)
158  row_max += val;
159  else
160  return fprintf(stderr, "Error: row %d numerical overflow\n", r), true;
161  }
162  else if (val < 0)
163  {
164  if (row_min > min_coef_val - val)
165  row_min += val;
166  else
167  return fprintf(stderr, "Error: row %d numerical negative overflow\n", r), true;
168  }
169  else
170  {
171  assert(val == 0);
172  }
173  }
174  }
175  return false;
176 }
int cols
number of columns (variables)
Definition: bip_enum.c:48
Numb a[BIP_MAX_ROWS][BIP_MAX_COLS]
coefficient matrix
Definition: bip_enum.c:49
static Numb max_coef_val
Definition: bip_enum.c:59
int rows
number of rows (constraints)
Definition: bip_enum.c:46
static Numb min_coef_val
Definition: bip_enum.c:60
static bool bip_is_valid(const BIP *bip)
Check whether BIP data structure is consistent.
Definition: bip_enum.c:66
int bip_enumerate ( const BIP bip,
bool  with_output 
)

Prints all solutions.

Returns
number of feasible solutions found.

Definition at line 439 of file bip_enum.c.

440 {
441  assert(bip_is_valid(bip));
442 
443  clock_t start = clock();
444  int solus = 0;
445  int count = 0;
446 
447  /* generate all permutation
448  */
449  for(unsigned long long bitvec = 0; bitvec < (1uL << bip->cols); bitvec++)
450  {
451  unsigned long long mask = 1; // long long because long is 32 bit on 32 bit computers
452  double x[BIP_MAX_COLS]; // having this always double is questionable
453 
454  assert(sizeof(bitvec) * 8 > BIP_MAX_COLS); //lint !e506
455 
456  /* construct solution vector
457  */
458  for(int j = 0; j < bip->cols; j++, mask <<= 1)
459  x[j] = (bitvec & mask) ? 1.0 : 0.0;
460 
461  if (bip_is_feasible(bip, &x[0])) //lint !e772
462  {
463  if (with_output)
464  print_solu(stdout, bip->cols, &x[0]);
465 
466  solus++;
467  }
468  count++;
469  }
470  assert((unsigned)count == (1u << bip->cols));
471 
472  double elapsed = GET_SEC(start, clock());
473 
474  printf("Checked %d vectors in %.3f s = %.3f kvecs/s\n",
475  count, elapsed, count / elapsed / 1000.0);
476 
477  return solus;
478 }
#define GET_SEC(a, b)
Definition: bip_enum.c:57
static void print_solu(FILE *fp, int vars, const double *x)
Print solution vector.
Definition: bip_enum.c:376
static bool bip_is_feasible(const BIP *bip, const double *x)
Check whether a particular vector is a feasible solution to a BIP.
Definition: bip_enum.c:394
int cols
number of columns (variables)
Definition: bip_enum.c:48
#define BIP_MAX_COLS
Definition: bip_enum.c:37
static bool bip_is_valid(const BIP *bip)
Check whether BIP data structure is consistent.
Definition: bip_enum.c:66
void bip_free ( BIP bip)

Definition at line 133 of file bip_enum.c.

134 {
135  assert(bip_is_valid(bip));
136 
137  mem_check(bip);
138 
139  free(bip);
140 }
#define mem_check(a)
Definition: mshell.h:71
static bool bip_is_valid(const BIP *bip)
Check whether BIP data structure is consistent.
Definition: bip_enum.c:66
#define free(a)
Definition: mshell.h:57
void bip_init ( void  )

Definition at line 91 of file bip_enum.c.

92 {
93 #if defined(USE_INT)
94 
95  max_coef_val = INT_MAX;
96  min_coef_val = INT_MIN;
97  int_coef = true;
98 
99 #elif defined(USE_LONGLONG)
100 
101  max_coef_val = LLONG_MAX;
102  min_coef_val = LLONG_MIN;
103  int_coef = true;
104 
105 #elif defined(USE_FLOAT)
106 
107  max_coef_val = powf(10, (float)FLT_DIG);
108  min_coef_val = -powf(10, (float)FLT_DIG);
109  int_coef = false;
110 
111 #elif defined(USE_DOUBLE)
112 
113  max_coef_val = pow(10, (double)DBL_DIG);
114  min_coef_val = -pow(10, (double)DBL_DIG);
115  int_coef = false;
116 
117 #elif defined(USE_LONGDOUBLE)
118 
119  max_coef_val = powl(10, (long double)LDBL_DIG);
120  min_coef_val = -powl(10, (long double)LDBL_DIG);
121  int_coef = false;
122 
123 #else
124 #error "No number type defined"
125 #endif
126 
127  // printf("Min/Max coefficient values [%.0Lf,%.0Lf]\n",
128  // (long double)min_coef_val, (long double)max_coef_val);
129 }
static bool int_coef
Definition: bip_enum.c:61
static Numb max_coef_val
Definition: bip_enum.c:59
static Numb min_coef_val
Definition: bip_enum.c:60
static bool bip_is_feasible ( const BIP bip,
const double *  x 
)
static
Returns
true if feasible, false otherwise.

Definition at line 394 of file bip_enum.c.

395 {
396  assert(bip_is_valid(bip));
397 
398  int r;
399 
400  for(r = 0; r < bip->rows; r++)
401  {
402  double lhs = 0.0;
403 
404  for(int c = 0; c < bip->cols; c++)
405  {
406  assert(x[c] == 0.0 || x[c] == 1.0);
407 
408  lhs += bip->a[r][c] * x[c];
409 
410  assert(fetestexcept(FE_ALL_EXCEPT & ~FE_INEXACT) == 0);
411  }
412 
413  switch(bip->sense[r])
414  {
415  case LE :
416  if (lhs <= bip->b[r])
417  continue;
418  break;
419  case GE :
420  if (lhs >= bip->b[r])
421  continue;
422  break;
423  case EQ :
424  if (lhs == bip->b[r])
425  continue;
426  break;
427  default :
428  abort();
429  }
430  break;
431  }
432  return r == bip->rows;
433 }
Definition: bip_enum.c:42
int cols
number of columns (variables)
Definition: bip_enum.c:48
Numb a[BIP_MAX_ROWS][BIP_MAX_COLS]
coefficient matrix
Definition: bip_enum.c:49
int rows
number of rows (constraints)
Definition: bip_enum.c:46
Definition: bip_enum.c:42
Numb b[BIP_MAX_ROWS]
right hand side
Definition: bip_enum.c:50
Definition: bip_enum.c:42
Sense sense[BIP_MAX_ROWS]
equation sense
Definition: bip_enum.c:51
static bool bip_is_valid(const BIP *bip)
Check whether BIP data structure is consistent.
Definition: bip_enum.c:66
static bool bip_is_valid ( const BIP bip)
static
Returns
true if ok, false otherwise.

Definition at line 66 of file bip_enum.c.

67 {
68  if (NULL == bip)
69  return false;
70 
71  if (max_coef_val <= min_coef_val) // bip_init not called.
72  return false;
73 
74  if (bip->rows < 1 || bip->rows > BIP_MAX_ROWS)
75  return false;
76  if (bip->cols < 1 || bip->cols > BIP_MAX_COLS)
77  return false;
78 
79  for(int r = 0; r < bip->rows; r++)
80  {
81  for(int c = 0; c < bip->cols; c++)
82  if (bip->a[r][c] < min_coef_val || bip->a[r][c] > max_coef_val) // can only happen with floating point Numb
83  return false;
84 
85  if (bip->b[r] < min_coef_val || bip->b[r] > max_coef_val) // can only happen with floating point Numb
86  return false;
87  }
88  return true;
89 }
int cols
number of columns (variables)
Definition: bip_enum.c:48
#define BIP_MAX_ROWS
Definition: bip_enum.c:38
Numb a[BIP_MAX_ROWS][BIP_MAX_COLS]
coefficient matrix
Definition: bip_enum.c:49
static Numb max_coef_val
Definition: bip_enum.c:59
int rows
number of rows (constraints)
Definition: bip_enum.c:46
#define BIP_MAX_COLS
Definition: bip_enum.c:37
Numb b[BIP_MAX_ROWS]
right hand side
Definition: bip_enum.c:50
static Numb min_coef_val
Definition: bip_enum.c:60
void bip_print ( const BIP bip,
FILE *  fp 
)

Definition at line 359 of file bip_enum.c.

360 {
361  const char* sense[3] = { "<=", ">=", "==" };
362 
363  assert(NULL != fp);
364  assert(bip_is_valid(bip));
365 
366  for(int r = 0; r < bip->rows; r++)
367  {
368  for(int c = 0; c < bip->cols; c++)
369  fprintf(fp, "%Lf ", (long double)bip->a[r][c]);
370  fprintf(fp, "%s %Lf\n", sense[bip->sense[r]], (long double)bip->b[r]);
371  }
372 }
int cols
number of columns (variables)
Definition: bip_enum.c:48
Numb a[BIP_MAX_ROWS][BIP_MAX_COLS]
coefficient matrix
Definition: bip_enum.c:49
int rows
number of rows (constraints)
Definition: bip_enum.c:46
Numb b[BIP_MAX_ROWS]
right hand side
Definition: bip_enum.c:50
Sense sense[BIP_MAX_ROWS]
equation sense
Definition: bip_enum.c:51
static bool bip_is_valid(const BIP *bip)
Check whether BIP data structure is consistent.
Definition: bip_enum.c:66
BIP* bip_read ( const char *  filename)

Format example:

4 # cols (variables) 3 # rows (constraints) 2 3 5 4 <= 8 3 6 0 8 <= 10 0 0 1 1 <= 1

comments (#) and empty lines are ignored.

Parameters
filenamename of file to read
Returns
ptr to BIP data structure

Definition at line 296 of file bip_enum.c.

297 {
298  assert(NULL != filename);
299  assert(0 < strlen(filename));
300 
301  char buf[MAX_LINE_LEN];
302  char* s;
303  FILE* fp;
304  BIP* bip = calloc(1, sizeof(*bip));
305  LFS* lfs = NULL;
306  int lines = 0;
307  LINE_MODE mode = READ_COLS;
308 
309  if (NULL == (fp = fopen(filename, "r")))
310  {
311  fprintf(stderr, "Can't open file %s\n", filename);
312  free(bip);
313  return NULL;
314  }
315  printf("Reading %s\n", filename);
316 
317  while(mode != READ_ERROR && NULL != (s = fgets(buf, sizeof(buf), fp)))
318  {
319  lines++;
320 
321  lfs = lfs_split_line(lfs, s, "#");
322  mode = process_line(mode, lfs, lines, bip);
323  }
324  fclose(fp);
325 
326  if (NULL != lfs)
327  lfs_free(lfs);
328 
329  if (READ_ERROR == mode)
330  {
331  free(bip);
332 
333  return NULL;
334  }
335  if (bip->cols == 0 || bip->max_rows == 0 || bip->rows < bip->max_rows)
336  {
337  fprintf(stderr, "Error: unexpected EOF\n");
338  free(bip);
339  return NULL;
340  }
341 
342  assert(bip->rows == bip->max_rows);
343 
344  assert(bip_is_valid(bip));
345 
346  printf("Read %d rows, %d cols\n", bip->rows, bip->cols);
347 
348  if (bip_can_overflow(bip))
349  {
350  bip_free(bip);
351 
352  return NULL;
353  }
354  return bip;
355 }
#define MAX_LINE_LEN
Maximum input line length.
Definition: bip_enum.c:55
int max_rows
maximum number of rows
Definition: bip_enum.c:47
int cols
number of columns (variables)
Definition: bip_enum.c:48
void bip_free(BIP *bip)
Deallocate BIP data structure.
Definition: bip_enum.c:133
static LINE_MODE process_line(LINE_MODE mode, const LFS *lfs, const int lines, BIP *bip)
Definition: bip_enum.c:179
void lfs_free(LFS *lfs)
Definition: splitline.c:35
static bool bip_can_overflow(const BIP *bip)
Definition: bip_enum.c:142
int rows
number of rows (constraints)
Definition: bip_enum.c:46
LINE_MODE
Definition: bip_enum.c:40
#define calloc(a, b)
Definition: mshell.h:54
LFS * lfs_split_line(LFS *lfs, const char *line, const char *comment)
Definition: splitline.c:44
static bool bip_is_valid(const BIP *bip)
Check whether BIP data structure is consistent.
Definition: bip_enum.c:66
#define free(a)
Definition: mshell.h:57
static void print_solu ( FILE *  fp,
int  vars,
const double *  x 
)
static
Parameters
fpfile pointer to output to
varsnumber of variables
xptr to solution vector

Definition at line 376 of file bip_enum.c.

380 {
381  assert(NULL != fp);
382  assert(vars >= 0);
383  assert(vars < BIP_MAX_COLS);
384  assert(NULL != x);
385 
386  for(int r = 0; r < vars; r++)
387  fprintf(fp, "%2g ", x[r]);
388  fputc('\n', fp);
389 }
#define BIP_MAX_COLS
Definition: bip_enum.c:37
static LINE_MODE process_line ( LINE_MODE  mode,
const LFS lfs,
const int  lines,
BIP bip 
)
static

Definition at line 179 of file bip_enum.c.

180 {
181  /* If line is not empty
182  */
183  if (lfs_used_fields(lfs) > 0)
184  {
185  long double val;
186  char* t;
187 
188  /* do processing here:
189  * mode tells which kind of line is next.
190  */
191  switch(mode)
192  {
193  case READ_COLS :
194  if (lfs_used_fields(lfs) != 1)
195  return fprintf(stderr, "Error line %d: Got %d fields, expected 1\n",
196  lines, lfs_used_fields(lfs)),
197  READ_ERROR;
198 
199  val = strtold(lfs_get_field(lfs, 0), &t);
200 
201  if (errno == ERANGE || isnan(val) || isinf(val) || rintl(val) != val || val < 1.0 || val > (long double)BIP_MAX_COLS || *t != '\0')
202  return fprintf(stderr, "Error line=%d Number of cols %s=%Lf out of range or not integer %s\n",
203  lines, lfs_get_field(lfs, 0), val, errno ? strerror(errno) : ""),
204  READ_ERROR;
205 
206  bip->cols = (int)val;
207  mode = READ_ROWS;
208  break;
209  case READ_ROWS :
210  if (lfs_used_fields(lfs) != 1)
211  return fprintf(stderr, "Error line %d: Got %d fields, expected 1\n",
212  lines, lfs_used_fields(lfs)),
213  READ_ERROR;
214 
215  val = strtold(lfs_get_field(lfs, 0), &t);
216 
217  if (errno == ERANGE || isnan(val) || isinf(val) || rintl(val) != val || val < 1.0 || val > (long double)BIP_MAX_ROWS || *t != '\0')
218  return fprintf(stderr, "Error line=%d Number of rows %s=%Lf out of range or not integer %s\n",
219  lines, lfs_get_field(lfs, 0), val, errno ? strerror(errno) : ""),
220  READ_ERROR;
221 
222  bip->max_rows = (int)val;
223  mode = READ_COEF;
224  break;
225  case READ_COEF :
226  if (bip->rows >= bip->max_rows)
227  return fprintf(stderr, "Error line=%d Expetced %d rows, got more\n",
228  lines, bip->max_rows),
229  READ_ERROR;
230 
231  if (lfs_used_fields(lfs) != bip->cols + 2)
232  return fprintf(stderr, "Error line %d: Got %d fields, expected %d\n",
233  lines, lfs_used_fields(lfs), bip->cols + 2),
234  READ_ERROR;
235 
236  for(int col = 0; col < bip->cols + 2; col++)
237  {
238  if (col != bip->cols)
239  {
240  val = strtold(lfs_get_field(lfs, col), &t);
241 
242  if (errno == ERANGE || isnan(val) || isinf(val)
243  || (int_coef && rintl(val) != val)
244  || val > (long double)max_coef_val
245  || val < (long double)min_coef_val
246  || *t != '\0')
247  return fprintf(stderr, "Error line=%d Number %s=%Lf out of range %s: %s\n",
248  lines, lfs_get_field(lfs, col), val, int_coef ? "or not integer" : "", errno ? strerror(errno) : ""),
249  READ_ERROR;
250 
251  if (col < bip->cols)
252  bip->a[bip->rows][col] = (Numb)val;
253  else
254  bip->b[bip->rows] = (Numb)val;
255  }
256  else
257  {
258  const char* sense = lfs_get_field(lfs, bip->cols);
259 
260  if (!strcmp(sense, "<="))
261  bip->sense[bip->rows] = LE;
262  else if (!strcmp(sense, ">="))
263  bip->sense[bip->rows] = GE;
264  else if (!strcmp(sense, "=") || !strcmp(sense, "=="))
265  bip->sense[bip->rows] = EQ;
266  else
267  return fprintf(stderr, "Error line=%d Expected <=, >=, ==, got \"%s\"\n",
268  lines, sense),
269  READ_ERROR;
270  }
271  }
272  bip->rows++;
273  break;
274  default :
275  abort();
276  }
277  }
278  return mode;
279 }
Definition: bip_enum.c:42
static bool int_coef
Definition: bip_enum.c:61
int max_rows
maximum number of rows
Definition: bip_enum.c:47
int cols
number of columns (variables)
Definition: bip_enum.c:48
#define BIP_MAX_ROWS
Definition: bip_enum.c:38
Numb a[BIP_MAX_ROWS][BIP_MAX_COLS]
coefficient matrix
Definition: bip_enum.c:49
const char * lfs_get_field(const LFS *lfs, int fno)
Definition: splitline.c:116
static Numb max_coef_val
Definition: bip_enum.c:59
int rows
number of rows (constraints)
Definition: bip_enum.c:46
Definition: bip_enum.c:42
#define BIP_MAX_COLS
Definition: bip_enum.c:37
Numb b[BIP_MAX_ROWS]
right hand side
Definition: bip_enum.c:50
int lfs_used_fields(const LFS *lfs)
Definition: splitline.c:109
Definition: bip_enum.c:42
static Numb min_coef_val
Definition: bip_enum.c:60
Sense sense[BIP_MAX_ROWS]
equation sense
Definition: bip_enum.c:51

Variable Documentation

bool int_coef
static

Definition at line 61 of file bip_enum.c.

Numb max_coef_val
static

Definition at line 59 of file bip_enum.c.

Numb min_coef_val
static

Definition at line 60 of file bip_enum.c.