void CompositeOFTest::test_composite_clone( ObjectiveFunction& OF ) { // save current count of instances of underlying OFs for later const int init_count = FauxObjectiveFunction::get_instance_count(); // clone the objective function ObjectiveFunction* clone = OF.clone(); // check that the underlying OFs were also cloned CPPUNIT_ASSERT( init_count < FauxObjectiveFunction::get_instance_count() ); // check that the value is the same MsqPrintError err(cout); double orig_val, clone_val; bool rval; rval = OF.evaluate( ObjectiveFunction::CALCULATE, patch(), orig_val, false, err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT(rval); rval = clone->evaluate( ObjectiveFunction::CALCULATE, patch(), clone_val, false, err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT(rval); CPPUNIT_ASSERT_DOUBLES_EQUAL( orig_val, clone_val, 1e-6 ); // check that cloned instances of underlying OFs are deleted delete clone; CPPUNIT_ASSERT_EQUAL( init_count, FauxObjectiveFunction::get_instance_count() ); }
void generateSimplexTab(const std::vector<Constraint<ArgType>>& constraints, const ObjectiveFunction<ArgType, RetType, CoeffType>& function, Matrix<CoeffType>& simplexTab) { unsigned long cols = simplexTab.getColumnsNumber(), rows = simplexTab.getRowsNumber(), constrNum = constraints.size(), argsNum = function.size(); if(constrNum + 1 != rows || argsNum + constrNum + 2 != cols) throw "simplexTab has not proper size"; for (unsigned long i = 0; i < constrNum; i++) //generuje część odpowiedzialna za ograniczenia pod argumentami for (unsigned long j = 0; j < argsNum; j++) simplexTab(i, j) = constraints[i].getCoeff(j); for (unsigned long j = 0; j < argsNum; j++) // generuje dolną część tablicy pod argumentami simplexTab(rows - 1, j) = -function.getCoeff(j); for (unsigned long j = 0; j < constrNum; j++) // generuje część związaną ze zmiennymi dodatkowymi simplexTab(j, j + argsNum) = 1; for (unsigned long j = 0; j < constrNum; j++) // część pod p - same zera simplexTab(j, argsNum + constrNum) = 0; for (unsigned long j = 0; j < constrNum; j++) // ostatnia kolumna, kolumna B simplexTab(j, argsNum + constrNum + 1) = constraints[j].getB(); for (unsigned long j = argsNum; j < argsNum + constrNum - 1; j++) //ostatni wiersz pod zmienn. dodatk. - same zera simplexTab(rows - 1, j) = 0; simplexTab(rows - 1, cols - 2) = 1; simplexTab(rows - 1, cols - 1) = 0; }
void UnOptimizer::optimize_vertex_positions( PatchData &pd, MsqError &err) { assert( pd.num_free_vertices() == 1 && pd.vertex_by_index(0).is_free_vertex() ); std::vector<Vector3D> grad(1); double val, junk, coeff; bool state; state = objectiveFunction->evaluate_with_gradient( ObjectiveFunction::CALCULATE, pd, val, grad, err ); MSQ_ERRRTN(err); if (!state) { MSQ_SETERR(err)(MsqError::INVALID_MESH); return; } grad[0] /= grad[0].length(); PatchDataVerticesMemento* memento = pd.create_vertices_memento( err ); MSQ_ERRRTN(err); std::auto_ptr<PatchDataVerticesMemento> deleter( memento ); pd.get_minmax_edge_length( junk, coeff ); for (int i = 0; i < 100; ++i) { pd.set_free_vertices_constrained( memento, &grad[0], 1, coeff, err ); MSQ_ERRRTN(err); state = objectiveFunction->evaluate( ObjectiveFunction::CALCULATE, pd, val, true, err ); MSQ_ERRRTN(err); if (state) break; coeff *= 0.5; } if (!state) { pd.set_to_vertices_memento( memento, err ); } }
std::vector<double> OptimizerNaive::generateRandomPoint(const ObjectiveFunction & objective_function) const { static RandomNumberGenerator random_generator(0., 1.); std::vector<double> dmin = objective_function.getDomainMin(); std::vector<double> dmax = objective_function.getDomainMax(); int x_dim = objective_function.getDimension(); std::vector<double> x; for(int i=0 ; i<x_dim ; i++) { x.push_back(random_generator.generateNumber() * (dmax[i] - dmin[i]) + dmin[i]); // TODO denormalize in dmin dmax } return x; }
// Gradient computations double DenseCRF::gradient( int n_iterations, const ObjectiveFunction & objective, VectorXf * unary_grad, VectorXf * lbl_cmp_grad, VectorXf * kernel_grad) const { // Run inference std::vector< MatrixXf > Q(n_iterations+1); MatrixXf tmp1, unary( M_, N_ ), tmp2; unary.fill(0); if( unary_ ) unary = unary_->get(); expAndNormalize( Q[0], -unary ); for( int it=0; it<n_iterations; it++ ) { tmp1 = -unary; for( unsigned int k=0; k<pairwise_.size(); k++ ) { pairwise_[k]->apply( tmp2, Q[it] ); tmp1 -= tmp2; } expAndNormalize( Q[it+1], tmp1 ); } // Compute the objective value MatrixXf b( M_, N_ ); double r = objective.evaluate( b, Q[n_iterations] ); sumAndNormalize( b, b, Q[n_iterations] ); // Compute the gradient if(unary_grad && unary_) *unary_grad = unary_->gradient( b ); if( lbl_cmp_grad ) *lbl_cmp_grad = 0*labelCompatibilityParameters(); if( kernel_grad ) *kernel_grad = 0*kernelParameters(); for( int it=n_iterations-1; it>=0; it-- ) { // Do the inverse message passing tmp1.fill(0); int ip = 0, ik = 0; // Add up all pairwise potentials for( unsigned int k=0; k<pairwise_.size(); k++ ) { // Compute the pairwise gradient expression if( lbl_cmp_grad ) { VectorXf pg = pairwise_[k]->gradient( b, Q[it] ); lbl_cmp_grad->segment( ip, pg.rows() ) += pg; ip += pg.rows(); } // Compute the kernel gradient expression if( kernel_grad ) { VectorXf pg = pairwise_[k]->kernelGradient( b, Q[it] ); kernel_grad->segment( ik, pg.rows() ) += pg; ik += pg.rows(); } // Compute the new b pairwise_[k]->applyTranspose( tmp2, b ); tmp1 += tmp2; } sumAndNormalize( b, tmp1.array()*Q[it].array(), Q[it] ); // Add the gradient if(unary_grad && unary_) *unary_grad += unary_->gradient( b ); } return r; }
void CompositeOFTest::test_eval_fails( ObjectiveFunction& OF ) { MsqError err; double value; OF.evaluate( ObjectiveFunction::CALCULATE, patch(), value, false, err ); CPPUNIT_ASSERT_EQUAL(MsqError::INTERNAL_ERROR, err.error_code()); }
void CompositeOFTest::test_invalid_eval( ObjectiveFunction& OF ) { MsqPrintError err(cout); bool rval; double value; rval = OF.evaluate( ObjectiveFunction::CALCULATE, patch(), value, false, err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT(rval == false); }
void CompositeOFTest::test_evaluate( double expected, ObjectiveFunction& OF ) { MsqPrintError err(cout); double value; bool rval = OF.evaluate( ObjectiveFunction::CALCULATE, patch(), value, false, err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT(rval); CPPUNIT_ASSERT_DOUBLES_EQUAL( expected, value, 1e-6 ); }
/*! Numerically Calculates the gradient of the ObjectiveFunction for the free vertices in the patch. Returns 'false' if the patch is outside of a required feasible region, returns 'ture' otherwise. The behavior of the function depends on the value of the boolean useLocalGradient. If useLocalGradient is set to 'true', compute_numerical_gradient creates a sub-patch around a free vertex, and then perturbs that vertex in one of the coordinate directions. Only the ObjectiveFunction value on the local sub-patch is used in the computation of the gradient. Therefore, useLocalGradient should only be set to 'true' for ObjectiveFunctions which can use this method. Unless the concrete ObjectiveFunction sets useLocalGradient to 'true' in its constructor, the value will be 'false'. In this case, the objective function value for the entire patch is used in the calculation of the gradient. This is computationally expensive, but it is numerically correct for all (C_1) functions. \param pd PatchData on which the gradient is taken. \param grad Array of Vector3D of length the number of vertices used to store gradient. \param OF_val will be set to the objective function value. */ bool ObjectiveFunction::evaluate_with_gradient( EvalType eval_type, PatchData &pd, double& OF_val, std::vector<Vector3D>& grad, MsqError &err ) { bool b; grad.resize( pd.num_free_vertices() ); // Fast path for single-free-vertex patch if (pd.num_free_vertices() == 1) { const EvalType sub_type = (eval_type == CALCULATE) ? CALCULATE : TEMPORARY; b = compute_subpatch_numerical_gradient( eval_type, sub_type, pd, OF_val, grad[0], err ); return !MSQ_CHKERR(err) && b; } ObjectiveFunction* of = this; std::auto_ptr<ObjectiveFunction> deleter; if (eval_type == CALCULATE) { of->clear(); b = of->evaluate( ACCUMULATE, pd, OF_val, OF_FREE_EVALS_ONLY, err ); if (err) { // OF doesn't support BCD type evals, try slow method err.clear(); of->clear(); b = compute_patch_numerical_gradient( CALCULATE, CALCULATE, pd, OF_val, grad, err ); return !MSQ_CHKERR(err) && b; } else if (!b) return b; } else { b = this->evaluate( eval_type, pd, OF_val, OF_FREE_EVALS_ONLY, err ); if (MSQ_CHKERR(err) || !b) return false; of = this->clone(); deleter = std::auto_ptr<ObjectiveFunction>(of); } // Determine number of layers of adjacent elements based on metric type. unsigned layers = min_patch_layers(); // Create a subpatch for each free vertex and use it to evaluate the // gradient for that vertex. double flocal; PatchData subpatch; for (size_t i = 0; i < pd.num_free_vertices(); ++i) { pd.get_subpatch( i, layers, subpatch, err ); MSQ_ERRZERO(err); b = of->compute_subpatch_numerical_gradient( SAVE, TEMPORARY, subpatch, flocal, grad[i], err ); if (MSQ_CHKERR(err) || !b) { of->clear(); return false; } } of->clear(); return true; }
FunctionArguments<ArgType> simplex( const std::vector<Constraint<ArgType>>& constraints, const ObjectiveFunction<ArgType, RetType, CoeffType>& function) { if(constraints.size() == 0) throw "No constraints"; if(constraints[0].size() != function.size()) throw "Size of constraints not equal to function size"; Matrix<CoeffType> simplexTab(constraints.size() + 1, function.size() + constraints.size() + 2); unsigned long cols = simplexTab.getColumnsNumber(), rows = simplexTab.getRowsNumber(), constrNum = constraints.size(), argsNum = function.size(); generateSimplexTab(constraints, function, simplexTab); std::map<unsigned long,unsigned long> slackSwaped; while (simplexTab.countIfInRange(rows - 1, 0, rows - 1, cols - 1, [](const CoeffType& x) { return x<0;})) { unsigned long pivotColumn, row; simplexTab.findMinimumInRange(rows - 1, 0, rows - 1, cols - 3, row, pivotColumn); row = findMinInColumnBDiv(simplexTab, pivotColumn); slackSwaped[row]=pivotColumn; simplexTab.multiplyRow(1/simplexTab(row,pivotColumn),row); for(unsigned long j=0;j<rows;j++) if(j!=row) simplexTab.addRow(-simplexTab(j,pivotColumn),row,j); } std::cout<<simplexTab; FunctionArguments<ArgType> bestSolution; bestSolution.size(argsNum); for(unsigned long j=0;j<constrNum;j++) bestSolution.setArg(slackSwaped[j],simplexTab(j,cols-1)); return bestSolution; }
void ProgNmaAlignment::processImage(const FileName &fnImg, const FileName &fnImgOut, const MDRow &rowIn, MDRow &rowOut) { static size_t imageCounter = 0; ++imageCounter; double rhoStart=trustradius_scale*250.; double rhoEnd=trustradius_scale*50.; int niter=10000; ObjectiveFunction *of; int dim = numberOfModes; parameters.initZeros(dim + 5); currentImgName = fnImg; sprintf(nameTemplate, "_node%d_img%lu_XXXXXX", rangen, (long unsigned int)imageCounter); trial.initZeros(dim + 5); trial_best.initZeros(dim + 5); fitness_min.initZeros(1); fitness_min(0) = 1000000.0; currentStage = 1; #ifdef DEBUG std::cerr << std::endl << "DEBUG: ===== Node: " << rangen <<" processing image " << fnImg <<"(" << objId << ")" << " at stage: " << currentStage << std::endl; #endif of = new ObjFunc_nma_alignment(1, dim); of->xStart.setSize(dim); for (int i = 0; i < dim; i++) of->xStart[i] = 0.; #ifdef DEBUG strcpy(of->name,("OF1_"+integerToString(rangen)).c_str()); of->setSaveFile(); #endif CONDOR(rhoStart, rhoEnd, niter, of); #ifdef DEBUG of->printStats(); FILE *ff = fopen(("res1_"+integerToString(rangen)+".xmd").c_str(),"w"); fprintf(ff,"%s & %i & %i & (%i) & %e \\\\\n", of->name, of->dim(), of->getNFE(), of->getNFE2(), of->valueBest); fclose(ff); #endif bestStage1 = trial = parameters = trial_best; delete of; currentStage = 2; #ifdef DEBUG std::cerr << std::endl << "DEBUG: ===== Node: " << rangen <<" processing image " << fnImg <<"(" << objId << ")" << " at stage: " << currentStage << std::endl; #endif fitness_min(0) = 1000000.0; of = new ObjFunc_nma_alignment(1, dim); of->xStart.setSize(dim); for (int i = 0; i < dim; i++) of->xStart[i] = parameters(i); #ifdef DEBUG strcpy(of->name,("OF2_"+integerToString(rangen)).c_str()); of->setSaveFile(); #endif rhoStart=trustradius_scale*50.-1., rhoEnd=0.5; CONDOR(rhoStart, rhoEnd, niter, of); #ifdef DEBUG of->printStats(); ff=fopen(("res2_"+integerToString(rangen)+".xmd").c_str(),"w"); fprintf(ff,"%s & %i & %i & (%i) & %e \\\\\n", of->name, of->dim(), of->getNFE(), of->getNFE2(), of->valueBest); fclose(ff); #endif #ifdef DEBUG std::cout << "Best fitness = " << fitness << std::endl; for (int i=0; i<dim; i++) { std::cout << "Best deformations = " << dd[i] << std::endl; } #endif trial = trial_best; for (int i = dim; i < dim + 5; i++) { parameters(i - dim) = trial_best(i); } for (int i = 0; i < dim; i++) { parameters(5 + i) = trial_best(i); } parameters.resize(VEC_XSIZE(parameters) + 1); parameters(VEC_XSIZE(parameters) - 1) = fitness_min(0); writeImageParameters(fnImg); delete of; }