Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Молотков Иван molotkov.1997@mail.ru
- # Дробный алгоритм метода отсечений
- from fractions import Fraction
- import numpy as np
- from copy import deepcopy
- from math import floor, ceil
- # Эта хня создает массив B, содержащий коэффициенты в простых дробях
- def getB(A):
- B = []
- for i in range(len(A)):
- B.append([])
- for k in range(len(A[0])):
- B[i].append(Fraction(A[i][k]))
- return B
- # Печать массива B
- def printla(B):
- print(str(np.array(B)).replace('Fraction', '').replace(', ', ' / '))
- # Принимает массив В и координаты ведущего элемента, возвращает новый массив В с каким-то там преобразованием
- def ref(B, newBas):
- a = newBas[0]
- b = newBas[1]
- C = deepcopy(B)
- for i in range(len(C)):
- for k in range(len(C[0])):
- if ( k == b):
- B[i][k] = (-C[i][k] / C[a][b])
- else:
- B[i][k] = ((C[i][k] - C[a][k] * C[i][b] / C[a][b]))
- return B
- # Эта хрень ищет ведущий элемент
- def find1(B, cur_bas):
- if True: # True для выбора минимального индекса, False для максимального
- b = B[0].index(min(B[0][1:]))
- else:
- la = B[0][1:]
- la.reverse()
- b = len(la) - la.index(min(la))
- st = [
- B[i][0] / B[i][b]
- if B[i][b] != 0 # Не делить же на ноль
- and i not in cur_bas and i != 0
- and (np.sign(B[i][0]) == 0 and np.sign(B[i][b]) == 1
- or (np.sign(B[i][0]) * np.sign(B[i][b])) == 1)
- else np.inf
- for i in range(len(B))
- ]
- if (min(st) is np.inf):
- return None
- a = st.index(min(st))
- cur_bas[b - 1] = a
- return(a, b)
- # Ведущий элемент для псевдооптимального плана
- def find2(B, bb):
- tm = [
- B[i][0]
- if i not in bb and i != 0
- else np.inf
- for i in range(len(B))
- ]
- a = tm.index(min(tm))
- st = [
- - B[0][i] / B[a][i]
- if B[a][i] != 0 # Не делить же на ноль
- and i != 0
- and (np.sign(-B[0][i]) == 0 and np.sign(B[a][i]) == 1
- or (np.sign(-B[0][i]) * np.sign(B[a][i])) == 1)
- else np.inf
- for i in range(0, len(B[a]))
- ]
- if (min(st) is np.inf):
- return None
- t = st.index(min(st))
- for i in range(1, len(st)):
- if st[i] is not np.inf:
- if st[i] == st[t]:
- if False: # True для выбора минимального индекса, False для максимального
- if bb[i - 1] < bb[t - 1]:
- t = i
- else:
- if bb[i - 1] > bb[t - 1]:
- t = i
- b = t
- bb[b - 1] = a
- return(a, b)
- # Возвращает true, если решение оптимально
- def opt(B):
- if (min(B[0][1:]) < 0):
- return 1
- if (min([B[i][0] for i in range(1, len(B))]) < 0):
- return 2
- return 0
- # Делает отсечение и возвращает индекс переменной, для которой идет отсечение
- def ots(B):
- lala = [B[i][0] -floor(B[i][0]) for i in range(1, len(B[0]))]
- x = int(lala.index(max(lala)) + 1)
- B.append([floor(B[x][i])-B[x][i] for i in range(0, len(B[0]))])
- return x
- # Ищет ведущий элемент
- def find(B, bb):
- if (opt(B) == 1):
- return find1(B, Bas)
- else:
- return find2(B, Bas)
- print('okay')
- # Решение
- A = np.array([
- [0, -1, 0],
- [0, -1, 0],
- [0, 0, -1],
- [12, 1, 3],
- [24, 3, -8],
- ])
- B = getB(A)
- Bas = [i for i in range(1, len(B[0]))]
- Bas0 = deepcopy(Bas)
- B0 = deepcopy(B)
- flag = 0
- n_it = 50
- it = n_it
- while True:
- # Оптимальное решение
- while (opt(B) != 0):
- print(Bas)
- printla(B)
- newBas = find(B, Bas)
- if (newBas is None):
- print('Вроде как такое не решить...')
- flag = 1
- break
- print(newBas)
- print('\n')
- ref(B, newBas)
- it -= 1
- if it == 0:
- print('Кажется мы зациклились :(')
- flag = 1
- break
- if flag == 1:
- break
- # Вывод оптимального решения
- print(Bas)
- printla(B)
- print('\n')
- if sum([abs(floor(B[i][0]) - B[i][0]) for i in range(len(B))]) == 0:
- break
- # Отсечение
- print('Отсечение x = ', ots(B))
- it -= 1
- print('Итераций', n_it - it)
- print('F =', B[0][0])
- for i in range(1, len(B[0])):
- print ('x', i, '=', B[i][0])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement