mango.hpp
Go to the documentation of this file.
1 // Copyright 2019, University of Maryland and the MANGO development team.
2 //
3 // This file is part of MANGO.
4 //
5 // MANGO is free software: you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License as
7 // published by the Free Software Foundation, either version 3 of the
8 // License, or (at your option) any later version.
9 //
10 // MANGO is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with MANGO. If not, see
17 // <https://www.gnu.org/licenses/>.
18 
19 
20 #ifndef MANGO_H
21 #define MANGO_H
22 
23 #include <mpi.h>
24 #include <string>
25 
26 //! This C++ namespace contains everything related to MANGO.
27 namespace mango {
28 
29  //! The list of packages, i.e. libraries that MANGO can call to perform optimization.
30  /**
31  * Note that all packages are enumerated here even if MANGO is built
32  * without support for all of them. This list of packages is
33  * generated by the update_algorithms script from the master table
34  * of algorithms in algorithms.dat.
35  */
36  typedef enum {
37  // <packages>
38  // This section was automatically generated by ./update_algorithms
44  // </packages>
45  NUM_PACKAGES //!< Not an actual package, just counting.
46  } package_type;
47 
48  //! A large finite number
49  /**
50  * This number is not yet used in the code.
51  */
52  const double NUMBER_FOR_FAILED = 1.0e+12;
53 
54  //////////////////////////////////////////////////////////////////////////////////////
55  // Items related to algorithms:
56 
57  //! Some properties of each algorithm that MANGO is aware of.
58  typedef struct {
59  std::string name; //!< A short string with the algorithm's name, e.g. 'petsc_pounders' or 'hopspack'.
60  package_type package; //!< The optimization library that the algorithm belongs to.
61  bool least_squares; //!< Whether or not the algorithm assumes the objective function has least-squares form.
62  bool uses_derivatives; //!< Whether the algorithm requires derivatives of the objective function or residuals to be supplied.
63  bool parallel; //!< Whether the algorithm can support concurrent evaluations of the objective function. Any algorithm that uses derivatives is parallel in this sense, because finite difference derivatives can be computed using concurrent function evaluations.
64  bool allows_bound_constraints; //!< Whether the algorithm allows maximum and minimum values (a.k.a. box constraints) to be imposed on the independent variables.
65  bool requires_bound_constraints; //!< Whether the algorithm requires maximum and minimum values (a.k.a. box constraints) to be imposed on the independent variables.
67 
68  //! A list of the algorithms that MANGO can potentially use.
69  /**
70  * Each algorithm in this list is only actually available if MANGO is built
71  * with the corresponding package. This list of packages is
72  * generated by the update_algorithms script from the master table
73  * of algorithms in algorithms.dat.
74  */
75  typedef enum {
76  // <enum>
77  // This section was automatically generated by ./update_algorithms
116  // </enum>
117  NUM_ALGORITHMS //!< Not an actual algorithm, just counting.
118  } algorithm_type;
119 
120  //! A database of the algorithms that MANGO is aware of, including various properties of each algorithm.
121  /**
122  * This databse is automatically generated from the master database algorithms.dat by the update_algorithms script.
123  */
125  // <database>
126  // This section was automatically generated by ./update_algorithms
127  // name, package, least_squares, uses_derivatives, parallel, allows_bound_constraints, requires_bound_constraints
128  {"mango_levenberg_marquardt", PACKAGE_MANGO, true, true, true, false, false},
129  {"mango_imfil", PACKAGE_MANGO, false, false, true, true, true },
130  {"petsc_nm", PACKAGE_PETSC, false, false, false, false, false},
131  {"petsc_pounders", PACKAGE_PETSC, true, false, false, true, false},
132  {"petsc_brgn", PACKAGE_PETSC, true, true, true, true, false},
133  {"nlopt_gn_direct", PACKAGE_NLOPT, false, false, false, true, true },
134  {"nlopt_gn_direct_l", PACKAGE_NLOPT, false, false, false, true, true },
135  {"nlopt_gn_direct_l_rand", PACKAGE_NLOPT, false, false, false, true, true },
136  {"nlopt_gn_direct_noscal", PACKAGE_NLOPT, false, false, false, true, true },
137  {"nlopt_gn_direct_l_noscal", PACKAGE_NLOPT, false, false, false, true, true },
138  {"nlopt_gn_direct_l_rand_noscal", PACKAGE_NLOPT, false, false, false, true, true },
139  {"nlopt_gn_orig_direct", PACKAGE_NLOPT, false, false, false, true, true },
140  {"nlopt_gn_orig_direct_l", PACKAGE_NLOPT, false, false, false, true, true },
141  {"nlopt_gn_crs2_lm", PACKAGE_NLOPT, false, false, false, true, true },
142  {"nlopt_ln_cobyla", PACKAGE_NLOPT, false, false, false, true, false},
143  {"nlopt_ln_bobyqa", PACKAGE_NLOPT, false, false, false, true, false},
144  {"nlopt_ln_praxis", PACKAGE_NLOPT, false, false, false, true, false},
145  {"nlopt_ln_neldermead", PACKAGE_NLOPT, false, false, false, true, false},
146  {"nlopt_ln_sbplx", PACKAGE_NLOPT, false, false, false, true, false},
147  {"nlopt_ld_mma", PACKAGE_NLOPT, false, true, true, true, false},
148  {"nlopt_ld_ccsaq", PACKAGE_NLOPT, false, true, true, true, false},
149  {"nlopt_ld_slsqp", PACKAGE_NLOPT, false, true, true, true, false},
150  {"nlopt_ld_lbfgs", PACKAGE_NLOPT, false, true, true, true, false},
151  {"nlopt_ld_tnewton_precond_restart",PACKAGE_NLOPT, false, true, true, true, false},
152  {"nlopt_ld_tnewton_precond", PACKAGE_NLOPT, false, true, true, true, false},
153  {"nlopt_ld_tnewton_restart", PACKAGE_NLOPT, false, true, true, true, false},
154  {"nlopt_ld_tnewton", PACKAGE_NLOPT, false, true, true, true, false},
155  {"nlopt_ld_var1", PACKAGE_NLOPT, false, true, true, true, false},
156  {"nlopt_ld_var2", PACKAGE_NLOPT, false, true, true, true, false},
157  {"hopspack", PACKAGE_HOPSPACK,false, false, true, true, false},
158  {"gsl_lm", PACKAGE_GSL, true, true, true, false, false},
159  {"gsl_dogleg", PACKAGE_GSL, true, true, true, false, false},
160  {"gsl_ddogleg", PACKAGE_GSL, true, true, true, false, false},
161  {"gsl_subspace2d", PACKAGE_GSL, true, true, true, false, false},
162  {"gsl_conjugate_fr", PACKAGE_GSL, false, true, true, false, false},
163  {"gsl_conjugate_pr", PACKAGE_GSL, false, true, true, false, false},
164  {"gsl_bfgs", PACKAGE_GSL, false, true, true, false, false},
165  {"gsl_nm", PACKAGE_GSL, false, false, false, false, false}
166  // </database>
167  };
168 
169  //! Checks whether or not a string corresponds to the name of one of the optimization algorithms known by MANGO.
170  /**
171  * @param[in] algorithm_name A candidate name for an optimization algorithm. These names correspond to the
172  * <span class="paramname">name</span> field of the \ref algorithm_properties type.
173  * @return true if an algorithm exists in MANGO's database with the corresponding name, false otherwise.
174  */
175  bool does_algorithm_exist(std::string algorithm_name);
176 
177  //! Returns the integer (enum) for an optimization algorithm associated with its string name.
178  /**
179  * @param[in] name A name of an optimization algorithm, e.g. "petsc_pounders" or "nlopt_ln_neldermead"
180  * @param[out] algorithm_int The integer code for the algorithm with name specified by <span class="paramname">name</span>.
181  * If no matching algorithm is found, the value pointed to by <span class="paramname">algorithm_int</span> will not be changed from its input value.
182  * @return true if an algorithm exists with a name equal to the specified <span class="paramname">name</span>, false otherwise.
183  */
184  bool get_algorithm(std::string name, algorithm_type* algorithm_int);
185 
186  //////////////////////////////////////////////////////////////////////////////////////
187  // Items related to partitioning the processors into worker groups:
188 
189  /** \brief A class for dividing the set of MPI processes into worker groups.
190  *
191  * Each group works together on evaluations of the objective function.
192  * For more information, see @ref concepts.
193  */
194 
196  private:
197  MPI_Comm comm_world;
198  MPI_Comm comm_worker_groups;
199  MPI_Comm comm_group_leaders;
200  int N_procs_world;
201  int rank_world;
202  int N_procs_worker_groups;
203  int rank_worker_groups;
204  int N_procs_group_leaders;
205  int rank_group_leaders;
206  int worker_group;
207  bool proc0_world;
208  bool proc0_worker_groups;
209  int N_worker_groups;
210  bool initialized;
211 
212  void verify_initialized();
213  void print();
214  void write_line(std::ofstream&, int, std::string[], int[]);
215 
216  public:
217 
218  //! If true, information is printed to stdout that may be useful for debugging.
219  int verbose;
220 
221  //! Constructor
222  MPI_Partition();
223 
224  //! Destructor
225  ~MPI_Partition();
226 
227  //! Divide up a given "world" communicator into worker groups.
228  /**
229  * Normally this function is not called directly. Instead it is preferable to call
230  * mango::Problem::mpi_init(), since it sets the number of worker groups to 1 for optimization algorithms that
231  * do not support multiple worker groups.
232  *
233  * This subroutine creates the "worker groups" and "group leaders" communicators.
234  * @param[in] comm_world An MPI communicator consisting of all the processors that will be divided up into worker groups.
235  */
236  void init(MPI_Comm comm_world);
237 
238  //! Use a user-supplied partitioning of the MPI processes into worker groups.
239  /**
240  * Use either this subroutine or mango::MPI_Partition::init(), not both.
241  * @param[in] comm_world An MPI communicator consisting of all the processors that will be divided up into worker groups.
242  * @param[in] comm_group_leaders An MPI communicator consisting only of the group leaders.
243  * @param[in] comm_worker_groups An MPI communicator containing all the processors of comm_world,
244  * but with a separate "color" for each worker group. The processes with rank 0 in this communicator
245  * must be the same as the processes in <span class="paramname">comm_group_leaders</span>.
246  */
247  void set_custom(MPI_Comm comm_world, MPI_Comm comm_group_leaders, MPI_Comm comm_worker_groups);
248 
249  //! Get the MPI communicator for MANGO's world communicator.
250  /**
251  * For more information about MPI communicators, see @ref concepts.
252  * This function can only be called after calling mango::Problem::mpi_init(), mango::MPI_Partition::init(), or
253  * mango::MPI_Partition::set_custom(). Otherwise a C++ exception will be thrown.
254  * @return The MPI communicator for MANGO's world communicator.
255  */
256  MPI_Comm get_comm_world();
257 
258  //! Get the MPI communicator for MANGO's "worker groups" communicator.
259  /**
260  * For more information about MPI communicators, see @ref concepts.
261  * This function can only be called after calling mango::Problem::mpi_init(), mango::MPI_Partition::init(), or
262  * mango::MPI_Partition::set_custom(). Otherwise a C++ exception will be thrown.
263  * @return The MPI communicator for MANGO's "worker groups" communicator.
264  */
265  MPI_Comm get_comm_worker_groups();
266 
267  //! Get the MPI communicator for MANGO's "group leaders" communicator.
268  /**
269  * For more information about MPI communicators, see @ref concepts.
270  * This function can only be called after calling mango::Problem::mpi_init(), mango::MPI_Partition::init(), or
271  * mango::MPI_Partition::set_custom(). Otherwise a C++ exception will be thrown.
272  * @return The MPI communicator for MANGO's "group leaders" communicator.
273  */
274  MPI_Comm get_comm_group_leaders();
275 
276  //! Determine whether this MPI processor has rank 0 in MANGO's world communicator.
277  /**
278  * This function can only be called after calling mango::Problem::mpi_init(), mango::MPI_Partition::init(), or
279  * mango::MPI_Partition::set_custom(). Otherwise a C++ exception will be thrown.
280  * @return True if this MPI processor has rank 0 in MANGO's world communicator, false otherwise.
281  */
282  bool get_proc0_world();
283 
284  //! Determine whether this MPI processor has rank 0 in MANGO's "worker groups" communicator.
285  /**
286  * Equivalently, this function determines whether this MPI processor is a group leader.
287  *
288  * This function can only be called after calling mango::Problem::mpi_init(), mango::MPI_Partition::init(), or
289  * mango::MPI_Partition::set_custom(). Otherwise a C++ exception will be thrown.
290  * @return True if this MPI processor has rank 0 in MANGO's "worker groups" communicator, false otherwise.
291  */
293 
294  //! Get the MPI rank of this processor in MANGO's world communicator.
295  /**
296  * For more information about MPI communicators, see @ref concepts.
297  * This function can only be called after calling mango::Problem::mpi_init(), mango::MPI_Partition::init(), or
298  * mango::MPI_Partition::set_custom(). Otherwise a C++ exception will be thrown.
299  * @return The MPI rank of this processor in MANGO's world communicator.
300  */
301  int get_rank_world();
302 
303  //! Get the MPI rank of this processor in MANGO's "worker groups" communicator.
304  /**
305  * For more information about MPI communicators, see @ref concepts.
306  * This function can only be called after calling mango::Problem::mpi_init(), mango::MPI_Partition::init(), or
307  * mango::MPI_Partition::set_custom(). Otherwise a C++ exception will be thrown.
308  * @return The MPI rank of this processor in MANGO's "worker groups" communicator.
309  */
311 
312  //! Get the MPI rank of this processor in MANGO's "group leaders" communicator.
313  /**
314  * For more information about MPI communicators, see @ref concepts.
315  * This function can only be called after calling mango::Problem::mpi_init(), mango::MPI_Partition::init(), or
316  * mango::MPI_Partition::set_custom(). Otherwise a C++ exception will be thrown.
317  * @return The MPI rank of this processor in MANGO's "group leaders" communicator.
318  */
320 
321  //! Get the number of processors in MANGO's world communicator.
322  /**
323  * For more information about MPI communicators, see @ref concepts.
324  * This function can only be called after calling mango::Problem::mpi_init(), mango::MPI_Partition::init(), or
325  * mango::MPI_Partition::set_custom(). Otherwise a C++ exception will be thrown.
326  * @return The number of processors in MANGO's world communicator.
327  */
328  int get_N_procs_world();
329 
330  //! Get the number of processors in MANGO's "worker groups" communicator.
331  /**
332  * For more information about MPI communicators, see @ref concepts.
333  * This function can only be called after calling mango::Problem::mpi_init(), mango::MPI_Partition::init(), or
334  * mango::MPI_Partition::set_custom(). Otherwise a C++ exception will be thrown.
335  * @return The number of processors in MANGO's "worker groups" communicator.
336  */
338 
339  //! Get the number of processors in MANGO's "group leaders" communicator.
340  /**
341  * For more information about MPI communicators, see @ref concepts.
342  * This function can only be called after calling mango::Problem::mpi_init(), mango::MPI_Partition::init(), or
343  * mango::MPI_Partition::set_custom(). Otherwise a C++ exception will be thrown.
344  * @return The number of processors in MANGO's "group leaders" communicator.
345  * This number is the same as the number of worker groups.
346  */
348 
349  //! Returns an integer indicating the worker group to which this MPI process belongs.
350  /**
351  * This function can only be called after calling mango::Problem::mpi_init(), mango::MPI_Partition::init(), or
352  * mango::MPI_Partition::set_custom(). Otherwise a C++ exception will be thrown.
353  * @return An integer indicating the worker group to which this MPI process belongs.
354  */
355  int get_worker_group();
356 
357  //! Returns the number of worker groups.
358  /**
359  * @return The number of worker groups.
360  */
361  int get_N_worker_groups();
362 
363  //! Set the number of worker groups to the given integer.
364  /**
365  * Except when using a custom partition, this method must be
366  * called before any of the 'get' methods or before using the
367  * MPI_Partition for an optimization. This method does not need to
368  * be called when using a custom partition.
369  * @param[in] N_worker_groups The desired number of worker groups
370  */
371  void set_N_worker_groups(int N_worker_groups);
372 
373  //! Write a file with the given filename, showing the worker group assignments and rank of each process in each communicator.
374  /**
375  * @param[in] filename The name of the file in which to write the MPI data. If the file already exists, it will be over-written.
376  */
377  void write(std::string filename);
378 
379  //! Tell the worker MPI processes (i.e. those that are not group leaders) that the optimization problem is complete.
380  /**
381  * This subroutine should only be called by group leaders.
382  * This subroutine is typically called immediately after mango::Problem::optimize().
383  * You can see typical usage of this subroutine in the examples. However you are also free to
384  * use your own approach to stopping the worker processes instead of this subroutine.
385  */
386  void stop_workers();
387 
388  //! Tell the worker MPI processes (i.e. those that are not group leaders) to begin an evaluation of the objective function.
389  /**
390  * This subroutine should only be called by group leaders.
391  * This subroutine is typically called at the beginning of the user-supplied subroutine for the objective function.
392  * You can see typical usage of this subroutine in the examples. However you are also free to
393  * use your own approach to controlling the worker processes instead of this subroutine.
394  */
395  void mobilize_workers();
396 
397  //! For an MPI worker, determine whether to carry out another evaluation of the objective function or exit.
398  /**
399  * This subroutine should only be called on MPI processors that are not group leaders.
400  * You can see typical usage of this subroutine in the examples. However you are also free to
401  * use your own approach to controlling the worker processes instead of this subroutine.
402  * @return If true, this processor should help to evaluate the objective function. If false, the optimization has been completed,
403  * so this processor can move on.
404  */
405  bool continue_worker_loop();
406  };
407 
408  //////////////////////////////////////////////////////////////////////////////////////
409  // Items specific to an optimization problem
410 
411  class Problem;
412 
413  //! Format for the user-supplied subroutine that computes the objective function for a general (non least-squares) optimization problem
414  /**
415  * @param[in] N_parameters The number of independent variables, i.e. the dimension of the search space.
416  * @param[in] state_vector An array of size <span class="paramname">N_parameters</span> containing the values of the indpendent variables.
417  * @param[out] objective_value The subroutine must set this variable to the value of the objective function.
418  * @param[out] failed Set the value pointed to by this variable to 1 if the calculation of the objective function fails for some reason.
419  * Otherwise the value should be 0.
420  * @param[in] problem A pointer to the class representing this optimization problem. This pointer can be useful for
421  * getting information about the MPI communicators.
422  * @param[in] user_data Pointer to user-supplied data, which can be set by mango::Problem::set_user_data().
423  */
424  typedef void (*objective_function_type)(int* N_parameters, const double* state_vector, double* objective_value, int* failed, mango::Problem* problem, void* user_data);
425 
426  //! Format for the user-supplied subroutine that computes the residuals for a least-squares optimization problem
427  /**
428  * @param[in] N_parameters The number of independent variables, i.e. the dimension of the search space.
429  * @param[in] state_vector An array of size <span class="paramname">N_parameters</span> containing the values of the indpendent variables.
430  * @param[in] N_terms The number of least-squares terms that are summed in the total objective function, i.e. the number of residuals.
431  * @param[in] residuals An array of size <span class="paramname">N_terms</span> which must be set to the residuals, denoted \f$ R_j \f$
432  * on @ref concepts.
433  * @param[out] failed Set the value pointed to by this variable to 1 if the calculation of the residuals fails for some reason.
434  * Otherwise the value should be 0.
435  * @param[in] problem A pointer to the class representing this optimization problem. This pointer can be useful for
436  * getting information about the MPI communicators.
437  * @param[in] user_data Pointer to user-supplied data, which can be set by mango::Problem::set_user_data().
438  */
439  typedef void (*vector_function_type)(int* N_parameters, const double* state_vector, int* N_terms, double* residuals, int* failed, mango::Problem* problem, void* user_data);
440 
441  class Solver;
442  class Problem {
443  friend class Solver;
444  protected:
445  // Many implementation details are hidden in the Solver class, so users see only the interface provided by Problem.
447 
448  public:
450 
451  //! Constructor for a standard optimization problem
452  /**
453  * @param[in] N_parameters Number of independent variables.
454  * @param[in] state_vector An array of size <span class="paramname">N_parameters</span>, giving the initial values of the independent variables.
455  * @param[in] objective_function The objective function to minimize.
456  * @param[in] argc (Optional) A number of arguments. Used to pass options to some optimization libraries.
457  * @param[in] argv (Optional) An array of arguments. Used to pass options to some optimization libraries.
458  */
459  Problem(int N_parameters, double* state_vector, objective_function_type objective_function, int argc, char** argv); // For non-least-squares problems
460 
461  //! Destructor
462  ~Problem();
463 
464  //! Initialize MANGO's internal MPI data that describes the partitioning of the processes into worker groups.
465  /**
466  * This subroutine divides up the available MPI processes into worker groups, after checking to see
467  * if the selected optimization algorithm supports concurrent function evaluations.
468  * Do not confuse this subroutine with MPI_Init, the routine from MPI that initializes MPI itself!
469  * mango_mpi_init must be called by the driver code after the call to MPI_Init.
470  * This subroutine should be called after setting N_worker_groups and setting the optimization algorithm.
471  * This way, MANGO can change N_worker_groups to 1 if an algorithm is chosen that does not support concurrent function evaluations.
472  * @param[in] mpi_comm The MPI communicator to use for the optimization. Usually this is MPI_COMM_WORLD. However,
473  * if you want to run the optimization on a subset of MPI_COMM_WORLD, you can supply the appropriate communicator instead.
474  */
475  void mpi_init(MPI_Comm mpi_comm);
476 
477  //! Sets the optimization algorithm
478  /**
479  * Note the related subroutine of the same name that takes a std::string as input.
480  * @param[in] algorithm One of the enumerated constants representing optimization algorithms.
481  * If this supplied integer is too large or too small, a C++ exception will be thrown.
482  */
483  void set_algorithm(algorithm_type algorithm);
484 
485  //! Sets the optimization algorithm
486  /**
487  * Note the related subroutine of the same name that takes a mango::algorithm_type as input.
488  * @param[in] algorithm_str A lowercase string containing one of the available algorithms, e.g. "petsc_nm".
489  * If the string supplied does not match any of the available algorithms, a C++ exception will be thrown.
490  */
491  void set_algorithm(std::string algorithm_str);
492 
493  //! Reads in the number of worker groups and algorithm from a file.
494  /**
495  * This subroutine is used in the examples, so the testing framework can vary the number of worker groups and optimization algorithm.
496  * @param[in] filename The filename of the file to read.
497  */
498  void read_input_file(std::string filename);
499 
500  //! Sets the name of the output file that will record values of the objective function at each evaluation.
501  /**
502  * @param[in] filename A string giving the filename to use for the output file. If the file already exists, it will be over-written.
503  */
504  void set_output_filename(std::string filename);
505 
506  //! Sets bound constraints for the optimization problem.
507  /**
508  * @param[in] lower An array of lower bounds, corresponding to
509  * the vector of independent parameters. It is
510  * assumed that an array of size N_parameters has
511  * been properly allocated.
512  * @param[in] upper An array of upper bounds, corresponding to
513  * the vector of independent parameters. It is
514  * assumed that an array of size N_parameters has
515  * been properly allocated.
516  */
517  void set_bound_constraints(double* lower, double* upper);
518 
519  //! Solve the optimization problem that has been set up.
520  /**
521  * This is the main computationally demanding step.
522  * @return The minimum value found for the objective function.
523  */
524  double optimize();
525 
526  //! Get the number of independent variables for an optimization problem.
527  /*
528  * @return The number of independent variables, i.e. the dimensionality of the parameter space.
529  */
530  int get_N_parameters();
531 
532  //! For an optimization problem that has already been solved, return the index of the function evaluation corresponding to the optimum.
533  /**
534  * @return The index of the function evaluation corresponding to the optimum.
535  * If mango::Problem::optimize() has not yet been called, a value of -1 will be returned.
536  */
538 
539  //! For an optimization problem that has already been solved, return the number of times the objective function was evaluated.
540  /**
541  * @return The number of times the objective function was evaluated.
542  * If \ref mango_optimize has not yet been called, a value of 0 will be returned.
543  */
545 
546  //! Get the vector of independent variables.
547  /**
548  * If mango::Problem::optimize() has not yet been called, this vector corresponds to the initial condition.
549  * If mango::Problem::optimize() has been called, this vector corresponds to the location of the optimum that was found.
550  * @return A pointer to the vector of length N_parameters storing the independent variables.
551  */
552  double* get_state_vector();
553 
554  //! Control whether 1-sided or centered finite differences will be used to compute derivatives of the objective function.
555  /**
556  * @param centered_differences If true, centered differences will be used. If false, 1-sided differences will be used.
557  * Centered differences are more accurate, but require more function evaluations (2*N_parameters) compared to
558  * 1-sided differences (which require N_parameters+1 evaluations).
559  */
560  void set_centered_differences(bool centered_differences);
561 
562  //! Set an absolute step size for finite difference derivatives.
563  /**
564  * @param[in] finite_difference_step_size An absolute step size to use for finite difference derivatives.
565  */
566  void set_finite_difference_step_size(double finite_difference_step_size);
567 
568  //! Set the maximum number of evaluations of the objective function that will be allowed before the optimization is terminated.
569  /**
570  * @param[in] N The maximum number of evaluations of the objective function that will be allowed before the optimization is terminated.
571  * If this number is less than 1, a C++ exception will be thrown.
572  */
573  void set_max_function_evaluations(int N);
574 
575  //! Control how much diagnostic information is printed by MANGO.
576  /**
577  * This diagnostic information may be helpful for debugging.
578  * @param[in] verbose If <= 0, no diagnostic information will be printed. If >0, diagnostic information will be printed.
579  */
580  void set_verbose(int verbose);
581 
582  //! Sets the name of the output file that will record values of the objective function at each evaluation.
583  /**
584  * @param[in] filename A string giving the filename to use for the output file. If the file already exists, it will be over-written.
585  */
586  void set_output_filename(std::string& filename);
587 
588  //! Pass the prescribed pointer to the objective function whenever it is called.
589  /**
590  * This method allows any data structure to be passed to the objective function.
591  * @param[in] user_data A pointer to any data (you can cast any pointer to type void*).
592  */
593  void set_user_data(void* user_data);
594 
595  //! Impose bound constraints on an optimization problem, with the bounds chosen as multiples of the initial state vector.
596  /**
597  * To use this subroutine, you must first call mango::Problem::set_bound_constraints, so MANGO has pointers to the
598  * arrays allocted by the user for lower and upper bounds. mango::Problem::set_relative_bound_constraints will overwrite the entries of these arrays.
599  *
600  * There are two possible methods of determining the bound constraints using this subroutine, depending
601  * on the parameter preserve_sign.
602  *
603  * If preserve_sign is false, the bounds will be symmetric about 0, given by the value
604  * of the initial condition multiplied by max_factor, expanded to be at least min_radius different from
605  * the initial condition. Thus, for independent
606  * variable \f$ x_j \f$, the bounds will be \f$ x_j \in [-R_j, R_j] \f$, where
607  * \f$ R_j = \max(\mathtt{min\_radius}, |x_j| \mathtt{max\_factor})\f$.
608  * Note that the parameter min_factor is not used in this case.
609  *
610  * If preserve_sign is true, the lower and upper bounds for a given independent variable
611  * will have the same sign as the corresponding element of state_vector (the initial condition supplied to the constructor).
612  * The bounds are determined by multiplying each independent variable by min_factor and max_factor, keeping
613  * both bounds at least min_radius from the initial condition (while not crossing 0).
614  * Thus, if independent variable \f$ x_j \f$ is positive, the bounds will be \f$ x_j \in [L_j, R_j] \f$ where
615  * \f$ L_j = \max(0, \min(x_j - \mathtt{min\_radius}, x_j \, \mathtt{min\_factor})) \f$ and
616  * \f$ R_j = \max(x_j + \mathtt{min\_radius}, x_j \, \mathtt{max\_factor}) \f$.
617  * If independent variable \f$ x_j \f$ is negative, the bounds will be \f$ x_j \in [L_j, R_j] \f$ where
618  * \f$ L_j = \min(x_j - \mathtt{min\_radius}, x_j \, \mathtt{max\_factor}) \f$ and
619  * \f$ R_j = \min(0, \max(x_j + \mathtt{min\_radius}, x_j \, \mathtt{min\_factor})) \f$.
620  * For the special case \f$x_j=0\f$, then the bounds are \f$ x_j \in [-\mathtt{min\_radius}, \mathtt{min\_radius}] \f$.
621  *
622  * Note that not every optimization algorithm allows bound constraints. If bound constraints
623  * have been turned on with this subroutine and mango::Problem::optimize is called,
624  * MANGO will check whether the selected algorithm supports bound constraints. If not,
625  * a warning message will be printed to stdout, and the optimization will proceed,
626  * ignoring the bound constraints.
627  * @param min_factor See description above. The value must lie in [0,1] or else a C++ exception will be thrown.
628  * @param max_factor See description above. The value must be \f$ \ge 1 \f$, or else a C++ expection will be thrown.
629  * @param min_radius See description above. The value must be \f$ \ge 0 \f$, or else a C++ exception will be thrown.
630  * @param preserve_sign See description above.
631  */
632  void set_relative_bound_constraints(double min_factor, double max_factor, double min_radius, bool preserve_sign);
633 
634  //! Sets the number of points considered as a set for parallel line searches
635  /**
636  * The default value is 0.
637  * If the value is \f$\le 0\f$, the number will be set to the number of worker groups.
638  * Normally this default is the best choice, in terms of load balancing. However you may occasionally
639  * wish to set the number of points in a line search to some other value, particularly for tests
640  * involving parallelization.
641  * @param N_line_search The number of points considered as a set for parallel line searches.
642  */
643  void set_N_line_search(int N_line_search);
644 
645  //! Get the Solver object associated with the optimization problem.
646  /**
647  * Users generally should not need this method.
648  * @return The Solver object associated with the optimization problem.
649  */
650  Solver* get_solver();
651  };
652 
653 
654  //////////////////////////////////////////////////////////////////////////////////////
655  // A least-squares problem is a subclass of Problem
656 
657  class Least_squares_solver;
659  private:
660  // Many implementation details are hidden in the Least_squares_solver class, so users see only the interface provided by Least_squares_problem.
661  Least_squares_solver* least_squares_solver;
662 
663  public:
664  //! Constructor for a least-squares optimization problem
665  /**
666  * @param[in] N_parameters Number of independent variables.
667  * @param[in] state_vector An array of size <span class="paramname">N_parameters</span>, giving the initial values of the independent variables.
668  * @param[in] N_terms The number of least-squares terms that are summed to form the total objective function.
669  * @param[in] targets An array of size <span class="paramname">N_terms</span>, containing the target values \f$ T_j \f$ in @ref concepts.
670  * @param[in] sigmas An array of size <span class="paramname">N_terms</span>, containing the weights \f$ \sigma_j \f$ in @ref concepts.
671  * @param[in] best_residual_function An array of size <span class="paramname">N_terms</span>, which will be used to store the
672  * values of the residuals \f$ R_j \f$ at the optimum.
673  * @param[in] residual_function The user-supplied subroutine that computes the residuals \f$ R_j \f$.
674  * @param[in] argc (Optional) A number of arguments. Used to pass options to some optimization libraries.
675  * @param[in] argv (Optional) An array of arguments. Used to pass options to some optimization libraries.
676  */
677  Least_squares_problem(int N_parameters, double* state_vector, int N_terms, double* targets, double* sigmas, double* best_residual_function, vector_function_type residual_function, int argc, char** argv);
678 
679  //! Destructor
681 
682  //! Return the number of least-squares terms that are summed to form the objective function.
683  /*
684  * @return The number of least-squares terms that are summed to form the objective function.
685  */
686  int get_N_terms();
687 
688  //! Determine whether or not to print each individual residual in the MANGO output file.
689  /**
690  * You may wish to print this information to see the relative magnitude of each term
691  * in the objective function. On the other hand, for problems with many terms, you may
692  * wish to suppress this information to make the file more readable.
693  *
694  * @param[in] print Whether or not to print every residual term in the output file.
695  */
696  void set_print_residuals_in_output_file(bool print);
697  };
698 }
699 
700 #endif
mango::NUM_PACKAGES
@ NUM_PACKAGES
Not an actual package, just counting.
Definition: mango.hpp:45
mango::MPI_Partition::set_N_worker_groups
void set_N_worker_groups(int N_worker_groups)
Set the number of worker groups to the given integer.
Definition: mpi_partition.cpp:106
mango::GSL_CONJUGATE_PR
@ GSL_CONJUGATE_PR
Definition: mango.hpp:113
mango::NLOPT_LD_CCSAQ
@ NLOPT_LD_CCSAQ
Definition: mango.hpp:98
mango::algorithm_properties
Some properties of each algorithm that MANGO is aware of.
Definition: mango.hpp:58
mango::NLOPT_LN_NELDERMEAD
@ NLOPT_LN_NELDERMEAD
Definition: mango.hpp:95
mango::package_type
package_type
The list of packages, i.e. libraries that MANGO can call to perform optimization.
Definition: mango.hpp:36
mango::NLOPT_LD_MMA
@ NLOPT_LD_MMA
Definition: mango.hpp:97
mango::GSL_DDOGLEG
@ GSL_DDOGLEG
Definition: mango.hpp:110
mango::NLOPT_GN_DIRECT_L_NOSCAL
@ NLOPT_GN_DIRECT_L_NOSCAL
Definition: mango.hpp:87
mango::Problem::set_N_line_search
void set_N_line_search(int N_line_search)
Sets the number of points considered as a set for parallel line searches.
Definition: Problem.cpp:176
mango::Problem::solver
Solver * solver
Definition: mango.hpp:446
mango::MPI_Partition::stop_workers
void stop_workers()
Tell the worker MPI processes (i.e. those that are not group leaders) that the optimization problem i...
Definition: mpi_partition.cpp:111
mango::Least_squares_problem::set_print_residuals_in_output_file
void set_print_residuals_in_output_file(bool print)
Determine whether or not to print each individual residual in the MANGO output file.
Definition: Least_squares_problem.cpp:61
mango::NLOPT_LN_PRAXIS
@ NLOPT_LN_PRAXIS
Definition: mango.hpp:94
mango::algorithm_properties::parallel
bool parallel
Whether the algorithm can support concurrent evaluations of the objective function....
Definition: mango.hpp:63
mango::PETSC_POUNDERS
@ PETSC_POUNDERS
Definition: mango.hpp:81
mango::MPI_Partition::get_comm_world
MPI_Comm get_comm_world()
Get the MPI communicator for MANGO's world communicator.
Definition: mpi_partition.cpp:41
mango::NLOPT_LD_VAR1
@ NLOPT_LD_VAR1
Definition: mango.hpp:105
mango::MPI_Partition::get_proc0_worker_groups
bool get_proc0_worker_groups()
Determine whether this MPI processor has rank 0 in MANGO's "worker groups" communicator.
Definition: mpi_partition.cpp:61
mango::get_algorithm
bool get_algorithm(std::string name, algorithm_type *algorithm_int)
Returns the integer (enum) for an optimization algorithm associated with its string name.
Definition: algorithms.cpp:49
mango::NLOPT_LD_SLSQP
@ NLOPT_LD_SLSQP
Definition: mango.hpp:99
mango::MPI_Partition::~MPI_Partition
~MPI_Partition()
Destructor.
Definition: mpi_partition.cpp:32
mango::MPI_Partition::get_comm_group_leaders
MPI_Comm get_comm_group_leaders()
Get the MPI communicator for MANGO's "group leaders" communicator.
Definition: mpi_partition.cpp:51
mango::Problem::get_N_parameters
int get_N_parameters()
Get the number of independent variables for an optimization problem.
Definition: Problem.cpp:42
mango::Problem::set_user_data
void set_user_data(void *user_data)
Pass the prescribed pointer to the objective function whenever it is called.
Definition: Problem.cpp:85
mango::NLOPT_LD_TNEWTON_RESTART
@ NLOPT_LD_TNEWTON_RESTART
Definition: mango.hpp:103
mango::algorithm_properties::package
package_type package
The optimization library that the algorithm belongs to.
Definition: mango.hpp:60
mango::does_algorithm_exist
bool does_algorithm_exist(std::string algorithm_name)
Checks whether or not a string corresponds to the name of one of the optimization algorithms known by...
Definition: algorithms.cpp:72
mango::Least_squares_solver
Definition: Least_squares_solver.hpp:28
mango::Problem::mpi_partition
MPI_Partition mpi_partition
Definition: mango.hpp:449
mango::algorithm_type
algorithm_type
A list of the algorithms that MANGO can potentially use.
Definition: mango.hpp:75
mango::NLOPT_LD_TNEWTON
@ NLOPT_LD_TNEWTON
Definition: mango.hpp:104
mango::GSL_DOGLEG
@ GSL_DOGLEG
Definition: mango.hpp:109
mango::NLOPT_GN_CRS2_LM
@ NLOPT_GN_CRS2_LM
Definition: mango.hpp:91
mango::MPI_Partition::get_worker_group
int get_worker_group()
Returns an integer indicating the worker group to which this MPI process belongs.
Definition: mpi_partition.cpp:96
mango::NLOPT_GN_DIRECT_L
@ NLOPT_GN_DIRECT_L
Definition: mango.hpp:84
mango::NLOPT_GN_DIRECT_NOSCAL
@ NLOPT_GN_DIRECT_NOSCAL
Definition: mango.hpp:86
mango::algorithms
const algorithm_properties algorithms[NUM_ALGORITHMS]
A database of the algorithms that MANGO is aware of, including various properties of each algorithm.
Definition: mango.hpp:124
mango::MANGO_IMFIL
@ MANGO_IMFIL
Definition: mango.hpp:79
mango::Problem::set_max_function_evaluations
void set_max_function_evaluations(int N)
Set the maximum number of evaluations of the objective function that will be allowed before the optim...
Definition: Problem.cpp:72
mango::Problem::set_verbose
void set_verbose(int verbose)
Control how much diagnostic information is printed by MANGO.
Definition: Problem.cpp:77
mango::MPI_Partition::set_custom
void set_custom(MPI_Comm comm_world, MPI_Comm comm_group_leaders, MPI_Comm comm_worker_groups)
Use a user-supplied partitioning of the MPI processes into worker groups.
Definition: mpi_partition_set_custom.cpp:24
mango::Problem::get_best_function_evaluation
int get_best_function_evaluation()
For an optimization problem that has already been solved, return the index of the function evaluation...
Definition: Problem.cpp:46
mango::MPI_Partition::MPI_Partition
MPI_Partition()
Constructor.
Definition: mpi_partition.cpp:25
mango::PACKAGE_PETSC
@ PACKAGE_PETSC
Definition: mango.hpp:43
mango::PACKAGE_HOPSPACK
@ PACKAGE_HOPSPACK
Definition: mango.hpp:39
mango::Problem::set_algorithm
void set_algorithm(algorithm_type algorithm)
Sets the optimization algorithm.
Definition: algorithms.cpp:25
mango::vector_function_type
void(* vector_function_type)(int *N_parameters, const double *state_vector, int *N_terms, double *residuals, int *failed, mango::Problem *problem, void *user_data)
Format for the user-supplied subroutine that computes the residuals for a least-squares optimization ...
Definition: mango.hpp:439
mango::Problem::set_output_filename
void set_output_filename(std::string filename)
Sets the name of the output file that will record values of the objective function at each evaluation...
Definition: Problem.cpp:81
mango::algorithm_properties::requires_bound_constraints
bool requires_bound_constraints
Whether the algorithm requires maximum and minimum values (a.k.a. box constraints) to be imposed on t...
Definition: mango.hpp:65
mango::PACKAGE_MANGO
@ PACKAGE_MANGO
Definition: mango.hpp:40
mango::Least_squares_problem
Definition: mango.hpp:658
mango::Problem::get_state_vector
double * get_state_vector()
Get the vector of independent variables.
Definition: Problem.cpp:50
mango::NLOPT_LN_SBPLX
@ NLOPT_LN_SBPLX
Definition: mango.hpp:96
mango::Problem::set_centered_differences
void set_centered_differences(bool centered_differences)
Control whether 1-sided or centered finite differences will be used to compute derivatives of the obj...
Definition: Problem.cpp:64
mango::Least_squares_problem::Least_squares_problem
Least_squares_problem(int N_parameters, double *state_vector, int N_terms, double *targets, double *sigmas, double *best_residual_function, vector_function_type residual_function, int argc, char **argv)
Constructor for a least-squares optimization problem.
Definition: Least_squares_problem.cpp:27
mango::algorithm_properties::allows_bound_constraints
bool allows_bound_constraints
Whether the algorithm allows maximum and minimum values (a.k.a. box constraints) to be imposed on the...
Definition: mango.hpp:64
mango::NLOPT_LN_COBYLA
@ NLOPT_LN_COBYLA
Definition: mango.hpp:92
mango::GSL_LM
@ GSL_LM
Definition: mango.hpp:108
mango::MPI_Partition::get_rank_group_leaders
int get_rank_group_leaders()
Get the MPI rank of this processor in MANGO's "group leaders" communicator.
Definition: mpi_partition.cpp:76
mango::Problem::set_finite_difference_step_size
void set_finite_difference_step_size(double finite_difference_step_size)
Set an absolute step size for finite difference derivatives.
Definition: Problem.cpp:68
mango::MPI_Partition::init
void init(MPI_Comm comm_world)
Divide up a given "world" communicator into worker groups.
Definition: mpi_partition_init.cpp:24
mango::MANGO_LEVENBERG_MARQUARDT
@ MANGO_LEVENBERG_MARQUARDT
Definition: mango.hpp:78
mango::MPI_Partition::get_N_procs_group_leaders
int get_N_procs_group_leaders()
Get the number of processors in MANGO's "group leaders" communicator.
Definition: mpi_partition.cpp:91
mango::MPI_Partition::get_N_procs_worker_groups
int get_N_procs_worker_groups()
Get the number of processors in MANGO's "worker groups" communicator.
Definition: mpi_partition.cpp:86
mango::NLOPT_LN_BOBYQA
@ NLOPT_LN_BOBYQA
Definition: mango.hpp:93
mango::MPI_Partition::get_rank_world
int get_rank_world()
Get the MPI rank of this processor in MANGO's world communicator.
Definition: mpi_partition.cpp:66
mango::Problem::get_solver
Solver * get_solver()
Get the Solver object associated with the optimization problem.
Definition: Problem.cpp:180
mango::objective_function_type
void(* objective_function_type)(int *N_parameters, const double *state_vector, double *objective_value, int *failed, mango::Problem *problem, void *user_data)
Format for the user-supplied subroutine that computes the objective function for a general (non least...
Definition: mango.hpp:424
mango::NLOPT_LD_LBFGS
@ NLOPT_LD_LBFGS
Definition: mango.hpp:100
mango::NLOPT_GN_ORIG_DIRECT
@ NLOPT_GN_ORIG_DIRECT
Definition: mango.hpp:89
mango
This C++ namespace contains everything related to MANGO.
Definition: Imfil.hpp:7
mango::NUMBER_FOR_FAILED
const double NUMBER_FOR_FAILED
A large finite number.
Definition: mango.hpp:52
mango::GSL_SUBSPACE2D
@ GSL_SUBSPACE2D
Definition: mango.hpp:111
mango::NLOPT_LD_TNEWTON_PRECOND_RESTART
@ NLOPT_LD_TNEWTON_PRECOND_RESTART
Definition: mango.hpp:101
mango::PACKAGE_NLOPT
@ PACKAGE_NLOPT
Definition: mango.hpp:41
mango::NLOPT_GN_DIRECT
@ NLOPT_GN_DIRECT
Definition: mango.hpp:83
mango::GSL_NM
@ GSL_NM
Definition: mango.hpp:115
mango::GSL_BFGS
@ GSL_BFGS
Definition: mango.hpp:114
mango::MPI_Partition::get_proc0_world
bool get_proc0_world()
Determine whether this MPI processor has rank 0 in MANGO's world communicator.
Definition: mpi_partition.cpp:56
mango::Solver
Definition: Solver.hpp:31
mango::algorithm_properties::uses_derivatives
bool uses_derivatives
Whether the algorithm requires derivatives of the objective function or residuals to be supplied.
Definition: mango.hpp:62
mango::MPI_Partition::get_N_worker_groups
int get_N_worker_groups()
Returns the number of worker groups.
Definition: mpi_partition.cpp:101
mango::GSL_CONJUGATE_FR
@ GSL_CONJUGATE_FR
Definition: mango.hpp:112
mango::MPI_Partition::get_rank_worker_groups
int get_rank_worker_groups()
Get the MPI rank of this processor in MANGO's "worker groups" communicator.
Definition: mpi_partition.cpp:71
mango::PETSC_BRGN
@ PETSC_BRGN
Definition: mango.hpp:82
mango::MPI_Partition::verbose
int verbose
If true, information is printed to stdout that may be useful for debugging.
Definition: mango.hpp:219
mango::NLOPT_GN_DIRECT_L_RAND_NOSCAL
@ NLOPT_GN_DIRECT_L_RAND_NOSCAL
Definition: mango.hpp:88
mango::Problem::Problem
Problem(int N_parameters, double *state_vector, objective_function_type objective_function, int argc, char **argv)
Constructor for a standard optimization problem.
Definition: Problem.cpp:27
mango::algorithm_properties::name
std::string name
A short string with the algorithm's name, e.g. 'petsc_pounders' or 'hopspack'.
Definition: mango.hpp:59
mango::MPI_Partition::get_comm_worker_groups
MPI_Comm get_comm_worker_groups()
Get the MPI communicator for MANGO's "worker groups" communicator.
Definition: mpi_partition.cpp:46
mango::Problem::mpi_init
void mpi_init(MPI_Comm mpi_comm)
Initialize MANGO's internal MPI data that describes the partitioning of the processes into worker gro...
Definition: Problem.cpp:90
mango::NLOPT_LD_VAR2
@ NLOPT_LD_VAR2
Definition: mango.hpp:106
mango::algorithm_properties::least_squares
bool least_squares
Whether or not the algorithm assumes the objective function has least-squares form.
Definition: mango.hpp:61
mango::Least_squares_problem::~Least_squares_problem
~Least_squares_problem()
Destructor.
Definition: Least_squares_problem.cpp:55
mango::Problem::set_relative_bound_constraints
void set_relative_bound_constraints(double min_factor, double max_factor, double min_radius, bool preserve_sign)
Impose bound constraints on an optimization problem, with the bounds chosen as multiples of the initi...
Definition: Problem.cpp:126
mango::NLOPT_GN_DIRECT_L_RAND
@ NLOPT_GN_DIRECT_L_RAND
Definition: mango.hpp:85
mango::NLOPT_GN_ORIG_DIRECT_L
@ NLOPT_GN_ORIG_DIRECT_L
Definition: mango.hpp:90
mango::Problem::get_function_evaluations
int get_function_evaluations()
For an optimization problem that has already been solved, return the number of times the objective fu...
Definition: Problem.cpp:54
mango::HOPSPACK
@ HOPSPACK
Definition: mango.hpp:107
mango::Problem::~Problem
~Problem()
Destructor.
Definition: Problem.cpp:37
mango::MPI_Partition::mobilize_workers
void mobilize_workers()
Tell the worker MPI processes (i.e. those that are not group leaders) to begin an evaluation of the o...
Definition: mpi_partition.cpp:118
mango::MPI_Partition::continue_worker_loop
bool continue_worker_loop()
For an MPI worker, determine whether to carry out another evaluation of the objective function or exi...
Definition: mpi_partition.cpp:125
mango::Least_squares_problem::get_N_terms
int get_N_terms()
Return the number of least-squares terms that are summed to form the objective function.
Definition: Least_squares_problem.cpp:65
mango::Problem::read_input_file
void read_input_file(std::string filename)
Reads in the number of worker groups and algorithm from a file.
Definition: read_input_file.cpp:25
mango::NLOPT_LD_TNEWTON_PRECOND
@ NLOPT_LD_TNEWTON_PRECOND
Definition: mango.hpp:102
mango::NUM_ALGORITHMS
@ NUM_ALGORITHMS
Not an actual algorithm, just counting.
Definition: mango.hpp:117
mango::PETSC_NM
@ PETSC_NM
Definition: mango.hpp:80
mango::Problem::optimize
double optimize()
Solve the optimization problem that has been set up.
Definition: Problem.cpp:119
mango::MPI_Partition::get_N_procs_world
int get_N_procs_world()
Get the number of processors in MANGO's world communicator.
Definition: mpi_partition.cpp:81
mango::MPI_Partition
A class for dividing the set of MPI processes into worker groups.
Definition: mango.hpp:195
mango::MPI_Partition::write
void write(std::string filename)
Write a file with the given filename, showing the worker group assignments and rank of each process i...
Definition: mpi_partition_print.cpp:51
mango::Problem::set_bound_constraints
void set_bound_constraints(double *lower, double *upper)
Sets bound constraints for the optimization problem.
Definition: Problem.cpp:58
mango::PACKAGE_GSL
@ PACKAGE_GSL
Definition: mango.hpp:42
mango::Problem
Definition: mango.hpp:442