private List <int[]> CalcVertexIndex(int vertex, List <int> vertices, int[][] graphNumeration)
        {
            List <int[]> alts           = new List <int[]>();
            var          localDirection = new T();
            int          v_0            = vertices[0];

            while (localDirection.Valid())
            {
                var offset      = localDirection.GetNextOffset();
                var alternative = new int[offset.Count()];
                for (int i = 0; i < alternative.Count(); ++i)
                {
                    alternative[i] = graphNumeration[v_0][i] + offset[i];
                }
                int altCount = 0;
                if (!NumerationHelper.IndexExists(alternative, graphNumeration))
                {
                    foreach (var v in vertices)
                    {
                        if (NumerationHelper.CompareVertex(graphNumeration[v], alternative, alternative.Count()) >= 0)
                        {
                            ++altCount;
                        }
                    }
                    if (altCount == vertices.Count())
                    {
                        alts.Add(alternative);
                    }
                }
            }
            return(alts.Count() == 0 ? null : alts);
        }
        public virtual Error TryToNumerate(int[][] graphNumeration)
        {
            if (!direction.Valid())
            {
                return(Error.IMPOSSIBLE_NUM);
            }

            var vertices = GetNumeratedAdjVertices(graphNumeration);

            if (vertices.Count == 0)
            {
                return(Error.NEED_MORE_DATA);
            }
            if (vertices.Count() > 1)
            {
                var alts = CalcVertexIndex(vertex, vertices, graphNumeration);
                if (alts != null)
                {
                    foreach (var alternative in alts)
                    {
                        if (!ContainsAlternative(alternative))
                        {
                            graphNumeration[vertex] = alternative;
                            alternatives.Add(alternative);
                            return(Error.OK);
                        }
                    }
                }
                return(Error.IMPOSSIBLE_NUM);
            }
            int[] index         = null;
            bool  newIndexFound = false;

            if (graphNumeration[vertices[0]] != null)
            {
                while (!newIndexFound && direction.Valid())
                {
                    var offset = direction.GetNextOffset();
                    index = new int[offset.Count()];
                    for (int i = 0; i < offset.Count(); ++i)
                    {
                        index[i] = graphNumeration[vertices[0]][i] + offset[i];
                    }
                    newIndexFound = !NumerationHelper.IndexExists(index, graphNumeration);
                    if (newIndexFound)
                    {
                        graphNumeration[vertex] = index;
                        if (!ContainsAlternative(index))
                        {
                            alternatives.Add(index);
                        }
                    }
                }
            }
            return(newIndexFound ? Error.OK : Error.IMPOSSIBLE_NUM);
        }
        /// <summary>
        /// Method restores geometry information for each graph node
        /// </summary>
        /// <param name="xadj">Index array for graph</param>
        /// <param name="size">Size of index array</param>
        /// <param name="adjncy">Adjacency list</param>
        /// <param name="graphNumeration">Restored numeration for the input graph</param>
        /// <returns>
        /// Return code:
        /// 0 - success
        /// -1 - error
        /// </returns>
        public static int Numerate(long[] xadj, int size, int[] adjncy, out int[][] graphNumeration)
        {
            Graph graph = new Graph(xadj, adjncy);

            graphNumeration = null;
            int V     = graph.GetVerticesCount();
            int error = 0;

            switch (GetDimension(graph))
            {
            case 1:
                error = new Numerator1D().Run(graph, out graphNumeration);
                if (error != 0)
                {
                    NumerationHelper.Clear(graphNumeration);
                    error = new Numerator2D().Run(graph, out graphNumeration);
                }
                if (error != 0)
                {
                    NumerationHelper.Clear(graphNumeration);
                    error = new Numerator3D().Run(graph, out graphNumeration);
                }
                break;

            case 2:
                error = new Numerator2D().Run(graph, out graphNumeration);
                if (error != 0)
                {
                    NumerationHelper.Clear(graphNumeration);
                    error = new Numerator3D().Run(graph, out graphNumeration);
                }
                break;

            case 3:
                error = new Numerator3D().Run(graph, out graphNumeration);
                break;

            default: return(-1);
            }
            return(error);
        }
