private static void SolveWithHeuristic(WeightedGraph graph) { int currentAnswerWeight = 0; int candidateWeight = 0; List <int> answer = new List <int> (); _stopwatch.Start(); foreach (int v in graph.Vertices.Keys) { candidateWeight = 0; // Select all neighbors List <int> neighbors = Neighbors(v, graph); List <int> cliqueCandidate = new List <int> (); // Start the candidate clique with the current vertex cliqueCandidate.Add(v); // Sort neighbors by combined Weight and degree List <KeyValuePair <int, int> > neighborsByWeightPlus = SortNeighbors(v, neighbors, graph, "weight+"); // For each neighbor check if it makes a clique with the candidate foreach (var neighbor in neighborsByWeightPlus) { bool makeClique = true; foreach (int vCand in cliqueCandidate) { // Check for maxTime if (_stopwatch.Elapsed >= _maxRunTime) { Log("Abort! Max Run Time exceeded!"); break; } if (!graph.Edges[vCand].Contains(neighbor.Key)) { makeClique = false; break; } } if (makeClique) { cliqueCandidate.Add(neighbor.Key); } // Check for maxTime if (_stopwatch.Elapsed >= _maxRunTime) { Log("Abort! Max Run Time exceeded!"); break; } } // Check if the new candidate is better than the current best answer candidateWeight = 0; cliqueCandidate.ForEach(c => candidateWeight += graph.Vertices[c]); Log(String.Format("current weight: {0}", currentAnswerWeight)); Log(String.Format("candidate weight: {0}", candidateWeight)); Log("================================================"); if (candidateWeight < currentAnswerWeight) { continue; } else { currentAnswerWeight = candidateWeight; answer.Clear(); answer.AddRange(cliqueCandidate); } // Check for maxTime if (_stopwatch.Elapsed >= _maxRunTime) { Log("Abort! Max Run Time exceeded!"); break; } } TimeSpan timeElapsed = _stopwatch.Elapsed; List <string> answerLabels = new List <string> (); answer.ForEach(v => answerLabels.Add(graph.VertexIndexMap[v])); Log(String.Format("Max Clique: [{0}]", String.Join(", ", answerLabels))); Log(String.Format("Max Clique Weight: {0}", currentAnswerWeight)); using (StreamWriter sw = new StreamWriter(_graphInstancePath.Replace(".txt", "out.csv"), append: true)) { sw.WriteLine(String.Format("{0}\t{1}\t{2}", timeElapsed.ToString(), _graphInstancePath, currentAnswerWeight)); } }
private static bool BronKerbosch(List <int> R, List <int> P, List <int> X, WeightedGraph graph, ref List <int> answer) { _backtrackCallCount++; //Log ("======================================================"); //Log (String.Format ("R: [{0}]", String.Join(", ", R))); //Log (String.Format ("P: [{0}]", String.Join(", ", P))); //Log (String.Format ("X: [{0}]", String.Join(", ", X))); int currentCliqueWeight = 0; int possibleMaxCliqueWeight = 0; int candidateCliqueWeight = 0; if (_optimizeBacktrack) { // Check if we can increase the max clique with the current set possibleMaxCliqueWeight = 0; foreach (int vPos in R.Union(P)) { possibleMaxCliqueWeight += graph.Vertices[vPos]; } // calculate weight of maximal clique currentCliqueWeight = 0; foreach (int vAns in answer) { currentCliqueWeight += graph.Vertices[vAns]; } //Log (String.Format ("Possible Max Weight: {0}", possibleMaxCliqueWeight)); //Log (String.Format ("Current Weight: {0}", currentCliqueWeight)); if (possibleMaxCliqueWeight < currentCliqueWeight) { return(false); } } //if P and X are both empty: if (P.Count == 0 && X.Count == 0) { //report R as a maximal clique return(true); } int[] auxP = new int[P.Count]; P.CopyTo(auxP); List <int> auxPList = auxP.ToList(); //for each vertex v in P: foreach (int v in P) { // Check for maxTime if (_stopwatch.Elapsed >= _maxRunTime) { Log("Abort! Max Run Time exceeded!"); return(false); } List <int> Nv = Neighbors(v, graph); //BronKerbosch1(R ⋃ {v}, P ⋂ N(v), X ⋂ N(v)) if (BronKerbosch(R.Union(new List <int> { v }).ToList(), auxPList.Intersect(Nv).ToList(), X.Intersect(Nv).ToList(), graph, ref answer)) { // calculate weight of maximal clique currentCliqueWeight = 0; foreach (int vAns in answer) { currentCliqueWeight += graph.Vertices[vAns]; } Log(String.Format("current weight: {0}", currentCliqueWeight)); candidateCliqueWeight = 0; foreach (int vCand in R.Union(new List <int> { v }).ToList()) { candidateCliqueWeight += graph.Vertices[vCand]; } Log(String.Format("candidate weight: {0}", candidateCliqueWeight)); // Save heaviest clique as answer if (candidateCliqueWeight > currentCliqueWeight) { answer = R.Union(new List <int> { v }).ToList(); Log(String.Format("Candidate is the new max clique! Weight: {0}. Clique: [{1}]", candidateCliqueWeight, String.Join(", ", answer))); } Log("================================================"); } //P := P \ {v} auxPList.Remove(v); //X := X ⋃ {v} X = X.Union(new List <int> { v }).ToList(); } return(false); }
private static List <int> Neighbors(int v, WeightedGraph graph) { return(graph.Edges[v].ToList()); }
private static List <KeyValuePair <int, int> > SortNeighbors(int v, List <int> neighbors, WeightedGraph graph, string mode) { List <KeyValuePair <int, int> > sortedList = new List <KeyValuePair <int, int> >(); switch (mode) { case "weight": foreach (int neighbor in neighbors) { sortedList.Add(new KeyValuePair <int, int> (neighbor, graph.Vertices[neighbor])); } break; case "degree": foreach (int neighbor in neighbors) { sortedList.Add(new KeyValuePair <int, int> (neighbor, graph.Edges[neighbor].Count)); } break; case "weight+": foreach (int neighbor in neighbors) { sortedList.Add(new KeyValuePair <int, int> (neighbor, CalculateVertexCumulateWeight(neighbor, graph) - graph.Vertices[v] + graph.Vertices[neighbor])); } break; } sortedList.Sort((pair1, pair2) => pair2.Value.CompareTo(pair1.Value)); return(sortedList); }