Пример #1
0
    def __init__(self, G, max_res, min_res, preprocess, REF, algorithm=None):
        # Check inputs
        check(G, max_res, min_res, REF_forward=REF, algorithm=__name__)
        # Preprocess graph
        self.G = preprocess_graph(G, max_res, min_res, preprocess, REF)

        self.max_res = max_res
        self.min_res = min_res
        # Update resource extension function if given
        if REF:
            self.REF = REF
        else:
            self.REF = add

        if negative_edge_cycle(G) or algorithm == "simple":
            self.algorithm = "simple"
        else:
            self.algorithm = "astar"

        # Attribute to hold source-sink path
        self.st_path = None

        # Attribrutes for exposure #
        # resource feasible source-sink path
        self.best_path = None
        # Final cost
        self.best_path_cost = None
        # Final resource consumption
        self.best_path_total_res = None
Пример #2
0
    def __init__(
            self,
            G: DiGraph,
            max_res: List[float],
            min_res: List[float],
            preprocess: Optional[bool] = False,
            direction: Optional[str] = "both",
            method: Optional[str] = "unprocessed",
            time_limit: Optional[Union[float, int]] = None,
            threshold: Optional[float] = None,
            elementary: Optional[bool] = False,
            bounds_pruning: Optional[bool] = False,
            find_critical_res: Optional[bool] = False,
            critical_res: Optional[int] = None,
            # seed: Union[int] = None,
            REF_callback: Optional[REFCallback] = None):
        # Check inputs
        check(G, max_res, min_res, direction, REF_callback, __name__)
        # check_seed(seed, __name__)
        # Preprocess and save graph
        self.G: DiGraph = preprocess_graph(G, max_res, min_res, preprocess,
                                           REF_callback)
        # Vertex id with source/sink
        self._source_id: int = None
        self._sink_id: int = None

        max_res_vector = _convert_list_to_double_vector(max_res)
        min_res_vector = _convert_list_to_double_vector(min_res)

        # Pass graph
        self._init_graph()
        self.bidirectional_cpp = BiDirectionalCpp(len(self.G.nodes()),
                                                  len(self.G.edges()),
                                                  self._source_id,
                                                  self._sink_id,
                                                  max_res_vector,
                                                  min_res_vector)
        self._load_graph()
        # pass solving attributes
        if direction != "both":
            self.bidirectional_cpp.setDirection(direction)
        if method in ["random", "generated", "processed"]:
            self.bidirectional_cpp.setMethod(method)
        if time_limit is not None and isinstance(time_limit, (int, float)):
            self.bidirectional_cpp.setTimeLimit(time_limit)
        if threshold is not None and isinstance(time_limit, (int, float)):
            self.bidirectional_cpp.setThreshold(threshold)
        if isinstance(elementary, bool) and elementary:
            self.bidirectional_cpp.setElementary(True)
        if isinstance(bounds_pruning, bool) and not bounds_pruning:
            self.bidirectional_cpp.setBoundsPruning(bounds_pruning)
        if isinstance(find_critical_res, bool) and critical_res:
            self.bidirectional_cpp.setFindCriticalRes(True)
        if isinstance(critical_res, int) and critical_res != 0:
            self.bidirectional_cpp.setCriticalRes(critical_res)
        if REF_callback is not None:
            # Add a Python callback (caller owns the callback, so we
            # disown it first by calling __disown__).
            # see: https://github.com/swig/swig/blob/b6c2438d7d7aac5711376a106a156200b7ff1056/Examples/python/callback/runme.py#L36
            self.bidirectional_cpp.setREFCallback(REF_callback.__disown__())
