My Project
MILP_Model.h
1 #ifndef MILP_MODEL_H
2 #define MILP_MODEL_H
3 
4 #include <algorithm>
5 #include <cassert>
6 #include <fstream>
7 #include <map>
8 #include <sstream>
9 #include <string>
10 #include <utility>
11 #include <vector>
12 #include <string.h>
13 #include <unistd.h>
14 #include <regex>
15 
16 using namespace std;
17 
27 {
28 public:
29 
30  enum VarType {REAL, INTEGER, BOOLEAN};
31  enum RowType {LEQ, GEQ, EQ};
32  enum Status {OPTIMAL, NONOPTIMAL, UNFEASIBLE, UNBOUNDED, UNKNOWN, ERROR};
33 
34  //SHAB_q: I don't understand what 'Term' means.
35  //SHAB_ans: the pair literally mean: coefficient * vecVars[var index]. like 2a, 3x, etc.
36  using Term = pair<double, int>;
37  using vecTerms = vector<Term>;
38  using vecVars = vector<int>;
39 
43  Milp_Model(const string& solver="") {
44  init(solver);
45  }
46 
50  const string& getError() const {
51  return errorMsg;
52  }
53 
58  void setError(const string& err = "") {
59  errorMsg = err;
60  }
61 
65  void setMinimize() {
66  MinMax = true;
67  }
68 
72  void setMaximize() {
73  MinMax = false;
74  }
75 
80  void setEpsilon(double eps) {
81  epsilon = eps;
82  }
83 
87  int numVariables() const {
88  return Vars.size();
89  }
90 
91  int numConstraints() const {
92  return Matrix.size();
93  }
94 
102  int newRealVar(string name="",
103  double lower_bound = 0.0,
104  double upper_bound = -1.0) {
105  return newVar(name, REAL, lower_bound, upper_bound);
106  }
107 
115  int newIntegerVar(string name="",
116  double lower_bound = 0,
117  double upper_bound = -1) {
118  return newVar(name, INTEGER, lower_bound, upper_bound);
119  }
120 
126  int newBooleanVar(string name="") {
127  return newVar(name, BOOLEAN, 0, 1);
128  }
129 
133  Status getStatus() const {
134  return stat;
135  }
136 
140  double getObj() const {
141  return obj;
142  }
143 
149  double operator[](int i) const {
150  assert (i >= 0 and i < Vars.size());
151  return Vars[i].value;
152  }
153 
159  double operator[](const string& name) const {
160  assert (Name2Var.count(name) > 0);
161  return Vars[Name2Var.at(name)].value;
162  }
163 
169  bool isTrue(int i) const {
170  assert (i >= 0 and i < Vars.size() and Vars[i].type == BOOLEAN);
171  return Vars[i].value > 0.5;
172  }
173 
179  bool isFalse(int i) const {
180  return not isTrue(i);
181  }
182 
190  int newRow(char type = '<', double rhs = 0.0, const string& name = "") {
191  RowType t;
192  if (type == '<') t = LEQ;
193  else if (type == '>') t = GEQ;
194  else if (type == '=') t = EQ;
195  else assert(false);
196  Matrix.push_back(Row {name, t, rhs});
197  return Matrix.size() - 1;
198  }
199 
208  int newRow(const vecTerms& terms, char type = '<', double rhs = 0.0, const string& name = "") {
209  int r = newRow(type, rhs, name);
210  for (auto t: terms) newTerm(r, t.first, t.second);
211  return r;
212  }
213 
220  void newTerm(int rowIndex, double coeff, int varIndex) {
221  assert (rowIndex >= 0);
222  assert (rowIndex < Matrix.size());
223  assert (varIndex >= 0);
224  assert (varIndex < Vars.size());
225  assert (rowIndex >= 0 and rowIndex < Matrix.size() and
226  varIndex >= 0 and varIndex < Vars.size());
227  Matrix[rowIndex].vecRow.push_back( {coeff, varIndex});
228  }
229 
235  void setRHS(int rowIndex, double rhs) {
236  assert (rowIndex >= 0 and rowIndex < Matrix.size());
237  Matrix[rowIndex].rhs = rhs;
238  }
239 
246  int atMostOne(const vecVars& vars, const string& name="") {
247  int r = newRow('<', 1.0, name);
248  for (int v: vars) newTerm(r, 1.0, v);
249  return r;
250  }
251 
258  int atLeastOne(const vecVars& vars, const string& name="") {
259  int r = newRow('>', 1.0, name);
260  for (int v: vars) newTerm(r, 1.0, v);
261  return r;
262  }
263 
270  int exactlyOne(const vecVars& vars, const string& name="") {
271  int r = newRow('=', 1.0, name);
272  for (int v: vars) newTerm(r, 1.0, v);
273  return r;
274  }
275 
285  int equalSum(const vecVars& x, const vecVars& y, const string& name="") {
286  int r = newRow('=', 0.0, name);
287  for (int v: x) newTerm(r, 1.0, v);
288  for (int v: y) newTerm(r, -1.0, v);
289  return r;
290  }
291 
299  int allEqual(const vecVars& v) {
300  assert (v.size() > 1);
301  int row = newRow( {{1, v[0]}, {-1, v[1]}}, '=');
302  for (unsigned int i = 2; i < v.size(); ++i) newRow( {{1, v[0]}, {-1, v[i]}}, '=');
303  return row;
304  }
305 
313  int implies(int x, const vecVars& y) {
314  int r = newRow('>', 0.0);
315  newTerm(r, -1.0, x);
316  for (int v: y) newTerm(r, 1.0, v);
317  return r;
318  }
319 
327  int implies(const vecVars& x, int y) {
328  int first = -1;
329  for (int v: x) {
330  int r = newRow('>', 0.0);
331  if (first < 0) first = r;
332  newTerm(r, -1.0, v);
333  newTerm(r, 1.0, y);
334  }
335  return first;
336  }
337 
338 
344  void newCostTerm(double coeff, int varIndex) {
345  assert (varIndex >= 0 and varIndex < Vars.size());
346  Cost.push_back( {coeff, varIndex});
347  }
348 
354  bool writeLP(const string& filename) {
355  ofstream f;
356  f.open(filename);
357  if (not f.is_open()) {
358  setError("Could not open file " + filename + ".");
359  return false;
360  }
361  writeLP(f);
362  f.close();
363  return true;
364  }
365 
371  bool solve(int timelimit = -1) {
372 
373  if (solver != "cbc" and solver != "glpsol" and solver != "gurobi_cl") { //Carmine 25.02.22 gurobi_cl included as MILP solver
374  setError("Unkonwn solver " + solver + ".");
375  return false;
376  }
377 
378  string exec = "which " + solver + " >/dev/null 2>&1";
379  if (system(exec.c_str())) {
380  setError("Solver " + solver + " is not available.");
381  return false;
382  }
383 
384  // The solver seems to be working. Let us solve the MILP model.
385  string lpfile = createTempFilename("MILP_lpmodel", ".lp");
386  string outfile;
387  if(solver == "gurobi_cl") //Carmine 25.02.22 gurobi_cl accepts solution in sol format
388  outfile = createTempFilename("MILP_solution", ".sol");
389  else
390  outfile = createTempFilename("MILP_solution", ".gsol");
391  string command = writeCommand(solver, lpfile, outfile, timelimit) + " >/dev/null 2>&1";
392  writeLP(lpfile);
393 
394  int status = system(command.c_str());
395 
396  if (status != 0) {
397  deleteTempFilename(outfile);
398  setError("Error when executing " + solver + ".");
399  return false;
400  }
401  bool opt_status; //Carmine 25.02.22 Important to check if the status optimization is OPTIMAL or SUBOPTIMAL
402  if (solver == "cbc") opt_status = readCbcSolution(outfile);
403  else if (solver == "glpsol") opt_status = readGlpsolSolution(outfile);
404  else if (solver == "gurobi_cl") opt_status = readGurobiSolution(outfile); //Carmine 25.02.22 gurobi_cl included as MILP solver
405  else assert(false);
406 
407  if(!opt_status)
408  cout << "*ERROR* MILP solution is UNFEASIBLE or UNBOUNDED" << endl;
409 
410  //deleteTempFilename(lpfile);
411  //deleteTempFilename(outfile);
412  return true;
413  }
414 
420  bool init(const string& solver = "") {
421  MinMax=true;
422  epsilon=10e-10;
423  numRealVars=numIntegerVars=numBooleanVars=0;
424  numEmptyRows = 0;
425  numUsedVars = 0;
426  stat=UNKNOWN;
427  errorMsg = "";
428  Cost.clear();
429  Vars.clear();
430  Matrix.clear();
431  Name2Var.clear();
432  Name2delays.clear();
433  return find_solver(solver);
434  }
435 
440  void writeOutDelays(const string& file_name) {
441  ofstream file;
442  file.open(file_name);
443  for (auto const& values: Name2delays){
444  file << values.second << " " << Vars[values.first].value << endl;
445  }
446  file.close();
447 
448  file.open("tmp_delays.txt");
449  int i, ord = Vars.size();
450  for (i = 0; i< ord; i++){
451  file << Vars[i].name << " " << Vars[i].value << endl;
452  }
453  file.close();
454  }
455 
460  string getVarName(int id) {
461  return Vars[id].name;
462  }
463 
464 private:
465 
466  struct Var {
467  string name;
468  VarType type;
469  double lower_bound;
470  double upper_bound; // unbounded if upper_bound < lower_bound
471  double value;
472  };
473 
474  struct Row {
475  string name;
476  RowType type;
477  double rhs;
478  vecTerms vecRow;
479  };
480 
481  string solver;
482  bool MinMax;
483  vecTerms Cost;
484  vector<Var> Vars;
485  vector<Row> Matrix;
486  int numEmptyRows;
487  vector<int>appearanceOrder;
488  vector<bool>appeared;
489  int numUsedVars;
490  double epsilon;
491  int numRealVars;
492  int numIntegerVars;
493  int numBooleanVars;
494  map<string, int> Name2Var;
495  Status stat;
496  double obj;
497  string errorMsg;
498 
499  map<int, string> Name2delays; //Carmine 07.02.2022 map containing the output delay of the blocks
500 
501  bool find_solver(const string& s) {
502 
503  if (not s.empty() and s != "cbc" and s != "glpsol" and s != "gurobi_cl") { //Carmine 25.02.22 gurobi_cl included as MILP solver
504  setError("Unkonwn solver " + solver + ".");
505  return false;
506  }
507 
508  // First try cbc
509  if (s.empty() or s == "cbc") {
510  string exec = "which cbc >/dev/null 2>&1";
511  if (system(exec.c_str()) == 0) {
512  solver = "cbc";
513  return true;
514  }
515 
516  if (s == "cbc") {
517  setError("MILP solver cbc not found.");
518  return false;
519  }
520  }
521 
522  // Next try glpsol
523  if (s.empty() or s == "glpsol") {
524  string exec = "which glpsol >/dev/null 2>&1";
525  if (system(exec.c_str()) == 0) {
526  solver = "glpsol";
527  return true;
528  }
529 
530  if (s == "glpsol") {
531  setError("MILP solver glpsol not found.");
532  return false;
533  }
534  }
535 
536  // Next try gurobi_cl
537  if (s.empty() or s == "gurobi_cl") { //Carmine 25.02.22 gurobi_cl included as MILP solver
538  string exec = "which gurobi_cl >/dev/null 2>&1";
539  if (system(exec.c_str()) == 0) {
540  solver = "gurobi_cl";
541  return true;
542  }
543 
544  if (s == "gurobi_cl") {
545  setError("MILP solver gurobi_cl not found.");
546  return false;
547  }
548  }
549 
550  // No more solvers for the moment
551  setError("No MILP solver found.");
552  return false;
553  }
554 
563  int newVar(const string& name, VarType type, double lower_bound, double upper_bound) {
564  string n = name.empty() ? "x" + to_string(Vars.size()) : name;
565  if (Name2Var.count(n) > 0) {
566  setError("Variable " + n + " multiply defined.");
567  return -1;
568  }
569  Name2Var[n] = Vars.size();
570  Vars.push_back(Var {n, type, lower_bound, upper_bound, 0});
571  if (type == REAL) numRealVars++;
572  else if (type == INTEGER) numIntegerVars++;
573  else numBooleanVars++;
574  return Vars.size() - 1;
575  }
576 
583  int newOutDelay(int ind, string output) {
584  if (Name2delays.count(ind) > 0)
585  return 0;
586  Name2delays[ind] = output;
587  return 1;
588  }
589 
594  void normalize() {
595  normalizeRow(Cost);
596  for (Row& r: Matrix) normalizeRow(r.vecRow);
597  }
598 
604  void normalizeRow(vecTerms& r) {
605  // Sorts the terms by variable index
606  sort(r.begin(), r.end(), [](Term& t1, Term& t2) {
607  return t1.second < t2.second;
608  });
609 
610  // Now check consecutive terms and accumulate coefficients
611  int i = 0;
612  int last = r.size();
613  while (i < last - 1) {
614  int var = r[i].second;
615  unsigned int k = i + 1;
616  while (k < last and r[k].second == var) {
617  r[i].first += r[k].first;
618  r[k].first = 0;
619  ++k;
620  }
621  i = k;
622  }
623 
624  // Now remove the terms with zero coefficient
625  unsigned int k = 0; // to point at the first available slot
626  for (i = 0; i < last; ++i) {
627  if (abs(r[i].first) >= epsilon) r[k++] = r[i];
628  }
629  r.resize(k);
630  }
631 
637  void writeTerms(ofstream& f, const vecTerms& terms) {
638  assert (terms.size() > 0);
639  double coeff = terms[0].first;
640  if (abs(coeff) != 1.0) f << coeff << ' ';
641  else if (coeff < 0) f << '-';
642  int idx = terms[0].second;
643  f << Vars[idx].name;
644  if (not appeared[idx]) {
645  appearanceOrder.push_back(idx);
646  appeared[idx] = true;
647  regex regexp ("timePath_(.)+_out[0-9]+"); //Carmine 07.02.2022 Extracting timing output pins indexes
648  if (regex_search(Vars[idx].name, regexp)){
649  newOutDelay(idx, Vars[idx].name);
650  }
651  }
652 
653  for (unsigned int i = 1; i < terms.size(); ++i) {
654  coeff = terms[i].first;
655  f << ' ' << (coeff < 0 ? '-' : '+') << ' ';
656  if (abs(coeff) != 1) f << abs(coeff) << ' ';
657  idx = terms[i].second;
658  f << Vars[idx].name;
659  if (not appeared[idx]) {
660  appearanceOrder.push_back(idx);
661  appeared[idx] = true;
662  regex regexp ("timePath_(.)+_out[0-9]+"); //Carmine 07.02.2022 Extracting timing output pins indexes
663  if (regex_search(Vars[idx].name, regexp)){
664  newOutDelay(idx, Vars[idx].name);
665  }
666  }
667  }
668  }
669 
675  void writeRow(ofstream& f, const Row& r) {
676  if (r.vecRow.empty()) {
677  ++numEmptyRows;
678  return;
679  }
680  f << " ";
681  if (not r.name.empty()) f << r.name << ": ";
682  writeTerms(f, r.vecRow);
683  if (r.type == EQ) f << " = ";
684  else if (r.type == GEQ) f << " >= ";
685  else f << " <= ";
686  f << r.rhs << endl;
687  }
688 
693  void writeLP(ofstream& f) {
694  normalize();
695  appearanceOrder.clear();
696  appeared = vector<bool>(Vars.size(), false);
697 
698  // Cost function: if no cost, create a fake cost function
699  if (Cost.empty()) newCostTerm(0, 0);
700 
701  // Cost function
702  f << (MinMax ? "Minimize" : "Maximize") << endl;
703  f << " ";
704  writeTerms(f, Cost);
705  f << endl;
706 
707  f << "Subject to" << endl;
708  for (const Row& r: Matrix) writeRow(f, r);
709 
710  numUsedVars = 0;
711  for (bool b: appeared) if (b) ++numUsedVars;
712 
713  bool need_bounds = false;
714  for (const Var& v: Vars) {
715  if (v.type != BOOLEAN and v.lower_bound <= v.upper_bound) {
716  need_bounds = true;
717  break;
718  }
719  }
720 
721  if (need_bounds) {
722  f << "Bounds" << endl;
723  for (const Var& v: Vars) {
724  if (v.type != BOOLEAN and v.lower_bound <= v.upper_bound) {
725  f << " " << v.lower_bound << " <= " << v.name << " <= " << v.upper_bound << endl;
726  }
727  }
728  }
729 
730  if (numIntegerVars > 0) {
731  f << "General" << endl << ' ';
732  for (const Var& v: Vars) {
733  if (v.type == INTEGER) f << ' ' << v.name;
734  }
735  f << endl;
736  }
737 
738  if (numBooleanVars > 0) {
739  f << "Binary" << endl << ' ';
740  for (const Var& v: Vars) {
741  if (v.type == BOOLEAN) f << ' ' << v.name;
742  }
743  f << endl;
744  }
745 
746  f << "End" << endl;
747  }
748 
755  static int readLine(ifstream& f, vector<string>& items) {
756  string line;
757  getline(f, line);
758  istringstream myStream(line);
759  items.clear();
760  string s;
761  while (myStream >> s) items.push_back(s);
762  return items.size();
763  }
764 
770  bool readCbcSolution(const string& filename) {
771  ifstream f;
772  f.open(filename);
773  if (not f.is_open()) return false;
774 
775  vector<string> values;
776  int nv = readLine(f, values);
777  assert(nv == 2);
778 
779  int nrows = stoi(values[0]);
780  int ncols = stoi(values[1]);
781 
782  assert (nrows == Matrix.size() - numEmptyRows + 1);
783  assert (ncols == numUsedVars);
784 
785  // This is a tricky function that has to deal with the
786  // fact that cbc sometimes puts three values per line
787  // and sometimes only one (possibly when MILP model).
788  nv = readLine(f, values);
789 
790  int st = stoi(values[0]);
791  switch (st) {
792  case 1:
793  stat = UNBOUNDED;
794  break;
795  case 2:
796  stat = NONOPTIMAL;
797  break;
798  case 4:
799  stat = UNFEASIBLE;
800  break;
801  case 5:
802  stat = OPTIMAL;
803  break;
804  default:
805  assert(false);
806  }
807 
808  if (stat != OPTIMAL and stat != NONOPTIMAL) {
809  f.close();
810  return false; //Carmine 25.02.22 if it is unfeasible or unbounded it should stop dynamatic execution
811  }
812 
813  obj = stod(values.back());
814  if (not MinMax) obj = -obj;
815 
816  // Skip the value of the rows
817  for (unsigned int i = 0; i < nrows; ++i) readLine(f, values);
818 
819  // Read the variables
820  for (unsigned int i = 0; i < ncols; ++i) {
821  nv = readLine(f, values);
822  int loc = nv > 1 ? 1 : 0;
823  Vars[appearanceOrder[i]].value = stod(values[loc]);
824  }
825 
826  f.close();
827  return true;
828  }
829 
835  bool readGlpsolSolution(const string& filename) {
836  ifstream f;
837  f.open(filename);
838  if (not f.is_open()) return false;
839 
840  bool cost_read = false;
841  vector<string> line;
842 
843  while (readLine(f, line) > 0) {
844  char c = line[0][0];
845  if (c != 's' and c != 'j') {
846  // Skip line
847  continue;
848  } else if (c == 'j') {
849  // Now we can read the value of a variable
850  int nvar = stoi(line[1]);
851  int loc = line.size() == 3 ? 2 : 3;
852  Vars[appearanceOrder[nvar-1]].value = stod(line[loc]);
853  } else { // c == 's'
854  assert (not cost_read);
855  cost_read = true;
856  // Read the cost function
857  int nrows = stoi(line[2]);
858  int ncols = stoi(line[3]);
859  char st = line[4][0];
860  obj = stod(line.back());
861 
862  assert (nrows == Matrix.size() - numEmptyRows);
863  assert (ncols == numUsedVars);
864 
865  switch (st) {
866  case 'u':
867  stat = UNBOUNDED;
868  break;
869  case 'f':
870  stat = NONOPTIMAL;
871  break;
872  case 'n':
873  stat = UNFEASIBLE;
874  break;
875  case 'o':
876  stat = OPTIMAL;
877  break;
878  default:
879  assert(false);
880  }
881  }
882  }
883 
884  f.close();
885  return true;
886  }
887 
893  bool readGurobiSolution(const string& filename) {
894  ifstream f;
895  f.open(filename);
896  if (not f.is_open()) return false;
897 
898  vector<string> values;
899  readLine(f, values); // first line only tells the optimization function cost of the solution
900 
901  string line;
902  int numVars = 0;
903  while(getline(f, line)){
904  istringstream myStream(line);
905  values.clear();
906  string s;
907  while (myStream >> s) values.push_back(s);
908  Vars[Name2Var[values[0]]].value = stod(values[1]);
909  numVars++;
910  }
911 
912  //assert (numVars == numUsedVars);
913 
914  //TODO: check the optimization status of gurobi
915  stat = OPTIMAL;
916 
917  f.close();
918  return true;
919  }
920 
929  string writeCommand(const string& solver, const string& lpfile, const string& solfile,
930  int timeout = -1) {
931  ostringstream command;
932  command << solver << ' ';
933  if (solver == "cbc") {
934  command << lpfile;
935  if (timeout > 0) command << " sec " << timeout;
936  command << " solve gsolution " << solfile;
937  } else if (solver == "glpsol") {
938  command << " --lp " << lpfile;
939  if (timeout > 0) command << " --tmlim " << timeout;
940  command << " -w " << solfile;
941  } else if (solver == "gurobi_cl") { //Carmine 25.02.22 gurobi_cl included as MILP solver
942  if (timeout > 0) command << " TimeLimit=" << timeout;
943  command << " ResultFile=" << solfile;
944  command << " " << lpfile;
945  } else {
946  assert(false);
947  }
948  return command.str();
949  }
950 
958  static std::string createTempFilename(const std::string& prefix, const std::string& suffix = "") {
959  char fname[1000];
960  strcat(strcpy(fname, prefix.c_str()), ".XXXXXX");
961  if (not suffix.empty()) strcat(fname, suffix.c_str());
962  int file = mkstemps(fname, suffix.size());
963  if (file == -1) return "";
964  return fname;
965  }
966 
971  static void deleteTempFilename(const std::string& filename) {
972  unlink(filename.c_str());
973  }
974 };
975 #endif // MILP_INTERFACE_H
vector< int > vecVars
Vector of terms.
Definition: MILP_Model.h:38
int atMostOne(const vecVars &vars, const string &name="")
Creates an at-most-one constraint (v1+...+vn <= 1).
Definition: MILP_Model.h:246
double operator[](int i) const
Returns the value of a variable.
Definition: MILP_Model.h:149
int exactlyOne(const vecVars &vars, const string &name="")
Creates an exactly-one constraint (v1+...+vn = 1).
Definition: MILP_Model.h:270
pair< double, int > Term
Type of solution.
Definition: MILP_Model.h:36
int numVariables() const
Definition: MILP_Model.h:87
double operator[](const string &name) const
Returns the value of a variable.
Definition: MILP_Model.h:159
void newTerm(int rowIndex, double coeff, int varIndex)
Adds a new term to a constraint.
Definition: MILP_Model.h:220
string getVarName(int id)
Get variables names.
Definition: MILP_Model.h:460
void setRHS(int rowIndex, double rhs)
Defines the RHS of a constraint.
Definition: MILP_Model.h:235
void setMinimize()
Defines a model to minimize the cost function.
Definition: MILP_Model.h:65
bool init(const string &solver="")
Initializes the MILP model.
Definition: MILP_Model.h:420
Status getStatus() const
Definition: MILP_Model.h:133
void setError(const string &err="")
Defines the error message of the object (no error by default).
Definition: MILP_Model.h:58
void setMaximize()
Defines a model to maximize the cost function.
Definition: MILP_Model.h:72
Status
Type of constraints.
Definition: MILP_Model.h:32
void writeOutDelays(const string &file_name)
Writes a output file to save output pin timing to retrieve critical path.
Definition: MILP_Model.h:440
const string & getError() const
Definition: MILP_Model.h:50
void setEpsilon(double eps)
Defines the min epsilon value to distinguish from zero.
Definition: MILP_Model.h:80
double getObj() const
Definition: MILP_Model.h:140
Definition: MILP_Model.h:26
int newRow(const vecTerms &terms, char type='<', double rhs=0.0, const string &name="")
Creates a new row in the constraint matrix from a vector of terms.
Definition: MILP_Model.h:208
bool writeLP(const string &filename)
Write the LP model into a file in CPLEX LP format.
Definition: MILP_Model.h:354
int newRow(char type='<', double rhs=0.0, const string &name="")
Creates a new row in the constraint matrix.
Definition: MILP_Model.h:190
void newCostTerm(double coeff, int varIndex)
Adds a new term to the cost function.
Definition: MILP_Model.h:344
bool isFalse(int i) const
Checks whether the value of a boolean variable is false.
Definition: MILP_Model.h:179
Milp_Model(const string &solver="")
Vector of variables.
Definition: MILP_Model.h:43
int equalSum(const vecVars &x, const vecVars &y, const string &name="")
Creates a constraint indicating that the sum of a set of variables must be equal to the sum of anothe...
Definition: MILP_Model.h:285
bool solve(int timelimit=-1)
Calls the MILP solver.
Definition: MILP_Model.h:371
int implies(const vecVars &x, int y)
Creates a set of constraints representing the Boolean implication x1 + ... + xn => y...
Definition: MILP_Model.h:327
int newBooleanVar(string name="")
Creates a new Boolean variable.
Definition: MILP_Model.h:126
int allEqual(const vecVars &v)
Creates a set of constraints that enforces a set of variables to have the same value.
Definition: MILP_Model.h:299
int newRealVar(string name="", double lower_bound=0.0, double upper_bound=-1.0)
Creates a new real variable.
Definition: MILP_Model.h:102
vector< Term > vecTerms
Type to represent a term (coefficient, var index)
Definition: MILP_Model.h:37
int newIntegerVar(string name="", double lower_bound=0, double upper_bound=-1)
Creates a new integer variable.
Definition: MILP_Model.h:115
int implies(int x, const vecVars &y)
Creates a constraint representing the Boolean implication x => y1 + ... + ym.
Definition: MILP_Model.h:313
int atLeastOne(const vecVars &vars, const string &name="")
Creates an at-least-one constraint (v1+...+vn >= 1).
Definition: MILP_Model.h:258
bool isTrue(int i) const
Checks whether the value of a boolean variable is true.
Definition: MILP_Model.h:169
RowType
Types of variables.
Definition: MILP_Model.h:31