def run(self): """ Execute the BGP protocol. Must be called after init_partition. """ converged = False log.debug("running BGP...") for r in self._active_in_partition: if r.is_external(): r.local_bgp_step(self._igp_cost_provider) nof_rounds = 0 while not converged: nof_rounds += 1 if nof_rounds > 100: log.error("BGP did not converge after 100 rounds, is it diverging?") raise Exception("Bgp did not converge after 100 rounds") # log.debug("started next BGP round") converged = True for r in self._all_in_partition: # need to do this also for passive nodes to clear their msg_in lists r.prepare_next_round() converged = converged and r.is_converged() if not converged: for r in self._active_in_partition: r.local_bgp_step(self._igp_cost_provider) log.debug("BGP converged after %d rounds", nof_rounds) # select best announcement for all passive nodes as well for r in self._passive_in_partition: r.local_bgp_step(self._igp_cost_provider, send=False)
def _setup_partition_run_bgp(self, flow: Flow): self.problem.bgp.init_partition(flow, self._igp_provider) # run BGP to determine the selected next hops self.problem.bgp.run() self._igp_provider.update_bgp_next_hops( flow.dst, self.problem.bgp.get_next_hops_for_internal()) log.debug("computed next hops: %s", self._igp_provider._bgp_next_hop_data)
def _explore(self, state: list): log.debug("Exploring: {}".format(state)) p_state = self.problem.failure_model.get_state_prob(state) self._igp_provider.recompute() fw_graphs = {} for flow in self.problem.property.flows: self._setup_partition_run_bgp(flow) fwg, _ = self._construct_fw_graph_decision_points(flow) fw_graphs[flow] = fwg self.solution.p_explored = self.solution.p_explored + p_state log.debug("checking property for fw graphs: %s", fw_graphs) if self.problem.property.check(fw_graphs): log.debug(" -> HOLDS") self.solution.p_property += p_state else: log.debug(" -> DOES NOT HOLD") self.solution.num_explored += 1 if self._full_trace: fw_graphs[self.problem.property.flows[0]].normalize() data = { 'state': state.copy(), 'fw_graph': fw_graphs[self.problem.property.flows[0]].next } self._trace.append(data) log.data("explored_reference", data)
def compute_bn_event_prob(self, event: BnEvent): if len(event.data) == 0: return 1.0 log.debug("started Bayes Net inference") # build up minimal network from scratch ppy_event = ppy.Event() for bnn in self.bn_nodes: bnn.clear() self.network = [] for bnn, val in event.data: bnn.build_network(self.network) ppy_event.setValue(bnn.var, val) # perform inference res = self._compute_event_prob(ppy_event) log.debug("finished inference") return res
def _explore(self, state: list): """ Explore a given state. """ log.debug("exploring: {}".format(state)) self._update_graph(state) # update shortest paths, partitions, etc. self._igp_provider.recompute() hot_edges = set() fw_graphs = {} for flow in self.problem.property.flows: self._setup_partition_run_bgp(flow) fwg, decision_points = self._construct_fw_graph_decision_points( flow) fw_graphs[flow] = fwg log.debug("computed forwarding graph: %s", fwg) self._add_hot_edges_bgp(flow, fwg, decision_points, hot_edges) for e in hot_edges: e_id = self.problem.link_id_for_edge[e] if state[e_id] == -1: state[e_id] = 0 p_state = self.problem.failure_model.get_state_prob(state) self._add_to_explore_queue(state, p_state.val()) state[e_id] = 1 p_state = self.problem.failure_model.get_state_prob( state) # probability that all hot edges are up self.solution.p_explored = self.solution.p_explored + p_state log.debug("checking property for fw graphs: %s", fw_graphs) if self.problem.property.check(fw_graphs): log.debug(" -> HOLDS") self.solution.p_property += p_state else: log.debug(" -> DOES NOT HOLD") self.solution.num_explored += 1 log.debug("current precision: {}".format( self.solution.p_explored.invert().val())) if self._stat_prec: log.data("precision", self.solution.p_explored.invert().val()) if self._stat_hot and self.solution.num_explored <= 10: log.data("fraction_hot", len(hot_edges) / float(len(state))) if self._full_trace: fw_graphs[self.problem.property.flows[0]].normalize() data = { 'state': state, 'fw_graph': fw_graphs[self.problem.property.flows[0]].next } self._trace.append(data) log.data("explored_smart", data)