smtcvc4

Calculate the sum of an Int Set


Using the set theory of CVC4 (version 1.8-prerelease [git master a90b9e2b]) I have defined a set of integers with a fixed cardinality

(set-logic ALL_SUPPORTED)
(set-option :produce-models true)

(declare-fun A () (Set Int))
(assert (= 5 (card A)))

;;(assert (= sum (???)))

(check-sat)
(get-model)

CVC4 then gives me one correct model

sat
(model
(define-fun A () (Set Int) (union (union (union (union (singleton 0) (singleton 1)) (singleton (- 1))) (singleton 2)) (singleton (- 2))))
)

Is there a way to ask for the sum of the integers in set A?


Solution

  • As Patrick mentioned, these sorts of operations over arbitrary sets (like summing them up) is just not possible in SMTLib. However, you've more information: You know that the cardinality of the set is 5, so you can encode the summation indirectly.

    The trick is to construct a set of the required cardinality explicitly and sum those elements. Obviously this only works well if the set is small enough, but you can "generate" the code automatically from a high-level API if necessary. (Hand coding it would be difficult!)

    The below works with z3; Unfortunately CVC4 and Z3 differ in the function names for Sets a bit:

    (set-option :produce-models true)
    
    ; declare-original set
    (declare-fun A () (Set Int))
    (assert (= 5 (card A)))
    
    ; declare the "elements". We know there are 5 in this case. Declare one for each.
    (declare-fun elt1 () Int)
    (declare-fun elt2 () Int)
    (declare-fun elt3 () Int)
    (declare-fun elt4 () Int)
    (declare-fun elt5 () Int)
    
    ; form the set out of these elements:
    (define-fun B () (Set Int) (store (store (store (store (store ((as const (Array Int Bool)) false) elt1 true)
                                                           elt2 true)
                                                    elt3 true)
                                             elt4 true)
                                      elt5 true))
    
    ; make sure our set is equal to the set just constructed:
    (assert (= A B))
    
    ; now sum-up the elements
    (declare-fun sum () Int)
    (assert (= sum (+ elt1 elt2 elt3 elt4 elt5)))
    
    (check-sat)
    (get-value (elt1 elt2 elt3 elt4 elt5 sum A))
    

    This produces:

    $ z3 a.smt2
    sat
    ((elt1 0)
     (elt2 1)
     (elt3 3)
     (elt4 6)
     (elt5 7)
     (sum 17)
     (A (let ((a!1 (store (store (store ((as const (Set Int)) false) 0 true) 1 true)
                      3
                      true)))
      (store (store a!1 6 true) 7 true))))
    

    For CVC4, the encoding is similar:

    (set-option :produce-models true)
    (set-logic ALL_SUPPORTED)
    
    ; declare-original set
    (declare-fun A () (Set Int))
    (assert (= 5 (card A)))
    
    ; declare the "elements". We know there are 5 in this case. Declare one for each.
    (declare-fun elt1 () Int)
    (declare-fun elt2 () Int)
    (declare-fun elt3 () Int)
    (declare-fun elt4 () Int)
    (declare-fun elt5 () Int)
    
    ; form the set out of these elements:
    (define-fun B () (Set Int) (union (singleton elt1)
                                      (union (singleton elt2)
                                             (union (singleton elt3)
                                                    (union (singleton elt4) (singleton elt5))))))
    
    ; make sure our set is equal to the set just constructed:
    (assert (= A B))
    
    ; now sum-up the elements
    (declare-fun sum () Int)
    (assert (= sum (+ elt1 elt2 elt3 elt4 elt5)))
    
    (check-sat)
    (get-value (elt1 elt2 elt3 elt4 elt5 sum A))
    

    For which, cvc4 produces:

    sat
    ((elt1 (- 4)) (elt2 (- 3)) (elt3 (- 2)) (elt4 (- 1)) (elt5 0) (sum (- 10)) (A (union (union (union (union (singleton 0) (singleton (- 1))) (singleton (- 2))) (singleton (- 3))) (singleton (- 4)))))
    

    If the cardinality isn't fixed; I don't think you can code this up unless the domain is finite (or drawn from a finite subset of an infinite domain) as Patrick described.

    Hope that helps!