123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785 |
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; File: sboyer.sch
- ; Description: The Boyer benchmark
- ; Author: Bob Boyer
- ; Created: 5-Apr-85
- ; Modified: 10-Apr-85 14:52:20 (Bob Shaw)
- ; 22-Jul-87 (Will Clinger)
- ; 2-Jul-88 (Will Clinger -- distinguished #f and the empty list)
- ; 13-Feb-97 (Will Clinger -- fixed bugs in unifier and rules,
- ; rewrote to eliminate property lists, and added
- ; a scaling parameter suggested by Bob Boyer)
- ; 19-Mar-99 (Will Clinger -- cleaned up comments)
- ; 4-Apr-01 (Will Clinger -- changed four 1- symbols to sub1)
- ; Language: Scheme
- ; Status: Public Domain
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;; SBOYER -- Logic programming benchmark, originally written by Bob Boyer.
- ;;; Much less CONS-intensive than NBOYER because it uses Henry Baker's
- ;;; "sharing cons".
- ; Note: The version of this benchmark that appears in Dick Gabriel's book
- ; contained several bugs that are corrected here. These bugs are discussed
- ; by Henry Baker, "The Boyer Benchmark Meets Linear Logic", ACM SIGPLAN Lisp
- ; Pointers 6(4), October-December 1993, pages 3-10. The fixed bugs are:
- ;
- ; The benchmark now returns a boolean result.
- ; FALSEP and TRUEP use TERM-MEMBER? rather than MEMV (which is called MEMBER
- ; in Common Lisp)
- ; ONE-WAY-UNIFY1 now treats numbers correctly
- ; ONE-WAY-UNIFY1-LST now treats empty lists correctly
- ; Rule 19 has been corrected (this rule was not touched by the original
- ; benchmark, but is used by this version)
- ; Rules 84 and 101 have been corrected (but these rules are never touched
- ; by the benchmark)
- ;
- ; According to Baker, these bug fixes make the benchmark 10-25% slower.
- ; Please do not compare the timings from this benchmark against those of
- ; the original benchmark.
- ;
- ; This version of the benchmark also prints the number of rewrites as a sanity
- ; check, because it is too easy for a buggy version to return the correct
- ; boolean result. The correct number of rewrites is
- ;
- ; n rewrites peak live storage (approximate, in bytes)
- ; 0 95024
- ; 1 591777
- ; 2 1813975
- ; 3 5375678
- ; 4 16445406
- ; 5 51507739
- ; Sboyer is a 2-phase benchmark.
- ; The first phase attaches lemmas to symbols. This phase is not timed,
- ; but it accounts for very little of the runtime anyway.
- ; The second phase creates the test problem, and tests to see
- ; whether it is implied by the lemmas.
- (define (sboyer-benchmark . args)
- (let ((n (if (null? args) 0 (car args))))
- (setup-boyer)
- (run-benchmark (string-append "sboyer"
- (number->string n))
- 1
- (lambda () (test-boyer n))
- (lambda (rewrites)
- (and (number? rewrites)
- (case n
- ((0) (= rewrites 95024))
- ((1) (= rewrites 591777))
- ((2) (= rewrites 1813975))
- ((3) (= rewrites 5375678))
- ((4) (= rewrites 16445406))
- ((5) (= rewrites 51507739))
- ; If it works for n <= 5, assume it works.
- (else #t)))))))
- (define (setup-boyer) #t) ; assigned below
- (define (test-boyer) #t) ; assigned below
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;
- ; The first phase.
- ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; In the original benchmark, it stored a list of lemmas on the
- ; property lists of symbols.
- ; In the new benchmark, it maintains an association list of
- ; symbols and symbol-records, and stores the list of lemmas
- ; within the symbol-records.
- (let ()
-
- (define (setup)
- (add-lemma-lst
- (quote ((equal (compile form)
- (reverse (codegen (optimize form)
- (nil))))
- (equal (eqp x y)
- (equal (fix x)
- (fix y)))
- (equal (greaterp x y)
- (lessp y x))
- (equal (lesseqp x y)
- (not (lessp y x)))
- (equal (greatereqp x y)
- (not (lessp x y)))
- (equal (boolean x)
- (or (equal x (t))
- (equal x (f))))
- (equal (iff x y)
- (and (implies x y)
- (implies y x)))
- (equal (even1 x)
- (if (zerop x)
- (t)
- (odd (sub1 x))))
- (equal (countps- l pred)
- (countps-loop l pred (zero)))
- (equal (fact- i)
- (fact-loop i 1))
- (equal (reverse- x)
- (reverse-loop x (nil)))
- (equal (divides x y)
- (zerop (remainder y x)))
- (equal (assume-true var alist)
- (cons (cons var (t))
- alist))
- (equal (assume-false var alist)
- (cons (cons var (f))
- alist))
- (equal (tautology-checker x)
- (tautologyp (normalize x)
- (nil)))
- (equal (falsify x)
- (falsify1 (normalize x)
- (nil)))
- (equal (prime x)
- (and (not (zerop x))
- (not (equal x (add1 (zero))))
- (prime1 x (sub1 x))))
- (equal (and p q)
- (if p (if q (t)
- (f))
- (f)))
- (equal (or p q)
- (if p (t)
- (if q (t)
- (f))))
- (equal (not p)
- (if p (f)
- (t)))
- (equal (implies p q)
- (if p (if q (t)
- (f))
- (t)))
- (equal (fix x)
- (if (numberp x)
- x
- (zero)))
- (equal (if (if a b c)
- d e)
- (if a (if b d e)
- (if c d e)))
- (equal (zerop x)
- (or (equal x (zero))
- (not (numberp x))))
- (equal (plus (plus x y)
- z)
- (plus x (plus y z)))
- (equal (equal (plus a b)
- (zero))
- (and (zerop a)
- (zerop b)))
- (equal (difference x x)
- (zero))
- (equal (equal (plus a b)
- (plus a c))
- (equal (fix b)
- (fix c)))
- (equal (equal (zero)
- (difference x y))
- (not (lessp y x)))
- (equal (equal x (difference x y))
- (and (numberp x)
- (or (equal x (zero))
- (zerop y))))
- (equal (meaning (plus-tree (append x y))
- a)
- (plus (meaning (plus-tree x)
- a)
- (meaning (plus-tree y)
- a)))
- (equal (meaning (plus-tree (plus-fringe x))
- a)
- (fix (meaning x a)))
- (equal (append (append x y)
- z)
- (append x (append y z)))
- (equal (reverse (append a b))
- (append (reverse b)
- (reverse a)))
- (equal (times x (plus y z))
- (plus (times x y)
- (times x z)))
- (equal (times (times x y)
- z)
- (times x (times y z)))
- (equal (equal (times x y)
- (zero))
- (or (zerop x)
- (zerop y)))
- (equal (exec (append x y)
- pds envrn)
- (exec y (exec x pds envrn)
- envrn))
- (equal (mc-flatten x y)
- (append (flatten x)
- y))
- (equal (member x (append a b))
- (or (member x a)
- (member x b)))
- (equal (member x (reverse y))
- (member x y))
- (equal (length (reverse x))
- (length x))
- (equal (member a (intersect b c))
- (and (member a b)
- (member a c)))
- (equal (nth (zero)
- i)
- (zero))
- (equal (exp i (plus j k))
- (times (exp i j)
- (exp i k)))
- (equal (exp i (times j k))
- (exp (exp i j)
- k))
- (equal (reverse-loop x y)
- (append (reverse x)
- y))
- (equal (reverse-loop x (nil))
- (reverse x))
- (equal (count-list z (sort-lp x y))
- (plus (count-list z x)
- (count-list z y)))
- (equal (equal (append a b)
- (append a c))
- (equal b c))
- (equal (plus (remainder x y)
- (times y (quotient x y)))
- (fix x))
- (equal (power-eval (big-plus1 l i base)
- base)
- (plus (power-eval l base)
- i))
- (equal (power-eval (big-plus x y i base)
- base)
- (plus i (plus (power-eval x base)
- (power-eval y base))))
- (equal (remainder y 1)
- (zero))
- (equal (lessp (remainder x y)
- y)
- (not (zerop y)))
- (equal (remainder x x)
- (zero))
- (equal (lessp (quotient i j)
- i)
- (and (not (zerop i))
- (or (zerop j)
- (not (equal j 1)))))
- (equal (lessp (remainder x y)
- x)
- (and (not (zerop y))
- (not (zerop x))
- (not (lessp x y))))
- (equal (power-eval (power-rep i base)
- base)
- (fix i))
- (equal (power-eval (big-plus (power-rep i base)
- (power-rep j base)
- (zero)
- base)
- base)
- (plus i j))
- (equal (gcd x y)
- (gcd y x))
- (equal (nth (append a b)
- i)
- (append (nth a i)
- (nth b (difference i (length a)))))
- (equal (difference (plus x y)
- x)
- (fix y))
- (equal (difference (plus y x)
- x)
- (fix y))
- (equal (difference (plus x y)
- (plus x z))
- (difference y z))
- (equal (times x (difference c w))
- (difference (times c x)
- (times w x)))
- (equal (remainder (times x z)
- z)
- (zero))
- (equal (difference (plus b (plus a c))
- a)
- (plus b c))
- (equal (difference (add1 (plus y z))
- z)
- (add1 y))
- (equal (lessp (plus x y)
- (plus x z))
- (lessp y z))
- (equal (lessp (times x z)
- (times y z))
- (and (not (zerop z))
- (lessp x y)))
- (equal (lessp y (plus x y))
- (not (zerop x)))
- (equal (gcd (times x z)
- (times y z))
- (times z (gcd x y)))
- (equal (value (normalize x)
- a)
- (value x a))
- (equal (equal (flatten x)
- (cons y (nil)))
- (and (nlistp x)
- (equal x y)))
- (equal (listp (gopher x))
- (listp x))
- (equal (samefringe x y)
- (equal (flatten x)
- (flatten y)))
- (equal (equal (greatest-factor x y)
- (zero))
- (and (or (zerop y)
- (equal y 1))
- (equal x (zero))))
- (equal (equal (greatest-factor x y)
- 1)
- (equal x 1))
- (equal (numberp (greatest-factor x y))
- (not (and (or (zerop y)
- (equal y 1))
- (not (numberp x)))))
- (equal (times-list (append x y))
- (times (times-list x)
- (times-list y)))
- (equal (prime-list (append x y))
- (and (prime-list x)
- (prime-list y)))
- (equal (equal z (times w z))
- (and (numberp z)
- (or (equal z (zero))
- (equal w 1))))
- (equal (greatereqp x y)
- (not (lessp x y)))
- (equal (equal x (times x y))
- (or (equal x (zero))
- (and (numberp x)
- (equal y 1))))
- (equal (remainder (times y x)
- y)
- (zero))
- (equal (equal (times a b)
- 1)
- (and (not (equal a (zero)))
- (not (equal b (zero)))
- (numberp a)
- (numberp b)
- (equal (sub1 a)
- (zero))
- (equal (sub1 b)
- (zero))))
- (equal (lessp (length (delete x l))
- (length l))
- (member x l))
- (equal (sort2 (delete x l))
- (delete x (sort2 l)))
- (equal (dsort x)
- (sort2 x))
- (equal (length (cons x1
- (cons x2
- (cons x3 (cons x4
- (cons x5
- (cons x6 x7)))))))
- (plus 6 (length x7)))
- (equal (difference (add1 (add1 x))
- 2)
- (fix x))
- (equal (quotient (plus x (plus x y))
- 2)
- (plus x (quotient y 2)))
- (equal (sigma (zero)
- i)
- (quotient (times i (add1 i))
- 2))
- (equal (plus x (add1 y))
- (if (numberp y)
- (add1 (plus x y))
- (add1 x)))
- (equal (equal (difference x y)
- (difference z y))
- (if (lessp x y)
- (not (lessp y z))
- (if (lessp z y)
- (not (lessp y x))
- (equal (fix x)
- (fix z)))))
- (equal (meaning (plus-tree (delete x y))
- a)
- (if (member x y)
- (difference (meaning (plus-tree y)
- a)
- (meaning x a))
- (meaning (plus-tree y)
- a)))
- (equal (times x (add1 y))
- (if (numberp y)
- (plus x (times x y))
- (fix x)))
- (equal (nth (nil)
- i)
- (if (zerop i)
- (nil)
- (zero)))
- (equal (last (append a b))
- (if (listp b)
- (last b)
- (if (listp a)
- (cons (car (last a))
- b)
- b)))
- (equal (equal (lessp x y)
- z)
- (if (lessp x y)
- (equal (t) z)
- (equal (f) z)))
- (equal (assignment x (append a b))
- (if (assignedp x a)
- (assignment x a)
- (assignment x b)))
- (equal (car (gopher x))
- (if (listp x)
- (car (flatten x))
- (zero)))
- (equal (flatten (cdr (gopher x)))
- (if (listp x)
- (cdr (flatten x))
- (cons (zero)
- (nil))))
- (equal (quotient (times y x)
- y)
- (if (zerop y)
- (zero)
- (fix x)))
- (equal (get j (set i val mem))
- (if (eqp j i)
- val
- (get j mem)))))))
-
- (define (add-lemma-lst lst)
- (cond ((null? lst)
- #t)
- (else (add-lemma (car lst))
- (add-lemma-lst (cdr lst)))))
-
- (define (add-lemma term)
- (cond ((and (pair? term)
- (eq? (car term)
- (quote equal))
- (pair? (cadr term)))
- (put (car (cadr term))
- (quote lemmas)
- (cons
- (translate-term term)
- (get (car (cadr term)) (quote lemmas)))))
- (else (error "ADD-LEMMA did not like term: " term))))
-
- ; Translates a term by replacing its constructor symbols by symbol-records.
-
- (define (translate-term term)
- (cond ((not (pair? term))
- term)
- (else (cons (symbol->symbol-record (car term))
- (translate-args (cdr term))))))
-
- (define (translate-args lst)
- (cond ((null? lst)
- '())
- (else (cons (translate-term (car lst))
- (translate-args (cdr lst))))))
-
- ; For debugging only, so the use of MAP does not change
- ; the first-order character of the benchmark.
-
- (define (untranslate-term term)
- (cond ((not (pair? term))
- term)
- (else (cons (get-name (car term))
- (map untranslate-term (cdr term))))))
-
- ; A symbol-record is represented as a vector with two fields:
- ; the symbol (for debugging) and
- ; the list of lemmas associated with the symbol.
-
- (define (put sym property value)
- (put-lemmas! (symbol->symbol-record sym) value))
-
- (define (get sym property)
- (get-lemmas (symbol->symbol-record sym)))
-
- (define (symbol->symbol-record sym)
- (let ((x (assq sym *symbol-records-alist*)))
- (if x
- (cdr x)
- (let ((r (make-symbol-record sym)))
- (set! *symbol-records-alist*
- (cons (cons sym r)
- *symbol-records-alist*))
- r))))
-
- ; Association list of symbols and symbol-records.
-
- (define *symbol-records-alist* '())
-
- ; A symbol-record is represented as a vector with two fields:
- ; the symbol (for debugging) and
- ; the list of lemmas associated with the symbol.
-
- (define (make-symbol-record sym)
- (vector sym '()))
-
- (define (put-lemmas! symbol-record lemmas)
- (vector-set! symbol-record 1 lemmas))
-
- (define (get-lemmas symbol-record)
- (vector-ref symbol-record 1))
-
- (define (get-name symbol-record)
- (vector-ref symbol-record 0))
-
- (define (symbol-record-equal? r1 r2)
- (eq? r1 r2))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;
- ; The second phase.
- ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (define (test n)
- (let ((term
- (apply-subst
- (translate-alist
- (quote ((x f (plus (plus a b)
- (plus c (zero))))
- (y f (times (times a b)
- (plus c d)))
- (z f (reverse (append (append a b)
- (nil))))
- (u equal (plus a b)
- (difference x y))
- (w lessp (remainder a b)
- (member a (length b))))))
- (translate-term
- (do ((term
- (quote (implies (and (implies x y)
- (and (implies y z)
- (and (implies z u)
- (implies u w))))
- (implies x w)))
- (list 'or term '(f)))
- (n n (- n 1)))
- ((zero? n) term))))))
- (tautp term)))
-
- (define (translate-alist alist)
- (cond ((null? alist)
- '())
- (else (cons (cons (caar alist)
- (translate-term (cdar alist)))
- (translate-alist (cdr alist))))))
-
- (define (apply-subst alist term)
- (cond ((not (pair? term))
- (let ((temp-temp (assq term alist)))
- (if temp-temp
- (cdr temp-temp)
- term)))
- (else (cons (car term)
- (apply-subst-lst alist (cdr term))))))
-
- (define (apply-subst-lst alist lst)
- (cond ((null? lst)
- '())
- (else (cons (apply-subst alist (car lst))
- (apply-subst-lst alist (cdr lst))))))
-
- (define (tautp x)
- (tautologyp (rewrite x)
- '() '()))
-
- (define (tautologyp x true-lst false-lst)
- (cond ((truep x true-lst)
- #t)
- ((falsep x false-lst)
- #f)
- ((not (pair? x))
- #f)
- ((eq? (car x) if-constructor)
- (cond ((truep (cadr x)
- true-lst)
- (tautologyp (caddr x)
- true-lst false-lst))
- ((falsep (cadr x)
- false-lst)
- (tautologyp (cadddr x)
- true-lst false-lst))
- (else (and (tautologyp (caddr x)
- (cons (cadr x)
- true-lst)
- false-lst)
- (tautologyp (cadddr x)
- true-lst
- (cons (cadr x)
- false-lst))))))
- (else #f)))
-
- (define if-constructor '*) ; becomes (symbol->symbol-record 'if)
-
- (define rewrite-count 0) ; sanity check
-
- ; The next procedure is Henry Baker's sharing CONS, which avoids
- ; allocation if the result is already in hand.
- ; The REWRITE and REWRITE-ARGS procedures have been modified to
- ; use SCONS instead of CONS.
-
- (define (scons x y original)
- (if (and (eq? x (car original))
- (eq? y (cdr original)))
- original
- (cons x y)))
-
- (define (rewrite term)
- (set! rewrite-count (+ rewrite-count 1))
- (cond ((not (pair? term))
- term)
- (else (rewrite-with-lemmas (scons (car term)
- (rewrite-args (cdr term))
- term)
- (get-lemmas (car term))))))
-
- (define (rewrite-args lst)
- (cond ((null? lst)
- '())
- (else (scons (rewrite (car lst))
- (rewrite-args (cdr lst))
- lst))))
-
- (define (rewrite-with-lemmas term lst)
- (cond ((null? lst)
- term)
- ((one-way-unify term (cadr (car lst)))
- (rewrite (apply-subst unify-subst (caddr (car lst)))))
- (else (rewrite-with-lemmas term (cdr lst)))))
-
- (define unify-subst '*)
-
- (define (one-way-unify term1 term2)
- (begin (set! unify-subst '())
- (one-way-unify1 term1 term2)))
-
- (define (one-way-unify1 term1 term2)
- (cond ((not (pair? term2))
- (let ((temp-temp (assq term2 unify-subst)))
- (cond (temp-temp
- (term-equal? term1 (cdr temp-temp)))
- ((number? term2) ; This bug fix makes
- (equal? term1 term2)) ; nboyer 10-25% slower!
- (else
- (set! unify-subst (cons (cons term2 term1)
- unify-subst))
- #t))))
- ((not (pair? term1))
- #f)
- ((eq? (car term1)
- (car term2))
- (one-way-unify1-lst (cdr term1)
- (cdr term2)))
- (else #f)))
-
- (define (one-way-unify1-lst lst1 lst2)
- (cond ((null? lst1)
- (null? lst2))
- ((null? lst2)
- #f)
- ((one-way-unify1 (car lst1)
- (car lst2))
- (one-way-unify1-lst (cdr lst1)
- (cdr lst2)))
- (else #f)))
-
- (define (falsep x lst)
- (or (term-equal? x false-term)
- (term-member? x lst)))
-
- (define (truep x lst)
- (or (term-equal? x true-term)
- (term-member? x lst)))
-
- (define false-term '*) ; becomes (translate-term '(f))
- (define true-term '*) ; becomes (translate-term '(t))
-
- ; The next two procedures were in the original benchmark
- ; but were never used.
-
- (define (trans-of-implies n)
- (translate-term
- (list (quote implies)
- (trans-of-implies1 n)
- (list (quote implies)
- 0 n))))
-
- (define (trans-of-implies1 n)
- (cond ((equal? n 1)
- (list (quote implies)
- 0 1))
- (else (list (quote and)
- (list (quote implies)
- (- n 1)
- n)
- (trans-of-implies1 (- n 1))))))
-
- ; Translated terms can be circular structures, which can't be
- ; compared using Scheme's equal? and member procedures, so we
- ; use these instead.
-
- (define (term-equal? x y)
- (cond ((pair? x)
- (and (pair? y)
- (symbol-record-equal? (car x) (car y))
- (term-args-equal? (cdr x) (cdr y))))
- (else (equal? x y))))
-
- (define (term-args-equal? lst1 lst2)
- (cond ((null? lst1)
- (null? lst2))
- ((null? lst2)
- #f)
- ((term-equal? (car lst1) (car lst2))
- (term-args-equal? (cdr lst1) (cdr lst2)))
- (else #f)))
-
- (define (term-member? x lst)
- (cond ((null? lst)
- #f)
- ((term-equal? x (car lst))
- #t)
- (else (term-member? x (cdr lst)))))
-
- (set! setup-boyer
- (lambda ()
- (set! *symbol-records-alist* '())
- (set! if-constructor (symbol->symbol-record 'if))
- (set! false-term (translate-term '(f)))
- (set! true-term (translate-term '(t)))
- (setup)))
-
- (set! test-boyer
- (lambda (n)
- (set! rewrite-count 0)
- (let ((answer (test n)))
- (write rewrite-count)
- (display " rewrites")
- (newline)
- (if answer
- rewrite-count
- #f)))))
|