Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import numpy as np
- import pandas as pd
- import sympy as sp
- def beautiful_table(df, N):
- beaut_t = df.copy()
- for col in range(3, len(beaut_t.columns)-1):
- for row in range(1, N+2):
- value = beaut_t.iloc[row, col]
- if isinstance(value, (int, float)):
- beaut_t.iloc[row, col] = round(value, 4)
- elif isinstance(value, sp.Basic):
- beaut_t.iloc[row, col] = value.evalf()
- if isinstance(beaut_t.iloc[row, col], sp.Float):
- beaut_t.iloc[row, col] = round(float(beaut_t.iloc[row, col]), 4)
- for row in range(1, N+2):
- value = beaut_t.iloc[row, -1]
- try:
- beaut_t.iloc[row, -1] = round(value, 4)
- except:
- _ = None
- beaut_t = beaut_t.map(lambda x: f'${x}$')
- beaut_t.index = beaut_t.index.map(lambda x: f'${x}$')
- beaut_t.columns = beaut_t.columns.map(lambda x: f'${x}$')
- beaut_t.index = [' ' for i in range(len(beaut_t.index))]
- return beaut_t
- def symplex_M_method(F, A, B, direction='max'):
- db = []
- N = len(A)
- len_x = len(A[0])
- M = sp.symbols('M')
- M_value = 10**5
- count_M = 0
- j = 0
- not_M_rows = []
- for i in range(len_x):
- if np.sum(A[:, i] == 0) == N-1:
- if 1 not in A[:, i]:
- count_M += 1
- if 1 in A[:, i]:
- not_M_rows.append(np.argwhere(A[:, i] == 1)[0][0])
- else:
- j += 1
- if j == (len_x - count_M):
- count_M += (N - count_M)
- len_x += count_M
- A_stack = np.eye(count_M)
- if count_M != N:
- array_to_insert = np.zeros(count_M)
- for i in np.sort(not_M_rows):
- index_to_insert = i
- A_stack = np.vstack((A_stack[:index_to_insert], array_to_insert, A_stack[index_to_insert:]))
- A_stack = A_stack.astype(int)
- A = np.hstack((A, A_stack))
- if direction == 'max':
- F = np.hstack((F, [-M for i in range(count_M)]))
- if direction == 'min':
- F = np.hstack((F, [M for i in range(count_M)]))
- print(f'F:\n{F}\nA:\n{A}\nB:\n{B}\n')
- columns = ['№', 'Коеф. \ при \ базисних \ змінних \ ЦФ', 'Базис', 'Вільні \ члени \ системи \ обмежень']
- for col in F:
- columns.append(col)
- columns.append('Оцінне \ відношення')
- table = pd.DataFrame(columns=columns)
- row = [' ' for i in range(4)]
- for i in range(len(F)):
- row.append(f'x_{i+1}')
- row.append(' ')
- table.loc[0] = row
- arr = []
- copy_arr = []
- for i in range(len_x):
- if np.sum(A[:, i] == 0) == N-1:
- if 1 in A[:, i]:
- arr.append(i)
- copy_arr.append(np.where(A[:, i] == 1)[0][0])
- B_full = np.array([0.0 for i in range(len_x)])
- for i, k in enumerate(arr):
- B_full[k] = B[copy_arr[i]]
- print(f'X={B_full}\n')
- F_i = np.sum(F * B_full)
- for i in range(N):
- row = [i+1, F[arr[i]], f'x_{arr[i]+1}', B[copy_arr[i]]]
- for a in (A[copy_arr[i]]):
- row.append(a)
- row.append(' ')
- table.loc[i+1] = row
- row = [' ', ' ', 'F', F_i]
- for i in range(len_x):
- row.append(np.sum(table.iloc[1:N+1, 1] * table.iloc[1:N+1, i+4]) - F[i])
- row.append(' ')
- table.loc[max(table.index) + 1] = row
- data = table.copy()
- data = data.drop(columns=['№', 'Коеф. \ при \ базисних \ змінних \ ЦФ', 'Базис', 'Вільні \ члени \ системи \ обмежень', 'Оцінне \ відношення'])
- data = data.loc[1:]
- row = []
- for i in data.iloc[-1].values:
- try:
- row.append(i.subs(M, M_value))
- except:
- row.append(i)
- row = np.array(row)
- if direction == 'max':
- min_ = np.argmin(row)
- if direction == 'min':
- min_ = np.argmax(row)
- ratio = []
- min_ratio = np.inf
- for i in range(N):
- if data.iloc[i, min_] != 0:
- r = table.iloc[i+1, 3] / data.iloc[i, min_]
- if r > 0:
- ratio.append(r)
- if r < min_ratio:
- min_ratio = r
- divider = i
- else:
- ratio.append('-')
- else:
- ratio.append('-')
- table.loc[1:N, 'Оцінне \ відношення'] = ratio[:]
- row_index = divider + 1
- min_ += 4
- solv_a = table.iloc[row_index, min_]
- new_x = table.iloc[0, min_]
- db.append(beautiful_table(table, N))
- print(table)
- row = []
- for i in table.iloc[N+1, 4:-1]:
- try:
- row.append(i.subs(M, M_value))
- except:
- row.append(i)
- row = np.array(row)
- if direction == 'max':
- test = (row < 0).any()
- if direction == 'min':
- test = (row > 0).any()
- while test:
- print(f"\n\nРозв'язувальний елемент: {solv_a} (Рядок: {row_index}; Колонка: {new_x})\n\n")
- new_table = table.copy()
- new_table.iloc[row_index, 2] = new_x
- new_table.iloc[row_index, 1] = new_table.columns[int(min_)]
- if solv_a != 1:
- new_table.iloc[row_index, (-len_x-2):-1] = new_table.iloc[row_index, (-len_x-2):-1].apply(lambda x: x / solv_a)
- c = table.iloc[row_index, 3]
- for row in range(1, N+2):
- if new_table.iloc[row, 2] != new_x:
- a = new_table.iloc[row, 3]
- b = new_table.iloc[row, min_]
- new_table.iloc[row, 3] = a - ((b * c) / solv_a)
- arr = []
- for value in new_table.loc[1:N, 'Базис'].values:
- arr.append(np.where(new_table.iloc[0] == value)[0][0])
- for col in np.sort(arr):
- for i in range(1, N+2):
- if (new_table.iloc[0, col] == new_table.loc[i, 'Базис']):
- new_table.iloc[i, col] = 1
- else:
- new_table.iloc[i, col] = 0
- for col in range(4, 4+len_x):
- if col not in arr:
- for row in range(1, N+2):
- if row != row_index:
- a = table.iloc[row, col]
- c = table.iloc[row, min_]
- b = table.iloc[row_index, col]
- new_table.iloc[row, col] = a - ((b * c) / solv_a)
- data = new_table.copy()
- data = data.drop(columns=['№', 'Коеф. \ при \ базисних \ змінних \ ЦФ', 'Базис', 'Вільні \ члени \ системи \ обмежень', 'Оцінне \ відношення'])
- data = data.loc[1:]
- row = []
- for i in data.iloc[-1].values:
- try:
- row.append(i.subs(M, M_value))
- except:
- row.append(i)
- row = np.array(row)
- if direction == 'max':
- min_ = np.argmin(row) + 4
- if direction == 'min':
- min_ = np.argmax(row) + 4
- ratio = []
- min_ratio = np.inf
- for i in range(1, N+1):
- if data.iloc[i-1, min_-4] != 0:
- r = new_table.iloc[i, 3] / data.iloc[i-1, min_-4]
- if r <= 0:
- ratio.append('-')
- else:
- ratio.append(r)
- if r < min_ratio:
- min_ratio = r
- divider = i
- else:
- ratio.append('-')
- new_table.loc[1:N, 'Оцінне \ відношення'] = ratio[:]
- row_index = divider
- solv_a = new_table.iloc[row_index, min_]
- new_x = new_table.iloc[0, min_]
- table = new_table.copy()
- print(new_table.iloc[:, :-1])
- print(new_table.iloc[:, -2:])
- db.append(beautiful_table(new_table, N))
- row = []
- for i in table.iloc[N+1, 4:-1].values:
- try:
- row.append(i.subs(M, M_value))
- except:
- row.append(i)
- row = np.array(row)
- if direction == 'max':
- test = (row < 0).any()
- if direction == 'min':
- test = (row > 0).any()
- if min_ratio == np.inf:
- if direction == 'min':
- print('\nМінімум прямує до мінус нескінченності.\n')
- if direction == 'max':
- print('\nМаксимум прямує до нескінченності.\n')
- test = False
- return pd.concat(db, ignore_index=False), db
- B_full = np.zeros(len_x)
- arr = np.array(arr) - 4
- for i, k in enumerate(arr):
- B_full[k] = np.round(new_table.iloc[i+1, 3], 4)
- print(f'\nПеревірка\nF = sum({B_full} * {F}) = {round(np.sum(B_full * F), 4)}')
- return pd.concat(db, ignore_index=False), db
- F = np.array([1, 7, 0, 0, 0, 0])
- direction = 'max'
- A = np.array([
- [3, 4, 1, 0, 0, 0],
- [2, 1, 0, 1, 0, 0],
- [1, 0, 0, 0, 1, 0],
- [0, 5, 0, 0, 0, 1]
- ])
- B = np.array([264, 140, 68, 150])
- # # 2.49
- # F = np.array([-3, -1, 0, 5, 0, 2])
- # direction = 'max'
- # A = np.array([
- # [7, 1, 1, 0, 0, 0],
- # [-2, -2, 0, 1, 0, 0],
- # [3, 1, 0, 0, 1, 0],
- # [-1, 1, 0, 0, 0, 1]
- # ])
- # B = np.array([1, 2, 2, 1])
- # # 2.61
- # F = np.array([1, 2, 3, -1])
- # direction = 'max'
- # A = np.array([
- # [1, 2, 2, -1],
- # [2, 1, 1, 2],
- # [1, 2, 1, 0]
- # ])
- # B = np.array([22, 20, 18])
- print(f'F:\n{F}\nA:\n{A}\nB:\n{B}\n')
- db, tables = symplex_M_method(F, A, B, direction)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement