Example #1
0
    def pathSearch(self, n1, n2=None, edgecb=None, tocb=None):
        '''
        Search for the shortest path from one node to another
        with the option to filter based on edges using
        edgecb.  edgecb should be a function:

        def myedgecb(graph, eid, n1, n2, depth)

        which returns True if it's OK to traverse this node
        in the search.

        Additionally, n2 may be None and the caller may specify
        tocb with a function such as:

        def mytocb(graph, nid)

        which must return True on finding the target node

        Returns a list of edge ids...
        '''

        if n2 is None and tocb is None:
            raise Exception('You must use either n2 or tocb!')

        root = vg_pathcore.newPathNode(nid=n1, eid=None)

        todo = [
            (root, 0),
        ]

        # FIXME make this a deque so it can be FIFO
        while len(todo):

            pnode, depth = todo.pop()  # popleft()
            ppnode, pkids, pprops = pnode

            nid = pprops.get('nid')
            for edge in self.getRefsFromByNid(nid):

                eid, srcid, dstid, eprops = edge

                if vg_pathcore.isPathLoop(pnode, 'nid', dstid):
                    continue

                # Check if the callback is present and likes us...
                if edgecb is not None:
                    if not edgecb(self, edge, depth):
                        continue

                # Are we the match?
                match = False
                if dstid == n2:
                    match = True

                if tocb and tocb(self, dstid):
                    match = True

                if match:

                    m = vg_pathcore.newPathNode(pnode, nid=dstid, eid=eid)
                    path = vg_pathcore.getPathToNode(m)

                    ret = []
                    for ppnode, pkids, pprops in path:
                        eid = pprops.get('eid')
                        if eid is not None:
                            ret.append(eid)

                    yield ret

                # Add the next set of choices to evaluate.
                branch = vg_pathcore.newPathNode(pnode, nid=dstid, eid=eid)
                todo.append((branch, depth + 1))
def getCodePaths(vw, fromva, tova, trim=True):
    """
    Return a list of paths, where each path is a list
    of code blocks from fromva to tova.

    Usage: getCodePaths(vw, <fromva>, <tova>) -> [ [frblock, ..., toblock], ...]

    NOTE: "trim" causes an optimization which may not reveal *all* the paths,
          but is much faster to run.  It will never return no paths when there
          are some, but may not return all of them... (based on path overlap)
    """

    done = {}
    res = []

    frcb = vw.getCodeBlock(fromva)
    tocb = vw.getCodeBlock(tova)
    if frcb == None:
        raise viv_exc.InvalidLocation(fromva)
    if tocb == None:
        raise viv_exc.InvalidLocation(tova)

    frva = frcb[0]  # For compare speed

    root = vg_path.newPathNode(cb=tocb, cbva=tocb[0])
    todo = [
        root,
    ]
    done[tova] = tocb

    cbcache = {}

    while len(todo):

        path = todo.pop()
        cbva = vg_path.getNodeProp(path, 'cbva')

        codeblocks = cbcache.get(cbva)
        if codeblocks == None:
            codeblocks = getCodeFlow(vw, cbva)
            cbcache[cbva] = codeblocks

        for cblock in codeblocks:

            bva, bsize, bfva = cblock

            # Don't follow loops...
            if vg_path.isPathLoop(path, 'cbva', bva):
                continue

            # If we have been here before and it's *not* the answer,
            # skip out...
            if trim and done.get(bva) != None: continue

            done[bva] = cblock

            newpath = vg_path.newPathNode(parent=path, cb=cblock, cbva=bva)

            # If this one is a match, we don't need to
            # track past it.  Also, put it in the results list
            # so we don't have to do it later....
            if bva == frva:
                res.append(newpath)
            else:
                todo.append(newpath)

    # Now...  if we have some results, lets build the block list.
    ret = []
    for cpath in res:
        fullpath = vg_path.getPathToNode(cpath)
        # We actually do it by inbound references, so reverse the result!
        fullpath.reverse()
        ret.append([vg_path.getNodeProp(path, 'cb') for path in fullpath])

    return ret
Example #3
0
    def pathSearch(self, n1, n2=None, edgecb=None, tocb=None):
        '''
        Search for the shortest path from one node to another
        with the option to filter based on edges using
        edgecb.  edgecb should be a function:

        def myedgecb(graph, eid, n1, n2, depth)

        which returns True if it's OK to traverse this node
        in the search.

        Additionally, n2 may be None and the caller may specify
        tocb with a function such as:

        def mytocb(graph, nid)

        which must return True on finding the target node

        Returns a list of edge ids...
        '''

        if n2 == None and tocb == None:
            raise Exception('You must use either n2 or tocb!')

        root = vg_pathcore.newPathNode(nid=n1, eid=None)

        todo = [(root, 0),]

        # FIXME make this a deque so it can be FIFO
        while len(todo):

            pnode,depth = todo.pop() # popleft()
            ppnode, pkids, pprops = pnode

            nid = pprops.get('nid')
            for edge in self.getRefsFromByNid(nid):

                eid, srcid, dstid, eprops = edge

                if vg_pathcore.isPathLoop(pnode, 'nid', dstid):
                    continue

                # Check if the callback is present and likes us...
                if edgecb != None:
                    if not edgecb(self, edge, depth):
                        continue

                # Are we the match?
                match = False
                if dstid == n2:
                    match = True

                if tocb and tocb(self, dstid):
                    match = True

                if match:

                    m = vg_pathcore.newPathNode(pnode, nid=dstid, eid=eid)
                    path = vg_pathcore.getPathToNode(m)

                    ret = []
                    for ppnode, pkids, pprops in path:
                        eid = pprops.get('eid')
                        if eid != None:
                            ret.append(eid)

                    yield ret

                # Add the next set of choices to evaluate.
                branch = vg_pathcore.newPathNode(pnode, nid=dstid, eid=eid)
                todo.append((branch, depth+1))
Example #4
0
def getCodePaths(vw, fromva, tova, trim=True):
    """
    Return a list of paths, where each path is a list
    of code blocks from fromva to tova.

    Usage: getCodePaths(vw, <fromva>, <tova>) -> [ [frblock, ..., toblock], ...]

    NOTE: "trim" causes an optimization which may not reveal *all* the paths,
          but is much faster to run.  It will never return no paths when there
          are some, but may not return all of them... (based on path overlap)
    """

    done = {}
    res = []

    frcb = vw.getCodeBlock(fromva)
    tocb = vw.getCodeBlock(tova)
    if frcb == None:
        raise viv_exc.InvalidLocation(fromva)
    if tocb == None:
        raise viv_exc.InvalidLocation(tova)

    frva = frcb[0] # For compare speed

    root = vg_path.newPathNode(cb=tocb, cbva=tocb[0])
    todo = [root, ]
    done[tova] = tocb

    cbcache = {}

    while len(todo):

        path = todo.pop()
        cbva = vg_path.getNodeProp(path, 'cbva')

        codeblocks = cbcache.get(cbva)
        if codeblocks == None:
            codeblocks = getCodeFlow(vw, cbva)
            cbcache[cbva] = codeblocks

        for cblock in codeblocks:

            bva,bsize,bfva = cblock

            # Don't follow loops...
            if vg_path.isPathLoop(path, 'cbva', bva):
                continue

            # If we have been here before and it's *not* the answer,
            # skip out...
            if trim and done.get(bva) != None: continue

            done[bva] = cblock

            newpath = vg_path.newPathNode(parent=path, cb=cblock, cbva=bva)

            # If this one is a match, we don't need to
            # track past it.  Also, put it in the results list
            # so we don't have to do it later....
            if bva == frva:
                res.append(newpath)
            else:
                todo.append(newpath)


    # Now...  if we have some results, lets build the block list.
    ret = []
    for cpath in res:
        fullpath = vg_path.getPathToNode(cpath)
        # We actually do it by inbound references, so reverse the result!
        fullpath.reverse()
        ret.append([vg_path.getNodeProp(path, 'cb') for path in fullpath])

    return ret