OverviewFilesCommitsIssuesDocsReleasesPeers

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

126 lines · scm ref:
;;
;; test-pmfg-minimal.scm - Minimal PMFG test
;;

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

(display "\n=== Minimal PMFG Test ===\n\n")

;; Build a tiny 5x5 MI matrix with known values
;; Words: 0="the", 1="cat", 2="sat", 3="on", 4="mat"
;; MI values set to favor: the-cat, cat-sat, sat-on, on-mat (consecutive)

(define vocab 5)
(define mi-vals
  (list
    ;; Row 0: the
    0.0 5.0 1.0 0.5 0.1   ; the-cat=5.0 is highest
    ;; Row 1: cat
    5.0 0.0 4.0 0.8 0.2   ; cat-sat=4.0
    ;; Row 2: sat
    1.0 4.0 0.0 3.0 0.3   ; sat-on=3.0
    ;; Row 3: on
    0.5 0.8 3.0 0.0 2.0   ; on-mat=2.0
    ;; Row 4: mat
    0.1 0.2 0.3 2.0 0.0))

(display "Test sentence: the cat sat on mat (indices 0 1 2 3 4)\n")
(display "Expected PMFG edges (by MI, no crossings):\n")
(display "  [0-1] the-cat MI=5.0\n")
(display "  [1-2] cat-sat MI=4.0\n")
(display "  [2-3] sat-on MI=3.0\n")
(display "  [3-4] on-mat MI=2.0\n")
(display "  Max edges = 3*5-6 = 9\n\n")

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

;; Parameters matching kernel signature:
;; pmfg_single(mi_matrix, words, n_words_arr, vocab_size_arr, pmfg_edges, n_edges_out, sz)

(define mi-matrix (apply Number mi-vals))
(define words (Number 0 1 2 3 4))
(define n-words (Number 5))
(define vocab-size (Number 5))
(define edges-out (Number 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))  ; 9 edges * 2
(define n-edges-out (Number 0))

(display "Running GPU kernel...\n")
(define start (get-internal-real-time))

(cog-execute!
  (SetValue gpu (Predicate "*-write-*")
    (Section (Item "pmfg_single")
             (ConnectorSeq mi-matrix words n-words vocab-size edges-out n-edges-out))))

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

(define elapsed (/ (- (get-internal-real-time) start) internal-time-units-per-second))
(format #t "GPU time: ~,3f seconds~%~%" elapsed)

;; Parse result
(display "GPU Result:\n")
(display result)
(newline)

;; The result is a Section with the output values
;; Let's extract the pmfg_edges and n_edges
(define args (cog-value-ref result 1))  ; ConnectorSeq or LinkValue
(format #t "~%Args type: ~a~%" (cog-type args))

;; The output arrays are at positions 4 and 5 (0-indexed)
(define edges-val (cog-value-ref args 4))
(define nedges-val (cog-value-ref args 5))

(format #t "~%Edges output: ~a~%" edges-val)
(format #t "N-edges output: ~a~%~%" nedges-val)

;; CPU verification
(display "=== CPU PMFG for comparison ===\n\n")

(define (get-mi i j)
  (list-ref mi-vals (+ (* i vocab) j)))

;; Get pairs sorted by MI
(define pairs '())
(do ((i 0 (+ i 1))) ((= i 5))
  (do ((j (+ i 1) (+ j 1))) ((= j 5))
    (set! pairs (cons (list (get-mi i j) i j) pairs))))

(set! pairs (sort pairs (lambda (a b) (> (car a) (car b)))))

(display "Pairs by MI (descending):\n")
(for-each
  (lambda (p)
    (format #t "  [~a-~a] MI=~a~%" (cadr p) (caddr p) (car p)))
  pairs)

;; Greedy selection
(define (crosses? i j k l)
  (let ((a (min i j)) (b (max i j))
        (c (min k l)) (d (max k l)))
    (or (and (< a c) (< c b) (< b d))
        (and (< c a) (< a d) (< d b)))))

(define cpu-edges '())
(for-each
  (lambda (p)
    (when (< (length cpu-edges) 9)
      (let ((pos1 (cadr p)) (pos2 (caddr p)) (ok #t))
        (for-each
          (lambda (e)
            (when (crosses? pos1 pos2 (car e) (cadr e))
              (set! ok #f)))
          cpu-edges)
        (when ok
          (set! cpu-edges (cons (list pos1 pos2) cpu-edges))))))
  pairs)

(display "\nCPU PMFG edges:\n")
(for-each
  (lambda (e) (format #t "  [~a-~a]~%" (car e) (cadr e)))
  (reverse cpu-edges))
(format #t "Total: ~a edges~%" (length cpu-edges))