示例#4
0
        public int Run(Graph graph, out int[][] graphNumeration)
        {
            InitMembers(graph, out graphNumeration);

            int  vertexWithMaxDegree = INVALID_INDEX;
            long maxDegree           = 0;

            var traversal = new Traversal <BFS>(graph);

            //Step 1. Find start vertex with max degree
            traversal.NewVertex = (sender, e) =>
            {
                long currDegree = graph.GetAdjVerticesCount(e);
                if (currDegree > maxDegree)
                {
                    vertexWithMaxDegree = e;
                    maxDegree           = currDegree;
                }
            };
            traversal.Run();

            Error error = Error.OK;

            if (vertexWithMaxDegree != INVALID_INDEX)
            {
                int[] vertices;
                graph.GetAdjVertices(vertexWithMaxDegree, out vertices);
                Array.Sort(vertices);

                bool permutationExists = true;
                while (permutationExists)
                {
                    NumerationHelper.Clear(graphNumeration);
                    foreach (var numerator in numerators)
                    {
                        numerator.Clear();
                    }
                    foreach (var data in verticesData)
                    {
                        data.Clear();
                    }

                    // Step 2. Numerate first vertices
                    NumerateFirstVertices(vertexWithMaxDegree, vertices);

                    // Step 3. Try to numerate adj vertices of the each vertex in the first vertices
                    foreach (var v in vertices)
                    {
                        error = NumerateAdjVertices(v);
                        if (error != Error.OK)
                        {
                            break;
                        }
                    }

                    // Step 4. Try to numerate other ambiguous vertices
                    if (error == Error.OK)
                    {
                        error = TryToNumerateVertices(GetEnumeratedVertices());
                    }
                    permutationExists = error != Error.OK && Helpers.GetNextPermutation(vertices);
                }
                return((int)error);
            }
            return((int)Error.INVALID_DIM);
        }
        /// <summary>
        /// Method restores geometry information for graph in 2 dimension
        /// </summary>
        /// <param name="graph">It`s a graph, Mr. Graph</param>
        /// <param name="graphNumeration">Restored numeration for the input graph</param>
        /// <returns>
        /// Return code:
        /// 0 - success
        /// -1 - error
        private static int TwoDimensionNumerate(Graph graph, out int[][] graphNumeration)
        {
            int       result    = 0;
            Traversal traversal = new Traversal(graph);
            int       V         = graph.GetVerticesCount();

            int[][] res_graphNumeration = new int[V][];
            int[][] history_guess       = new int[V][]; // which vertex and which index was increased and where
            int     index_guess         = 0;

            graphNumeration = res_graphNumeration;
            int start_vertex         = -1;
            int another_start_vertex = -1;

            //find start vertex
            traversal.NewVertex = (sender, e) =>
            {
                if ((graph.GetAdjVerticesCount(e) == 3))
                {
                    another_start_vertex = e;
                }
                if ((graph.GetAdjVerticesCount(e) == 4))
                {
                    start_vertex = e;
                }
            };
            traversal.Run();
            if (another_start_vertex == -1 && start_vertex == -1)
            {
                return(-1); // not two dimension graph
            }
            else if (start_vertex == -1)
            {
                start_vertex = another_start_vertex;
            }
            bool fixed_first = false; //

            //set start information
            res_graphNumeration[start_vertex] = new int[] { 0, 0 };
            int[] buf;
            long  count_around_start = graph.GetAdjVertices(start_vertex, out buf);
            int   x_start = 1, y_start = 0;

            for (int i = 0; i < count_around_start; ++i)
            {
                res_graphNumeration[buf[i]] = new int[] { x_start, y_start }; // NB: make it easy
                y_start = x_start;
                if (--x_start == -2)
                {
                    x_start = 0;
                }
            }
            traversal.NewVertex = (sender, e) =>
            {
                if (res_graphNumeration[e] == null)
                {
                    int[] buff;
                    long  adj_count = graph.GetAdjVertices(e, out buff);
                    //try to determine with al least 2 numerated vertex
                    int v1 = -1, v2 = -1;
                    for (int i = 0; i < adj_count; ++i)
                    {
                        if (res_graphNumeration[buff[i]] != null)
                        {
                            v2 = v1;
                            v1 = buff[i];
                        }
                    }
                    if (v1 == -1 || v2 == -1)
                    {//if not
                     //check that there is vertex with all pohers numerated neighbours
                        if (v1 != -1)
                        {
                            adj_count = graph.GetAdjVertices(v1, out buff);
                            int  numerated = 0;
                            int  x = 0, y = 0;
                            bool direction = true; // let change x by default
                            for (int i = 0; i < adj_count; ++i)
                            {
                                if (res_graphNumeration[buff[i]] != null)
                                {
                                    x += res_graphNumeration[buff[i]][0];
                                    if (y / (numerated + 1) == res_graphNumeration[buff[i]][1])
                                    {
                                        direction = false;
                                    }
                                    y += res_graphNumeration[buff[i]][1];
                                    ++numerated;
                                }
                            }
                            if (adj_count - numerated == 1)
                            {
                                if (adj_count == 4)
                                {
                                    res_graphNumeration[e] = new int[] { res_graphNumeration[v1][0] * 4 - x, res_graphNumeration[v1][1] * 4 - y };
                                }
                                else
                                {
                                    int x_direction = direction ? ((res_graphNumeration[v1][0] * 4 - 1 > 0) ? 1 : -1) : 0;
                                    int y_direction = !direction ? ((res_graphNumeration[v1][1] * 4 - 1 > 0) ? 1 : -1) : 0;
                                    res_graphNumeration[e]       = new int[] { res_graphNumeration[v1][0] + x_direction, res_graphNumeration[v1][1] + y_direction };
                                    history_guess[index_guess++] = new int[] { e, x_direction, y_direction };
                                }
                            }
                            else if (adj_count - numerated == 3)
                            {
                                int x_direction = (res_graphNumeration[v1][0] * 4 - 1 > 0) ? 1 : -1;
                                int y_direction = (res_graphNumeration[v1][1] * 4 - 1 > 0) ? 1 : -1;
                                res_graphNumeration[e]       = new int[] { res_graphNumeration[v1][0] + x_direction, res_graphNumeration[v1][1] };
                                history_guess[index_guess++] = new int[] { e, x_direction, y_direction };
                            }
                            else if (adj_count - numerated == 2)
                            {
                                int x_direction = direction ? 1 * ((res_graphNumeration[v1][0] * 4 - 1 > 0) ? 1 : -1) : 0;
                                int y_direction = !direction ? 1 * ((res_graphNumeration[v1][1] * 4 - 1 > 0) ? 1 : -1) : 0;
                                res_graphNumeration[e]       = new int[] { res_graphNumeration[v1][0] + x_direction, res_graphNumeration[v1][1] + y_direction };
                                history_guess[index_guess++] = new int[] { e, x_direction, y_direction };
                            }
                            //here we give up
                        }
                        else
                        {
                            result = -1;
                        }
                    }
                    else
                    {
                        //special case of start vertex
                        //swap v1 and reversed from start vertex neighbours
                        if ((res_graphNumeration[v1][0] == res_graphNumeration[v2][0]) || (res_graphNumeration[v1][1] == res_graphNumeration[v2][1]))
                        {
                            if (!fixed_first)
                            {
                                for (int i = 0; i < count_around_start; ++i)
                                {
                                    if ((res_graphNumeration[buf[i]][0] == res_graphNumeration[v1][1]) && (res_graphNumeration[buf[i]][1] == res_graphNumeration[v1][0]))
                                    {
                                        int[] temp = res_graphNumeration[v1];
                                        res_graphNumeration[v1]     = res_graphNumeration[buf[i]];
                                        res_graphNumeration[buf[i]] = temp;
                                        fixed_first = true;
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                if (index_guess > 0)
                                {
                                    res_graphNumeration[history_guess[index_guess - 1][0]] = new int[] { res_graphNumeration[history_guess[index_guess - 1][0]][0] - history_guess[index_guess - 1][1], res_graphNumeration[history_guess[index_guess - 1][0]][1] + history_guess[index_guess - 1][2] }
                                }
                                ;
                                --index_guess;
                            }
                        }

                        int[] bufv1;
                        int[] bufv2;
                        long  couunt_bufv1    = graph.GetAdjVertices(v1, out bufv1);
                        long  couunt_bufv2    = graph.GetAdjVertices(v2, out bufv2);
                        int   opposite_vertex = -1;
                        for (int i = 0; i < couunt_bufv1; ++i)
                        {
                            for (int j = 0; j < couunt_bufv2; ++j)
                            {
                                if (bufv1[i] == bufv2[j] && bufv1[i] != e)
                                {
                                    opposite_vertex = bufv1[i];
                                }
                            }
                        }
                        if ((opposite_vertex != -1) && (res_graphNumeration[opposite_vertex] != null))
                        {
                            int x = res_graphNumeration[v1][0] + res_graphNumeration[v2][0] - res_graphNumeration[opposite_vertex][0];
                            int y = res_graphNumeration[v1][1] + res_graphNumeration[v2][1] - res_graphNumeration[opposite_vertex][1];
                            if ((x == res_graphNumeration[opposite_vertex][0]) && y == res_graphNumeration[opposite_vertex][1])
                            {
                                result = -1;
                            }
                            res_graphNumeration[e] = new int[] { x, y };
                        }
                        else
                        {
                            result = -1;
                        }
                    }
                    //here we give up
                    //but we will do it again!!
                }
            };

            traversal.Run(start_vertex);

            for (int i = 0; i < index_guess; ++i)
            {
                count_around_start = graph.GetAdjVertices(history_guess[i][0], out buf);
                for (int j = 0; j < count_around_start; ++j)
                {
                    if (NumerationHelper.CompareVertex(res_graphNumeration[history_guess[i][0]], res_graphNumeration[buf[j]], 2) < 0)
                    {
                        //try to repair vertex
                        res_graphNumeration[history_guess[index_guess - 1][0]] = new int[] { res_graphNumeration[history_guess[index_guess - 1][0]][0] - history_guess[index_guess - 1][1], res_graphNumeration[history_guess[index_guess - 1][0]][1] + history_guess[index_guess - 1][2] };
                    }
                }
            }
            graphNumeration = res_graphNumeration;
            return(result);
        }
    }