sicp/mceval/amb-natural-language.rkt

298 lines
11 KiB
Racket

(define nouns '(noun student professor cat class))
(define verbs '(verb studies lectures eats sleeps))
(define articles '(article the a))
(define adjectives '(adjective happy lazy))
(define connectives '(connective and but or))
;; output of parse
'(sentence (noun-phrase (article the) (noun cat))
(verb eats))
(define (parse-noun-phrase)
(list 'noun-phrase
(parse-word articles)
(parse-word nouns)))
(define (parse-word word-list)
(require (not (null? *unparsed*)))
(require (memq (car *unparsed*) (cdr word-list)))
(let ((found-word (car *unparsed*)))
(set! *unparsed* (cdr *unparsed*))
(list (car word-list) found-word)))
;; Exercise 4.48: generate a word by ignoring the unparsed input and
;; just working through all possible sentences.
(define (generate-word word-list)
(if null? (cdr word-list) (amb)
(let ((word-type (car word-list)))
(amb (list word-type (cadr word-list))
(generate-word (cons word-type (cdr (cdr word-list))))))))
;; Exercise 4.50: use ramb instead of amb to avoid getting stuck in
;; recursions.
(define (generate-word-ramb word-list)
(if (null? (cdr word-list)) (amb)
(let ((word-type (car word-list)))
(ramb (list word-type (cadr word-list))
(generate-word-ramb (cons word-type (cdr (cdr word-list))))))))
(define *unparsed* '())
(define (parse input)
(set! *unparsed* input)
(let ((sent (parse-sentence)))
(require (null? *unparsed*))
sent))
;: (parse '(the cat eats))
;; output of parse
'(sentence (noun-phrase (article the) (noun cat)) (verb eats))
(define prepositions '(prep for to in by with))
(define (parse-prepositional-phrase)
(list 'prep-phrase
(parse-word prepositions)
(parse-noun-phrase)))
(define (parse-simple-sentence)
(list 'simple-sentence
(parse-noun-phrase)
(parse-verb-phrase)))
(define (parse-sentence)
(define (maybe-extend sentence)
(amb sentence
(maybe-extend (list 'compound-sentence
sentence
(parse-word connectives)
(parse-simple-sentence)))))
(maybe-extend (parse-simple-sentence)))
(define (parse-verb-phrase)
(define (maybe-extend verb-phrase)
(amb verb-phrase
(maybe-extend (list 'verb-phrase
verb-phrase
(parse-prepositional-phrase)))))
(maybe-extend (parse-word verbs)))
;; Extend this to allow an adjective between the article and noun.
(define (parse-simple-noun-phrase)
(list 'simple-noun-phrase
(parse-word articles)
(parse-adjective-phrase)))
(define (parse-noun-phrase)
(define (maybe-extend noun-phrase)
(amb noun-phrase
(maybe-extend (list 'noun-phrase
noun-phrase
(parse-prepositional-phrase)))))
(maybe-extend (parse-simple-noun-phrase)))
;; An adjective phrase is any number of adjectives followed by a
;; simple noun.
(define (parse-adjective-phrase)
(amb (list (parse-word nouns))
(cons
(parse-word adjectives)
(parse-adjective-phrase))))
;; Exercise 4.45: Output of (parse '(the professor lectures to the student in the class with the cat))
(sentence
(simple-noun-phrase (article the) (noun professor))
(verb-phrase
(verb-phrase
(verb-phrase (verb lectures)
(prep-phrase (prep to)
(simple-noun-phrase (article the) (noun student))))
(prep-phrase (prep in) (simple-noun-phrase (article the) (noun class))))
(prep-phrase (prep with) (simple-noun-phrase (article the) (noun cat)))))
;; The cat is with the professor. The professor is in the class
;; lecturing the student. The student may be elsewhere.
(sentence
(simple-noun-phrase (article the) (noun professor))
(verb-phrase
(verb-phrase
(verb lectures)
(prep-phrase (prep to)
(simple-noun-phrase (article the) (noun student))))
(prep-phrase (prep in)
(noun-phrase (simple-noun-phrase (article the) (noun class))
(prep-phrase (prep with)
(simple-noun-phrase (article the) (noun cat)))))))
;; The cat is in the class in which the professor is lecturing the student
(sentence
(simple-noun-phrase (article the) (noun professor))
(verb-phrase
(verb-phrase
(verb lectures)
(prep-phrase (prep to)
(noun-phrase (simple-noun-phrase (article the) (noun student))
(prep-phrase (prep in)
(simple-noun-phrase (article the)
(noun class))))))
(prep-phrase (prep with)
(simple-noun-phrase (article the) (noun cat)))))
;; The student is in the class. The professor is with the cat and is
;; lecturing to the student. The professor and cat may or may not be
;; in the class.
(sentence
(simple-noun-phrase (article the) (noun professor))
(verb-phrase
(verb lectures)
(prep-phrase (prep to)
(noun-phrase
(noun-phrase (simple-noun-phrase (article the) (noun student))
(prep-phrase (prep in)
(simple-noun-phrase (article the) (noun class))))
(prep-phrase (prep with)
(simple-noun-phrase (article the) (noun cat)))))))
;; The professor is lecturing the student. The student is in the
;; class with the cat.
(sentence
(simple-noun-phrase (article the) (noun professor))
(verb-phrase
(verb lectures)
(prep-phrase (prep to)
(noun-phrase (simple-noun-phrase (article the) (noun student))
(prep-phrase (prep in)
(noun-phrase
(simple-noun-phrase (article the)
(noun class))
(prep-phrase (prep with)
(simple-noun-phrase
(article the)
(noun cat)))))))))
;; The professor lectures to the student, who is in the class with the cat
;; Exercise 4.46
;; If amb evaluated its arguments in any order other than
;; left-to-right, then the recursive maybe-extend rules would never
;; terminate, as the second argument is a recursive call to the
;; procedure. We rely on the recursion stopping at each decision
;; point.
;;
;; Also, since parse has side-effects (namely, it removes a word from
;; the input), it is important that we parse the different parts of
;; the sentence in the correct order.
;; Exercise 4.47
(define (parse-verb-phrase level)
(log (list 'parse-verb-phrase level))
(amb (parse-word verbs)
(list 'verb-phrase
(parse-verb-phrase (+ level 1))
(parse-prepositional-phrase (+ level 1)))))
;; In this case, if (parse-word verbs) fails, then we evaluate the 2nd
;; argument, which calls parse-verb-phrase recursively, creating a new
;; amb, which tries (parse-word verbs), which still fails. In the
;; orinal procedure, we evaluate (parse-word verbs) once and bind it
;; to verb-phrase. We then keep extending the phrase until it either
;; succeeds or fails. If it fails, the whole amb call fails. The
;; version here never fails because it keeps calling
;; parse-verb-phrase, leading to an infinite recursion. The only case
;; where this procedure works is when we pass it a valid verb phrase
;; and don't try again (ie trigger a fail).
;; If we swap the order of the clauses in the amb, then we get an
;; infinite loop, as the first clause immediately calls
;; parse-verb-phrase recursively. There is nothing to limit this
;; recursion.
;; Exercise 4.49
;;; Amb-Eval input:
(set! parse-word generate-word)
;;; Starting a new problem
;;; Amb-Eval value:
0
ok
;;; Amb-Eval input:
(parse '())
;;; Starting a new problem
;;; Amb-Eval value:
0
(simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies))
;;; Amb-Eval input:
try-again
;;; Amb-Eval value:
6
(compound-sentence (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies)) (connective and) (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies)))
;;; Amb-Eval input:
try-again
;;; Amb-Eval value:
10
(compound-sentence (compound-sentence (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies)) (connective and) (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies))) (connective and) (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies)))
;;; Amb-Eval input:
try-again
;;; Amb-Eval value:
14
(compound-sentence (compound-sentence (compound-sentence (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies)) (connective and) (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies))) (connective and) (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies))) (connective and) (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies)))
;;; Amb-Eval input:
try-again
;;; Amb-Eval value:
18
(compound-sentence (compound-sentence (compound-sentence (compound-sentence (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies)) (connective and) (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies))) (connective and) (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies))) (connective and) (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies))) (connective and) (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies)))
;;; Amb-Eval input:
try-again
;;; Amb-Eval value:
23
(compound-sentence (compound-sentence (compound-sentence (compound-sentence (compound-sentence (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies)) (connective and) (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies))) (connective and) (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies))) (connective and) (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies))) (connective and) (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies))) (connective and) (simple-sentence (simple-noun-phrase (article the) ((noun student))) (verb studies)))
;;; Amb-Eval input:
;; The generation gets stuck in the outer-most recursion. In this
;; case, it is the generation of compound sentences from simple sentences.