Example #1
0
    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()
Example #2
0
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()
Example #3
0
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
Example #4
0
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
Example #5
0
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