HyperGraph

Конструктор копирования и деструктор для HyperGraph Вычисление

12/4/2018 3:09:29 PM

Details

diff --git a/HyperGraph/HyperGraph.cs b/HyperGraph/HyperGraph.cs
index 43e9a94..7b8f552 100644
--- a/HyperGraph/HyperGraph.cs
+++ b/HyperGraph/HyperGraph.cs
@@ -26,5 +26,41 @@ namespace HyperGraph
                 }
             }
         }
+
+        //  Конструктор копирования
+        public HyperGraph(HyperGraph graph)
+        {
+            HyperEdge = new List<List<string>>();                       
+
+            foreach (var edge in graph.HyperEdge)
+            {
+                HyperEdge.Add(new List<string>());
+                foreach (var elem in edge)
+                    HyperEdge.Last().Add(elem);                
+            }
+            Console.WriteLine();
+        }
+
+        //  При уничтожении
+        ~HyperGraph()
+        {
+            this.Dispose();
+        }
+
+        //  Очистка памяти
+        public void Dispose()
+        {
+            if (HyperEdge != null)
+            {
+                for (int i = 0; i < HyperEdge.Count; i++)
+                    HyperEdge[i] = null;
+                HyperEdge = null;
+            }
+            //  Так делать не хорошо. 
+            //  Принудительный вызов сборщика мусора после удаления ссылок на списки данных.
+            //  Очистит теперь неиспользуемую память.
+            GC.Collect();
+            GC.WaitForPendingFinalizers();
+        }
     }
 }
diff --git a/HyperGraph/HyperGraph.csproj b/HyperGraph/HyperGraph.csproj
index 37d2194..670d2f4 100644
--- a/HyperGraph/HyperGraph.csproj
+++ b/HyperGraph/HyperGraph.csproj
@@ -46,6 +46,7 @@
     <Compile Include="Matrix.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Theorem.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="App.config" />
diff --git a/HyperGraph/Matrix.cs b/HyperGraph/Matrix.cs
index 51065fa..34fd42d 100644
--- a/HyperGraph/Matrix.cs
+++ b/HyperGraph/Matrix.cs
@@ -186,7 +186,7 @@ namespace HyperGraph
                     {
                         string temp = r0w.Split(' ')[j];
                         T tmp = ConvertValue<T,string>(temp);                        
-                        matrix.matrix[i][j] = tmp;
+                        matrix[i,j] = tmp;
                     }
                 }
             }
diff --git a/HyperGraph/Program.cs b/HyperGraph/Program.cs
index 0118ca8..93a2467 100644
--- a/HyperGraph/Program.cs
+++ b/HyperGraph/Program.cs
@@ -17,15 +17,46 @@ namespace HyperGraph
         0 0 0 0 1 0 1
         */
 
+        /* 11 3
+        1 1 1
+        1 0 0
+        1 0 0
+        1 0 0
+        0 1 0
+        0 1 0
+        0 1 0
+        0 1 0
+        0 0 1
+        0 0 1
+        1 1 1
+        */
+
         static void Main(string[] args)
-        {            
+        {
+            Matrix<int> u = new Matrix<int>(4);
+
             System.IO.StreamReader input = new System.IO.StreamReader("D:\\input.txt");
             System.IO.StreamWriter output = new System.IO.StreamWriter("D:\\output.txt");
 
             //  Экземпляр гипер-графа, созданный на основе загружаемой матрицы инцидентности
-            //  6 - кол-во строк, 7 - кол-во столбцов
-            HyperGraph graph = new HyperGraph(Matrix<int>.LoadFromStream(input, 6, 7));
+            //  11 - кол-во строк, 3 - кол-во столбцов
+            HyperGraph graph = new HyperGraph(Matrix<int>.LoadFromStream(input, 11, 3));
+
+
+            //  Все перестановки гипер-графа
+            //ExampleAllTranspos(graph, input, output);
 
+            //  Вычислить количество автоморфизмов графа и вывести перестановки
+            ExampleTheorema(graph, output);
+
+            input.Close(); output.Close();
+            Console.WriteLine("Completed. Press any key");
+            Console.ReadKey();
+        }
+
+        //  Все перестановки графа вывести в файл
+        static void ExampleAllTranspos(HyperGraph graph, System.IO.StreamWriter output)
+        {
             //  Массив (лист) всех возможных перестановок одного множества (гипер-ребра)
             List<List<string>> transpos;
 
@@ -51,17 +82,33 @@ namespace HyperGraph
                 //  Алгоритм перестановок не учитывает начальную, а начинает со следующей
                 for (int g = 0; g < transpos.Count; g++)
                 {
-                    output.Write("{0}: ", g+2);
+                    output.Write("{0}: ", g + 2);
                     for (int f = 0; f < transpos[g].Count; f++)
                         output.Write("{0} ", transpos[g][f]);
                     output.WriteLine("\n\t-----------");
                 }
                 output.WriteLine();
             }
+        }
 
