/******************************************************************* Copyright (C) 2020 AMPL Optimization, Inc.; written by David M. Gay. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation. The author and AMPL Optimization, Inc. disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall the author be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. *******************************************************************/ /* Variant that duplicates columns for ranges when presenting the dual problem to CPLEX. (I thought this wasn't necessary, but CPLEX seems to botch the solve without it.) */ /* Compile with -DNO_CPLEX_MIP to disable MIP keywords. */ /* Compile with -DNO_BARRIER to disable barrier keywords. */ #ifndef NO_CPLEX_MIP #undef CPLEX_MIP #define CPLEX_MIP #endif #ifndef NO_BARRIER #undef BARRIER #define BARRIER #endif #include "limits.h" #if CPX_APIMODEL == CPX_APIMODEL_LARGE #include "ilcplex/cplexx.h" #endif #include "ilcplex/cplex.h" #if CPX_VERSION < 12060200 #define OBJ_ADJ #endif #if CPX_VERSION < 12060000 #undef Want_Distmipopt #else #undef filename #ifdef Want_Distmipopt #include "cplexdistmip.h" #endif #endif #if CPX_VERSION < 12090000 #undef NO_MOkwf #define NO_MOkwf #endif #define STDIO_H_included #include "nlp.h" #include "getstub.h" #include "avltree.h" #include "signal.h" /* {Modifications for CPLEX 7.1 */ #ifndef CPX_PARAM_WORKDIR #define CPX_PARAM_WORKDIR CPX_PARAM_NODEFILEDIR #endif #ifndef CPX_PARAM_PDSWITCH #ifndef CPX_PARAM_QPMETHOD #define CPX_PARAM_PDSWITCH 1063 #endif #endif /* End Modifications for CPLEX 7.1} */ /* {Modifications for CPLEX 8 */ #undef Const #undef BARRIER_FOR_QP #ifdef CPXERR_Q_NEG_ZERO_COMP /* CPLEX 7.1 */ #define CPX_STAT_INFEASIBLE CPX_INFEASIBLE #define CPX_STAT_UNBOUNDED CPX_UNBOUNDED #define CPXCENVptr CPXENVptr #define Const /*nothing*/ #define BARRIER_FOR_QP #else #define Const const #endif /* End Modifications for CPLEX 8} */ /* {Hidden params of CPLEX 6.5.1 */ #ifndef CPX_PARAM_EPSAGG #define CPX_PARAM_EPSAGG 1055 #endif /* End hidden params} */ #ifndef Sig_ret_type #define Sig_ret_type void #define SigRet /*nothing*/ #endif #ifndef SigRet #define SigRet /*nothing*/ #endif #ifndef Sig_func_type typedef void sig_func_type ANSI((int)); #endif #ifdef _WIN32 /* Win32 is too hard. */ #undef KEEP_BANNER #define KEEP_BANNER #else #ifndef KEEP_BANNER #include "fcntl.h" #include "unistd.h" #endif #endif #if CPX_APIMODEL == CPX_APIMODEL_LARGE #define ForceZ | ASL_use_Z typedef size_t CStype; #undef nzc #undef A_colstarts #define nzc asl->i.nZc_ #define A_colstarts asl->i.A_colstartsZ_ #define CPXcopylpwnames(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17) CPXLcopylpwnames(a1,a2,a3,a4,a5,a6,a7,a8,(CPXLONG*)a9,a10,a11,a12,a13,a14,a15,(char const *const *)(a16),(char const *const *)(a17)) #define CPXaddlazyconstraints(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) CPXLaddlazyconstraints(a1,a2,a3,a4,a5,a6,(CPXLONG*)a7,a8,a9,(char const *const *)(a10)) #define CPXaddusercuts(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) CPXLaddusercuts(a1,a2,a3,a4,a5,a6,(CPXLONG*)a7,a8,a9,(char const *const *)(a10)) #else typedef int CStype; #define ForceZ /*nothing*/ #endif static ASL *asl; static double Times[4]; #if CPX_VERSION >= 12050000 static double DTimes[4]; static int DTimes_failed, num_cores; #endif typedef struct PBuf { char *s, *se; } PBuf; static void Bpf(PBuf *b, const char *fmt, ...) { va_list ap; if (b->s < b->se) { va_start(ap, fmt); b->s += Vsnprintf(b->s, b->se - b->s, fmt, ap); va_end(ap); } } typedef struct cpxlp cpxlp; typedef struct mint_values { int L; int U; int val; } mint_values; typedef struct mdbl_values { double L; double U; double val; } mdbl_values; enum { /* sf_mint f values */ set_crossover = 0, set_dualthresh = 1, set_netopt = 2, set_objno = 3, set_conpri = 4, set_objpri = 5, set_prestats = 6, set_sos2 = 7, set_timing = 8, set_iis = 9, set_mipststat = 10, set_mipstval = 11, set_namernd = 12, set_sos = 13, set_mipcuts = 14, set_round = 15, set_rays = 16, set_mipbasis = 17, set_basis_cond = 18, set_retmipgap = 19, set_feasopt = 20, set_feasoptobj = 21, set_lazy = 22, set_populate = 23, set_pooldual = 24, set_resolve = 25, set_cutstats = 26, set_incompat = 27, set_objrep = 28, set_qcdual = 29, set_multiobj = 30, set_finalmipalg = 31 }; #ifdef CPX_PARAM_FEASOPTMODE /* >= 9.2b */ #define Uselazy #endif enum { /* sf_mdbl f values */ set_dual_ratio = 0, set_droptol = 1 }; static mint_values mint_val[32] = { /* set_crossover */ {0, 2, 1}, /* set_dualthresh */ {-0x7fffffff, 0x7fffffff, 0}, /* set_netopt */ {0, 3, 1}, /* set_objno */ {0, 0/*n_obj*/, 1}, /* set_conpri */ {0, 0x7fffffff, 1}, /* set_objpri */ {0, 0x7fffffff, 2}, /* set_prestats */ {0, 1, 0}, /* set_sos2 */ {0, 1, 1}, #if CPX_VERSION >= 12050000 /* set_timing */ {0, 0x3f, 0}, #else /* set_timing */ {0, 3, 0}, #endif /* set_iis */ {0, 3, 0}, /* set_mipststat */ {0, 1, 1}, /* set_mipstval */ {0, 7, 1}, /* set_namernd */ {0, 1, 0}, /* set_sos */ {0, 1, 1}, /* set_mipcuts */ {-1, 2, 0}, /* set_round */ {0, 15, 1}, /* set_rays */ {0, 3, 3}, /* set_mipbasis */ {-1, 1, -1}, /* set_basis_cond */ {0, 1, 0}, /* set_retmipgap */ {0, 7, 0}, /* set_feasopt */ {0, 2, 0}, /* set_feasoptobj */ {1, 3, 1}, /* set_lazy */ {0, 3, 3}, /* set_populate */ {0, 2, 0}, /* set_pooldual */ {0, 1, 0}, /* set_resolve */ {0, 1, 1}, /* set_cutstats */ {0, 1, 0}, /* set_incompat */ {0, 2, 1}, /* set_objrep */ {0, 3, 2}, /* set_qcdual */ {0, 1, 1}, /* set_multiobj */ {0, 1, 0}, /* set_finalmipalg */ {0, 6, 0} }; static mdbl_values mdbl_val[] = { /* set_dual_ratio */ {1., 1e30, 3.}, /* set_droptol */ {0., 1e30, 0.} }; #define crossover mint_val[0].val #define dual_thresh mint_val[1].val #define use_netopt mint_val[2].val #define objno mint_val[3].val #define conpri mint_val[4].val #define objpri mint_val[5].val #define prestats mint_val[6].val #define sos2 mint_val[7].val #define time_flag mint_val[8].val #define want_iis mint_val[9].val #define mipststat mint_val[10].val #define mipstval mint_val[11].val #define Nameround mint_val[12].val #define sos mint_val[13].val /* #define mipcuts mint_val[14].val */ /* only set_mipcuts is used */ #define Round mint_val[15].val #define rays mint_val[16].val #define mipbasis mint_val[17].val #define basis_cond mint_val[18].val #define retmipgap mint_val[19].val #define want_feasopt mint_val[20].val #define feasoptobj mint_val[21].val #define uselazy mint_val[22].val #define populate mint_val[23].val #define pooldual mint_val[24].val #define Resolve mint_val[25].val #define cutstats mint_val[26].val #define Incompat mint_val[27].val #define objrep mint_val[28].val #define want_qcdual mint_val[29].val #define multiobj mint_val[30].val #define finalmipalg_val mint_val[31].val #define dual_ratio mdbl_val[0].val #define droptol mdbl_val[1].val static int hybmethod = CPX_ALG_PRIMAL; static int netiters = -1; #if CPX_VERSION >= 12080000 #define USE_CHANNELS #else #undef USE_CHANNELS #endif #ifdef USE_CHANNELS static CPXCHANNELptr cpxlog; #else static CPXFILEptr Logf; #endif static char cplex_version[] = "AMPL/CPLEX with bad license\0\nAMPL/CPLEX Driver Version 20210726\n"; static char *baralgname, *endbas, *endsol, *endtree, *endvec, *logfname; static char *paramfile, *poolstub, *pretunefile, *pretunefileprm; static char *startbas, *startsol, *starttree, *startvec, *tunefile, *tunefileprm; static char *tunefix, *tunefixfile, *vmconfig, *workfiledir, *wrtfname, *wrtmipstart; static int bestnode, breaking, costsens, lpoptalg, mbas, method; static int nbas, netopting, nosolve, objadj, objsen, relax, zap_lpcbf; static int aggtries, net_status, net_nodes, net_arcs; static double obj_adj; static char *algname = ""; static real intwarn_tol = 1e-9; static real qcdmax = 1e9; #ifdef CPXERR_QCP_SENSE static real qctol1 = 1e-5, qctol2 = 1e-5, qctol3 = 1e-5; #endif typedef struct { char *msg; int code; int wantobj; } Sol_info; static Sol_info solinfo[] = { { "unrecoverable failure", 500, 0 }, { "optimal solution", 000, 1 }, { "infeasible problem", 200, 0 }, /* 2 */ { "unbounded problem", 300, 0 }, { "phase II objective limit exceeded", 400, 1 }, /* 4 */ { "iteration limit in phase II", 401, 1 }, { "iteration limit in phase I", 402, 1 }, /* 6 */ { "time limit in phase II", 403, 1 }, { "time limit in phase I", 404, 1 }, /* 8 */ { "infeasible with phase II singularities", 201, 0 }, { "infeasible with phase I singularities", 202, 0 }, { "optimal with unscaled infeasibilities", 110, 1 }, /* 11 */ { "aborted in phase II", 501, 1 }, { "aborted in phase I", 502, 0 }, { "aborted in barrier, dual infeasible", 503, 0 }, /* 14* */ { "aborted in barrier, primal infeasible", 504, 0 }, { "aborted in barrier, primal and dual infeasible", 505, 0 }, { "aborted in barrier, primal and dual feasible", 506, 0 }, { "aborted in crossover", 507, 0 }, /* 18 */ { "converged, dual feasible, primal infeasible", 204, 1 }, /*32 --> 19*/ { "converged, primal feasible, dual infeasible", 301, 1 }, { "converged, primal and dual infeasible", 205, 1 }, { "primal objective limit reached", 405, 1 }, /* 35 --> 22 */ { "dual objective limit reached", 406, 1 }, { "primal has unbounded optimal face", 001, 1 }, { "best solution found, primal-dual feasible", 100, 1 },/* 38 --> 25*/ { "best solution found, primal infeasible", 206, 1 }, { "best solution found, dual infeasible", 302, 1 }, { "best solution found, primal-dual infeasible", 207, 1 }, /* 41 --> 28 */ { "solution found, numerical difficulties", 508, 1}, { "solution found, inconsistent equations", 509, 1}, /* 43 --> 30*/ { "infeasible or unbounded in presolve", 208, 0 }, /*1101*/ { "not licensed to solve MIP problems", 571, 0}, /* 32 */ { "not licensed to use the barrier algorithm", 572, 0 }, { "not licensed to solve MIQP or QCP problems", 573, 0 }, { "locally optimal solution of indefinite QP", 130, 1 } #ifdef CPLEX_MIP ,{ "optimal integer solution", 002, 1 }, /* 101 --> 36 */ { "optimal integer solution within mipgap or absmipgap", 003, 1 }, { "integer infeasible", 220, 0 }, /* 103 */ { "mixed-integer solutions limit", 420, 1 }, { "node limit with integer solution", 421, 1 }, /* 105 */ { "node limit with no integer solution", 410, 0 }, { "time limit with integer solution", 422, 1 }, { "time limit with no integer solution", 411, 0 }, /* 108 */ { "unrecoverable failure with integer solution", 520, 1 }, { "unrecoverable failure with no integer solution", 510, 0 }, { "treememory limit with integer solution", 423, 1 }, { "treememory limit with no integer solution", 412, 0 },/* 112 */ { "aborted, integer solution exists", 521, 1 }, { "aborted, no integer solution", 511, 0 }, /* 114 */ { "integer optimal with unscaled infeasibilities", 111, 1 }, { "out of memory, no tree; solution may exist", 523, 1 },/* 116 */ { "out of memory, no tree; no integer solution", 512, 1 }, #ifdef CPX_STAT_OPTIMAL /* >= 8.0 */ { "integer unbounded ray", 320, 0}, /* 118 */ { "integer infeasible or unbounded in presolve", 209, 0 }, /* 119 --> 54 */ #else { "node file limit with integer solution", 424, 1 }, { "node file limit with no integer solution", 413, 1 }, /* 119 --> 54 */ #endif /*CPX_STAT_OPTIMAL*/ { "optimal (non-)integer solution", 102, 1 }, { "optimal (non-)integer solution within mipgap or absmipgap", 103, 1 }, { "feasible relaxed sum in feasopt", 121, 1}, /* --> 57 */ { "optimal relaxed sum in feasopt", 122, 1}, { "feasible relaxed infeasibility count in feasopt", 123, 1}, { "optimal relaxed infeasibility count in feasopt", 124, 1}, { "feasible relaxed quadratic penalty in feasopt", 125, 1}, { "optimal relaxed quadratic penalty in feasopt", 126, 1}, /* --> 62 */ { "dettimelim reached with feasible solution", 440, 1}, { "dettimelim reached with infeasible solution", 441, 0} #ifdef CPX_PARAM_FEASOPTMODE /* >= 9.2b {*/ ,{ "minimal sum of constraint relaxations", 230, 1 }, /* --> 65 */ { "optimal among minimal sum of constraint relaxations", 231, 1 }, { "minimal number of constraint relaxations", 232, 1 }, { "optimal among minimal number of constraint relaxations", 233, 1 }, { "minimal sum of squares of constraint relaxations", 234, 1 }, { "optimal among minimal sum of squares of constraint relaxations", 235, 1 }, { "integer minimal sum of constraint relaxations", 240, 1 }, { "integer optimal among minimal sum of constraint relaxations", 241, 1 }, { "integer minimal number of constraint relaxations", 242, 1 }, { "integer optimal among minimal number of constraint relaxations", 243, 1 }, { "integer minimal sum of squares of constraint relaxations", 244, 1 }, { "integer optimal among minimal sum of squares of constraint relaxations", 245, 1 } #ifdef CPX_STAT_MULTIOBJ_OPTIMAL /*{*/ ,{ "multiobjective optimal", 6, 1 }, /*77*/ { "multiobjective infeasible", 211, 0 }, { "multiobjective infeasible or unbounded", 212, 0 }, { "multiobjective unbounded", 311, 0 }, { "multiobjective nonoptimal", 140, 1 }, { "multiobjective stopped", 450, 1 } #endif /*}*/ #endif /*}*/ #endif /*CPLEX_MIP*/ }; typedef struct Cbfinfo { int disp, mipdisp, np[4], nx[2], nint, pres; char *xkind; } Cbfinfo; static Cbfinfo cbi; /* Stuff to cope with current CPLEX political correctness... */ static CPXENVptr Env; typedef struct dims { double *c; double *x; double *y; int *cstat; int *rstat; SufDesc *csd; SufDesc *rsd; char *rtype; /* for linadj and qcduals */ cde *consave; cde *objsave; ograd **ogsave; /* Stuff for netopt... */ int *cs; int *rs; /* for solution pools */ int npool; } dims; static char * strcpy1(char *t, const char *s) { while((*t = *s++)) t++; return t; } static void badretfmt(int rc, const char *fmt, ...) { va_list ap; char buf[4200], *s; int k; va_start(ap, fmt); k = Vsnprintf(buf, sizeof(buf), fmt, ap) + 1; if (rc) { solve_result_num = rc; memcpy(s = (char*)M1alloc(k), buf, k); asl->i.uinfo = s; } else fprintf(Stderr, "%s\n", buf); } static void badret(const char *what, int i, int rc) { char buf[4096]; if (!CPXgeterrorstring(Env, i, buf)) badretfmt(rc, "%s failed; error code %d.", what, i); else badretfmt(rc, "%s failed; %s.", what, buf); if (rc) exit(1); } static void badwrite(int rc, const char *fmt, const char *fname, int status) { badretfmt(rc, fmt, fname, status); exit(1); } #ifdef CPX_CON_INDICATOR /* >= 9.2b */ #define ALLOW_CLP ASL_allow_CLP static int add_indic(void *v, int iv, int compl, int sense, int nz, int *ig, real *g, real rhs) { return CPXaddindconstr(Env, (CPXLPptr)v, iv, compl, nz, rhs, "LGE"[sense], ig, g, 0); } #else /*!CPX_CON_INDICATOR*/ #define ALLOW_CLP 0 #endif /*CPX_CON_INDICATOR*/ #ifdef BASDEBUG int basdebug; static void Basedebug(char *name, int *cs, int *rs) /*!!!!*/ { FILE *f; int i; if (!basdebug) return; if (!(f = fopen(name,"w"))) { fprintf(Stderr, "Basedebug: cannot open \"%s\".\n", name); return; } for(i = 0; i < nbas; i++) fprintf(f, "cs[%d] = %d\n", i, cs[i]); for(i = 0; i < mbas; i++) fprintf(f, "rs[%d] = %d\n", i, rs[i]); fclose(f); } #else #define Basedebug(a,b,c) #endif static void bascopy(CPXLPptr cpx, dims *d, int n, int m, int *cmap, int *ncs, int *nrs, int *rmap) { int *cs, i, j, *rs; #ifdef BASDEBUG if (basdebug & 1) return; #endif if ((cs = d->cs)) rs = d->rs; else { cs = (int*)Malloc((nbas + mbas + 1)*sizeof(int)); rs = cs + nbas; } for (i = 0; i < nbas; ++i) cs[i] = CPX_AT_LOWER; for(i = 0; i < mbas; ++i) rs[i] = CPX_BASIC; for(i = 0; i < m; ++i) if ((j = rmap[i]) >= 0) rs[j] = nrs[i]; for(i = 0; i < n; ++i) { if ((j = cmap[i]) >= 0) cs[j] = ncs[i]; else { j = -(j+1); rs[j] = ncs[i]; } } Basedebug("net.bas",cs,rs); CPXcopybase(Env, cpx, cs, rs); if (!d->cs) free(cs); } static int netopt(CPXLPptr cpx, dims *d, int *st, int *nodes, int *arcs, int *its) { CPXNETptr net; int i, j, k, m, n; int *cmap, *ncs, *nrs, *rmap, *s; k = 0; if (!(net = CPXNETcreateprob(Env,&k,"embedded")) || k) return 1; m = mbas + 1; /* CPXNETextract may add a dummy node */ n = mbas + nbas; cmap = (int*)Malloc(2*(m+n)*sizeof(int)); rmap = cmap + n; ncs = rmap + m; nrs = ncs + n; if (CPXNETextract(Env, net, cpx, cmap, rmap) || (*nodes = CPXNETgetnumnodes(Env,net)) <= 0) { free(cmap); return 1; } *arcs = CPXNETgetnumarcs(Env,net); CPXgetintparam(Env, CPX_PARAM_SIMDISPLAY, &k); if (!k) { netopting = 1; /* suppress netopt termination msg */ CPXsetintparam(Env, CPX_PARAM_SIMDISPLAY, 1); } if ((s = d->cs)) { n = *arcs; for(i = 0; i < n; i++) ncs[i] = (j = cmap[i]) >= 0 ? s[j] : CPX_BASIC; n = *nodes; s = d->rs; for(i = 0; i < n; i++) nrs[i] = (j = rmap[i]) >= 0 ? s[j] : CPX_BASIC; if ((i = CPXNETcopybase(Env, net, ncs, nrs))) fprintf(Stderr, "Return %d from CPXNETcopybase.\n", i); } if ((i = CPXNETprimopt(Env, net))) { fprintf(Stderr, "Return %d from CPXNETprimopt\n", i); *st = 11; #ifdef Student_Edition #ifndef CPXERR_RESTRICTED_VERSION #define CPXERR_RESTRICTED_VERSION CPXERR_PROMOTION_VERSION #endif if (i == CPXERR_RESTRICTED_VERSION) *st = 12; #endif } else { i = CPXNETgetstat(Env, net); if (i >= 1 && i <= 8) { *st = i; if (i == 4) goto bug; } else if (i >= 12 && i <= 13) *st = i - 3; else if (i == 19) *st = 4; else { bug: fprintf(Stderr, "Return %d from CPXNETgetstat\n", i); *st = 11; } *its = CPXNETgetitcnt(Env,net); #ifdef BASDEBUG CPXNETbasewrite(Env,net,"net.bw"); #endif if (!CPXNETgetbase(Env, net, ncs, nrs)) { bascopy(cpx, d, *arcs, *nodes, cmap, ncs, nrs, rmap); #ifdef BASDEBUG CPXmbasewrite(Env, cpx, "m.bw"); #endif } } netopting = 0; if (!k) CPXsetintparam(Env, CPX_PARAM_SIMDISPLAY, 0); free(cmap); CPXNETfreeprob(Env, &net); return 0; } typedef int (CPXPUBLIC *Optalg)(CPXCENVptr, cpxlp*); static Optalg Optimize; static jmp_buf Jb; #ifdef CPXERR_IN_INFOCALLBACK /* CPLEX 11 */ static int breaknow; #endif Sig_ret_type intcatch(int n) { printf("\n (cplex)\n", n); fflush(stdout); #ifdef CPXERR_IN_INFOCALLBACK breaknow = 1; #endif if (++breaking > 3) longjmp(Jb, 2); signal(SIGINT, intcatch); SigRet; } static int CPXPUBLIC breakcallback(CPXCENVptr e, void *c, int w, void *h) { Not_Used(e); Not_Used(c); Not_Used(w); Not_Used(h); return breaking > 1; } #ifdef BARRIER static int CPXPUBLIC Optimize2(CPXCENVptr e, cpxlp *c) { return CPXhybbaropt(e, c, hybmethod); } static int CPXPUBLIC Optimizebar(CPXCENVptr e, cpxlp *c) { int rv; rv = CPXbaropt(e, c); #if !defined(NO_DEPRECATED) && CPX_VERSION < 12070000 if (!rv) { int s; if (endvec && (s = CPXvecwrite(e, c, endvec))) printf("\n*** return %d from CPXvecwrite.\n", s); } #endif return rv; } static void set_baropt(VOID) { baralgname = ""; if (crossover) { Optimize = Optimize2; if (crossover == 1) { algname = "crossover primal "; hybmethod = CPX_ALG_PRIMAL; } else { algname = "crossover dual "; hybmethod = CPX_ALG_DUAL; } } else { Optimize = Optimizebar; algname = ""; } } static int startcomp(ASL *asl, int n0, int m, int nextra, CStype *ka, int *kal, int *ia, double *a, double *b, double *c, double **cdualp, double **cprimp, double **rdualp, double **rprimp) { CStype i, j, k, n; double *r, t, *x, *y; /* Why can't CPXcopystart do this calculation? */ if (!X0 && !pi0) return 0; n = n0 - objadj; if (method > 0) { x = X0; y = pi0; } else { x = pi0; y = X0; } if (x) { if (method < 0 && (i = nextra + nranges) > 0) { r = (double *)M1alloc(n0*sizeof(double)); memcpy(r, x, (j = n - i)*sizeof(double)); memset(r+j, 0, i*sizeof(double)); /* Can we do better? */ x = r; if (objadj) x[n] = obj_adj; } else if (objadj) { r = (double *)M1alloc(n0*sizeof(double)); memcpy(r, x, n*sizeof(double)); x = r; x[n] = obj_adj; } *cprimp = x; *rprimp = r = (double *)M1alloc(m*sizeof(double)); memcpy(r, b, m*sizeof(double)); for(i = 0; i < n; i++) if ((t = x[i])) { j = ka[i]; for(k = j + kal[i]; j < k; j++) r[ia[j]] -= t*a[j]; } } else *cprimp = *rprimp = 0; if (y) { if (method > 0 && objadj) { r = (double *)M1alloc(m*sizeof(double)); memcpy(r, y, (m-1)*sizeof(double)); r[m-1] = obj_adj; y = r; } *rdualp = y; *cdualp = r = (double*)M1alloc(n0*sizeof(double)); for(i = 0; i < n0; i++) { t = c[i]; j = ka[i]; for(k = j + kal[i]; j < k; j++) t -= y[ia[j]]*a[j]; r[i] = t; } } else *cdualp = *rdualp = 0; return 1; } #endif /*BARRIER*/ #ifdef CPX_PARAM_FEASOPTMODE /* >= 9.2b */ static int feasopt(CPXENVptr e, cpxlp *cpx) { char *grptype; double *L, *U, *lb, *rhs, *rng, *ub; int *grpbeg, *grpind, i, j, k, n, nqc; i = want_feasopt + 2*feasoptobj - 3; if (CPXsetintparam(e, CPX_PARAM_FEASOPTMODE, i)) printf("Could not set CPX_PARAM_FEASOPTMODE to %d\n", i); /* bug */ if (!(nqc = nlc)) { n = 2*(mbas + nbas); lb = (double*)Malloc(n*sizeof(double)); for(i = 0; i < n; i++) lb[i] = 1.; /* preferences */ ub = lb + nbas; rhs = ub + nbas; rng = rhs + mbas; i = CPXfeasopt(e, cpx, rhs, rng, lb, ub); } else { L = LUv; U = Uvx; k = nbas; n = mbas; for(i = 0; i < k; i++) { if (L[i] > negInfinity) n++; if (U[i] < Infinity) n++; } lb = (double*)Malloc(n*(sizeof(double)+2*sizeof(int)+1)); grpbeg = (int*)(lb + n); grpind = grpbeg + n; grptype = (char*)(grpind + n); for(i = 0; i < n; i++) { lb[i] = 1.; /* preferences */ grpbeg[i] = i; } for(i = j = 0; i < k; i++) { if (L[i] > negInfinity) { grpind[j] = i; grptype[j++] = CPX_CON_LOWER_BOUND; } if (U[i] < Infinity) { grpind[j] = i; grptype[j++] = CPX_CON_UPPER_BOUND; } } k = n_con - nqc; for(i = 0; i < k; i++) { grpind[j] = i; grptype[j++] = CPX_CON_LINEAR; } k = nqc; for(i = 0; i < k; i++) { grpind[j] = i; grptype[j++] = CPX_CON_QUADRATIC; } i = CPXfeasoptext(e, cpx, n, n, lb, grpbeg, grpind, grptype); } free(lb); return i; } #endif /*CPX_PARAM_FEASOPTMODE*/ #ifdef MSDOS #undef Stand_alone #endif #ifdef Student_Edition #undef Stand_alone #endif extern int cpxmain ANSI((int, char**)); typedef char *sfunc ANSI((char *, char *, int)); #ifdef CPLEX_MIP #ifdef CPX_PARAM_IISIND /* version < 9.2b */ typedef int (CPXPUBLIC *Treeio)(CPXCENVptr,CPXLPptr,Const char*); static void treeio(cpxlp *cpx, char *fname, char *what, Treeio tio) { if ((*tio)(Env,cpx,fname)) { printf("Could not %s tree file \"%s\".\n", what, fname); need_nl = 0; } } #endif #endif enum { /* sf_known f values */ set_barrier = 0, set_dual = 1, set_dualopt = 2, set_max = 3, set_min = 4, set_primal = 5, set_primalopt = 6, set_relax = 7, set_sens = 8, set_bestnode = 9, set_autoopt = 10, set_siftopt = 11, set_concurrentopt=12, set_bestbound = 13, set_nosolve = 14, set_benders = 15 }; static char * sf_known(Option_Info *oi, keyword *kw, char *v) { switch(Intcast kw->info) { #ifdef BARRIER case set_barrier: set_baropt(); break; #endif case set_dual: method = -1; break; case set_dualopt: Optimize = CPXdualopt; algname = "dual "; baralgname = ""; break; case set_max: objsen = -1; break; case set_min: objsen = 1; break; case set_primal: method = 1; break; case set_primalopt: Optimize = CPXprimopt; algname = baralgname = ""; break; case set_relax: relax = 1; break; case set_sens: costsens = 1; break; case set_bestbound: bestnode |= 1; break; case set_bestnode: bestnode |= 2; break; case set_autoopt: lpoptalg = CPX_ALG_AUTOMATIC; use_lpopt: Optimize = CPXlpopt; CPXsetintparam(Env, CPX_PARAM_LPMETHOD, lpoptalg); break; #ifdef CPX_STAT_OPTIMAL /* >= 8.0 */ case set_siftopt: lpoptalg = CPX_ALG_SIFTING; goto use_lpopt; case set_concurrentopt: lpoptalg = CPX_ALG_CONCURRENT; goto use_lpopt; #endif /*CPX_STAT_OPTIMAL*/ #ifdef CPXPARAM_Benders_Strategy case set_benders: Optimize = CPXbendersopt; break; #endif case set_nosolve: nosolve = 1; } return v; } static void baddval(Option_Info *oi, keyword *kw, double t, double L, double U) { printf("Rejecting %s %g; must be between %g and %g\n", kw->name, t, L, U); badopt_ASL(oi); } static void badival(Option_Info *oi, keyword *kw, int t, int L, int U) { printf("Rejecting %s %d; must be between %d and %d\n", kw->name, t, L, U); badopt_ASL(oi); } static char* sf_mdbl(Option_Info *oi, keyword *kw, char *v) { char *rv; double t; int i = Intcast kw->info; mdbl_values *m = mdbl_val + i; if (*v == '?' && v[1] <= ' ') { printf("%s=%g\n", kw->name, m->val); oi->option_echo &= ~ASL_OI_echothis; return v + 1; } t = strtod(v, &rv); if (rv == v) { printf("Expected a floating-point value for %s, not \"%s\"\n", kw->name, v); badopt_ASL(oi); return v; } if (t < m->L || t > m->U) { baddval(oi,kw,t,m->L,m->U); return rv; } m->val = t; return rv; } static char * sf_mint(Option_Info *oi, keyword *kw, char *v) { int t; char *rv; int i = Intcast kw->info; mint_values *m = mint_val + i; if (*v == '?' && v[1] <= ' ') { printf("%s=%d\n", kw->name, m->val); oi->option_echo &= ~ASL_OI_echothis; return v + 1; } t = (int)strtol(v, &rv, 10); if (rv == v) { printf("Expected an integer value for %s, not \"%s\"\n", kw->name, v); badopt_ASL(oi); return v; } if (t < m->L || t > m->U) { badival(oi,kw,t,m->L,m->U); return rv; } m->val = t; switch(i) { #ifdef BARRIER case set_crossover: set_baropt(); break; #endif case set_netopt: if (t == 3) { m->val = 0; CPXsetintparam(Env, CPX_PARAM_LPMETHOD, CPX_ALG_NET); } break; #ifdef CPLEX_MIP case set_mipcuts: {static int op[] = { CPX_PARAM_CLIQUES, CPX_PARAM_COVERS, CPX_PARAM_DISJCUTS, CPX_PARAM_FLOWCOVERS, CPX_PARAM_FLOWPATHS, CPX_PARAM_FRACCUTS, CPX_PARAM_GUBCOVERS, CPX_PARAM_IMPLBD, CPX_PARAM_MIRCUTS #ifdef CPX_PARAM_ZEROHALFCUTS ,CPX_PARAM_ZEROHALFCUTS #endif }; int f; for(f = 0; f < sizeof(op)/sizeof(int); f++) CPXsetintparam(Env, op[f], t); } break; #endif } return rv; } #ifdef CPXERR_PARAM_INCOMPATIBLE /*{*/ static char * incompatible(Option_Info *oi, keyword *kw, char *rv, char *v) { oi->option_echo &= ~ASL_OI_echothis; if (Incompat) { printf("%s \"%s%s%.*s\" as incompatible " "with earlier parameter settings.\n", Incompat == 1 ? "Ignoring" : "Rejecting", kw->name, oi->eqsign, (int)(rv-v), v); if (Incompat == 2) badopt_ASL(oi); } return rv; } #endif /*}*/ static char * sf_int(Option_Info *oi, keyword *kw, char *v) { int f, k, t, z[3]; char *rv; const char *what = kw->name; f = Intcast kw->info; if (*v == '?' && v[1] <= ' ') { CPXgetintparam(Env, f, &t); printf("%s=%d\n", what, t); oi->option_echo &= ~ASL_OI_echothis; return v + 1; } t = (int)strtol(v, &rv, 10); if (rv == v) { printf("Expected an integer value for %s, not \"%s\"\n", what, v); badopt_ASL(oi); } else if ((k = CPXsetintparam(Env, f, t))) { #ifdef CPXERR_PARAM_INCOMPATIBLE if (k == CPXERR_PARAM_INCOMPATIBLE) return incompatible(oi, kw, rv, v); #endif z[2] = 0; z[1] = 1; CPXinfointparam(Env, f, z, z+1, z+2); badival(oi, kw, t, z[1], z[2]); } return rv; } static char * sf_ipar(Option_Info *oi, keyword *kw, char *v) { int f, t, z[3]; char *rv, *v0 = v; const char *fmt, *what = kw->name; f = (int)strtol(v, &rv, 10); if (rv == v || (*rv != '=' && *rv != ' ')) { printf("Expected an integer parameter number after %s%s, not \"%s\"\n", what, oi->eqsign, v); badopt_ASL(oi); while(*v > ' ' && *v++ != ','); return v; } for(v = rv; *v <= ' '; v++) if (!*v) { printf("Expected an integer value after %s%s\n", what, oi->eqsign); badopt_ASL(oi); } if (*v == '=') while(*++v <= ' ') if (!*v) { printf("Expected an integer value after %s%s%s\n", what, oi->eqsign, v0); badopt_ASL(oi); } if (*v == '?' && v[1] <= ' ') { rv = v + 1; if (CPXgetintparam(Env, f, &t)) goto badopt; printf("%s=%d=%d\n", what, f, t); oi->option_echo &= ~ASL_OI_echothis; return rv; } t = (int)strtol(v, &rv, 10); if (rv == v) { printf("Expected an integer value for %s %d, not \"%s\"\n", what, f, v); badopt_ASL(oi); } else if (CPXsetintparam(Env, f, t)) { z[2] = 0; z[1] = 1; if (CPXinfointparam(Env, f, z, z+1, z+2)) { badopt: fmt = "Rejecting %s=%d=%d; bad iparam number %d.\n"; z[1] = f; } else fmt = "Rejecting %s=%d=%d; assigned value must be between %d and %d\n"; printf(fmt, what, f, t, z[1], z[2]); badopt_ASL(oi); } return rv; } static char * sf_spar(Option_Info *oi, keyword *kw, char *v) { int c, f, q; char *b, *be, buf[CPX_STR_PARAM_MAX], buf1[CPX_STR_PARAM_MAX], *rv, *v0 = v; const char *what = kw->name; f = (int)strtol(v, &rv, 10); if (rv == v || (*rv != '=' && *rv != ' ')) { printf("Expected an integer parameter number after %s%s, not \"%s\".\n", what, oi->eqsign, v); bad: badopt_ASL(oi); while(*v > ' ' && *v++ != ','); return v; } for(v = rv; *v <= ' '; v++) if (!*v) { printf("Expected an integer value after %s%s.\n", what, oi->eqsign); goto bad; } if (*v == '=') { while(*++v <= ' ') if (!*v) { printf("Expected an integer value after %s%s%s.\n", what, oi->eqsign, v0); goto bad; } } if (*v == '?' && v[1] <= ' ') { ++v; if (!CPXgetstrparam(Env, f, buf)) printf("%s=%d=\"%s\"\n", what, f, buf); else { badparnum: printf("Bad string parameter number %d.\n", f); badpar: badopt_ASL(oi); } oi->option_echo &= ~ASL_OI_echothis; return v; } b = buf; be = buf + sizeof(buf); if ((q = *v) == '"' || q == '\'') { while((c = *++v)) { if (c == q) { ++v; break; } if (b < be) *b++ = c; } } else do { if (b < be) *b++ = q; } while((q = *++v) > ' '); if (b < be) { *b = 0; if (CPXsetstrparam(Env, f, buf)) { if (CPXgetstrparam(Env, f, buf1)) goto badparnum; printf("Bad value \"%s\" for %s=%d.\n", buf, what, f); goto badpar; } } else { printf("Oversize value for %s=%d.\n", what, f); badopt_ASL(oi); } return v; } static char * sf_str(Option_Info *oi, keyword *kw, char *v) { int c, f, q; char *b, *be, buf[CPX_STR_PARAM_MAX]; const char *what = kw->name; f = Intcast kw->info; if (*v == '?' && v[1] <= ' ') { ++v; buf[0] = 0; CPXgetstrparam(Env, f, buf); printf("%s=\"%s\"\n", what, buf); oi->option_echo &= ~ASL_OI_echothis; return v; } b = buf; be = buf + sizeof(buf); if ((q = *v) == '"' || q == '\'') { while((c = *++v)) { if (c == q) { ++v; break; } if (b < be) *b++ = c; } } else do { if (b < be) *b++ = q; } while((q = *++v) > ' '); if (b < be) { *b = 0; if (CPXsetstrparam(Env, f, buf)) { printf("Bad value \"%s\" for %s.\n", buf, what); badopt_ASL(oi); } } else { printf("Oversize value for %s.\n", what); badopt_ASL(oi); } return v; } /* In case some reason surfaces to distinguish the old setzzzpar() */ /* calls from the old setzzzind calls (which had sfunc value sf_int and */ /* sf_int1, respectively, in the keywds table, we use the following */ /* #define and retain appearances of sf_int1 in the keywds table. */ #define sf_int1 sf_int static char * sf_dbl(Option_Info *oi, keyword *kw, char *v) { double t, z[3]; char *rv; const char *what = kw->name; int f, k; f = Intcast kw->info; if (*v == '?' && v[1] <= ' ') { CPXgetdblparam(Env, f, &t); printf("%s=%g\n", what, t); oi->option_echo &= ~ASL_OI_echothis; return v + 1; } t = strtod(v, &rv); if (rv == v) { printf("Expected a numeric value for %s, not \"%s\"\n", what, v); badopt_ASL(oi); } else if ((k = CPXsetdblparam(Env, f, t))) { #ifdef CPXERR_PARAM_INCOMPATIBLE if (k == CPXERR_PARAM_INCOMPATIBLE) return incompatible(oi, kw, rv, v); #endif z[2] = 0; z[1] = 1; CPXinfodblparam(Env, f, z, z+1, z+2); printf("Rejecting %s %g; must be between %g and %g\n", what, t, z[1], z[2]); badopt_ASL(oi); } return rv; } /* sf_int2 and sf_dbl2 are variants of sf_int and sf_dbl for */ /* synonyms, so getparinfo() will not deal with the synonyms. */ static char * sf_int2(Option_Info *oi, keyword *kw, char *v) { return sf_int(oi,kw,v); } static char * sf_dbl2(Option_Info *oi, keyword *kw, char *v) { return sf_dbl(oi,kw,v); } static char * sf_dpar(Option_Info *oi, keyword *kw, char *v) { double t, z[3]; int f; char *rv, *v0 = v; const char *what = kw->name; f = (int)strtol(v, &rv, 10); if (rv == v) { printf("Expected an integer parameter number after %s%s, not \"%s\"\n", what, oi->eqsign, v); badopt_ASL(oi); while(*v > ' ' && *v++ != ','); return v; } for(v = rv; *v <= ' '; v++) if (!*v) { printf("Expected a floating-point value after %s%s\n", what, oi->eqsign); badopt_ASL(oi); } if (*v == '=') while(*++v <= ' ') if (!*v) { printf("Expected a floating-point value after %s%s%s\n", what, oi->eqsign, v0); badopt_ASL(oi); } if (*v == '?' && v[1] <= ' ') { CPXgetdblparam(Env, f, &t); printf("%s=%d=%g\n", what, f, t); oi->option_echo &= ~ASL_OI_echothis; return v + 1; } t = strtod(v, &rv); if (rv == v) { printf("Expected a floating-point value for %s %d, not \"%s\"\n", what, f, v); badopt_ASL(oi); } else if (CPXsetdblparam(Env, f, t)) { z[2] = 0; z[1] = 1; CPXinfodblparam(Env, f, z, z+1, z+2); printf("Rejecting %s=%d=%g; assigned value must be between %g and %g\n", what, f, t, z[1], z[2]); badopt_ASL(oi); } return rv; } static char **file_name[22] = { &endbas, &endtree, &startbas, &starttree, &startsol, &endsol, &logfname, &wrtfname, &workfiledir, &poolstub, ¶mfile, &pretunefile, &pretunefileprm, &tunefile, &tunefileprm, &tunefix, &tunefixfile, &startvec, &endvec, &vmconfig, &wrtmipstart }; enum { /* sf_char f values */ set_endbas = 0, set_endtree = 1, set_startbas = 2, set_starttree = 3, set_startsol = 4, set_endsol = 5, set_logname = 6, set_wrtfname = 7, set_workfiledir = 8, set_poolstub = 9, set_paramfile = 10, set_pretunefile = 11, set_pretunefileprm = 12, set_tunefile = 13, set_tunefileprm = 14, set_tunefix = 15, set_tunefixfile = 16, set_startvector = 17, set_endvector = 18, set_vmconfig = 19, set_wrtmipstart = 20 }; static char * sf_char(Option_Info *oi, keyword *kw, char *v) { char *rv, *s, *t; const char *fmt; int c, f, q; size_t n; if (!*v) { printf("Rejecting %s: no following file name\n", kw->name); badopt_ASL(oi); return v; } f = Intcast kw->info; if (*v == '?' && v[1] <= ' ') { fmt = "%s=%s\n"; if ((t = *file_name[f])) { for(s = t; (c = *s); ++s) if (c <= ' ') goto qfmt; } else { t = ""; qfmt: fmt = "%s=\"%s\"\n"; } printf(fmt, kw->name, t); oi->option_echo &= ~ASL_OI_echothis; return v + 1; } q = 0; if (*v == '\'' || *v == '"') { q = *v++; for(rv = v; *rv != q; ++rv) { if (!*rv) { printf("Missing final %c in file name for %s.\n", q, kw->name); badname: badopt_ASL(oi); return rv+1; } } if (v == rv) { printf("Empty file name for %s.\n", kw->name); goto badname; } if (*++rv > ' ') { printf("Unexpected '%c' after closing $c of file name for %s.\n", *rv, q, kw->name); goto badname; } n = rv - v; } else { for(rv = v; *++rv > ' ';); n = rv - v + 1; } t = M1alloc(n); strncpy(t, v, --n); t[n] = 0; *file_name[f] = t; if (f == set_logname) { #ifdef USE_CHANNELS if (CPXsetlogfilename(Env, logfname, "w")) #else if (!(Logf = CPXfopen(t,"w"))) #endif { printf("Cannot open logfile \"%s\"\n", t); logfname = 0; badopt_ASL(oi); } else #ifdef USE_CHANNELS if (CPXgetchannels(Env, NULL, NULL, NULL, &cpxlog)) { printf("Cannot get cpxlog channel; ignoring logfile.\n"); CPXsetlogfilename(Env, NULL, NULL); logfname = 0; } #else CPXsetlogfile(Env, Logf); #endif } return rv; } static Option_Info Oinfo; static char * sf_par(Option_Info *oi, keyword *kw, char *v) { FILE *f; char buf[4096], *s; if (*v == '?' && v[1] <= ' ') { printf("# %s is processed when specified.\n", kw->name); return v + 1; } paramfile = 0; v = sf_char(oi, kw, v); if (!paramfile) return v; if (!(f = fopen(paramfile, "r"))) { printf("Cannot open %s \"%s\"\n", kw->name, paramfile); badopt_ASL(oi); return v; } while(fgets(buf, sizeof(buf), f)) for(s = buf; *s; s = get_opt_ASL(&Oinfo, s)); fclose(f); if (Oinfo.n_badopts) { if (amplflag) badretfmt(564, "Error reading paramfile \"%s\".", paramfile); exit(1); } return v; } #if CPX_VERSION >= 1000 /*{*/ static char * sf_parm(Option_Info *oi, keyword *kw, char *v) { if (*v == '?' && v[1] <= ' ') { printf("# %s is processed when specified.\n", kw->name); return v + 1; } paramfile = 0; v = sf_char(oi, kw, v); if (!paramfile) return v; if (CPXreadcopyparam(Env, paramfile)) { if (amplflag) badretfmt(564, "Error reading paramfileprm \"%s\".", paramfile); exit(1); } return v; } #endif /*}*/ #ifdef NO_MOkwf #define MOkwf 0 #else /*{*/ typedef struct MOkwval { struct MOkwval *next; keyword *kw; char *val; int Objno; } MOkwval; static MOkwval *first_MOkw, **pnext_MOkw = &first_MOkw; static int *indobj, *mopriority, nmo, nmopri, *objind, *pri0; static real *moabstol, *momem, *moreltol, *moweight; static struct paramset **mopars; static int CPXPUBLIC Optimizemo(CPXCENVptr env, cpxlp *cpx) { int i, j, k, no, nz, ono, *vn; ograd *og; real *c; if ((i = CPXsetnumobjs(Env, cpx, no = nmo))) badret("CPXsetnumobjs", i, 1); ono = obj_no; if ((i = objind[ono]) > 0) { j = indobj[i]; k = indobj[0]; indobj[0] = j; indobj[i] = k; objind[j] = 0; objind[k] = i; } c = (real*)M1alloc(n_var*(sizeof(real) + sizeof(int))); vn = (int*)(c + n_var); i = 0; if (indobj[0] == ono) { #ifndef NAN /* CPX_NO_OFFSET_CHANGE is #defined as NAN, so we construct a NaN */ /* using constants in arith.h. */ union { double d; unsigned int x[2]; } u; u.x[0] = QNaN0; u.x[1] = QNaN1; #undef CPX_NO_OFFSET_CHANGE #define CPX_NO_OFFSET_CHANGE u.d #endif if ((k = CPXmultiobjchgattribs(env, cpx, 0, CPX_NO_OFFSET_CHANGE, moweight[ono], mopriority[ono], moabstol[ono], moreltol[ono], obj_name(ono)))) badret("CPXmultiobjchgattribs", k, 1); i = 1; } for(; i < no; ++i) { j = indobj[i]; for(nz = 0, og = Ograd[j]; og; og = og->next) { c[nz] = og->coef; vn[nz++] = og->varno; } if ((k = CPXmultiobjsetobj(env, cpx, i, nz, vn, c, objconst(j), moweight[j], mopriority[i], moabstol[j], moreltol[j], obj_name(j)))) badret("CPXmultiobjsetobj", k, 1); } return CPXmultiobjopt(env, cpx, (const struct paramset * const*)mopars); } static fint MOkwf(char *key, fint klen) { ASL *asl; MOkwval *v; char *key0; int c, on; keyword *kw; key0 = key; if (klen < 7 || strncmp(key, "obj_", 4)) { badkey: printf("Unrecognized keyword \"%s\"\n", key0); return 1; } on = 0; for(key += 4;;) { c = *key++; if (c == '_') break; if (c < '0' || c > '9') return 1; on = 10*on + (c - '0'); } asl = Oinfo.asl; if (on <= 0 || on > n_obj) { printf("Rejecting obj_%d; obj_n must have 1 <= n <= %d\n", on, n_obj); return 1; } if (!(kw = (keyword*)b_search_ASL(Oinfo.keywds, (int)sizeof(keyword), Oinfo.n_keywds, &key, &Oinfo.eqsign))) goto badkey; *pnext_MOkw = v = (MOkwval*)mem(sizeof(MOkwval) + strlen(key) + 1); pnext_MOkw = &v->next; v->next = 0; v->kw = kw; strcpy(v->val = (char*)(v+1), key); v->Objno = on - 1; return 0; } static char modisplay_desc[] = "how much to report during multiobjective optimization:\n\ 0 = nothing\n\ 1 = summary after each subproblem (default)\n\ 2 = subproblem logs as well as summaries."; static char multiobj_desc[] = "whether to do multi-objective optimization:\n\ 0 = no (default)\n\ 1 = yes\n\ When multiobj = 1 and several linear objectives are\n\ present, suffixes .objpriority, .objweight, .objreltol,\n\ and .objabstol on the objectives are relevant.\n\ Objectives with greater (integer) .objpriority values\n\ have higher priority. Objectives with the same\n\ .objpriority are weighted by .objweight. Objectives\n\ with positive .objabstol or .objreltol are allowed to\n\ be degraded by lower priority objectives by amounts not\n\ exceeding the .objabstol (absolute) and .objreltol\n\ (relative) limits. The objective must all be linear.\n\ Objective-specific values may be assigned via keywords\n\ of the form obj_n_name, such as obj_1_pricing to\n\ specify \"pricing\" for the first objective. If no\n\ .objweight values are provided, 1. is assumed for all.\n\ Similarly, if no .objpriority values are given, 1 is\n\ assumed for all. For .objreltol and .objabstol, if\n\ no values are given, all are assumed to be 0." ; static int pricomp(const void *a, const void *b, void *c) { int d, *x; x = (int*)c; d = x[*(int*)a] - x[*(int*)b]; if (d < 0) return -1; if (d > 0) return 1.; return 0; } static void MOcheck(ASL *asl) { Kwfunc *kf; MOkwval *kwv; SufDesc *oat, *opr, *ort, *owt; char *s, *x; int Nlo, *apri, f, i, j, k, nbad, no, nzw, *operm, *opinv, *pri, z[3]; keyword *kw; real *at, d, *rt, *wt, zd[3]; size_t L; struct paramset *ps; static char BadOption[] = "bad multiobjective keyword assignment"; static char NonlinOjb[] = "multiobjective problem involving a nonlinear objective"; static char Toofew[] = "fewer than 2 nonzero multiobjective weights"; pri = 0; at = rt = wt = 0; no = n_obj; L = no*(4*sizeof(int) + sizeof(struct parmset*)); if ((oat = suf_get("objabstol", ASL_Sufkind_obj))) at = oat->u.r; if ((opr = suf_get("objpriority", ASL_Sufkind_obj))) pri = opr->u.i; if ((ort = suf_get("objreltol", ASL_Sufkind_obj))) rt = ort->u.r; else L += no*sizeof(real); if ((owt = suf_get("objweight", ASL_Sufkind_obj))) wt = owt->u.r; else L += no*sizeof(real); if (!at) L += no*sizeof(real); if (!rt) L += no*sizeof(real); if (!wt) L += no*sizeof(real); momem = (real*)M1alloc(L); x = (char*)momem; if (!at) { memset(at = (real*)x, 0, no*sizeof(real)); x = (char*)(at + no); } if (!(rt)) { memset(rt = (real*)x, 0, no*sizeof(real)); x = (char*)(rt + no); } if (!(wt)) { wt = (real*)x; for(i = 0; i < no; ++i) wt[i] = 1.; x = (char*)(wt + no); } memset(mopars = (struct paramset **)x, 0, no*sizeof(struct paramset*)); x = (char*)(mopars + no); operm = (int*)x; opinv = operm + no; pri0 = opinv + no; apri = pri0 + no; x = (char*)(apri + no); for(i = 0; i < no; ++i) operm[i] = i; nzw = 0; if (owt) { for(i = 0; i < no; ++i) { if (wt[i] == 0.) { operm[i] = -1; ++nzw; } } } if ((Nlo = nlo)) { for(i = 0; i < Nlo; ++i) { if (operm[i] >= 0) { solve_result_num = 532; asl->i.uinfo = NonlinOjb; longjmp(Jb, 1); } } } for(i = 0; i < no; ++i) opinv[i] = -1; if (nzw) { if (nzw >= no - 1) { solve_result_num = 534; asl->i.uinfo = Toofew; longjmp(Jb, 1); } for(i = j = 0; i < no; ++i) { if (operm[i] >= 0) operm[j++] = i; } no = j; } nmo = no; if (pri) { qsortv(operm, no, sizeof(int), pricomp, pri); apri[0] = j = 1; pri0[0] = pri[operm[0]]; for(i = 1; i < no; ++i) { if ((k = pri[operm[i]]) > pri[operm[i-1]]) pri0[j++] = k; apri[i] = j; } nmopri = j; } else { nmopri = 1; pri0[0] = 0; for(i = 0; i < no; ++i) apri[i] = 1; } for(i = 0; i < no; ++i) opinv[operm[i]] = i; nbad = 0; for(kwv = first_MOkw; kwv; kwv = kwv->next) { if ((j = operm[kwv->Objno]) >= 0) { j = apri[j]; if (!(ps = mopars[j])) { if (!(mopars[j] = ps = CPXparamsetcreate(Env, &i))) badret("CPXparamsetcreate", i, 1); } kw = kwv->kw; kf = kw->kf; if (kf == sf_int) { j = (int)strtol(s = kwv->val, &s, 10); if (s == kwv->val) { printf("Expected an integer value for %s, not \"%s\"\n", kw->name, s); badopt_ASL(&Oinfo); } else if ((i = CPXparamsetaddint(Env, ps, f = Intcast kw->info, j))) { ++nbad; if (i == CPXERR_PARAM_INCOMPATIBLE) incompatible(&Oinfo, kw, s, kwv->val); else { z[2] = 0; z[1] = 1; CPXinfointparam(Env, f, z, z+1, z+2); badival(&Oinfo, kw, j, z[1], z[2]); } } } else if (kf == sf_dbl) { d = strtod(s = kwv->val, &s); if (s == kwv->val) { printf("Expected a numeric value for %s, not \"%s\"\n", kw->name, s); badopt_ASL(&Oinfo); } else if ((i = CPXparamsetadddbl(Env, ps, f = Intcast kw->info, d))) { ++nbad; if (i == CPXERR_PARAM_INCOMPATIBLE) incompatible(&Oinfo, kw, s, kwv->val); else { zd[2] = 0.; zd[1] = 1.; CPXinfodblparam(Env, f, zd, zd+1, zd+2); printf("Rejecting obj_%d_%s %g; must be " "between %g and %g\n", kwv->Objno+1, kw->name, d, z[1], z[2]); badopt_ASL(&Oinfo); } } } else { ++nbad; printf("Rejecting inappropriate obj_%d_%s assignment.\n", kwv->Objno + 1, kw->name); badopt_ASL(&Oinfo); } } } if (nbad) { solve_result_num = 533; asl->i.uinfo = BadOption; longjmp(Jb, 1); } mopriority = apri; moabstol = at; objind = operm; indobj = opinv; moreltol = rt; moweight = wt; } #endif /*}*/ #if 0 char undoc[] = "Undocumented."; #endif #ifdef CPLEX_MIP /*{*/ static char absmipap_desc[] = "Absolute mixed-integer optimality gap tolerance\n\ (for difference between current best integer solution\n\ and optimal value of LP relaxation). Default 0.", aggcutlim_desc[] = "Bound on the number of constraints aggregated to\n\ generate flow-cover and mixed-integer-rounding cuts;\n\ default = 3.", #ifdef CPX_PARAM_AUXROOTTHREADS auxrootthreads_desc[] = "Controls the number of threads used for auxiliary\n\ chores when solving the root node of a MIP problem.\n\ When N threads are available (possibly limited by\n\ \"threads\"), auxrootthreads must be less than N.\n\ Possible values:\n\ 0 = automatic choice (default)\n\ n < N: use N-n threads for the root node and\n\ n threads for auxiliary chores.", #endif bbinterval_desc[] = "For nodeselect = 2, select the best-bound node,\n\ rather than the best-estimate node, every\n\ bbinterval iterations (default 7); 0 means\n\ always use the best-estimate node.", #ifdef CPXPARAM_Benders_Strategy /*{*/ benders_feascut_desc[] = "Tolerance for violations of feasibility cuts in Benders\n\ algorithm. Default = 1e-6.", benders_optcut_desc[] = "Tolerance for violations of optimality cuts in Benders\n\ algorithm. Default = 1e-6.", benders_strategy_desc[] = "How to decompose the problem for Benders algorithm:\n\ -1 = do not apply Benders algorithm\n\ 0 = automatic choice (default): if suffix benders\n\ is present on variables, variables that have\n\ .benders = 0 go into the master and CPLEX\n\ assigns other variables to workers; otherwise\n\ integer variables go into the master and\n\ continuous variables into workers\n\ 1 = use suffix benders to determine which variables\n\ are for the master (.benders = 0) and which\n\ for workers (.benders = n > 0 ==> worker n\n\ 2 = similar to 0, but suffix benders is required\n\ 3 = similar to 0, but ignore suffix benders (if\n\ present).", #ifdef CPXPARAM_Benders_WorkerAlgorithm benders_worker_desc[] = "Designate the algorithm that CPLEX applies to solve the\n\ subproblems when using Benders decomposition:\n\ 0 = automatic (default)\n\ 1 = primal simplex\n\ 2 = dual simplex\n\ 3 = network simplex\n\ 4 = barrier algorithm\n\ 5 = sifting algorithm.", #endif bendersopt_desc[] = "Single-word phrase: use Benders algorithm.\n\ Both integer and continuous variables must be present.", #endif /*}*/ bestbound_desc[] = "Single-word phrase requesting return of suffix\n\ .bestbound on the objective and problem for the\n\ best known bound on the objective value. For MIP\n\ problems with .bestnode value from a feasible node\n\ (see below), .bestbound = .bestnode.", bestnode_desc[] = "Single-word phrase requesting return of suffix\n\ .bestnode on the objective and problem for the\n\ objective value at the best feasible MIP node.\n\ For non-MIP problems and for MIP problems for which\n\ a feasible node has not yet been found, this value\n\ is +Infinity for minimization problems and -Infinity\n\ for maximization problems.", boundstr_desc[] = "Whether to use bound strengthening in solving MIPs:\n\ -1 (default) = automatic choice\n\ 0 = never\n\ 1 = always.", #ifdef CPX_PARAM_BQPCUTS bqpcuts_desc[] = "Whether to generate boolean quadratic polytope (BQP)\n\ cuts for nonconvex QP amd MIQP problems when solved\n\ to optimality:\n\ -1 = do not generate BQP cuts\n\ 0 = automatic choice (default)\n\ 1 = generate BQP cuts moderateely\n\ 2 = generate BQP cuts agressively\n\ 3 = generate BQP cuts very agressively.", #endif branch_desc[] = "Branching direction for integer variables:\n\ -1 = down, 0 = algorithm decides, 1 = up; default = 0.", branchdir_desc[] = "Synonym for \"branch\".", cliquecuts_desc[] = "Synonym for \"cliques\".", cliques_desc[] = "Whether to use clique cuts in solving MIPs:\n\ -1 = never\n\ 0 = automatic choice (default)\n\ 1, 2, 3 = ever more aggressive generation.", coeffreduce_desc[] = "Whether to use coefficient reduction when\n\ preprocessing MIPS:\n\ -1 = automatic choice (default)\n\ 0 = no\n\ 1 = reduce only integral coefficients\n\ 2 = reduce all potential coefficients\n\ 3 = reduce aggressively with tiling.", covercuts_desc[] = "Synonym for \"covers\".", covers_desc[] = "Whether to use cover cuts in solving MIPs:\n\ -1 = never\n\ 0 = automatic choice (default)\n\ 1, 2, 3 = ever more aggressive generation.", #ifdef CPX_PARAM_CPUMASK cpumask_desc[] = "Whether and how to bind threads to cores\n\ on systems where this is possible:\n\ off = no CPU binding\n\ auto = automatic binding (default).\n\ Values other than \"off\" and \"auto\" must be a\n\ hexadecimal string (digits 0-9 and a-f, ignoring\n\ case, so values A-F and a-f are treated alike).\n\ The lowest order bit is for the first logical CPU.\n\ For example, \"a5\" and \"A5\" indicate that CPUs 0, 2,\n\ 5, and 7 are available for binding to threads, since\n\ hex value a5 = 2^7 + 2^5 + 2^2 + 2^0.", #endif cutpass_desc[] = "Number of passes permitted when generating MIP\n\ cutting plane:\n\ -1 = none\n\ 0 = automatic choice (default)\n\ positive = at most that many passes.", cutsfactor_desc[] = #if CPX_VERSION >= 12060200 "Limit on MIP cuts added:\n\ > 1 ==> (cutsfactor-1)*m, where m\n\ is the original number of rows (after presolve);\n\ < 0 ==> no limit;\n\ 0 <= cutsfactor <= 1 ==> no MIP cuts\n\ Default = -1 (no limit).", #else "Limit MIP cuts added to (cutsfactor-1)*m, where m\n\ is the original number of rows (after presolve).\n\ Default = 4.", #endif #if CPX_VERSION >= 1100 cutstats_desc[] = "0 or 1 (default 0): Whether the solve_message report\n\ the numbers and kinds of cuts used.", #endif disjcuts_desc[] = "Whether to generate MIP disjunctive cuts:\n\ -1 = no\n\ 0 = automatic choice (default)\n\ 1, 2, 3 = ever more aggressive generation.", #ifdef CPX_PARAM_IISIND /* version < 9.2b */ endtree_desc[] = "File for writing final branch & bound search tree.\n\ Withdrawn from CPLEX 10.", #endif finalmipalg_desc[] = "Specify the algorithm to solve the final LP\n\ obtained by fixing all integer variables at\n\ their integer values:\n\ 0 = automatic (default)\n\ 1 = primal simplex\n\ 2 = dual simplex\n\ 3 = network simplex\n\ 4 = barrier\n\ 5 = sifting (not applicable to QP)\n\ 6 = concurrent optimizer.", flowcuts_desc[] = "Whether to use flow cuts in solving MIPs:\n\ -1 = never\n\ 0 = automatic choice (default)\n\ 1, 2 = ever more aggressive use.", flowpathcuts_desc[] = "Whether to generate MIP flow-path cuts:\n\ -1 = no\n\ 0 = automatic choice (default)\n\ 1, 2 = ever more aggressive generation.", #ifdef CPX_PARAM_FPHEUR fpheur_desc[] = "Whether to use the feasibility pump heuristic on MIP\n\ problems:\n\ -1 = no\n\ 0 = automatic choice (default)\n\ 1 = yes, focus on finding a feasible solution\n\ 2 = yes, focus on finding a good objective\n\ value at a feasible solution.", #endif #ifndef NO_CPLEX66 /* for versions prior to CPLEX 6.6 */ fraccand_desc[] = "Limit on number of candidate variables when\n\ generating Gomory cuts for MIP problems:\n\ default = 200.", fraccuts_desc[] = "Whether to generate MIP fractional Gomory\n\ cuts:\n\ -1 = no\n\ 0 = decide automatically (default)\n\ 1 = generate moderately\n\ 2 = generate aggressively.", fracpass_desc[] = "Limit on number of passes to generate MIP\n\ fractional Gomory cuts:\n\ 0 = automatic choice (default)\n\ positive = at most that many passes.", fractionalcuts_desc[] = "Synonym for \"fracpass\".", #endif gubcuts_desc[] = "Whether to use GUB cuts in solving MIPs:\n\ -1 = never\n\ 0 = automatic choice (default)\n\ 1, 2 = ever more aggressive generation.", #ifdef CPX_PARAM_HEURFREQ heurfreq_desc[] = "How often to apply \"node heuristics\" for MIPS:\n\ -1 = never\n\ 0 = automatic choice (default)\n\ n > 0 = every n nodes.", #endif #ifdef CPXPARAM_MIP_Strategy_HeuristicEffort heureffort_desc[] = "Whether to increase ( > 1) or decrease ( < 1) efforts\n\ spent on heuristics during MIP solvers;\n\ heureffort = 0 ==> suppress all MIP heuristics.", #endif #ifdef CPX_PARAM_HEURISTIC heuristic_desc[] = "Deprecated: withdrawn from CPLEX 9.0.\n\ What heuristic to use on MIPS for finding an\n\ initial integer solution:\n\ -1 = none\n\ 0 = decide automatically (default)\n\ 1 = use a rounding heuristic at node 0.", #endif #ifdef CPX_PARAM_HEURFREQ heuristicfreq_desc[] = "Synonym for \"heurfreq\".", #endif iisfind_desc[] = "Whether to find and return an IIS (irreducible\n\ infeasible set of variables and constraints) if\n\ the problem is infeasible:\n\ 0 = no (default)\n\ 1 = find an IIS.\n\ IIS details are returned in suffix .iis, which\n\ assumes one of the values \"non\" for variables\n\ and constraints not in the IIS; \"low\" for\n\ variables or inequality constraint bodies whose lower\n\ bounds are in the IIS; \"upp\" for variables and\n\ inequality constraint bodies whose upper bounds are\n\ in the IIS; and \"fix\" for equality constraints that\n\ are in the IIS.", impliedcuts_desc[] = "Whether to use implied cuts in solving MIPs:\n\ -1 = never\n\ 0 = automatic choice (default)\n\ 1, 2 = ever more aggressive use.", integrality_desc[] = "Amount by which an integer variable can differ\n\ from the nearest integer and still be considered\n\ feasible. Default = 1e-5; must be in [1e-9, 0.5].\n\ (The upper bound was not enforced prior to CPLEX 11.)", intwarntol_desc[] = "Do not warn about perturbations to \"integer\"\n\ variables to make them integers when the maximum\n\ perturbation is at most intwarntol (default 1e-9);\n\ see \"round\".", #ifdef CPX_PARAM_LBHEUR lbheur_desc[] = "Whether to use a local branching heuristic in an\n\ attempt to improve new incumbents found during a\n\ MIP search. (Default = 0 = no; 1 = yes.)", #endif #ifdef CPXPARAM_MIP_Cuts_LocalImplied localimpliedcuts_desc[] = "Whether to generate locally valid implied bound\n\ cuts for MIP problems:\n\ -1 ==> no\n\ 0 ==> automatic choice (default)\n\ 1 ==> yes, moderately\n\ 2 ==> yes, aggressively\n\ 3 ==> yes, very aggressively.", #endif lowercutoff_desc[] = "For maximization problems involving integer\n\ variables, skip any branch whose LP relaxation's\n\ optimal value is less than lowercutoff. Warning:\n\ if lowercutoff is too large, the problem will\n\ appear infeasible. Default = -1e75.", #ifdef CPX_PARAM_MCFCUTS mcfcuts_desc[] = "Whether to use multi-commodity flow (MCF) cuts:\n\ -1 = no\n\ 0 = let CPLEX decide (default)\n\ 1 = generate a modest number of MCS cuts\n\ 2 = generate MCS cuts aggressively.", #endif #if 0 /* old mipalg_desc; not sure when it change to the one for 12.6.1, given below */ mipalg_desc[] = "Algorithm used on mixed-integer subproblems\n\ (default 2):\n\ 1 = primal simplex\n\ 2 = dual simplex (plus primal, if dual fails)\n\ 3 = network alg., then dual simplex\n\ 4 = barrier with crossover\n\ The next two are not available in CPLEX versions >= 8;\n\ specify mipcrossover instead.\n\ 5 = dual to iteration limit, then barrier\n\ 6 = barrier without crossover.", #else /* valid at least for CPLEX 12.6.1 */ mipalg_desc[] = "Algorithm used on mixed-integer subproblems:\n\ 0 = automatic choice (default)\n\ 1 = primal simplex\n\ 2 = dual simplex\n\ 3 = network simplex\n\ 4 = barrier\n\ 5 = sifting.\n\ For MIQP problems (quadratic objective, linear\n\ constraints), settings other than 3 and 5 are treated\n\ as 0. For MIQCP problems (quadratic objective and\n\ constraints), all settings are treated as 4.", #endif mipalgorithm_desc[] = "Synonym for \"mipalg\".", mipbasis_desc[] = "Whether to compute a basis and dual variables for MIP\n\ problems when endbasis is not specified:\n\ -1 = default (described below)\n\ 0 = no\n\ 1 = yes\n\ This keyword is new with driver version 20040716.\n\ When endbasis is specified, mipbasis=1 is assumed.\n\ Otherwise, when mipbasis=0 is specified for a MIP\n\ problem, no solver-status values for variables are\n\ returned to AMPL. The default is to assume 1 unless\n\ a quadratic objective or constraint is present, in\n\ which case qcdual is assumed if quadratic constraints\n\ are present and 0 is assumed otherwise (as finding a\n\ basis can be time consuming).", mipcrossover_desc[] = "Crossover method used when using the barrier\n\ method for MIP subproblems:\n\ -1 = no crossover\n\ 0 (default) = automatic choice\n\ 1 = primal\n\ 2 = dual.", mipcuts_desc[] = "Sets all ten of cliques, covers, disjcuts,\n\ flowcuts, flowpathcuts, fraccuts, gubcuts,\n\ impliedcuts, mircuts and zerohalfcuts to the\n\ specified value.", mipdisplay_desc[] = "Frequency of displaying branch-and-bound\n\ information (for optimizing integer variables):\n\ 0 (default) = never\n\ 1 = each integer feasible solution\n\ 2 = every \"mipinterval\" nodes\n\ 3 = every \"mipinterval\" nodes plus\n\ information on LP relaxations\n\ (as controlled by \"display\")\n\ 4 = same as 2, plus LP relaxation info\n\ 5 = same as 2, plus LP subproblem info.", mipemphasis_desc[] = "How to balance seeking seeking\n\ feasibility versus optimality when solving a MIP:\n\ 0 = balance optimality and feasibility (default)\n" #ifdef CPX_MIPEMPHASIS_FEASIBILITY "\ 1 = emphasize feasibility over optimality\n\ 2 = emphasize optimality over feasibility\n\ 3 = emphasize moving the best bound" #endif #ifdef CPX_MIPEMPHASIS_HIDDENFEAS "\n\ 4 = emphasize finding hidden feasible solutions" #endif #ifdef CPX_MIPEMPHASIS_HEURISTIC "\n\ 5 = emphasize finding good feasible solutions sooner" #endif ".", mipgap_desc[] = "Relative tolerance for optimizing integer\n\ variables: stop if\n\ abs((best bound) - (best integer))\n\ < mipgap * (1 + abs(best bound)).\n\ Default = 1e-4; must be between 1e-9 and 1.", mipinterval_desc[] = "Frequency of node logging for mipdisplay >= 2.\n\ Default = 0 ==> automatic choice. Values n > 0 ==>\n\ every n nodes and every new incumbent; n < 0 ==> less\n\ frequently the more negative n is.", #ifdef CPX_PARAM_MIPKAPPASTATS mipkappa_desc[] = "For MIP problems, whether to compute the \"MIP kappa\",\n\ which summarizes the condition numbers of the optimal\n\ bases seen while solving the problem:\n\ -1 = no\n\ 0 = automatic choice (default)\n\ 1 = compute for a sample of subproblems\n\ 2 = compute for all subproblems (possibly expensive).", #endif mipordertype_desc[] = "Synonym for \"ordertype\".", #ifdef CPX_PARAM_MIPSEARCH mipsearch_desc[] = "Search strategy for mixed-integer problems, new\n\ in CPLEX 11:\n\ 0 = automatic choice (default)\n\ 1 = traditional branch and cut\n\ 2 = dynamic search.", #endif mipsolutions_desc[] = "Stop branch-and-bound for integer variables\n\ after finding \"mipsolutions\" feasible solutions.\n\ Default = 2^31 - 1.", mipstart_desc[] = "Synonym for \"mipstartvalue\".", #if 0 /* old mipstartalg_desc; not sure when it change to the one for 12.6.1, given below */ mipstartalg_desc[] = "Which LP algorithm to use in solving the initial\n\ MIP subproblem:\n\ 1 = primal simplex\n\ 2 = dual simplex (default)\n\ 3 = netopt\n\ 4 = barrier with crossover\n\ The next two are not available in CPLEX versions >= 8;\n\ specify mipcrossover instead.\n\ 5 = dual simplex to iteration limit,\n\ then barrier\n\ 6 = barrier without crossover.", #else /* valid at least for CPLEX 12.6.1 */ mipstartalg_desc[] = "For problems with integer variables, which algorithm\n\ to use in solving the initial MIP subproblem:\n\ 0 = automatic choice (default)\n\ 1 = primal simplex\n\ 2 = dual simplex\n\ 3 = network simplex\n\ 4 = barrier\n\ 5 = sifting\n\ 6 = concurrent (several at once, if possible).\n\ For MIQP problems (quadratic objective, linear\n\ constraints), setting 5 is treated as 0 and 6 as 4.\n\ For MIQCP problems (quadratic objective & constraints),\n\ all settings are treated as 4.", #endif mipstartstatus_desc[] = "Whether to use incoming variable and constraint\n\ statuses if the problem has integer variables:\n\ 0 = no\n\ 1 = yes (default).", mipstartvalue_desc[] = "Whether to use initial guesses in problems with\n\ integer variables:\n\ 0 = no.\n\ 1 = yes (default), automatic choice of algorithm." #if CPX_VERSION < 12070000 "\n\ 2 = yes, using the deprecated CPXcopymipstart\n\ function (as formerly done), rather than\n\ the now preferred CPXaddmipstarts (starting\n\ with driver version 20110607); this is for\n\ debugging and is to be withdrawn.", #else "\n\ 2 = withdrawn and now treated as 0.\n\ 3 = effort level = CPX_MIPSTART_CHECKFEAS, which\n\ fails if the starting point is infeasiable.\n\ 4 = effort level = CPX_MIPSTART_SOLVEFIXED, which\n\ solves the fixed problem specified by the starting\n\ guess.\n\ 5 = effort level = CPX_MIPSTART_SOLVEMIP, which\n\ causes a subMIP problem to be solved; \"submipnodelim\"\n\ limits the number of nodes explored.\n\ 6 = effort level = CPX_MIPSTART_REPAIR, which causes\n\ an attempt to repair an infeasible starting guess;\n\ \"repairtries\" tells how often to attempt a repair, and\n\ \"submipnodelim\" limits the number of nodes explored.\n\ 7 = effort level = CPX_MIPSTART_NOCHECK, under which\n\ the starting guess is simply assumed to be feasiable.", #endif mipsubalg_desc[] = "Synonym for \"mipalg\".", #ifdef CPX_PARAM_MIPTHREADS mipthreads_desc[] = "Maximum threads for the MIP algorithm\n\ (1 unless you have a CPLEX license for multiple\n\ threads). Withdrawn from CPLEX 11.", #endif #ifdef CPX_PARAM_MIQCPSTRAT miqcpstrat_desc[] = "Strategy for solving quadratically-constrained MIPs\n\ (MIQCP problems):\n\ 0 = automatic choice (default)\n\ 1 = solve a quadratically-constrained node\n\ relaxation (QCP) at each node\n\ 2 = solve an LP node relaxation at each node.", #endif mircuts_desc[] = "Whether to generate MIP rounding cuts:\n\ -1 = no\n\ 0 = automatic choice (default)\n\ 1 = moderate generation\n\ 2 = aggressive generation.", node_desc[] = "Synonym for \"nodes\".", #ifdef CPX_PARAM_NODECUTS nodecuts_desc[] = "Decides whether or not cutting planes are separated\n\ at the nodes of the branch-and-bound tree:\n\ -1 = do not generate node cuts\n\ 0 = automatic (default)\n\ 1 = generate moderately\n\ 2 = generate aggressively\n\ 3 = genertate very aggresively.", #endif nodefile_desc[] = "Whether to save node information in a temporary file:\n\ 0 = no\n\ 1 (default) = compressed node file in memory\n\ 2 = node file on disk\n\ 3 = compressed node file on disk.", nodefiledir_desc[] = "Synonym for workfiledir. Prior to CPLEX 7.1,\n\ this directory is just for node information files.", #ifdef CPX_PARAM_NODEFILELIM nodefilelim_desc[] = "Maximum size for the node file. Default 1e75.\n\ Removed from CPLEX 7.1. See workfilelim.", nodefilesize_desc[] = "Synonym for \"nodefilelim\".", #endif nodelim_desc[] = "Synonym for \"nodes\".", nodes_desc[] = "Stop branch-and-bound for integer variables\n\ after \"nodes\" LP relaxations. Default = 2^31 - 1;\n\ nodes = 0 ==> complete processing at the root (create\n\ cuts, apply heuristics at root);\n\ 1 ==> allow branching from root: create but do not\n\ solve nodes.", nodesel_desc[] = "Strategy for choosing next node while optimizing\n\ integer variables:\n\ 0 = depth-first search;\n\ 1 = breadth-first search (default);\n\ 2 = best-estimate search;\n\ 3 = alternate best-estimate search.", nodeselect_desc[] = "Synonym for \"nodesel\".", nosolve_desc[] = "Stop after loading the problem and honoring any\n\ \"writeprob\" or \"writemipstart\" directives.", ordertype_desc[] = "How to generate default priorities for integer\n\ variables when no .priority suffix is specified:\n\ 0 = do not generate priorities (default)\n\ 1 = use decreasing costs\n\ 2 = use increasing bound range\n\ 3 = use coefficient count.", plconpri_desc[] = "Priority (default 1) for SOS2 constraints for nonconvex\n\ piecewise-linear terms in constraints.", plobjpri_desc[] = "Priority (default 2) for SOS2 constraints for nonconvex\n\ piecewise-linear terms in objectives.", #ifdef CPX_PARAM_POLISHAFTEREPAGAP polishafter_absmipgap_desc[] = "Start polishing integer solutions after the\n\ absolute mixed-integer optimality gap is at most\n\ polishafter_absmipgap. Default 1e-6.", polishafter_intsol_desc[] = "Start polishing integer solutions after the\n\ finding polishafter_intsol integer-feasible\n\ solutions. Default 2^31 - 1.", polishafter_mipgap_desc[] = "Start polishing integer solutions after the\n\ relative mixed-integer optimality gap is at most\n\ polishafter_mipgap. Default 0.", polishafter_nodes_desc[] = "Start polishing integer solutions after the\n\ processing polishafter_nodes nodes.\n\ Default 2^31 - 1.", polishafter_time_desc[] = "Start polishing integer solutions after finding\n\ at least one integer feasible solution and spending\n\ polishafter_time CPU seconds seeking integer\n\ solutions. Default 1e75.", #endif #ifdef CPX_PARAM_POLISHAFTERDETTIME polishafter_timedet_desc[] = "Start polishing integer solutions after finding\n\ at least one integer feasible solution and spending\n\ polishafter_time \"ticks\" seeking integer solutions.\n\ Default 1e75.", #endif #ifdef CPX_PARAM_POLISHTIME polishtime_desc[] = "New in CPLEX 10.0: seconds to spend \"polishing\"\n\ integer solutions. Default 0.\n\ Deprecated in CPLEX 11.2 (in favor of the polishafter\n\ keywords above).", #endif #ifdef CPX_PARAM_POPULATELIM poolagap_desc[] = "Solutions with objective worse in absolute value by\n\ poolgap than the best solution are not kept in the\n\ solution pool; see poolstub. Default 1e75.", poolcapacity_desc[] = "Number of solutions to keep in solution pool;\n\ see poolstub. Default 2100000000.", pooldual_desc[] = "Whether to return dual values (corresponding to fixed\n\ integer variables) for MIP and MIQP problems in the\n\ solution pool:\n\ 0 = no (default)\n\ 1 = yes (which takes extra computation)", poolgap_desc[] = "Solutions with objective worse in a relative sense by\n\ poolgap than the best solution are not kept in the\n\ solution pool; see poolstub. Default 1e75.", poolintensity_desc[] = "How hard to try adding MIP solutions to the solution\n\ pool. Useful only if poolstub is specified. Default 0\n\ is treated as 1 if poolstub is specified without\n\ populate, or 2 if populate is specified. Larger values\n\ (3 or 4) cause more additions to the solution pool,\n\ possibly consuming considerable time; poolintensity 4\n\ tries to generate all MIP solutions, which could be a\n\ very large number.", poolreplace_desc[] = "Policy for replacing solutions in the solution pool if\n\ more than poolcapacity solutions are generated:\n\ 0 = FIFO (first-in, first-out); default\n\ 1 = Keep best solutions\n\ 2 = Keep most diverse solutions.", poolstub_desc[] = "Stub for solution files in the MIP solution pool.\n\ New in CPLEX 11 and meaningful only if some variables\n\ are integer or binary. A pool of alternate MIP\n\ solutions is computed if poolstub is specified, and the\n\ solutions that remain in the solution pool (after some\n\ are replaced if more than poolcapacity solutions are\n\ found) are written to files\n\ (poolstub & '1') ... (poolstub & |solution pool|),\n\ where |solution pool| is the number of solutions in the\n\ solution pool. That is, file names are obtained by\n\ appending 1, 2, ... |solution pool| to poolstub. The\n\ value of |solution pool| is returned in suffix npool\n\ on the objective and problem.", populate_desc[] = "Whether to run CPLEX's \"populate\" algorithm in an\n\ attempt to add more solutions to the MIP solution pool.\n\ 0 = no; just keep solutions found during the\n\ initial solve\n\ 1 = run \"populate\" after finding a MIP solution\n\ 2 = run \"populate\" instead of seeking a single\n\ best solution.\n\ See poolstub.", populatelim_desc[] = "Limit on number of solutions added to the solution pool\n\ by the populate algorithm. See poolstub and populate.\n\ Default 20.", prerelax_desc[] = "Whether to use CPLEX's presolve on the initial LP\n\ relaxation of a MIP:\n\ -1 = automatic choice (default)\n\ 0 = no\n\ 1 = yes.", #endif priorities_desc[] = "Whether to consider priorities for MIP branching:\n\ 0 = no\n\ 1 = yes (default).", probe_desc[] = "Whether to do variable probing when solving MIPs\n\ (which sometimes dramatically affects performance,\n\ for better or worse):\n\ -1 = no\n\ 0 = automatic choice (default)\n\ 1, 2, or 3 = ever more probing.", #ifdef CPX_PARAM_PROBETIME probetime_desc[] = "Limit in seconds on time spent probing.\n\ Default = 1e75.", #endif #ifdef CPX_PARAM_PROBEDETTIME probetimedet_desc[] = "Limit in \"ticks\" on time spent probing.\n\ Default = 1e75.", #endif #ifdef Want_Distmipopt rampup_duration_desc[] = "How to ramp up distributed parallel optimization:\n\ -1 = no ramp up\n\ 0 = automatic choice (default)\n\ 1 = dynamic rampup, limited by rampup_timelim and\n\ rampup_walltimelim\n\ 2 = infinite ramp up: concurrent MIP optimization.", rampup_timelim_desc[] = "Time limit in deterministic \"ticks\" to spend on the\n\ \"ramp up\" phase of distributed parallel optimization.\n\ This only matters when rampup_duration = 0 or 1.\n\ Default = 1e75.", rampup_walltimelim_desc[] = "Time limit limit in wall-clock seconds to spend on the\n\ \"ramp up\" phase of distributed parallel optimization.\n\ This only matters when rampup_duration = 0 or 1.\n\ Default = 1e75.", #endif relax_desc[] = "Single-word phrase: ignore integrality.", relaxpresolve_desc[] = "Synonym for \"prerelax\".", relobjdif_desc[] = "Synonym for \"relobjdiff\".", relobjdiff_desc[] = "If the objdifference parameter is 0,\n\ relobjdiff times the absolute value of the objective\n\ value is added to (for maximizing) or subtracted\n\ from (for minimizing) the best (so far) feasible\n\ objective value while optimizing integer variables.\n\ Subsequent nodes will be ignored if their LP\n\ relaxations have optimal values worse than this\n\ sum. Default = 0. Positive values may speed\n\ the search -- and may cause the optimal solution\n\ to be missed.", relpresolve_desc[] = "Synonym for \"prerelax\".", #ifdef CPX_PARAM_REPAIRTRIES repairtries_desc[] = "How many times to try to repair in infeasible\n\ MIP starting guess:\n\ -1 = none\n\ 0 = automatic choice (default)\n\ > 0 = that many times.", #endif #ifdef CPX_PARAM_REPEATPRESOLVE repeatpresolve_desc[] = "Whether to repeat CPLEX's presolve at MIP nodes:\n\ -1 = automatic choice (default)\n\ 0 = no\n\ 1 = presolve again ignoring cuts\n\ 2 = presolve again considering cuts\n\ 3 = presolve again considering cuts and\n\ allowing new root cuts.", #endif #undef REQCONVEX #ifdef CPX_PARAM_OPTIMALITYTARGET #define REQCONVEX CPX_PARAM_OPTIMALITYTARGET #elif defined(CPX_PARAM_SOLUTIONTARGET) #define REQCONVEX CPX_PARAM_SOLUTIONTARGET #endif #ifdef REQCONVEX reqconvex_desc[] = "Whether to require a quadratic model to be convex:\n\ 0 = automatic choice (default)\n\ 1 = require convexity\n\ 2 = do not require convexity; just look\n\ for a local solution" #if CPX_VERSION >= 12060000 "\n\ 3 = globally solve if noncovex.", #else ".", #endif #endif resolve_desc[] = "Whether to re-solve the problem with CPLEX's\n\ presolve turned off when it reports the problem\n\ to be infeasible or unbounded. Re-solving may\n\ take extra time but should determine whether the\n\ problem is infeasible or unbounded.\n\ 0 = no\n\ 1 = yes (default).", return_mipgap_desc[] = "Whether to return mipgap suffixes or include\n\ mipgap values in the solve_message: sum of\n\n\ 1 = return relmipgap suffix\n\ 2 = return absmipgap suffix\n\ 4 = suppress mipgap values in solve_message\n\n\ The suffixes are on the objective and problem;\n\ returned suffix values are +Infinity if no integer-\n\ feasible solution has been found, in which case no\n\ mipgap values are reported in the solve_message.\n\ Default = 0. See also bestbound and bestnode above.", #ifdef CPX_PARAM_RINSHEUR rinsheur_desc[] = "Relaxation INduced neighborhood Search HEURistic\n\ for MIP problems:\n\ -1 = none\n\ 0 = automatic choice of interval (default)\n\ n (for n > 0) = every n nodes.", #endif #ifdef CPXPARAM_MIP_Cuts_RLT rltcuts_desc[] = "Whether to use RLT (Reformulation Linearization\n\ Technique) cuts:\n\ -1 = no\n\ 0 = automatic choice (default)\n\ 1 = generate RLT cuts moderately\n\ 2 = generate RLT cuts aggressively\n\ 3 = generate RLT cuts very aggressively", #endif #ifdef CPX_PARAM_HEURISTIC rootheuristic_desc[] = "Withdrawn from CPLEX 9.0. Synonym for \"heuristic\".", #endif round_desc[] = "Whether to round integer variables to integral\n\ values before returning the solution, and whether\n\ to report that CPLEX returned noninteger values\n\ for integer values (default 1): sum of\n\ 1 ==> round nonintegral integer variables\n\ 2 ==> do not modify solve_result\n\ 4 ==> do not modify solve_message\n\ 8 ==> modify solve_result and solve_message\n\ even if maxerr < intwarntol (default 1e-9).\n\ Modifications take place only if CPLEX assigned\n\ nonintegral values to one or more integer variables.", solutionlim_desc[] = "Synonym for \"mipsolutions\".", sos_desc[] = "0 or 1 (default 1): Whether to honor declared\n\ suffixes .sosno and .ref describing SOS sets.\n\ Each distinct nonzero .sosno value designates an SOS\n\ set, of type 1 for positive .sosno values and of type\n\ 2 for negative values. The .ref suffix contains\n\ corresponding reference values.", sos2_desc[] = "0 or 1 (default 1): Whether to tell CPLEX about SOS2\n\ constraints for nonconvex piecewise-linear terms.", #ifdef CPX_PARAM_LANDPCUTS splitcuts_desc[] = "Whether to use lift-and-project cuts on MIP problems\n\ (new for CPLEX 12.5.1):\n\ -1 = no\n\ 0 = automatic choice (default)\n\ 1 = moderate use\n\ 2 = aggressive use\n\ 3 = very aggressive use.", #endif startalg_desc[] = "Synonym for \"mipstartalg\".", startalgorithm_desc[] = "Synonym for \"mipstartalg\".", startbasis_desc[] = "\"startbasis foo\" reads the initial basis\n\ (in BAS format) from file \"foo\".", startsol_desc[] = "Synonym for \"readsol\".", #ifdef CPX_PARAM_IISIND /* version < 9.2b */ starttree_desc[] = "File for reading initial branch-and-bound search tree.", #endif strongcand_desc[] = "Length of the candidate list for \"strong branching\"\n\ when solving MIPs: default 10.", strongit_desc[] = "Number of simplex iterations on each variable in\n\ the candidate list during strong branching.\n\ Default = 0 = automatic choice.", #ifdef CPX_PARAM_STRONGTHREADLIM strongthreads_desc[] = "Maximum threads during strong branching.\n\ Default = 1.", #endif subalg_desc[] = "Synonym for \"mipalg\".", subalgorithm_desc[] = "Synonym for \"mipalg\".", #ifdef CPX_PARAM_SUBMIPSUBALG submipalg_desc[] = "Choice of algorithm used to solve the subproblems\n\ of a subMIP: not a subproblem, but an auxiliary MIP\n\ that CPLEX sometimes forms and solves, e.g., when\n\ * dealing with a partial MIP start\n\ * repairing an infeasible MIP start\n\ * using the RINS heuristic\n\ * branching locally\n\ * polishing a solution.\n\ Possible values (when appropriate):\n\ 0 = automatic choice (default)\n\ 1 = primal simplex\n\ 2 = dual simplex\n\ 3 = network simplex (not for MIQPs)\n\ 4 = barrier\n\ 5 = sifting (0 is used for MIQPs).\n\ Only 0 is allowed for MIQCPs.", #endif #ifdef CPXPARAM_MIP_SubMIP_NodeLimit submipnodelim_desc[] = "Limit on nodes searched by relaxation induced\n\ neighborhood search (RINS) heuristic for MIP\n\ problems and for processing of MIP starting values.\n\ Default = 500.", #endif #ifdef CPX_PARAM_SUBMIPSCAIND submipscale_desc[] = "Rarely used choice of scaling for auxiliary subMIPs\n\ (described with \"submipalg\"):\n\ -1 = no scaling\n\ 0 = equilibration scaling (default)\n\ 1 = more aggressive scaling.", #endif #ifdef CPX_PARAM_SUBMIPSTARTALG submipstartalg_desc[] = "Rarely used choice of algorithm for the initial\n\ relaxation of a subMIP (described with \"submipalg\"):\n\ 0 = automatic choice (default)\n\ 1 = primal simplex\n\ 2 = dual simplex\n\ 3 = network simplex\n\ 4 = barrier\n\ 5 = sifting (0 is used for MIQPs)\n\ 6 = concurrent (dual, barrier and primal in\n\ opportunistic mode; dual and barrier in\n\ deterministic mode; 4 is used for MIPQs).\n\ Only 0 is allowed for MIQCPs.", #endif #ifdef CPX_PARAM_SYMMETRY symmetry_desc[] = "Whether to break symmetry during\n\ preprocessing of MIP problems:\n\ -1 = automatic choice (default)\n\ 0 = no\n\ 1 = moderate effort\n\ 2 = more effort\n\ 3 = still more effort" #if CPX_VERSION >= 11000000 "\n\ 4 = even more effort (new in CPLEX 11)\n\ 5 = more effort than 4 (new in CPLEX 11).", #else ".", #endif #endif treelimit_desc[] = "Synonym for \"treememory\".", treememlim_desc[] = "Synonym for \"treememory\".", treememory_desc[] = "Max. megabytes of memory (default 1e75) to use for\n\ branch-and-bound tree.", uppercutoff_desc[] = "For minimization problems involving integer\n\ variables, skip any branch whose LP relaxation's\n\ optimal value is more than uppercutoff. Warning:\n\ if uppercutoff is too small, the problem will\n\ appear infeasible. Default = 1e75.", varsel_desc[] = "Strategy for selecting the next branching\n\ variable during integer branch-and-bound:\n\ -1 = branch on variable with smallest\n\ integer infeasibility\n\ 0 = algorithm decides (default)\n\ 1 = branch on variable with largest\n\ integer infeasibility" #if CPX_VERSION >= 6050000 "\n\ 2 = branch based on pseudo costs\n\ 3 = strong branching\n\ 4 = branch based on pseudo reduced costs.", #else "\n\ 2 = branch based on pseudo reduced costs.", #endif varselect_desc[] = "Synonym for \"varsel\"." #ifdef Want_Distmipopt ,vmconf_desc[] = "For distributed parallel MIP optimization, if vmconf\n\ starts with @, then the remainder is the name of a file\n\ containing a parallel MIP configuration; otherwise\n\ vmconf itself is a parallel MIP configuration string,\n\ which must be quoted if it contains white space." #endif #ifdef CPX_PARAM_ZEROHALFCUTS ,zerohalfcuts_desc[] = "Whether to generate zero-half cuts for MIP problems:\n\ -1 = no\n\ 0 = automatic choice (default): continue\n\ generating until new cuts are not helpful\n\ 1 = generate zero-half cuts moderately\n\ 2 = generate zero-half cuts aggressively." #endif ; #endif /*}*/ static char advance_desc[] = "Whether to use advance basis information (initial\n\ primal and dual variable values and basis indicators).\n\ Default 1 (yes).", aggfill_desc[] = "Synonym for \"agglim\".", agglim_desc[] = "Variables that appear in more than agglim rows\n\ (default 10) will not be substituted away by the\n\ \"aggregate\" algorithm.", aggregate_desc[] = "Whether to make substitutions to reduce the number of\n\ rows: 0 ==> no; n > 0 ==> apply aggregator n times.\n\ Default -1 ==> automatic choice.", aggtol_desc[] = "Pivot tolerance for aggregating. It seldom needs\n\ fiddling. Default = .05; must be in [1e-10, .99].", autoopt_desc[] = "Single-word phrase: use CPLEX's automatic choice of\n\ optimizer (currently dualopt for LPs).", autopt_desc[] = "Synonym for \"autoopt\".", backtrack_desc[] = "Tolerance (> 0, default 0.9999) for when to backtrack\n\ during branch & bound. Low values tend to pure\n\ best-bound search. High values (> 1) tend to pure\n\ depth-first search. Values less than the default\n\ are often good when subproblems are expensive.", #ifdef BARRIER baralg_desc[] = "How to start the barrier algorithm:\n\ 0 (default) = 1 for MIP subproblems, else 3\n\ 1 = infeasibility-estimate start\n\ 2 = infeasibility-constant start\n\ 3 = standard start.", barcorr_desc[] = "Limit on centering corrections in each iteration\n\ of the barrier algorithm:\n\ -1 = decide automatically (default)\n\ nonnegative = at most that many.", bardisplay_desc[] = "Specifies how much the barrier algorithm chatters:\n\ 0 = no output (default)\n\ 1 = one line per iteration\n\ 2 = more output.", bargrowth_desc[] = "Tolerance for detecting unbounded faces in the\n\ barrier algorithm: higher values make the test\n\ for unbounded faces harder to satisfy.\n\ Default = 1e12.", bariterlim_desc[] = "Maximum barrier iterations allowed (default 2^31 - 1).", barobjrange_desc[] = "Limit on the absolute objective value before the\n\ barrier algorithm considers the problem unbounded.\n\ Default = 1e20.", baropt_desc[] = "Single-word phrase: use the barrier algorithm\n\ (unless there are discrete variables).", #ifdef CPX_PARAM_BAROOC baroutofcore_desc[] = "Whether the barrier solver should use disk\n\ (out-of-core) storage for Cholesky factors:\n\ 0 = no (default)\n\ 1 = yes.\n\ Withdrawn in CPLEX 10.0.", #endif barstart_desc[] = "Barrier starting-point algorithm:\n\ 1 = assume dual is 0 (default)\n\ 2 = estimate dual\n\ 3 = average of primal estimate, 0 dual\n\ 4 = average of primal and dual estimates.", barstartalg_desc[] = "Synonym for \"barstart\".", #ifdef CPX_PARAM_BARTHREADS barthreads_desc[] = "Maximum threads for the barrier algorithm\n\ (1 unless you have a CPLEX license for multiple\n\ threads). Withdrawn from CPLEX 11.", #endif #ifdef CPX_PARAM_BARVARUP barvarup_desc[] = "Upper bound imposed by barrier algorithm on\n\ variables with infinite upper bound; used to\n\ prevent trouble with problems having unbounded\n\ optimal faces. Default = 1e20.\n\ Withdrawn from CPLEX 9.0.", #endif #endif /* BARRIER */ #ifdef BASDEBUG basdebug_desc[] = "Filename for output to debug basis transmission.", #endif basis_cond_desc[] = "Whether to show the condition number of the simplex\n\ basis in the solve_message and to return its value\n\ in the problem.basis_cond and objective.basis_cond\n\ suffixes. (Default = 0 = no; 1 = yes).", #ifdef CPX_PARAM_BASINTERVAL basisinterval_desc[] = "Number of interations between savings of current\n\ simplex basis to a file. Default = 50000.\n\ Deprecated in 10.0, removed in 12.6.1.", #endif clocktype_desc[] = "Kind of times CPLEX reports during the solution\n\ process:\n\ 0 = automatic choice\n\ 1 = CPU time\n\ 2 = wall clock time (total elapsed time = default)", #ifdef BARRIER comptol_desc[] = "Convergence tolerance for barrier algorithm:\n\ the algorithm stops when the relative\n\ complementarity is < bartol (default 1e-8).", #endif concurrent_desc[] = "Single-word phrase: with CPLEX versions >= 8\n\ and when hardware and licensing permit, try\n\ several methods in parallel.", concurrentopt_desc[] = "Synonym for \"concurrent\".", #ifdef CPXPARAM_Conflict_Algorithm conflictalg_desc[] = "Choice of algorithm used by the CPLEX's conflict\n\ refiner:\n\ 0 = automatic choice (default)\n\ 1 = fast\n\ 2 = propagate\n\ 3 = presolve\n\ 4 = IIS\n\ 5 = limited solve\n\ 6 = full solve.\n\ Settings 1, 2, and 3 are fast but may not discard\n\ many constraints; 5 and 6 work harder at this.\n\ Setting 4 searches for an Irreducible Infeasible\n\ Set of linear constraints (e.g., ignoring quadratic\n\ constraints).", #endif #ifdef CPX_PARAM_CONFLICTDISPLAY conflictdisplay_desc[] = "What to report when the conflict finder is working:\n\ 0 = nothing\n\ 1 = summary (default)\n\ 2 = detailed display.", #endif crash_desc[] = "Crash strategy (used to obtain starting basis);\n\ possible values = -1, 0, 1; default = 1.\n\ The best setting is problem-dependent and\n\ can only be found by experimentation.\n\ 0 completely ignores the objective.", crossover_desc[] = "Causes the barrier algorithm to be run (in the\n\ absence of discrete variables) and specifies\n\ whether to \"crossover\" to an optimal simplex\n\ basis afterwards:\n\ 0 = no crossover\n\ 1 = crossover with primal simplex\n\ (default for baropt)\n\ 2 = crossover with dual simplex.", #if CPX_VERSION >= 12070000 datacheck_desc[] = "debug option; possible values:\n\ 0 = no data checking (default)\n\ 1 = issue warnings\n\ 2 = try to \"assist\" by warning about bad scaling.", #elif defined(WANT_DATACHECK) datacheck_desc[] = "debug option; gives inappropriate complaints\n\ about Infinity" "\n\ Possible values:\n\ 0 = no data checking (default)\n\ 1 = issue warnings.", #endif #ifdef BARRIER dense_desc[] = "Synonym for \"densecol\".", densecol_desc[] = "If positive, minimum nonzeros in a column for\n\ the barrier algorithm to consider the column dense.\n\ If 0 (default), this tolerance is selected\n\ automatically.", #endif dependency_desc[] = "Whether to use CPLEX's presolve dependency checker:\n\ -1 = automatic choice (default)\n\ 0 = no\n\ 1 = turn on only at start of preprocessing\n\ 2 = turn on only at end of preprocessing\n\ 3 = turn on at both start and end of\n\ preprocessing.", #ifdef CPX_PARAM_DETTILIM dettimelim_desc[] = "Time limit in platform-dependent \"ticks\".\n\ Default = 1e75. See timing.", #endif dgradient_desc[] = "Pricing algorithm for dual simplex (default 0):\n\ 0 = choose automatically\n\ 1 = standard dual pricing\n\ 2 = steepest-edge pricing\n\ 3 = steepest-edge pricing in slack space\n\ 4 = steepest-edge with unit initial norms\n\ 5 = devex pricing.", display_desc[] = "Frequency of displaying LP progress information:\n\ 0 (default) = never\n\ 1 = each factorization\n\ 2 = each iteration.", doperturb_desc[] = "1 means initially perturb the problem (by an\n\ amount governed by \"perturbation\", which is\n\ described below). 0 (default) means let the\n\ algorithm decide. Setting doperturb to 1\n\ is occasionally helpful for highly degenerate\n\ problems.", dparam_desc[] = "Used with syntax \"dparam=n=d\" (no spaces), where n\n\ is a decimal integer, the number of a CPLEX \"double\"\n\ (i.e., floating-point valued) parameter. If d is a\n\ decimal floating-point value, assign d to \"double\"\n\ parameter n. If d is ?, report the current value of\n\ \"double\" parameter n. This facility provides a way\n\ to modify \"double\" parameters that have not (yet)\n\ been assigned a keyword.", #if CPX_VERSION >= 1100 droptol_desc[] = "If droptol > 0 is specified, linear constraint\n\ and objective coefficients less than droptol in\n\ magnitude are treated as zero.", #endif dual_desc[] = "Single-word phrase: solve the dual problem.", dualopt_desc[] = "Single-word phrase: use a dual simplex algorithm.", dualratio_desc[] = "If neither \"primal\" nor \"dual\" was specified and\n\ \"dual\" is possible (e.g., no integer variables and\n\ no node and arc declarations), choose between\n\ \"primal\" and \"dual\" as follows.\n\ Let m = number of rows, n = number of columns;\n\ if m - n > dualthresh > 0 or m > dualratio*n,\n\ solve the dual; otherwise solve the primal.\n\ Defaults: dualthresh = 0, dualratio = 3.", dualthresh_desc[] = "See dualratio.", #ifdef CPX_PARAM_EACHCUTLIM eachcutlim_desc[] = "Limit on the number of cuts of each time.\n\ Default = 2100000000.", #endif endbasis_desc[] = "\"endbasis foo\" writes the final basis to\n\ file \"foo\" (in BAS format).", endsol_desc[] = "File for writing the final solution as an XML file.", #if defined(BARRIER) && !defined(NO_DEPRECATED) && CPX_VERSION < 12070000 endvector_desc[] = "File for writing solution from barrier algorithm\n\ without crossover: only meaningful with\n\ \"baropt crossover=0\". Deprecated; use endsol instead.", #endif feasibility_desc[] = "Amount by which basic variables can violate\n\ their bounds. Default = 1e-6; possible\n\ values are between 1e-9 and 0.1.", #ifdef CPX_PARAM_FEASOPTMODE /* >= 9.2b */ feasopt_desc[] = "For infeasible problems, whether to find a feasible\n\ point for a relaxed problem (see feasoptobj):\n\ 0 = no (default)\n\ 1 = find a relaxed feasible point\n\ 2 = find a \"best\" solution among the relaxed\n\ feasible points.", feasoptobj_desc[] = "Objective for \"feasopt\":\n\ 1 = minimize the sum of constraint and variable\n\ bound relaxations (default)\n\ 2 = minimize the number of constraint and variable\n\ bounds relaxed (a MIP problem, generally\n\ harder than feasoptobj = 1)\n\ 3 = minimize the sum of squares of constraint and\n\ variable bound relaxations.", #endif file_desc[] = "Synonym for \"writeprob\".", #ifdef CPX_PARAM_FINALFACTOR finalfactor_desc[] = "Whether to factor the basis after \"uncrushing\"\n\ the problem at the end.\n\ 0 = no\n\ 1 = yes (default)\n\ Withdrawn in CPLEX 10.0.", #endif #ifdef BARRIER growth_desc[] = "Synonym for \"bargrowth\".", #endif #ifdef CPXERR_PARAM_INCOMPATIBLE incompat_desc[] = "How to treat parameter settings that CPLEX finds\n\ incompatible:\n\ 0 = quietly ignore incompatibilities\n\ 1 = report and ignore them (default)\n\ 2 = reject them, refusing to solve.\n\ For example, CPLEX regards the polishafter_* parameters\n\ introduced in CPLEX 11.2 as incompatible with the older\n\ polishtime parameter.", #endif iparam_desc[] = "Used with syntax \"iparam=n=i\" (no spaces), where n\n\ is a decimal integer, the number of a CPLEX integer\n\ parameter. If i is a decimal integer, assign i to\n\ integer parameter n. If i is ?, report the current\n\ value of integer parameter n. This facility provides\n\ a way to modify integer parameters that have not (yet)\n\ been assigned a keyword.", iterations_desc[] = "Limit on total LP iterations; default 2^31 - 1.", iterlim_desc[] = "Synonym for \"iterations\".", #ifdef Uselazy lazy_desc[] = "Whether to recognize suffix .lazy on constraints\n\ (new for CPLEX 10): sum of\n\ 1 ==> treat .lazy = 1 as lazy constraint\n\ 2 ==> treat .lazy = 2 as user cut\n\ Default lazy = 3 ==> treat both. (Suffix .lazy on\n\ constraints is ignored if not 0, 1, or 2 modulo 3.)", #endif limitperturb_desc[] = "Synonym for \"perturblimit\".", logfile_desc[] = "Name of file to receive all CPLEX messages.", lowerobj_desc[] = "Stop minimizing when the objective value\n\ goes below lowerobj. Default = -1e75.", lowerobjlim_desc[] = "Synonym for \"lowerobj\".", lpdisplay_desc[] = "Synonym for \"display\".", lpiterlim_desc[] = "Synonym for \"iterations\".", lptimelim_desc[] = "Synonym for \"time\".", markowitz_desc[] = "Pivot tolerance; default = 0.01; must be between\n\ 0.0001 and 0.99999. Bigger values may improve\n\ numerical properties of the solution (and may\n\ take more time).", maximize_desc[] = "Single-word phrase: maximize the objective,\n\ regardless of model specifications.", #ifdef CPX_PARAM_MEMORYEMPHASIS memoryemphasis_desc[] = "Whether to compress data to reduce the memory used,\n\ which may make some information (e.g., basis condition)\n\ unavailable:\n\ 0 = no (default)\n\ 1 = yes.", #endif minimize_desc[] = "Single-word phrase: minimize the objective,\n\ regardless of model specifications.", nameround_desc[] = "Whether to mangle variable and constraint names\n\ by turning [ and ] into ( and ), respectively:\n\ 0 = no (default)\n\ 1 = yes.\n\ This only matters if you specify endbasis=...\n\ or startbasis=... or perhaps writeprob=something.lp\n\ and have instructed AMPL to write .row and .col files.\n\ (It is usually better to let AMPL's status facilities\n\ convey basis information.) An alternative under Unix\n\ is to use the \"tr\" command to make the above changes\n\ if they are needed.", netdisplay_desc[] = "Which objective value to show when using the\n\ network simplex algorithm with display > 0\n\ or netopt=3:\n\ 0 = none\n\ 1 = true objective\n\ 2 = penalized objective (default).", netfeasibility_desc[] = "Feasibility tolerance for the network simplex\n\ algorithm. Default = 1e-6; possible values are\n\ between 1e-11 and 1e-1.", netfind_desc[] = "Algorithm for finding embedded networks:\n\ 1 = extract only the natural network\n\ 2 = use reflection scaling (default)\n\ 3 = use general scaling.", netfinder_desc[] = "Synonym for \"netfind\".", netiterations_desc[] = "Limit on network simplex iterations.\n\ Default = large (e.g., 2^31 - 1).", netopt_desc[] = "0 means never invoke the network optimizer.\n\ 1 (default) means invoke the network optimizer\n\ only if the model had node and arc declarations.\n\ 2 means always invoke the network optimizer\n\ (unless there are integer variables); the network\n\ optimizer may be able to find and exploit an\n\ embedded network.\n\ 3 is similar to 2, but sets CPLEX's LPMethod\n\ to CPX_ALG_NET rather than explicitly invoking\n\ the network optimizer. This might make a\n\ difference if CPLEX's presolve makes relevant\n\ reductions.", netoptimality_desc[] = "Tolerance for optimality of reduced costs in the\n\ network simplex algorithm. Default 1e-6; must be\n\ between 1e-11 and 1e-1.", netpricing_desc[] = "How to price in the network simplex algorithm:\n\ 0 = automatic choice (default)\n\ 1 = partial pricing\n\ 2 = multiple partial pricing\n\ 3 = multiple partial pricing with sorting.", #ifdef CPX_PARAM_NUMERICALEMPHASIS numericalemphasis_desc[] = "Whether to try to improve numerical accuracy (at a\n\ possible cost of time or memory):\n\ 0 = no (default)\n\ 1 = yes.", #endif objdifference_desc[] = "Amount added to (for maximizing) or subtracted\n\ from (for minimizing) the best (so far) feasible\n\ objective value while optimizing integer variables.\n\ Subsequent nodes will be ignored if their LP\n\ relaxations have optimal values worse than this\n\ sum. Default = 0. Positive values may speed\n\ the search -- and may cause the optimal solution\n\ to be missed.", objno_desc[] = "1 (default) = first objective, 2 = second, etc.;\n\ 0 ==> no objective: just find a feasible point.", objrep_desc[] = "Whether to replace\n\ minimize obj: v;\n\ with\n\ minimize obj: f(x)\n\ when variable v appears linearly in exactly one\n\ constraint of the form\n\ s.t. c: v >= f(x);\n\ or\n\ s.t. c: v == f(x);\n\ Possible objrep values:\n\ 0 = no\n\ 1 = yes for v >= f(x)\n\ 2 = yes for v == f(x) (default)\n\ 3 = yes in both cases\n\ For maximization problems, \">= f(x)\" is changed to\n\ \"<= f(x)\" in the description above. This is new\n\ with driver version 20130622.", optimality_desc[] = "Tolerance for optimality of reduced costs.\n\ Default 1e-6; must be between 1e-9 and 1e-1.", optimize_desc[] = "Synonym for \"primal\".", #ifdef BARRIER ordering_desc[] = "Ordering algorithm used by the barrier algorithm\n\ 0 = automatic choice (default)\n\ 1 = approximate minimum degree\n\ 2 = approximate minimum fill\n\ 3 = nested dissection.", #endif outlev_desc[] = "Synonym for \"display\".", #ifdef CPX_PARAM_PARALLELMODE parallelmode_desc[] = "Parallel optimization mode:\n\ -1 = opportunistic mode\n\ 0 = automatic: let CPLEX decide (default)\n\ 1 = deterministic mode.", #endif paramfile_desc[] = "File containing param settings to import. The file\n\ is read and settings in it echoed when the keyword\n\ is processed.", #if CPX_VERSION >= 1000 paramfileprm_desc[] = "File containing param settings in CPLEX PRM format\n\ to import. The file is read without echoing settings\n\ in it when the keyword is processed.", #endif #ifdef CPX_PARAM_PDSWITCH pdswitch_desc[] = "Whether to switch algorithms (from primal to dual\n\ or vice versa) when undoing perturbations or shifts\n\ made during the primal or dual simplex algorithm:\n\ -1 = no\n\ 0 = automatic choice (default)\n\ 1 = yes\n\ pdswitch=1 may help if there are many cycles\n\ of undoing perturbations. New in CPLEX 7.0,\n\ hidden in CPLEX 7.1.", #endif perturb_desc[] = "Synonym for \"doperturb\".", perturbation_desc[] = "Amount by which to perturb variable bounds\n\ when perturbing problems (see \"doperturb\").\n\ Default 1e-6; must be positive.", perturbconst_desc[] = "Synonym for \"perturbation\".", perturblim_desc[] = "Number of stalled simplex iterations before the\n\ problem is perturbed. Default = 0 = automatic.", perturblimit_desc[] = "Synonym for \"perturblim\".", pgradient_desc[] = "Pricing algorithm for primal simplex (default 0):\n\ -1 = reduced-cost pricing\n\ 0 = hybrid reduced-cost and Devex pricing\n\ 1 = Devex pricing\n\ 2 = steepest-edge pricing\n\ 3 = steepest-edge with slack initial norms\n\ 4 = full pricing.", #ifdef CPX_PARAM_PRECOMPRESS precompress_desc[] = "New in CPLEX 7.1: whether to compress the original\n\ problem after CPLEX's presolve:\n\ -1 = no\n\ 0 = automatic choice (default)\n\ 1 = yes\n\ Withdrawn in CPLEX 10.0.", #endif predual_desc[] = "Whether CPLEX's presolve phase should present the\n\ CPLEX solution algorithm with the primal (-1) or\n\ dual (1) problem or (default = 0) should decide\n\ which automatically. Specifying \"predual=1\" often\n\ gives better performance than specifying just \"dual\",\n\ but sometimes \"dual predual=1\" is still better.", prelinear_desc[] = "Whether CPLEX's presolve should do full reductions\n\ or only linear ones. Default = 1 = full.", #ifdef CPX_PARAM_PREPASS prepass_desc[] = "Limit on number of CPLEX presolve passes.\n\ Default = -1 = decide limit automatically.", #endif prereduce_desc[] = "Kinds of reductions permitted during CPLEX presolve:\n\ 0 = none\n\ 1 = only primal\n\ 2 = only dual\n\ 3 = both primal and dual (default).", #ifdef CPXPARAM_Preprocessing_Reformulations prereformulations_desc[] = "Reformulations applied during CPLEX presolve:\n\ 0 = none\n\ 1 = allow reformulations that interphere with\n\ crushing forms\n\ 2 = allow reformulations that interphere with\n\ uncrushing forms\n\ 3 = all reformulations (default).", #endif presolve_desc[] = "0 or 1 (default 1): Whether to run CPLEX's presolve\n\ algorithm.", presolvedual_desc[] = "Synonym for \"predual\".", presolvenode_desc[] = "-1, 0, or 1 (default 0): Whether to run CPLEX's\n\ presolve at each node of the MIP branch-and-bound\n\ tree: -1 = no; 1 = yes; 0 = automatic choice.", #ifdef CPXPARAM_Preprocessing_SOS1Reform presos1reformulations_desc[] = "Control the reformulation of SOS of type 1:\n\ -1 = no reformulation\n\ 0 = automatic (default)\n\ 1 = reformulate as linear constraints, with a\n\ reformulation which is logarithmic in the\n\ size of the SOSs.", presos2reformulations_desc[] = "Control the reformulation of SOS of type 2:\n\ -1 = no reformulation\n\ 0 = automatic (default)\n\ 1 = reformulate as linear constraints, with a\n\ reformulation which is logarithmic in the\n\ size of the SOSs.", #endif prestats_desc[] = "0 or 1 (default 0): Whether to include summary\n\ statistics (if nonzero) for CPLEX's \"aggregate\" and\n\ \"presolve\" algorithms in the solve_message.", #ifdef CPX_TUNE_TILIM pretunefile_desc[] = "File to which nondefault keyword settings are written\n\ before tuning; written whether or not tunefile or\n\ tunefilecpx is specified.", pretunefileprm_desc[] = "File to which nondefault keyword settings are written\n\ in CPLEX PRM format before tuning; written whether or\n\ not tunefile or tunefileprm is specified. Includes\n\ some display settings suppressed by pretunefile.", #endif pricing_desc[] = "Size of pricing candidate list (for partial pricing).\n\ 0 (default) means the algorithm decides.", primal_desc[] = "Single-word phrase: solve the primal problem.", primalopt_desc[] = "Use the primal simplex algorithm.", #ifdef CPXERR_QCP_SENSE qcdmax_desc[] = "Limit on k*n*n for computing duals for quadratically\n\ constrained problems, where k = number of quadratic\n\ constraints and n = number of variables. Default = 1e9.", qcdual_desc[] = "Whether to compute dual variable values for problems\n\ with quadratic constraints. Default = 1 (for \"yes\").\n\ This may be expensive if there are many quadratic\n\ constraints. Specifying qcdual=0 suppresses the\n\ computation.", #endif #ifdef CPX_PARAM_BARQCPEPCOMP qcpconvergetol_desc[] = "Convergence tolerance on relative complementarity for\n\ problems with quadratic constraints. Default = 1e-7.", #endif #ifdef CPXERR_QCP_SENSE qctol1_desc[] = "Tolerance on a quadratic inequality constraint's slack.\n\ After CPLEX has returned a solution, dual values are\n\ deduced for \"active\" quadratic constraints.\n\ Default 1e-5; a negative value is quietly treated as 0.", qctol2_desc[] = "Tolerance on the maxnorm of the gradient of an\n\ \"active\" quadratic constraint (see qctol1): if the\n\ maxnorm is no more than qctol2, the gradient is\n\ considered to vanish and dual value 0 is deduced.\n\ Default 1e-5; a negative value is quietly treated as 0.", qctol3_desc[] = "Tolerance on the reduction during QR factorization of\n\ the maxnorm of an \"active\" constraint's gradient\n\ (see qctol1) for the constraint to be considered\n\ independent of the other active quadratic constraints.\n\ Dual value 0 is deduced for dependent constraints.\n\ Default 1e-5; a negative value is quietly treated as 0.", #endif #ifdef CPX_PARAM_QPMETHOD qpmethod_desc[] = "Choice of algorithm for a continuous quadratic\n\ programming problem:\n\ 0 = automatic choice (default)\n\ 1 = primal simplex\n\ 2 = dual simplex\n\ 3 = network simplex\n\ 4 = barrier algorithm\n\ 6 = concurrent optimizer.", #endif #ifdef CPX_PARAM_QTOLININD qtolin_desc[] = "Whether to to linearize products of bounded variables\n\ in quadratic objectives:\n\ -1 = automatic choice (default)\n\ 0 = no\n\ 1 = yes.", #endif rays_desc[] = "Whether to return suffix .unbdd when the objective is\n\ unbounded or suffix .dunbdd when the constraints are\n\ infeasible:\n\ 0 = neither\n\ 1 = just .unbdd\n\ 2 = just .dunbdd\n\ 3 = both (default)\n\ To get .dunbdd, you may need to specify presolve=0\n\ in $cplex_options.", readbasis_desc[] = "BAS file containing starting basis.", readsol_desc[] = "File (previously written by an endsol directive) for\n\ reading the starting point. This is for debugging\n\ and is normally not used.", #if defined(BARRIER) && !defined(NO_DEPRECATED) readvector_desc[] = "VEC file containing starting point for barrier alg.\n\ Deprecated; use \"readsol\" instead.", #endif #ifdef CPX_PARAM_RECORD record_desc[] = "Whether to record CPLEX library calls for debugging use\n\ by IBM in a file with an automatically chosen name of\n\ the form cplexXXXXXXX.db:\n\ 0 = no (default)\n\ 1 = yes.", #endif refactor_desc[] = "LP iterations between refactorizing the basis.\n\ 0 (default) means the algorithm decides.", scale_desc[] = "How to scale the problem:\n\ -1 = no scaling\n\ 0 (default) = equilibration\n\ 1 = a more aggressive scheme that sometimes helps.", #ifdef CPX_PARAM_RANDOMSEED seed_desc[] = "Seed for random number generator used internally\n\ by CPLEX. Use \"seed=?\" to see the default, which\n\ depends on the CPLEX release.", #endif sensitivity_desc[] = "Single-word phrase: return sensitivity information for\n\ the objective (in suffixes .up for the largest value\n\ of a variable's cost coefficient or constraint's\n\ right-hand side before the optimal basis changes,\n\ .down for the smallest such value, and .current for\n\ the current cost coefficient or right-hand side).", siftingopt_desc[] = "Synonym for \"siftopt\".", siftopt_desc[] = "Single-word phrase: on LPs with CPLEX versions >= 8,\n\ solve ever larger sequences of subproblems until the\n\ whole LP is solved.", #ifdef CPX_PARAM_SIFTSIM simplexsifting_desc[] = "Whether to allow the simplex algorithm to use sifting\n\ when appropriate:\n\ 0 = no\n\ 1 = yes (default).", #endif #ifdef CPX_PARAM_SIMTHREADS simthreads_desc[] = "Maximum threads for the dual simplex algorithm\n\ (currently always 1). Withdrawn from CPLEX 9.0.", #endif singular_desc[] = "Maximum number of times CPLEX should try to\n\ repair the basis when it encounters singularities.\n\ Default = 10.", singularlim_desc[] = "Synonym for \"singular\".", #ifdef CPX_PARAM_SOLUTIONTYPE solutiontype_desc[] = "Whether to seek a basic solution when solving an LP:\n\ 0 = automatic choice (default)\n\ 1 = yes\n\ 2 = no (just seek a primal-dual pair).", #endif sparam_desc[] = "Used with syntax \"sparam=n=str\" (no spaces), where n\n\ is a decimal integer, the number of a CPLEX string\n\ parameter. If str is ?, report the current value of\n\ string parameter n. Otherwise, if str is a quoted\n\ string or a sequence of nonblank characters, assign\n\ str to string parameter n. This facility provides a\n\ way to modify string parameters that have not (yet)\n\ been assigned a keyword.", #ifdef CPX_PARAM_THREADS threads_desc[] = "Default maximum number of threads for any of\n\ the parallel CPLEX optimizers (limited also\n\ by licensing). Default = 1 prior to CPLEX 11,\n\ or 0 (use maximum threads available) starting\n\ with CPLEX 11. May be overridden, prior to\n\ CPLEX 11, by more specific limits, such as\n\ barthreads or mipthreads.", #endif time_desc[] = "Time limit in seconds; default = 1e75.", timelimit_desc[] = "Synonym for \"time\".", timing_desc[] = "Whether to write times in seconds or \"ticks\" to\n\ stdout or stderr: sum of\n\ 1 = write time in seconds to stdout\n\ 2 = write time in seconds to stderr" #if CPX_VERSION >= 12050000 "\n\ 4 = write time in \"ticks\" to stdout\n\ 8 = write time in \"ticks\" to stderr\n\ 16 = write number of logical cores to stdout\n\ 32 = write number of logical cores to stderr" #endif ".\n\ Default = 0.", tranopt_desc[] = "Synonym for \"dualopt\".", #ifdef CPX_TUNE_TILIM tunedisplay_desc[] = "How much to print during tuning:\n\ 0 = nothing\n\ 1 = minimal printing (default)\n\ 2 = show parameters being tried\n\ 3 = exhaustive printing.", tunefile_desc[] = "Name of file for tuning results. If specified, CPLEX\n\ will experiment with parameter settings that would\n\ make the solution faster. This can significantly\n\ increase execution time of the current invocation, but\n\ the settings it finds might save time in future runs.", tunefileprm_desc[] = "Name of file for tuning results in CPLEX PRM format.\n\ If specified, CPLEX will experiment with parameter\n\ settings as described for \"tunefile\".", tunefix_desc[] = "List of keywords not to tune, enclosed in quotes\n\ (\" or ') or separated by commas without white space\n\ if more than one.", tunefixfile_desc[] = "Name of file containing keywords not to tune.\n\ (There is no PRM format alternative.) Merged with\n\ tunefix specification (if any).", tunerepeat_desc[] = "How many times to perturb the problem during tuning.\n\ Default = 1.", tunetime_desc[] = "Limit (in seconds) on tuning time; meaningful\n\ if < time. Default = 1e75.", #ifdef CPX_PARAM_TUNINGDETTILIM tunetimedet_desc[] = "Limit (in \"ticks\") on tuning time; meaningful\n\ if < time. Default = 1e75.", #endif #endif upperobj_desc[] = "Stop maximizing when the objective value\n\ goes above upperobj. Default = 1e75.", upperobjlim_desc[] = "Synonym for \"upperobj\".", version_desc[] = "Single-word phrase: show the current version.", wantsol_desc[] = "solution report without -AMPL: sum of\n\ 1 = write .sol file\n\ 2 = print primal variable values\n\ 4 = print dual variable values\n\ 8 = do not print solution message", #ifdef CPXPARAM_Read_WarningLimit warninglimit_desc[] = "Limit on the number of warnings per issue\n\ given when \"datacheck=2\" is specified. Default = 10.", #endif workfiledir_desc[] = "Directory where CPLEX creates a temporary\n\ subdirectory for temporary files, e.g., for\n\ node information and Cholesky factors.", #ifdef CPX_PARAM_WORKMEM workfilelim_desc[] = "Maximum size in megabytes for in-core work \"files\".\n\ Default 2048.", #endif writebasis_desc[] = "Synonym for \"endbasis\".", writemipstart_desc[] = "[Debug option] The name of a file to which the MIP\n\ starting guess (if any) is written in \".mst\" format.\n\ If there is no MIP start, an empty file is written.", writeprob_desc[] = "Name of file to which the problem is written\n\ in a format determined by the name's suffix:\n\ .sav = binary SAV file;\n\ .mps = MPS file, original names;\n\ .lp = LP file, original names;\n\ .rmp = MPS file, generic names;\n\ .rew = MPS file, generic names;\n\ .rlp = LP file, generic names.\n\ SAV and LP formats are peculiar to CPLEX.", writesol_desc[] = "Synonym for \"endsol\"." #if defined(BARRIER) && !defined(NO_DEPRECATED) && CPX_VERSION < 12070000 ,writevector_desc[] = "Synonym for \"endvector\"." #endif #ifdef CPX_PARAM_XXXIND uxxxstart_desc[] = "Whether to read .xxx files to resume an\n\ interrupted run of CPLEX (deprecated in 10.0,\n\ removed in 12.6.1):\n\ 0 = no (default)\n\ 1 = yes." #endif ; #define VP (void*) static keyword keywds[] = { /* must be in alphabetical order */ #if 0 /* These can be accessed via iparam and dparam. {*/ /* Undocumented keywords start with underscore... */ { "_aggsort", sf_int, VP 1061 /*CPX_PARAM_PREAGGSORT*/, undoc}, { "_aggtolerance", sf_dbl, VP 1055 /*CPX_PARAM_EPSAGG*/, undoc}, { "_cancel", sf_int, VP 1071 /*CPX_PARAM_PRECANCEL*/, undoc}, { "_clique", sf_int, VP 1072 /*CPX_PARAM_PRECLIQUE*/, undoc}, { "_cliquetablesize", sf_dbl, VP 2064 /*CPX_PARAM_CLIQUETABLESZ*/, undoc}, { "_domination", sf_int, VP 2038 /*CPX_PARAM_COLDOMIND*/, undoc}, { "_effslack", sf_int, VP 1042 /*CPX_PARAM_EFFSLACKIND*/, undoc}, { "_factormem", sf_dbl, VP 3021 /*CPX_PARAM_BARFACTMEM*/, undoc}, { "_flip", sf_int, VP 1051 /*CPX_PARAM_FLIPIND*/, undoc}, { "_hfeasibility", sf_dbl, VP 1050 /*CPX_PARAM_EPRHS_H*/, undoc}, { "_hoptimality", sf_dbl, VP 1049 /*CPX_PARAM_EPOPT_H*/, undoc}, { "_insubtree", sf_int, VP 2063 /*CPX_PARAM_INSUBTREE*/, undoc}, { "_kernel", sf_int, VP 3020 /*CPX_PARAM_BARKERNEL*/, undoc}, { "_knapcoeff", sf_int, VP 1059 /*CPX_PARAM_KNAPCOERED*/, undoc}, { "_localcovers", sf_int, VP 2061 /*CPX_PARAM_LOCALCOVERS*/, undoc}, { "_logparams", sf_int, VP 1075 /*CPX_PARAM_LOGPARAMS*/, undoc}, { "_memfact", sf_dbl, VP 1045 /*CPX_PARAM_PREMEMFACT*/, undoc}, { "_memsave", sf_int, VP 1060 /*CPX_PARAM_PREMEMSAVE*/, undoc}, { "_minstuck", sf_int, VP 3023 /*CPX_PARAM_BARMINSTUCK*/, undoc}, { "_oldpricing", sf_int, VP 1054 /*CPX_PARAM_OLDPRICING*/, undoc}, { "_oldqpfactor", sf_int, VP 3024 /*CPX_PARAM_OLDQPFACTOR*/, undoc}, { "_oldratio", sf_int, VP 1068 /*CPX_PARAM_OLDRATIO*/, undoc}, { "_orderthreads", sf_int, VP 3022 /*CPX_PARAM_BARORDERTHREADS*/, undoc}, { "_primalstart", sf_dbl, VP 3005 /*CPX_PARAM_BARPSTART*/, undoc}, { "_probe", sf_int, VP 1070 /*CPX_PARAM_PREPROBE*/, undoc}, { "_recurseheur", sf_int, VP 2062 /*CPX_PARAM_RECURSEHEUR*/, undoc}, #ifdef CPX_PARAM_IISIND /* version < 9.2b */ { "_rowsdense", sf_int, VP 3015 /*CPX_PARAM_BARROWSDEN*/, undoc}, #endif { "_splitrow", sf_int, VP 1079 /*CPX_PARAM_PRESPLITROW*/, undoc}, { "_svbound", sf_int, VP 1069 /*CPX_PARAM_SVBNDSTR*/, undoc}, #endif /*}*/ /* Documented keywords... */ #ifdef CPLEX_MIP { "absmipgap", sf_dbl, VP CPX_PARAM_EPAGAP, absmipap_desc }, #endif { "advance", sf_int1, VP CPX_PARAM_ADVIND, advance_desc }, #ifdef CPLEX_MIP { "aggcutlim", sf_int, VP CPX_PARAM_AGGCUTLIM, aggcutlim_desc }, #endif { "aggfill", sf_int2, VP CPX_PARAM_AGGFILL, aggfill_desc }, { "agglim", sf_int, VP CPX_PARAM_AGGFILL, agglim_desc }, { "aggregate", sf_int1, VP CPX_PARAM_AGGIND, aggregate_desc }, { "aggtol", sf_dbl, VP CPX_PARAM_EPSAGG, aggtol_desc }, { "autoopt", sf_known, VP set_autoopt, autoopt_desc }, { "autopt", sf_known, VP set_autoopt, autopt_desc }, #ifdef CPLEX_MIP #ifdef CPX_PARAM_AUXROOTTHREADS { "auxrootthreads", sf_int, VP CPX_PARAM_AUXROOTTHREADS, auxrootthreads_desc }, #endif { "backtrack", sf_dbl, VP CPX_PARAM_BTTOL, backtrack_desc }, #endif #ifdef BARRIER { "baralg", sf_int, VP CPX_PARAM_BARALG, baralg_desc }, { "barcorr", sf_int, VP CPX_PARAM_BARMAXCOR, barcorr_desc }, { "bardisplay", sf_int2, VP CPX_PARAM_BARDISPLAY, bardisplay_desc }, { "bargrowth", sf_dbl, VP CPX_PARAM_BARGROWTH, bargrowth_desc }, { "bariterlim", sf_int, VP CPX_PARAM_BARITLIM, bariterlim_desc }, { "barobjrange", sf_dbl, VP CPX_PARAM_BAROBJRNG, barobjrange_desc }, { "baropt", sf_known, VP set_barrier, baropt_desc }, #ifdef CPX_PARAM_BAROOC { "baroutofcore", sf_int, VP CPX_PARAM_BAROOC, baroutofcore_desc }, #endif { "barstart", sf_int, VP CPX_PARAM_BARSTARTALG, barstart_desc }, { "barstartalg", sf_int, VP CPX_PARAM_BARSTARTALG, barstartalg_desc }, #ifdef CPX_PARAM_BARTHREADS { "barthreads", sf_int, VP CPX_PARAM_BARTHREADS, barthreads_desc }, #endif #ifdef CPX_PARAM_BARVARUP { "barvarup", sf_dbl, VP CPX_PARAM_BARVARUP, barvarup_desc }, #endif #endif /* BARRIER */ #ifdef BASDEBUG { "basdebug", I_val, VP &basdebug, basdebug_desc }, #endif { "basis_cond", sf_mint, VP set_basis_cond, basis_cond_desc }, #ifdef CPX_PARAM_BASINTERVAL { "basisinterval", sf_int, VP CPX_PARAM_BASINTERVAL, basisinterval_desc }, #endif #ifdef CPLEX_MIP { "bbinterval", sf_int, VP CPX_PARAM_BBINTERVAL, bbinterval_desc }, #ifdef CPXPARAM_Benders_Strategy { "benders_feascut_tol", sf_dbl,VP CPXPARAM_Benders_Tolerances_feasibilitycut, benders_feascut_desc }, { "benders_optcut_tol", sf_dbl, VP CPXPARAM_Benders_Tolerances_optimalitycut, benders_optcut_desc }, { "benders_strategy", sf_int, VP CPXPARAM_Benders_Strategy, benders_strategy_desc }, { "benders_worker", sf_int, VP CPXPARAM_Benders_WorkerAlgorithm, benders_worker_desc }, { "bendersopt", sf_known, VP set_benders, bendersopt_desc }, #endif { "bestbound", sf_known, VP set_bestbound, bestbound_desc }, { "bestnode", sf_known, VP set_bestnode, bestnode_desc }, { "boundstr", sf_int, VP CPX_PARAM_BNDSTRENIND, boundstr_desc }, #ifdef CPX_PARAM_BQPCUTS { "bqpcuts", sf_int, VP CPX_PARAM_BQPCUTS, bqpcuts_desc }, #endif { "branch", sf_int, VP CPX_PARAM_BRDIR, branch_desc }, { "branchdir", sf_int, VP CPX_PARAM_BRDIR, branchdir_desc }, { "cliquecuts", sf_int2, VP CPX_PARAM_CLIQUES, cliquecuts_desc }, { "cliques", sf_int, VP CPX_PARAM_CLIQUES, cliques_desc }, #endif { "clocktype", sf_int, VP CPX_PARAM_CLOCKTYPE, clocktype_desc }, #ifdef CPLEX_MIP { "coeffreduce", sf_int1, VP CPX_PARAM_COEREDIND, coeffreduce_desc }, #endif #ifdef BARRIER { "comptol", sf_dbl, VP CPX_PARAM_BAREPCOMP, comptol_desc }, #endif { "concurrent", sf_known, VP set_concurrentopt, concurrent_desc }, { "concurrentopt", sf_known, VP set_concurrentopt, concurrentopt_desc }, #ifdef CPXPARAM_Conflict_Algorithm { "conflictalg", sf_int, VP CPXPARAM_Conflict_Algorithm, conflictalg_desc }, #endif #ifdef CPX_PARAM_CONFLICTDISPLAY { "conflictdisplay", sf_int, VP CPX_PARAM_CONFLICTDISPLAY, conflictdisplay_desc }, #endif #ifdef CPLEX_MIP { "covercuts", sf_int2, VP CPX_PARAM_COVERS, covercuts_desc }, { "covers", sf_int, VP CPX_PARAM_COVERS, covers_desc }, #endif #ifdef CPX_PARAM_CPUMASK { "cpumask", sf_str, VP CPX_PARAM_CPUMASK, cpumask_desc }, #endif { "crash", sf_int, VP CPX_PARAM_CRAIND, crash_desc }, #ifdef BARRIER { "crossover", sf_mint, VP set_crossover, crossover_desc }, #endif #ifdef CPLEX_MIP { "cutpass", sf_int, VP CPX_PARAM_CUTPASS, cutpass_desc }, { "cutsfactor", sf_dbl, VP CPX_PARAM_CUTSFACTOR, cutsfactor_desc }, #if CPX_VERSION >= 1100 { "cutstats", sf_mint, VP set_cutstats, cutstats_desc }, #endif #endif #if CPX_VERSION >= 12070000 || defined(WANT_DATACHECK) { "datacheck", sf_int, VP CPX_PARAM_DATACHECK, datacheck_desc }, #endif #ifdef BARRIER { "dense", sf_int2, VP CPX_PARAM_BARCOLNZ, dense_desc }, { "densecol", sf_int, VP CPX_PARAM_BARCOLNZ, densecol_desc }, #endif { "dependency", sf_int1, VP CPX_PARAM_DEPIND, dependency_desc }, #ifdef CPX_PARAM_DETTILIM { "dettimelim", sf_dbl, VP CPX_PARAM_DETTILIM, dettimelim_desc }, #endif { "dgradient", sf_int, VP CPX_PARAM_DPRIIND, dgradient_desc }, #ifdef CPLEX_MIP { "disjcuts", sf_int, VP CPX_PARAM_DISJCUTS, disjcuts_desc }, #endif { "display", sf_int2, VP CPX_PARAM_SIMDISPLAY, display_desc }, { "doperturb", sf_int1, VP CPX_PARAM_PERIND, doperturb_desc }, { "dparam", sf_dpar, 0, dparam_desc }, #if CPX_VERSION >= 1100 { "droptol", sf_mdbl, VP set_droptol, droptol_desc }, #endif { "dual", sf_known, VP set_dual, dual_desc }, { "dualopt", sf_known, VP set_dualopt, dualopt_desc }, { "dualratio", sf_mdbl, VP set_dual_ratio, dualratio_desc }, { "dualthresh", sf_mint, VP set_dualthresh, dualthresh_desc }, #ifdef CPX_PARAM_EACHCUTLIM { "eachcutlim", sf_int, VP CPX_PARAM_EACHCUTLIM, eachcutlim_desc }, #endif { "endbasis", sf_char, VP set_endbas, endbasis_desc }, { "endsol", sf_char, VP set_endsol, endsol_desc }, #ifdef CPLEX_MIP #ifdef CPX_PARAM_IISIND /* version < 9.2b */ { "endtree", sf_char, VP set_endtree, endtree_desc }, #endif #endif #if defined(BARRIER) && !defined(NO_DEPRECATED) && CPX_VERSION < 12070000 { "endvector", sf_char, VP set_endvector, endvector_desc }, #endif { "feasibility", sf_dbl, VP CPX_PARAM_EPRHS, feasibility_desc }, #ifdef CPX_PARAM_FEASOPTMODE /* >= 9.2b */ { "feasopt", sf_mint, VP set_feasopt, feasopt_desc }, { "feasoptobj", sf_mint, VP set_feasoptobj, feasoptobj_desc }, #endif { "file", sf_char, VP set_wrtfname, file_desc }, #ifdef CPX_PARAM_FINALFACTOR { "finalfactor", sf_int, VP CPX_PARAM_FINALFACTOR, finalfactor_desc }, #endif #ifdef CPLEX_MIP { "finalmipalg", sf_mint, VP set_finalmipalg, finalmipalg_desc }, { "flowcuts", sf_int, VP CPX_PARAM_FLOWCOVERS, flowcuts_desc }, { "flowpathcuts", sf_int, VP CPX_PARAM_FLOWPATHS, flowpathcuts_desc }, #ifdef CPX_PARAM_FPHEUR { "fpheur", sf_int, VP CPX_PARAM_FPHEUR, fpheur_desc }, #endif #ifndef NO_CPLEX66 /* for versions prior to CPLEX 6.6 */ { "fraccand", sf_int, VP CPX_PARAM_FRACCAND, fraccand_desc }, { "fraccuts", sf_int, VP CPX_PARAM_FRACCUTS, fraccuts_desc }, { "fracpass", sf_int, VP CPX_PARAM_FRACPASS, fracpass_desc }, { "fractionalcuts", sf_int, VP CPX_PARAM_FRACCUTS, fractionalcuts_desc }, #endif #endif #ifdef BARRIER { "growth", sf_dbl, VP CPX_PARAM_BARGROWTH, growth_desc }, #endif #ifdef CPLEX_MIP { "gubcuts", sf_int, VP CPX_PARAM_GUBCOVERS, gubcuts_desc }, #ifdef CPXPARAM_MIP_Strategy_HeuristicEffort { "heureffort", sf_dbl, VP CPXPARAM_MIP_Strategy_HeuristicEffort, heureffort_desc }, #endif #ifdef CPX_PARAM_HEURFREQ { "heurfreq", sf_int, VP CPX_PARAM_HEURFREQ, heurfreq_desc }, #endif #ifdef CPX_PARAM_HEURISTIC { "heuristic", sf_int, VP CPX_PARAM_HEURISTIC, heuristic_desc }, #endif #ifdef CPX_PARAM_HEURFREQ { "heuristicfreq", sf_int, VP CPX_PARAM_HEURFREQ, heuristicfreq_desc }, #endif #endif { "iisfind", sf_mint, VP set_iis, iisfind_desc }, #ifdef CPLEX_MIP { "impliedcuts", sf_int, VP CPX_PARAM_IMPLBD, impliedcuts_desc }, #endif #ifdef CPXERR_PARAM_INCOMPATIBLE { "incompat", sf_mint, VP set_incompat, incompat_desc }, #endif #ifdef CPLEX_MIP { "integrality", sf_dbl, VP CPX_PARAM_EPINT, integrality_desc }, { "intwarntol", D_val, VP &intwarn_tol, intwarntol_desc }, #endif { "iparam", sf_ipar, 0, iparam_desc }, { "iterations", sf_int, VP CPX_PARAM_ITLIM, iterations_desc }, { "iterlim", sf_int, VP CPX_PARAM_ITLIM, iterlim_desc }, #ifdef Uselazy { "lazy", sf_mint, VP set_lazy, lazy_desc }, #endif #ifdef CPLEX_MIP #ifdef CPX_PARAM_LBHEUR { "lbheur", sf_int, VP CPX_PARAM_LBHEUR, lbheur_desc }, #endif #endif { "limitperturb", sf_int2, VP CPX_PARAM_PERLIM, limitperturb_desc }, #ifdef CPXPARAM_MIP_Cuts_LocalImplied { "localimpliedcuts", sf_int, VP CPXPARAM_MIP_Cuts_LocalImplied, localimpliedcuts_desc }, #endif { "logfile", sf_char, VP set_logname, logfile_desc }, #ifdef CPLEX_MIP { "lowercutoff", sf_dbl, VP CPX_PARAM_CUTLO, lowercutoff_desc }, #endif { "lowerobj", sf_dbl, VP CPX_PARAM_OBJLLIM, lowerobj_desc }, { "lowerobjlim", sf_dbl, VP CPX_PARAM_OBJLLIM, lowerobjlim_desc }, { "lpdisplay", sf_int2, VP CPX_PARAM_SIMDISPLAY, lpdisplay_desc }, { "lpiterlim", sf_int2, VP CPX_PARAM_ITLIM, lpiterlim_desc }, { "lptimelim", sf_dbl2, VP CPX_PARAM_TILIM, lptimelim_desc }, { "markowitz", sf_dbl, VP CPX_PARAM_EPMRK, markowitz_desc }, { "maximize", sf_known, VP set_max, maximize_desc }, #ifdef CPX_PARAM_MCFCUTS { "mcfcuts", sf_int, VP CPX_PARAM_MCFCUTS, mcfcuts_desc }, #endif #ifdef CPX_PARAM_MEMORYEMPHASIS { "memoryemphasis", sf_int, VP CPX_PARAM_MEMORYEMPHASIS, memoryemphasis_desc }, #endif { "minimize", sf_known, VP set_min, minimize_desc }, #ifdef CPLEX_MIP /*{*/ { "mipalg", sf_int, VP CPX_PARAM_SUBALG, mipalg_desc }, { "mipalgorithm", sf_int, VP CPX_PARAM_SUBALG, mipalgorithm_desc }, { "mipbasis", sf_mint, VP set_mipbasis, mipbasis_desc }, { "mipcrossover", sf_int, VP CPX_PARAM_BARCROSSALG, mipcrossover_desc }, { "mipcuts", sf_mint, VP set_mipcuts, mipcuts_desc }, { "mipdisplay", sf_int2, VP CPX_PARAM_MIPDISPLAY, mipdisplay_desc }, { "mipemphasis", sf_int, VP CPX_PARAM_MIPEMPHASIS, mipemphasis_desc }, { "mipgap", sf_dbl, VP CPX_PARAM_EPGAP, mipgap_desc }, { "mipinterval", sf_int, VP CPX_PARAM_MIPINTERVAL, mipinterval_desc }, #ifdef CPX_PARAM_MIPKAPPASTATS { "mipkappa", sf_int, VP CPX_PARAM_MIPKAPPASTATS, mipkappa_desc }, #endif { "mipordertype", sf_int2, VP CPX_PARAM_MIPORDTYPE, mipordertype_desc }, #ifdef CPX_PARAM_MIPSEARCH { "mipsearch", sf_int, VP CPX_PARAM_MIPSEARCH, mipsearch_desc }, #endif { "mipsolutions", sf_int, VP CPX_PARAM_INTSOLLIM, mipsolutions_desc }, { "mipstart", sf_mint, VP set_mipstval, mipstart_desc }, { "mipstartalg", sf_int, VP CPX_PARAM_STARTALG, mipstartalg_desc }, { "mipstartstatus", sf_mint, VP set_mipststat, mipstartstatus_desc }, { "mipstartvalue", sf_mint, VP set_mipstval, mipstartvalue_desc }, { "mipsubalg", sf_int, VP CPX_PARAM_SUBALG, mipsubalg_desc }, #ifdef CPX_PARAM_MIPTHREADS { "mipthreads", sf_int, VP CPX_PARAM_MIPTHREADS, mipthreads_desc }, #endif #ifdef CPX_PARAM_MIQCPSTRAT { "miqcpstrat", sf_int, VP CPX_PARAM_MIQCPSTRAT, miqcpstrat_desc }, #endif { "mircuts", sf_int, VP CPX_PARAM_MIRCUTS, mircuts_desc }, #endif /*}*/ #ifndef NO_MOkwf { "modisplay", sf_int, VP CPXPARAM_MultiObjective_Display, modisplay_desc }, { "multiobj", sf_mint, VP set_multiobj, multiobj_desc }, #endif { "nameround", sf_mint, VP set_namernd, nameround_desc }, { "netdisplay", sf_int, VP CPX_PARAM_NETDISPLAY, netdisplay_desc }, { "netfeasibility", sf_dbl, VP CPX_PARAM_NETEPRHS, netfeasibility_desc }, { "netfind", sf_int, VP CPX_PARAM_NETFIND, netfind_desc }, { "netfinder", sf_int, VP CPX_PARAM_NETFIND, netfinder_desc }, { "netiterations", sf_int, VP CPX_PARAM_NETITLIM, netiterations_desc }, { "netopt", sf_mint, VP set_netopt, netopt_desc }, { "netoptimality", sf_dbl, VP CPX_PARAM_NETEPOPT, netoptimality_desc }, { "netpricing", sf_int, VP CPX_PARAM_NETPPRIIND, netpricing_desc }, #ifdef CPLEX_MIP { "node", sf_int2, VP CPX_PARAM_NODELIM, node_desc }, #ifdef CPX_PARAM_NODECUTS { "nodecuts", sf_int, VP CPX_PARAM_NODECUTS, nodecuts_desc }, #endif { "nodefile", sf_int, VP CPX_PARAM_NODEFILEIND, nodefile_desc }, { "nodefiledir", sf_char, VP set_workfiledir, nodefiledir_desc }, #ifdef CPX_PARAM_NODEFILELIM { "nodefilelim", sf_dbl, VP CPX_PARAM_NODEFILELIM, nodefilelim_desc }, { "nodefilesize", sf_dbl, VP CPX_PARAM_NODEFILELIM, nodefilesize_desc }, #endif { "nodelim", sf_int2, VP CPX_PARAM_NODELIM, nodelim_desc }, { "nodes", sf_int, VP CPX_PARAM_NODELIM, nodes_desc }, { "nodesel", sf_int, VP CPX_PARAM_NODESEL, nodesel_desc }, { "nodeselect", sf_int, VP CPX_PARAM_NODESEL, nodeselect_desc }, #endif { "nosolve", sf_known, VP set_nosolve, nosolve_desc }, #ifdef CPX_PARAM_NUMERICALEMPHASIS { "numericalemphasis", sf_int, VP CPX_PARAM_NUMERICALEMPHASIS, numericalemphasis_desc }, #endif #ifdef CPLEX_MIP { "objdifference", sf_dbl, VP CPX_PARAM_OBJDIF, objdifference_desc }, #endif { "objno", sf_mint, VP set_objno, objno_desc }, { "objrep", sf_mint, VP set_objrep, objrep_desc }, { "optimality", sf_dbl, VP CPX_PARAM_EPOPT, optimality_desc }, { "optimize", sf_known, VP set_primalopt, optimize_desc }, #ifdef BARRIER { "ordering", sf_int, VP CPX_PARAM_BARORDER, ordering_desc }, #endif #ifdef CPLEX_MIP { "ordertype", sf_int, VP CPX_PARAM_MIPORDTYPE, ordertype_desc }, #endif { "outlev", sf_int2, VP CPX_PARAM_SIMDISPLAY, outlev_desc }, #ifdef CPX_PARAM_PARALLELMODE { "parallelmode", sf_int, VP CPX_PARAM_PARALLELMODE, parallelmode_desc }, #endif { "paramfile", sf_par, VP set_paramfile, paramfile_desc }, #if CPX_VERSION >= 1000 { "paramfileprm", sf_parm, VP set_paramfile, paramfileprm_desc }, #endif #ifdef CPX_PARAM_PDSWITCH { "pdswitch", sf_int, VP CPX_PARAM_PDSWITCH, pdswitch_desc }, #endif { "perturb", sf_int1, VP CPX_PARAM_PERIND, perturb_desc }, { "perturbation", sf_dbl, VP CPX_PARAM_EPPER, perturbation_desc }, { "perturbconst", sf_dbl, VP CPX_PARAM_EPPER, perturbconst_desc }, { "perturblim", sf_int, VP CPX_PARAM_PERLIM, perturblim_desc }, { "perturblimit", sf_int, VP CPX_PARAM_PERLIM, perturblimit_desc }, { "pgradient", sf_int, VP CPX_PARAM_PPRIIND, pgradient_desc }, #ifdef CPLEX_MIP /*{*/ { "plconpri", sf_mint, VP set_conpri, plconpri_desc }, { "plobjpri", sf_mint, VP set_objpri, plobjpri_desc }, #ifdef CPX_PARAM_POLISHAFTEREPAGAP { "polishafter_absmipgap", sf_dbl, VP CPX_PARAM_POLISHAFTEREPAGAP, polishafter_absmipgap_desc }, { "polishafter_intsol", sf_int, VP CPX_PARAM_POLISHAFTERINTSOL, polishafter_intsol_desc }, { "polishafter_mipgap", sf_dbl, VP CPX_PARAM_POLISHAFTEREPGAP, polishafter_mipgap_desc }, { "polishafter_nodes", sf_int, VP CPX_PARAM_POLISHAFTERNODE, polishafter_nodes_desc }, { "polishafter_time", sf_dbl, VP CPX_PARAM_POLISHAFTERTIME, polishafter_time_desc }, #endif #ifdef CPX_PARAM_POLISHAFTERDETTIME { "polishafter_timedet", sf_dbl, VP CPX_PARAM_POLISHAFTERDETTIME, polishafter_timedet_desc }, #endif #ifdef CPX_PARAM_POLISHTIME { "polishtime", sf_dbl, VP CPX_PARAM_POLISHTIME, polishtime_desc }, #endif #ifdef CPX_PARAM_POPULATELIM { "poolagap", sf_dbl, VP CPX_PARAM_SOLNPOOLAGAP, poolagap_desc }, { "poolcapacity", sf_int2, VP CPX_PARAM_SOLNPOOLCAPACITY, poolcapacity_desc }, { "pooldual", sf_mint, VP set_pooldual, pooldual_desc }, { "poolgap", sf_dbl, VP CPX_PARAM_SOLNPOOLGAP, poolgap_desc }, { "poolintensity", sf_int, VP CPX_PARAM_SOLNPOOLINTENSITY, poolintensity_desc }, { "poolreplace", sf_int, VP CPX_PARAM_SOLNPOOLREPLACE, poolreplace_desc }, { "poolstub", sf_char, VP set_poolstub, poolstub_desc }, { "populate", sf_mint, VP set_populate, populate_desc }, { "populatelim", sf_int, VP CPX_PARAM_POPULATELIM, populatelim_desc }, #endif #endif /*}CPLEX_MIP*/ #ifdef CPX_PARAM_PRECOMPRESS { "precompress", sf_int, VP CPX_PARAM_PRECOMPRESS, precompress_desc }, #endif { "predual", sf_int, VP CPX_PARAM_PREDUAL, predual_desc }, { "prelinear", sf_int, VP CPX_PARAM_PRELINEAR, prelinear_desc }, #ifdef CPX_PARAM_PREPASS { "prepass", sf_int, VP CPX_PARAM_PREPASS, prepass_desc }, #endif { "prereduce", sf_int, VP CPX_PARAM_REDUCE, prereduce_desc }, #ifdef CPXPARAM_Preprocessing_Reformulations { "prereformulations", sf_int, VP CPXPARAM_Preprocessing_Reformulations, prereformulations_desc }, #endif #ifdef CPLEX_MIP { "prerelax", sf_int1, VP CPX_PARAM_RELAXPREIND, prerelax_desc }, #endif { "presolve", sf_int1, VP CPX_PARAM_PREIND, presolve_desc }, { "presolvedual", sf_int, VP CPX_PARAM_PREDUAL, presolvedual_desc }, #ifdef CPLEX_MIP { "presolvenode", sf_int, VP CPX_PARAM_PRESLVND, presolvenode_desc }, #endif #ifdef CPXPARAM_Preprocessing_SOS1Reform { "presos1reform", sf_int, VP CPXPARAM_Preprocessing_SOS1Reform, presos1reformulations_desc }, { "presos2reform", sf_int, VP CPXPARAM_Preprocessing_SOS1Reform, presos2reformulations_desc }, #endif { "prestats", sf_mint, VP set_prestats, prestats_desc }, #ifdef CPX_TUNE_TILIM { "pretunefile", sf_char, VP set_pretunefile, pretunefile_desc }, { "pretunefileprm", sf_char, VP set_pretunefileprm, pretunefileprm_desc }, #endif { "pricing", sf_int, VP CPX_PARAM_PRICELIM, pricing_desc }, { "primal", sf_known, VP set_primal, primal_desc }, { "primalopt", sf_known, VP set_primalopt, primalopt_desc }, #ifdef CPLEX_MIP { "priorities", sf_int1, VP CPX_PARAM_MIPORDIND, priorities_desc }, { "probe", sf_int, VP CPX_PARAM_PROBE, probe_desc }, #ifdef CPX_PARAM_PROBETIME { "probetime", sf_dbl, VP CPX_PARAM_PROBETIME, probetime_desc }, #endif #ifdef CPX_PARAM_PROBEDETTIME { "probetimedet", sf_dbl, VP CPX_PARAM_PROBEDETTIME, probetimedet_desc }, #endif #endif /*CPLEX_MIP*/ #ifdef CPXERR_QCP_SENSE { "qcdmax", D_val, VP &qcdmax, qcdmax_desc }, { "qcdual", sf_mint, VP set_qcdual, qcdual_desc }, #endif #ifdef CPX_PARAM_BARQCPEPCOMP { "qcpconvergetol", sf_dbl, VP CPX_PARAM_BARQCPEPCOMP, qcpconvergetol_desc }, #endif #ifdef CPXERR_QCP_SENSE { "qctol1", D_val, VP &qctol1, qctol1_desc }, { "qctol2", D_val, VP &qctol2, qctol2_desc }, { "qctol3", D_val, VP &qctol3, qctol3_desc }, #endif #ifdef CPX_PARAM_QPMETHOD { "qpmethod", sf_int, VP CPX_PARAM_QPMETHOD, qpmethod_desc }, #endif #ifdef CPX_PARAM_QTOLININD { "qtolin", sf_int, VP CPX_PARAM_QTOLININD, qtolin_desc }, #endif #ifdef Want_Distmipopt { "rampup_duration", sf_int, VP CPX_PARAM_RAMPUPDURATION, rampup_duration_desc }, { "rampup_timelim", sf_dbl, VP CPX_PARAM_RAMPUPDETTILIM, rampup_timelim_desc }, { "rampup_walltimelim", sf_dbl, VP CPX_PARAM_RAMPUPTILIM, rampup_walltimelim_desc }, #endif { "rays", sf_mint, VP set_rays, rays_desc }, { "readbasis", sf_char, VP set_startbas, readbasis_desc }, { "readsol", sf_char, VP set_startsol, readsol_desc }, #if defined(BARRIER) && !defined(NO_DEPRECATED) { "readvector", sf_char, VP set_startvector, readvector_desc }, #endif #ifdef CPX_PARAM_RECORD { "record", sf_int, VP CPX_PARAM_RECORD, record_desc }, #endif { "refactor", sf_int, VP CPX_PARAM_REINV, refactor_desc }, #ifdef CPLEX_MIP { "relax", sf_known, VP set_relax, relax_desc }, { "relaxpresolve", sf_int, VP CPX_PARAM_RELAXPREIND, relaxpresolve_desc }, { "relobjdif", sf_dbl2, VP CPX_PARAM_RELOBJDIF, relobjdif_desc }, { "relobjdiff", sf_dbl, VP CPX_PARAM_RELOBJDIF, relobjdiff_desc }, { "relpresolve", sf_int, VP CPX_PARAM_RELAXPREIND, relpresolve_desc }, #ifdef CPX_PARAM_REPAIRTRIES { "repairtries", sf_int, VP CPX_PARAM_REPAIRTRIES, repairtries_desc }, #endif #ifdef CPX_PARAM_REPEATPRESOLVE { "repeatpresolve", sf_int, VP CPX_PARAM_REPEATPRESOLVE, repeatpresolve_desc }, #endif #ifdef REQCONVEX { "reqconvex", sf_int, VP REQCONVEX, reqconvex_desc }, #endif { "resolve", sf_mint, VP set_resolve, resolve_desc }, { "return_mipgap", sf_mint, VP set_retmipgap, return_mipgap_desc }, #ifdef CPX_PARAM_RINSHEUR { "rinsheur", sf_int, VP CPX_PARAM_RINSHEUR, rinsheur_desc }, #endif #ifdef CPXPARAM_MIP_Cuts_RLT { "rltcuts", sf_int, VP CPXPARAM_MIP_Cuts_RLT, rltcuts_desc }, #endif #ifdef CPX_PARAM_HEURISTIC { "rootheuristic", sf_int, VP CPX_PARAM_HEURISTIC, rootheuristic_desc }, #endif { "round", sf_mint, VP set_round, round_desc }, #endif /*CPLEX_MIP*/ { "scale", sf_int, VP CPX_PARAM_SCAIND, scale_desc }, #ifdef CPX_PARAM_RANDOMSEED { "seed", sf_int, VP CPX_PARAM_RANDOMSEED, seed_desc }, #endif { "sensitivity", sf_known, VP set_sens, sensitivity_desc }, { "siftingopt", sf_known, VP set_siftopt, siftingopt_desc }, { "siftopt", sf_known, VP set_siftopt, siftopt_desc }, #ifdef CPX_PARAM_SIFTSIM { "simplexsifting", sf_int, VP CPX_PARAM_SIFTSIM, simplexsifting_desc}, #endif #ifdef CPX_PARAM_SIMTHREADS { "simthreads", sf_int, VP CPX_PARAM_SIMTHREADS, simthreads_desc }, #endif { "singular", sf_int, VP CPX_PARAM_SINGLIM, singular_desc }, { "singularlim", sf_int, VP CPX_PARAM_SINGLIM, singularlim_desc }, #ifdef CPLEX_MIP /*{*/ { "solutionlim", sf_int, VP CPX_PARAM_INTSOLLIM, solutionlim_desc }, #endif /*}*/ #ifdef CPX_PARAM_SOLUTIONTYPE { "solutiontype", sf_int, VP CPX_PARAM_SOLUTIONTYPE, solutiontype_desc }, #endif #ifdef CPLEX_MIP /*{*/ { "sos", sf_mint, VP set_sos, sos_desc }, { "sos2", sf_mint, VP set_sos2, sos2_desc }, { "sparam", sf_spar, 0, sparam_desc }, #ifdef CPX_PARAM_LANDPCUTS { "splitcuts", sf_int, VP CPX_PARAM_LANDPCUTS, splitcuts_desc }, #endif { "startalg", sf_int, VP CPX_PARAM_STARTALG, startalg_desc }, { "startalgorithm", sf_int, VP CPX_PARAM_STARTALG, startalgorithm_desc }, { "startbasis", sf_char, VP set_startbas, startbasis_desc }, { "startsol", sf_char, VP set_startsol, startsol_desc }, #ifdef CPX_PARAM_IISIND /* version < 9.2b */ { "starttree", sf_char, VP set_starttree, starttree_desc }, #endif #if defined(BARRIER) && !defined(NO_DEPRECATED) { "startvector", sf_char, VP set_startvector, "Synonym for \"readvector\"." }, #endif { "strongcand", sf_int, VP CPX_PARAM_STRONGCANDLIM, strongcand_desc }, { "strongit", sf_int, VP CPX_PARAM_STRONGITLIM, strongit_desc }, #ifdef CPX_PARAM_STRONGTHREADLIM { "strongthreads", sf_int, VP CPX_PARAM_STRONGTHREADLIM, strongthreads_desc }, #endif { "subalg", sf_int, VP CPX_PARAM_SUBALG, subalg_desc }, { "subalgorithm", sf_int, VP CPX_PARAM_SUBALG, subalgorithm_desc }, #ifdef CPX_PARAM_SUBMIPSUBALG { "submipalg", sf_int, VP CPX_PARAM_SUBMIPSUBALG, submipalg_desc }, #endif #ifdef CPXPARAM_MIP_SubMIP_NodeLimit { "submipnodelim", sf_int, VP CPXPARAM_MIP_SubMIP_NodeLimit, submipnodelim_desc }, #endif #ifdef CPX_PARAM_SUBMIPSCAIND { "submipscale", sf_int, VP CPX_PARAM_SUBMIPSCAIND, submipscale_desc }, #endif #ifdef CPX_PARAM_SUBMIPSTARTALG { "submipstartalg", sf_int, VP CPX_PARAM_SUBMIPSTARTALG, submipstartalg_desc }, #endif #ifdef CPX_PARAM_SYMMETRY { "symmetry", sf_int, VP CPX_PARAM_SYMMETRY, symmetry_desc }, #endif #endif /*}*/ #ifdef CPX_PARAM_THREADS { "threads", sf_int, VP CPX_PARAM_THREADS, threads_desc }, #endif { "time", sf_dbl, VP CPX_PARAM_TILIM, time_desc }, { "timelimit", sf_dbl, VP CPX_PARAM_TILIM, timelimit_desc }, { "timing", sf_mint, VP set_timing, timing_desc }, { "tranopt", sf_known, VP set_dualopt, tranopt_desc }, #ifdef CPLEX_MIP { "treelimit", sf_dbl2, VP CPX_PARAM_TRELIM, treelimit_desc }, { "treememlim", sf_dbl2, VP CPX_PARAM_TRELIM, treememlim_desc }, { "treememory", sf_dbl, VP CPX_PARAM_TRELIM, treememory_desc }, #endif #ifdef CPX_TUNE_TILIM { "tunedisplay", sf_int, VP CPX_PARAM_TUNINGDISPLAY, tunedisplay_desc }, { "tunefile", sf_char, VP set_tunefile, tunefile_desc }, { "tunefileprm", sf_char, VP set_tunefileprm, tunefileprm_desc }, { "tunefix", sf_char, VP set_tunefix, tunefix_desc }, { "tunefixfile", sf_char, VP set_tunefixfile, tunefixfile_desc }, { "tunerepeat", sf_int, VP CPX_PARAM_TUNINGREPEAT, tunerepeat_desc }, { "tunetime", sf_dbl, VP CPX_PARAM_TUNINGTILIM, tunetime_desc }, #ifdef CPX_PARAM_TUNINGDETTILIM { "tunetimedet", sf_dbl, VP CPX_PARAM_TUNINGDETTILIM, tunetimedet_desc }, #endif #endif #ifdef CPLEX_MIP { "uppercutoff", sf_dbl, VP CPX_PARAM_CUTUP, uppercutoff_desc }, #endif { "upperobj", sf_dbl, VP CPX_PARAM_OBJULIM, upperobj_desc }, { "upperobjlim", sf_dbl, VP CPX_PARAM_OBJULIM, upperobjlim_desc }, #ifdef CPLEX_MIP { "varsel", sf_int, VP CPX_PARAM_VARSEL, varsel_desc }, { "varselect", sf_int, VP CPX_PARAM_VARSEL, varselect_desc }, #endif { "version", Ver_val, 0, version_desc }, #ifdef Want_Distmipopt { "vmconf", sf_char, VP set_vmconfig, vmconf_desc }, #endif { "wantsol", WS_val, 0, wantsol_desc }, #ifdef CPXPARAM_Read_WarningLimit { "warninglimit", sf_int, VP CPXPARAM_Read_WarningLimit, warninglimit_desc }, #endif { "workfiledir", sf_char, VP set_workfiledir, workfiledir_desc }, #ifdef CPX_PARAM_WORKMEM { "workfilelim", sf_dbl, VP CPX_PARAM_WORKMEM, workfilelim_desc }, #endif { "writebasis", sf_char, VP set_endbas, writebasis_desc }, { "writemipstart", sf_char, VP set_wrtmipstart, writemipstart_desc }, { "writeprob", sf_char, VP set_wrtfname, writeprob_desc }, { "writesol", sf_char, VP set_endsol, writesol_desc }, #if defined(BARRIER) && !defined(NO_DEPRECATED) && CPX_VERSION < 12070000 { "writevector", sf_char, VP set_endvector, writevector_desc }, #endif #ifdef CPX_PARAM_XXXIND { "xxxstart", sf_int, VP CPX_PARAM_XXXIND, xxxstart_desc }, #endif #ifdef CPX_PARAM_ZEROHALFCUTS { "zerohalfcuts", sf_int, VP CPX_PARAM_ZEROHALFCUTS, zerohalfcuts_desc }, #endif }; static Option_Info Oinfo = { "cplex", 0, "cplex_options", keywds, nkeywds, ASL_OI_keep_underscores, cplex_version, 0, MOkwf,0,0,0, 20210726, 0,0,0,0,0,0,0, ASL_OI_tabexpand | ASL_OI_addnewline }; static void badlic(int rc, int status) { char buf[4096]; if (!CPXgeterrorstring(Env, status, buf)) Snprintf(buf, sizeof(buf), "CPLEX licensing problem: error code %d from CPXopenCPLEX.", status); badretfmt(rc, "%s", buf); } static void nonlin(int n, int rc, char *what) { if (n) { badretfmt(rc, "%s contains %s.\n", asl->i.filename_, what); exit(4); } } static unsigned namemem(int n) { int k, L; unsigned int rv; L = 3; k = 9; rv = 0; while(n > k) { rv += k*L++; n -= k; k *= 10; } return rv + n*L; } static char * namegen(char *stub, char **name, char *s, int n) { int i, j, k, k0, L; k0 = 10; for(i = 1; i <= n; i++) { if (k0 <= i) k0 *= 10; *name++ = s; *s++ = *stub; for(j = i, k = k0; k /= 10; ) { L = j / k; j -= L * k; *s++ = '0' + L; } *s++ = 0; } return s; } static unsigned int brlen(char **name, int n) { char *s, *s0; unsigned int x = 0; top: while(n > 0) for(s = s0 = name[--n];;) switch(*s++) { case 0: goto top; case '[': case ']': x += strlen(s0) + 1; goto top; } return x; } static char* br_round(char **name, int n, char *s) { char *t, *t0; top: while(n > 0) for(t = t0 = name[--n];;) switch(*t++) { case 0: goto top; case '[': case ']': name[n] = s; for(;;) switch(*s++ = *t0++) { case 0: goto top; case '[': s[-1] = '('; break; case ']': s[-1] = ')'; } } return s; } static void make_names(char ***cnamep, char ***rnamep) { char buf[24], **cname, **rname, *s; int cnlen, i, j, n, rnlen; unsigned int cstorsz, rstorsz, rsz; cnlen = rnlen = 0; if (method > 0) { cnlen = maxcolnamelen; rnlen = maxrownamelen; } cstorsz = cnlen > 0 ? 0 : namemem(nbas); rstorsz = rnlen > 0 ? 0 : namemem(mbas); *cnamep = cname = (char **)Malloc((mbas+nbas)*sizeof(char *) + cstorsz + rstorsz); *rnamep = rname = cname + nbas; s = (char*)(rname + mbas); if (cnlen > 0) { for(i = 0, n = n_var; i < n; i++) cname[i] = var_name(i); while(i < nbas) { j = sprintf(buf, "_svar[%d]", i+1) + 1; memcpy(cname[i++] = (char*)mem(j), buf, j); } } else s = namegen("x", cname, s, nbas); if (rnlen > 0) { for(i = 0, n = n_con; i < n; i++) rname[i] = con_name(i); while(i < mbas) { j = sprintf(buf, "_scon[%d]", i+1) + 1; memcpy(rname[i++] = (char*)mem(j), buf, j); } } else namegen("c", rname, s, mbas); if (Nameround) { /* This would be better done by running "tr" separately. */ rsz = 0; if (cnlen > 0) rsz = brlen(cname, nbas); if (rnlen > 0) rsz += brlen(rname, mbas); if (!rsz) return; s = (char*)M1alloc(rsz); if (cnlen > 0) s = br_round(cname, nbas, s); if (rnlen > 0) br_round(rname, mbas, s); } } #ifdef CPLEX_MIP /*{*/ static int nzeros(int *p, int n) { int *pe = p + n; n = 0; while(p < pe) if (*p++) n++; return n; } static void mip_priorities(ASL *asl, cpxlp *cpx) { int baddir, badpri, i, j, k, listsize, nnames, pvk, sk; int *ci, *colindex, *dir, *direction, *p, *priority; int *start, *num, *pri; SufDesc *dp, *dd; baddir = badpri = i = listsize = 0; dd = suf_get("direction", ASL_Sufkind_var); dir = dd->u.i; dp = suf_get("priority", ASL_Sufkind_var); direction = 0; if ((p = dp->u.i) || dir) { nnames = n_var; k = 2; if (p && dir) { k = 3; for(; i < nnames; i++) if (p[i] || dir[i]) listsize++; } else if (p) listsize = nzeros(p, nnames); else listsize = nzeros(dir, nnames); if (!listsize) return; priority = 0; colindex = (int*)Malloc(k*listsize*sizeof(int)); i = k = 0; if (dir && p) { priority = colindex + listsize; direction = priority + listsize; for(; i < nnames; i++) if (p[i] || dir[i]) { colindex[k] = i; if ((j = p[i]) < 0) { badpri++; j = 0; } priority[k] = j; switch(dir[i]) { case -1: j = CPX_BRANCH_DOWN; break; case 1: j= CPX_BRANCH_UP; break; default: baddir++; /* no break */ case 0: j = CPX_BRANCH_GLOBAL; } direction[k++] = j; } } else if (p) { priority = colindex + listsize; for(; i < nnames; i++) if (p[i]) { colindex[k] = i; if ((j = p[i]) < 0) { badpri++; j = 0; } priority[k++] = j; } } else { direction = colindex + listsize; for(; i < nnames; i++) if (dir[i]) { switch(dir[i]) { case -1: j = CPX_BRANCH_DOWN; break; case 1: j= CPX_BRANCH_UP; break; default: baddir++; /* no break */ case 0: j = CPX_BRANCH_GLOBAL; } direction[k] = j; colindex[k++] = i; } } listsize = k; if (baddir) fprintf(Stderr, "Treating %d .direction values outside [-1, 1] as 0.\n", baddir); if (badpri) fprintf(Stderr, "Treating %d negative .priority values as 0\n", badpri); } else if ((nnames = mip_pri(&start, &num, &pri, 2147483647))) { for(; i < nnames; i++) listsize += num[i]; ci = colindex = (int *)Malloc(listsize*(2*sizeof(int))); priority = p = ci + listsize; for(k = 0; k < nnames; k++) { i = num[k]; pvk = pri[k]; sk = start[k]; while(--i >= 0) { *ci++ = sk++; *p++ = pvk; } } listsize = ci - colindex; } else return; if (CPXcopyorder(Env,cpx,listsize,colindex,priority,direction)) printf("error in CPXcopyorder!\n"); free(colindex); } static void mipinit_loop(ASL *asl, int **rp, int *np, real **xp, int j, int k) { int i, *r; real *L, *U, t, *v, *x; v = X0 + j; L = LUv + j; U = Uvx + j; r = *rp; x = *xp; for(i = 0; i < k; ++i) { *r++ = i + j; if ((t = v[i]) < L[i]) t = L[i]; else if (t > U[i]) t = U[i]; *x++ = t; } *rp = r; *xp = x; *np -= k; } static void set_mipinit(ASL *asl, cpxlp *cpx, int nint) { int *effortlev, effortlev0[1], i, n1, *r, *r1; real *x, *x1; #if !defined(NO_DEPRECATED) && CPX_VERSION < 12070000 int k, m, m0; #endif #if CPX_VERSION_VERSION >= 12 int beg[2]; if (mipstval != 2) nint = n_var; #endif #if CPX_VERSION >= 12070000 if (mipstval == 2) { fprintf(Stderr, "Ignoring mipstval = 2.\n"); return; } #endif x = x1 = (real*)Malloc(nint*(sizeof(real) + sizeof(int))); r = r1 = (int*)(x + nint); n1 = nint; #if CPX_VERSION_VERSION >= 12 if ( #ifndef NO_DEPRECATED mipstval != #endif 2) { mipinit_loop(asl, &r1, &n1, &x1, 0, nint); beg[0] = 0; beg[1] = nint; effortlev = 0; if (mipstval > 2) { effortlev = effortlev0; effortlev0[0] = mipstval - 2; } if ((i = CPXaddmipstarts(Env, cpx, 1, nint, beg, r, x, effortlev, 0))) badret("CPXaddmipstarts", i, 0); } else { #endif #if CPX_VERSION < 12070000 /*{*/ #ifndef NO_DEPRECATED if ((k = nlvbi)) mipinit_loop(asl, &r1, &n1, &x1, nlvb - k, k); m0 = nlvb; m = nlvc - nlvb; if ((k = nlvci)) mipinit_loop(asl, &r1, &n1, &x1, m0 + m - k, k); m0 += m; if ((k = nlvoi)) mipinit_loop(asl, &r1, &n1, &x1, m0 + nlvo - nlvc - k, k); if (n1) mipinit_loop(asl, &r1, &n1, &x1, n_var - (niv + nbv), n1); if ((i = CPXcopymipstart(Env, cpx, nint, r, x))) badret("CPXcopymipstart", i, 0); #ifdef CPX_PARAM_MIPSTART else if (i = CPXsetintparam(Env, CPX_PARAM_MIPSTART, 1)) badret("CPXsetintparam(CPX_PARAM_MIPSTART)", i, 0); #endif #endif #endif /*}*/ #if CPX_VERSION_VERSION >= 12 } #endif free(x); } #endif /*}*/ static int parval(int par) { int rv; CPXgetintparam(Env, par, &rv); return rv; } static int CPXPUBLIC lpcbf(CPXCENVptr env, void *lp, int wf, void *cbh) { int i; static int n[4]; static int wi[8] = { CPX_CALLBACK_INFO_PRESOLVE_ROWSGONE, CPX_CALLBACK_INFO_PRESOLVE_COLSGONE, CPX_CALLBACK_INFO_PRESOLVE_AGGSUBST, CPX_CALLBACK_INFO_PRESOLVE_COEFFS, CPX_CALLBACK_INFO_CROSSOVER_PPUSH, CPX_CALLBACK_INFO_CROSSOVER_PEXCH, CPX_CALLBACK_INFO_CROSSOVER_DPUSH, CPX_CALLBACK_INFO_CROSSOVER_DEXCH }; static int wf0 = -1; static void *lp0; Not_Used(cbh); if ((wf != wf0 || lp != lp0) && wf0 == CPX_CALLBACK_PRESOLVE && prestats) { if (n[0] + n[1] + n[2]) for(i = 0; i < 4; ++i) { cbi.np[i] += n[i]; n[i] = 0; } n[3] = 0; } switch(wf) { case CPX_CALLBACK_PRESOLVE: if (prestats) for(i = 0; i < 4; i++) CPXgetcallbackinfo(env, lp, wf, wi[i], &n[i]); break; case CPX_CALLBACK_PRIMAL_CROSSOVER: cbi.xkind = "primal"; for(i = 0; i < 2; i++) CPXgetcallbackinfo(env, lp, wf, wi[i+4], &cbi.nx[i]); break; case CPX_CALLBACK_DUAL_CROSSOVER: cbi.xkind = "dual"; for(i = 0; i < 2; i++) CPXgetcallbackinfo(env, lp, wf, wi[i+6], &cbi.nx[i]); break; } lp0 = lp; wf0 = wf; return breaking > 1; } static void stat_map(int *stat, int n, int *map, int mx, char *what) { int bad, i, i1, j, j1; static char badfmt[] = "cplex driver: %s[%d] = %d\n"; for(i = bad = 0; i < n; i++) { if ((j = stat[i]) >= 0 && j <= mx) stat[i] = map[j]; else { stat[i] = 0; i1 = i; j1 = j; if (!bad++) fprintf(Stderr, badfmt, what, i, j); } } if (bad > 1) { if (bad == 2) fprintf(Stderr, badfmt, what, i1, j1); else fprintf(Stderr, "cplex driver: %d messages about bad %s values suppressed.\n", bad-1, what); } } static void get_statuses(ASL *asl, cpxlp *cpx, dims *d) { SufDesc *sd; int *cs, *cstat, havestats, i, j, m, n, *rs, *rstat; real *L, *U; static int map[] = {0, 1, 3, 0, 2, 3, 3}; havestats = 0; sd = d->csd; n = n_var; if (sd->kind & ASL_Sufkind_input) havestats = 1; sd = d->rsd; m = n_con; if (sd->kind & ASL_Sufkind_input) havestats = 1; d->cs = d->rs = 0; if (!havestats || (!mipststat && niv + nbv)) return; if (method > 0) { stat_map(d->cs = d->cstat, n, map, 6, "incoming cstat"); stat_map(d->rs = d->rstat, m, map, 6, "incoming rstat"); if (objadj) { d->cstat[n] = CPX_BASIC; d->rstat[m] = CPX_FREE_SUPER; } if ((i = CPXcopybase(Env, cpx, d->cstat, d->rstat))) { bad_copybase: badret("CPXcopybase", i, 0); } return; } cs = (int*)(use_netopt ? M1alloc((mbas + nbas)*sizeof(int)) : Malloc((mbas + nbas)*sizeof(int))); rs = cs + nbas; m = n_con; n = n_var; L = LUrhs; U = Urhsx; cstat = d->cstat; rstat = d->rstat; for(i = 0; i < m; i++) { if (L[i] <= negInfinity) cs[i] = rstat[i] == 1 ? CPX_AT_UPPER : CPX_BASIC; else cs[i] = rstat[i] == 1 ? CPX_AT_LOWER : CPX_BASIC; } if (nranges) { for(j = 0; j < m; j++) if (L[j] < U[j] && L[j] > negInfinity && U[j] < Infinity) cs[i++] = rstat[j] == 4 ? CPX_BASIC : CPX_AT_UPPER; } L = LUv; U = Uvx; for(j = 0; j < n; j++) { rs[j] = CPX_AT_LOWER; if (L[j] > negInfinity) { if (L[j]) cs[i++] = cstat[j] == 3 ? CPX_BASIC : CPX_AT_LOWER; else rs[j] = cstat[j] == 3 ? CPX_BASIC : CPX_AT_UPPER; if (U[j] < Infinity) goto finite_ub; } else if (U[j] < Infinity) { finite_ub: if (U[j]) cs[i++] = cstat[j] == 4 ? CPX_BASIC : CPX_AT_LOWER; else rs[j] = cstat[j] == 4 ? CPX_BASIC : CPX_AT_LOWER; } else if (cstat[j] != 1) rs[j] = CPX_BASIC; } if (objadj) cs[i] = 1; i = CPXcopybase(Env, cpx, cs, rs); if (use_netopt) { d->cs = cs; d->rs = rs; } else free(cs); if (i) goto bad_copybase; } static int qmatadj(int k, int nr, int os, CPXNNZ *colq, int *colqcnt, double **qmatp, char *ctype) { double badd[3], *oqmat, osd, *qmat, t; int badk[3], i, nbad = 0, nb, w, w1; oqmat = *qmatp; *qmatp = qmat = (double *)Malloc(nr*sizeof(double)); while(nr > k) qmat[--nr] = 0.; osd = os; while(--k >= 0) { t = 0.; if (colqcnt[k]) { t = oqmat[colq[k]]; if (t*osd < 0. && (!ctype || ctype[k] == 'C')) { if (nbad < 3) { badd[nbad] = t; badk[nbad] = k; } nbad++; } } qmat[k] = t; } #ifdef REQCONVEX if (nbad && parval(REQCONVEX) >= 2) nbad = 0; #endif if (!nbad) return 0; fprintf(Stderr, "%d diagonal QP coefficients of the wrong sign:\n", nbad); if ((nb = nbad) > 3) nb = 3; w = 8; for(i = 0; i < nb; i++) { w1 = strlen(var_name(badk[i])); if (w < w1) w = w1; } fprintf(Stderr, "Variable%.*s Diagonal\n", w-8, ""); for(i = 0; i < nb; i++) fprintf(Stderr, "%-*s %g\n", w, var_name(badk[i]), 0.5*badd[i]); solve_result_num = 540; asl->i.uinfo = "Diagonal QP Hessian has elements of the wrong sign."; return 1; } static int refcomp(const void *a, const void *b, void *c) { double d, *x; x = (double*)c; d = x[*(int*)a] - x[*(int*)b]; if (d < 0.) return -1; if (d > 0.) return 1.; return 0; } static void sos_kludge(int nsos, int *sosbeg, double *sosref) { /* Adjust sosref if necessary to accommodate CPLEX's */ /* undocumented requirement that sosref values differ */ /* by at least 1e-10. */ int i, i0, i1, j, k, m, m1, *z, z0[16]; double t, t1; for(i = j = 0; i++ < nsos; ) { k = sosbeg[i]; t = sosref[j]; while(++j < k) { t1 = sosref[j]; t += 1e-10; if (t1 <= t) { if (t1 < t) goto trysort; sosref[j] = t1 = t + 1e-10; } t = t1; } } return; trysort: j = sosbeg[i0 = i - 1]; m = 0; for(i = i0; i++ < nsos; j = k) { k = sosbeg[i]; if ((m1 = k - j) > m) m = m1; } z = z0; if (m > sizeof(z0)/sizeof(z0[0])) z = (int *)Malloc(m*sizeof(int)); for(j = sosbeg[i = i0]; i++ < nsos; j = k) { k = sosbeg[i]; m1 = k - j; for(i1 = 0; i1 < m1; ++i1) z[i1] = i1 + j; qsortv(z, m1, sizeof(int), refcomp, sosref); t = sosref[z[0]]; for(i1 = 1; i1 < m1; ++i1, t = t1) { t1 = sosref[z[i1]]; t += 1e-10; if (t1 <= t) sosref[z[i1]] = t1 = t + 1e-10; } } if (z != z0) free(z); } #ifdef CPXERR_QCP_SENSE /*{*/ static void Surprise(ASL *asl, int n, char *who) { char msgbuf[64]; sprintf(msgbuf, "Surprise return %d from %s.", n, who); nonlin(1, 561, msgbuf); } static void** linadj(ASL *asl, CStype *ka, int *ia, double *a, int **kaqp, int **kalqp, int **iaqp, double **aqp, CPXNNZ **nelqcp, int ***rowqcp, int ***colqcp, double ***qcmatp, dims *d, void **v) { /* Move linear parts of nqc quadratic constraints from ka, ia, a */ /* to kaq, kalq, iaq, aq and corresponding Cgrad pointers and return a */ /* pointer to the relevant allocation. */ CPXNNZ *nelqc; QPinfo *qpi; cde *consave; cgrad **cgp, *cg, *cga, *cg0; char *what; double *aq, **qcmat, *x, *y; int i, i1, i2, j, k, m, m0, m1, n, ncol, nqc; int *colno, **colqc, *iaq, *kalq, *kaq, *kaq0, *rowno, **rowqc, *z, *z1; size_t *colbeg, is, js, ks, ms, nelq, nl, nqcnl; ssize_t nq; m = n_con; m1 = asl->i.n_con1; n = n_var; nqc = nlc; d->consave = consave = (cde*)M1alloc(m1*sizeof(cde)); memcpy(consave, ((ASL_fg*)asl)->I.con_de_, m1*sizeof(cde)); kaq0 = (int*)Malloc(nqc*sizeof(int)); if ((cgp = Cgrad)) { nl = 0; for(i = 0; i < nqc; ++i) { for(j = 0, cg = cgp[i]; cg; cg = cg->next) ++j; kaq0[i] = j; nl += j; } cga = (cgrad*)M1alloc(nl*sizeof(cgrad)); } else { js = nzc; for(is = nl = 0; is < js; ++is) if (ia[is] < nqc) nl++; cg = cga = (cgrad*)M1alloc(m1*sizeof(cgrad*) + nl*sizeof(cgrad)); cgp = (cgrad**)(cga + nl); memset(kaq0, 0, nqc*sizeof(int)); memset(cgp, 0, m*sizeof(cgrad*)); Cgrad = cgp; for(js = i = 0; i < n; i++) { for(ks = ka[i+1]; js < ks; js++) if ((i1 = ia[js]) < nqc) { kaq0[i1]++; cg->varno = i; cg->coef = a[js]; cg->next = cgp[i1]; cgp[i1] = cg++; } } } x = LUrhs; y = Urhsx; for(nl = nqcnl = i = 0; i < nqc; i++) { if (x[i] > negInfinity && y[i] < Infinity) { badretfmt(562, "Constraint %s is not convex quadratic since it is %s constraint.", con_name(i), x[i] == y[i] ? "an equality" : "a two-sided"); exit(4); } k = nl; nl += kaq0[i]; kaq0[i] = k; nq = mqpcheckv(-(i+1), 0, v); if (nq <= 0) { what = con_name(i); if (nq == -2) badretfmt(558, "Constraint %s is a quadratic constraint " "involving division by 0.", what); else if (nq < 0) badretfmt(550, "Constraint %s is a nonquadratic " "nonlinear constraint.", what); else badretfmt(559, "CPLEX driver bug: no quadratic terms " "in \"nonlinear\" constraint %s.", what); exit(4); } nqcnl += nq; } *aqp = aq = (double*)Realloc(kaq0, nqc*(sizeof(double*) + 2*sizeof(int*)) + (2*(nqc + nqcnl) + nl)*sizeof(int) + nqc*sizeof(CPXNNZ) + (nl+nqcnl)*sizeof(double)); x = aq + nl; *qcmatp = qcmat = (double**)(x + nqcnl); *rowqcp = rowqc = (int**)(qcmat + nqc); *colqcp = colqc = rowqc + nqc; *nelqcp = nelqc = (CPXNNZ*)(colqc + nqc); *kaqp = kaq = (int*)(nelqc + nqc); *kalqp = kalq = kaq + nqc; z = kalq + nqc; *iaqp = iaq = z + 2*nqcnl; kaq0 = (int*)aq; for(i = nqc; i > 0; ) { --i; kaq[i] = kaq0[i]; } memset(cgp, 0, nqc*sizeof(cgrad*)); for(ms = i = j = 0; j < n; j++) { ka[j] = ms; for(k = ka[j+1]; i < k; i++) if ((i1 = ia[i]) < nqc) { iaq[i2 = kaq[i1]++] = j; aq[i2] = a[i]; } else { ia[ms] = i1 - nqc; a[ms++] = a[i]; } } nzc = ka[n] = ms; for(i = nqc; --i > 0; ) kaq[i] = kaq[i-1]; kaq[0] = 0; j = nl; for(i = nqc; i > 0; ) { k = kaq[--i]; cg0 = 0; while(j > k) { cg = cga++; cg->next = cg0; cg0 = cg; cg->coef = aq[--j]; cg->varno = iaq[j]; } cgp[i] = cg0; } for(i = m = 0; i < nqc; i++) { nelqc[i] = nelq = mqpcheckv(-(i+1), &qpi, v); qcmat[i] = x; y = qpi->delsq; for(js = 0; js < nelq; ++js) *x++ = 0.5*y[js]; rowqc[i] = z1 = z; colqc[i] = z += nelq; rowno = qpi->rowno; colbeg = qpi->colbeg; colno = qpi->colno; ncol = qpi->nc; is = colbeg[0]; for(j = 0; j < ncol;) { k = colno[j]; for(js = colbeg[++j]; is < js; ++is) { *z1++ = rowno[is]; *z++ = k; } } free(qpi); kaq[i] = m0 = m; for(cg = cgp[i]; cg; cg = cg->next) if (cg->coef) { iaq[m] = cg->varno; aq[m++] = cg->coef; } kalq[i] = m - m0; } return M1record((void*)aq); } static real vmax(real *x, size_t n) /* returns max{i in 0..n-1} |x[i]|, assuming n >= 1 */ { real mn, mx, t, *xe; mn = mx = *x; xe = x + n; while(++x < xe) { if (mn > (t = *x)) mn = t; else if (mx < t) mx = t; } if (mx < 0.) mx = -mn; else if ((t = -mn) > mx) mx = t; return mx; } static real dot(real *x, real *y, size_t n) { real rv, *xe; xe = x + n; rv = 0.; while(x < xe) rv += *x++ * *y++; return rv; } static real ssq(real *x, size_t n) { real rv, t; size_t i; rv = 0.; for(i = 0; i < n; ++i) { t = x[i]; rv += t*t; } return rv; } static void LSsol(size_t n, size_t m, real *A, real *x, real *b, int *bt) { /* Solve A*x = b in the least-squares sense, with A consisting of m */ /* columns of length n, stored column-wise, subject to x[i] >= 0 */ /* if bt[i] > 0 and to x[i] <= 0 if bt[i] < 0. */ /* We clobber A and b. */ /* We use column pivoting and Householder transformations. */ /* Given vector x = (x1, x2)^T with x1 a scalar and x2 a vector, */ /* H = I - 2*y*y^T/y^T*y with y = (x1 + sigma*norm(x), x2)^T, sigma = +-1, */ /* norm(x) = sqrt(x^T*x) is a reflection (Householder transformation) */ /* with H*x = (-sigma*norm(x), 0)^T. */ /* Note that y^T*y = 2*(x^T*x + sigma*x1*norm(x)). */ /* For stability, sigma = sign(x1). */ int move; real *ai, *aie, *aj, *bnew, di, *rd, *scale, t, t2, tb, x1, *xnew; size_t i, j, jb, k, k1, k2, m1, ni, ni1, nq, *p, pj, *q, *ql; if ((k = m) > n) k = n; if (k <= 0) { for(i = 0; i < m; ++i) x[i] = 0.; return; } rd = (real*)Malloc((3*m + n)*sizeof(real) + (m+2*k)*sizeof(size_t)); scale = rd + m; bnew = scale + m; xnew = bnew + n; p = (size_t*)(xnew + m); q = p + m; ql = q + k; for(i = 0; i < m; ++i) { p[i] = i; x[i] = 0.; } ai = A + n*m; do { --i; t = vmax(ai -= n, n); if (t <= qctol2) p[i] = p[--m]; else if (t != 1.) { t = 1. / t; for(j = 0; j < n; ++j) ai[j] *= t; } scale[i] = t; } while(i > 0); m1 = m; k1 = move = 0; while(i < n) { findbest: /* find "best" column to process next */ for(jb = i;;) { pj = p[jb]; tb = dot(A + n*pj, b, n); if (bt[pj] < 0 || (bt[pj] == 0 && tb < 0.)) tb = -tb; if (tb > 0.) { ai = A + n*pj; for(j = i; j < n; ++j) if (ai[j] != 0.) goto have_jb0; } if (++jb >= m1) { if (!move || m1 >= m) goto break2; m1 = m; move = 0; } } /* now jb = candidate "best" next column; look for better ones */ have_jb0: for(j = jb; ++j < m1; ) { pj = p[j]; t = dot(A + n*pj, b, n); if (bt[pj] < 0 || (bt[pj] == 0 && t < 0.)) t = -t; if (tb < t) { tb = t; jb = j; } } /* now jb = "best" next column */ pj = p[jb]; if (jb > i) { p[jb] = p[i]; p[i] = pj; } ni = n - i; ni1 = ni - 1; aie = A + n*pj; ai = aie + i; aie += n; t = sqrt(t2 = ssq(ai, ni)); if ((x1 = *ai) < 0.) t = -t; /* now t == sigma*norm(x) */ di = 1. / (t2 + x1*t); rd[i] = -t; *ai += t; /* apply the just-constructed Householder transformation */ for(j = i + 1; j < m; ) { pj = p[j]; aj = A + i + n*pj; if ((t = dot(ai, aj, ni))) { t *= di; for(k = 0; k < ni; ++k) aj[k] -= t*ai[k]; if (ni1 > 0) { t2 = vmax(aj+1, ni1); if (t2 <= qctol3) { p[j] = p[--m]; p[m] = pj; continue; } } } ++j; } /* apply the Householder to the rhs */ aj = b + i; if ((t = dot(ai, aj, ni))) { t *= di; for(k = 0; k < ni; ++k) aj[k] -= t*ai[k]; } /* update column i -- later we may move x[i] to 0 and still later */ /* we may need to apply future Householder transforms to it */ *ai = rd[i]; while(++ai < aie) *ai = 0.; /* compute xnew */ for(j = 0; j <= i; ++j) bnew[j] = b[j]; for(;;) { pj = p[--j]; t = bnew[j] /= rd[j]; xnew[pj] = x[pj] + t*scale[pj]; if (j == 0) break; if (t) { aj = A + n*pj; k = j; do { --k; bnew[k] -= t*aj[k]; } while(k > 0); } } /* see if xnew is feasible */ for(jb = 0; jb < i; ++jb) { pj = p[jb]; if (xnew[pj] * bt[pj] < 0.) { /* no: find the first x component to be zeroed */ /* as we move from x to xnew */ tb = x[pj] / (x[pj] - xnew[pj]); for(j = jb; ++j < i; ) { pj = p[j]; if (xnew[pj] * bt[pj] < 0.) { t = x[pj] / (x[pj] - xnew[pj]); if (tb > t) { tb = t; jb = j; } } } if (tb > 0.) ++move; /* move tb of the way from x to xnew, */ /* noting nq zeroed x components in q */ nq = 0; for(j = k = 0; j <= i; ++j) { pj = p[j]; x[pj] += tb * (xnew[pj] - x[pj]); if (j == jb || (bt[pj] && bt[pj]*x[pj] <= 0.)) { if (!nq) k1 = j; q[nq++] = pj; } else { p[k] = pj; ql[k++] = j; } t = tb * bnew[j]; aj = A + pj*n; for(k2 = 0; k2 <= j; ++k2) b[k2] -= t*aj[k2]; } while(j < m1) p[k++] = p[j++]; for(j = 0; j < nq; ++j) p[k++] = q[j]; m1 -= nq; i -= nq; /* bring R matrix back to triangular form */ for(j = k1; j < i; ++j) { pj = p[j]; ai = A + pj*n + j; ni = ql[j] - j + 1; t = sqrt(t2 = ssq(ai, ni)); if ((x1 = *aj) < 0.) t = -t; di = 1. / (t2 + x1*t); rd[j] = -t; for(k = j + 1; k < m; ++k) { aj = A + n*p[k] + j; if ((t = dot(ai, aj, ni))) { t *= di; for(k1 = 0; k1 < ni; ++k1) aj[k1] -= t*ai[k1]; } } aj = b + j; if ((t = dot(ai, aj, ni))) { t *= di; for(k1 = 0; k1 < ni; ++k1) aj[k1] -= t*ai[k1]; } *ai = rd[j]; for(k1 = 1; k1 < ni; ++k1) ai[k1] = 0.; } goto findbest; } } /* we can take the full step */ ++move; for(j = 0; j <= i; ++j) { pj = p[j]; x[pj] = xnew[pj]; aj = A + pj*n; if ((t = bnew[j])) /* the increment */ for(k2 = 0; k2 <= j; ++k2) b[k2] -= t*aj[k2]; } if (++i >= n) break; if (i >= m1) { if (m1 >= m) break; move = 0; m1 = m; } } break2: free(rd); } static void qcduals(ASL *asl, PBuf *B, cpxlp *cpx, dims *d, real *x, real *y) { CStype *cs; cde *Csave, *Osave; int bs, *bt, gmap, i1, k, *p, *q, *qinv, *rn; ograd **Ogsave; real *A, *A1, *Av, *L, *U, *b, *c, *r, t, tm, tn, tw; size_t Ls, i, j, je, m, m1, m2, n, n0, n1; ssize_t on; tm = n_conjac[1] = m = nlc; tn = n = n_var; t = (tn*(tm+2) + tm)*sizeof(real) + tn*(3*sizeof(int)) + tm*sizeof(int); Ls = (n*(m+2) + m)*sizeof(real) + n*(3*sizeof(int)) + m*sizeof(int); if (Ls != t) return; if ((tw = tn*tm*tm) > qcdmax) { if (solve_result_num == 0) solve_result_num = 5; Bpf(B, "\nComputing of dual variables for quadratic constraints suppressed since " "qcdmax = %.g < k*n*n = %.g\n(k = number of quadratic constraints = %d," " n = number of variables = %d).", qcdmax, tw, m, n); return; } A = (real*)Malloc(Ls); b = A + n*m; r = b + n; c = r + n; p = (int*)(c+m); q = p + n; qinv = q + n; bt = qinv + n; L = LUv; U = Uvx; for(i = n0 = n1 = 0; i < n; ++i) { if ((t = x[i]) > L[i] && t < U[i]) { qinv[i] = n1; q[n1++] = i; } else qinv[i] = -1; } if ((gmap = n1 < n)) { for(; n0 < n1 && q[n0] == n0; ++n0); } Csave = ((ASL_fg*)asl)->I.con_de_; Osave = ((ASL_fg*)asl)->I.obj_de_; ((ASL_fg*)asl)->I.con_de_ = d->consave; ((ASL_fg*)asl)->I.obj_de_ = d->objsave; qp_opify(); bs = 0; if ((on = obj_no) >= 0) { bs = objtype[on] ? -1 : 1; Ogsave = Ograd; Ograd = d->ogsave; objgrd(on, x, b, 0); Ograd = Ogsave; if (gmap) for(i = n0; i < n1; ++i) b[i] = b[q[i]]; } else memset(b, 0, n*sizeof(real)); if ((m2 = n_con - m)) { cs = A_colstarts; rn = A_rownos; Av = A_vals; for(i = 0; i < n; ++i) { if ((i1 = qinv[i]) >= 0) { j = cs[i]; t = b[i1]; for(je = cs[i+1]; j < je; ++j) { k = rn[j]; t -= y[k]*Av[j]; } b[i1] = t; } } for(i = m2; i-- > 0;) y[i+m] = y[i]; } conval(x, c, 0); A1 = A; L = LUrhs; U = Urhsx; if (qctol1 < 0.) qctol1 = 0.; for(i = m1 = 0; i < m; ++i) { t = c[i]; if (t <= L[i] + qctol1) { k = bs; if (t >= U[i] - qctol1) k = 0; } else if (t >= U[i] - qctol1) k = -bs; else { y[i] = 0.; continue; } congrd(i, x, A1, 0); if (gmap) { for(j = n0; j < n1; ++j) A1[j] = A1[q[j]]; } A1 += n1; p[m1] = i; bt[m1++] = k; } ((ASL_fg*)asl)->I.con_de_ = Csave; ((ASL_fg*)asl)->I.obj_de_ = Osave; if (m1) { if (qctol2 < 0.) qctol2 = 0.; if (qctol3 < 0.) qctol3 = 0.; LSsol(n1, m1, A, r, b, bt); for(i = 0; i < m1; ++i) y[p[i]] = r[i]; } free(A); } #endif /*CPXERR_QCP_SENSE }*/ #ifdef CPXPARAM_Benders_Strategy /*{*/ static void benders_sufcheck(ASL *asl, cpxlp *cpx) { CPXLONG *Z; SufDesc *b; int a, *ind, i, j, k, n, nm, ns, *z, zi; k = 0; CPXgetintparam(Env, CPXPARAM_Benders_Strategy, &k); if (k < 0 || k >= 3) return; b = suf_get("benders", ASL_Sufkind_var); if (!(z = b->u.i)) { if (k) { fprintf(Stderr, "Ignoring bendersopt because suffix benders is not present\n" "and benders_strategy = %d, which requires .benders.\n", k); Optimize = CPXmipopt; } return; } n = n_var; for(i = nm = ns = 0; i < n; ++i) { if (z[i]) ++ns; else ++nm; } if (!nm || !ns) { fprintf(Stderr, "Ignoring .benders because %s variables have .benders = 0.\n", nm ? "all" : "no"); if (k) Optimize = CPXmipopt; return; } if ((j = CPXnewlongannotation(Env, cpx, CPX_BENDERS_ANNOTATION, 0))) fprintf(Stderr, "\n*** CPXnewlongannotation() returned %d\n", j); a = 0; j = CPXgetlongannotationindex(Env, cpx, CPX_BENDERS_ANNOTATION, &a); if (j) { fprintf(Stderr, "\n*** CPXgetlongannotationindex(CPX_BENDERS_ANNOTATION) returned %d\n", j); return; } Z = (CPXLONG*)Malloc(ns*(sizeof(int) + sizeof(CPXLONG))); ind = (int*)(Z + ns); for(i = j = 0; i < n; ++i) { if ((zi = z[i]) > 0) { ind[j] = i; Z[j++] = zi; } } j = CPXsetlongannotations(Env, cpx, a, CPX_ANNOTATIONDATA_LONG, ns, ind, Z); if (j) fprintf(Stderr, "\n*** CPXsetlongannotations returned %d\n", j); free(Z); } #endif /*}*/ #ifdef Uselazy typedef struct LazyInfo { CStype nz[2], *rowbeg[2]; char *sense[2], **rowname[2]; int *colno[2], rows[2]; double *matval[2], *rhs[2]; } LazyInfo; void ** lazyadj(ASL *asl, LazyInfo *LI, int n, int nint, int nqc, int *mp, double *b, char *senx, CStype *ka, int *kal, int *ia, double *a, double *rngvec, char **rname) { CStype i, i2, j, j0, j1, k, m, m0, nq, nrt, nz; CStype *rowbeg; SufDesc *lp; char *nn, *nn1, *sense, **rowname; const char *s1, *s2; double *matval, *rhs; int *colno, i1, nr[3], nt[2], *rl, *z, *z0; size_t Lnn, Lrl; void *rv; nr[0] = nr[1] = nr[2] = 0; rv = 0; if (!(uselazy & 3) || !nint) goto done; lp = suf_get("lazy", ASL_Sufkind_con); if (!(z = lp->u.i)) goto done; /* Expect .lazy values, i.e., values in z, to be 0, 1, or 2 */ /* with 1 ==> lazy constraint, 2 ==> user cut. */ /* For simplicity, we treat 3 as 1 and ignore bits beyond the first two. */ m0 = n_con; for(i = nq = 0; i < m0; i++) { if ((j = z[i] & uselazy) && j <= 2) { if (i < nqc) { ++nq; continue; } ++nr[j = 1 - (j&1)]; if (senx[i] == 'R') { ++nr[j]; ++nr[2]; } } } if (nq) { if (nq == 1) s1 = s2 = ""; else { s1 = "es"; s2 = "s"; } fprintf(Stderr, "Ignoring .lazy suffix%s on %d quadratic constraint%s.\n", s1, nq, s2); } /* nr[0] = number of lazy constraints */ /* nr[1] = number of user cuts */ /* nr[2] = number of range constraints among above */ if (!(nrt = nr[0] + nr[1])) goto done; z0 = z += nqc; m = *mp; if (m > m0) { z = (int*)Malloc(m*sizeof(int)); memcpy(z, z0, m0*sizeof(int)); memset(&z[m0], 0, (m-m0)*sizeof(int)); } *mp = m - (nrt - nr[2]); nt[1] = 0; nt[0] = nr[0]; /* nt[0] = for user cuts, nt[1] for lazy constraints */ if (nr[2]) for(i = 0; i < m; i++) { if ((j = (z[i]&3))) { z[i] = ++nt[j &= 1]; if (senx[i] == 'R') ++nt[j]; } else z[i] = 0; } else for(i = 0; i < m; i++) z[i] = (j = (z[i]&3)) ? ++nt[j&1] : 0; for(i = nz = 0; i < n; i++) { for(j = ka[i], k = j + kal[i]; j < k; j++) if (z[ia[j]]) nz++; } Lnn = Lrl = 0; if (rname) Lnn = nrt*sizeof(char*); if (nr[2]) { /* ranges */ Lrl = nrt; for(i = 0; i < n; i++) { for(j = ka[i], k = j + kal[i]; j < k; j++) if (z[j1 = ia[j]] && senx[j1] == 'R') nz++; } if (rname) for(i = 0; i < m; i++) if (senx[i] == 'R') Lnn += strlen(rname[i]) + 3; } matval = (double*)Malloc((nz+nrt)*sizeof(double) + nz*sizeof(int) + (nrt+2)*sizeof(CStype) + Lrl*sizeof(int) + nrt + Lnn); rv = (void*)matval; rhs = matval + nz; if (rname) { rowname = (char**)(rhs + nrt); rowbeg = (CStype*)(rowname + nrt); } else { rowname = 0; rowbeg = (CStype*)(rhs + nrt); } colno = (int*)(rowbeg + nrt + 2); rl = colno + nz; sense = (char*)(rl + Lrl); nn = sense + nrt; memset(rowbeg, 0, nrt*sizeof(CStype)); if (Lrl) memset(rl, 0, Lrl*sizeof(int)); for(i = 0; i < n; i++) { for(j = ka[i], k = j + kal[i]; j < k; j++) if ((j1 = z[ia[j]])) ++rowbeg[j1-1]; } if (nr[2]) { for(i = 0; i < m; i++) if ((j = z[i]) && senx[i] == 'R') rl[j] = rowbeg[j] = rowbeg[j-1]; } for(i = k = 0; i < nrt; i++) { j = rowbeg[i]; rowbeg[i] = k; k += j; } for(i = k = 0; i < m; i++) if (!z[i]) z[i] = k--; for(i = j1 = 0; i < n; i++) { j = ka[i]; ka[i] = j0 = j1; for(k = j + kal[i]; j < k; j++) if ((i1 = z[ia[j]]) > 0) { i2 = rowbeg[i1-1]++; colno[i2] = i; matval[i2] = a[j]; } else { ia[j1] = -i1; a[j1++] = a[j]; } kal[i] = j1 - j0; } if (nr[2]) { for(i = 0; i < nrt; i++) if ((j = rl[i])) { k = rowbeg[i]; rowbeg[i] = k + j; memcpy(colno + k, colno - j + k, j*sizeof(int)); memcpy(matval + k, matval - j + k, j*sizeof(double)); } } for(i = k = 0; i < nr[0]; i++) { j = rowbeg[i]; rowbeg[i] = k; k = j; } LI->nz[0] = k; LI->nz[1] = nz - k; for(j1 = 0; i < nrt; i++) { j = rowbeg[i]; rowbeg[i] = j1; j1 = j - k; } rowbeg[i+1] = j1; for(; i > nr[0]; --i) rowbeg[i] = rowbeg[i-1]; rowbeg[i] = k; LI->sense[0] = sense; LI->sense[1] = sense + nr[0]; for(i = 0; i < m; i++) { if ((i1 = z[i]) > 0) { rhs[--i1] = b[i]; if ((sense[i1] = senx[i]) == 'R') { sense[i1] = 'G'; sense[++i1] = 'L'; rhs[i1] = b[i] + rngvec[i]; if (rname) { nn1 = strcpy1(rowname[i1] = nn, rname[i]); nn = strcpy(nn1, ".u"); } } } else { b[i1 = -i1] = b[i]; rngvec[i1] = rngvec[i]; senx[i1] = senx[i]; } } if (rname) { LI->rowname[0] = rowname; LI->rowname[1] = rowname + nr[0]; for(i = 0; i < m; i++) if ((i1 = z[i]) > 0) rowname[i1-1] = rname[i]; else rname[-i1] = rname[i]; } else LI->rowname[0] = LI->rowname[1] = 0; LI->colno[0] = colno; LI->colno[1] = colno + k; LI->rowbeg[0] = rowbeg; LI->rowbeg[1] = rowbeg + nr[0] + 1; LI->matval[0] = matval; LI->matval[1] = matval + k; LI->rhs[0] = rhs; LI->rhs[1] = rhs + nr[0]; if (z != z0) free(z); done: LI->rows[0] = nr[0]; LI->rows[1] = nr[1]; return M1record(rv); } #endif /*Uselazy*/ static void amplin(ASL *asl, cpxlp **pcpx, FILE **nl, dims *d, int *nelqp, int *nintp, char **av) { CStype *ka, *ka1, *ka2, nz, nz1, nzc0, nzr; int *ia, *ia1, *ia2, *ja, *kal, *kal1, *kal2, *vmi; double *a, *a1, *b, *b1, *c, *c1, *l, *l1, *le, *lrhs, *lx, *rngvec, *rv1, *u, *u1, *urhs, *ux; double nos, os; ograd *og, *og1, **ogp; int i, j, j0, k, k0, m, m0, mq, n, n0, nbv1, nextra, nint, nint1, no, nqc, nr, nsos, nzextra; char **cname, **rname, *s, *senx; void **zap[5]; size_t L, nelqf; #ifdef BARRIER CPXNNZ *colq; int *colno, *colqcnt; int havestart, *rowq; size_t *colqf; ssize_t nq; double *cdual, *cprim, *qmat, *rdual, *rprim; #undef Want_mqpcheck #ifdef BARRIER_FOR_QP #ifdef BARRIER #define Want_mqpcheck #endif #else /*!BARRIER_FOR_QP, i.e., >= 8.0*/ #define Want_mqpcheck #endif #ifdef Want_mqpcheck QPinfo *qpi; void *v; #else #undef CPXERR_QCP_SENSE #endif #ifdef CPXERR_QCP_SENSE /* CPLEX version >= 9.0 */ CPXNNZ *nelqc; double *aq, **qcmat; int **colqc, *iaq, *kaq, *kalq, **rowqc; #endif /*CPXERR_QCP_SENSE*/ #endif /*BARRIER*/ char probname[48]; cpxlp *cpx; #ifdef CPLEX_MIP /*{*/ char *ctype; char *sostype; int nsosnz, *sosbeg, *sosind; double *sosref; #ifdef CPX_PARAM_IISIND /* version < 9.2b */ int copri[2], **p_sospri, *sospri; #else #define copri 0 #define p_sospri 0 #endif #endif /*}*/ #ifdef CPX_CON_INDICATOR int errinfo[2], nlogc; #else #define nlogc 0 #endif /*CPX_CON_INDICATOR*/ #ifdef Uselazy LazyInfo LI; #endif /*Uselazy*/ static int repmap[4] = { 0, ASL_obj_replace_ineq, ASL_obj_replace_eq, ASL_obj_replace_ineq | ASL_obj_replace_eq }; /* change default display to 0 */ CPXsetintparam(Env, CPX_PARAM_SIMDISPLAY, 0); #ifdef CPLEX_MIP /* change default mipdisplay to 0 */ CPXsetintparam(Env, CPX_PARAM_MIPDISPLAY, 0); #endif #ifdef BARRIER /* change default bardisplay to 0 */ CPXsetintparam(Env, CPX_PARAM_BARDISPLAY, 0); #endif aggtries = 0; if (!(mint_val[set_objno].U = no = n_obj)) objno = 0; nqc = nlc; #ifndef CPXERR_QCP_SENSE /* if CPLEX version >= 9.0 */ nonlin(nqc, 550, "nonlinear constraints"); #endif nonlin(plterms, 554, "piecewise-linear terms"); nonlin(n_cc, 567, "complementarity constraints"); if (getopts(av, &Oinfo)) { if (amplflag) badretfmt(560, "Error in $cplex_options."); exit(1); } obj_no = objno - 1; #if CPX_VERSION >= 12050000 if (time_flag & 0x30) CPXgetnumcores(Env, &num_cores); #endif #ifndef CPX_PARAM_FEASOPTMODE /* < 9.2b */ if (want_iis #ifdef CPXERR_QCP_SENSE /* if CPLEX version >= 9.0 */ && !nqc #endif ) { multiobj = 0; if (want_iis == 3) want_iis = 2; /* The IIS finder requires use of primal or dual simplex. */ if (Optimize && Optimize != CPXprimopt #ifdef CPXERR_QCP_SENSE /* if CPLEX version >= 9.0 */ && Optimize != CPXdualopt #endif ) { printf("Assuming primalopt so iisfind will work.\n"); Optimize = CPXprimopt; algname = baralgname = ""; } } #endif /*CPX_PARAM_FEASOPTMODE*/ #ifndef NO_MOkwf /*{*/ if (no > 1 && multiobj && obj_no >= 0 && !Optimize) { Optimize = Optimizemo; method = 1; use_netopt = 0; algname = baralgname = ""; } else #endif /*}*/ if (!Optimize || nqc) { /* check nqc in case baropt was specified */ /* with CPLEX 12.2, at least, we cannot use */ /* CPXhybbaropt on problems with quadratic constraints. */ Optimize = CPXlpopt; if (!lpoptalg) lpoptalg = CPX_ALG_AUTOMATIC; #ifdef CPXERR_QCP_SENSE if (nqc | nlo) { Optimize = CPXqpopt; lpoptalg = CPX_ALG_AUTOMATIC; } #endif algname = baralgname = ""; } m = n_con + 1; /* allow elbow room for obj_adj */ n = n_var + 1; nzr = nzc + 1; #ifdef CPX_CON_INDICATOR /* >= 9.2b */ nlogc = 2*n_lcon; #endif d->cstat = (int*)M1zapalloc((m+n+2+nlogc)*sizeof(int)); d->rstat = d->cstat + n + 1; d->csd = suf_iput("sstatus", ASL_Sufkind_var, d->cstat); d->rsd = suf_iput("sstatus", ASL_Sufkind_con, d->rstat); b = LUrhs = (double *)M1alloc(2*sizeof(double)*(m+n)); Urhsx = b + m; LUv = Urhsx + m; Uvx = LUv + n; L = nzr*(sizeof(double) + sizeof(int)) + (n+1)*sizeof(CStype); a = A_vals = (double *)Malloc(L); zap[0] = M1record(a); zap[1] = zap[2] = zap[3] = zap[4] = 0; ka = A_colstarts = (CStype*)(a + nzr); ia = A_rownos = (int*)(ka + n + 1); nelqf = 0; #ifdef Want_mqpcheck /*{{*/ v = 0; nint = nbv + niv + nlvbi + nlvci + nlvoi; if (Optimize == Optimize2 || Optimize == Optimizebar || nlo || nqc || (nint && mipstval)) want_xpi0 = 3; qp_read(*nl, ALLOW_CLP | repmap[objrep] ForceZ); nqc = nlc; /* may have been adjusted */ *nl = 0; /* Indicate closed file -- in case we're */ /* subsequently interrupted. */ if (obj_no >= 0 && obj_no < no) { if (nqc) { og = og1 = Ograd[obj_no]; for(i = 0; og; og = og->next) ++i; d->ogsave = (ograd**)M1alloc( no*(sizeof(ograd*) + sizeof(cde)) + i*sizeof(ograd)); memcpy(d->ogsave, Ograd, no*sizeof(ograd*)); d->objsave = (cde*)(d->ogsave + no); memcpy(d->objsave, ((ASL_fg*)asl)->I.obj_de_, no*sizeof(cde)); ogp = &d->ogsave[obj_no]; og = (ograd*)(d->objsave + no); while(og1) { og->varno = og1->varno; og->coef = og1->coef; *ogp = og; ogp = &og->next; og1 = og1->next; ++og; } *ogp = 0; } if (nlo && (nelqf = nq = mqpcheckv(obj_no, &qpi, &v))) { if (nq < 0) { nonlin(nq == -2, 555, "a quadratic objective involving division by 0"); nonlin(1, 551, "a nonlinear objective"); } #ifdef BARRIER_FOR_QP nonlin(nint, 553, "integer variables and a quadratic objective"); #endif crossover = 0; #ifndef BARRIER_FOR_QP #ifdef REQCONVEX if (nint) { i = 0; CPXgetintparam(Env, REQCONVEX, &i); if (i == 2) { printf("Changing reqconvex from 2 to 3 for a " "QP with integer variables.\n"); CPXsetintparam(Env, REQCONVEX, 3); } } #endif if (Optimize == Optimize2) #endif set_baropt(); method = 1; } } #ifdef BARRIER_FOR_QP else nonlin(nlvoi, 552, "nonlinear integer variables"); #endif if (mipbasis == -1) mipbasis = endbas ? 1 : nlc ? want_qcdual : nlo ? 0 : 1; #ifdef CPXERR_QCP_SENSE /* if CPLEX version >= 9.0 */ iaq = kaq = kalq = 0; /* silence buggy warning */ nelqc = 0; /* ditto */ colqc = rowqc = 0; /* ditto */ aq = 0; /* ditto */ qcmat = 0; /* ditto */ if (nqc > 0) zap[0] = linadj(asl, ka, ia, a, &kaq, &kalq, &iaq, &aq, &nelqc, &rowqc, &colqc, &qcmat, d, &v); #endif /*CPXERR_QCP_SENSE*/ #else /*}{Want_mqpcheck*/ nonlin(nlvoi, 552, "nonlinear integer variables"); f_read(*nl, 0 ForceZ); *nl = 0; #endif/*}}Want_mqpcheck*/ nsos = 0; #ifdef CPLEX_MIP ctype = 0; /* silence buggy warning */ if (!relax) { #ifdef CPX_PARAM_IISIND /* version < 9.2b */ copri[0] = objpri; copri[1] = conpri; p_sospri = &sospri; #endif i = ASL_suf_sos_explict_free; if (!sos) i |= ASL_suf_sos_ignore_sosno; if (!sos2) i |= ASL_suf_sos_ignore_amplsos; nsos = suf_sos(i, &nsosnz, &sostype, p_sospri, copri, &sosbeg, &sosind, &sosref); } #endif m = m0 = n_con; n = n0 = nr = n_var; nzc0 = nzc; nint = nbv + niv + nlvoi + nlvci + nlvbi; if (nint #ifdef CPLEX_MIP && relax #endif ) { if (nint) { printf("Ignoring integrality of %d variable%s.\n", nint, nint > 1 ? "s" : ""); need_nl = nint = 0; } } *nelqp = nelqf; *nintp = nint1 = nint + nsos; if (use_netopt == 1 && !lnc) use_netopt = 0; if (nint1 || m <= 0 || nqc > 0) { method = 1; use_netopt = 0; } else if (!method) method = use_netopt ? 1 : (dual_thresh > 0 && m - n > dual_thresh) || m > dual_ratio*n ? -1 : 1; nbv1 = nbv; if (method < 0 && use_netopt == 1) use_netopt = 0; if (!nint) niv = nbv = nbv1 = 0; og = 0; vmi = 0; if (obj_no >= 0 && obj_no < no) { og = Ograd[obj_no]; if (asl->i.vmap) vmi = get_vminv_ASL(asl); if (!objsen) objsen = objtype[obj_no] ? -1 : 1; obj_adj = objconst(obj_no); } else if (!objsen) objsen = 1; #ifndef BARRIER nonlin(nl_obj(obj_no), 556, "nonlinear objective terms"); #endif *stub_end = 0; for(i = 0, og1 = og; og1; i++) og1 = og1->next; sprintf(probname, "c%dv%di%do%d", n_var, n_con, niv, i); if (!(cpx = CPXcreateprob(Env, &i, probname))) badret("CPXcreateprob", i, 531); *pcpx = cpx; n = n0; m = m0; nextra = nzextra = 0; if (method < 0) { /* solve dual */ l = LUv; u = Uvx; for(le = l + n0; l < le; l++, u++) { if (*l > negInfinity && *l) nextra++; if (*u < Infinity && *u) nextra++; } if (nranges) { ja = (int *)Malloc(m0*sizeof(int)); memset((char *)ja, 0, m0*sizeof(int)); ia1 = ia + nzc0; while(ia1 > ia) ja[*--ia1]++; l = LUrhs; u = Urhsx; for(le = l + m0; l < le; l++, u++) if (*l < *u && *l > negInfinity && *u < Infinity) nzextra += ja[l - LUrhs]; free(ja); } m = n0; n = m0 + nranges + nextra; } #ifdef OBJ_ADJ if (obj_adj || m <= 0) { objadj = 1; n++; nextra++; } #endif nz = nzc0 + nextra; if (method < 0) /* dual */ { nz1 = nz += nzextra; a = (double *)Malloc((nz1+2*n+m)*sizeof(double) + nz1*sizeof(int) + (n+1)*sizeof(CStype)); *zap[0] = a; l = a + nz1; u = l + n; b = u + n; ka = (CStype*)(b + m); ia = (int *)(ka + n + 1); nr = n; } else { m += objadj; nr += objadj; nz1 = nz; l = LUv; u = Uvx; if (nint1) { #ifdef CPLEX_MIP ctype = M1alloc(nr); if ((i = n - nbv1 - niv - nextra)) memset(ctype, 'C', i); if (nbv1) memset(ctype+i, 'B', nbv1); if (niv) memset(ctype+i+nbv1, 'I', niv); if (nextra) memset(ctype+i+nbv1+niv, 'C', nextra); #ifndef BARRIER_FOR_QP if (nlvbi) for(j = nlvb, i = j - nlvbi; i < j; i++) ctype[i] = l[i] == 0. && u[i] == 1. ? 'B' : 'I'; if (nlvci) for(j = nlvc, i = j - nlvci; i < j; i++) ctype[i] = l[i] == 0. && u[i] == 1. ? 'B' : 'I'; if (nlvoi) for(j = nlvo, i = j - nlvoi; i < j; i++) ctype[i] = l[i] == 0. && u[i] == 1. ? 'B' : 'I'; #endif #else badretfmt(557, "CPLEX's MIP option is needed to solve problems with\n%s.\n", "nonconvex (nonconcave) piecewise-linear terms"); exit(1); #endif } } d->x = (double *)M1zapalloc((m+nlogc+2L*nr)*sizeof(double) + m); d->y = d->x + nr; d->c = c = d->y + m + nlogc; d->rtype = senx = (char*)(c + nr); rngvec = (double *)Malloc(m*sizeof(double) + nr*sizeof(int)); zap[1] = M1record((void*)rngvec); kal = (int *)(rngvec + m); #ifdef CPLEX_MIP #ifdef CPXPARAM_Benders_Strategy if (Optimize == CPXbendersopt) { baralgname = ""; if (nint <= 0 || nint >= n0) { fprintf(Stderr, "Ignoring bendersopt since all variables are %s.", nint <= 0 ? "continuous" : "integer"); if (nint1) Optimize = CPXmipopt; else { Optimize = CPXlpopt; if (!lpoptalg) lpoptalg = CPX_ALG_AUTOMATIC; } } } else #endif #ifndef NO_MOkwf if (Optimize == Optimizemo) MOcheck(asl); else #endif if (nint1) { Optimize = CPXmipopt; baralgname = ""; } #endif if (method > 0) { b = (double*)Malloc(m*sizeof(double)); zap[2] = M1record((void*)b); } b1 = b + m; s = senx + m; rv1 = rngvec + m; ia1 = ia + nz; a1 = a + nz; l1 = l + n; u1 = u + n; kal1 = kal + n; ka1 = ka + n; lrhs = LUrhs + m0; urhs = Urhsx + m0; if (method < 0) { /* dual */ os = objsen; nos = -os; objsen = -objsen; memset(b, 0, m*sizeof(double)); c1 = c + (m0 + nranges + nextra); #ifdef OBJ_ADJ if (objadj) { *--l1 = *--u1 = 1; *--kal1 = 0; *--ka1 = nz1; *--c1 = obj_adj; } #endif j = n0; lx = LUv + n0; ux = Uvx + n0; do { *--rv1 = 0; *--s = 'E'; --j; if (*--ux < Infinity) { if (*ux) { *--kal1 = 1; *--ka1 = --nz1; *--ia1 = j; *--a1 = -1; *--c1 = nos * *ux; *--l1 = 0; *--u1 = Infinity; } else *s = 'G'; } if (*--lx > negInfinity) { if (*lx) { *--kal1 = 1; *--ka1 = --nz1; *--ia1 = j; *--a1 = 1; *--c1 = os * *lx; *--l1 = 0; *--u1 = Infinity; } else *s = 'L'; } } while(lx > LUv); if (vmi) for(; og; og = og->next) b[vmi[og->varno]] = os * og->coef; else for(; og; og = og->next) b[og->varno] = os * og->coef; memset((char *)kal, 0, m0*sizeof(int)); ia1 = A_rownos; ia2 = ia1 + nzc0; while(ia1 < ia2) kal[*ia1++]++; for(i = j = 0; i < m0; i++) ka[i] = j += kal[i]; a1 = A_vals + nzc0; j = n0; while(--j >= 0) { ia1 = A_rownos + A_colstarts[j]; while(ia2 > ia1) { ia[i = --ka[*--ia2]] = j; a[i] = *--a1; } } if (nranges) { /* This could be merged with the following while * loop but for cplex's undocumented assumption * that elements of ka are in ascending order! */ kal2 = kal + m0; ka2 = ka + m0; for(i = m0; --i >= 0; ) { --ka2; --kal2; if (*--lrhs < *--urhs && *lrhs > negInfinity && *urhs < Infinity) { *--kal1 = j = *kal2; *--ka1 = nz1 -= j; memcpy((char *)(a+nz1), (char *)(a+*ka2), j*sizeof(double)); memcpy((char *)(ia+nz1), (char *)(ia+*ka2), j*sizeof(int)); *--c1 = os * *urhs; *--l1 = negInfinity; *--u1 = 0; } } lrhs = LUrhs + m0; urhs = Urhsx + m0; } i = m0; while(--i >= 0) { --c1; --l1; --u1; --urhs; if (*--lrhs <= negInfinity) { *c1 = os * *urhs; *l1 = negInfinity; *u1 = 0.; } else { *u1 = Infinity; *c1 = os * *lrhs; *l1 = *urhs == *lrhs ? negInfinity : 0.; } } free(A_vals); } else { /* primal */ memset(c, 0, n0*sizeof(double)); #ifdef OBJ_ADJ if (objadj) { c[n0] = obj_adj; /* fixed adjustment to objective */ *--l1 = 0; *--u1 = 2; *--ia1 = m0-nqc; *--a1 = *--b1 = 1; *--kal1 = 1; *--ka1 = --nz1; *--s = 'E'; *--rv1 = 0; } #endif if (vmi) for(; og; og = og->next) c[vmi[og->varno]] = og->coef; else for(; og; og = og->next) c[og->varno] = og->coef; i = m0; while(--i >= 0) { --b1; *--rv1 = 0; --s; --urhs; if ((*b1 = *--lrhs) <= negInfinity) { *s = 'L'; *b1 = *urhs; } else if (*urhs >= Infinity) *s = 'G'; else if (*lrhs < *urhs) { *s = 'R'; *rv1 = *urhs - *lrhs; } else *s = 'E'; } ka2 = ka + n0; *ka2 = nz1; while(ka2 > ka) { --ka2; *--kal1 = ka2[1] - ka2[0]; } } mbas = m; nbas = n; cname = rname = 0; if (startbas || endbas || startsol || endsol || wrtfname || startvec || endvec || Optimize == CPXprimopt || Optimize == CPXdualopt || Optimize == CPXlpopt || Optimize == CPXqpopt #ifdef CPX_PARAM_XXXIND || parval(CPX_PARAM_XXXIND) #endif ) { make_names(&cname, &rname); zap[3] = M1record((void*)cname); } mq = m - nqc; #ifdef Uselazy i = mq; zap[4] = lazyadj(asl, &LI, n, nint, nqc, &mq, b+nqc, senx+nqc, ka, kal, ia, a, rngvec+nqc, rname ? rname+nqc : 0); if ((j = LI.rows[0] + LI.rows[1] - (i - mq)) > 0) { /* unlikely; allocate extra space... */ j += n_con + mq + nqc + nlogc; d->y = (double*)M1zapalloc(j*(sizeof(double) + sizeof(int))); ia1 = (int*)(d->y + j); memcpy(ia1, d->rstat, n_con * sizeof(int)); d->rsd->u.i = d->rstat = ia1; } #endif /*Uselazy*/ i = CPXcopylpwnames(Env, cpx, n, mq, objsen, c, b+nqc, senx+nqc, ka, kal, ia, a, l, u, rngvec+nqc, cname, rname ? rname+nqc : 0); if (i) badret("CPXcopylpwnames", i, 531); #if CPX_VERSION >= 12060200 if (obj_adj && (i = CPXchgobjoffset(Env, cpx, obj_adj))) badret("CPXchgobjoffset", i, 531); #endif #ifdef CPXERR_QCP_SENSE /* if CPLEX version >= 9.0 */ lrhs = LUrhs; urhs = Urhsx; for(i = 0; i < nqc; i++) { j = CPXXaddqconstr(Env, cpx, kalq[i], nelqc[i], b[i], senx[i], iaq+kaq[i], aq+kaq[i], rowqc[i], colqc[i], qcmat[i], rname ? rname[i] : 0); if (j) Surprise(asl, j, "CPXaddqconstr"); } mbas += nqc; #endif /*CPXERR_QCP_SENSE*/ #ifdef CPLEX_MIP if (nint1) { if ((i = CPXcopyctype(Env, cpx, ctype))) badret("CPXcopyctype", i, 531); if (nsos) { sos_kludge(nsos, sosbeg, sosref); #ifdef CPX_PARAM_IISIND /* version < 9.2b */ i = CPXcopysos(Env,cpx,nsos,nsosnz,sostype,sospri, sosbeg,sosind,sosref); #else i = CPXcopysos(Env,cpx,nsos,nsosnz,sostype, sosbeg,sosind,sosref,0); #endif free(sosref); if (i) badret("CPXcopysos", i, 531); } if (nint) { mip_priorities(asl, cpx); if (mipstval && X0 && (i = nbv1 + niv + nlvbi + nlvci + nlvoi)) set_mipinit(asl, cpx, i); } if (workfiledir) CPXsetstrparam(Env, CPX_PARAM_WORKDIR, workfiledir); #ifdef CPXPARAM_Benders_Strategy if (Optimize == CPXbendersopt) benders_sufcheck(asl, cpx); #endif } #endif #ifdef Uselazy if (LI.rows[0]) { CPXgetintparam(Env, CPX_PARAM_REDUCE, &i); if (i & ~1) { i &= 1; fprintf(Stderr, "Assuming prereduce = %d for lazy constraints.\n", i); if ((j = CPXsetintparam(Env, CPX_PARAM_REDUCE, i))) badret("CPXsetintparam(CPX_PARAM_REDUCE)", j, 531); } if ((i = CPXaddlazyconstraints(Env, cpx, LI.rows[0], LI.nz[0], LI.rhs[0], LI.sense[0], LI.rowbeg[0], LI.colno[0], LI.matval[0], LI.rowname[0]))) badret("CPXaddlazyconstraints", i, 531); } if (LI.rows[1]) { CPXgetintparam(Env, CPX_PARAM_PRELINEAR, &i); if (i) { fprintf(Stderr, "Assuming prelinear = 0 for user cuts.\n"); if ((j = CPXsetintparam(Env, CPX_PARAM_PRELINEAR, 0))) badret("CPXsetintparam(CPX_PARAM_PRELINEAR)", j, 531); } if ((i = CPXaddusercuts(Env, cpx, LI.rows[1], LI.nz[1], LI.rhs[1], LI.sense[1], LI.rowbeg[1], LI.colno[1], LI.matval[1], LI.rowname[1]))) badret("CPXaddusercuts", i, 531); } #endif #ifdef BARRIER havestart = 0; if (Optimize == Optimize2 || Optimize == Optimizebar) havestart = startcomp(asl, n, m, nextra, ka, kal, ia, a, b, c, &cdual, &cprim, &rdual, &rprim); #endif if (nelqf) { colq = (CPXNNZ*)Malloc(L = (sizeof(int)+sizeof(CPXNNZ))*nr); colqcnt = (int*)(colq + nr); rowq = qpi->rowno; colqf = qpi->colbeg; qmat = qpi->delsq; colno = qpi->colno; k = qpi->nc; for(i = j0 = k0 = 0; i < k; i++) { j = colno[i]; while(j0 < j) { colqcnt[j0] = 0; colq[j0++] = k0; } colq[j] = colqf[i]; colqcnt[j] = (int)((k0 = colqf[i+1]) - colqf[i]); j0 = j + 1; } while(j0 < nr) { colqcnt[j0] = 0; colq[j0++] = k0; } k = n_var; for(i = 0; ; i++) { if (i == k) { i = qmatadj(k, nr, objsen, colq, colqcnt, &qmat, ctype); if (!i) { for(i = k; i < nr; i++) qmat[i++] = 0.; i = CPXcopyqpsep(Env,cpx,qmat); if (i) badret("CPXcopyqpsep",i,531); } free(qpi); if (i) exit(1); baralgname = "separable QP "; break; } if (!(j = colqcnt[i])) continue; if (j > 1 || rowq[colq[i]] != i) { i = CPXXcopyquad(Env,cpx,colq,colqcnt,rowq,qmat); free(qpi); if (i) badret("CPXcopyquad", i, 531); baralgname = "QP "; break; } } } if (v) mqpcheckv_free(&v); #ifdef CPX_CON_INDICATOR if (nlogc && (i = indicator_constrs_ASL(asl, cpx, add_indic, errinfo))) { switch(i) { case 1: badretfmt(563,"logical constraint %s is not an indicator constraint.\n", lcon_name(errinfo[0])); break; case 2: badretfmt(563,"logical constraint %s is not an indicator constraint\n\ due to bad comparison with %s.\n", lcon_name(errinfo[0]), var_name(errinfo[1])); break; case 3: badret("CPXaddindconstr", i, 531); break; default: badret("indicator_constrs_ASL", i, 531); } exit(4); } #endif /*CPX_CON_INDICATOR*/ #ifdef BARRIER if (havestart) { if ((i = CPXcopystart(Env,cpx,0,0,cprim,rprim,cdual,rdual))) badret("CPXcopystart", i, 0); } #endif for(i = 5; i > 0; ) if (zap[--i]) { free(*zap[i]); *zap[i] = 0; } get_statuses(asl, cpx, d); cbi.disp = parval(CPX_PARAM_SIMDISPLAY); #ifdef CPLEX_MIP cbi.mipdisp = nint && parval(CPX_PARAM_MIPDISPLAY); #endif if (prestats #ifndef NO_BARRIER || Optimize == Optimize2 #endif ) { zap_lpcbf = 1; cbi.nint = nint; cbi.pres = parval(CPX_PARAM_PREIND); CPXsetlpcallbackfunc(Env, lpcbf, 0); #ifndef NO_BARRIER if (Optimize != Optimize2) #endif { zap_lpcbf = 2; CPXsetmipcallbackfunc(Env, lpcbf, 0); } } breaking = 1; #if CPX_VERSION >= 1100 if (droptol > 0.) CPXcleanup(Env, cpx, droptol); #endif } /* The following routine was named "round", but HPUX 11 reportedly */ /* could not cope with this name. */ static int xround(double *x, fint n, int assign, double *w) { double d, dx, *xe, y; int m = 0; dx = *w; for(xe = x + n; x < xe; x++) { y = floor(*x + 0.5); if ((d = *x - y) != 0.) { if (d < 0) d = -d; if (dx < d) dx = d; m++; if (assign) *x = y; } } *w = dx; return m; } static char * failstat(int j) { static char buf[32]; switch(j) { /* cases and text provided by Ed Klotz */ case CPXERR_NO_MEMORY: return "insufficient memory"; case CPXERR_NO_PROBLEM: return "no problem"; case CPXERR_SINGULAR: return "singular basis"; case CPXERR_PRIIND: return "invalid pricing setting"; #ifdef CPXERR_BOUNDS_INFEAS case CPXERR_BOUNDS_INFEAS: return "contradictory bounds"; #endif case CPXERR_PRESLV_INForUNBD: return "presolve: infeasible or unbounded problem"; case CPXERR_INDEX_RANGE: return "illegal list length"; #ifdef CPXERR_NET_IMBALANCE case CPXERR_NET_IMBALANCE: return "an infeasible or unbounded network"; #endif case CPXERR_BAD_METHOD: return "unknown method after network optimization"; #ifdef CPXERR_PRESLV_TIME_LIM /* CPLEX 11 */ case CPXERR_PRESLV_TIME_LIM: return "time limit exceeded in CPLEX's presolve"; case CPXERR_THREAD_FAILED: return "thread creation failed"; #endif } sprintf(buf, "CPLEX error # %d.", j); return buf; } static int statadjust(cpxlp *cpx, int stat) { #ifdef CPX_STAT_OPTIMAL /* >= 8.0 {{*/ static int statmap[23] = { 1, 3, 2, 31, 11, 9, -1, -1, -1, 5, 7, 4, 12, 57, 58, 59, 60, 61, 62, 24, 22, 23, 31 }; int adj, dfeas, pfeas, solmeth, soltype; if (stat >= 101 && stat <= 119) return stat + (36 - 101); if (stat > 15 || stat <= 0) { #ifndef CPXERR_ALGNOTLICENSED #define CPXERR_ALGNOTLICENSED 32024 #endif switch(stat) { case CPXERR_ALGNOTLICENSED: return (obj_no >= 0 && obj_no < nlo) || nlc ? 34 : 32; #ifdef CPXMIP_POPULATESOL_LIM case CPXMIP_POPULATESOL_LIM: case CPXMIP_OPTIMAL_POPULATED: case CPXMIP_OPTIMAL_POPULATED_TOL: stat = 36; break; #endif #ifdef CPX_STAT_FIRSTORDER case CPX_STAT_FIRSTORDER: stat = 35; break; #endif case CPXMIP_DETTIME_LIM_FEAS: stat = 63; break; case CPXMIP_DETTIME_LIM_INFEAS: stat = 64; break; #ifdef CPX_PARAM_FEASOPTMODE /* >= 9.2b {*/ case CPX_STAT_FEASIBLE_RELAXED_SUM: stat = 65; break; case CPX_STAT_OPTIMAL_RELAXED_SUM: stat = 66; break; case CPX_STAT_FEASIBLE_RELAXED_INF: stat = 67; break; case CPX_STAT_OPTIMAL_RELAXED_INF: stat = 68; break; case CPX_STAT_FEASIBLE_RELAXED_QUAD: stat = 69; break; case CPX_STAT_OPTIMAL_RELAXED_QUAD: stat = 70; break; case CPXMIP_FEASIBLE_RELAXED_SUM: stat = 71; break; case CPXMIP_OPTIMAL_RELAXED_SUM: stat = 72; break; case CPXMIP_FEASIBLE_RELAXED_INF: stat = 73; break; case CPXMIP_OPTIMAL_RELAXED_INF: stat = 74; break; case CPXMIP_FEASIBLE_RELAXED_QUAD: stat = 75; break; case CPXMIP_OPTIMAL_RELAXED_QUAD: stat = 76; break; #ifdef CPX_STAT_MULTIOBJ_OPTIMAL /*{*/ case CPX_STAT_MULTIOBJ_OPTIMAL: stat = 77; break; case CPX_STAT_MULTIOBJ_INFEASIBLE: stat = 78; break; case CPX_STAT_MULTIOBJ_INForUNBD: stat = 79; break; case CPX_STAT_MULTIOBJ_UNBOUNDED: stat = 80; break; case CPX_STAT_MULTIOBJ_NON_OPTIMAL: stat = 81; break; case CPX_STAT_MULTIOBJ_STOPPED: stat = 82; break; #endif /*}*/ #endif /*}*/ default: stat = 0; } } else { adj = 0; pfeas = dfeas = 1; switch(stat) { case CPX_STAT_INFEASIBLE: CPXsolninfo(Env, cpx, &solmeth, &soltype, &pfeas, &dfeas); if (solmeth == CPX_ALG_BARRIER && (!pfeas || !dfeas)) { adj = pfeas ? 16 : 17; if (!dfeas) adj += 2; } /* no break */ case CPX_STAT_UNBOUNDED: if (method < 0) stat = CPX_STAT_INFEASIBLE + CPX_STAT_UNBOUNDED - stat; break; case CPX_STAT_NUM_BEST: CPXsolninfo(Env, cpx, &solmeth, &soltype, &pfeas, &dfeas); if (solmeth == CPX_ALG_BARRIER) { adj = 16; if (!pfeas) adj++; if (!dfeas) adj += 2; } break; case CPX_STAT_ABORT_IT_LIM: case CPX_STAT_ABORT_TIME_LIM: CPXsolninfo(Env, cpx, &solmeth, &soltype, &pfeas, &dfeas); if (!dfeas) adj = 1; break; case CPX_STAT_ABORT_USER: CPXsolninfo(Env, cpx, &solmeth, &soltype, &pfeas, &dfeas); if (solmeth == CPX_ALG_BARRIER) { if (pfeas && dfeas) adj = 5; else { adj = dfeas ? 1 : 2; if (!pfeas) adj += 2; } } } stat = statmap[stat-1] + adj; } #else /*}{*/ if (stat > 100 && stat < 120) stat -= 66; else if (stat > 18 && stat < 44) stat -= 13; else if (stat == 1101) stat = 31; /* should not happen */ else if (stat < 0 || stat > 18) stat = 0; else if (stat >= 2 && stat <= 3 && Optimize == CPXdualopt) stat = 5 - stat; #endif /*}}*/ return stat; } static void write_basis(cpxlp *cpx) { if (CPXmbasewrite(Env, cpx, endbas)) { printf("Could not write ending basis to \"%s\"\n", endbas); need_nl = 0; } } static void cud_cadjust(ASL *asl) { int i, m; real *L, *U; m = n_con; L = LUrhs; U = Urhsx; for(i = 0; i < m; i++) if (L[i] <= negInfinity) L[i] = U[i]; } static void Kludge_getbase(dims *d, int *rstat) { /* Kludge around CPLEX bug in rstat values for <= constraints... */ int i, m = mbas; char *rt = d->rtype; for(i = 0; i < m; i++) if (rt[i] == 'L' && rstat[i] == 0) rstat[i] = 2; } static int send_statuses(ASL *asl, cpxlp *cpx, dims *d) { int i, j, m, n; int *cs, *cstat, *rs, *rstat; real *L, *U; static int map[] = {3, 1, 4, 6, 0}; if (!(Oinfo.wantsol & 1) && !amplflag) return 0; cstat = d->cstat; rstat = d->rstat; memset(cstat, 0, n_var*sizeof(int)); memset(rstat, 0, n_con*sizeof(int)); if (method > 0) { if ((i = CPXgetbase(Env, cpx, cstat, rstat))) { no_basis: if (i != CPXERR_NO_BASIS) badret("CPXgetbase", i, 0); d->csd->kind &= ~ASL_Sufkind_output; d->rsd->kind &= ~ASL_Sufkind_output; return 1; } Basedebug("spx.bas",cstat,rstat); Kludge_getbase(d, rstat); stat_map(cstat, n_var, map, 4, "outgoing cstat"); stat_map(rstat, n_con, map, 4, "outgoing rstat"); equ_adjust(cstat, rstat); if (costsens) { L = (real*)M1alloc(2*sizeof(real)*(nbas + mbas)); U = L + nbas; if ((i = CPXobjsa(Env, cpx, 0, nbas-1, L, U))) badret("CPXobjsa", i, 0); else { suf_rput("down", ASL_Sufkind_var, L); suf_rput("up", ASL_Sufkind_var, U); suf_rput("current", ASL_Sufkind_var, d->c); } L = U + nbas; U = L + mbas; if ((i = CPXrhssa(Env, cpx, 0, mbas-1, L, U))) badret("CPXrhssa", i, 0); else { cud_cadjust(asl); suf_rput("down", ASL_Sufkind_con, L); suf_rput("up", ASL_Sufkind_con, U); suf_rput("current", ASL_Sufkind_con, LUrhs); } } return 0; } cs = (int*)M1alloc((mbas + nbas)*sizeof(int)); rs = cs + nbas; if ((i = CPXgetbase(Env, cpx, cs, rs))) goto no_basis; m = n_con; n = n_var; Kludge_getbase(d, rs); L = LUrhs; U = Urhsx; for(i = 0; i < m; i++) { if (L[i] <= negInfinity) rstat[i] = cs[i] == CPX_AT_UPPER ? 1 : 4; else rstat[i] = L[i] == U[i] || cs[i] == CPX_BASIC ? 3 : 1; } if (nranges) { for(j = 0; j < m; j++) if (L[j] < U[j] && L[j] > negInfinity && U[j] < Infinity && cs[i++] == CPX_BASIC) rstat[j] = 4; } L = LUv; U = Uvx; for(j = 0; j < n; j++) { if (L[j] > negInfinity) { if (L[j]) cstat[j] = cs[i++] == CPX_BASIC ? 3 : 1; else cstat[j] = rs[j] == CPX_BASIC ? 3 : 1; if (U[j] < Infinity) if ((U[j] ? cs[i++] : rs[j]) == CPX_BASIC) cstat[j] = 4; } else if (U[j] < Infinity) { if (U[j]) cstat[j] = cs[i++] == CPX_BASIC ? 4 : 1; else cstat[j] = rs[j] == CPX_BASIC ? 4 : 1; } else cstat[j] = rs[j] == CPX_BASIC ? 2 : 1; } equ_adjust(cstat, rstat); return 0; } static int send_dray(ASL *asl, cpxlp *cpx, int nelqf) { real proof, *y, *y1, *ye; if (nelqf) { /* CPLEX 8.0 faulted in this case; */ /* CPLEX 8.1 would issue a message. */ return 2; } y = (real*)M1zapalloc(mbas*sizeof(real)); if (CPXdualfarkas(Env, cpx, y, &proof)) return 1; if (obj_no >= 0 && objtype[obj_no]) { /* circumvent CPLEX bug */ for(y1 = y, ye = y + mbas; y1 < ye; ++y1) *y1 = -*y1; } suf_rput("dunbdd", ASL_Sufkind_con, y); return 0; } static int send_ray(ASL *asl, cpxlp *cpx) { int i, j, n, rc; real *r; if (CPXgetijdiv(Env, cpx, &i, &j)) return 1; if ((n = n_var) < nbas) n = nbas; r = (real*)M1zapalloc(n*sizeof(real)); if (!(rc = CPXgetray(Env, cpx, r))) suf_rput("unbdd", ASL_Sufkind_var, r); return rc; } #ifdef CPX_PARAM_IISIND static void iis_put(ASL *asl, int kind, int n, int *ind, int *stat) { int i, *x; x = (int*)M1zapalloc((&asl->i.n_var_)[kind]*sizeof(int)); suf_iput("iis", kind, x); for(i = 0; i < n; i++) x[ind[i]] = stat[i] + 1; } #endif /*CPX_PARAM_IISIND*/ static void retfrom(PBuf *B, int k, const char *what) { Bpf(B, "\nReturn %d from %s.", k, what); } #ifdef CPX_PARAM_FEASOPTMODE /* >= 9.2b */ /* use conflict finder to determine IIS */ static int confiis_put(ASL *asl, int kind, int n, int *ind, int *stat) { int i, j, k, *x; static int stmap[7] = {0, 5, 6, 7, 4, 1, 3 }; x = (int*)M1zapalloc((&asl->i.n_var_)[kind]*sizeof(int)); suf_iput("iis", kind, x); for(i = k = 0; i < n; i++) { if ((j = stat[i] + 1) < 0 || j > 6) j = 8; else j = stmap[j]; if ((x[ind[i]] = j)) k++; } return k; } static void send_confiis_ext(ASL *asl, cpxlp *cpx, PBuf *B) { char *grptype; double *L, *U, *gp; int *ci, *grpbeg, *grpind, *gs, i, i1, j, j1, k, lc0, n, nc, nv, *vi; static int cmap[8] = {0, 5, 6, 7, 4, 1, 3, 8 }; L = LUv; U = Uvx; k = n_var; n = n_con; for(i = 0; i < k; i++) { if (L[i] > negInfinity) n++; if (U[i] < Infinity) n++; } gp = (double*)Malloc(n*(sizeof(double)+3*sizeof(int)+1)+2*k); grpbeg = (int*)(gp + n); grpind = grpbeg + n; gs = grpind + n; grptype = (char*)(gs + n); for(i = 0; i < n; i++) { grpbeg[i] = i; gp[i] = 1.; } for(i = j = 0; i < k; i++) { if (L[i] > negInfinity) { grpind[j] = i; grptype[j++] = CPX_CON_LOWER_BOUND; } if (U[i] < Infinity) { grpind[j] = i; grptype[j++] = CPX_CON_UPPER_BOUND; } } lc0 = nlc; for(i = 0, k += n_con - lc0; j < k; j++) { grpind[j] = i++; grptype[j] = CPX_CON_LINEAR; } for(i = 0, k += nlc; j < k; j++) { grpind[j] = i++; grptype[j] = CPX_CON_QUADRATIC; } if ((i = CPXrefineconflictext(Env, cpx, n, n, gp, grpbeg, grpind, grptype))) { retfrom(B, i, "CPXrefineconflictext"); goto ret; } if ((i = CPXgetconflictext(Env, cpx, gs, 0, n-1))) { retfrom(B, i, "CPXgetconflictext"); goto ret; } for(i = 0; i < n; i++) if ((j = ++gs[i]) < 0 || j > 6) gs[i] = 7; vi = (int*)M1zapalloc((n_var+n_con)*sizeof(int)); ci = vi + n_var; k = n_var; for(i = j = nv = 0; i < k; i++) { i1 = 0; if (L[i] > negInfinity) { if ((vi[i] = cmap[gs[j++]])) i1 = 1; } if (U[i] < Infinity && (j1 = cmap[gs[j++]])) { i1 = 1; if (vi[i] && L[i] == U[i]) j1 = 2; vi[i] = j1; } nv += i1; } for(i = nc = 0, k = n_con; i < k; i++) if ((ci[i] = cmap[gs[j++]])) nc++; suf_iput("iis", ASL_Sufkind_var, vi); suf_iput("iis", ASL_Sufkind_con, ci); Bpf(B, "\nReturning an IIS involving %d variables and %d constraints.", nv, nc); ret: free(gp); } static void send_confiis(ASL *asl, cpxlp *cpx, PBuf *B) { int cs, k, mc, mc1, nc, nc1; int *colind, *colst, *rowind, *rowst; static char *abort_reason[7] = { "contradiction", "time limit", "iteration limit", "node limit", "objective limit", "memory limit", "user request" }; if ((k = CPXrefineconflict(Env, cpx, &mc, &nc))) { retfrom(B, k, "CPXrefineconflict"); return; } k = mc + nc; if (mc < 0 || nc < 0 || k == 0) Bpf(B, "\nSurprise values mc = %d, nc = %d from CPXrefineconflict.", mc, nc); colind = (int*)Malloc(2*sizeof(int)*k); colst = colind + nc; rowind = colst + nc; rowst = rowind + mc; if ((k = CPXgetconflict(Env, cpx, &cs, rowind, rowst, &mc1, colind, colst, &nc1))) { retfrom(B, k, "CPXgetconflict"); goto ret; } if (cs == CPX_STAT_CONFLICT_FEASIBLE) { Bpf(B, "\nNo IIS after all: problem is feasible!"); goto ret; } if (cs != CPX_STAT_CONFLICT_MINIMAL) { if ((cs - CPX_STAT_CONFLICT_ABORT_CONTRADICTION) < 0 || cs > CPX_STAT_CONFLICT_ABORT_CONTRADICTION + 6) Bpf(B, "\nSurprise conflict status = %d from CPXgetconflict\n", cs); else Bpf(B, "\nSearch for conflicts aborted because of %s\n", abort_reason[cs - CPX_STAT_CONFLICT_ABORT_CONTRADICTION]); goto ret; } if (mc1 > mc || nc1 > nc) { Bpf(B, "\nSurprise confnumrows = %d (should be <= %d)," "\nconfnumcols = %d (should be <= %d) from CPXgetconflict.", mc1, mc, nc1, nc); goto ret; } nc = confiis_put(asl, ASL_Sufkind_var, nc1, colind, colst); mc = confiis_put(asl, ASL_Sufkind_con, mc1, rowind, rowst); Bpf(B, "\nReturning an IIS of %d variables and %d constraints.", nc, mc); ret: free(colind); } #endif /*CPX_PARAM_FEASOPTMODE*/ static void send_iis(ASL *asl, cpxlp *cpx, PBuf *B) { char *ckind; int i, j, m, m1, n, n1; int *ci, *cs, *ri, *rs; if (!want_iis) return; #ifdef CPX_PARAM_FEASOPTMODE /* >= 9.2b */ if (nlc) { send_confiis_ext(asl, cpx, B); return; } if (want_iis > 2 || (nbv + niv + nlvoi + nlvci + nlvbi > 0 && !relax) || (Optimize != CPXprimopt && Optimize != CPXdualopt)) { send_confiis(asl, cpx, B); return; } #else if (nlc) { printf("Ignoring iisfind request because of nonlinearities.\n"); return; } #endif #ifdef CPX_PARAM_IISIND CPXsetintparam(Env, CPX_PARAM_IISIND, want_iis-1); if (i = CPXfindiis(Env, cpx, &m, &n)) { retfrom(B, i, "CPXfindiis"); return; } #else if ((i = CPXrefineconflict(Env, cpx, &m, &n))) { retfrom(B, i, "CPXrefineconflict"); return; } #endif ci = (int*)M1alloc((2*(m+n))*sizeof(int)); cs = ci + n; ri = cs + n; rs = ri + m; ckind = ""; #ifdef CPX_PARAM_IISIND if (i = CPXgetiis(Env, cpx, &j, ri, rs, &m1, ci, cs, &n1)) { retfrom(B, i, "CPXgetiis"); return; } iis_put(asl, ASL_Sufkind_var, n, ci, cs); iis_put(asl, ASL_Sufkind_con, m, ri, rs); if (j != 1) ckind = "partial "; #else if ((i = CPXgetconflict(Env, cpx, &j, ri, rs, &m1, ci, cs, &n1))) { retfrom(B, i, "CPXgetconflict"); return; } switch(j) { case CPX_STAT_CONFLICT_MINIMAL: confiis_put(asl, ASL_Sufkind_var, n, ci, cs); confiis_put(asl, ASL_Sufkind_con, m, ri, rs); break; case CPX_STAT_CONFLICT_FEASIBLE: Bpf(B, "\nCPXgetconflict claims the problem is feasible."); return; default: Bpf(B, "\nSurprise conflict status %d from CPXgetconflict.", j); return; } #endif Bpf(B, "\nReturning %siis of %d variables and %d constraints.", ckind, n, m); } static int wantray(int dual, cpxlp **pcpx, int *itcp, int *itcip, int nelqf) { Optalg Rayalg; cpxlp *cpx, *cpx1; int i; static Optalg PDalg[2] = { CPXprimopt, CPXdualopt }; *itcp = 0; if (want_iis || !(rays & (1 << dual))) return 0; Rayalg = PDalg[dual]; if ((!dual && Optimize == CPXprimopt) || (nelqf && (Optimize == CPXdualopt || Optimize == CPXprimopt))) { *itcip = 0; return 1; } if (Optimize == CPXmipopt || Optimize == Optimizebar) return 0; cpx = *pcpx; if (Resolve && dual) { i = 0; CPXgetintparam(Env, CPX_PARAM_PREIND, &i); if (i) { if (!(cpx1 = CPXcloneprob(Env, cpx, &i))) badret("CPXcloneprob", i, 531); CPXfreeprob(Env, pcpx); *pcpx = cpx = cpx1; CPXsetintparam(Env, CPX_PARAM_PREIND, 0); } } (*Rayalg)(Env, cpx); *itcp = CPXgetitcnt(Env, cpx); *itcip = CPXgetphase1cnt(Env, cpx); algname = dual ? "dual " : ""; return 1; } #ifdef CPX_PARAM_POPULATELIM /*{*/ static void poolwrite(ASL *asl, cpxlp *cpx, dims *d, int nelqf, PBuf *B) { PBuf B1; char buf[32], buf1[1200], *fname, *s; const char *whence; int j, k, m, n, nm1, npm, nprt, nsols, oprt, rft, srn, stat1, status; int *cstat, *ocstat, *orstat, *rstat; real feastol, inttol, obj, *x, *y, *y1; size_t L; static char errfmt1[] = "\nCPLEX solution status %d with fixed integers " "on solution pool\nmember %d (file %s):\n\t%s", errfmt2[] = "\nCPLEX status %d from CPXsolution " "on solution pool\nmember %d (file %s)."; B1.s = buf1; B1.se = buf1 + sizeof(buf1); srn = solve_result_num; solve_result_num = 0; j = rft = 0; y = 0; ocstat = orstat = 0; if (populate == 1) { if ((k = CPXpopulate(Env, cpx))) { Bpf(B, "\nReturn %d from CPXpopulate.", k); goto done; } } nsols = CPXgetsolnpoolnumsolns(Env,cpx); if (nsols <= 0) { Bpf(B, "\n%d solutions in solution pool.", nsols); goto done; } m = n_con; n = npm = n_var; nprt = 0; /* silence buggy warning */ if ((k = pooldual && m > 0 && !nlc)) { nprt = nelqf ? CPXPROB_FIXEDMIQP : CPXPROB_FIXEDMILP; npm += m; } L = strlen(poolstub); x = (real*)Malloc(npm*(sizeof(real) + k*sizeof(int)) + L + 32); fname = (char*)(x + n); if (k) { y = x + n; if (d->cstat && (rstat = d->rstat)) { cstat = d->cstat; ocstat = (int*)(y + m); orstat = ocstat + n; fname = (char*)(orstat + m); memcpy(ocstat, cstat, n*sizeof(int)); memcpy(orstat, rstat, m*sizeof(int)); } if ((rft = !CPXgetdblparam(Env,CPX_PARAM_EPRHS,&feastol) && !CPXgetdblparam(Env,CPX_PARAM_EPINT,&inttol) && inttol > feastol)) CPXsetdblparam(Env, CPX_PARAM_EPRHS, inttol); } strcpy(fname, poolstub); nm1 = n - 1; whence = 0; for(j = k = 0; j < nsols; j++) { if ((k = CPXgetsolnpoolx(Env, cpx, j, x, 0, nm1))) { whence = "CPXgetsolnpoolx"; break; } if ((k = CPXgetsolnpoolobjval(Env, cpx, j, &obj))) { whence = "CPXgetsolnpoolobjval"; break; } g_fmtop(buf, obj); Bpf(&B1, "Solution pool member %d (of %d); objective %s", j+1, nsols, buf); sprintf(fname+L, "%d.sol", j+1); if ((y1 = y)) { oprt = CPXgetprobtype(Env, cpx); if ((k = CPXchgprobtypesolnpool(Env, cpx, j, nprt))) { whence = "CPXchgprobtypesolnpool"; break; } status = CPXprimopt(Env, cpx); stat1 = CPXgetstat(Env, cpx); if (status || stat1 != 1) { Bpf(&B1, errfmt1, stat1, j, fname, solinfo[statadjust(cpx,stat1)].msg); y1 = 0; } else if (CPXsolution(Env, cpx, &stat1, &obj, x, y, 0, 0)) { y1 = 0; status = CPXgetstat(Env, cpx); stat1 = statadjust(cpx, status); Bpf(&B1, errfmt2, status, j, fname); } else if (send_statuses(asl, cpx, d)) Bpf(&B1, "\nNo basis."); if ((k = CPXchgprobtype(Env, cpx, oprt))) { whence = "CPXchgprobtype"; break; } } #ifdef CPXERR_QCP_SENSE if (nlc && y1 && x) { solve_result_num = 0; qcduals(asl, B, cpx, d, x, y1); } #endif if (write_solf_ASL(asl, buf1, x, y1, 0, fname)) { whence = ""; break; } B1.s = buf1; } Bpf(B, "\nWrote %d solution%s in solution pool", j, j == 1 ? "" : "s"); s = L > 32 ? "\n" : " "; if (j > 0) switch(j) { case 1: Bpf(B, "\nto file %s1.sol", poolstub); break; case 2: Bpf(B, "\nto files %s1.sol%sand %s2.sol", poolstub, s, poolstub); break; default: Bpf(B, "\nto files %s1.sol%s... %s%d.sol", poolstub, s, poolstub, j); } Bpf(B, "."); if (whence) { if (k) Bpf(B, "\nSolution pool writing stopped by return %d from %s.", k, whence); else Bpf(B, "\nCould not open \"%s\"", fname); } if (ocstat) { memcpy(cstat, ocstat, n*sizeof(int)); memcpy(rstat, orstat, m*sizeof(int)); } free(x); done: solve_result_num = srn; if (rft) /*restore "feasibility" tolerance*/ CPXsetdblparam(Env, CPX_PARAM_EPRHS, feastol); d->npool = j; suf_iput("npool", ASL_Sufkind_obj, &d->npool); suf_iput("npool", ASL_Sufkind_prob, &d->npool); } struct Element { keyword *kw; union { double dval; int ival; } u; }; typedef struct ParInfo { double align; Element *nd; AVL_Tree *tree; int n_dbl, n_int; } ParInfo; static int int_elcmp(void *v, const Element *L, const Element *R) { return (Intcast L->kw->info) - (Intcast R->kw->info); } static ParInfo * getparinfo(void) { AVL_Tree *at; Element *e; ParInfo *PI; double w[4]; int k, z[4]; keyword *kw, *kwe; size_t L, n; /* Use of AVL stuff here is only needed if the choice between */ /* (sf_int and sf_int2) or (sf_dbl and sf_dbl2) is wrong in keywds. */ n = nkeywds; L = n*sizeof(Element) + sizeof(ParInfo); /* overkill */ PI = (ParInfo*)Malloc(L); PI->nd = e = (Element*)(PI + 1); PI->tree = at = AVL_Tree_alloc(0, int_elcmp, mymalloc_ASL); PI->n_dbl = PI->n_int = 0; kw = keywds; for(kwe = kw + nkeywds; kw < kwe; ++kw) { k = Intcast kw->info; if (kw->kf == sf_int) { CPXinfointparam(Env, k, z, z+1, z+2); CPXgetintparam(Env, k, z+3); if (z[0] != z[3]) { e->kw = kw; if (!AVL_insert(e,at)) { e->u.ival = z[3]; ++e; PI->n_int++; } } } else if (kw->kf == sf_dbl) { CPXinfodblparam(Env, k, w, w+1, w+2); CPXgetdblparam(Env, k, w+3); if (w[0] != w[3]) { e->kw = kw; if (!AVL_insert(e,at)) { e->u.dval = w[3]; ++e; PI->n_dbl++; } } } } return PI; } static void tunewrite(char *fname, const char *fkeywd, PBuf *B) { Element *e, *ee; FILE *f; ParInfo *PI; int n; keyword *kw; if (!(f = fopen(fname, "w"))) { Bpf(B, "\nCould not open %s file \"%s\"", fkeywd, fname);; solve_result_num = 565; return; } PI = getparinfo(); n = 0; e = PI->nd; n = AVL_Tree_size(PI->tree); ee = e + n; for(; e < ee; ++e) { kw = e->kw; if (kw->kf == sf_int) fprintf(f, "%s = %d\n", kw->name, e->u.ival); else fprintf(f, "%s = %.g\n", kw->name, e->u.dval); } fclose(f); Bpf(B, "\n%d settings written to %s file \"%s\"", n, fkeywd, fname); AVL_Tree_free(&PI->tree); free(PI); } #endif /*}*/ #if CPX_VERSION >= 1000 /*{*/ static void tunewriteprm(char *fname, const char *fkeywd, PBuf *B) { char *fmt; if (CPXwriteparam(Env, fname)) { fmt = "\nError writing %s file \"%s\""; solve_result_num = 565; } else fmt = "\n%s file \"%s\" written"; Bpf(B, fmt, fkeywd, fname); } #endif /*}*/ #if CPX_VERSION >= 1100 /*{*/ typedef struct Tunefix { AVL_Tree *avi, *avr; Element *e; int *num0, *nume, *numi, *numr; } Tunefix; static void tunefixname(Tunefix *Tf, char *s, const char *what) { AVL_Tree *T; Element *e; Kwfunc *f; char *peq; int L; keyword *kw; if ((kw = (keyword *)b_search_ASL(keywds, (int)sizeof(keyword), nkeywds, &s, &peq))) { f = kw->kf; e = Tf->e; e->kw = kw; if (f == sf_int || f == sf_int2) { if (!(T = Tf->avi)) Tf->avi = T = AVL_Tree_alloc(0, int_elcmp, mymalloc_ASL); if (!AVL_insert(e,T)) { *Tf->numi++ = Intcast kw->info; ++Tf->e; } } else if (f == sf_dbl || f == sf_dbl2) { if (!(T = Tf->avr)) Tf->avr = T = AVL_Tree_alloc(0, int_elcmp, mymalloc_ASL); if (!AVL_insert(e,T)) { *--Tf->numr = Intcast kw->info; ++Tf->e; } } } else { for(L = 0; s[L] > ' '; ++L); badretfmt(566, "unrecognized keyword \"%.*s\" in %s", L, s, what); } } static void tunefix_proc(Tunefix *Tf, char *s) { char buf[64], *s1; size_t inc, L; for(;;) { while(*s <= ' ') if (!*s++) return; for(L = inc = 0; s[L] > 0; ++L) { if (s[L] == ',') { inc = 1; break; } } if (L && L < sizeof(buf)) { s1 = s; if (inc) { memcpy(s1 = buf, s, L); s1[L] = 0; } tunefixname(Tf, s1, "tunefix"); } s += L + inc; } } static void tunefixfile_proc(Tunefix *Tf) { FILE *f; char buf[4096], *b, *b1, *be; if (!(f = fopen(tunefixfile, "rb"))) badretfmt(564, "Could not open tunefixfile \"%s\"", tunefixfile); top: while(fgets(buf, sizeof(buf), f)) { b = buf; be = b + strlen(b); if (be > b && be[-1] == '\n') *--be = 0; for(;;) { while(*b <= ' ') if (!*b++) goto top; b1 = b; while(*++b > ' '); tunefixname(Tf, b1, "tunefixfile"); } } fclose(f); } static void tunerun(cpxlp *cpx, PBuf *B) { Element *E; Tunefix TF; const char *what; double *dblval; int *intval; int i, j, k, n_dbl, n_int; dblval = 0; intval = 0; TF.avi = TF.avr = 0; TF.e = E = (Element *)Malloc((nkeywds)*(sizeof(Element) + sizeof(int))); TF.num0 = TF.numi = (int*)(E + nkeywds); TF.nume = TF.numr = TF.num0 + nkeywds; if (tunefix) tunefix_proc(&TF, tunefix); if (tunefixfile) tunefixfile_proc(&TF); n_dbl = TF.nume - TF.numr; n_int = TF.numi - TF.num0; if (n_dbl + n_int) { dblval = (double*)Malloc(n_dbl*sizeof(double) + n_int*sizeof(int)); intval = (int*)(dblval + n_dbl); for(i = 0; i < n_int; ++i) CPXgetintparam(Env, TF.num0[i], intval + i); for(i = 0; i < n_dbl; ++i) CPXgetdblparam(Env, TF.numr[i], dblval + i); } k = CPXtuneparam(Env, cpx, n_int, TF.num0, intval, n_dbl, TF.numr, dblval, 0, 0, 0, &j); if (k) Bpf(B, "\nSurprise return %d from CPXtuneparam.", k); else { switch(j) { case 0: what = "finished"; break; case CPX_TUNE_ABORT: what = "aborted"; break; case CPX_TUNE_TILIM: what = "time limit reached"; break; default: Bpf(B, "\nTuning got surprise tunestat = %d.", j); goto no_what; } Bpf(B, "\nTuning %s.", what); } no_what: if (dblval) { free(dblval); if (TF.avi) AVL_Tree_free(&TF.avi); if (TF.avr) AVL_Tree_free(&TF.avr); } free(E); } #endif /*}*/ #ifdef CPXPROB_MIQCP static void fixints(ASL *asl, cpxlp *cpx, real *x) { char *t; int i, k, nint, *z, *z1; real *b, *b1; nint = nbv + niv + nlvoi + nlvci + nlvbi; b = b1 = (real*)Malloc(nint*(sizeof(real) + sizeof(int) + 1)); z = z1 = (int*)(b + nint); t = (char*)(z + nint); memset(t, 'B', nint); i = n_var - nbv - niv; if ((k = nbv)) { memcpy(b1, x + i, k*sizeof(real)); b1 += k; while(k--) *z1++ = i++; } if ((k = niv)) { memcpy(b1, x + i, k*sizeof(real)); b1 += k; while(k--) *z1++ = i++; } if ((k = nlvbi)) { i = nlvb - k; memcpy(b1, x + i, k*sizeof(real)); b1 += k; while(k--) *z1++ = i++; } if ((k = nlvci)) { i = nlvc - k; memcpy(b1, x + i, k*sizeof(real)); b1 += k; while(k--) *z1++ = i++; } if ((k = nlvoi)) { i = nlvo - k; memcpy(b1, x + i, k*sizeof(real)); b1 += k; while(k--) *z1++ = i++; } i = CPXchgbds(Env, cpx, nint, z, t, b); if (i) fprintf(Stderr, "CPxchbds() returned %d\n", i); free(b); } #endif static void amplout(ASL *asl, cpxlp **pcpx, dims *d, int status, int nelqf, int nint1, int *nosp) { Optalg Contopt; PBuf B; Sol_info *SI; char buf[32], hbuf[4096]; const char *wb, *what; cpxlp *cpx, *cpx1; int bitc, finalMIPParam, i, ii, itc, itci, j, m, mipstat, n, needsol, nint; int nodecnt, nodelim, nos, npt, nround, opt, savedAlg, stat, stat0, stat1, stat10; real *bb, *bn, *l, *le, *u, w[4], *x, *x2, *y, *z, *z1; real absmipgap, bbound, bcond, bobj, bobj0, feastol, inttol; real relmipgap, obj, t; #ifndef NO_MOkwf int k, maxobjlen, objlen; #endif static Sol_info solinfo1[] = { { "QP Hessian is not positive semi-definite", 542, 0 }, { "primal optimal (no dual solution available)", 004, 1 }, { "ran out of memory", 522, 0 } #ifdef CPXERR_Q_NEG_ZERO_COMP /* CPLEX 7.1 */ ,{ "QP Hessian has diag. elements of the wrong sign", 541, 0 } #endif }; #ifdef CPXERR_NOT_MIP static Sol_info solinfo2[1] = { { "problem is not a MIP or has a nonconvex quadratic constraint", 543, 0 }}; #endif #ifdef CPXERR_NOT_FOR_DISTMIP static Sol_info solinfo3[1] = { { "problem is not suitable for the distributed MIP algorithm", 544, 0 }}; #endif static Sol_info subprob_failed = { "Failed to solve a MIP subproblem", 513, 0 }; static char *netmsg[] = { "no network", /*"an optimal network solution"*/ "", "an unbounded network", "an infeasible network", "an infeasible or unbounded network", "iteration limit with a feasible network solution", "iteration limit with an infeasible network solution", "time limit with a feasible network solution", "time limit with an infeasible network solution", "a feasible aborted network solution", "an infeasible aborted network solution", "a bug" #ifdef Student_Edition ,"the adjusted problem too large" #endif }; static char *dray_msg[4] = { "\nconstraint.dunbdd returned", "\nfailed to compute variable.dunbdd", "\nQP simplex cannot compute variable.dunbdd" }; #if CPX_VERSION < 1100 /*{{*/ int cl0, cl, cov, ccpr = 0; #else /*}{*/ typedef struct CutInfo { const char *cutname; int cuttype; } CutInfo; CutInfo *CI; static CutInfo Cut_Info[] = { { "cover", CPX_CUT_COVER }, { "GUB-cover", CPX_CUT_GUBCOVER }, { "flow-cover", CPX_CUT_FLOWCOVER }, { "clique", CPX_CUT_CLIQUE }, { "Gomory", CPX_CUT_FRAC }, { "flow-path", CPX_CUT_FLOWPATH }, { "disjunctive", CPX_CUT_DISJ }, { "implied-bound", CPX_CUT_IMPLBD }, { "zero-half", CPX_CUT_ZEROHALF }, { "mixed-integer rounding", CPX_CUT_MIR }, #ifdef CPX_CUT_LOCALCOVER { "local cover", CPX_CUT_LOCALCOVER }, #endif #ifdef CPX_CUT_MCF { "multi-commodity flow", CPX_CUT_MCF }, #endif #ifdef CPX_CUT_LANDP { "split", CPX_CUT_LANDP }, #endif #if 0 { "", CPX_CUT_TIGHTEN }, { "", CPX_CUT_OBJDISJ }, { "", CPX_CUT_USER }, { "", CPX_CUT_TABLE }, { "", CPX_CUT_SOLNPOOL } #endif { 0, 0}}; #ifdef CPX_PARAM_MIPKAPPASTATS /*{*/ typedef struct QualityInfo { const char *desc; int key; } QualityInfo; enum {QinfoN = 6}; static QualityInfo QualInfo[QinfoN] = { {"max. condition number of optimal bases", CPX_KAPPA_MAX}, {"attention statistic (weighted sum of percentages of bases with\n" "high condition numbers", CPX_KAPPA_ATTENTION}, {"percentage of stable bases (condition number < 1e7)", CPX_KAPPA_STABLE}, {"percentage of suspect bases (condition between 1e7 and 1e10)", CPX_KAPPA_SUSPICIOUS}, {"percentage of unstable bases (condition number between 1e10 and 1e14)", CPX_KAPPA_UNSTABLE}, {"percentage of ill-posed bases (condition number > 1e14)", CPX_KAPPA_ILLPOSED}}; int haveqmet = 0; real qmet[QinfoN]; #endif /*}*/ #endif /*}}*/ B.s = hbuf; B.se = hbuf + sizeof(hbuf); cpx = *pcpx; absmipgap = obj = relmipgap = Infinity; stat0 = stat10 = -1; stat1 = 1; ii = mipstat = nodecnt = npt = nround = opt = 0; m = n_con; n = n_var; x = d->x; y = d->y; #ifdef USE_CHANNELS if (logfname) CPXsetlogfilename(Env, NULL, NULL); #else if (Logf) CPXsetlogfile(Env, NULL); /* suppress idiotic Error 1217 */ #endif #ifdef BARRIER bitc = CPXgetbaritcnt(Env, cpx); #else bitc = 0; #endif #ifdef CPLEX_MIP bobj = bobj0 = objsen * Infinity; #endif itc = CPXgetitcnt(Env, cpx); itci = CPXgetphase1cnt(Env, cpx); nos = nosp ? *nosp : 0; switch (status) { case 0: break; case CPXERR_SUBPROB_SOLVE: SI = &subprob_failed; x = y = 0; Bpf(&B, "%s: %s", Oinfo.bsname, SI->msg); if ((stat0 = CPXgetsubstat(Env,cpx)) && (stat = statadjust(cpx,stat0))) Bpf(&B, ": %s", solinfo[stat].msg); else Bpf(&B, "; CPXgetsubstat returned %d.", stat0); goto have_SI1; case CPXERR_NO_MEMORY: SI = solinfo1 + 2; stat = -1; goto have_SI; case CPXERR_Q_NOT_POS_DEF: SI = solinfo1; stat = -1; goto have_SI; #ifdef CPXERR_Q_NEG_ZERO_COMP case CPXERR_Q_NEG_ZERO_COMP: SI = solinfo1 + 3; stat = -1; goto have_SI; #endif case CPXERR_PRESLV_INForUNBD: SI = solinfo + 31; goto have_SI; case 32024: stat = 33; goto more_default; #ifdef CPXERR_NOT_MIP case CPXERR_NOT_MIP: SI = solinfo2; goto have_SI; #endif #ifdef CPXERR_NOT_FOR_DISTMIP case CPXERR_NOT_FOR_DISTMIP: SI = solinfo3; goto have_SI; #endif default: stat = 0; more_default: stat0 = status; x = y = 0; goto have_stat; } if (Optimize == CPXlpopt #ifndef BARRIER_FOR_QP || Optimize == CPXqpopt #endif /* BARRIER_FOR_QP */ ) { if (lpoptalg == CPX_ALG_AUTOMATIC) switch(i = CPXgetmethod(Env,cpx)) { case CPX_ALG_DUAL: Optimize = CPXdualopt; algname = "dual "; break; case CPX_ALG_PRIMAL: Optimize = CPXprimopt; break; case CPX_ALG_MIP: /* possible with reqconvex == 3 */ nint1 = 1; break; #ifdef CPX_STAT_OPTIMAL /* >= 8.0 */ case CPX_ALG_SIFTING: case CPX_ALG_BARRIER: #ifdef CPX_ALG_FEASOPT /* >= 9.2b */ case CPX_ALG_FEASOPT: #endif Optimize = CPXlpopt; lpoptalg = i; #endif /* CPX_STAT_OPTIMAL */ } } #ifdef CPLEX_MIP else if (Optimize == CPXmipopt) { #if CPX_VERSION < 1100 /*{*/ if (prestats && nint1 && (parval(CPX_PARAM_CLIQUES) || parval(CPX_PARAM_COVERS))) { cl0 = CPXgetgenclqcnt(Env, cpx); cl = CPXgetclqcnt(Env, cpx); cov = CPXgetcovcnt(Env, cpx); ccpr = 1; } #endif /*}*/ if (status > 0) { mipstat = statadjust(cpx, stat0 = status); status = 0; } } #endif #ifdef CPLEX_MIP if (nint1) { #ifdef CPX_PARAM_MIPKAPPASTATS /*{*/ if (CPXgetintparam(Env, CPX_PARAM_MIPKAPPASTATS, &j) == 0 && j >= 0) { memset(qmet, 0, sizeof(qmet)); j = CPXgetdblquality(Env, cpx, &qmet[0], QualInfo[0].key); if (j == 0 && qmet[0] > 0.) { haveqmet = 1; for(j = 1; j < QinfoN; ++j) { CPXgetdblquality(Env, cpx, &qmet[j], QualInfo[j].key); if (qmet[j] > 0.) haveqmet = j; } } } #endif /*}*/ if (mipstat) { stat = mipstat; if (mipstat < 4 || mipstat > 8) goto have_ii; switch(mipstat) { /* Increase limits to permit recovering best sol'n */ case 5: case 6: CPXsetintparam(Env, CPX_PARAM_ITLIM, 2*parval(CPX_PARAM_ITLIM)); break; case 7: case 8: { double tl = 1e75; CPXgetdblparam(Env, CPX_PARAM_TILIM, &tl); CPXsetdblparam(Env, CPX_PARAM_TILIM, 2.*tl); } } } else { stat0 = CPXgetstat(Env, cpx); if (stat0 == CPXMIP_INForUNBD && Resolve) { CPXgetintparam(Env, CPX_PARAM_PREIND, &i); if (i) { if (!(cpx1 = CPXcloneprob(Env, cpx, &i))) badret("CPXcloneprob", i, 531); CPXsetintparam(Env, CPX_PARAM_PREIND, 0); CPXfreeprob(Env, &cpx); CPXmipopt(Env, *pcpx = cpx = cpx1); stat0 = CPXgetstat(Env, cpx); } } stat = statadjust(cpx, stat0); } ii = CPXgetmipitcnt(Env, cpx); nodecnt = CPXgetnodecnt(Env, cpx); have_ii: if (CPXgetbestobjval(Env, cpx, &bobj)) bobj = bobj0; if (!solinfo[stat].wantobj) x = y = 0; if (solinfo[stat].wantobj || endbas) { if (zap_lpcbf) { if (zap_lpcbf == 2) CPXsetmipcallbackfunc(Env, breakcallback, 0); CPXsetlpcallbackfunc(Env, breakcallback, 0); zap_lpcbf = 0; } if (!CPXgetmipobjval(Env, cpx, &obj) && bobj != bobj0) { if ((absmipgap = obj - bobj) < 0.) absmipgap = -absmipgap; if ((t = obj) < 0.) t = -t; relmipgap = absmipgap / (1e-10 + t); } if (endbas) mipbasis = 1; needsol = 0; if ((i = CPXgetmipx(Env, cpx, x, 0, n-1))) { fprintf(Stderr, "Surprise return %d from CPXgetmipx\n", i); x = 0; } if (mipbasis) { opt = CPXgetprobtype(Env, cpx); Contopt = CPXlpopt; what = "CPXlpopt"; #ifdef CPXPROB_MIQCP npt = CPXPROB_FIXEDMILP; switch(opt) { case CPXPROB_MIQP: npt = CPXPROB_FIXEDMIQP; goto use_qpopt; case CPXPROB_MIQCP: if (!x) goto no_qcbasis; npt = CPXPROB_QCP; use_qpopt: Contopt = CPXqpopt; what = "CPXqpopt"; if (finalmipalg_val == 5) { Bpf(&B, "Sifting cannot be applied to QP problems.\nSetting finalmipalg to automatic.\n"); finalmipalg_val = 0; } } #else npt = nelqf ? 8 : 3; #endif if (npt != opt) { i = CPXchgprobtype(Env, cpx, npt); if (i) { fprintf(Stderr, "CPXchgprobtype(...,%d) returned %d\n", npt, i); goto no_qcbasis; } } #ifdef CPXPROB_MIQCP if (npt == CPXPROB_QCP) fixints(asl, cpx, x); #endif if ((i = !CPXgetdblparam(Env,CPX_PARAM_EPRHS,&feastol) && !CPXgetdblparam(Env,CPX_PARAM_EPINT,&inttol) && inttol > feastol)) CPXsetdblparam(Env, CPX_PARAM_EPRHS, inttol); if (Contopt == CPXqpopt) finalMIPParam = CPXPARAM_QPMethod; else finalMIPParam = CPXPARAM_LPMethod; /*Set algorithm for the final LP*/ CPXgetintparam(Env, finalMIPParam, &savedAlg); CPXsetintparam(Env, finalMIPParam, finalmipalg_val); /*Solve final LP/QP*/ status = Contopt(Env, cpx); stat1 = CPXgetstat(Env, cpx); CPXsetintparam(Env, finalMIPParam, savedAlg); /*restore original*/ if (i) /*restore "feasibility" tolerance*/ CPXsetdblparam(Env, CPX_PARAM_EPRHS, feastol); if (status) { fprintf(Stderr, "\n%s returned %d\n", what, status); y = 0; } else if (stat1 != 1) { fprintf(Stderr, "CPLEX solution status %d with fixed integers:\n\t%s\n", stat1, solinfo[statadjust(cpx,stat1)].msg); y = 0; } else if (x) needsol = 1; stat1 = 1; if (endbas && !nelqf) write_basis(cpx); } else if (!nlc) y = 0; no_qcbasis: if (!solinfo[stat].wantobj) goto have_stat; if (needsol) { if (CPXsolution(Env, cpx, &stat1, &obj, x, y, 0, 0)) stat1 = CPXgetstat(Env, cpx); stat1 = statadjust(cpx, stat10 = stat1); } /* round to integer */ if (!relax && Round >= 0 && x) { w[0] = 0; if ((nint = niv + nbv)) { x2 = x + n_var - nint; nround = xround(x2, nint, Round & 1, w); } if ((nint = nlvbi)) { x2 = x + (nlvb - nint); nround += xround(x2, nint, Round & 1, w); } if ((nint = nlvci)) { x2 = x + (nlvc - nint); nround += xround(x2, nint, Round & 1, w); } if ((nint = nlvoi)) { x2 = x + (nlvo - nint); nround += xround(x2, nint, Round & 1, w); } if (nround) { CPXinfodblparam(Env, CPX_PARAM_EPINT, w+1, w+2, w+3); if (w[0] <= intwarn_tol && !(Round & 8)) nround = 0; else CPXgetdblparam(Env, CPX_PARAM_EPINT, w+1); } if (nround) { if ((solinfo[stat].code & ~1) == 2 && !(Round & 2)) stat += 19; if (Round & 4) nround = 0; else if (!(Round & 1)) nround = -nround; } } } } else #endif { switch(CPXsolution(Env, cpx, &stat, &obj, x, y, 0, 0)) { case 0: break; #ifdef CPXERR_NO_DUAL_SOLN case CPXERR_NO_DUAL_SOLN: y = 0; if (!CPXsolution(Env, cpx, &stat, &obj, x, y, 0, 0)) { if (method > 0 && stat == 1) { SI = solinfo1 + 1; goto have_SI; } break; } #endif /*CPXERR_NO_DUAL_SOLN*/ default: stat = CPXgetstat(Env, cpx); } stat = nos == 2 ? 2 : statadjust(cpx, stat0 = stat); } if (method < 0) { /* dual */ z = x; x = y; y = z; z1 = z + m; l = LUrhs; u = Urhsx; /* fix dual variables */ for(le = l + m; l < le; l++, u++, z++) if (*u > *l && *l > negInfinity && *u < Infinity) { if (*z < -*z1) *z = *z1; z1++; } if (objsen > 0) { for(z = y, z1 = y + m; z < z1; z++) *z = -*z; for(z = x, z1 = x + n; z < z1; z++) *z = -*z; } } have_stat: SI = solinfo + stat; have_SI: Bpf(&B, "%s: %s", Oinfo.bsname, SI->msg); if (!stat) Bpf(&B, ": %s", failstat(stat0)); #ifdef CPLEX_MIP else if (stat == 16 || stat == 17) { CPXgetintparam(Env, CPX_PARAM_NODELIM, &nodelim); Bpf(&B, ".\nCurrent node limit = %d", nodelim); } #endif else if (!SI->wantobj) Bpf(&B, "."); if (SI->wantobj) { #ifndef NO_MOkwf if (Optimize == Optimizemo) { maxobjlen = 0; for(i = 0; i < nmo; ++i) { objlen = strlen(obj_name(indobj[i])); if (maxobjlen < objlen) maxobjlen = objlen; } ++maxobjlen; Bpf(&B, "; %d objectives:\n", nmo); for(i = 0; i < nmo; ++i) { k = objind[i]; if ((j = CPXmultiobjgetobjval(Env, cpx, k, &obj))) badret("CPXmultiobjgetobjval", j, 1); g_fmtop(buf, obj); Bpf(&B, "\t%-*s= %s\n", maxobjlen, obj_name(indobj[k]), buf); } Bpf(&B, "Blended objective value%s:\n", nmopri == 1 ? "" : "s"); for(i = nmopri; i > 0; --i) { if ((j = CPXmultiobjgetobjvalbypriority(Env, cpx, i, &obj))) badret("CPXmultiobjgetobjvalbypriority", j, 1); g_fmtop(buf, obj); Bpf(&B, "\tPriority %d (.pri = %d): %s\n", i, pri0[i-1], buf); } } else #endif { if (obj == Infinity) CPXgetobjval(Env, cpx, &obj); g_fmtop(buf, obj); Bpf(&B, "; objective %s", buf); } } have_SI1: solve_result_num = SI->code; if (!SI->wantobj && SI->code >= 300 && SI->code < 400) x = y = 0; if (nosp) { if (nos < 0 || nos > 12) nos = 11; if (nos != 1) Bpf(&B, "\nnetopt found %s.", netmsg[nos]); if (net_nodes != lnc || net_arcs != nwv) Bpf(&B, "\nNetwork extractor found %d nodes and %d arcs.", net_nodes, net_arcs); Bpf(&B, "\n%d network simplex iterations.", netiters); } if (nint1 && !mipstat) Bpf(&B, "\n%d MIP simplex iterations\n%d branch-and-bound nodes", ii, nodecnt); if (itc > 0 || itci > 0 || Optimize == CPXprimopt || Optimize == CPXdualopt) { Bpf(&B, "\n%d %s%ssimplex iterations (%d in phase I)%s", itc, nelqf ? "QP " : "", algname, itci, method > 0 ? "" : " on the dual problem"); if (itc == 0 && itci == 0 && netiters <= 0 && solve_result_num == 0) solve_result_num = 4; } #ifdef CPX_STAT_OPTIMAL /* >= 8.0 */ else if (Optimize == CPXlpopt && lpoptalg == CPX_ALG_SIFTING) { itc = CPXgetsiftitcnt(Env, cpx); itci = CPXgetsiftphase1cnt(Env, cpx); Bpf(&B, "\n%d sifting subproblems solved (%d in phase I)", itc, itci); } #endif if (bitc > 0) { Bpf(&B, "\n%d %sbarrier iterations", bitc, baralgname); if (cbi.nx[0] | cbi.nx[1]) Bpf(&B, "\n%d push, %d exchange %s crossover iterations", cbi.nx[0], cbi.nx[1], cbi.xkind); } if (cbi.np[0] + cbi.np[1] + cbi.np[3]) Bpf(&B, "\nCPLEX's %spresolve eliminated totals of %d " "constraints and %d variables\n(perhaps repeatedly) " "and made %d coefficient changes.", nint1 ? "MIP " : "", cbi.np[0], cbi.np[1], cbi.np[3]); if (cbi.np[2]) Bpf(&B, "\nCPLEX's aggregator made %d substitutions.", cbi.np[2]); #ifdef CPLEX_MIP if (bestnode) { bbound = bobj0; if ((j = SI->code) < 200) { if (objsen*(bbound = bobj) > objsen*obj) bbound = obj; } else if (j < 400) { if (j >= 300) bbound = -bbound; } else if (j < 500 && objsen*bobj <= objsen*obj) bbound = bobj; if (bobj >= 1e75) bobj = Infinity; else if (bobj <= -1e75) bobj = negInfinity; if (n_obj > 0) { if ((bestnode & 3) == 3) { bb = (real*)M1zapalloc(2*sizeof(real)*n_obj); bn = bb + n_obj; } else bn = bb = (real*)M1zapalloc(n_obj*sizeof(real)); if (bestnode & 1) { if (obj_no >= 0) bb[obj_no] = bbound; suf_rput("bestbound", ASL_Sufkind_obj, bb); } if (bestnode & 2) { if (obj_no >= 0) bn[obj_no] = bobj; suf_rput("bestnode", ASL_Sufkind_obj, bn); } } if (bestnode & 1) suf_rput("bestbound", ASL_Sufkind_prob, &bbound); if (bestnode & 2) suf_rput("bestnode", ASL_Sufkind_prob, &bobj); } #if CPX_VERSION < 1100 if (ccpr) { if (cl0 | cl | cov) { if (cl0) Bpf(&B, "\n%d of %d clique inequalities used", cl, cl0); if (cov) Bpf(&B, "\n%d cover cuts added", cov); } else Bpf(&B, "\nNo clique or cover cuts used."); } #endif if (absmipgap > 0. && absmipgap < Infinity && !(retmipgap & 4)) Bpf(&B, "\nabsmipgap = %g, relmipgap = %g", absmipgap, relmipgap); if (retmipgap & 1) { suf_rput("relmipgap", ASL_Sufkind_obj, &relmipgap); suf_rput("relmipgap", ASL_Sufkind_prob, &relmipgap); } if (retmipgap & 2) { suf_rput("absmipgap", ASL_Sufkind_obj, &absmipgap); suf_rput("absmipgap", ASL_Sufkind_prob, &absmipgap); } #endif if (stat1 != 1) { SI = solinfo + stat1; Bpf(&B, "\nStatus recovering solution: %s", SI->msg); if (!stat1) Bpf(&B, ": stat = %d", stat10); if (solve_result_num < SI->code) solve_result_num = SI->code; } if (aggtries > 1) Bpf(&B, "\nTried aggregator %d times", aggtries); if (solve_result_num >= 200 && solve_result_num < 300) send_iis(asl, cpx, &B); if (send_statuses(asl, cpx, d)) Bpf(&B, "\nNo basis."); else if (asl->i.flags & 1 && method > 0) { j = 1; switch(stat) { /* Note: stat values have been adjusted to accord with */ /* earlier CPLEX versions -- don't use CPX_STAT_INFEASIBLE */ /* or CPX_STAT_UNBOUNDED here... */ case 2: /*infeasible*/ if (wantray(1,&cpx,&itc,&itci,nelqf)) { j = send_dray(asl,cpx,nelqf); Bpf(&B, dray_msg[j]); } goto j_check; case 3: /*unbounded*/ if (wantray(0,&cpx,&itc,&itci,0)) Bpf(&B, (j = send_ray(asl,cpx)) ? "\nfailed to compute variable.unbdd" : "\nvariable.unbdd returned"); j_check: *pcpx = cpx; if (itc) { Bpf(&B, "\n%d extra %ssimplex iterations for ray", itc, algname); if (itci) Bpf(&B, " (%d in phase I)",itci); } if (!j) solve_result_num += 10; } } if (basis_cond) { if (CPXgetdblquality(Env, cpx, &bcond, CPX_KAPPA)) { Bpf(&B, "\nBasis condition is unavailable."); bcond = 0; } else Bpf(&B, "\nBasis condition = %g", bcond); if (n_obj > 0) suf_rput("basis_cond", ASL_Sufkind_obj, &bcond); suf_rput("basis_cond", ASL_Sufkind_prob, &bcond); } #ifdef CPX_PARAM_MIPKAPPASTATS if (haveqmet) { Bpf(&B, "\n%s = %.3g", QualInfo[0].desc, qmet[0]); for(j = 1; j < haveqmet; ++j) if (qmet[j] > 0.) Bpf(&B, "\n%s = %.3g", QualInfo[j].desc, qmet[j]); } #endif if (nround) { wb = ""; if (nround < 0) { nround = -nround; wb = "would be "; } Bpf(&B, "\n%d integer variables %srounded (maxerr = %g).", nround, wb, w[0]); if (w[0] > intwarn_tol && 0.5*w[0] > w[2]) Bpf(&B, "\nAssigning integrality = %.1g might help." "\nCurrently integrality = %g.", 0.5*w[0], w[1]); } #if CPX_VERSION >= 1100 if (npt != opt) CPXchgprobtype(Env, cpx, opt); if (cutstats && nint1) for(CI = Cut_Info; CI->cutname; ++CI) if (!CPXgetnumcuts(Env, cpx, CI->cuttype, &j) && j > 0) Bpf(&B, "\n%d %s cut%s", j, CI->cutname, j == 1 ? "" : "s"); #endif #ifdef CPX_PARAM_POPULATELIM if (Optimize == CPXmipopt && poolstub && x) poolwrite(asl, cpx, d, nelqf, &B); if (pretunefile) tunewrite(pretunefile, "pretunefile", &B); #endif #if CPX_VERSION >= 1000 /*{*/ if (pretunefileprm) tunewriteprm(pretunefileprm, "pretunefileprm", &B); #ifdef CPX_TUNE_TILIM /* CPLEX 11 */ if (tunefile || tunefileprm) { tunerun(cpx, &B); if (tunefile) tunewrite(tunefile, "tunefile", &B); if (tunefileprm) tunewriteprm(tunefileprm, "tunefileprm", &B); } #endif #endif /*}*/ #ifdef CPXERR_QCP_SENSE if (nlc) { if (y && x && want_qcdual && SI->wantobj) qcduals(asl, &B, cpx, d, x, y); else y = 0; } #endif write_sol(hbuf, x, y, &Oinfo); #ifdef USE_CHANNELS if (logfname) { CPXsetlogfilename(Env, logfname, "a"); CPXgetchannels(Env, NULL, NULL, NULL, &cpxlog); Bpf(&B, "\n"); CPXmsgstr(cpxlog, hbuf); CPXsetlogfilename(Env, NULL, NULL); logfname = 0; } #else if (Logf) { FILE *f; CPXsetlogfile(Env, NULL); CPXfclose(Logf); Logf = 0; if ((f = fopen(*file_name[set_logname], "a"))) { fprintf(f, "%s\n", hbuf); fclose(f); } } #endif } static void show_times(void) { int i; Times[3] = xectim_(); for(i = 1; i <= 2; ++i) if (time_flag & i) { fprintf(i == 1 ? stdout : Stderr, "\nTimes (seconds):\nInput = %g\nSolve = %g\nOutput = %g\n", Times[1] - Times[0], Times[2] - Times[1], Times[3] - Times[2]); } #if CPX_VERSION >= 12050000 if (!DTimes_failed) for(i = 4; i <= 8; i += 4) if (time_flag & i) { fprintf(i == 4 ? stdout : Stderr, "\nTimes (ticks):\nInput = %g\nSolve = %g\nOutput = %g\n", DTimes[1] - DTimes[0], DTimes[2] - DTimes[1], DTimes[3] - DTimes[2]); } if (time_flag & 0x30 && num_cores) { for(i = 16; i <= 32; i += 16) if (time_flag & i) fprintf(i == 16 ? stdout : stderr, "\n%d logical cores are available.\n", num_cores); } #endif } static void basread(ASL *asl, cpxlp *cpx) { if (CPXreadcopybase(Env, cpx, startbas)) { printf("Could not read starting basis file \"%s\"\n", startbas); need_nl = 0; } } static void CPXPUBLIC mymsgfunc(void *handle, Const char *msg) { static int wantnl; Const char *msg1; handle = handle; /* shut up non-use warning */ #if CPX_VERSION >= 12070100 if (!strncmp(msg, "CPXPARAM", 8)) return; #endif #ifdef USE_CHANNELS if (logfname) CPXmsgstr(cpxlog, msg); #else if (Logf) CPXfputs(msg, Logf); #endif if (!strncmp(msg, "Tried aggregator ", 17)) aggtries = atoi(msg+17); else if (prestats) { if (!netopting || !strncmp(msg,"Extract",7)) goto print_msg; } else if (!netopting) { msg1 = msg; switch(*msg) { case 'M': if (msg[1] != 'I') break; msg1++; /* no break */ case 'L': case 'Q': if (msg1[1] == 'P' && msg1[2] == ' ') msg1 += 3; } switch(*msg1) { case 'A': if (strncmp(msg,"Aggregator",10)) goto accept; break; case 'N': if (strncmp(msg,"No presolve",11)) goto accept; break; case 'P': if (!strncmp(msg,"Presolve",8)) { wantnl = !strchr(msg+8,'\n'); break; } /* no break */ default: accept: if (wantnl) wantnl = !strchr(msg,'\n'); else { print_msg: printf("%s", msg); fflush(stdout); /* in case AMPL is */ /* writing a log file */ } } } } static char iis_table[] = "\n\ 0 non not in the iis\n\ 1 low at lower bound\n\ 2 fix fixed\n\ 3 upp at upper bound\n\ 4 mem member\n\ 5 pmem possible member\n\ 6 plow possibly at lower bound\n\ 7 pupp possibly at upper bound\n\ 8 bug\n"; static SufDecl suftab[] = { { "absmipgap", 0, ASL_Sufkind_obj | ASL_Sufkind_outonly }, { "absmipgap", 0, ASL_Sufkind_prob | ASL_Sufkind_outonly }, { "basis_cond", 0, ASL_Sufkind_obj | ASL_Sufkind_outonly }, { "basis_cond", 0, ASL_Sufkind_prob | ASL_Sufkind_outonly }, #ifdef CPXPARAM_Benders_Strategy { "benders", 0, ASL_Sufkind_var }, #endif { "bestbound", 0, ASL_Sufkind_obj | ASL_Sufkind_outonly }, { "bestbound", 0, ASL_Sufkind_prob | ASL_Sufkind_outonly }, { "bestnode", 0, ASL_Sufkind_obj | ASL_Sufkind_outonly }, { "bestnode", 0, ASL_Sufkind_prob | ASL_Sufkind_outonly }, { "current", 0, ASL_Sufkind_con | ASL_Sufkind_outonly }, { "current", 0, ASL_Sufkind_var | ASL_Sufkind_outonly }, { "direction", 0, ASL_Sufkind_var }, { "down", 0, ASL_Sufkind_con | ASL_Sufkind_outonly }, { "down", 0, ASL_Sufkind_var | ASL_Sufkind_outonly }, { "dunbdd", 0, ASL_Sufkind_con | ASL_Sufkind_outonly }, { "iis", iis_table, ASL_Sufkind_var | ASL_Sufkind_outonly }, { "iis", 0, ASL_Sufkind_con | ASL_Sufkind_outonly }, #ifdef CPX_PARAM_FEASOPTMODE /* >= 9.2b */ { "lazy", 0, ASL_Sufkind_con }, #endif #ifdef CPX_PARAM_POPULATELIM { "npool", 0, ASL_Sufkind_obj | ASL_Sufkind_outonly}, { "npool", 0, ASL_Sufkind_prob | ASL_Sufkind_outonly}, #endif #ifndef NO_MOkwf { "objabstol", 0, ASL_Sufkind_obj | ASL_Sufkind_real }, { "objpriority", 0, ASL_Sufkind_obj }, { "objreltol", 0, ASL_Sufkind_obj | ASL_Sufkind_real }, { "objweight", 0, ASL_Sufkind_obj | ASL_Sufkind_real }, #endif { "priority", 0, ASL_Sufkind_var }, { "ref", 0, ASL_Sufkind_var | ASL_Sufkind_real }, { "relmipgap", 0, ASL_Sufkind_obj | ASL_Sufkind_outonly }, { "relmipgap", 0, ASL_Sufkind_prob | ASL_Sufkind_outonly }, { "sos", 0, ASL_Sufkind_var }, { "sos", 0, ASL_Sufkind_con }, { "sosno", 0, ASL_Sufkind_var | ASL_Sufkind_real }, { "sosref", 0, ASL_Sufkind_var | ASL_Sufkind_real }, { "sstatus", 0, ASL_Sufkind_var, 1 }, { "sstatus", 0, ASL_Sufkind_con, 1 }, { "unbdd", 0, ASL_Sufkind_var | ASL_Sufkind_outonly}, { "up", 0, ASL_Sufkind_con | ASL_Sufkind_outonly }, { "up", 0, ASL_Sufkind_var | ASL_Sufkind_outonly } }; static void adjust_version(ASL *asl) { char *t; const char *s; int n; s = CPXversion(Env); n = 2*strlen(s) + 19; Oinfo.bsname = M1alloc(n); t = strcpy1(Oinfo.bsname, "CPLEX "); t = strcpy1(t, s); Oinfo.version = ++t; t = strcpy1(t, "AMPL/"); t = strcpy1(t, Oinfo.bsname); } static int Optimize1(CPXENVptr e, cpxlp *c) { int k, rc; #ifdef CPX_PARAM_POPULATELIM #ifdef Want_Distmipopt const char *cname; char *s, *t; int (CPXPUBLIC *vmconf)(CPXENVptr, const char*); size_t L; if ((s = vmconfig) && *s) { if (*s == '@') { ++s; cname = "CPXreadcopyvmconfig"; vmconf = CPXreadcopyvmconfig; } else { cname = "CPXcopyvmconfig"; vmconf = CPXcopyvmconfig; } if ((k = vmconf(e,s))) { solve_result_num = 580; asl->i.uinfo = t = (char*)M1alloc(L = strlen(s) + 80); Snprintf(t, L, "Return %d from %s(e, \"%s\").", k, cname, s); longjmp(Jb,1); } rc = CPXdistmipopt(e, c); CPXdelvmconfig(e); } else #endif if (Optimize == CPXmipopt) { if (populate == 2 && poolstub) rc = CPXpopulate(e,c); else { if (!poolstub) CPXsetintparam(Env, CPX_PARAM_SOLNPOOLCAPACITY, 0); rc = CPXmipopt(e,c); } } else #endif rc = Optimize(e, c); if (rc == CPXERR_PRESLV_INForUNBD #ifdef CPX_STAT_INForUNBD /* >= 8.0 */ || CPXgetstat(e,c) == CPX_STAT_INForUNBD #endif ) { CPXsetintparam(e, CPX_PARAM_AGGIND, 0); CPXsetintparam(e, CPX_PARAM_PREIND, 0); rc = Optimize(e, c); } #ifdef CPX_PARAM_FEASOPTMODE /* >= 9.2b */ if (want_feasopt) switch(k = CPXgetstat(e,c)) { case CPX_STAT_INFEASIBLE: case CPX_INTEGER_INFEASIBLE: case CPX_STAT_INForUNBD: case CPXMIP_INForUNBD: case CPXMIP_INFEASIBLE: rc = feasopt(e, c); } #endif /*CPX_PARAM_FEASOPTMODE*/ return rc; } int main(int argc, char **argv) { CPXCHANNELptr cpxresults; char *s, *solmsg, *stub; dims d; const char *fmt; int nelqf, nint1, nms, nos, *nosp, rc, status, z; size_t L; /* static values for use with longjmp */ static cpxlp *cpx; static sig_func_type *oic; static FILE *nl; Times[0] = xectim_(); Oinfo.bsname = basename(argv[0]); /* in case CPXopenCPLEX fails */ #ifdef BARRIER asl = ASL_alloc(ASL_read_fg); #else asl = ASL_alloc(ASL_read_f); #endif mdbl_val[0].U = Infinity; Env = 0; cpx = 0; breaking = 0; oic = 0; nl = 0; rc = setjmp(Jb); if (rc) { if (nl) fclose(nl); --rc; if (solve_result_num > 0){ if (amplflag | (Oinfo.wantsol & 1)) rc = 0; goto ws_now; } goto done; } if (argc < 2) #ifdef Stand_alone return cpxmain(argc,argv); #else usage_ASL(&Oinfo, 1); #endif #ifndef KEEP_BANNER /* keep banner only if first arg is -v */ if (argc > 1 && *(stub = argv[1]) == '-' && stub[1] == 'v') nos = -1; else { nos = dup(2); close(2); z = open("/dev/null",O_WRONLY); /* should return 2 */ } #endif #ifdef LICENSE_FILE if (!(stub = getenv("ILOG_LICENSE_FILE")) || !*stub) putenv("ILOG_LICENSE_FILE=" LICENSE_FILE); #endif if ((Env = CPXopenCPLEX(&z))) { #if CPX_VERSION >= 12050000 DTimes_failed = CPXgetdettime(Env, &DTimes[0]); #endif adjust_version(asl); } #ifndef KEEP_BANNER if (nos >= 0) { close(2); dup(nos); /* should dup onto 2 */ close(nos); } #endif #if CPX_VERSION >= 12100000 CPXsetintparam(Env, CPX_PARAM_PARAMDISPLAY, 0); #endif /* prepare to return error messages in .sol file */ if (!(stub = getstub(&argv, &Oinfo))) usage_ASL(&Oinfo, 1); nl = jac0dim(stub, (fint)0); #ifdef CPXERR_IN_INFOCALLBACK /* CPLEX 11 */ CPXsetterminate(Env, &breaknow); #endif oic = signal(SIGINT, intcatch); if (!Env) { if (amplflag) { badlic(570, z); goto ws_now; } badlic(0, z); goto done; } if ((z = CPXgetchannels(Env, &cpxresults, 0,0,0))) { badret("CPXgetchannels", z, 531); goto ws_now; } suf_declare(suftab, sizeof(suftab)/sizeof(SufDecl)); amplin(asl, &cpx, &nl, &d, &nelqf, &nint1, argv); if (!cpx) { if (solve_result_num > 0) { ws_now: L = strlen(Oinfo.bsname); fmt = "%s"; if ((s = (char*)asl->i.uinfo)) { L += strlen(s); fmt = "%s: %s"; } solmsg = (char*)M1alloc(L+3); sprintf(solmsg, fmt, Oinfo.bsname, s); write_sol(solmsg, 0, 0, &Oinfo); } else { printf("Failed to load the problem!\n"); rc = 1; } goto done; } if (startsol && CPXreadcopysol(Env, cpx, startsol)) printf("Failed to read startsol file \"%s\".\n", startsol); if (wrtfname && (status = CPXwriteprob(Env, cpx, wrtfname, NULL))) badwrite(581, "writeprob=\"%s\" failed with status %d.\n", wrtfname, status); if (startbas) basread(asl, cpx); #ifdef BARRIER #if !defined(NO_DEPRECATED) && CPX_VERSION < 12070000 if (startvec && (status = CPXreadcopyvec(Env, cpx, startvec))) printf("\n*** return %d from CPXreadcopyvec.\n", status); #endif #endif #ifdef CPX_PARAM_IISIND /* version < 9.2b */ #ifdef CPLEX_MIP if (nint1 && starttree) treeio(cpx, starttree, "read", CPXreadcopytree); #endif #endif fflush(stdout); if (wrtmipstart) { if (!(nms = CPXgetnummipstarts(Env, cpx))) { if (!(nl = fopen(wrtmipstart, "w"))) badwrite(582, "writemipstart=\"%s\" failed: could not create an\n" "empty file to indidate that no MIP start is available.\n", wrtmipstart, status); fclose(nl); nl = 0; } else if ((status = CPXwritemipstarts(Env, cpx, wrtmipstart, 0, nms-1))) badwrite(582, "writemipstart=\"%s\" failed:\n" "\tCPXwritemipstarts() returned %d.\n", wrtmipstart, status); } if (nosolve) { badretfmt(600, "Not solved because of \"nosolve\".\n"); exit(1); } Times[1] = xectim_(); #if CPX_VERSION >= 12050000 if (!DTimes_failed) DTimes_failed = CPXgetdettime(Env, &DTimes[1]); #endif nosp = 0; CPXdisconnectchannel(Env, cpxresults); CPXaddfuncdest(Env, cpxresults, 0, mymsgfunc); if (use_netopt) { nos = netopt(cpx,&d,&net_status,&net_nodes,&net_arcs,&netiters); if (nos) net_status = 0; nosp = &net_status; } if (prestats && Optimize == CPXmipopt) { CPXpresolve(Env, cpx, CPX_ALG_NONE); /* Collect presolve statistics. */ lpcbf(Env, 0, -1, 0); /* Turn off call-backs to allow use of multiple threads in CPXmipopt. */ CPXsetmipcallbackfunc(Env, 0, 0); CPXsetlpcallbackfunc(Env, 0, 0); } status = Optimize1(Env,cpx); Times[2] = xectim_(); #if CPX_VERSION >= 12050000 if (!DTimes_failed) DTimes_failed = CPXgetdettime(Env, &DTimes[2]); #endif breaking = 1; /* reset in case, e.g., amplout runs CPXprimopt */ if (endbas && !nint1) write_basis(cpx); if (endsol && CPXsolwrite(Env, cpx, endsol)) printf("Failed to write endsol file \"%s\"\n", endsol); #ifdef CPX_PARAM_IISIND /* version < 9.2b */ #ifdef CPLEX_MIP if (nint1 && endtree) treeio(cpx, endtree, "write", (Treeio)CPXtreewrite); #endif #endif amplout(asl, &cpx, &d, status, nelqf, nint1, nosp); done: if (oic) signal(SIGINT, oic); #if CPX_VERSION >= 12050000 if (!DTimes_failed) DTimes_failed = CPXgetdettime(Env, &DTimes[3]); #endif if (cpx) CPXfreeprob(Env, &cpx); if (Env) CPXcloseCPLEX(&Env); ASL_free(&asl); show_times(); return rc; } void mainexit_ASL(int rc) { longjmp(Jb, rc+1); }