int * get_vminv_ASL(ASL *asl) { int i, j, n, nv, *vm, *x; if ((x = asl->i.vminv)) return x; if (!(vm = asl->i.vmap)) vm = get_vcmap_ASL(asl, ASL_Sufkind_var); n = asl->i.n_var0 + asl->i.nsufext[ASL_Sufkind_var]; x = (int*)M1alloc(n*sizeof(int)); for(i = 0; i < n; ++i) x[i] = -1; nv = n_var; for(i = 0; i < nv; ++i) { if ((j = vm[i]) >= 0) x[j] = i; } j = n; for(i = 0; i < n; ++i) { if (x[i] < 0) x[i] = j++; } return asl->i.vminv = x; }
void mpec_adjust_ASL(ASL *asl) { MPEC_Adjust *mpa; cde *cd; cde2 *cd2; cgrad **Cgrd, **Cgrd1, **Cgrda, *cg, *cg1, *ncg, **pcg; char *hx0; int *cc, *ck, *cv, *ind1, *ind2, *map; int i, incc, incv, j, k, m, m0, n, n0, n1, n2, nb, ncc, ncc0, nib, nib0; int nnv, nz, nz0, nznew, v1, v2, v3, v4; real *Lc, *Lc0, *Lc1, *Lv, *Lv0, *Lv1, *Uc, *Uc0, *Uc1, *Uv, *Uv0, *Uv1; real a, b, *x; extern void f_OPVARVAL_ASL(), f2_VARVAL_ASL(); n = n0 = n1 = n_var; n2 = asl->i.n_var0; nib = niv + nbv; nib0 = n - nib; /* offset of first linear integer or binary variable */ m = m0 = n_con; nz = nz0 = nzc; cv = cvar; Cgrd = Cgrad; Cgrd1 = Cgrd + m; incc = incv = 1; Lc0 = LUrhs; if (!(Uc0 = Urhsx)) { Uc0 = Lc0 + 1; incc = 2; } Lv0 = LUv; if (!(Uv0 = Uvx)) { Uv0 = Lv0 + 1; incv = 2; } ncc = ncc0 = n_cc; Lc1 = Lc0 + m*incc; Uc1 = Uc0 + m*incc; Lv1 = Lv0 + n*incv; Uv1 = Uv0 + n*incv; for(i = k = 0; i < m0; ++i) if ((j = cv[i])) { ++k; Lc = Lc0 + incc*i; Uc = Uc0 + incc*i; nb = (*Lc > negInfinity) + (*Uc < Infinity); /* nb == 0 or 1 */ if (!nb) { m += 2; n += 4; nz += 6; ++ncc; } else { Lv = Lv0 + incv*(j-1); if (*Lv != 0.) { ++m; ++n; nz += 2; } /* Even if constraint i has the form v >= 0, */ /* add a new variable v1 >= 0 and change the */ /* constraint to v1 = v - rhs, in case v is */ /* involved in more than one complementarity */ ++n; ++nz; } } if (k != ncc0) { fprintf(Stderr, "\nERROR: mpec_adjust saw %d rather than %d incoming complementarities.\n", k, ncc0); exit(1); } n_var = n; n_con = m; nnv = n - n0; if (n_obj) adjust_zerograds_ASL(asl, nnv); if (n_conjac[1] >= m0) n_conjac[1] = m; nzc = nz; n_cc = ncc; nznew = nz - nz0; ncg = (cgrad*)M1alloc(2*(ncc + ncc0)*sizeof(int) + nznew*sizeof(cgrad) + ncc0*sizeof(cgrad*) + sizeof(MPEC_Adjust)); asl->i.mpa = mpa = (MPEC_Adjust*)(ncg + nznew); Cgrda = mpa->Cgrda = (cgrad**)(mpa + 1); asl->i.ccind1 = ind1 = (int*)(Cgrda + ncc0); asl->i.ccind2 = ind2 = ind1 + ncc; mpa->cc = cc = ind2 + ncc; mpa->ck = ck = mpa->cce = cc + ncc0; mpa->m0 = m0; mpa->n0 = n0 - nib; mpa->rhs1 = Lc1; mpa->incc = incc; mpa->incv = incv; map = get_vcmap_ASL(asl, ASL_Sufkind_var); if (n1 < n2) { j = n2; k = n2 + asl->i.nsufext[ASL_Sufkind_var]; for(i = n1; i < k; ++i, ++j) map[i] = j; } if (nib) { /* Three reverse calls move nib values of map up nnv places. */ j = n0 - nib; reverse(map+j, map + n0 + nnv); reverse(map+j, map + j + nnv); reverse(map + j + nnv, map + n0 + nnv); i = n0 + nnv; while(--i >= n0) { j = i - nnv; Lv0[incv*i] = Lv0[incv*j]; Uv0[incv*i] = Uv0[incv*j]; } if ((x = X0)) { i = n0 + nnv; while(--i >= n0) x[i] = x[i-nnv]; for(i = n0 - nnv; i < n0; ++i) x[i] = 0.; if ((hx0 = havex0)) { for(i = n0 + nnv; --i >= n0; ) hx0[i] = hx0[i-nnv]; for(i = n0 - nnv;i < n0; ++i) hx0[i] = 0; } } Lv1 -= j = incv*nib; Uv1 -= j; } else if ((x = X0)) { memset(x + n0, 0, nnv*sizeof(real)); if ((hx0 = havex0)) memset(hx0 + n0, 0, nnv); } #define vset(x,y) *x = y; x += incv; for(i = 0; i < m0; ++i) if ((j = cv[i])) { if (j > nib0) j += nnv; *cc++ = i; pcg = &Cgrd[i]; cg = 0; while((cg1 = *pcg)) pcg = &(cg = cg1)->next; *Cgrda++ = cg; Lc = Lc0 + incv*i; Uc = Uc0 + incc*i; Lv = Lv0 + incv*--j; Uv = Uv0 + incv*j; a = *Lc; b = *Uc; *ck++ = nb = (a > negInfinity) + (b < Infinity); if (nb == 0) { /* change L <= v = _svar[j] <= U */ /* and -Infinity <= body <= Infinity into */ /* v1 = v - L >= 0, v2 = U - v >= 0, */ /* v3 - v4 = body, v3 >= 0, v4 >= 0, */ /* v1 complements v3, v2 complements v4 */ *Lc = *Uc = 0.; *ind1++ = v1 = n1++; *ind1++ = v2 = n1++; *ind2++ = v3 = n1++; *ind2++ = v4 = n1++; for(k = 0; k < 4; ++k) { vset(Lv1, 0.); vset(Uv1, Infinity); } ncg[1].varno = n2+3; ncg[1].coef = 1.; ncg[1].next = 0; ncg[0].varno = n2+2; ncg[0].coef = -1.; ncg[0].next = &ncg[1]; *pcg = ncg; ncg += 2; ncg[1].varno = n2; ncg[1].coef = -1.; ncg[1].next = 0; ncg[0].varno = j; ncg[0].coef = 1.; ncg[0].next = &ncg[1]; *Lc1 = *Uc1 = *Lv; Lc1 += incc; Uc1 += incc; *Cgrd1++ = ncg; ncg += 2; ncg[1].varno = n2+1; ncg[1].coef = 1.; ncg[1].next = 0; ncg[0].varno = j; ncg[0].coef = 1.; ncg[0].next = &ncg[1]; *Lc1 = *Uc1 = *Uv; Lc1 += incc; Uc1 += incc; *Cgrd1++ = ncg; ncg += 2; n2 += 4; } else { /*nb == 1*/ v1 = j; if (*Lv != 0.) { /* For v = _svar[j], replace */ /* v >= a with v1 = v - a, v1 >= 0, or */ /* v <= b with v1 = b - v, v1 >= 0 */ v1 = n1++; vset(Lv1, 0.); vset(Uv1, Infinity); ncg[1].varno = n2++; ncg[1].next = 0; ncg[0].varno = j; ncg[0].coef = 1.; ncg[0].next = &ncg[1]; if (*Lv > negInfinity) { ncg[1].coef = -1.; *Lc1 = *Uc1 = *Lv; } else { ncg[1].coef = 1.; *Lc1 = *Uc1 = *Uv; } Lc1 += incc; Uc1 += incc; *Cgrd1++ = ncg; ncg += 2; } *ind1++ = v1; *ind2++ = n1++; ncg->varno = n2++; ncg->next = 0; vset(Lv1, 0.); vset(Uv1, Infinity); if (*Lv > negInfinity) { ncg->coef = -1.; *Uc = *Lc; } else { ncg->coef = 1.; *Lc = *Uc; } *pcg = ncg++; } } #undef vset if ((map = asl->i.cmap)) { j = asl->i.n_con0; Cgrd1 = asl->i.Cgrad0; for(i = m0; i < m; ++i) { map[i] = -1; Cgrd1[j++] = Cgrd[i]; } } i = m0; k = m - m0; switch(asl->i.ASLtype) { case ASL_read_pfg: memset(((ASL_pfg*)asl)->P.cps + m0, 0, k*sizeof(ps_func)); cd = ((ASL_pfg*)asl)->I.con_de_; goto have_cd; case ASL_read_f: case ASL_read_fg: cd = ((ASL_fg*)asl)->I.con_de_; have_cd: while(i < m) cd[i++].e = (expr*)&ZeroExpr; break; case ASL_read_fgh: cd2 = ((ASL_fgh*)asl)->I.con2_de_; goto have_cd2; case ASL_read_pfgh: memset(((ASL_pfgh*)asl)->P.cps + m0, 0, k*sizeof(ps_func2)); cd2 = ((ASL_pfgh*)asl)->I.con2_de_; have_cd2: while(i < m) cd2[i++].e = (expr2*)&ZeroExpr; } }
static void obj_adj1(ASL *asl, int no) { Objrep *od, **pod; cgrad **Cgrd, **Cgrd0, *cg, *cgo, **pcg, **pcge; efunc_n *op; expr_n *e; int co, cv, flags, i, incc, incv, j, k, m, n; int *Cvar, *cm, *vm, *zg, **zgp; ograd *og; ps_func *P; ps_func2 *P2; real *Lc, *Lv, *Uc, *Uv, c1, c2, rhs, t; op = f_OPNUM_ASL; switch (asl->i.ASLtype) { case ASL_read_fg: e = (expr_n*)((ASL_fg*)asl)->I.obj_de_[no].e; break; case ASL_read_fgh: e = (expr_n*)((ASL_fgh*)asl)->I.obj2_de_[no].e; break; case ASL_read_pfg: e = (expr_n*)((ASL_pfg*)asl)->I.obj_de_[no].e; P = &((ASL_pfg*)asl)->P.ops[no]; if (P->nb || P->ng) return; op = (efunc_n*)OPNUM; break; case ASL_read_pfgh: e = (expr_n*)((ASL_pfgh*)asl)->I.obj2_de_[no].e; P2 = &((ASL_pfgh*)asl)->P.ops[no]; if (P2->nb || P2->ng) return; op = (efunc_n*)OPNUM; break; default: fprintf(Stderr, "Bug: surprise ASLtype = %d in obj_adj\n", asl->i.ASLtype); exit(1); } if (e->op != op) return; og = Ograd[no]; if (!og || og->next) return; cv = og->varno; if (cv < nlvc) return; if (!(c1 = og->coef)) return; if (Uvx) { Lv = LUv + cv; Uv = Uvx + cv; incv = 1; } else { Lv = LUv + 2*cv; Uv = Lv + 1; incv = 2; } if (*Lv > negInfinity || *Uv < Infinity) return; pcg = Cgrd = Cgrad; cgo = 0; for(pcge = pcg + n_con; pcg < pcge; ++pcg) { for(cg = *pcg; cg; cg = cg->next) if (cg->varno == cv) { if (cgo) return; cgo = cg; co = pcg - Cgrd; for(k = 0, cg = *pcg; cg; cg = cg->next) ++k; break; } } if (!cgo) return; if (n_cc && cvar[co]) return; if ((c2 = cgo->coef) == 0.) return; t = c1 / c2; j = t < 0.; if (objtype[no]) j = 1 - j; if (Urhsx) { Lc = LUrhs + co; Uc = Urhsx + co; incc = 1; } else { Lc = LUrhs + 2*co; Uc = Lc + 1; incc = 2; } if (j) { if ((rhs = *Uc) >= Infinity) return; } else { if ((rhs = *Lc) <= negInfinity) return; } flags = asl->i.rflags; if (*Lc < *Uc) { if (!(flags & ASL_obj_replace_ineq)) return; } else { if (!(flags & ASL_obj_replace_eq)) return; } if (co < nlc) { --nlc; ++nlo; } nzc -= k; nzo += k - 1; pod = asl->i.Or; od = (Objrep*)M1alloc(sizeof(Objrep) + (pod ? 0 : n_obj*sizeof(Objrep*))); if (!pod) { pod = asl->i.Or = (Objrep**)(od+1); for(k = n_obj; --k >= 0; ) pod[k] = 0; } pod[no] = od; od->ico = co; od->ivo = cv; od->c0 = e->v; od->c0a = e->v + t*rhs; od->c1 = c1; od->c12 = -t; od->nxval = -1; od->f = 0.; pcg = &Cgrd[co]; while((cg = *pcg) != cgo) pcg = &cg->next; *pcg = cgo->next; if ((cm = asl->i.cmap) && (Cgrd0 = asl->i.Cgrad0)) Cgrd0[cm[co]] = Cgrd[co]; m = --n_con; if (n_conjac[1] > m) n_conjac[1] = m; if (co != m) { cm = get_vcmap_ASL(asl, ASL_Sufkind_con); pcg = Cgrd; Cvar = cvar; for(i = co; i < m; i = j) { cm[i] = cm[j = i + 1]; pcg[i] = pcg[j]; if (Cvar) Cvar[i] = Cvar[j]; } cm[m] = -1; } for(i = co; i < m; ++i) { *Lc = Lc[incc]; *Uc = Uc[incc]; Lc += incc; Uc += incc; } n = --n_var; if (cv != n) { vm = get_vcmap_ASL(asl, ASL_Sufkind_var); for(i = cv; i < n; ++i) vm[i] = vm[i+1]; vm[n] = -1; } for(i = cv; i < n; ++i) { *Lv = Lv[incv]; *Uv = Uv[incv]; Lv += incv; Uv += incv; } if ((zgp = zerograds)) for(zg = zgp[no]; *zg >= 0; ++zg) if (*zg >= cv) --*zg; }
static void paradj(ASL *asl, int *pno, real **pow, real **py) { Objrep *Od, **Or; int *cm, i, j, k, nc, nc0, needow, no, nobj; real *ow, wo, *ws, *y, *ys; nobj = n_obj; no = *pno; Od = 0; ow = *pow; wo = 1.; Or = asl->i.Or; ws = asl->i.orscratch; ys = ws + nobj; memset(ys, 0, asl->i.n_con0*sizeof(real)); cm = get_vcmap_ASL(asl, ASL_Sufkind_con); if ((y = *py)) { *py = ys; nc = n_con; nc0 = asl->i.n_con0; for(i = 0; i < nc; ++i) if ((j = cm[i]) < nc0) ys[j] = y[i]; } needow = 1; if (no >= 0 && no < nobj) { k = nobj; if (ow && (wo = ow[no]) == 0.) no = *pno = -1; else Od = Or[no]; ow = 0; } else if (ow) { needow = 0; for(i = k = 0; i < nobj; ++i) { if (ow[i]) { if (Or[i]) { if (!Od) { k = i; Od = Or[i]; wo = ow[i]; continue; } } else ++needow; } } if (!needow) ow = 0; } if (Od) { *pno = -1; if (!y) *py = ys; if (ow) { memcpy(*pow = ws, ow, nobj*sizeof(real)); ow = ws; wo = ow[k]; } loop: ys[Od->ico] = wo * Od->c12; if (ow) { ow[k] = 0.; while(++k < nobj) if ((wo = ow[k]) && (Od = Or[k])) goto loop; } } *pow = ow; }