/**************************************************************** Copyright (C) 1997-1999 Lucent Technologies All Rights Reserved 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, and that the name of Lucent or any of its entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES 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" #define OBJ_ADJ #ifdef __cplusplus #define CPX_PROTOTYPE_ANSI #else #ifdef KR_headers #define CPX_PROTOTYPE_CKR #define size_t int #else #define CPX_PROTOTYPE_ANSI #endif #endif #include "cplex.h" #define STDIO_H_included #include "nlp.h" #include "getstub.h" #include "signal.h" #ifndef CPXPUBLIC /* version 5 */ #define CPXPUBLIC /* nothing */ #define CPXfopen fopen #define CPXFILEptr FILE* #define CPXfputs(a,b) fprintf(b,a) #endif #ifdef Sig_ret_type #ifndef SigRet #define SigRet return 0 #endif #else #define Sig_ret_type void #define SigRet /*nothing*/ #endif #ifndef Sig_func_type typedef void sig_func_type ANSI((int)); #endif static ASL *asl; typedef struct cpxlp cpxlp; typedef struct mint_values { int L; int U; int val; } mint_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_fcpri = 12, set_sos = 13 }; static mint_values mint_val[14] = { /* set_crossover */ 0, 2, 1, /* set_dualthresh */ -0x7fffffff, 0x7fffffff, 32000, /* set_netopt */ 0, 2, 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, /* set_timing */ 0, 3, 0, /* set_iis */ 0, 2, 0, /* set_mipststat */ 0, 1, 1, /* set_mipstval */ 0, 1, 1, /* set_fcpri */ 0, 0x7fffffff, 3, /* set_sos */ 0, 1, 1 }; #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 fcpri mint_val[12].val #define sos mint_val[13].val static char hybmethod = 'o'; static int netiters = -1; static CPXFILEptr Logf; extern char cplex_version[]; static char *baralgname, *endbas, *endtree, *endvec, *logfname, *version; static char *startbas, *starttree, *startvec, *wrtfname; static int breaking, costsens, dispzap, mbas, method, nbas, netopting; static int objadj, objsen, relax, zap_lpcbf; static int aggtries, net_status, net_nodes, net_arcs, net_its; static double obj_adj; typedef struct Cbfinfo { int agg, disp, m, mipdisp, n, n0[4], nint, npr, pres; } Cbfinfo; static Cbfinfo cbi; /* Stuff to cope with current CPLEX political correctness... */ static CPXENVptr Env; #define disconnectchannel(a) CPXdisconnectchannel(Env,a) #define addfuncdest(a,b,c) CPXaddfuncdest(Env,a,b,c) #define getitfoind(a) CPXgetintparam(Env, CPX_PARAM_SIMDISPLAY, a) #define setitfoind(a,b,c) CPXsetintparam(Env, CPX_PARAM_SIMDISPLAY, a) #define netopt(a,b,c,d,e) CPXnetopt(Env, a,b,c,d,e) #ifdef KR_headers static int (CPXPUBLIC *Optimize)(); #else static int (CPXPUBLIC *Optimize)(CPXENVptr, cpxlp*); #endif static jmp_buf Jb; Sig_ret_type #ifdef KR_headers intcatch(n) int n; #else intcatch(int n) #endif { printf("\n (cplex)\n", n); fflush(stdout); if (++breaking > 3) longjmp(Jb, 2); signal(SIGINT, intcatch); SigRet; } static int CPXPUBLIC #ifdef KR_headers breakcallback(e, c, w, h) CPXENVptr e; void *c; int w; void *h; #else breakcallback(CPXENVptr e, void *c, int w, void *h) #endif { Not_Used(e); Not_Used(c); Not_Used(w); Not_Used(h); return breaking > 1; } #ifdef BARRIER static int CPXPUBLIC #ifdef KR_headers Optimize2(e, c) CPXENVptr e; cpxlp *c; #else Optimize2(CPXENVptr e, cpxlp *c) #endif { return CPXhybbaropt(e, c, hybmethod); } static int CPXPUBLIC Optimizebar(CPXENVptr e, cpxlp *c) { int rv, s; if (!(rv = CPXbaropt(e, c)) && endvec && (s = CPXvecwrite(e, c, endvec))) printf("\n*** return %d from CPXvecwrite.\n", s); return rv; } static void set_baropt(VOID) { if (crossover) { Optimize = Optimize2; if (crossover == 1) { baralgname = " crossover primal simplex"; hybmethod = 'o'; } else { baralgname = " crossover dual simplex"; hybmethod = 't'; } } else { Optimize = Optimizebar; baralgname = " barrier"; } } static int #ifdef KR_headers startcomp(asl,n0,m,nextra,ka,kal,ia,a,b,c,cdualp,cprimp,rdualp,rprimp) ASL *asl; int n0, m, nextra, *ka, *kal, *ia; double *a, *b, *c, **cdualp, **cprimp, **rdualp, **rprimp; #else startcomp(ASL *asl, int n0, int m, int nextra, int *ka, int *kal, int *ia, double *a, double *b, double *c, double **cdualp, double **cprimp, double **rdualp, double **rprimp) #endif { double *r, t, *x, *y; int i, j, k; int n = n0 - objadj; /* Why can't CPXcopystart do this calculation? */ if (!X0 && !pi0) return 0; 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 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)); typedef struct dims { int nrows; /* as seen by CPLEX */ double *c; double *x; double *y; int *cstat; int *rstat; SufDesc *csd; SufDesc *rsd; char *rtype; } dims; #ifdef CPLEX_MIP static void #ifdef KR_headers treeio(cpx, fname, what, tio) cpxlp *cpx; char *fname, *what; int (CPXPUBLIC *tio)(); #else treeio(cpxlp *cpx, char *fname, char *what, int (CPXPUBLIC *tio)(CPXENVptr,cpxlp*,char*)) #endif { if ((*tio)(Env,cpx,fname)) { printf("Could not %s tree file \"%s\".\n", what, fname); need_nl = 0; } } #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_version = 8, set_sens = 9 }; static char * #ifdef KR_headers sf_known(oi, kw, v) Option_Info *oi; keyword *kw; char *v; #else sf_known(Option_Info *oi, keyword *kw, char *v) #endif { switch(Intcast kw->info) { #ifdef BARRIER case set_barrier: set_baropt(); break; #endif case set_dual: method = -1; break; case set_dualopt: Optimize = CPXdualopt; 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; baralgname = ""; break; case set_relax: relax = 1; break; case set_version: #ifdef Student_Edition #define Fmt "%sStudent %s\n" #else #define Fmt "%s%s\n" #endif printf(Fmt, oi->nnl ? "\n" : "", version); oi->option_echo &= ~ASL_OI_echothis; #undef Fmt if (oi->option_echo & ASL_OI_clopt) exit(0); break; case set_sens: costsens = 1; break; } return v; } static void #ifdef KR_headers badival(oi, kw, t, L, U) Option_Info *oi; keyword *kw; int t, L, U; #else badival(Option_Info *oi, keyword *kw, int t, int L, int U) #endif { printf("rejecting %s %d; must be between %d and %d\n", kw->name, t, L, U); badopt_ASL(oi); } static char * #ifdef KR_headers sf_mint(oi, kw, v) Option_Info *oi; keyword *kw; char *v; #else sf_mint(Option_Info *oi, keyword *kw, char *v) #endif { 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; #ifdef BARRIER if (i == set_crossover) set_baropt(); #endif return rv; } static char * #ifdef KR_headers sf_int(oi, kw, v) Option_Info *oi; keyword *kw; char *v; #else sf_int(Option_Info *oi, keyword *kw, char *v) #endif { int f, t, z[3]; char *rv, *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 (CPXsetintparam(Env, f, t)) { z[2] = 0; z[1] = 1; CPXinfointparam(Env, f, z, z+1, z+2); badival(oi, kw, t, z[1], z[2]); } return rv; } /* 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 * #ifdef KR_headers sf_dbl(oi, kw, v) Option_Info *oi; keyword *kw; char *v; #else sf_dbl(Option_Info *oi, keyword *kw, char *v) #endif { double t, z[3]; char *rv, *what = kw->name; int 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 (CPXsetdblparam(Env, f, t)) { 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; } static char **file_name[8] = { &endbas, &endtree, &startbas, &starttree, &endvec, &startvec, &logfname, &wrtfname }; enum { /* sf_char f values */ set_endbas = 0, set_endtree = 1, set_startbas = 2, set_starttree = 3, set_endvector = 4, set_startvector = 5, set_logname = 6, set_wrtfname = 7 }; static char * #ifdef KR_headers sf_char(oi, kw, v) Option_Info *oi; keyword *kw; char *v; #else sf_char(Option_Info *oi, keyword *kw, char *v) #endif { char *rv, *t; int f, 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] <= ' ') { if (!(t = *file_name[f])) t = ""; printf("%s=%s\n", kw->name, t); oi->option_echo &= ~ASL_OI_echothis; return v + 1; } for(rv = v; *++rv > ' ';); t = M1alloc(n = rv - v + 1); strncpy(t, v, --n); t[n] = 0; *file_name[f] = t; if (f == set_logname) { if (!(Logf = CPXfopen(t,"w"))) { printf("Cannot open logfile \"%s\"\n", t); badopt_ASL(oi); } else CPXsetlogfile(Env, Logf); } return rv; } #define VP (Char*) struct option_word { char *name; sfunc *sf; int ival; }; typedef struct option_word option_word; static keyword keywds[] = { /* must be in alphabetical order */ #ifdef CPLEX_MIP { "absmipgap", sf_dbl, VP CPX_PARAM_EPAGAP }, #endif { "advance", sf_int1, VP CPX_PARAM_ADVIND }, { "aggfill", sf_int, VP CPX_PARAM_AGGFILL }, { "agglim", sf_int, VP CPX_PARAM_AGGFILL }, { "aggregate", sf_int1, VP CPX_PARAM_AGGIND }, #ifdef CPLEX_MIP { "backtrack", sf_dbl, VP CPX_PARAM_BTTOL }, #endif #ifdef BARRIER { "baralg", sf_int, VP CPX_PARAM_BARALG }, { "barcorr", sf_int, VP CPX_PARAM_BARMAXCOR }, { "bardisplay", sf_int, VP CPX_PARAM_BARDISPLAY }, { "bargrowth", sf_dbl, VP CPX_PARAM_BARGROWTH }, { "bariterlim", sf_int, VP CPX_PARAM_BARITLIM }, { "barobjrange",sf_dbl, VP CPX_PARAM_BAROBJRNG }, { "baropt", sf_known, VP set_barrier }, { "barthreads", sf_int, VP CPX_PARAM_BARTHREADS }, { "barvarup",sf_dbl, VP CPX_PARAM_BARVARUP }, #endif { "basisinterval",sf_int, VP CPX_PARAM_BASINTERVAL }, #ifdef CPLEX_MIP { "branch", sf_int, VP CPX_PARAM_BRDIR }, { "branchdir", sf_int, VP CPX_PARAM_BRDIR }, { "cliques", sf_int, VP CPX_PARAM_CLIQUES }, #endif { "clocktype", sf_int, VP CPX_PARAM_CLOCKTYPE }, #ifdef CPLEX_MIP { "coeffreduce",sf_int1, VP CPX_PARAM_COEREDIND }, #endif #ifdef BARRIER { "comptol", sf_dbl, VP CPX_PARAM_BAREPCOMP }, #endif #ifdef CPLEX_MIP { "covers", sf_int, VP CPX_PARAM_COVERS }, #endif { "crash", sf_int, VP CPX_PARAM_CRAIND }, #ifdef BARRIER { "crossover", sf_mint, VP set_crossover }, { "dense", sf_int, VP CPX_PARAM_BARCOLNZ }, { "densecol", sf_int, VP CPX_PARAM_BARCOLNZ }, #endif { "dependency", sf_int1, VP CPX_PARAM_DEPIND }, { "dgradient", sf_int, VP CPX_PARAM_DPRIIND }, { "display", sf_int, VP CPX_PARAM_SIMDISPLAY }, { "doperturb", sf_int1, VP CPX_PARAM_PERIND }, { "dual", sf_known, VP set_dual }, { "dualopt", sf_known, VP set_dualopt }, { "dualthresh", sf_mint, VP set_dualthresh }, { "endbasis", sf_char, VP set_endbas }, #ifdef CPLEX_MIP { "endtree", sf_char, VP set_endtree }, #endif #ifdef BARRIER { "endvector", sf_char, VP set_endvector }, #endif #ifdef CPLEX_MIP { "fcvarpri", sf_mint, VP set_fcpri }, #endif { "feasibility",sf_dbl, VP CPX_PARAM_EPRHS }, #ifdef BARRIER { "growth", sf_dbl, VP CPX_PARAM_BARGROWTH }, /*== bargrowth*/ #endif #ifdef CPLEX_MIP { "heuristic", sf_int, VP CPX_PARAM_HEURISTIC }, #endif { "iisfind", sf_mint, VP set_iis }, #ifdef CPLEX_MIP { "integrality",sf_dbl, VP CPX_PARAM_EPINT }, #endif { "iterations", sf_int, VP CPX_PARAM_ITLIM }, { "iterlim", sf_int, VP CPX_PARAM_ITLIM }, { "logfile", sf_char, VP set_logname }, #ifdef CPLEX_MIP { "lowercutoff",sf_dbl, VP CPX_PARAM_CUTLO }, #endif { "lowerobj", sf_dbl, VP CPX_PARAM_OBJLLIM }, { "lowerobjlim",sf_dbl, VP CPX_PARAM_OBJLLIM }, { "lpdisplay", sf_int, VP CPX_PARAM_SIMDISPLAY }, { "lpiterlim", sf_int, VP CPX_PARAM_ITLIM }, { "lptimelim", sf_dbl, VP CPX_PARAM_TILIM }, { "markowitz", sf_dbl, VP CPX_PARAM_EPMRK }, { "maximize", sf_known, VP set_max }, { "minimize", sf_known, VP set_min }, #ifdef CPLEX_MIP { "mipalg", sf_int, VP CPX_PARAM_SUBALG }, { "mipalgorithm",sf_int, VP CPX_PARAM_SUBALG }, { "mipdisplay", sf_int, VP CPX_PARAM_MIPDISPLAY }, { "mipgap", sf_dbl, VP CPX_PARAM_EPGAP }, { "mipinterval",sf_int, VP CPX_PARAM_MIPINTERVAL }, { "mipsolutions", sf_int, VP CPX_PARAM_INTSOLLIM }, { "mipstartalg",sf_int, VP CPX_PARAM_STARTALG }, { "mipstartstatus", sf_mint, VP set_mipststat }, { "mipstartvalue", sf_mint, VP set_mipstval }, { "mipsubalg", sf_int, VP CPX_PARAM_SUBALG }, { "mipthreads", sf_int, VP CPX_PARAM_MIPTHREADS }, #endif { "netfind", sf_int, VP CPX_PARAM_NETFIND }, { "netfinder", sf_int, VP CPX_PARAM_NETFIND }, { "netopt", sf_mint, VP set_netopt }, #ifdef CPLEX_MIP { "node", sf_int, VP CPX_PARAM_NODELIM }, { "nodefile", sf_int, VP CPX_PARAM_NODEFILEIND }, { "nodelim", sf_int, VP CPX_PARAM_NODELIM }, { "nodes", sf_int, VP CPX_PARAM_NODELIM }, { "nodesel", sf_int, VP CPX_PARAM_NODESEL }, { "nodeselect", sf_int, VP CPX_PARAM_NODESEL }, { "objdifference", sf_dbl, VP CPX_PARAM_OBJDIF }, #endif { "objno", sf_mint, VP set_objno }, { "optimality", sf_dbl, VP CPX_PARAM_EPOPT }, { "optimize", sf_known, VP set_primalopt }, #ifdef BARRIER { "ordering", sf_int, VP CPX_PARAM_BARORDER }, #endif { "outlev", sf_int, VP CPX_PARAM_SIMDISPLAY }, { "perturb", sf_int1, VP CPX_PARAM_PERIND }, { "perturbation", sf_dbl, VP CPX_PARAM_EPPER }, { "perturbconst", sf_dbl, VP CPX_PARAM_EPPER }, { "pgradient", sf_int, VP CPX_PARAM_PPRIIND }, #ifdef CPLEX_MIP { "plconpri", sf_mint, VP set_conpri }, { "plobjpri", sf_mint, VP set_objpri }, #endif { "predual", sf_int, VP CPX_PARAM_PREDUAL }, { "presolve", sf_int1, VP CPX_PARAM_PREIND }, { "prestats", sf_mint, VP set_prestats }, { "pricing", sf_int, VP CPX_PARAM_PRICELIM }, { "primal", sf_known, VP set_primal }, { "primalopt", sf_known, VP set_primalopt }, #ifdef CPLEX_MIP { "priorities", sf_int1, VP CPX_PARAM_MIPORDIND }, #endif { "readbasis", sf_char, VP set_startbas }, #ifdef BARRIER { "readvector",sf_char, VP set_startvector }, #endif #ifdef CPLEX_MIP { "reducecostfix",sf_int1, VP CPX_PARAM_RCFIXIND }, #endif { "refactor", sf_int, VP CPX_PARAM_REINV }, #ifdef CPLEX_MIP { "relax", sf_known, VP set_relax }, { "relobjdif", sf_dbl, VP CPX_PARAM_RELOBJDIF }, { "relobjdiff", sf_dbl, VP CPX_PARAM_RELOBJDIF }, #endif { "scale", sf_int, VP CPX_PARAM_SCAIND }, { "sensitivity",sf_known, VP set_sens }, { "simthreads", sf_int, VP CPX_PARAM_SIMTHREADS }, { "singular", sf_int, VP CPX_PARAM_SINGLIM }, { "singularlim",sf_int, VP CPX_PARAM_SINGLIM }, #ifdef CPLEX_MIP { "solutionlim",sf_int, VP CPX_PARAM_INTSOLLIM }, { "sos", sf_mint, VP set_sos }, { "sos2", sf_mint, VP set_sos2 }, { "sosmin", sf_int, VP CPX_PARAM_SOSMINSZ }, { "sosscan", sf_int1, VP CPX_PARAM_SOSIND }, { "startalg", sf_int, VP CPX_PARAM_STARTALG }, { "startalgorithm",sf_int, VP CPX_PARAM_STARTALG }, { "startbasis", sf_char, VP set_startbas }, { "starttree", sf_char, VP set_starttree }, #ifdef BARRIER { "startvector",sf_char, VP set_startvector }, #endif { "subalg", sf_int, VP CPX_PARAM_SUBALG }, { "subalgorithm",sf_int, VP CPX_PARAM_SUBALG }, #endif { "time", sf_dbl, VP CPX_PARAM_TILIM }, { "timelimit", sf_dbl, VP CPX_PARAM_TILIM }, { "timing", sf_mint, VP set_timing }, { "tranopt", sf_known, VP set_dualopt }, #ifdef CPLEX_MIP { "treelimit", sf_dbl, VP CPX_PARAM_TRELIM }, { "treememlim", sf_dbl, VP CPX_PARAM_TRELIM }, { "treememory", sf_dbl, VP CPX_PARAM_TRELIM }, { "uppercutoff",sf_dbl, VP CPX_PARAM_CUTUP }, #endif { "upperobj", sf_dbl, VP CPX_PARAM_OBJULIM }, { "upperobjlim",sf_dbl, VP CPX_PARAM_OBJULIM }, #ifdef CPLEX_MIP { "varsel", sf_int, VP CPX_PARAM_VARSEL }, { "varselect", sf_int, VP CPX_PARAM_VARSEL }, #endif { "version", sf_known, VP set_version }, { "wantsol", WS_val, 0 }, { "writebasis", sf_char, VP set_endbas }, { "writeprob", sf_char, VP set_wrtfname }, #ifdef BARRIER { "writevector", sf_char, VP set_endvector }, #endif { "xxxstart", sf_int, VP CPX_PARAM_XXXIND } }; static Option_Info Oinfo = { "cplex", 0/*cplex_bsname*/, "cplex_options", keywds, nkeywds /*, 0, cplex_version+1*/}; static void badretfmt /*{*/ #ifdef KR_headers (va_alist) va_dcl { char *fmt; int rc; va_list ap; va_start(ap); rc = va_arg(ap, int); fmt = va_arg(ap, char*); /*}*/ #else (int rc, char *fmt, ...) { va_list ap; va_start(ap, fmt); /*}*/ #endif { char buf[128], *s; int k = vsprintf(buf, fmt, ap) + 1; if (rc) { solve_result_num = rc; memcpy(s = (char*)M1alloc(k), buf, k); asl->i.uinfo = s; } if (!amplflag || !rc) fprintf(Stderr, "%s\n", buf); }} static void #ifdef KR_headers badret(what, i, rc) char *what; int i, rc; #else badret(char *what, int i, int rc) #endif { badretfmt(rc, "%s failed; error code %d.", what, i); } static void #ifdef KR_headers nonlin(n, rc, what) int n, rc; char *what; #else nonlin(int n, int rc, char *what) #endif { if (n) { badretfmt(rc, "%s contains %s.\n", filename, what); exit(4); } } static unsigned #ifdef KR_headers namemem(n) int n; #else namemem(int n) #endif { int k, L; unsigned rv; L = 3; k = 9; rv = 0; while(n > k) { rv += k*L++; n -= k; k *= 10; } return rv + n*L; } static char * #ifdef KR_headers namegen(stub, name, s, n) char *stub, **name, *s; int n; #else namegen(char *stub, char **name, char *s, int n) #endif { 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 void #ifdef KR_headers make_names(cnamep, rnamep) char ***cnamep, ***rnamep; #else make_names(char ***cnamep, char ***rnamep) #endif { char **cname, **rname, *s; unsigned cstorsz, rstorsz; cstorsz = namemem(nbas); rstorsz = namemem(mbas); *cnamep = cname = (char **)Malloc((mbas+nbas)*sizeof(char *) + cstorsz + rstorsz); *rnamep = rname = cname + nbas; s = namegen("x", cname, (char *)(rname + mbas), nbas); namegen("c", rname, s, mbas); } #ifdef CPLEX_MIP static int #ifdef KR_headers nzeros(p, n) int *p; int n; #else nzeros(int *p, int n) #endif { int *pe = p + n; n = 0; while(p < pe) if (*p++) n++; return n; } static void #ifdef KR_headers mip_priorities(asl, cpx) ASL *asl; cpxlp *cpx; #else mip_priorities(ASL *asl, cpxlp *cpx) #endif { 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 #ifdef KR_headers set_mipinit(asl, cpx, nint) ASL *asl; cpxlp *cpx; int nint; #else set_mipinit(ASL *asl, cpxlp *cpx, int nint) #endif { int i, m, *r; real *L, *U, *v; r = (int*)Malloc(nint*sizeof(int)); m = n_var - (niv + nbv); v = X0 + m; L = LUv + m; U = Uvx + m; for(i = 0; i < nint; i++) { r[i] = m + i; if (v[i] < L[i]) v[i] = L[i]; else if (v[i] > U[i]) v[i] = U[i]; } if (i = CPXcopymipstart(Env, cpx, nint, r, v)) badret("CPXcopymipstart", i, 0); else if (i = CPXsetintparam(Env, CPX_PARAM_MIPSTART, 1)) badret("CPXsetintparam(CPX_PARAM_MIPSTART)", i, 0); free(r); } #endif static int #ifdef KR_headers parval(par) int par; #else parval(int par) #endif { int rv; CPXgetintparam(Env, par, &rv); return rv; } static int CPXPUBLIC #ifdef KR_headers lpcbf(env, lp, wf, cbh) CPXENVptr env; char *lp, *cbh; int wf; #else lpcbf(CPXENVptr env, void *lp, int wf, void *cbh) #endif { int i; static int n[4]; static int wi[4] = { CPX_CALLBACK_INFO_PRESOLVE_ROWSGONE, CPX_CALLBACK_INFO_PRESOLVE_COLSGONE, CPX_CALLBACK_INFO_PRESOLVE_AGGSUBST, CPX_CALLBACK_INFO_PRESOLVE_COEFFS }; static char pfmt[] = "%sLP Presolve eliminated %d rows and %d columns.\n"; static int wf0; char *pfx, *prob; Not_Used(cbh); if (wf == CPX_CALLBACK_PRESOLVE) { for(i = 0; i < 4; i++) CPXgetcallbackinfo(env, lp, wf, wi[i], &n[i]); wf0 = wf; goto done; } if (wf == wf0) goto done; wf0 = wf; if (cbi.npr++ && !memcmp(n, cbi.n0, 4*sizeof(int))) goto done; memcpy(cbi.n0, n, 4*sizeof(int)); if (cbi.nint) { pfx = "MIP "; prob = "MIP"; } else { pfx = ""; prob = "LP"; } if (!(n[0] + n[1] + n[2])) { printf("No %s presolve or aggregator reductions.\n", prob); goto done; } if (cbi.pres) printf(pfmt, pfx, n[0], n[1]); if (n[2]) printf("Aggregator did %d substitutions.\n", n[2]); if (n[3]) printf("%d coefficients modified.\n", n[3]); done: return breaking > 1; } static void #ifdef KR_headers stat_map(stat, n, map, mx, what) int *stat; int n; int *map; int mx; char *what; #else stat_map(int *stat, int n, int *map, int mx, char *what) #endif { 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 #ifdef KR_headers get_statuses(asl, cpx, d) ASL *asl; cpxlp *cpx; dims *d; #else get_statuses(ASL *asl, cpxlp *cpx, dims *d) #endif { 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; if (!havestats || !mipststat && niv + nbv) return; if (method > 0) { stat_map(d->cstat, n, map, 6, "incoming cstat"); stat_map(d->rstat, m, map, 6, "incoming rstat"); d->cstat[n] = objadj; if (i = CPXcopybase(Env, cpx, d->cstat, d->rstat)) { bad_copybase: badret("CPXcopybase", i, 0); } return; } cs = (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] == 3 ? CPX_BASIC : CPX_AT_LOWER; } 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] = cstat[j] == 1 ? CPX_AT_LOWER : CPX_BASIC; 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) { if (U[j]) cs[i++] = cstat[j] == 4 ? CPX_BASIC : CPX_AT_LOWER; else rs[j] = cstat[j] == 4 ? CPX_BASIC : CPX_AT_LOWER; } } i = CPXcopybase(Env, cpx, cs, rs); free(cs); if (i) goto bad_copybase; } static int #ifdef KR_headers qmatadj(k, nr, os, colq, colqcnt, qmatp) int k, nr, os, *colq, *colqcnt; double **qmatp; #else qmatadj(int k, int nr, int os, int *colq, int *colqcnt, double **qmatp) #endif { 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.) { if (nbad < 3) { badd[nbad] = t; badk[nbad] = k; } nbad++; } } qmat[k] = t; } free(oqmat); 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 void #ifdef KR_headers sos_kludge(nsos, sosbeg, sosref) int nsos; int *sosbeg; double *sosref; #else sos_kludge(int nsos, int *sosbeg, double *sosref) #endif { /* Adjust sosref if necessary to accommodate CPLEX's */ /* undocumented requirement that sosref values differ */ /* by at least 1e-10. */ int i, j, k; 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) sosref[j] = t1 = t + 1e-10; t = t1; } } } static void #ifdef KR_headers amplin(asl, pcpx, nl, d, nintp, av) ASL *asl; cpxlp **pcpx, FILE **nl; dims *d; int *nintp; char **av; #else amplin(ASL *asl, cpxlp **pcpx, FILE **nl, dims *d, int *nintp, char **av) #endif { int *ia, *ia1, *ia2, *ja, *ka, *ka1, *ka2, *kal, *kal1, *kal2; double *a, *a1, *b, *b1, *c, *c1, *l, *l1, *le, *lrhs, *lx, *rngvec, *rv1, *u, *u1, *urhs, *ux; double nos, os; ograd *og, *og1; int i, j, k, m, m0, n, n0, nbv1, nextra, nint, nint1, nr, nsos, nz, nz1, nzc0, nzextra, nzr; int copri[2]; char **cname, **rname, *s, *senx; Char **zap[3]; #ifdef BARRIER fint nelqf, *colqf, *rowqf; int havestart, nelq, *colq, *colqcnt, *rowq; double *cdual, *cprim, *qmat, *rdual, *rprim; #endif char probname[48]; cpxlp *cpx; #ifdef CPLEX_MIP char *ctype; char *sostype; int nsosnz, *sosbeg, *sosind, *sospri; double *sosref; #endif /* 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 Optimize = CPXprimopt; baralgname = ""; aggtries = 0; if (!(mint_val[set_objno].U = n_obj)) objno = 0; nonlin(nlc, 550, "nonlinear constraints"); nonlin(nlvoi, 552, "nonlinear integer variables"); nonlin(plterms, 554, "piecewise-linear terms"); if (getopts(av, &Oinfo)) { if (amplflag) badretfmt(560, "Error in $cplex_options."); exit(1); } obj_no = objno - 1; m = n_con + 1; /* allow elbow room for obj_adj */ n = n_var + 1; nzr = nzc + 1; d->cstat = (int*)M1zapalloc((m+n+2)*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; a = A_vals = (double *)Malloc(nzr*Sizeof(double) + ((fint)nzr + n + 1)*sizeof(int)); zap[0] = M1record((Char*)a); zap[1] = zap[2] = 0; ia = A_rownos = (int *)(a + nzr); ka = A_colstarts = ia + nzr; #ifdef BARRIER nint = nbv + niv; if (Optimize == Optimize2 || Optimize == Optimizebar || nlo || nint && mipstval) want_xpi0 = 3; want_deriv = 0; qp_read(*nl,0); *nl = 0; /* Indicate closed file -- in case we're */ /* subsequently interrupted. */ nelqf = 0; if (obj_no >= 0 && obj_no < n_obj && (nelqf = mqpcheck(obj_no, &rowqf, &colqf, &qmat))) { if (nelqf < 0) { nonlin(nelqf == -2, 555, "a quadratic objective involving division by 0"); nonlin(1, 551, "a nonlinear objective"); } nonlin(nint, 553, "integer variables and a quadratic objective"); crossover = 0; set_baropt(); method = 1; } #else ed0read(*nl); *nl = 0; #endif #ifdef CPLEX_MIP if (!relax) { copri[0] = objpri; copri[1] = conpri; 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, &sospri, copri, &sosbeg, &sosind, &sosref); } #endif m = m0 = n_con; n = n0 = nr = n_var; nzc0 = nzc; nint = nbv + niv; 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; } } *nintp = nint1 = nint + nsos; if (use_netopt == 1 && !lnc) use_netopt = 0; if (nint1 || m <= 0) { method = 1; use_netopt = 0; } else if (!method) method = m - n > dual_thresh && !use_netopt ? -1 : 1; nbv1 = nbv; if (method < 0 && use_netopt == 1) use_netopt = 0; if (!nint) niv = nbv = nbv1 = 0; og = 0; if (obj_no >= 0 && obj_no < n_obj) { og = Ograd[obj_no]; 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); return; } *pcpx = cpx; n = n0; m = m0; nextra = 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++; } nzextra = 0; 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+2L*n+m)*sizeof(double) + (nz1+1L+n)*sizeof(int)); *zap[0] = (Char*)a; l = a + nz1; u = l + n; b = u + n; ia = (int *)(b + m); ka = ia + nz1; 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); #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+2L*nr)*sizeof(double) + m); d->y = d->x + nr; d->c = c = d->y + m; d->rtype = senx = (char*)(c + nr); rngvec = (double *)Malloc(m*Sizeof(double) + nr*Sizeof(int)); zap[1] = M1record((Char*)rngvec); kal = (int *)(rngvec + m); #ifdef CPLEX_MIP if (nint1) { Optimize = CPXmipopt; baralgname = ""; } #endif 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); 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; *--a1 = *--b1 = 1; *--kal1 = 1; *--ka1 = --nz1; *--s = 'E'; *--rv1 = 0; } #endif 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 || startvec || endvec || Optimize == CPXprimopt || Optimize == CPXdualopt || parval(CPX_PARAM_XXXIND)) { make_names(&cname, &rname); zap[2] = M1record((Char*)cname); } i = CPXcopylpwnames(Env, cpx, n, m, objsen, c, b, senx, ka, kal, ia, a, l, u, rngvec, cname, rname); d->nrows = m; if (i) { badret("CPXcopylpwnames", i, 531); bailout: CPXfreeprob(Env, pcpx); return; } #ifdef CPLEX_MIP if (nint1) { if (i = CPXcopyctype(Env, cpx, ctype)) { badret("CPXcopyctype", i, 531); goto bailout; } if (nsos) { sos_kludge(nsos, sosbeg, sosref); i = CPXcopysos(Env,cpx,nsos,nsosnz,sostype,sospri, sosbeg,sosind,sosref); free(sosref); if (i) { badret("CPXcopysos", i, 531); goto bailout; } } if (nint) { mip_priorities(asl, cpx); if (mipstval && X0 && (i = nbv1 + niv)) set_mipinit(asl, cpx, i); } } else #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 #ifdef BARRIER if (nelqf) { nelq = (int)nelqf; colq = (int*)Malloc(2*sizeof(int)*nr); colqcnt = colq + nr; if (sizeof(fint) != sizeof(int)) { /* should not happen */ rowq = (int*)Malloc(nelq*sizeof(int)); for(i = 0; i < nelq; i++) rowq[i] = (int)rowqf[i]; free(rowqf); } else rowq = (int*)rowqf; k = n_var; for(i = j = 0; i < k; i++) { colq[i] = (int)colqf[i]; colqcnt[i] = (int)(colqf[i+1] - colqf[i]); } free(colqf); for(;i < nr; i++) colq[i] = colqcnt[i] = 0; for(i = 0; ; i++) { if (i == k) { i = qmatadj(k, nr, objsen, colq, colqcnt, &qmat); if (!i) { for(i = k; i < nr; i++) qmat[i++] = 0.; i = CPXcopyqpsep(Env,cpx,qmat); if (i) badret("CPXcopyqpsep", i,531); } free(rowq); free(qmat); free(colq); if (i) goto bailout; baralgname = " separable QP barrier"; break; } if (!(j = colqcnt[i])) continue; if (j > 1 || rowq[colq[i]] != i) { i = CPXcopyquad(Env,cpx,colq, colqcnt,rowq,qmat); free(rowq); free(qmat); free(colq); if (i) { badret("CPXcopyquad", i, 531); goto bailout; } baralgname = " QP barrier"; break; } } } if (havestart) { if (i = CPXcopystart(Env,cpx,0,0,cprim,rprim,cdual,rdual)) badret("CPXcopystart", i, 0); } #endif } for(i = 0; i < 3; i++) 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 = parval(CPX_PARAM_MIPDISPLAY); #endif if (prestats && (dispzap = !cbi.disp || nint && !cbi.mipdisp)) { zap_lpcbf = 1; cbi.agg = parval(CPX_PARAM_AGGIND); cbi.m = m; cbi.n = n; cbi.nint = nint; cbi.pres = parval(CPX_PARAM_PREIND); CPXsetlpcallbackfunc(Env, lpcbf, 0); CPXsetmipcallbackfunc(Env, lpcbf, 0); } else { CPXsetlpcallbackfunc(Env, breakcallback, 0); CPXsetmipcallbackfunc(Env, breakcallback, 0); } breaking = 1; } static void #ifdef KR_headers round(x, n) double *x; fint n; #else round(double *x, fint n) #endif { double *xe; for(xe = x + n; x < xe; x++) *x = floor(*x + 0.5); } static char * #ifdef KR_headers failstat(j) int j; #else failstat(int j) #endif { 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"; case CPXERR_BOUNDS_INFEAS: return "contradictory bounds"; case CPXERR_PRESLV_INForUNBD: return "presolve: infeasible or unbounded problem"; case CPXERR_INDEX_RANGE: return "illegal list length"; case CPXERR_NET_SMALL: return "no network"; case CPXERR_NET_IMBALANCE: return "an infeasible or unbounded network"; case CPXERR_BAD_METHOD: return "unknown method after network optimization"; } sprintf(buf, "CPLEX error # %d.", j); return buf; } static int #ifdef KR_headers statadjust(stat) int stat; #else statadjust(int stat) #endif { if (stat > 100 && stat < 117) stat -= 71; else if (stat > 18 && stat < 42) stat -= 13; else if (stat == 1101) stat = 29; else if (stat < 0 || stat > 18) stat = 0; return stat; } static void #ifdef KR_headers write_basis(cpx) cpxlp *cpx; #else write_basis(cpxlp *cpx) #endif { if (CPXmbasewrite(Env, cpx, endbas)) { printf("Could not write ending basis to \"%s\"\n", endbas); need_nl = 0; } } static void #ifdef KR_headers cud_cadjust(asl) ASL *asl; #else cud_cadjust(ASL *asl) #endif { 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 #ifdef KR_headers Kludge_getbase(d, rstat) dims *d; int *rstat; #else Kludge_getbase(dims *d, int *rstat) #endif { /* Kludge around CPLEX bug in rstat values for <= constraints... */ int i, m = d->nrows; char *rt = d->rtype; for(i = 0; i < m; i++) if (rt[i] == 'L' && rstat[i] == 0) rstat[i] = 2; } static int #ifdef KR_headers send_statuses(asl, cpx, d) ASL *asl; cpxlp *cpx; dims *d; #else send_statuses(ASL *asl, cpxlp *cpx, dims *d) #endif { int i, j, m, n; int *cs, *cstat, *rs, *rstat; real *L, *U; static int map[] = {3, 1, 4, 6, 0}; if (!(asl->i.flags & 1)) 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); return 1; } 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)*(n_var + n_con)); U = L + n_var; 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 + n_var; U = L + n_con; 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; } return 0; } static int #ifdef KR_headers send_ray(asl, cpx) ASL *asl; cpxlp *cpx; #else send_ray(ASL *asl, cpxlp *cpx) #endif { int i, j, n, rc; int *cs, *rs; real *r, scale, *x; if (CPXgetijdiv(Env, cpx, &i, &j)) return 1; if ((n = n_var) < nbas) n = nbas; r = (real*)M1zapalloc(n*sizeof(real)); rc = 1; x = (real*)Malloc(mbas*sizeof(real) + (mbas+nbas)*sizeof(int)); cs = (int*)(x + mbas); rs = cs + nbas; if (CPXgetbase(Env, cpx, cs, rs)) goto done; scale = -1.; if (i >= 0) { if (CPXbinvcol(Env, cpx, i, x)) goto done; if (rs[i] == CPX_AT_UPPER) scale = 1.; } else if (j >= 0) { if (CPXbinvacol(Env, cpx, j, x)) goto done; if (cs[j] == CPX_AT_UPPER) scale = 1.; r[j] = -scale; } else goto done; for(i = 0; i < nbas; i++) if (cs[i] == CPX_BASIC) { if (CPXgetijrow(Env, cpx, -1, i, &j)) goto done; r[i] = scale*x[j]; } suf_rput("unbdd", ASL_Sufkind_var, r); rc = 0; done: free(x); return rc; } static void #ifdef KR_headers iis_put(asl, kind, n, ind, stat) ASL *asl; int kind; int n; int *ind; int *stat; #else iis_put(ASL *asl, int kind, int n, int *ind, int *stat) #endif { 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; } static int #ifdef KR_headers send_iis(asl, cpx, hbuf) ASL *asl; cpxlp *cpx; char *hbuf; #else send_iis(ASL *asl, cpxlp *cpx, char *hbuf) #endif { int i, j, m, m1, n, n1; int *ci, *cs, *ri, *rs; if (!want_iis) return 0; CPXsetintparam(Env, CPX_PARAM_IISIND, want_iis-1); if (i = CPXfindiis(Env, cpx, &m, &n)) return Sprintf(hbuf, "\nReturn %d from CPXfindiis.", i); ci = (int*)M1alloc((2*(m+n))*sizeof(int)); cs = ci + n; ri = cs + n; rs = ri + m; if (i = CPXgetiis(Env, cpx, &j, ri, rs, &m1, ci, cs, &n1)) return Sprintf(hbuf, "\nReturn %d from CPXgetiis.", i); iis_put(asl, ASL_Sufkind_var, n, ci, cs); iis_put(asl, ASL_Sufkind_con, m, ri, rs); return Sprintf(hbuf, "\nReturning %siis of %d variables and %d constraints.", j == 1 ? "" : "partial ", n, m); } static void #ifdef KR_headers amplout(asl, cpx, d, status, nint1, nosp) ASL *asl; cpxlp *cpx; dims *d; int status, nint1, *nosp; #else amplout(ASL *asl, cpxlp *cpx, dims *d, int status, int nint1, int *nosp) #endif { char buf[32], hbuf[512]; double obj, *l, *le, *u, *x, *x2, *y, *z, *z1; int ccpr, cl0, cl, cov, i, itc, itci, m, mipstat, n, nint, nodelim, nos, stat, stat0, stat10; int ii = 0, stat1 = 1; #ifdef CPLEX_MIP int nodecnt; #endif typedef struct { char *msg; int code; int wantobj; } Sol_info; Sol_info *SI; 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, 0 }, { "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 */ { "converged, primal feasible, dual infeasible", 301, 1 }, { "converged, primal and dual infeasible", 205, 1 }, { "primal objective limit reached", 405, 1 }, /* 35 */ { "dual objective limit reached", 406, 1 }, { "primal has unbounded optimal face", 001, 1 }, { "best solution found, primal-dual feasible", 100, 1 },/* 38 */ { "best solution found, primal infeasible", 206, 1 }, { "best solution found, dual infeasible", 302, 1 }, { "best solution found, primal-dual infeasible", 207, 1 }, /* 41 */ { "infeasible or unbounded in presolve", 208, 0 }, /*1101*/ #ifdef CPLEX_MIP { "optimal integer solution", 002, 1 }, /* 101 */ { "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 */ #endif }; static Sol_info solinfo1[] = { { "QP Hessian has diag. elements of the wrong sign", 541, 0 }, { "QP Hessian is not positive definite", 542, 0 } }; static char *netmsg[] = { "memory failure", "an infeasible or unbounded network", "an unbounded network", "an infeasible network", /*"an optimal network solution"*/ "", "no network", "a bug" }; #if 0 static char wantobj[] = {0,1,0,0,1,1,1,1,1,0,0,1, /* 0-11 */ 0,0,0,0,0,0,0, /* 12-18 */ 1,1,1,1,1,0,1,1,1,1, /* 32-41 */ 0, /* 1101 */ 1,1,0,1,1,0,1,0,1,0,1,0, 1,0,1,1}; #endif mipstat = 0; #ifdef CPLEX_MIP ccpr = 0; if (Optimize == CPXmipopt) { 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; } if (status > 0) { mipstat = statadjust(stat0 = status); status = 0; } } #endif m = n_con; n = n_var; x = d->x; y = d->y; itc = CPXgetitcnt(Env, cpx); itci = CPXgetphase1cnt(Env, cpx); nos = nosp ? *nosp + 5 : 0; switch (status) { case 0: break; case CPXERR_Q_NEG_ZERO_COMP: SI = solinfo1; goto have_SI; case CPXERR_Q_NOT_POS_DEF: SI = solinfo1 + 1; goto have_SI; case CPXERR_PRESLV_INForUNBD: SI = solinfo + 29; goto have_SI; default: stat0 = status; stat = 0; x = y = 0; goto have_stat; } #ifdef CPLEX_MIP if (nint1) { if (mipstat) { stat = mipstat; if (mipstat < 4 || mipstat > 8) { ii = 0; goto have_ii; } #if 0 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); } } #endif } else stat = statadjust(stat0 = CPXgetstat(Env, cpx)); ii = CPXgetmipitcnt(Env, cpx); nodecnt = CPXgetnodecnt(Env, cpx); have_ii: if (solinfo[stat].wantobj || endbas) { if (zap_lpcbf) { zap_lpcbf = 0; CPXsetlpcallbackfunc(Env, breakcallback, 0); CPXsetmipcallbackfunc(Env, breakcallback, 0); } CPXgetmipobjval(Env, cpx, &obj); CPXchgprobtype(Env, cpx, 3); status = CPXprimopt(Env, cpx); if (status) fprintf(Stderr, "CPLEX status %d with fixed integers:\n\t%s\n", status, solinfo[statadjust(status)].msg); if (endbas) write_basis(cpx); if (!solinfo[stat].wantobj) { x = y = 0; goto have_stat; } CPXsolution(Env, cpx, &stat1, &obj, x, y, 0, 0); stat1 = statadjust(stat10 = stat1); /* round to integer */ if (!relax) { nint = niv + nbv; x2 = x + n_var - nint; round(x2, nint); } } } else #endif { CPXsolution(Env, cpx, &stat, &obj, x, y, 0, 0); stat = nos == 3 ? 2 : statadjust(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: i = Sprintf(hbuf, "%s: %s", Oinfo.bsname, SI->msg); if (!stat) i += Sprintf(hbuf+i, ": %s", failstat(stat0)); #ifdef CPLEX_MIP else if (stat == 16 || stat == 17) { CPXgetintparam(Env, CPX_PARAM_NODELIM, &nodelim); i += Sprintf(hbuf+i, ".\nCurrent node limit = %d", nodelim); } #endif else if (!SI->wantobj) i += Sprintf(hbuf+i, "."); if (SI->wantobj) { g_fmtop(buf, obj); i += Sprintf(hbuf+i, "; objective %s", buf); } solve_result_num = SI->code; if (nosp) { if (nos < 0 || nos > 6) nos = 6; i += nos == 4 ? Sprintf(hbuf+i, "\n%d network simplex iterations.", netiters) : Sprintf(hbuf+i, "\nnetopt found %s.", netmsg[nos]); } #ifdef CPLEX_MIP if (nint1 && !mipstat) i += Sprintf(hbuf+i, "\n%d simplex iterations\n%d branch-and-bound nodes", ii, nodecnt); else #endif if (netiters < 0 || itc) { i += Sprintf(hbuf+i, "\n%d%s iterations", itc, ii ? " simplex" : baralgname); if (itc) #ifdef BARRIER if (!*baralgname) #endif i += Sprintf(hbuf+i, " (%d in phase I)", itci); if (ii) Sprintf(hbuf+i, "\n%d integer iterations", ii); } #ifdef CPLEX_MIP if (ccpr) { if (cl0 | cl | cov) { if (cl0) i += Sprintf(hbuf+i, "\n%d of %d clique inequalities used", cl, cl0); if (cov) i += Sprintf(hbuf+i, "\n%d cover cuts added", cov); } else i += Sprintf(hbuf+i, "\nNo clique or cover cuts used."); } #endif if (stat1 != 1) { i += Sprintf(hbuf+i, "\nStatus recovering solution: %s", solinfo[stat1].msg); if (!stat1) i += Sprintf(hbuf+i, ": stat = %d", stat10); } if (aggtries > 1) i += Sprintf(hbuf+i, "\nTried aggregator %d times", aggtries); if (solve_result_num >= 200 && solve_result_num < 300) i += send_iis(asl, cpx, hbuf+i); if (send_statuses(asl, cpx, d)) i += Sprintf(hbuf+i, "; no basis."); else if (stat == CPX_UNBOUNDED && asl->i.flags & 1 && method > 0) i += Sprintf(hbuf+i, send_ray(asl,cpx) ? "\nfailed to compute variable.unbdd" : "\nvariable.unbdd returned"); write_sol(hbuf, x, y, &Oinfo); } static double Times[4]; static void #ifdef KR_headers show_times() #else show_times(void) #endif { 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]); } } static void #ifdef KR_headers basread(asl, cpx) ASL *asl; cpxlp *cpx; #else basread(ASL *asl, cpxlp *cpx) #endif { if (CPXreadcopybase(Env, cpx, startbas)) { printf("Could not read starting basis file \"%s\"\n", startbas); need_nl = 0; } } static void CPXPUBLIC #ifdef KR_headers mymsgfunc(handle, msg) char *handle, *msg; #else mymsgfunc(void *handle, char *msg) #endif { static int wantnl; char *msg1; int n; handle = handle; /* shut up non-use warning */ if (Logf) CPXfputs(msg, Logf); if (dispzap) { if (!strncmp(msg, "MIP start va", 12)) goto print_msg; n = strlen(msg); if (n > 20 && !strcmp(msg+n-20, "variable selection.\n")) goto print_msg; if (*msg != '\n') return; dispzap = 0; } if (!strncmp(msg, "Total network iterations = ", 27)) netiters = atoi(msg+27); else 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"; static SufDecl suftab[] = { { "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 }, { "iis", iis_table, ASL_Sufkind_var | ASL_Sufkind_outonly }, { "iis", 0, ASL_Sufkind_con | ASL_Sufkind_outonly }, { "priority", 0, ASL_Sufkind_var }, { "ref", 0, ASL_Sufkind_var | ASL_Sufkind_real }, { "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 char * #ifdef KR_headers strcpy1(t, s) char *t; char *s; #else strcpy1(char *t, char *s) #endif { while(*t = *s++) t++; return t; } static void #ifdef KR_headers adjust_version(asl) ASL *asl; #else adjust_version(ASL *asl) #endif { char *d, *de, *s, *t; int cvlen, dvlen; for(d = cplex_version; *d != '('; d++); for(de = d; *de++ != ')'; ); *de = 0; dvlen = de - d; s = CPXversion(Env); cvlen = strlen(s); Oinfo.bsname = M1alloc(2*cvlen + dvlen + 24); t = strcpy1(Oinfo.bsname, "CPLEX "); t = strcpy1(t, s); Oinfo.version = version = ++t; t = strcpy1(t, Oinfo.bsname); t = strcpy1(t, ", driver"); t = strcpy1(t, d); strcpy1(t, "\n"); } static int #ifdef KR_headers Optimize1(e, c) CPXENVptr e; cpxlp *c; #else Optimize1(CPXENVptr e, cpxlp *c) #endif { int rc = Optimize(e, c); if (rc == 1101) { CPXsetintparam(e, CPX_PARAM_AGGIND, 0); CPXsetintparam(e, CPX_PARAM_PREIND, 0); rc = Optimize(e, c); } return rc; } int #ifdef KR_headers main(argc, argv) int argc; char **argv; #else main(int argc, char **argv) #endif { int itfoind, nint1, nos, *nosp, rc, status, z; dims d; char *stub; CPXCHANNELptr cpxresults; /* static values for use with longjmp */ static cpxlp *cpx; static sig_func_type *oic; static FILE *nl; Times[0] = xectim_(); #ifdef BARRIER asl = ASL_alloc(ASL_read_fg); #else asl = ASL_alloc(ASL_read_f); #endif Env = 0; cpx = 0; breaking = 0; oic = 0; nl = 0; rc = setjmp(Jb); if (rc) { if (nl) fclose(nl); if (solve_result_num > 0) { rc = 0; goto ws_now; } --rc; goto done; } if (argc < 2) #ifdef Stand_alone return cpxmain(argc,argv); #else usage_ASL(&Oinfo, 1); #endif if (Env = CPXopenCPLEXdevelop(&z)) adjust_version(asl); /* prepare to return error messages in .sol file */ if (!(stub = getstub(&argv, &Oinfo))) usage_ASL(&Oinfo, 1); nl = jac0dim(stub, (fint)0); oic = signal(SIGINT, intcatch); if (!Env) { if (z == 32027) badretfmt(571, "CPLEX licensing limit: maximum processes exceeded."); else badretfmt(570, "CPLEX licensing problem: error code %d from CPXopenCPLEXdevelop.", z); goto ws_now; } 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, &nint1, argv); if (!cpx) { if (solve_result_num > 0) { ws_now: write_sol((char*)asl->i.uinfo, 0, 0, &Oinfo); } else { printf("Failed to load the problem!\n"); rc = 1; } goto done; } if (wrtfname) CPXwriteprob(Env, cpx, wrtfname, NULL); if (startbas) basread(asl, cpx); #ifdef BARRIER if (startvec && (status = CPXreadcopyvec(Env, cpx, startvec))) printf("\n*** return %d from CPXreadcopyvec.\n", status); #endif #ifdef CPLEX_MIP if (nint1 && starttree) treeio(cpx, starttree, "read", CPXreadcopytree); #endif fflush(stdout); Times[1] = xectim_(); nosp = 0; disconnectchannel(cpxresults); addfuncdest(cpxresults, 0, mymsgfunc); if (use_netopt) { getitfoind(&itfoind); if (!itfoind) { netopting = 1; /* suppress netopt termination msg */ setitfoind(1, &z, &z); } nos = netopt(cpx,&net_status,&net_nodes,&net_arcs,&net_its); if (nos) net_status = -5; nosp = &net_status; netopting = 0; if (!itfoind) setitfoind(0, &z, &z); if (nos != -2) status = Optimize1(Env,cpx); } else status = Optimize1(Env,cpx); Times[2] = xectim_(); if (endbas && !nint1) write_basis(cpx); #ifdef CPLEX_MIP if (nint1 && endtree) treeio(cpx, endtree, "write", CPXtreewrite); #endif amplout(asl, cpx, &d, status, nint1, nosp); done: if (oic) signal(SIGINT, oic); if (cpx) CPXfreeprob(Env, &cpx); if (Env) CPXcloseCPLEX(&Env); ASL_free(&asl); show_times(); return rc; } void #ifdef KR_headers mainexit_ASL(rc) int rc; #else mainexit_ASL(int rc) #endif { longjmp(Jb, rc+1); }