int GLPKAddConstraint(LinEquation* InEquation) { if (InEquation->QuadCoeff.size() > 0) { FErrorFile() << "GLPK solver cannot accept quadratic constraints." << endl; FlushErrorFile(); return FAIL; } if (GLPKModel == NULL) { FErrorFile() << "Could not add constraint because GLPK object does not exist." << endl; FlushErrorFile(); return FAIL; } int NumRows = glp_get_num_rows(GLPKModel); if (InEquation->Index >= NumRows) { glp_add_rows(GLPKModel, 1); } if (InEquation->EqualityType == EQUAL) { glp_set_row_bnds(GLPKModel, InEquation->Index+1, GLP_FX, InEquation->RightHandSide, InEquation->RightHandSide); } else if (InEquation->EqualityType == GREATER) { glp_set_row_bnds(GLPKModel, InEquation->Index+1, GLP_LO, InEquation->RightHandSide, InEquation->RightHandSide); } else if (InEquation->EqualityType == LESS) { glp_set_row_bnds(GLPKModel, InEquation->Index+1, GLP_UP, InEquation->RightHandSide, InEquation->RightHandSide); } else { FErrorFile() << "Could not add constraint because the constraint type was not recognized." << endl; FlushErrorFile(); return FAIL; } int NumColumns = glp_get_num_cols(GLPKModel); int* Indecies = new int[int(InEquation->Variables.size())+1]; double* Coeff = new double[int(InEquation->Variables.size())+1]; for (int i=0; i < int(InEquation->Variables.size()); i++) { if (InEquation->Variables[i]->Index < NumColumns) { if (InEquation->Variables[i]->Exclude) { Coeff[i+1] = 0; } else { Coeff[i+1] = InEquation->Coefficient[i]; } Indecies[i+1] = InEquation->Variables[i]->Index+1; } else { FErrorFile() << "Variable index found in constraint is out of the range found in GLPK problem" << endl; FlushErrorFile(); return FAIL; } } glp_set_mat_row(GLPKModel, InEquation->Index+1, int(InEquation->Variables.size()), Indecies, Coeff); delete [] Indecies; delete [] Coeff; return SUCCESS; }
int main(void) { glp_prob *mip = glp_create_prob(); glp_set_prob_name(mip, "sample"); glp_set_obj_dir(mip, GLP_MAX); // 拘束条件 // 具体的な関数は後で glp_add_rows(mip, 3); // 拘束条件の数 glp_set_row_name(mip, 1, "c1"); glp_set_row_bnds(mip, 1, GLP_DB, 0.0, 20.0); glp_set_row_name(mip, 2, "c2"); glp_set_row_bnds(mip, 2, GLP_DB, 0.0, 30.0); glp_set_row_name(mip, 3, "c3"); glp_set_row_bnds(mip, 3, GLP_FX, 0.0, 0); // 変数 // 変数そのものにかかる拘束は、拘束条件ではなくてこちらで管理 glp_add_cols(mip, 4); // 変数の数 glp_set_col_name(mip, 1, "x1"); glp_set_col_bnds(mip, 1, GLP_DB, 0.0, 40.0); glp_set_obj_coef(mip, 1, 1.0); glp_set_col_name(mip, 2, "x2"); glp_set_col_bnds(mip, 2, GLP_LO, 0.0, 0.0); glp_set_obj_coef(mip, 2, 2.0); glp_set_col_name(mip, 3, "x3"); glp_set_col_bnds(mip, 3, GLP_LO, 0.0, 0.0); glp_set_obj_coef(mip, 3, 3.0); glp_set_col_kind(mip, 3, GLP_IV); // 整数値としての宣言 glp_set_col_name(mip, 4, "x4"); glp_set_col_bnds(mip, 4, GLP_DB, 2.0, 3.0); glp_set_obj_coef(mip, 4, 1.0); glp_set_col_kind(mip, 4, GLP_IV); // 整数値としての宣言 int ia[1+9], ja[1+9]; double ar[1+9]; ia[1]=1,ja[1]=1,ar[1]=-1; // a[1,1] = -1 ia[2]=1,ja[2]=2,ar[2]=1; // a[1,2] = 1 ia[3]=1,ja[3]=3,ar[3]=1; // a[1,3] = 1 ia[4]=1,ja[4]=4,ar[4]=10; // a[1,4] = 10 ia[5]=2,ja[5]=1,ar[5]=1; // a[2,1] = 1 ia[6]=2,ja[6]=2,ar[6]=-3; // a[2,2] = -3 ia[7]=2,ja[7]=3,ar[7]=1; // a[2,3] = 1 ia[8]=3,ja[8]=2,ar[8]=1; // a[3,2] = 1 ia[9]=3,ja[9]=4,ar[9]=-3.5; // a[3,4] = -3.5 glp_load_matrix(mip, 9, ia, ja, ar); glp_iocp parm; glp_init_iocp(&parm); parm.presolve = GLP_ON; int err = glp_intopt(mip, &parm); double z = glp_mip_obj_val(mip); double x1 = glp_mip_col_val(mip, 1); double x2 = glp_mip_col_val(mip, 2); double x3 = glp_mip_col_val(mip, 3); double x4 = glp_mip_col_val(mip, 4); printf("\nz = %g; x1 = %g; x2 = %g; x3 = %g, x4 = %g\n", z, x1, x2, x3, x4); // z = 122.5; x1 = 40; x2 = 10.5; x3 = 19.5, x4 = 3 glp_delete_prob(mip); return 0; }
void NADA() { glp_prob *lp; lp = glp_create_prob(); glp_add_cols(lp, 3); glp_set_col_bnds(lp, 1, GLP_LO, 0.0, 3.0); // 0 <= x1 glp_set_col_bnds(lp, 2, GLP_LO, 0.0, 2.0); // 0 <= x2 glp_set_col_bnds(lp, 3, GLP_LO, 0.0, 0.0); // 0 <= x3 glp_set_obj_dir(lp, GLP_MAX); //max glp_set_obj_coef(lp, 1, -3.0); // -3x1 glp_set_obj_coef(lp, 2, 4.0); // +4x2 glp_set_obj_coef(lp, 3, 11.0); // +11x3 // max -3x1 + 4x2 + 11 x3. int indCol[123]; double val[123]; glp_add_rows(lp, 1); indCol[1] = 1; val[1] = 10; // 10*x1 indCol[2] = 2; val[2] = 3; // 3*x2 glp_set_row_bnds(lp, 1, GLP_UP, 0.0, 15.0);// <=15 glp_set_mat_row(lp, 1, 2, indCol, val);// 10 x1 + 3 x2 <= 15 glp_add_rows(lp, 1); indCol[1] = 3; val[1] = 9; // 9*x3 indCol[2] = 1; val[2] = 7; // 7*x1 glp_set_row_bnds(lp, 2, GLP_UP, 0.0, 38.0);// <=38 glp_set_mat_row(lp, 2, 2, indCol, val);// 7x1+9x2<=38 glp_add_rows(lp, 1); indCol[1] = 3; val[1] = 15; // 15*x3 glp_set_row_bnds(lp, 3, GLP_LO, 0.0, 25.0);// >=25 glp_set_mat_row(lp, 3, 1, indCol, val);// 15x3 >=25 glp_set_col_kind(lp, 1, GLP_IV);// X1 EH INTEIRO glp_set_col_kind(lp, 2, GLP_IV);// X2 EH INTEIRO glp_set_col_kind(lp, 3, GLP_IV);// X3 EH INTEIRO glp_intopt(lp, NULL); // acha solucao com restricao de integralidade // glp_simplex(lp, NULL); // printf("Solucao Otima: %.3f\n", glp_get_obj_val(lp)); // printf("X1: %.3f\n", glp_get_col_prim(lp, 1)); // printf("X2: %.3f\n", glp_get_col_prim(lp, 2)); // printf("X3: %.3f\n", glp_get_col_prim(lp, 3)); printf("Solucao Otima: %.3f\n", glp_mip_obj_val(lp)); printf("X1: %.3f\n", glp_mip_col_val(lp, 1)); printf("X2: %.3f\n", glp_mip_col_val(lp, 2)); printf("X3: %.3f\n", glp_mip_col_val(lp, 3)); // for (int est = 1; est <= nEstradas; ++est) { // glp_set_col_bnds(lp, est, GLP_LO, 0.0, 0.0); // } }
int make_constraint(IP::BoundType bnd, double l, double u) { int row = glp_add_rows(ip_, 1); switch (bnd) { case IP::FR: glp_set_row_bnds(ip_, row, GLP_FR, l, u); break; case IP::LO: glp_set_row_bnds(ip_, row, GLP_LO, l, u); break; case IP::UP: glp_set_row_bnds(ip_, row, GLP_UP, l, u); break; case IP::DB: glp_set_row_bnds(ip_, row, GLP_DB, l, u); break; case IP::FX: glp_set_row_bnds(ip_, row, GLP_FX, l, u); break; } return row; }
int main(void) { glp_prob *lp; int ia[1+1000], ja[1+1000]; double ar[1+1000], z, x1, x2, x3; s1: lp = glp_create_prob(); s2: glp_set_prob_name(lp, "sample"); s3: glp_set_obj_dir(lp, GLP_MAX); s4: glp_add_rows(lp, 3); s5: glp_set_row_name(lp, 1, "p"); s6: glp_set_row_bnds(lp, 1, GLP_UP, 0.0, 100.0); s7: glp_set_row_name(lp, 2, "q"); s8: glp_set_row_bnds(lp, 2, GLP_UP, 0.0, 600.0); s9: glp_set_row_name(lp, 3, "r"); s10: glp_set_row_bnds(lp, 3, GLP_UP, 0.0, 300.0); s11: glp_add_cols(lp, 3); s12: glp_set_col_name(lp, 1, "x1"); s13: glp_set_col_bnds(lp, 1, GLP_LO, 0.0, 0.0); s14: glp_set_obj_coef(lp, 1, 10.0); s15: glp_set_col_name(lp, 2, "x2"); s16: glp_set_col_bnds(lp, 2, GLP_LO, 0.0, 0.0); s17: glp_set_obj_coef(lp, 2, 6.0); s18: glp_set_col_name(lp, 3, "x3"); s19: glp_set_col_bnds(lp, 3, GLP_LO, 0.0, 0.0); s20: glp_set_obj_coef(lp, 3, 4.0); s21: ia[1] = 1, ja[1] = 1, ar[1] = 1.0; /* a[1,1] = 1 */ s22: ia[2] = 1, ja[2] = 2, ar[2] = 1.0; /* a[1,2] = 1 */ s23: ia[3] = 1, ja[3] = 3, ar[3] = 1.0; /* a[1,3] = 1 */ s24: ia[4] = 2, ja[4] = 1, ar[4] = 10.0; /* a[2,1] = 10 */ s25: ia[5] = 3, ja[5] = 1, ar[5] = 2.0; /* a[3,1] = 2 */ s26: ia[6] = 2, ja[6] = 2, ar[6] = 4.0; /* a[2,2] = 4 */ s27: ia[7] = 3, ja[7] = 2, ar[7] = 2.0; /* a[3,2] = 2 */ s28: ia[8] = 2, ja[8] = 3, ar[8] = 5.0; /* a[2,3] = 5 */ s29: ia[9] = 3, ja[9] = 3, ar[9] = 6.0; /* a[3,3] = 6 */ s30: glp_load_matrix(lp, 9, ia, ja, ar); s31: glp_simplex(lp, NULL); s32: z = glp_get_obj_val(lp); s33: x1 = glp_get_col_prim(lp, 1); s34: x2 = glp_get_col_prim(lp, 2); s35: x3 = glp_get_col_prim(lp, 3); s36: printf("\nz = %g; x1 = %g; x2 = %g; x3 = %g\n", z, x1, x2, x3); s37: glp_delete_prob(lp); return 0; }
glp_prob * montarModeloInicial() { glp_prob *lp; lp = glp_create_prob();//cria problema glp_add_cols(lp, nEstradas); // cria uma variavel por estrada for(int est = 1; est <= nEstradas; ++est) { // para cada estrada glp_set_col_bnds(lp, est, GLP_DB, 0.0, 1.0); // estrada entre 0 e 1 glp_set_col_kind(lp, est, GLP_BV); // estrada binaria } glp_set_obj_dir(lp, GLP_MIN); //MIN for(int est=1; est <= nEstradas; ++est) { // para cada estrada glp_set_obj_coef(lp, est, estradas[est].dist); // custo da estrada eh coeficiente da objetivo } for (int cid = 1; cid <= nCidades; ++cid) { //para cada cidade int indCol[123]; double val[123]; int nCoef = 0; for (int est = 1; est < nEstradas; ++est) { //para cada estrada Estrada estrada = estradas[est]; if (estrada.ori == cid || estrada.dest == cid) { //se cidade toca estrada est indCol[nCoef + 1] = est; // a est-esima estrada val[nCoef + 1] = 1.0; // com coeficiente 1 na linha nCoef++; //incremente numero de coeficiente } } glp_add_rows(lp, 1); glp_set_mat_row(lp, cid, nCoef, indCol, val); // adiciona coeficientes da linha glp_set_row_bnds(lp, cid, GLP_DB, 2.0, 2.0); // restringe linha = 2. } }
void B2GlpkHasher::add_str_constraints() { std::vector<ConstraintBounds> constraint_bounds_vec; std::vector<ConstraintCoeff> constraint_coeffs_vec; unsigned int constraint_idx = 0; for(B2StrSet::const_iterator str_it = _str_set.begin(); str_it != _str_set.end(); ++str_it) { const std::string &str = str_it->first; const char *first_even_trace = str.c_str(); const char *first_odd_trace = (str.c_str() + 1); const char *trace_limit = (str.c_str() + str.size() - 2); unsigned int even_upper_bound = add_single_constraint(++constraint_idx, first_even_trace, trace_limit, constraint_coeffs_vec); constraint_bounds_vec.push_back(ConstraintBounds(constraint_idx, std::string("E") + str, even_upper_bound)); unsigned int odd_upper_bound = add_single_constraint(++constraint_idx, first_odd_trace, trace_limit, constraint_coeffs_vec); constraint_bounds_vec.push_back(ConstraintBounds(constraint_idx, std::string("O") + str, odd_upper_bound)); }; glp_add_rows(_lp, constraint_bounds_vec.size()); for(std::vector<ConstraintBounds>::const_iterator bounds_it = constraint_bounds_vec.begin(); bounds_it != constraint_bounds_vec.end(); ++bounds_it) { const ConstraintBounds &bounds = *bounds_it; glp_set_row_name(_lp, bounds._constraint_idx, bounds._str.c_str()); if(bounds._upper_bound > 1) { glp_set_row_bnds(_lp, bounds._constraint_idx, GLP_DB, 1, bounds._upper_bound); } else { glp_set_row_bnds(_lp, bounds._constraint_idx, GLP_FX, 1, 1); }; }; int *ia = new int[1 + constraint_coeffs_vec.size()]; int *ja = new int[1 + constraint_coeffs_vec.size()]; double *ar = new double[1 + constraint_coeffs_vec.size()]; unsigned int coeff_count = 0; for(std::vector<ConstraintCoeff>::const_iterator coeffs_it = constraint_coeffs_vec.begin(); coeffs_it != constraint_coeffs_vec.end(); ++coeffs_it) { const ConstraintCoeff &coeff = *coeffs_it; ++coeff_count; ia[coeff_count] = coeff._constraint_idx, ja[coeff_count] = coeff._trace_var_idx, ar[coeff_count] = coeff._coeff; /* a[constraint_idx,trace_var_idx] = coeff */ }; glp_load_matrix(_lp, coeff_count, ia, ja, ar); delete [] ia; delete [] ja; delete [] ar; };
void glpk_wrapper::set_constraint(int index, Enode * const e) { DREAL_LOG_INFO << "glpk_wrapper::set_constraint " << e << " with " << e->getPolarity(); assert(is_linear(e)); changed = true; LAExpression la(e); auto vars = e->get_vars(); auto s = vars.size(); auto indices = new int[s + 1]; auto values = new double[s + 1]; int i = 1; for (auto it = la.begin(); it != la.end(); ++it) { auto v = it->first; double c = it->second; if (v != nullptr && c != 0.0) { DREAL_LOG_INFO << "glpk_wrapper::set_constraint " << c << " * " << v; indices[i] = get_index(v) + 1; values[i] = c; i += 1; } else { if (e->isEq()) { assert(!e->hasPolarity() || e->getPolarity() != l_False); DREAL_LOG_INFO << "glpk_wrapper::set_constraint == " << c; glp_set_row_bnds(lp, index, GLP_FX, -c, -c); } else { if (!e->hasPolarity() || e->getPolarity() != l_False) { DREAL_LOG_INFO << "glpk_wrapper::set_constraint <= " << (-c); glp_set_row_bnds(lp, index, GLP_UP, 0, -c); } else { DREAL_LOG_INFO << "glpk_wrapper::set_constraint >= " << (-c); glp_set_row_bnds(lp, index, GLP_LO, -c, 0); } } } } glp_set_mat_row(lp, index, i-1, indices, values); delete[] indices; delete[] values; // name the constraints (helps debugging) if (DREAL_LOG_INFO_IS_ON) { std::ostringstream stream; if (e->getPolarity() == l_False) { stream << "¬"; } stream << e; glp_set_row_name(lp, index, stream.str().c_str()); } }
/* add the goal, it is in row_idx,row_val[1..n] */ static void add_goal(int n) {int i,in; double v; sort_rowidx(n); for(i=1,in=1;i<=rows;i++){ if(in<=n && row_idx[in]==i){ v=row_val[in]; in++; } else { v=0.0; } glp_set_row_bnds(P,i,GLP_FX,v,0.0); } }
int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names, int v_set, int a_cost) { glp_vertex *v; glp_arc *a; int i, j, ret, ind[1+2]; double cost, val[1+2]; if (!(form == GLP_ASN_MIN || form == GLP_ASN_MAX || form == GLP_ASN_MMP)) xerror("glp_asnprob_lp: form = %d; invalid parameter\n", form); if (!(names == GLP_ON || names == GLP_OFF)) xerror("glp_asnprob_lp: names = %d; invalid parameter\n", names); if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) xerror("glp_asnprob_lp: v_set = %d; invalid offset\n", v_set); if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) xerror("glp_asnprob_lp: a_cost = %d; invalid offset\n", a_cost); ret = glp_check_asnprob(G, v_set); if (ret != 0) goto done; glp_erase_prob(P); if (names) glp_set_prob_name(P, G->name); glp_set_obj_dir(P, form == GLP_ASN_MIN ? GLP_MIN : GLP_MAX); if (G->nv > 0) glp_add_rows(P, G->nv); for (i = 1; i <= G->nv; i++) { v = G->v[i]; if (names) glp_set_row_name(P, i, v->name); glp_set_row_bnds(P, i, form == GLP_ASN_MMP ? GLP_UP : GLP_FX, 1.0, 1.0); } if (G->na > 0) glp_add_cols(P, G->na); for (i = 1, j = 0; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { j++; if (names) { char name[50+1]; sprintf(name, "x[%d,%d]", a->tail->i, a->head->i); xassert(strlen(name) < sizeof(name)); glp_set_col_name(P, j, name); } ind[1] = a->tail->i, val[1] = +1.0; ind[2] = a->head->i, val[2] = +1.0; glp_set_mat_col(P, j, 2, ind, val); glp_set_col_bnds(P, j, GLP_DB, 0.0, 1.0); if (a_cost >= 0) memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); else cost = 1.0; glp_set_obj_coef(P, j, cost); } } xassert(j == G->na); done: return ret; }
void LinearProblem::RemoveRow(int row) { static int indices[MAX_VARS]; static double values[MAX_VARS]; int nonZeros = glp_get_mat_row(lp_, row, indices, values); glp_set_row_bnds(lp_, row, GLP_FR, 0.0, 0.0); // glpk ignores the 0's index of the array int ind[2]; double val[2]; for (int i = 1; i <= nonZeros; ++i) { ind[1] = indices[i]; val[1] = (isMax(colToVar_[indices[i]]) ? -1 : 1); int r = glp_add_rows(lp_, 1); glp_set_row_bnds(lp_, r, GLP_UP, 0.0, MINUS_INFTY); glp_set_mat_row(lp_, r, 1, ind, val); } }
static void parse_constraints(struct csa *csa) { int i, len, type; double s; /* parse the keyword 'subject to' */ xassert(csa->token == T_SUBJECT_TO); scan_token(csa); loop: /* create new row (constraint) */ i = glp_add_rows(csa->P, 1); /* parse row name */ if (csa->token == T_NAME && csa->c == ':') { /* row name is followed by a colon */ if (glp_find_row(csa->P, csa->image) != 0) error(csa, "constraint '%s' multiply defined\n", csa->image); glp_set_row_name(csa->P, i, csa->image); scan_token(csa); xassert(csa->token == T_COLON); scan_token(csa); } else { /* row name is not specified; use default */ char name[50]; sprintf(name, "r.%d", csa->count); glp_set_row_name(csa->P, i, name); } /* parse linear form */ len = parse_linear_form(csa); glp_set_mat_row(csa->P, i, len, csa->ind, csa->val); /* parse constraint sense */ if (csa->token == T_LE) type = GLP_UP, scan_token(csa); else if (csa->token == T_GE) type = GLP_LO, scan_token(csa); else if (csa->token == T_EQ) type = GLP_FX, scan_token(csa); else error(csa, "missing constraint sense\n"); /* parse right-hand side */ if (csa->token == T_PLUS) s = +1.0, scan_token(csa); else if (csa->token == T_MINUS) s = -1.0, scan_token(csa); else s = +1.0; if (csa->token != T_NUMBER) error(csa, "missing right-hand side\n"); glp_set_row_bnds(csa->P, i, type, s * csa->value, s * csa->value); /* the rest of the current line must be empty */ if (!(csa->c == '\n' || csa->c == EOF)) error(csa, "invalid symbol(s) beyond right-hand side\n"); scan_token(csa); /* if the next token is a sign, numeric constant, or a symbolic name, here is another constraint */ if (csa->token == T_PLUS || csa->token == T_MINUS || csa->token == T_NUMBER || csa->token == T_NAME) goto loop; return; }
/* Create from the base problem, an other problem which forces stocks to be 0. * The cronstruted solution stay feasible for the first problem. */ node* construction (glp_prob * prob) { node* res = (node *) malloc (sizeof(node)); glp_prob * constProb = glp_create_prob(); glp_copy_prob(constProb, prob, GLP_ON); int i = glp_add_rows(constProb, 1); int k = glp_add_rows(constProb, 1); int nbj = glp_get_num_cols(prob)/3 -1; int ind[nbj+2]; double val[nbj+2]; int indk[nbj+2]; double valk[nbj+2]; int j; ind[0] = 0; val[0] = 1; ind[1] = 1; val[1] = 1; indk[1] = 2 ; valk[1] = 1; for (j = 1; j <= nbj; ++j) { ind[j] = j * 3 +2; indk[j] = j *3 + 3; val[j] = 1; valk[j] = 1; } glp_set_mat_row(constProb, i, nbj, ind, val); glp_set_row_bnds(constProb, i, GLP_FX, 0, 0); glp_set_mat_row(constProb, k, nbj, indk, valk); glp_set_row_bnds(constProb, k, GLP_FX, nbj, nbj); create_node(res, constProb, NULL, 0, 0); return res; }
/* Different cases : * - if the created node is root, then father is NULL, the problem version in the node is the one gave as parameter. * - else we copy the problem, and had the constraint "x_{y} = valy" */ void create_node(node* n, glp_prob* prob, node* father, int y, double valy) { n->father = father; n->leftSon = NULL; n->rightSon = NULL; n->check = 0; int i = 0; int ind[] = {0,y}; double val[] = {0,1}; if (n-> father == NULL) { n->prob = prob; } else { n->prob = glp_create_prob(); glp_copy_prob(n->prob, n->father->prob, GLP_ON); i = glp_add_rows(n->prob, 1); glp_set_mat_row(n->prob, i, 1, ind, val); glp_set_row_bnds(n->prob, i, GLP_FX, valy, valy); } glp_smcp parm; glp_init_smcp(&parm); parm.msg_lev = GLP_MSG_OFF; glp_iocp parmip; glp_init_iocp(&parmip); parmip.msg_lev = GLP_MSG_OFF; glp_write_lp(prob, NULL, "ULS.lp"); n->solveFlag = glp_simplex(n->prob, &parm); glp_intopt(n->prob, &parmip); n->z = glp_mip_obj_val(n->prob); n->x = (double *) malloc (glp_get_num_cols(n->prob) * sizeof(double)); for (i = 0; i < glp_get_num_cols(n->prob); ++i) n->x[i] = glp_mip_col_val(n->prob, i+1); }
int main(int argc, char *argv[]) { leEstradas(); glp_prob *lp = montarModeloInicial(); while(1){ glp_intopt(lp, NULL); // acha solucao com restricao de integralidade printf("Solucao Otima: %.3f\n", glp_mip_obj_val(lp)); printf("X1: %.3f\n", glp_mip_col_val(lp, 1)); printf("X2: %.3f\n", glp_mip_col_val(lp, 2)); printf("X3: %.3f\n", glp_mip_col_val(lp, 3)); int arestaEscolhida[1234]; for(int est = 1; est) { arestaEscolhida[est] = glp_mip_col_val(lp, est); } int verticesAlcancados[123]; for( ) ; // para contar se todos os vertices foram alcancados // se tiverem sido, de um break e mostre a resposta; encontraVerticesAlcancaveis(arestaEscolhida, verticesAlcancados); glp_add_row(lp, 1); int indCol[123]; double val[123]; int nCoef = 0; for (int e = 1; e <= nArestas; ++e) { Estrada estrada = estradas[e]; int nextremosAlcancados = verticesAlcancados[estrada.ori] + verticesAlcancados[estrada.dest]; if (nextremosAlcancados == 1) { indCol[nCoef + 1] = e; val[nCoef + 1] = 1.0; } } glp_set_mat_row(lp, glp_get_num_rows(lp), nCoef, indCol, val); glp_set_row_bnds(lp, glp_get_num_rows(lp), GLP_LO, 2.0, 2.0); system("PAUSE"); return EXIT_SUCCESS; }
/* Restriction xj - xi >= Sij */ void addSeparationConstraint(glp_prob * Prob, int plane1, int plane2) { int cardinal, constr[3], i = plane1, j = plane2; double cValues[3]; char buf[AUXSIZE]; cardinal = glp_add_rows(Prob, 1); sprintf(buf,"S%i,%i",i,j); glp_set_row_name(Prob, cardinal, buf); glp_set_row_bnds(Prob, cardinal, GLP_LO, planes[i].sep[j], 0); sprintf(buf,"x%i",j); constr[1] = glp_find_col(Prob, buf); sprintf(buf,"x%i",i); constr[2] = glp_find_col(Prob, buf); cValues[1] = 1; cValues[2] = -1; glp_set_mat_row(Prob, cardinal, 2, constr, cValues); }
/* Restriction bci = ai - bi + xi = Ti and z += ai*Ei + bi*Li */ void addBasicRestriction(glp_prob * Prob, int plane) { int cardinal, constr[4], i = plane, cardRow; double cValues[4]; char buf[AUXSIZE]; cardinal = glp_add_cols(Prob, 3); sprintf(buf,"a%i",i); glp_set_col_name(Prob, cardinal, buf); glp_set_col_bnds(Prob, cardinal, GLP_LO, 0, 0); glp_set_obj_coef(Prob, cardinal, planes[i].costE); sprintf(buf,"b%i",i); glp_set_col_name(Prob, cardinal+1, buf); glp_set_col_bnds(Prob, cardinal+1, GLP_LO, 0, 0); glp_set_obj_coef(Prob, cardinal+1, planes[i].costL); sprintf(buf,"x%i",i); glp_set_col_name(Prob, cardinal+2, buf); if( planes[i].earliest == planes[i].latest ) glp_set_col_bnds(Prob, cardinal+2, GLP_FX, planes[i].earliest, 0); else glp_set_col_bnds(Prob, cardinal+2, GLP_DB, planes[i].earliest, planes[i].latest); cardRow = glp_add_rows(Prob, 1); sprintf(buf,"bc%i",i); glp_set_row_name(Prob, cardRow, buf); glp_set_row_bnds(Prob, cardRow, GLP_FX, planes[i].ideal, 0); constr[3] = 1 + (constr[2] = 1 + (constr[1] = cardinal)); cValues[3] = cValues[1] = 1; cValues[2] = -1; glp_set_mat_row(Prob, cardRow, 3, constr, cValues); }
void NUMlinprog_addConstraint (NUMlinprog me, double lowerBound, double upperBound) { try { if (my ind == NULL) { /* * Check without change. */ autoNUMvector <int> ind (1, my numberOfVariables); autoNUMvector <double> val (1, my numberOfVariables); /* * Change without error. */ my ind = ind.transfer(); my val = val.transfer(); } glp_add_rows (my linearProgram, 1); // TODO: check glp_set_row_bnds (my linearProgram, ++ my numberOfConstraints, lowerBound == NUMundefined ? ( upperBound == NUMundefined ? GLP_FR : GLP_UP ) : upperBound == NUMundefined ? GLP_LO : lowerBound == upperBound ? GLP_FX : GLP_DB, lowerBound, upperBound); my ivar = 0; } catch (MelderError) { Melder_throw (U"Linear programming: constraint not added."); } }
int main(int argc, char *argv[]) { /* structures de données propres à GLPK */ glp_prob *prob; // déclaration d'un pointeur sur le problème int ia[1 + NBCREUX]; int ja[1 + NBCREUX]; double ar[1 + NBCREUX]; // déclaration des 3 tableaux servant à définir la partie creuse de la matrice des contraintes int p[N+1]; p[1] = 34; p[2] = 6; p[3] = 8; p[4] = 17; p[5] = 16; p[6] = 5; p[7] = 13; p[8] = 21; p[9] = 25; p[10] = 31; p[11] = 14; p[12] = 13; p[13] = 33; p[14] = 9; p[15] = 25; p[16] = 25; /* variables récupérant les résultats de la résolution du problème (fonction objectif et valeur des variables) */ int i,j,pos; double z; double x[NBVAR]; /* Les déclarations suivantes sont optionnelles, leur but est de donner des noms aux variables et aux contraintes. Cela permet de lire plus facilement le modèle saisi si on en demande un affichage à GLPK, ce qui est souvent utile pour détecter une erreur! */ char nomcontr[NBCONTR][8]; /* ici, les contraintes seront nommées "caisse1", "caisse2",... */ char numero[NBCONTR][3]; /* pour un nombre à deux chiffres */ char nomvar[NBVAR][3]; /* "xA", "xB", ... */ /* Création d'un problème (initialement vide) */ prob = glp_create_prob(); /* allocation mémoire pour le problème */ glp_set_prob_name(prob, "wagons"); /* affectation d'un nom (on pourrait mettre NULL) */ glp_set_obj_dir(prob, GLP_MIN); /* Il s'agit d'un problème de minimisation, on utiliserait la constante GLP_MAX dans le cas contraire */ /* Déclaration du nombre de contraintes (nombre de lignes de la matrice des contraintes) : NBCONTR */ glp_add_rows(prob, NBCONTR); /* On commence par préciser les bornes sur les constrainte, les indices des contraintes commencent à 1 (!) dans GLPK */ for(i = 1;i <= N;i++) { /* partie optionnelle : donner un nom aux contraintes */ strcpy(nomcontr[i-1], "caisse"); sprintf(numero[i-1], "%d", i); strcat(nomcontr[i-1], numero[i-1]); /* Les contraintes sont nommés "salle1", "salle2"... */ glp_set_row_name(prob, i, nomcontr[i-1]); /* Affectation du nom à la contrainte i */ /* partie indispensable : les bornes sur les contraintes */ glp_set_row_bnds(prob, i, GLP_FX, 1.0, 1.0); } for(i = N+1;i <= NBCONTR;i++) { /* partie optionnelle : donner un nom aux contraintes */ strcpy(nomcontr[i-1], "chaMax"); sprintf(numero[i-1], "%d", i); strcat(nomcontr[i-1], numero[i-1]); /* Les contraintes sont nommés "chargemax", "chargemax2"... */ glp_set_row_name(prob, i, nomcontr[i-1]); /* Affectation du nom à la contrainte i */ // il doit manquer un bout ici glp_set_row_bnds(prob, i, GLP_UP, 0.0, 0.0); //<=0 // on met cmax a gauche car c'est une variable // il aura le coeff -1 dans la mat creuse } /* Déclaration du nombre de variables : NBVAR */ glp_add_cols(prob, NBVAR); /* On précise le type des variables, les indices commencent à 1 également pour les variables! */ for(i = 1;i <= NBVAR;i++) { if(i==NBVAR){ sprintf(nomvar[i-1],"Cm"); glp_set_col_name(prob, i , nomvar[i-1]); glp_set_col_bnds(prob, i, GLP_LO, 0.0, 0.0); }else{ /* partie optionnelle : donner un nom aux variables */ sprintf(nomvar[i-1],"x%d",i-1); glp_set_col_name(prob, i , nomvar[i-1]); /* Les variables sont nommées "xA", "xB"... afin de respecter les noms de variables de l'exercice 2.2 */ /* partie obligatoire : bornes éventuelles sur les variables, et type */ glp_set_col_bnds(prob, i, GLP_DB, 0.0, 1.0); /* bornes sur les variables, comme sur les contraintes */ glp_set_col_kind(prob, i, GLP_BV); /* les variables sont par défaut continues, nous précisons ici qu'elles sont binaires avec la constante GLP_BV, on utiliserait GLP_IV pour des variables entières */ } } /* définition des coefficients des variables dans la fonction objectif */ for(i = 1;i <= N*M;i++) glp_set_obj_coef(prob,i,0.0); // Tous les coûts sont ici à 0! Mais on doit specifier quand meme glp_set_obj_coef(prob,N*M+1,1.0); // 1 fois cmax /* Définition des coefficients non-nuls dans la matrice des contraintes, autrement dit les coefficients de la matrice creuse */ /* Les indices commencent également à 1 ! */ // pour i de 1 a n //pour i de 1 a m /* xij intervient dans la ligne i avec un coeff 1 et dans la ligne n+j avec un coeff pi ia -> i et n+j ar -> 1 et pi ja -> xij -> (i-1)*m+j */ pos = 1; for(i=1; i<=N; i++){ for(j=1; j<=M; j++){ ia[pos] = i; ja[pos] = (i-1)*M+j; ar[pos] = 1; pos++; ia[pos] = N+j; ja[pos] = (i-1)*M+j; ar[pos] = p[i]; pos++; } } //Cmax a -1 !!! for(i=N+1; i<=N+M;i++){ ia[pos] = i; ja[pos] = N*M+1; ar[pos] = -1; pos++; } /* chargement de la matrice dans le problème */ glp_load_matrix(prob,NBCREUX,ia,ja,ar); /* Optionnel : écriture de la modélisation dans un fichier (TRES utile pour debugger!) */ glp_write_lp(prob,NULL,"wagons.lp"); /* Résolution, puis lecture des résultats */ glp_simplex(prob,NULL); glp_intopt(prob,NULL); /* Résolution */ z = glp_mip_obj_val(prob); /* Récupération de la valeur optimale. Dans le cas d'un problème en variables continues, l'appel est différent : z = glp_get_obj_val(prob); */ for(i = 0;i < NBVAR; i++) x[i] = glp_mip_col_val(prob,i+1); /* Récupération de la valeur des variables, Appel différent dans le cas d'un problème en variables continues : for(i = 0;i < p.nbvar;i++) x[i] = glp_get_col_prim(prob,i+1); */ printf("z = %lf\n",z); for(i = 0;i < NBVAR;i++) printf("x%d = %d, ",i,(int)(x[i] + 0.5)); /* un cast est ajouté, x[i] pourrait être égal à 0.99999... */ puts(""); /* libération mémoire */ glp_delete_prob(prob); /* J'adore qu'un plan se déroule sans accroc! */ return 0; }
void Constraint::set_bounds(int type, double lb, double ub) { glp_set_row_bnds(lp_, lineNumber_, type, lb, ub); }
int main() { // Variáveis auxiliares int i, j, constraintNumber, *constraintIndices; double *constraintCoefficients; // Aloca os vetores utilizados para criar as restrições do problema // *********************************************************************************************** // ATENÇÃO ===> É importante dizer que estes vetores serão utilizados da posição 1 em diante // Ou seja, no GLPK você aloca uma posição a mais e descarta a posição 0 dos vetores. // *********************************************************************************************** constraintIndices = (int*)malloc((n+1)*sizeof(int)); constraintCoefficients = (double*)malloc((n+1)*sizeof(double)); // Cria um modelo com nenhuma variável e nenhuma restrição glp_prob *model = glp_create_prob(); // Define o sentido da otimização que, para este problema, é minimização glp_set_obj_dir(model, GLP_MIN); // Cria as variáveis (colunas) no modelo // Para este problema são necessárias n*n variáveis // Estas n*n variáveis são definidas pelo GLPK através dos indices que vão de 1 até n*n (x1, x2, ..., x(n*n)) // Portanto, neste momento é importante determinar qual variável no GLPK (índice) representará qual variável x[i,j] // Para tanto, fazemos o mapeamento das variáveis x[i,j] utilizando a fórmula (i-1)*n + j // Isto é, a variável x[i,j] será representada pela variável de índice (i-1)*n + j no modelo do GLPK // Note que é imprescindível que cada índice (variável do GLPK) seja associado a no máximo uma variável x[i,j] // Caso contrário, uma variável do GLPK pode representar duas variáveis x[i,j] diferentes que assumem valores distintos nas soluções ótimas // Neste caso, o modelo estará incorreto glp_add_cols(model, n*n); // Ajuste dos tipos, limitantes e coeficientes da função objetivo das variáveis do modelo for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) { // Define o tipo da variável como sendo binária (em outros modelos poderia ser contínua (GLP_CV) ou inteira (GLP_IV)) glp_set_col_kind(model, (i-1)*n + j, GLP_BV); // Define o limitante inferior (0) e superior (1) da variável // Consultem no manual as outras forma para definir apenas o limitante inferior ou superior glp_set_col_bnds(model, (i-1)*n + j, GLP_DB, 0.0, 1.0); // Define o coeficiente da variável na função objetivo glp_set_obj_coef(model, (i-1)*n + j, c[i-1][j-1]); } // Cria no modelo 2n restrições (linhas) nulas (com os coeficientes e limitantes zerados) // Ou seja, neste momento é criada uma matriz de zeros que correspondem aos coeficientes das restrições do modelo // O próximo passo será modificar esta matriz de tal forma que ela represente as restrições do problema descrito glp_add_rows(model, 2*n); // Esta variável define qual das restrições (qual linha da matriz de coeficientes) estamos modificando // ************************************************************************************************************ // ATENÇÃO: perceba que as restrições (linhas), assim como as variáveis (colunas), são indexadas a partir de 1. // ************************************************************************************************************ constraintNumber = 1; // Preenchimento das restrições limitando a soma das linhas: // sum{j in 1..n} w[i,j]*x[i,j] <= u[i] para i in 1..n for (i = 1; i <= n; i++) { // Define o limite superior (RHS) da restrição glp_set_row_bnds(model, constraintNumber, GLP_UP, 0.0, u[i-1]); for (j = 1; j <= n; j++) { // Ajusta o índice da variável que será informado à rotina do GLPK constraintIndices[j] = (i-1)*n + j; // Ajusta o coeficiente da variável cujo índice foi definido na linha anterior para ser informado ao GLPK // ****************************************************************************************************** // ATENÇÃO: perceba que na matriz w os índices e colunas são indexados a partir de ZERO ! // ****************************************************************************************************** constraintCoefficients[j] = w[i-1][j-1]; } // Passa ao GLPK a restrição que acabou de ser definida nos vetores constraintIndices e constraintCoefficients glp_set_mat_row(model, constraintNumber, n, constraintIndices, constraintCoefficients); // atualiza o indice da próxima restrição a ser inserida constraintNumber++; } // Preenchimento das restrições limitando a soma das colunas: // sum{i in 1..n} w[i,j]*x[i,j] >= l[i] para j in 1..n for (j = 1; j <= n; j++) { // Define o limite inferior (RHS) da restrição glp_set_row_bnds(model, constraintNumber, GLP_LO, l[j-1], 0.0); for (i = 1; i <= n; i++) { // Ajusta o índice da variável que será informado a rotina do GLPK constraintIndices[i] = (i-1)*n + j; // Ajusta o coeficiente da variável cujo índice foi definido na linha anterior para ser informado ao GLPK constraintCoefficients[i] = w[i-1][j-1]; } // Passa ao GLPK a restrição que acabou de ser definida nos vetores constraintIndices e constraintCoefficients glp_set_mat_row(model, constraintNumber, n, constraintIndices, constraintCoefficients); // atualiza o indice da próxima restrição a ser inserida constraintNumber++; } // Define os parâmetros que serão passados ao resolvedor glp_iocp param; glp_init_iocp(¶m); // Ativa o presolver param.presolve = GLP_ON; // Resolve o modelo int status = glp_intopt(model, ¶m); // Verifica se houve algum erro durante a otimização if (status) { printf("Ocorreu um erro durante o processo de otimizacao.\n"); } else { // Verifica se o método encontrou uma solução status = glp_mip_status(model); if ((status == GLP_OPT) || (status == GLP_FEAS)) { // Imprime a solução encontrada if (status == GLP_OPT) printf("Solucao otima encontrada!\n"); else printf("A solucao encontrada pode nao ser otima!\n"); printf("Custo da solucao: %f\n", glp_mip_obj_val(model)); for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) printf("%f ", glp_mip_col_val(model, (i-1)*n + j)); printf("\n"); } } else { printf("Nenhuma solucao foi encontrada!\n"); } } // Desaloca os vetores free(constraintIndices); free(constraintCoefficients); return 0; }
int max_flow_lp(int nn, int ne, const int beg[/*1+ne*/], const int end[/*1+ne*/], const int cap[/*1+ne*/], int s, int t, int x[/*1+ne*/]) { glp_prob *lp; glp_smcp smcp; int i, k, nz, flow, *rn, *cn; double temp, *aa; /* create LP problem instance */ lp = glp_create_prob(); /* create LP rows; i-th row is the conservation condition of the * flow at i-th node, i = 1, ..., nn */ glp_add_rows(lp, nn); for (i = 1; i <= nn; i++) glp_set_row_bnds(lp, i, GLP_FX, 0.0, 0.0); /* create LP columns; k-th column is the elementary flow thru * k-th edge, k = 1, ..., ne; the last column with the number * ne+1 is the total flow through the network, which goes along * a dummy feedback edge from the sink to the source */ glp_add_cols(lp, ne+1); for (k = 1; k <= ne; k++) { xassert(cap[k] > 0); glp_set_col_bnds(lp, k, GLP_DB, -cap[k], +cap[k]); } glp_set_col_bnds(lp, ne+1, GLP_FR, 0.0, 0.0); /* build the constraint matrix; structurally this matrix is the * incidence matrix of the network, so each its column (including * the last column for the dummy edge) has exactly two non-zero * entries */ rn = xalloc(1+2*(ne+1), sizeof(int)); cn = xalloc(1+2*(ne+1), sizeof(int)); aa = xalloc(1+2*(ne+1), sizeof(double)); nz = 0; for (k = 1; k <= ne; k++) { /* x[k] > 0 means the elementary flow thru k-th edge goes from * node beg[k] to node end[k] */ nz++, rn[nz] = beg[k], cn[nz] = k, aa[nz] = -1.0; nz++, rn[nz] = end[k], cn[nz] = k, aa[nz] = +1.0; } /* total flow thru the network goes from the sink to the source * along the dummy feedback edge */ nz++, rn[nz] = t, cn[nz] = ne+1, aa[nz] = -1.0; nz++, rn[nz] = s, cn[nz] = ne+1, aa[nz] = +1.0; /* check the number of non-zero entries */ xassert(nz == 2*(ne+1)); /* load the constraint matrix into the LP problem object */ glp_load_matrix(lp, nz, rn, cn, aa); xfree(rn); xfree(cn); xfree(aa); /* objective function is the total flow through the network to * be maximized */ glp_set_obj_dir(lp, GLP_MAX); glp_set_obj_coef(lp, ne + 1, 1.0); /* solve LP instance with the (primal) simplex method */ glp_term_out(0); glp_adv_basis(lp, 0); glp_term_out(1); glp_init_smcp(&smcp); smcp.msg_lev = GLP_MSG_ON; smcp.out_dly = 5000; xassert(glp_simplex(lp, &smcp) == 0); xassert(glp_get_status(lp) == GLP_OPT); /* obtain optimal elementary flows thru edges of the network */ /* (note that the constraint matrix is unimodular and the data * are integral, so all elementary flows in basic solution should * also be integral) */ for (k = 1; k <= ne; k++) { temp = glp_get_col_prim(lp, k); x[k] = (int)floor(temp + .5); xassert(fabs(x[k] - temp) <= 1e-6); } /* obtain the maximum flow thru the original network which is the * flow thru the dummy feedback edge */ temp = glp_get_col_prim(lp, ne+1); flow = (int)floor(temp + .5); xassert(fabs(flow - temp) <= 1e-6); /* delete LP problem instance */ glp_delete_prob(lp); /* return to the calling program */ return flow; }
int glp_intfeas1(glp_prob *P, int use_bound, int obj_bound) { /* solve integer feasibility problem */ NPP *npp = NULL; glp_prob *mip = NULL; int *obj_ind = NULL; double *obj_val = NULL; int obj_row = 0; int i, j, k, obj_len, temp, ret; /* check the problem object */ if (P == NULL || P->magic != GLP_PROB_MAGIC) xerror("glp_intfeas1: P = %p; invalid problem object\n", P); if (P->tree != NULL) xerror("glp_intfeas1: operation not allowed\n"); /* integer solution is currently undefined */ P->mip_stat = GLP_UNDEF; P->mip_obj = 0.0; /* check columns (variables) */ for (j = 1; j <= P->n; j++) { GLPCOL *col = P->col[j]; #if 0 /* currently binarization is not yet implemented */ if (!(col->kind == GLP_IV || col->type == GLP_FX)) { xprintf("glp_intfeas1: column %d: non-integer non-fixed var" "iable not allowed\n", j); #else if (!((col->kind == GLP_IV && col->lb == 0.0 && col->ub == 1.0) || col->type == GLP_FX)) { xprintf("glp_intfeas1: column %d: non-binary non-fixed vari" "able not allowed\n", j); #endif ret = GLP_EDATA; goto done; } temp = (int)col->lb; if ((double)temp != col->lb) { if (col->type == GLP_FX) xprintf("glp_intfeas1: column %d: fixed value %g is non-" "integer or out of range\n", j, col->lb); else xprintf("glp_intfeas1: column %d: lower bound %g is non-" "integer or out of range\n", j, col->lb); ret = GLP_EDATA; goto done; } temp = (int)col->ub; if ((double)temp != col->ub) { xprintf("glp_intfeas1: column %d: upper bound %g is non-int" "eger or out of range\n", j, col->ub); ret = GLP_EDATA; goto done; } if (col->type == GLP_DB && col->lb > col->ub) { xprintf("glp_intfeas1: column %d: lower bound %g is greater" " than upper bound %g\n", j, col->lb, col->ub); ret = GLP_EBOUND; goto done; } } /* check rows (constraints) */ for (i = 1; i <= P->m; i++) { GLPROW *row = P->row[i]; GLPAIJ *aij; for (aij = row->ptr; aij != NULL; aij = aij->r_next) { temp = (int)aij->val; if ((double)temp != aij->val) { xprintf("glp_intfeas1: row = %d, column %d: constraint c" "oefficient %g is non-integer or out of range\n", i, aij->col->j, aij->val); ret = GLP_EDATA; goto done; } } temp = (int)row->lb; if ((double)temp != row->lb) { if (row->type == GLP_FX) xprintf("glp_intfeas1: row = %d: fixed value %g is non-i" "nteger or out of range\n", i, row->lb); else xprintf("glp_intfeas1: row = %d: lower bound %g is non-i" "nteger or out of range\n", i, row->lb); ret = GLP_EDATA; goto done; } temp = (int)row->ub; if ((double)temp != row->ub) { xprintf("glp_intfeas1: row = %d: upper bound %g is non-inte" "ger or out of range\n", i, row->ub); ret = GLP_EDATA; goto done; } if (row->type == GLP_DB && row->lb > row->ub) { xprintf("glp_intfeas1: row %d: lower bound %g is greater th" "an upper bound %g\n", i, row->lb, row->ub); ret = GLP_EBOUND; goto done; } } /* check the objective function */ temp = (int)P->c0; if ((double)temp != P->c0) { xprintf("glp_intfeas1: objective constant term %g is non-integ" "er or out of range\n", P->c0); ret = GLP_EDATA; goto done; } for (j = 1; j <= P->n; j++) { temp = (int)P->col[j]->coef; if ((double)temp != P->col[j]->coef) { xprintf("glp_intfeas1: column %d: objective coefficient is " "non-integer or out of range\n", j, P->col[j]->coef); ret = GLP_EDATA; goto done; } } /* save the objective function and set it to zero */ obj_ind = xcalloc(1+P->n, sizeof(int)); obj_val = xcalloc(1+P->n, sizeof(double)); obj_len = 0; obj_ind[0] = 0; obj_val[0] = P->c0; P->c0 = 0.0; for (j = 1; j <= P->n; j++) { if (P->col[j]->coef != 0.0) { obj_len++; obj_ind[obj_len] = j; obj_val[obj_len] = P->col[j]->coef; P->col[j]->coef = 0.0; } } /* add inequality to bound the objective function, if required */ if (!use_bound) xprintf("Will search for ANY feasible solution\n"); else { xprintf("Will search only for solution not worse than %d\n", obj_bound); obj_row = glp_add_rows(P, 1); glp_set_mat_row(P, obj_row, obj_len, obj_ind, obj_val); if (P->dir == GLP_MIN) glp_set_row_bnds(P, obj_row, GLP_UP, 0.0, (double)obj_bound - obj_val[0]); else if (P->dir == GLP_MAX) glp_set_row_bnds(P, obj_row, GLP_LO, (double)obj_bound - obj_val[0], 0.0); else xassert(P != P); } /* create preprocessor workspace */ xprintf("Translating to CNF-SAT...\n"); xprintf("Original problem has %d row%s, %d column%s, and %d non-z" "ero%s\n", P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s", P->nnz, P->nnz == 1 ? "" : "s"); npp = npp_create_wksp(); /* load the original problem into the preprocessor workspace */ npp_load_prob(npp, P, GLP_OFF, GLP_MIP, GLP_OFF); /* perform translation to SAT-CNF problem instance */ ret = npp_sat_encode_prob(npp); if (ret == 0) ; else if (ret == GLP_ENOPFS) xprintf("PROBLEM HAS NO INTEGER FEASIBLE SOLUTION\n"); else if (ret == GLP_ERANGE) xprintf("glp_intfeas1: translation to SAT-CNF failed because o" "f integer overflow\n"); else xassert(ret != ret); if (ret != 0) goto done; /* build SAT-CNF problem instance and try to solve it */ mip = glp_create_prob(); npp_build_prob(npp, mip); ret = glp_minisat1(mip); /* only integer feasible solution can be postprocessed */ if (!(mip->mip_stat == GLP_OPT || mip->mip_stat == GLP_FEAS)) { P->mip_stat = mip->mip_stat; goto done; } /* postprocess the solution found */ npp_postprocess(npp, mip); /* the transformed problem is no longer needed */ glp_delete_prob(mip), mip = NULL; /* store solution to the original problem object */ npp_unload_sol(npp, P); /* change the solution status to 'integer feasible' */ P->mip_stat = GLP_FEAS; /* check integer feasibility */ for (i = 1; i <= P->m; i++) { GLPROW *row; GLPAIJ *aij; double sum; row = P->row[i]; sum = 0.0; for (aij = row->ptr; aij != NULL; aij = aij->r_next) sum += aij->val * aij->col->mipx; xassert(sum == row->mipx); if (row->type == GLP_LO || row->type == GLP_DB || row->type == GLP_FX) xassert(sum >= row->lb); if (row->type == GLP_UP || row->type == GLP_DB || row->type == GLP_FX) xassert(sum <= row->ub); } /* compute value of the original objective function */ P->mip_obj = obj_val[0]; for (k = 1; k <= obj_len; k++) P->mip_obj += obj_val[k] * P->col[obj_ind[k]]->mipx; xprintf("Objective value = %17.9e\n", P->mip_obj); done: /* delete the transformed problem, if it exists */ if (mip != NULL) glp_delete_prob(mip); /* delete the preprocessor workspace, if it exists */ if (npp != NULL) npp_delete_wksp(npp); /* remove inequality used to bound the objective function */ if (obj_row > 0) { int ind[1+1]; ind[1] = obj_row; glp_del_rows(P, 1, ind); } /* restore the original objective function */ if (obj_ind != NULL) { P->c0 = obj_val[0]; for (k = 1; k <= obj_len; k++) P->col[obj_ind[k]]->coef = obj_val[k]; xfree(obj_ind); xfree(obj_val); } return ret; }
void glp_maxflow_lp(glp_prob *lp, glp_graph *G, int names, int s, int t, int a_cap) { glp_vertex *v; glp_arc *a; int i, j, type, ind[1+2]; double cap, val[1+2]; if (!(names == GLP_ON || names == GLP_OFF)) xerror("glp_maxflow_lp: names = %d; invalid parameter\n", names); if (!(1 <= s && s <= G->nv)) xerror("glp_maxflow_lp: s = %d; source node number out of rang" "e\n", s); if (!(1 <= t && t <= G->nv)) xerror("glp_maxflow_lp: t = %d: sink node number out of range " "\n", t); if (s == t) xerror("glp_maxflow_lp: s = t = %d; source and sink nodes must" " be distinct\n", s); if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) xerror("glp_maxflow_lp: a_cap = %d; invalid offset\n", a_cap); glp_erase_prob(lp); if (names) glp_set_prob_name(lp, G->name); glp_set_obj_dir(lp, GLP_MAX); glp_add_rows(lp, G->nv); for (i = 1; i <= G->nv; i++) { v = G->v[i]; if (names) glp_set_row_name(lp, i, v->name); if (i == s) type = GLP_LO; else if (i == t) type = GLP_UP; else type = GLP_FX; glp_set_row_bnds(lp, i, type, 0.0, 0.0); } if (G->na > 0) glp_add_cols(lp, G->na); for (i = 1, j = 0; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { j++; if (names) { char name[50+1]; sprintf(name, "x[%d,%d]", a->tail->i, a->head->i); xassert(strlen(name) < sizeof(name)); glp_set_col_name(lp, j, name); } if (a->tail->i != a->head->i) { ind[1] = a->tail->i, val[1] = +1.0; ind[2] = a->head->i, val[2] = -1.0; glp_set_mat_col(lp, j, 2, ind, val); } if (a_cap >= 0) memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); else cap = 1.0; if (cap == DBL_MAX) type = GLP_LO; else if (cap != 0.0) type = GLP_DB; else type = GLP_FX; glp_set_col_bnds(lp, j, type, 0.0, cap); if (a->tail->i == s) glp_set_obj_coef(lp, j, +1.0); else if (a->head->i == s) glp_set_obj_coef(lp, j, -1.0); } } xassert(j == G->na); return; }
void ios_feas_pump(glp_tree *T) { glp_prob *P = T->mip; int n = P->n; glp_prob *lp = NULL; struct VAR *var = NULL; RNG *rand = NULL; GLPCOL *col; glp_smcp parm; int j, k, new_x, nfail, npass, nv, ret, stalling; double dist, tol; xassert(glp_get_status(P) == GLP_OPT); /* this heuristic is applied only once on the root level */ if (!(T->curr->level == 0 && T->curr->solved == 1)) goto done; /* determine number of binary variables */ nv = 0; for (j = 1; j <= n; j++) { col = P->col[j]; /* if x[j] is continuous, skip it */ if (col->kind == GLP_CV) continue; /* if x[j] is fixed, skip it */ if (col->type == GLP_FX) continue; /* x[j] is non-fixed integer */ xassert(col->kind == GLP_IV); if (col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0) { /* x[j] is binary */ nv++; } else { /* x[j] is general integer */ if (T->parm->msg_lev >= GLP_MSG_ALL) xprintf("FPUMP heuristic cannot be applied due to genera" "l integer variables\n"); goto done; } } /* there must be at least one binary variable */ if (nv == 0) goto done; if (T->parm->msg_lev >= GLP_MSG_ALL) xprintf("Applying FPUMP heuristic...\n"); /* build the list of binary variables */ var = xcalloc(1+nv, sizeof(struct VAR)); k = 0; for (j = 1; j <= n; j++) { col = P->col[j]; if (col->kind == GLP_IV && col->type == GLP_DB) var[++k].j = j; } xassert(k == nv); /* create working problem object */ lp = glp_create_prob(); more: /* copy the original problem object to keep it intact */ glp_copy_prob(lp, P, GLP_OFF); /* we are interested to find an integer feasible solution, which is better than the best known one */ if (P->mip_stat == GLP_FEAS) { int *ind; double *val, bnd; /* add a row and make it identical to the objective row */ glp_add_rows(lp, 1); ind = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); for (j = 1; j <= n; j++) { ind[j] = j; val[j] = P->col[j]->coef; } glp_set_mat_row(lp, lp->m, n, ind, val); xfree(ind); xfree(val); /* introduce upper (minimization) or lower (maximization) bound to the original objective function; note that this additional constraint is not violated at the optimal point to LP relaxation */ #if 0 /* modified by xypron <*****@*****.**> */ if (P->dir == GLP_MIN) { bnd = P->mip_obj - 0.10 * (1.0 + fabs(P->mip_obj)); if (bnd < P->obj_val) bnd = P->obj_val; glp_set_row_bnds(lp, lp->m, GLP_UP, 0.0, bnd - P->c0); } else if (P->dir == GLP_MAX) { bnd = P->mip_obj + 0.10 * (1.0 + fabs(P->mip_obj)); if (bnd > P->obj_val) bnd = P->obj_val; glp_set_row_bnds(lp, lp->m, GLP_LO, bnd - P->c0, 0.0); } else xassert(P != P); #else bnd = 0.1 * P->obj_val + 0.9 * P->mip_obj; /* xprintf("bnd = %f\n", bnd); */ if (P->dir == GLP_MIN) glp_set_row_bnds(lp, lp->m, GLP_UP, 0.0, bnd - P->c0); else if (P->dir == GLP_MAX) glp_set_row_bnds(lp, lp->m, GLP_LO, bnd - P->c0, 0.0); else xassert(P != P); #endif } /* reset pass count */ npass = 0; /* invalidate the rounded point */ for (k = 1; k <= nv; k++) var[k].x = -1; pass: /* next pass starts here */ npass++; if (T->parm->msg_lev >= GLP_MSG_ALL) xprintf("Pass %d\n", npass); /* initialize minimal distance between the basic point and the rounded one obtained during this pass */ dist = DBL_MAX; /* reset failure count (the number of succeeded iterations failed to improve the distance) */ nfail = 0; /* if it is not the first pass, perturb the last rounded point rather than construct it from the basic solution */ if (npass > 1) { double rho, temp; if (rand == NULL) rand = rng_create_rand(); for (k = 1; k <= nv; k++) { j = var[k].j; col = lp->col[j]; rho = rng_uniform(rand, -0.3, 0.7); if (rho < 0.0) rho = 0.0; temp = fabs((double)var[k].x - col->prim); if (temp + rho > 0.5) var[k].x = 1 - var[k].x; } goto skip; } loop: /* innermost loop begins here */ /* round basic solution (which is assumed primal feasible) */ stalling = 1; for (k = 1; k <= nv; k++) { col = lp->col[var[k].j]; if (col->prim < 0.5) { /* rounded value is 0 */ new_x = 0; } else { /* rounded value is 1 */ new_x = 1; } if (var[k].x != new_x) { stalling = 0; var[k].x = new_x; } } /* if the rounded point has not changed (stalling), choose and flip some its entries heuristically */ if (stalling) { /* compute d[j] = |x[j] - round(x[j])| */ for (k = 1; k <= nv; k++) { col = lp->col[var[k].j]; var[k].d = fabs(col->prim - (double)var[k].x); } /* sort the list of binary variables by descending d[j] */ qsort(&var[1], nv, sizeof(struct VAR), fcmp); /* choose and flip some rounded components */ for (k = 1; k <= nv; k++) { if (k >= 5 && var[k].d < 0.35 || k >= 10) break; var[k].x = 1 - var[k].x; } } skip: /* check if the time limit has been exhausted */ if (T->parm->tm_lim < INT_MAX && (double)(T->parm->tm_lim - 1) <= 1000.0 * xdifftime(xtime(), T->tm_beg)) goto done; /* build the objective, which is the distance between the current (basic) point and the rounded one */ lp->dir = GLP_MIN; lp->c0 = 0.0; for (j = 1; j <= n; j++) lp->col[j]->coef = 0.0; for (k = 1; k <= nv; k++) { j = var[k].j; if (var[k].x == 0) lp->col[j]->coef = +1.0; else { lp->col[j]->coef = -1.0; lp->c0 += 1.0; } } /* minimize the distance with the simplex method */ glp_init_smcp(&parm); if (T->parm->msg_lev <= GLP_MSG_ERR) parm.msg_lev = T->parm->msg_lev; else if (T->parm->msg_lev <= GLP_MSG_ALL) { parm.msg_lev = GLP_MSG_ON; parm.out_dly = 10000; } ret = glp_simplex(lp, &parm); if (ret != 0) { if (T->parm->msg_lev >= GLP_MSG_ERR) xprintf("Warning: glp_simplex returned %d\n", ret); goto done; } ret = glp_get_status(lp); if (ret != GLP_OPT) { if (T->parm->msg_lev >= GLP_MSG_ERR) xprintf("Warning: glp_get_status returned %d\n", ret); goto done; } if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("delta = %g\n", lp->obj_val); /* check if the basic solution is integer feasible; note that it may be so even if the minimial distance is positive */ tol = 0.3 * T->parm->tol_int; for (k = 1; k <= nv; k++) { col = lp->col[var[k].j]; if (tol < col->prim && col->prim < 1.0 - tol) break; } if (k > nv) { /* okay; the basic solution seems to be integer feasible */ double *x = xcalloc(1+n, sizeof(double)); for (j = 1; j <= n; j++) { x[j] = lp->col[j]->prim; if (P->col[j]->kind == GLP_IV) x[j] = floor(x[j] + 0.5); } #if 1 /* modified by xypron <*****@*****.**> */ /* reset direction and right-hand side of objective */ lp->c0 = P->c0; lp->dir = P->dir; /* fix integer variables */ for (k = 1; k <= nv; k++) #if 0 /* 18/VI-2013; fixed by mao * this bug causes numerical instability, because column statuses * are not changed appropriately */ { lp->col[var[k].j]->lb = x[var[k].j]; lp->col[var[k].j]->ub = x[var[k].j]; lp->col[var[k].j]->type = GLP_FX; } #else glp_set_col_bnds(lp, var[k].j, GLP_FX, x[var[k].j], 0.); #endif /* copy original objective function */ for (j = 1; j <= n; j++) lp->col[j]->coef = P->col[j]->coef; /* solve original LP and copy result */ ret = glp_simplex(lp, &parm); if (ret != 0) { if (T->parm->msg_lev >= GLP_MSG_ERR) xprintf("Warning: glp_simplex returned %d\n", ret); goto done; } ret = glp_get_status(lp); if (ret != GLP_OPT) { if (T->parm->msg_lev >= GLP_MSG_ERR) xprintf("Warning: glp_get_status returned %d\n", ret); goto done; } for (j = 1; j <= n; j++) if (P->col[j]->kind != GLP_IV) x[j] = lp->col[j]->prim; #endif ret = glp_ios_heur_sol(T, x); xfree(x); if (ret == 0) { /* the integer solution is accepted */ if (ios_is_hopeful(T, T->curr->bound)) { /* it is reasonable to apply the heuristic once again */ goto more; } else { /* the best known integer feasible solution just found is close to optimal solution to LP relaxation */ goto done; } } }
void glp_mincost_lp(glp_prob *lp, glp_graph *G, int names, int v_rhs, int a_low, int a_cap, int a_cost) { glp_vertex *v; glp_arc *a; int i, j, type, ind[1+2]; double rhs, low, cap, cost, val[1+2]; if (!(names == GLP_ON || names == GLP_OFF)) xerror("glp_mincost_lp: names = %d; invalid parameter\n", names); if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) xerror("glp_mincost_lp: v_rhs = %d; invalid offset\n", v_rhs); if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) xerror("glp_mincost_lp: a_low = %d; invalid offset\n", a_low); if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) xerror("glp_mincost_lp: a_cap = %d; invalid offset\n", a_cap); if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) xerror("glp_mincost_lp: a_cost = %d; invalid offset\n", a_cost) ; glp_erase_prob(lp); if (names) glp_set_prob_name(lp, G->name); if (G->nv > 0) glp_add_rows(lp, G->nv); for (i = 1; i <= G->nv; i++) { v = G->v[i]; if (names) glp_set_row_name(lp, i, v->name); if (v_rhs >= 0) memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double)); else rhs = 0.0; glp_set_row_bnds(lp, i, GLP_FX, rhs, rhs); } if (G->na > 0) glp_add_cols(lp, G->na); for (i = 1, j = 0; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { j++; if (names) { char name[50+1]; sprintf(name, "x[%d,%d]", a->tail->i, a->head->i); xassert(strlen(name) < sizeof(name)); glp_set_col_name(lp, j, name); } if (a->tail->i != a->head->i) { ind[1] = a->tail->i, val[1] = +1.0; ind[2] = a->head->i, val[2] = -1.0; glp_set_mat_col(lp, j, 2, ind, val); } if (a_low >= 0) memcpy(&low, (char *)a->data + a_low, sizeof(double)); else low = 0.0; if (a_cap >= 0) memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); else cap = 1.0; if (cap == DBL_MAX) type = GLP_LO; else if (low != cap) type = GLP_DB; else type = GLP_FX; glp_set_col_bnds(lp, j, type, low, cap); if (a_cost >= 0) memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); else cost = 0.0; glp_set_obj_coef(lp, j, cost); } } xassert(j == G->na); return; }
int main(int argc, char *argv[]) { /* Structures de données propres à GLPK */ glp_prob *prob; // Déclaration d'un pointeur sur le problème int ia[1 + NBCREUX]; int ja[1 + NBCREUX]; double ar[1 + NBCREUX]; // Déclaration des 3 tableaux servant à définir la partie creuse de la matrice des contraintes /* Variables récupérant les résultats de la résolution du problème (fonction objectif et valeur des variables) */ int i, j; double z; double x[NBVAR]; // Autres variables int * p = (int*)malloc(n * sizeof(int)); p[1] = 34; p[2] = 6; p[3] = 8; p[4] = 17; p[5] = 16; p[6] = 5; p[7] = 13; p[8] = 21; p[9] = 25; p[10] = 31; p[11] = 14; p[12] = 13; p[13] = 33; p[14] = 9; p[15] = 25; p[16] = 25; /* Transfert de ces données dans les structures utilisées par la bibliothèque GLPK */ prob = glp_create_prob(); /* allocation mémoire pour le problème */ glp_set_prob_name(prob, "wagons"); /* affectation d'un nom */ glp_set_obj_dir(prob, GLP_MIN); /* Il s'agit d'un problème de minimisation */ /* Déclaration du nombre de contraintes (nombre de lignes de la matrice des contraintes) */ glp_add_rows(prob, NBCONTR); /* On commence par préciser les bornes sur les contraintes, les indices commencent à 1 (!) dans GLPK */ /* Premier ensemble de contraintes ( c = 1 ) */ for(i = 1; i <= n; i++) { glp_set_row_bnds(prob, i, GLP_FX, 1.0, 1.0); } /* Second ensembles de contraintes (c <= 0 ) */ for(i = n + 1; i <= NBCONTR; i++) { glp_set_row_bnds(prob, i, GLP_UP, 0.0, 0.0); } /* Déclaration du nombre de variables */ glp_add_cols(prob, NBVAR); /* On précise le type des variables, les indices commencent à 1 également pour les variables! */ for(i = 1; i <= NBVAR - 1; i++) { glp_set_col_bnds(prob, i, GLP_DB, 0.0, 1.0); glp_set_col_kind(prob, i, GLP_BV); /* les variables sont binaires */ } glp_set_col_bnds(prob, NBVAR, GLP_LO, 0.0, 0.0); /* La dernière variables est continue (par défaut) non négative */ /* Définition des coefficients des variables dans la fonction objectif */ for(i = 1;i <= n*m;i++) { glp_set_obj_coef(prob,i,0.0); // Tous les coûts sont à 0 (sauf le dernier) } /* Dernier coût (qui vaut 1) */ glp_set_obj_coef(prob,n*m + 1,1.0); /* Définition des coefficients non-nuls dans la matrice des contraintes, autrement dit les coefficients de la matrice creuse */ int pos = 1; for(i = 1; i <= n; i++) { for(j = 1; j <= m; j++) { // Première moitié de la matrice ja[pos] = (i - 1)*m + j; ia[pos] = i; ar[pos] = 1; pos++; // Deuxième moitié de la matrice ja[pos] = (i - 1)*m + j; ia[pos] = n + j; ar[pos] = p[i]; pos++; } } // ajout des -1 dans la dernière colonne for(i = n + 1; i <= n + m; i++) { ja[pos] = n*m + 1; ia[pos] = i; ar[pos] = -1; pos++; } /* Chargement de la matrice dans le problème */ glp_load_matrix(prob,NBCREUX,ia,ja,ar); /* Ecriture de la modélisation dans un fichier */ glp_write_lp(prob,NULL,"wagons.lp"); /* Résolution, puis lecture des résultats */ glp_simplex(prob,NULL); glp_intopt(prob,NULL); /* Résolution */ z = glp_mip_obj_val(prob); /* Récupération de la valeur optimale. Dans le cas d'un problème en variables continues, l'appel est différent : z = glp_get_obj_val(prob); */ for(i = 0;i < NBVAR; i++) x[i] = glp_mip_col_val(prob,i+1); /* Récupération de la valeur des variables, Appel différent dans le cas d'un problème en variables continues : for(i = 0;i < p.nbvar;i++) x[i] = glp_get_col_prim(prob,i+1); */ printf("z = %lf\n",z); for(i = 0;i < NBVAR;i++) printf("x%c = %d, ",'B'+i,(int)(x[i] + 0.5)); /* un cast est ajouté, x[i] pourrait être égal à 0.99999... */ puts(""); /* Libération de la mémoire */ glp_delete_prob(prob); free(p); return 0; }
static void mlp_add_constraints_all_addresses (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_MultiHashMap * addresses) { unsigned int n_addresses; int c; char *name; /* Problem matrix*/ n_addresses = GNUNET_CONTAINER_multihashmap_size(addresses); /* Required indices in the constrain matrix * * feasibility constraints: * * c 1) bandwidth capping * #rows: |n_addresses| * #indices: 2 * |n_addresses| * * c 2) one active address per peer * #rows: |peers| * #indices: |n_addresses| * * c 3) minium bandwidth assigned * #rows: |n_addresses| * #indices: 2 * |n_addresses| * * c 4) minimum number of active connections * #rows: 1 * #indices: |n_addresses| * * c 5) maximum ressource consumption * #rows: |ressources| * #indices: |n_addresses| * * c 10) obey network specific quota * #rows: |network types * #indices: |n_addresses| * * Sum for feasibility constraints: * #rows: 3 * |n_addresses| + |ressources| + |peers| + 1 * #indices: 7 * |n_addresses| * * optimality constraints: * * c 6) diversity * #rows: 1 * #indices: |n_addresses| + 1 * * c 7) quality * #rows: |quality properties| * #indices: |n_addresses| + |quality properties| * * c 8) utilization * #rows: 1 * #indices: |n_addresses| + 1 * * c 9) relativity * #rows: |peers| * #indices: |n_addresses| + |peers| * */ /* last +1 caused by glpk index starting with one: [1..pi]*/ int pi = ((7 * n_addresses) + (5 * n_addresses + mlp->m_q + mlp->c_p + 2) + 1); mlp->cm_size = pi; mlp->ci = 1; /* row index */ int *ia = GNUNET_malloc (pi * sizeof (int)); mlp->ia = ia; /* column index */ int *ja = GNUNET_malloc (pi * sizeof (int)); mlp->ja = ja; /* coefficient */ double *ar= GNUNET_malloc (pi * sizeof (double)); mlp->ar = ar; /* Adding constraint rows * This constraints are kind of "for all addresses" * Feasibility constraints: * * c 1) bandwidth capping * c 3) minimum bandwidth * c 4) minimum number of connections * c 6) maximize diversity * c 10) obey network specific quota */ /* Row for c4) minimum connection */ int min = mlp->n_min; /* Number of minimum connections is min(|Peers|, n_min) */ if (mlp->n_min > mlp->c_p) min = mlp->c_p; mlp->r_c4 = glp_add_rows (mlp->prob, 1); glp_set_row_name (mlp->prob, mlp->r_c4, "c4"); glp_set_row_bnds (mlp->prob, mlp->r_c4, GLP_LO, min, min); /* Add row for c6) */ mlp->r_c6 = glp_add_rows (mlp->prob, 1); /* Set type type to fix */ glp_set_row_bnds (mlp->prob, mlp->r_c6, GLP_FX, 0.0, 0.0); /* Setting -D */ ia[mlp->ci] = mlp->r_c6 ; ja[mlp->ci] = mlp->c_d; ar[mlp->ci] = -1; mlp->ci++; /* Add rows for c 10) */ for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++) { mlp->r_quota[c] = glp_add_rows (mlp->prob, 1); char * text; GNUNET_asprintf(&text, "quota_ats_%i", mlp->quota_index[c]); glp_set_row_name (mlp->prob, mlp->r_quota[c], text); GNUNET_free (text); /* Set bounds to 0 <= x <= quota_out */ glp_set_row_bnds (mlp->prob, mlp->r_quota[c], GLP_UP, 0.0, mlp->quota_out[c]); } GNUNET_CONTAINER_multihashmap_iterate (addresses, create_constraint_it, mlp); /* Adding constraint rows * This constraints are kind of "for all peers" * Feasibility constraints: * * c 2) 1 address per peer * sum (n_p1_1 + ... + n_p1_n) = 1 * * c 8) utilization * sum (f_p * b_p1_1 + ... + f_p * b_p1_n) - u = 0 * * c 9) relativity * V p : sum (bt_1 + ... +bt_n) - f_p * r = 0 * */ /* Adding rows for c 8) */ mlp->r_c8 = glp_add_rows (mlp->prob, mlp->c_p); glp_set_row_name (mlp->prob, mlp->r_c8, "c8"); /* Set row bound == 0 */ glp_set_row_bnds (mlp->prob, mlp->r_c8, GLP_FX, 0.0, 0.0); /* -u */ ia[mlp->ci] = mlp->r_c8; ja[mlp->ci] = mlp->c_u; ar[mlp->ci] = -1; mlp->ci++; struct ATS_Peer * peer = mlp->peer_head; /* For all peers */ while (peer != NULL) { struct ATS_Address *addr = peer->head; struct MLP_information *mlpi = NULL; /* Adding rows for c 2) */ peer->r_c2 = glp_add_rows (mlp->prob, 1); GNUNET_asprintf(&name, "c2_%s", GNUNET_i2s(&peer->id)); glp_set_row_name (mlp->prob, peer->r_c2, name); GNUNET_free (name); /* Set row bound == 1 */ glp_set_row_bnds (mlp->prob, peer->r_c2, GLP_FX, 1.0, 1.0); /* Adding rows for c 9) */ #if ENABLE_C9 peer->r_c9 = glp_add_rows (mlp->prob, 1); GNUNET_asprintf(&name, "c9_%s", GNUNET_i2s(&peer->id)); glp_set_row_name (mlp->prob, peer->r_c9, name); GNUNET_free (name); /* Set row bound == 0 */ glp_set_row_bnds (mlp->prob, peer->r_c9, GLP_LO, 0.0, 0.0); /* Set -r */ ia[mlp->ci] = peer->r_c9; ja[mlp->ci] = mlp->c_r; ar[mlp->ci] = -peer->f; mlp->ci++; #endif /* For all addresses of this peer */ while (addr != NULL) { mlpi = (struct MLP_information *) addr->mlp_information; /* coefficient for c 2) */ ia[mlp->ci] = peer->r_c2; ja[mlp->ci] = mlpi->c_n; ar[mlp->ci] = 1; mlp->ci++; /* coefficient for c 8) */ ia[mlp->ci] = mlp->r_c8; ja[mlp->ci] = mlpi->c_b; ar[mlp->ci] = peer->f; mlp->ci++; #if ENABLE_C9 /* coefficient for c 9) */ ia[mlp->ci] = peer->r_c9; ja[mlp->ci] = mlpi->c_b; ar[mlp->ci] = 1; mlp->ci++; #endif addr = addr->next; } peer = peer->next; } /* c 7) For all quality metrics */ for (c = 0; c < mlp->m_q; c++) { struct ATS_Peer *tp; struct ATS_Address *ta; struct MLP_information * mlpi; double value = 1.0; /* Adding rows for c 7) */ mlp->r_q[c] = glp_add_rows (mlp->prob, 1); GNUNET_asprintf(&name, "c7_q%i_%s", c, mlp_ats_to_string(mlp->q[c])); glp_set_row_name (mlp->prob, mlp->r_q[c], name); GNUNET_free (name); /* Set row bound == 0 */ glp_set_row_bnds (mlp->prob, mlp->r_q[c], GLP_FX, 0.0, 0.0); ia[mlp->ci] = mlp->r_q[c]; ja[mlp->ci] = mlp->c_q[c]; ar[mlp->ci] = -1; mlp->ci++; for (tp = mlp->peer_head; tp != NULL; tp = tp->next) for (ta = tp->head; ta != NULL; ta = ta->next) { mlpi = ta->mlp_information; value = mlpi->q_averaged[c]; mlpi->r_q[c] = mlp->r_q[c]; ia[mlp->ci] = mlp->r_q[c]; ja[mlp->ci] = mlpi->c_b; ar[mlp->ci] = tp->f_q[c] * value; mlp->ci++; } } }
/** * Add constraints that are iterating over "forall addresses" * and collects all existing peers for "forall peers" constraints * * @param cls GAS_MLP_Handle * @param key Hashcode * @param value ATS_Address * * @return GNUNET_OK to continue */ static int create_constraint_it (void *cls, const GNUNET_HashCode * key, void *value) { struct GAS_MLP_Handle *mlp = cls; struct ATS_Address *address = value; struct MLP_information *mlpi; unsigned int row_index; char *name; GNUNET_assert (address->mlp_information != NULL); mlpi = (struct MLP_information *) address->mlp_information; /* c 1) bandwidth capping * b_t + (-M) * n_t <= 0 */ row_index = glp_add_rows (mlp->prob, 1); mlpi->r_c1 = row_index; /* set row name */ GNUNET_asprintf(&name, "c1_%s_%s", GNUNET_i2s(&address->peer), address->plugin); glp_set_row_name (mlp->prob, row_index, name); GNUNET_free (name); /* set row bounds: <= 0 */ glp_set_row_bnds (mlp->prob, row_index, GLP_UP, 0.0, 0.0); mlp->ia[mlp->ci] = row_index; mlp->ja[mlp->ci] = mlpi->c_b; mlp->ar[mlp->ci] = 1; mlp->ci++; mlp->ia[mlp->ci] = row_index; mlp->ja[mlp->ci] = mlpi->c_n; mlp->ar[mlp->ci] = -mlp->BIG_M; mlp->ci++; /* c 3) minimum bandwidth * b_t + (-n_t * b_min) >= 0 */ row_index = glp_add_rows (mlp->prob, 1); /* set row name */ GNUNET_asprintf(&name, "c3_%s_%s", GNUNET_i2s(&address->peer), address->plugin); glp_set_row_name (mlp->prob, row_index, name); GNUNET_free (name); mlpi->r_c3 = row_index; /* set row bounds: >= 0 */ glp_set_row_bnds (mlp->prob, row_index, GLP_LO, 0.0, 0.0); mlp->ia[mlp->ci] = row_index; mlp->ja[mlp->ci] = mlpi->c_b; mlp->ar[mlp->ci] = 1; mlp->ci++; mlp->ia[mlp->ci] = row_index; mlp->ja[mlp->ci] = mlpi->c_n; mlp->ar[mlp->ci] = - (double) mlp->b_min; mlp->ci++; /* c 4) minimum connections * (1)*n_1 + ... + (1)*n_m >= n_min */ mlp->ia[mlp->ci] = mlp->r_c4; mlp->ja[mlp->ci] = mlpi->c_n; mlp->ar[mlp->ci] = 1; mlp->ci++; /* c 6) maximize diversity * (1)*n_1 + ... + (1)*n_m - d == 0 */ mlp->ia[mlp->ci] = mlp->r_c6; mlp->ja[mlp->ci] = mlpi->c_n; mlp->ar[mlp->ci] = 1; mlp->ci++; /* c 10) obey network specific quotas * (1)*b_1 + ... + (1)*b_m <= quota_n */ int cur_row = 0; int c; for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++) { if (mlp->quota_index[c] == address->atsp_network_type) { cur_row = mlp->r_quota[c]; break; } } if (cur_row != 0) { mlp->ia[mlp->ci] = cur_row; mlp->ja[mlp->ci] = mlpi->c_b; mlp->ar[mlp->ci] = 1; mlp->ci++; } else { GNUNET_break (0); } return GNUNET_OK; }
void npp_build_prob(NPP *npp, glp_prob *prob) { /* build resultant (preprocessed) problem */ NPPROW *row; NPPCOL *col; NPPAIJ *aij; int i, j, type, len, *ind; double dir, *val; glp_erase_prob(prob); glp_set_prob_name(prob, npp->name); glp_set_obj_name(prob, npp->obj); glp_set_obj_dir(prob, npp->orig_dir); if (npp->orig_dir == GLP_MIN) dir = +1.0; else if (npp->orig_dir == GLP_MAX) dir = -1.0; else xassert(npp != npp); glp_set_obj_coef(prob, 0, dir * npp->c0); /* build rows */ for (row = npp->r_head; row != NULL; row = row->next) { row->temp = i = glp_add_rows(prob, 1); glp_set_row_name(prob, i, row->name); if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) type = GLP_FR; else if (row->ub == +DBL_MAX) type = GLP_LO; else if (row->lb == -DBL_MAX) type = GLP_UP; else if (row->lb != row->ub) type = GLP_DB; else type = GLP_FX; glp_set_row_bnds(prob, i, type, row->lb, row->ub); } /* build columns and the constraint matrix */ ind = xcalloc(1+prob->m, sizeof(int)); val = xcalloc(1+prob->m, sizeof(double)); for (col = npp->c_head; col != NULL; col = col->next) { j = glp_add_cols(prob, 1); glp_set_col_name(prob, j, col->name); #if 0 glp_set_col_kind(prob, j, col->kind); #else glp_set_col_kind(prob, j, col->is_int ? GLP_IV : GLP_CV); #endif if (col->lb == -DBL_MAX && col->ub == +DBL_MAX) type = GLP_FR; else if (col->ub == +DBL_MAX) type = GLP_LO; else if (col->lb == -DBL_MAX) type = GLP_UP; else if (col->lb != col->ub) type = GLP_DB; else type = GLP_FX; glp_set_col_bnds(prob, j, type, col->lb, col->ub); glp_set_obj_coef(prob, j, dir * col->coef); len = 0; for (aij = col->ptr; aij != NULL; aij = aij->c_next) { len++; ind[len] = aij->row->temp; val[len] = aij->val; } glp_set_mat_col(prob, j, len, ind, val); } xfree(ind); xfree(val); /* resultant problem has been built */ npp->m = prob->m; npp->n = prob->n; npp->nnz = prob->nnz; npp->row_ref = xcalloc(1+npp->m, sizeof(int)); npp->col_ref = xcalloc(1+npp->n, sizeof(int)); for (row = npp->r_head, i = 0; row != NULL; row = row->next) npp->row_ref[++i] = row->i; for (col = npp->c_head, j = 0; col != NULL; col = col->next) npp->col_ref[++j] = col->j; /* transformed problem segment is no longer needed */ dmp_delete_pool(npp->pool), npp->pool = NULL; npp->name = npp->obj = NULL; npp->c0 = 0.0; npp->r_head = npp->r_tail = NULL; npp->c_head = npp->c_tail = NULL; return; }