Задача назначения — это хорошо известная задача оптимизации, которая предполагает распределение K человек на каждую работу наиболее эффективным способом. В этой статье мы рассмотрим несколько методов решения проблемы назначения и предоставим примеры кода для каждого метода.
- Подход линейного программирования.
Один из популярных методов решения задачи назначения — формулировка ее как задачи линейного программирования. Идея состоит в том, чтобы назначить переменные, представляющие распределение каждого человека на работу, и определить целевые и ограничивающие функции для оптимизации распределения. Вот пример кода с использованием библиотеки PuLP на Python:
import pulp
def solve_assignment_linear_programming(cost_matrix, k):
n = len(cost_matrix)
m = len(cost_matrix[0])
# Create a binary variable for each person-job pair
variables = pulp.LpVariable.dicts("x", (range(n), range(m)), cat="Binary")
# Create the linear programming problem
problem = pulp.LpProblem("Assignment Problem", pulp.LpMinimize)
# Set the objective function
problem += pulp.lpSum([cost_matrix[i][j] * variables[i][j] for i in range(n) for j in range(m)])
# Add constraints
for i in range(n):
problem += pulp.lpSum([variables[i][j] for j in range(m)]) == k
for j in range(m):
problem += pulp.lpSum([variables[i][j] for i in range(n)]) <= 1
# Solve the problem
problem.solve()
# Extract the solution
allocation = [[variables[i][j].varValue for j in range(m)] for i in range(n)]
return allocation
- Венгерский алгоритм:
Венгерский алгоритм — это хорошо известный метод эффективного решения задачи о назначениях. Он использует комбинацию сокращения строк и столбцов, а также метод увеличения пути для поиска оптимального назначения. Вот пример кода, использующего функциюscipy.optimize.linear_sum_assignmentв Python:
import numpy as np
from scipy.optimize import linear_sum_assignment
def solve_assignment_hungarian(cost_matrix, k):
n = len(cost_matrix)
m = len(cost_matrix[0])
# Duplicate the cost matrix k times
cost_matrix_extended = np.tile(cost_matrix, (k, 1, 1))
# Solve the assignment using the Hungarian algorithm
row_indices, col_indices = linear_sum_assignment(cost_matrix_extended)
# Extract the solution
allocation = np.zeros((n, m))
for row, col in zip(row_indices, col_indices):
allocation[row % n][col] = 1
return allocation.tolist()
- Двустороннее сопоставление.
Другой подход к решению проблемы назначения — ее моделирование как задачи двустороннего сопоставления. Этот метод включает в себя построение двудольного графа, где каждый человек и работа представлены в виде узла, а ребра представляют совместимость между людьми и должностями. Вот пример кода с использованием библиотеки NetworkX на Python:
import networkx as nx
def solve_assignment_bipartite(cost_matrix, k):
n = len(cost_matrix)
m = len(cost_matrix[0])
# Create a bipartite graph
graph = nx.Graph()
# Add person nodes
graph.add_nodes_from(range(n), bipartite=0)
# Add job nodes
graph.add_nodes_from(range(n, n + m), bipartite=1)
# Add edges with costs
for i in range(n):
for j in range(m):
graph.add_edge(i, n + j, weight=cost_matrix[i][j])
# Solve the bipartite matching problem
matching = nx.bipartite.maximum_matching(graph)
# Extract the solution
allocation = [[0] * m for _ in range(n)]
for person, job in matching.items():
if person < n:
allocation[person][job - n] = 1
return allocation
В этой статье мы исследовали три различных метода решения задачи назначения: линейное программирование, венгерский алгоритм и двустороннее сопоставление. Каждый метод предлагает уникальный подход к эффективному распределению K человек на каждую работу. Используя эти методы и предоставленные примеры кода, вы можете решать проблемы назначения в различных сценариях и эффективно оптимизировать распределение ресурсов.