Z3 を使用して部分文字列について推論しようとしていますが、直感的でない動作に遭遇しました。Z3 は、「xy」が「xy」内にあるかどうかを判断するように求められると「sat」を返しますが、「x」が「x」にあるか、「x」が「xy」にあるかを尋ねられると「unknown」を返します。
この動作を説明するために、次のコードにコメントを付けました。
(set-logic AUFLIA)
(declare-sort Char 0)
;characters to build strings are _x_ and _y_
(declare-fun _x_ () Char)
(declare-fun _y_ () Char)
(assert (distinct _x_ _y_))
;string literals
(declare-fun findMeX () (Array Int Char))
(declare-fun findMeXY () (Array Int Char))
(declare-fun x () (Array Int Char))
(declare-fun xy () (Array Int Char))
(declare-fun length ( (Array Int Char) ) Int )
;set findMeX = 'x'
(assert (= (select findMeX 0) _x_))
(assert (= (length findMeX) 1))
;set findMeXY = 'xy'
(assert (= (select findMeXY 0) _x_))
(assert (= (select findMeXY 1) _y_))
(assert (= (length findMeXY) 2))
;set x = 'x'
(assert (= (select x 0) _x_))
(assert (= (length x) 1))
;set xy = 'xy'
(assert (= (select xy 0) _x_))
(assert (= (select xy 1) _y_))
(assert (= (length xy) 2))
問題が設定されたので、部分文字列を見つけようとします。
;search for findMeX='x' in x='x'
(push 1)
(assert
(exists
((offset Int))
(and
(<= offset (- (length x) (length findMeX)))
(>= offset 0)
(forall
((index Int))
(=>
(and
(< index (length findMeX))
(>= index 0))
(=
(select x (+ index offset))
(select findMeX index)))))))
(check-sat) ;'sat' expected, 'unknown' returned
(pop 1)
findMeXY
代わりにinを検索するとxy
、ソルバーは予想どおり 'sat' を返します。ソルバーは「xy」についてこのクエリを処理できるため、「x」についても処理できるはずです。さらに、 で検索するfindMeX='x'
と'xy='xy'
、「不明」が返されます。
SMTソルバー内でこの問題を表現するための説明、またはおそらく代替モデルを提案できる人はいますか?