public Vertex MergeVertices(int id1, int id2) { var v1 = Vertices.SingleOrDefault(e => e.Id == id1); var v2 = Vertices.SingleOrDefault(e => e.Id == id2); if (v1 == null) { throw new Exception($"Vertex '{id1}' not found"); } if (v2 == null) { throw new Exception($"Vertex '{id2}' not found"); } int maxId = Vertices.Select(e => e.Id).Max(); var merged = new Vertex(maxId + 1); // add all neighbors foreach (var neighbor in v1.Neighbors.ToList()) { merged.AddNeighborBiDirection(neighbor); } foreach (var neighbor in v2.Neighbors.ToList()) { merged.AddNeighborBiDirection(neighbor); } // remove old neighbor references from graph foreach (var neighbor in v1.Neighbors.ToList()) { v1.RemoveNeighborBiDirection(neighbor); } foreach (var neighbor in v2.Neighbors.ToList()) { v2.RemoveNeighborBiDirection(neighbor); } merged.IdsBeforeMerge.AddRange(v1.IdsBeforeMerge); merged.IdsBeforeMerge.AddRange(v2.IdsBeforeMerge); Vertices.Remove(v1); Vertices.Remove(v2); Vertices.Add(merged); return(merged); }
/// <summary> /// Generate graph by Holme & Kim model /// </summary> /// <param name="n">Number of vertices</param> /// <param name="m0">Number of fundamental nodes</param> /// <param name="m">Number of edges for new created vertices</param> /// <para name="p">Probability of making a triad formation</para> /// <returns></returns> public Graph GenerateHolmeKimModel(int n, int m0, int m, double p) { var vertices = Enumerable.Range(0, m0).Select(id => new Vertex(id)).ToList(); // create base graph (complete graph) for (int i = 0; i < m0; i++) { for (int j = 0; j < m0; j++) { if (i == j) { continue; } vertices[i].AddNeighborBiDirection(vertices[j]); } } var vertexDegreeDistribution = new List <int>(); foreach (var vertex in vertices) { for (int i = 0; i < vertex.Degree; i++) { vertexDegreeDistribution.Add(vertex.Id); } } // add new nodes for (int i = m0; i < n; i++) { var vertex = new Vertex(m0 + i + 1); var usedNodeIds = new List <int>(); Vertex newNeighbor = null; for (int j = 0; j < m; j++) { if (j == 0 || p < _random.NextDouble()) { int randomIndex = _random.Next(vertexDegreeDistribution.Count - 1); while (usedNodeIds.Contains(vertexDegreeDistribution[randomIndex])) { randomIndex = _random.Next(vertexDegreeDistribution.Count - 1); } newNeighbor = vertices.Single(e => e.Id == vertexDegreeDistribution[randomIndex]); bool isAdded = newNeighbor.AddNeighborBiDirection(vertex); usedNodeIds.Add(vertexDegreeDistribution[randomIndex]); } else { if (newNeighbor == null) { throw new Exception(); } var possibleNeighborsToAdd = newNeighbor.Neighbors.Except(new[] { vertex }).ToList(); var otherNeighbor = possibleNeighborsToAdd[_random.Next(possibleNeighborsToAdd.Count)]; vertex.AddNeighborBiDirection(otherNeighbor); } } for (int j = 0; j < m; j++) { vertexDegreeDistribution.Add(vertex.Id); vertexDegreeDistribution.Add(vertex.Neighbors[j].Id); } vertices.Add(vertex); } return(new Graph(vertices)); }