static gboolean threshold_exceeded (gfloat *pixel1, gfloat *pixel2, gfloat threshold) { gfloat derivative[4]; gint i; gfloat sum; get_derivative (pixel1, pixel2, derivative); sum = 0.0; for (i = 0; i < 4; i++) sum += derivative[i]; return ((sum / 4.0) > (threshold/100.0)); }
/** \param[in] model The model to score. \param[in] model_data The corresponding ModelData. \param[in] float_indices Indices of optimizable variables. \param[in] x Current value of optimizable variables. \param[out] dscore First derivatives for current state. \return The model score. */ ConjugateGradients::NT ConjugateGradients::get_score( Vector<FloatIndex> float_indices, Vector<NT> &x, Vector<NT> &dscore) { int i, opt_var_cnt = float_indices.size(); /* set model state */ for (i = 0; i < opt_var_cnt; i++) { IMP_CHECK_VALUE(x[i]); #ifdef IMP_CG_SCALE double v = get_scaled_value(float_indices[i]); // scaled #else double v = get_value(float_indices[i]); // scaled #endif if (std::abs(x[i] - v) > max_change_) { if (x[i] < v) { x[i] = v - max_change_; } else { x[i] = v + max_change_; } } #ifdef IMP_CG_SCALE set_scaled_value(float_indices[i], x[i]); #else set_value(float_indices[i], x[i]); #endif } NT score; /* get score */ try { score = get_scoring_function()->evaluate(true); } catch (ModelException) { // if we took a bad step, just return a bad score return std::numeric_limits<NT>::infinity(); } /* get derivatives */ for (i = 0; i < opt_var_cnt; i++) { #ifdef IMP_CG_SCALE dscore[i] = get_scaled_derivative(float_indices[i]); // scaled #else dscore[i] = get_derivative(float_indices[i]); // scaled #endif IMP_USAGE_CHECK(is_good_value(dscore[i]), "Bad input to CG"); } return score; }
double SteepestDescent::do_optimize(unsigned int max_steps) { IMP_OBJECT_LOG; Float last_score, new_score = 0.0; // set up the indexes FloatIndexes float_indexes = get_optimized_attributes(); Float current_step_size = step_size_; // ... and space for the old values algebra::VectorKD temp_derivs = algebra::get_zero_vector_kd(float_indexes.size()); algebra::VectorKD temp_values = algebra::get_zero_vector_kd(float_indexes.size()); for (unsigned int step = 0; step < max_steps; step++) { // model.show(std::cout); int cnt = 0; // evaluate the last model state last_score = get_scoring_function()->evaluate(true); IMP_LOG_TERSE("start score: " << last_score << std::endl); // store the old values for (unsigned int i = 0; i < temp_derivs.get_dimension(); i++) { temp_derivs[i] = get_derivative(float_indexes[i]); temp_values[i] = get_value(float_indexes[i]); } bool constant_score = false; while (true) { cnt++; // try new values based on moving down the gradient at the current // step size IMP_LOG_VERBOSE("step: " << temp_derivs * current_step_size << std::endl); for (unsigned int i = 0; i < float_indexes.size(); i++) { set_value(float_indexes[i], temp_values[i] - temp_derivs[i] * current_step_size); } // check the new model new_score = get_scoring_function()->evaluate(false); IMP_LOG_TERSE("last score: " << last_score << " new score: " << new_score << " step size: " << current_step_size << std::endl); // if the score got better, we'll take it if (new_score < last_score) { IMP_LOG_TERSE("Accepting step of size " << current_step_size); update_states(); if (new_score <= threshold_) { IMP_LOG_TERSE("Below threshold, returning." << std::endl); return new_score; } current_step_size = std::min(current_step_size * 1.4, max_step_size_); break; } // if the score is the same, keep going one more time if (std::abs(new_score - last_score) < .0000001) { if (constant_score) { break; } current_step_size *= 0.9; constant_score = true; } else { constant_score = false; current_step_size *= .7; } if (cnt > 200) { // stuck for (unsigned int i = 0; i < float_indexes.size(); i++) { set_value(float_indexes[i], temp_values[i]); } IMP_LOG_TERSE("Unable to find a good step. Returning" << std::endl); return last_score; } if (current_step_size < .00000001) { // here is as good as any place we found update_states(); IMP_LOG_TERSE("Unable to make progress, returning." << std::endl); return new_score; } } } return new_score; }