def add_controllable(fro, to, lb, ub, edge_id): # lb cannot be larger than ub # assert lb <= ub ub_edge = DistanceGraphEdge(fro, to, ub, EdgeType.SIMPLE, renaming=renaming) lb_edge = DistanceGraphEdge(to, fro, -lb, EdgeType.SIMPLE, renaming=renaming) if edge_id is not None: self.edge_support[ub_edge] = EdgeSupport.base({ (EdgeSupport.UPPER, edge_id): 1, }) self.edge_support[lb_edge] = EdgeSupport.base({ (EdgeSupport.LOWER, edge_id): -1, }) else: self.edge_support[ub_edge] = EdgeSupport.base({}) self.edge_support[lb_edge] = EdgeSupport.base({}) if not math.isinf(ub): edge_list.append(ub_edge) # print("UB edge: "+ str(ub_edge)) # else: # print("Ignoring +inf UB of " + e.id) if not math.isinf(lb): edge_list.append(lb_edge)
def add_uncontrollable(fro, to, lb, ub, edge_id): # no negative lower bound # no infinite upperbound assert lb <= ub assert not lb < 0 assert not math.isinf(ub) ub_edge = DistanceGraphEdge(fro, to, ub, EdgeType.SIMPLE, renaming=renaming) lb_edge = DistanceGraphEdge(to, fro, -lb, EdgeType.SIMPLE, renaming=renaming) if edge_id is not None: # Note that the sign for the upper and lower bound supports are reversed # Since they are being subtracted during the reduction self.edge_support[ub_edge] = EdgeSupport.base({(EdgeSupport.UPPER, edge_id): -1,}) self.edge_support[lb_edge] = EdgeSupport.base({(EdgeSupport.LOWER, edge_id): 1,}) else: self.edge_support[ub_edge] = EdgeSupport.base({}) self.edge_support[lb_edge] = EdgeSupport.base({}) #edge_list.append(ub_edge) #edge_list.append(lb_edge) #contingent_nodes.append(to) if to in contingent_edges_at_node: collection = contingent_edges_at_node[to] collection.append(lb_edge) collection.append(ub_edge) else: collection = [] collection.append(lb_edge) collection.append(ub_edge) contingent_edges_at_node[to] = collection
def add_uncontrollable(fro, to, lb, ub, edge_id): # no negative lower bound # no infinite upperbound assert lb <= ub assert not lb < 0 assert not math.isinf(ub) ub_edge = DistanceGraphEdge(fro, to, ub, EdgeType.SIMPLE, renaming=renaming) lb_edge = DistanceGraphEdge(to, fro, -lb, EdgeType.SIMPLE, renaming=renaming) if edge_id is not None: # Note that the sign for the upper and lower bound supports are reversed # Since they are being subtracted during the reduction self.edge_support[ub_edge] = EdgeSupport.base({ (EdgeSupport.UPPER, edge_id): -1, }) self.edge_support[lb_edge] = EdgeSupport.base({ (EdgeSupport.LOWER, edge_id): 1, }) else: self.edge_support[ub_edge] = EdgeSupport.base({}) self.edge_support[lb_edge] = EdgeSupport.base({}) #edge_list.append(ub_edge) #edge_list.append(lb_edge) #contingent_nodes.append(to) if to in contingent_edges_at_node: collection = contingent_edges_at_node[to] collection.append(lb_edge) collection.append(ub_edge) else: collection = [] collection.append(lb_edge) collection.append(ub_edge) contingent_edges_at_node[to] = collection
def reduce_edge(self, edge1, edge2): # X ---edge1----> Y ----edge2----> Z assert edge2.fro == edge1.to new_fro = edge1.fro new_to = edge2.to new_value = edge1.value + edge2.value new_type = None new_maybe_letter = None # UPPER CASE REDUCTION if edge1.edge_type == EdgeType.SIMPLE and edge2.edge_type == EdgeType.UPPER_CASE: new_maybe_letter = edge2.maybe_letter new_type = EdgeType.UPPER_CASE # print("Upper Case " + str(edge1) + "+++" + str(edge2)); # LOWER CASE REDUCTION elif (edge1.edge_type == EdgeType.LOWER_CASE and edge2.edge_type == EdgeType.SIMPLE and edge2.value < 0): new_type = EdgeType.SIMPLE # CROSS CASE REDUCTION elif (edge1.edge_type == EdgeType.LOWER_CASE and edge2.edge_type == EdgeType.UPPER_CASE and edge2.value < 0 and edge1.maybe_letter != edge2.maybe_letter): new_maybe_letter = edge2.maybe_letter new_type = EdgeType.UPPER_CASE # NO-CASE REDUCITON elif edge1.edge_type == EdgeType.SIMPLE and edge2.edge_type == EdgeType.SIMPLE: new_type = EdgeType.SIMPLE if new_type is None: # not reduction matched return None if new_type == EdgeType.UPPER_CASE: # try applying LABEL REMOVAL # If you thing about this for our purposes SIMPLE edge is strictly # better than upper case. if new_value >= 0: new_type = EdgeType.SIMPLE new_maybe_letter = None new_edge = DistanceGraphEdge(new_fro, new_to, new_value, new_type, new_maybe_letter, renaming=edge1.renaming) self.edge_support[new_edge] = EdgeSupport.derived(edge1, edge2) # if (new_edge.fro == new_edge.to and new_edge.value < 0): # print('combine \t%s \twith \t%s \tto get \t%s' %(edge1, edge2, new_edge)) # return None return new_edge
def add_controllable(fro, to, lb, ub, edge_id): # lb cannot be larger than ub # assert lb <= ub ub_edge = DistanceGraphEdge(fro, to, ub, EdgeType.SIMPLE, renaming=renaming) lb_edge = DistanceGraphEdge(to, fro, -lb, EdgeType.SIMPLE, renaming=renaming) if edge_id is not None: self.edge_support[ub_edge] = EdgeSupport.base({ (EdgeSupport.UPPER, edge_id): 1, }) self.edge_support[lb_edge] = EdgeSupport.base({ (EdgeSupport.LOWER, edge_id): -1, }) else: self.edge_support[ub_edge] = EdgeSupport.base({}) self.edge_support[lb_edge] = EdgeSupport.base({}) if not math.isinf(ub): edge_list.append(ub_edge) # else: # print("Ignoring +inf UB of " + e.id) if not math.isinf(lb): edge_list.append(lb_edge)
def add_uncontrollable(fro, new_node, to, lb, ub, edge_id): # no negative lower bound # no infinite upperbound assert lb <= ub assert not lb < 0 assert not math.isinf(ub) if new_node is not None: lb_ub_edge = DistanceGraphEdge(fro, new_node, lb, EdgeType.SIMPLE, renaming=renaming) lb_lb_edge = DistanceGraphEdge(new_node, fro, -lb, EdgeType.SIMPLE, renaming=renaming) self.edge_support[lb_ub_edge] = EdgeSupport.base({ (EdgeSupport.LOWER, edge_id): 1, }) self.edge_support[lb_lb_edge] = EdgeSupport.base({ (EdgeSupport.LOWER, edge_id): -1, }) edge_list.append(lb_ub_edge) edge_list.append(lb_lb_edge) # print("LBUB edge: "+ str(lb_ub_edge)) # print("LBLB edge: "+ str(lb_lb_edge)) else: new_node = fro ub_edge = DistanceGraphEdge(new_node, to, ub-lb, EdgeType.SIMPLE, renaming=renaming) lb_edge = DistanceGraphEdge(to, new_node, 0, EdgeType.SIMPLE, renaming=renaming) self.edge_support[ub_edge] = EdgeSupport.base({ (EdgeSupport.LOWER, edge_id): -1, (EdgeSupport.UPPER, edge_id): 1, }) self.edge_support[lb_edge] = EdgeSupport.base({}) ub_cond_edge = DistanceGraphEdge(to, new_node, lb-ub, EdgeType.UPPER_CASE, to, renaming=renaming) lb_cond_edge = DistanceGraphEdge(new_node, to, 0, EdgeType.LOWER_CASE, to, renaming=renaming) self.edge_support[ub_cond_edge] = EdgeSupport.base({ (EdgeSupport.LOWER, edge_id): 1, (EdgeSupport.UPPER, edge_id): -1, }) self.edge_support[lb_cond_edge] = EdgeSupport.base({}) edge_list.append(ub_edge) edge_list.append(lb_edge) edge_list.append(ub_cond_edge) edge_list.append(lb_cond_edge)
def generate_graph_from_tpnu(self, network): """Generates distance graph from a tpnu""" num_nodes = network.num_nodes contingent_edges_at_node = {} edge_list = [] if hasattr(network, 'node_number_to_id'): renaming = network.node_number_to_id def add_controllable(fro, to, lb, ub, edge_id): # lb cannot be larger than ub # assert lb <= ub ub_edge = DistanceGraphEdge(fro, to, ub, EdgeType.SIMPLE, renaming=renaming) lb_edge = DistanceGraphEdge(to, fro, -lb, EdgeType.SIMPLE, renaming=renaming) if edge_id is not None: self.edge_support[ub_edge] = EdgeSupport.base({(EdgeSupport.UPPER, edge_id): 1,}) self.edge_support[lb_edge] = EdgeSupport.base({(EdgeSupport.LOWER, edge_id): -1,}) else: self.edge_support[ub_edge] = EdgeSupport.base({}) self.edge_support[lb_edge] = EdgeSupport.base({}) if not math.isinf(ub): edge_list.append(ub_edge) # else: # print("Ignoring +inf UB of " + e.id) if not math.isinf(lb): edge_list.append(lb_edge) # else: # print("Ignoring -inf LB of " + e.id) def add_uncontrollable(fro, to, lb, ub, edge_id): # no negative lower bound # no infinite upperbound assert lb <= ub assert not lb < 0 assert not math.isinf(ub) ub_edge = DistanceGraphEdge(fro, to, ub, EdgeType.SIMPLE, renaming=renaming) lb_edge = DistanceGraphEdge(to, fro, -lb, EdgeType.SIMPLE, renaming=renaming) if edge_id is not None: # Note that the sign for the upper and lower bound supports are reversed # Since they are being subtracted during the reduction self.edge_support[ub_edge] = EdgeSupport.base({(EdgeSupport.UPPER, edge_id): -1,}) self.edge_support[lb_edge] = EdgeSupport.base({(EdgeSupport.LOWER, edge_id): 1,}) else: self.edge_support[ub_edge] = EdgeSupport.base({}) self.edge_support[lb_edge] = EdgeSupport.base({}) #edge_list.append(ub_edge) #edge_list.append(lb_edge) #contingent_nodes.append(to) if to in contingent_edges_at_node: collection = contingent_edges_at_node[to] collection.append(lb_edge) collection.append(ub_edge) else: collection = [] collection.append(lb_edge) collection.append(ub_edge) contingent_edges_at_node[to] = collection encoded_node_pairs = {} # Encode initial edges for e in network.temporal_constraints.values(): # We only consider constraints that are active if e.activated: if e.fro == 0 or e.to == 0: raise Exception("Node with id zero is not allowed (see documentation for check function.)") if e.controllable: # Make sure no two edges share the same from and to nodes if (e.fro,e.to) not in encoded_node_pairs: add_controllable(e.fro,e.to,e.get_lower_bound(),e.get_upper_bound(),e.id) encoded_node_pairs[(e.fro,e.to)] = True else: new_node = num_nodes + 1 num_nodes += 1 renaming[new_node] = renaming[e.to] + "'" add_controllable(e.fro,new_node,e.get_lower_bound(),e.get_upper_bound(),e.id) add_controllable(new_node,e.to,0,0,None) else: # Make sure no two edges share the same from and to nodes if (e.fro,e.to) not in encoded_node_pairs: add_uncontrollable(e.fro,e.to,e.get_lower_bound(),e.get_upper_bound(),e.id) encoded_node_pairs[(e.fro,e.to)] = True else: new_node = num_nodes + 1 num_nodes += 1 renaming[new_node] = renaming[e.to] + "'" add_uncontrollable(e.fro,new_node,e.get_lower_bound(),e.get_upper_bound(),e.id) add_controllable(new_node,e.to,0,0,None) # Execute triangular reduction procedure on the edges reduced_edges = [] for edge in edge_list: new_edges = [] if edge.fro in contingent_edges_at_node: contingent_edges = contingent_edges_at_node[edge.fro] for contingent_edge in contingent_edges: if contingent_edge.fro == edge.fro: reduced_edge = DistanceGraphEdge(contingent_edge.to, edge.to, edge.value-contingent_edge.value, EdgeType.SIMPLE, renaming=renaming) self.edge_support[reduced_edge] = EdgeSupport.derived(edge, contingent_edge) new_edges.append(reduced_edge) # print("Reducing: " + str(edge) + " and " + str(contingent_edge)) # print("Adding reduced from edge: " + str(reduced_edge.fro) + "->" + str(reduced_edge.to) + " (" + str(reduced_edge.value) + ")") else: new_edges.append(edge) for new_edge in new_edges: if new_edge.to in contingent_edges_at_node: contingent_edges = contingent_edges_at_node[edge.to] for contingent_edge in contingent_edges: if contingent_edge.to == edge.to: reduced_edge = DistanceGraphEdge(edge.fro, contingent_edge.fro, edge.value-contingent_edge.value, EdgeType.SIMPLE, renaming=renaming) self.edge_support[reduced_edge] = EdgeSupport.derived(edge, contingent_edge) reduced_edges.append(reduced_edge) # print("Reducing: " + str(new_edge) + " and " + str(contingent_edge)) # print("Adding reduced to edge: " + str(reduced_edge.fro) + "->" + str(reduced_edge.to) + " (" + str(reduced_edge.value) + ")") else: reduced_edges.append(new_edge) return num_nodes, reduced_edges
def generate_graph_from_tpnu(self, network): """Generates distance graph from a tpnu""" num_nodes = network.num_nodes contingent_edges_at_node = {} edge_list = [] if hasattr(network, 'node_number_to_id'): renaming = network.node_number_to_id def add_controllable(fro, to, lb, ub, edge_id): # lb cannot be larger than ub # assert lb <= ub ub_edge = DistanceGraphEdge(fro, to, ub, EdgeType.SIMPLE, renaming=renaming) lb_edge = DistanceGraphEdge(to, fro, -lb, EdgeType.SIMPLE, renaming=renaming) if edge_id is not None: self.edge_support[ub_edge] = EdgeSupport.base({ (EdgeSupport.UPPER, edge_id): 1, }) self.edge_support[lb_edge] = EdgeSupport.base({ (EdgeSupport.LOWER, edge_id): -1, }) else: self.edge_support[ub_edge] = EdgeSupport.base({}) self.edge_support[lb_edge] = EdgeSupport.base({}) if not math.isinf(ub): edge_list.append(ub_edge) # else: # print("Ignoring +inf UB of " + e.id) if not math.isinf(lb): edge_list.append(lb_edge) # else: # print("Ignoring -inf LB of " + e.id) def add_uncontrollable(fro, to, lb, ub, edge_id): # no negative lower bound # no infinite upperbound assert lb <= ub assert not lb < 0 assert not math.isinf(ub) ub_edge = DistanceGraphEdge(fro, to, ub, EdgeType.SIMPLE, renaming=renaming) lb_edge = DistanceGraphEdge(to, fro, -lb, EdgeType.SIMPLE, renaming=renaming) if edge_id is not None: # Note that the sign for the upper and lower bound supports are reversed # Since they are being subtracted during the reduction self.edge_support[ub_edge] = EdgeSupport.base({ (EdgeSupport.UPPER, edge_id): -1, }) self.edge_support[lb_edge] = EdgeSupport.base({ (EdgeSupport.LOWER, edge_id): 1, }) else: self.edge_support[ub_edge] = EdgeSupport.base({}) self.edge_support[lb_edge] = EdgeSupport.base({}) #edge_list.append(ub_edge) #edge_list.append(lb_edge) #contingent_nodes.append(to) if to in contingent_edges_at_node: collection = contingent_edges_at_node[to] collection.append(lb_edge) collection.append(ub_edge) else: collection = [] collection.append(lb_edge) collection.append(ub_edge) contingent_edges_at_node[to] = collection encoded_node_pairs = {} # Encode initial edges for e in network.temporal_constraints.values(): # We only consider constraints that are active if e.activated: if e.fro == 0 or e.to == 0: raise Exception( "Node with id zero is not allowed (see documentation for check function.)" ) if e.controllable: # Make sure no two edges share the same from and to nodes if (e.fro, e.to) not in encoded_node_pairs: add_controllable(e.fro, e.to, e.get_lower_bound(), e.get_upper_bound(), e.id) encoded_node_pairs[(e.fro, e.to)] = True else: new_node = num_nodes + 1 num_nodes += 1 renaming[new_node] = renaming[e.to] + "'" add_controllable(e.fro, new_node, e.get_lower_bound(), e.get_upper_bound(), e.id) add_controllable(new_node, e.to, 0, 0, None) else: # Make sure no two edges share the same from and to nodes if (e.fro, e.to) not in encoded_node_pairs: add_uncontrollable(e.fro, e.to, e.get_lower_bound(), e.get_upper_bound(), e.id) encoded_node_pairs[(e.fro, e.to)] = True else: new_node = num_nodes + 1 num_nodes += 1 renaming[new_node] = renaming[e.to] + "'" add_uncontrollable(e.fro, new_node, e.get_lower_bound(), e.get_upper_bound(), e.id) add_controllable(new_node, e.to, 0, 0, None) # Execute triangular reduction procedure on the edges reduced_edges = [] for edge in edge_list: new_edges = [] if edge.fro in contingent_edges_at_node: contingent_edges = contingent_edges_at_node[edge.fro] for contingent_edge in contingent_edges: if contingent_edge.fro == edge.fro: reduced_edge = DistanceGraphEdge(contingent_edge.to, edge.to, edge.value - contingent_edge.value, EdgeType.SIMPLE, renaming=renaming) self.edge_support[reduced_edge] = EdgeSupport.derived( edge, contingent_edge) new_edges.append(reduced_edge) # print("Reducing: " + str(edge) + " and " + str(contingent_edge)) # print("Adding reduced from edge: " + str(reduced_edge.fro) + "->" + str(reduced_edge.to) + " (" + str(reduced_edge.value) + ")") else: new_edges.append(edge) for new_edge in new_edges: if new_edge.to in contingent_edges_at_node: contingent_edges = contingent_edges_at_node[edge.to] for contingent_edge in contingent_edges: if contingent_edge.to == edge.to: reduced_edge = DistanceGraphEdge( edge.fro, contingent_edge.fro, edge.value - contingent_edge.value, EdgeType.SIMPLE, renaming=renaming) self.edge_support[ reduced_edge] = EdgeSupport.derived( edge, contingent_edge) reduced_edges.append(reduced_edge) # print("Reducing: " + str(new_edge) + " and " + str(contingent_edge)) # print("Adding reduced to edge: " + str(reduced_edge.fro) + "->" + str(reduced_edge.to) + " (" + str(reduced_edge.value) + ")") else: reduced_edges.append(new_edge) return num_nodes, reduced_edges
def add_uncontrollable(fro, new_node, to, lb, ub, edge_id): # no negative lower bound # no infinite upperbound assert lb <= ub assert not lb < 0 assert not math.isinf(ub) if new_node is not None: lb_ub_edge = DistanceGraphEdge(fro, new_node, lb, EdgeType.SIMPLE, renaming=renaming) lb_lb_edge = DistanceGraphEdge(new_node, fro, -lb, EdgeType.SIMPLE, renaming=renaming) self.edge_support[lb_ub_edge] = EdgeSupport.base({ (EdgeSupport.LOWER, edge_id): 1, }) self.edge_support[lb_lb_edge] = EdgeSupport.base({ (EdgeSupport.LOWER, edge_id): -1, }) edge_list.append(lb_ub_edge) edge_list.append(lb_lb_edge) # print("LBUB edge: "+ str(lb_ub_edge)) # print("LBLB edge: "+ str(lb_lb_edge)) else: new_node = fro ub_edge = DistanceGraphEdge(new_node, to, ub - lb, EdgeType.SIMPLE, renaming=renaming) lb_edge = DistanceGraphEdge(to, new_node, 0, EdgeType.SIMPLE, renaming=renaming) self.edge_support[ub_edge] = EdgeSupport.base({ (EdgeSupport.LOWER, edge_id): -1, (EdgeSupport.UPPER, edge_id): 1, }) self.edge_support[lb_edge] = EdgeSupport.base({}) ub_cond_edge = DistanceGraphEdge(to, new_node, lb - ub, EdgeType.UPPER_CASE, to, renaming=renaming) lb_cond_edge = DistanceGraphEdge(new_node, to, 0, EdgeType.LOWER_CASE, to, renaming=renaming) self.edge_support[ub_cond_edge] = EdgeSupport.base({ (EdgeSupport.LOWER, edge_id): 1, (EdgeSupport.UPPER, edge_id): -1, }) self.edge_support[lb_cond_edge] = EdgeSupport.base({}) edge_list.append(ub_edge) edge_list.append(lb_edge) edge_list.append(ub_cond_edge) edge_list.append(lb_cond_edge)