;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This file is part of AIslash.
;
; AIslash is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; AIslash is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with AIslash. If not, see
We have
(defstruct node (id (incf (wm-id *w*)))) (defstruct (nodes (:include node )) kids) (defstruct (node1 (:include node )) kid ) (defstruct ($and (:include nodes)) ) (defstruct ($or (:include nodes)) ) (defstruct ($not (:include node1)) ) (defstruct (thing (:include node1)) name ; short print name description ; long name ako ; a kind of what? (priority 1) ; how much to stress on achieving this one givens ; known prior distributions goals ; desired future distributions computeds ; what we can achieve costs ; cost of reaching parts parts of the distribitions (lockedp t) ; locked or free (are you allowed to adjust the prior?) ) ; goals not used at proppergation, just at rrepport ; change if goal then delta computeds to goal ; if given then delta computers to given ;;
Note that, as far as users are concerned, all their domain
;concepts are the only
Most
(defmethod clear ((x node )) t) (defmethod clear ((x thing)) (setf (thing-computeds x) nil)) ;
(defmethod node+ ((x node))
(setf (gethash (node-handle x) (wm-verticies *w*)) x)
x)
(defmethod node+ ((x thing))
(call-next-method)
(if (thing-ako x)
(push (node-handle x) ; add to kinds (if this has an 'ako')
(gethash (thing-ako x) (wm-kinds *w*))))
x)
(defmethod node= ((x integer)) (gethash x (wm-verticies *w*)))
(defmethod node= ((x symbol)) (gethash x (wm-verticies *w*)))
(defmethod node= ((x node)) x)
(deftest test-node+ ()
(zap)
(let ((th (make-thing :name 'happiness
:description "Happiness is an emotion associated
with feelings ranging from
contentment and satisfaction
to bliss and intense joy."
:ako 'emotion
:givens (rare!))))
(node+ th)
(let ((out (with-output-to-string (s)
(showh (wm-verticies *w*) :stream s))))
(check
(samep out
"HAPPINESS = #S(THING
:ID 1 :KID NIL :NAME HAPPINESS
:DESCRIPTION Happiness is an emotion associated
with feelings ranging from
contentment and satisfaction
to bliss and intense joy.
:AKO EMOTION :PRIORITY 1
:GIVENS #S(DIST
:BUCKETS ((1 . 0.23529412) (2 . 0.4117647)
(3 . 0.23529412) (4 . 0.11764706) (5 . 0.0)
(6 . 0.0) (7 . 0.0) (8 . 0.0) (9 . 0.0)
(10 . 0.0))
:CARDINALITY 10 :MIN 0 :MAX 100)
:GOALS NIL :COMPUTEDS NIL :COSTS NIL :LOCKEDP t)")))))
(deftest test-node= ()
(zap)
(let ((thing (make-thing :name 'happiness
:description "Happiness is an emotion associated
with feelings ranging from
contentment and satisfaction
to bliss and intense joy."
:ako 'emotion
:givens (rare!))))
(node+ thing)
(node= (node-id thing))))
(defmethod ! ((x null )) nil)
(defmethod ! ((x number)) (! (node= x)))
(defmethod ! ((x node)) (error "{!} shouyld be inplemented by sub-class"))
(defmethod ! ((x thing))
(or (thing-computed x)
(setf (thing-computed x) (? x))))
(defmethod ? ((x thing)) ; if no kids then just return your our dist
(if (thing-locked? x)
(thing-givens x)
(! (thing-kid x))))
(defmethod ? ((x $not)) (dist-not (! x)))
(defmethod ? ((x $and)) (accumulate #'dist-and
(first (nodes-kid x))
(rest (nodes-kides))))
(defmethod ? ((x $or)) (accumulate #'dist-or
(first (nodes-kid x))
(rest (nodes-kides))))
(defmethod node-handle ((x node)) (node-id x))
(defmethod node-handle ((x thing)) (thing-name x))
(defmethod node-kid+ (dad kid)
(if (node1-kid dad)
(error "~% can't have more than one kid" (node-handle dad))
(setf (node1-kid dad) (node-handle kid))))
(defun node-kids+ (a b creator)
(let* ((dad (node= a))
(grandkid (node-handle (node= b)))
(kid (node1-kid dad)))
(if kid
(push grandkid (nodes-kids (node= kid)))
(setf (node1-kid dad)
(node-handle
(node+
(funcall creator :kids (list grandkid))))))))
(defmacro == (a b) `(node-kid+ (node= ',a) (node= ',b)))
(defmacro ^ (a b) `(node-kids+ ',a ',b #'make-$and))
(defmacro v (a b) `(node-kids+ ',a ',b #'make-$or))
(defmacro thing (name &key help ako)
`(node+ (make-thing :name ',name :description ',help :ako ',ako)))
(defun model1 ()
(zap)
(thing happy)
(thing healthy)
(thing rich)
(thing wise)
(thing poor)
(^ happy healthy)
(^ happy rich)
(^ happy wise)
(== wise poor) ;XXX or
)
(deftest test-model1 ()
(zap)
(model1)
(let ((string (with-output-to-string (str)
(showh (wm-verticies *w*) :stream str))))
(check
(samep
string
"6 = #S($AND :ID 6 :KIDS (WISE RICH HEALTHY))
HAPPY = #S(THING
:ID 1 :KID 6 :NAME HAPPY :DESCRIPTION NIL :AKO NIL
:PRIORITY 1 :GIVENS NIL :GOALS NIL
:COMPUTEDS NIL :COSTS NIL :LOCKEDP T)
HEALTHY = #S(THING
:ID 2 :KID NIL :NAME HEALTHY :DESCRIPTION NIL :AKO NIL
:PRIORITY 1 :GIVENS NIL :GOALS NIL
:COMPUTEDS NIL :COSTS NIL :LOCKEDP T)
POOR = #S(THING
:ID 5 :KID NIL :NAME POOR :DESCRIPTION NIL :AKO NIL
:PRIORITY 1 :GIVENS NIL :GOALS NIL
:COMPUTEDS NIL :COSTS NIL :LOCKEDP T)
RICH = #S(THING
:ID 3 :KID NIL :NAME RICH :DESCRIPTION NIL :AKO NIL
:PRIORITY 1 :GIVENS NIL :GOALS NIL
:COMPUTEDS NIL :COSTS NIL :LOCKEDP T)
WISE = #S(THING
:ID 4 :KID POOR :NAME WISE :DESCRIPTION NIL :AKO NIL
:PRIORITY 1 :GIVENS NIL :GOALS NIL
:COMPUTEDS NIL :COSTS NIL :LOCKEDP T)"))))