// baseset ∪ (∪ S) = XとなるようなSを求める(複数返す) static public IEnumerable<IEnumerable<BitField>> Solve (IEnumerable<BitField> subsets, BitField baseset = null) { // 自明の場合 if (subsets.Count() == 0) { return Enumerable.Empty<IEnumerable<BitField>>(); } if (baseset == null) { baseset = new BitField (subsets.First().Length); } // 1つしか選択肢がないものを抽出 var subsets1 = subsets.ToList (); var need = new List<BitField> (); for (int i = 0; i < baseset.Length; i ++) { if (baseset [i]) continue; BitField candidate = null; int candiCount = 0; foreach (BitField aSubset in subsets1) { if (aSubset [i]) { candiCount ++; if (candidate == null) candidate = aSubset; else break; } } // 1つも無ければエラー if (candiCount < 1) { return Enumerable.Empty<IEnumerable<BitField>>(); } else if (candiCount == 1) { subsets1.Remove (candidate); need.Add (candidate); baseset |= candidate; } } // 包含関係を除去 var subsets2 = subsets1.Where (x => subsets1.All (y => ReferenceEquals(x, y) || !y.Contains(x))); // 0から総当り var first = Tuple.Create (Enumerable.Empty<BitField>(), baseset); var candidates = first.ToEnumerable (); while (candidates.SingleOrDefault () != null) { var ok = candidates.Where (x => x.Item2.IsMax).Select (x => x.Item1); if (ok.SingleOrDefault() != null) { return ok.Select (x => x.Concat(need)); } candidates = candidates.SelectMany (src => subsets2 .Where(x => !src.Item2.Contains(x)) .Select(x => Tuple.Create(src.Item1.Add(x), src.Item2 | x))); } return Enumerable.Empty<IEnumerable<BitField>>(); }
// 包含関係 public bool Contains (BitField a) { var last = fields.Length - 1; for (int i = 0; i < last; i ++) { if ((a.fields [i] | fields [i]) != fields[i]) return false; } return ((a.fields [last] & a.highMask) | fields [last]) == fields [last]; }
public QMColumn (int size, int colCount) : base (size) { Flags = new BitField (colCount); }
public QMColumn (TruthTableColumn ttc, int colCount) : base (ttc) { Result = ttc.Result; Flags = new BitField (colCount); }
// 長さが違うとエラー(特にエラー処理はしない) public static BitField operator | (BitField a, BitField b){ var c = new BitField (a.length); for (int i = 0; i < a.fields.Length; i ++) { c.fields [i] = a.fields [i] | b.fields [i]; } return c; }