;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; This file is part of "NOVA": NOVA = search + COCOMO tools ; Copyright, 2008, Tim Menzies tim@menzies.us ; ; NOVA 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. ; ; NOVA 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 ; a long with NOVA. If not, see . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; random items from a list (defun ?elt (choices) "choose one item from a list of choices" (elt choices (floor (my-random (length choices))))) (defun ?elts (choices n) "return up to n randomly selected choices" (if (zerop n) nil (let ((any (?elt choices))) (cons any (?elts (remove any choices) (- n 1)))))) (defun ?any (l &key (control 0.8) (power 1)) "Select any of items from list l, favoring smaller policies. If control is 0.9, then some items of lists of size 5 includes the whole list. " (let* ((factor (expt control power)) (r (?quantity 0 1)) (some (round (log r factor))) (enough (min (length l) (max 1 some)))) (?elts l enough))) (defun ?lots (l) "Pull lots of things from a list." (?any l :power 1)) (defun ?some (l) "Pull some things from a list." (?any l :power 2)) (defun ?few (l) "Pull a few things from a list." (?any l :power 3)) (defun ?quantity (min max) "Choose a number between min to max" (+ min (my-random (- max min)))) (defstruct thing) (defstruct (num (:include thing)) min max) (defstruct (bag (:include thing)) range) (defun ?bag (x) "select one item from a range" (?elt (bag-range x))) (defmacro ?num (x) "select one item within a number min to max" `(?quantity (num-min ,x) (num-max ,x))) ;;;; *db* management (defun zap (key) "zap key from the *db* cache" (setf (db-! *db*) (rassoc key (db-! *db*)))) (defun zaps () "zap all keys in the *db* cache" (setf (db-! *db*) nil)) ;;;; working the lookups and the cache (defun ? (key) "find one value for 'key' in *db*" (let ((range (geta key (db-settings *db*)))) (guess range))) (defun guess (range) "Central station of the 'guess' system. All guessable types have to be registered here." (case (type-of range) (one-a (?one-a range)) (one-b (?one-b range)) (bag (?bag range)) (num (?num range)) (sf (?sf range)) (dr (?dr range)) (em (?em range)) (otherwise (warn "can't handle ~a of type ~a" range (type-of range))))) (defun ! (key) "find (or compute), then store a value for 'key' in *db*" (let ((value (cdr (assoc key (db-! *db*))))) (unless value (setf value (? key)) (push (cons key value) (db-! *db*))) value)) (defun guess0a (&optional (*db* *db*)) (zaps) (format t "~a ~a~%" (! 'a) (! 'a)) (zaps) (format t "~a ~a~%" (! 'a) (! 'a)) t ) (let ((db (make-db :settings `((a . ,(make-num :min 20 :max 40)) (b . ,(make-bag :range '(1 3 5 7 9))))))) (egs :guess0 (eg '(?quantity 10 20)) (eg '(?num (make-num :min 10 :max 20))) (eg '(?elt '(a b c d e))) (eg '(?bag (make-bag :range '(1 2 3 4)))) (eg `(guess0a ,db)) ))