ilqgames
A new real-time solver for large-scale differential games.
constraint.h
1 /*
2  * Copyright (c) 2020, The Regents of the University of California (Regents).
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following
14  * disclaimer in the documentation and/or other materials provided
15  * with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Please contact the author(s) of this library if you have any questions.
34  * Authors: David Fridovich-Keil ( dfk@eecs.berkeley.edu )
35  */
36 
37 ///////////////////////////////////////////////////////////////////////////////
38 //
39 // Base class for all explicit (scalar-valued) constraints. These
40 // constraints are of the form: g(x) = 0 or g(x) <= 0 for some vector x.
41 //
42 // In addition to checking for satisfaction (and returning the constraint value
43 // g(x)), they also support computing first and second derivatives of the
44 // constraint value itself and the square of the constraint value, each scaled
45 // by lambda or mu respectively (from the augmented Lagrangian). That is, they
46 // compute gradients and Hessians of
47 // L(x, lambda, mu) = lambda * g(x) + mu * g(x) * g(x) / 2
48 //
49 ///////////////////////////////////////////////////////////////////////////////
50 
51 #ifndef ILQGAMES_CONSTRAINT_CONSTRAINT_H
52 #define ILQGAMES_CONSTRAINT_CONSTRAINT_H
53 
54 #include <ilqgames/cost/cost.h>
55 #include <ilqgames/utils/types.h>
56 
57 #include <glog/logging.h>
58 #include <memory>
59 #include <string>
60 
61 namespace ilqgames {
62 
63 class Constraint : public Cost {
64  public:
65  virtual ~Constraint() {}
66 
67  // Check if this constraint is satisfied, and optionally return the constraint
68  // value, which equals zero if the constraint is satisfied.
69  bool IsSatisfied(Time t, const VectorXf& input, float* level) const {
70  const float value = Evaluate(t, input);
71  if (level) *level = value;
72 
73  return IsSatisfied(value);
74  }
75  bool IsSatisfied(float level) const {
76  return (is_equality_) ? std::abs(level) <= constants::kSmallNumber
77  : level <= constants::kSmallNumber;
78  }
79 
80  // Evaluate this constraint value, i.e., g(x), and the augmented Lagrangian,
81  // i.e., lambda g(x) + mu g(x) g(x) / 2.
82  virtual float Evaluate(Time t, const VectorXf& input) const = 0;
83  float EvaluateAugmentedLagrangian(Time t, const VectorXf& input) const {
84  const float g = Evaluate(t, input);
85  const float lambda = lambdas_[TimeIndex(t)];
86  return lambda * g + 0.5 * Mu(lambda, g) * g * g;
87  }
88 
89  // Quadraticize the constraint value and its square, each scaled by lambda or
90  // mu, respectively (terms in the augmented Lagrangian).
91  virtual void Quadraticize(Time t, const VectorXf& input, MatrixXf* hess,
92  VectorXf* grad) const = 0;
93 
94  // Accessors and setters.
95  bool IsEquality() const { return is_equality_; }
96  float& Lambda(Time t) { return lambdas_[TimeIndex(t)]; }
97  float Lambda(Time t) const { return lambdas_[TimeIndex(t)]; }
98  void IncrementLambda(Time t, float value) {
99  const size_t kk = TimeIndex(t);
100  const float new_lambda = lambdas_[kk] + mu_ * value;
101  lambdas_[kk] = (is_equality_) ? new_lambda : std::max(0.0f, new_lambda);
102  }
103  void ScaleLambdas(float scale) {
104  for (auto& lambda : lambdas_) lambda *= scale;
105  }
106  static float& GlobalMu() { return mu_; }
107  static void ScaleMu(float scale) { mu_ *= scale; }
108  float Mu(Time t, const VectorXf& input) const {
109  const float g = Evaluate(t, input);
110  return Mu(Lambda(t), g);
111  }
112  float Mu(float lambda, float g) const {
113  if (!is_equality_ && g <= constants::kSmallNumber &&
114  std::abs(lambda) <= constants::kSmallNumber)
115  return 0.0;
116  return mu_;
117  }
118 
119  protected:
120  explicit Constraint(bool is_equality, const std::string& name)
121  : Cost(1.0, name),
122  is_equality_(is_equality),
123  lambdas_(time::kNumTimeSteps, constants::kDefaultLambda) {}
124 
125  // Modify derivatives to account for the multipliers and the quadratic term in
126  // the augmented Lagrangian. The inputs are the derivatives of g in the
127  // appropriate variables (assumed to be arbitrary coordinates of the input,
128  // here called x and y).
129  void ModifyDerivatives(Time t, float g, float* dx, float* ddx,
130  float* dy = nullptr, float* ddy = nullptr,
131  float* dxdy = nullptr) const;
132 
133  // Is this an equality constraint? If not, it is an inequality constraint.
134  bool is_equality_;
135 
136  // Multipliers, one per time step. Also a static augmented multiplier for an
137  // augmented Lagrangian.
138  std::vector<float> lambdas_;
139  static float mu_;
140 }; //\class Constraint
141 
142 } // namespace ilqgames
143 
144 #endif