private void GetPrimes() { SufficientCandidateKeys.Clear(); _prime = new BitArray(Keys.Count); var leftBits = new BitArray(Keys.Count); foreach (var key in Left) { _prime[key] = true; leftBits[key] = true; } foreach (var key in Right) { _prime[key] = false; } foreach (var key in Middle) { _prime[key] = false; } var currentCover = Reachability(leftBits); var candidates = new List <int>(Middle); candidates.RemoveAll(key => currentCover[key]); if (candidates.Count == 0) { SufficientCandidateKeys.Add(leftBits); return; } var graph = new Graph(Keys.Count); foreach (var dependency in DependencyList) { var str = dependency.Item1.ToBitString(); if (str.Count(c => c == '1') != 1) { continue; } var index = str.IndexOf('1'); if (!candidates.Contains(index)) { continue; } for (var i = 0; i < Keys.Count; i++) { if (dependency.Item2[i] && candidates.Contains(i)) { graph.AddEdge(index, i); } } } graph.GetSccs(); var sccs = new List <List <int> >(); for (var i = 0; i < candidates.Count; i++) { sccs.Add(new List <int>()); sccs.Last().Add(candidates[i]); for (var j = i + 1; j < candidates.Count; j++) { if (graph.Scc[candidates[i]] != graph.Scc[candidates[j]]) { continue; } sccs.Last().Add(candidates[j]); candidates.RemoveAt(j); j--; } } for (var i = 0; i < candidates.Count; i++) { if (sccs[i].Any(candidate => DependencyList.Any(dependency => dependency.Item2[candidate] && Keys.Any(key => dependency.Item1[key] && graph.Scc[key] != graph.Scc[candidate])))) { continue; } leftBits[sccs[i][0]] = true; foreach (var key in sccs[i]) { _prime[key] = true; Left.Add(key); Middle.Remove(key); } sccs.RemoveAt(i); candidates.RemoveAt(i); i--; } currentCover = Reachability(leftBits); for (var i = 0; i < candidates.Count; i++) { if (!currentCover[candidates[i]]) { continue; } foreach (var key in sccs[i]) { _prime[key] = false; } sccs.RemoveAt(i); candidates.RemoveAt(i); i--; } if (candidates.Count == 0) { SufficientCandidateKeys.Add(leftBits); return; } // I claim by this line, the number of candidates can't be more than 16; given that the number of attributes isn't more than 4069, but who knows! if (candidates.Count > 20) { throw new ConstraintException("Too many attributes!"); } var foundSets = new List <int>(); for (var i = 1; i < (1 << candidates.Count); i++) { var currentSet = new BitArray(leftBits); var newSet = false; for (var j = 0; j < candidates.Count; j++) { if ((i & (1 << j)) != 0) { currentSet[candidates[j]] = true; newSet |= !_prime[candidates[j]]; } } if (foundSets.Any(set => (i & set) == set)) { i += i & -i; i--; continue; } if (Reachability(currentSet).ToBitString().Contains('0')) { continue; } foundSets.Add(i); SufficientCandidateKeys.Add(currentSet); for (var j = 0; j < candidates.Count; j++) { if ((i & (1 << j)) != 0 && !_prime[candidates[j]]) { foreach (var k in sccs[j]) { _prime[k] = true; } } } i += i & -i; i--; } }