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); }
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); } }