Search code examples
pythondirected-acyclic-graphs

Check if directed acyclic graph is feasible


For a given directed acyclic graph G I'm looking for a way to verify if a list L, containing the activities, is precedence feasible. A resource-saving solution would be nice since the size of G may increase drastically.

Example:

enter image description here

G = {0: [], 1: [0], 2: [0], 3: [0], 4: [1], 5: [1], 6: [4], 7: [4], 8: [3,6,7], 9: [2,5,6], 10: [2,5], 11: [8,9,10]}

Now this list

L1 = [0, 1, 2, 3, 4, 5, 10, 6, 7, 9, 8, 11]

for example is feasible but

L2 = [1, 0, 2, 3, 4, 10, 5, 6, 7, 9, 8, 11]

is not because activity 0 is a predecessor of 1 and activity 5 is a predecessor of 10.


Solution

  • As I understand the question you want to check whether a given ordering of nodes is consistent with partial ordering defined by the edges in the graph. Maybe I'm missing something, but for this it should be enough to check for all edges a ---> b that the index of a in the list is lower than the index of b. If you create a dictionary mapping elements to their positions first, the complexity for this will be only O(e), e being the number of edges.

    def check(g, l):
        pos = {x: i for i, x in enumerate(l)} # for O(1) index
        return all(pos[a] < pos[b] for b in g for a in g[b])
    
    G = {0: [], 1: [0], 2: [0], 3: [0], 4: [1], 5: [1], 6: [4],
         7: [4], 8: [3,6,7], 9: [2,5,6], 10: [2,5], 11: [8,9,10]}
    L1 = [0, 1, 2, 3, 4, 5, 10, 6, 7, 9, 8, 11]
    L2 = [1, 0, 2, 3, 4, 10, 5, 6, 7, 9, 8, 11]
    print(check(G, L1)) # True
    print(check(G, L2)) # False