Skip to content

Commit b2a46e8

Browse files
committed
feat: OT Lab - 7 (Big M method)
1 parent ddd0775 commit b2a46e8

File tree

5 files changed

+565
-0
lines changed

5 files changed

+565
-0
lines changed

OT Lab - 7 (06-09-24)/7.cpp

+251
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
#include <bits/stdc++.h>
2+
#include <vector>
3+
#include <iomanip>
4+
#include <limits>
5+
6+
using namespace std;
7+
8+
class Simplex {
9+
private:
10+
int n, m, artificialCount;
11+
vector<vector<double>> A;
12+
vector<double> c;
13+
vector<double> b;
14+
vector<double> CB;
15+
vector<int> B;
16+
vector<double> delta;
17+
const double M = 1e2; // Large penalty value
18+
int extravar = 0;
19+
set<int> arti_ind;
20+
21+
public:
22+
Simplex(int variables, int constraints) : n(variables), m(constraints),
23+
A(constraints, vector<double>(variables + constraints+constraints)),
24+
c(variables + constraints + constraints), // c includes slack and artificial variables
25+
b(constraints),
26+
CB(constraints),
27+
B(constraints),
28+
delta(variables + constraints + constraints),
29+
artificialCount(0) {}
30+
31+
void readInput() {
32+
cout << "Enter the coefficients of the objective function: ";
33+
for (int i = 0; i < n; i++) {
34+
cin >> c[i];
35+
}
36+
37+
cout << "Enter the coefficients of the constraints:" << endl;
38+
for (int i = 0; i < m; i++) {
39+
for (int j = 0; j < n; j++) {
40+
cin >> A[i][j];
41+
}
42+
}
43+
44+
vector<string> sign(m);
45+
cout << "Enter >=/<=/=: " << endl;
46+
for(int i = 0 ;i<m;i++) cin>>sign[i];
47+
48+
cout << "Enter the right-hand side of the constraints: ";
49+
for (int i = 0; i < m; i++) {
50+
cin >> b[i];
51+
if (b[i] < 0) {
52+
b[i]*=-1;
53+
for(int j = 0 ;j<n;j++){
54+
A[i][j]*=-1;
55+
}
56+
if(sign[i]==">=") sign[i] = "<=";
57+
else if(sign[i]=="<=") sign[i] = ">=";
58+
}
59+
}
60+
61+
// Set up slack and artificial variables
62+
63+
for (int i = 0; i < m; i++) {
64+
string constraintType = sign[i];
65+
66+
if (constraintType == "<=") {
67+
// Slack variable
68+
A[i][n + extravar] = 1.0; // Slack variable coefficient
69+
c[n + extravar] = 0.0; // Slack variable in the objective function
70+
B[i] = n + extravar; // Slack variables start as basic variables
71+
CB[i] = 0.0; // Coefficient of slack variable in the objective
72+
extravar++;
73+
}
74+
else if (constraintType == "=") {
75+
// Artificial variable
76+
A[i][n + extravar] = 1.0; // Artificial variable coefficient
77+
c[n + extravar] = -M; // Penalty M in objective function
78+
B[i] = n + extravar; // Artificial variable starts as basic
79+
CB[i] = -M; // Artificial variable in the basis
80+
artificialCount++;
81+
arti_ind.insert(n+extravar);
82+
extravar++;
83+
}
84+
else if (constraintType == ">=") {
85+
// Surplus variable
86+
A[i][n + extravar] = -1.0; // Surplus variable coefficient
87+
c[n + extravar] = 0.0; // Surplus variable in objective function
88+
extravar++;
89+
// Artificial variable
90+
A[i][n +extravar] = 1.0; // Artificial variable coefficient
91+
c[n + extravar] = -M; // Penalty M in objective function
92+
B[i] = n + extravar; // Artificial variable starts as basic
93+
CB[i] = -M; // Artificial variable in the basis
94+
artificialCount++;
95+
arti_ind.insert(n+extravar);
96+
extravar++;
97+
}
98+
}
99+
}
100+
101+
void computeDelta() {
102+
for (int j = 0; j < n +extravar; j++) {
103+
double sum = 0.0;
104+
for (int i = 0; i < m; i++) {
105+
sum += CB[i] * A[i][j];
106+
}
107+
delta[j] = sum - c[j];
108+
}
109+
}
110+
111+
int findEnteringVariable() {
112+
int entering = -1;
113+
for (int j = 0; j < n + extravar; j++) {
114+
if (delta[j] < 0) {
115+
if (entering == -1 || delta[j] < delta[entering]) {
116+
entering = j;
117+
}
118+
}
119+
}
120+
return entering;
121+
}
122+
123+
int findLeavingVariable(int entering) {
124+
int leaving = -1;
125+
double minRatio = numeric_limits<double>::infinity(); // Use infinity for comparison
126+
for (int i = 0; i < m; i++) {
127+
if (A[i][entering] > 0) { // Check if pivot element is positive
128+
double ratio = b[i] / A[i][entering];
129+
if (ratio < minRatio || (ratio == minRatio && B[i] < B[leaving])) { // Handle degeneracy
130+
minRatio = ratio;
131+
leaving = i;
132+
}
133+
}
134+
}
135+
if (minRatio == numeric_limits<double>::infinity()) {
136+
cout << "Unbounded solution: no positive entries in the column of the entering variable." << endl;
137+
return -1;
138+
}
139+
return leaving;
140+
}
141+
142+
void pivot(int entering, int leaving) {
143+
double pivotElement = A[leaving][entering];
144+
145+
// Normalize pivot row
146+
for (int j = 0; j < n +extravar; j++) {
147+
A[leaving][j] /= pivotElement;
148+
}
149+
b[leaving] /= pivotElement;
150+
151+
// Update other rows
152+
for (int i = 0; i < m; i++) {
153+
if (i != leaving) {
154+
double factor = A[i][entering];
155+
for (int j = 0; j < n +extravar; j++) {
156+
A[i][j] -= factor * A[leaving][j];
157+
}
158+
b[i] -= factor * b[leaving];
159+
}
160+
}
161+
162+
// Update basis
163+
B[leaving] = entering;
164+
CB[leaving] = c[entering];
165+
}
166+
167+
void printTable() {
168+
cout << endl << "Simplex Table:" << endl;
169+
cout << ' ' << "XB" << ' ' << "CB";
170+
for (int j = 0; j < n + extravar; j++) {
171+
cout << ' ' << "X" << j + 1;
172+
}
173+
cout << ' ' << "b" << endl;
174+
175+
for (int i = 0; i < m; i++) {
176+
177+
cout << ' ' << "X" << B[i] + 1 << ' ' ;
178+
if(CB[i]==-100) cout<<"-M";
179+
else cout<<CB[i];
180+
for (int j = 0; j < n + extravar; j++) {
181+
cout << ' ' << A[i][j];
182+
}
183+
cout << ' ' << b[i] << endl;
184+
}
185+
186+
cout << "Δj: ";
187+
for (int j = 0; j < n +extravar; j++) {
188+
cout << ' ' << delta[j];
189+
}
190+
cout << endl;
191+
}
192+
193+
void solve() {
194+
while (true) {
195+
computeDelta();
196+
printTable();
197+
198+
int entering = findEnteringVariable();
199+
if (entering == -1) {
200+
cout << "Optimal solution found." << endl;
201+
break;
202+
}
203+
204+
int leaving = findLeavingVariable(entering);
205+
if (leaving == -1) {
206+
cout << "Problem is unbounded." << endl;
207+
return;
208+
}
209+
210+
// Check for degenerate solution
211+
if (b[leaving] == 0) {
212+
cout << "Degenerate solution detected." << endl;
213+
}
214+
215+
pivot(entering, leaving);
216+
}
217+
218+
// Print final solution
219+
cout << "Final Solution:" << endl;
220+
for (int i = 0; i < m; i++) {
221+
if(B[i]<n)
222+
cout << "X" << B[i] + 1 << " = " << b[i] << endl;
223+
}
224+
double optimalValue = 0;
225+
for (int i = 0; i < m; i++) {
226+
optimalValue += CB[i] * b[i];
227+
}
228+
cout << "Optimal value of the objective function: " << optimalValue << endl;
229+
230+
// Check for infeasibility
231+
for (int i = 0; i < m; i++) {
232+
233+
if (arti_ind.find(B[i])!=arti_ind.end() && b[i] != 0) {
234+
cout << "Infeasible solution: artificial variable X" << B[i] + 1 << " is still in the basis." << endl;
235+
return;
236+
}
237+
}
238+
}
239+
};
240+
241+
int main() {
242+
int variables, constraints;
243+
cout << "Enter the number of variables and constraints: ";
244+
cin >> variables >> constraints;
245+
246+
Simplex simplex(variables, constraints);
247+
simplex.readInput();
248+
simplex.solve();
249+
250+
return 0;
251+
}

0 commit comments

Comments
 (0)