/** * The best member of the population will be used as starting point for the minimisation process. The algorithm will stop * if the size of the simplex falls below the tol parameter, if the maximum number of iterations max_iter is exceeded or if * the inner GSL routine call reports an error (which will be logged on std::cout). After the end of the minimisation process, * the minimised decision vector will replace the best individual in the population, after being modified to fall within * the problem bounds if necessary. * * @param[in,out] pop population to evolve. */ void gsl_derivative_free::evolve(population &pop) const { // Do nothing if the population is empty. if (!pop.size()) { return; } // Useful variables. const problem::base &problem = pop.problem(); if (problem.get_f_dimension() != 1) { pagmo_throw(value_error,"this algorithm does not support multi-objective optimisation"); } if (problem.get_c_dimension()) { pagmo_throw(value_error,"this algorithm does not support constrained optimisation"); } const problem::base::size_type cont_size = problem.get_dimension() - problem.get_i_dimension(); if (!cont_size) { pagmo_throw(value_error,"the problem has no continuous part"); } // Extract the best individual. const population::size_type best_ind_idx = pop.get_best_idx(); const population::individual_type &best_ind = pop.get_individual(best_ind_idx); // GSL wrapper parameters structure. objfun_wrapper_params params; params.p = &problem; // Integer part of the temporay decision vector must be filled with the integer part of the best individual, // which will not be optimised. params.x.resize(problem.get_dimension()); std::copy(best_ind.cur_x.begin() + cont_size, best_ind.cur_x.end(), params.x.begin() + cont_size); params.f.resize(1); // GSL function structure. gsl_multimin_function gsl_func; // Number of function components. gsl_func.n = boost::numeric_cast<std::size_t>(cont_size); gsl_func.f = &objfun_wrapper; gsl_func.params = (void *)¶ms; // Mimimizer. gsl_multimin_fminimizer *s = 0; // Starting point and step sizes. gsl_vector *x = 0, *ss = 0; // Here we start the allocations. // Recast as size_t here, in order to avoid potential overflows later. const std::size_t s_cont_size = boost::numeric_cast<std::size_t>(cont_size); // Allocate and check the allocation results. x = gsl_vector_alloc(s_cont_size); ss = gsl_vector_alloc(s_cont_size); const gsl_multimin_fminimizer_type *minimiser = get_gsl_minimiser_ptr(); pagmo_assert(minimiser); s = gsl_multimin_fminimizer_alloc(minimiser,s_cont_size); // Check the allocations. check_allocs(x,ss,s); // Starting point comes from the best individual. for (std::size_t i = 0; i < s_cont_size; ++i) { gsl_vector_set(x,i,best_ind.cur_x[i]); } // Set initial step sizes. gsl_vector_set_all(ss,m_step_size); // Init the solver. gsl_multimin_fminimizer_set(s,&gsl_func,x,ss); // Iterate. std::size_t iter = 0; int status; double size; try { do { status = gsl_multimin_fminimizer_iterate(s); ++iter; if (status) { break; } size = gsl_multimin_fminimizer_size(s); status = gsl_multimin_test_size(size, m_tol); if (m_screen_output) { if (!((iter-1)%20)) { std::cout << std::endl << std::left << std::setw(20) << "Iter." << std::setw(20) << "Best " << std::setw(20) << "Size "<< std::endl; } std::cout << std::left << std::setprecision(14) << std::setw(20) << iter << std::setw(20) << gsl_multimin_fminimizer_minimum(s) << std::setw(20) << size << std::endl; } } while (status == GSL_CONTINUE && iter < m_max_iter); } catch (const std::exception &e) { // Cleanup and re-throw. cleanup(x,ss,s); throw e; } catch (...) { // Cleanup and throw. cleanup(x,ss,s); pagmo_throw(std::runtime_error,"unknown exception caught in gsl_derivative_free::evolve"); } // Free up resources. cleanup(x,ss,s); // Check the generated individual and change it to respect the bounds as necessary. for (problem::base::size_type i = 0; i < cont_size; ++i) { if (params.x[i] < problem.get_lb()[i]) { params.x[i] = problem.get_lb()[i]; } if (params.x[i] > problem.get_ub()[i]) { params.x[i] = problem.get_ub()[i]; } } // Replace the best individual. pop.set_x(best_ind_idx,params.x); }
void find_periodic_solution_multi_dims(struct_all_ode *sao) { struct_state_ode sx; int NB_PAR = 2; int nb_jump, ij, iq; double t_max = 2; ; double th_init = 2 * M_PI / 180, vz_init = -1; double vth_init, vth_min, vth_max, vth_tolabs, deltaf; int status; int iter = 0, max_iter = 100; double size; const gsl_multimin_fminimizer_type *T; gsl_multimin_fminimizer *s = NULL; gsl_vector *ss, *x; gsl_multimin_function F; // init the function to minimize vth_init = 0 * M_PI / 180; vth_min = -200 * M_PI / 180; vth_max = 200 * M_PI / 180; vth_tolabs = 0.001 * M_PI / 180; // find vth init such as to obtain a periodic solution if (sao == NULL) { sao = new_all_ode(sao, NULL); } sao->eps_rel = 1e-6; sao->eps_abs = 1e-6; sao->h = 1e-6; sao->hmax = 1; sao->mode = MODE_FLY; sao->x[INDX_PH] = 0 * M_PI / 180; sao->x[INDX_TH] = th_init; sao->x[INDX_X] = 0; sao->x[INDX_Z] = 0; sao->x[INDX_R] = sao->r0; sao->x[INDX_VPH] = 0 * M_PI / 180; sao->x[INDX_VTH] = 0; sao->x[INDX_VR] = 0; // vr for flying model sao->x[INDX_ROOT] = 0; // trajectoire periodique => pas de perte d'energie a l'aterrisage, // vx =-vz.tan(theta) est imposee par vz et theta // le seul parametre permettant de fixer la periodicite est vtheta sao->x[INDX_TH] = th_init; sao->x[INDX_VX] = -vz_init * sin(th_init) / cos(th_init); sao->x[INDX_VZ] = vz_init; sx.NX = sao->NX; memcpy(sx.x, sao->x, sx.NX * sizeof (double)); sx.mode = sao->mode; sx.time_s = 0; sx.NX = sao->NX; sao->initial_state = sx; x = gsl_vector_alloc(NB_PAR); gsl_vector_set(x, 0, sao->x[INDX_VTH]); gsl_vector_set(x, 1, sao->x[INDX_VZ]); /* Initialize method and iterate */ T = gsl_multimin_fminimizer_nmsimplex2; F.n = NB_PAR; // vth,vz F.f = &get_delta_x_on_period_multi_dims; F.params = (void *) sao; /* Set initial step sizes to 1 */ ss = gsl_vector_alloc(2); gsl_vector_set(ss, 0, 0.1 * M_PI / 180); gsl_vector_set(ss, 1, 0.1); s = gsl_multimin_fminimizer_alloc(T, F.n); gsl_multimin_fminimizer_set(s, &F, x, ss); do { iter++; status = gsl_multimin_fminimizer_iterate(s); if (status) break; size = gsl_multimin_fminimizer_size(s); status = gsl_multimin_test_size(size, 1e-4); if (status == GSL_SUCCESS) { printf("converged to minimum at %d\n", iter); } if (status == GSL_SUCCESS) { deltaf = get_delta_x_on_period_multi_dims(x, sao); printf("Converged, delta f= %.5e:\n", deltaf); } } while (status == GSL_CONTINUE && iter < max_iter); gsl_vector_free(x); gsl_vector_free(ss); gsl_multimin_fminimizer_free(s); memcpy(sao->x, sao->initial_state.x, sao->NX * sizeof (double)); sao->time_second = 0; sao->mode = sx.mode; sao->print_values_fly_to_sol = 1; printf("--- initial state at time t= %e ----------\n", sao->final_state.time_s); print_state(sao->initial_state.x, NULL); print_energies(sao, sao->initial_state.x); printf("--- final state at time t= %e ----------\n", sao->final_state.time_s); print_state(sao->final_state.x, NULL); print_energies(sao, sao->final_state.x); }
std::vector<double> Calibrator::Calibrate(std::vector<double> initialVector, OptionParameterSet options[], double (*objectiveFunction)(const gsl_vector *v, void *params), std::ofstream &output){ const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex2; gsl_multimin_fminimizer *s = NULL; gsl_vector *ss, *x; gsl_multimin_function minex_func; size_t iter = 0; int status; double size; std::vector<double> result; int numOfVariable = (int) initialVector.size(); //Starting point x = gsl_vector_alloc(numOfVariable); for (int i = 0; i < numOfVariable; i++) { gsl_vector_set (x, i, initialVector[i]); } minex_func.f = objectiveFunction; ss = gsl_vector_alloc(numOfVariable); minex_func.n = numOfVariable; s = gsl_multimin_fminimizer_alloc (T, numOfVariable); //Set initial step sizes to 1 gsl_vector_set_all (ss, 1); //Initialize method and iterate minex_func.params = options; gsl_multimin_fminimizer_set (s, &minex_func, x, ss); do{ status = gsl_multimin_fminimizer_iterate(s); if (status) break; size = gsl_multimin_fminimizer_size (s); status = gsl_multimin_test_size (size, 1e-3); //1e-3 for Heston, 1e-4 for VGSA for better result if (status == GSL_SUCCESS){ std::cout << "A solution is found!" << std::endl; output << "Final Result:"<< std::endl; for (int i = 0; i < numOfVariable; ++i) result.push_back( gsl_vector_get (s->x, i) ); } //Print current step info std::cout << "size = " << size << ", f() = " << s->fval << ": "; output << "size = " << size << ",f() = " << s->fval << ","; for (int i = 0; i < numOfVariable; ++i) { double val = gsl_vector_get (s->x, i); output << val << ","; std::cout << val << ", "; } output << std::endl; std::cout << std::endl; iter++; } while (status == GSL_CONTINUE && iter < 50000 ); gsl_vector_free(x); gsl_vector_free(ss); gsl_multimin_fminimizer_free (s); return result; }
/** Executes the algorithm * * @throw runtime_error Thrown if algorithm cannot execute */ void Fit1D::exec() { // Custom initialization prepare(); // check if derivative defined in derived class bool isDerivDefined = true; gsl_matrix * M = NULL; try { const std::vector<double> inTest(m_parameterNames.size(),1.0); std::vector<double> outTest(m_parameterNames.size()); const double xValuesTest = 0; JacobianImpl J; M = gsl_matrix_alloc(m_parameterNames.size(),1); J.setJ(M); // note nData set to zero (last argument) hence this should avoid further memory problems functionDeriv(&(inTest.front()), &J, &xValuesTest, 0); } catch (Exception::NotImplementedError&) { isDerivDefined = false; } gsl_matrix_free(M); // Try to retrieve optional properties int histNumber = getProperty("WorkspaceIndex"); const int maxInterations = getProperty("MaxIterations"); // Get the input workspace MatrixWorkspace_const_sptr localworkspace = getProperty("InputWorkspace"); // number of histogram is equal to the number of spectra const size_t numberOfSpectra = localworkspace->getNumberHistograms(); // Check that the index given is valid if ( histNumber >= static_cast<int>(numberOfSpectra) ) { g_log.warning("Invalid Workspace index given, using first Workspace"); histNumber = 0; } // Retrieve the spectrum into a vector const MantidVec& XValues = localworkspace->readX(histNumber); const MantidVec& YValues = localworkspace->readY(histNumber); const MantidVec& YErrors = localworkspace->readE(histNumber); //Read in the fitting range data that we were sent double startX = getProperty("StartX"); double endX = getProperty("EndX"); //check if the values had been set, otherwise use defaults if ( isEmpty( startX ) ) { startX = XValues.front(); modifyStartOfRange(startX); // does nothing by default but derived class may provide a more intelligent value } if ( isEmpty( endX ) ) { endX = XValues.back(); modifyEndOfRange(endX); // does nothing by default but derived class may previde a more intelligent value } int m_minX; int m_maxX; // Check the validity of startX if ( startX < XValues.front() ) { g_log.warning("StartX out of range! Set to start of frame."); startX = XValues.front(); } // Get the corresponding bin boundary that comes before (or coincides with) this value for (m_minX = 0; XValues[m_minX+1] < startX; ++m_minX) {} // Check the validity of endX and get the bin boundary that come after (or coincides with) it if ( endX >= XValues.back() || endX < startX ) { g_log.warning("EndX out of range! Set to end of frame"); endX = XValues.back(); m_maxX = static_cast<int>(YValues.size()); } else { for (m_maxX = m_minX; XValues[m_maxX] < endX; ++m_maxX) {} } afterDataRangedDetermined(m_minX, m_maxX); // create and populate GSL data container warn user if l_data.n < l_data.p // since as a rule of thumb this is required as a minimum to obtained 'accurate' // fitting parameter values. FitData l_data(this,getProperty("Fix")); l_data.n = m_maxX - m_minX; // m_minX and m_maxX are array index markers. I.e. e.g. 0 & 19. if (l_data.n == 0) { g_log.error("The data set is empty."); throw std::runtime_error("The data set is empty."); } if (l_data.n < l_data.p) { g_log.error("Number of data points less than number of parameters to be fitted."); throw std::runtime_error("Number of data points less than number of parameters to be fitted."); } l_data.X = new double[l_data.n]; l_data.sigmaData = new double[l_data.n]; l_data.forSimplexLSwrap = new double[l_data.n]; l_data.parameters = new double[nParams()]; // check if histogram data in which case use mid points of histogram bins const bool isHistogram = localworkspace->isHistogramData(); for (unsigned int i = 0; i < l_data.n; ++i) { if (isHistogram) l_data.X[i] = 0.5*(XValues[m_minX+i]+XValues[m_minX+i+1]); // take mid-point if histogram bin else l_data.X[i] = XValues[m_minX+i]; } l_data.Y = &YValues[m_minX]; // check that no error is negative or zero for (unsigned int i = 0; i < l_data.n; ++i) { if (YErrors[m_minX+i] <= 0.0) { l_data.sigmaData[i] = 1.0; } else l_data.sigmaData[i] = YErrors[m_minX+i]; } // create array of fitted parameter. Take these to those input by the user. However, for doing the // underlying fitting it might be more efficient to actually perform the fitting on some of other // form of the fitted parameters. For instance, take the Gaussian sigma parameter. In practice it // in fact more efficient to perform the fitting not on sigma but 1/sigma^2. The methods // modifyInitialFittedParameters() and modifyFinalFittedParameters() are used to allow for this; // by default these function do nothing. m_fittedParameter.clear(); for (size_t i = 0; i < nParams(); i++) { m_fittedParameter.push_back(getProperty(m_parameterNames[i])); } modifyInitialFittedParameters(m_fittedParameter); // does nothing except if overwritten by derived class for (size_t i = 0; i < nParams(); i++) { l_data.parameters[i] = m_fittedParameter[i]; } // set-up initial guess for fit parameters gsl_vector *initFuncArg; initFuncArg = gsl_vector_alloc(l_data.p); for (size_t i = 0,j = 0; i < nParams(); i++) { if (l_data.active[i]) gsl_vector_set(initFuncArg, j++, m_fittedParameter[i]); } // set-up GSL container to be used with GSL simplex algorithm gsl_multimin_function gslSimplexContainer; gslSimplexContainer.n = l_data.p; // n here refers to number of parameters gslSimplexContainer.f = &gsl_costFunction; gslSimplexContainer.params = &l_data; // set-up GSL least squares container gsl_multifit_function_fdf f; f.f = &gsl_f; f.df = &gsl_df; f.fdf = &gsl_fdf; f.n = l_data.n; f.p = l_data.p; f.params = &l_data; // set-up remaining GSL machinery for least squared const gsl_multifit_fdfsolver_type *T = gsl_multifit_fdfsolver_lmsder; gsl_multifit_fdfsolver *s = NULL; if (isDerivDefined) { s = gsl_multifit_fdfsolver_alloc(T, l_data.n, l_data.p); gsl_multifit_fdfsolver_set(s, &f, initFuncArg); } // set-up remaining GSL machinery to use simplex algorithm const gsl_multimin_fminimizer_type *simplexType = gsl_multimin_fminimizer_nmsimplex; gsl_multimin_fminimizer *simplexMinimizer = NULL; gsl_vector *simplexStepSize = NULL; if (!isDerivDefined) { simplexMinimizer = gsl_multimin_fminimizer_alloc(simplexType, l_data.p); simplexStepSize = gsl_vector_alloc(l_data.p); gsl_vector_set_all (simplexStepSize, 1.0); // is this always a sensible starting step size? gsl_multimin_fminimizer_set(simplexMinimizer, &gslSimplexContainer, initFuncArg, simplexStepSize); } // finally do the fitting int iter = 0; int status; double size; // for simplex algorithm double finalCostFuncVal; double dof = static_cast<double>(l_data.n - l_data.p); // dof stands for degrees of freedom // Standard least-squares used if derivative function defined otherwise simplex Progress prog(this,0.0,1.0,maxInterations); if (isDerivDefined) { do { iter++; status = gsl_multifit_fdfsolver_iterate(s); if (status) // break if error break; status = gsl_multifit_test_delta(s->dx, s->x, 1e-4, 1e-4); prog.report(); } while (status == GSL_CONTINUE && iter < maxInterations); double chi = gsl_blas_dnrm2(s->f); finalCostFuncVal = chi*chi / dof; // put final converged fitting values back into m_fittedParameter for (size_t i = 0, j = 0; i < nParams(); i++) if (l_data.active[i]) m_fittedParameter[i] = gsl_vector_get(s->x,j++); } else { do { iter++; status = gsl_multimin_fminimizer_iterate(simplexMinimizer); if (status) // break if error break; size = gsl_multimin_fminimizer_size(simplexMinimizer); status = gsl_multimin_test_size(size, 1e-2); prog.report(); } while (status == GSL_CONTINUE && iter < maxInterations); finalCostFuncVal = simplexMinimizer->fval / dof; // put final converged fitting values back into m_fittedParameter for (unsigned int i = 0, j = 0; i < m_fittedParameter.size(); i++) if (l_data.active[i]) m_fittedParameter[i] = gsl_vector_get(simplexMinimizer->x,j++); } modifyFinalFittedParameters(m_fittedParameter); // do nothing except if overwritten by derived class // Output summary to log file std::string reportOfFit = gsl_strerror(status); g_log.information() << "Iteration = " << iter << "\n" << "Status = " << reportOfFit << "\n" << "Chi^2/DoF = " << finalCostFuncVal << "\n"; for (size_t i = 0; i < m_fittedParameter.size(); i++) g_log.information() << m_parameterNames[i] << " = " << m_fittedParameter[i] << " \n"; // also output summary to properties setProperty("OutputStatus", reportOfFit); setProperty("OutputChi2overDoF", finalCostFuncVal); for (size_t i = 0; i < m_fittedParameter.size(); i++) setProperty(m_parameterNames[i], m_fittedParameter[i]); std::string output = getProperty("Output"); if (!output.empty()) { // calculate covariance matrix if derivatives available gsl_matrix *covar(NULL); std::vector<double> standardDeviations; std::vector<double> sdExtended; if (isDerivDefined) { covar = gsl_matrix_alloc (l_data.p, l_data.p); gsl_multifit_covar (s->J, 0.0, covar); int iPNotFixed = 0; for(size_t i=0;i<nParams();i++) { sdExtended.push_back(1.0); if (l_data.active[i]) { sdExtended[i] = sqrt(gsl_matrix_get(covar,iPNotFixed,iPNotFixed)); iPNotFixed++; } } modifyFinalFittedParameters(sdExtended); for(size_t i=0;i<nParams();i++) if (l_data.active[i]) standardDeviations.push_back(sdExtended[i]); declareProperty( new WorkspaceProperty<API::ITableWorkspace>("OutputNormalisedCovarianceMatrix","",Direction::Output), "The name of the TableWorkspace in which to store the final covariance matrix" ); setPropertyValue("OutputNormalisedCovarianceMatrix",output+"_NormalisedCovarianceMatrix"); Mantid::API::ITableWorkspace_sptr m_covariance = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace"); m_covariance->addColumn("str","Name"); std::vector<std::string> paramThatAreFitted; // used for populating 1st "name" column for(size_t i=0;i<nParams();i++) { if (l_data.active[i]) { m_covariance->addColumn("double",m_parameterNames[i]); paramThatAreFitted.push_back(m_parameterNames[i]); } } for(size_t i=0;i<l_data.p;i++) { Mantid::API::TableRow row = m_covariance->appendRow(); row << paramThatAreFitted[i]; for(size_t j=0;j<l_data.p;j++) { if (j == i) row << 1.0; else { row << 100.0*gsl_matrix_get(covar,i,j)/sqrt(gsl_matrix_get(covar,i,i)*gsl_matrix_get(covar,j,j)); } } } setProperty("OutputNormalisedCovarianceMatrix",m_covariance); } declareProperty( new WorkspaceProperty<API::ITableWorkspace>("OutputParameters","",Direction::Output), "The name of the TableWorkspace in which to store the final fit parameters" ); declareProperty(new WorkspaceProperty<MatrixWorkspace>("OutputWorkspace","",Direction::Output), "Name of the output Workspace holding resulting simlated spectrum"); setPropertyValue("OutputParameters",output+"_Parameters"); setPropertyValue("OutputWorkspace",output+"_Workspace"); // Save the final fit parameters in the output table workspace Mantid::API::ITableWorkspace_sptr m_result = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace"); m_result->addColumn("str","Name"); m_result->addColumn("double","Value"); if (isDerivDefined) m_result->addColumn("double","Error"); Mantid::API::TableRow row = m_result->appendRow(); row << "Chi^2/DoF" << finalCostFuncVal; for(size_t i=0;i<nParams();i++) { Mantid::API::TableRow row = m_result->appendRow(); row << m_parameterNames[i] << m_fittedParameter[i]; if (isDerivDefined && l_data.active[i]) { // perhaps want to scale standard deviations with sqrt(finalCostFuncVal) row << sdExtended[i]; } } setProperty("OutputParameters",m_result); // Save the fitted and simulated spectra in the output workspace MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace"); int iSpec = getProperty("WorkspaceIndex"); const MantidVec& inputX = inputWorkspace->readX(iSpec); const MantidVec& inputY = inputWorkspace->readY(iSpec); int histN = isHistogram ? 1 : 0; Mantid::DataObjects::Workspace2D_sptr ws = boost::dynamic_pointer_cast<Mantid::DataObjects::Workspace2D> ( Mantid::API::WorkspaceFactory::Instance().create( "Workspace2D", 3, l_data.n + histN, l_data.n) ); ws->setTitle(""); ws->getAxis(0)->unit() = inputWorkspace->getAxis(0)->unit();// UnitFactory::Instance().create("TOF"); for(int i=0;i<3;i++) ws->dataX(i).assign(inputX.begin()+m_minX,inputX.begin()+m_maxX+histN); ws->dataY(0).assign(inputY.begin()+m_minX,inputY.begin()+m_maxX); MantidVec& Y = ws->dataY(1); MantidVec& E = ws->dataY(2); double* lOut = new double[l_data.n]; // to capture output from call to function() modifyInitialFittedParameters(m_fittedParameter); // does nothing except if overwritten by derived class function(&m_fittedParameter[0], lOut, l_data.X, l_data.n); modifyInitialFittedParameters(m_fittedParameter); // reverse the effect of modifyInitialFittedParameters - if any for(unsigned int i=0; i<l_data.n; i++) { Y[i] = lOut[i]; E[i] = l_data.Y[i] - Y[i]; } delete [] lOut; setProperty("OutputWorkspace",boost::dynamic_pointer_cast<MatrixWorkspace>(ws)); if (isDerivDefined) gsl_matrix_free(covar); } // clean up dynamically allocated gsl stuff if (isDerivDefined) gsl_multifit_fdfsolver_free(s); else { gsl_vector_free(simplexStepSize); gsl_multimin_fminimizer_free(simplexMinimizer); } delete [] l_data.X; delete [] l_data.sigmaData; delete [] l_data.forSimplexLSwrap; delete [] l_data.parameters; gsl_vector_free (initFuncArg); return; }
int main (int argc, char **argv) { struct experiment_params params; double dx, dy; double speed, angle; gsl_vector *solution; int c; double compute_start, delta; while ((c = getopt (argc, argv, "v")) != EOF) { switch (c) { case 'v': vflag = 1; break; default: usage (); } } memset (¶ms, 0, sizeof params); params.observed_hit[0] = 0; params.observed_hit[1] = 0; params.observed_hit[2] = 1; params.observed_bounce[0] = 25; params.observed_bounce[1] = 0; params.observed_bounce[2] = 0; params.observed_secs = 1.359; dx = params.observed_bounce[0] - params.observed_hit[0]; dy = params.observed_bounce[1] - params.observed_hit[1]; params.observed_dist = hypot (dy, dx); params.simulator_dimen = 4; params.odesys.function = sim_func; params.odesys.dimension = params.simulator_dimen; params.odesys.params = ¶ms; params.stepper = gsl_odeiv_step_alloc (gsl_odeiv_step_rk8pd, params.simulator_dimen); params.controller = gsl_odeiv_control_y_new (1e-6, 0.0); params.evolver = gsl_odeiv_evolve_alloc (params.simulator_dimen); params.minimizer_dimen = 2; params.starting_point = gsl_vector_alloc (params.minimizer_dimen); params.minimizer_step_sizes = gsl_vector_alloc (params.minimizer_dimen); params.minimizer = gsl_multimin_fminimizer_alloc (gsl_multimin_fminimizer_nmsimplex2, params.minimizer_dimen); gsl_vector_set_all (params.starting_point, 0); gsl_vector_set_all (params.minimizer_step_sizes, 1.0); if (0) { graph_error_func (¶ms); } compute_start = get_secs (); solve_by_simulation (¶ms); delta = get_secs () - compute_start; solution = gsl_multimin_fminimizer_x (params.minimizer); speed = gsl_vector_get (solution, 0); angle = gsl_vector_get (solution, 1); printf ("speed = %8.3f angle = %8.3f; compute time %.3fms\n", speed * METERS_PER_SEC_TO_MPH, RTOD (angle), delta * 1000); return (0); }
int lua_multimin_minimize(lua_State * L) { bool ssdel=false; double eps=0.00001; double tol=0.0001; double step_size=0.01; int maxiter=1000; bool print=false; array<double> * x=0; array<double> * ss=0; const gsl_multimin_fminimizer_type *Tf = 0; const gsl_multimin_fdfminimizer_type *Tdf = 0; multi_param mp; mp.L=L; mp.fdf_index=-1; lua_pushstring(L,"f"); lua_gettable(L,-2); if(lua_isfunction(L,-1)) { mp.f_index=luaL_ref(L, LUA_REGISTRYINDEX); } else { luaL_error(L,"%s\n","missing function"); } lua_pushstring(L,"df"); lua_gettable(L,-2); if(lua_isfunction(L,-1)) { mp.df_index=luaL_ref(L, LUA_REGISTRYINDEX); Tdf= gsl_multimin_fdfminimizer_conjugate_fr; } else { lua_pop(L,1); Tf= gsl_multimin_fminimizer_nmsimplex2; } lua_pushstring(L,"fdf"); lua_gettable(L,-2); if(lua_isfunction(L,-1)) { mp.fdf_index=luaL_ref(L, LUA_REGISTRYINDEX); } else { lua_pop(L,1); mp.fdf_index=-1; } lua_pushstring(L,"algorithm"); lua_gettable(L,-2); if(lua_isstring(L,-1)) { if(Tf!=0) { if(!strcmp(lua_tostring(L,-1),"nmsimplex")) { Tf = gsl_multimin_fminimizer_nmsimplex; } else if(!strcmp(lua_tostring(L,-1),"nmsimplex2rand")) { Tf = gsl_multimin_fminimizer_nmsimplex2rand; } else if(!strcmp(lua_tostring(L,-1),"nmsimplex2")) { Tf = gsl_multimin_fminimizer_nmsimplex2; } else { luaL_error(L,"%s\n","invalid algorithm"); } } else { if(!strcmp(lua_tostring(L,-1),"conjugate_pr")) { Tdf = gsl_multimin_fdfminimizer_conjugate_pr; } else if(!strcmp(lua_tostring(L,-1),"steepest_descent")) { Tdf = gsl_multimin_fdfminimizer_steepest_descent; } else if(!strcmp(lua_tostring(L,-1),"vector_bfgs")) { Tdf = gsl_multimin_fdfminimizer_vector_bfgs; } else if(!strcmp(lua_tostring(L,-1),"vector_bfgs2")) { Tdf = gsl_multimin_fdfminimizer_vector_bfgs2; } else if(!strcmp(lua_tostring(L,-1),"conjugate_fr")) { Tdf = gsl_multimin_fdfminimizer_conjugate_fr; } else { luaL_error(L,"%s\n","invalid algorithm"); } } } lua_pop(L,1); lua_pushstring(L,"show_iterations"); lua_gettable(L,-2); if(lua_isboolean(L,-1)) { print=(lua_toboolean(L,-1)==1); } lua_pop(L,1); lua_pushstring(L,"eps"); lua_gettable(L,-2); if(lua_isnumber(L,-1)) { eps=lua_tonumber(L,-1); } lua_pop(L,1); lua_pushstring(L,"step_size"); lua_gettable(L,-2); if(lua_isnumber(L,-1)) { step_size=lua_tonumber(L,-1); } lua_pop(L,1); lua_pushstring(L,"tol"); lua_gettable(L,-2); if(lua_isnumber(L,-1)) { tol=lua_tonumber(L,-1); } lua_pop(L,1); lua_pushstring(L,"maxiter"); lua_gettable(L,-2); if(lua_isnumber(L,-1)) { maxiter=(int)lua_tonumber(L,-1); } lua_pop(L,1); lua_pushstring(L,"starting_point"); lua_gettable(L,-2); if(!lua_isuserdata(L,-1)) lua_error(L); if (!SWIG_IsOK(SWIG_ConvertPtr(L,-1,(void**)&x,SWIGTYPE_p_arrayT_double_t,0))){ luaL_error(L,"%s\n","missing starting point"); } lua_pop(L,1); if(Tf) { lua_pushstring(L,"step_sizes"); lua_gettable(L,-2); if(lua_isuserdata(L,-1)) { if (!SWIG_IsOK(SWIG_ConvertPtr(L,-1,(void**)&ss,SWIGTYPE_p_arrayT_double_t,0))){ lua_error(L); } } else { ssdel=true; ss=new array<double>(x->size()); ss->set_all(1.0); if(lua_isnumber(L,-1)) { double v=lua_tonumber(L,-1); ss->set_all(v); } } lua_pop(L,1); } lua_pop(L,1); if(Tf) { gsl_multimin_fminimizer *s = NULL; gsl_vector SS, X; gsl_multimin_function minex_func; int iter = 0; int status; double size; int N=x->size(); /* Starting point */ X.size=x->size(); X.stride=1; X.data=x->data(); X.owner=0; /* Set initial step sizes */ SS.size=ss->size(); SS.stride=1; SS.data=ss->data(); SS.owner=0; /* Initialize method and iterate */ minex_func.n = N; minex_func.f = multimin_f_cb; minex_func.params = ∓ s = gsl_multimin_fminimizer_alloc (Tf, N); gsl_multimin_fminimizer_set (s, &minex_func, &X, &SS); if(print) printf ("running algorithm '%s'\n", gsl_multimin_fminimizer_name (s)); do { iter++; status = gsl_multimin_fminimizer_iterate(s); if (status) break; size = gsl_multimin_fminimizer_size (s); status = gsl_multimin_test_size (size, eps); if (status == GSL_SUCCESS) { if(print) printf ("converged to minimum at\n"); } if(print) printf ("%5d f() = %12.3f size = %.9f\n", iter, s->fval, size); } while (status == GSL_CONTINUE && iter < maxiter); for(int i=0;i<N;++i) x->set(i,gsl_vector_get(s->x,i)); luaL_unref(L, LUA_REGISTRYINDEX, mp.f_index); gsl_multimin_fminimizer_free (s); } else { gsl_multimin_fdfminimizer *s = NULL; gsl_vector X; gsl_multimin_function_fdf minex_func; int iter = 0; int status; double size; int N=x->size(); /* Starting point */ X.size=x->size(); X.stride=1; X.data=x->data(); X.owner=0; /* Initialize method and iterate */ minex_func.n = N; minex_func.f = multimin_f_cb; minex_func.df = multimin_df_cb; minex_func.fdf = multimin_fdf_cb; minex_func.params = ∓ s = gsl_multimin_fdfminimizer_alloc (Tdf, N); gsl_multimin_fdfminimizer_set (s, &minex_func, &X, step_size, tol); if(print) printf ("running algorithm '%s'\n", gsl_multimin_fdfminimizer_name (s)); do { iter++; status = gsl_multimin_fdfminimizer_iterate(s); if (status) break; status = gsl_multimin_test_gradient (s->gradient, eps); if (status == GSL_SUCCESS) { if(print) printf ("converged to minimum at\n"); } if(print) printf ("%5d f() = %12.3f\n", iter, s->f); } while (status == GSL_CONTINUE && iter < maxiter); for(int i=0;i<N;++i) x->set(i,gsl_vector_get(s->x,i)); luaL_unref(L, LUA_REGISTRYINDEX, mp.f_index); luaL_unref(L, LUA_REGISTRYINDEX, mp.df_index); gsl_multimin_fdfminimizer_free (s); } if(mp.fdf_index>=0) { luaL_unref(L, LUA_REGISTRYINDEX, mp.fdf_index); } if(ssdel) { delete ss; } return 0; }
/** Executes the algorithm * * @throw runtime_error Thrown if algorithm cannot execute */ void DiffractionEventCalibrateDetectors::exec() { // Try to retrieve optional properties const int maxIterations = getProperty("MaxIterations"); const double peakOpt = getProperty("LocationOfPeakToOptimize"); // Get the input workspace EventWorkspace_const_sptr inputW = getProperty("InputWorkspace"); // retrieve the properties const std::string rb_params=getProperty("Params"); //Get some stuff from the input workspace Instrument_const_sptr inst = inputW->getInstrument(); //Build a list of Rectangular Detectors std::vector<boost::shared_ptr<RectangularDetector> > detList; // --------- Loading only one bank ---------------------------------- std::string onebank = getProperty("BankName"); bool doOneBank = (onebank != ""); for (int i=0; i < inst->nelements(); i++) { boost::shared_ptr<RectangularDetector> det; boost::shared_ptr<ICompAssembly> assem; boost::shared_ptr<ICompAssembly> assem2; det = boost::dynamic_pointer_cast<RectangularDetector>( (*inst)[i] ); if (det) { if (det->getName().compare(onebank) == 0) detList.push_back(det); if (!doOneBank) detList.push_back(det); } else { //Also, look in the first sub-level for RectangularDetectors (e.g. PG3). // We are not doing a full recursive search since that will be very long for lots of pixels. assem = boost::dynamic_pointer_cast<ICompAssembly>( (*inst)[i] ); if (assem) { for (int j=0; j < assem->nelements(); j++) { det = boost::dynamic_pointer_cast<RectangularDetector>( (*assem)[j] ); if (det) { if (det->getName().compare(onebank) == 0) detList.push_back(det); if (!doOneBank) detList.push_back(det); } else { //Also, look in the second sub-level for RectangularDetectors (e.g. PG3). // We are not doing a full recursive search since that will be very long for lots of pixels. assem2 = boost::dynamic_pointer_cast<ICompAssembly>( (*assem)[j] ); if (assem2) { for (int k=0; k < assem2->nelements(); k++) { det = boost::dynamic_pointer_cast<RectangularDetector>( (*assem2)[k] ); if (det) { if (det->getName().compare(onebank) == 0) detList.push_back(det); if (!doOneBank) detList.push_back(det); } } } } } } } } // set-up minimizer std::string inname = getProperty("InputWorkspace"); std::string outname = inname+"2"; //getProperty("OutputWorkspace"); IAlgorithm_sptr algS = createSubAlgorithm("SortEvents"); algS->setPropertyValue("InputWorkspace",inname); algS->setPropertyValue("SortBy", "X Value"); algS->executeAsSubAlg(); inputW=algS->getProperty("InputWorkspace"); //Write DetCal File double baseX,baseY,baseZ,upX,upY,upZ; std::string filename=getProperty("DetCalFilename"); std::fstream outfile; outfile.open(filename.c_str(), std::ios::out); if(detList.size() > 1) { outfile << "#\n"; outfile << "# Mantid Optimized .DetCal file for SNAP with TWO detector panels\n"; outfile << "# Old Panel, nominal size and distance at -90 degrees.\n"; outfile << "# New Panel, nominal size and distance at +90 degrees.\n"; outfile << "#\n"; outfile << "# Lengths are in centimeters.\n"; outfile << "# Base and up give directions of unit vectors for a local\n"; outfile << "# x,y coordinate system on the face of the detector.\n"; outfile << "#\n"; std::time_t current_t = DateAndTime::get_current_time().to_time_t() ; std::tm * current = gmtime( ¤t_t ); outfile << "# "<<asctime (current) <<"\n"; outfile << "#\n"; outfile << "6 L1 T0_SHIFT\n"; IObjComponent_const_sptr source = inst->getSource(); IObjComponent_const_sptr sample = inst->getSample(); outfile << "7 "<<source->getDistance(*sample)*100<<" 0\n"; outfile << "4 DETNUM NROWS NCOLS WIDTH HEIGHT DEPTH DETD CenterX CenterY CenterZ BaseX BaseY BaseZ UpX UpY UpZ\n"; } Progress prog(this,0.0,1.0,detList.size()); for (int det=0; det < static_cast<int>(detList.size()); det++) { std::string par[6]; par[0]=detList[det]->getName(); par[1]=inname; par[2]=outname; std::ostringstream strpeakOpt; strpeakOpt<<peakOpt; par[3]=strpeakOpt.str(); par[4]=rb_params; // --- Create a GroupingWorkspace for this detector name ------ CPUTimer tim; IAlgorithm_sptr alg2 = AlgorithmFactory::Instance().create("CreateGroupingWorkspace", 1); alg2->initialize(); alg2->setPropertyValue("InputWorkspace", getPropertyValue("InputWorkspace")); alg2->setPropertyValue("GroupNames", detList[det]->getName()); std::string groupWSName = "group_" + detList[det]->getName(); alg2->setPropertyValue("OutputWorkspace", groupWSName); alg2->executeAsSubAlg(); par[5] = groupWSName; std::cout << tim << " to CreateGroupingWorkspace" << std::endl; const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex; gsl_multimin_fminimizer *s = NULL; gsl_vector *ss, *x; gsl_multimin_function minex_func; // finally do the fitting int nopt = 6; int iter = 0; int status = 0; double size; /* Starting point */ x = gsl_vector_alloc (nopt); gsl_vector_set (x, 0, 0.0); gsl_vector_set (x, 1, 0.0); gsl_vector_set (x, 2, 0.0); gsl_vector_set (x, 3, 0.0); gsl_vector_set (x, 4, 0.0); gsl_vector_set (x, 5, 0.0); /* Set initial step sizes to 0.1 */ ss = gsl_vector_alloc (nopt); gsl_vector_set_all (ss, 0.1); /* Initialize method and iterate */ minex_func.n = nopt; minex_func.f = &Mantid::Algorithms::gsl_costFunction; minex_func.params = ∥ s = gsl_multimin_fminimizer_alloc (T, nopt); gsl_multimin_fminimizer_set (s, &minex_func, x, ss); do { iter++; status = gsl_multimin_fminimizer_iterate(s); if (status) break; size = gsl_multimin_fminimizer_size (s); status = gsl_multimin_test_size (size, 1e-2); } while (status == GSL_CONTINUE && iter < maxIterations && s->fval != -0.000 ); // Output summary to log file if (s->fval != -0.000) movedetector(gsl_vector_get (s->x, 0), gsl_vector_get (s->x, 1), gsl_vector_get (s->x, 2), gsl_vector_get (s->x, 3), gsl_vector_get (s->x, 4), gsl_vector_get (s->x, 5), par[0], getProperty("InputWorkspace")); else { gsl_vector_set (s->x, 0, 0.0); gsl_vector_set (s->x, 1, 0.0); gsl_vector_set (s->x, 2, 0.0); gsl_vector_set (s->x, 3, 0.0); gsl_vector_set (s->x, 4, 0.0); gsl_vector_set (s->x, 5, 0.0); } std::string reportOfDiffractionEventCalibrateDetectors = gsl_strerror(status); if (s->fval == -0.000) reportOfDiffractionEventCalibrateDetectors = "No events"; g_log.information() << "Detector = " << det << "\n" << "Method used = " << "Simplex" << "\n" << "Iteration = " << iter << "\n" << "Status = " << reportOfDiffractionEventCalibrateDetectors << "\n" << "Minimize PeakLoc-" << peakOpt << " = " << s->fval << "\n"; //Move in cm for small shifts g_log.information() << "Move (X) = " << gsl_vector_get (s->x, 0)*0.01 << " \n"; g_log.information() << "Move (Y) = " << gsl_vector_get (s->x, 1)*0.01 << " \n"; g_log.information() << "Move (Z) = " << gsl_vector_get (s->x, 2)*0.01 << " \n"; g_log.information() << "Rotate (X) = " << gsl_vector_get (s->x, 3) << " \n"; g_log.information() << "Rotate (Y) = " << gsl_vector_get (s->x, 4) << " \n"; g_log.information() << "Rotate (Z) = " << gsl_vector_get (s->x, 5) << " \n"; Kernel::V3D CalCenter=V3D(gsl_vector_get (s->x, 0)*0.01, gsl_vector_get (s->x, 1)*0.01, gsl_vector_get (s->x, 2)*0.01); Kernel::V3D Center=detList[det]->getPos()+CalCenter; int pixmax = detList[det]->xpixels()-1; int pixmid = (detList[det]->ypixels()-1)/2; BoundingBox box; detList[det]->getAtXY(pixmax, pixmid)->getBoundingBox(box); baseX = box.xMax(); baseY = box.yMax(); baseZ = box.zMax(); Kernel::V3D Base=V3D(baseX,baseY,baseZ)+CalCenter; pixmid = (detList[det]->xpixels()-1)/2; pixmax = detList[det]->ypixels()-1; detList[det]->getAtXY(pixmid, pixmax)->getBoundingBox(box); upX = box.xMax(); upY = box.yMax(); upZ = box.zMax(); Kernel::V3D Up=V3D(upX,upY,upZ)+CalCenter; Base-=Center; Up-=Center; //Rotate around x baseX = Base[0]; baseY = Base[1]; baseZ = Base[2]; double deg2rad=M_PI/180.0; double angle = gsl_vector_get (s->x, 3)*deg2rad; Base=V3D(baseX,baseY*cos(angle)-baseZ*sin(angle), baseY*sin(angle)+baseZ*cos(angle)); upX = Up[0]; upY = Up[1]; upZ = Up[2]; Up=V3D(upX,upY*cos(angle)-upZ*sin(angle), upY*sin(angle)+upZ*cos(angle)); //Rotate around y baseX = Base[0]; baseY = Base[1]; baseZ = Base[2]; angle = gsl_vector_get (s->x, 4)*deg2rad; Base=V3D(baseZ*sin(angle)+baseX*cos(angle), baseY,baseZ*cos(angle)-baseX*sin(angle)); upX = Up[0]; upY = Up[1]; upZ = Up[2]; Up=V3D(upZ*cos(angle)-upX*sin(angle),upY, upZ*sin(angle)+upX*cos(angle)); //Rotate around z baseX = Base[0]; baseY = Base[1]; baseZ = Base[2]; angle = gsl_vector_get (s->x, 5)*deg2rad; Base=V3D(baseX*cos(angle)-baseY*sin(angle), baseX*sin(angle)+baseY*cos(angle),baseZ); upX = Up[0]; upY = Up[1]; upZ = Up[2]; Up=V3D(upX*cos(angle)-upY*sin(angle), upX*sin(angle)+upY*cos(angle),upZ); Base.normalize(); Up.normalize(); Center*=100.0; // << det+1 << " " outfile << "5 " << detList[det]->getName().substr(4) << " " << detList[det]->xpixels() << " " << detList[det]->ypixels() << " " << 100.0*detList[det]->xsize() << " " << 100.0*detList[det]->ysize() << " " << "0.2000" << " " << Center.norm() << " " ; Center.write(outfile); outfile << " "; Base.write(outfile); outfile << " "; Up.write(outfile); outfile << "\n"; // clean up dynamically allocated gsl stuff gsl_vector_free(x); gsl_vector_free(ss); gsl_multimin_fminimizer_free (s); // Remove the now-unneeded grouping workspace AnalysisDataService::Instance().remove(groupWSName); prog.report(detList[det]->getName()); } // Closing outfile.close(); return; }