Пример #3
0
    def __init__(self,
                 G: DiGraph,
                 max_res: List[float],
                 min_res: List[float],
                 preprocess: Optional[bool] = False,
                 direction: Optional[str] = "both",
                 method: Optional[str] = "random",
                 time_limit: Optional[float] = None,
                 threshold: Optional[float] = None,
                 elementary: Optional[bool] = False,
                 dominance_frequency: Optional[int] = 1,
                 seed: Union[int, RandomState, None] = None,
                 REF_forward: Optional[Callable] = None,
                 REF_backward: Optional[Callable] = None,
                 REF_join: Optional[Callable] = None):
        # Check inputs
        check(G,
              max_res,
              min_res,
              direction,
              REF_forward=REF_forward,
              REF_backward=REF_backward,
              REF_join=REF_join,
              algorithm=__name__)
        # Preprocess graph
        self.G = preprocess_graph(G, max_res, min_res, preprocess, REF_forward)

        self.max_res = max_res.copy()
        self.min_res = min_res.copy()
        self.max_res_in, self.min_res_in = array(max_res.copy()), array(
            min_res.copy())
        self.direction = direction
        self.method = method
        self.time_limit = time_limit
        self.elementary = elementary
        self.threshold = threshold
        self.dominance_frequency = dominance_frequency
        self.random_state = check_seed(seed)
        # Set label class attributes
        Label.REF_forward = REF_forward if REF_forward else add
        Label.REF_backward = REF_backward if REF_backward else sub

        self.REF_join = REF_join

        # Algorithm specific attributes
        self.iteration = 0
        # Containers for labels
        self.current_label: Dict[str, Label] = None
        self.unprocessed_labels: Dict[str, List[Label]] = None
        self.best_labels: Dict[str, List[Label]] = None
        # Containers for counters
        self.unprocessed_counts: Dict[str, int] = 0
        self.processed_counts: Dict[str, int] = 0
        self.generated_counts: Dict[str, int] = 0
        # For exposure
        self.final_label: Label = None
        self.best_label: Label = None
        # Populate containers
        self._init_containers()
Пример #4
0
    def __init__(self,
                 G: DiGraph,
                 max_res: List[float],
                 min_res: List[float],
                 preprocess: Optional[bool] = False,
                 direction: Optional[str] = "both",
                 method: Optional[str] = "unprocessed",
                 time_limit: Optional[Union[float, int]] = None,
                 threshold: Optional[float] = None,
                 elementary: Optional[bool] = False,
                 bounds_pruning: Optional[bool] = False,
                 seed: Union[int] = None,
                 REF_callback: Optional[REFCallback] = None):
        # Check inputs
        check(G, max_res, min_res, direction, REF_callback, __name__)
        # check_seed(seed, __name__)
        # Preprocess graph
        G = preprocess_graph(G, max_res, min_res, preprocess, REF_callback)
        # To save original node type (for conversion at the end)
        self._original_node_type: str = None

        max_res_vector = _convert_list_to_double_vector(max_res)
        min_res_vector = _convert_list_to_double_vector(min_res)

        self.bidirectional_cpp = BiDirectionalCpp(len(G.nodes()),
                                                  len(G.edges()),
                                                  max_res_vector,
                                                  min_res_vector)
        # pass solving attributes
        if direction != "both":
            self.bidirectional_cpp.direction = direction
        if method in ["random", "generated", "processed"]:
            self.bidirectional_cpp.method = method
        if time_limit is not None and isinstance(time_limit, (int, float)):
            self.bidirectional_cpp.time_limit = time_limit
        if threshold is not None and isinstance(time_limit, (int, float)):
            self.bidirectional_cpp.threshold = threshold
        if isinstance(elementary, bool) and elementary:
            self.bidirectional_cpp.elementary = elementary
        if isinstance(bounds_pruning, bool) and not bounds_pruning:
            self.bidirectional_cpp.bounds_pruning = bounds_pruning
        if isinstance(seed, int) and seed is not None:
            self.bidirectional_cpp.setSeed(seed)
        if REF_callback is not None:
            # Add a Python callback (caller owns the callback, so we
            # disown it first by calling __disown__).
            # see: https://github.com/swig/swig/blob/b6c2438d7d7aac5711376a106a156200b7ff1056/Examples/python/callback/runme.py#L36
            self.bidirectional_cpp.setREFCallback(REF_callback.__disown__())

        # Pass graph
        self._init_graph(G)
Пример #5
0
    def __init__(self, G, max_res, min_res, REF=None, preprocess=False):
        # Check inputs
        check(G, max_res, min_res, REF, algorithm=__name__)
        # Preprocess graph
        self.G = preprocess_graph(G, max_res, min_res, preprocess, REF)

        self.max_res = max_res
        self.min_res = min_res
        # Update resource extension function if given
        if REF:
            self.REF = REF
        else:
            self.REF = add

        # Attribute to hold source-sink path
        self.st_path = None

        # Attribrutes for exposure #
        # resource feasible source-sink path
        self.best_path = None
        # Final cost
        self.best_path_cost = None
        # Final resource consumption
        self.best_path_total_res = None
