|
12 | 12 | """
|
13 | 13 |
|
14 | 14 |
|
15 |
| -def simplex(A: np.array, b: np.array, c: np.array) -> np.array: |
| 15 | +def simplex(A: np.array, b: np.array, c: np.array, slacks_amt: int) -> np.array: |
16 | 16 | # https://sdu.itslearning.com/ContentArea/ContentArea.aspx?LocationID=17727&LocationType=1&ElementID=589350
|
17 |
| - x_current = basic_feasible_solution(A, b, c) |
18 |
| - print(A, b, c) |
19 |
| - |
20 |
| - ## Choosing a pivot |
21 |
| - # Pick a non-negative column TODO |
22 |
| - positives = np.where(c > 0) |
23 |
| - if (not len(positives[0])): |
24 |
| - return "All coefficients negative" |
25 |
| - |
26 |
| - x_index = positives[0][0] |
27 |
| - y_index = None |
28 |
| - |
29 |
| - val = float("inf") |
30 |
| - a = A[:,x_index] |
31 |
| - for i in range(b.size): |
32 |
| - if (a[i] > 0): |
33 |
| - val_current = b[i] / a[i] |
34 |
| - if (val_current <= val): |
35 |
| - y_index = i |
36 |
| - val = val_current |
37 |
| - |
38 |
| - print(y_index) |
39 |
| - print(x_index) |
| 17 | + #x_current = basic_feasible_solution(A, b, c) |
| 18 | + N = [i for i in range(c.size - slacks_amt)] # Not In basis |
| 19 | + B = [i for i in range(slacks_amt, c.size)] # In basis |
40 | 20 |
|
| 21 | + print(A, b, c) |
| 22 | + print(N, B) |
| 23 | + |
| 24 | + while True: |
| 25 | + ## Choosing a pivot |
| 26 | + # Pick a non-negative column TODO |
| 27 | + positives = np.where(c > 0) |
| 28 | + if (not len(positives[0])): |
| 29 | + break |
| 30 | + |
| 31 | + xx = positives[0][0] |
| 32 | + yy = None |
| 33 | + yy_old = None |
| 34 | + |
| 35 | + # Picking smallest row b[i] / a[i] |
| 36 | + val = float("inf") |
| 37 | + a = A[:,xx] |
| 38 | + for i in range(b.size): |
| 39 | + if (a[i] > 0): |
| 40 | + val_current = b[i] / a[i] |
| 41 | + if (val_current <= val): |
| 42 | + yy = i |
| 43 | + val = val_current |
| 44 | + |
| 45 | + # Find column from where basis was exited |
| 46 | + a = A[yy,:] |
| 47 | + for i in range(a.size): |
| 48 | + if (a[i] == 1): |
| 49 | + s = np.sum(A[:,i]) + c[i] |
| 50 | + if (s == 1): |
| 51 | + yy_old = i |
| 52 | + break |
| 53 | + # Remove yy_old from basis and add yy to basis |
| 54 | + B.remove(yy_old) |
| 55 | + B.append(yy) |
| 56 | + N.append(yy_old) |
| 57 | + N.remove(yy) |
| 58 | + |
| 59 | + ## Pivot: A[xx, yy] - Peform row operations |
| 60 | + # Set yy row with in column xx to 1 |
| 61 | + b[yy] = b[yy] * 1 / A[yy, xx] |
| 62 | + A = row_mult(A, yy, 1 / A[yy, xx]) |
| 63 | + |
| 64 | + # Set column xx in c to 0 |
| 65 | + c = c - A[yy,:] * c[xx] |
| 66 | + |
| 67 | + # Set other values in column xx to 0 |
| 68 | + for i in range(A.shape[0]): |
| 69 | + if (i == yy): |
| 70 | + continue |
| 71 | + b[i] = b[i] - A[i, xx] * b[yy] |
| 72 | + A = row_add(A, i, yy, -A[yy, xx] * A[i, xx]) |
| 73 | + |
| 74 | + # Get solution |
| 75 | + x_sol = np.zeros(c.size) |
| 76 | + for i in range(len(B)): |
| 77 | + x_sol[B[i]] = b[i] |
| 78 | + return np.array(x_sol) |
| 79 | + |
| 80 | +def row_mult(A: np.array, row_index: int, scalar: int) -> np.array: |
| 81 | + # Row operation: R1 = scalar * R1 |
| 82 | + # Inspiration: (TODO - optimize) |
| 83 | + # https://personal.math.ubc.ca/~pwalls/math-python/linear-algebra/solving-linear-systems/ |
| 84 | + I = np.eye(A.shape[0]) |
| 85 | + I[row_index, row_index] = scalar |
| 86 | + return I @ A |
| 87 | + |
| 88 | +def row_add(A: np.array, row_main_index: int, row_other_index: int, scalar: int) -> np.array: |
| 89 | + # Row operation: R1 = R1 + scalar * R2 |
| 90 | + # Inspiration: (TODO - optimize) |
| 91 | + # https://personal.math.ubc.ca/~pwalls/math-python/linear-algebra/solving-linear-systems/ |
| 92 | + |
| 93 | + I = np.eye(A.shape[0]) |
| 94 | + if (row_main_index == row_other_index): |
| 95 | + I[row_main_index, row_main_index] = scalar + 1 |
| 96 | + else: |
| 97 | + I[row_main_index, row_other_index] = scalar |
| 98 | + return I @ A |
41 | 99 |
|
42 | 100 | def basic_feasible_solution(A: np.array, b: np.array, c: np.array) -> np.array:
|
43 | 101 | zero_point = zero_point_solution(A, b, c)
|
|
0 commit comments