// -*- c++ -*- #ifndef HUGO_LP_SOLVER_WRAPPER_H #define HUGO_LP_SOLVER_WRAPPER ///\ingroup misc ///\file ///\brief Dijkstra algorithm. // #include #include // #include //#include #include "glpk.h" #include #include #include #include #include #include //#include //#include //#include #include //#include //#include //#include //#include //#include using std::cout; using std::cin; using std::endl; namespace hugo { /// \addtogroup misc /// @{ /// \brief A partitioned vector with iterable classes. /// /// This class implements a container in which the data is stored in an /// stl vector, the range is partitioned into sets and each set is /// doubly linked in a list. /// That is, each class is iterable by hugo iterators, and any member of /// the vector can bo moved to an other class. template class IterablePartition { protected: struct Node { T data; int prev; //invalid az -1 int next; }; std::vector nodes; struct Tip { int first; int last; }; std::vector tips; public: /// The classes are indexed by integers from \c 0 to \c classNum()-1. int classNum() const { return tips.size(); } /// This hugo style iterator iterates through a class. class ClassIt; /// Constructor. The number of classes is to be given which is fixed /// over the life of the container. /// The partition classes are indexed from 0 to class_num-1. IterablePartition(int class_num) { for (int i=0; i::ClassIt RowIt; ///. IterablePartition row_iter_map; ///. typedef IterablePartition::ClassIt ColIt; ///. IterablePartition col_iter_map; //std::vector row_id_to_lp_row_id; //std::vector col_id_to_lp_col_id; ///. const int VALID_ID; ///. const int INVALID_ID; public: ///. LPSolverWrapper() : lp(lpx_create_prob()), row_iter_map(2), col_iter_map(2), //row_id_to_lp_row_id(), col_id_to_lp_col_id(), VALID_ID(0), INVALID_ID(1) { lpx_set_int_parm(lp, LPX_K_DUAL, 1); } ///. ~LPSolverWrapper() { lpx_delete_prob(lp); } ///. void setMinimize() { lpx_set_obj_dir(lp, LPX_MIN); } ///. void setMaximize() { lpx_set_obj_dir(lp, LPX_MAX); } ///. ColIt addCol() { int i=lpx_add_cols(lp, 1); ColIt col_it; col_iter_map.first(col_it, INVALID_ID); if (col_iter_map.valid(col_it)) { //van hasznalhato hely col_iter_map.set(col_it, INVALID_ID, VALID_ID); col_iter_map[col_it]=i; //col_id_to_lp_col_id[col_iter_map[col_it]]=i; } else { //a cucc vegere kell inzertalni mert nincs szabad hely //col_id_to_lp_col_id.push_back(i); //int j=col_id_to_lp_col_id.size()-1; col_it=col_iter_map.push_back(i, VALID_ID); } // edge_index_map.set(e, i); // lpx_set_col_bnds(lp, i, LPX_DB, 0.0, 1.0); // lpx_set_obj_coef(lp, i, cost[e]); return col_it; } ///. RowIt addRow() { int i=lpx_add_rows(lp, 1); RowIt row_it; row_iter_map.first(row_it, INVALID_ID); if (row_iter_map.valid(row_it)) { //van hasznalhato hely row_iter_map.set(row_it, INVALID_ID, VALID_ID); row_iter_map[row_it]=i; } else { //a cucc vegere kell inzertalni mert nincs szabad hely row_it=row_iter_map.push_back(i, VALID_ID); } return row_it; } //pair-bol kell megadni egy std range-et ///. template void setColCoeffs(const ColIt& col_it, Begin begin, End end) { int mem_length=1+lpx_get_num_rows(lp); int* indices = new int[mem_length]; double* doubles = new double[mem_length]; int length=0; for ( ; begin!=end; ++begin) { ++length; indices[length]=row_iter_map[begin->first]; doubles[length]=begin->second; } lpx_set_mat_col(lp, col_iter_map[col_it], length, indices, doubles); delete [] indices; delete [] doubles; } //pair-bol kell megadni egy std range-et ///. template void setRowCoeffs(const RowIt& row_it, Begin begin, End end) { int mem_length=1+lpx_get_num_cols(lp); int* indices = new int[mem_length]; double* doubles = new double[mem_length]; int length=0; for ( ; begin!=end; ++begin) { ++length; indices[length]=col_iter_map[begin->first]; doubles[length]=begin->second; } lpx_set_mat_row(lp, row_iter_map[row_it], length, indices, doubles); delete [] indices; delete [] doubles; } ///. void eraseCol(const ColIt& col_it) { col_iter_map.set(col_it, VALID_ID, INVALID_ID); int cols[2]; cols[1]=col_iter_map[col_it]; lpx_del_cols(lp, 1, cols); col_iter_map[col_it]=0; //glpk specifikus ColIt it; for (col_iter_map.first(it, VALID_ID); col_iter_map.valid(it); col_iter_map.next(it)) { if (col_iter_map[it]>cols[1]) --col_iter_map[it]; } } ///. void eraseRow(const RowIt& row_it) { row_iter_map.set(row_it, VALID_ID, INVALID_ID); int rows[2]; rows[1]=row_iter_map[row_it]; lpx_del_rows(lp, 1, rows); row_iter_map[row_it]=0; //glpk specifikus RowIt it; for (row_iter_map.first(it, VALID_ID); row_iter_map.valid(it); row_iter_map.next(it)) { if (row_iter_map[it]>rows[1]) --row_iter_map[it]; } } ///. void setColBounds(const ColIt& col_it, int bound_type, double lo, double up) { lpx_set_col_bnds(lp, col_iter_map[col_it], bound_type, lo, up); } ///. void setObjCoef(const ColIt& col_it, double obj_coef) { lpx_set_obj_coef(lp, col_iter_map[col_it], obj_coef); } ///. void setRowBounds(const RowIt& row_it, int bound_type, double lo, double up) { lpx_set_row_bnds(lp, row_iter_map[row_it], bound_type, lo, up); } // void setObjCoef(const RowIt& row_it, double obj_coef) { // lpx_set_obj_coef(lp, row_iter_map[row_it], obj_coef); // } ///. void solveSimplex() { lpx_simplex(lp); } ///. void solvePrimalSimplex() { lpx_simplex(lp); } ///. void solveDualSimplex() { lpx_simplex(lp); } ///. double getPrimal(const ColIt& col_it) { return lpx_get_col_prim(lp, col_iter_map[col_it]); } ///. double getObjVal() { return lpx_get_obj_val(lp); } ///. int rowNum() const { return lpx_get_num_rows(lp); } ///. int colNum() const { return lpx_get_num_cols(lp); } ///. int warmUp() { return lpx_warm_up(lp); } ///. void printWarmUpStatus(int i) { switch (i) { case LPX_E_OK: cout << "LPX_E_OK" << endl; break; case LPX_E_EMPTY: cout << "LPX_E_EMPTY" << endl; break; case LPX_E_BADB: cout << "LPX_E_BADB" << endl; break; case LPX_E_SING: cout << "LPX_E_SING" << endl; break; } } ///. int getPrimalStatus() { return lpx_get_prim_stat(lp); } ///. void printPrimalStatus(int i) { switch (i) { case LPX_P_UNDEF: cout << "LPX_P_UNDEF" << endl; break; case LPX_P_FEAS: cout << "LPX_P_FEAS" << endl; break; case LPX_P_INFEAS: cout << "LPX_P_INFEAS" << endl; break; case LPX_P_NOFEAS: cout << "LPX_P_NOFEAS" << endl; break; } } ///. int getDualStatus() { return lpx_get_dual_stat(lp); } ///. void printDualStatus(int i) { switch (i) { case LPX_D_UNDEF: cout << "LPX_D_UNDEF" << endl; break; case LPX_D_FEAS: cout << "LPX_D_FEAS" << endl; break; case LPX_D_INFEAS: cout << "LPX_D_INFEAS" << endl; break; case LPX_D_NOFEAS: cout << "LPX_D_NOFEAS" << endl; break; } } /// Returns the status of the slack variable assigned to row \c row_it. int getRowStat(const RowIt& row_it) { return lpx_get_row_stat(lp, row_iter_map[row_it]); } ///. void printRowStatus(int i) { switch (i) { case LPX_BS: cout << "LPX_BS" << endl; break; case LPX_NL: cout << "LPX_NL" << endl; break; case LPX_NU: cout << "LPX_NU" << endl; break; case LPX_NF: cout << "LPX_NF" << endl; break; case LPX_NS: cout << "LPX_NS" << endl; break; } } /// Returns the status of the variable assigned to column \c col_it. int getColStat(const ColIt& col_it) { return lpx_get_col_stat(lp, col_iter_map[col_it]); } ///. void printColStatus(int i) { switch (i) { case LPX_BS: cout << "LPX_BS" << endl; break; case LPX_NL: cout << "LPX_NL" << endl; break; case LPX_NU: cout << "LPX_NU" << endl; break; case LPX_NF: cout << "LPX_NF" << endl; break; case LPX_NS: cout << "LPX_NS" << endl; break; } } }; /// @} } //namespace hugo #endif //HUGO_LP_SOLVER_WRAPPER_H