def to_pert_graph(self): """Build PertGraph from nodes table (creating dummy activities for parallel activities)""" pm_graph = pert.PertMultigraph() for i in range(self.num_real_activities): pm_graph.add_arc((self.node_list[i][0], self.node_list[i][1]), (self.activity_names[i], False)) for i in range(self.num_real_activities, len(self.node_list)): pm_graph.add_arc((self.node_list[i][0], self.node_list[i][1]), (self.activity_names[i], True)) return pm_graph.to_directed_graph()
def cohen_sadeh(prelations): """ Build graph PERT using Cohen-Sadeh algorithm Note: the original algorithm does not consider parallel activities (creates a multigraph) prelations = {'activity': ['predecesor1', 'predecesor2'...} return graph pert.Pert() """ # Adaptation to avoid multiple end nodes successors = graph.reversed_prelation_table(prelations) end_act = graph.ending_activities(successors) #Step 1. Construct work table with Immediate Predecessors Columns = namedlist.namedlist('Columns', ['pre', 'blocked', 'dummy', 'suc', 'start_node', 'end_node']) # [0 Predecesors, 1 Blocked, 2 Dummy, 3 Successors, 4 Start node, 5 End node] # Blocked = (False or Activity with same precedents) work_table = {} for act, predecessors in prelations.items(): work_table[act] = Columns(set(predecessors), False, False, None, None, None) # print "\n--- Step 1 ---" # __print_work_table(work_table) #Step 2. Identify Identical Precedence Constraint of Diferent Activities visited_pred = {} for act, columns in work_table.items(): pred = frozenset(columns.pre) if pred not in visited_pred: visited_pred[pred] = act else: columns.blocked = visited_pred[pred] # print "\n--- Step 2 ---" # __print_work_table(work_table) #Step 3. Identify Necessary Dummy Arcs dups = set() visited_act = set() for columns in work_table.values(): if not columns.blocked: for act in columns.pre: if act in visited_act: dups.add(act) visited_act.add(act) # print "\n--- Step 3.1 ---" # print dups #Step 3.2, 3.3 and 4. Create rows and information for Dummy Arcs dummy_counter = collections.Counter() for _, columns in work_table.items(): # Avoid blocked if not columns.blocked: predecessors = columns.pre if len(predecessors) > 1: for pre in list(predecessors): if pre in dups: predecessors.remove(pre) dummy_name = pre + '-d' + str(dummy_counter[pre]) dummy_counter[pre] += 1 predecessors.add(dummy_name) work_table[dummy_name] = Columns(set([pre]), False, True, None, None, None) # print "\n--- Step 4 ---" # __print_work_table(work_table) #Step 5. Creating nodes node = 0 # instead of 0, can start at 100 to avoid confusion with activities named with numbers when debugging for act, columns in work_table.items(): if not columns.dummy and not columns.blocked: columns.start_node = node node += 1 # print "\n--- Step 5a ---" # __print_work_table(work_table) for act, columns in work_table.items(): if not columns.dummy and columns.blocked: columns.start_node = work_table[columns.blocked].start_node # print "\n--- Step 5b ---" # __print_work_table(work_table) #Step 6. Associate activities with their end nodes # (a) find one non-dummy successor for each activity for act, columns in work_table.items(): for suc, suc_columns in work_table.items(): if not suc_columns.dummy and not suc_columns.blocked: if act in suc_columns.pre: columns.suc = suc break # print "\n--- Step 6a ---" # __print_work_table(work_table) # (b) find end nodes graph_end_node = node # Reserve one node for graph end node += 1 for act, columns in work_table.items(): suc = columns.suc if suc: columns.end_node = work_table[suc].start_node else: # Create needed end nodes, avoiding multiple graph end nodes (adaptation) if act in end_act: columns.end_node = graph_end_node else: columns.end_node = node node += 1 # print "\n--- Step 6b ---" # __print_work_table(work_table) #Step 7. Associate dummy arcs with start nodes for act, columns in work_table.items(): if columns.dummy: pred = iter(columns.pre).next() start_node = work_table[pred].end_node columns.start_node = start_node # print "\n--- Step 7 ---" # __print_work_table(work_table) #Step 8. Generate the graph pm_graph = pert.PertMultigraph() for act, columns in work_table.items(): _, _, dummy, _, start, end = columns pm_graph.add_arc((start, end), (act, dummy)) p_graph = pm_graph.to_directed_graph() return p_graph.renumerar()
def sysloOptimal(prelations): """ Build a PERT graph using Syslo algorithm return p_graph pert.PertMultigraph() """ # Adaptation to avoid multiple end nodes successors = graph.reversed_prelation_table(prelations) end_act = graph.ending_activities(successors) #Kahn1962.check_cycles(successors) prela = successors.copy() Columns = namedlist.namedlist('Columns', ['pre', 'blocked', 'dummy', 'suc', 'start_node', 'end_node']) # [0 Predecesors, 1 Blocked, 2 Dummy, 3 Successors, 4 Start node, 5 End node] # Blocked = (False or Activity with same precedents) #Step 0. grafo = {} alt = graph.successors2precedents(successors) grafo = graph.successors2precedents(syslo_table.syslo(prela, grafo, alt)) #Step 1. Save the new prelation table in a work table work_table = {} for act, pre in grafo.items(): if not act in prelations: work_table[act] = Columns(pre, False, True, None, None, None) else: work_table[act] = Columns(pre, False, False, None, None, None) #Step 2. Identify Dummy Activities And Identical Precedence Constraint of Diferent Activities visited_pred = {} for act, columns in work_table.items(): pred = frozenset(columns.pre) if pred not in visited_pred: visited_pred[pred] = act else: columns.blocked = visited_pred[pred] #Step 3. Creating nodes # (a) find start nodes node = 0 # instead of 0, can start at 100 to avoid confusion with activities named with numbers when debugging for act, columns in work_table.items(): if not columns.blocked: columns.start_node = node node += 1 if columns.blocked: columns.start_node = work_table[columns.blocked].start_node # Associate activities with their end nodes for suc, suc_columns in work_table.items(): if not suc_columns.blocked: if act in suc_columns.pre: columns.suc = suc break # (b) find end nodes graph_end_node = node # Reserve one node for graph end node += 1 for act, columns in work_table.items(): suc = columns.suc if suc: columns.end_node = work_table[suc].start_node else: # Create needed end nodes, avoiding multiple graph end nodes (adaptation) if act in end_act: columns.end_node = graph_end_node else: columns.end_node = node node += 1 # Step 4. Remove redundancy of dummy activities vis = [] for act, columns in work_table.items(): if columns.dummy == False: for q in work_table[act].pre: for w in work_table[act].pre: if q in work_table and w in work_table: if q != w and work_table[q].pre == work_table[w].pre and work_table[q].dummy==True and work_table[w].dummy==True: if w not in vis: del work_table[w] vis.append(q) #Step 5. Generate the graph pm_graph = pert.PertMultigraph() for act, columns in work_table.items(): _, _, dummy, _, start, end = columns pm_graph.add_arc((start, end), (act, dummy)) p_graph = pm_graph.to_directed_graph() return p_graph return p_graph
def sysloPolynomial(prelations): # Adaptation to avoid multiple end nodes successors = graph.reversed_prelation_table(prelations) end_act = graph.ending_activities(successors) #Step 0. Construct work table with Immediate Predecessors Columns = namedlist.namedlist('Columns', ['pre', 'blocked', 'dummy', 'suc', 'start_node', 'end_node']) # [0 Predecesors, 1 Blocked, 2 Dummy, 3 Successors, 4 Start node, 5 End node] # Blocked = (False or Activity with same precedents) #Step 1. Create the improper covers work_table_pol = makeCover(prelations, successors) # Step 2. Syslo Polynomial algorithm final = successors.copy() visited = [] for act, pred in prelations.items(): for v in pred: for u in pred: if u != v and successors[v] != successors[u] and act not in visited: # Find activity in the improper cover table for key, value in work_table_pol.items(): if act in value.w: w = value.w # Find each row that belongs to the predecessors of activity for key, value in work_table_pol.items(): if set(value.u).issubset(prelations[act]) and value.u: vertex = set(value.u).pop() # Compare successors of a row with the improper cover of the activity if successors[vertex] != w: for q in value.u: if final.has_key(q): final[q] = list((set(final[q]) - set(w) | set([str(vertex) + separator + str(act)])) - set([act])) else: final[q] = list(set(successors[q]) - set(w) | set([str(vertex) + separator + str(act)])) final[str(vertex) + separator + str(act)] = [act] for l in w: visited.append(l) final = graph.successors2precedents(final) work_table = {} for act, pred in final.items(): work_table[act] = Columns(pred, False, False, None, None, None) if act not in prelations: work_table[act].dummy = True #Step 3. Identify Dummy Activities And Identical Precedence Constraint of Diferent Activities visited_pred = {} for act, columns in work_table.items(): pred = frozenset(columns.pre) if pred not in visited_pred: visited_pred[pred] = act else: columns.blocked = visited_pred[pred] #Step 4. Creating nodes # (a) find start nodes node = 0 # instead of 0, can start at 100 to avoid confusion with activities named with numbers when debugging for act, columns in work_table.items(): if not columns.blocked: columns.start_node = node node += 1 if columns.blocked: columns.start_node = work_table[columns.blocked].start_node # Associate activities with their end nodes for suc, suc_columns in work_table.items(): if not suc_columns.blocked: if act in suc_columns.pre: columns.suc = suc break # (b) find end nodes graph_end_node = node # Reserve one node for graph end node += 1 pm_graph = pert.PertMultigraph() for act, columns in work_table.items(): suc = columns.suc if suc: columns.end_node = work_table[suc].start_node else: # Create needed end nodes, avoiding multiple graph end nodes (adaptation) if act in end_act: columns.end_node = node else: columns.end_node = graph_end_node node += 1 # Generate the graph _, _, dummy, _, start, end = columns pm_graph.add_arc((start, end), (act, dummy)) p_graph = pm_graph.to_directed_graph() return p_graph
def mouhoub(prelations): """ Build a PERT graph using Mouhoub algorithm prelations = {'activity': ['predecesor1', 'predecesor2'...} return p_graph pert.PertMultigraph() """ Columns = namedlist.namedlist('Columns', ['pre', 'su', 'blocked', 'dummy', 'suc', 'start_node', 'end_node', 'aux']) # [0 Predecesors, 1 Successors, 2 Blocked, 3 Dummy, 4 Blocked successor, 5 Start node, 6 End node, 7 Auxiliar ] # Blocked = (False or Activity with same precedents) # Adaptation to avoid multiple end nodes successors = graph.reversed_prelation_table(prelations) successors_copy = graph.reversed_prelation_table(prelations.copy()) end_act = graph.ending_activities(successors) # Step 0. Remove Z Configuration. Update the prelation table in complete_bipartite dictionary complete_bipartite = successors complete_bipartite.update(zConfiguration.zconf(successors)) # STEPS TO BUILD THE PERT GRAPH #Step 1. Save the prelations in the work table complete_bipartite = graph.successors2precedents(complete_bipartite) work_table = {} for act, sucesores in complete_bipartite.items(): work_table[act] = Columns(set(sucesores), successors[act], None, False, None, None, None, None) if act not in prelations: work_table[act].dummy = True #Step 2. Identify Identical Precedence Constraint of Diferent Activities visited_pred = {} for act, columns in work_table.items(): pred = frozenset(columns.pre) if pred not in visited_pred: visited_pred[pred] = act else: columns.blocked = visited_pred[pred] #Step 3. Creating nodes # (a) Find start nodes node = 0 # instead of 0, can start at 100 to avoid confusion with activities named with numbers when debugging for act, columns in work_table.items(): if not columns.blocked: columns.start_node = node node += 1 if columns.blocked: columns.start_node = work_table[columns.blocked].start_node # Associate activities with their end nodes for suc, suc_columns in work_table.items(): if not suc_columns.blocked: if act in suc_columns.pre: columns.suc = suc break # (b) Find end nodes graph_end_node = node # Reserve one node for graph end node += 1 for act, columns in work_table.items(): suc = columns.suc if suc: columns.end_node = work_table[suc].start_node else: # Create needed end nodes, avoiding multiple graph end nodes (adaptation) if act in end_act: columns.end_node = graph_end_node else: columns.end_node = node node += 1 #Step 4. MOUHOUB algorithm rules to remove extra dummy activities mouhoubRules.rule_1(successors_copy, work_table) G2 = mouhoubRules.rule_2(prelations, work_table) G3 = mouhoubRules.rule_3(G2, work_table) G4 = mouhoubRules.rule_4(G3, work_table) G5_6 = mouhoubRules.rule_5_6(successors_copy, work_table, G4) G3a = mouhoubRules.rule_3(G5_6, work_table) G4a = mouhoubRules.rule_4(G3a, work_table) G7 = mouhoubRules.rule_7(successors_copy, successors, G4a, node) work_table_final = {} for act, sucesores in G7.items(): work_table_final[act] = Columns([], [], [], sucesores.dummy, sucesores.suc, sucesores.start_node, sucesores.end_node, []) #Step 5. Delete Dummy Cycles for act, sucesores in work_table_final.items(): for act2, sucesores2 in work_table_final.items(): if act != act2: if sucesores.end_node == sucesores2.end_node and sucesores.start_node == sucesores2.start_node: if act not in successors: del work_table_final[act] #Step 6. Generate the graph pm_graph = pert.PertMultigraph() for act, columns in work_table_final.items(): _, _, _, dummy, _, start, end, _ = columns pm_graph.add_arc((start, end), (act, dummy)) p_graph = pm_graph.to_directed_graph() return p_graph