-
Notifications
You must be signed in to change notification settings - Fork 0
/
complementarity_solver.cpp
53 lines (44 loc) · 1.51 KB
/
complementarity_solver.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <cassert>
#include <cmath>
#include <eigen3/Eigen/Dense>
#include <eigen3/Eigen/src/Core/Matrix.h>
#include <eigen3/Eigen/src/Core/util/Constants.h>
#include <math.h>
#include "complementarity_solver.h"
float window(float minval, float val, float maxval) {
return fminf(fmaxf(minval, val), maxval);
}
//returns lambda
Eigen::VectorXf pgs_solve(struct linear_complementarity_problem* problem, int iterations, float mu) {
//assert(problem->A.rows() == problem->A.cols());
assert(problem->lambda_max.size() == problem->lambda_min.size());
assert(problem->A.cols() == problem->lambda_min.size());
assert(problem->A.rows() == problem->b.size());
const int system_size = problem->lambda_max.size();
Eigen::VectorXf lambda = Eigen::VectorXf(system_size);
for (int iteration = 0; iteration < iterations; iteration++) {
// Gauss-Siedel
for (int i = 0; i < system_size; i++) {
lambda(i) = -problem->b(i);
//sum
for(int j = 0; j < i; j++) {
lambda(i) -= problem->A.coeff(i, j) * lambda(j);
}
for(int j = i+1; j < system_size; j++) {
lambda(i) -= problem->A.coeff(i, j) * lambda(j);
}
assert(fpclassify(problem->A.coeff(i, i)) != FP_ZERO);
lambda(i) = lambda(i) / problem->A.coeff(i, i);
int r = i % 3;
if(0 != r) {
problem->lambda_max(i) = mu * lambda(i - r);
problem->lambda_min(i) = -problem->lambda_max(i);
}
}
// Projection
for (int i = 0; i < system_size; i++) {
lambda(i) = window(problem->lambda_min(i), lambda(i), problem->lambda_max(i));
}
}
return lambda;
}