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; } }
int prob_adj_ASL(ASL *asl) { #undef cde cde *d, *de; cde2 *d2, *d2e; cgrad *cg, **pcg, **pcge; int flags, k; #ifndef NO_BOUNDSFILE_OPTION /*{*/ FILE *f; char *bf, buf[4096], *s, *s1, *se; int a, i, n1, nr, nv, swap; real *L, *U, *x; size_t inc, m, n; #endif /*}*/ if (n_obj) adjust_zerograds_ASL(asl, 0); flags = asl->i.rflags; asl->i.Cgrad0 = asl->i.Cgrad_; if ((k = asl->i.nsufext[ASL_Sufkind_con])) { switch(asl->i.ASLtype) { case ASL_read_f: case ASL_read_fg: d = ((ASL_fg*)asl)->I.con_de_; goto have_d; case ASL_read_fgh: d2 = ((ASL_fgh*)asl)->I.con2_de_; goto have_d2; case ASL_read_pfg: d = ((ASL_pfg*)asl)->I.con_de_; have_d: d += n_con; for(de = d + k; d < de; ++d) d->e = (expr*)&Zero; break; case ASL_read_pfgh: d2 = ((ASL_pfgh*)asl)->I.con2_de_; have_d2: d2 += n_con; for(d2e = d2 + k; d2 < d2e; ++d2) d2->e = (expr2*)&Zero; } } if (flags & (ASL_obj_replace_eq | ASL_obj_replace_ineq)) obj_adj_ASL(asl); if (!A_vals) { if (flags & ASL_cc_simplify && n_cc) mpec_adjust_ASL(asl); if (flags & ASL_rowwise_jac) { pcg = Cgrad; pcge = pcg + n_con; k = 0; while(pcg < pcge) for(cg = *pcg++; cg; cg = cg->next) cg->goff = k++; } } if (n_obj) zerograd_chk(asl); #ifndef NO_BOUNDSFILE_OPTION /*{*/ if ((bf = asl->i.boundsfile)) { if (!(f = fopen(bf, "rb"))) bad_bounds(asl, "Cannot open boundsfile \"%s\".", bf); m = sizeof(buf); if ((n = fread(buf, 1, m, f)) < 24 || strncmp(buf, "Bounds, x; arith ", 17)) { badmagic: bad_bounds(asl, "Bad magic in boundsfile \"%s\".", bf); } a = (int)strtol(s = buf+17, &se, 10); if (se <= s || a < 0 || a > 2 || *se >= ' ') goto badmagic; if (a == 0 && *se == '\r') ++se; if (*se++ != '\n') goto badmagic; nv = n_var; L = LUv; if ((U = Uvx)) inc = 1; else { U = L + 1; inc = 2; } if (!(x = X0)) X0 = x = (real*)M1alloc(nv*sizeof(real)); swap = 0; if (a) { if (a != Arith_Kind_ASL) swap = 1; s = buf + 20; n1 = *(int*)s; if (swap) bswap_ASL(&n1, sizeof(n1)); if (n1 != nv) { bad_n1: bad_bounds(asl, "Expected %d bounds triples in boundsfile" " \"%s\"; got %d.", nv, bf, n1); } s += sizeof(int); se = buf + n; for(i = 1; i <= nv; ++i) { if (se-s < 3*sizeof(real)) { for(s1 = buf; s < se; ++s, ++s1) *s1 = *s; m = s1 - buf; m += n = fread(s1, 1, sizeof(buf) - m, f); se = buf + m; if (m < 3*sizeof(real)) { too_few: bad_bounds(asl, "%d too few bound triples " "in boundsfile \"%s\".", nv - i + 1, bf); } s = buf; } *L = *(real*)s; s += sizeof(real); *x = *(real*)s; s += sizeof(real); *U = *(real*)s; s += sizeof(real); if (swap) { bswap_ASL(L, sizeof(real)); bswap_ASL(x, sizeof(real)); bswap_ASL(U, sizeof(real)); } if (*L > *U || *x < *L || *x > *U) { bad_triple: bad_bounds(asl, "bad bound triple %d in bounds file " "\"%s\":\n\tL = %.g\n\tx = %.g\n\tU = %.g", i, bf, *L, *x, *U); } L += inc; U += inc; ++x; } } else { n1 = (int)strtol(se, &s, 10); if (n1 != nv) goto bad_n1; se = buf + n; for(i = 1; i <= nv; ++i) { nr = 0; tryagain: while(s < se && *s <= ' ') ++s; s1 = s; for(k = 0; k < 3 && s1 < se; ++k) { while(s1 < se && *s1 > ' ') ++s1; while(s1 < se && *s1 <= ' ') ++s1; } if (k < 3) { if (nr) goto too_few; for(s1 = buf; s < se; ++s, ++s1) *s1 = *s; m = sizeof(buf) - (s1 - buf); n = fread(s1, 1, m, f); se = s1 + n; s = buf; nr = 1; goto tryagain; } *L = strtod(s, &s1); if (s1 <= s || *s1 > ' ') { badnumber: while(s1 < se && *s1 > ' ') ++s1; bad_bounds(asl, "Bound triple %d: bad number \"%.*s\"" " in boundsfile \"%s\".", i, (int)(s1-s), s, bf); } *x = strtod(s = s1, &s1); if (s1 <= s || *s1 > ' ') goto badnumber; *U = strtod(s = s1, &s1); if (s1 <= s || *s1 > ' ') goto badnumber; if (*L > *U || *x < *L || *x > *U) goto bad_triple; L += inc; U += inc; ++x; s = s1; } } fclose(f); } #endif /*}*/ asl->i.err_jmp_ = 0; asl->i.rd_M1z_bytes = asl->i.tot_M1z_bytes; return 0; }