trajopt
 All Classes Namespaces Files Functions Variables Typedefs Pages
optimizers.hpp
1 #pragma once
2 #include <string>
3 #include "modeling.hpp"
4 #include <boost/function.hpp>
5 /*
6  * Algorithms for non-convex, constrained optimization
7  */
8 
9 namespace sco {
10 
11 using std::string;
12 using std::vector;
13 
14 
15 enum OptStatus {
16  OPT_CONVERGED,
17  OPT_SCO_ITERATION_LIMIT, // hit iteration limit before convergence
18  OPT_PENALTY_ITERATION_LIMIT,
19  OPT_FAILED,
20  INVALID
21 };
22 static const char* OptStatus_strings[] = {
23  "CONVERGED",
24  "SCO_ITERATION_LIMIT",
25  "PENALTY_ITERATION_LIMIT",
26  "FAILED",
27  "INVALID"
28 };
29 inline string statusToString(OptStatus status) {
30  return OptStatus_strings[status];
31 }
32 
33 
34 struct OptResults {
35  DblVec x; // solution estimate
36  OptStatus status;
37  double total_cost;
38  vector<double> cost_vals;
39  DblVec cnt_viols;
40  int n_func_evals, n_qp_solves;
41  void clear() {
42  x.clear();
43  status = INVALID;
44  cost_vals.clear();
45  cnt_viols.clear();
46  n_func_evals = 0;
47  n_qp_solves = 0;
48  }
49  OptResults() {clear();}
50 };
51 std::ostream& operator<<(std::ostream& o, const OptResults& r);
52 
53 class Optimizer {
54  /*
55  * Solves an optimization problem
56  */
57 public:
58  virtual OptStatus optimize() = 0;
59  virtual ~Optimizer() {}
60  virtual void setProblem(OptProbPtr prob) {prob_ = prob;}
61  void initialize(const vector<double>& x);
62  vector<double>& x() {return results_.x;}
63  OptResults& results() {return results_;}
64 
65  typedef boost::function<void(OptProb*, DblVec&)> Callback;
66  void addCallback(const Callback& f); // called before each iteration
67 protected:
68  vector<Callback> callbacks_;
69  void callCallbacks(DblVec& x);
70  OptProbPtr prob_;
71  OptResults results_;
72 };
73 
75  /*
76  * Alternates between convexifying objectives and constraints and then solving convex subproblem
77  * Uses a merit function to decide whether or not to accept the step
78  * merit function = objective + merit_err_coeff * | constraint_error |
79  * Note: sometimes the convexified objectives and constraints lead to an infeasible subproblem
80  * In that case, you should turn them into penalties and solve that problem
81  * (todo: implement penalty-based sqp that gracefully handles infeasible constraints)
82  */
83 public:
84  double improve_ratio_threshold_, // minimum ratio true_improve/approx_improve to accept step
85  min_trust_box_size_, // if trust region gets any smaller, exit and report convergence
86  min_approx_improve_, // if model improves less than this, exit and report convergence
87  min_approx_improve_frac_, // if model improves less than this, exit and report convergence
88  max_iter_,
89  trust_shrink_ratio_, // if improvement is less than improve_ratio_threshold, shrink trust region by this ratio
90  trust_expand_ratio_, // see above
91  cnt_tolerance_, // after convergence of penalty subproblem, if constraint violation is less than this, we're done
92  max_merit_coeff_increases_, // number of times that we jack up penalty coefficient
93  merit_coeff_increase_ratio_, // ratio that we increate coeff each time
94  max_time_ // not yet implemented
95  ;
96  double merit_error_coeff_, // initial penalty coefficient
97  trust_box_size_ // current size of trust region (component-wise)
98  ;
99 
101  BasicTrustRegionSQP(OptProbPtr prob);
102  void setProblem(OptProbPtr prob);
103  OptStatus optimize();
104 protected:
105  void adjustTrustRegion(double ratio);
106  void setTrustBoxConstraints(const vector<double>& x);
107  void initParameters();
108  ModelPtr model_;
109 };
110 
111 
112 }