Добавил:
koteykA
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Практическая работа №1 / 0375_Yablokov_№1
.pyimport pandas as pd
from tabulate import tabulate
from cvxopt import matrix, glpk
def print_constraints(constraints, constr_names, var_names):
'''Выводит левую часть матрицы ограничений в виде таблицы.'''
data = dict(zip(constr_names, constraints))
df = pd.DataFrame(data, index=var_names)
print(tabulate(df, headers='keys', tablefmt='psql'))
# Переменные
# Кол-во постоянных работников:
# x1-7 - пон-воскр, утренняя смена;
# x8-14 - пон-воскр, вечерняя смена.
# Кол-во почасовых рабочих:
# y1-7 - пон-воскр, первая четверть рабочего дня;
# y8-14 - пон-воскр, вторая;
# y15-21 - третья;
# y22-28 - четвертая.
CONSTRAINT_COUNT = 70
X_COUNT = 14
Y_COUNT = 28
VAR_COUNT = 42
WORKER_SALARY = 54400
FREELANCER_SALARY = 6720
# Задача минимазации - знак переменных не меняется.
c = [WORKER_SALARY] * X_COUNT
c.extend([FREELANCER_SALARY] * Y_COUNT)
G = []
# Условия на занятость в течение недели.
# k - смена: утренняя или вечерняя.
for s in range(2):
# i - день недели.
for i in range(7):
constraint = [0] * VAR_COUNT
# Ставим 1 на месте постоянных рабочих:
# j + 3 - дни, в которые заступили рабочие, которые будут
# работать в i день;
# 7 * s - учитывает смену.
for j in range(5):
constraint[(i + j + 3) % 7 + 7 * s] = -1 # Ограничение снизу
# Теперь на месте временных.
one_quart = constraint.copy()
# Одно условие: почасовой рабочий выходит в одну четверть.
one_quart[X_COUNT * (s + 1) + i] = -1
G.append(one_quart)
# Второе условие: почасовой рабочий выходит в другую четверть.
second_quart = constraint.copy()
second_quart[X_COUNT * (s + 1) + i + 7] = -1
G.append(second_quart)
# Условия на неотрицательность количества рабочих.
for i in range(VAR_COUNT):
constraint = [0] * VAR_COUNT
constraint[i] = -1 # Ограничение снизу
G.append(constraint)
# Вывод матрицы ограничений неравенств.
weekdays = ["пн", "вт", "ср", "чт", "пт", "сб", "вс"]
times = ['7-11', '11-15', '15-19', '19-23']
shift = ['у', 'в']
column_names = [f"{col}, {time}" for col in weekdays for time in times[:2]]
column_names.extend(
[f"{col}, {time}" for col in weekdays for time in times[2:]]
)
var_names = [f"x({weekdays[i % 7]}, {shift[i // 7]})" for i in range(X_COUNT)]
var_names.extend(
[f"y({weekdays[i % 7]}, {times[i // 7]})" for i in range(0, Y_COUNT)]
)
print("Матрица ограничений неравенств:")
print_constraints(G, column_names, var_names)
# Правая часть матрицы ограничений неравенств.
h = [-8, -8, -6, -5, -6, -5, -5, -6, -7, -8, -9, -8, -6, -5,
-7, -6, -4, -5, -4, -4, -6, -7, -8, -9, -7, -6, -4, -4]
h.extend([0] * VAR_COUNT)
# Проверка на то, что кол-во переменных правильное.
assert(len(c) == VAR_COUNT)
assert(len(G) == CONSTRAINT_COUNT)
assert(len(G[0]) == VAR_COUNT)
assert(len(h) == CONSTRAINT_COUNT)
c = matrix(c, tc='d')
G = matrix(G, tc='d')
h = matrix(h, tc='d')
status, solution = glpk.ilp(c, G.T, h, I=set(range(VAR_COUNT)))
# Вывод результатов и расчет целевой функции.
x_morning = list(map(int, solution[0:X_COUNT - 7]))
x_evening = list(map(int, solution[7:X_COUNT]))
y = [
list(map(int, solution[X_COUNT + 7*(i - 1):X_COUNT + 7*i]))
for i in range(1, 5)
]
weekdays = ["пн", "вт", "ср", "чт", "пт", "сб", "вс"]
columns = [[x1, x2] for x1, x2 in zip(x_morning, x_evening)]
print("\nКоличество постоянных работников, заступающих на работу в опр. день:")
print_constraints(columns, constr_names=weekdays, var_names=['утро', 'вечер'])
columns = [[*col] for col in zip(*y)]
print("\nКоличество временных работников по дням и сменам:")
print_constraints(columns, weekdays, ['7-11', '11-15', '15-19', '19-23'])
objective = sum(map(lambda x: x * WORKER_SALARY, solution[0:X_COUNT]))
objective += sum(map(lambda x: x * FREELANCER_SALARY, solution[X_COUNT:]))
print(f"\nЗначение целевой функции: {int(objective)} рублей.")
print(f'Количество постоянных рабочих: {sum(x_morning) + sum(x_evening)} чел.')
print(f'Количество временных рабочих: {sum(map(sum, y))} чел.', )
Соседние файлы в папке Практическая работа №1