def sharma1998ext(precedents): """ Generates a AOA graph (PERT) from successors table Algorithm sharma1998 extended returns: pert.Pert() graph data structure """ pert_graph = pert.Pert() successors = graph.reversed_prelation_table(precedents) # Close the graph (not in sharma1998) origin = pert_graph.nextNodeNumber() pert_graph.add_node(origin) dest = pert_graph.nextNodeNumber() pert_graph.add_node(dest) begin_act = graph.begining_activities(successors) end_act = graph.ending_activities(successors) begin_end_act = begin_act.intersection(end_act) # -Creates a common node for starting activities for act in begin_act - begin_end_act: pert_graph.addActivity(act, origin) # -Creates a common node for ending activities for act in end_act - begin_end_act: pert_graph.addActivity(act, origin=None, destination=dest) # -Deals with begin-end activities if begin_end_act: act = begin_end_act.pop() pert_graph.addActivity(act, origin, dest) for act in begin_end_act: o, d = pert_graph.addActivity(act, origin) pert_graph.addActivity("seDummy", d, dest, dummy=True) # Sharma1998 algorithm for act in successors: #print "Processing", act, pert_graph #window.images.append( graph.pert2image(pert_graph) ) if not pert_graph.activityArc(act): pert_graph.addActivity(act) #window.images.append( graph.pert2image(pert_graph) ) a_origin, a_dest = pert_graph.activityArc(act) #print '(', a_origin, a_dest, ')' for pre in precedents[act]: #print pert_graph.successors #print pre, pre in pert_graph.inActivitiesR(graph.reversed_prelation_table(pert_graph.successors), a_origin) if pre not in pert_graph.inActivitiesR(a_origin): if not pert_graph.activityArc(pre): pert_graph.addActivity(pre) #window.images.append( graph.pert2image(pert_graph) ) pert_graph.makePrelation(pre, act) a_origin, a_dest = pert_graph.activityArc(act) return pert_graph.renumerar()
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 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