/* * Computes residuals. * * hrx = -A'*y - G'*z; rx = hrx - c.*tau; hresx = norm(rx,2); * hry = A*x; ry = hry - b.*tau; hresy = norm(ry,2); * hrz = s + G*x; rz = hrz - h.*tau; hresz = norm(rz,2); * rt = kappa + c'*x + b'*y + h'*z; */ void computeResiduals(pwork *w) { /* rx = -A'*y - G'*z - c.*tau */ if( w->p > 0 ) { sparseMtVm(w->A, w->y, w->rx, 1, 0); sparseMtVm(w->G, w->z, w->rx, 0, 0); } else { sparseMtVm(w->G, w->z, w->rx, 1, 0); } w->hresx = norm2(w->rx, w->n); vsubscale(w->n, w->tau, w->c, w->rx); /* ry = A*x - b.*tau */ if( w->p > 0 ){ sparseMV(w->A, w->x, w->ry, 1, 1); w->hresy = norm2(w->ry, w->p); vsubscale(w->p, w->tau, w->b, w->ry); } else { w->hresy = 0; w->ry = NULL; } /* rz = s + G*x - h.*tau */ sparseMV(w->G, w->x, w->rz, 1, 1); vadd(w->m, w->s, w->rz); w->hresz = norm2(w->rz, w->m); vsubscale(w->m, w->tau, w->h, w->rz); /* rt = kappa + c'*x + b'*y + h'*z; */ w->cx = eddot(w->n, w->c, w->x); w->by = w->p > 0 ? eddot(w->p, w->b, w->y) : 0.0; w->hz = eddot(w->m, w->h, w->z); w->rt = w->kap + w->cx + w->by + w->hz; }
/* * Updates statistics. */ void updateStatistics(pwork* w) { pfloat nry, nrz; stats* info = w->info; /* mu = (s'*z + kap*tau) / (D+1) where s'*z is the duality gap */ info->gap = eddot(w->m, w->s, w->z); info->mu = (info->gap + w->kap*w->tau) / (w->D + 1); info->kapovert = w->kap / w->tau; info->pcost = w->cx / w->tau; info->dcost = -(w->hz + w->by) / w->tau; /* relative duality gap */ if( info->pcost < 0 ){ info->relgap = info->gap / (-info->pcost); } else if( info->dcost > 0 ){ info->relgap = info->gap / info->dcost; } else info->relgap = NAN; /* residuals */ nry = w->p > 0 ? norm2(w->ry, w->p)/w->resy0 : 0.0; nrz = norm2(w->rz, w->m)/w->resz0; info->pres = MAX(nry, nrz) / w->tau; info->dres = norm2(w->rx, w->n)/w->resx0 / w->tau; /* infeasibility measures * * CVXOPT uses the following: * info->pinfres = w->hz + w->by < 0 ? w->hresx / w->resx0 / (-w->hz - w->by) : NAN; * info->dinfres = w->cx < 0 ? MAX(w->hresy/w->resy0, w->hresz/w->resz0) / (-w->cx) : NAN; */ info->pinfres = w->hz + w->by < 0 ? w->hresx/w->resx0 : NAN; info->dinfres = w->cx < 0 ? MAX(w->hresy/w->resy0, w->hresz/w->resz0) : NAN; #if PRINTLEVEL > 2 PRINTTEXT("TAU=%6.4e KAP=%6.4e PINFRES=%6.4e DINFRES=%6.4e\n",w->tau,w->kap,info->pinfres, info->dinfres ); #endif }
void get_bounds(idxint node_idx, ecos_bb_pwork* prob){ idxint i, ret_code, branchable, viable_rounded_sol; viable_rounded_sol = 0; set_prob( prob, get_bool_node_id(node_idx,prob), get_int_node_id(node_idx, prob) ); ret_code = ECOS_solve(prob->ecos_prob); #if MI_PRINTLEVEL > 1 if (prob->stgs->verbose){ print_ecos_solution(prob); } if (ret_code != ECOS_OPTIMAL && ret_code != ECOS_PINF && ret_code != ECOS_DINF){ PRINTTEXT("1Exit code: %u\n", ret_code); } #endif if (ret_code >= 0 || ret_code == ECOS_MAXIT || ret_code == ECOS_NUMERICS ) { prob->nodes[node_idx].L = eddot(prob->ecos_prob->n, prob->ecos_prob->x, prob->ecos_prob->c); /* Figure out if x is already an integer solution if the solution had no numerical errors*/ branchable = 1; for (i=0; i<prob->num_bool_vars; ++i){ prob->tmp_bool_node_id[i] = (char) pfloat_round( prob->ecos_prob->x[prob->bool_vars_idx[i]] ); branchable &= float_eqls( prob->ecos_prob->x[i] , (pfloat) prob->tmp_bool_node_id[i], prob->stgs->integer_tol ); } for (i=0; i<prob->num_int_vars; ++i){ prob->tmp_int_node_id[2 * i + 1] = pfloat_round(prob->ecos_prob->x[prob->int_vars_idx[i]] ); prob->tmp_int_node_id[2*i] = -(prob->tmp_int_node_id[2*i + 1]); branchable &= float_eqls( prob->ecos_prob->x[i] , prob->tmp_int_node_id[2*i + 1], prob->stgs->integer_tol ); } branchable = !branchable; #if MI_PRINTLEVEL > 1 if (prob->stgs->verbose){ PRINTTEXT("Is branchable: %u\n",branchable); } #endif if (branchable){ /* pfloat_round and check feasibility*/ get_branch_var(prob, &(prob->nodes[node_idx].split_idx), &(prob->nodes[node_idx].split_val) ); prob->nodes[node_idx].status = MI_SOLVED_BRANCHABLE; #if MI_PRINTLEVEL > 1 if (prob->stgs->verbose){ print_node(prob,-1); PRINTTEXT("Rounded Solution:\n"); } #endif set_prob(prob, prob->tmp_bool_node_id, prob->tmp_int_node_id); ret_code = ECOS_solve(prob->ecos_prob); #if MI_PRINTLEVEL > 1 if (prob->stgs->verbose){ print_ecos_solution(prob); } if (ret_code != ECOS_OPTIMAL && ret_code != ECOS_PINF && ret_code != ECOS_DINF){ PRINTTEXT("2Exit code: %u\n", ret_code); } #endif if (ret_code == ECOS_OPTIMAL){ /* Use the node's U as tmp storage */ prob->nodes[node_idx].U = eddot(prob->ecos_prob->n, prob->ecos_prob->x, prob->ecos_prob->c); viable_rounded_sol = 1; } }else{ /* This is already an integer solution*/ prob->nodes[node_idx].status = MI_SOLVED_NON_BRANCHABLE; prob->nodes[node_idx].U = eddot(prob->ecos_prob->n, prob->ecos_prob->x, prob->ecos_prob->c); } if (prob->nodes[node_idx].U < prob->global_U){ #if MI_PRINTLEVEL > 1 if (prob->stgs->verbose){ PRINTTEXT("New optimal solution, U: %.2f\n", prob->nodes[node_idx].U); print_ecos_xequil(prob); print_ecos_c(prob); print_ecos_solution(prob); } #endif store_solution(prob); prob->global_U = prob->nodes[node_idx].U; } if (viable_rounded_sol){ /* Reset the node's U back to INF because it was not originally feasible */ prob->nodes[node_idx].U = INFINITY; } }else { /*Assume node infeasible*/ prob->nodes[node_idx].L = INFINITY; prob->nodes[node_idx].U = INFINITY; prob->nodes[node_idx].status = MI_SOLVED_NON_BRANCHABLE; } }
/* * 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; }
/* * Line search according to Vandenberghe (cf. �8 in his manual). */ pfloat lineSearch(pfloat* lambda, pfloat* ds, pfloat* dz, pfloat tau, pfloat dtau, pfloat kap, pfloat dkap, cone* C, kkt* KKT) { idxint i, j, cone_start, conesize; pfloat rhomin, sigmamin, alpha, lknorm, lknorminv, rhonorm, sigmanorm, conic_step, temp; pfloat lkbar_times_dsk, lkbar_times_dzk, factor; pfloat* lk; pfloat* dsk; pfloat* dzk; pfloat* lkbar = KKT->work1; pfloat* rho = KKT->work2; pfloat* sigma = KKT->work2; pfloat minus_tau_by_dtau = -tau/dtau; pfloat minus_kap_by_dkap = -kap/dkap; /* LP cone */ if( C->lpc->p > 0 ){ rhomin = ds[0] / lambda[0]; sigmamin = dz[0] / lambda[0]; for( i=1; i < C->lpc->p; i++ ){ rho[0] = ds[i] / lambda[i]; if( rho[0] < rhomin ){ rhomin = rho[0]; } sigma[0] = dz[i] / lambda[i]; if( sigma[0] < sigmamin ){ sigmamin = sigma[0]; } } if( -sigmamin > -rhomin ){ alpha = sigmamin < 0 ? 1.0 / (-sigmamin) : 1.0 / EPS; } else { alpha = rhomin < 0 ? 1.0 / (-rhomin) : 1.0 / EPS; } } else { alpha = 10; } /* tau and kappa */ if( minus_tau_by_dtau > 0 && minus_tau_by_dtau < alpha ) { alpha = minus_tau_by_dtau; } if( minus_kap_by_dkap > 0 && minus_kap_by_dkap < alpha ) { alpha = minus_kap_by_dkap; } /* Second-order cone */ cone_start = C->lpc->p; for( i=0; i < C->nsoc; i++ ){ /* indices */ conesize = C->soc[i].p; lk = lambda + cone_start; dsk = ds + cone_start; dzk = dz + cone_start; /* normalize */ lknorm = sqrt( lk[0]*lk[0] - eddot(conesize-1, lk+1, lk+1) ); for( j=0; j < conesize; j++ ){ lkbar[j] = lk[j] / lknorm; } lknorminv = 1.0 / lknorm; /* calculate products */ lkbar_times_dsk = lkbar[0]*dsk[0]; for( j=1; j < conesize; j++ ){ lkbar_times_dsk -= lkbar[j]*dsk[j]; } lkbar_times_dzk = lkbar[0]*dzk[0]; for( j=1; j < conesize; j++ ){ lkbar_times_dzk -= lkbar[j]*dzk[j]; } /* now construct rhok and sigmak, the first element is different */ rho[0] = lknorminv * lkbar_times_dsk; factor = (lkbar_times_dsk+dsk[0])/(lkbar[0]+1); for( j=1; j < conesize; j++ ){ rho[j] = lknorminv*(dsk[j] - factor*lkbar[j]); } rhonorm = norm2(rho+1, conesize-1) - rho[0]; sigma[0] = lknorminv * lkbar_times_dzk; factor = (lkbar_times_dzk+dzk[0])/(lkbar[0]+1); for( j=1; j < conesize; j++ ){ sigma[j] = lknorminv*(dzk[j] - factor*lkbar[j]); } sigmanorm = norm2(sigma+1, conesize-1) - sigma[0]; /* update alpha */ conic_step = 0; if( rhonorm > conic_step ){ conic_step = rhonorm; } if( sigmanorm > conic_step ){ conic_step = sigmanorm; } if( conic_step != 0 ){ temp = 1.0 / conic_step; if( temp < alpha ){ alpha = temp; } } cone_start += C->soc[i].p; } /* saturate between STEPMIN and STEPMAX */ if( alpha > STEPMAX ) alpha = STEPMAX; if( alpha < STEPMIN ) alpha = STEPMIN; /* return alpha */ return alpha; }