2013-03-09 29 views
5

Tôi muốn tìm tất cả các tập con của một tập hợp nhất định loại trừ lẫn nhau và chứa càng nhiều phần tử của bộ siêu âm càng tốt. Nơi người dùng xác định ý nghĩa cho tính độc quyền:Đặt tập hợp con độc lập tối đa qua máy phát điện C#

bool exclusion<T>(T a, T b) 

nơi ít nhất exclusion(a, b) == exclusion(b, a) giữ.

exclusion(a, b) == true được đảm bảo nếu a.Equals(b) == true

Mã của tôi trông như thế này:

public static HashSet<HashSet<T>> MutuallyExclusive<T>(this IEnumerable<T> available, Func<T, T, bool> exclusion) { 
    HashSet<HashSet<T>> finished = new HashSet<HashSet<T>>(new HashSetEquality<T>()); 
    Recursion<T>(available, new HashSet<T>(), finished, exclusion); 
    return finished; 
} 

private static void Recursion<T>(IEnumerable<T> available, HashSet<T> accepted, HashSet<HashSet<T>> finished, Func<T, T, bool> exclusion) { 
    if (!available.Any()) 
     finished.Add(accepted); 
    else 
     foreach (T a in available) 
      Recursion<T>(available.Where(b => !exclusion(a, b)), new HashSet<T>(accepted) { a }, finished, exclusion); 
} 

private class HashSetEquality<T> : IEqualityComparer<HashSet<T>> { 
    public bool Equals(HashSet<T> x, HashSet<T> y) { 
     if (x.Count != y.Count) 
      return false; 
     return x.All(t => y.Contains(t)); 
    } 

    public int GetHashCode(HashSet<T> obj) { 
     return obj.Aggregate(0, (i, t) => i^t.GetHashCode()); 
    } 
} 

Có cách nào để biến mã này vào một iterator di chuyển qua các giá trị được chấp nhận từng người một?

Edit:

Có vẻ như tôi là tôi ít unprecise trong câu hỏi của tôi, xin lỗi. Tôi đã thực sự tìm kiếm một máy phát điện để thực hiện deffered. Vì vậy mà mỗi khi bạn gọi nó là chỉ tập được chấp nhận tiếp theo được tính

+0

ngoài bất kỳ vấn đề nào khác khi tính toán mã băm bằng xor tất cả các giá trị gethashcode không phải là cách tiếp cận tốt nhất. –

+0

@MitchWheat mọi đề xuất cách thực hiện tốt hơn? – Maxwell

+0

Vì vậy, bạn đang tìm kiếm tất cả [bộ độc lập tối đa] (http://en.wikipedia.org/wiki/Maximal_independent_set)? – svick

Trả lời

2

Về cơ bản, những gì bạn muốn làm là để tạo ra một tập hợp mới mỗi khi bạn gọi finished.Add() và nó trả true.

Nhưng vì đệ quy, bạn cũng cần phải mang lại tất cả các giá trị được trả về từ các cuộc gọi đệ quy. Bạn có thể làm điều đó bằng năng suất tất cả những giá trị trong một vòng lặp:

public static IEnumerable<HashSet<T>> MutuallyExclusive<T>(
    this IEnumerable<T> available, Func<T, T, bool> exclusion) 
{ 
    var finished = new HashSet<HashSet<T>>(new HashSetEquality<T>()); 
    return Recursion<T>(available, new HashSet<T>(), finished, exclusion); 
} 

private static IEnumerable<HashSet<T>> Recursion<T>(
    IEnumerable<T> available, HashSet<T> accepted, HashSet<HashSet<T>> finished, 
    Func<T, T, bool> exclusion) 
{ 
    if (!available.Any()) 
    { 
     if (finished.Add(accepted)) 
      yield return finished; 
    } 
    else 
     foreach (T a in available) 
     { 
      var results = Recursion<T>(
       available.Where(b => !exclusion(a, b)), 
       new HashSet<T>(accepted) { a }, finished, exclusion); 

      foreach (var set in results) 
       yield return set; 
     } 
} 

Đó là lẽ không phải là giải pháp hiệu quả nhất, nhưng nó được công việc làm.

Ngoài ra, bạn có thể muốn cân nhắc xem xét từng tập hợp con chỉ một lần. Bằng cách đó, bạn sẽ không cần thiết lập finished và bạn có thể trực tiếp mang lại tất cả các kết quả mà bạn tìm thấy.

-1

Thay vì return finished; bạn có thể sử dụng

foreach (HashSet<T> set in finished) 
    yield return set; 

Và kể từ khi bạn đang làm cho một máy phát điện (Tôi nghĩ đó là những gì họ đang gọi?), bạn cần thay đổi chữ ký của MutuallyExclusive từ HashSet<HashSet<T>> thành IEnumerable<HashSet<T>>. Vì vậy, về cơ bản MutuallyExclusive sẽ trông như thế:

public static IEnumerable<HashSet<T>> MutuallyExclusive<T>(this IEnumerable<T> available, Func<T, T, bool> exclusion) 
{ 
    HashSet<HashSet<T>> finished = new HashSet<HashSet<T>>(new HashSetEquality<T>()); 
    Recursion<T>(available, new HashSet<T>(), finished, exclusion); 
    foreach (HashSet<T> set in finished) 
     yield return set; 
} 
+0

Điều đó không giúp được gì, mục đầu tiên sẽ vẫn được trả lại chỉ sau khi toàn bộ thiết lập được tính toán. – svick

Các vấn đề liên quan