OverviewFilesCommitsIssuesDocsReleasesPeers

hypercore-kb / opencog-kb / language-learning / concepts / typicality-surprise.scm

328 lines · scm ref:
;
; typicality-surprise.scm
;
; Encoding ASSUMPTIONS and TYPICALITY:
; - What is typical behavior for an agent type?
; - When is an interpretation SURPRISING?
; - How do priors shift based on who/what is the subject?
;

(use-modules (srfi srfi-1))
(use-modules (ice-9 format))
(use-modules (ice-9 rdelim))

(display "═══════════════════════════════════════════════════════════════════\n")
(display "   TYPICALITY, ASSUMPTIONS, AND SURPRISE                           \n")
(display "═══════════════════════════════════════════════════════════════════\n\n")

;; ═══════════════════════════════════════════════════════════════════
;; THE KEY INSIGHT
;; ═══════════════════════════════════════════════════════════════════

(display "THE INSIGHT:\n")
(display "─────────────────────────────────────────────────────────────────\n\n")

(display "  'The penguin swam to the bank'\n")
(display "  'The man walked to the bank'\n\n")

(display "  Same structure, but different PRIORS based on subject:\n\n")

(display "  PENGUIN assumptions (from corpus statistics):\n")
(display "    P(swim | penguin) = 0.85        (penguins swim a lot)\n")
(display "    P(use_financial | penguin) = 0.001 (penguins don't bank)\n")
(display "    P(be_near_water | penguin) = 0.90  (penguins live near water)\n\n")

(display "  HUMAN assumptions:\n")
(display "    P(swim | human) = 0.15          (humans sometimes swim)\n")
(display "    P(use_financial | human) = 0.70 (humans often use banks)\n")
(display "    P(be_near_water | human) = 0.30 (humans live various places)\n\n")

;; ═══════════════════════════════════════════════════════════════════
;; AGENT-TYPE KNOWLEDGE BASE
;; ═══════════════════════════════════════════════════════════════════

(display "═══════════════════════════════════════════════════════════════════\n")
(display "AGENT-TYPE KNOWLEDGE (learnable from corpus)\n")
(display "─────────────────────────────────────────────────────────────────\n\n")

;; This would be learned by counting "penguin + verb" patterns
(define agent-priors (make-hash-table))

