Exemplo n.º 1
0
        /// <summary>
        /// Perform random matching partitioning.
        /// Input graph must be weighted on nodes.
        /// Nodes are only matched if they share an edge.
        /// </summary>
        /// <param name="graph">Graph with weighted nodes.</param>
        /// <param name="maxWeight">Maximum weight a matched pair is allowed to have.</param>
        /// <returns>A random matching of the nodes of the graph.</returns>
        public static Dictionary <int, int> RandomMatching(MultiDirectedGraph <int, int> graph, int maxWeight)
        {
            int counter = 0;
            var matches = new Dictionary <int, int>();

            // Visit nodes randomly
            var nodes = graph.Nodes.ToArray();

            nodes.Shuffle();
            foreach (var u in nodes)
            {
                if (!matches.ContainsKey(u))
                {
                    // Node u in unmatched, match it with one of the unmatched neighbors
                    var unmatchedNeighbors = graph.Neighbors(u).Where(v => !u.Equals(v) && !matches.ContainsKey(v) && graph.NodeLabel(u) + graph.NodeLabel(v) <= maxWeight).ToArray();

                    // Only match if such a neighbor exists
                    if (unmatchedNeighbors.Length > 0)
                    {
                        var v = Utils.Shuffled(unmatchedNeighbors).First();
                        matches.Add(u, counter);
                        matches.Add(v, counter);
                    }
                    else
                    {
                        matches.Add(u, counter);
                    }

                    counter += 1;
                }
            }

            return(matches);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Splits the nodes of a graph into P blocks by exploring.
        /// </summary>
        /// <typeparam name="TNode">Type of node.</typeparam>
        /// <typeparam name="TLabel">Type of label.</typeparam>
        /// <param name="graph">Graph to partition the nodes of.</param>
        /// <param name="P">Number of partition blocks.</param>
        public static Dictionary <TNode, int> ExploreSplit <TNode, TLabel>(MultiDirectedGraph <TNode, TLabel> graph, int P)
        {
            int n = graph.NumNodes;
            // Bucket size
            int B     = (n + P - 1) / P;
            var V     = new HashSet <TNode>();
            var Q     = new AiroQueue <TNode>();
            var nodes = graph.Nodes.ToArray();

            Utils.Shuffle(nodes);
            int seedIndex = 0;
            var partition = new Dictionary <TNode, int>();

            Action <TNode> bucketize = node =>
            {
                partition.Add(node, (n - 1) / B);
            };

            // Walk while we need to add nodes
            while (n > 0)
            {
                if (Q.Count <= 0)
                {
                    // Find next seed node, from an undiscovered connected component, and resume from there
                    while (V.Contains(nodes[seedIndex]))
                    {
                        seedIndex += 1;
                    }
                    var seed = nodes[seedIndex];

                    // Add seed to queue and set of nodes
                    Q.Put(seed);
                    V.Add(seed);
                    bucketize(seed);
                    n -= 1;
                }

                var u = Q.Take();
                var N = graph.Neighbors(u);
                foreach (var v in N)
                {
                    if (!V.Contains(v) && n > 0)
                    {
                        Q.Put(v);
                        V.Add(v);
                        bucketize(v);
                        n -= 1;
                    }
                }
            }

            return(partition);
        }