typename DownhillSimplexMethod< DIM >::Converged DownhillSimplexMethod< DIM >::optimize( const ParamsT& initial ) { assert( m_refl > 0.0 ); assert( m_exp > 1.0 ); assert( m_exp > m_refl ); assert( 0 < m_contr && m_contr < 1 ); assert( 0 < m_shri && m_shri < 1 ); assert( m_initFactor > 0.0 ); // Prepare optimization m_iterations = 0; createInitials( initial ); Converged conv = CONVERGED_NO; Step next = STEP_START; while( next != STEP_EXIT ) { switch( next ) { case STEP_START: order(); conv = converged(); if( conv != CONVERGED_NO ) { next = STEP_EXIT; break; } ++m_iterations; centroid(); next = STEP_REFLECTION; break; case STEP_REFLECTION: next = reflection(); break; case STEP_EXPANSION: next = expansion(); break; case STEP_CONTRACTION: next = contraction(); break; case STEP_SHRINKAGE: next = shrinkage(); break; default: std::cerr << "Undefined control flow!"; next = STEP_EXIT; break; } } return conv; }
void divide(int now, int n, int l, int r, int connect) { for(int i = 0; i != n; ++i) { d[i] = edge[now][i]; map[d[i].id] = i; } for(int i = l; i <= r; ++i) { for(int j = 0; j != ques[i].num; ++j) d[map[ques[i].d[j]]].mark = 1; } if(l == r) { for(int i = 0; i != n; ++i) { int u = ms.find(d[i].u), v = ms.find(d[i].v); if(u != v && !d[i].mark) { ms.fa[u] = ms.fa[v]; --connect; } } ms.reset(n, d); ques[l].ans = connect; return; } connect -= contraction(n); reduction(n, l, r); for(int i = 0; i != n; ++i) edge[now + 1][i] = d[i]; int m = (l + r) >> 1; divide(now + 1, n, l, m, connect); divide(now + 1, n, m + 1, r, connect); }
// simplex routine // f is n dimensional function to be minimised, lower and upper are bounds of coordinates for initial vertices // simplex_goal_size is tolerance for convergene and W is workspace for simplex routine of dimension n // out termination the vector W->ce will contain coordinates for lowest vertex int simplex(double f(gsl_vector* x),double lower, double upper, double simplex_goal_size, simplex_workspace* W) { int steps = 0; double fp1, fp2, flo, fhi; // initialize system by generating vertices and // finding their function values simplex_generate(lower,upper,W); simplex_initialize(f,W); do { // make an update for higher, lower and centroid simplex_update(W); fhi = gsl_vector_get(W->fp,W->hi); flo = gsl_vector_get(W->fp,W->lo); // make reflection reflection(W); fp1 = f(W->p1); if (fp1 < flo) { // if f(reflected) < f(lower) attempt expansion expansion(W); fp2 = f(W->p2); if (fp2 < fp1) { // if f(expanded) < f(reflecred) accept expansion gsl_matrix_set_row(W->simplex,W->hi,W->p2); gsl_vector_set(W->fp,W->hi,fp2); } else { // if not, accept reflection gsl_matrix_set_row(W->simplex,W->hi,W->p1); gsl_vector_set(W->fp,W->hi,fp1); } } else { if (fp1 < fhi) { // if f(reflected) < f(higher) accept reflection gsl_matrix_set_row(W->simplex,W->hi,W->p1); gsl_vector_set(W->fp,W->hi,fp1); } else { // if not, attempt contraction contraction(W); fp2 = f(W->p2); if (fp2 < fhi) { // if f(contracted) < f(higher), accept contraction gsl_matrix_set_row(W->simplex,W->hi,W->p2); gsl_vector_set(W->fp,W->hi,fp2); } else { // if not, we must be in a valley, perform reduction reduction(f,W); } } } steps++; // if simplex has reduced sufficiently, that is size(simplex) < simplex_goal_size // convergence is achieved. Return number of steps before convergence. } while (simplex_size(W) > simplex_goal_size); // copy lowest vertex to centroid vector gsl_matrix_get_row(W->ce,W->simplex,W->lo); return steps; }