;; PENGUIN priors
(hash-set! agent-priors '(penguin swim) 0.85)
(hash-set! agent-priors '(penguin walk) 0.40)
(hash-set! agent-priors '(penguin fly) 0.01)
(hash-set! agent-priors '(penguin deposit) 0.001)
(hash-set! agent-priors '(penguin withdraw) 0.001)
(hash-set! agent-priors '(penguin be-near-water) 0.90)
(hash-set! agent-priors '(penguin be-near-financial) 0.001)
(hash-set! agent-priors '(penguin use-money) 0.001)

;; HUMAN priors
(hash-set! agent-priors '(human swim) 0.15)
(hash-set! agent-priors '(human walk) 0.95)
(hash-set! agent-priors '(human fly) 0.001)  ; without plane
(hash-set! agent-priors '(human deposit) 0.60)
(hash-set! agent-priors '(human withdraw) 0.65)
(hash-set! agent-priors '(human be-near-water) 0.30)
(hash-set! agent-priors '(human be-near-financial) 0.70)
(hash-set! agent-priors '(human use-money) 0.95)

;; DOG priors
(hash-set! agent-priors '(dog swim) 0.40)
(hash-set! agent-priors '(dog walk) 0.80)
(hash-set! agent-priors '(dog deposit) 0.001)
(hash-set! agent-priors '(dog be-near-water) 0.35)
(hash-set! agent-priors '(dog be-near-financial) 0.05)

;; FISH priors
(hash-set! agent-priors '(fish swim) 0.99)
(hash-set! agent-priors '(fish walk) 0.001)
(hash-set! agent-priors '(fish deposit) 0.0001)
(hash-set! agent-priors '(fish be-near-water) 0.999)
(hash-set! agent-priors '(fish be-near-financial) 0.0001)

(define (get-prior agent action)
  (hash-ref agent-priors (list agent action) 0.5))

(display "  Agent    │ swim  │ deposit │ near-water │ near-financial\n")
(display "  ─────────┼───────┼─────────┼────────────┼───────────────\n")
(format #t "  penguin  │ ~,2f  │  ~,3f   │    ~,2f    │     ~,3f\n"
  (get-prior 'penguin 'swim) (get-prior 'penguin 'deposit)
  (get-prior 'penguin 'be-near-water) (get-prior 'penguin 'be-near-financial))
(format #t "  human    │ ~,2f  │  ~,2f   │    ~,2f    │     ~,2f\n"
  (get-prior 'human 'swim) (get-prior 'human 'deposit)
  (get-prior 'human 'be-near-water) (get-prior 'human 'be-near-financial))
(format #t "  dog      │ ~,2f  │  ~,3f   │    ~,2f    │     ~,2f\n"
  (get-prior 'dog 'swim) (get-prior 'dog 'deposit)
  (get-prior 'dog 'be-near-water) (get-prior 'dog 'be-near-financial))
(format #t "  fish     │ ~,2f  │  ~,4f  │    ~,3f   │     ~,4f\n\n"
  (get-prior 'fish 'swim) (get-prior 'fish 'deposit)
  (get-prior 'fish 'be-near-water) (get-prior 'fish 'be-near-financial))

;; ═══════════════════════════════════════════════════════════════════
;; SURPRISE METRIC
;; ═══════════════════════════════════════════════════════════════════

(display "═══════════════════════════════════════════════════════════════════\n")
(display "THE SURPRISE METRIC\n")
(display "─────────────────────────────────────────────────────────────────\n\n")

(display "  SURPRISE = -log₂(P(interpretation | agent_type))\n\n")

(display "  Low surprise (< 2 bits)  → typical, expected behavior\n")
(display "  Medium surprise (2-5)    → somewhat unusual\n")
(display "  High surprise (> 5 bits) → very atypical, possibly intentional\n\n")

(define (surprise prob)
  (if (> prob 0)
      (- (/ (log prob) (log 2)))
      99.0))  ; Very high surprise for impossible events

(display "  Examples:\n")
(format #t "    P=0.85 (penguin swim)      → surprise = ~,1f bits (expected)\n" (surprise 0.85))
(format #t "    P=0.50 (coin flip)         → surprise = ~,1f bits (uncertain)\n" (surprise 0.50))
(format #t "    P=0.15 (human swim)        → surprise = ~,1f bits (less common)\n" (surprise 0.15))
(format #t "    P=0.01 (penguin fly)       → surprise = ~,1f bits (rare)\n" (surprise 0.01))
(format #t "    P=0.001 (penguin deposit)  → surprise = ~,1f bits (absurd)\n\n" (surprise 0.001))

;; ═══════════════════════════════════════════════════════════════════
;; DISAMBIGUATION WITH AGENT-SPECIFIC PRIORS
;; ═══════════════════════════════════════════════════════════════════

(display "═══════════════════════════════════════════════════════════════════\n")
(display "DISAMBIGUATION WITH AGENT-SPECIFIC PRIORS\n")
(display "─────────────────────────────────────────────────────────────────\n\n")

(define (disambiguate-bank agent verb)
  (display "───────────────────────────────────────────────────────────────────\n")
  (format #t "  'The ~a ~a to the bank'\n\n" agent verb)

  ;; Compute priors for each interpretation
  (let* ((p-verb (get-prior agent verb))
         (p-near-water (get-prior agent 'be-near-water))
         (p-near-financial (get-prior agent 'be-near-financial))
         (p-use-money (get-prior agent 'use-money))

         ;; GEOGRAPHIC interpretation plausibility
         ;; Agent does verb + ends up near water
         (p-geographic (* p-verb p-near-water))

         ;; FINANCIAL interpretation plausibility
         ;; Agent does verb + ends up at financial institution + uses money
         (p-financial (* p-verb p-near-financial p-use-money))

         ;; Normalize
         (p-total (+ p-geographic p-financial))
         (p-geo-norm (if (> p-total 0) (/ p-geographic p-total) 0.5))
         (p-fin-norm (if (> p-total 0) (/ p-financial p-total) 0.5))

         ;; Surprise for each interpretation
         (surprise-geo (surprise p-geo-norm))
         (surprise-fin (surprise p-fin-norm)))

    (format #t "  Agent priors for '~a':\n" agent)
    (format #t "    P(~a) = ~,2f\n" verb p-verb)
    (format #t "    P(near-water) = ~,2f\n" p-near-water)
    (format #t "    P(near-financial) = ~,2f\n" p-near-financial)
    (format #t "    P(use-money) = ~,2f\n\n" p-use-money)

    (display "  Interpretation scores:\n")
    (format #t "    GEOGRAPHIC: ~,4f → normalized: ~,1f% → surprise: ~,1f bits\n"
            p-geographic (* 100 p-geo-norm) surprise-geo)
    (format #t "    FINANCIAL:  ~,4f → normalized: ~,1f% → surprise: ~,1f bits\n\n"
            p-financial (* 100 p-fin-norm) surprise-fin)

    ;; Decision
    (cond
      ;; Clear winner with low surprise
      ((and (> p-geo-norm 0.8) (< surprise-geo 2))
       (display "  ┌─────────────────────────────────────────────────────────┐\n")
       (format #t "  │  RESULT: bank = GEOGRAPHIC (river bank)               │\n")
       (format #t "  │  CONFIDENCE: HIGH (~,0f%)                              │\n" (* 100 p-geo-norm))
       (display "  │  SURPRISE: LOW (typical behavior)                      │\n")
       (display "  │  ASSUMPTION: This is what we'd expect                  │\n")
       (display "  └─────────────────────────────────────────────────────────┘\n\n"))

      ((and (> p-fin-norm 0.8) (< surprise-fin 2))
       (display "  ┌─────────────────────────────────────────────────────────┐\n")
       (format #t "  │  RESULT: bank = FINANCIAL                              │\n")
       (format #t "  │  CONFIDENCE: HIGH (~,0f%)                              │\n" (* 100 p-fin-norm))
       (display "  │  SURPRISE: LOW (typical behavior)                      │\n")
       (display "  │  ASSUMPTION: This is what we'd expect                  │\n")
       (display "  └─────────────────────────────────────────────────────────┘\n\n"))

      ;; High surprise - flag as unusual
      ((and (> p-fin-norm 0.5) (> surprise-fin 5))
       (display "  ┌─────────────────────────────────────────────────────────┐\n")
       (format #t "  │  RESULT: bank = FINANCIAL (but SURPRISING!)           │\n")
       (format #t "  │  CONFIDENCE: ~,0f%                                     │\n" (* 100 p-fin-norm))
       (format #t "  │  SURPRISE: HIGH (~,1f bits)                            │\n" surprise-fin)
       (display "  │  ⚠️  This is ATYPICAL - might be humor/fiction/error    │\n")
       (display "  └─────────────────────────────────────────────────────────┘\n\n"))

      ;; Ambiguous - priors don't help enough
      (else
       (display "  ┌─────────────────────────────────────────────────────────┐\n")
       (format #t "  │  RESULT: AMBIGUOUS                                     │\n")
       (format #t "  │  GEOGRAPHIC: ~,0f%  FINANCIAL: ~,0f%                    │\n"
               (* 100 p-geo-norm) (* 100 p-fin-norm))
       (display "  │  Need more context to disambiguate                     │\n")
       (display "  └─────────────────────────────────────────────────────────┘\n\n")))))

;; Test cases
(disambiguate-bank 'penguin 'swim)
(disambiguate-bank 'human 'walk)
(disambiguate-bank 'human 'swim)
(disambiguate-bank 'dog 'walk)
(disambiguate-bank 'fish 'swim)

;; ═══════════════════════════════════════════════════════════════════
;; DETECTING SURPRISING SENTENCES
;; ═══════════════════════════════════════════════════════════════════

(display "═══════════════════════════════════════════════════════════════════\n")
(display "SURPRISING SENTENCES (intentionally absurd?)\n")
(display "─────────────────────────────────────────────────────────────────\n\n")

(display "  'The penguin deposited money at the bank'\n\n")

(let* ((p-deposit (get-prior 'penguin 'deposit))
       (p-money (get-prior 'penguin 'use-money))
       (p-combined (* p-deposit p-money))
       (surp (surprise p-combined)))
  (format #t "    P(penguin deposits money) = ~,6f\n" p-combined)
  (format #t "    Surprise = ~,1f bits\n\n" surp)
  (display "    This is EXTREMELY surprising!\n")
  (display "    Possible interpretations:\n")
  (display "      1. Humor/joke\n")
  (display "      2. Children's story\n")
  (display "      3. Error in text\n")
  (display "      4. Metaphorical penguin (Linux mascot?)\n\n"))

(display "  'The fish swam to the bank'\n\n")

(let* ((p-swim (get-prior 'fish 'swim))
       (p-water (get-prior 'fish 'be-near-water))
       (p-geo (* p-swim p-water))
       (surp (surprise p-geo)))
  (format #t "    P(fish swims near water) = ~,3f\n" p-geo)
  (format #t "    Surprise = ~,2f bits\n\n" surp)
  (display "    This is COMPLETELY EXPECTED!\n")
  (display "    bank = GEOGRAPHIC with ~100% confidence\n\n"))

;; ═══════════════════════════════════════════════════════════════════
;; HOW TO LEARN THESE PRIORS FROM CORPUS
;; ═══════════════════════════════════════════════════════════════════

(display "═══════════════════════════════════════════════════════════════════\n")
(display "HOW TO LEARN AGENT PRIORS FROM CORPUS\n")
(display "─────────────────────────────────────────────────────────────────\n\n")

(display "METHOD: Count agent-verb patterns\n\n")

(display "  Step 1: Extract (subject, verb) pairs from parsed sentences\n")
(display "    'The penguin swam quickly' → (penguin, swim)\n")
(display "    'The man deposited his check' → (man, deposit)\n")
(display "    'A fish jumped out of water' → (fish, jump)\n\n")

(display "  Step 2: Cluster subjects by type\n")
(display "    BIRD-cluster: {penguin, eagle, sparrow, ...}\n")
(display "    MAMMAL-cluster: {human, dog, cat, ...}\n")
(display "    FISH-cluster: {salmon, trout, fish, ...}\n\n")

(display "  Step 3: Count verbs per agent-type\n")
(display "    C(BIRD, swim) = 1,200\n")
(display "    C(BIRD, fly) = 45,000\n")
(display "    C(BIRD, deposit) = 5  (probably metaphorical/errors)\n\n")

(display "  Step 4: Normalize to get P(verb | agent-type)\n")
(display "    P(swim | BIRD) = 1,200 / total-bird-verbs\n")
(display "    P(deposit | BIRD) = 5 / total-bird-verbs ≈ 0.0001\n\n")

(display "  Step 5: Also count location associations\n")
(display "    C(BIRD, near-water) from 'bird at/by/in water/river/lake'\n")
(display "    C(BIRD, near-financial) from 'bird at/in bank/ATM/teller'\n\n")

(display "  This is ALL just counting! The assumptions emerge from statistics.\n\n")

;; ═══════════════════════════════════════════════════════════════════
;; THE COMPLETE PICTURE
;; ═══════════════════════════════════════════════════════════════════

(display "═══════════════════════════════════════════════════════════════════\n")
(display "THE COMPLETE DISAMBIGUATION FORMULA\n")
(display "─────────────────────────────────────────────────────────────────\n\n")

(display "  P(sense | sentence) ∝ P(sense) × P(sentence | sense)\n\n")

(display "  Where:\n")
(display "    P(sense) = prior from:\n")
(display "      - Base word frequency (bank=financial 75% of time)\n")
(display "      - Agent-specific priors (penguin → water-related)\n")
(display "      - Document context (nature doc → geographic)\n\n")

(display "    P(sentence | sense) = likelihood from:\n")
(display "      - Lexical evidence (PMI of word pairs)\n")
(display "      - Syntactic evidence (grammatical roles)\n")
(display "      - Spatial evidence (prepositions)\n")
(display "      - Temporal evidence (event sequences)\n")
(display "      - Modal evidence (can/must/might)\n")
(display "      - Selectional evidence (verb-argument fit)\n\n")

(display "  And we ALSO compute:\n")
(display "    VAGUENESS = 1 / (1 + total_evidence)\n")
(display "    SURPRISE = -log₂(P(best_interpretation))\n\n")

(display "  ┌─────────────────────────────────────────────────────────────┐\n")
(display "  │                                                             │\n")
(display "  │  VAGUENESS tells us: Do we have enough information?        │\n")
(display "  │  SURPRISE tells us: Is this interpretation expected?       │\n")
(display "  │                                                             │\n")
(display "  │  High vagueness → SEARCH for context or ASK               │\n")
(display "  │  High surprise → FLAG as unusual (humor? error? fiction?) │\n")
(display "  │                                                             │\n")
(display "  │  Both metrics are INFORMATION about the sentence itself.   │\n")
(display "  │                                                             │\n")
(display "  └─────────────────────────────────────────────────────────────┘\n\n")