/**************************************************************** Copyright (C) 1997, 1998, 2001 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. ****************************************************************/ #include "signal.h" #include "ctype.h" #include "getstub.h" #include "obj_adj.h" /* For (defective) Linux on Alpha chips where infinity arithmetic fails: */ /* compile, e.g., with -DFinite_Plinfy=1e154 */ #ifdef Finite_Plinfy #undef Infinity #define Infinity Finite_Plinfy #endif #define N_FNAMES 100 static char *fnames[N_FNAMES]; #ifdef __cplusplus extern "C" { #endif typedef void fgCon ANSI((fint *MODE, fint *M, fint *N, fint *NJAC, real *X, real *F, real *G, fint *NSTATE, char *CU, fint *LENCU, fint *IU, fint *LENIU, real *RU, fint *LENRU, ftnlen len_cu)); typedef void fgObj ANSI((fint *MODE, fint *N, real *X, real *F, real *G, fint *NSTATE, char *CU, fint *LENCU, fint *IU, fint *LENIU, real *RU, fint *LENRU, ftnlen len_cu)); typedef void fQp ANSI((fint*, real*, real*, fint*, char*, fint*, fint*, fint*, real*, fint*, ftnlen)); static fgCon funcon; static fgObj funobj; extern void s1file_ ANSI((fint *, fint*, fint*)); extern int snmemb_ ANSI((fint *info, fint *m, fint *n, fint *ne, fint *negcon, fint *nncon, fint *nnjac, fint *nnobj, fint *mincw, fint *miniw, fint *minrw, char *cw, fint *lencw, fint *iw, fint *leniw, real *rw, fint *lenrw, ftnlen cw_len)); extern void sninit_ ANSI((fint *iprint, fint *isumm, char *cw, fint *lencw, fint *iw, fint *leniw, real *rw, fint *lenrw, ftnlen cw_len)); extern void snopt_ ANSI((char *start, fint *m, fint *n, fint *ne, fint *nname, fint *nncon, fint *nnobj, fint *nnjac, fint *iobj, real *objadd, char *prob, fgCon *fgcon, fgObj *fgobj, real *jcol, fint *indj, fint *locj, real *bl, real *bu, char *names, fint *hs, real *x, real *pi, real *rc, fint *info, fint *mincw, fint *miniw, fint *minrw, fint *ns, fint *ninf, real *sinf, real *obj, char *cu, fint *lencu, fint *iu, fint *leniu, real *ru, fint *lenru, char *cw, fint *lencw, fint *iw, fint *leniw, real *rw, fint *lenrw, ftnlen start_len, ftnlen prob_len, ftnlen names_len, ftnlen cu_len, ftnlen cw_len)); extern void snset_(char *buffer, fint *iprint, fint *isumm, fint *errors, char *cw, fint *lencw, fint *iw, fint *leniw, real *rw, fint *lenrw, ftnlen buffer_len, ftnlen cw_len); extern void sntitle_ ANSI((char*, ftnlen)); extern void sqopt_ ANSI((char *start, fQp*, fint *m, fint *n, fint *ne, fint *nname, fint *lenc, fint *ncolh, fint *iobj, real *objadd, char *prob, real *acol, fint *inda, fint *loca, real *bl, real *bu, real *c, char *names, fint *helast, fint *hs, real *x, real *pi, real *rc, fint *inform, fint *mincw, fint *miniw, fint *minrw, fint *ns, fint *ninf, real *sinf, real *obj, char *cu, fint *lencu, fint *iu, fint *leniu, real *ru, fint *lenru, char *cw, fint *lencw, fint *iw, fint *leniw, real *rw, fint *lenrw, ftnlen start_len, ftnlen prob_len, ftnlen names_len, ftnlen cu_len, ftnlen cw_len)); #define Aijtol rw[94] #define Itn iw[420] #define Objsen iw[86] #define Objtru rw[420] #define Plinfy rw[69] #define iPrint iw[11] #define iSumm iw[12] #define itnlim iw[88] #define lDenJ iw[104] #define lenalu iw[212] #define lprSol iw[83] #define lvlScl iw[74] #define lvlTim iw[181] #define maxcw iw[6] #define maxiw iw[4] #define maxrw iw[2] #define maxS iw[52] #define minlen iw[162] #define nMajor iw[421] #define nQNmod iw[380] #define neGcon iw[19] #define nnCon iw[22] #define nnJac iw[20] #define nnObj iw[21] #define objno iw[107] #define stkyOp iw[115] static fint Objno, iObj; extern char **xargv; typedef struct Winfo { char *cw; fint *iw; real *rw; fint lencw, leniw, lenrw; ftnlen cw_len; } Winfo; static Jmp_buf Jb; static Winfo winfo; static char Emsgbuf[96], *Errmsg = Emsgbuf; static int Errnum = 599; /* should be assigned if needed */ static int functimes, wantfuncs; static int nfuncon, nfungrd, nfunjac, nfunobj; static int objrep = 3, outlev = 1, qpcheck = 1; static fint i_exit, last_state, memadj, meminc, timing; static real Times[6]; static char Title[32]; #define asl cur_ASL static char *usage_msg[] = { " where stub is from `ampl -obstub` or `ampl -ogstub`. Assignments", " have the form u=filename or spec=value in which the integers u are", " file unit numbers that appear in spec assignments (don't use 5 or 6", " for u) and spec is a SNOPT SPECS file keyword phrase, with keywords", " in the phrase separated by _ (underscore). Use", " outlev=0 for no options echoed on stdout,", " outlev=1 for neither log nor summary file on stdout (default),", " outlev=2 to see summary output on stdout,", " outlev=3 to see detailed (log file) output on stdout, and", " outlev=4 to get log file plus solution on stdout.", " For outlev <= 2, use 7=logfilename to get the log file. Assignments", " may also be given in $snopt_options .", 0 }; typedef struct Phrase Phrase; struct Phrase { Phrase *next; ftnlen len; char val[1]; /*really [len+1]*/ }; static Phrase *firstphrase, **lastnext; static char *phbuf; static size_t phblen; static fint mkey(char *phrase, ftnlen len) { Phrase **ln, *p; char *s; size_t L, L1; ln = lastnext; L1 = (len + sizeof(Phrase) + sizeof(char*)) & ~(sizeof(char*)-1); if (L1 > phblen) { L = L1; if (L < 4096) L = 4096; phbuf = (char*)M1alloc(phblen = L); if (!ln) ln = &firstphrase; } *ln = p = (Phrase*)phbuf; phbuf += L1; lastnext = &p->next; p->next = 0; memcpy(s = p->val, phrase, (size_t)(p->len = len)); s[len] = 0; return 0; } static fint nkey(fint *np, char *fname, ftnlen L) { fint n = *np; char *s; if (n < 0 || n >= N_FNAMES) { printf("Unit number > %d\n", N_FNAMES-1); return 1; } fnames[n] = s = (char*)M1alloc(L+1); memcpy(s, fname, L); s[L] = 0; return 0; } static char * set_outlev(Option_Info *oi, keyword *kw, char *s) { char *rv = I_val(oi,kw,s); if (!*(int *)kw->info) oi->option_echo = 0; return rv; } static char qpcheck_msg[] = "whether to pass LPs and QPs to SQOPT rather than SNOPT:\n\ 0 = no\n\ 1 = yes (default)"; static char objrep_desc[] = "Whether to replace\n\t\t\t\tminimize obj: v;\n\t\t\twith\n\t\t\t\t" "minimize obj: f(x)\n\t\t\twhen variable v appears linearly\n\t" "\t\tin exactly one constraint of the form\n\t\t\t\t" "s.t. c: v >= f(x);\n\t\t\tor\n\t\t\t\ts.t. c: v == f(x);\n" "\t\t\tPossible objrep values:\n\t\t\t0 = no\n" "\t\t\t1 = yes for v >= f(x)\n" "\t\t\t2 = yes for v == f(x)\n" "\t\t\t3 = yes in both cases (default)"; static keyword keywds[] = { KW("ftimes", I_val, &functimes, "report function eval. times"), KW("maxfwd", IA_val, voffset_of(ASL,p.maxfwd_), "max vars in fwd AD of common exprs (default 5)"), KW("meminc", L_val, &meminc, "increment to minimum memory allocation"), KW("objno", L_val, &Objno, "objective number: 0 = none, 1 = first (default)"), KW("objrep", I_val, &objrep, objrep_desc), KW("outlev", set_outlev, &outlev, "output level; 1 = default"), KW("qpcheck", I_val, &qpcheck, qpcheck_msg), KW("timing", I_val, &timing, "report I/O and solution times: 1 = stdout, 2 = stderr, 3 = both"), KW("version", Ver_val, 0, "report version"), KW("wantsol", WS_val, 0, WS_desc_ASL+5) }; static keyword options[] = { KW("f", IK1_val, &wantfuncs, "list available user-defined functions"), KW("t", IK1_val, &functimes, "time function evaluations") }; static Option_Info Oinfo = { "snopt", Title, "snopt_options", keywds, nkeywds, 1, 0, usage_msg, mkey, nkey, options, sizeof(options)/sizeof(keyword), 20190314 }; static void get_Title(VOID) { /* Get title from sntitl and omit excessive blanks. */ char *s, *se, *t, *t1; size_t L, L1; int keepblank = 0; sntitle_(Title, sizeof(Title)); s = t = Title; se = s + sizeof(Title); t1 = 0; while(s < se) { while(*s > ' ') { if (*s == '('/*)*/ && !t1) t1 = t; *t++ = *s++; if (s >= se) goto done; } if (!*s || s+1 >= se) break; if (keepblank || s[1] == ' ') { *t++ = *s++; keepblank = 0; } while(*s <= ' ') if (!*s || ++s >= se) goto done; if (*s == '(')/*)*/ keepblank = 1; } done: if (!t1) t1 = t; *t = 0; L = t - Title; L1 = t1 - Title; Oinfo.bsname = M1alloc(L + L1 + 2); Oinfo.version = se = Oinfo.bsname + L1 + 1; strncpy(Oinfo.bsname, Title, L1); Oinfo.bsname[L1] = 0; memcpy(se, Title, L); se[L] = 0; } static SufDecl suftab[] = { { "sstatus", 0, ASL_Sufkind_var, 1 }, { "sstatus", 0, ASL_Sufkind_con, 1 } }; static int envopt(void) { Phrase *p; fint inform, *iw; int rv; static fint lprint, lsumm = 6; iw = winfo.iw; if (fnames[7]) iPrint = 7; if (fnames[0] && !freopen(fnames[0], "w", Stderr)) printf("Can't redirect Stderr to %s\n", fnames[0]); rv = 0; for(p = firstphrase; p; p = p->next) { inform = 0; snset_(p->val, &lprint, &lsumm, &inform, winfo.cw, &winfo.lencw, winfo.iw, &winfo.leniw, winfo.rw, &winfo.lenrw, p->len, (ftnlen)winfo.lencw); if (inform) ++rv; } fflush(stdout); return rv; } #undef asl static fint objmunge(fint M, fint *mp, fint N, fint NZ, fint *nzp, fint *hs, real *lb, real *ub, real *A, fint *ha, fint *ja, real *objadj, real *x) { ASL *asl; Objrep *od, **pod; cgrad *cg, *cg1, **cgp, **cgx, *ncg; char *h, *he; fint *ha1, *ha2, *hae, *iw, *ja1, *kadj, *kadj1; fint i, j, k, na0, ne, nlclim, nlvlim, nz, rv, si, vi; int *cm, *vmi; ograd *og, **ogp; real *a1, *a2, *lbe, *rw; real aijtol, ninf, pinf, t, t1; asl = cur_ASL; iw = winfo.iw; rw = winfo.rw; rv = ne = na0 = 0; i = N; cgp = 0; ogp = 0; cm = vmi = 0; od = 0; if (Objno >= 0 && (pod = asl->i.Or) && (od = pod[Objno])) { if (!asl->i.cmap) i += asl->i.n_con0; if (!asl->i.vmap) i += asl->i.n_var0; } kadj = (fint *)Malloc(i *= sizeof(fint)); memset((char *)kadj, 0, N*sizeof(fint)); if (od) { vmi = (int*)kadj + N; if (!(cm = asl->i.cmap)) { cm = vmi; vmi += j = asl->i.n_con0; while(j > 0) { --j; cm[j] = j; } } if (asl->i.vmap) vmi = get_vminv_ASL(asl); else { j = asl->i.n_var0; while(j > 0) { --j; vmi[j] = j; } } } aijtol = Aijtol; nz = NZ; nlvlim = nlvc; nlclim = nlc; /* omit tiny components of A */ if (aijtol > 0) { a1 = a2 = A; ha1 = ha2 = ha; ja1 = ja; for(i = 0; i < N; i++) { j = *++ja1; hae = ha + j - 1; while(ha1 < hae) { t = *a1++; if ((si = *ha1++) > nlclim && i >= nlvlim && (t < 0 ? -t : t) < aijtol) { na0++; continue; } *a2++ = t; *ha2++ = si; } *ja1 = j - na0; } nz -= na0; } /* find objective, count gradient components */ *objadj = 0; if (Objno >= 0) { if (Objsen == 2) Objsen = objtype[Objno] ? -1 : 1; if (nl_obj(Objno)) rv = od ? nlvc : nlvo; else *objadj = objconst(Objno); if (od) { if (!(cgp = asl->i.Cgrad0)) cgp = asl->i.Cgrad_; cgp += od->ico; for(cg = *cgp; cg; cg = cg->next) { if ((i = vmi[cg->varno]) < rv) goto ckeep; if ((t = cg->coef) < 0) t = -t; if (t >= aijtol) { ckeep: kadj[i] = 1; ne++; } else na0++; } } else { ogp = &Ograd[Objno]; for(og = *ogp; og; og = og->next) { if (og->varno < rv) goto keep; else { if ((t = og->coef) < 0) t = -t; if (t >= aijtol) { keep: kadj[og->varno] = 1; ne++; } else na0++; } } } } else Objsen = 0; h = havex0; he = h + N; pinf = Plinfy; ninf = -pinf; while(h < he) { si = 2; if ((t1 = *lb) <= ninf) t1 = *lb = ninf; else si = 0; if ((t = *ub) >= pinf) t = *ub = pinf; else si = t <= 0; lb++; ub++; if (*h++ && si != 2) { if (*x <= t1) { *x = t1; si = 4; } else if (*x >= t) { *x = t; si = 5; } } *hs++ = si; x++; } /* adjust bounds */ lbe = lb + M; while(lb < lbe) { si = 2; if ((t = *lb) <= ninf) t = ninf; else si = 0; if ((t1 = *ub) >= pinf) t1 = pinf; else si = 0; *lb++ = t; *ub++ = t1; *hs++ = si; } /* insert objective */ si = M; if (ne) { iObj = *mp = ++si; *lb = ninf; *ub = pinf; *hs = 0; a1 = A + nz; ha1 = ha + nz; k = nz; nz += ne; a2 = A + nz; ha2 = ha + nz; ja1 = ja + N; kadj1 = kadj + N; for(;;) { *ja1-- += ne; if (*--kadj1) { *kadj1 = a2 - A; *--a2 = 0; *--ha2 = si; if (!--ne) break; } for(j = *ja1; k >= j; k--) { *--a2 = *--a1; *--ha2 = *--ha1; } } if (cgp) { od->cg0 = cg = *cgp; t = od->c12; for(k = 0; cg; cg = cg->next) { if ((i = kadj[vi = vmi[cg->varno]]) && vi >= rv) A[i - 1] = t * cg->coef; else ++k; } if (k) { cg1 = (cgrad*)M1alloc(k*sizeof(cgrad)); for(cg = *cgp; cg; cg = cg->next) { if (!kadj[vi = vmi[cg->varno]] || vi < rv) { *cg1 = *cg; *cgp = cg1; cgp = &cg1->next; ++cg1; } } } *cgp = 0; } else { while((og = *ogp)) { if ((i = kadj[og->varno]) && og->varno >= rv) { A[i - 1] = og->coef; *ogp = og->next; } else ogp = &og->next; } } } else *mp = M; *nzp = nz; /* adjust for computing Jacobian */ neGcon = 0; if (nlvlim) { hae = ha + (ja[nlvlim] - 1); for(ha1 = ha, k = 0; ha1 < hae;) if (*ha1++ <= nlclim) k++; neGcon = k; if ((cgx = asl->i.Cgrad0)) { memset(kadj, 0, N*sizeof(fint)); j = 0; if (cm) for(; j < nlclim; ++j) { for(cg = cgx[cm[j]]; cg; cg = cg->next) ++kadj[vmi[cg->varno]]; } else for(; j < nlclim; ++j) { for(cg = cgx[j]; cg; cg = cg->next) ++kadj[cg->varno]; } for(j = k = 0; j < N; ++j) { i = kadj[j]; kadj[j] += k; k += i; } j = nlclim; if (cm) while(j > 0) { for(cgp = &cgx[cm[--j]]; (cg = *cgp); cgp = &cg->next) { i = vmi[cg->varno]; if (i >= nlvlim) { *cgp = 0; break; } cg->goff = --kadj[i]; } } else while(j > 0) { for(cgp = &cgx[--j]; (cg = *cgp); cgp = &cg->next) { i = cg->varno; if (i >= nlvlim) { *cgp = 0; break; } cg->goff = --kadj[i]; } } for(a1 = A, ha1 = ha; ha1 < hae; a1++) { if (*ha1++ <= nlclim) *a1 = 0.; } } else { free(kadj); kadj = 0; Cgrad = (cgrad **)M1alloc(nlclim*sizeof(cgrad *)); memset((char *)Cgrad, 0, nlclim*sizeof(cgrad *)); for(ha1 = ha, k = 0; ha1 < hae;) if (*ha1++ <= nlclim) k++; ncg = (cgrad *)M1alloc(k*sizeof(cgrad)); i = k = 0; ja1 = ja + 1; for(a1 = A, ha1 = ha; ha1 < hae; a1++) { if ((j = *ha1++) <= nlclim) { cgx = Cgrad + j - 1; cg = ncg++; cg->next = *cgx; *cgx = cg; cg->goff = k++; j = ha1 - ha; while(j >= *ja1) { ja1++; i++; } cg->varno = i; cg->coef = *a1; *a1 = 0.; } } } } if (kadj) free(kadj); if (na0) { printf("%d coefficients less than aij = %g treated as 0.\n", na0, aijtol); need_nl = 0; } c_vars = nlvlim; return o_vars = rv; } static void time_out(FILE *f) { fprintf(f," SNOPT times:\n read: %10.2f\n solve: %9.2f", Times[1] - Times[0], Times[2] - Times[1]); fprintf(f, "\n write: %9.2f\n total: %9.2f\n", Times[3] - Times[2], Times[3] - Times[0]); if (functimes) { fprintf(f, "\n"); if (nfuncon) fprintf(f, " constraints: %9.2f for %d evaluations, %d Jacobians\n", Times[4], nfuncon, nfunjac); if (nfunobj) fprintf(f, " objective: %11.2f for %d evaluations, %d gradients\n", Times[5], nfunobj, nfungrd); } } static void negate(fint M, register real *x) { register real *xe; for(xe = x + M; x < xe; x++) *x = -*x; } static fint vtrans[] = { 0, 3, 2, 0, 1, 0, 0 }, ctrans[] = { 0, 3, 2, 1, 0, 0, 0 }; static void hs1_adjust(fint N, int *s, fint *ss, fint *trans) { fint i; for(i = 0; i < N; i++) ss[i] = trans[s[i]]; } static char * hs_adjust(ASL *asl, fint N, fint M, fint m1, fint *vss, int *vs, SufDesc *vsd, SufDesc *csd, real *A, fint *ha, fint *ja) { fint *jae, nerror; fint *hae, i1, i2, is; int nlin; real t, *x, *xe; if (!(vsd->kind & ASL_Sufkind_input) || !(csd->kind & ASL_Sufkind_input)) return "Cold"; hs1_adjust(N, vs, vss, vtrans); hs1_adjust(M, vs+N, vss+N, ctrans); if (m1 > M) vss[M+N] = 3; /* Why can't minos compute the initial slacks? */ /* Then we could eliminate the following mess... */ if (nlc) { nerror = 0; conval(X0, x = X0+N, &nerror); if (nerror) memset(X0+N, 0, nlc*sizeof(real)); else for(xe = x + nlc; x < xe; x++) *x = -*x; } if ((nlin = n_con - nlc) > 0) { x = X0 + N + nlc; i1 = nlc + 1; i2 = n_con; memset(x, 0, nlin*sizeof(real)); hae = ha; xe = X0; for(jae = ja + N; ja < jae; ja++) { hae += ja[1] - ja[0]; for(t = *xe++; ha < hae; A++) if ((is = *ha++) >= i1 && is <= i2) x[is - i1] -= t**A; } } return "Warm"; } static void send_status(fint N, fint *ss, int *s, fint *trans, real *L, real *U) { fint i; for(i = 0; i < N; i++) if ((((s[i] = trans[ss[i]]) + 1) & ~1) == 4 && L[i] == U[i]) s[i] = 5; } #undef scream #undef asl static void scream(char *fmt, ...) { va_list ap; va_start(ap, fmt); fprintf(Stderr, "snopt: "); vfprintf(Stderr, fmt, ap); va_end(ap); longjmp(Jb.jb, 4); } static fint *colq, ncolh, *rowq; static real *delsq; static void qpHx(fint *ncolH, real *x, real *Hx, fint *nState, char *cu, fint *lencu, fint *iu, fint *leniu, real *ru, fint *lenru, ftnlen culen) { fint *cq, i, n, *rq, *rqe; real *h, t, *xe; n = *ncolH; if (n != ncolh) { scream("qpHx expected ncolH = %d but got %d\n", (int)n, (int)ncolh); /* suppress warning about unused variables: */ Not_Used(nState); Not_Used(cu); Not_Used(lencu); Not_Used(iu); Not_Used(leniu); Not_Used(ru); Not_Used(lenru); Not_Used(culen); } for(i = 0; i < n; i++) Hx[i] = 0; xe = x + n; cq = colq; rq = rowq; h = delsq; while(x < xe) { t = *x++; rqe = rowq + *++cq; while(rq < rqe) Hx[*rq++] += t**h++; } } typedef struct { fint *itnlimp; fint zapped; } Itnzapper; static Itnzapper Itnzap; static void itnlimzap(int sig, void *v) { Itnzapper *I = (Itnzapper*)v; if (*I->itnlimp > 0) { *I->itnlimp = 0; I->zapped = 1; } } void MAIN__(void) { ASL *asl; FILE *nl; SufDesc *csd, *vsd; char **av, *cw, *cw0, *msg1, *stub, *s, *start; char Prob[8], buf[64], msg[400]; fint *ha, *helast, *hs,*iw, *iw0, *ja; fint INFORM, M, MXROW, MXCOL, N, N1, NB, NO, NS, NZ; fint i, m1, mincw, mincw0, miniw, miniw0, minrw, minrw0, nInf, nint, nz, nzh; int flags, qpsol, *varstat; real *A, *lb, *pi, *rc, *ub, *y, *z; real c0, nlobj, objadj, sInf, *rw, *rw0; size_t L0, L2; void **vw; typedef struct { char *msg; int code, wantobj; } Sol_info; Sol_info *SI; static int objrep_flags[4] = { 0, ASL_obj_replace_ineq, ASL_obj_replace_eq, ASL_obj_replace_ineq | ASL_obj_replace_eq }; static Sol_info info_optimal = {/*1*/ "Optimal solution found", 0, 1}, info_feaspt = {/*2*/ "Feasible point found", 1, 1}, info_inacc = {/*3*/ "Requested accuracy could not be achieved", 102, 1}, info_infeas_lin = {/*11*/ "Infeasible linear constraints", 202, 1}, info_infeas_leq = {/*12*/ "Infeasible linear equalities", 203, 1}, info_infeas_nlm = {/*13*/ "Nonlinear infeasibilities minimized", 204, 1}, info_infeas_min = {/*14*/ "Infeasibilities minimized", 205, 1}, info_unbdd_obj = {/*21*/ "Unbounded objective", 301, 1}, info_unbdd_con = {/*22*/ "Constraint violation limit reached", 302, 1}, info_limit_iter = {/*31*/ "Too many iterations", 400, 1}, info_limit_maji = {/*32*/ "Major iteration limit reached", 401, 1}, info_limit_supb = {/*33*/ "The superbasics limit is too small", 402, 1}, info_cannot_imp = {/*41*/ "The current point cannot be improved", 101, 1}, info_sing_basis = {/*42*/ "Singular basis", 508, 1}, info_infeasgenc = {/*43*/ "Cannot satisfy nonlinear constraints", 206, 1}, info_ill_condnb = {/*44*/ "Ill-conditioned null-space basis", 522, 1}, info_bad_objgrd = {/*51*/ "Incorrect gradients from funobj", 502, 0}, info_bad_congrd = {/*52*/ "Incorrect gradients from funcon", 503, 0}, info_indef_hes = {/*53*/ "Indefinite Hessian", 530, 0}, info_bad_obj0 = { "Error evaluating initial objective", 515, 0}, info_bad_init = {/*61*/ "Error evaluating initial constraint values", 514, 0}, info_bad_feas = {/*62*/ "Error evaluating objective at 1st feas. pt.", 513, 1}, info_bad_prog = {/*63*/ "Cannot proceed into undefined region", 523, 1}, info_short_work = {/*81*/ "Work arrays too small", 550, 0}, info_short_char = {/*82*/ "Not enough character storage", 551, 0}, info_short_int = {/*83*/ "Not enough integer storage", 552, 0}, info_short_real = {/*84*/ "Not enough real storage", 553, 0}, info_bad_input = {/*91*/ "Invalid input argument", 554, 0}, info_bad_basis = {/*92*/ "Wrong basis file dimentions", 524, 0}, info_bad_numbv = {/*141*/ "Wrong number of basic variables", 555, 0}, info_basis_err = {/*142*/ "Error in basis package", 556, 0}, info_surprise = { 0, 560, 0}, info_lj[6] = { { "Evaluation error", 562, 0 }, { "Derivative evaluation error", 563, 0 }, { "Bug: surprise setjmp() return", 564, 0 }, { "Bug: \"scream\" called", 561, 0 }, { "Bad \"nn=filename\" assignment", 517, 0 }, { "Floating-point error", 565, 0 }}; static char names[8] = " "; static fint I0 = 0, I1 = 1, openF = 1; static fint sctrans[] = { 4, 3, 2, 1 }, svtrans[] = { 3, 4, 2, 1 }; Times[0] = xectim_(); asl = ASL_alloc(ASL_read_fg); get_Title(); Times[4] = Times[5] = 0; winfo.lencw = winfo.leniw = winfo.lenrw = 500; L0 = 500*(sizeof(fint) + sizeof(real) + 8); winfo.rw = rw0 = rw = (real*)M1alloc(L0); winfo.iw = iw0 = iw = (fint*)(rw + 500); winfo.cw = cw0 = cw = (char*)(iw + 500); winfo.cw_len = 8; memset(rw, 0, L0); sninit_(&I0, &I0, cw, &winfo.lencw, iw, &winfo.leniw, rw, &winfo.lenrw, winfo.cw_len); Plinfy = Infinity; lDenJ = 2; lvlTim = 1; asl->i.congrd_mode = 2; /* sparse Jacobians */ av = xargv; stub = getstub(&av, &Oinfo); if (!stub) usage_ASL(&Oinfo, 1); nl = jacdim(stub, &M, &N, &NO, &NZ, &MXROW, &MXCOL, (fint)strlen(stub)); Objno = n_obj > 0; meminc = 20*(M + N); if (getopts(av,&Oinfo)) exit(1); if (wantfuncs) { show_funcs(); exit(0); } if (N <= 0) { sprintf(Errmsg = Emsgbuf, "%s has no variables\n", filename); Errnum = 516; bailout: solve_result_num = Errnum; write_sol(Errmsg, 0, 0, &Oinfo); exit(0); } suf_declare(suftab, sizeof(suftab)/sizeof(SufDecl)); itnlim = 99999999; nnCon = n_conjac[1] = nlc; nnJac = nlvc; N1 = N + 1; m1 = M + 1; NB = N + m1; nz = NZ + N; Fortran = 1; LUv = lb = (real *)M1alloc((4*NB + m1 + nz)*sizeof(real) + (N1 + NB + nz)*sizeof(fint) + N); LUrhs = lb + N; Uvx = ub = LUrhs + m1; Urhsx = ub + N; X0 = Urhsx + m1; A = A_vals = X0 + NB; memset((char *)(X0 + N), 0, m1*sizeof(real)); rc = A + nz; pi = pi0 = rc + NB; ja = (fint *)(pi + m1); ha = ja + N1; hs = ha + nz; varstat = (int*)M1alloc(NB*sizeof(int)); vsd = suf_iput("sstatus", ASL_Sufkind_var, varstat); csd = suf_iput("sstatus", ASL_Sufkind_con, varstat + N); havex0 = (char *)(hs + NB); if (sizeof(int) == sizeof(fint)) A_rownos = (int *)ha; else A_rownos = (int *)M1alloc(NZ*sizeof(int)); if (sizeof(int) == sizeof(fint)) A_colstarts = (int *)ja; else A_colstarts = (int *)M1alloc(N1*sizeof(int)); asl->i.nlvog = nlvo; Objsen = 2; if (meminc <= 0) meminc = 20*(M + N); nQNmod = 20; lvlTim = -999; if (setjmp(Jb.jb)) goto bailout; if (envopt()) { Errmsg = "Bad options"; Errnum = 517; goto bailout; } if (Objno > n_obj || Objno < 0) { sprintf(Errmsg = Emsgbuf, "Objno = %ld must be in [0, %d]", (long)Objno, n_obj); Errnum = 518; goto bailout; } --Objno; objno = obj_no = Objno; flags = objrep_flags[objrep & 3]; if ((qpsol = qpcheck && nlc == 0) && nlo > 0) { qp_read(nl, flags); nzh = nqpcheck((int)Objno, &rowq, &colq, &delsq); ncolh = 0; /* not necessary -- it's file static */ if (nzh > 0) { /* undo Fortran numbering and compute ncolh */ for(i = 1; i <= N; i++) if (colq[i-1]-- < colq[i]) ncolh = i; i = --colq[N]; while(--i >= 0) rowq[i]--; } else if (nzh < 0) switch(nzh + 2) { case 0: /* unlikely */ Errmsg = "Objective involves division by 0"; Errnum = 519; goto bailout; case 1: /* nonlinear */ qpsol = 0; qp_opify(); break; default: sprintf(Errmsg = Emsgbuf, "Unexpected return %ld from nqpcheck\n", (long)nzh); Errnum = 521; goto bailout; } } else fg_read(nl,flags); if (n_con < M) { nnCon = n_conjac[1] = nlc; M = n_con; N = n_var; N1 = N + 1; m1 = M + 1; NB = N + m1; NZ = nzc; nz = NZ + N; y = lb + N; z = LUrhs; for(i = 0; i < M; ++i) y[i] = z[i]; LUrhs = y; y = ub + N; z = Urhsx; for(i = 0; i < M; ++i) y[i] = z[i]; Urhsx = y; } if (sizeof(int) != sizeof(fint)) { fint *ja1 = ja; fint *ja1e = ja + N1; int *ja2 = A_colstarts; while(ja1 < ja1e) *ja1++ = *ja2++; } if ((nint = nlogv + niv + nlvbi + nlvci + nlvoi)) { printf("ignoring integrality of %ld variables\n", (long)nint); need_nl = 0; } nnObj = objmunge(M,&m1,N,NZ,&nz,hs,lb,ub,A,ha,ja,&objadj,X0); helast = 0; if (qpsol) { if (nnObj < ncolh) nnObj = ncolh; i = N + m1; helast = (fint*)M1zapalloc(i*sizeof(fint)); while(--i >= N) helast[i] = 3; } start = hs_adjust(asl, N, M, m1, hs, varstat, vsd, csd, A, ha, ja); if ((i = nnObj) < nnJac) i = nnJac; if (lvlScl < 0) lvlScl = i > 0 ? 1 : 2; if (outlev > 1) { if (lvlTim == -999) lvlTim = 3; if (outlev == 2) iSumm = 6; else { iPrint = 6; lprSol = 0; if (outlev > 3) lprSol = 2; } } else if (lvlTim == -999) lvlTim = iPrint == 0 && iSumm == 0 ? 0 : 3; if ((iSumm == 6 || iPrint == 6) && need_nl) { printf("\n"); need_nl = 0; } s1file_(&openF, iw, &winfo.leniw); mincw0 = miniw0 = minrw0 = 501; i = 0; snmemb_(&i, &m1, &N, &nz, &neGcon, &nnCon, &nnJac, &nnObj, &mincw0, &miniw0, &minrw0, cw, &winfo.lencw, iw, &winfo.leniw, rw, &winfo.lenrw, winfo.cw_len); if (i != 104) scream("Unexpected return %ld from snMemb.", (long)i); stkyOp = 1; /* retain lenalu and minlen */ vw = 0; tryagain: maxiw = winfo.leniw = miniw0 + 2*meminc; maxrw = winfo.lenrw = minrw0 + meminc; maxcw = winfo.lencw = mincw0; mincw = miniw = minrw = 501; L2 = winfo.leniw*sizeof(fint) + winfo.lenrw*sizeof(real) + winfo.lencw*8; if (!vw) vw = M1record(Malloc(L2)); else *vw = Realloc(*vw, L2); winfo.rw = (real*)*vw; winfo.iw = (fint*)(winfo.rw + winfo.lenrw); winfo.cw = (char*)(winfo.iw + winfo.leniw); memcpy(winfo.rw, rw0, 500*sizeof(real)); memcpy(winfo.iw, iw0, 500*sizeof(fint)); memcpy(winfo.cw, cw0, 500*8); rw = winfo.rw; iw = winfo.iw; cw = winfo.cw; *stub_end = 0; i = strlen(s = basename(stub)); if (i > 8) i = 8; memcpy(Prob, s, i); while(i < 8) Prob[i++] = ' '; INFORM = NS = 0; Itnzap.itnlimp = &itnlim; Itnzap.zapped = 0; int_catch(itnlimzap, &Itnzap); err_jmp1 = &Jb; SI = 0; Itn = 0; if ((i = setjmp(Jb.jb))) { if (--i < 0 || i > 4) i = 3; longjumped: SI = &info_lj[i]; } else { if (setjmp(fpe_jmpbuf)) { report_where(asl); printf("\nFloating point error.\n"); fflush(stdout); need_nl = 0; i = 5; goto longjumped; } #ifdef SYMANTEC if (_8087) #endif signal(SIGFPE, fpecatch); if (Objsen < 0) negate(M,pi); if (m1 > M) pi[M] = 0; Times[1] = xectim_(); if (qpsol) sqopt_(start, qpHx, &m1, &N, &nz, &I1, &I0, &ncolh, &iObj, &objadj, Prob, A, ha, ja, lb, ub, &c0, names, helast, hs, X0, pi, rc, &INFORM, &mincw, &miniw, &minrw, &NS, &nInf, &sInf, &nlobj, 0, &I0, 0, &I0, 0, &I0, cw, &winfo.lencw, iw, &winfo.leniw, rw, &winfo.lenrw, (ftnlen)4, (ftnlen)8, (ftnlen)8, (ftnlen)0, winfo.cw_len); else snopt_(start, &m1, &N, &nz, &I1, &nnCon, &nnObj, &nnJac, &iObj, &objadj, Prob, funcon, funobj, A, ha, ja, lb, ub, names, hs, X0, pi, rc, &INFORM, &mincw, &miniw, &minrw, &NS, &nInf, &sInf, &nlobj, 0, &I0, 0, &I0, 0, &I0, cw, &winfo.lencw, iw, &winfo.leniw, rw, &winfo.lenrw, (ftnlen)4, (ftnlen)8, (ftnlen)8, (ftnlen)0, winfo.cw_len); i = INFORM; if (i == 84 && !memadj && minlen > lenalu) { memadj = meminc += minlen - lenalu + 10; goto tryagain; } } Times[2] = xectim_(); if (functimes && !timing) timing = 1; if (need_nl && timing & 1) { printf("\n"); need_nl = 0; } msg1 = msg + Sprintf(msg, "%s: ", Oinfo.bsname); if (!SI) switch(i) { case 1: SI = &info_optimal; break; case 2: SI = &info_feaspt; break; case 3: SI = &info_inacc; break; case 11: SI = &info_infeas_lin; break; case 12: SI = &info_infeas_leq; break; case 13: SI = &info_infeas_nlm; break; case 14: SI = &info_infeas_min; break; case 21: SI = &info_unbdd_obj; break; case 22: SI = &info_unbdd_con; break; case 31: SI = &info_limit_iter; break; case 32: SI = &info_limit_maji; break; case 33: SI = &info_limit_supb; break; case 41: SI = &info_cannot_imp; break; case 42: SI = &info_sing_basis; break; case 43: SI = &info_infeasgenc; break; case 44: SI = &info_ill_condnb; break; case 51: SI = &info_bad_objgrd; break; case 53: SI = &info_indef_hes; break; case 52: SI = &info_bad_congrd; break; case 61: SI = &info_bad_init; if (last_state && i_exit == 20) SI = &info_bad_obj0; break; case 62: SI = &info_bad_feas; break; case 63: SI = &info_bad_prog; break; case 81: SI = &info_short_work; break; case 82: SI = &info_short_char; break; case 83: SI = &info_short_int; break; case 84: SI = &info_short_real; break; case 91: SI = &info_bad_input; break; case 92: SI = &info_bad_basis; break; case 141: SI = &info_bad_numbv; break; case 142: SI = &info_basis_err; break; default: SI = &info_surprise; Sprintf(SI->msg = buf, "Surprise INFO = %ld from snOptB", i); } solve_result_num = SI->code; msg1 += Sprintf(msg1, SI->msg, (long)INFORM); msg1 += Sprintf(msg1, ".\n%d iterations", Itn); if (SI->wantobj) { g_fmtop(buf, Objtru); msg1 += Sprintf(msg1, ", objective %s", buf); } else if (i == 1) { g_fmtop(buf, sInf); msg1 += Sprintf(msg1, ", infeasibility sum %s", buf); } if (nfuncon + nfunobj) { msg1 += Sprintf(msg1, "\nNonlin evals: "); if (nfunobj) msg1 += Sprintf(msg1, "obj = %d, grad = %d%s", nfunobj, nfungrd, nfuncon ? ", " : ""); if (nfuncon) msg1 += Sprintf(msg1, "constrs = %d, Jac = %d", nfuncon, nfunjac); msg1 += Sprintf(msg1, "."); } if (memadj) Sprintf(msg1, "\nAssumed meminc = %ld.", (long)memadj); send_status(N, hs, varstat, svtrans, LUv, Uvx); send_status(M, hs+N, varstat+N, sctrans, LUrhs, Urhsx); write_sol(msg, X0, pi, &Oinfo); if (timing) { Times[3] = xectim_(); if (timing & 1) time_out(stdout); if (timing & 2) { fflush(stdout); time_out(Stderr); } } ASL_free(&asl); /* for Purify */ } void getfnm_(fint *i0, char *fname, fint *last, ftnlen fname_len) { int i = *i0, L; char *s; if (i >= N_FNAMES || i < 0) { sprintf(Errmsg = Emsgbuf, "File assignment nn=filename with nn = %d not in [0, %d]", i, N_FNAMES-1); Errnum = 517; longjmp(Jb.jb, 5); } if ((s = fnames[i])) L = Sprintf(fname, "%s", s); else L = Sprintf(fname, "fort.%d", i); *last = L; while (L < fname_len) fname[L++] = ' '; } static void funcon(fint *MODE, fint *M, fint *N, fint *NJAC, real *X, real *F, real *G, fint *NSTATE, char *CU, fint *LENCU, fint *IU, fint *LENIU, real *RU, fint *LENRU, ftnlen len_cu) { real t0; int wantder; ASL *asl; fint nerror = 0; if (Itnzap.zapped) { *MODE = -2; return; } t0 = 0.; if (functimes) t0 = xectim_(); asl = cur_ASL; if ((last_state = *NSTATE)) { if (*NSTATE != 1) return; if (*N != c_vars) { scream("funcon expected N = %d but got %d\n", c_vars, (int)*N); /* suppress warning about unused vars: */ Not_Used(M); Not_Used(NJAC); Not_Used(CU); Not_Used(LENCU); Not_Used(IU); Not_Used(LENIU); Not_Used(RU); Not_Used(LENRU); Not_Used(len_cu); } } nfuncon++; wantder = 0; if ((int)*MODE & 2) { wantder = 1; nfunjac++; } want_deriv = wantder; xknowne(X, &nerror); if (nerror <= 0) conval(X, F, &nerror); if (nerror > 0) { i_exit = 21; *MODE = -1; return; } if (wantder) jacval(X, G, 0); xunknown(); if (functimes) Times[4] += xectim_() - t0; } static void funobj(fint *MODE, fint *N, real *X, real *F, real *G, fint *NSTATE, char *CU, fint *LENCU, fint *IU, fint *LENIU, real *RU, fint *LENRU, ftnlen len_cu) { int i, wantder; real t0; fint nerror = 0; ASL *asl = cur_ASL; if (Itnzap.zapped) { *MODE = -2; return; } t0 = 0.; if (functimes) t0 = xectim_(); if ((last_state = *NSTATE)) { if (*NSTATE != 1) return; if (*N != o_vars) { scream("funobj expected N = %d but got %d\n", o_vars, (int)*N); /* suppress warning about unused vars: */ Not_Used(CU); Not_Used(LENCU); Not_Used(IU); Not_Used(LENIU); Not_Used(RU); Not_Used(LENRU); Not_Used(len_cu); } } nfunobj++; wantder = 0; if ((int)*MODE & 2) { nfungrd++; wantder = 1; } want_deriv = wantder; i = Objno; if (i < 0 || i >= n_obj) { *F = 0.; if (wantder) memset(G, 0, *N*sizeof(real)); } else { xknowne(X, &nerror); if (nerror >= 0) *F = objval(i,X,&nerror); if (nerror > 0) { i_exit = 20; *MODE = -1; return; } if (wantder) objgrd(i,X,G,0); xunknown(); } if (functimes) Times[5] += xectim_() - t0; } #ifdef __cplusplus } #endif