11/*
2- *Description:* Optimizes linear function, based of linear restrictions, in $O(n^2)$
3- *Status:* Not tested
2+ *Author:* KACTL Based
3+ *Description:* Solves a general linear maximization problem:
4+ maximize $c^T x$ subject to $A x <= b$, $x >= 0$.
5+ Returns $-infinity$ if infeasible, $infinity$ if unbounded,
6+ or the maximum value of $c^T x$ otherwise.
7+ The input vector is set to an optimal $x$ (or in the unbounded
8+ case, an arbitrary solution fulfilling the constraints).
9+ Numerical stability is not guaranteed. For better performance,
10+ define variables such that $x = 0$ is viable.
11+ *Time:* $O(n m dot "pivots")$ per pivot. $O(2^n)$ worst case,
12+ fast in practice.
13+ *Usage:*
14+ `lp_solver<double> lp(A, b, c);`
15+ `vector<double> x;`
16+ `double val = lp.solve(x);`
17+ *Status:* Tested
418*/
5- template <class T > struct Simplex {
6- T ans;
7- vector<vector<T>> a;
8- vector<T> b,c,d;
9- void pivot (int ii, int jj){
10- d[ii] = c[jj];
11- T s1 = a[ii][jj];
12- for (int i = 0 ; i < a[0 ].size (); i++)
13- a[ii][i] /= s1;
14- b[ii] /= s1;
15- for (int i = 0 ; i < d.size (); i++){
16- if (i == ii || a[i][jj] == 0 ) continue ;
17- T s2 = a[i][jj];
18- for (int j = 0 ; j < a[0 ].size (); j++)
19- a[i][j] -= s2*a[ii][j];
20- b[i] -= s2*b[ii];
21- }
19+ template <class T >
20+ struct lp_solver {
21+ T eps = 1e-8 , inf = 1e18 ;
22+ int m, n;
23+ vector<int > N, B;
24+ vector<vector<T>> D;
25+
26+ lp_solver (vector<vector<T>> A, vector<T> b, vector<T> c)
27+ : m(b.size()), n(c.size()),
28+ N (n + 1 ), B(m), D(m + 2 , vector<T>(n + 2 )) {
29+ for (int i = 0 ; i < m; i++)
30+ for (int j = 0 ; j < n; j++)
31+ D[i][j] = A[i][j];
32+ for (int i = 0 ; i < m; i++)
33+ B[i] = n + i, D[i][n] = -1 , D[i][n + 1 ] = b[i];
34+ iota (N.begin (), N.end () - 1 , 0 );
35+ for (int j = 0 ; j < n; j++)
36+ D[m][j] = -c[j];
37+ N[n] = -1 ;
38+ D[m + 1 ][n] = 1 ;
39+ }
40+
41+ void pivot (int r, int s) {
42+ T *a = D[r].data (), inv = 1 / a[s];
43+ for (int i = 0 ; i < m + 2 ; i++) {
44+ if (i == r || abs (D[i][s]) <= eps) continue ;
45+ T *b = D[i].data (), inv2 = b[s] * inv;
46+ for (int j = 0 ; j < n + 2 ; j++)
47+ b[j] -= a[j] * inv2;
48+ b[s] = a[s] * inv2;
2249 }
23- bool next_point (){
24- int idx = -1 ; T mx;
25- for (int i = 0 ; i < (int )a[0 ].size (); i++){
26- T z = 0 ;
27- for (int j = 0 ; j < (int )d.size (); j++)
28- z += a[j][i]*d[j];
29- if (idx == -1 || mx < c[i]-z)
30- mx = c[i]-z, idx = i;
31- }
32- if (mx > 0 ){
33- int idx2 = -1 ; T mn;
34- for (int i = 0 ; i < (int )b.size (); i++){
35- if (a[i][idx] == 0 || b[i]/a[i][idx] <= 0 ) continue ;
36- if (idx2 == -1 || mn > b[i]/a[i][idx])
37- mn = b[i]/a[i][idx], idx2 = i;
38- }
39- if (idx2 == -1 ) return 0 ; // unbounded
40- pivot (idx2,idx);
41- return 1 ;
42- }
43- return 0 ;
50+ for (int j = 0 ; j < n + 2 ; j++)
51+ if (j != s) D[r][j] *= inv;
52+ for (int i = 0 ; i < m + 2 ; i++)
53+ if (i != r) D[i][s] *= -inv;
54+ D[r][s] = inv;
55+ swap (B[r], N[s]);
56+ }
57+
58+ int sel (int lo, int hi, vector<T> &row, int phase = 0 ) {
59+ int s = -1 ;
60+ for (int j = lo; j < hi; j++)
61+ if (N[j] != -phase)
62+ if (s == -1 || pair{row[j], N[j]} < pair{row[s], N[s]})
63+ s = j;
64+ return s;
65+ }
66+
67+ bool simplex (int phase) {
68+ int x = m + phase - 1 ;
69+ for (;;) {
70+ int s = sel (0 , n + 1 , D[x], phase);
71+ if (D[x][s] >= -eps) return true ;
72+ int r = -1 ;
73+ for (int i = 0 ; i < m; i++) {
74+ if (D[i][s] <= eps) continue ;
75+ if (r == -1 ||
76+ pair{D[i][n+1 ] / D[i][s], B[i]} <
77+ pair{D[r][n+1 ] / D[r][s], B[r]})
78+ r = i;
79+ }
80+ if (r == -1 ) return false ;
81+ pivot (r, s);
4482 }
45- Simplex (vector<vector<T>> & _a, vector<T> & _b, vector<T> & _c) : a(_a),b(_b),c(_c){
46- d.resize (b.size (),0 );
47- while (next_point ());
48- ans = 0 ;
49- for (int i = 0 ; i < b.size (); i++)
50- ans += b[i]*d[i];
83+ }
84+
85+ T solve (vector<T> &x) {
86+ int r = 0 ;
87+ for (int i = 1 ; i < m; i++)
88+ if (D[i][n + 1 ] < D[r][n + 1 ]) r = i;
89+ if (D[r][n + 1 ] < -eps) {
90+ pivot (r, n);
91+ if (!simplex (2 ) || D[m + 1 ][n + 1 ] < -eps)
92+ return -inf;
93+ for (int i = 0 ; i < m; i++)
94+ if (B[i] == -1 )
95+ pivot (i, sel (0 , n + 1 , D[i]));
5196 }
97+ bool ok = simplex (1 );
98+ x.assign (n, 0 );
99+ for (int i = 0 ; i < m; i++)
100+ if (B[i] < n)
101+ x[B[i]] = D[i][n + 1 ];
102+ return ok ? D[m][n + 1 ] : inf;
103+ }
52104};
0 commit comments