Edit page
(define (filter pred lst)
  (fold (lambda (x y)
          (if (pred x)
              (pair x y)

(define (my-iota n)
  (define (helper n x)
    (if (= x n)
        (pair x (helper n (+ x 1)))
  (helper n 0))

(define (my-sample-integer n)
  (uniform-draw (my-iota n))

(define (extend a b)
  (if (equal? a '())
      (extend (rest a) (pair (first a) b))))

(define (flatten-nonrecursive a)
  (fold (lambda (x y) (extend x y)) '() a))

(define (generate-subsets elements)
  (if (equal? (length elements) 0)
      (let ((first-element (first elements))
            (rest-subsets (generate-subsets (rest elements))))
        (let ((new-subsets (pair (list first-element)
                                 (map (lambda (x) (pair first-element x)) rest-subsets))))
          (extend new-subsets rest-subsets)))))

(define (sample-nonempty-subset elements)
  (let ((subsets (generate-subsets elements)))
    (list-ref subsets (my-sample-integer (length subsets)))))

(define (zip a b)
  (if (equal? (length a) 0)
      (pair (list (first a) (first b)) (zip (rest a) (rest b)))))

(define (member-of e elements)
  (if (> (length elements) 0)
      (if (equal? e (first elements))
          (member-of e (rest elements)))

;; _______________________________________________________________________________

(define states (list 'bob 'mary 'bobmary))
;;either bob went to the restaurant alone, or mary did, or both bob and mary went

;;the speaker either knows the exact state, or knows that at least bob went, or knows that at least mary went
(define knowledge-states (list (list 'bob) (list 'mary) (list 'bobmary) (list 'bob 'bobmary) (list 'mary 'bobmary)))
(define (knowledge-prior) (multinomial knowledge-states '(1 1 1 1 1)))

(define knowledge-state-combinations
  (flatten-nonrecursive (map (lambda (x) (map (lambda (y) (list x y)) x)) knowledge-states)))

(define (sample-from-knowledge-state knowledge-state)
  (uniform-draw knowledge-state))

(define utterances '(bob mary bobandmary))
(define (get-utterance-prob utterance)
  (case utterance
        (('bob 'mary) 1)
        (('bobandmary) 0.5)
        (('null) 0)))
(define (utterance-prior) (multinomial utterances (map get-utterance-prob utterances)))

(define prosodies (list #f #t))
(define (get-prosody-prob prosody)
  (case prosody
        ((#f) 1)
        ((#t) 1)))
(define (prosody-prior) (multinomial prosodies (map get-prosody-prob prosodies)))

(define (noise-model utterance prosody)
  (if prosody
      (lambda (x)
        (case x
              ((utterance) 0.99)
              (('bob) 0.005)
              (('mary) 0.005)
              (else 0)))
      (lambda (x)
        (case x
              ((utterance) 0.98)
              (('bob) 0.01)
              (('mary) 0.01)
              (else 0)))))

;;sample a new utterance from the noise model
(define (sample-noise-model utterance prosody)
  (let ((noise-dist (noise-model utterance prosody)))
    (multinomial utterances (map noise-dist utterances))))

(define (literal-meaning utterance)
  (case utterance
        (('bob) (list 'bob 'bobmary))
        (('mary) (list 'mary 'bobmary))
        (('bobandmary) (list 'bobmary))
        (('null) (list 'bob 'mary 'bobmary))))

(define (literal-evaluation utterance state)
  (member-of state (literal-meaning utterance)))

(define (find-state-prob listener-probs state)
  (if (equal? listener-probs '())
      (if (equal? state (second (first (first listener-probs))))
          (second (first listener-probs))
          (find-state-prob (rest listener-probs) state))))

(define (get-expected-surprisal knowledge-state listener)
  (let ((listener (zip (first listener) (second listener))))
    (let ((relevant-listener-probs (filter (lambda (x) (equal? knowledge-state (first (first x))))
      (let ((state-probs (map (lambda (x) (find-state-prob relevant-listener-probs x)) knowledge-state)))
        (sum (map (lambda (x) (* (/ 1 (length knowledge-state)) (log x))) state-probs))))))

(define (speaker-utility knowledge-state utterance prosody depth)
  (let ((utterance-dist (zip utterances (map (noise-model utterance prosody) utterances))))
    (let ((utterance-dist (filter (lambda (x) (> (second x) 0)) utterance-dist)))
      (let ((listeners (map (lambda (x) (listener (first x) prosody (- depth 1))) utterance-dist)))
        (let ((surprisals (map (lambda (x) (get-expected-surprisal knowledge-state x)) listeners)))
          (sum (map (lambda (x y) (* (second x) y)) utterance-dist surprisals)))))))

(define (speaker-literal-evaluate knowledge-state utterance)
  (let ((truth-value (all (map (lambda (x) (literal-evaluation utterance x)) knowledge-state))))
    (if truth-value

(define speaker
  (mem (lambda (knowledge-state depth)
          (define utterance (utterance-prior))
          (define prosody (prosody-prior))
          (list (sample-noise-model utterance prosody) prosody)
          (factor (+ (* (- hardness 1) (log (get-utterance-prob utterance)))
                     (* (- hardness 1) (log (get-prosody-prob prosody)))
                     (* hardness (speaker-utility knowledge-state utterance prosody depth))))))))

(define listener
  (mem (lambda (utterance prosody depth)
          (define knowledge-state (knowledge-prior))
          (define state (sample-from-knowledge-state knowledge-state))
          (list knowledge-state state)
          (if (equal? depth 0)
              (let ((intended-utterance (utterance-prior)))
                (and (equal? utterance (sample-noise-model intended-utterance prosody))
                     (literal-evaluation intended-utterance state)))
              (equal? (list utterance prosody) (apply multinomial (speaker knowledge-state depth))))))))

(define hardness 2)

(map first (map (lambda (x) (second (listener 'bob #f x))) (list 0 1 2 3 4 5 6 7 8 9 10 11 12)))