;;
;; exp9-compare-polysemy.scm — Compare All Polysemy Detection Approaches
;;
;; Loads and runs all 4 approaches, then produces a comparison table.
;;
;; Usage:
;; (load "experiments/exp9-compare-polysemy.scm")
;; (compare-polysemy-approaches)
;;
;; Load all polysemy experiments
(let ((exp-dir (string-append *mvp-dir* "/experiments/")))
(for-each
(lambda (file)
(format #t "Loading ~a...~%" file)
(load (string-append exp-dir file)))
(list "exp9b-word-polysemy.scm"
"exp9c-mi-neighborhood.scm"
"exp9d-class-centrality.scm"
"exp9e-connector-entropy.scm")))
(define (compare-polysemy-approaches)
"Run all 4 polysemy detection approaches and compare results."
(format #t "~%╔══════════════════════════════════════════════════════════╗~%")
(format #t "║ POLYSEMY DETECTION: 4-Approach Comparison ║~%")
(format #t "╚══════════════════════════════════════════════════════════╝~%~%")
;; Ensure exp7 data is available (all approaches depend on it)
(when (null? *exp7-compartments*)
(format #t "Running exp7 first (needed by all approaches)...~%~%")
(run-exp7))
;; Run all 4 approaches
(format #t "~%════ Running Approach 1: Word-Level Connector Cosine ════~%")
(run-exp9b)
(format #t "~%════ Running Approach 2: MI Neighborhood Divergence ════~%")
(run-exp9c)
(format #t "~%════ Running Approach 3: Class Centrality Difference ════~%")
(run-exp9d)
(format #t "~%════ Running Approach 4: Connector Entropy / JSD ════~%")
(run-exp9e)
;; ── Comparison Table ──
(format #t "~%~%")
(format #t "╔══════════════════════════════════════════════════════════════════════════╗~%")
(format #t "║ COMPARISON OF ALL APPROACHES ║~%")
(format #t "╚══════════════════════════════════════════════════════════════════════════╝~%~%")
;; Extract results
(let* ((approaches
(list
(list "9a: Class cosine"
(if (null? *exp9-results*)
(list 0 1 0 '() '() #f)
;; Normalize: exp9 = (aligned poly aligns-list poly-list passed)
;; Convert to (analyzed poly stable poly-list stable-list passed)
(list (list-ref *exp9-results* 0) ; aligned as "analyzed"
(list-ref *exp9-results* 1) ; polysemy count
0 ; no stable metric
(list-ref *exp9-results* 3) ; polysemy list
'() ; no stable list
(list-ref *exp9-results* 4))) ; passed
"Compare connector profiles of CLASSES across compartments"
"Polysemy = word in classes with cosine < 0.1")
(list "9b: Word connector"
(if (null? *exp9b-results*)
(list 0 0 0 '() '() #f)
*exp9b-results*)
"Compare a WORD's own connector vector across compartments"
"Polysemy = word connector-cosine < 0.3")
(list "9c: MI neighborhood"
(if (null? *exp9c-results*)
(list 0 0 0 '() '() #f)
*exp9c-results*)
"Compare a word's MI partners across compartments"
"Polysemy = MI-neighborhood cosine < 0.3")
(list "9d: Centrality diff"
(if (null? *exp9d-results*)
(list 0 0 0 '() '() #f)
*exp9d-results*)
"Compare word's distance to class centroid across compartments"
"Polysemy = centrality difference > 0.4")
(list "9e: Entropy/JSD"
(if (null? *exp9e-results*)
(list 0 0 0 '() '() #f)
*exp9e-results*)
"Compare connector entropy + Jensen-Shannon divergence"
"Polysemy = JSD > 0.3"))))
;; Summary table
(format #t "┌────────────────────────┬─────────┬──────────┬─────────┬──────────┐~%")
(format #t "│ Approach │ Analyzed│ Polysemy │ Stable │ Verdict │~%")
(format #t "├────────────────────────┼─────────┼──────────┼─────────┼──────────┤~%")
(for-each
(lambda (a)
(let* ((name (list-ref a 0))
(results (list-ref a 1))
(analyzed (list-ref results 0))
(polysemy (list-ref results 1))
(stable (list-ref results 2))
(passed (list-ref results 5)))
(format #t "│ ~22a │ ~7a │ ~8a │ ~7a │ ~8a │~%"
name analyzed polysemy stable
(if passed "PASS" "FAIL"))))
approaches)
(format #t "└────────────────────────┴─────────┴──────────┴─────────┴──────────┘~%")
;; What each approach measures
(format #t "~%── What Each Approach Measures ──~%")
(for-each
(lambda (a)
(format #t "~% ~a:~%" (list-ref a 0))
(format #t " Method: ~a~%" (list-ref a 2))
(format #t " Signal: ~a~%" (list-ref a 3)))
approaches)
;; Cross-approach agreement: which words appear as polysemy candidates in multiple approaches?
(format #t "~%── Cross-Approach Agreement ──~%")
(let ((word-votes (make-hash-table))
(word-approaches (make-hash-table)))
;; Count how many approaches flag each word
(let ((approach-names (list "9a" "9b" "9c" "9d" "9e"))
(approach-results (list *exp9-results* *exp9b-results*
*exp9c-results* *exp9d-results*
*exp9e-results*)))
(do ((i 0 (+ i 1))) ((>= i 5))
(let ((results (list-ref approach-results i))
(aname (list-ref approach-names i)))
(unless (null? results)
(let ((candidates (list-ref results 3)))
(for-each
(lambda (c)
(let ((word (if (and (= i 0) (pair? c))
(list-ref c 0) ; exp9 format: (word name-a ci-a ...)
(list-ref c 0)))) ; exp9b-e format: (word ...)
(hash-set! word-votes word
(+ (hash-ref word-votes word 0) 1))
(hash-set! word-approaches word
(cons aname (hash-ref word-approaches word '())))))
candidates))))))
;; Show words flagged by multiple approaches
(let ((multi-flagged '()))
(hash-for-each
(lambda (word votes)
(when (>= votes 2)
(set! multi-flagged
(cons (list word votes (hash-ref word-approaches word '()))
multi-flagged))))
word-votes)
(set! multi-flagged
(sort multi-flagged (lambda (a b) (> (cadr a) (cadr b)))))
(if (null? multi-flagged)
(format #t " No words flagged by 2+ approaches.~%")
(begin
(format #t " Words flagged by multiple approaches:~%")
(for-each
(lambda (mf)
(format #t " ~15a flagged by ~a/5 approaches (~a)~%"
(list-ref mf 0)
(list-ref mf 1)
(string-join (reverse (list-ref mf 2)) ", ")))
multi-flagged)))
;; Also show ALL unique polysemy words across all approaches
(let ((all-poly-words '()))
(hash-for-each
(lambda (word _) (set! all-poly-words (cons word all-poly-words)))
word-votes)
(format #t "~% Total unique polysemy words across all approaches: ~a~%"
(length all-poly-words))
(format #t " Multi-approach agreement: ~a/~a (~,0f%)~%"
(length multi-flagged) (length all-poly-words)
(if (> (length all-poly-words) 0)
(* 100.0 (/ (length multi-flagged) (length all-poly-words)))
0.0)))))
;; Recommendation
(format #t "~%── RECOMMENDATION ──~%")
(let* ((results-list (list *exp9b-results* *exp9c-results*
*exp9d-results* *exp9e-results*))
(n-passed (length (filter (lambda (r)
(and (not (null? r)) (list-ref r 5)))
results-list)))
(best-approach
(let ((best-name "none") (best-count 0))
(for-each
(lambda (name results)
(unless (null? results)
(when (> (list-ref results 1) best-count)
(set! best-count (list-ref results 1))
(set! best-name name))))
(list "9b" "9c" "9d" "9e")
results-list)
(cons best-name best-count))))
(format #t "~% ~a/4 new approaches passed (≥3 polysemy candidates)~%" n-passed)
(format #t " Best approach: ~a with ~a candidates~%"
(car best-approach) (cdr best-approach))
(cond
((>= n-passed 3)
(format #t "~% Multiple approaches confirm polysemy → use ensemble (vote ≥ 2)~%"))
((>= n-passed 1)
(format #t "~% Some approaches find polysemy → use best single approach for compartment.scm~%"))
(else
(format #t "~% No approach reliably finds polysemy at this scale → ~%")
(format #t " polysemy detection needs more data (>1000 sentences/compartment)~%")))
;; Write comparison results
(let ((out-file (string-append *mvp-dir* "/experiments/results/exp9-comparison.txt")))
(call-with-output-file out-file
(lambda (port)
(format port "# Polysemy Detection Approach Comparison~%")
(format port "# Date: ~a~%" (strftime "%Y-%m-%d %H:%M:%S" (localtime (current-time))))
(format port "#~%")
(for-each
(lambda (a)
(let ((results (list-ref a 1)))
(format port "approach: ~a analyzed=~a polysemy=~a stable=~a verdict=~a~%"
(list-ref a 0) (list-ref results 0) (list-ref results 1)
(list-ref results 2) (if (list-ref results 5) "PASS" "FAIL"))))
approaches)
(format port "#~%")
(format port "best_approach: ~a~%" (car best-approach))
(format port "best_count: ~a~%" (cdr best-approach))
(format port "n_passed: ~a~%" n-passed)))
(format #t "~%Comparison written to ~a~%" out-file)))))
(format #t "~%═══ Polysemy Comparison Loaded ═══~%")
(format #t " (compare-polysemy-approaches) Run all 4 + compare~%")
(format #t " (run-exp9b) Word connector cosine~%")
(format #t " (run-exp9c) MI neighborhood divergence~%")
(format #t " (run-exp9d) Class centrality difference~%")
(format #t " (run-exp9e) Connector entropy / JSD~%")
(format #t "═══════════════════════════════════════════════════════~%~%")