Ejemplo n.º 1
0
 public new bool Contains(IEnumerable <T> collection)
 {
     if (Settings.EnableCudafy)
     {
         try
         {
             int[,] matrix;
             int first;
             lock (CudafySequencies.Semaphore)
             {
                 CudafySequencies.SetSequencies(
                     collection.Select(GetInts).Select(item => item.ToArray()).ToArray(),
                     this.Select(GetInts).Select(item => item.ToArray()).ToArray()
                     );
                 CudafySequencies.Execute("Compare");
                 matrix = CudafySequencies.GetMatrix();
             }
             lock (CudafyMatrix.Semaphore)
             {
                 CudafyMatrix.SetMatrix(matrix);
                 CudafyMatrix.ExecuteRepeatZeroIndexOfZeroFirstIndexOfNonPositive();
                 first = CudafyMatrix.GetFirst();
             }
             return(first < 0);
         }
         catch (Exception ex)
         {
             Debug.WriteLine(ex.ToString());
             return(collection.All(Contains));
         }
     }
     return(collection.All(Contains));
 }
Ejemplo n.º 2
0
        public IEnumerable <Path> SplitBy(Segment segment)
        {
            var list = new StackListQueue <Path>();
            StackListQueue <int> indexes;

            try
            {
                int[,] matrix;
                lock (CudafySequencies.Semaphore)
                {
                    CudafySequencies.SetSequencies(
                        segment.Select(GetInts).Select(item => item.ToArray()).ToArray(),
                        GetRange(1, Count - 2).Select(GetInts).Select(item => item.ToArray()).ToArray()
                        );
                    CudafySequencies.Execute("Compare");
                    matrix = CudafySequencies.GetMatrix();
                }
                lock (CudafyMatrix.Semaphore)
                {
                    CudafyMatrix.SetMatrix(matrix);
                    CudafyMatrix.ExecuteRepeatZeroIndexOfZero();
                    indexes = new StackListQueue <int>(CudafyMatrix.GetIndexes()
                                                       .Where(index => index >= 0)
                                                       .Select(index => index + 1));
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
                indexes = new StackListQueue <int>(GetRange(1, Count - 2).Intersect(segment).Select(v => IndexOf(v)));
            }

            indexes.Sort();
            indexes.Prepend(0);
            indexes.Append(Count - 1);
            for (int prev = indexes.Dequeue(); indexes.Any(); prev = indexes.Dequeue())
            {
                if (((prev + 1) == indexes[0]) &&
                    segment.Contains(this[prev]) &&
                    segment.Contains(this[indexes[0]]))
                {
                    continue;
                }
                list.Add(new Path(GetRange(prev, indexes[0] - prev + 1)));
            }
            Debug.WriteLineIf(list.Any(), this + " split by " + segment + " is " +
                              string.Join(",", list.Select(item => item.ToString())));
            return(list);
        }
Ejemplo n.º 3
0
 public IEnumerable <T> Distinct()
 {
     if (Settings.EnableCudafy)
     {
         try
         {
             if (Count == 0)
             {
                 return(new StackListQueue <T>());
             }
             IEnumerable <IEnumerable <int> > list = this.Select(GetInts);
             int[,] matrix;
             int[] indexes;
             lock (CudafySequencies.Semaphore)
             {
                 int[][] arr = this.Select(GetInts).Select(item => item.ToArray()).ToArray();
                 CudafySequencies.SetSequencies(arr, arr);
                 CudafySequencies.Execute("Compare");
                 matrix = CudafySequencies.GetMatrix();
             }
             lock (CudafyMatrix.Semaphore)
             {
                 CudafyMatrix.SetMatrix(matrix);
                 CudafyMatrix.ExecuteRepeatZeroIndexOfZero();
                 indexes = CudafyMatrix.GetIndexes();
             }
             return(indexes.Where((value, index) => value == index)
                    .Select(index => this[index]));
         }
         catch (Exception ex)
         {
             Debug.WriteLine(ex.ToString());
             return(this.ToList().Distinct());
         }
     }
     return(this.ToList().Distinct());
 }
Ejemplo n.º 4
0
        public bool IsPlanar(Graph graphArgument)
        {
            var enableCudafy = Settings.EnableCudafy;

            Settings.EnableCudafy = true;

            if (WorkerLog != null)
            {
                WorkerLog("Начало гамма-алгоритма");
            }
            var graph = new Graph(graphArgument);

            Debug.Assert(
                graph.Children.All(pair => pair.Value
                                   .All(value => graph.Children.ContainsKey(value) &&
                                        graph.Children[value].Contains(pair.Key)))
                );

            if (WorkerBegin != null)
            {
                WorkerBegin();
            }
            // Шаг первый - удаляем все листья и узлы степени 2
            if (WorkerLog != null)
            {
                WorkerLog("Удаляем все листья и узлы степени 2");
            }

            // листья представляют собой дерево и нарисовать его плоскую укладку тривиально.
            graph.RemoveAllTrees();

            // Замечание. Если на ребра планарного графа нанести произвольное число вершин степени 2,
            // то он останется планарным; равным образом, если на ребра непланарного графа
            // нанести вершины степени 2, то он планарным не станет.
            graph.RemoveIntermedians();

            // Шаг второй - граф нужно укладывать отдельно по компонентам связности.
            if (WorkerLog != null)
            {
                WorkerLog("Находим ВСЕ пути в графе длины не более размера графа + 1");
            }
            Dictionary <int, PathDictionary> cachedAllGraphPaths = graph.GetAllGraphPaths();
            var queue = new StackListQueue <Context>
            {
                graph.GetAllSubGraphs().Select(subgraph =>
                                               new Context
                {
                    SubGraphQueue =
                        new StackListQueue <Graph>
                    {
                        subgraph
                    },
                    CachedSubGraphPathsQueue =
                        new StackListQueue <Dictionary <int, PathDictionary> >
                    {
                        Graph.GetSubgraphPaths(subgraph.Vertices, cachedAllGraphPaths)
                    },
                })
            };

            Debug.WriteLine("start ");

            foreach (Context context in queue)
            {
                while (context.SubGraphQueue.Any())
                {
                    Graph subGraph = context.SubGraphQueue.Dequeue();
                    if (WorkerLog != null)
                    {
                        WorkerLog("Проверка связанной компоненты " + subGraph);
                    }
                    Dictionary <int, PathDictionary> cachedSubGraphPaths =
                        context.CachedSubGraphPathsQueue.Dequeue();

                    // На вход подаются графы, обладающие следующими свойствами:
                    // граф связный;
                    // граф имеет хотя бы один цикл;
                    // граф не имеет мостиков, т. е. ребер, после удаления которых
                    // граф распадается на две компонеты связности.

                    if (WorkerLog != null)
                    {
                        WorkerLog(
                            "Находим мосты после удаления которых граф распадается на несколько компонет связности");
                    }

                    var vertices = new StackListQueue <Vertex>(subGraph.Vertices);
                    var bridges  = new StackListQueue <Vertex>();
                    for (int i = 0; i < vertices.Count; i++)
                    {
                        Vertex dequeue = vertices.Dequeue();
                        IEnumerable <Graph> subsubgraphs = subGraph.GetSubgraph(vertices).GetAllSubGraphs();
                        if (subsubgraphs.Count() > 1)
                        {
                            bridges.Add(dequeue);
                        }
                        vertices.Enqueue(dequeue);
                    }

                    Debug.Assert(bridges.Count != vertices.Count);

                    if (bridges.Any())
                    {
                        // Если в графе есть мосты, то их нужно разрезать, провести отдельно плоскую укладку
                        // каждой компоненты связности, а затем соединить их мостами.
                        // Здесь может возникнуть трудность: в процессе укладки концевые вершины моста могут
                        // оказаться внутри плоского графа. Нарисуем одну компоненту связности,
                        // и будем присоединять к ней другие последовательно.
                        // Каждую новую компоненту связности будем рисовать в той грани, в которой лежит
                        // концевая вершина соответствующего моста. Так как граф связности мостами компонент
                        // связности является деревом, мы сумеем получить плоскую укладку.
                        if (WorkerLog != null)
                        {
                            WorkerLog(
                                "В графе есть мосты, их нужно разрезать, провести отдельно плоскую укладку, а затем соединить их мостами.");
                        }
                        if (WorkerLog != null)
                        {
                            WorkerLog("Мосты: " + string.Join(",", bridges));
                        }

                        IEnumerable <Vertex> exceptBridges = vertices.Except(bridges);
                        IEnumerable <Graph>  subsubgraphs  = subGraph.GetSubgraph(exceptBridges).GetAllSubGraphs();
                        Debug.WriteLine("subsubgraphs = " + subsubgraphs.Count());
                        context.SubGraphQueue.Enqueue(
                            subsubgraphs.Select(subgraph => subGraph.GetSubgraph(subgraph.Vertices.Union(bridges))));
                        context.CachedSubGraphPathsQueue.Enqueue(
                            subsubgraphs.Select(
                                subgraph =>
                                Graph.GetSubgraphPaths(subgraph.Vertices.Union(bridges), cachedSubGraphPaths)));

                        continue;
                    }

                    if (WorkerLog != null)
                    {
                        WorkerLog("Находим ЛЮБОЙ МАКСИМАЛЬНОЙ ДЛИНЫ простой цикл в графе");
                    }
                    Circle circle = null;
                    for (int i = cachedSubGraphPaths.Keys.Max(); i > 3; i--)
                    {
                        foreach (var pair in cachedSubGraphPaths.Where(pair => pair.Key == i))
                        {
                            foreach (
                                var key in
                                subGraph.Vertices.Select(vertex => new KeyValuePair <Vertex, Vertex>(vertex, vertex))
                                )
                            {
                                if (pair.Value.ContainsKey(key) && pair.Value[key].Any())
                                {
                                    foreach (Path path in pair.Value[key])
                                    {
                                        circle = new Circle(path.GetRange(0, path.Count - 1));
                                        if (Circle.IsSimple(circle))
                                        {
                                            break;
                                        }
                                        circle = null;
                                    }
                                    if (circle != null)
                                    {
                                        break;
                                    }
                                }
                                if (circle != null)
                                {
                                    break;
                                }
                            }
                            if (circle != null)
                            {
                                break;
                            }
                        }
                        if (circle != null)
                        {
                            break;
                        }
                    }

                    if (circle == null && !context.Edges.Any())
                    {
                        // граф — дерево и нарисовать его плоскую укладку тривиально.
                        // Поскольку мы ещё не начинали рисовать, то значит всё проверено
                        continue;
                    }

                    // Инициализация алгоритма производится так: выбираем любой простой цикл;
                    // и получаем две грани: Γ1 — внешнюю и Γ2 — внутреннюю

                    if (circle != null && !context.Edges.Any())
                    {
                        context.Edges.Add(new Edge(circle));
                    }

                    if (circle != null)
                    {
                        context.Edges.Add(new Edge(circle));
                        context.Builded.Add(context.Edges.Last());
                    }
                    // Если циклов нет, то надо проверить, что данное дерево
                    // можно вписать в уже построенный граф

                    Debug.WriteLine("SubGraph " + subGraph);
                    Debug.WriteLine("builded " + context.Builded);
                    Debug.WriteLine("edges:" +
                                    string.Join(Environment.NewLine, context.Edges.Select(e => e.ToString())));


                    //// Каждый сегмент S относительно уже построенного графа G′ представляет собой одно из двух:
                    //// ребро, оба конца которого принадлежат G′, но само оно не принадлежит G′;
                    //// связную компоненту графа G – G′, дополненную всеми ребрами графа G,
                    //// один из концов которых принадлежит связной компоненте,
                    //// а второй из графа G′.

                    VertexSortedCollection           buildedVertices = context.Builded.Vertices;
                    Dictionary <int, PathDictionary> fromTo          = Graph.GetFromToPaths(buildedVertices,
                                                                                            buildedVertices,
                                                                                            cachedSubGraphPaths);
                    var paths =
                        new PathCollection(fromTo
                                           .SelectMany(pair => pair.Value)
                                           .SelectMany(pair => pair.Value)
                                           .Where(Path.IsNoVertix)
                                           .Where(Path.IsNoCircle)
                                           );
                    Debug.WriteLine("paths " + paths);

                    //var secondGraph = new Graph(subGraph.Except(context.Builded));

                    //if (secondGraph.Any())
                    //{
                    //    IEnumerable<Graph> collection = secondGraph.GetAllSubGraphs();
                    //    context.SubGraphQueue.Enqueue(collection);
                    //    context.CachedSubGraphPathsQueue.Enqueue(
                    //        collection.Select(subgraph => Graph.GetSubgraphPaths(subgraph.Vertices, cachedSubGraphPaths)));
                    //}



                    paths.ReplaceAll(paths.Distinct());
                    Debug.WriteLine("paths " + paths);
                    paths.RemoveAll(context.Builded.Contains);

                    Debug.WriteLine("paths " + paths);
                    Debug.WriteLine("builded " + context.Builded);
                    Debug.WriteLine("edges:" +
                                    string.Join(Environment.NewLine, context.Edges.Select(e => e.ToString())));

                    while (paths.Any())
                    {
                        paths.RemoveAll(context.Builded.Contains);
                        Debug.WriteLine("paths " + paths);
                        if (!paths.Any())
                        {
                            continue;
                        }
                        if (Settings.EnableCudafy)
                        {
                            try
                            {
                                while (paths.Any(Path.IsLong))
                                {
                                    // Находим для всех путей их перечечения с уже построенным графом
                                    // Разбиваем пути в найденных точках пересечения с уже построенным графом
                                    // Если точек пересечения не найдено, то выходим из цикла

                                    int[,] matrix;
                                    int[] indexes;
                                    lock (CudafySequencies.Semaphore)
                                    {
                                        CudafySequencies.SetSequencies(
                                            paths.Select(
                                                path =>
                                                path.GetRange(1, path.Count - 2)
                                                .Select(vertex => vertex.Id)
                                                .ToArray())
                                            .ToArray(),
                                            context.Builded.Vertices.Select(
                                                vertex => new StackListQueue <int>(vertex.Id).ToArray())
                                            .ToArray()
                                            );
                                        CudafySequencies.Execute("CountIntersections");
                                        // подсчитываем число пересечений
                                        matrix = CudafySequencies.GetMatrix();
                                    }
                                    lock (CudafyMatrix.Semaphore)
                                    {
                                        CudafyMatrix.SetMatrix(matrix);
                                        CudafyMatrix.ExecuteRepeatZeroIndexOfNonZero();
                                        // находим индексы ненулевых элементов в строках
                                        indexes = CudafyMatrix.GetIndexes();
                                    }
                                    Dictionary <int, int> dictionary = indexes.Select(
                                        (value, index) => new KeyValuePair <int, int>(index, value))
                                                                       .Where(pair => pair.Value >= 0)
                                                                       .ToDictionary(pair => pair.Key, pair => pair.Value);
                                    if (!dictionary.Any())
                                    {
                                        break;
                                    }
                                    Debug.Assert(dictionary.All(pair => pair.Key >= 0));
                                    Debug.Assert(dictionary.All(pair => pair.Value >= 0));
                                    Debug.Assert(dictionary.All(pair => pair.Key < paths.Count));
                                    Debug.Assert(dictionary.All(pair => pair.Value < context.Builded.Vertices.Count));
                                    var dictionary2 = new StackListQueue <KeyValuePair <Path, Vertex> >(
                                        dictionary.Select(
                                            pair =>
                                            new KeyValuePair <Path, Vertex>(new Path(paths[pair.Key]),
                                                                            new Vertex(context.Builded.Vertices[pair.Value])))
                                        );
                                    var list = new StackListQueue <int>(dictionary.Select(pair => pair.Key).Distinct());
                                    list.Sort();
                                    Debug.Assert(dictionary2.All(pair => pair.Key.Count > 1));
                                    for (int i = list.Count; i-- > 0;)
                                    {
                                        paths.RemoveAt(list[i]);
                                    }
                                    paths.AddRangeExcept(
                                        new PathCollection(
                                            dictionary2.SelectMany(pair => pair.Key.SplitBy(pair.Value)
                                                                   .Where(Path.IsNoVertix)
                                                                   .Where(Path.IsNoCircle))
                                            .Distinct()));
                                    paths.ReplaceAll(paths.Distinct());
                                    paths.RemoveAll(context.Builded.Contains);
                                }
                            }
                            catch (Exception ex)
                            {
                                if (WorkerLog != null)
                                {
                                    WorkerLog(ex.ToString());
                                }
                                paths.ReplaceAll(
                                    paths.SelectMany(context.Builded.Split)
                                    .Where(Path.IsNoVertix)
                                    .Where(Path.IsNoCircle)
                                    );
                                paths.ReplaceAll(paths.Distinct());
                                paths.RemoveAll(context.Builded.Contains);
                            }
                        }
Ejemplo n.º 5
0
        /// <summary>
        ///     Разбиение пути в точках перечечения пути с графом на отдельные подпути
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public IEnumerable <Path> Split(Path path)
        {
            Debug.Assert(Count >= 2);
            var list = new StackListQueue <Path>();
            StackListQueue <int> indexes;

            if (Settings.EnableCudafy)
            {
                try
                {
                    int[,] matrix;
                    lock (CudafySequencies.Semaphore)
                    {
                        CudafySequencies.SetSequencies(
                            Vertices.Select(path.GetInts).Select(item => item.ToArray()).ToArray(),
                            path.GetRange(1, Count - 2).Select(path.GetInts).Select(item => item.ToArray()).ToArray()
                            );
                        CudafySequencies.Execute("Compare");
                        matrix = CudafySequencies.GetMatrix();
                    }
                    lock (CudafyMatrix.Semaphore)
                    {
                        CudafyMatrix.SetMatrix(matrix);
                        CudafyMatrix.ExecuteRepeatZeroIndexOfZero();
                        indexes = new StackListQueue <int>(CudafyMatrix.GetIndexes()
                                                           .Where(index => index >= 0)
                                                           .Select(index => index + 1));
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.ToString());
                    indexes =
                        new StackListQueue <int>(
                            path.GetRange(1, Count - 2)
                            .Intersect(Vertices)
                            .Select(v => path.IndexOf(v)));
                }
            }
            else
            {
                indexes =
                    new StackListQueue <int>(
                        path.GetRange(1, Count - 2)
                        .Intersect(Vertices)
                        .Select(v => path.IndexOf(v)));
            }
            indexes.Sort();
            indexes.Prepend(0);
            indexes.Append(Count - 1);
            Dictionary <Vertex, VertexSortedCollection> children = Children;

            for (int prev = indexes.Dequeue(); indexes.Any(); prev = indexes.Dequeue())
            {
                if (((prev + 1) == indexes[0]) &&
                    children.ContainsKey(path[prev]) &&
                    children[path[prev]].Contains(path[indexes[0]]))
                {
                    continue;
                }
                list.Add(new Path(path.GetRange(prev, indexes[0] - prev + 1)));
            }
            Debug.WriteLineIf(list.Any(), path + " split by " + this + " is " +
                              string.Join(",", list.Select(item => item.ToString())));
            return(list);
        }
Ejemplo n.º 6
0
        public BooleanVector GetVector(Circle circle)
        {
            Debug.Assert(circle.Any());
            int count      = circle.Count;
            var collection = new SegmentCollection();

            for (int i = 0; i < count; i++)
            {
                collection.Add(new Segment(circle[i], circle[(i + 1) % count]));
            }
            Debug.Assert(collection.All(Contains));
            List <int> indexes;

            if (Settings.EnableCudafy)
            {
                try
                {
                    IEnumerable <IEnumerable <int> > list1 = collection.Select(GetInts);
                    IEnumerable <IEnumerable <int> > list2 = this.Select(GetInts);
                    int[,] matrix;
                    lock (CudafySequencies.Semaphore)
                    {
                        CudafySequencies.SetSequencies(
                            list1.Select(item => item.ToArray()).ToArray(),
                            list2.Select(item => item.ToArray()).ToArray()
                            );
                        CudafySequencies.Execute("Compare");
                        matrix = CudafySequencies.GetMatrix();
                    }
                    lock (CudafyMatrix.Semaphore)
                    {
                        CudafyMatrix.SetMatrix(matrix);
                        CudafyMatrix.ExecuteRepeatZeroIndexOfZero();
                        indexes = CudafyMatrix.GetIndexes().ToList();
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.ToString());
                    indexes = collection.Select(segment => IndexOf(segment)).ToList();
                }
            }
            else
            {
                indexes = collection.Select(segment => IndexOf(segment)).ToList();
            }
            indexes.Sort();
            var booleanVector = new BooleanVector();

            if (indexes[0] > 0)
            {
                booleanVector.AddRange(Enumerable.Repeat(false, indexes[0]));
            }
            booleanVector.Add(true);
            for (int i = 1; i < indexes.Count; i++)
            {
                if (indexes[i] - indexes[i - 1] > 1)
                {
                    booleanVector.AddRange(Enumerable.Repeat(false, indexes[i] - indexes[i - 1] - 1));
                }
                booleanVector.Add(true);
            }
            return(booleanVector);
        }
Ejemplo n.º 7
0
        public void TestCudafyGaussJordan()
        {
            var random = new Random();

            for (int k = 0; k < 10; k++)
            {
                var matrix =
                    new BooleanMatrix(
                        Enumerable.Range(0, 5).Select(i1 => Enumerable.Range(0, 10).Select(i => random.Next() % 2 == 0)));

                StackListQueue <int> list2;
                int rows    = matrix.Count;
                int columns = matrix.Length;
                lock (CudafyMatrix.Semaphore)
                {
                    CudafyMatrix.SetMatrix(
                        new ArrayOfArray <int>(matrix.Select(vector => vector.Select(b => b ? 1 : 0).ToArray()).ToArray())
                        .ToTwoDimensional());

                    CudafyMatrix.ExecuteGaussJordan();

                    list2 = new StackListQueue <int>(CudafyMatrix.GetIndexes()
                                                     .Select((first, row) => new KeyValuePair <int, int>(row, first))
                                                     .Where(pair => pair.Value >= 0)
                                                     .Select(pair => pair.Value)
                                                     .ToList());

                    Console.WriteLine(matrix);
                    Console.WriteLine();
                    Console.WriteLine(string.Join(Environment.NewLine,
                                                  Enumerable.Range(0, rows)
                                                  .Select(row => string.Join("", Enumerable.Range(0, columns)
                                                                             .Select(
                                                                                 column => CudafyMatrix.GetMatrix()[row, column].ToString())
                                                                             .ToList())).ToList()));
                    Console.WriteLine();
                    Console.WriteLine(string.Join(Environment.NewLine,
                                                  CudafyMatrix.GetIndexes().Select(i => i.ToString()).ToList()));
                }

                for (int i = matrix.Count; i-- > 0;)
                {
                    BooleanVector vector = matrix.Dequeue();
                    if (BooleanVector.IsZero(vector))
                    {
                        continue;
                    }
                    matrix.Enqueue(vector);
                }
                for (int i = matrix.Count; i-- > 0;)
                {
                    BooleanVector vector = matrix.Dequeue();
                    int           index  = vector.IndexOf(true);
                    for (int j = matrix.Count; j-- > 0;)
                    {
                        BooleanVector vector1 = matrix.Dequeue();
                        if (vector1.Count > index && vector1[index])
                        {
                            vector1 = BooleanVector.Xor(vector1, vector);
                        }
                        if (BooleanVector.IsZero(vector1))
                        {
                            continue;
                        }
                        matrix.Enqueue(vector1);
                    }
                    matrix.Enqueue(vector);
                }
                Console.WriteLine("matrix:");
                Console.WriteLine(matrix);
                var list1 = new StackListQueue <int>(matrix.Select(booleanVector => booleanVector.IndexOf(true)));
                list1.Sort();
                list2.Sort();
                Console.WriteLine("list1:" + list1);
                Console.WriteLine("list2:" + list2);
                Assert.IsTrue(list1.SequenceEqual(list2));
            }
        }
Ejemplo n.º 8
0
        public void TestCudafyMacLane()
        {
            var random = new Random();

            for (int k = 0; k < 10; k++)
            {
                var matrix =
                    new BooleanMatrix(
                        Enumerable.Range(0, 5).Select(i1 => Enumerable.Range(0, 10).Select(i => random.Next() % 2 == 0)));
                int[] indexes = Enumerable.Range(1, 5).Select(i => random.Next() % 5).ToArray();
                Console.WriteLine(string.Join(",",
                                              indexes.Select(i => i.ToString()).ToList()));

                ///////////////////////////////////////////////////
                // Вычисление целевой функции обычным методом
                IEnumerable <KeyValuePair <int, int> > dictionary =
                    indexes.Select((item, value) => new KeyValuePair <int, int>(value, item));
                var matrix2 = new BooleanMatrix(
                    dictionary.Select(
                        pair1 =>
                        dictionary
                        .Where(pair2 => pair2.Value == pair1.Key && pair2.Key != pair1.Key)
                        .Select(pair => matrix[pair.Key])
                        .Aggregate(matrix[pair1.Key], BooleanVector.Xor)));

                int macLane1 = matrix2.MacLane;

                int rows    = matrix.Count;
                int columns = matrix.Length;
                lock (CudafyMatrix.Semaphore)
                {
                    CudafyMatrix.SetMatrix(
                        new ArrayOfArray <int>(matrix.Select(vector => vector.Select(b => b ? 1 : 0).ToArray()).ToArray())
                        .ToTwoDimensional());
                    CudafyMatrix.SetIndexes(indexes.ToArray());
                    CudafyMatrix.ExecuteMacLane();
                    int macLane2 = CudafyMatrix.GetMacLane();

                    CudafyMatrix.ExecuteUpdate();
                    Console.WriteLine(string.Join(",",
                                                  CudafyMatrix.GetIndexes().Select(i => i.ToString()).ToList()));

                    Console.WriteLine();
                    Console.WriteLine(matrix);
                    Console.WriteLine();
                    Console.WriteLine(matrix2);
                    Console.WriteLine();
                    Console.WriteLine(string.Join(Environment.NewLine,
                                                  Enumerable.Range(0, rows)
                                                  .Select(row => string.Join("", Enumerable.Range(0, columns)
                                                                             .Select(
                                                                                 column => CudafyMatrix.GetMatrix()[row, column].ToString())
                                                                             .ToList())).ToList()));
                    Console.WriteLine();

                    //Console.WriteLine(string.Join(Environment.NewLine,
                    //    Enumerable.Range(0, rows)
                    //    .Select(row => string.Join("", Enumerable.Range(0, columns)
                    //        .Select(column => CudafyMatrix.GetMatrix()[row * columns + column].ToString()).ToList())).ToList()));

                    Console.WriteLine(macLane1);
                    Console.WriteLine(macLane2);
                    Assert.AreEqual(macLane1, macLane2);
                }
            }
        }
Ejemplo n.º 9
0
        public int Compare(StackListQueue <T> x, StackListQueue <T> y)
        {
            int[][] list1 = x.Select(x.GetInts).Select(i => i.ToArray()).ToArray();
            int[][] list2 = y.Select(x.GetInts).Select(i => i.ToArray()).ToArray();
            int     value = list1.Length - list2.Length;

            if (value != 0)
            {
                return(value);
            }
            var list11 = new StackListQueue <StackListQueue <int> >(list1.Select(i => new StackListQueue <int>(i.Length)));
            var list22 = new StackListQueue <StackListQueue <int> >(list2.Select(i => new StackListQueue <int>(i.Length)));

            try
            {
                int[,] matrix;
                int first;
                lock (CudafySequencies.Semaphore)
                {
                    CudafySequencies.SetSequencies(list11.Select(i => i.ToArray()).ToArray(),
                                                   list22.Select(i => i.ToArray()).ToArray());
                    CudafySequencies.Execute("Compare");
                    matrix = CudafySequencies.GetMatrix();
                }
                lock (CudafyMatrix.Semaphore)
                {
                    CudafyMatrix.SetMatrix(matrix);
                    CudafyMatrix.ExecuteRangeSelectFirstIndexOfNonNegative();
                    first = CudafyMatrix.GetFirst();
                }
                if (first >= 0)
                {
                    return(matrix[first, first]);
                }
            }
            catch (Exception exception)
            {
                value = list11.Select((c, i) => c[0] - list22[i][0]).FirstOrDefault(compare => compare != 0);
                if (value != 0)
                {
                    return(value);
                }
            }
            try
            {
                int[,] matrix;
                int first;
                lock (CudafySequencies.Semaphore)
                {
                    CudafySequencies.SetSequencies(list1, list2);
                    CudafySequencies.Execute("Compare");
                    matrix = CudafySequencies.GetMatrix();
                }
                lock (CudafyMatrix.Semaphore)
                {
                    CudafyMatrix.SetMatrix(matrix);
                    CudafyMatrix.ExecuteRangeSelectFirstIndexOfNonNegative();
                    first = CudafyMatrix.GetFirst();
                }
                return((first < 0) ? 0 : matrix[first, first]);
            }
            catch (Exception exception)
            {
                return
                    (list1.Select((t, i) => t.Select((item, j) => item - list2[i][j])
                                  .FirstOrDefault(compare => compare != 0))
                     .FirstOrDefault(compare => compare != 0));
            }
        }
Ejemplo n.º 10
0
 public new IEnumerable <Path> Distinct()
 {
     if (Count == 0)
     {
         return(new MyLibrary.Collections.StackListQueue <Path>());
     }
     if (Settings.EnableCudafy)
     {
         try
         {
             var list =
                 new StackListQueue <StackListQueue <int> >(
                     this.Select(path => new StackListQueue <int>(path.Select(vertex => vertex.Id))));
             int[][] arr = list.Select(item => item.ToArray()).ToArray();
             Debug.Assert(Count == arr.Length);
             int[,] matrix;
             int[] indexes;
             lock (CudafySequencies.Semaphore)
             {
                 CudafySequencies.SetSequencies(arr, arr);
                 CudafySequencies.Execute("Compare");
                 matrix = CudafySequencies.GetMatrix();
             }
             Debug.Assert(matrix.GetLength(0) == arr.Length);
             Debug.Assert(matrix.GetLength(1) == arr.Length);
             lock (CudafyMatrix.Semaphore)
             {
                 CudafyMatrix.SetMatrix(matrix);
                 CudafyMatrix.ExecuteRepeatZeroIndexOfZero();
                 indexes = CudafyMatrix.GetIndexes();
             }
             Debug.Assert(indexes.GetLength(0) == arr.Length);
             IEnumerable <Path> paths1 = indexes.Where((value, index) => value == index)
                                         .Select(this.ElementAt);
             var list1 =
                 new StackListQueue <StackListQueue <int> >(
                     paths1.Select(path => new StackListQueue <int>(path.Select(vertex => vertex.Id))));
             var list2 =
                 new StackListQueue <StackListQueue <int> >(
                     paths1.Select(path => new StackListQueue <int>(path.GetReverse().Select(vertex => vertex.Id))));
             lock (CudafySequencies.Semaphore)
             {
                 CudafySequencies.SetSequencies(
                     list1.Select(item => item.ToArray()).ToArray(),
                     list2.Select(item => item.ToArray()).ToArray()
                     );
                 CudafySequencies.Execute("Compare");
                 matrix = CudafySequencies.GetMatrix();
             }
             Debug.Assert(matrix.GetLength(0) == paths1.Count());
             Debug.Assert(matrix.GetLength(1) == paths1.Count());
             lock (CudafyMatrix.Semaphore)
             {
                 CudafyMatrix.SetMatrix(matrix);
                 CudafyMatrix.ExecuteRepeatZeroIndexOfZero();
                 indexes = CudafyMatrix.GetIndexes();
             }
             Debug.Assert(indexes.GetLength(0) == paths1.Count());
             return
                 (new PathCollection(
                      paths1.Where((value, index) => indexes[index] == -1 || indexes[index] >= index)));
         }
         catch (Exception ex)
         {
             return(new PathCollection(base.Distinct()));
         }
     }
     {
         return(new PathCollection(base.Distinct()));
     }
 }
Ejemplo n.º 11
0
        public bool IsPlanar(Graph graphArgument)
        {
            if (WorkerLog != null)
            {
                WorkerLog("Начало алгоритма Мак-Лейна");
            }
            var graph = new Graph(graphArgument);

            Debug.Assert(
                graph.Children.All(pair => pair.Value
                                   .All(value => graph.Children.ContainsKey(value) &&
                                        graph.Children[value].Contains(pair.Key))));

            if (WorkerBegin != null)
            {
                WorkerBegin();
            }
            // Шаг первый - удаляем все листья и узлы степени 2
            if (WorkerLog != null)
            {
                WorkerLog("Удаляем все листья и узлы степени 2");
            }

            // листья представляют собой дерево и нарисовать его плоскую укладку тривиально.
            graph.RemoveAllTrees();

            // Замечание. Если на ребра планарного графа нанести произвольное число вершин степени 2,
            // то он останется планарным; равным образом, если на ребра непланарного графа
            // нанести вершины степени 2, то он планарным не станет.
            graph.RemoveIntermedians();

            // Шаг второй - граф нужно укладывать отдельно по компонентам связности.
            var stackListQueue = new StackListQueue <Graph> {
                graph.GetAllSubGraphs()
            };

            if (WorkerLog != null)
            {
                WorkerLog("Находим ВСЕ пути в графе длины не более размера графа + 1");
            }
            // Глобальные кэшированные данные
            Dictionary <int, PathDictionary> cachedAllGraphPaths =
                graph.GetAllGraphPaths();

            foreach (Graph subGraph in stackListQueue)
            {
                if (WorkerLog != null)
                {
                    WorkerLog("Проверка связанной компоненты " + subGraph);
                }
                // листья представляют собой дерево и нарисовать его плоскую укладку тривиально.
                subGraph.RemoveAllTrees();
                if (subGraph.Vertices.Count() < 2)
                {
                    continue;
                }

                Dictionary <int, PathDictionary> cachedSubGraphPaths =
                    Graph.GetSubgraphPaths(subGraph.Vertices, cachedAllGraphPaths);

                if (WorkerLog != null)
                {
                    WorkerLog("Находим ВСЕ циклы в графе длины не менее 2 и не более размера графа");
                }
                var circles = new StackListQueue <Circle>(cachedSubGraphPaths.Where(pair => pair.Key > 2)
                                                          .SelectMany(pair => subGraph.Vertices
                                                                      .SelectMany(vertex => pair.Value.Where(pair2 => pair2.Key.Key.Equals(pair2.Key.Value))
                                                                                  .SelectMany(
                                                                                      pair2 => pair2.Value.Select(path => new Circle(path.GetRange(0, path.Count - 1)))))));
                if (WorkerLog != null)
                {
                    WorkerLog(string.Format("Количество циклов {0}", circles.Count()));
                }

                //if (WorkerLog != null) WorkerLog("Находим все циклы в графе");
                //IEnumerable<Circle> circles = subGraph.GetAllGraphCircles(cachedSubGraphPaths);

                if (!circles.Any())
                {
                    continue;                 // граф — дерево и нарисовать его плоскую укладку тривиально.
                }
                if (WorkerLog != null)
                {
                    WorkerLog("Удаляем дубликаты");
                }
                circles = new StackListQueue <Circle>(circles.Distinct(CircleComparer));
                if (WorkerLog != null)
                {
                    WorkerLog(string.Format("Количество циклов {0}", circles.Count()));
                }

                //Debug.Assert(subGraph.Vertices.Count() ==
                //             circles.SelectMany(circle => circle.ToList()).Distinct().Count());

                //     С технической точки зрения проверять, что цикл является простым и тау-циклом нет необходимости, поскольку не
                //     приведён алгорим позволяющий проверить , что цикл является тау-циклом за количество операций меньшее чем приведение
                //     матрицы к каноническому виду. Поэтому если действительно надо сделать хорошую реализацию, то либо надо закоментировать
                //     проверки циклов на простоту и что они являются тау-циклами с помощью приведения к каноническому виду , либо
                //     предложить алгоритм быстрой проверки, что цикл является тау-циклом

                if (WorkerLog != null)
                {
                    WorkerLog("Ограничиваем простыми циклами");
                }
                circles.RemoveAll(Circle.IsNotSimple);
                if (WorkerLog != null)
                {
                    WorkerLog(string.Format("Количество циклов {0}", circles.Count()));
                }

                if (WorkerLog != null)
                {
                    WorkerLog("Удаляем элементарные циклы и петли");
                }
                circles.RemoveAll(circle => circle.Count < 3);
                if (WorkerLog != null)
                {
                    WorkerLog(string.Format("Количество циклов {0}", circles.Count()));
                }

                //if (WorkerLog != null) WorkerLog("Ограничиваем тау-циклами");
                //circles.RemoveAll(circle => !circle.IsTau());
                //if (WorkerLog != null) WorkerLog(string.Format("Количество циклов {0}", circles.Count()));

                Debug.WriteLine(string.Join(Environment.NewLine, circles.Select(circle => circle.ToString())));

                if (WorkerLog != null)
                {
                    WorkerLog("Строим матрицу над GF2 из найденных циклов");
                }
                var booleanMatrix = new BooleanMatrix(circles.Select(subGraph.GetVector));
                if (WorkerLog != null)
                {
                    WorkerLog(string.Format("Размер матрицы {0}х{1}", booleanMatrix.Count(), booleanMatrix.Length));
                }

                foreach (var r in booleanMatrix)
                {
                    if (r.Count() < booleanMatrix.Length)
                    {
                        r.Add(Enumerable.Repeat(false, booleanMatrix.Length - r.Count()));
                    }
                }

                Debug.WriteLine("matrix:");
                Debug.WriteLine(booleanMatrix);

                // отыскание минимума некоторого функционала на множестве базисов подпространства квазициклов
                // Шаг 1. Приведение матрицы к каноническому виду
                if (WorkerLog != null)
                {
                    WorkerLog("Приводим матрицу к каноническому виду");
                }
                if (Settings.EnableCudafy)
                {
                    lock (CudafyMatrix.Semaphore)
                    {
                        try
                        {
                            /////////////////////////////////////////////////////
                            // Использование параллельных вычислений CUDA
                            // для приведения матрицы к каноническому виду
                            CudafyMatrix.SetMatrix(
                                new ArrayOfArray <int>(
                                    booleanMatrix.Select(vector => vector.Select(b => b ? 1 : 0).ToArray()).ToArray())
                                .ToTwoDimensional());

                            // Использование алгоритма Гаусса-Жордана
                            // Для приведения матрицы к каноническому виду
                            CudafyMatrix.ExecuteGaussJordan();

                            // Удаляем нулевые строки
                            int[][] arrayOfArray =
                                new TwoDimensionalArray <int>(CudafyMatrix.GetMatrix()).ToArrayOfArray();
                            booleanMatrix = new BooleanMatrix(CudafyMatrix.GetIndexes()
                                                              .Select((first, row) => new KeyValuePair <int, int>(row, first))
                                                              .Where(pair => pair.Value >= 0)
                                                              .Select(pair => arrayOfArray[pair.Key].Select(value => value != 0)));

                            CudafyMatrix.SetMatrix(
                                new ArrayOfArray <int>(
                                    booleanMatrix.Select(vector => vector.Select(b => b ? 1 : 0).ToArray()).ToArray())
                                .ToTwoDimensional());
                        }
                        catch (Exception ex)
                        {
                            if (WorkerLog != null)
                            {
                                WorkerLog(ex.ToString());
                            }
                            /////////////////////////////////////////////////////
                            // Приведение матрицы к каноническому виду обычным способом
                            booleanMatrix.GaussJordan();
                            booleanMatrix.RemoveAll(BooleanVector.IsZero);
                        }
                        if (WorkerLog != null)
                        {
                            WorkerLog(string.Format("Размер матрицы {0}х{1}", booleanMatrix.Count(),
                                                    booleanMatrix.Length));
                        }

                        // Матрица имеет канонический вид
                        Debug.WriteLine("matrix:");
                        Debug.WriteLine(booleanMatrix);
                        Debug.Assert(booleanMatrix.Select(vector => vector.IndexOf(true)).Distinct().Count() ==
                                     booleanMatrix.Count);
                        Debug.Assert(booleanMatrix.Select(vector => vector.IndexOf(true))
                                     .SelectMany(
                                         index => booleanMatrix.Where(vector => vector.Count > index && vector[index]))
                                     .Count() == booleanMatrix.Count);
                        // Поскольку в колонках содержится по одной единице, то к строке можно прибавить только одну другую строку
                        int n = booleanMatrix.Count;
                        int macLane;
                        try
                        {
                            /////////////////////////////////////////////////////
                            // Использование параллельных вычислений CUDA
                            // для расчёта целевой функции симплекс-метода
                            Debug.Assert(CudafyMatrix.GetMatrix() != null);
                            CudafyMatrix.SetIndexes(Enumerable.Range(0, n).ToArray());
                            CudafyMatrix.ExecuteMacLane();
                            macLane = CudafyMatrix.GetMacLane();
#if DEBUG
                            int[][] arrayOfArray = new TwoDimensionalArray <int>(CudafyMatrix.GetMatrix()).ToArrayOfArray();
                            Debug.WriteLine(string.Join(Environment.NewLine,
                                                        arrayOfArray.Select(v => string.Join(",", v.Select(i => i.ToString())))));
#endif
                        }
                        catch (Exception ex)
                        {
                            if (WorkerLog != null)
                            {
                                WorkerLog(ex.ToString());
                            }
                            ///////////////////////////////////////////////////
                            // Вычисление целевой функции обычным методом
                            macLane = booleanMatrix.MacLane;
                        }
                        Debug.WriteLine("macLane = " + macLane);
                        Debug.WriteLine("matrix:");
                        Debug.WriteLine(booleanMatrix);
                        int k = Math.Min(2, Math.Max(1, n));
                        k = Math.Min(n, k);
                        if (WorkerLog != null)
                        {
                            WorkerLog("Начало симплекс-метода");
                        }
                        if (WorkerLog != null)
                        {
                            WorkerLog("Текущий macLane = " + macLane);
                        }
                        for (bool updated = true; k <= n && updated && macLane > 0;)
                        {
                            Debug.Assert(booleanMatrix.Length == subGraph.Count());
                            List <int> values = Enumerable.Range(0, n).ToList();

                            updated = false;
                            List <int> indexOfIndex = Enumerable.Range(n - k, k).ToList();
                            while (macLane > 0)
                            {
                                if (WorkerLog != null)
                                {
                                    WorkerLog(string.Format("Перебираем индексы в позициях {0}",
                                                            string.Join(",",
                                                                        indexOfIndex.Select(index => index.ToString(CultureInfo.InvariantCulture)))));
                                }
                                CudafyMatrix.SetMatrix(
                                    new ArrayOfArray <int>(
                                        booleanMatrix.Select(vector => vector.Select(b => b ? 1 : 0).ToArray())
                                        .ToArray())
                                    .ToTwoDimensional());
                                List <int> indexes = values.ToList();
                                foreach (int index in indexOfIndex)
                                {
                                    indexes[index] = n - 1;
                                }
                                while (macLane > 0)
                                {
                                    Debug.Write(string.Format("Проверяем индексы {0} ... ",
                                                              string.Join(",",
                                                                          indexes.Select(index => index.ToString(CultureInfo.InvariantCulture)))));
                                    // Проверяем, что матрица образованная indexes является обратимой
                                    var detMatrix = new BooleanMatrix(indexes);
                                    if (detMatrix.Det())
                                    {
                                        BooleanMatrix matrix2;
                                        int           macLane2 = 0;
                                        try
                                        {
                                            /////////////////////////////////////////////////////
                                            // Использование параллельных вычислений CUDA
                                            // для расчёта целевой функции симплекс-метода
                                            Debug.Assert(CudafyMatrix.GetMatrix() != null);
                                            CudafyMatrix.SetIndexes(indexes.ToArray());
                                            CudafyMatrix.ExecuteMacLane();
                                            macLane2 = CudafyMatrix.GetMacLane();
#if DEBUG
                                            CudafyMatrix.ExecuteUpdate();
                                            int[][] arrayOfArray =
                                                new TwoDimensionalArray <int>(CudafyMatrix.GetMatrix()).ToArrayOfArray();
                                            matrix2 =
                                                new BooleanMatrix(
                                                    arrayOfArray.Select(r => new BooleanVector(r.Select(c => c != 0))));

                                            CudafyMatrix.SetMatrix(
                                                new ArrayOfArray <int>(
                                                    booleanMatrix.Select(v => v.Select(b => b ? 1 : 0).ToArray())
                                                    .ToArray())
                                                .ToTwoDimensional());
#endif
                                        }
                                        catch (Exception ex)
                                        {
                                            if (WorkerLog != null)
                                            {
                                                WorkerLog(ex.ToString());
                                            }
                                            ///////////////////////////////////////////////////
                                            // Вычисление целевой функции обычным методом
                                            Dictionary <int, int> dictionary =
                                                indexes.Select((item, value) => new KeyValuePair <int, int>(value, item))
                                                .ToDictionary(pair => pair.Key, pair => pair.Value);
                                            matrix2 = new BooleanMatrix(
                                                dictionary.Select(
                                                    pair1 =>
                                                    dictionary
                                                    .Where(
                                                        pair2 =>
                                                        pair2.Value == pair1.Key && pair2.Key != pair1.Key)
                                                    .Select(pair => booleanMatrix[pair.Key])
                                                    .Aggregate(booleanMatrix[pair1.Key], BooleanVector.Xor)));
                                            macLane2 = matrix2.MacLane;
                                        }
                                        finally
                                        {
                                            Debug.WriteLine("macLane = " + macLane2);
                                        }
                                        if (macLane > macLane2)
                                        {
                                            if (WorkerLog != null)
                                            {
                                                WorkerLog("Найденое решение улучшилось ( " + macLane + " -> " + macLane2 +
                                                          " )");
                                            }
                                            Debug.WriteLine("macLane: " + macLane + "->" + macLane2);
                                            values  = indexes.ToList();
                                            macLane = macLane2;
                                            updated = true;
                                            Debug.WriteLine(string.Join(",", values.Select(item => item.ToString())));
                                            Debug.WriteLine("matrix2:");
                                            Debug.WriteLine(matrix2);
                                        }
                                        if (macLane == 0)
                                        {
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        Debug.WriteLine("Матрица не обратима");
                                    }
                                    int i = k;
                                    while (i-- > 0)
                                    {
                                        if (indexes[indexOfIndex[i]]-- > 0)
                                        {
                                            break;
                                        }
                                        else
                                        {
                                            indexes[indexOfIndex[i]] = n - 1;
                                        }
                                    }
                                    if (i < 0)
                                    {
                                        break;
                                    }
                                }
                                int count = k;
                                while (count-- > 0)
                                {
                                    if (indexOfIndex[count]-- > (count == 0 ? 0 : (indexOfIndex[count - 1] + 1)))
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        indexOfIndex[count] = (count == (k - 1)
                                            ? n - 1
                                            : (indexOfIndex[count + 1] - 1));
                                    }
                                }
                                if (count < 0)
                                {
                                    break;
                                }
                            }
                            if (WorkerLog != null)
                            {
                                WorkerLog("Смена начальной точки симплекс-метода");
                            }
                            try
                            {
                                /////////////////////////////////////////////////////
                                // Использование параллельных вычислений CUDA
                                // для смены базиса симплекс-метода
                                Debug.Assert(CudafyMatrix.GetMatrix() != null);
                                CudafyMatrix.SetIndexes(values.ToArray());
                                CudafyMatrix.ExecuteUpdate();
#if DEBUG
                                int[][] arrayOfArray =
                                    new TwoDimensionalArray <int>(CudafyMatrix.GetMatrix()).ToArrayOfArray();
                                booleanMatrix =
                                    new BooleanMatrix(arrayOfArray.Select(r => new BooleanVector(r.Select(c => c != 0))));
#endif
                            }
                            catch (Exception ex)
                            {
                                if (WorkerLog != null)
                                {
                                    WorkerLog(ex.ToString());
                                }
                                ///////////////////////////////////////////////////
                                // Cмена базиса симплекс-метода обычным методом
                                Dictionary <int, int> dictionary =
                                    values.Select((item, value) => new KeyValuePair <int, int>(value, item))
                                    .ToDictionary(pair => pair.Key, pair => pair.Value);
                                booleanMatrix = new BooleanMatrix(
                                    dictionary.Select(
                                        pair1 =>
                                        dictionary
                                        .Where(pair2 => pair2.Value == pair1.Key && pair2.Key != pair1.Key)
                                        .Select(pair => booleanMatrix[pair.Key])
                                        .Aggregate(booleanMatrix[pair1.Key], BooleanVector.Xor)));
                            }
                            Debug.WriteLine(string.Join(",", values.Select(item => item.ToString())));
                            Debug.WriteLine("matrix:");
                            Debug.WriteLine(booleanMatrix);
                        }
                        if (macLane > 0)
                        {
                            if (WorkerLog != null)
                            {
                                WorkerLog("Не найдено нулевое значение фунции Мак-Лейна");
                            }
                            if (WorkerLog != null)
                            {
                                WorkerLog("Граф не планарен");
                            }
                            bool result = false;
                            if (WorkerComplite != null)
                            {
                                WorkerComplite(result);
                            }
                            return(result);
                        }
                    }
                }
                else
                {
                    // Приведение матрицы к каноническому виду обычным способом
                    booleanMatrix.GaussJordan();
                    booleanMatrix.RemoveAll(BooleanVector.IsZero);
                    if (WorkerLog != null)
                    {
                        WorkerLog(string.Format("Размер матрицы {0}х{1}", booleanMatrix.Count(),
                                                booleanMatrix.Length));
                    }
                    int macLane = booleanMatrix.MacLane;
                    Debug.WriteLine("macLane = " + macLane);
                    Debug.WriteLine("matrix:");
                    Debug.WriteLine(booleanMatrix);
                    int n = booleanMatrix.Count;
                    int k = Math.Min(2, Math.Max(1, n));
                    k = Math.Min(n, k);
                    if (WorkerLog != null)
                    {
                        WorkerLog("Начало симплекс-метода");
                    }
                    if (WorkerLog != null)
                    {
                        WorkerLog("Текущий macLane = " + macLane);
                    }
                    for (bool updated = true; k <= n && updated && macLane > 0;)
                    {
                        Debug.Assert(booleanMatrix.Length == subGraph.Count());
                        List <int> values = Enumerable.Range(0, n).ToList();

                        updated = false;
                        List <int> indexOfIndex = Enumerable.Range(n - k, k).ToList();
                        while (macLane > 0)
                        {
                            if (WorkerLog != null)
                            {
                                WorkerLog(string.Format("Перебираем индексы в позициях {0}",
                                                        string.Join(",",
                                                                    indexOfIndex.Select(index => index.ToString(CultureInfo.InvariantCulture)))));
                            }
                            CudafyMatrix.SetMatrix(
                                new ArrayOfArray <int>(
                                    booleanMatrix.Select(vector => vector.Select(b => b ? 1 : 0).ToArray())
                                    .ToArray())
                                .ToTwoDimensional());
                            List <int> indexes = values.ToList();
                            foreach (int index in indexOfIndex)
                            {
                                indexes[index] = n - 1;
                            }
                            while (macLane > 0)
                            {
                                Debug.Write(string.Format("Проверяем индексы {0} ... ",
                                                          string.Join(",",
                                                                      indexes.Select(index => index.ToString(CultureInfo.InvariantCulture)))));
                                // Проверяем, что матрица образованная indexes является обратимой
                                var detMatrix = new BooleanMatrix(indexes);
                                if (detMatrix.Det())
                                {
                                    int macLane2 = 0;
                                    ///////////////////////////////////////////////////
                                    // Вычисление целевой функции обычным методом
                                    Dictionary <int, int> dictionary =
                                        indexes.Select((item, value) => new KeyValuePair <int, int>(value, item))
                                        .ToDictionary(pair => pair.Key, pair => pair.Value);
                                    var matrix2 = new BooleanMatrix(
                                        dictionary.Select(
                                            pair1 =>
                                            dictionary
                                            .Where(
                                                pair2 =>
                                                pair2.Value == pair1.Key && pair2.Key != pair1.Key)
                                            .Select(pair => booleanMatrix[pair.Key])
                                            .Aggregate(booleanMatrix[pair1.Key], BooleanVector.Xor)));
                                    macLane2 = matrix2.MacLane;
                                    Debug.WriteLine("macLane = " + macLane2);
                                    if (macLane > macLane2)
                                    {
                                        if (WorkerLog != null)
                                        {
                                            WorkerLog("Найденое решение улучшилось ( " + macLane + " -> " + macLane2 +
                                                      " )");
                                        }
                                        Debug.WriteLine("macLane: " + macLane + "->" + macLane2);
                                        values  = indexes.ToList();
                                        macLane = macLane2;
                                        updated = true;
                                        Debug.WriteLine(string.Join(",", values.Select(item => item.ToString())));
                                        Debug.WriteLine("matrix2:");
                                        Debug.WriteLine(matrix2);
                                    }
                                    if (macLane == 0)
                                    {
                                        break;
                                    }
                                }
                                else
                                {
                                    Debug.WriteLine("Матрица не обратима");
                                }
                                int i = k;
                                while (i-- > 0)
                                {
                                    if (indexes[indexOfIndex[i]]-- > 0)
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        indexes[indexOfIndex[i]] = n - 1;
                                    }
                                }
                                if (i < 0)
                                {
                                    break;
                                }
                            }
                            int count = k;
                            while (count-- > 0)
                            {
                                if (indexOfIndex[count]-- > (count == 0 ? 0 : (indexOfIndex[count - 1] + 1)))
                                {
                                    break;
                                }
                                else
                                {
                                    indexOfIndex[count] = (count == (k - 1)
                                        ? n - 1
                                        : (indexOfIndex[count + 1] - 1));
                                }
                            }
                            if (count < 0)
                            {
                                break;
                            }
                        }
                        if (WorkerLog != null)
                        {
                            WorkerLog("Смена начальной точки симплекс-метода");
                        }
                        ///////////////////////////////////////////////////
                        // Cмена базиса симплекс-метода обычным методом
                        Dictionary <int, int> dictionary2 =
                            values.Select((item, value) => new KeyValuePair <int, int>(value, item))
                            .ToDictionary(pair => pair.Key, pair => pair.Value);
                        booleanMatrix = new BooleanMatrix(
                            dictionary2.Select(
                                pair1 =>
                                dictionary2
                                .Where(pair2 => pair2.Value == pair1.Key && pair2.Key != pair1.Key)
                                .Select(pair => booleanMatrix[pair.Key])
                                .Aggregate(booleanMatrix[pair1.Key], BooleanVector.Xor)));
                        Debug.WriteLine(string.Join(",", values.Select(item => item.ToString())));
                        Debug.WriteLine("matrix:");
                        Debug.WriteLine(booleanMatrix);
                    }
                    if (macLane > 0)
                    {
                        if (WorkerLog != null)
                        {
                            WorkerLog("Не найдено нулевое значение фунции Мак-Лейна");
                        }
                        if (WorkerLog != null)
                        {
                            WorkerLog("Граф не планарен");
                        }
                        bool result = false;
                        if (WorkerComplite != null)
                        {
                            WorkerComplite(result);
                        }
                        return(result);
                    }
                }
                if (WorkerLog != null)
                {
                    WorkerLog("Конец проверки связанной компоненты");
                }
            }
            {
                if (WorkerLog != null)
                {
                    WorkerLog("Конец алгоритма Мак-Лейна");
                }
                if (WorkerLog != null)
                {
                    WorkerLog("Граф планарен");
                }
                bool result = true;
                if (WorkerComplite != null)
                {
                    WorkerComplite(result);
                }
                return(result);
            }
        }