From 574c75b95b55fdcb5eb0c49bf99ce76f1765fcd1 Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Fri, 1 Nov 2019 16:59:43 +0300 Subject: [PATCH 01/20] Create Program.cs --- Task02/Program.cs | 110 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 Task02/Program.cs diff --git a/Task02/Program.cs b/Task02/Program.cs new file mode 100644 index 0000000..635b822 --- /dev/null +++ b/Task02/Program.cs @@ -0,0 +1,110 @@ +using System; +using System.IO; +using System.Diagnostics; + +namespace Task02 +{ + class Program + { + static void Main() + { + StreamWriter foutFloyd = new StreamWriter("floyd.txt"); + StreamWriter foutKruskal = new StreamWriter("kruskal.txt"); + StreamWriter foutPrim = new StreamWriter("prim.txt"); + + Console.WriteLine("Введите количество вершин нового графа:"); + string inputN = Console.ReadLine(); + int n = int.Parse(inputN); + Console.WriteLine("Введите примерное количество рёбер нового графа:"); + string inputM = Console.ReadLine(); + int m = int.Parse(inputM); + Console.WriteLine("Введите два числа - диапазон весов рёбер нового графа:"); + string[] inputW = Console.ReadLine().Split(" "); + int minWeight = int.Parse(inputW[0]); + int maxWeight = int.Parse(inputW[1]); + + Console.WriteLine("\nСоздание нового графа..."); + GenerateMatrix.Execute(n, m, minWeight, maxWeight); + Console.WriteLine("Новый граф успешно создан.\n"); + + Stopwatch timeSequentialFloyd = Stopwatch.StartNew(); + int[,] ansSequentialFloyd = SequentialAlgoFloyd.Execute(); + timeSequentialFloyd.Stop(); + Console.WriteLine($"Время исполнения последовательного алгоритма Флойда = {timeSequentialFloyd.ElapsedMilliseconds} мс."); + + Stopwatch timeParallelFloyd = Stopwatch.StartNew(); + int[,] ansParallelFloyd = ParallelAlgoFloyd.Execute(); + timeParallelFloyd.Stop(); + Console.WriteLine($"Время исполнения параллельного алгоритма Флойда = {timeParallelFloyd.ElapsedMilliseconds} мс."); + + Stopwatch timeSequentialKruskal = Stopwatch.StartNew(); + int ansSequentialKruskal = SequentialAlgoKruskal.Execute(); + timeSequentialKruskal.Stop(); + Console.WriteLine($"Время исполнения последовательного алгоритма Краскала = {timeSequentialKruskal.ElapsedMilliseconds} мс."); + + Stopwatch timeParallelKruskal = Stopwatch.StartNew(); + int ansParallelKruskal = ParallelAlgoKruskal.Execute(); + timeParallelKruskal.Stop(); + Console.WriteLine($"Время исполнения параллельного алгоритма Краскала = {timeParallelKruskal.ElapsedMilliseconds} мс."); + + Stopwatch timeParallelPrim = Stopwatch.StartNew(); + int ansParallelPrim = ParallelAlgoPrim.Execute(); + timeParallelPrim.Stop(); + Console.WriteLine($"Время исполнения параллельного алгоритма Прима = {timeParallelPrim.ElapsedMilliseconds} мс."); + + Console.WriteLine(); + + bool ansEquals = true; + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + if (ansSequentialFloyd[i, j] != ansParallelFloyd[i, j]) + { + ansEquals = false; + break; + } + } + } + if (ansEquals) + { + Console.WriteLine("OK: Ответ параллельного алгоритма Флойда совпал с последовательным."); + } + else + { + Console.WriteLine("WA: Ответ параллельного алгоритма Флойда не совпал с последовательным."); + } + + if (ansSequentialKruskal == ansParallelKruskal) + { + Console.WriteLine("OK: Ответ параллельного алгоритма Краскала совпал с последовательным."); + } + else + { + Console.WriteLine("WA: Ответ параллельного алгоритма Краскала не совпал с последовательным."); + } + + if (ansSequentialKruskal == ansParallelPrim) + { + Console.WriteLine("OK: Ответ параллельного алгоритма Прима совпал с последовательным алгоритмом Краскала."); + } + else + { + Console.WriteLine("WA: Ответ параллельного алгоритма Прима не совпал с последовательным алгоритмом Краскала."); + } + + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + foutFloyd.Write($"{ansParallelFloyd[i, j]}{(j + 1 == n ? '\n' : ' ')}"); + } + } + foutKruskal.Write(ansParallelKruskal); + foutPrim.Write(ansParallelPrim); + foutFloyd.Close(); + foutKruskal.Close(); + foutPrim.Close(); + } + } +} From 8e90ff5d1e19f2a6ca1d4ba4bcde96e8c9043dce Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Fri, 1 Nov 2019 17:01:00 +0300 Subject: [PATCH 02/20] Create GeneralResources.cs --- Task02/GeneralResources.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 Task02/GeneralResources.cs diff --git a/Task02/GeneralResources.cs b/Task02/GeneralResources.cs new file mode 100644 index 0000000..7add4dd --- /dev/null +++ b/Task02/GeneralResources.cs @@ -0,0 +1,10 @@ +namespace Task02 +{ + public class GeneralResources + { + public const int INF = 1000000000; + public static int[,] graphMatrix; + public static (int, int, int)[] graphListEdges; + public static int n; + } +} From defeff116c3a9db202036dbe35aa21c89af51ddd Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Fri, 1 Nov 2019 17:01:27 +0300 Subject: [PATCH 03/20] Create GenerateMatrix.cs --- Task02/GenerateMatrix.cs | 59 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 Task02/GenerateMatrix.cs diff --git a/Task02/GenerateMatrix.cs b/Task02/GenerateMatrix.cs new file mode 100644 index 0000000..5d9056e --- /dev/null +++ b/Task02/GenerateMatrix.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; + +namespace Task02 +{ + public class GenerateMatrix + { + static int Whole = 1000000; + + public static void Execute(int n, int m, int minWeight, int maxWeight) + { + GeneralResources.n = n; + GeneralResources.graphMatrix = new int[n, n]; + Random random = new Random(); + int partAmountEdgesFromMax = (int)((long)m * Whole / (n * (n - 1) / 2)); + m = 0; + for (int i = 0; i < n; i++) + { + for (int j = i + 1; j < n; j++) + { + if (random.Next(Whole) < partAmountEdgesFromMax) + { + int weight = random.Next(minWeight, maxWeight); + GeneralResources.graphMatrix[i, j] = GeneralResources.graphMatrix[j, i] = weight; + m++; + } + else + { + GeneralResources.graphMatrix[i, j] = GeneralResources.graphMatrix[j, i] = GeneralResources.INF; + } + } + } + + GeneralResources.graphListEdges = new (int, int, int)[m]; + int k = 0; + for (int i = 0; i < n; i++) + { + for (int j = i + 1; j < n; j++) + { + if (GeneralResources.graphMatrix[i, j] != GeneralResources.INF) + { + GeneralResources.graphListEdges[k] = (GeneralResources.graphMatrix[i, j], i, j); + k++; + } + } + } + + StreamWriter foutMatrix = new StreamWriter("matrix.txt"); + foutMatrix.Write($"{n} {m}\n"); + for (k = 0; k < m; k++) + { + foutMatrix.Write($"{GeneralResources.graphListEdges[k].Item2 + 1} " + + $"{GeneralResources.graphListEdges[k].Item3 + 1} " + + $"{GeneralResources.graphListEdges[k].Item1}\n"); + } + foutMatrix.Close(); + } + } +} From 06eaed3546d970b400b1644d3151cf8e792992a4 Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Fri, 1 Nov 2019 17:01:56 +0300 Subject: [PATCH 04/20] Create SequentialAlgoFloyd.cs --- Task02/SequentialAlgoFloyd.cs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 Task02/SequentialAlgoFloyd.cs diff --git a/Task02/SequentialAlgoFloyd.cs b/Task02/SequentialAlgoFloyd.cs new file mode 100644 index 0000000..34087ce --- /dev/null +++ b/Task02/SequentialAlgoFloyd.cs @@ -0,0 +1,27 @@ +using System; + +namespace Task02 +{ + public class SequentialAlgoFloyd + { + public static int[,] Execute() + { + int n = GeneralResources.n; + int[,] dist = new int[n, n]; + Array.Copy(GeneralResources.graphMatrix, dist, n * n); + + for (int k = 0; k < n; k++) + { + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + if (dist[i, j] > dist[i, k] + dist[k, j]) + dist[i, j] = dist[i, k] + dist[k, j]; + } + } + } + return dist; + } + } +} From e8ad5fefc0389ab73b08953d42c80c1b1a37bc76 Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Fri, 1 Nov 2019 17:02:21 +0300 Subject: [PATCH 05/20] Create SequentialAlgoKruskal.cs --- Task02/SequentialAlgoKruskal.cs | 46 +++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 Task02/SequentialAlgoKruskal.cs diff --git a/Task02/SequentialAlgoKruskal.cs b/Task02/SequentialAlgoKruskal.cs new file mode 100644 index 0000000..4ab4200 --- /dev/null +++ b/Task02/SequentialAlgoKruskal.cs @@ -0,0 +1,46 @@ +using System; + +namespace Task02 +{ + public class SequentialAlgoKruskal + { + static int[] dsu; + + static int getDsu(int x) + { + return dsu[x] == -1 ? x : dsu[x] = getDsu(dsu[x]); + } + + static bool unionDsu(int x, int y) + { + x = getDsu(x); + y = getDsu(y); + if (x == y) + return false; + if ((x + 2 * y) % 4 * 2 % 6 != 0) // псевдорандом + dsu[y] = x; + else + dsu[x] = y; + return true; + } + + public static int Execute() + { + int ans = 0; + (int, int, int)[] edges = GeneralResources.graphListEdges; + Array.Sort(edges); + + dsu = new int[GeneralResources.n]; + Array.Fill(dsu, -1); + + for (int i = 0; i < edges.Length; i++) + { + if (unionDsu(edges[i].Item2, edges[i].Item3)) + { + ans += edges[i].Item1; + } + } + return ans; + } + } +} From f3b19ec9cde938d4a92fa4f6319a9a60fb3aea5f Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Fri, 1 Nov 2019 17:02:46 +0300 Subject: [PATCH 06/20] Create ParallelAlgoFloyd.cs --- Task02/ParallelAlgoFloyd.cs | 50 +++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Task02/ParallelAlgoFloyd.cs diff --git a/Task02/ParallelAlgoFloyd.cs b/Task02/ParallelAlgoFloyd.cs new file mode 100644 index 0000000..0b40924 --- /dev/null +++ b/Task02/ParallelAlgoFloyd.cs @@ -0,0 +1,50 @@ +using System; +using System.Threading.Tasks; + +namespace Task02 +{ + public class ParallelAlgoFloyd + { + static int[,] dist; + + static void parallelProc(int n, int k, int i) + { + for (int j = 0; j < n; j++) + { + if (j != k) + { + if (dist[i, j] > dist[i, k] + dist[k, j]) + dist[i, j] = dist[i, k] + dist[k, j]; + } + } + } + + public static int[,] Execute() + { + int n = GeneralResources.n; + dist = new int[n, n]; + Task[] tasks = new Task[n - 1]; + Array.Copy(GeneralResources.graphMatrix, dist, n * n); + + for (int k = 0; k < n; k++) + { + for (int i = 0; i < n; i++) + { + if (i != k) + { + int newK = k; + int newI = i; + // передаём newK и newI для того, чтобы избежать замыкания + tasks[i < k ? i : i - 1] = Task.Run(() => parallelProc(n, newK, newI)); + } + } + // ждём выполнения всех задач для того, чтобы случайно не получилось так, что + // задача с большим k не обогнала задачу с меньшим k (и чтобы нам всегда хватило + // ровно n - 1 задачи) + Task.WaitAll(tasks); + } + + return dist; + } + } +} From 42657e1dd074d245c442e2989ddda06f3aa35585 Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Fri, 1 Nov 2019 17:03:17 +0300 Subject: [PATCH 07/20] Create ParallelAlgoKruskal.cs --- Task02/ParallelAlgoKruskal.cs | 95 +++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 Task02/ParallelAlgoKruskal.cs diff --git a/Task02/ParallelAlgoKruskal.cs b/Task02/ParallelAlgoKruskal.cs new file mode 100644 index 0000000..991f792 --- /dev/null +++ b/Task02/ParallelAlgoKruskal.cs @@ -0,0 +1,95 @@ +using System; +using System.Threading; + +namespace Task02 +{ + public class ParallelAlgoKruskal + { + static int[] dsu; + static int parallelDepth = 3; // глубина рекурсии, до которой происходит распараллеливание сортировки рёбер + + static int getDsu(int x) + { + return dsu[x] == -1 ? x : dsu[x] = getDsu(dsu[x]); + } + + static bool unionDsu(int x, int y) + { + x = getDsu(x); + y = getDsu(y); + if (x == y) + return false; + if ((x + 2 * y) % 4 * 2 % 6 != 0) // псевдорандом + dsu[y] = x; + else + dsu[x] = y; + return true; + } + + static void parallelSort(T[] edges, T[] buffer, int LIndex, int RIndex, int parallelDepth) where T : IComparable + { + // parallelSort до глубины parallelDepth реализуется как параллельная MergeSort, а глубже - встроенную сортировку + if (parallelDepth <= 0) + { + Array.Sort(edges, LIndex, RIndex - LIndex); + return; + } + if (RIndex - LIndex <= 1) + return; + int MIndex = (LIndex + RIndex) / 2; + + // чтобы поток просто так не стоял, он берёт на себя сортировку половины массива, а другую отдаёт новому потоку + Thread helperThread = new Thread(() => parallelSort(edges, buffer, LIndex, MIndex, parallelDepth - 1)); + helperThread.Start(); + parallelSort(edges, buffer, MIndex, RIndex, parallelDepth - 1); + helperThread.Join(); + + // объединение двух отсортированных массивов через buffer + int i = LIndex, j = MIndex; + for (int k = LIndex; k < RIndex; k++) + { + if (i == MIndex) + { + buffer[k] = edges[j]; + j++; + } + else if (j == RIndex) + { + buffer[k] = edges[i]; + i++; + } + else if (edges[i].CompareTo(edges[j]) < 0) + { + buffer[k] = edges[i]; + i++; + } + else + { + buffer[k] = edges[j]; + j++; + } + } + for (int k = LIndex; k < RIndex; k++) + edges[k] = buffer[k]; + } + + public static int Execute() + { + int ans = 0; + (int, int, int)[] edges = GeneralResources.graphListEdges; + parallelSort(edges, new (int, int, int)[edges.Length], 0, edges.Length, parallelDepth); + + dsu = new int[GeneralResources.n]; + Array.Fill(dsu, -1); + + for (int i = 0; i < edges.Length; i++) + { + if (unionDsu(edges[i].Item2, edges[i].Item3)) + { + ans += edges[i].Item1; + } + } + return ans; + } + } +} From 6f54d71639b043b9ca813b8f70811f5a0180f106 Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Fri, 1 Nov 2019 17:04:09 +0300 Subject: [PATCH 08/20] Create ParallelAlgoPrim.cs --- Task02/ParallelAlgoPrim.cs | 91 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 Task02/ParallelAlgoPrim.cs diff --git a/Task02/ParallelAlgoPrim.cs b/Task02/ParallelAlgoPrim.cs new file mode 100644 index 0000000..77f6344 --- /dev/null +++ b/Task02/ParallelAlgoPrim.cs @@ -0,0 +1,91 @@ +using System; +using System.Threading; +using System.Collections.Generic; + +namespace Task02 +{ + public class ParallelAlgoPrim + { + static int v; // вершина, не лежащая в дереве, расстояние до которой от дерева минимально + static int newV; + static int amountThreads = 6; + static int runningThreads; // количество выполняющихся потоков + static int chunkSize; + static Mutex mutRunningThreads = new Mutex(); // блокировка при изменении runningThreads + static Mutex mutNewV = new Mutex(); // блокировка при чтении и изменении newV + static HashSet tree; // вершины, лежащие в остовном дереве + static int[] minDistToTree; + + static void FindNewV(int LIndex, int RIndex) + { + // нахождение очередной вершины с минимальным расстоянием до дерева + int localV = -1; // локальный ответ + + for (int to = LIndex; to < RIndex; to++) + { + if (!tree.Contains(to)) + { + // обновление минимального расстояния после добавления v в дерево + if (minDistToTree[to] > GeneralResources.graphMatrix[v, to]) + { + minDistToTree[to] = GeneralResources.graphMatrix[v, to]; + } + + // обновление локального ответа + if (localV == -1 || minDistToTree[localV] > minDistToTree[to]) + localV = to; + } + } + + if (localV != -1) + { + mutNewV.WaitOne(); + // обновление глобального ответа + if (newV == -1 || minDistToTree[newV] > minDistToTree[localV]) + newV = localV; + mutNewV.ReleaseMutex(); + } + + mutRunningThreads.WaitOne(); + runningThreads--; + mutRunningThreads.ReleaseMutex(); + } + + public static int Execute() + { + int ans = 0; + tree = new HashSet(); + minDistToTree = new int[GeneralResources.n]; + Array.Fill(minDistToTree, GeneralResources.INF); + chunkSize = GeneralResources.n / amountThreads; + + // начинаем с вершины 0 + minDistToTree[0] = 0; + v = 0; + + while (v != -1) + { + ans += minDistToTree[v]; + tree.Add(v); + + newV = -1; + + runningThreads = amountThreads; + for (int i = 0; i < amountThreads - 1; i++) + { + int LIndex = chunkSize * i; + int RIndex = chunkSize * (i + 1); + ThreadPool.QueueUserWorkItem(_ => FindNewV(LIndex, RIndex)); + } + // загрзим главный поток чтобы он просто так не ждал + FindNewV(chunkSize * (amountThreads - 1), GeneralResources.n); + + while (runningThreads > 0) {} + + v = newV; + } + + return ans; + } + } +} From 4c38cefbacf7ecbd026b9818328376a14f454305 Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Sun, 8 Dec 2019 12:03:57 +0300 Subject: [PATCH 09/20] Update GeneralResources.cs --- Task02/GeneralResources.cs | 61 +++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/Task02/GeneralResources.cs b/Task02/GeneralResources.cs index 7add4dd..e41565c 100644 --- a/Task02/GeneralResources.cs +++ b/Task02/GeneralResources.cs @@ -1,10 +1,63 @@ +using System; +using System.IO; + namespace Task02 { - public class GeneralResources + public class Graph { public const int INF = 1000000000; - public static int[,] graphMatrix; - public static (int, int, int)[] graphListEdges; - public static int n; + public int[,] graphMatrix; + public (int, int, int)[] graphListEdges; + public int graphAmountVertexes; + static int NumberOfConventionalUnitsInTotal = 1000000; + + public Graph(int n, int m, int minWeight, int maxWeight) + { + graphAmountVertexes = n; + graphMatrix = new int[n, n]; + Random random = new Random(); + int partAmountEdgesFromMax = (int)((long)m * NumberOfConventionalUnitsInTotal / (n * (n - 1) / 2)); + m = 0; + for (int i = 0; i < n; i++) + { + for (int j = i + 1; j < n; j++) + { + if (random.Next(NumberOfConventionalUnitsInTotal) < partAmountEdgesFromMax) + { + int weight = random.Next(minWeight, maxWeight); + graphMatrix[i, j] = graphMatrix[j, i] = weight; + m++; + } + else + { + graphMatrix[i, j] = graphMatrix[j, i] = INF; + } + } + } + + graphListEdges = new (int, int, int)[m]; + int k = 0; + for (int i = 0; i < n; i++) + { + for (int j = i + 1; j < n; j++) + { + if (graphMatrix[i, j] != INF) + { + graphListEdges[k] = (graphMatrix[i, j], i, j); + k++; + } + } + } + + StreamWriter foutMatrix = new StreamWriter("matrix.txt"); + foutMatrix.Write($"{n} {m}\n"); + for (k = 0; k < m; k++) + { + foutMatrix.Write($"{graphListEdges[k].Item2 + 1} " + + $"{graphListEdges[k].Item3 + 1} " + + $"{graphListEdges[k].Item1}\n"); + } + foutMatrix.Close(); + } } } From 4b3b2e0d0434e6f0cb77288cd99c9ae40340cf86 Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Sun, 8 Dec 2019 12:04:23 +0300 Subject: [PATCH 10/20] Delete GenerateMatrix.cs --- Task02/GenerateMatrix.cs | 59 ---------------------------------------- 1 file changed, 59 deletions(-) delete mode 100644 Task02/GenerateMatrix.cs diff --git a/Task02/GenerateMatrix.cs b/Task02/GenerateMatrix.cs deleted file mode 100644 index 5d9056e..0000000 --- a/Task02/GenerateMatrix.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.IO; - -namespace Task02 -{ - public class GenerateMatrix - { - static int Whole = 1000000; - - public static void Execute(int n, int m, int minWeight, int maxWeight) - { - GeneralResources.n = n; - GeneralResources.graphMatrix = new int[n, n]; - Random random = new Random(); - int partAmountEdgesFromMax = (int)((long)m * Whole / (n * (n - 1) / 2)); - m = 0; - for (int i = 0; i < n; i++) - { - for (int j = i + 1; j < n; j++) - { - if (random.Next(Whole) < partAmountEdgesFromMax) - { - int weight = random.Next(minWeight, maxWeight); - GeneralResources.graphMatrix[i, j] = GeneralResources.graphMatrix[j, i] = weight; - m++; - } - else - { - GeneralResources.graphMatrix[i, j] = GeneralResources.graphMatrix[j, i] = GeneralResources.INF; - } - } - } - - GeneralResources.graphListEdges = new (int, int, int)[m]; - int k = 0; - for (int i = 0; i < n; i++) - { - for (int j = i + 1; j < n; j++) - { - if (GeneralResources.graphMatrix[i, j] != GeneralResources.INF) - { - GeneralResources.graphListEdges[k] = (GeneralResources.graphMatrix[i, j], i, j); - k++; - } - } - } - - StreamWriter foutMatrix = new StreamWriter("matrix.txt"); - foutMatrix.Write($"{n} {m}\n"); - for (k = 0; k < m; k++) - { - foutMatrix.Write($"{GeneralResources.graphListEdges[k].Item2 + 1} " + - $"{GeneralResources.graphListEdges[k].Item3 + 1} " + - $"{GeneralResources.graphListEdges[k].Item1}\n"); - } - foutMatrix.Close(); - } - } -} From cfc194a2b5c10013199fdd91b836d18d2a53ee39 Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Sun, 8 Dec 2019 12:04:45 +0300 Subject: [PATCH 11/20] Update ParallelAlgoFloyd.cs --- Task02/ParallelAlgoFloyd.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Task02/ParallelAlgoFloyd.cs b/Task02/ParallelAlgoFloyd.cs index 0b40924..55d9724 100644 --- a/Task02/ParallelAlgoFloyd.cs +++ b/Task02/ParallelAlgoFloyd.cs @@ -19,12 +19,12 @@ static void parallelProc(int n, int k, int i) } } - public static int[,] Execute() + public static int[,] Execute(Graph graph) { - int n = GeneralResources.n; + int n = graph.graphAmountVertexes; dist = new int[n, n]; Task[] tasks = new Task[n - 1]; - Array.Copy(GeneralResources.graphMatrix, dist, n * n); + Array.Copy(graph.graphMatrix, dist, n * n); for (int k = 0; k < n; k++) { From 5cacdd1e166950993f671f683cd66ea72852b6ad Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Sun, 8 Dec 2019 12:05:03 +0300 Subject: [PATCH 12/20] Update ParallelAlgoKruskal.cs --- Task02/ParallelAlgoKruskal.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Task02/ParallelAlgoKruskal.cs b/Task02/ParallelAlgoKruskal.cs index 991f792..998ff74 100644 --- a/Task02/ParallelAlgoKruskal.cs +++ b/Task02/ParallelAlgoKruskal.cs @@ -73,13 +73,13 @@ static void parallelSort(T[] edges, T[] buffer, int LIndex, int RIndex, int p edges[k] = buffer[k]; } - public static int Execute() + public static int Execute(Graph graph) { int ans = 0; - (int, int, int)[] edges = GeneralResources.graphListEdges; + (int, int, int)[] edges = graph.graphListEdges; parallelSort(edges, new (int, int, int)[edges.Length], 0, edges.Length, parallelDepth); - dsu = new int[GeneralResources.n]; + dsu = new int[graph.graphAmountVertexes]; Array.Fill(dsu, -1); for (int i = 0; i < edges.Length; i++) From f55666a4b07da77814c2e60b58ac18660836ae61 Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Sun, 8 Dec 2019 12:05:22 +0300 Subject: [PATCH 13/20] Update ParallelAlgoPrim.cs --- Task02/ParallelAlgoPrim.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Task02/ParallelAlgoPrim.cs b/Task02/ParallelAlgoPrim.cs index 77f6344..304bf30 100644 --- a/Task02/ParallelAlgoPrim.cs +++ b/Task02/ParallelAlgoPrim.cs @@ -16,7 +16,7 @@ public class ParallelAlgoPrim static HashSet tree; // вершины, лежащие в остовном дереве static int[] minDistToTree; - static void FindNewV(int LIndex, int RIndex) + static void FindNewV(Graph graph, int LIndex, int RIndex) { // нахождение очередной вершины с минимальным расстоянием до дерева int localV = -1; // локальный ответ @@ -26,9 +26,9 @@ static void FindNewV(int LIndex, int RIndex) if (!tree.Contains(to)) { // обновление минимального расстояния после добавления v в дерево - if (minDistToTree[to] > GeneralResources.graphMatrix[v, to]) + if (minDistToTree[to] > graph.graphMatrix[v, to]) { - minDistToTree[to] = GeneralResources.graphMatrix[v, to]; + minDistToTree[to] = graph.graphMatrix[v, to]; } // обновление локального ответа @@ -51,13 +51,13 @@ static void FindNewV(int LIndex, int RIndex) mutRunningThreads.ReleaseMutex(); } - public static int Execute() + public static int Execute(Graph graph) { int ans = 0; tree = new HashSet(); - minDistToTree = new int[GeneralResources.n]; - Array.Fill(minDistToTree, GeneralResources.INF); - chunkSize = GeneralResources.n / amountThreads; + minDistToTree = new int[graph.graphAmountVertexes]; + Array.Fill(minDistToTree, Graph.INF); + chunkSize = graph.graphAmountVertexes / amountThreads; // начинаем с вершины 0 minDistToTree[0] = 0; @@ -75,10 +75,10 @@ public static int Execute() { int LIndex = chunkSize * i; int RIndex = chunkSize * (i + 1); - ThreadPool.QueueUserWorkItem(_ => FindNewV(LIndex, RIndex)); + ThreadPool.QueueUserWorkItem(_ => FindNewV(graph, LIndex, RIndex)); } // загрзим главный поток чтобы он просто так не ждал - FindNewV(chunkSize * (amountThreads - 1), GeneralResources.n); + FindNewV(graph, chunkSize * (amountThreads - 1), graph.graphAmountVertexes); while (runningThreads > 0) {} From 85e0d6fa823259b260b34ef91dea26bbae61bea8 Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Sun, 8 Dec 2019 12:05:37 +0300 Subject: [PATCH 14/20] Update Program.cs --- Task02/Program.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Task02/Program.cs b/Task02/Program.cs index 635b822..ad6bf93 100644 --- a/Task02/Program.cs +++ b/Task02/Program.cs @@ -24,31 +24,31 @@ static void Main() int maxWeight = int.Parse(inputW[1]); Console.WriteLine("\nСоздание нового графа..."); - GenerateMatrix.Execute(n, m, minWeight, maxWeight); + Graph graph = new Graph(n, m, minWeight, maxWeight); Console.WriteLine("Новый граф успешно создан.\n"); Stopwatch timeSequentialFloyd = Stopwatch.StartNew(); - int[,] ansSequentialFloyd = SequentialAlgoFloyd.Execute(); + int[,] ansSequentialFloyd = SequentialAlgoFloyd.Execute(graph); timeSequentialFloyd.Stop(); Console.WriteLine($"Время исполнения последовательного алгоритма Флойда = {timeSequentialFloyd.ElapsedMilliseconds} мс."); Stopwatch timeParallelFloyd = Stopwatch.StartNew(); - int[,] ansParallelFloyd = ParallelAlgoFloyd.Execute(); + int[,] ansParallelFloyd = ParallelAlgoFloyd.Execute(graph); timeParallelFloyd.Stop(); Console.WriteLine($"Время исполнения параллельного алгоритма Флойда = {timeParallelFloyd.ElapsedMilliseconds} мс."); Stopwatch timeSequentialKruskal = Stopwatch.StartNew(); - int ansSequentialKruskal = SequentialAlgoKruskal.Execute(); + int ansSequentialKruskal = SequentialAlgoKruskal.Execute(graph); timeSequentialKruskal.Stop(); Console.WriteLine($"Время исполнения последовательного алгоритма Краскала = {timeSequentialKruskal.ElapsedMilliseconds} мс."); Stopwatch timeParallelKruskal = Stopwatch.StartNew(); - int ansParallelKruskal = ParallelAlgoKruskal.Execute(); + int ansParallelKruskal = ParallelAlgoKruskal.Execute(graph); timeParallelKruskal.Stop(); Console.WriteLine($"Время исполнения параллельного алгоритма Краскала = {timeParallelKruskal.ElapsedMilliseconds} мс."); Stopwatch timeParallelPrim = Stopwatch.StartNew(); - int ansParallelPrim = ParallelAlgoPrim.Execute(); + int ansParallelPrim = ParallelAlgoPrim.Execute(graph); timeParallelPrim.Stop(); Console.WriteLine($"Время исполнения параллельного алгоритма Прима = {timeParallelPrim.ElapsedMilliseconds} мс."); From c6b46676b4424eb006282ca0cf94741dcf5c4a2a Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Sun, 8 Dec 2019 12:05:54 +0300 Subject: [PATCH 15/20] Update SequentialAlgoFloyd.cs --- Task02/SequentialAlgoFloyd.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Task02/SequentialAlgoFloyd.cs b/Task02/SequentialAlgoFloyd.cs index 34087ce..2586ae1 100644 --- a/Task02/SequentialAlgoFloyd.cs +++ b/Task02/SequentialAlgoFloyd.cs @@ -4,11 +4,11 @@ namespace Task02 { public class SequentialAlgoFloyd { - public static int[,] Execute() + public static int[,] Execute(Graph graph) { - int n = GeneralResources.n; + int n = graph.graphAmountVertexes; int[,] dist = new int[n, n]; - Array.Copy(GeneralResources.graphMatrix, dist, n * n); + Array.Copy(graph.graphMatrix, dist, n * n); for (int k = 0; k < n; k++) { From b5fc6440e627b27fbf1cc0478c9d9b66b1935888 Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Sun, 8 Dec 2019 12:06:21 +0300 Subject: [PATCH 16/20] Update SequentialAlgoKruskal.cs --- Task02/SequentialAlgoKruskal.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Task02/SequentialAlgoKruskal.cs b/Task02/SequentialAlgoKruskal.cs index 4ab4200..a371dbc 100644 --- a/Task02/SequentialAlgoKruskal.cs +++ b/Task02/SequentialAlgoKruskal.cs @@ -24,13 +24,13 @@ static bool unionDsu(int x, int y) return true; } - public static int Execute() + public static int Execute(Graph graph) { int ans = 0; - (int, int, int)[] edges = GeneralResources.graphListEdges; + (int, int, int)[] edges = graph.graphListEdges; Array.Sort(edges); - dsu = new int[GeneralResources.n]; + dsu = new int[graph.graphAmountVertexes]; Array.Fill(dsu, -1); for (int i = 0; i < edges.Length; i++) From b5d4a689046c13967e544c5c139aec80c9debb94 Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Sun, 8 Dec 2019 12:54:33 +0300 Subject: [PATCH 17/20] Update GeneralResources.cs --- Task02/GeneralResources.cs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/Task02/GeneralResources.cs b/Task02/GeneralResources.cs index e41565c..d6b9492 100644 --- a/Task02/GeneralResources.cs +++ b/Task02/GeneralResources.cs @@ -11,22 +11,23 @@ public class Graph public int graphAmountVertexes; static int NumberOfConventionalUnitsInTotal = 1000000; - public Graph(int n, int m, int minWeight, int maxWeight) + public Graph(int amountVertexes, int approximateAmountEdges, int minWeight, int maxWeight) { - graphAmountVertexes = n; - graphMatrix = new int[n, n]; + graphAmountVertexes = amountVertexes; + graphMatrix = new int[amountVertexes, amountVertexes]; Random random = new Random(); - int partAmountEdgesFromMax = (int)((long)m * NumberOfConventionalUnitsInTotal / (n * (n - 1) / 2)); - m = 0; - for (int i = 0; i < n; i++) + int partAmountEdgesFromMax = (int)((long)approximateAmountEdges * NumberOfConventionalUnitsInTotal / + (amountVertexes * (amountVertexes - 1) / 2)); + int exectAmountEdges = 0; + for (int i = 0; i < amountVertexes; i++) { - for (int j = i + 1; j < n; j++) + for (int j = i + 1; j < amountVertexes; j++) { if (random.Next(NumberOfConventionalUnitsInTotal) < partAmountEdgesFromMax) { int weight = random.Next(minWeight, maxWeight); graphMatrix[i, j] = graphMatrix[j, i] = weight; - m++; + exectAmountEdges++; } else { @@ -35,11 +36,11 @@ public Graph(int n, int m, int minWeight, int maxWeight) } } - graphListEdges = new (int, int, int)[m]; + graphListEdges = new (int, int, int)[exectAmountEdges]; int k = 0; - for (int i = 0; i < n; i++) + for (int i = 0; i < amountVertexes; i++) { - for (int j = i + 1; j < n; j++) + for (int j = i + 1; j < amountVertexes; j++) { if (graphMatrix[i, j] != INF) { @@ -50,8 +51,8 @@ public Graph(int n, int m, int minWeight, int maxWeight) } StreamWriter foutMatrix = new StreamWriter("matrix.txt"); - foutMatrix.Write($"{n} {m}\n"); - for (k = 0; k < m; k++) + foutMatrix.Write($"{amountVertexes} {exectAmountEdges}\n"); + for (k = 0; k < exectAmountEdges; k++) { foutMatrix.Write($"{graphListEdges[k].Item2 + 1} " + $"{graphListEdges[k].Item3 + 1} " + From 26ef6b4e265230f2a786f4cfaf3663c91ae7137d Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Sun, 8 Dec 2019 12:54:58 +0300 Subject: [PATCH 18/20] Update ParallelAlgoFloyd.cs --- Task02/ParallelAlgoFloyd.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Task02/ParallelAlgoFloyd.cs b/Task02/ParallelAlgoFloyd.cs index 55d9724..c7c74a4 100644 --- a/Task02/ParallelAlgoFloyd.cs +++ b/Task02/ParallelAlgoFloyd.cs @@ -5,7 +5,7 @@ namespace Task02 { public class ParallelAlgoFloyd { - static int[,] dist; + private static int[,] dist; static void parallelProc(int n, int k, int i) { @@ -36,6 +36,10 @@ static void parallelProc(int n, int k, int i) int newI = i; // передаём newK и newI для того, чтобы избежать замыкания tasks[i < k ? i : i - 1] = Task.Run(() => parallelProc(n, newK, newI)); + // так как i из 0..(n-1), но одно из значений i не используется (блокируется + // условием i != k), то для единообразия обработки Task tasks.Length == n - 1, + // и выражение (i < k ? i : i - 1) задаёт биекцию из [0; k-1] U [k+1; n-1] в + // [0; n-2] } } // ждём выполнения всех задач для того, чтобы случайно не получилось так, что From 751cc47da0d893ea0d644b866f0dbee804bcbe8f Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Sun, 8 Dec 2019 12:55:25 +0300 Subject: [PATCH 19/20] Update ParallelAlgoKruskal.cs --- Task02/ParallelAlgoKruskal.cs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/Task02/ParallelAlgoKruskal.cs b/Task02/ParallelAlgoKruskal.cs index 998ff74..4feee45 100644 --- a/Task02/ParallelAlgoKruskal.cs +++ b/Task02/ParallelAlgoKruskal.cs @@ -5,6 +5,7 @@ namespace Task02 { public class ParallelAlgoKruskal { + static Random rand = new Random(); static int[] dsu; static int parallelDepth = 3; // глубина рекурсии, до которой происходит распараллеливание сортировки рёбер @@ -19,7 +20,7 @@ static bool unionDsu(int x, int y) y = getDsu(y); if (x == y) return false; - if ((x + 2 * y) % 4 * 2 % 6 != 0) // псевдорандом + if (rand.Next(0, 1) == 1) // псевдорандом dsu[y] = x; else dsu[x] = y; @@ -48,26 +49,16 @@ static void parallelSort(T[] edges, T[] buffer, int LIndex, int RIndex, int p int i = LIndex, j = MIndex; for (int k = LIndex; k < RIndex; k++) { - if (i == MIndex) + if (i == MIndex || (j != RIndex && edges[i].CompareTo(edges[j]) >= 0)) { buffer[k] = edges[j]; j++; } - else if (j == RIndex) - { - buffer[k] = edges[i]; - i++; - } - else if (edges[i].CompareTo(edges[j]) < 0) + else { buffer[k] = edges[i]; i++; } - else - { - buffer[k] = edges[j]; - j++; - } } for (int k = LIndex; k < RIndex; k++) edges[k] = buffer[k]; From c5345439d989fedb39abdaaa746f50e2605cbb8b Mon Sep 17 00:00:00 2001 From: Kuzivanov Sergey <43182277+SergeyKuz1001@users.noreply.github.com> Date: Sun, 8 Dec 2019 12:55:48 +0300 Subject: [PATCH 20/20] Update ParallelAlgoPrim.cs --- Task02/ParallelAlgoPrim.cs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Task02/ParallelAlgoPrim.cs b/Task02/ParallelAlgoPrim.cs index 304bf30..9734ae9 100644 --- a/Task02/ParallelAlgoPrim.cs +++ b/Task02/ParallelAlgoPrim.cs @@ -6,8 +6,8 @@ namespace Task02 { public class ParallelAlgoPrim { - static int v; // вершина, не лежащая в дереве, расстояние до которой от дерева минимально - static int newV; + static int minDistVertex; // вершина, не лежащая в дереве, расстояние до которой от дерева минимально + static int newMinDistVertex; static int amountThreads = 6; static int runningThreads; // количество выполняющихся потоков static int chunkSize; @@ -19,30 +19,30 @@ public class ParallelAlgoPrim static void FindNewV(Graph graph, int LIndex, int RIndex) { // нахождение очередной вершины с минимальным расстоянием до дерева - int localV = -1; // локальный ответ + int localMinDistVertex = -1; // локальный ответ for (int to = LIndex; to < RIndex; to++) { if (!tree.Contains(to)) { // обновление минимального расстояния после добавления v в дерево - if (minDistToTree[to] > graph.graphMatrix[v, to]) + if (minDistToTree[to] > graph.graphMatrix[minDistVertex, to]) { - minDistToTree[to] = graph.graphMatrix[v, to]; + minDistToTree[to] = graph.graphMatrix[minDistVertex, to]; } // обновление локального ответа - if (localV == -1 || minDistToTree[localV] > minDistToTree[to]) - localV = to; + if (localMinDistVertex == -1 || minDistToTree[localMinDistVertex] > minDistToTree[to]) + localMinDistVertex = to; } } - if (localV != -1) + if (localMinDistVertex != -1) { mutNewV.WaitOne(); // обновление глобального ответа - if (newV == -1 || minDistToTree[newV] > minDistToTree[localV]) - newV = localV; + if (newMinDistVertex == -1 || minDistToTree[newMinDistVertex] > minDistToTree[localMinDistVertex]) + newMinDistVertex = localMinDistVertex; mutNewV.ReleaseMutex(); } @@ -61,14 +61,14 @@ public static int Execute(Graph graph) // начинаем с вершины 0 minDistToTree[0] = 0; - v = 0; + minDistVertex = 0; - while (v != -1) + while (minDistVertex != -1) { - ans += minDistToTree[v]; - tree.Add(v); + ans += minDistToTree[minDistVertex]; + tree.Add(minDistVertex); - newV = -1; + newMinDistVertex = -1; runningThreads = amountThreads; for (int i = 0; i < amountThreads - 1; i++) @@ -82,7 +82,7 @@ public static int Execute(Graph graph) while (runningThreads > 0) {} - v = newV; + minDistVertex = newMinDistVertex; } return ans;