-            input.Close(); output.Close();
-            Console.WriteLine("Completed. Press any key");
-            Console.ReadKey();
+        //  Найти общие вершины для всех гипер-ребер, подсчитать количество автоморфизмов гипер-графа и вывести все перестановки оставшихся ребер
+        static void ExampleTheorema(HyperGraph graph, System.IO.StreamWriter output)
+        {
+            //  Получить результат вычислений
+            var result = Theorem.TheoremAutomorphism(graph);
+            //  Вывод числа автоморфизмов в консоль
+            Console.WriteLine("Count of automorphism: " + result.CountAutomorphism);
+
+            //  Вывод вершин и числа автоморфизмов в файл
+            output.Write("Automorphism with nodes: ");
+            foreach (var node in result.AutomorphismNodes)
+                output.Write(node + " ");
+            output.WriteLine("\nCount of automorphism: " + result.CountAutomorphism + "\n");
+
+            //  Вывести перестановки в файл
+            ExampleAllTranspos(result.GraphWithoutAutoEdges, output);
+            //  Уничтожить временный граф
+            result.GraphWithoutAutoEdges.Dispose();
         }
     }
 }
diff --git a/HyperGraph/Theorem.cs b/HyperGraph/Theorem.cs
new file mode 100644
index 0000000..af311a6
--- /dev/null
+++ b/HyperGraph/Theorem.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace HyperGraph
+{
+    class Theorem
+    {
+        //  Структура для результурующих данных
+        public struct TheoremAuto
+        {
+            //  Число автоморфизмов
+            public Int64 CountAutomorphism;
+            //  Список общих вершин
+            public List<string> AutomorphismNodes;
+            //  Гипер-граф, содержащий гипер-ребра без общих вершин
+            public HyperGraph GraphWithoutAutoEdges;
+        }
+
+        public static TheoremAuto TheoremAutomorphism(HyperGraph Graph)
+        {
+            //  Копирую гипер-граф, чтобы не изменять исходный
+            HyperGraph graph = new HyperGraph(Graph);
+            //  Число автоморфизмов
+            Int64 count;
+
+            //  Список вершин 0-ого гипер-ребра
+            List<string> intersect = new List<string>(graph.HyperEdge[0]);
+
+            //  Находим пересечение множеств вершин гипер-ребер каждого с каждым
+            for (int i = 1; i < graph.HyperEdge.Count; i++)
+            {
+                var res = intersect.Select(j => j.ToString()).Intersect(graph.HyperEdge[i]);
+                //  Сохраняем резудьтат пересечения для дальнейшей операции
+                intersect = new List<string>();
+                foreach (var item in res)
+                    intersect.Add(item);                
+            }
+            //  В списке intersect расположены общие для всех гипер-ребер вершины
+
+            //  Удаляем из каждого гипер-ребра все общие вершины
+            foreach (var edge in graph.HyperEdge)
+                foreach (var elem in intersect)
+                    edge.RemoveAll(s => s.Equals(elem));
+
+            //  Согласно формуле, подсчитываем количество автоморфизмов
+            count = Factorial(intersect.Count);     //  !k, где k = количество общих вершин
+            foreach (var edge in graph.HyperEdge)   
+                count *= Factorial(edge.Count);     //  *(n - k)!, где n = количество вершин в исходном гипер-ребер, 
+                                                    //  а (n-k) = количество вершин в новом гипер-графе без общих вершин
+
+            //  Вовращаемое значение в виде структуры
+            return new TheoremAuto
+            {
+                CountAutomorphism = count,
+                AutomorphismNodes = intersect,
+                GraphWithoutAutoEdges = graph
+            };
+        }
+
+
+        private static Int64 Factorial(int input)
+        {
+            //  Предрассчитанные значения
+            switch (input)
+            {
+                case 1: return 1;
+                case 2: return 2;
+                case 3: return 6;
+                case 4: return 24;
+                case 5: return 120;
+                case 6: return 720;
+                case 7: return 5040;
+                default:
+                    break;
+            }
+            int x;
+            Int64 fact = 1;
+            try
+            {
+                //  Вдруг выйдем за пределы максимального значения
+                for (x = input; x > 1; x--)
+                    fact *= x;
+            }
+            catch (Exception e)
+            {
+                Console.WriteLine("\n" + e.Message);
+                Console.ReadKey();
+                return -1;
+            }          
+            return fact;            
+        }
+    }
+}
\ No newline at end of file