Beispiel #1
0
    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
Beispiel #2
0
    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
Beispiel #3
0
    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
Beispiel #4
0
    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