-
-
Notifications
You must be signed in to change notification settings - Fork 46.7k
/
Copy pathmy_script.py
124 lines (94 loc) · 3.91 KB
/
my_script.py
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import numpy as np
class Tableau:
def __init__(self, tableau):
self.tableau = tableau
self.num_rows, self.num_cols = tableau.shape
def pivot(self, row, col):
# Divide the pivot row by the pivot element
self.tableau[row] /= self.tableau[row, col]
# Subtract multiples of the pivot row from all other rows
for i in range(self.num_rows):
if i != row:
self.tableau[i] -= self.tableau[i, col] * self.tableau[row]
def find_pivot_column(self):
# The pivot column is the most negative value in the objective row
obj_row = self.tableau[0, :-1]
pivot_col = np.argmin(obj_row)
if obj_row[pivot_col] >= 0:
return -1 # No negative value, we are done
return pivot_col
def find_pivot_row(self, pivot_col):
# Calculate the ratio of the righthand side to the pivotcolumnentries
rhs = self.tableau[1:, -1]
col = self.tableau[1:, pivot_col]
ratios = []
for i in range(len(rhs)):
if col[i] > 0:
ratios.append(rhs[i] / col[i])
else:
ratios.append(np.inf) # Ignore non-positive entries
pivot_row = np.argmin(ratios) + 1 # Add 1 because we ignored row 0
if np.isinf(ratios[pivot_row - 1]):
return -1 # No valid pivot row (unbounded)
return pivot_row
def run_simplex(self):
while True:
pivot_col = self.find_pivot_column()
if pivot_col == -1:
break # Optimal solution found
pivot_row = self.find_pivot_row(pivot_col)
if pivot_row == -1:
raise ValueError("Linear program is unbounded.")
self.pivot(pivot_row, pivot_col)
return self.extract_solution()
def extract_solution(self):
solution = np.zeros(self.num_cols - 1)
for i in range(1, self.num_rows):
col = self.tableau[i, :-1]
if np.count_nonzero(col) == 1:
solution[np.argmax(col)] = self.tableau[i, -1]
return solution, -self.tableau[0, -1] # Returnsolutionandoptimalvalue
def construct_tableau(objective, constraints, rhs):
"""
Constructs the initial tableau for the simplex algorithm.
Parameters:
- objective: List of coefficients of the objective function (maximize).
- constraints: List of lists representing coefficients of the constraints.
- rhs: List of right-hand-side values of constraints.
Returns:
- tableau: A numpy array representing the initial simplex tableau.
"""
n_constraints = len(constraints)
n_vars = len(objective)
# Creating the tableau matrix
tableau = np.zeros((n_constraints + 1, n_vars + n_constraints + 1))
# Fill the objective function (row 0, cols 0 to n_vars)
tableau[0, :n_vars] = -np.array(objective) # Maximization -> negate
# Fill the constraints
for i in range(n_constraints):
tableau[i + 1, :n_vars] = constraints[i]
tableau[i + 1, n_vars + i] = 1 # Slack variable
tableau[i + 1, -1] = rhs[i] # RHS of the constraints
return tableau
def solve_linear_program(objective, constraints, rhs):
# Constructing the tableau
tableau = construct_tableau(objective, constraints, rhs)
# Instantiate the Tableau class
simplex_tableau = Tableau(tableau)
# Run the simplex algorithm
solution, optimal_value = simplex_tableau.run_simplex()
# Output the solution
print("Optimal Solution:", solution)
print("Optimal Value:", optimal_value)
# Example usage
if __name__ == "__main__":
# Coefficients of the objective function: maximize 3x1 + 2x2
objective = [3, 2]
# Coefficients of the constraints:
# 2x1 + x2 <= 18
# x1 + 2x2 <= 20
constraints = [[2, 1], [1, 2]]
# Right-hand side of the constraints
rhs = [18, 20]
# Solve the linear program
solve_linear_program(objective, constraints, rhs)