⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 koza-gp.lisp

📁 this code define genetic programming tools and some applications
💻 LISP
📖 第 1 页 / 共 3 页
字号:
(defun create-individual-program           (function-set argument-map terminal-set            allowable-depth top-node-p full-p)  "Creates a program recursively using the specified functions   and terminals.  Argument map is used to determine how many   arguments each function in the function set is supposed to   have if it is selected.  Allowable depth is the remaining   depth of the tree we can create, when we hit zero we will   only select terminals.  Top-node-p is true only when we   are being called as the top node in the tree.  This allows   us to make sure that we always put a function at the top   of the tree.  Full-p indicates whether this individual   is to be maximally bushy or not."  (cond ((<= allowable-depth 0)         ;; We've reached maxdepth, so just pack a terminal.         (choose-from-terminal-set terminal-set))        ((or full-p top-node-p)         ;; We are the top node or are a full tree,         ;; so pick only a function.         (let ((choice (random-integer (length function-set))))           (let ((function (nth choice function-set))                 (number-of-arguments                   (nth choice argument-map)))             (cons function                   (create-arguments-for-function                     number-of-arguments function-set                     argument-map terminal-set                     (- allowable-depth 1) full-p)))))        (:otherwise         ;; choose one from the bag of functions and terminals.         (let ((choice (random-integer                         (+ (length terminal-set)                            (length function-set)))))           (if (< choice (length function-set))               ;; We chose a function, so pick it out and go               ;; on creating the tree down from here.               (let ((function (nth choice function-set))                     (number-of-arguments                       (nth choice argument-map)))                 (cons function                       (create-arguments-for-function                         number-of-arguments function-set                         argument-map terminal-set                         (- allowable-depth 1) full-p)))               ;; We chose an atom, so pick it out.               (choose-from-terminal-set terminal-set))))))(defun create-arguments-for-function           (number-of-arguments function-set            argument-map terminal-set allowable-depth            full-p)  "Creates the argument list for a node in the tree.     Number-Of-Arguments is the number of arguments still   remaining to be created.  Each argument is created   in the normal way using Create-Individual-Program."  (if (= number-of-arguments 0)      nil      (cons (create-individual-program              function-set argument-map terminal-set              allowable-depth nil full-p)            (create-arguments-for-function              (- number-of-arguments 1) function-set              argument-map terminal-set              allowable-depth full-p))))(defun execute-generations    (population new-programs fitness-cases maximum-generations     fitness-function termination-predicate function-set     argument-map terminal-set)  "Loops until the user's termination predicate says to stop."  (do ((current-generation 0 (+ 1 current-generation)))      ;; loop incrementing current generation until      ;; termination-predicate succeeds.      ((let ((best-of-generation (aref population 0)))         (funcall           termination-predicate current-generation           maximum-generations           (individual-standardized-fitness best-of-generation)           (individual-hits best-of-generation))))    (when (> current-generation 0)      ;; Breed the new population to use on this generation      ;; (except gen 0, of course).      (breed-new-population population new-programs function-set                            argument-map terminal-set))    ;; Clean out the fitness measures.    (zeroize-fitness-measures-of-population population)    ;; Measure the fitness of each individual.  Fitness values    ;; are stored in the individuals themselves.    (evaluate-fitness-of-population      population fitness-cases fitness-function)    ;; Normalize fitness in preparation for crossover, etc.    (normalize-fitness-of-population population)    ;; Sort the population so that the roulette wheel is easy.    (sort-population-by-fitness population)    ;; Keep track of best-of-run individual    (let ((best-of-generation (aref population 0)))      (when (or (not *best-of-run-individual*)                (> (individual-standardized-fitness *best-of-run-individual*)                   (individual-standardized-fitness best-of-generation)))        (setf *best-of-run-individual* (copy-individual best-of-generation))        (setf *generation-of-best-of-run-individual* current-generation)))    ;; Print out the results for this generation.    (report-on-generation current-generation population)))(defun zeroize-fitness-measures-of-population (population)  "Clean out the statistics in each individual in the   population.  This is not strictly necessary, but it helps to   avoid confusion that might be caused if, for some reason, we   land in the debugger and there are fitness values associated    with the individual records that actually matched the program    that used to occupy this individual record."  (dotimes (individual-index (length population))    (let ((individual (aref population individual-index)))      (setf (individual-standardized-fitness individual) 0.0)      (setf (individual-adjusted-fitness individual) 0.0)      (setf (individual-normalized-fitness individual) 0.0)      (setf (individual-hits individual) 0))))(defun evaluate-fitness-of-population (population fitness-cases                                       fitness-function)  "Loops over the individuals in the population evaluating and   recording the fitness and hits."  (dotimes (individual-index (length population))    (let ((individual (aref population individual-index)))      (multiple-value-bind (standardized-fitness hits)          (funcall fitness-function                   (individual-program individual)                   fitness-cases)        ;; Record fitness and hits for this individual.        (setf (individual-standardized-fitness individual)              standardized-fitness)        (setf (individual-hits individual) hits)))))(defun normalize-fitness-of-population (population)  "Computes the normalized and adjusted fitness of each   individual in the population."  (let ((sum-of-adjusted-fitnesses 0.0))    (dotimes (individual-index (length population))      (let ((individual (aref population individual-index)))        ;; Set the adjusted fitness.        (setf (individual-adjusted-fitness individual)              (/ 1.0 (+ 1.0 (individual-standardized-fitness                              individual))))        ;; Add up the adjusted fitnesses so that we can        ;; normalize them.        (incf sum-of-adjusted-fitnesses              (individual-adjusted-fitness individual))))    ;; Loop through population normalizing the adjusted fitness.    (dotimes (individual-index (length population))      (let ((individual (aref population individual-index)))        (setf (individual-normalized-fitness individual)              (/ (individual-adjusted-fitness individual)                 sum-of-adjusted-fitnesses))))))(defun sort-population-by-fitness (population)  "Sorts the population according to normalized fitness.    The population array is destructively modified."  (sort population #'> :key #'individual-normalized-fitness))(defun sort-population-by-fitness    (population &optional (low 0) (high (length population)))  "Uses a trivial quicksort to sort the population destructively   into descending order of normalized fitness."  (unless (>= (+ low 1) high)    (let ((pivot (individual-normalized-fitness (aref population low)))          (index1 (+ low 1))          (index2 (- high 1)))      (loop (do () ((or (>= index1 high)                        (<= (individual-normalized-fitness                             (aref population index1)) pivot)))              (incf index1))            (do () ((or (>= low index2)                        (>= (individual-normalized-fitness                             (aref population index2)) pivot)))              (decf index2))            (when (>= index1 index2) (return nil))            (rotatef (aref population index1) (aref population index2))            (decf index2))      (rotatef (aref population low) (aref population (- index1 1)))      (sort-population-by-fitness population low index1)      (sort-population-by-fitness population index1 high)))  population)(defun breed-new-population      (population new-programs function-set       argument-map terminal-set)  "Controls the actual breeding of the new population.     Loops through the population executing each operation   (e.g., crossover, fitness-proportionate reproduction,   mutation) until it has reached the specified fraction.     The new programs that are created are stashed in new-programs   until we have exhausted the population, then we copy the new   individuals into the old ones, thus avoiding consing a new   bunch of individuals."  (let ((population-size (length population)))    (do ((index 0)         (fraction 0 (/ index population-size)))        ((>= index population-size))      (let ((individual-1              (find-individual population)))        (cond ((and (< index (- population-size 1))                    (< fraction                       (+ *crossover-at-function-point-fraction*                          *crossover-at-any-point-fraction*)))               (multiple-value-bind (new-male new-female)                 (funcall                  (if (< fraction                         *crossover-at-function-point-fraction*)                      'crossover-at-function-points                      'crossover-at-any-points)                  individual-1                  (find-individual population))                 (setf (aref new-programs index) new-male)                 (setf (aref new-programs (+ 1 index))                       new-female))               (incf index 2))              ((< fraction                (+ *fitness-proportionate-reproduction-fraction*                   *crossover-at-function-point-fraction*                   *crossover-at-any-point-fraction*))               (setf (aref new-programs index) individual-1)               (incf index 1))              (:otherwise	       (setf (aref new-programs index)		     (mutate individual-1 function-set			     argument-map terminal-set))	       (incf index 1)))))    (dotimes (index population-size)      (setf (individual-program (aref population index))            (aref new-programs index)))))(defun find-individual (population)  "Finds an individual in the population according to the   defined selection method."  (ecase *method-of-selection*    (:tournament (find-individual-using-tournament-selection                   population))    (:fitness-proportionate-with-over-selection      (find-fitness-proportionate-individual        (random-floating-point-number-with-over-selection          population)        population))    (:fitness-proportionate      (find-fitness-proportionate-individual        (random-floating-point-number 1.0) population))))(defun random-floating-point-number-with-over-selection (population)  "Picks a random number between 0.0 and 1.0 biased using the   over-selection method."  (let ((pop-size (length population)))    (when (< pop-size 1000)      (error "A population size of ~D is too small ~              for over-selection." pop-size))    (let ((boundary (/ 320.0 pop-size)))      ;; The boundary between the over and under selected parts.      (if (< (random-floating-point-number 1.0) 0.8)          ;; 80% are in the over-selected part          (random-floating-point-number boundary)          (+ boundary	     (random-floating-point-number (- 1.0 boundary)))))))(defun find-individual-using-tournament-selection (population)  "Picks two individuals from the population at random and   returns the better one."  (let ((individual-a          (aref population                 (random-integer (length population))))        (individual-b          (aref population                 (random-integer (length population)))))    (if (< (individual-standardized-fitness individual-a)           (individual-standardized-fitness individual-b))        (individual-program individual-a)        (individual-program individual-b))))(defun find-fitness-proportionate-individual    (after-this-fitness population)  "Finds an individual in the specified population whose   normalized fitness is greater than the specified value.   All we need to do is count along the population from the   beginning adding up the fitness until we get past the   specified point."  (let ((sum-of-fitness 0.0)        (population-size (length population)))    (let ((index-of-selected-individual            (do ((index 0 (+ index 1)))                ;; Exit condition                ((or (>= index population-size)                     (>= sum-of-fitness after-this-fitness))                 (if (>= index population-size)                     (- (length population) 1)                     (- index 1)))              ;; Body.  Sum up the fitness values.              (incf sum-of-fitness                    (individual-normalized-fitness                      (aref population index))))))      (individual-program        (aref population index-of-selected-individual)))))(defun crossover-at-any-points (male female)  "Performs crossover on the programs at any point   in the trees."  ;; Pick points in the respective trees   ;; on which to perform the crossover.  (let ((male-point          (random-integer (count-crossover-points male)))        (female-point          (random-integer (count-crossover-points female))))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -