/* Set the type of constraint in row Row (LE, GE, EQ) */ long __declspec(dllexport) WINAPI _set_constr_type(lprec *lp, long row, long con_type) { long ret; if (lp != NULL) { freebuferror(); ret = set_constr_type(lp, row, (short) con_type); } else ret = 0; return(ret); }
// check, if v is a positive integer combination of the vectors in gens bool is_spanned_by(const VecSparse& v, const std::set<VecSparse>& gens) { #ifdef LPSOLVE_OPT // std::cout << "Check: is " << v << "spanned by " << gens << "?..."; if(gens.empty()) { return false; } if(v.empty()) { return true; } if(gens.find(v) != gens.end()) { //std::cout << "trivially spanned!"<<std::endl; return true; } lprec *lp; unsigned int N = gens.size(); // dim = number of variables that "gens" is talking about (altogether) //collect the variables of all the sparse vectors (v and gens) and number them unsigned int num_vars = 1; //we start counting at 1, since the 0-th row will be the values of the objective function std::map<VarPtr, unsigned int> vars; for(auto &pair : v) { if(vars.find(pair.first) == vars.end()) { vars[pair.first] = num_vars; num_vars++; } } for(auto &g : gens) { for(auto &pair : g) { if(vars.find(pair.first) == vars.end()) { vars[pair.first] = num_vars; num_vars++; } } } unsigned int dim = num_vars-1; lp = make_lp(dim, N); //first row = objective function (will be zeros in our case)! if(lp==NULL) { std::cerr << "ERROR: could not create LP (make_lp) of size " << dim+1 << "," << N << std::endl; return false; } set_verbose(lp, IMPORTANT); int colno = 1; // set the columns of the LP to the generators for (auto &g : gens) { int num_entries = g.size(); //std::cout << "num_entries: " << num_entries << std::endl; REAL *sparsecolumn = new REAL[num_entries]; //non-zero-vals int *rowno = new int[num_entries]; //numbers of the non-zero rows int idx = 0; //assemble the columns and write them to the LP for(auto &pair : g) { sparsecolumn[idx] = pair.second; rowno[idx] = vars[pair.first]; idx++; } set_columnex(lp, colno, num_entries, sparsecolumn, rowno); colno++; delete[] sparsecolumn; delete[] rowno; } // set the rhs to v REAL *rhs = new REAL[dim+1]; for(auto pair : v) { rhs[vars[pair.first]] = pair.second; } set_rh_vec(lp, rhs); delete[] rhs; // set all variables to be integers and >=0 for(int i=1; i<=N; i++){ set_int(lp, i, TRUE); // set_lowbo(lp, i, 0); // the default should be 0 anyways } for(int i=1; i<=dim; i++){ set_constr_type(lp, i, EQ); } set_maxim(lp); //print_lp(lp); int ret = solve(lp); if(ret == 0) { // std::cout << "yes!" << std::endl; //feasible solution found /* REAL *row = new REAL[N]; get_variables(lp, row); for(int j = 0; j < N; j++) printf("%s: %f\n", get_col_name(lp, j + 1), row[j]); delete[] row; */ return true; } else if(ret == 2) { // std::cout << "no!" << std::endl; // LP is infeasible return false; } else { std::cerr << "ERROR: lp_solve returned: " << ret << std::endl; return false; } #else return false; #endif }
main(int argc, char **argv) #endif { char *stub; ASL *asl; FILE *nl; lprec *lp; ograd *og; int ct, i, intmin, *is, j, j0, j1, k, nalt, rc; short *basis, *lower; real *LU, *c, lb, objadj, *rshift, *shift, t, ub, *x, *x0, *x1; char buf[256]; typedef struct { char *msg; int code; } Sol_info; static Sol_info solinfo[] = { { "optimal", 0 }, { "integer programming failure", 502 }, { "infeasible", 200 }, { "unbounded", 300 }, { "failure", 501 }, { "bug", 500 } }; sprintf(lp_solve_version+9, "%.*s", (int)sizeof(lp_solve_version)-10, PATCHLEVEL); sprintf(lp_solve_vversion, "%s, driver(20001002)", lp_solve_version); asl = ASL_alloc(ASL_read_f); stub = getstub(&argv, &Oinfo); nl = jac0dim(stub, (fint)strlen(stub)); suf_declare(suftab, sizeof(suftab)/sizeof(SufDecl)); /* set A_vals to get the constraints column-wise */ A_vals = (real *)M1alloc(nzc*sizeof(real)); f_read(nl,0); lp = make_lp(n_con, 0); Oinfo.uinfo = (char *)lp; if (getopts(argv, &Oinfo)) return 1; i = n_var + n_con + 1; x = (real*)M1alloc(i*sizeof(real)); /* scratch vector */ memset(x, 0, i*sizeof(real)); x0 = x++; c = x + n_con; /* supply objective */ objadj = 0; if (--nobj >= 0 && nobj < n_obj) { for(og = Ograd[nobj]; og; og = og->next) c[og->varno] = og->coef; if (objtype[nobj]) set_maxim(lp); objadj = objconst(nobj); } /* supply columns and variable bounds */ LU = LUv; intmin = n_var - (nbv + niv); j1 = nalt = 0; rshift = shift = 0; for(i = 1; i <= n_var; i++, LU += 2) { lb = LU[0]; ub = LU[1]; j0 = j1; j1 = A_colstarts[i]; *x0 = *c++; /* cost coefficient */ if (lb <= negInfinity && ub < Infinity) { /* negate this variable */ nalt++; lb = -ub; ub = -LU[0]; for(j = j0; j < j1; j++) x[A_rownos[j]] = -A_vals[j]; *x0 = -*x0; add_column(lp, x0); if (lb) goto shift_check; } else { for(j = j0; j < j1; j++) x[A_rownos[j]] = A_vals[j]; add_column(lp, x0); if (lb <= negInfinity) { nalt++; if (i > intmin) set_int(lp, lp->columns, TRUE); /* split free variable */ *x0 = -*x0; for(j = j0; j < j1; j++) x[A_rownos[j]] *= -1.; add_column(lp,x0); } else if (lb) { shift_check: if (lb > 0) set_lowbo(lp, lp->columns, lb); else { if (!rshift) { rshift = (real*)M1zapalloc( (n_var+n_con)*sizeof(real)); shift = rshift + n_con - 1; } shift[i] = lb; for(j = j0; j < j1; j++) { k = A_rownos[j]; rshift[k] += lb*x[k]; } if (ub < Infinity) ub -= lb; objadj += lb**x0; } } if (ub < Infinity) set_upbo(lp, lp->columns, ub); } for(j = j0; j < j1; j++) x[A_rownos[j]] = 0; if (i > intmin) set_int(lp, lp->columns, TRUE); } if (objadj) { /* add a fixed variable to adjust the objective value */ *x0 = objadj; add_column(lp, x0); set_lowbo(lp, i, 1.); set_upbo(lp, i, 1.); } /* supply constraint rhs */ LU = LUrhs; for(i = 1; i <= n_con; i++, LU += 2) { t = LU[0]; if (t == LU[1]) ct = EQ; else if (t <= negInfinity) { t = LU[1]; if (t >= Infinity) { /* This is possible only with effort: */ /* one must turn presolve off and */ /* explicitly specify a constraint */ /* with infinite bounds. */ fprintf(Stderr, "Sorry, can't handle free rows.\n"); exit(1); } ct = LE; } else ct = GE; set_constr_type(lp, i, ct); set_rh(lp, i, rshift ? t - *rshift++ : t); if (ct == GE && LU[1] < Infinity) lp->orig_upbo[i] = LU[1] - t; } if (prlp) print_lp(lp); if (scaling) auto_scale(lp); /* Unfortunately, there seems to be no way to suggest */ /* a starting basis to lp_solve; thus we must ignore */ /* any incoming .sstatus values. */ rc = solve(lp); if (rc < 0 || rc > 5) rc = 5; solve_result_num = solinfo[rc].code; i = sprintf(buf, "%s: %s", Oinfo.bsname, solinfo[rc].msg); if (rc == OPTIMAL) i += sprintf(buf+i, ", objective %.*g", obj_prec(), lp->best_solution[0]); i += sprintf(buf+i,"\n%d simplex iterations", lp->total_iter); if (lp->max_level > 1 || lp->total_nodes > 1) sprintf(buf+i, "\n%d branch & bound nodes: depth %d", lp->total_nodes, lp->max_level); /* Prepare to report solution: deal with split free variables. */ x1 = lp->best_solution+lp->rows+1; if (nalt || shift) { x = x0; LU = LUv; for(i = 0; i < n_var; i++, LU += 2) { if (LU[0] > negInfinity) x[i] = *x1++; else if (LU[1] < Infinity) x[i] = -*x1++; else { x[i] = x1[0] - x1[1]; x1 += 2; } if (shift) x[i] += *++shift; } } else x = x1; if (solinfo[rc].code < 500 && !(nbv + niv)) { /* return .sstatus values */ basis = lp->basis; lower = lp->lower; is = M1alloc((n_var + n_con)*sizeof(int)); suf_iput("sstatus", ASL_Sufkind_con, is); for(i = 0; i < n_con; i++) { j = *++lower; *is++ = *++basis ? 1 : j ? 3 : 4; } suf_iput("sstatus", ASL_Sufkind_var, is); LU = LUv; for(i = 0; i < n_var; i++, LU += 2) { j0 = *++basis; j1 = *++lower; if (LU[0] > negInfinity) j = j0 ? 1 : j1 ? 3 : 4; else if (LU[1] < Infinity) j = j0 ? 1 : j1 ? 4 : 3; else { ++lower; j = *++basis || j0; } *is++ = j; } } write_sol(buf, x, lp->duals+1, &Oinfo); /* The following calls would only be needed */ /* if execution were to continue... */ delete_lp(lp); ASL_free(&asl); return 0; }