Example #1
0
 def test_006_NotAGraph(self):
     """ findAllPathsTest_006_NotAGraph: Tests cases where inputs are not graphs """
     # Objects lacking 'has_key' attribute, raise error when try and use nodes as keys
     self.assertRaises(AttributeError, xayacore.findAllPaths,['This', 'Is', 'A', 'List'], 'This', 'List')
     self.assertRaises(AttributeError, xayacore.findAllPaths, 'This is a String', 'This', 'String')
     # Wrong Object, No Nodes, give an Empty Graph.
     #NOTE: CONSIDER EXPLICITLY RAISING AN ERROR HERE
     self.assertEqual(xayacore.findAllPaths(['This', 'Is', 'A', 'List']), {})
     self.assertEqual(xayacore.findAllPaths('This is a String'), {})
Example #2
0
def findComponents (graph = {}):
    """
    Given a directed graph (network) findComponents returns a list of isolated
    "Islands in the Network" or components. Within an island, there are paths
    to nodes. Across islands, there is not direct path.
    General Algorithm:
    
    1. Define the keyset (the parent nodes in a set of directed arcs)
    2. Assign each parent node and its direct children (arcs) to a new component
    3. Iterate through the node-set and combine parent nodes that have paths, including their child arcs
        (These are the candidate components)
    4. Remove candidate components that are subsets of each other.
    5. Create final components from the remaining candidate components
        (and do a check on the results of loops -- note this may be a bug in the path-finding algorithm)
    6. Return the final list of components 
    """
    
    # Define the keyset
    keys = graph.keys()
    keys2 = copy.deepcopy(keys)
    
    # For each key,  assign arcs to a new component.
    compgraph = {}
    compkey = 0
    for key in keys:
        compkey = compkey +1
        compgraph[compkey] = [key] + graph[key]
        
        # Iterate through keys, and combine pairs of keys with a path between them
        # These are the 'candidate' components
        for dkey in keys2:
            if key <> dkey:
                if xayacore.findAllPaths(graph, key, dkey) <> {}:
                    compgraph[compkey] =  [key] + graph[key]  + graph[dkey]
                    keys2.remove(key) # remove the key that has been combined

    # Remove candidate components that are simply subsets of each other
    compkeys = compgraph.keys()
    compkeys2 = copy.deepcopy(compkeys)
    for key in compkeys:
        for nextkey in compkeys:
            if key <> nextkey:
                set1 = set(compgraph[key])
                set2 = set(compgraph[nextkey])
                if set1.difference(set2) == set([]) and set2.difference(set1) <> set([]):
                    compkeys2.remove(key)
                    
                            
    # Create Final components                        
    finalcomp = {}
    finalcompkey = 0
    for key in compkeys2:
        # Check on and remove the output from loops -- same element is repeated so list <> set cardinality
        if len(compgraph[key]) == len(set(compgraph[key])): 
            finalcompkey = finalcompkey + 1
            finalcomp[finalcompkey] = compgraph[key]
   

    
    return  finalcomp
Example #3
0
 def test_001_NormalCase(self):
     """ findAllPathsTest_001_Normal Case:  Tests cases where non-cyclic paths found """
     # Correctly finds all paths for the graph structure used in GvR's "Python Patterns -- Implementing Graphs"
     self.assertEqual(xayacore.findAllPaths(self.guidoGraph,'A','C'), {"['A', 'C']": ['A', 'C'],
                      "['A', 'B', 'C']": ['A', 'B', 'C'],
                      "['A', 'B', 'D', 'C']": ['A', 'B', 'D', 'C']})
     # Misses "corner case" where there is a second path right through the finish node C (a cycle):
         # E-->F-->C-->D-->C
     self.assertEqual(xayacore.findAllPaths(self.guidoGraph,'E','C'), {"['E', 'F', 'C']": ['E', 'F', 'C']})
     # Correctly finds acyclic paths on two branches from start node G in a graph with cycles
     self.assertEqual(xayacore.findAllPaths(self.cycleGraph,'g','a'), {"['g', 'h', 'c', 'd', 'a']": ['g', 'h', 'c', 'd', 'a'],
                                                                            "['g', 'd', 'a']": ['g', 'd', 'a']})
     #Misses "corner case" where there is a second path through the start node a (another cycle):
         # a-->b-->c-->d-->a-->e--f 
     self.assertEqual(xayacore.findAllPaths(self.cycleGraph, 'a', 'f'), {"['a', 'e', 'f']": ['a', 'e', 'f']})
     # Two examples of paths through a database schema modelling forest inventory data relationships
     self.assertEqual(xayacore.findAllPaths(self.forestryDBSchema, 'StandStructure', 'GrowthModelData'), {"['StandStructure', 'Plot', 'Tree', 'GrowthModelData']": ['StandStructure', 'Plot', 'Tree', 'GrowthModelData'],
                                                                                                     "['StandStructure', 'Polygon', 'Plot', 'Tree', 'GrowthModelData']": ['StandStructure', 'Polygon', 'Plot', 'Tree', 'GrowthModelData']})
     self.assertEqual( xayacore.findAllPaths(self.forestryDBSchema, 'Plot', 'StandTable'), {"['Plot', 'PlotMeasurements', 'StandTable']": ['Plot', 'PlotMeasurements', 'StandTable']})
     # Two examples of opening a safe. The costly way and the lucky way.
     self.assertEqual(xayacore.findAllPaths(self.safeattackTree, 'Bribe', 'Open Safe'), {"['Bribe', 'Get Combo from Target', 'Learn Combo', 'Open Safe']": ['Bribe', 'Get Combo from Target', 'Learn Combo', 'Open Safe']})
     self.assertEqual(xayacore.findAllPaths(self.safeattackTree, 'Find Written Combo', 'Open Safe'), {"['Find Written Combo', 'Learn Combo', 'Open Safe']": ['Find Written Combo', 'Learn Combo', 'Open Safe']})
Example #4
0
 def test_005_NoInputParams(self):
     """  findAllPathsTest_005_NoInputParams: Tests case where defaults inputs are taken """
     self.assertEqual(xayacore.findAllPaths(), {})
Example #5
0
 def test_004_StartIsEnd(self):
     """  findAllPathsTest_004_StartIsEnd: Tests case of a single node path """
     self.assertEqual(xayacore.findAllPaths(self.guidoGraph, 'C', 'C'), {"['C']": ['C']})
Example #6
0
 def test_003_NoSuchNode(self):
     """ findAllPathsTest_003_NoSuchNode: Tests cases where start or end node or both do not exist """
     self.assertEqual(xayacore.findAllPaths(self.guidoGraph, 'X', 'A'), {})
     self.assertEqual(xayacore.findAllPaths(self.guidoGraph, 'E', 'X'), {})
     self.assertEqual(xayacore.findAllPaths(self.guidoGraph, 'X', 'Y'), {})
Example #7
0
 def test_002_NoSuchPath(self):
     """ findAllPathsTest_002_NoSuchPath: Tests cases where the path does not exist   """
     # No Path, only one root node
     self.assertEqual(xayacore.findAllPaths(self.guidoGraph, 'E', 'B'), {})
     # No path, as both nodes are roots
     self.assertEqual(xayacore.findAllPaths(self.guidoGraph, 'E', 'A'), {})