Simple clinical reasoning using Kanren

Here’s an example of construction of a tiny ontology and use of a particularly robust logic programming system — Dan Friedman and Oleg Kiselyov’s Kanren and a functional language like Scheme:

;; Assert a few simple facts
(define causes
  (extend-relation (a1 a2)
                   (fact () 'schizophrenia 'paranoia)
                   (fact () 'depression 'paranoia)
                   (fact () 'depression 'anhedonia)
                   (fact () 'depression 'insomnia)))

;; We can also add facts to our little ontology
(define causes
  (extend-relation (a1 a2) causes
    (fact () '(bipolar disorder) 'paranoia)))
(define causes
  (extend-relation (a1 a2) causes
    (fact () '(bipolar disorder) 'mania)))
(define causes
  (extend-relation (a1 a2) causes
    (fact () '(bipolar disorder) 'insomnia)))

;; Establish relationship of anatomical structures
(define caudal-to
  (extend-relation (a1 a2)
    (fact () 'capsule 'midbrain)
    (fact () 'midbrain 'pons)
    (fact () 'pons 'medulla)
    (fact () 'medulla 'cord)))

(define crosses-at
  (extend-relation (a1)
    (fact () 'pons)))

(define caudal-all
  (lambda (cephalic caudal)
     (adjacent cephalic caudal)
     (exists (intermediate)
       (all (adjacent cephalic intermediate)
         (caudal-all intermediate caudal))))))

(define ipsilateral-symptoms?
  (lambda (lesion-at)
    (names (solve 5 (x)
      (caudal-all lesion-at
        (car (names
          (solve 5 (s) (crosses-at s))))))))

;; Prettify solutions a bit
(define names
  (lambda (ls)
     (map car
          (map cdr
               (map car ls)))))

;; Try a simple relationship query:
;;   What symptoms can depression cause?
;;   (solve 5 ...) means 'give me at most 5 solutions
;;   for the logic variable x that would make
;;   (causes 'depression x) true.
> (names (solve 5 (x) (causes 'depression x)))
(paranoia anhedonia insomnia)

;; What symptoms can bipolar disorder cause?
> (names (solve 5 (x) (causes '(bipolar disorder) x)))
(paranoia mania insomnia)

;; What conditions cause paranoia?
> (names (solve 5 (x) (causes x 'paranoia)))
(schizophrenia depression (bipolar disorder))

;; What structure is immediately caudal to the midbrain?
> (names (solve 5 (x) (caudal-to 'midbrain x)))

;; What are *all* structures caudal to midbrain?
> (names (solve 5 (x) (caudal-all 'midbrain x)))
(pons medulla cord)

;; What structure is cephalic to the pons?
;;    (Note reordering of terms in the predicate.
;;    You can read this logic statement as 'give me
;;    all answers such that x makes predicate caudal-all true'
> (names (solve 5 (x) (caudal-to x 'pons)))

;; Give all terms cephalic to pons:
> (names (solve 5 (x) (caudal-all x 'pons)))
(midbrain capsule)

;; Are symptoms ipsilateral to a given lesion location?
> (ipsilateral-symptoms? 'cord)
()  ;; i.e., false (empty list)

> (ipsilateral-symptoms? 'medulla)
(_.0) ;; i.e., true for all

These are trivial examples. However, very sophisticated systems can be constructed using logical rather than declarative programming models.

The old standby for logic programming is Prolog. However, systems like the Kanren family can be embedded in languages like Scheme, Lisp, and Haskell to take advantage of a functional paradigm. Compilation is possible to lower level languages like C for easy porting to various platforms, including increasingly ubiquitous portable computers.

For a good introduction to the use of logic programming embedded in a functional language like Scheme, see sections 4.3 – 4.4 of SICP [1].

Much if not all of the current talk around clinical software unfortunately stops at electronic health records (EHR) – the paper chart (with all its limitations) mirrored in various incarnations of ‘the cloud’ (with the additional disadvantage of confidentiality rot). For all the endless effort put into EHR, it was a problem solved long ago with nothing more than punched-card-fed mainframes. All we are seeing now is the iterative pursuit of competing data interchange platforms.

Physicians and researchers need software that advances the goal of making routine things routine beyond just the level of data storage and retrieval…to decision support, data discovery and visualization, unsupervised ontology construction, and scripting of reasoning agents.

Historical attempts at decision support include Mycin for diagnosing infectious blood diseases, which contained assertions and rules in the form if IF-THEN clauses:

   the site of the culture is blood, AND the organism gram +, AND
   the original infectious site was the GI tract, AND
   the abdomen is the locus of infection, OR
   the pelvis is the locus of infection
   therapy should cover Enterobacteriaceae

Rules structured in this manner are brittle, and don’t use unification. Such a system, for example, would not robustly provide answers to queries for all flora that would be likely found in a pelvic infection. The narrow domains and lack of some of what we might call “common sense” knowledge can be problematic: H.R. Ekbia [1] humorously notes that querying a medical inference engine for suggestions on what could be causing the reddish-brown spots on the chassis and body of your Jeep, you’d get “measles”. Another medical support program, asked to suggest treatment for bacterial infection in the kidney, suggested boiling the kidney in hot water.

Another decision support system of historical interest was Internist-I – a system with a much broader domain of medical rules and knowledge. Here’s a transcript of a consultation with that system.


[1] Abelson H, Sussman GJ, Sussman J. Structure and Interpretation of Computer Programs, 2nd Edition. 1996, MIT Press, Cambridge MA.
[2] Ekbia, HR. Artificial Dreams – The Quest for Non-Biological Intelligence. 2008, Cambridge University Press, ppg 96-97.

This entry was posted in medicine. Bookmark the permalink.

Comments are closed.