#ifndef __LPSOLVE_H #define __LPSOLVE_H #include "config.h" #include "gen.h" #include "unary.h" #ifdef HAVE_LIBGLPK #include #endif #ifndef NO_NAMESPACE_GIAC namespace giac { #endif //ndef NO_NAMESPACE_GIAC #define LP_SCORE_FACTOR 0.1667 #define LP_MIN_AWAY 0.08 #define LP_MIN_PARALLELISM 0.86 #define LP_MAX_MAGNITUDE 1e6 #define LP_CONSTR_MAXSIZE 1e5 typedef std::vector ints; enum lp_results { _LP_SOLVED, _LP_INFEASIBLE, _LP_UNBOUNDED, _LP_ERROR }; enum lp_parsing_errors { _LP_ERR_SIZE = 1, _LP_ERR_TYPE = 2, _LP_ERR_DIM = 3 }; enum lp_precision_types { _LP_EXACT, _LP_INEXACT, _LP_PROB_DEPENDENT }; enum lp_relation_types { _LP_LEQ = -1, _LP_EQ = 0, _LP_GEQ = 1 }; enum lp_variable_sign_types { _LP_VARSIGN_POS, _LP_VARSIGN_NEG, _LP_VARSIGN_POS_PART, _LP_VARSIGN_NEG_PART }; struct lp_settings { //solver parameters int solver; int precision; bool presolve; bool maximize; int assumption; int iteration_limit; bool has_binary_vars; //branch&bound parameters int varselect; int nodeselect; double relative_gap_tolerance; int depth_limit; int node_limit; int time_limit; //in miliseconds int max_cuts; //message report parameters bool verbose; double status_report_freq; lp_settings(); }; struct lp_stats { int subproblems_examined; int cuts_applied; int max_active_nodes; double mip_gap; lp_stats(); }; struct lp_range { gen lbound; gen ubound; inline void tighten_lbound(const gen &l,GIAC_CONTEXT) { lbound=max(lbound,l,contextptr); } inline void tighten_ubound(const gen &u,GIAC_CONTEXT) { ubound=min(ubound,u,contextptr); } inline bool is_unrestricted_below() { return is_inf(lbound); } inline bool is_unrestricted_above() { return is_inf(ubound); } lp_range(); }; struct lp_variable { bool is_integral; int sign_type; lp_range range; std::string name; double pseudocost[2]; int nbranch[2]; lp_variable(); void set_type(int t,GIAC_CONTEXT); void update_pseudocost(double delta,double fr,int dir); double score(double fr); }; struct lp_constraints { matrice lhs; vecteur rhs; ints rv; std::vector score; inline int nrows() { return lhs.size(); } inline int ncols() { return lhs.empty()?0:lhs.front()._VECTptr->size(); } void append(const vecteur &lh,const gen &rh,int relation_type); vecteur column(int index); void duplicate_column(int index); void negate_column(int index); void subtract_from_rhs_column(const vecteur &v); void set(int index,const vecteur &lh,const gen &rh,int relation_type); void get(int index,vecteur &lh,gen &rh,int &relation_type); void get_lr(int index,vecteur &lh,gen &rh); void div(int index,const gen &g,GIAC_CONTEXT); void subtract(int index,const vecteur &v,const gen &g); void remove(int index); }; struct lp_node; struct lp_problem { const context *ctx; std::pair objective; double objective_norm; std::vector obj_approx; std::vector variables; vecteur variable_identifiers; lp_constraints constr; lp_constraints cuts; lp_settings settings; lp_stats stats; int nvars_initial; vecteur solution; gen optimum; lp_problem(GIAC_CONTEXT) { ctx=contextptr; settings=lp_settings(); } inline int nc() { return constr.lhs.size(); } inline int nv() { return variables.size(); } void message(const char* msg,bool err=false); void report_status(const char* msg,int count); void add_identifiers_from(const gen &g); int get_variable_index(const identificateur &idnt); void set_objective(const vecteur &v,const gen &ft); void create_variables(int n); void make_problem_exact(); void add_slack_variables(); void tighten_variable_bounds(int i,const gen &l,const gen &u); void make_all_vars_bounded_below(); bool has_integral_variables(); bool has_approx_coefficients(); bool lincomb_coeff(const gen &g,vecteur &varcoeffs,gen &freecoeff); int solve(); vecteur output_solution(); //GLPK routines #ifdef HAVE_LIBGLPK glp_prob *glpk_initialize(); int glpk_simplex(glp_prob *prob); int glpk_interior_point(glp_prob *prob); int glpk_branchcut(glp_prob *prob); #endif int glpk_solve(); bool glpk_load_from_file(const char *fname); }; struct lp_node { lp_problem *prob; int depth; std::vector ranges; gen optimum; vecteur solution; double opt_approx; gen infeas; int most_fractional; std::map fractional_vars; ints cut_indices; inline bool is_integer_feasible() { return is_zero(infeas); } bool is_var_fractional(int index); gen fracpart(const gen &g); lp_node create_child(); int solve_relaxation(); }; gen _lpsolve(const gen &args,GIAC_CONTEXT); extern const unary_function_ptr * const at_lpsolve; #ifndef NO_NAMESPACE_GIAC } //namespace giac #endif //ndef NO_NAMESPACE_GIAC #endif //__LPSOLVE_H