Advertisement
mirosh111000

Симплексний метод(розширений)

Mar 22nd, 2024
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.78 KB | None | 0 0
  1. import numpy as np
  2. import pandas as pd
  3. import sympy as sp
  4.  
  5.  
  6.  
  7. def beautiful_table(df, N):
  8.     beaut_t = df.copy()
  9.  
  10.     for col in range(3, len(beaut_t.columns)-1):
  11.         for row in range(1, N+2):
  12.             value = beaut_t.iloc[row, col]
  13.             if isinstance(value, (int, float)):
  14.                 beaut_t.iloc[row, col] = round(value, 4)
  15.             elif isinstance(value, sp.Basic):
  16.                 beaut_t.iloc[row, col] = value.evalf()
  17.                 if isinstance(beaut_t.iloc[row, col], sp.Float):
  18.                     beaut_t.iloc[row, col] = round(float(beaut_t.iloc[row, col]), 4)
  19.                    
  20.     for row in range(1, N+2):
  21.         value = beaut_t.iloc[row, -1]
  22.         try:
  23.             beaut_t.iloc[row, -1] = round(value, 4)
  24.         except:
  25.             _ = None
  26.    
  27.     beaut_t = beaut_t.map(lambda x: f'${x}$')
  28.     beaut_t.index = beaut_t.index.map(lambda x: f'${x}$')
  29.     beaut_t.columns = beaut_t.columns.map(lambda x: f'${x}$')
  30.     beaut_t.index = [' ' for i in range(len(beaut_t.index))]
  31.    
  32.     return beaut_t
  33.  
  34. def symplex_M_method(F, A, B, direction='max'):
  35.    
  36.     db = []
  37.    
  38.     N = len(A)
  39.     len_x = len(A[0])
  40.    
  41.    
  42.     M = sp.symbols('M')
  43.     M_value = 10**5
  44.     count_M = 0
  45.     j = 0
  46.     not_M_rows = []
  47.     for i in range(len_x):
  48.         if np.sum(A[:, i] == 0) == N-1:
  49.             if 1 not in A[:, i]:
  50.                 count_M += 1
  51.             if 1 in A[:, i]:
  52.                 not_M_rows.append(np.argwhere(A[:, i] == 1)[0][0])
  53.         else:
  54.             j += 1
  55.    
  56.     if j == (len_x - count_M):
  57.         count_M += (N - count_M)
  58.        
  59.     len_x += count_M
  60.     A_stack = np.eye(count_M)
  61.     if count_M != N:
  62.         array_to_insert = np.zeros(count_M)
  63.         for i in np.sort(not_M_rows):
  64.             index_to_insert = i
  65.             A_stack = np.vstack((A_stack[:index_to_insert], array_to_insert, A_stack[index_to_insert:]))
  66.        
  67.     A_stack = A_stack.astype(int)
  68.     A = np.hstack((A, A_stack))
  69.     if direction == 'max':
  70.         F = np.hstack((F, [-M for i in range(count_M)]))
  71.     if direction == 'min':
  72.         F = np.hstack((F, [M for i in range(count_M)]))
  73.     print(f'F:\n{F}\nA:\n{A}\nB:\n{B}\n')
  74.    
  75.     columns = ['№', 'Коеф. \ при \ базисних \ змінних \ ЦФ', 'Базис', 'Вільні \ члени \ системи \ обмежень']
  76.     for col in F:
  77.         columns.append(col)
  78.     columns.append('Оцінне \ відношення')
  79.     table = pd.DataFrame(columns=columns)
  80.     row = [' ' for i in range(4)]
  81.     for i in range(len(F)):
  82.         row.append(f'x_{i+1}')
  83.     row.append(' ')
  84.     table.loc[0] = row
  85.    
  86.    
  87.     arr = []
  88.     copy_arr = []
  89.     for i in range(len_x):
  90.         if np.sum(A[:, i] == 0) == N-1:
  91.             if 1 in A[:, i]:
  92.                 arr.append(i)
  93.                 copy_arr.append(np.where(A[:, i] == 1)[0][0])
  94.  
  95.    
  96.     B_full = np.array([0.0 for i in range(len_x)])
  97.     for i, k in enumerate(arr):
  98.         B_full[k] = B[copy_arr[i]]
  99.     print(f'X={B_full}\n')
  100.     F_i = np.sum(F * B_full)
  101.     for i in range(N):
  102.         row = [i+1, F[arr[i]], f'x_{arr[i]+1}', B[copy_arr[i]]]
  103.         for a in (A[copy_arr[i]]):
  104.             row.append(a)
  105.         row.append(' ')
  106.         table.loc[i+1] = row
  107.     row = [' ',  ' ', 'F', F_i]
  108.     for i in range(len_x):
  109.         row.append(np.sum(table.iloc[1:N+1, 1] * table.iloc[1:N+1, i+4]) - F[i])
  110.     row.append(' ')
  111.     table.loc[max(table.index) + 1] = row
  112.    
  113.     data = table.copy()
  114.     data = data.drop(columns=['№', 'Коеф. \ при \ базисних \ змінних \ ЦФ', 'Базис', 'Вільні \ члени \ системи \ обмежень', 'Оцінне \ відношення'])
  115.     data = data.loc[1:]
  116.     row = []
  117.     for i in data.iloc[-1].values:
  118.         try:
  119.             row.append(i.subs(M, M_value))
  120.         except:
  121.             row.append(i)
  122.     row = np.array(row)
  123.     if direction == 'max':
  124.         min_ = np.argmin(row)
  125.     if direction == 'min':
  126.         min_ = np.argmax(row)
  127.    
  128.    
  129.     ratio = []
  130.     min_ratio = np.inf
  131.     for i in range(N):
  132.         if data.iloc[i, min_] != 0:
  133.             r = table.iloc[i+1, 3] / data.iloc[i, min_]
  134.             if r > 0:
  135.                 ratio.append(r)
  136.                 if r < min_ratio:
  137.                     min_ratio = r
  138.                     divider = i
  139.             else:
  140.                 ratio.append('-')
  141.         else:
  142.             ratio.append('-')  
  143.     table.loc[1:N, 'Оцінне \ відношення'] = ratio[:]
  144.     row_index = divider + 1
  145.     min_ += 4
  146.     solv_a = table.iloc[row_index, min_]
  147.     new_x = table.iloc[0, min_]
  148.    
  149.     db.append(beautiful_table(table, N))
  150.    
  151.     print(table)
  152.    
  153.    
  154.     row = []
  155.     for i in table.iloc[N+1, 4:-1]:
  156.         try:
  157.             row.append(i.subs(M, M_value))
  158.         except:
  159.             row.append(i)
  160.     row = np.array(row)
  161.    
  162.     if direction == 'max':
  163.         test = (row < 0).any()
  164.     if direction == 'min':
  165.         test = (row > 0).any()
  166.    
  167.     while test:
  168.        
  169.         print(f"\n\nРозв'язувальний елемент: {solv_a} (Рядок: {row_index}; Колонка: {new_x})\n\n")
  170.        
  171.         new_table = table.copy()
  172.         new_table.iloc[row_index, 2] = new_x
  173.         new_table.iloc[row_index, 1] = new_table.columns[int(min_)]
  174.         if solv_a != 1:
  175.             new_table.iloc[row_index, (-len_x-2):-1] = new_table.iloc[row_index, (-len_x-2):-1].apply(lambda x: x / solv_a)
  176.  
  177.         c = table.iloc[row_index, 3]
  178.         for row in range(1, N+2):
  179.             if new_table.iloc[row, 2] != new_x:
  180.                 a = new_table.iloc[row, 3]
  181.                 b = new_table.iloc[row, min_]
  182.                 new_table.iloc[row, 3] = a - ((b * c) / solv_a)
  183.  
  184.  
  185.         arr = []
  186.         for value in new_table.loc[1:N, 'Базис'].values:
  187.             arr.append(np.where(new_table.iloc[0] == value)[0][0])
  188.         for col in np.sort(arr):
  189.             for i in range(1, N+2):
  190.                 if (new_table.iloc[0, col] == new_table.loc[i, 'Базис']):
  191.                     new_table.iloc[i, col] = 1
  192.                 else:
  193.                     new_table.iloc[i, col] = 0
  194.  
  195.         for col in range(4, 4+len_x):
  196.             if col not in arr:
  197.                 for row in range(1, N+2):
  198.                     if row != row_index:
  199.                         a = table.iloc[row, col]
  200.                         c = table.iloc[row, min_]
  201.                         b = table.iloc[row_index, col]
  202.                         new_table.iloc[row, col] = a - ((b * c) / solv_a)
  203.  
  204.         data = new_table.copy()
  205.         data = data.drop(columns=['№', 'Коеф. \ при \ базисних \ змінних \ ЦФ', 'Базис', 'Вільні \ члени \ системи \ обмежень', 'Оцінне \ відношення'])
  206.         data = data.loc[1:]
  207.         row = []
  208.         for i in data.iloc[-1].values:
  209.             try:
  210.                 row.append(i.subs(M, M_value))
  211.             except:
  212.                 row.append(i)
  213.         row = np.array(row)
  214.         if direction == 'max':
  215.             min_ = np.argmin(row) + 4
  216.         if direction == 'min':
  217.             min_ = np.argmax(row) + 4
  218.            
  219.            
  220.         ratio = []
  221.         min_ratio = np.inf
  222.         for i in range(1, N+1):
  223.             if data.iloc[i-1, min_-4] != 0:
  224.                 r = new_table.iloc[i, 3] / data.iloc[i-1, min_-4]
  225.                 if r <= 0:
  226.                     ratio.append('-')
  227.                 else:
  228.                     ratio.append(r)
  229.                     if r < min_ratio:
  230.                         min_ratio = r
  231.                         divider = i
  232.             else:
  233.                 ratio.append('-')
  234.         new_table.loc[1:N, 'Оцінне \ відношення'] = ratio[:]
  235.         row_index = divider
  236.         solv_a = new_table.iloc[row_index, min_]
  237.         new_x = new_table.iloc[0, min_]
  238.         table = new_table.copy()
  239.         print(new_table.iloc[:, :-1])
  240.         print(new_table.iloc[:, -2:])
  241.  
  242.         db.append(beautiful_table(new_table, N))
  243.        
  244.        
  245.        
  246.         row = []
  247.         for i in table.iloc[N+1, 4:-1].values:
  248.             try:
  249.                 row.append(i.subs(M, M_value))
  250.             except:
  251.                 row.append(i)
  252.         row = np.array(row)
  253.         if direction == 'max':
  254.             test = (row < 0).any()
  255.         if direction == 'min':
  256.             test = (row > 0).any()
  257.         if min_ratio == np.inf:
  258.             if direction == 'min':
  259.                 print('\nМінімум прямує до мінус нескінченності.\n')
  260.             if direction == 'max':
  261.                 print('\nМаксимум прямує до нескінченності.\n')
  262.             test = False
  263.             return pd.concat(db, ignore_index=False), db
  264.        
  265.      
  266.     B_full = np.zeros(len_x)
  267.     arr = np.array(arr) - 4
  268.     for i, k in enumerate(arr):
  269.         B_full[k] = np.round(new_table.iloc[i+1, 3], 4)
  270.     print(f'\nПеревірка\nF = sum({B_full} * {F}) = {round(np.sum(B_full * F), 4)}')
  271.    
  272.     return pd.concat(db, ignore_index=False), db
  273.  
  274.  
  275.  
  276. F = np.array([1, 7, 0, 0, 0, 0])
  277. direction = 'max'
  278.  
  279. A = np.array([
  280.     [3, 4, 1, 0, 0, 0],
  281.     [2, 1, 0, 1, 0, 0],
  282.     [1, 0, 0, 0, 1, 0],
  283.     [0, 5, 0, 0, 0, 1]
  284. ])
  285. B = np.array([264, 140, 68, 150])
  286.  
  287.  
  288.  
  289. # # 2.49
  290. # F = np.array([-3, -1, 0, 5, 0, 2])
  291. # direction = 'max'
  292. # A = np.array([
  293. #     [7, 1, 1, 0, 0, 0],
  294. #     [-2, -2, 0, 1, 0, 0],
  295. #     [3, 1, 0, 0, 1, 0],
  296. #     [-1, 1, 0, 0, 0, 1]
  297. # ])
  298. # B = np.array([1, 2, 2, 1])
  299.  
  300.  
  301. # # 2.61
  302. # F = np.array([1, 2, 3, -1])
  303. # direction = 'max'
  304. # A = np.array([
  305. #     [1, 2, 2, -1],
  306. #     [2, 1, 1, 2],
  307. #     [1, 2, 1, 0]
  308. # ])
  309. # B = np.array([22, 20, 18])
  310.  
  311.  
  312. print(f'F:\n{F}\nA:\n{A}\nB:\n{B}\n')
  313. db, tables = symplex_M_method(F, A, B, direction)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement