Example #1
0
    def find_paths(self,
                   input_set,
                   target,
                   max_paths=1,
                   max_path_length=5,
                   loop=False):
        """Check for a source/target path in the model.

        Parameters
        ----------
        input_set : list or None
            A list of potenital sources or None if the test statement subject
            is None.
        target : tuple
            Tuple representing the target node (usually common target node).
        max_paths : int
            The maximum number of specific paths to return.
        max_path_length : int
            The maximum length of specific paths to return.
        loop : bool
            Whether we are looking for a loop path.

        Returns
        -------
        PathResult
            PathResult object indicating the results of the attempt to find
            a path.
        """
        # # -- Route to the path sampling function --
        # NOTE this is not generic at this point!
        # if self.do_sampling:
        #     if not has_pg:
        #         raise Exception('The paths_graph package could not be '
        #                         'imported.')
        #     return self._sample_paths(input_set, obj, target_polarity,
        #                               max_paths, max_path_length)

        # -- Do Breadth-First Enumeration --
        # Generate the predecessors to our observable and count the paths
        path_lengths = []
        path_metrics = []
        sources = []
        for source, path_length in find_sources(self.graph, target, input_set):
            # Path already includes an edge from targets to common target, so
            # we need to subtract one edge. In case of loops, we are
            # already missing one edge, there's no need to subtract one more.
            if not loop:
                path_length = path_length - 1
            # There might be a case when sources and targets contain the same
            # nodes (e.g. different agent state in PyBEL networks) that would
            # show up as paths of length 0. We only want to include meaningful
            # paths that contain at least one edge.
            if path_length > 0:
                pm = PathMetric(source, target, path_length)
                path_metrics.append(pm)
                path_lengths.append(path_length)
                # Keep unique sources but use a list (not set) to preserve order
                if source not in sources:
                    sources.append(source)
        # Now, look for paths
        if path_metrics and max_paths == 0:
            pr = PathResult(True, 'MAX_PATHS_ZERO', max_paths, max_path_length)
            pr.path_metrics = path_metrics
            return pr
        elif path_metrics:
            if min(path_lengths) <= max_path_length:
                if not loop:
                    search_path_length = min(path_lengths) + 1
                else:
                    search_path_length = min(path_lengths)
                pr = PathResult(True, 'PATHS_FOUND', max_paths,
                                max_path_length)
                pr.path_metrics = path_metrics
                # Get the first path
                # Try to find paths of fixed length using sources found above
                for source in sources:
                    logger.info('Finding paths between %s and %s' %
                                (str(source), target))
                    path_iter = get_path_iter(self.graph, source, target,
                                              search_path_length, loop)
                    for path in path_iter:
                        pr.add_path(tuple(path))
                        # Do not get next path if reached max_paths
                        if len(pr.paths) >= max_paths:
                            break
                    # Do not check next source if reached max_paths
                    if len(pr.paths) >= max_paths:
                        break
                return pr
            # There are no paths shorter than the max path length, so we
            # don't bother trying to get them
            else:
                pr = PathResult(True, 'MAX_PATH_LENGTH_EXCEEDED', max_paths,
                                max_path_length)
                pr.path_metrics = path_metrics
                return pr
        else:
            return PathResult(False, 'NO_PATHS_FOUND', max_paths,
                              max_path_length)
Example #2
0
    def find_paths(self,
                   subj,
                   obj,
                   max_paths=1,
                   max_path_length=5,
                   loop=False,
                   filter_func=None,
                   allow_direct=True):
        """Check for a source/target path in the model.

        Parameters
        ----------
        subj : indra.explanation.model_checker.NodesContainer
            NodesContainer representing test statement subject.
        obj : indra.explanation.model_checker.NodesContainer
            NodesContainer representing test statement object.
        max_paths : int
            The maximum number of specific paths to return.
        max_path_length : int
            The maximum length of specific paths to return.
        loop : bool
            Whether we are looking for a loop path.
        filter_func : function or None
            A function to constrain the search. A function should take a node
            as a parameter and return True if the node is allowed to be in a
            path and False otherwise. If None, then no filtering is done.
        allow_direct : Optional[bool]
            Whether to allow direct path of length 1 (edge between source and
            target) to be returned as a result. Default: True.

        Returns
        -------
        PathResult
            PathResult object indicating the results of the attempt to find
            a path.
        """
        # # -- Route to the path sampling function --
        # NOTE this is not generic at this point!
        # if self.do_sampling:
        #     if not has_pg:
        #         raise Exception('The paths_graph package could not be '
        #                         'imported.')
        #     return self._sample_paths(input_set, obj, target_polarity,
        #                               max_paths, max_path_length)

        # -- Do Breadth-First Enumeration --
        # Generate the predecessors to our observable and count the paths
        path_lengths = []
        path_metrics = []
        sources = []
        if obj.common_target:
            target = obj.common_target
            dummy_target = True
        else:
            target = obj.all_nodes[0]
            dummy_target = False
        for source, path_length in find_sources(self.graph, target,
                                                subj.all_nodes, filter_func):
            # If a dummy target is used, we need to subtract one edge.
            # In case of loops, we are already missing one edge, there's no
            # need to subtract one more.
            if dummy_target and not loop:
                path_length = path_length - 1
            # There might be a case when sources and targets contain the same
            # nodes (e.g. different agent state in PyBEL networks) that would
            # show up as paths of length 0. We only want to include meaningful
            # paths that contain at least one edge.
            if path_length > 0:
                pm = PathMetric(source, target, path_length)
                path_metrics.append(pm)
                path_lengths.append(path_length)
                # Keep unique sources but use a list, not set to preserve order
                if source not in sources:
                    sources.append(source)
        # Now, look for paths
        if path_metrics and max_paths == 0:
            pr = PathResult(True, 'MAX_PATHS_ZERO', max_paths, max_path_length)
            pr.path_metrics = path_metrics
            return pr
        elif path_metrics:
            min_path_length = min(path_lengths)
            # If we don't want to get direct connections as paths, we need
            # to increase the desired path length to get paths with
            # intermediate nodes (if they exist)
            if not allow_direct and min_path_length == 1 and \
                    len(path_lengths) > 1:
                min_path_length = min([pl for pl in path_lengths if pl != 1])
            if min_path_length <= max_path_length:
                if dummy_target and not loop:
                    search_path_length = min_path_length + 1
                else:
                    search_path_length = min_path_length
                pr = PathResult(True, 'PATHS_FOUND', max_paths,
                                max_path_length)
                pr.path_metrics = path_metrics
                # Get the first path
                # Try to find paths of fixed length using sources found above
                for source in sources:
                    logger.info('Finding paths between %s and %s' %
                                (str(source), target))
                    path_iter = get_path_iter(self.graph, source, target,
                                              search_path_length, loop,
                                              dummy_target, filter_func)
                    for path in path_iter:
                        # Check if the path starts with a refinement
                        if subj.is_ref(path[0]):
                            path.insert(
                                0,
                                self.get_ref(subj.main_agent, path[0],
                                             'has_ref'))
                        # Check if the path ends with a refinement
                        if obj.is_ref(path[-1]):
                            path.append(
                                self.get_ref(obj.main_agent, path[-1],
                                             'is_ref'))
                        pr.add_path(tuple(path))
                        # Do not get next path if reached max_paths
                        if len(pr.paths) >= max_paths:
                            break
                    # Do not check next source if reached max_paths
                    if len(pr.paths) >= max_paths:
                        break
                return pr
            # There are no paths shorter than the max path length, so we
            # don't bother trying to get them
            else:
                pr = PathResult(True, 'MAX_PATH_LENGTH_EXCEEDED', max_paths,
                                max_path_length)
                pr.path_metrics = path_metrics
                return pr
        else:
            return PathResult(False, 'NO_PATHS_FOUND', max_paths,
                              max_path_length)