public static long RunParallelForPrim(this Graph g) { var used = new HashSet <int>(); var unused = new HashSet <int>(); used.Add(0); for (var i = 1; i < g.VerticesNumber; ++i) { unused.Add(i); } long result = 0; while (unused.Count != 0) { var curs = new long[g.VerticesNumber]; var ends = new int[g.VerticesNumber]; Parallel.ForEach(used, v => { foreach (var u in unused) { var cost = g.AdjacencyMatrix[v, u]; if (cost != 0 && (curs[v] == 0 || curs[v] > cost)) { curs[v] = cost; ends[v] = u; } } }); var cur = new Graph.Edge(0, 0, long.MaxValue); foreach (var v in used) { if (cur.weight > curs[v]) { cur = new Graph.Edge(v, ends[v], curs[v]); } } result += cur.weight; unused.Remove(cur.end); used.Add(cur.end); } return(result); }
public static long RunSequentialPrim(this Graph g) { var used = new HashSet <int>(); var unused = new HashSet <int>(); used.Add(0); for (var i = 1; i < g.VerticesNumber; ++i) { unused.Add(i); } long result = 0; while (unused.Count != 0) { var cur = new Graph.Edge(0, 0, long.MaxValue); foreach (var v in used) { foreach (var u in unused) { var cost = g.AdjacencyMatrix[v, u]; if (cost != 0 && cur.weight > cost) { cur = new Graph.Edge(v, u, cost); } } } result += cur.weight; unused.Remove(cur.end); used.Add(cur.end); } return(result); }
public static long RunParallelThreadsPrim(this Graph g) { var used = new HashSet <int>(); var unused = new HashSet <int>(); used.Add(0); for (var i = 1; i < g.VerticesNumber; ++i) { unused.Add(i); } long result = 0; while (unused.Count != 0) { var curs = new long[g.VerticesNumber]; var ends = new int[g.VerticesNumber]; var isDone = new AutoResetEvent(false); var completed = used.Count; foreach (var v in used) { ThreadPool.QueueUserWorkItem(_ => { foreach (var u in unused) { var cost = g.AdjacencyMatrix[v, u]; if (cost != 0 && (curs[v] == 0 || curs[v] > cost)) { curs[v] = cost; ends[v] = u; } } if (Interlocked.Decrement(ref completed) == 0) { isDone.Set(); } }); } isDone.WaitOne(); var cur = new Graph.Edge(0, 0, long.MaxValue); foreach (var v in used) { if (cur.weight > curs[v]) { cur = new Graph.Edge(v, ends[v], curs[v]); } } result += cur.weight; unused.Remove(cur.end); used.Add(cur.end); } return(result); }
public static long RunParallelThreadsKruskal(this Graph g) { var dsu = new DisjointSetUnion(g.VerticesNumber); var edges = new List <Graph.Edge>(); var chunkSize = g.EdgesNumber; if (g.EdgesNumber > Environment.ProcessorCount) { chunkSize = g.EdgesNumber / Environment.ProcessorCount; } var chunksNumber = g.EdgesNumber / chunkSize; var chunks = new List <Graph.Edge> [chunksNumber]; var tasks = new List <Task>(); var start = new int[chunksNumber]; for (int i = 0, chunk = chunkSize; i < g.EdgesNumber; i += chunk) { if (i + 2 * chunk > g.EdgesNumber) { chunk = g.EdgesNumber - i; } chunks[i / chunkSize] = new List <Graph.Edge>(); for (var j = i; j < i + chunk; ++j) { chunks[i / chunkSize].Add(g.Edges[j]); } var i1 = i / chunkSize; tasks.Add(Task.Run(() => chunks[i1].Sort())); } Task.WaitAll(tasks.ToArray()); while (edges.Count != g.EdgesNumber) { var cur = new Graph.Edge(); var id = -1; for (var i = 0; i < chunks.Length; ++i) { if (start[i] < chunks[i].Count && (id == -1 || chunks[i][start[i]].weight < cur.weight)) { id = i; cur = chunks[i][start[i]]; } } edges.Add(cur); ++start[id]; } long result = 0; foreach (var edge in edges) { if (dsu.Find(edge.start) != dsu.Find(edge.end)) { result += edge.weight; dsu.Union(edge.start, edge.end); } } return(result); }