Пример #6
0
    def __init__(self,
                 G,
                 max_res,
                 min_res,
                 preprocess=False,
                 direction="both",
                 method="random",
                 seed=None,
                 REF_forward=None,
                 REF_backward=None,
                 REF_join=None):

        # Check inputs
        check(G,
              max_res,
              min_res,
              REF_forward=REF_forward,
              REF_backward=REF_backward,
              REF_join=REF_join,
              direction=direction,
              algorithm=__name__)
        # Preprocess graph
        self.G = preprocess_graph(G, max_res, min_res, preprocess, REF_forward)
        self.REF_join = REF_join
        self.direc_in = direction
        self.max_res, self.min_res = max_res.copy(), min_res.copy()
        self.max_res_in, self.min_res_in = array(max_res.copy()), array(
            min_res.copy())
        self.method = method
        # To expose results
        self.best_label = None

        # Algorithm specific parameters #
        # set bounds for bacward search
        bwd_start = deepcopy(min_res)
        bwd_start[0] = max_res[0]
        # Current forward and backward labels
        self.current_label = OrderedDict({
            "forward":
            Label(0, "Source", min_res, ["Source"]),
            "backward":
            Label(0, "Sink", bwd_start, ["Sink"])
        })
        # Unprocessed labels dict (both directions)
        self.unprocessed_labels = OrderedDict({
            "forward": deque(),
            "backward": deque()
        })
        # All generated label
        self.generated_labels = OrderedDict({"forward": 0, "backward": 0})
        # Best labels
        # (with initial labels for small cases, see:
        # https://github.com/torressa/cspy/issues/38 )
        self.best_labels = OrderedDict({
            "forward":
            deque([self.current_label["forward"]]),
            "backward":
            deque([self.current_label["backward"]])
        })
        # Final labels dicts for unidirectional search
        self.final_label = None

        # If given, set REFs for dominance relations and feasibility checks
        if REF_forward:
            Label._REF_forward = REF_forward
        else:
            Label._REF_forward = add
        if REF_backward:
            Label._REF_backward = REF_backward
        else:
            Label._REF_backward = sub
        # Init with seed if given
        if seed is None:
            self.random_state = RandomState()
        elif isinstance(seed, int):
            self.random_state = RandomState(seed)
        elif isinstance(seed, RandomState):
            self.random_state = seed
        else:
            raise Exception("{} cannot be used to seed".format(seed))
Пример #7
0
 def testUnreachable(self):
     """
     Tests if the unreachable node 'B' is removed.
     """
     self.G = preprocess_graph(self.G, [5, 20], [0, 0], True)
     self.assertTrue('B' not in self.G.nodes())
Пример #8
0
    def __init__(self,
                 G,
                 max_res,
                 min_res,
                 REF=None,
                 preprocess=False,
                 direction="both",
                 method="random",
                 seed=None):
        # Check inputs and preprocess G unless option disabled
        check(G, max_res, min_res, REF, direction, __name__)
        # Preprocess graph
        self.G = preprocess_graph(G, max_res, min_res, preprocess, REF)
        self.direc_in = direction
        self.max_res, self.min_res = max_res.copy(), min_res.copy()
        self.max_res_in, self.min_res_in = array(max_res.copy()), array(
            min_res.copy())
        self.method = method
        # To expose results
        self.best_label = None

        # Algorithm specific parameters #
        # set bounds for bacward search
        bwd_start = deepcopy(min_res)
        bwd_start[0] = max_res[0]
        # Current forward and backward labels
        self.current_label = OrderedDict({
            "forward":
            Label(0, "Source", min_res, ["Source"]),
            "backward":
            Label(0, "Sink", bwd_start, ["Sink"])
        })
        # Unprocessed labels dict (both directions)
        self.unprocessed_labels = OrderedDict({
            "forward": deque(),
            "backward": deque()
        })
        # All generated label
        self.generated_labels = OrderedDict({"forward": 0, "backward": 0})
        # To save all best labels
        self.best_labels = OrderedDict({
            "forward": deque(),
            "backward": deque()
        })
        # Final labels dicts for unidirectional search
        self.final_label = None

        # If given, set REFs for dominance relations and feasibility checks
        if REF:
            Label._REF = REF
        else:
            Label._REF = add
        # Init with seed if given
        if seed is None:
            self.random_state = RandomState()
        elif isinstance(seed, int):
            self.random_state = RandomState(seed)
        elif isinstance(seed, RandomState):
            self.random_state = seed
        else:
            raise Exception("{} cannot be used to seed".format(seed))
Пример #9
0
 def testFindBadNode(self):
     """
     Tests if expensive node 'B' is removed
     """
     self.F = preprocess_graph(self.F, [5], [1], True)
     self.assertTrue('B' not in self.F.nodes())