| (defpackage #:nekod.selfmod
|
| (:use #:cl #:nekod)
|
| (:export
|
| #:generation-loop
|
| #:mutate-spec
|
| #:evolve
|
| #:fitness
|
| #:*generation*
|
| #:*population*))
|
|
|
| (in-package #:nekod.selfmod)
|
|
|
|
|
|
|
| (defvar *generation* 0)
|
| (defvar *population* nil)
|
|
|
| (defun mutate-spec (spec mutation-rate)
|
| "Randomly mutate a container spec for evolutionary optimization."
|
| (when (< (random 1.0) mutation-rate)
|
| (let ((new-spec (copy-structure spec)))
|
|
|
| (setf (container-spec-restart-policy new-spec)
|
| (nth (random 3) '(:always :on-failure :never)))
|
| new-spec)))
|
|
|
| (defun fitness (spec telemetry)
|
| "Score a container spec based on runtime telemetry.
|
| High uptime + low cpu + low memory = high fitness."
|
| (declare (ignore spec))
|
| (let ((uptime (getf telemetry :uptime 0.0))
|
| (cpu (getf telemetry :cpu 0.5))
|
| (memory (getf telemetry :memory 0.5)))
|
| (- (* 0.6 uptime)
|
| (* 0.2 cpu)
|
| (* 0.2 memory))))
|
|
|
| (defun evolve (population telemetry &optional (mutation-rate 0.1))
|
| "One generation of evolutionary optimization.
|
| Returns new population: survivors + mutants."
|
| (incf *generation*)
|
| (let* ((scored (mapcar (lambda (s) (cons s (fitness s telemetry))) population))
|
| (sorted (sort scored #'> :key #'cdr))
|
| (survivors (mapcar #'car (subseq sorted 0 (ceiling (length sorted) 2))))
|
| (mutants (remove nil (mapcar (lambda (s) (mutate-spec s mutation-rate)) survivors))))
|
| (append survivors mutants)))
|
|
|
| (defun generation-loop (population telemetry-fn
|
| &key (generations 10) (mutation-rate 0.1) (verbose t))
|
| "Run N generations of evolutionary container optimization.
|
|
|
| POPULATION: initial list of container-specs
|
| TELEMETRY-FN: called each generation, returns plist (:uptime f :cpu f :memory f)
|
| Returns the final optimized population."
|
| (loop repeat generations
|
| for pop = population then (evolve pop telemetry mutation-rate)
|
| for telemetry = (funcall telemetry-fn)
|
| do (when verbose
|
| (format t "Gen ~a: ~a containers, best fitness ~,3f~%"
|
| *generation*
|
| (length pop)
|
| (if pop (fitness (first pop) telemetry) 0.0)))
|
| finally (return pop)))
|
|
|