OverviewFilesCommitsIssuesDocsReleasesPeers

hypercore-kb / opencog-kb / language-learning / mvp / test-pmfg-final.scm

148 lines · scm ref:
;;
;; test-pmfg-final.scm - Clean GPU vs CPU PMFG comparison
;;
;; Use unique variable names to avoid CogServer state contamination
;;

(use-modules (opencog) (opencog exec))
(use-modules (opencog sensory) (opencog opencl))
(use-modules (ice-9 format))

(display "\n")
(display "════════════════════════════════════════════════════════════════\n")
(display "  GPU vs CPU PMFG - Final Verification\n")
(display "════════════════════════════════════════════════════════════════\n\n")

;; ═══════════════════════════════════════════════════════════════════════
;; Test data: 5 words with known MI values
;; ═══════════════════════════════════════════════════════════════════════

(define final-mi-matrix
  (list 0.0 5.0 1.0 0.5 0.1    ; word 0
        5.0 0.0 4.0 0.8 0.2    ; word 1
        1.0 4.0 0.0 3.0 0.3    ; word 2
        0.5 0.8 3.0 0.0 2.0    ; word 3
        0.1 0.2 0.3 2.0 0.0))  ; word 4

(display "MI Matrix (5x5, symmetric):\n")
(display "  [0-1]=5.0  [1-2]=4.0  [2-3]=3.0  [3-4]=2.0  [0-2]=1.0\n\n")

;; ═══════════════════════════════════════════════════════════════════════
;; GPU PMFG
;; ═══════════════════════════════════════════════════════════════════════

(display "═══ GPU PMFG ═══\n\n")

(define final-gpu (OpenclNode "opencl://:/storage/projects/code/hypercore-kb/opencog-kb/language-learning/mvp/pmfg-kernel.cl"))

;; Anchor for output
(define final-anchor (Anchor "final-pmfg"))
(cog-set-value! final-anchor (Predicate "out-edges")
  (OpenclFloatValue 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))
(cog-set-value! final-anchor (Predicate "out-n")
  (OpenclFloatValue 0))

;; Run
(define final-start (get-internal-real-time))

(cog-execute!
  (SetValue final-gpu (Predicate "*-write-*")
    (Section (Item "pmfg_single")
             (ConnectorSeq
               (apply Number final-mi-matrix)
               (Number 0 1 2 3 4)
               (Number 5)
               (Number 5)
               (ValueOf final-anchor (Predicate "out-edges"))
               (ValueOf final-anchor (Predicate "out-n"))))))

(cog-execute! (ValueOf final-gpu (Predicate "*-read-*")))

(define final-elapsed (/ (- (get-internal-real-time) final-start)
                         internal-time-units-per-second))

;; Extract
(define final-edges-raw (cog-execute! (ValueOf final-anchor (Predicate "out-edges"))))
(define final-n-raw (cog-execute! (ValueOf final-anchor (Predicate "out-n"))))
(define final-n-edges (inexact->exact (round (cog-value-ref final-n-raw 0))))

(format #t "GPU execution time: ~,3f seconds~%" final-elapsed)
(format #t "GPU found ~a edges:~%" final-n-edges)

(do ((i 0 (+ i 1))) ((= i final-n-edges))
  (let ((p1 (inexact->exact (round (cog-value-ref final-edges-raw (* i 2)))))
        (p2 (inexact->exact (round (cog-value-ref final-edges-raw (+ (* i 2) 1))))))
    (format #t "  [~a-~a]~%" p1 p2)))

;; ═══════════════════════════════════════════════════════════════════════
;; CPU PMFG (clean implementation)
;; ═══════════════════════════════════════════════════════════════════════

(display "\n═══ CPU PMFG ═══\n\n")

(define (final-crosses? i1 j1 i2 j2)
  (let ((a (min i1 j1)) (b (max i1 j1))
        (c (min i2 j2)) (d (max i2 j2)))
    (or (and (< a c) (< c b) (< b d))
        (and (< c a) (< a d) (< d b)))))

(define final-cpu-start (get-internal-real-time))

;; Build pairs
(define final-pairs '())
(do ((i 0 (+ i 1))) ((= i 5))
  (do ((j (+ i 1) (+ j 1))) ((= j 5))
    (let ((mi (list-ref final-mi-matrix (+ (* i 5) j))))
      (set! final-pairs (cons (list mi i j) final-pairs)))))

;; Sort descending by MI
(set! final-pairs (sort final-pairs (lambda (a b) (> (car a) (car b)))))

;; Greedy PMFG
(define final-cpu-edges '())
(for-each
  (lambda (p)
    (when (< (length final-cpu-edges) 9)  ; max 3*5-6 = 9
      (let ((pos1 (cadr p)) (pos2 (caddr p)) (ok #t))
        (for-each
          (lambda (e)
            (when (final-crosses? pos1 pos2 (car e) (cadr e))
              (set! ok #f)))
          final-cpu-edges)
        (when ok
          (set! final-cpu-edges (cons (list pos1 pos2) final-cpu-edges))))))
  final-pairs)

(define final-cpu-elapsed (/ (- (get-internal-real-time) final-cpu-start)
                             internal-time-units-per-second))

(format #t "CPU execution time: ~,3f seconds~%" final-cpu-elapsed)
(format #t "CPU found ~a edges:~%" (length final-cpu-edges))

(for-each
  (lambda (e) (format #t "  [~a-~a]~%" (car e) (cadr e)))
  (reverse final-cpu-edges))

;; ═══════════════════════════════════════════════════════════════════════
;; Comparison
;; ═══════════════════════════════════════════════════════════════════════

(display "\n═══ COMPARISON ═══\n\n")

(if (= final-n-edges (length final-cpu-edges))
    (format #t "✓ Edge counts match: ~a edges~%" final-n-edges)
    (format #t "✗ Edge counts differ: GPU=~a, CPU=~a~%"
            final-n-edges (length final-cpu-edges)))

(display "\nExpected edges (by greedy PMFG on MI):\n")
(display "  1. [0-1] MI=5.0 (highest)\n")
(display "  2. [1-2] MI=4.0\n")
(display "  3. [2-3] MI=3.0\n")
(display "  4. [3-4] MI=2.0\n")
(display "  5. [0-2] MI=1.0 (no crossing)\n")
(display "  6. [1-3] MI=0.8 ← crosses [0-2], skip\n")
(display "  7. [0-3] MI=0.5 (no crossing)\n")
(display "  8. [2-4] ← crosses [0-3], skip\n")
(display "  9. [0-4] MI=0.1 (no crossing)\n")
(display "\nExpected 7 edges: [0-1],[1-2],[2-3],[3-4],[0-2],[0-3],[0-4]\n")