compile ltl specs

This commit is contained in:
Sam Caldwell 2020-06-17 15:01:47 -04:00
parent 2ba5366986
commit 04995b5fb3
2 changed files with 155 additions and 32 deletions

View File

@ -3,14 +3,15 @@
;; TODO - syntax for LTL
(require "proto.rkt")
(require "ltl.rkt")
(module+ test
(require rackunit)
(require "test-utils.rkt"))
;; a SpinProgram is a
;; (sprog [Assignment [Listof SpinProcess]])
(struct sprog [assignment procs] #:transparent)
;; (sprog Assignment [Listof SpinProcess] [LTL SName])
(struct sprog [assignment procs spec] #:transparent)
;; a SpinProcess is a
@ -64,8 +65,8 @@
;; a NameEnvironment is a [Hashof τ SName]
;; [Sequenceof RoleGraph] -> SpinProgram
(define (program->spin rgs)
;; [Sequenceof RoleGraph] [LTL τ] -> SpinProgram
(define (program->spin rgs [spec #t])
(define assertion-tys (all-assertions rgs))
(define event-tys (all-events rgs))
(define event-subty# (make-event-map assertion-tys event-tys))
@ -73,7 +74,8 @@
(define name-env (make-name-env all-mentioned-tys))
(define globals (initial-assertion-vars-for all-mentioned-tys name-env))
(define procs (for/list ([rg rgs]) (rg->spin rg event-subty# name-env)))
(sprog globals procs))
(define spec-spin (rename-ltl spec name-env))
(sprog globals procs spec-spin))
;; RoleGraph [Hashof τ [Setof τ]] NameEnvironment -> SpinProcess
(define (rg->spin rg event-subty# name-env #:name [name (gensym 'proc)])
@ -221,6 +223,11 @@
[(Message τ)
(raise-argument-error 'rename-event "messages not implemented yet" D+)]))
;; [LTL τ] -> [LTL SName]
(define (rename-ltl ltl name-env)
(define (lookup τ) (hash-ref name-env τ))
(map-atomic ltl lookup))
(module+ test
(test-case
"sanity: compile book seller type"
@ -386,13 +393,15 @@
;; SpinThang -> Void
(define (gen-spin spin)
(match spin
[(sprog assignment procs)
[(sprog assignment procs spec)
(display SPIN-PRELUDE)
(gen-assignment assignment)
(newline)
(for ([p procs])
(gen-spin p)
(newline))
(gen-spec "spec" (lambda () (gen-ltl spec)))
(newline)
(gen-sanity-ltl assignment)]
[(sproc name state-names init asserts states)
(indent) (declare-mtype state-names)
@ -501,17 +510,68 @@
[(Message nm)
(raise-argument-error 'predicate-for "message sending not supported yet" event)]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; LTL
;; String {-> Void} -> Void
(define (gen-spec name mk-body)
(indent) (printf "ltl ~a {\n" name)
(with-indent
(mk-body))
(newline)
(indent) (displayln "}"))
;; [LTL SName] -> Void
(define (gen-ltl ltl)
(match ltl
[(always p)
(indent) (displayln "[](")
(with-indent
(gen-ltl p))
(indent) (displayln ")")]
[(eventually p)
(indent) (displayln "<>(")
(with-indent
(gen-ltl p))
(indent) (displayln ")")]
[(weak-until p q)
(gen-ltl-bin-op "W" p q)]
[(strong-until p q)
(gen-ltl-bin-op "U" p q)]
[(ltl-implies p q)
(gen-ltl-bin-op "->" p q)]
[(ltl-and p q)
(gen-ltl-bin-op "&&" p q)]
[(ltl-or p q)
(gen-ltl-bin-op "||" p q)]
[(ltl-not p)
(indent) (display "!(")
(gen-ltl p)
(displayln ")")]
[(atomic nm)
(printf "ASSERTED(~a)\n" nm)]
[#t
(display "true")]
[#f
(display "false")]))
;; String [LTL SName] [LTL SName] -> Void
(define (gen-ltl-bin-op name p q)
(indent) (display "(") (gen-ltl p) (display ") ")
(displayln name)
(newline)
(indent) (display "(") (gen-ltl q) (displayln ")"))
;; Assignment -> Void
(define (gen-sanity-ltl assignment)
(indent) (displayln "ltl sanity {")
(with-indent
(indent) (displayln "[](")
(with-indent
(for ([assertion-var (in-hash-keys assignment)])
(indent) (printf "~a >= 0 &&\n" (svar-name assertion-var)))
(indent) (displayln "true"))
(indent) (displayln ")"))
(indent) (displayln "}"))
(gen-spec "sanity"
(lambda ()
(indent) (displayln "[](")
(with-indent
(for ([assertion-var (in-hash-keys assignment)])
(indent) (printf "~a >= 0 &&\n" (svar-name assertion-var)))
(indent) (displayln "true"))
(indent) (displayln ")"))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Misc Utils
@ -552,18 +612,17 @@
(Reacts (Asserted (ClubMemberT (Bind String))))))))
(define seller-rg (compile seller-actual))
(define member-rg (compile member-actual))
(define book-club-spin (program->spin (list leader-rg seller-rg member-rg)))
(gen-spin/to-file book-club-spin "gen-book-club.pml")
;; handwritten LTL formula I've added to gen-book-club.pml:
#|
&&
<> (BookQuoteT_String_star_assertions > 0)
&&
[] (ASSERTED(Obs_BookQuoteT_String_star) -> <> ASSERTED(BookQuoteT_String_star))
&&
[] (ASSERTED(Obs_BookInterestT_String_star_star) -> <> ASSERTED(BookInterestT_String_star_star))
|#
)
(define bq (book-quote String ))
(define bi (book-interest String ))
(define book-club-spec
(&& (eventually (atomic bq))
(always (ltl-implies (atomic (Observe bq))
(eventually (atomic bq))))
(always (ltl-implies (atomic (Observe bi))
(eventually (atomic bi))))))
(define book-club-spin (program->spin (list leader-rg seller-rg member-rg)
book-club-spec))
(gen-spin/to-file book-club-spin "gen-book-club.pml"))
(module+ flink
(define (import r)
@ -574,8 +633,3 @@
(define tr-rg (import task-runner-ty))
(define flink-spin (program->spin (list tr-rg tm-rg jm-rg)))
(gen-spin/to-file flink-spin "gen-flink.pml"))
(require racket/trace)
#;(trace make-spin-id)
#;(trace state->spin)
#;(trace state-name->spin-id)

69
racket/typed/ltl.rkt Normal file
View File

@ -0,0 +1,69 @@
#lang racket
(provide (all-defined-out))
;; an [LTL X] is one of
;; - (always [LTL X])
;; - (eventually [LTL X])
;; - (weak-until [LTL X] [LTL X])
;; - (strong-until [LTL X] [LTL X])
;; - (ltl-implies [LTL X] [LTL X])
;; - (ltl-and [Listof [LTL X]])
;; - (ltl-or [Listof [LTL X]])
;; - (ltl-not [LTL X])
;; - (atomic X)
;; - Bool
;; where X represents the type of atomic propositions
(struct always [p] #:transparent)
(struct eventually [p] #:transparent)
(struct atomic [p] #:transparent)
(struct weak-until [p q] #:transparent)
(struct strong-until [p q] #:transparent)
(struct ltl-implies [p q] #:transparent)
(struct ltl-and [p q] #:transparent)
(struct ltl-or [p q] #:transparent)
(struct ltl-not [p] #:transparent)
;; [LTL X] {X -> Y} -> [LTL Y]
(define (map-atomic ltl op)
(let loop ([ltl ltl])
(match ltl
[(always p)
(always (loop p))]
[(eventually p)
(eventually (loop p))]
[(weak-until p q)
(weak-until (loop p) (loop q))]
[(strong-until p q)
(strong-until (loop p) (loop q))]
[(ltl-implies p q)
(ltl-implies (loop p) (loop q))]
[(ltl-and p q)
(ltl-and (loop p) (loop q))]
[(ltl-or p q)
(ltl-or (loop p) (loop q))]
[(ltl-not p)
(ltl-not (loop p))]
[(atomic x)
(atomic (op x))]
[#t
#t]
[#f
#f])))
(define (&& . args)
(fold-bin-op ltl-and args #t))
(define (|| . args)
(fold-bin-op ltl-or args #f))
(define (fold-bin-op op args base)
(let loop ([args args])
(match args
['()
base]
[(list x y)
(op x y)]
[(cons fst rst)
(op fst (loop rst))])))