-
Notifications
You must be signed in to change notification settings - Fork 1
/
tableu_simplex.py
114 lines (84 loc) · 3.25 KB
/
tableu_simplex.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
import numpy as np
class LinearModel:
def __init__(self, A=np.empty([0, 0]), b=np.empty([0, 0]), c=np.empty([0, 0]), minmax="MAX"):
self.A = A
self.b = b
self.c = c
self.x = [float(0)] * len(c)
self.minmax = minmax
self.printIter = False
self.optimalValue = None
def getTableau(self):
# construct starting tableau
t1 = np.array([None, 0])
numVar = len(self.c)
numSlack = len(self.A)
t1 = np.hstack(([None], [0], self.c, [0] * numSlack))
basis = np.array([0] * numSlack)
for i in range(0, len(basis)):
basis[i] = numVar + i
A = self.A
if not ((numSlack + numVar) == len(self.A[0])):
B = np.identity(numSlack)
A = np.hstack((self.A, B))
t2 = np.hstack((np.transpose([basis]), np.transpose([self.b]), A))
tableau = np.vstack((t1, t2))
tableau = np.array(tableau, dtype="float")
return tableau
def optimize(self):
tableau = self.getTableau()
# assume initial basis is not optimal
optimal = False
# keep track of iterations for display
iter = 1
itermap = {0:-tableau[0,1]}
while True:
if self.minmax == "MAX":
for profit in tableau[0, 2:]:
if profit > 0:
optimal = False
break
optimal = True
else:
for cost in tableau[0, 2:]:
if cost < 0:
optimal = False
break
optimal = True
# if all directions result in decreased profit or increased cost
if optimal == True:
break
# nth variable enters basis, account for tableau indexing
if self.minmax == "MAX":
n = tableau[0, 2:].tolist().index(np.amax(tableau[0, 2:])) + 2
else:
n = tableau[0, 2:].tolist().index(np.amin(tableau[0, 2:])) + 2
# minimum ratio test, rth variable leaves basis
minimum = 99999
r = -1
for i in range(1, len(tableau)):
if tableau[i, n] > 0:
val = tableau[i, 1] / tableau[i, n]
if val < minimum:
minimum = val
r = i
pivot = tableau[r, n]
# perform row operations
# divide the pivot row with the pivot element
tableau[r, 1:] = tableau[r, 1:] / pivot
# pivot other rows
for i in range(0, len(tableau)):
if i != r:
mult = tableau[i, n] / tableau[r, n]
tableau[i, 1:] = tableau[i, 1:] - mult * tableau[r, 1:]
# new basic variable
tableau[r, 0] = n - 2
itermap[iter] = -tableau[0,1]
iter += 1
self.x = np.array([0] * len(self.c), dtype=float)
# save coefficients
for key in range(1, (len(tableau))):
if tableau[key, 0] < len(self.c):
self.x[int(tableau[key, 0])] = tableau[key, 1]
self.optimalValue = -1 * tableau[0, 1]
return self.x, itermap