#include "spnbox.h"
#include "../third-party/lp_solve_5.5/lp_lib.h"
#include <stdlib.h>
#include <stdio.h>

ipslv_r ipslv(REAL* f, REAL** L, REAL* b, int m, int n, int* intlist, REAL* ub, REAL* lb, int* ctype) {

  /* This is the interface of ip_solve to LPSOLVE. 

     m: the number of rows of L; n: the number of columns of L; See ip_solve
     for the meaning of the remaining parameters.

     The function compares upper and lower bounds to +INF and -INF in order to
     determine whether the bounds are infinite.
  */

  ipslv_r out;

  lprec* lp;
  int i, j;
  REAL *tf, inf, r;

  //Trej = 1e-4; /* default value in lp_solve.c */

  lp = make_lp(0, n);
  set_verbose(lp, 0);
  set_minim(lp);

  tf  = (REAL*) calloc(n+1, sizeof(REAL));
  for (i=0; i < n; i++)
    tf[i+1] = f[i];
  set_obj_fn(lp, tf);

  for (i=0; i < m; i++) {
    for(j = 0; j < n; j++)
      tf[j+1] = L[i][j];
    if (ctype[i] < 0)
      add_constraint(lp, tf, LE, b[i]);
    else if (ctype[i] == 0)
      add_constraint(lp, tf, EQ, b[i]);
    else
      add_constraint(lp, tf, GE, b[i]);
  }

  for (j = 0; j < n; j++) {
    r = lb[j];
    if(r <= -INF)
      set_lowbo(lp, j+1, -INF);
    else if(r >= INF)
      set_lowbo(lp, j+1, INF);
    else
      set_lowbo(lp, j+1, lb[j]);

    r = ub[j];
    if(r <= -INF)
      set_upbo(lp, j+1, -INF);
    else if(r >= INF)
      set_upbo(lp, j+1, INF);
    else
      set_upbo(lp, j+1, ub[j]);

    if(intlist[j])
      set_int(lp, j+1, TRUE);
  }
  /* lp->debug = TRUE;  
     lp->trace = TRUE;*/

  //print_lp(lp); 

  set_infinite(lp, INF);
  out.kind = solve(lp); 

  out.solution = (REAL*) calloc(n, sizeof(*(out.solution)));
  for(i = 0; i < lp->columns; i++) {
    r = lp->best_solution[lp->rows + i + 1];
    out.solution[i] = r;
    if(!out.kind) {
      if(r >= INF || r <= -INF)
	out.kind = 3; /* UNBOUNDED */
    }
  }

  delete_lp(lp);

  free(tf);

  return out;
}
