[英]Representing temporal constraints in SMT-LIB
我試圖在SMT-LIB中表示時間約束,以檢查它們的可滿足性。 我正在尋找有關我正在采取的方向的反饋。 我對SMT-LIB比較陌生,我非常欣賞輸入。
我所擁有的約束是關於事件的時間和持續時間。 例如,考慮以自然語言給出的以下約束:
約翰在13:03:41開始寫一篇文章,花了20分鍾完成它。
寫完之后,他檢查了他的電子郵件,這花了他超過40分鍾。
檢查完他的電子郵件后,他打電話給他的妻子。
他在14:00:00之后打電話給他的妻子。
很容易看出這組約束是令人滿意的,我試圖用SMT求解器來推斷它。
為了對時間和持續時間的概念有一些封裝的痛處,我定義了在數組中表示它們的新排序。 一些宏被定義為用作構造:
(define-sort Time () (Array Int Int))
(define-fun new_time_ns ((hours Int) (minutes Int) (seconds Int) (nanos Int)) Time
(store (store (store (store ((as const (Array Int Int)) 0) 1 hours) 2 minutes) 3 seconds) 4 nanos)
)
(define-sort Duration () (Array Int Int))
(define-fun new_duration_ns ((seconds Int) (nanos Int)) Duration
(store (store ((as const (Array Int Int)) 0) 1 seconds) 2 nanos)
)
使用宏定義getter並允許我們檢索特定度量,例如:
(define-fun getDurationSecond ((d Duration)) Int
(select d 1)
)
(define-fun getDurationNano ((d Duration)) Int
(select d 2)
)
一些實用程序宏被定義為時間和持續時間算術以及表達關系。 例如,使用一些輔助宏我們定義isLongerThan , isShorterThan和isEqualDuration ,如下所示:
(define-fun cmpInt ((i1 Int) (i2 Int)) Int
(ite (< i1 i2) -1 (ite(> i1 i2) 1 0))
)
(define-fun cmpDuration ((d1 Duration) (d2 Duration)) Int
(ite (= (cmpInt (getDurationSecond d1) (getDurationSecond d2)) 0)
(ite (= (cmpInt (getDurationNano d1) (getDurationNano d2)) 0)
0
(cmpInt (getDurationNano d1) (getDurationNano d2)))
(cmpInt (getDurationSecond d1) (getDurationSecond d2)))
)
(define-fun isLongerThan ((d1 Duration) (d2 Duration)) Bool
(> (cmpDuration d1 d2) 0)
)
(define-fun isShorterThan ((d1 Duration) (d2 Duration)) Bool
(< (cmpDuration d1 d2) 0)
)
(define-fun isEqualDuration ((d1 Duration) (d2 Duration)) Bool
(= (cmpDuration d1 d2) 0)
)
其余定義可以在此文件中找到。
基於此,我可以通過一組斷言來表達約束:
(declare-const write_start Time)
(declare-const write_end Time)
(declare-const write_duration Duration)
(declare-const check_start Time)
(declare-const check_end Time)
(declare-const check_duration Duration)
(declare-const phone_start Time)
(assert (= write_start (new_time_ns 13 03 41 0))) ; the writing started at 13:03:41
(assert (= write_duration (new_duration 1200))) ; the writing took 20 min (1200 sec).
(assert (= write_end (plusDuration write_start write_duration)))
(assert (isAfter check_start write_end)) ; the check started after the writing
(assert (isLongerThan check_duration (new_duration 2400))) ; the check took more than 40 min
(assert (= check_end (plusDuration check_start check_duration)))
(assert (isAfter phone_start check_end)) ; he phoned after the check
(assert (isAfter phone_start (new_time_ns 14 00 00 0))) ; it was after 14:00:00
(check-sat)
一些問題和問題:
在設計方面,我有興趣知道這是否是SMT-LIB中問題的合理建模。
這里要添加一些注意事項:(A)我決定使用數組來表示時間和持續時間對象,因為它們有助於對這些概念的內部字段進行分組(小時,分鍾,秒,納米)。 也可以使用單個整數。 (B)我非常依賴宏(define-fun ...),這可能會使約束變得有點復雜,但我不知道還能用什么來達到所需的表達能力和清晰度當前代碼有。 (C)目前沒有限制時間字段的約束,因此例如,分鍾字段的值可以是78.應該添加斷言,將秒限制為59,將分鍾限制為59,將小時限制為23 ,但我沒有找到一種優雅的方式來做到這一點。
我假設我處於FOL的可判斷片段 - QF_LIA - 因為所有約束都是使用線性函數在整數常量上聲明的。 但是,我嘗試通過Z3運行附加代碼 ,即使在普通計算機本地運行40分鍾后,它仍然沒有以分辨率(sat /不滿)返回。 我實際上不知道它是否可以解決問題。 我在QF-LIA中的假設可能是錯誤的,並且Z3也可能在這種類型的約束下掙扎。 我可以補充一點,當我嘗試更簡單的約束時,Z3設法達到分辨率,但我注意到它生成的模型非常復雜,有很多內部結構。 有人可以給我一些想法來調查嗎? 我的代碼可以在這里找到Z3的在線證明。 我還沒有嘗試過其他的SMT求解器。
我不知道嘗試在SMT-LIB中定義此類型的時間約束的並行工作。 我非常感謝對現有作品的參考。
謝謝!
我喜歡你的方法,但我認為通過定義你自己的種類,尤其是使用數組理論,你的情況過於復雜。
而且,在數學上,整數理論比它們的真實對應物更難。 例如,如果n , p和q是實數,則“ n = pq ,求解p ”是微不足道的,但如果它們是整數,則它是整數因子分解,這很難。 類似地, x n + y n = z n ,n> 2在實數中很容易求解,但在整數中,這是費馬的最后定理。 這些例子是非線性的,但是如果你認為用於解決QF_LRA的技術被教給中學和高中學生,我聲稱你在QF_LRA比QF_LIA更好。 無論如何,時間更接近實數而不是一堆整數。
根據我對SMT解算器的總體經驗,特別是Z3,你最好使用更簡單的理論。 它將允許Z3使用其最強大的內部解算器。 如果您使用更復雜的理論(如數組),您可能會得到一個驚人的結果,或者您可能會發現求解器超時並且您不知道為什么,就像您提出的解決方案一樣。
從軟件工程的角度來看,這並不是很好,但在數學上我推薦以下簡單的解決方案來解決您提出的問題,其中所有時間都表示為實數,就感興趣當天午夜以來的秒數而言:
; Output all real-valued numbers in decimal-format.
(set-option :pp.decimal true)
; Convenience function for converting hh:mm:ss formatted times to seconds since midnight.
(define-fun time_hms ((hour Real) (minute Real) (second Real)) Real
(+ (+ (* 3600.0 hour) (* 60.0 minute)) second)
)
; Convenience function for converting durations in minutes to seconds.
(define-fun duration_m ((minute Real)) Real
(* 60.0 minute)
)
; Variable declarations. Durations are in seconds. Times are in seconds since midnight.
(declare-fun write_start () Real)
(declare-fun write_end () Real)
(declare-fun write_duration () Real)
(declare-fun check_start () Real)
(declare-fun check_end () Real)
(declare-fun check_duration () Real)
(declare-fun phone_start () Real)
; Constraints.
; 1. John started writing an essay at 13:03:41, and it took him 20 min to complete it.
(assert (= write_start (time_hms 13 03 41)))
(assert (= write_duration (duration_m 20)))
(assert (= write_end (+ write_start write_duration)))
; 2. After writing, he checked his emails, which took him more than 40 min.
(assert (> check_start write_end))
(assert (> check_duration (duration_m 40)))
(assert (= check_end (+ check_start check_duration)))
; 3. After checking his emails, he phoned his wife.
(assert (> phone_start check_end))
; 4. He phoned his wife after 14:00:00.
(assert (> phone_start (time_hms 14 00 00)))
(check-sat)
(get-value (write_start write_duration write_end check_start check_end check_duration phone_start))
(exit)
Z3和CVC4都很快找到了解決方案:
sat
((write_start 47021.0)
(write_duration 1200.0)
(write_end 48221.0)
(check_start 48222.0)
(check_end 50623.0)
(check_duration 2401.0)
(phone_start 50624.0))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.