SPIDAR API Library  0x16033101
Space Interface Device for Artificial Reality
QuadraticProgramming.hpp
Go to the documentation of this file.
1 
5 #ifndef SPIDAR_QUADRATIC_PROGRAMMING_HPP
6 #define SPIDAR_QUADRATIC_PROGRAMMING_HPP
7 
8 #include <cstdint>
9 
10 #include "GaussianElimination.hpp"
11 
12 namespace Spidar
13 {
14 namespace Math
15 {
19 template <class Traits>
21 {
22 public:
23  typedef typename Traits::ValueType ValueType;
24  typedef typename Traits::MatrixType MatrixType;
25  typedef typename Traits::VectorType VectorType;
26  typedef typename Traits::ActiveSetType ActiveSetType;
27 
28  static const int size(void) { return Traits::SIZE; }
29 
30  // コンストラクタ
32  {
33  Identity(identity_);
34  }
35 
36  //
37  // QP Main Function
38  // q: 目的関数の2次の係数行列
39  // c: 目的関数の1次の係数ベクトル
40  // x: 解 min < x < max
41  // min: xの最小値
42  // max: xの最大値
43  int solve(const MatrixType& q, const VectorType& c, VectorType& x, const VectorType& min, const VectorType& max)
44  {
45  // 初期化
46  initialize(x, min, max);
47 
48  // 繰り返し
49  for (int i=0; i<64; ++i)
50  {
51  updateMatrix(q, c);
52 
53  GaussianElimination::solve(matR_, vecL_, vecX_);
54 
55  checkResult();
56 
57  if (x==vecX_)
58  {
59  if(calcLambda()) return i;
60  }
61  else
62  {
63  calcAlpha(x);
64  }
65  }
66  return -1;
67  }
68 
69 private:
70 
71  //
72  void initialize(VectorType& x, const VectorType& min, const VectorType& max)
73  {
74  minX_ = VectorType() - min;
75  maxX_ = max;
76 
77  for (int i=0; i<size(); ++i)
78  {
79  x[i] = minX_[i];
80  activeSet_[i] = -1;
81  }
82  }
83 
84  //
85  void updateMatrix(const MatrixType& q, const VectorType& c)
86  {
87  for (int i=0; i<size(); ++i)
88  {
89  vecL_[i] = c[i];
90 
91  for (int j=0; j<size(); ++j)
92  {
93  if (activeSet_[j] > 0)
94  {
95  vecL_[i] -= q[i][j] * maxX_[i];
96  matR_[i][j] = identity_[i][j];
97  }
98  else if (activeSet_[j] < 0)
99  {
100  vecL_[i] += q[i][j] * minX_[i];
101  matR_[i][j] = -identity_[i][j];
102  }
103  else
104  {
105  matR_[i][j] = q[i][j];
106  }
107  }
108  }
109  }
110 
111  void checkResult(void)
112  {
113  for (int i=0; i<size(); ++i)
114  {
115  if (activeSet_[i] > 0)
116  {
117  vecY_[i] = vecX_[i];
118  vecX_[i] = maxX_[i];
119  }
120  else if (activeSet_[i] < 0)
121  {
122  vecY_[i] = vecX_[i];
123  vecX_[i] = -minX_[i];
124  }
125  else // activeSet_[i]==0
126  {
127  vecY_[i] = ValueType(0);
128  }
129  }
130  }
131 
132  //
133  bool calcLambda(void)
134  {
135  bool bval = true;
136 
137  for (int i=0; i<size(); ++i)
138  {
139  if (activeSet_[i]!=0)
140  {
141  if (vecY_[i]<0)
142  {
143  activeSet_[i] = 0;
144  bval = false;
145  }
146  }
147  }
148  return bval;
149  }
150 
151  //
152  void calcAlpha(VectorType& x)
153  {
154  int minIndex = -1, bval;
155  ValueType alpha, minAlpha = 1;
156 
157  for (int i=0; i<size(); ++i)
158  {
159  if (activeSet_[i]==0)
160  {
161  vecD_[i] = vecX_[i] - x[i];
162 
163  if (vecD_[i] < 0)
164  {
165  alpha = -(minX_[i] + x[i]) / vecD_[i];
166 
167  if (alpha > 0 && minAlpha > alpha)
168  {
169  minAlpha = alpha;
170  minIndex = i;
171  bval = -1;
172  }
173  else if (alpha <= 0)
174  {
175  activeSet_[i] = -1;
176  }
177  }
178  else if (vecD_[i] > 0)
179  {
180  alpha = (maxX_[i] - x[i]) / vecD_[i];
181 
182  if (alpha > 0 && minAlpha > alpha)
183  {
184  minAlpha = alpha;
185  minIndex = i;
186  bval = 1;
187  }
188  else if (alpha <= 0)
189  {
190  activeSet_[i] = 1;
191  }
192  }
193  }
194  }
195 
196  if (minIndex >= 0)
197  {
198  activeSet_[minIndex] = bval;
199 
200  for (int i=0; i<size(); ++i)
201  {
202  if (!activeSet_[i])
203  {
204  x[i] += minAlpha * vecD_[i];
205  }
206  }
207  }
208  else
209  {
210  for (int i=0; i<size(); ++i)
211  {
212  x[i] = vecX_[i];
213  }
214  }
215  }
216 
217  MatrixType identity_;
218  VectorType minX_;
219  VectorType maxX_;
220 
221  MatrixType matR_;
222  VectorType vecL_;
223 
224  VectorType vecX_;
225  VectorType vecY_;
226  VectorType vecD_;
227  ActiveSetType activeSet_;
228 
229 }; // end of class QuadraticProgramming.
230 
231 } // end of namespace Math.
232 } // end of namespace Spidar.
233 
234 #endif // SPIDAR_QUADRATIC_PROGRAMMING_HPP
235 
236 // end of file.
SPIDARライブラリのルート名前空間です.
2次計画法のクラスです.
static void solve(MatrixType &a, VectorType &b, VectorType &x)
ガウスの消去法を用いて連立一次方程式を解きます.