-
Notifications
You must be signed in to change notification settings - Fork 0
/
simplex.cpp
100 lines (94 loc) · 2.28 KB
/
simplex.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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/* Author: Aunt
Usage: 解单纯形
A[0][j] 为参数,函数为f = \Sigma A[0][j]
约束条件:\SigmaA[i][j] <= A[i][0] */
#define swap(a, b) int temp = a; a = b; b = temp
const int MAXN = 1000;
const int MAXM = 1000;
const double EPS = 1e-8;
int id[MAXN + MAXM] = {};
double v[MAXN] = {};
double a[MAXM][MAXN] = {};
int sgn(double x) {
if (x < -EPS)
return -1;
return x > EPS ? 1 : 0;
}
void pivot(int r, int c) {
swap(id[n + r], id[c]);
double x = -a[r][c];
a[r][c] = -1;
for (int i = 0; i <= n; ++i)
a[r][i] /= x;
for (int i = 0; i <= m; ++i) {
if (sgn(a[i][c]) && i != r) {
x = a[i][c];
a[i][c] = 0;
for (int j = 0; j <= n; ++j)
a[i][j] += x * a[r][j];
}
}
}
int simplex() {
/* important: revert symbols of conditions */
/* bug fixed thanks to TuoMianZiGan */
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
a[i][j] *= -1;
}
}
for (int i = 1; i <= n; ++i)
id[i] = i;
/* initial-simplex */
while (true) {
int x = 0, y = 0;
for (int i = 1; i <= m; ++i) {
if (sgn(a[i][0]) < 0) {
x = i;
break;
}
}
if (!x)
break;
for (int i = 1; i <= n; ++i) {
if (sgn(a[x][i]) > 0) {
y = i;
break;
}
}
if (!y)
return -1; // infeasible
pivot(x, y);
}
/* solve-simplex */
while (true) {
int x = 0, y = 0;
for (int i = 1; i <= n; ++i) {
if (sgn(a[0][i]) > 0) {
x = i;
break;
}
}
if (!x)
break; // finished
double w = 0, t = 0;
bool f = true;
for (int i = 1; i <= m; ++i) {
if (sgn(a[i][x]) < 0) {
t = -a[i][0] / a[i][x];
if (f || t < w) {
w = t, y = i, f = false;
}
}
}
if (!y) {
return 1;
} // unbounded
pivot(y, x);
}
for (int i = 1; i <= n; ++i)
v[i] = 0;
for (int i = n + 1; i <= n + m; ++i)
v[id[i]] = a[i - n][0];
return 0;
}