/* * Sets up all data structures needed. * Replace by codegen */ pwork* ECOS_setup(idxint n, idxint m, idxint p, idxint l, idxint ncones, idxint* q, pfloat* Gpr, idxint* Gjc, idxint* Gir, pfloat* Apr, idxint* Ajc, idxint* Air, pfloat* c, pfloat* h, pfloat* b) { idxint i, j, k, cidx, conesize, lnz, amd_result, nK, *Ljc, *Lir, *P, *Pinv, *Sign; pwork* mywork; double Control [AMD_CONTROL], Info [AMD_INFO]; pfloat rx, ry, rz, *Lpr; spmat *At, *Gt, *KU; #if PROFILING > 0 timer tsetup; #endif #if PROFILING > 1 timer tcreatekkt; timer tmattranspose; timer tordering; #endif #if PROFILING > 0 tic(&tsetup); #endif #if PRINTLEVEL > 2 PRINTTEXT("\n"); PRINTTEXT(" *******************************************************************************\n"); PRINTTEXT(" * ECOS: Embedded Conic Solver - Sparse Interior Point method for SOCPs *\n"); PRINTTEXT(" * *\n"); PRINTTEXT(" * NOTE: The solver is based on L. Vandenberghe's 'The CVXOPT linear and quad- *\n"); PRINTTEXT(" * ratic cone program solvers', March 20, 2010. Available online: *\n"); PRINTTEXT(" * [http://abel.ee.ucla.edu/cvxopt/documentation/coneprog.pdf] *\n"); PRINTTEXT(" * *\n"); PRINTTEXT(" * This code uses T.A. Davis' sparse LDL package and AMD code. *\n"); PRINTTEXT(" * [http://www.cise.ufl.edu/research/sparse] *\n"); PRINTTEXT(" * *\n"); PRINTTEXT(" * Written during a summer visit at Stanford University with S. Boyd. *\n"); PRINTTEXT(" * *\n"); PRINTTEXT(" * (C) Alexander Domahidi, Automatic Control Laboratory, ETH Zurich, 2012-13. *\n"); PRINTTEXT(" * Email: [email protected] *\n"); PRINTTEXT(" *******************************************************************************\n"); PRINTTEXT("\n\n"); PRINTTEXT("PROBLEM SUMMARY:\n"); PRINTTEXT(" Primal variables (n): %d\n", (int)n); PRINTTEXT("Equality constraints (p): %d\n", (int)p); PRINTTEXT(" Conic variables (m): %d\n", (int)m); PRINTTEXT("- - - - - - - - - - - - - - -\n"); PRINTTEXT(" Size of LP cone: %d\n", (int)l); PRINTTEXT(" Number of SOCs: %d\n", (int)ncones); for( i=0; i<ncones; i++ ){ PRINTTEXT(" Size of SOC #%02d: %d\n", (int)(i+1), (int)q[i]); } #endif /* get work data structure */ mywork = (pwork *)MALLOC(sizeof(pwork)); #if PRINTLEVEL > 2 PRINTTEXT("Memory allocated for WORK struct\n"); #endif /* dimensions */ mywork->n = n; mywork->m = m; mywork->p = p; mywork->D = l + ncones; #if PRINTLEVEL > 2 PRINTTEXT("Set dimensions\n"); #endif /* variables */ mywork->x = (pfloat *)MALLOC(n*sizeof(pfloat)); mywork->y = (pfloat *)MALLOC(p*sizeof(pfloat)); mywork->z = (pfloat *)MALLOC(m*sizeof(pfloat)); mywork->s = (pfloat *)MALLOC(m*sizeof(pfloat)); mywork->lambda = (pfloat *)MALLOC(m*sizeof(pfloat)); mywork->dsaff_by_W = (pfloat *)MALLOC(m*sizeof(pfloat)); mywork->dsaff = (pfloat *)MALLOC(m*sizeof(pfloat)); mywork->dzaff = (pfloat *)MALLOC(m*sizeof(pfloat)); mywork->saff = (pfloat *)MALLOC(m*sizeof(pfloat)); mywork->zaff = (pfloat *)MALLOC(m*sizeof(pfloat)); mywork->W_times_dzaff = (pfloat *)MALLOC(m*sizeof(pfloat)); #if PRINTLEVEL > 2 PRINTTEXT("Memory allocated for variables\n"); #endif /* best iterates so far */ mywork->best_x = (pfloat *)MALLOC(n*sizeof(pfloat)); mywork->best_y = (pfloat *)MALLOC(p*sizeof(pfloat)); mywork->best_z = (pfloat *)MALLOC(m*sizeof(pfloat)); mywork->best_s = (pfloat *)MALLOC(m*sizeof(pfloat)); mywork->best_info = (stats *)MALLOC(sizeof(stats)); /* cones */ mywork->C = (cone *)MALLOC(sizeof(cone)); #if PRINTLEVEL > 2 PRINTTEXT("Memory allocated for cone struct\n"); #endif /* LP cone */ mywork->C->lpc = (lpcone *)MALLOC(sizeof(lpcone)); mywork->C->lpc->p = l; if( l > 0 ){ mywork->C->lpc->w = (pfloat *)MALLOC(l*sizeof(pfloat)); mywork->C->lpc->v = (pfloat *)MALLOC(l*sizeof(pfloat)); mywork->C->lpc->kkt_idx = (idxint *)MALLOC(l*sizeof(idxint)); #if PRINTLEVEL > 2 PRINTTEXT("Memory allocated for LP cone\n"); #endif } else { mywork->C->lpc->w = NULL; mywork->C->lpc->v = NULL; mywork->C->lpc->kkt_idx = NULL; #if PRINTLEVEL > 2 PRINTTEXT("No LP cone present, pointers filled with NULL\n"); #endif } /* Second-order cones */ mywork->C->soc = (socone *)MALLOC(ncones*sizeof(socone)); mywork->C->nsoc = ncones; cidx = 0; for( i=0; i<ncones; i++ ){ conesize = (idxint)q[i]; mywork->C->soc[i].p = conesize; mywork->C->soc[i].a = 0; mywork->C->soc[i].eta = 0; mywork->C->soc[i].q = (pfloat *)MALLOC((conesize-1)*sizeof(pfloat)); mywork->C->soc[i].skbar = (pfloat *)MALLOC((conesize)*sizeof(pfloat)); mywork->C->soc[i].zkbar = (pfloat *)MALLOC((conesize)*sizeof(pfloat)); #if CONEMODE == 0 mywork->C->soc[i].Didx = (idxint *)MALLOC((conesize)*sizeof(idxint)); #endif #if CONEMODE > 0 mywork->C->soc[i].colstart = (idxint *)MALLOC((conesize)*sizeof(idxint)); #endif cidx += conesize; } #if PRINTLEVEL > 2 PRINTTEXT("Memory allocated for second-order cones\n"); #endif /* info struct */ mywork->info = (stats *)MALLOC(sizeof(stats)); #if PROFILING > 1 mywork->info->tfactor = 0; mywork->info->tkktsolve = 0; mywork->info->tfactor_t1 = 0; mywork->info->tfactor_t2 = 0; #endif #if PRINTLEVEL > 2 PRINTTEXT("Memory allocated for info struct\n"); #endif #if defined EQUILIBRATE && EQUILIBRATE > 0 /* equilibration vector */ mywork->xequil = (pfloat *)MALLOC(n*sizeof(pfloat)); mywork->Aequil = (pfloat *)MALLOC(p*sizeof(pfloat)); mywork->Gequil = (pfloat *)MALLOC(m*sizeof(pfloat)); #if PRINTLEVEL > 2 PRINTTEXT("Memory allocated for equilibration vectors\n"); #endif #endif /* settings */ mywork->stgs = (settings *)MALLOC(sizeof(settings)); mywork->stgs->maxit = MAXIT; mywork->stgs->gamma = GAMMA; mywork->stgs->delta = DELTA; mywork->stgs->eps = EPS; mywork->stgs->nitref = NITREF; mywork->stgs->abstol = ABSTOL; mywork->stgs->feastol = FEASTOL; mywork->stgs->reltol = RELTOL; mywork->stgs->abstol_inacc = ATOL_INACC; mywork->stgs->feastol_inacc = FTOL_INACC; mywork->stgs->reltol_inacc = RTOL_INACC; mywork->stgs->verbose = VERBOSE; #if PRINTLEVEL > 2 PRINTTEXT("Written settings\n"); #endif mywork->c = c; mywork->h = h; mywork->b = b; #if PRINTLEVEL > 2 PRINTTEXT("Hung pointers for c, h and b into WORK struct\n"); #endif /* Store problem data */ if(Apr && Ajc && Air) { mywork->A = createSparseMatrix(p, n, Ajc[n], Ajc, Air, Apr); } else { mywork->A = NULL; } if (Gpr && Gjc && Gir) { mywork->G = createSparseMatrix(m, n, Gjc[n], Gjc, Gir, Gpr); } else { /* create an empty sparse matrix */ mywork->G = createSparseMatrix(m, n, 0, Gjc, Gir, Gpr); } #if defined EQUILIBRATE && EQUILIBRATE > 0 set_equilibration(mywork); #if PRINTLEVEL > 2 PRINTTEXT("Done equilibrating\n"); #endif #endif #if PROFILING > 1 mywork->info->ttranspose = 0; tic(&tmattranspose); #endif if(mywork->A) At = transposeSparseMatrix(mywork->A); else At = NULL; #if PROFILING > 1 mywork->info->ttranspose += toc(&tmattranspose); #endif #if PRINTLEVEL > 2 PRINTTEXT("Transposed A\n"); #endif #if PROFILING > 1 tic(&tmattranspose); #endif Gt = transposeSparseMatrix(mywork->G); #if PROFILING > 1 mywork->info->ttranspose += toc(&tmattranspose); #endif #if PRINTLEVEL > 2 PRINTTEXT("Transposed G\n"); #endif /* set up KKT system */ #if PROFILING > 1 tic(&tcreatekkt); #endif createKKT_U(Gt, At, mywork->C, &Sign, &KU); #if PROFILING > 1 mywork->info->tkktcreate = toc(&tcreatekkt); #endif #if PRINTLEVEL > 2 PRINTTEXT("Created upper part of KKT matrix K\n"); #endif /* * Set up KKT system related data * (L comes later after symbolic factorization) */ nK = KU->n; #if DEBUG > 0 dumpSparseMatrix(KU, "KU0.txt"); #endif #if PRINTLEVEL > 2 PRINTTEXT("Dimension of KKT matrix: %d\n", (int)nK); PRINTTEXT("Non-zeros in KKT matrix: %d\n", (int)KU->nnz); #endif /* allocate memory in KKT system */ mywork->KKT = (kkt *)MALLOC(sizeof(kkt)); mywork->KKT->D = (pfloat *)MALLOC(nK*sizeof(pfloat)); mywork->KKT->Parent = (idxint *)MALLOC(nK*sizeof(idxint)); mywork->KKT->Pinv = (idxint *)MALLOC(nK*sizeof(idxint)); mywork->KKT->work1 = (pfloat *)MALLOC(nK*sizeof(pfloat)); mywork->KKT->work2 = (pfloat *)MALLOC(nK*sizeof(pfloat)); mywork->KKT->work3 = (pfloat *)MALLOC(nK*sizeof(pfloat)); mywork->KKT->work4 = (pfloat *)MALLOC(nK*sizeof(pfloat)); mywork->KKT->work5 = (pfloat *)MALLOC(nK*sizeof(pfloat)); mywork->KKT->work6 = (pfloat *)MALLOC(nK*sizeof(pfloat)); mywork->KKT->Flag = (idxint *)MALLOC(nK*sizeof(idxint)); mywork->KKT->Pattern = (idxint *)MALLOC(nK*sizeof(idxint)); mywork->KKT->Lnz = (idxint *)MALLOC(nK*sizeof(idxint)); mywork->KKT->RHS1 = (pfloat *)MALLOC(nK*sizeof(pfloat)); mywork->KKT->RHS2 = (pfloat *)MALLOC(nK*sizeof(pfloat)); mywork->KKT->dx1 = (pfloat *)MALLOC(mywork->n*sizeof(pfloat)); mywork->KKT->dx2 = (pfloat *)MALLOC(mywork->n*sizeof(pfloat)); mywork->KKT->dy1 = (pfloat *)MALLOC(mywork->p*sizeof(pfloat)); mywork->KKT->dy2 = (pfloat *)MALLOC(mywork->p*sizeof(pfloat)); mywork->KKT->dz1 = (pfloat *)MALLOC(mywork->m*sizeof(pfloat)); mywork->KKT->dz2 = (pfloat *)MALLOC(mywork->m*sizeof(pfloat)); mywork->KKT->Sign = (idxint *)MALLOC(nK*sizeof(idxint)); mywork->KKT->PKPt = newSparseMatrix(nK, nK, KU->nnz); mywork->KKT->PK = (idxint *)MALLOC(KU->nnz*sizeof(idxint)); #if PRINTLEVEL > 2 PRINTTEXT("Created memory for KKT-related data\n"); #endif /* calculate ordering of KKT matrix using AMD */ P = (idxint *)MALLOC(nK*sizeof(idxint)); #if PROFILING > 1 tic(&tordering); #endif AMD_defaults(Control); amd_result = AMD_order(nK, KU->jc, KU->ir, P, Control, Info); #if PROFILING > 1 mywork->info->torder = toc(&tordering); #endif if( amd_result == AMD_OK ){ #if PRINTLEVEL > 2 PRINTTEXT("AMD ordering successfully computed.\n"); AMD_info(Info); #endif } else { #if PRINTLEVEL > 2 PRINTTEXT("Problem in AMD ordering, exiting.\n"); AMD_info(Info); #endif return NULL; } /* calculate inverse permutation and permutation mapping of KKT matrix */ pinv(nK, P, mywork->KKT->Pinv); Pinv = mywork->KKT->Pinv; #if DEBUG > 0 dumpDenseMatrix_i(P, nK, 1, "P.txt"); dumpDenseMatrix_i(mywork->KKT->Pinv, nK, 1, "PINV.txt"); #endif permuteSparseSymmetricMatrix(KU, mywork->KKT->Pinv, mywork->KKT->PKPt, mywork->KKT->PK); /* permute sign vector */ for( i=0; i<nK; i++ ){ mywork->KKT->Sign[Pinv[i]] = Sign[i]; } #if PRINTLEVEL > 3 PRINTTEXT("P = ["); for( i=0; i<nK; i++ ){ PRINTTEXT("%d ", (int)P[i]); } PRINTTEXT("];\n"); PRINTTEXT("Pinv = ["); for( i=0; i<nK; i++ ){ PRINTTEXT("%d ", (int)Pinv[i]); } PRINTTEXT("];\n"); PRINTTEXT("Sign = ["); for( i=0; i<nK; i++ ){ PRINTTEXT("%+d ", (int)Sign[i]); } PRINTTEXT("];\n"); PRINTTEXT("SignP = ["); for( i=0; i<nK; i++ ){ PRINTTEXT("%+d ", (int)mywork->KKT->Sign[i]); } PRINTTEXT("];\n"); #endif /* symbolic factorization */ Ljc = (idxint *)MALLOC((nK+1)*sizeof(idxint)); #if PRINTLEVEL > 2 PRINTTEXT("Allocated memory for cholesky factor L\n"); #endif LDL_symbolic2( mywork->KKT->PKPt->n, /* A and L are n-by-n, where n >= 0 */ mywork->KKT->PKPt->jc, /* input of size n+1, not modified */ mywork->KKT->PKPt->ir, /* input of size nz=Ap[n], not modified */ Ljc, /* output of size n+1, not defined on input */ mywork->KKT->Parent, /* output of size n, not defined on input */ mywork->KKT->Lnz, /* output of size n, not defined on input */ mywork->KKT->Flag /* workspace of size n, not defn. on input or output */ ); /* assign memory for L */ lnz = Ljc[nK]; #if PRINTLEVEL > 2 PRINTTEXT("Nonzeros in L, excluding diagonal: %d\n", (int)lnz) ; #endif Lir = (idxint *)MALLOC(lnz*sizeof(idxint)); Lpr = (pfloat *)MALLOC(lnz*sizeof(pfloat)); mywork->KKT->L = createSparseMatrix(nK, nK, lnz, Ljc, Lir, Lpr); #if PRINTLEVEL > 2 PRINTTEXT("Created Cholesky factor of K in KKT struct\n"); #endif /* permute KKT matrix - we work on this one from now on */ permuteSparseSymmetricMatrix(KU, mywork->KKT->Pinv, mywork->KKT->PKPt, NULL); #if DEBUG > 0 dumpSparseMatrix(mywork->KKT->PKPt, "PKPt.txt"); #endif #if CONEMODE > 0 /* zero any off-diagonal elements in (permuted) scalings in KKT matrix */ for (i=0; i<mywork->C->nsoc; i++) { for (j=1; j<mywork->C->soc[i].p; j++) { for (k=0; k<j; k++) { mywork->KKT->PKPt->pr[mywork->KKT->PK[mywork->C->soc[i].colstart[j]+k]] = 0; } } } #endif #if DEBUG > 0 dumpSparseMatrix(mywork->KKT->PKPt, "PKPt0.txt"); #endif /* set up RHSp for initialization */ k = 0; j = 0; for( i=0; i<n; i++ ){ mywork->KKT->RHS1[Pinv[k++]] = 0; } for( i=0; i<p; i++ ){ mywork->KKT->RHS1[Pinv[k++]] = b[i]; } for( i=0; i<l; i++ ){ mywork->KKT->RHS1[Pinv[k++]] = h[i]; j++; } for( l=0; l<ncones; l++ ){ for( i=0; i < mywork->C->soc[l].p; i++ ){ mywork->KKT->RHS1[Pinv[k++]] = h[j++]; } #if CONEMODE == 0 mywork->KKT->RHS1[Pinv[k++]] = 0; mywork->KKT->RHS1[Pinv[k++]] = 0; #endif } #if PRINTLEVEL > 2 PRINTTEXT("Written %d entries of RHS1\n", (int)k); #endif /* set up RHSd for initialization */ for( i=0; i<n; i++ ){ mywork->KKT->RHS2[Pinv[i]] = -c[i]; } for( i=n; i<nK; i++ ){ mywork->KKT->RHS2[Pinv[i]] = 0; } /* get scalings of problem data */ rx = norm2(c, n); mywork->resx0 = MAX(1, rx); ry = norm2(b, p); mywork->resy0 = MAX(1, ry); rz = norm2(h, m); mywork->resz0 = MAX(1, rz); /* get memory for residuals */ mywork->rx = (pfloat *)MALLOC(n*sizeof(pfloat)); mywork->ry = (pfloat *)MALLOC(p*sizeof(pfloat)); mywork->rz = (pfloat *)MALLOC(m*sizeof(pfloat)); /* clean up */ mywork->KKT->P = P; FREE(Sign); if(At) freeSparseMatrix(At); freeSparseMatrix(Gt); freeSparseMatrix(KU); #if PROFILING > 0 mywork->info->tsetup = toc(&tsetup); #endif return mywork; }
/* * Main solver routine. */ idxint ECOS_solve(pwork* w) { idxint i, initcode, KKT_FACTOR_RETURN_CODE; pfloat dtau_denom, dtauaff, dkapaff, sigma, dtau, dkap, bkap, pres_prev; idxint exitcode = ECOS_FATAL, interrupted; #if DEBUG char fn[20]; #endif #if (defined _WIN32 || defined _WIN64 ) /* sets width of exponent for floating point numbers to 2 instead of 3 */ unsigned int old_output_format = _set_output_format(_TWO_DIGIT_EXPONENT); #endif #if PROFILING > 0 timer tsolve; #endif #if PROFILING > 1 timer tfactor, tkktsolve; #endif #if PROFILING > 0 /* start timer */ tic(&tsolve); #endif /* initialize ctrl-c support */ init_ctrlc(); /* Initialize solver */ initcode = init(w); if( initcode == ECOS_FATAL ){ #if PRINTLEVEL > 0 if( w->stgs->verbose ) PRINTTEXT("\nFatal error during initialization, aborting."); #endif return ECOS_FATAL; } /* MAIN INTERIOR POINT LOOP ---------------------------------------------------------------------- */ for( w->info->iter = 0; w->info->iter <= w->stgs->maxit ; w->info->iter++ ){ /* Compute residuals */ computeResiduals(w); /* Update statistics */ updateStatistics(w); #if PRINTLEVEL > 1 /* Print info */ if( w->stgs->verbose ) printProgress(w->info); #endif /* SAFEGUARD: Backtrack to best previously seen iterate if * * - the update was bad such that the primal residual PRES has increased by a factor of SAFEGUARD, or * - the gap became negative * * If the safeguard is activated, the solver tests if reduced precision has been reached, and reports * accordingly. If not even reduced precision is reached, ECOS returns the flag ECOS_NUMERICS. */ if( w->info->iter > 0 && (w->info->pres > SAFEGUARD*pres_prev || w->info->gap < 0) ){ #if PRINTLEVEL > 1 if( w->stgs->verbose ) deleteLastProgressLine( w->info ); if( w->stgs->verbose ) PRINTTEXT("Unreliable search direction detected, recovering best iterate (%d) and stopping.\n", (int)w->best_info->iter); #endif restoreBestIterate( w ); /* Determine whether we have reached at least reduced accuracy */ exitcode = checkExitConditions( w, ECOS_INACC_OFFSET ); /* if not, exit anyways */ if( exitcode == ECOS_NOT_CONVERGED_YET ){ exitcode = ECOS_NUMERICS; #if PRINTLEVEL > 0 if( w->stgs->verbose ) PRINTTEXT("\nNUMERICAL PROBLEMS (reached feastol=%3.1e, reltol=%3.1e, abstol=%3.1e).", MAX(w->info->dres, w->info->pres), w->info->relgap, w->info->gap); #endif break; } else { break; } } pres_prev = w->info->pres; /* Check termination criteria to full precision and exit if necessary */ exitcode = checkExitConditions( w, 0 ); interrupted = check_ctrlc(); if( exitcode == ECOS_NOT_CONVERGED_YET ){ /* * Full precision has not been reached yet. Check for two more cases of exit: * (i) min step size, in which case we assume we won't make progress any more, and * (ii) maximum number of iterations reached * If these two are not fulfilled, another iteration will be made. */ /* Did the line search c**k up? (zero step length) */ if( w->info->iter > 0 && w->info->step == STEPMIN*GAMMA ){ #if PRINTLEVEL > 0 if( w->stgs->verbose ) deleteLastProgressLine( w->info ); if( w->stgs->verbose ) PRINTTEXT("No further progress possible, recovering best iterate (%d) and stopping.", (int)w->best_info->iter ); #endif restoreBestIterate( w ); /* Determine whether we have reached reduced precision */ exitcode = checkExitConditions( w, ECOS_INACC_OFFSET ); if( exitcode == ECOS_NOT_CONVERGED_YET ){ exitcode = ECOS_NUMERICS; #if PRINTLEVEL > 0 if( w->stgs->verbose ) PRINTTEXT("\nNUMERICAL PROBLEMS (reached feastol=%3.1e, reltol=%3.1e, abstol=%3.1e).", MAX(w->info->dres, w->info->pres), w->info->relgap, w->info->gap); #endif } break; } /* MAXIT reached? */ else if( interrupted || w->info->iter == w->stgs->maxit ){ #if PRINTLEVEL > 0 const char *what = interrupted ? "SIGINT intercepted" : "Maximum number of iterations reached"; #endif /* Determine whether current iterate is better than what we had so far */ if( compareStatistics( w->info, w->best_info) ){ #if PRINTLEVEL > 0 if( w->stgs->verbose ) PRINTTEXT("%s, stopping.\n",what); #endif } else { #if PRINTLEVEL > 0 if( w->stgs->verbose ) PRINTTEXT("%s, recovering best iterate (%d) and stopping.\n", what, (int)w->best_info->iter); #endif restoreBestIterate( w ); } /* Determine whether we have reached reduced precision */ exitcode = checkExitConditions( w, ECOS_INACC_OFFSET ); if( exitcode == ECOS_NOT_CONVERGED_YET ){ exitcode = interrupted ? ECOS_SIGINT : ECOS_MAXIT; #if PRINTLEVEL > 0 if( w->stgs->verbose ) { const char* what = interrupted ? "INTERRUPTED" : "RAN OUT OF ITERATIONS"; PRINTTEXT("\n%s (reached feastol=%3.1e, reltol=%3.1e, abstol=%3.1e).", what, MAX(w->info->dres, w->info->pres), w->info->relgap, w->info->gap); } #endif } break; } } else { /* Full precision has been reached, stop solver */ break; } /* SAFEGUARD: * Check whether current iterate is worth keeping as the best solution so far, * before doing another iteration */ if (w->info->iter == 0) { /* we're at the first iterate, so there's nothing to compare yet */ saveIterateAsBest( w ); } else if( compareStatistics( w->info, w->best_info) ){ /* PRINTTEXT("Better solution found, saving as best so far \n"); */ saveIterateAsBest( w ); } /* Compute scalings */ if( updateScalings(w->C, w->s, w->z, w->lambda) == OUTSIDE_CONE ){ /* SAFEGUARD: we have to recover here */ #if PRINTLEVEL > 0 if( w->stgs->verbose ) deleteLastProgressLine( w->info ); if( w->stgs->verbose ) PRINTTEXT("Slacks/multipliers leaving the cone, recovering best iterate (%d) and stopping.\n", (int)w->best_info->iter); #endif restoreBestIterate( w ); /* Determine whether we have reached at least reduced accuracy */ exitcode = checkExitConditions( w, ECOS_INACC_OFFSET ); if( exitcode == ECOS_NOT_CONVERGED_YET ){ #if PRINTLEVEL > 0 if( w->stgs->verbose ) PRINTTEXT("\nNUMERICAL PROBLEMS (reached feastol=%3.1e, reltol=%3.1e, abstol=%3.1e).", MAX(w->info->dres, w->info->pres), w->info->relgap, w->info->gap); #endif return ECOS_OUTCONE; } else { break; } } /* Update KKT matrix with scalings */ kkt_update(w->KKT->PKPt, w->KKT->PK, w->C); #if DEBUG > 0 /* DEBUG: Store matrix to be factored */ sprintf(fn, "PKPt_updated_%02i.txt", (int)w->info->iter); dumpSparseMatrix(w->KKT->PKPt, fn); #endif /* factor KKT matrix */ #if PROFILING > 1 tic(&tfactor); KKT_FACTOR_RETURN_CODE = kkt_factor(w->KKT, w->stgs->eps, w->stgs->delta, &w->info->tfactor_t1, &w->info->tfactor_t2); w->info->tfactor += toc(&tfactor); #else KKT_FACTOR_RETURN_CODE = kkt_factor(w->KKT, w->stgs->eps, w->stgs->delta); #endif #if DEBUG > 0 /* DEBUG: store factor */ sprintf(fn, "PKPt_factor_%02i.txt", (int)w->info->iter); dumpSparseMatrix(w->KKT->L, fn); #endif /* Solve for RHS1, which is used later also in combined direction */ #if PROFILING > 1 tic(&tkktsolve); #endif w->info->nitref1 = kkt_solve(w->KKT, w->A, w->G, w->KKT->RHS1, w->KKT->dx1, w->KKT->dy1, w->KKT->dz1, w->n, w->p, w->m, w->C, 0, w->stgs->nitref); #if PROFILING > 1 w->info->tkktsolve += toc(&tkktsolve); #endif #if DEBUG > 0 && PRINTLEVEL > 2 /* Print result of linear system solve */ printDenseMatrix(w->KKT->dx1, 1, 5, "dx1(1:5)"); printDenseMatrix(w->KKT->dy1, 1, 5, "dy1(1:5)"); printDenseMatrix(w->KKT->dz1, 1, 5, "dz1(1:5)"); #endif /* AFFINE SEARCH DIRECTION (predictor, need dsaff and dzaff only) */ RHS_affine(w); #if PROFILING > 1 tic(&tkktsolve); #endif w->info->nitref2 = kkt_solve(w->KKT, w->A, w->G, w->KKT->RHS2, w->KKT->dx2, w->KKT->dy2, w->KKT->dz2, w->n, w->p, w->m, w->C, 0, w->stgs->nitref); #if PROFILING > 1 w->info->tkktsolve += toc(&tkktsolve); #endif /* dtau_denom = kap/tau - (c'*x1 + by1 + h'*z1); */ dtau_denom = w->kap/w->tau - eddot(w->n, w->c, w->KKT->dx1) - eddot(w->p, w->b, w->KKT->dy1) - eddot(w->m, w->h, w->KKT->dz1); /* dtauaff = (dt + c'*x2 + by2 + h'*z2) / dtau_denom; */ dtauaff = (w->rt - w->kap + eddot(w->n, w->c, w->KKT->dx2) + eddot(w->p, w->b, w->KKT->dy2) + eddot(w->m, w->h, w->KKT->dz2)) / dtau_denom; /* dzaff = dz2 + dtau_aff*dz1 */ for( i=0; i<w->m; i++ ){ w->W_times_dzaff[i] = w->KKT->dz2[i] + dtauaff*w->KKT->dz1[i]; } scale(w->W_times_dzaff, w->C, w->W_times_dzaff); /* W\dsaff = -W*dzaff -lambda; */ for( i=0; i<w->m; i++ ){ w->dsaff_by_W[i] = -w->W_times_dzaff[i] - w->lambda[i]; } /* dkapaff = -(bkap + kap*dtauaff)/tau; bkap = kap*tau*/ dkapaff = -w->kap - w->kap/w->tau*dtauaff; /* Line search on W\dsaff and W*dzaff */ w->info->step_aff = lineSearch(w->lambda, w->dsaff_by_W, w->W_times_dzaff, w->tau, dtauaff, w->kap, dkapaff, w->C, w->KKT); /* Centering parameter */ sigma = 1.0 - w->info->step_aff; sigma = sigma*sigma*sigma; if( sigma > SIGMAMAX ) sigma = SIGMAMAX; if( sigma < SIGMAMIN ) sigma = SIGMAMIN; w->info->sigma = sigma; /* COMBINED SEARCH DIRECTION */ RHS_combined(w); #if PROFILING > 1 tic(&tkktsolve); #endif w->info->nitref3 = kkt_solve(w->KKT, w->A, w->G, w->KKT->RHS2, w->KKT->dx2, w->KKT->dy2, w->KKT->dz2, w->n, w->p, w->m, w->C, 0, w->stgs->nitref); #if PROFILING > 1 w->info->tkktsolve += toc(&tkktsolve); #endif /* bkap = kap*tau + dkapaff*dtauaff - sigma*info.mu; */ bkap = w->kap*w->tau + dkapaff*dtauaff - sigma*w->info->mu; /* dtau = ((1-sigma)*rt - bkap/tau + c'*x2 + by2 + h'*z2) / dtau_denom; */ dtau = ((1-sigma)*w->rt - bkap/w->tau + eddot(w->n, w->c, w->KKT->dx2) + eddot(w->p, w->b, w->KKT->dy2) + eddot(w->m, w->h, w->KKT->dz2)) / dtau_denom; /* dx = x2 + dtau*x1; dy = y2 + dtau*y1; dz = z2 + dtau*z1; */ for( i=0; i < w->n; i++ ){ w->KKT->dx2[i] += dtau*w->KKT->dx1[i]; } for( i=0; i < w->p; i++ ){ w->KKT->dy2[i] += dtau*w->KKT->dy1[i]; } for( i=0; i < w->m; i++ ){ w->KKT->dz2[i] += dtau*w->KKT->dz1[i]; } /* ds_by_W = -(lambda \ bs + conelp_timesW(scaling,dz,dims)); */ /* note that ath this point w->dsaff_by_W holds already (lambda \ ds) */ scale(w->KKT->dz2, w->C, w->W_times_dzaff); for( i=0; i < w->m; i++ ){ w->dsaff_by_W[i] = -(w->dsaff_by_W[i] + w->W_times_dzaff[i]); } /* dkap = -(bkap + kap*dtau)/tau; */ dkap = -(bkap + w->kap*dtau)/w->tau; /* Line search on combined direction */ w->info->step = lineSearch(w->lambda, w->dsaff_by_W, w->W_times_dzaff, w->tau, dtau, w->kap, dkap, w->C, w->KKT) * w->stgs->gamma; /* ds = W*ds_by_W */ scale(w->dsaff_by_W, w->C, w->dsaff); /* Update variables */ for( i=0; i < w->n; i++ ){ w->x[i] += w->info->step * w->KKT->dx2[i]; } for( i=0; i < w->p; i++ ){ w->y[i] += w->info->step * w->KKT->dy2[i]; } for( i=0; i < w->m; i++ ){ w->z[i] += w->info->step * w->KKT->dz2[i]; } for( i=0; i < w->m; i++ ){ w->s[i] += w->info->step * w->dsaff[i]; } w->kap += w->info->step * dkap; w->tau += w->info->step * dtau; } /* scale variables back */ backscale(w); /* stop timer */ #if PROFILING > 0 w->info->tsolve = toc(&tsolve); #endif #if PRINTLEVEL > 0 #if PROFILING > 0 if( w->stgs->verbose ) PRINTTEXT("\nRuntime: %f seconds.", w->info->tsetup + w->info->tsolve); #endif if( w->stgs->verbose ) PRINTTEXT("\n\n"); #endif remove_ctrlc(); return exitcode; }
/* * Main solver routine. */ idxint ECOS_solve(pwork* w) { idxint i, initcode, KKT_FACTOR_RETURN_CODE; pfloat dtau_denom, dtauaff, dkapaff, sigma, dtau, dkap, bkap, pres_prev; idxint exitcode = ECOS_FATAL; #if PROFILING > 0 timer tsolve; #endif #if PROFILING > 1 timer tfactor, tkktsolve; #endif #if PROFILING > 0 /* start timer */ tic(&tsolve); #endif /* Initialize solver */ initcode = init(w); if( initcode == ECOS_FATAL ){ #if PRINTLEVEL > 0 if( w->stgs->verbose ) PRINTTEXT("\nFatal error during initialization, aborting."); #endif return ECOS_FATAL; } /* MAIN INTERIOR POINT LOOP ---------------------------------------------------------------------- */ for( w->info->iter = 0; w->info->iter <= w->stgs->maxit; w->info->iter++ ){ /* Compute residuals */ computeResiduals(w); /* Update statistics */ updateStatistics(w); #if PRINTLEVEL > 1 /* Print info */ if( w->stgs->verbose ) printProgress(w->info); #endif /* SAFEGUARD: Backtrack to old iterate if the update was bad such that the primal residual PRES has * increased by a factor of SAFEGUARD. * If the safeguard is activated, the solver quits with the flag ECOS_NUMERICS. */ if( w->info->iter > 0 && w->info->pres > SAFEGUARD*pres_prev ){ #if PRINTLEVEL > 1 if( w->stgs->verbose ) PRINTTEXT("\nNUMERICAL PROBLEMS, recovering iterate %d and stopping.\n", (int)w->info->iter-1); #endif /* Backtrack */ for( i=0; i < w->n; i++ ){ w->x[i] -= w->info->step * w->KKT->dx2[i]; } for( i=0; i < w->p; i++ ){ w->y[i] -= w->info->step * w->KKT->dy2[i]; } for( i=0; i < w->m; i++ ){ w->z[i] -= w->info->step * w->KKT->dz2[i]; } for( i=0; i < w->m; i++ ){ w->s[i] -= w->info->step * w->dsaff[i]; } w->kap -= w->info->step * dkap; w->tau -= w->info->step * dtau; exitcode = ECOS_NUMERICS; computeResiduals(w); updateStatistics(w); break; } pres_prev = w->info->pres; /* Check termination criteria and exit if necessary */ /* Optimal? */ if( ( ( -w->cx > 0 ) || ( -w->by - w->hz > 0) ) && w->info->pres < w->stgs->feastol && w->info->dres < w->stgs->feastol && ( w->info->gap < w->stgs->abstol || w->info->relgap < w->stgs->reltol ) ){ #if PRINTLEVEL > 0 if( w->stgs->verbose ) PRINTTEXT("\nOPTIMAL (within feastol=%3.1e, reltol=%3.1e, abstol=%3.1e).", w->stgs->feastol, w->stgs->reltol, w->stgs->abstol); #endif exitcode = ECOS_OPTIMAL; break; } /* Primal infeasible? */ else if( ((w->info->pinfres != NAN) && (w->info->pinfres < w->stgs->feastol)) || ((w->tau < w->stgs->feastol) && (w->kap < w->stgs->feastol && w->info->pinfres < w->stgs->feastol)) ){ #if PRINTLEVEL > 0 if( w->stgs->verbose ) PRINTTEXT("\nPRIMAL INFEASIBLE (within feastol=%3.1e, reltol=%3.1e, abstol=%3.1e).", w->stgs->feastol, w->stgs->reltol, w->stgs->abstol); #endif w->info->pinf = 1; w->info->dinf = 0; exitcode = ECOS_PINF; break; } /* Dual infeasible? */ else if( (w->info->dinfres != NAN) && (w->info->dinfres < w->stgs->feastol) ){ #if PRINTLEVEL > 0 if( w->stgs->verbose ) PRINTTEXT("\nUNBOUNDED (within feastol=%3.1e, reltol=%3.1e, abstol=%3.1e).", w->stgs->feastol, w->stgs->reltol, w->stgs->abstol); #endif w->info->pinf = 0; w->info->dinf = 1; exitcode = ECOS_DINF; break; } /* Did the line search c**k up? (zero step length) */ else if( w->info->iter > 0 && w->info->step == STEPMIN*GAMMA ){ #if PRINTLEVEL > 0 if( w->stgs->verbose ) PRINTTEXT("\nNo further progress possible (- numerics?), exiting."); #endif exitcode = ECOS_NUMERICS; break; } /* MAXIT reached? */ else if( w->info->iter == w->stgs->maxit ){ #if PRINTLEVEL > 0 if( w->stgs->verbose ) PRINTTEXT("\nMaximum number of iterations reached, exiting."); #endif exitcode = ECOS_MAXIT; break; } /* Compute scalings */ if( updateScalings(w->C, w->s, w->z, w->lambda) == OUTSIDE_CONE ){ #if PRINTLEVEL > 0 if( w->stgs->verbose ) PRINTTEXT("\nSlacks or multipliers leaving the positive orthant (- numerics ?), exiting.\n"); #endif return ECOS_OUTCONE; } /* Update KKT matrix with scalings */ kkt_update(w->KKT->PKPt, w->KKT->PK, w->C); #if DEBUG > 0 dumpSparseMatrix(w->KKT->PKPt,"PKPt_updated.txt"); #endif /* factor KKT matrix */ #if PROFILING > 1 tic(&tfactor); KKT_FACTOR_RETURN_CODE = kkt_factor(w->KKT, w->stgs->eps, w->stgs->delta, &w->info->tfactor_t1, &w->info->tfactor_t2); w->info->tfactor += toc(&tfactor); #else KKT_FACTOR_RETURN_CODE = kkt_factor(w->KKT, w->stgs->eps, w->stgs->delta); #endif /* Solve for RHS1, which is used later also in combined direction */ #if PROFILING > 1 tic(&tkktsolve); #endif w->info->nitref1 = kkt_solve(w->KKT, w->A, w->G, w->KKT->RHS1, w->KKT->dx1, w->KKT->dy1, w->KKT->dz1, w->n, w->p, w->m, w->C, 0, w->stgs->nitref); #if PROFILING > 1 w->info->tkktsolve += toc(&tkktsolve); #endif /* AFFINE SEARCH DIRECTION (predictor, need dsaff and dzaff only) */ RHS_affine(w); #if PROFILING > 1 tic(&tkktsolve); #endif w->info->nitref2 = kkt_solve(w->KKT, w->A, w->G, w->KKT->RHS2, w->KKT->dx2, w->KKT->dy2, w->KKT->dz2, w->n, w->p, w->m, w->C, 0, w->stgs->nitref); #if PROFILING > 1 w->info->tkktsolve += toc(&tkktsolve); #endif /* dtau_denom = kap/tau - (c'*x1 + by1 + h'*z1); */ dtau_denom = w->kap/w->tau - ddot(w->n, w->c, w->KKT->dx1) - ddot(w->p, w->b, w->KKT->dy1) - ddot(w->m, w->h, w->KKT->dz1); /* dtauaff = (dt + c'*x2 + by2 + h'*z2) / dtau_denom; */ dtauaff = (w->rt - w->kap + ddot(w->n, w->c, w->KKT->dx2) + ddot(w->p, w->b, w->KKT->dy2) + ddot(w->m, w->h, w->KKT->dz2)) / dtau_denom; /* dzaff = dz2 + dtau_aff*dz1 */ for( i=0; i<w->m; i++ ){ w->W_times_dzaff[i] = w->KKT->dz2[i] + dtauaff*w->KKT->dz1[i]; } scale(w->W_times_dzaff, w->C, w->W_times_dzaff); /* W\dsaff = -W*dzaff -lambda; */ for( i=0; i<w->m; i++ ){ w->dsaff_by_W[i] = -w->W_times_dzaff[i] - w->lambda[i]; } /* dkapaff = -(bkap + kap*dtauaff)/tau; bkap = kap*tau*/ dkapaff = -w->kap - w->kap/w->tau*dtauaff; /* Line search on W\dsaff and W*dzaff */ w->info->step_aff = lineSearch(w->lambda, w->dsaff_by_W, w->W_times_dzaff, w->tau, dtauaff, w->kap, dkapaff, w->C, w->KKT); /* Centering parameter */ sigma = 1.0 - w->info->step_aff; sigma = sigma*sigma*sigma; if( sigma > SIGMAMAX ) sigma = SIGMAMAX; if( sigma < SIGMAMIN ) sigma = SIGMAMIN; w->info->sigma = sigma; /* COMBINED SEARCH DIRECTION */ RHS_combined(w); #if PROFILING > 1 tic(&tkktsolve); #endif w->info->nitref3 = kkt_solve(w->KKT, w->A, w->G, w->KKT->RHS2, w->KKT->dx2, w->KKT->dy2, w->KKT->dz2, w->n, w->p, w->m, w->C, 0, w->stgs->nitref); #if PROFILING > 1 w->info->tkktsolve += toc(&tkktsolve); #endif /* bkap = kap*tau + dkapaff*dtauaff - sigma*info.mu; */ bkap = w->kap*w->tau + dkapaff*dtauaff - sigma*w->info->mu; /* dtau = ((1-sigma)*rt - bkap/tau + c'*x2 + by2 + h'*z2) / dtau_denom; */ dtau = ((1-sigma)*w->rt - bkap/w->tau + ddot(w->n, w->c, w->KKT->dx2) + ddot(w->p, w->b, w->KKT->dy2) + ddot(w->m, w->h, w->KKT->dz2)) / dtau_denom; /* dx = x2 + dtau*x1; dy = y2 + dtau*y1; dz = z2 + dtau*z1; */ for( i=0; i < w->n; i++ ){ w->KKT->dx2[i] += dtau*w->KKT->dx1[i]; } for( i=0; i < w->p; i++ ){ w->KKT->dy2[i] += dtau*w->KKT->dy1[i]; } for( i=0; i < w->m; i++ ){ w->KKT->dz2[i] += dtau*w->KKT->dz1[i]; } /* ds_by_W = -(lambda \ bs + conelp_timesW(scaling,dz,dims)); */ /* note that ath this point w->dsaff_by_W holds already (lambda \ ds) */ scale(w->KKT->dz2, w->C, w->W_times_dzaff); for( i=0; i < w->m; i++ ){ w->dsaff_by_W[i] = -(w->dsaff_by_W[i] + w->W_times_dzaff[i]); } /* dkap = -(bkap + kap*dtau)/tau; */ dkap = -(bkap + w->kap*dtau)/w->tau; /* Line search on combined direction */ w->info->step = lineSearch(w->lambda, w->dsaff_by_W, w->W_times_dzaff, w->tau, dtau, w->kap, dkap, w->C, w->KKT) * w->stgs->gamma; /* ds = W*ds_by_W */ scale(w->dsaff_by_W, w->C, w->dsaff); /* Update variables */ for( i=0; i < w->n; i++ ){ w->x[i] += w->info->step * w->KKT->dx2[i]; } for( i=0; i < w->p; i++ ){ w->y[i] += w->info->step * w->KKT->dy2[i]; } for( i=0; i < w->m; i++ ){ w->z[i] += w->info->step * w->KKT->dz2[i]; } for( i=0; i < w->m; i++ ){ w->s[i] += w->info->step * w->dsaff[i]; } w->kap += w->info->step * dkap; w->tau += w->info->step * dtau; } /* scale variables back */ backscale(w); /* stop timer */ #if PROFILING > 0 w->info->tsolve = toc(&tsolve); #endif #if PRINTLEVEL > 0 #if PROFILING > 0 if( w->stgs->verbose ) PRINTTEXT("\nRuntime: %f seconds.", w->info->tsetup + w->info->tsolve); #endif if( w->stgs->verbose ) PRINTTEXT("\n\n"); #endif return exitcode; }
/* * Initializes the solver. */ idxint init(pwork* w) { idxint i, j, k, l, KKT_FACTOR_RETURN_CODE; idxint* Pinv = w->KKT->Pinv; pfloat rx, ry, rz; #if PROFILING > 1 timer tfactor, tkktsolve; #endif /* set regularization parameter */ w->KKT->delta = w->stgs->delta; /* Initialize KKT matrix */ kkt_init(w->KKT->PKPt, w->KKT->PK, w->C); #if DEBUG > 0 dumpSparseMatrix(w->KKT->PKPt, "PKPt0.txt"); #endif /* initialize RHS1 */ k = 0; j = 0; for( i=0; i<w->n; i++ ){ w->KKT->RHS1[w->KKT->Pinv[k++]] = 0; } for( i=0; i<w->p; i++ ){ w->KKT->RHS1[w->KKT->Pinv[k++]] = w->b[i]; } for( i=0; i<w->C->lpc->p; i++ ){ w->KKT->RHS1[w->KKT->Pinv[k++]] = w->h[i]; j++; } for( l=0; l<w->C->nsoc; l++ ){ for( i=0; i < w->C->soc[l].p; i++ ){ w->KKT->RHS1[w->KKT->Pinv[k++]] = w->h[j++]; } #if CONEMODE == 0 w->KKT->RHS1[w->KKT->Pinv[k++]] = 0; w->KKT->RHS1[w->KKT->Pinv[k++]] = 0; #endif } #if PRINTLEVEL > 2 PRINTTEXT("Written %d entries of RHS1\n", (int)k); #endif /* initialize RHS2 */ for( i=0; i<w->n; i++ ){ w->KKT->RHS2[w->KKT->Pinv[i]] = -w->c[i]; } for( i=w->n; i<w->KKT->PKPt->n; i++ ){ w->KKT->RHS2[w->KKT->Pinv[i]] = 0; } /* get scalings of problem data */ rx = norm2(w->c, w->n); w->resx0 = MAX(1, rx); ry = norm2(w->b, w->p); w->resy0 = MAX(1, ry); rz = norm2(w->h, w->m); w->resz0 = MAX(1, rz); /* Factor KKT matrix - this is needed in all 3 linear system solves */ #if PROFILING > 1 tic(&tfactor); KKT_FACTOR_RETURN_CODE = kkt_factor(w->KKT, w->stgs->eps, w->stgs->delta, &w->info->tfactor_t1, &w->info->tfactor_t2); w->info->tfactor += toc(&tfactor); #else KKT_FACTOR_RETURN_CODE = kkt_factor(w->KKT, w->stgs->eps, w->stgs->delta); #endif /* check if factorization was successful, exit otherwise */ if( KKT_FACTOR_RETURN_CODE != KKT_OK ){ #if PRINTLEVEL > 0 if( w->stgs->verbose ) PRINTTEXT("\nProblem in factoring KKT system, aborting."); #endif return ECOS_FATAL; } /* * PRIMAL VARIABLES: * - solve xhat = arg min ||Gx-h||_2^2 such that Ax = b * - r = h - G*xhat * These two equations are solved by * * [ 0 A' G' ] [ xhat ] [ 0 ] * [ A 0 0 ] [ y ] = [ b ] * [ G 0 -I ] [ -r ] [ h ] * * and then take shat = r if alphap < 0, zbar + (1+alphap)*e otherwise * where alphap = inf{ alpha | sbar + alpha*e >= 0 } */ /* Solve for RHS [0; b; h] */ #if PROFILING > 1 tic(&tkktsolve); #endif w->info->nitref1 = kkt_solve(w->KKT, w->A, w->G, w->KKT->RHS1, w->KKT->dx1, w->KKT->dy1, w->KKT->dz1, w->n, w->p, w->m, w->C, 1, w->stgs->nitref); #if PROFILING > 1 w->info->tkktsolve += toc(&tkktsolve); #endif #if DEBUG > 0 #if PRINTLEVEL > 3 printDenseMatrix(w->KKT->dx1, w->n, 1, "dx1_init"); printDenseMatrix(w->KKT->dy1, w->p, 1, "dy1_init"); printDenseMatrix(w->KKT->dz1, w->m, 1, "dz1_init"); #endif #endif /* Copy out initial value of x */ for( i=0; i<w->n; i++ ){ w->x[i] = w->KKT->dx1[i]; } /* Copy out -r into temporary variable */ for( i=0; i<w->m; i++ ){ w->KKT->work1[i] = -w->KKT->dz1[i]; } /* Bring variable to cone */ bring2cone(w->C, w->KKT->work1, w->s ); /* * dual variables * solve (yhat,zbar) = arg min ||z||_2^2 such that G'*z + A'*y + c = 0 * * we can solve this by * * [ 0 A' G' ] [ x ] [ -c ] * [ A 0 0 ] [ yhat ] = [ 0 ] * [ G 0 -I ] [ zbar ] [ 0 ] * * and then take zhat = zbar if alphad < 0, zbar + (1+alphad)*e otherwise * where alphad = inf{ alpha | zbar + alpha*e >= 0 } */ /* Solve for RHS [-c; 0; 0] */ #if PROFILING > 1 tic(&tkktsolve); #endif w->info->nitref2 = kkt_solve(w->KKT, w->A, w->G, w->KKT->RHS2, w->KKT->dx2, w->KKT->dy2, w->KKT->dz2, w->n, w->p, w->m, w->C, 1, w->stgs->nitref); #if PROFILING > 1 w->info->tkktsolve += toc(&tkktsolve); #endif #if DEBUG > 0 #if PRINTLEVEL > 3 printDenseMatrix(w->KKT->dx2, w->n, 1, "dx2_init"); printDenseMatrix(w->KKT->dy2, w->p, 1, "dy2_init"); printDenseMatrix(w->KKT->dz2, w->m, 1, "dz2_init"); #endif #endif /* Copy out initial value of y */ for( i=0; i<w->p; i++ ){ w->y[i] = w->KKT->dy2[i]; } /* Bring variable to cone */ bring2cone(w->C, w->KKT->dz2, w->z ); /* Prepare RHS1 - before this line RHS1 = [0; b; h], after it holds [-c; b; h] */ for( i=0; i<w->n; i++){ w->KKT->RHS1[Pinv[i]] = -w->c[i]; } /* * other variables */ w->kap = 1.0; w->tau = 1.0; w->info->step = 0; w->info->step_aff = 0; w->info->dinf = 0; w->info->pinf = 0; return 0; }