static PyObject* Bar_getkind(BarObject *self, void *closure) { PyObject *retval=NULL; int kind = GLP_CV; if (!Bar_Valid(self, 1)) return NULL; if (!Bar_Row(self)) { kind = glp_get_col_kind(LP, Bar_Index(self)+1); } switch (kind) { case GLP_CV: retval = (PyObject*)&PyFloat_Type; break; case GLP_IV: retval = (PyObject*)&PyInt_Type; break; case GLP_BV: retval = (PyObject*)&PyBool_Type; break; default: PyErr_SetString(PyExc_RuntimeError, "unexpected variable kind encountered"); return NULL; } Py_INCREF(retval); return retval; }
static void solve(char* file_name) { ppl_Constraint_System_t ppl_cs; #ifndef NDEBUG ppl_Constraint_System_t ppl_cs_copy; #endif ppl_Generator_t optimum_location; ppl_Linear_Expression_t ppl_le; int dimension, row, num_rows, column, nz, i, j, type; int* coefficient_index; double lb, ub; double* coefficient_value; mpq_t rational_lb, rational_ub; mpq_t* rational_coefficient; mpq_t* objective; ppl_Linear_Expression_t ppl_objective_le; ppl_Coefficient_t optimum_n; ppl_Coefficient_t optimum_d; mpq_t optimum; mpz_t den_lcm; int optimum_found; glp_mpscp glpk_mpscp; glpk_lp = glp_create_prob(); glp_init_mpscp(&glpk_mpscp); if (verbosity == 0) { /* FIXME: find a way to suppress output from glp_read_mps. */ } #ifdef PPL_LPSOL_SUPPORTS_TIMINGS if (print_timings) start_clock(); #endif /* defined(PPL_LPSOL_SUPPORTS_TIMINGS) */ if (glp_read_mps(glpk_lp, GLP_MPS_FILE, &glpk_mpscp, file_name) != 0) fatal("cannot read MPS file `%s'", file_name); #ifdef PPL_LPSOL_SUPPORTS_TIMINGS if (print_timings) { fprintf(stderr, "Time to read the input file: "); print_clock(stderr); fprintf(stderr, " s\n"); start_clock(); } #endif /* defined(PPL_LPSOL_SUPPORTS_TIMINGS) */ glpk_lp_num_int = glp_get_num_int(glpk_lp); if (glpk_lp_num_int > 0 && !no_mip && !use_simplex) fatal("the enumeration solving method can not handle MIP problems"); dimension = glp_get_num_cols(glpk_lp); /* Read variables constrained to be integer. */ if (glpk_lp_num_int > 0 && !no_mip && use_simplex) { if (verbosity >= 4) fprintf(output_file, "Integer variables:\n"); integer_variables = (ppl_dimension_type*) malloc((glpk_lp_num_int + 1)*sizeof(ppl_dimension_type)); for (i = 0, j = 0; i < dimension; ++i) { int col_kind = glp_get_col_kind(glpk_lp, i+1); if (col_kind == GLP_IV || col_kind == GLP_BV) { integer_variables[j] = i; if (verbosity >= 4) { ppl_io_fprint_variable(output_file, i); fprintf(output_file, " "); } ++j; } } } coefficient_index = (int*) malloc((dimension+1)*sizeof(int)); coefficient_value = (double*) malloc((dimension+1)*sizeof(double)); rational_coefficient = (mpq_t*) malloc((dimension+1)*sizeof(mpq_t)); ppl_new_Constraint_System(&ppl_cs); mpq_init(rational_lb); mpq_init(rational_ub); for (i = 1; i <= dimension; ++i) mpq_init(rational_coefficient[i]); mpz_init(den_lcm); if (verbosity >= 4) fprintf(output_file, "\nConstraints:\n"); /* Set up the row (ordinary) constraints. */ num_rows = glp_get_num_rows(glpk_lp); for (row = 1; row <= num_rows; ++row) { /* Initialize the least common multiple computation. */ mpz_set_si(den_lcm, 1); /* Set `nz' to the number of non-zero coefficients. */ nz = glp_get_mat_row(glpk_lp, row, coefficient_index, coefficient_value); for (i = 1; i <= nz; ++i) { set_mpq_t_from_double(rational_coefficient[i], coefficient_value[i]); /* Update den_lcm. */ mpz_lcm(den_lcm, den_lcm, mpq_denref(rational_coefficient[i])); } lb = glp_get_row_lb(glpk_lp, row); ub = glp_get_row_ub(glpk_lp, row); set_mpq_t_from_double(rational_lb, lb); set_mpq_t_from_double(rational_ub, ub); mpz_lcm(den_lcm, den_lcm, mpq_denref(rational_lb)); mpz_lcm(den_lcm, den_lcm, mpq_denref(rational_ub)); ppl_new_Linear_Expression_with_dimension(&ppl_le, dimension); for (i = 1; i <= nz; ++i) { mpz_mul(tmp_z, den_lcm, mpq_numref(rational_coefficient[i])); mpz_divexact(tmp_z, tmp_z, mpq_denref(rational_coefficient[i])); ppl_assign_Coefficient_from_mpz_t(ppl_coeff, tmp_z); ppl_Linear_Expression_add_to_coefficient(ppl_le, coefficient_index[i]-1, ppl_coeff); } type = glp_get_row_type(glpk_lp, row); add_constraints(ppl_le, type, rational_lb, rational_ub, den_lcm, ppl_cs); ppl_delete_Linear_Expression(ppl_le); } free(coefficient_value); for (i = 1; i <= dimension; ++i) mpq_clear(rational_coefficient[i]); free(rational_coefficient); free(coefficient_index); #ifndef NDEBUG ppl_new_Constraint_System_from_Constraint_System(&ppl_cs_copy, ppl_cs); #endif /* FIXME: here we could build the polyhedron and minimize it before adding the variable bounds. */ /* Set up the columns constraints, i.e., variable bounds. */ for (column = 1; column <= dimension; ++column) { lb = glp_get_col_lb(glpk_lp, column); ub = glp_get_col_ub(glpk_lp, column); set_mpq_t_from_double(rational_lb, lb); set_mpq_t_from_double(rational_ub, ub); /* Initialize the least common multiple computation. */ mpz_set_si(den_lcm, 1); mpz_lcm(den_lcm, den_lcm, mpq_denref(rational_lb)); mpz_lcm(den_lcm, den_lcm, mpq_denref(rational_ub)); ppl_new_Linear_Expression_with_dimension(&ppl_le, dimension); ppl_assign_Coefficient_from_mpz_t(ppl_coeff, den_lcm); ppl_Linear_Expression_add_to_coefficient(ppl_le, column-1, ppl_coeff); type = glp_get_col_type(glpk_lp, column); add_constraints(ppl_le, type, rational_lb, rational_ub, den_lcm, ppl_cs); ppl_delete_Linear_Expression(ppl_le); } mpq_clear(rational_ub); mpq_clear(rational_lb); /* Deal with the objective function. */ objective = (mpq_t*) malloc((dimension+1)*sizeof(mpq_t)); /* Initialize the least common multiple computation. */ mpz_set_si(den_lcm, 1); mpq_init(objective[0]); set_mpq_t_from_double(objective[0], glp_get_obj_coef(glpk_lp, 0)); for (i = 1; i <= dimension; ++i) { mpq_init(objective[i]); set_mpq_t_from_double(objective[i], glp_get_obj_coef(glpk_lp, i)); /* Update den_lcm. */ mpz_lcm(den_lcm, den_lcm, mpq_denref(objective[i])); } /* Set the ppl_objective_le to be the objective function. */ ppl_new_Linear_Expression_with_dimension(&ppl_objective_le, dimension); /* Set value for objective function's inhomogeneous term. */ mpz_mul(tmp_z, den_lcm, mpq_numref(objective[0])); mpz_divexact(tmp_z, tmp_z, mpq_denref(objective[0])); ppl_assign_Coefficient_from_mpz_t(ppl_coeff, tmp_z); ppl_Linear_Expression_add_to_inhomogeneous(ppl_objective_le, ppl_coeff); /* Set values for objective function's variable coefficients. */ for (i = 1; i <= dimension; ++i) { mpz_mul(tmp_z, den_lcm, mpq_numref(objective[i])); mpz_divexact(tmp_z, tmp_z, mpq_denref(objective[i])); ppl_assign_Coefficient_from_mpz_t(ppl_coeff, tmp_z); ppl_Linear_Expression_add_to_coefficient(ppl_objective_le, i-1, ppl_coeff); } if (verbosity >= 4) { fprintf(output_file, "Objective function:\n"); if (mpz_cmp_si(den_lcm, 1) != 0) fprintf(output_file, "("); ppl_io_fprint_Linear_Expression(output_file, ppl_objective_le); } for (i = 0; i <= dimension; ++i) mpq_clear(objective[i]); free(objective); if (verbosity >= 4) { if (mpz_cmp_si(den_lcm, 1) != 0) { fprintf(output_file, ")/"); mpz_out_str(output_file, 10, den_lcm); } fprintf(output_file, "\n%s\n", (maximize ? "Maximizing." : "Minimizing.")); } ppl_new_Coefficient(&optimum_n); ppl_new_Coefficient(&optimum_d); ppl_new_Generator_zero_dim_point(&optimum_location); optimum_found = use_simplex ? solve_with_simplex(ppl_cs, ppl_objective_le, optimum_n, optimum_d, optimum_location) : solve_with_generators(ppl_cs, ppl_objective_le, optimum_n, optimum_d, optimum_location); ppl_delete_Linear_Expression(ppl_objective_le); if (glpk_lp_num_int > 0) free(integer_variables); if (optimum_found) { mpq_init(optimum); ppl_Coefficient_to_mpz_t(optimum_n, tmp_z); mpq_set_num(optimum, tmp_z); ppl_Coefficient_to_mpz_t(optimum_d, tmp_z); mpz_mul(tmp_z, tmp_z, den_lcm); mpq_set_den(optimum, tmp_z); if (verbosity == 1) fprintf(output_file, "Optimized problem.\n"); if (verbosity >= 2) fprintf(output_file, "Optimum value: %.10g\n", mpq_get_d(optimum)); if (verbosity >= 3) { fprintf(output_file, "Optimum location:\n"); ppl_Generator_divisor(optimum_location, ppl_coeff); ppl_Coefficient_to_mpz_t(ppl_coeff, tmp_z); for (i = 0; i < dimension; ++i) { mpz_set(mpq_denref(tmp1_q), tmp_z); ppl_Generator_coefficient(optimum_location, i, ppl_coeff); ppl_Coefficient_to_mpz_t(ppl_coeff, mpq_numref(tmp1_q)); ppl_io_fprint_variable(output_file, i); fprintf(output_file, " = %.10g\n", mpq_get_d(tmp1_q)); } } #ifndef NDEBUG { ppl_Polyhedron_t ph; unsigned int relation; ppl_new_C_Polyhedron_recycle_Constraint_System(&ph, ppl_cs_copy); ppl_delete_Constraint_System(ppl_cs_copy); relation = ppl_Polyhedron_relation_with_Generator(ph, optimum_location); ppl_delete_Polyhedron(ph); assert(relation == PPL_POLY_GEN_RELATION_SUBSUMES); } #endif maybe_check_results(PPL_MIP_PROBLEM_STATUS_OPTIMIZED, mpq_get_d(optimum)); mpq_clear(optimum); } ppl_delete_Constraint_System(ppl_cs); ppl_delete_Coefficient(optimum_d); ppl_delete_Coefficient(optimum_n); ppl_delete_Generator(optimum_location); glp_delete_prob(glpk_lp); }
int lpx_get_col_kind(LPX *lp, int j) { /* retrieve column kind */ return glp_get_col_kind(lp, j) == GLP_CV ? LPX_CV : LPX_IV; }
static int branch_drtom(glp_tree *T, int *_next) { glp_prob *mip = T->mip; int m = mip->m; int n = mip->n; char *non_int = T->non_int; int j, jj, k, t, next, kase, len, stat, *ind; double x, dk, alfa, delta_j, delta_k, delta_z, dz_dn, dz_up, dd_dn, dd_up, degrad, *val; /* basic solution of LP relaxation must be optimal */ xassert(glp_get_status(mip) == GLP_OPT); /* allocate working arrays */ ind = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); /* nothing has been chosen so far */ jj = 0, degrad = -1.0; /* walk through the list of columns (structural variables) */ for (j = 1; j <= n; j++) { /* if j-th column is not marked as fractional, skip it */ if (!non_int[j]) continue; /* obtain (fractional) value of j-th column in basic solution of LP relaxation */ x = glp_get_col_prim(mip, j); /* since the value of j-th column is fractional, the column is basic; compute corresponding row of the simplex table */ len = glp_eval_tab_row(mip, m+j, ind, val); /* the following fragment computes a change in the objective function: delta Z = new Z - old Z, where old Z is the objective value in the current optimal basis, and new Z is the objective value in the adjacent basis, for two cases: 1) if new upper bound ub' = floor(x[j]) is introduced for j-th column (down branch); 2) if new lower bound lb' = ceil(x[j]) is introduced for j-th column (up branch); since in both cases the solution remaining dual feasible becomes primal infeasible, one implicit simplex iteration is performed to determine the change delta Z; it is obvious that new Z, which is never better than old Z, is a lower (minimization) or upper (maximization) bound of the objective function for down- and up-branches. */ for (kase = -1; kase <= +1; kase += 2) { /* if kase < 0, the new upper bound of x[j] is introduced; in this case x[j] should decrease in order to leave the basis and go to its new upper bound */ /* if kase > 0, the new lower bound of x[j] is introduced; in this case x[j] should increase in order to leave the basis and go to its new lower bound */ /* apply the dual ratio test in order to determine which auxiliary or structural variable should enter the basis to keep dual feasibility */ k = glp_dual_rtest(mip, len, ind, val, kase, 1e-9); if (k != 0) k = ind[k]; /* if no non-basic variable has been chosen, LP relaxation of corresponding branch being primal infeasible and dual unbounded has no primal feasible solution; in this case the change delta Z is formally set to infinity */ if (k == 0) { delta_z = (T->mip->dir == GLP_MIN ? +DBL_MAX : -DBL_MAX); goto skip; } /* row of the simplex table that corresponds to non-basic variable x[k] choosen by the dual ratio test is: x[j] = ... + alfa * x[k] + ... where alfa is the influence coefficient (an element of the simplex table row) */ /* determine the coefficient alfa */ for (t = 1; t <= len; t++) if (ind[t] == k) break; xassert(1 <= t && t <= len); alfa = val[t]; /* since in the adjacent basis the variable x[j] becomes non-basic, knowing its value in the current basis we can determine its change delta x[j] = new x[j] - old x[j] */ delta_j = (kase < 0 ? floor(x) : ceil(x)) - x; /* and knowing the coefficient alfa we can determine the corresponding change delta x[k] = new x[k] - old x[k], where old x[k] is a value of x[k] in the current basis, and new x[k] is a value of x[k] in the adjacent basis */ delta_k = delta_j / alfa; /* Tomlin noticed that if the variable x[k] is of integer kind, its change cannot be less (eventually) than one in the magnitude */ if (k > m && glp_get_col_kind(mip, k-m) != GLP_CV) { /* x[k] is structural integer variable */ if (fabs(delta_k - floor(delta_k + 0.5)) > 1e-3) { if (delta_k > 0.0) delta_k = ceil(delta_k); /* +3.14 -> +4 */ else delta_k = floor(delta_k); /* -3.14 -> -4 */ } } /* now determine the status and reduced cost of x[k] in the current basis */ if (k <= m) { stat = glp_get_row_stat(mip, k); dk = glp_get_row_dual(mip, k); } else { stat = glp_get_col_stat(mip, k-m); dk = glp_get_col_dual(mip, k-m); } /* if the current basis is dual degenerate, some reduced costs which are close to zero may have wrong sign due to round-off errors, so correct the sign of d[k] */ switch (T->mip->dir) { case GLP_MIN: if (stat == GLP_NL && dk < 0.0 || stat == GLP_NU && dk > 0.0 || stat == GLP_NF) dk = 0.0; break; case GLP_MAX: if (stat == GLP_NL && dk > 0.0 || stat == GLP_NU && dk < 0.0 || stat == GLP_NF) dk = 0.0; break; default: xassert(T != T); } /* now knowing the change of x[k] and its reduced cost d[k] we can compute the corresponding change in the objective function delta Z = new Z - old Z = d[k] * delta x[k]; note that due to Tomlin's modification new Z can be even worse than in the adjacent basis */ delta_z = dk * delta_k; skip: /* new Z is never better than old Z, therefore the change delta Z is always non-negative (in case of minimization) or non-positive (in case of maximization) */ switch (T->mip->dir) { case GLP_MIN: xassert(delta_z >= 0.0); break; case GLP_MAX: xassert(delta_z <= 0.0); break; default: xassert(T != T); } /* save the change in the objective fnction for down- and up-branches, respectively */ if (kase < 0) dz_dn = delta_z; else dz_up = delta_z; } /* thus, in down-branch no integer feasible solution can be better than Z + dz_dn, and in up-branch no integer feasible solution can be better than Z + dz_up, where Z is value of the objective function in the current basis */ /* following the heuristic by Driebeck and Tomlin we choose a column (i.e. structural variable) which provides largest degradation of the objective function in some of branches; besides, we select the branch with smaller degradation to be solved next and keep other branch with larger degradation in the active list hoping to minimize the number of further backtrackings */ if (degrad < fabs(dz_dn) || degrad < fabs(dz_up)) { jj = j; if (fabs(dz_dn) < fabs(dz_up)) { /* select down branch to be solved next */ next = GLP_DN_BRNCH; degrad = fabs(dz_up); } else { /* select up branch to be solved next */ next = GLP_UP_BRNCH; degrad = fabs(dz_dn); } /* save the objective changes for printing */ dd_dn = dz_dn, dd_up = dz_up; /* if down- or up-branch has no feasible solution, we does not need to consider other candidates (in principle, the corresponding branch could be pruned right now) */ if (degrad == DBL_MAX) break; } } /* free working arrays */ xfree(ind); xfree(val); /* something must be chosen */ xassert(1 <= jj && jj <= n); #if 1 /* 02/XI-2009 */ if (degrad < 1e-6 * (1.0 + 0.001 * fabs(mip->obj_val))) { jj = branch_mostf(T, &next); goto done; } #endif if (T->parm->msg_lev >= GLP_MSG_DBG) { xprintf("branch_drtom: column %d chosen to branch on\n", jj); if (fabs(dd_dn) == DBL_MAX) xprintf("branch_drtom: down-branch is infeasible\n"); else xprintf("branch_drtom: down-branch bound is %.9e\n", lpx_get_obj_val(mip) + dd_dn); if (fabs(dd_up) == DBL_MAX) xprintf("branch_drtom: up-branch is infeasible\n"); else xprintf("branch_drtom: up-branch bound is %.9e\n", lpx_get_obj_val(mip) + dd_up); } done: *_next = next; return jj; }
int c_glp_get_col_kind (glp_prob *lp, int i){ return glp_get_col_kind (lp, i); }
// retrieve all missing values of LP/MILP void Rglpk_retrieve_MP_from_file (char **file, int *type, int *lp_n_constraints, int *lp_n_objective_vars, double *lp_objective_coefficients, int *lp_constraint_matrix_i, int *lp_constraint_matrix_j, double *lp_constraint_matrix_values, int *lp_direction_of_constraints, double *lp_right_hand_side, double *lp_left_hand_side, int *lp_objective_var_is_integer, int *lp_objective_var_is_binary, int *lp_bounds_type, double *lp_bounds_lower, double *lp_bounds_upper, int *lp_ignore_first_row, int *lp_verbosity, char **lp_constraint_names, char **lp_objective_vars_names ) { extern glp_prob *lp; glp_tran *tran; const char *str; int i, j, lp_column_kind, tmp; int ind_offset, status; // Turn on/off Terminal Output if (*lp_verbosity==1) glp_term_out(GLP_ON); else glp_term_out(GLP_OFF); // create problem object if (lp) glp_delete_prob(lp); lp = glp_create_prob(); // read file -> gets stored as an GLPK problem object 'lp' // which file type do we have? switch (*type){ case 1: // Fixed (ancient) MPS Format, param argument currently NULL status = glp_read_mps(lp, GLP_MPS_DECK, NULL, *file); break; case 2: // Free (modern) MPS format, param argument currently NULL status = glp_read_mps(lp, GLP_MPS_FILE, NULL, *file); break; case 3: // CPLEX LP Format status = glp_read_lp(lp, NULL, *file); break; case 4: // MATHPROG Format (based on lpx_read_model function) tran = glp_mpl_alloc_wksp(); status = glp_mpl_read_model(tran, *file, 0); if (!status) { status = glp_mpl_generate(tran, NULL); if (!status) { glp_mpl_build_prob(tran, lp); } } glp_mpl_free_wksp(tran); break; } // if file read successfully glp_read_* returns zero if ( status != 0 ) { glp_delete_prob(lp); lp = NULL; error("Reading file %c failed.", *file); } if(*lp_verbosity==1) Rprintf("Retrieve column specific data ...\n"); if(glp_get_num_cols(lp) != *lp_n_objective_vars) { glp_delete_prob(lp); lp = NULL; error("The number of columns is not as specified"); } // retrieve column specific data (values, bounds and type) for (i = 0; i < *lp_n_objective_vars; i++) { lp_objective_coefficients[i] = glp_get_obj_coef(lp, i+1); // Note that str must not be freed befor we have returned // from the .C call in R! str = glp_get_col_name(lp, i+1); if (str){ lp_objective_vars_names[i] = (char *) str; } lp_bounds_type[i] = glp_get_col_type(lp, i+1); lp_bounds_lower[i] = glp_get_col_lb (lp, i+1); lp_bounds_upper[i] = glp_get_col_ub (lp, i+1); lp_column_kind = glp_get_col_kind(lp, i+1); // set to TRUE if objective variable is integer or binary switch (lp_column_kind){ case GLP_IV: lp_objective_var_is_integer[i] = 1; break; case GLP_BV: lp_objective_var_is_binary[i] = 1; break; } } ind_offset = 0; if(*lp_verbosity==1) Rprintf("Retrieve row specific data ...\n"); if(glp_get_num_rows(lp) != *lp_n_constraints) { glp_delete_prob(lp); lp = NULL; error("The number of rows is not as specified"); } // retrieve row specific data (right hand side, direction of constraints) for (i = *lp_ignore_first_row; i < *lp_n_constraints; i++) { lp_direction_of_constraints[i] = glp_get_row_type(lp, i+1); str = glp_get_row_name(lp, i + 1); if (str) { lp_constraint_names[i] = (char *) str; } // the right hand side. Note we don't allow for double bounded or // free auxiliary variables if( lp_direction_of_constraints[i] == GLP_LO ) lp_right_hand_side[i] = glp_get_row_lb(lp, i+1); if( lp_direction_of_constraints[i] == GLP_UP ) lp_right_hand_side[i] = glp_get_row_ub(lp, i+1); if( lp_direction_of_constraints[i] == GLP_FX ) lp_right_hand_side[i] = glp_get_row_lb(lp, i+1); if( lp_direction_of_constraints[i] == GLP_DB ){ lp_right_hand_side[i] = glp_get_row_ub(lp, i+1); lp_left_hand_side[i] = glp_get_row_lb(lp, i+1); } tmp = glp_get_mat_row(lp, i+1, &lp_constraint_matrix_j[ind_offset-1], &lp_constraint_matrix_values[ind_offset-1]); if (tmp > 0) for (j = 0; j < tmp; j++) lp_constraint_matrix_i[ind_offset+j] = i+1; ind_offset += tmp; } if(*lp_verbosity==1) Rprintf("Done.\n"); }