(defun crisp (x a b crisp) "Return a point in a sigmoid function centered ar (a - b)/2" (labels ((as100 (x min max) (+ -50 (* 100 (/ (- x min) (- max min)))))) (/ 1 (+ 1 (exp (* -1 (as100 x a b) crisp)))))) (defun fuzzy-grade (x &optional (a 0) (b 1) (slope 0.1)) (crisp x a b slope)) (defun fuzzy-triangle (x a b c) (max 0 (min (/ (- x a) (- b a)) (/ (- c x) (- c b))))) (defun fuzzy-trapezoid (x a b c d) (max 0 (min (/ (- x a) (- b a)) 1 (/ (- d x) (- d c))))) (defun dist (d what) (case what (range '(close medium far)) (close (fuzzy-triangle d -30 0 30)) (medium (fuzzy-trapezoid d 10 30 50 70)) (far (fuzzy-grade d 0.3 50 100)) (t (warn "~a not known to dist" what)))) (defun size (s what) (case what (range '(tiny small moderate large)) (tiny (fuzzy-triangle s -10 0 10)) (small (fuzzy-trapezoid s 2.5 10 15 20)) (moderate (fuzzy-trapezoid s 15 20 25 30)) (large (fuzzy-grade s 0.3 25 40)) (t (warn "~a not known to size " what)))) (defmacro $and (&rest l) `(min ,@l)) (defmacro $or (&rest l) `(max ,@l)) (defun $not (x) (- 1 x)) (defun fuzzy-deploy (d s what) (macrolet (($if (x y) `($and (dist d ',x) (size s ',y)))) (case what (range '(low medum high)) (low ($or ($if medium tiny) ($if far tiny) ($if medium small) ($if far small))) (medium ($or ($if close tiny) ($if medium moderate))) (high ($or ($if close small) ($if close moderate) ($if close large) ($if medium moderate))) (t (warn "~a not known to fuzzy-deploy" what))))) (defun defuzzy-deploy (&key distance size) "Return how many marines to deply" (let ((low (fuzzy-deploy distance size 'low)) (medium (fuzzy-deploy distance size 'medium)) (high (fuzzy-deploy distance size 'high))) (round (/ (+ (* 10 low) (* 30 medium) (* 50 high)) (+ low medium high))))) (defun demo1 () "how many maries to call out?" (defuzzy-deploy :distance 25 :size 8))