Вы можете использовать ориентированный граф для моделирования отношений приоритета задачи.
Каждый узел соответствует задаче.Соединение от узла A к узлу B означает, что мы можем выполнить задачу A, за которой следует задача B.
Затем возникает проблема с нахождением всех путей на графике.
Код легко доступен в Интернетемоделировать графики и определять пути.Здесь я использую https://www.geeksforgeeks.org/find-paths-given-source-destination/
# https://www.geeksforgeeks.org/find-paths-given-source-destination/
from collections import defaultdict
#This class represents a directed graph (from https://www.geeksforgeeks.org/find-paths-given-source-destination/)
# using adjacency list representation
class Graph:
def __init__(self,vertices):
#No. of vertices
self.V= vertices
# default dictionary to store graph
self.graph = defaultdict(list)
# function to add an edge to graph
def addEdge(self,u,v):
self.graph[u].append(v)
'''A recursive function to print all paths from 'u' to 'd'.
visited[] keeps track of vertices in current path.
path[] stores actual vertices and path_index is current
index in path[]'''
def findAllPathsUtil(self, u, d, visited, path, results = set()):
# Mark the current node as visited and store in path
visited[u]= True
path.append(u)
# If current vertex is same as destination, then print
# current path[]
if u ==d:
results.add (tuple(path))
else:
# If current vertex is not destination
#Recur for all the vertices adjacent to this vertex
for i in self.graph[u]:
if visited[i]==False:
self.findAllPathsUtil(i, d, visited, path, results)
# Remove current vertex from path[] and mark it as unvisited
path.pop()
visited[u]= False
# Prints all paths from 's' to 'd'
def findAllPaths(self,s, d, results = set()):
# Mark all the vertices as not visited
visited = defaultdict(lambda: False) # [False]*(self.V)
# Create an array to store paths
path = []
# Call the recursive helper function to print all paths
return self.findAllPathsUtil(s, d,visited, path, results)
Выше приведен базовый код для создания ориентированного графа и печати всех путей между узлами.
Он был немного изменен, чтобы позволить нумерации узлов с 1, а не 0, чтобы соответствовать нумерации задач.
Мы используем его для:
- Создатьграфик из списка задач
- Найти все пути между узлами на графике
def create_graph(lst):
" Creates graph from list of task dependencies "
# Find the number of tasks (i.e. maximum task index)
n = max(max(sublist) for sublist in lst)
# Convert task precedence pairs into graph
g = Graph(n)
for sublist in lst:
g.addEdge(sublist[0], sublist[1])
return g
Далее Мы создаем все возможные цепочки задач Поместите цепочки задач в древовидную структуру (это позволяетбыстрая идентификация цепей с одинаковым префиксом пути)
# Trie code (see https://www.geeksforgeeks.org/trie-insert-and-search/)
_end = "_end"
def add_trie(lst, root):
for sublist in lst:
current_dict = root
for number in sublist:
current_dict = current_dict.setdefault(number, {})
current_dict[_end] = _end
return root
def get_longest_paths(root, results, path = []):
" Finds longest chains "
if len(root) == 1 and _end in root and len(path) > 1:
#print(f"adding {path} ") #{tuple(path[:-1])} {len(tuple(path[-1]))}")
results.add(tuple(path))
return
for k, v in root.items():
if len(root) == 1 or (len(root) > 1 and k != _end):
# Ingore key terminating key when we have other options since this means
# we are a prefix of a longest list
path.append(k)
get_longest_paths(v, results, path)
path.pop()
def create_task_chains(g, i):
" Creates all sequences of tasks starting at task i"
n = g.V # number of tasks which same as nodes in graph
results = set()
for j in range(n):
if i != j:
g.findAllPaths(i, j, results)
t = sorted(results, key=lambda x: (len(x), x))
return t
Проверьте программное обеспечение, используя оригинальный список
lst =[[1, 3],
[2, 3],
[3, 4],
[4, 5],
[4, 8],
[5, 6],
[6, 7],
[6, 10],
[7, 11],
[7, 12],
[8, 9],
[8, 11],
[9, 13],
[9, 10],
[11, 13],
[12, 15],
[13, 14],
[14, 16],
[14, 19],
[14, 20],
[15, 17],
[15, 22],
[16, 18],
[17, 18],
[17, 23],
[18, 25],
[19, 22],
[20, 21],
[20, 25],
[21, 22],
[21, 24],
[23, 25]]
# Create task dependency Graph
g = create_graph(lst)
# Number of tasks
number_tasks = max(max(sublist) for sublist in lst)
trie_tree = {}
for task in range(1, number_tasks + 1):
# Create task chains that start with task i
task_chains = create_task_chains(g, task)
# Create Trie Tree (i.e. prefix tree)
add_trie(task_chains, trie_tree)
# Find shortest paths
# Find the longest task chains (use set to remove repeated paths--only a few)
results = set() # Starting with a new set
get_longest_paths(trie_tree, results) # uses trie trie to ignore chains
# which are part of a longer chain
final_result = sorted(results, key = lambda x: (len(x), x), reverse = True)
print(final_result)
Вывод
[(2, 3, 4, 5, 6, 7, 11, 13, 14, 20, 21, 24),
(2, 3, 4, 5, 6, 7, 11, 13, 14, 20, 21,22),
(1, 3, 4, 5, 6, 7, 11, 13, 14, 20, 21, 24),
(1, 3, 4, 5, 6, 7, 11, 13, 14, 20,21, 22),
(3, 4, 5, 6, 7, 11, 13, 14, 20, 21, 24),
(3, 4, 5, 6, 7, 11, 13, 14, 20, 21, 22),
(2, 3, 4, 5, 6, 7, 11, 13, 14, 19, 22),
(2, 3, 4, 5, 6, 7, 11, 13, 14, 16, 18),
(1, 3, 4, 5, 6, 7, 11, 13, 14, 19, 22),
(1, 3, 4, 5, 6, 7, 11, 13, 14, 16, 18),
(4, 5, 6, 7, 11, 13, 14, 20, 21, 24),
(4, 5, 6, 7, 11, 13, 14, 20, 21, 22),
(3, 4, 5, 6, 7, 11, 13, 14, 19, 22),
(3, 4, 5, 6, 7, 11, 13, 14, 16, 18),
(2, 3, 4, 8, 11, 13, 14, 20, 21, 24),
(2, 3, 4, 8, 11, 13, 14, 20, 21, 22),
(2, 3, 4, 8, 9, 13, 14, 20, 21, 24),
(2, 3, 4, 8, 9, 13, 14, 20, 21, 22),
(2, 3, 4, 5, 6, 7, 12, 15, 17, 23),
(2, 3, 4, 5, 6, 7, 12, 15, 17, 18),
(1, 3, 4, 8, 11, 13, 14, 20, 21, 24),
(1, 3, 4, 8, 11, 13, 14, 20, 21, 22),
(1, 3, 4, 8, 9, 13, 14, 20, 21, 24),
(1, 3, 4, 8, 9, 13,14, 20, 21, 22),
(1, 3, 4, 5, 6, 7, 12, 15, 17, 23),
(1, 3, 4, 5, 6, 7, 12, 15, 17,18),
(5, 6, 7, 11, 13, 14, 20, 21, 24),
(5, 6, 7, 11, 13, 14, 20, 21, 22),
(4, 5, 6, 7, 11, 13, 14, 19, 22),
(4, 5, 6, 7, 11, 13, 14, 16, 18),
(3, 4, 8, 11, 13, 14, 20, 21, 24),
(3, 4, 8, 11, 13, 14, 20, 21, 22),
(3, 4, 8, 9, 13, 14, 20, 21, 24),
(3, 4, 8, 9, 13, 14, 20, 21, 22),
(3, 4, 5, 6, 7, 12, 15, 17, 23),
(3, 4, 5, 6, 7, 12, 15, 17, 18),
(2, 3, 4, 8, 11, 13, 14, 19, 22),
(2, 3, 4, 8, 11, 13, 14, 16, 18),
(2, 3, 4, 8, 9, 13, 14, 19, 22),
(2, 3, 4, 8, 9, 13, 14, 16, 18),
(2, 3, 4, 5, 6, 7, 12,15, 22),
(1, 3, 4, 8, 11, 13, 14, 19, 22),
(1, 3, 4, 8, 11, 13, 14, 16, 18),
(1, 3,4, 8, 9, 13, 14, 19, 22),
(1, 3, 4, 8, 9, 13, 14, 16, 18),
(1, 3, 4, 5, 6, 7, 12, 15, 22),
(6, 7, 11, 13, 14, 20, 21, 24),
(6, 7, 11, 13, 14, 20, 21, 22),
(5, 6, 7, 11, 13, 14, 19, 22),
(5, 6, 7, 11, 13, 14, 16, 18),
(4, 8, 11, 13, 14, 20, 21, 24),
(4, 8, 11, 13, 14, 20, 21, 22),
(4, 8, 9, 13, 14, 20, 21, 24),
(4, 8, 9, 13, 14, 20, 21, 22),
(4, 5, 6, 7, 12, 15, 17, 23),
(4, 5, 6, 7, 12, 15, 17, 18),
(3, 4, 8, 11, 13, 14, 19, 22),
(3, 4, 8, 11, 13, 14, 16, 18),
(3, 4, 8, 9, 13, 14, 19, 22),
(3, 4, 8, 9, 13, 14, 16, 18),
(3, 4, 5, 6, 7, 12, 15, 22),
(8, 11, 13, 14, 20, 21, 24),
(8, 11, 13, 14, 20, 21, 22),
(8, 9, 13, 14, 20, 21, 24),
(8, 9, 13, 14, 20, 21, 22),
(7,11, 13, 14, 20, 21, 24),
(7, 11, 13, 14, 20, 21, 22),
(6, 7, 11, 13, 14, 19, 22),
(6, 7, 11, 13, 14, 16, 18),
(5, 6, 7, 12, 15, 17, 23),
(5, 6, 7, 12, 15, 17, 18),
(4,8, 11, 13, 14, 19, 22),
(4, 8, 11, 13, 14, 16, 18),
(4, 8, 9, 13, 14, 19, 22),
(4, 8, 9, 13, 14, 16, 18),
(4, 5, 6, 7, 12, 15, 22),
(11, 13, 14, 20, 21, 24),
(11, 13, 14, 20, 21, 22),
(9, 13, 14, 20, 21, 24),
(9, 13, 14, 20, 21, 22),
(8, 11, 13, 14, 19, 22),
(8, 11, 13, 14, 16, 18),
(8, 9, 13, 14, 19, 22),
(8, 9, 13, 14, 16, 18),
(7,11, 13, 14, 19, 22),
(7, 11, 13, 14, 16, 18),
(6, 7, 12, 15, 17, 23),
(6, 7, 12, 15, 17, 18),
(5, 6, 7, 12, 15, 22),
(2, 3, 4, 8, 9, 10),
(2, 3, 4, 5, 6, 10),
(1, 3, 4, 8, 9, 10),
(1, 3, 4, 5, 6, 10),
(13, 14, 20, 21, 24),
(13, 14, 20, 21, 22),
(11, 13, 14, 19, 22),
(11, 13, 14, 16, 18),
(9, 13, 14, 19, 22),
(9, 13, 14, 16, 18),
(7, 12, 15, 17, 23),
(7, 12, 15, 17, 18),
(6, 7, 12, 15, 22),
(3, 4, 8, 9, 10),
(3, 4, 5, 6, 10),
(14, 20, 21, 24),
(14, 20, 21, 22),
(13, 14, 19, 22),
(13, 14, 16, 18),
(12, 15, 17, 23),
(12, 15, 17, 18),
(7, 12, 15, 22),
(4, 8, 9, 10),
(4, 5, 6, 10),
(20, 21, 24),
(20, 21, 22),
(15, 17, 23),
(15, 17, 18),
(14, 19, 22),
(14, 16, 18),
(12, 15, 22),
(8, 9, 10),
(5, 6, 10),
(21, 24),
(21, 22),
(19, 22),
(17, 23),
(17, 18),
(16, 18),
(15, 22),
(9, 10),
(6, 10)]