public static void Main() { int[] NM = IntLine(); int N = NM[0], M = NM[1]; UnionFind uf = new UnionFind(N); for (int i = 0; i < M; i++) { int[] a = IntLine(); uf.Unite(a[0] - 1, a[1] - 1); } Dictionary <int, int> nd = new Dictionary <int, int>(); for (int i = 0; i < N; i++) { var a = uf.Root(i); if (!nd.ContainsKey(a)) { nd[a] = 1; } else { nd[a]++; } } int ans = 0; foreach (var k in nd.Keys) { ans += (nd[k] - uf.data[k] == 1 ? 1 : 0); } Console.WriteLine(ans); }
static void Main() { int[] nkl = Console.ReadLine().Split().Select(int.Parse).ToArray(); UnionFind road = new UnionFind(nkl[0]); UnionFind train = new UnionFind(nkl[0]); for (int i = 0; i < nkl[1]; i++) { int[] a = Console.ReadLine().Split().Select(int.Parse).ToArray(); road.Union(a[0] - 1, a[1] - 1); } for (int i = 0; i < nkl[2]; i++) { int[] a = Console.ReadLine().Split().Select(int.Parse).ToArray(); train.Union(a[0] - 1, a[1] - 1); } Dictionary <long, int> dict = new Dictionary <long, int>(); for (int i = 0; i < nkl[0]; i++) { long key = (long)road.Parent(i) * int.MaxValue + (long)train.Parent(i); if (!dict.ContainsKey(key)) { dict.Add(key, 0); } dict[key]++; } int[] ans = new int[nkl[0]]; for (int i = 0; i < nkl[0]; i++) { long key = (long)road.Parent(i) * int.MaxValue + (long)train.Parent(i); ans[i] = dict[key]; } Console.WriteLine(string.Join(" ", ans)); }
static void Main() { int n = int.Parse(Console.ReadLine()); Tuple <int[], int>[] vert = Enumerable.Range(0, n).Select(x => new Tuple <int[], int>(Console.ReadLine().Split().Select(int.Parse).ToArray(), x)).ToArray(); Tuple <int[], int>[] sortbyx = vert.OrderBy(x => x.Item1[0]).ToArray(); Tuple <int[], int>[] sortbyy = vert.OrderBy(x => x.Item1[1]).ToArray(); List <Edge> edges = new List <Edge>(); edges.AddRange(temp(sortbyx)); edges.AddRange(temp(sortbyy)); Edge[] edge = edges.OrderBy(x => x.Length).ToArray(); UnionFind uf = new UnionFind(n); int cost = 0; for (int i = 0; i < edge.Length; i++) { if (!uf.IsSameGroup(edge[i].Start, edge[i].End)) { uf.Union(edge[i].Start, edge[i].End); cost += edge[i].Length; } } Console.WriteLine(cost); }
static void putAns(int[] a, int[] b, int n, int m) { var ans = new long[m + 1]; var uf = new UnionFind(n + 10); ans[0] = (long)n * (n - 1) / 2L; for (int i = 0; i < m; i++) { if (uf.IsSameGroup(a[i], b[i])) { ans[i + 1] = ans[i]; } else { long wa = uf.getMem(a[i]); long wb = uf.getMem(b[i]); ans[i + 1] = ans[i] - wa * wb; uf.Unite(a[i], b[i]); } } Array.Reverse(ans); var sb = new StringBuilder(); for (int i = 1; i <= m; i++) { sb.Append(string.Format("{0}\n", ans[i])); } Console.Write(sb); }
public static void Main() { var n = NextInt; var m = NextInt; List <Edge> edges = new List <Edge>(); for (int i = 0; i < n; i++) { edges.Add(new Edge() { From = 0, To = i + 1, Cost = NextLong }); } for (int i = 0; i < m; i++) { edges.Add(new Edge() { From = NextInt, To = NextInt, Cost = NextLong }); } long res = 0; UnionFind uf = new UnionFind(n + 1); foreach (var edge in edges.OrderBy(x => x.Cost)) { if (uf.TryUnite(edge.From, edge.To)) { res += edge.Cost; } } Console.WriteLine(res); }
private void TwoSitesCheck(UnionFind unionFind) { unionFind.Union(2, 8); Assert.IsTrue(unionFind.IsConnected(2, 8)); Assert.IsFalse(unionFind.IsConnected(1, 5)); }
static void Solve(IO io) { var n = io.I; var m = io.I; var uf = new UnionFind(n); for (var i = 0; i < m; i++) { var a = io.I - 1; var b = io.I - 1; uf.Union(a, b); } var ans = 0; for (var i = 1; i < n; i++) { if (uf.Union(i - 1, i)) { ans++; } } io.Write(ans); }
public int MinCostToSupplyWater(int n, int[] wells, int[][] pipes) { List <int[]> orderedEdges = new List <int[]>(n + 1 + pipes.Length); for (int i = 0; i < wells.Length; i++) { orderedEdges.Add(new int[] { 0, i + 1, wells[i] }); } for (int i = 0; i < pipes.Length; i++) { int[] edge = pipes[i]; orderedEdges.Add(edge); } orderedEdges.Sort((a, b) => a[2] - b[2]); UnionFind uf = new UnionFind(n); int totalCost = 0; foreach (int[] edge in orderedEdges) { int houseOne = edge[0]; int houseTwo = edge[1]; int cost = edge[2]; if (uf.Union(houseOne, houseTwo)) { totalCost += cost; } } return(totalCost); }
/// <summary> /// Connects any orphaned sections of the map together. /// </summary> /// <typeparam name="T"></typeparam> public static T ConnectOrphanedSections <T>(T map) where T : class, IMap, new() { var floodFillAnalyzer = new FloodFillAnalyzer(map); var returnMap = map.Clone <T>(); List <MapSection> mapSections = floodFillAnalyzer.GetMapSections(); var unionFind = new UnionFind(mapSections.Count); while (unionFind.Count > 1) { for (int i = 0; i < mapSections.Count; i++) { int closestMapSectionIndex = FindNearestMapSection(mapSections, i, unionFind); MapSection closestMapSection = mapSections[closestMapSectionIndex]; IEnumerable <ICell> tunnelCells = map.GetCellsAlongLine(mapSections[i].Bounds.Center.X, mapSections[i].Bounds.Center.Y, closestMapSection.Bounds.Center.X, closestMapSection.Bounds.Center.Y); ICell previousCell = null; foreach (ICell cell in tunnelCells) { returnMap.SetCellProperties(cell.X, cell.Y, true, true); if (previousCell != null) { if (cell.X != previousCell.X || cell.Y != previousCell.Y) { returnMap.SetCellProperties(cell.X + 1, cell.Y, true, true); } } previousCell = cell; } unionFind.Union(i, closestMapSectionIndex); } } return(returnMap); }
public void Solve() { // ARC097 D int N = NextInt(), M = NextInt(); var P = NextIntList(); var uf = new UnionFind(N); M.REP(i => { int xi = NextInt() - 1, yi = NextInt() - 1; uf.Unite(xi, yi); }); var cnt = 0; for (int i = 0; i < N; i++) { if (uf.IsSameGroup(P[i] - 1, i)) { cnt++; } } cnt.WL(); return; }
public KruskalMST(WeightedUnDirectedGraph g) { this.G = g; this.MSTEdges = new Queue <WeightedUndirectedEdge>(); this.TotalWeight = 0; minHeap = new MinHeap <WeightedUndirectedEdge>(this.G.GetVertices() * this.G.GetVertices()); Uf = new UnionFind(G.GetVertices()); foreach (var vertex in G.GetVerticesList()) { foreach (var edge in G.GetAdjacentEdges(vertex)) { minHeap.Insert(edge); } } while (!minHeap.IsEmpty()) { WeightedUndirectedEdge edge = minHeap.ExtractMin(); int u = edge.Either(); int v = edge.Other(u); if (!Uf.Connected(u, v)) { MSTEdges.Enqueue(edge); TotalWeight += edge.Weight(); Uf.Union(u, v); } } }
public int MinCostConnectPoints(int[][] points) { this.points = points; int pointCount = points.Length; var edges = new List <Edge>(); for (int i = 0; i < pointCount - 1; i++) { for (int j = i + 1; j < pointCount; j++) { edges.Add(new Edge(i, j, GetCost(i, j))); } } edges.Sort(); var uf = new UnionFind(pointCount); int ans = 0; foreach (var edge in edges) { if (!uf.Insert(edge.I, edge.J)) { continue; } ans += edge.Length; } return(ans); }
void InitPQ() { uf = VertexNode.MakeUnionFind(heMesh); for (int i = 0; i < uf.NumNodes; i++) { uf[i].Quadric = vertQuadrics[i]; } PQ = new FastPriorityQueue <FaceNode>(heMesh.Faces.Length); nodes = new FaceNode[heMesh.Faces.Length]; for (int i = 0; i < heMesh.Faces.Length; i++) { Face f = heMesh.Faces[i]; if (f.IsBoundary) { continue; } nodes[i] = new FaceNode(f); Edge lowestCost = OptimalEdge(f); float cost = Cost(lowestCost); PQ.Enqueue(nodes[i], cost); } }
static void Main() { var n = int.Parse(Console.ReadLine()); var a = Console.ReadLine().Split().Select(int.Parse).ToList(); a.Add(a.Aggregate(0, (x, y) => x ^ y)); var b = Console.ReadLine().Split().Select(int.Parse).ToList(); b.Add(b.Aggregate(0, (x, y) => x ^ y)); if (a.OrderBy(x => x).Zip(b.OrderBy(x => x), (x, y) => x != y).Any(x => x)) { Console.WriteLine(-1); return; } var compressed = a.Distinct().OrderBy(x => x).Select((elem, count) => new { elem, count }).ToDictionary(x => x.elem, x => x.count); int sameCount = 0; UnionFind uf = new UnionFind(compressed.Count); for (int i = 0; i < n; i++) { if (a[i] == b[i]) { sameCount++; } uf.TryUnite(compressed[a[i]], compressed[b[i]]); } //全ての違う変数を動かす+閉路の数だけ動かす必要がある 始点を閉路に組み込めているならば-1 Console.WriteLine((n - sameCount) + uf.AllRepresents.Count(x => 2 <= uf.GetSize(x)) - (n != sameCount && b.IndexOf(a.Last()) != n ? 1 : 0)); }
public int[] HitBricks(int[][] grid, int[][] hits) { int[] result = new int[hits.Length]; for (int i = 0; i < hits.Length; i++) { grid[hits[i][0]][hits[i][1]] -= 1; } int size = grid.Length * grid[0].Length; UnionFind uf = new UnionFind(size + 1); for (int i = 0; i < grid[0].Length; i++) { if (grid[0][i] == 1) { uf.Union(i, size); } } for (int i = 1; i < grid.Length; i++) { for (int j = 0; j < grid[0].Length; j++) { if (grid[i][j] == 1) { if (grid[i - 1][j] == 1) { uf.Union((i - 1) * grid[0].Length + j, i * grid[0].Length + j); } if (j > 0 && grid[i][j - 1] == 1) { uf.Union(i * grid[0].Length + j - 1, i * grid[0].Length + j); } } } } for (int i = hits.Length - 1; i > 0; i--) { grid[hits[i][0]][hits[i][1]] += 1; if (grid[hits[i][0]][hits[i][1]] == 1) { int preCount = uf.GetSize(size); if (hits[i][0] == 0) { uf.Union(hits[i][1], size); } for (int j = 0; j < 4; j++) { var x = hits[i][0] + step[j][0]; var y = hits[i][1] + step[j][0]; if (x >= 0 && y >= 0 && x < grid.Length && y < grid[0].Length && grid[x][y] == 1) { uf.Union(hits[i][0] * grid[0].Length + hits[i][1], x * grid[0].Length + y); } } int unionedCount = uf.GetSize(size); result[i] = Math.Max(0, unionedCount - preCount - 1); } } return(result); }
public static void Main() { int[] NM = IntLine(); int N = NM[0], M = NM[1]; int[] ps = IntLine(); UnionFind tree = new UnionFind(N); for (int i = 0; i < M; i++) { int[] box = IntLine().Select(v => v - 1).ToArray();; tree.Unite(box[0], box[1]); } int ans = 0; for (int i = 0; i < N; i++) { if (tree.Same(i, ps[i] - 1)) { ans++; } } Console.WriteLine(ans); }
public int NumIslands(char[][] grid) { if (grid == null || grid.Length == 0) { return(0); } rows = grid.Length; colums = grid[0].Length; UnionFind uf = new UnionFind(grid); for (int i = 0; i < rows; i++) { for (int j = 0; j < colums; j++) { if (grid[i][j] == '0') { continue; } for (int k = 0; k < 4; k++) { int newx = i + d[k, 0]; int newy = j + d[k, 1]; if (newx >= 0 && newy >= 0 && newx < rows && newy < colums && grid[newx][newy] == '1') { uf.Union(i * colums + j, newx * colums + newy); } } } } return(uf.Count); }
static void Main(string[] args) { var nm = Input.ar; var edge = new List <Edge>(); for (var i = 0; i < nm[0]; i++) { var cost = Input.num; edge.Add(new Edge(i, nm[0], cost)); } for (var i = 0; i < nm[1]; i++) { var e = Input.ar; edge.Add(new Edge(e[0] - 1, e[1] - 1, e[2])); } edge = edge.OrderBy(v => v.Item3).ToList(); var uf = UnionFind <int> .Make(nm[0] + 1); var res = 0L; foreach (var eg in edge) { if (!uf.IsSame(eg.Item1, eg.Item2)) { uf.Union(eg.Item1, eg.Item2); res += eg.Item3; } } WriteLine(res); }
public static void Main() { long N = NextLong(); int M = NextInt(); UnionFind UF = new UnionFind((int)N); Pair[] p = new Pair[M]; for (int i = 0; i < M; i++) { p[i].x = NextInt() - 1; p[i].y = NextInt() - 1; } Array.Reverse(p); List <long> ans = new List <long>(); long box = (N - 1) * N / 2; for (int i = 0; i < M; i++) { ans.Add(box); if (UF.Same(p[i].x, p[i].y)) { continue; } else { box -= UF.Get(p[i].x) * UF.Get(p[i].y); } UF.Unite(p[i].x, p[i].y); } ans.Reverse(); ans.ToList().ForEach(Console.WriteLine); }
public void Should_Connect_Two_By_Two() { //given UnionFind<String> uf = new UnionFind<String>(); String[] cc = new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }; //when uf.AddRange(cc); for(int i = 0; i < cc.Length; i += 2) { uf.Merge(i, i + 1); } //Then uf.AddRange(cc); for (int i = 0; i < cc.Length; i += 2) { bool connected = uf.IsConnected(i, i + 1); Assert.IsTrue(connected); if(i+2 < cc.Length) { connected = uf.IsConnected(i + 1, i + 2); Assert.IsFalse(connected); } } }
private void ConnectCaves() { var mapAnalyzer = new MapAnalyzer(_map); List <MapSection> mapSections = mapAnalyzer.GetMapSections(); var unionFind = new UnionFind(mapSections.Count); while (unionFind.Count > 1) { for (int i = 0; i < mapSections.Count; i++) { int closestMapSectionIndex = FindNearestMapSection(mapSections, i, unionFind); MapSection closestMapSection = mapSections[closestMapSectionIndex]; IEnumerable <Cell> tunnelCells = _map.GetCellsAlongLine(mapSections[i].Bounds.Center.X, mapSections[i].Bounds.Center.Y, closestMapSection.Bounds.Center.X, closestMapSection.Bounds.Center.Y); Cell previousCell = null; foreach (Cell cell in tunnelCells) { _map.SetCellProperties(cell.X, cell.Y, true, true); if (previousCell != null) { if (cell.X != previousCell.X || cell.Y != previousCell.Y) { _map.SetCellProperties(cell.X + 1, cell.Y, true, true); } } previousCell = cell; } unionFind.Union(i, closestMapSectionIndex); } } }
/// <summary> /// Returns the lightest tree that connects all the vertices in the graph. /// </summary> /// <returns>A list of edges that make up the minimum spanning tree.</returns> public List <Edge> Kruskal() { List <Edge> mst = new List <Edge>(); List <Edge> edges = new List <Edge>(); UnionFind <uint> unionFind = new UnionFind <uint>(); foreach (Vertex v in this.Vertices.Values) { foreach (Edge e in v.Neighbours.Values) { edges.Add(e); } } edges.Sort((x, y) => { return(x.Weight.CompareTo(y.Weight)); }); foreach (Vertex v in this.Vertices.Values) { unionFind.Make(v.ID); } foreach (Edge e in edges) { if (unionFind.Find(e.From) != unionFind.Find(e.To)) { mst.Add(e); unionFind.Union(e.From, e.To); } } return(mst); }
public static void Main() { int n = int.Parse(Console.ReadLine()); var ab = Enumerable.Repeat(0, n).Select(_ => Console.ReadLine().Split().Select(int.Parse).ToArray()).ToArray(); UnionFind uf = new UnionFind(400000 + 1); foreach (var item in ab) { uf.TryUnite(item[0], item[1]); } int[] edgeCount = new int[uf.Size]; for (int i = 0; i < n; i++) { edgeCount[uf.Find(ab[i][0])]++; } long res = 0; for (int i = 0; i < edgeCount.Length; i++) { res += Min(edgeCount[i], uf.GetSize(i)); } Console.WriteLine(res); }
static void Main() { int N = cin.Int(); int M = cin.Int(); var uf = new UnionFind(N + 10); var A = new int[M]; var B = new int[M]; for (int i = 0; i < M; i++) { A[i] = cin.Int(); B[i] = cin.Int(); if (!uf.IsSameGroup(A[i], B[i])) { uf.Unite(A[i], B[i]); } } var hash = new HashSet <int>(); for (int i = 1; i <= N; i++) { hash.Add(uf.Root(i)); } Console.WriteLine(hash.Count - 1); Console.ReadLine(); }
/// <summary> /// Builds the minimum-spanning tree using Kruskal's algorithm in O(|E|*log|E|) /// where |E| is the number of Edges /// and |V| the number of vertices (nodes) in the Graph /// </summary> /// <returns></returns> private Tree BuildMinimumSpanningTreeKruskal() { int N = m_nodes.Count; var unionFind = new UnionFind(m_nodes); //O(|V|) Func <Edge, Edge, int> cmp = (a, b) => a.CompareTo(b); var heap = new List <Edge>(EdgeCount); foreach (var e in Edges) { heap.HeapEnqueue(cmp, e); } var tree = new Tree(this); long i = 0; //O(|E|*log|E|) while (tree.EdgeCount < N - 1) { var edge = heap.HeapDequeue(cmp); i++; //O(1) amortized if (unionFind.Add(edge.Index0, edge.Index1)) { //O(1) tree.AddEdge(edge); } } //O(|V| + |E|*log|E|) return(tree); }
public void Solve() { int n = cin.nextint; int m = cin.nextint; int[,] edge = new int[m, 2]; for (int i = 0; i < m; i++) { edge[i, 0] = cin.nextint - 1; edge[i, 1] = cin.nextint - 1; } UnionFind uf = new UnionFind(n); long[] ans = new long[m]; ans[m - 1] = (long)n * (n - 1) / 2; for (int i = m - 1; i > 0; i--) { if (uf.IsSame(edge[i, 0], edge[i, 1])) { ans[i - 1] = ans[i]; } else { long size = uf.size[uf.Root(edge[i, 0])] * uf.size[uf.Root(edge[i, 1])]; ans[i - 1] = ans[i] - size; uf.Unite(edge[i, 0], edge[i, 1]); } } Console.WriteLine(String.Join("\n", ans)); }
/// <summary> /// Returns the lightest tree that connects all the node in the graph. /// </summary> /// <param name="graph">The graph to calculate the minimum spanning tree of.</param> /// <returns>A list of edges that make up the minimum spanning tree.</returns> public static List <IWeightedGraphEdge> MinimumSpanningTree(IGraph <IWeightedGraphEdge> graph) { List <IWeightedGraphEdge> mst = new List <IWeightedGraphEdge>(); List <IWeightedGraphEdge> edges = new List <IWeightedGraphEdge>(); UnionFind <uint> unionFind = new UnionFind <uint>(); foreach (Dictionary <uint, IWeightedGraphEdge> dict in graph.Edges.Values) { foreach (IWeightedGraphEdge e in dict.Values) { edges.Add(e); } } edges.Sort((x, y) => { return(x.Weight.CompareTo(y.Weight)); }); foreach (IGraphNode <IWeightedGraphEdge> n in graph.Nodes.Values) { unionFind.Make(n.ID); } foreach (IWeightedGraphEdge e in edges) { if (unionFind.Find(e.From) != unionFind.Find(e.To)) { mst.Add(e); unionFind.Union(e.From, e.To); } } return(mst); }
static void Method(string[] args) { int[] nm = ReadInts(); int n = nm[0]; int m = nm[1]; UnionFind unionFind = new UnionFind(n); for (int i = 0; i < m; i++) { int[] xyz = ReadInts(); unionFind.Unite(xyz[0] - 1, xyz[1] - 1); } int cnt = 0; for (int i = 0; i < n; i++) { if (i == unionFind.Root(i)) { cnt++; } } WriteLine(cnt); }
/// <summary> /// Sprawdza czy dla podanych par ulic możliwy jest przejazd między nimi (z użyciem być może innych ulic). /// </summary> /// <returns>Lista, w której na i-tym miejscu jest informacja czy przejazd między ulicami w i-tej parze z wejścia jest możliwy</returns> // etap 2 public bool[] CheckStreetsPairs(Street[] streets, int[] streetsToCheck1, int[] streetsToCheck2) { int n = streetsToCheck1.Length; int S = streets.Length; if (S == 0 || n == 0) { throw new ArgumentException(); } bool[] ret = new bool[n]; UnionFind u = new UnionFind(S); for (int i = 0; i < S - 1; ++i) { for (int j = i + 1; j < S; ++j) { if (CheckIntersection(streets[i], streets[j]) != 0) { u.Union(i, j); } } } for (int i = 0; i < n; ++i) { if (u.Find(streetsToCheck1[i]) == u.Find(streetsToCheck2[i])) { ret[i] = true; } } return(ret); }
static void Main() { int n, q; sc.Multi(out n, out q); var uf = new UnionFind(n * 2); for (int i = 0; i < q; i++) { int w, x, y, z; sc.Multi(out w, out x, out y, out z); --x; --y; if (w == 1) { if (z % 2 == 0) { uf.unite(x, y); uf.unite(x + n, y + n); } else { uf.unite(x, y + n); uf.unite(x + n, y); } } else { Prt(uf.same(x, y) ? "YES" : "NO"); } } sw.Flush(); }
static void putAns(int[] a, int[] b, int n, int m) { var ans = new long[m + 1]; var uf = new UnionFind(n + 10); ans[0] = (long)n * (n - 1) / 2L; for (int i = 0; i < m; i++) { if (uf.IsSameGroup(a[i], b[i])) { ans[i + 1] = ans[i]; } else { long wa = uf.getMem(a[i]); long wb = uf.getMem(b[i]); ans[i + 1] = ans[i] - wa * wb; uf.Unite(a[i], b[i]); } } Array.Reverse(ans); for (int i = 1; i <= m; i++) { Console.WriteLine(ans[i]); } }
public void ConnectedTest1() { var uf = new UnionFind<double>(EqualityComparer<double>.Default); uf.Union(3.14, 2.71); uf.Union(1, 2); uf.Union(3.14, 1.618); uf.Union(2.71, 0); Assert.Equal(false, uf.Connected(1, 3.14)); Assert.Equal(true, uf.Connected(2.71, 1.618)); Assert.Equal(true, uf.Connected(0, 1.618)); }
public void StringTest() { var uf = new UnionFind(); Assert.IsFalse(uf.IsSameGroup("1", "2")); Assert.IsFalse(uf.IsSameGroup("2", "3")); Assert.IsFalse(uf.IsSameGroup("1", "3")); uf.Unite("1", "3"); Assert.IsFalse(uf.IsSameGroup("1", "2")); Assert.IsFalse(uf.IsSameGroup("2", "3")); Assert.IsTrue(uf.IsSameGroup("1", "3")); }
public void TypeMixedTest() { var uf = new UnionFind(); Assert.IsFalse(uf.IsSameGroup(1, "1")); Assert.IsFalse(uf.IsSameGroup("2", 2)); Assert.IsFalse(uf.IsSameGroup("two", 2)); uf.Unite(1, "1"); uf.Unite(2, "2"); uf.Unite(2, "two"); Assert.IsTrue(uf.IsSameGroup(1, "1")); Assert.IsTrue(uf.IsSameGroup("2", 2)); Assert.IsTrue(uf.IsSameGroup("two", 2)); //2 and "two" should be the same group! Assert.IsTrue(uf.IsSameGroup("2", "two")); }
public void Ordinal() { var uf = new UnionFind(); Assert.IsFalse(uf.IsSameGroup(1, 2)); Assert.IsFalse(uf.IsSameGroup(2, 3)); Assert.IsFalse(uf.IsSameGroup(1, 3)); uf.Unite(1, 3); Assert.IsFalse(uf.IsSameGroup(1, 2)); Assert.IsFalse(uf.IsSameGroup(2, 3)); Assert.IsTrue(uf.IsSameGroup(1, 3)); uf.Unite(2, 3); Assert.IsTrue(uf.IsSameGroup(1, 2)); Assert.IsTrue(uf.IsSameGroup(2, 3)); Assert.IsTrue(uf.IsSameGroup(1, 3)); uf.Unite(50, 51); uf.Unite(52, 53); Assert.IsTrue(uf.IsSameGroup(50, 51)); Assert.IsTrue(uf.IsSameGroup(52, 53)); Assert.IsFalse(uf.IsSameGroup(50, 53)); uf.Unite(53, 54); Assert.IsTrue(uf.IsSameGroup(52, 54)); uf.Unite(50, 54); Assert.IsTrue(uf.IsSameGroup(50, 53)); Assert.IsTrue(uf.IsSameGroup(50, 54)); Assert.IsTrue(uf.IsSameGroup(50, 51)); uf.Unite(70, 71); uf.Unite(70, 72); uf.Unite(73, 72); Assert.IsTrue(uf.IsSameGroup(70, 73)); Assert.IsTrue(uf.IsSameGroup(73, 70)); Assert.IsTrue(uf.IsSameGroup(73, 72)); uf.Unite(99, 98); uf.Unite(0, 98); Assert.IsTrue(uf.IsSameGroup(98, 99)); Assert.IsTrue(uf.IsSameGroup(99, 0)); Assert.IsTrue(uf.IsSameGroup(98, 0)); }
public void Run() { MinHeap<Edge> minHeap = new MinHeap<Edge>(); foreach(Edge e in graph.Edges()) { minHeap.Push(e); } UnionFind<int> uf = new UnionFind<int>(); while(minHeap.Count > 0 && mst.Count < graph.VerticesCount - 1) { Edge e = minHeap.Pop(); int v = e.GetEither(); int w = e.GetOther(v); if(!uf.IsConnected(v, w)) { uf.Merge(v, w); mst.Enqueue(e); } } }
/// <summary> /// Returns the lightest tree that connects all the vertices in the graph. /// </summary> /// <returns>A list of edges that make up the minimum spanning tree.</returns> public List<Edge> Kruskal() { List<Edge> mst = new List<Edge>(); List<Edge> edges = new List<Edge>(); UnionFind<uint> unionFind = new UnionFind<uint>(); foreach (Vertex v in this.Vertices.Values) foreach (Edge e in v.Neighbours.Values) edges.Add(e); edges.Sort((x, y) => { return x.Weight.CompareTo(y.Weight); }); foreach (Vertex v in this.Vertices.Values) unionFind.Make(v.ID); foreach (Edge e in edges) if (unionFind.Find(e.From) != unionFind.Find(e.To)) { mst.Add(e); unionFind.Union(e.From, e.To); } return mst; }
/// <summary> /// Returns the lightest tree that connects all the node in the graph. /// </summary> /// <param name="graph">The graph to calculate the minimum spanning tree of.</param> /// <returns>A list of edges that make up the minimum spanning tree.</returns> public static List<IWeightedGraphEdge> MinimumSpanningTree(IGraph<IWeightedGraphEdge> graph) { List<IWeightedGraphEdge> mst = new List<IWeightedGraphEdge>(); List<IWeightedGraphEdge> edges = new List<IWeightedGraphEdge>(); UnionFind<uint> unionFind = new UnionFind<uint>(); foreach (Dictionary<uint, IWeightedGraphEdge> dict in graph.Edges.Values) foreach (IWeightedGraphEdge e in dict.Values) edges.Add(e); edges.Sort((x, y) => { return x.Weight.CompareTo(y.Weight); }); foreach (IGraphNode<IWeightedGraphEdge> n in graph.Nodes.Values) unionFind.Make(n.ID); foreach (IWeightedGraphEdge e in edges) if (unionFind.Find(e.From) != unionFind.Find(e.To)) { mst.Add(e); unionFind.Union(e.From, e.To); } return mst; }
// find objects public static Dictionary<Tuple<int, int>, List<Tuple<int, int>>> Groups(int[,] image) { // union find to store sets of all pixels in object UnionFind<Tuple<int, int>> unionFind = new UnionFind<Tuple<int, int>>(); for (int x = 0; x < image.GetLength(0); x++) for (int y = 0; y < image.GetLength(1); y++) { if (image[x, y] == 0) continue; Tuple<int, int> xy = new Tuple<int, int>(x, y); unionFind.Make(xy); if (x > 0) unionFind.Union(xy, new Tuple<int, int>(x - 1, y)); if (y > 0) unionFind.Union(xy, new Tuple<int, int>(x, y - 1)); } // turns union find "inside out": (pixel->set identifier)->(set identifier->all pixels in set) Dictionary<Tuple<int, int>, List<Tuple<int, int>>> labels = new Dictionary<Tuple<int, int>, List<Tuple<int, int>>>(); for (int x = 0; x < image.GetLength(0); x++) for (int y = 0; y < image.GetLength(1); y++) { if (image[x, y] == 0) continue; Tuple<int, int> xy = new Tuple<int, int>(x, y), label = unionFind.Find(xy); List<Tuple<int, int>> list; if (!labels.TryGetValue(label, out list)) { list = new List<Tuple<int, int>>(); labels[label] = list; } list.Add(xy); } return labels; }
private static void BuildNavCellConnectivityGrid( uint colomnCount, uint rowCount, BitArray navMeshData, out NavCell[] navCells, out uint nonEmptyNavCellCount) { UnionFind<uint> navCellUnion = new UnionFind<uint>(); // Create an initial set of nav cells // Any valid cell gets a connectivity id of 0 // Any invalid cell gets a connectivity id of EMPTY_NAV_CELL // Valid nav cells get added to the nav cell union set navCells = new NavCell[rowCount * colomnCount]; nonEmptyNavCellCount = 0; for (int navCellIndex = 0; navCellIndex < navMeshData.Length; ++navCellIndex) { if (navMeshData[navCellIndex]) { uint pvsCellIndex = nonEmptyNavCellCount++; navCells[navCellIndex] = new NavCell(0, pvsCellIndex); navCellUnion.AddElement((uint)navCellIndex); } else { navCells[navCellIndex] = new NavCell(); } } // Union together all neighboring nav cells for (int unionElementIndex = 0; unionElementIndex < navCellUnion.SetSize; ++unionElementIndex) { uint navCellIndex = navCellUnion.GetElement(unionElementIndex); for (MathConstants.eDirection direction = MathConstants.eDirection.first; direction < MathConstants.eDirection.count; ++direction) { uint neighborNavCellIndex; if (TryGetValidNeighborNavCellIndex( navCells, colomnCount, rowCount, navCellIndex, direction, out neighborNavCellIndex)) { navCellUnion.Union(navCellIndex, neighborNavCellIndex); } } } // Write the final connectivity IDs back into the nav cells for (int unionElementIndex = 0; unionElementIndex < navCellUnion.SetSize; ++unionElementIndex) { uint navCellIndex = navCellUnion.GetElement(unionElementIndex); int connectivityID = navCellUnion.FindRootIndex(unionElementIndex); navCells[navCellIndex].connectivityId = (short)connectivityID; } }
private bool ProcessImage(Color[,] image, CIELAB[,] imageLAB) { double thresh = 5; UnionFind<CIELAB> uf = new UnionFind<CIELAB>((a,b)=>(a.SqDist(b)<=thresh)); int[,] assignments = uf.ConnectedComponents(imageLAB);//Util.Map<Color, CIELAB>(image, Util.RGBtoLAB)); int numC = -1; for(int i=0; i<image.GetLength(0); i++) for (int j=0; j<image.GetLength(1); j++) numC = Math.Max(numC, assignments[i,j]+1); if (numC >= 2) RemoveBackground(image, imageLAB); //if it is a black and white image (with num connected components >= 2), it's not a valid color image return !(isBlackWhite(image, imageLAB) && numC >= 2); }
private void RemoveBackground(Color[,] image, CIELAB[,] imageLAB) { //check perimeter to see if it's mostly black or white //RGB to LAB CIELAB black = new CIELAB(0, 0, 0); CIELAB white = new CIELAB(100, 0, 0); int width = image.GetLength(0); int height = image.GetLength(1); CIELAB[,] labs = imageLAB;//Util.Map<Color, CIELAB>(image, (c) => Util.RGBtoLAB(c)); int numBlack = 0; int numWhite = 0; int thresh = 3 * 3; List<Point> perimeterIdx = new List<Point>(); double totalPerimeter = 4 * width + 4 * height; double bgThresh = totalPerimeter*0.75; for (int i = 0; i < width; i++) { //top for (int j = 0; j < 2; j++) { if (black.SqDist(labs[i, j])<thresh) numBlack++; if (white.SqDist(labs[i, j]) < thresh) numWhite++; perimeterIdx.Add(new Point(i, j)); } //bottom for (int j = height - 2; j < height; j++) { perimeterIdx.Add(new Point(i, j)); if (black.SqDist(labs[i, j]) < thresh) numBlack++; if (white.SqDist(labs[i, j]) < thresh) numWhite++; } } for (int j = 0; j < height; j++) { //left for (int i=0; i<2; i++) { perimeterIdx.Add(new Point(i,j)); if (black.SqDist(labs[i, j]) < thresh) numBlack++; if (white.SqDist(labs[i, j]) < thresh) numWhite++; } //right for (int i=width-2; i<width; i++) { perimeterIdx.Add(new Point(i, j)); if (black.SqDist(labs[i, j]) < thresh) numBlack++; if (white.SqDist(labs[i, j]) < thresh) numWhite++; } } if (numBlack >= bgThresh || numWhite >= bgThresh) { //connected components UnionFind<CIELAB> uf = new UnionFind<CIELAB>((a,b) => a.SqDist(b)<thresh); int[,] cc = uf.ConnectedComponents(labs); SortedSet<int> ids = new SortedSet<int>(); //go around the perimeter to collect the right ids foreach (Point p in perimeterIdx) { if (numWhite > numBlack) { if (labs[p.X, p.Y].SqDist(white) < thresh) ids.Add(cc[p.X, p.Y]); } else { if (labs[p.X, p.Y].SqDist(black) < thresh) ids.Add(cc[p.X, p.Y]); } } //fill the bitmap with transparency for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { if (ids.Contains(cc[i, j])) image[i, j] = Color.FromArgb(0, 0, 0, 0); } } } }
private bool VerifyRoomAccessibility( DungeonLayout layout, Dictionary<int, Portal> portalIdToPortalMap) { UnionFind<RoomKey> roomUnion = new UnionFind<RoomKey>(); RoomKey targetRoomKey = new RoomKey(); bool success = true; // Do a first pass over the rooms to fill out the union and the portal map for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid); iterator.Valid; iterator.Next()) { DungeonLayout.RoomIndex roomIndex = iterator.Current; Room room = layout.GetRoomByIndex(roomIndex); // Add the room to the union set roomUnion.AddElement(room.room_key); } // Union together all of the rooms connected by portals for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid); iterator.Valid; iterator.Next()) { DungeonLayout.RoomIndex roomIndex = iterator.Current; Room room = layout.GetRoomByIndex(roomIndex); foreach (Portal portal in room.portals) { Portal targetPortal= portalIdToPortalMap[portal.target_portal_id]; targetRoomKey.game_id= layout.GameID; targetRoomKey.x= targetPortal.room_x; targetRoomKey.y= targetPortal.room_y; targetRoomKey.z= targetPortal.room_z; roomUnion.Union(room.room_key, targetRoomKey); } } // Verify that all rooms share the same connectivity id int sharedConnectivityId = -1; for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid); iterator.Valid; iterator.Next()) { DungeonLayout.RoomIndex roomIndex = iterator.Current; Room room = layout.GetRoomByIndex(roomIndex); int roomConnectivityId= roomUnion.FindRootIndex(room.room_key); if (sharedConnectivityId != -1) { if (sharedConnectivityId != roomConnectivityId) { _logger.WriteLine("DungeonValidator: FAILED: Found room not connected to other rooms in dungeon!"); _logger.WriteLine(string.Format(" game_id: {0}", layout.GameID)); _logger.WriteLine(string.Format(" room_key: {0},{1},{2}", room.room_key.x, room.room_key.y, room.room_key.z)); success= false; break; } } else { sharedConnectivityId= roomConnectivityId; } } return success; }
//Test the quantization, connected components on different color layers, and output the descriptor private void OutputPatterns_Click(object sender, RoutedEventArgs e) { //Create output directories Directory.CreateDirectory(outdir + "\\cc\\"); Directory.CreateDirectory(outdir + "\\quantized\\"); Directory.CreateDirectory(outdir + "\\mesh\\"); //read in the patterns and save out their layers String[] files = System.IO.Directory.GetFiles(System.IO.Path.Combine(imagedir)); List<PatternItem> patterns = PatternIO.GetPatterns(imagedir); foreach (PatternItem p in patterns) { Bitmap image= new Bitmap(p.FullPath); String basename = p.Name; //TODO: sometimes keys are not found in patterns.csv...will need to look into recovering missing info. For now, just ignore those patterns if (!palettes.ContainsKey(basename)) continue; PaletteData palette = palettes[basename]; ColorTemplate template = new ColorTemplate(image, palette); //output the template descriptor SegmentMesh mesh = new SegmentMesh(template); PatternIO.SaveMesh(mesh, p, Path.Combine(outdir, "mesh")); if (outputDebugImages) { Bitmap result = template.DebugQuantization(); PatternIO.SavePattern(result, p, Path.Combine(outdir, "quantized"), "_quantized"); PatternIO.SavePattern(result, p, Path.Combine(outdir, "quantized"), "_original"); //save the connected components UnionFind<Color> uf = new UnionFind<Color>((a, b) => (a.GetHashCode() == b.GetHashCode())); Color[,] resultArray = Util.BitmapToArray(result); int[,] cc = uf.ConnectedComponentsNoiseRemoval(resultArray); int numColors = palette.colors.Count(); for (int i = 0; i < numColors; i++) { Bitmap debug = uf.RenderComponents(cc, resultArray, palette.colors[i]); PatternIO.SavePattern(debug, p, Path.Combine(outdir, "cc"), "_" + i); debug.Dispose(); } result.Dispose(); } image.Dispose(); } }
/// <summary> /// Constructs the graph pattern specified by the MATCH clause. /// The graph pattern may consist of multiple fully-connected sub-graphs. /// </summary> /// <param name="query">The SELECT query block</param> /// <returns>A graph object contains all the connected componeents</returns> private MatchGraph ConstructGraph(WSelectQueryBlock query) { if (query == null || query.MatchClause == null) return null; var unionFind = new UnionFind(); var edgeColumnToAliasesDict = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase); var pathDictionary = new Dictionary<string, MatchPath>(StringComparer.OrdinalIgnoreCase); var matchClause = query.MatchClause; var nodes = new Dictionary<string, MatchNode>(StringComparer.OrdinalIgnoreCase); var connectedSubGraphs = new List<ConnectedComponent>(); var subGrpahMap = new Dictionary<string, ConnectedComponent>(StringComparer.OrdinalIgnoreCase); var parent = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); unionFind.Parent = parent; // Constructs the graph pattern specified by the path expressions in the MATCH clause foreach (var path in matchClause.Paths) { var index = 0; MatchEdge preEdge = null; for (var count = path.PathEdgeList.Count; index < count; ++index) { var currentNodeTableRef = path.PathEdgeList[index].Item1; var currentEdgeColumnRef = path.PathEdgeList[index].Item2; var currentNodeExposedName = currentNodeTableRef.BaseIdentifier.Value; var nextNodeTableRef = index != count - 1 ? path.PathEdgeList[index + 1].Item1 : path.Tail; var nextNodeExposedName = nextNodeTableRef.BaseIdentifier.Value; var patternNode = nodes.GetOrCreate(currentNodeExposedName); if (patternNode.NodeAlias == null) { patternNode.NodeAlias = currentNodeExposedName; patternNode.Neighbors = new List<MatchEdge>(); patternNode.External = false; var nodeTable = _context[currentNodeExposedName] as WNamedTableReference; if (nodeTable != null) { patternNode.NodeTableObjectName = nodeTable.TableObjectName; if (patternNode.NodeTableObjectName.SchemaIdentifier == null) patternNode.NodeTableObjectName.Identifiers.Insert(0, new Identifier {Value = "dbo"}); } } string edgeAlias = currentEdgeColumnRef.Alias; if (edgeAlias == null) { var currentEdgeName = currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last().Value; edgeAlias = string.Format("{0}_{1}_{2}", currentNodeExposedName, currentEdgeName, nextNodeExposedName); if (edgeColumnToAliasesDict.ContainsKey(currentEdgeName)) { edgeColumnToAliasesDict[currentEdgeName].Add(edgeAlias); } else { edgeColumnToAliasesDict.Add(currentEdgeName, new List<string> { edgeAlias }); } } Identifier edgeIdentifier = currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last(); string schema = patternNode.NodeTableObjectName.SchemaIdentifier.Value.ToLower(); string nodeTableName = patternNode.NodeTableObjectName.BaseIdentifier.Value; string bindTableName = _context.EdgeNodeBinding[ new Tuple<string, string>(nodeTableName.ToLower(), edgeIdentifier.Value.ToLower())].ToLower(); MatchEdge edge; if (currentEdgeColumnRef.MinLength == 1 && currentEdgeColumnRef.MaxLength == 1) { edge = new MatchEdge { SourceNode = patternNode, EdgeColumn = currentEdgeColumnRef, EdgeAlias = edgeAlias, BindNodeTableObjName = new WSchemaObjectName( new Identifier {Value = schema}, new Identifier {Value = bindTableName} ), }; _context.AddEdgeReference(edge); } else { MatchPath matchPath = new MatchPath { SourceNode = patternNode, EdgeColumn = currentEdgeColumnRef, EdgeAlias = edgeAlias, BindNodeTableObjName = new WSchemaObjectName( new Identifier {Value = schema}, new Identifier {Value = bindTableName} ), MinLength = currentEdgeColumnRef.MinLength, MaxLength = currentEdgeColumnRef.MaxLength, ReferencePathInfo = false, AttributeValueDict = currentEdgeColumnRef.AttributeValueDict }; _context.AddEdgeReference(matchPath); pathDictionary[edgeAlias] = matchPath; edge = matchPath; } if (preEdge != null) { preEdge.SinkNode = patternNode; } preEdge = edge; if (!parent.ContainsKey(currentNodeExposedName)) parent[currentNodeExposedName] = currentNodeExposedName; if (!parent.ContainsKey(nextNodeExposedName)) parent[nextNodeExposedName] = nextNodeExposedName; unionFind.Union(currentNodeExposedName, nextNodeExposedName); patternNode.Neighbors.Add(edge); } var tailExposedName = path.Tail.BaseIdentifier.Value; var tailNode = nodes.GetOrCreate(tailExposedName); if (tailNode.NodeAlias == null) { tailNode.NodeAlias = tailExposedName; tailNode.Neighbors = new List<MatchEdge>(); var nodeTable = _context[tailExposedName] as WNamedTableReference; if (nodeTable != null) { tailNode.NodeTableObjectName = nodeTable.TableObjectName; if (tailNode.NodeTableObjectName.SchemaIdentifier == null) tailNode.NodeTableObjectName.Identifiers.Insert(0, new Identifier {Value = "dbo"}); } } if (preEdge != null) preEdge.SinkNode = tailNode; } // Puts nodes into subgraphs foreach (var node in nodes) { string root = unionFind.Find(node.Key); if (!subGrpahMap.ContainsKey(root)) { var subGraph = new ConnectedComponent(); subGraph.Nodes[node.Key] = node.Value; foreach (var edge in node.Value.Neighbors) { subGraph.Edges[edge.EdgeAlias] = edge; } subGrpahMap[root] = subGraph; connectedSubGraphs.Add(subGraph); subGraph.IsTailNode[node.Value] = false; } else { var subGraph = subGrpahMap[root]; subGraph.Nodes[node.Key] = node.Value; foreach (var edge in node.Value.Neighbors) { subGraph.Edges[edge.EdgeAlias] = edge; } subGraph.IsTailNode[node.Value] = false; } } var graph = new MatchGraph { ConnectedSubGraphs = connectedSubGraphs, }; unionFind.Parent = null; // When an edge in the MATCH clause is not associated with an alias, // assigns to it a default alias: sourceAlias_EdgeColumnName_sinkAlias. // Also rewrites edge attributes anywhere in the query that can be bound to this default alias. var replaceTableRefVisitor = new ReplaceEdgeReferenceVisitor(); replaceTableRefVisitor.Invoke(query, edgeColumnToAliasesDict); // Rematerializes node tables in the MATCH clause which are defined in the upper-level context // and join them with the upper-level table references. RematerilizeExtrenalNodeTableReference(query, nodes); // Transforms the path reference in the SELECT elements into a // scalar function to display path information. TransformPathInfoDisplaySelectElement(query, pathDictionary); return graph; }
/// <summary> /// Construct Graph from the match clause. The Graph can consist of multiple connected SubGraph. /// Not supported in this version /// </summary> /// <param name="query"></param> /// <returns></returns> private MatchGraph ConstructGraph(WSelectQueryBlock query) { var unionFind = new UnionFind(); if (query.MatchClause == null) return null; var edgeTableReferenceDict = new Dictionary<string, List<string>>(StringComparer.CurrentCultureIgnoreCase); var matchClause = query.MatchClause; var nodes = new Dictionary<string, MatchNode>(StringComparer.CurrentCultureIgnoreCase); var connectedSubGraphs = new List<ConnectedComponent>(); var subGrpahMap = new Dictionary<string, ConnectedComponent>(StringComparer.CurrentCultureIgnoreCase); var parent = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase); unionFind.Parent = parent; HashSet<Tuple<string, string>> nodeTypes = new HashSet<Tuple<string, string>>(); //Construct Graph from Match Pattern foreach (var path in matchClause.Paths) { var index = 0; MatchEdge preEdge = null; for (var count = path.PathNodeList.Count; index < count; ++index) { var currentNode = path.PathNodeList[index].Item1; var currentEdge = path.PathNodeList[index].Item2; var currentNodeExposedName = currentNode.BaseIdentifier.Value; var nextNode = index != count - 1 ? path.PathNodeList[index + 1].Item1 : path.Tail; var nextNodeExposedName = nextNode.BaseIdentifier.Value; var node = nodes.GetOrCreate(currentNodeExposedName); if (node.NodeAlias == null) { node.NodeAlias = currentNodeExposedName; node.Neighbors = new List<MatchEdge>(); node.External = false; var nodeTable = _context[currentNodeExposedName] as WNamedTableReference; if (nodeTable != null) { node.TableObjectName = nodeTable.TableObjectName; if (node.TableObjectName.SchemaIdentifier == null) node.TableObjectName.Identifiers.Insert(0, new Identifier { Value = "dbo" }); var nodeTypeTuple = WNamedTableReference.SchemaNameToTuple(node.TableObjectName); if (!nodeTypes.Contains(nodeTypeTuple)) nodeTypes.Add(nodeTypeTuple); } } if (currentEdge.AliasRole == AliasType.Default) { var currentEdgeName = currentEdge.MultiPartIdentifier.Identifiers.Last().Value; if (edgeTableReferenceDict.ContainsKey(currentEdgeName)) { edgeTableReferenceDict[currentEdgeName].Add(currentEdge.Alias); } else { edgeTableReferenceDict.Add(currentEdgeName, new List<string> { currentEdge.Alias }); } } var edge = new MatchEdge { SourceNode = node, EdgeColumn = new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier { Identifiers = new List<Identifier> { new Identifier {Value = node.NodeAlias}, currentEdge.MultiPartIdentifier.Identifiers.Last() } } }, EdgeAlias = currentEdge.Alias }; if (preEdge != null) { preEdge.SinkNode = node; } preEdge = edge; if (!parent.ContainsKey(currentNodeExposedName)) parent[currentNodeExposedName] = currentNodeExposedName; if (!parent.ContainsKey(nextNodeExposedName)) parent[nextNodeExposedName] = nextNodeExposedName; unionFind.Union(currentNodeExposedName, nextNodeExposedName); node.Neighbors.Add(edge); _context.AddEdgeReference(currentEdge.Alias, edge.SourceNode.TableObjectName, currentEdge); } var tailExposedName = path.Tail.BaseIdentifier.Value; var tailNode = nodes.GetOrCreate(tailExposedName); if (tailNode.NodeAlias == null) { tailNode.NodeAlias = tailExposedName; tailNode.Neighbors = new List<MatchEdge>(); var nodeTable = _context[tailExposedName] as WNamedTableReference; if (nodeTable != null) { tailNode.TableObjectName = nodeTable.TableObjectName; if (tailNode.TableObjectName.SchemaIdentifier == null) tailNode.TableObjectName.Identifiers.Insert(0, new Identifier { Value = "dbo" }); var nodeTypeTuple = WNamedTableReference.SchemaNameToTuple(tailNode.TableObjectName); if (!nodeTypes.Contains(nodeTypeTuple)) nodeTypes.Add(nodeTypeTuple); } } if (preEdge != null) preEdge.SinkNode = tailNode; } // Put nodes into subgraphs foreach (var node in nodes) { string root = unionFind.Find(node.Key); if (!subGrpahMap.ContainsKey(root)) { var subGraph = new ConnectedComponent(); subGraph.Nodes[node.Key] = node.Value; foreach (var edge in node.Value.Neighbors) { subGraph.Edges[edge.EdgeAlias] = edge; } subGrpahMap[root] = subGraph; connectedSubGraphs.Add(subGraph); subGraph.IsTailNode[node.Value] = false; } else { var subGraph = subGrpahMap[root]; subGraph.Nodes[node.Key] = node.Value; foreach (var edge in node.Value.Neighbors) { subGraph.Edges[edge.EdgeAlias] = edge; } subGraph.IsTailNode[node.Value] = false; } } // Replace Edge name alias with proper alias in the query var replaceTableRefVisitor = new ReplaceTableRefVisitor(); replaceTableRefVisitor.Invoke(query, edgeTableReferenceDict); // If a table alias in the MATCH clause is defined in an upper-level context, // to be able to translate this MATCH clause, this table alias must be re-materialized // in the FROM clause of the current context and joined with the corresponding table // in the upper-level context. var tableRefs = query.FromClause.TableReferences; var tableSet = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase); var newTableRefs = new List<WTableReference>(); for (int index = 0; index < tableRefs.Count; ++index) { var table = tableRefs[index] as WNamedTableReference; if (table == null) { newTableRefs.Add(tableRefs[index]); continue; } var tableTuple = WNamedTableReference.SchemaNameToTuple(table.TableObjectName); if (!nodeTypes.Contains(tableTuple)) { newTableRefs.Add(table); } else { tableSet.Add(table.ExposedName.Value); } } query.FromClause = new WFromClause { TableReferences = newTableRefs, }; WBooleanExpression whereCondiction = null; foreach (var node in nodes) { if (!tableSet.Contains(node.Key)) { node.Value.External = true; var newWhereCondition = new WBooleanComparisonExpression { ComparisonType = BooleanComparisonType.Equals, FirstExpr = new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = node.Key }, new Identifier { Value = "GlobalNodeId" }) }, SecondExpr = new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = node.Value.RefAlias }, new Identifier { Value = "GlobalNodeId" }) }, }; whereCondiction = WBooleanBinaryExpression.Conjunction(whereCondiction, newWhereCondition); } } if (whereCondiction != null) { if (query.WhereClause == null) { query.WhereClause = new WWhereClause { SearchCondition = whereCondiction }; } else { if (query.WhereClause.SearchCondition == null) { query.WhereClause.SearchCondition = whereCondiction; } else { query.WhereClause.SearchCondition = new WBooleanBinaryExpression { BooleanExpressionType = BooleanBinaryExpressionType.And, FirstExpr = new WBooleanParenthesisExpression { Expression = query.WhereClause.SearchCondition }, SecondExpr = new WBooleanParenthesisExpression { Expression = whereCondiction } }; } } } var graph = new MatchGraph { ConnectedSubGraphs = connectedSubGraphs, NodeTypesSet = nodeTypes, }; unionFind.Parent = null; return graph; }
public SegmentMesh(ColorTemplate template) { int numGroups = template.NumSlots(); imageWidth = template.Width(); imageHeight = template.Height(); groups = new List<SegmentGroup>(); segments = new List<Segment>(); //now populate the segments and segment groups //filter out groups that have no members (due to quantization) Dictionary<int, int> slotToGroup = new Dictionary<int, int>(); for (int i = 0; i < numGroups; i++) { if (template.PixelsInSlot(i) > 0) { slotToGroup.Add(i, groups.Count()); groups.Add(new SegmentGroup(template.OriginalSlotColor(i))); } } UnionFind<Color> uf = new UnionFind<Color>((a, b) => (a.GetHashCode() == b.GetHashCode())); Bitmap image = template.DebugQuantization(); assignments = uf.ConnectedComponentsNoiseRemoval(Util.BitmapToArray(image)); Dictionary<int, Segment> idToSegment = new Dictionary<int, Segment>(); int totalAdjacencyPerimeter = 0; Dictionary<int, HashSet<Point>> idToPerimeter = new Dictionary<int, HashSet<Point>>(); //populate segments int width = image.Width; int height = image.Height; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { int id = assignments[i, j]; if (!idToSegment.ContainsKey(id)) { idToSegment.Add(id, new Segment(id)); idToPerimeter.Add(id, new HashSet<Point>()); } idToSegment[id].points.Add(new Point(i, j)); idToSegment[id].groupId = slotToGroup[template.GetSlotId(i, j)]; //look for 8-neighbor adjacencies, 2 pixels away //TODO: measure adjacency strength and filter? for (int dx = -2; dx <= 2; dx++) { for (int dy = -2; dy <= 2; dy++) { int x = i + dx; int y = j + dy; if (x >= 0 && x < width && y >= 0 && y < height) { int nid = assignments[x, y]; if (nid != id) { idToSegment[id].adjacencies.Add(nid); //keep track of the total perimeter, and individual segment perimeters //don't double count the same point for each segment if (!idToPerimeter[id].Contains(new Point(x, y))) { idToPerimeter[id].Add(new Point(x, y)); totalAdjacencyPerimeter++; //keep track of the adjacecy strength per segment if (!idToSegment[id].adjacencyStrength.ContainsKey(nid)) idToSegment[id].adjacencyStrength.Add(nid, 0); idToSegment[id].adjacencyStrength[nid]++; } else { Console.WriteLine("Point already counted"); } } } else { //might as well be consistent here, and take into account the borders of the image when determining //enclosure. We don't need to do this for the totalAdjacencyPerimeter, because that is just a normalization //for the adjacency strengths of segments within the image if (!idToPerimeter[id].Contains(new Point(x,y))) { idToPerimeter[id].Add(new Point(x,y)); } } } } } } //finalize segment list and adjacency list Dictionary<int, int> idToIdx = new Dictionary<int, int>(); foreach (int id in idToSegment.Keys) { segments.Add(idToSegment[id]); idToIdx.Add(id, segments.Count() - 1); } //finalize adjacencies for (int i = 0; i < segments.Count(); i++) { SortedSet<int> renamedAdj = new SortedSet<int>(); foreach (int a in segments[i].adjacencies) renamedAdj.Add(idToIdx[a]); segments[i].adjacencies = renamedAdj; //finalize adjacency strengths int sid = assignments[segments[i].points.First().X, segments[i].points.First().Y]; Dictionary<int, double> renamedAdjStrength = new Dictionary<int, double>(); foreach (int nid in segments[i].adjacencyStrength.Keys) { double pixelsAdj = segments[i].adjacencyStrength[nid]; renamedAdjStrength.Add(idToIdx[nid], pixelsAdj / totalAdjacencyPerimeter); segments[i].enclosureStrength.Add(idToIdx[nid], new Tuple<double, double>(pixelsAdj / idToPerimeter[sid].Count(), pixelsAdj / idToPerimeter[nid].Count())); } segments[i].adjacencyStrength = renamedAdjStrength; } //finalize groups for (int i = 0; i < segments.Count(); i++) { int groupId = segments[i].groupId; groups[groupId].members.Add(i); } //finalize segment list ClassifySegments(); foreach (Segment s in segments) { ComputeFeatures(s); } foreach (SegmentGroup g in groups) { ComputeFeatures(g); } }
/// <summary> /// Play the given workload in a polling manner and store the results in the given file /// </summary> /// <param name="workload">The workload</param> /// <param name="employees">The amount of employees generated for the workload</param> /// <param name="path">The path for the results</param> /// <returns>The measurement results</returns> private static Results PlayWorkloadClassic(List<WorkloadAction> workload, int employees, string path) { var sb = new StringBuilder(); watch.Restart(); var employeesList = new List<Employee>(employees); sb.AppendLine("Initializing graph"); Console.WriteLine("Running workload on classic interface"); for (int i = 0; i < employees; i++) { workload[i].Perform(employeesList, sb); } watch.Stop(); var initTime = watch.ElapsedMilliseconds; var first = employeesList[0]; var second = employeesList[1]; sb.AppendFormat("Will query whether {0} and {1} are connected", first.Name, second.Name); sb.AppendLine(); ScenarioGenerator.Evaluation = () => { var analysis = new UnionFind<Employee>(e => e.Knows, employeesList); return analysis.AreConnected(first, second).ToString(); }; watch.Restart(); for (int i = employees; i < workload.Count; i++) { workload[i].Perform(employeesList, sb); } watch.Stop(); var main = watch.ElapsedMilliseconds; File.WriteAllText(path, sb.ToString()); Console.WriteLine("Completed. Polling took {0}ms", watch.ElapsedMilliseconds); //var memory = MemoryMeter.ComputeMemoryConsumption(pollQuery); return new Results() { Initialization = initTime, MainWorkload = main }; }
private void inputImageBox_MouseDown(object sender, MouseEventArgs e) { if (this.data == null) return; int xx = e.X - (inputImageBox.Width - inputImageBox.Image.Width) / 2; int yy = e.Y - (inputImageBox.Height - inputImageBox.Image.Height) / 2; switch (currentStep) { case 5: // Compactness decimal r = (decimal)Operations.Compactness(this.prevData, xx, yy); decimal rLow = Math.Floor(r * 100) / 100; decimal rHigh = Math.Ceiling(r * 100) / 100; minComp.Value = Math.Min(minComp.Value, rLow); maxComp.Value = Math.Max(maxComp.Value, rHigh); break; case 6: // Area decimal a = (decimal)Operations.Area(Operations.Perimeter(this.prevData, xx, yy)); decimal aLow = Math.Floor(a * 100) / 100; decimal aHigh = Math.Ceiling(a * 100) / 100; minArea.Value = Math.Min(minArea.Value, aLow); maxArea.Value = Math.Max(maxArea.Value, aHigh); break; case 7: // Convexity UnionFind<Tuple<int, int>> unionFind = new UnionFind<Tuple<int, int>>(); for (int x = 0; x < this.prevData.GetLength(0); x++) for (int y = 0; y < this.prevData.GetLength(1); y++) { if (this.prevData[x, y] == 0) continue; Tuple<int, int> xy = new Tuple<int, int>(x, y); unionFind.Make(xy); if (x > 0) unionFind.Union(xy, new Tuple<int, int>(x - 1, y)); if (y > 0) unionFind.Union(xy, new Tuple<int, int>(x, y - 1)); } Tuple<int, int> root; try { root = unionFind.Find(new Tuple<int, int>(xx, yy)); } catch { return; } List<Tuple<int, int>> points = new List<Tuple<int, int>>(); for (int x = 0; x < this.prevData.GetLength(0); x++) { for (int y = 0; y < this.prevData.GetLength(1); y++) { if (this.prevData[x, y] == 0) continue; Tuple<int, int> pos = new Tuple<int, int>(x, y); if (unionFind.Find(pos) == root) points.Add(pos); } } double hullArea = Operations.PolygonArea(Operations.ConvexHull(points)); double area = Operations.Area(Operations.Perimeter(this.prevData, xx, yy)); decimal c = (decimal) (area / hullArea); decimal cLow = Math.Floor(c * 100) / 100; decimal cHigh = Math.Ceiling(c * 100) / 100; minConv.Value = Math.Min(minConv.Value, cLow); maxConv.Value = Math.Max(maxConv.Value, cHigh); break; default: break; } }
/// <summary> /// Constructs the graph pattern specified by the MATCH clause. /// The graph pattern may consist of multiple fully-connected sub-graphs. /// </summary> /// <param name="query">The SELECT query block</param> /// <returns>A graph object contains all the connected componeents</returns> private MatchGraph ConstructGraph(WSelectQueryBlock query) { if (query == null || query.MatchClause == null) return null; var columnsOfNodeTables = _graphMetaData.ColumnsOfNodeTables; var nodeViewMapping = _graphMetaData.NodeViewMapping; var unionFind = new UnionFind(); var edgeColumnToAliasesDict = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase); var pathDictionary = new Dictionary<string, MatchPath>(StringComparer.OrdinalIgnoreCase); var reversedEdgeDict = new Dictionary<string, MatchEdge>(); var matchClause = query.MatchClause; var nodes = new Dictionary<string, MatchNode>(StringComparer.OrdinalIgnoreCase); var connectedSubGraphs = new List<ConnectedComponent>(); var subGrpahMap = new Dictionary<string, ConnectedComponent>(StringComparer.OrdinalIgnoreCase); var parent = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); unionFind.Parent = parent; // Constructs the graph pattern specified by the path expressions in the MATCH clause foreach (var path in matchClause.Paths) { var index = 0; MatchEdge preEdge = null; for (var count = path.PathEdgeList.Count; index < count; ++index) { var currentNodeTableRef = path.PathEdgeList[index].Item1; var currentEdgeColumnRef = path.PathEdgeList[index].Item2; var currentNodeExposedName = currentNodeTableRef.BaseIdentifier.Value; var nextNodeTableRef = index != count - 1 ? path.PathEdgeList[index + 1].Item1 : path.Tail; var nextNodeExposedName = nextNodeTableRef.BaseIdentifier.Value; var patternNode = nodes.GetOrCreate(currentNodeExposedName); if (patternNode.NodeAlias == null) { patternNode.NodeAlias = currentNodeExposedName; patternNode.Neighbors = new List<MatchEdge>(); patternNode.External = false; var nodeTable = _context[currentNodeExposedName] as WNamedTableReference; if (nodeTable != null) { patternNode.NodeTableObjectName = nodeTable.TableObjectName; if (patternNode.NodeTableObjectName.SchemaIdentifier == null) patternNode.NodeTableObjectName.Identifiers.Insert(0, new Identifier {Value = "dbo"}); } } Identifier edgeIdentifier = currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last(); string schema = patternNode.NodeTableObjectName.SchemaIdentifier.Value.ToLower(); string nodeTableName = patternNode.NodeTableObjectName.BaseIdentifier.Value; string bindTableName = _context.EdgeNodeBinding[ new Tuple<string, string>(nodeTableName.ToLower(), edgeIdentifier.Value.ToLower())].ToLower(); var bindNodeTableObjName = new WSchemaObjectName( new Identifier {Value = schema}, new Identifier {Value = bindTableName} ); var edgeColumn = columnsOfNodeTables[ WNamedTableReference.SchemaNameToTuple(bindNodeTableObjName)][ currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last().Value]; string edgeAlias = currentEdgeColumnRef.Alias; //string revEdgeAlias = edgeAlias; bool isReversed = path.IsReversed || edgeColumn.EdgeInfo.IsReversedEdge; string currentRevEdgeName = null; // get original edge name var currentEdgeName = currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last().Value; var originalSourceName = isReversed ? (_context[nextNodeExposedName] as WNamedTableReference).TableObjectName.BaseIdentifier.Value : (_context[currentNodeExposedName] as WNamedTableReference).TableObjectName.BaseIdentifier.Value; if (isReversed) { var i = currentEdgeName.IndexOf(originalSourceName, StringComparison.OrdinalIgnoreCase) + originalSourceName.Length; currentRevEdgeName = currentEdgeName.Substring(i + 1, currentEdgeName.Length - "Reversed".Length - i - 1); } else { var srcTuple = WNamedTableReference.SchemaNameToTuple(patternNode.NodeTableObjectName); // [nodeView]-[edge]->[node/nodeView] if (edgeColumn.Role == WNodeTableColumnRole.Edge && nodeViewMapping.ContainsKey(srcTuple)) { var physicalNodeName = _context.EdgeNodeBinding[new Tuple<string, string>(srcTuple.Item2, currentEdgeName.ToLower())]; currentRevEdgeName = physicalNodeName + "_" + currentEdgeName + "Reversed"; } else { currentRevEdgeName = originalSourceName + "_" + currentEdgeName + "Reversed"; } } if (edgeAlias == null) { edgeAlias = !isReversed ? string.Format("{0}_{1}_{2}", currentNodeExposedName, currentEdgeName, nextNodeExposedName) : string.Format("{0}_{1}_{2}", nextNodeExposedName, currentRevEdgeName, currentNodeExposedName); //when the current edge is a reversed edge, the key should still be the original edge name //e.g.: TestDeleteEdgeWithTableAlias var edgeNameKey = isReversed ? currentRevEdgeName : currentEdgeName; if (edgeColumnToAliasesDict.ContainsKey(edgeNameKey)) { edgeColumnToAliasesDict[edgeNameKey].Add(edgeAlias); } else { edgeColumnToAliasesDict.Add(edgeNameKey, new List<string> { edgeAlias }); } } MatchEdge edge, revEdge; if (currentEdgeColumnRef.MinLength == 1 && currentEdgeColumnRef.MaxLength == 1) { var isEdgeView = edgeColumn.Role == WNodeTableColumnRole.EdgeView; var hasRevEdge = edgeColumn.EdgeInfo.HasReversedEdge; edge = new MatchEdge { IsEdgeView = isEdgeView, IsReversedEdge = false, HasReversedEdge = hasRevEdge, SourceNode = patternNode, EdgeColumn = currentEdgeColumnRef, EdgeAlias = edgeAlias, BindNodeTableObjName = bindNodeTableObjName, }; _context.AddEdgeReference(edge); if (hasRevEdge) { revEdge = new MatchEdge { IsEdgeView = isEdgeView, IsReversedEdge = true, SinkNode = patternNode, EdgeColumn = new WEdgeColumnReferenceExpression() { ColumnType = currentEdgeColumnRef.ColumnType, Alias = currentEdgeColumnRef.Alias, MaxLength = currentEdgeColumnRef.MaxLength, MinLength = currentEdgeColumnRef.MinLength, AttributeValueDict = currentEdgeColumnRef.AttributeValueDict, MultiPartIdentifier = new WMultiPartIdentifier(new Identifier() { QuoteType = currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last().QuoteType, Value = currentRevEdgeName, }), }, EdgeAlias = edgeAlias, //EdgeAlias = revEdgeAlias, }; reversedEdgeDict[edge.EdgeAlias] = revEdge; } } else { MatchPath matchPath = new MatchPath { SourceNode = patternNode, EdgeColumn = currentEdgeColumnRef, EdgeAlias = edgeAlias, BindNodeTableObjName = new WSchemaObjectName( new Identifier {Value = schema}, new Identifier {Value = bindTableName} ), MinLength = currentEdgeColumnRef.MinLength, MaxLength = currentEdgeColumnRef.MaxLength, ReferencePathInfo = false, AttributeValueDict = currentEdgeColumnRef.AttributeValueDict }; _context.AddEdgeReference(matchPath); pathDictionary[edgeAlias] = matchPath; edge = matchPath; } if (preEdge != null) { preEdge.SinkNode = patternNode; if (preEdge.HasReversedEdge) { //var preSourceNode = preEdge.SourceNode; var preEdgeBindNodeTableObjName = preEdge.BindNodeTableObjName; var preEdgeColName = preEdge.EdgeColumn.MultiPartIdentifier.Identifiers.Last().Value; var preEdgeColumn = columnsOfNodeTables[ WNamedTableReference.SchemaNameToTuple(preEdgeBindNodeTableObjName)][ preEdgeColName]; var isEdgeView = preEdgeColumn.Role == WNodeTableColumnRole.EdgeView; var isNodeView = _graphMetaData.NodeViewMapping.ContainsKey( WNamedTableReference.SchemaNameToTuple(patternNode.NodeTableObjectName)); reversedEdgeDict[preEdge.EdgeAlias].SourceNode = patternNode; // [node/nodeView]-[edgeView]->[node/nodeView] if (isEdgeView) { reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = preEdgeBindNodeTableObjName; } // [node/nodeView]-[edge]->[nodeView] else if (!isEdgeView && isNodeView) { reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = new WSchemaObjectName( new Identifier { Value = "dbo" }, new Identifier { Value = preEdgeColumn.EdgeInfo.SinkNodes.First() } ); } else { reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = new WSchemaObjectName( new Identifier { Value = schema }, new Identifier { Value = bindTableName } ); } } } preEdge = edge; if (!parent.ContainsKey(currentNodeExposedName)) parent[currentNodeExposedName] = currentNodeExposedName; if (!parent.ContainsKey(nextNodeExposedName)) parent[nextNodeExposedName] = nextNodeExposedName; unionFind.Union(currentNodeExposedName, nextNodeExposedName); patternNode.Neighbors.Add(edge); } var tailExposedName = path.Tail.BaseIdentifier.Value; var tailNode = nodes.GetOrCreate(tailExposedName); if (tailNode.NodeAlias == null) { tailNode.NodeAlias = tailExposedName; tailNode.Neighbors = new List<MatchEdge>(); var nodeTable = _context[tailExposedName] as WNamedTableReference; if (nodeTable != null) { tailNode.NodeTableObjectName = nodeTable.TableObjectName; if (tailNode.NodeTableObjectName.SchemaIdentifier == null) tailNode.NodeTableObjectName.Identifiers.Insert(0, new Identifier {Value = "dbo"}); } } if (preEdge != null) { preEdge.SinkNode = tailNode; if (preEdge.HasReversedEdge) { var schema = tailNode.NodeTableObjectName.SchemaIdentifier.Value.ToLower(); var nodeTableName = tailNode.NodeTableObjectName.BaseIdentifier.Value; //var preSourceNode = preEdge.SourceNode; var preEdgeBindNodeTableObjName = preEdge.BindNodeTableObjName; var preEdgeColName = preEdge.EdgeColumn.MultiPartIdentifier.Identifiers.Last().Value; var preEdgeColumn = columnsOfNodeTables[ WNamedTableReference.SchemaNameToTuple(preEdgeBindNodeTableObjName)][ preEdgeColName]; var isEdgeView = preEdgeColumn.Role == WNodeTableColumnRole.EdgeView; var isNodeView = _graphMetaData.NodeViewMapping.ContainsKey( WNamedTableReference.SchemaNameToTuple(tailNode.NodeTableObjectName)); reversedEdgeDict[preEdge.EdgeAlias].SourceNode = tailNode; // [node/nodeView]-[edgeView]->[node/nodeView] if (isEdgeView) { reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = preEdgeBindNodeTableObjName; } // [node/nodeView]-[edge]->[nodeView] else if (!isEdgeView && isNodeView) { reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = new WSchemaObjectName( new Identifier { Value = "dbo" }, new Identifier { Value = preEdgeColumn.EdgeInfo.SinkNodes.First() } ); } else { reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = new WSchemaObjectName( new Identifier { Value = schema }, new Identifier { Value = nodeTableName.ToLower() } ); } } } } // Puts nodes into subgraphs foreach (var node in nodes) { string root = unionFind.Find(node.Key); if (!subGrpahMap.ContainsKey(root)) { var subGraph = new ConnectedComponent(); subGraph.Nodes[node.Key] = node.Value; foreach (var edge in node.Value.Neighbors) { subGraph.Edges[edge.EdgeAlias] = edge; } subGrpahMap[root] = subGraph; connectedSubGraphs.Add(subGraph); subGraph.IsTailNode[node.Value] = false; } else { var subGraph = subGrpahMap[root]; subGraph.Nodes[node.Key] = node.Value; foreach (var edge in node.Value.Neighbors) { subGraph.Edges[edge.EdgeAlias] = edge; } subGraph.IsTailNode[node.Value] = false; } } var graph = new MatchGraph { ReversedEdgeDict = reversedEdgeDict, ConnectedSubGraphs = connectedSubGraphs, SourceNodeStatisticsDict = new Dictionary<Tuple<string, bool>, Statistics>(), }; unionFind.Parent = null; // When an edge in the MATCH clause is not associated with an alias, // assigns to it a default alias: sourceAlias_EdgeColumnName_sinkAlias. // Also rewrites edge attributes anywhere in the query that can be bound to this default alias. var replaceTableRefVisitor = new ReplaceEdgeReferenceVisitor(); replaceTableRefVisitor.Invoke(query, edgeColumnToAliasesDict); // Rematerializes node tables in the MATCH clause which are defined in the upper-level context // and join them with the upper-level table references. RematerilizeExtrenalNodeTableReference(query, nodes); // Transforms the path reference in the SELECT elements into a // scalar function to display path information. TransformPathInfoDisplaySelectElement(query, pathDictionary); return graph; }
public bool RunTest() { string[] elements = new string[10] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" }; UnionFind<string> unionFind = new UnionFind<string>(); bool success = true; // Add in entries for (int i = 0; i < 10; i++) { unionFind.AddElement(elements[i]); } // Verify that the roots are setup correctly for (int i = 0; i < 10; i++) { success &= unionFind.GetElement(i).Equals(elements[i]); Debug.Assert(success); success &= unionFind.FindRootIndex(i) == i; Debug.Assert(success); success &= unionFind.FindRootIndex(elements[i]) == i; Debug.Assert(success); } // Verify that no one is initially connected to anyone else for (int i = 1; i < 10; i++) { success &= !unionFind.AreElementsConnected(i - 1, i); Debug.Assert(success); success &= !unionFind.AreElementsConnected(elements[i - 1], elements[i]); Debug.Assert(success); } // Union the first half of the nodes together for (int i = 1; i < 5; i++) { unionFind.Union(elements[i - 1], elements[i]); } // Union the last half of the nodes together for (int i = 6; i < 10; i++) { unionFind.Union(elements[i - 1], elements[i]); } // Verify that every element in the first half is connected // to every other element in the first half for (int i = 0; i < 5; i++) { for (int j = i + 1; j < 5; j++) { success &= unionFind.AreElementsConnected(i, j); Debug.Assert(success); success &= unionFind.AreElementsConnected(elements[i], elements[j]); Debug.Assert(success); } } // Verify that every element in the second half is connected // to every other element in the second half for (int i = 5; i < 10; i++) { for (int j = i + 1; j < 10; j++) { success &= unionFind.AreElementsConnected(i, j); Debug.Assert(success); success &= unionFind.AreElementsConnected(elements[i], elements[j]); Debug.Assert(success); } } // Verify that no element in the first half is connected // to any other element in the second half for (int i = 0; i < 5; i++) { for (int j = i + 5; j < 10; j++) { success &= !unionFind.AreElementsConnected(i, j); Debug.Assert(success); success &= !unionFind.AreElementsConnected(elements[i], elements[j]); Debug.Assert(success); } } return success; }