Example #1
0
    def split(self, graph):
        ''' Split nodes into d.cv alias nodes with identical edges '''
        self.a_graph = self.alias_graph(graph)

        new_disks = []
        new_edges = []
        originals = []

        for d in self.a_graph.nodes():
            if d.org.cv > 1:
                edges = self.a_graph.edges(d)
                originals += self.a_graph.edges(d)

                # Create d.cv number of clones
                clones = [Alias(d.org) for i in range(1, d.org.cv)]

                # Distribute edges round-robin
                for i, e in enumerate(edges):
                    new_edges.append((clones[i % len(clones)], e[1]))

        # Append cv clones
        self.a_graph.add_nodes_from(new_disks)
        self.a_graph.add_edges_from(new_edges)

        # Remove original edges for disks w/ cv > 1
        self.a_graph.remove_edges_from(originals)

        return self.a_graph
Example #2
0
    def alias_graph(self, graph):
        a = nx.MultiGraph()

        for d in graph.nodes():
            # Create alias disk
            disk_alias = Alias(d)

            # Copy edges from original
            edges = graph.edges(d)
            alias_edges = [(disk_alias, Alias(e[1])) for e in edges]

            # Add to alias graph
            a.add_node(disk_alias)
            a.add_edges_from(alias_edges)

        return a
Example #3
0
    def mg_split(self, graph):
        # Count occurence of edges
        occ = Counter(graph.edges())

        for e in occ:
            n = occ[e]
            while n > 1:
                # Create new edge using Alias of e[0]
                graph.add_edge(Alias(e[0]), e[1])

                # Remove old edge
                graph.remove_edge(e[0],e[1])

                n -= 1
Example #4
0
    def split(self, graph):
        ''' Split nodes into d.cv alias nodes with identical edges '''
        self.a_graph = self.alias_graph(graph)

        new_disks = []
        new_edges = []
        for d in self.a_graph.nodes():
            if d.org.cv > 1:
                edges = self.a_graph.edges(d)
                
                # Create d.cv number of clones with  a cv of 1
                for i in range(1,d.org.cv-1):
                    new_d = Alias(d.org)
                    new_edges = [(new_d, e[1]) for e in edges]

        # Append cv clones
        self.a_graph.add_nodes_from(new_disks)
        self.a_graph.add_edges_from(new_edges)
  
        return self.a_graph
Example #5
0
    def gen_edges(self, graph):
        ''' Build bipartite graph '''
        # Normalize
        if not self.normalized:
            # Relax CV
            for d in graph:
                if d.cv % 2:
                    d.cv -= 1
                    d.avail -= 1

            #self.mg_split(graph)
            self.normalize(graph)
            self.normalized = True

            # Euler cycle
            ec = nx.eulerian_circuit(graph)

            # Remove self-loops on graph
            loops = []
            for e in graph.edges():
                if e[0].org is e[1].org:
                    loops.append(e)

            graph.remove_edges_from(loops)

            # Bipartite graph for flow problem, NOTE: cannot express MG characteristics
            self.b = nx.DiGraph()

            # v-in aliases and edge mapping
            v_out = [d for d in graph.nodes()]
            v_in = {d: Alias(d) for d in graph.nodes()}

            # Added edges in euler cycle with capacity of 1
            c = 0
            for e in ec:
                self.b.add_edge(e[0], v_in[e[1]], capacity=1)

                if e[0].org is not e[1].org:
                    c += 1

            # Create s-node
            self.b.add_node('t')
            for d in v_in.items():
                self.b.add_edge(d[1], 't', capacity=ceil(d[1].org.cv / 2))

            # Create t-node
            self.b.add_node('s')
            for d in v_out:
                self.b.add_edge('s', d, capacity=ceil(d.cv / 2))

        # Ford-Fulkerson flow Returns: (flow_val, flow_dict)
        _, flow_dict = nx.maximum_flow(self.b, 's', 't')

        # Extract active edges and cull self loops and s/t nodes
        flow = [(d[0], d2[0]) for d in flow_dict.items() for d2 in d[1].items() \
                if d2[1] > 0 and d[0] not in ['s','t'] and d2[0] not in ['s','t']]

        self.b.remove_edges_from(flow)

        # Reassociate aliases and return queue
        return [(e[0].org, e[1].org) for e in flow if e[0].org is not e[1].org]