4

How do I extract an element in a Sequence to the base type, so that the following will work?

(define-sort ISeq () (Seq Int))
(define-const x ISeq (seq.unit 5))
(define-const y ISeq (seq.unit 6))
(assert (>= (seq.at x 0) (seq.at y 0)))
Adam
  • 406
  • 3
  • 6

3 Answers3

3

Until a suitable function is implemented (or its existence is revealed to us), you could use the following work-around:

(define-sort ISeq () (Seq Int))
(define-const x ISeq (seq.unit 5))
(define-const y ISeq (seq.unit 6))

(declare-const e1 Int)
(declare-const e2 Int)

(push)
  (assert (= (seq.unit e1) (seq.at x 0)))
  (assert (= (seq.unit e2) (seq.at y 0)))

  (assert (not (>= e2 e1)))
  (check-sat)
(pop)

(push) ;; or alternatively
  (assert (not
    (implies
      (and
        (= (seq.unit e1) (seq.at x 0))
        (= (seq.unit e2) (seq.at y 0)))
      (>= e2 e1))))
  (check-sat)
(pop)
Malte Schwerhoff
  • 12,684
  • 4
  • 41
  • 71
1

See the relevant discussion at the Z3 issue tracker: https://github.com/Z3Prover/z3/issues/1302

It seems a workaround is indeed possible, but due to quantifiers it's unlikely to give you an effective method. An explicit encoding like Malte suggests might be the most practical approach here in the meantime.

alias
  • 28,120
  • 2
  • 23
  • 40
1

You're looking for nth. Here is a simple example of it:

(define-sort ISeq () (Seq Int))
(declare-const x ISeq)
(declare-const y ISeq)
(assert (= (seq.len x) 4))
(assert (= (seq.len y) 3))
(assert (< (seq.nth x 3) (seq.nth y 1)))
(check-sat)
(get-value (x y))

And z3 answers immediately with a correct answer (1237 > 1236):

sat
((x (seq.++ (seq.unit 6)
        (seq.++ (seq.unit 7) (seq.++ (seq.unit 8) (seq.unit 1236)))))
 (y (seq.++ (seq.unit 9) (seq.++ (seq.unit 1237) (seq.unit 12)))))
OrenIshShalom
  • 5,974
  • 9
  • 37
  • 87