Đây là vấn đề của tôi: Tôi có một chuỗi S (nonempty nhưng có thể không phân biệt) bộ s_i, và cho mỗi s_i cần biết có bao nhiêu bộ s_j trong S (i ≠ j) là tập con của s_i.Tạo một DAG từ một poset bằng cách sử dụng lập trình hàm stricly
Tôi cũng cần hiệu suất gia tăng: một khi tôi có tất cả số đếm, tôi có thể thay thế một bộ s_i bằng một số tập hợp con của s_i và cập nhật số lượng tăng dần.
Thực hiện tất cả điều này bằng cách sử dụng mã thuần túy sẽ là một điểm cộng lớn (tôi viết bằng Scala).
Khi đặt bao gồm là một phần, tôi nghĩ cách tốt nhất để giải quyết vấn đề của tôi là xây dựng một DAG đại diện cho sơ đồ Hasse của các bộ, với các cạnh đại diện, và nối giá trị nguyên cho mỗi nút đại diện cho kích thước của sub-dag bên dưới nút cộng 1. Tuy nhiên, tôi đã bị mắc kẹt trong vài ngày cố gắng phát triển thuật toán xây dựng sơ đồ Hasse từ thứ tự một phần (chúng ta không nói về sự gia tăng!), mặc dù tôi nghĩ nó sẽ là một số tài liệu đại học tiêu chuẩn.
Dưới đây là cấu trúc dữ liệu của tôi:
case class HNode[A] (
val v: A,
val child: List[HNode[A]]) {
val rank = 1 + child.map(_.rank).sum
}
My DAG được xác định bởi một danh sách các rễ và một số đặt hàng phần:
class Hasse[A](val po: PartialOrdering[A], val roots: List[HNode[A]]) {
def +(v: A): Hasse[A] = new Hasse[A](po, add(v, roots))
private def collect(v: A, roots: List[HNode[A]], collected: List[HNode[A]]): List[HNode[A]] =
if (roots == Nil) collected
else {
val (subsets, remaining) = roots.partition(r => po.lteq(r.v, v))
collect(v, remaining.map(_.child).flatten, subsets.filter(r => !collected.exists(c => po.lteq(r.v, c.v))) ::: collected)
}
}
Tôi khá mắc kẹt ở đây. Lần cuối cùng tôi đưa ra để thêm một giá trị mới v cho DAG là:
- tìm tất cả "tập hợp con gốc" của v trong DAG, tức là tập con của v sao cho không có phần lớn của rs_i là tập con của v. Điều này có thể được thực hiện khá dễ dàng bằng cách thực hiện tìm kiếm (BFS hoặc DFS) trên biểu đồ (chức năng
collect
, có thể không tối ưu hoặc thậm chí thiếu sót). - tạo nút mới n_v, trẻ em trong số đó là rs_i được tìm thấy trước đây.
- Bây giờ, chúng ta hãy tìm ra nơi n_v nên được đính kèm: cho một danh sách nhất định của rễ, tìm supersets của v.Nếu không tìm thấy, thêm n_v vào gốc và loại bỏ tập hợp con của n_v từ rễ. Khác, thực hiện bước 3 đệ quy trên trẻ em của supersets.
Tôi chưa triển khai đầy đủ thuật toán này, nhưng dường như nó không được xử lý triệt để và không tối ưu cho vấn đề đơn giản của tôi. Có một số thuật toán đơn giản có sẵn (Google đã không biết gì về điều này)?
Thuật toán đó dường như rất đơn giản đối với tôi, không bị phức tạp một cách không cần thiết. Chính xác thì vấn đề là gì? Mã Scala cho nó sẽ hầu như không dài hơn mô tả của bạn. (Mặc dù tôi không nghĩ rằng bạn đã hoàn toàn mô tả nó đầy đủ.) –
Vâng, vì tôi đã tham gia vào lập trình hàm (~ 6 tháng trước), tôi đã quen với một lớp lót khi xử lý cấu trúc dữ liệu đệ quy. Nó cảm thấy khó xử khi phát triển một thuật toán ba bước, không nằm trong một cuộc gọi đệ quy (bước 1. bị ngắt kết nối từ bước 3.) Ngoài ra, thuật toán này sẽ kiểm tra các tập con hai lần (bước 1 và 3), sai rồi. – scand1sk
Là một tham chiếu, gần đây tôi đã triển khai một đống nhị thức, điều này cảm thấy dễ dàng hơn nhiều (mặc dù có thể do các thuật toán được xác định rõ hơn). – scand1sk