Theorem.cs

96 lines | 3.918 kB Blame History Raw Download
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;            
        }
    }
}