/// <summary> /// Disconnects the two groups. /// </summary> /// <remarks> /// This method assumes that two groups will only be connected via one import - export relation. This /// method will remove all connections from the exporting group to the importing group. /// </remarks> /// <param name="importingGroup">The ID of the group that owns the import.</param> /// <param name="exportingGroup">The ID of the group that owns the export.</param> /// <returns>A task which indicates when the disconnection has taken place.</returns> public Task Disconnect(GroupCompositionId importingGroup, GroupCompositionId exportingGroup) { { Debug.Assert(importingGroup != null, "The ID of the importing group should not be a null reference."); Debug.Assert(exportingGroup != null, "The ID of the exporting group should not be a null reference."); } m_Diagnostics.Log( LevelToLog.Trace, HostConstants.LogPrefix, string.Format( CultureInfo.InvariantCulture, Resources.ProxyCompositionLayer_LogMessage_DisconnectingGroups_WithImportAndExport, importingGroup, exportingGroup)); var remoteTask = m_Commands.Disconnect(importingGroup, exportingGroup); return(remoteTask.ContinueWith( t => { m_GroupConnections.RemoveInEdgeIf(importingGroup, edge => edge.Source.Equals(exportingGroup)); })); }
public void removeEdgeIfTest() { var graph = new BidirectionalGraph <int, IEdge <int> >(); graph.AddVertex(1); graph.AddVertex(2); graph.AddVertex(3); graph.AddEdge(new EquatableEdge <int>(1, 2)); graph.AddEdge(new EquatableEdge <int>(2, 3)); graph.AddEdge(new EquatableEdge <int>(2, 1)); graph.RemoveOutEdgeIf(2, (edge) => edge.Target == 1); Assert.IsTrue(graph.ContainsEdge(1, 2)); Assert.IsFalse(graph.ContainsEdge(2, 1)); Assert.IsTrue(graph.ContainsEdge(2, 3)); graph.RemoveInEdgeIf(2, (edge) => edge.Source == 1); Assert.IsTrue(graph.ContainsEdge(2, 3)); Assert.IsFalse(graph.ContainsEdge(1, 2)); }
public IBidirectionalGraph <Cluster <T>, ClusterEdge <T> > GenerateClusters(IEnumerable <T> dataObjects) { var tree = new BidirectionalGraph <Cluster <T>, ClusterEdge <T> >(false); var clusters = new List <Cluster <T> >(); foreach (T dataObject in dataObjects) { var cluster = new Cluster <T>(dataObject) { Description = dataObject.ToString() }; clusters.Add(cluster); tree.AddVertex(cluster); } var distances = new Dictionary <UnorderedTuple <Cluster <T>, Cluster <T> >, double>(); var heights = new Dictionary <Cluster <T>, double>(); for (int i = 0; i < clusters.Count; i++) { for (int j = i + 1; j < clusters.Count; j++) { double distance = _getDistance(clusters[i].DataObjects.First(), clusters[j].DataObjects.First()); if (double.IsNaN(distance) || double.IsInfinity(distance) || distance < 0) { throw new ArgumentException("Invalid distance between data objects.", "dataObjects"); } distances[UnorderedTuple.Create(clusters[i], clusters[j])] = distance; } heights[clusters[i]] = 0; } while (clusters.Count >= 2) { int minI = 0, minJ = 0; double minDist = double.MaxValue; for (int i = 0; i < clusters.Count; i++) { for (int j = i + 1; j < clusters.Count; j++) { double dist = distances[UnorderedTuple.Create(clusters[i], clusters[j])]; if (dist < minDist) { minDist = dist; minI = i; minJ = j; } } } Cluster <T> iCluster = clusters[minI]; Cluster <T> jCluster = clusters[minJ]; distances.Remove(UnorderedTuple.Create(iCluster, jCluster)); var uCluster = new Cluster <T>(); tree.AddVertex(uCluster); double height = minDist / 2; heights[uCluster] = height; int iCount = tree.GetAllDataObjects(iCluster).Count(); double iLen = height - heights[iCluster]; if (iLen <= 0 && !tree.IsOutEdgesEmpty(iCluster)) { foreach (ClusterEdge <T> edge in tree.OutEdges(iCluster)) { tree.AddEdge(new ClusterEdge <T>(uCluster, edge.Target, edge.Length)); } tree.RemoveVertex(iCluster); } else { tree.RemoveInEdgeIf(iCluster, edge => true); tree.AddEdge(new ClusterEdge <T>(uCluster, iCluster, Math.Max(iLen, 0))); } int jCount = tree.GetAllDataObjects(jCluster).Count(); double jLen = height - heights[jCluster]; if (jLen <= 0 && !tree.IsOutEdgesEmpty(jCluster)) { foreach (ClusterEdge <T> edge in tree.OutEdges(jCluster)) { tree.AddEdge(new ClusterEdge <T>(uCluster, edge.Target, edge.Length)); } tree.RemoveVertex(jCluster); } else { tree.RemoveInEdgeIf(jCluster, edge => true); tree.AddEdge(new ClusterEdge <T>(uCluster, jCluster, Math.Max(jLen, 0))); } double iWeight = (double)iCount / (iCount + jCount); double jWeight = (double)jCount / (iCount + jCount); foreach (Cluster <T> kCluster in clusters.Where(c => c != iCluster && c != jCluster)) { UnorderedTuple <Cluster <T>, Cluster <T> > kiKey = UnorderedTuple.Create(kCluster, iCluster); UnorderedTuple <Cluster <T>, Cluster <T> > kjKey = UnorderedTuple.Create(kCluster, jCluster); distances[UnorderedTuple.Create(uCluster, kCluster)] = (iWeight * distances[kiKey]) + (jWeight * distances[kjKey]); distances.Remove(kiKey); distances.Remove(kjKey); } clusters.RemoveAt(minJ); clusters.RemoveAt(minI); clusters.Add(uCluster); } return(tree); }
public IUndirectedGraph <Cluster <T>, ClusterEdge <T> > GenerateClusters(IEnumerable <T> dataObjects) { var tree = new BidirectionalGraph <Cluster <T>, ClusterEdge <T> >(false); var clusters = new List <Cluster <T> >(); foreach (T dataObject in dataObjects) { var cluster = new Cluster <T>(dataObject) { Description = dataObject.ToString() }; clusters.Add(cluster); tree.AddVertex(cluster); } var distances = new Dictionary <UnorderedTuple <Cluster <T>, Cluster <T> >, double>(); for (int i = 0; i < clusters.Count; i++) { for (int j = i + 1; j < clusters.Count; j++) { double distance = _getDistance(clusters[i].DataObjects.First(), clusters[j].DataObjects.First()); if (double.IsNaN(distance) || double.IsInfinity(distance) || distance < 0) { throw new ArgumentException("Invalid distance between data objects.", "dataObjects"); } distances[UnorderedTuple.Create(clusters[i], clusters[j])] = distance; } } while (clusters.Count > 2) { Dictionary <Cluster <T>, double> r = clusters.ToDictionary(c => c, c => clusters.Where(oc => oc != c).Sum(oc => distances[UnorderedTuple.Create(c, oc)] / (clusters.Count - 2))); int minI = 0, minJ = 0; double minDist = 0, minQ = double.MaxValue; for (int i = 0; i < clusters.Count; i++) { for (int j = i + 1; j < clusters.Count; j++) { double dist = distances[UnorderedTuple.Create(clusters[i], clusters[j])]; double q = dist - r[clusters[i]] - r[clusters[j]]; if (q < minQ) { minQ = q; minDist = dist; minI = i; minJ = j; } } } Cluster <T> iCluster = clusters[minI]; Cluster <T> jCluster = clusters[minJ]; distances.Remove(UnorderedTuple.Create(iCluster, jCluster)); var uCluster = new Cluster <T>(); tree.AddVertex(uCluster); double iLen = (minDist / 2) + ((r[iCluster] - r[jCluster]) / 2); if (iLen <= 0 && !tree.IsOutEdgesEmpty(iCluster)) { foreach (ClusterEdge <T> edge in tree.OutEdges(iCluster)) { tree.AddEdge(new ClusterEdge <T>(uCluster, edge.Target, edge.Length)); } tree.RemoveVertex(iCluster); } else { tree.RemoveInEdgeIf(iCluster, edge => true); tree.AddEdge(new ClusterEdge <T>(uCluster, iCluster, Math.Max(iLen, 0))); } double jLen = minDist - iLen; if (jLen <= 0 && !tree.IsOutEdgesEmpty(jCluster)) { foreach (ClusterEdge <T> edge in tree.OutEdges(jCluster)) { tree.AddEdge(new ClusterEdge <T>(uCluster, edge.Target, edge.Length)); } tree.RemoveVertex(jCluster); } else { tree.RemoveInEdgeIf(jCluster, edge => true); tree.AddEdge(new ClusterEdge <T>(uCluster, jCluster, Math.Max(jLen, 0))); } foreach (Cluster <T> kCluster in clusters.Where(c => c != iCluster && c != jCluster)) { UnorderedTuple <Cluster <T>, Cluster <T> > kiKey = UnorderedTuple.Create(kCluster, iCluster); UnorderedTuple <Cluster <T>, Cluster <T> > kjKey = UnorderedTuple.Create(kCluster, jCluster); distances[UnorderedTuple.Create(kCluster, uCluster)] = (distances[kiKey] + distances[kjKey] - minDist) / 2; distances.Remove(kiKey); distances.Remove(kjKey); } clusters.RemoveAt(minJ); clusters.RemoveAt(minI); clusters.Add(uCluster); } if (clusters.Count == 2) { tree.AddEdge(new ClusterEdge <T>(clusters[1], clusters[0], distances[UnorderedTuple.Create(clusters[0], clusters[1])])); clusters.RemoveAt(0); } var unrootedTree = new UndirectedGraph <Cluster <T>, ClusterEdge <T> >(false); unrootedTree.AddVertexRange(tree.Vertices); unrootedTree.AddEdgeRange(tree.Edges); return(unrootedTree); }