;;; greedy-set-cover.scm  --  Jens Axel S√łgaard

(require (planet "set.scm" ("soegaard" "galore.plt")))

; An instance (X,F) of the "set-covering problem" consists
; of a finite set X and a family F of subsets of X covering X,
; that is, every element of X belongs to at least one subset in F.

; Example:

(define X (insert* '(a b c
                     d e f
                     g h i
                     j k l)

(define S1 (insert* '(a b c d e f)  (empty)))
(define S2 (insert* '(e f h i)      (empty)))
(define S3 (insert* '(a d g j)      (empty)))
(define S4 (insert* '(b e h k j)    (empty)))
(define S5 (insert* '(c f i l)      (empty)))
(define S6 (insert* '(j k)          (empty)))

(define F  (list S1 S2 S3 S4 S5 S6))

; A minimum set cover is C={S3,S4,S5}.

; Let's try a greedy approach:

; greedy-set-cover : (set alpha) (list (set alpha))  ->  (list (set alpha))
;   given a set X and a list F of subsets of X covering X,
;   returns an approximation of the minimal set covering.
;   The covering is returned as a list of subsets from F.
(define (greedy-set-cover X F)
  (let loop ([U X]     ; elements not covered by the subsets in C
             [C '()])  ; list of subset in the covering chosen so far
    (if (empty? U)   
        (let ([S (select-S-in-F-such-that-S-intersect-U-maximal F U)])
          (loop (difference U S)
                (cons S C))))))

(define (select-S-in-F-such-that-S-intersect-U-maximal F U)
  (foldl (lambda (S S-best)
           (if (> (size (intersection S U))
                  (size (intersection S-best U)))
         (car F)
         (cdr F)))

; Let's try it on the exmaple:

(map elements
     (greedy-set-cover X F))

; => ((a d g j) (c f i l) (b e h j k) (a b c d e f))

; The greedy approach produces C={S1,S4,S5,S3} and
; thus doesn't find the minimal covering.