1191 lines
33 KiB
Diff
1191 lines
33 KiB
Diff
|
Index: 2.6.11-as-gl1/fs/proc/proc_misc.c
|
||
|
===================================================================
|
||
|
--- 2.6.11-as-gl1.orig/fs/proc/proc_misc.c 2005-03-02 01:37:49.000000000 -0600
|
||
|
+++ 2.6.11-as-gl1/fs/proc/proc_misc.c 2005-04-16 15:01:53.158735016 -0500
|
||
|
@@ -38,6 +38,7 @@
|
||
|
#include <linux/smp_lock.h>
|
||
|
#include <linux/seq_file.h>
|
||
|
#include <linux/times.h>
|
||
|
+#include <linux/genetic.h>
|
||
|
#include <linux/profile.h>
|
||
|
#include <linux/blkdev.h>
|
||
|
#include <linux/hugetlb.h>
|
||
|
@@ -200,6 +201,97 @@
|
||
|
#undef K
|
||
|
}
|
||
|
|
||
|
+#ifdef CONFIG_GENETIC_LIB
|
||
|
+extern struct proc_dir_entry * genetic_root_dir;
|
||
|
+
|
||
|
+int genetic_read_proc(char *page, char **start, off_t off,
|
||
|
+ int count, int *eof, void *data)
|
||
|
+{
|
||
|
+ int n = 0;
|
||
|
+ genetic_t * genetic = (genetic_t *)data;
|
||
|
+
|
||
|
+ struct list_head * p;
|
||
|
+ phenotype_t * pt;
|
||
|
+
|
||
|
+
|
||
|
+ n = sprintf(page, "%s:\n", genetic->name);
|
||
|
+ n += sprintf(page+n, "generation_number:\t\t%ld\n", genetic->generation_number);
|
||
|
+ n += sprintf(page+n, "num_children:\t\t\t%ld\n", genetic->num_children);
|
||
|
+ n += sprintf(page+n, "child_life_time:\t\t%ld\n\n", genetic->child_life_time);
|
||
|
+ n += sprintf(page+n, "child_number:\t\t\t%ld\n\n", genetic->child_number);
|
||
|
+
|
||
|
+ n += sprintf(page+n, "Phenotypes Average Fitness\n");
|
||
|
+
|
||
|
+ list_for_each(p, &genetic->phenotype) {
|
||
|
+ pt = list_entry(p, phenotype_t, phenotype);
|
||
|
+
|
||
|
+ n += sprintf(page+n, "%-24s:\t\t%lld\n", pt->name, pt->avg_fitness);
|
||
|
+ }
|
||
|
+
|
||
|
+ return proc_calc_metrics(page, start, off, count, eof, n);
|
||
|
+}
|
||
|
+
|
||
|
+int genetic_phenotype_read_proc(char *page, char **start, off_t off,
|
||
|
+ int count, int *eof, void *data)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+ int n = 0;
|
||
|
+ phenotype_t * pt = (phenotype_t *)data;
|
||
|
+
|
||
|
+ n = sprintf(page, "------ %s -----\n", pt->name);
|
||
|
+ n += sprintf(page+n, "generation_number:\t%ld\n", pt->genetic->generation_number);
|
||
|
+ n += sprintf(page+n, "num_children:\t\t%ld\n\n", pt->num_children);
|
||
|
+ n += sprintf(page+n, "child_number:\t\t%ld\n", pt->child_number);
|
||
|
+ n += sprintf(page+n, "mutation_rate:\t\t%ld\n", pt->mutation_rate);
|
||
|
+ n += sprintf(page+n, "num_mutations:\t\t%ld\n", pt->num_mutations);
|
||
|
+ n += sprintf(page+n, "num_genes:\t\t%ld\n", pt->num_genes);
|
||
|
+ n += sprintf(page+n, "uid:\t\t\t%ld\n", pt->uid);
|
||
|
+ n += sprintf(page+n, "avg_fitness:\t\t%lld\n", pt->avg_fitness);
|
||
|
+ n += sprintf(page+n, "last_gen_avg_fitness:\t%lld\n", pt->last_gen_avg_fitness);
|
||
|
+
|
||
|
+ n += sprintf(page+n, "\nFitness history\n");
|
||
|
+
|
||
|
+ for (i = pt->genetic->generation_number > GENETIC_HISTORY_SIZE ? GENETIC_HISTORY_SIZE
|
||
|
+ : pt->genetic->generation_number-1; i > 0; i--)
|
||
|
+ n += sprintf(page+n, "%ld:\t%lld\n",
|
||
|
+ pt->genetic->generation_number - i,
|
||
|
+ pt->fitness_history[(pt->fitness_history_index - i) & GENETIC_HISTORY_MASK]);
|
||
|
+
|
||
|
+ return proc_calc_metrics(page, start, off, count, eof, n);
|
||
|
+}
|
||
|
+
|
||
|
+#if GENETIC_DEBUG
|
||
|
+int genetic_debug_read_proc(char *page, char **start, off_t off,
|
||
|
+ int count, int *eof, void *data)
|
||
|
+{
|
||
|
+ int i, j, k;
|
||
|
+ int n = 0;
|
||
|
+ phenotype_t * pt = (phenotype_t *)data;
|
||
|
+
|
||
|
+ n = sprintf(page, "generation_number:\t%ld\n", pt->genetic->generation_number);
|
||
|
+
|
||
|
+ for (i = 0, j = 1; i < pt->debug_size; j++) {
|
||
|
+ /* print out child number, and ID */
|
||
|
+ n += sprintf(page+n, "%d (%lld):", j, pt->debug_history[i++]);
|
||
|
+ /* print out child fitness */
|
||
|
+ n += sprintf(page+n, " %-12lld:\t", pt->debug_history[i++]);
|
||
|
+
|
||
|
+ for (k = 0; k < pt->child_ranking[0]->num_genes; k++) {
|
||
|
+ n += sprintf(page+n, "%lld\t", pt->debug_history[i++]);
|
||
|
+ }
|
||
|
+ n += sprintf(page+n, "\n");
|
||
|
+
|
||
|
+ if (j == pt->num_children) {
|
||
|
+ n += sprintf(page+n, "\n");
|
||
|
+ j = 0;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return proc_calc_metrics(page, start, off, count, eof, n);
|
||
|
+}
|
||
|
+#endif /* GENETIC_DEBUG */
|
||
|
+#endif /* CONFIG_GENETIC_LIB */
|
||
|
+
|
||
|
extern struct seq_operations fragmentation_op;
|
||
|
static int fragmentation_open(struct inode *inode, struct file *file)
|
||
|
{
|
||
|
Index: 2.6.11-as-gl1/include/linux/genetic.h
|
||
|
===================================================================
|
||
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||
|
+++ 2.6.11-as-gl1/include/linux/genetic.h 2005-04-16 15:23:59.312856488 -0500
|
||
|
@@ -0,0 +1,233 @@
|
||
|
+#ifndef __LINUX_GENETIC_H
|
||
|
+#define __LINUX_GENETIC_H
|
||
|
+/*
|
||
|
+ * include/linux/genetic.h
|
||
|
+ *
|
||
|
+ * Jake Moilanen <moilanen@austin.ibm.com>
|
||
|
+ * Copyright (C) 2004 IBM
|
||
|
+ *
|
||
|
+ * Genetic algorithm library
|
||
|
+ *
|
||
|
+ * This program 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
|
||
|
+ * 2 of the License, or (at your option) any later version.
|
||
|
+ */
|
||
|
+
|
||
|
+#include <linux/list.h>
|
||
|
+#include <linux/timer.h>
|
||
|
+#include <linux/init.h>
|
||
|
+
|
||
|
+
|
||
|
+#define GENETIC_HISTORY_SIZE 0x8
|
||
|
+#define GENETIC_HISTORY_MASK (GENETIC_HISTORY_SIZE - 1)
|
||
|
+
|
||
|
+/* percentage of total number genes to mutate */
|
||
|
+#define GENETIC_DEFAULT_MUTATION_RATE 15
|
||
|
+
|
||
|
+/* XXX TODO Make this an adjustable runtime variable */
|
||
|
+/* Percentage that an iteration can jump within the range */
|
||
|
+#define GENETIC_ITERATIVE_MUTATION_RANGE 20
|
||
|
+
|
||
|
+/* the rate that GENETIC_DEFAULT_MUTATION_RATE itself can change */
|
||
|
+#define GENETIC_DEFAULT_MUTATION_RATE_CHANGE 4
|
||
|
+#define GENETIC_MAX_MUTATION_RATE 45
|
||
|
+#define GENETIC_MIN_MUTATION_RATE 10
|
||
|
+
|
||
|
+#define GENETIC_DEBUG 1
|
||
|
+#define GENETIC_NUM_DEBUG_POINTS 4
|
||
|
+
|
||
|
+#define GENETIC_PRINT_DEBUG 0
|
||
|
+#define gen_dbg(format, arg...) do { if (GENETIC_PRINT_DEBUG) printk(KERN_EMERG __FILE__ ": " format "\n" , ## arg); } while (0)
|
||
|
+#define gen_trc(format, arg...) do { if (GENETIC_PRINT_DEBUG) printk(KERN_EMERG __FILE__ ":%s:%d\n" , __FUNCTION__, __LINE__); } while (0)
|
||
|
+
|
||
|
+struct gene_param_s;
|
||
|
+struct genetic_s;
|
||
|
+struct phenotype_s;
|
||
|
+
|
||
|
+struct genetic_child_s {
|
||
|
+ struct list_head list;
|
||
|
+ long long fitness;
|
||
|
+ unsigned long num_genes;
|
||
|
+ void *genes;
|
||
|
+ struct gene_param_s *gene_param;
|
||
|
+ void *stats_snapshot;
|
||
|
+ int id;
|
||
|
+};
|
||
|
+
|
||
|
+typedef struct genetic_child_s genetic_child_t;
|
||
|
+
|
||
|
+/* Here's a generic idea of what it the genes could look like */
|
||
|
+struct gene_param_s {
|
||
|
+ unsigned long min;
|
||
|
+ unsigned long max;
|
||
|
+ unsigned long initial;
|
||
|
+ void (*mutate_gene)(genetic_child_t *, unsigned long);
|
||
|
+};
|
||
|
+
|
||
|
+typedef struct gene_param_s gene_param_t;
|
||
|
+
|
||
|
+struct phenotype_s {
|
||
|
+ struct list_head phenotype;
|
||
|
+
|
||
|
+ struct list_head children_queue[2];
|
||
|
+ struct list_head *run_queue;
|
||
|
+ struct list_head *finished_queue;
|
||
|
+ struct genetic_ops *ops;
|
||
|
+
|
||
|
+ char *name;
|
||
|
+
|
||
|
+ struct genetic_s *genetic; /* point back
|
||
|
+ * to genetic
|
||
|
+ * struct
|
||
|
+ */
|
||
|
+
|
||
|
+ unsigned long num_children; /* Must be power of 2 */
|
||
|
+ unsigned long natural_selection_cutoff; /* How many children
|
||
|
+ * will survive
|
||
|
+ */
|
||
|
+ void *stats_snapshot;
|
||
|
+ unsigned long child_number;
|
||
|
+
|
||
|
+ /* percentage of total number of genes to mutate */
|
||
|
+ long mutation_rate;
|
||
|
+ unsigned long num_mutations;
|
||
|
+ unsigned long num_genes;
|
||
|
+
|
||
|
+ genetic_child_t **child_ranking;
|
||
|
+
|
||
|
+ void (*natural_selection)(struct phenotype_s *);
|
||
|
+
|
||
|
+ /* This UID is bitmap comprised of other phenotypes that contribute
|
||
|
+ to the genes */
|
||
|
+ unsigned long uid;
|
||
|
+
|
||
|
+ /* performance metrics */
|
||
|
+ long long avg_fitness;
|
||
|
+ long long last_gen_avg_fitness;
|
||
|
+
|
||
|
+ unsigned long fitness_history_index;
|
||
|
+ long long fitness_history[GENETIC_HISTORY_SIZE];
|
||
|
+
|
||
|
+#if GENETIC_DEBUG
|
||
|
+ unsigned long debug_size; /* number of longs in
|
||
|
+ debug history */
|
||
|
+ unsigned long debug_index;
|
||
|
+ long long *debug_history;
|
||
|
+#endif
|
||
|
+};
|
||
|
+
|
||
|
+typedef struct phenotype_s phenotype_t;
|
||
|
+
|
||
|
+struct genetic_s {
|
||
|
+ char *name;
|
||
|
+ struct timer_list timer;
|
||
|
+
|
||
|
+ struct list_head phenotype;
|
||
|
+
|
||
|
+ unsigned long child_number;
|
||
|
+ unsigned long child_life_time;
|
||
|
+ unsigned long num_children; /* Must be power of 2 */
|
||
|
+
|
||
|
+ struct proc_dir_entry *dir;
|
||
|
+ struct proc_dir_entry *debug_dir;
|
||
|
+ unsigned long generation_number;
|
||
|
+
|
||
|
+};
|
||
|
+
|
||
|
+typedef struct genetic_s genetic_t;
|
||
|
+
|
||
|
+struct genetic_ops {
|
||
|
+ void (*create_child)(genetic_child_t *);
|
||
|
+ void (*set_child_genes)(void *);
|
||
|
+ void (*calc_fitness)(genetic_child_t *);
|
||
|
+ void (*combine_genes)(genetic_child_t *, genetic_child_t *,
|
||
|
+ genetic_child_t *);
|
||
|
+ void (*mutate_child)(genetic_child_t *);
|
||
|
+ void (*calc_post_fitness)(phenotype_t *); /* Fitness routine used when
|
||
|
+ * need to take into account
|
||
|
+ * other phenotype fitness
|
||
|
+ * results after they ran
|
||
|
+ */
|
||
|
+ void (*take_snapshot)(phenotype_t *);
|
||
|
+ void (*shift_mutation_rate)(phenotype_t *);
|
||
|
+};
|
||
|
+
|
||
|
+/* Setup routines */
|
||
|
+int __init genetic_init(genetic_t ** in_genetic, unsigned long num_children,
|
||
|
+ unsigned long child_life_time,
|
||
|
+ char * name);
|
||
|
+int __init genetic_register_phenotype(genetic_t * genetic, struct genetic_ops * ops,
|
||
|
+ unsigned long num_children, char * name,
|
||
|
+ unsigned long num_genes, unsigned long uid);
|
||
|
+void __init genetic_start(genetic_t * genetic);
|
||
|
+
|
||
|
+/* Generic helper functions */
|
||
|
+void genetic_generic_mutate_child(genetic_child_t * child);
|
||
|
+void genetic_generic_iterative_mutate_gene(genetic_child_t * child, long gene_num);
|
||
|
+void genetic_iterative_from_default_mutate_gene(genetic_child_t * child, long gene_num);
|
||
|
+void genetic_generic_combine_genes(genetic_child_t * parent_a,
|
||
|
+ genetic_child_t * parent_b,
|
||
|
+ genetic_child_t * child);
|
||
|
+void genetic_create_child_spread(genetic_child_t * child, unsigned long num_children);
|
||
|
+void genetic_create_child_defaults(genetic_child_t * child);
|
||
|
+void genetic_general_shift_mutation_rate(phenotype_t * in_pt);
|
||
|
+
|
||
|
+#if BITS_PER_LONG >= 64
|
||
|
+
|
||
|
+static inline void divll(long long *n, long div, long *rem)
|
||
|
+{
|
||
|
+ *rem = *n % div;
|
||
|
+ *n /= div;
|
||
|
+}
|
||
|
+
|
||
|
+#else
|
||
|
+
|
||
|
+static inline void divl(int32_t high, int32_t low,
|
||
|
+ int32_t div,
|
||
|
+ int32_t *q, int32_t *r)
|
||
|
+{
|
||
|
+ int64_t n = (u_int64_t)high << 32 | low;
|
||
|
+ int64_t d = (u_int64_t)div << 31;
|
||
|
+ int32_t q1 = 0;
|
||
|
+ int c = 32;
|
||
|
+ while (n > 0xffffffff) {
|
||
|
+ q1 <<= 1;
|
||
|
+ if (n >= d) {
|
||
|
+ n -= d;
|
||
|
+ q1 |= 1;
|
||
|
+ }
|
||
|
+ d >>= 1;
|
||
|
+ c--;
|
||
|
+ }
|
||
|
+ q1 <<= c;
|
||
|
+ if (n) {
|
||
|
+ low = n;
|
||
|
+ *q = q1 | (low / div);
|
||
|
+ *r = low % div;
|
||
|
+ } else {
|
||
|
+ *r = 0;
|
||
|
+ *q = q1;
|
||
|
+ }
|
||
|
+ return;
|
||
|
+}
|
||
|
+
|
||
|
+static inline void divll(long long *n, long div, long *rem)
|
||
|
+{
|
||
|
+ int32_t low, high;
|
||
|
+ low = *n & 0xffffffff;
|
||
|
+ high = *n >> 32;
|
||
|
+ if (high) {
|
||
|
+ int32_t high1 = high % div;
|
||
|
+ int32_t low1 = low;
|
||
|
+ high /= div;
|
||
|
+ divl(high1, low1, div, &low, (int32_t *)rem);
|
||
|
+ *n = (int64_t)high << 32 | low;
|
||
|
+ } else {
|
||
|
+ *n = low / div;
|
||
|
+ *rem = low % div;
|
||
|
+ }
|
||
|
+}
|
||
|
+#endif
|
||
|
+
|
||
|
+#endif
|
||
|
Index: 2.6.11-as-gl1/lib/Kconfig
|
||
|
===================================================================
|
||
|
--- 2.6.11-as-gl1.orig/lib/Kconfig 2005-03-02 01:38:10.000000000 -0600
|
||
|
+++ 2.6.11-as-gl1/lib/Kconfig 2005-04-16 15:01:53.160735760 -0500
|
||
|
@@ -30,6 +30,12 @@
|
||
|
require M here. See Castagnoli93.
|
||
|
Module will be libcrc32c.
|
||
|
|
||
|
+config GENETIC_LIB
|
||
|
+ bool "Genetic Library"
|
||
|
+ help
|
||
|
+ This option will build in a genetic library that will tweak
|
||
|
+ kernel parameters autonomically to improve performance.
|
||
|
+
|
||
|
#
|
||
|
# compression support is select'ed if needed
|
||
|
#
|
||
|
Index: 2.6.11-as-gl1/lib/Makefile
|
||
|
===================================================================
|
||
|
--- 2.6.11-as-gl1.orig/lib/Makefile 2005-03-02 01:37:47.000000000 -0600
|
||
|
+++ 2.6.11-as-gl1/lib/Makefile 2005-04-16 15:01:53.160735760 -0500
|
||
|
@@ -24,6 +24,7 @@
|
||
|
obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
|
||
|
obj-$(CONFIG_CRC32) += crc32.o
|
||
|
obj-$(CONFIG_LIBCRC32C) += libcrc32c.o
|
||
|
+obj-$(CONFIG_GENETIC_LIB) += genetic.o
|
||
|
obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
|
||
|
|
||
|
obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
|
||
|
Index: 2.6.11-as-gl1/lib/genetic.c
|
||
|
===================================================================
|
||
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||
|
+++ 2.6.11-as-gl1/lib/genetic.c 2005-04-16 15:24:26.437093456 -0500
|
||
|
@@ -0,0 +1,808 @@
|
||
|
+/*
|
||
|
+ * Genetic Algorithm Library
|
||
|
+ *
|
||
|
+ * Jake Moilanen <moilanen@austin.ibm.com>
|
||
|
+ * Copyright (C) 2004 IBM
|
||
|
+ *
|
||
|
+ *
|
||
|
+ * This program 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
|
||
|
+ * 2 of the License, or (at your option) any later version.
|
||
|
+ */
|
||
|
+
|
||
|
+/*
|
||
|
+ * Life cycle
|
||
|
+ *
|
||
|
+ * 1.) Create random children
|
||
|
+ * 2.) Run tests
|
||
|
+ * 3.) Calculate fitness
|
||
|
+ * 4.) Take top preformers
|
||
|
+ * 5.) Make children
|
||
|
+ * 6.) Mutate
|
||
|
+ * 7.) Goto step 2
|
||
|
+ */
|
||
|
+
|
||
|
+#include <linux/genetic.h>
|
||
|
+#include <linux/timer.h>
|
||
|
+#include <linux/jiffies.h>
|
||
|
+#include <linux/proc_fs.h>
|
||
|
+#include <linux/init.h>
|
||
|
+#include <linux/random.h>
|
||
|
+
|
||
|
+#include <asm/uaccess.h>
|
||
|
+#include <asm/string.h>
|
||
|
+#include <asm/bug.h>
|
||
|
+
|
||
|
+char genetic_lib_version[] = "0.2";
|
||
|
+
|
||
|
+int mutation_rate_change = GENETIC_DEFAULT_MUTATION_RATE_CHANGE;
|
||
|
+int genetic_lib_enabled = 1;
|
||
|
+
|
||
|
+static void genetic_ns_top_parents(phenotype_t *);
|
||
|
+static void genetic_ns_award_top_parents(phenotype_t *);
|
||
|
+static int genetic_create_children(phenotype_t *);
|
||
|
+static void genetic_split_performers(phenotype_t *);
|
||
|
+static void genetic_mutate(phenotype_t *);
|
||
|
+static void genetic_run_child(genetic_t * genetic);
|
||
|
+static void genetic_new_generation(genetic_t * genetic);
|
||
|
+
|
||
|
+void genetic_switch_child(unsigned long data);
|
||
|
+struct proc_dir_entry * genetic_root_dir = 0;
|
||
|
+
|
||
|
+extern int genetic_read_proc(char *page, char **start, off_t off,
|
||
|
+ int count, int *eof, void *data);
|
||
|
+extern int genetic_phenotype_read_proc(char *page, char **start, off_t off,
|
||
|
+ int count, int *eof, void *data);
|
||
|
+
|
||
|
+#if GENETIC_DEBUG
|
||
|
+extern int genetic_debug_read_proc(char *page, char **start, off_t off,
|
||
|
+ int count, int *eof, void *data);
|
||
|
+#endif
|
||
|
+
|
||
|
+
|
||
|
+int __init genetic_init(genetic_t ** in_genetic, unsigned long num_children,
|
||
|
+ unsigned long child_life_time,
|
||
|
+ char * name)
|
||
|
+{
|
||
|
+ struct proc_dir_entry *entry;
|
||
|
+ genetic_t * genetic;
|
||
|
+
|
||
|
+ if (!genetic_lib_enabled)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ printk(KERN_INFO "Initializing Genetic Library - version %s\n", genetic_lib_version);
|
||
|
+
|
||
|
+ genetic = (genetic_t *)kmalloc(sizeof(genetic_t), GFP_KERNEL);
|
||
|
+ if (!genetic) {
|
||
|
+ printk(KERN_ERR "genetic_init: not enough memory\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ *in_genetic = genetic;
|
||
|
+
|
||
|
+ genetic->name = (char *)kmalloc(strlen(name), GFP_KERNEL);
|
||
|
+ if (!genetic->name) {
|
||
|
+ printk(KERN_ERR "genetic_init: not enough memory\n");
|
||
|
+ kfree(genetic);
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Init some of our values */
|
||
|
+ strcpy(genetic->name, name);
|
||
|
+
|
||
|
+ genetic->num_children = num_children;
|
||
|
+ genetic->child_life_time = child_life_time;
|
||
|
+
|
||
|
+ genetic->generation_number = 1;
|
||
|
+ genetic->child_number = 0;
|
||
|
+
|
||
|
+ /* Setup how long each child has to live */
|
||
|
+ init_timer(&genetic->timer);
|
||
|
+ genetic->timer.function = genetic_switch_child;
|
||
|
+ genetic->timer.data = (unsigned long)genetic;
|
||
|
+
|
||
|
+#ifdef CONFIG_PROC_FS
|
||
|
+ /* Setup proc structure to monitor */
|
||
|
+ if (!genetic_root_dir)
|
||
|
+ genetic_root_dir = proc_mkdir("genetic", 0);
|
||
|
+
|
||
|
+ genetic->dir = proc_mkdir(name, genetic_root_dir);
|
||
|
+
|
||
|
+ entry = create_proc_entry("stats", 0644, genetic->dir);
|
||
|
+
|
||
|
+ if (entry) {
|
||
|
+ entry->nlink = 1;
|
||
|
+ entry->data = genetic;
|
||
|
+ entry->read_proc = genetic_read_proc;
|
||
|
+ }
|
||
|
+
|
||
|
+#ifdef GENETIC_DEBUG
|
||
|
+ genetic->debug_dir = proc_mkdir("debug", genetic->dir);
|
||
|
+#endif /* GENETIC_DEBUG */
|
||
|
+
|
||
|
+
|
||
|
+#endif /* CONFIG_PROC_FS */
|
||
|
+
|
||
|
+ INIT_LIST_HEAD(&genetic->phenotype);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+int __init genetic_register_phenotype(genetic_t * genetic, struct genetic_ops * ops,
|
||
|
+ unsigned long num_children, char * name,
|
||
|
+ unsigned long num_genes, unsigned long uid)
|
||
|
+{
|
||
|
+ struct proc_dir_entry *entry;
|
||
|
+ phenotype_t * pt;
|
||
|
+ int rc;
|
||
|
+
|
||
|
+ if (!genetic_lib_enabled)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ printk(KERN_INFO "Initializing %s's phenotype %s\n", genetic->name, name);
|
||
|
+
|
||
|
+ pt = (phenotype_t *)kmalloc(sizeof(phenotype_t), GFP_KERNEL);
|
||
|
+ if (!genetic) {
|
||
|
+ printk(KERN_ERR "genetic_register_phenotype: not enough memory\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ pt->name = (char *)kmalloc(strlen(name), GFP_KERNEL);
|
||
|
+ if (!pt->name) {
|
||
|
+ printk(KERN_ERR "genetic_register_phenotype: not enough memory\n");
|
||
|
+ kfree(pt);
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ pt->child_ranking = (genetic_child_t **)kmalloc(num_children * sizeof(genetic_child_t *), GFP_KERNEL);
|
||
|
+ if (!pt->child_ranking) {
|
||
|
+ printk(KERN_ERR "genetic_register_phenotype: not enough memory\n");
|
||
|
+ kfree(pt->name);
|
||
|
+ kfree(pt);
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ strcpy(pt->name, name);
|
||
|
+
|
||
|
+ INIT_LIST_HEAD(&pt->children_queue[0]);
|
||
|
+ INIT_LIST_HEAD(&pt->children_queue[1]);
|
||
|
+
|
||
|
+ pt->run_queue = &pt->children_queue[0];
|
||
|
+ pt->finished_queue = &pt->children_queue[1];
|
||
|
+
|
||
|
+ pt->ops = ops;
|
||
|
+ pt->num_children = num_children;
|
||
|
+
|
||
|
+ pt->mutation_rate = GENETIC_DEFAULT_MUTATION_RATE;
|
||
|
+ pt->natural_selection = genetic_ns_top_parents;
|
||
|
+ pt->natural_selection_cutoff = num_children / 2;
|
||
|
+ pt->avg_fitness = 0;
|
||
|
+ pt->last_gen_avg_fitness = 0;
|
||
|
+ pt->child_number = 0;
|
||
|
+
|
||
|
+ pt->genetic = genetic;
|
||
|
+ pt->uid = uid;
|
||
|
+ pt->num_genes = num_genes;
|
||
|
+
|
||
|
+ /* Create some children */
|
||
|
+ rc = genetic_create_children(pt);
|
||
|
+ if (rc)
|
||
|
+ return rc;
|
||
|
+
|
||
|
+#ifdef CONFIG_PROC_FS
|
||
|
+ entry = create_proc_entry(name, 0644, genetic->dir);
|
||
|
+
|
||
|
+ if (entry) {
|
||
|
+ entry->nlink = 1;
|
||
|
+ entry->data = pt;
|
||
|
+ entry->read_proc = genetic_phenotype_read_proc;
|
||
|
+ }
|
||
|
+
|
||
|
+#endif
|
||
|
+
|
||
|
+#if GENETIC_DEBUG
|
||
|
+ pt->debug_index = 0;
|
||
|
+ /* create array for history. The +2 on num_genes is for the
|
||
|
+ fitness and child id */
|
||
|
+ pt->debug_size = num_children * (num_genes + 2) * GENETIC_NUM_DEBUG_POINTS;
|
||
|
+
|
||
|
+ pt->debug_history = (long long *) kmalloc(pt->debug_size * sizeof(long long), GFP_KERNEL);
|
||
|
+
|
||
|
+#ifdef CONFIG_PROC_FS
|
||
|
+ entry = create_proc_entry(name, 0644, genetic->debug_dir);
|
||
|
+
|
||
|
+ if (entry) {
|
||
|
+ entry->nlink = 1;
|
||
|
+ entry->data = pt;
|
||
|
+ entry->read_proc = genetic_debug_read_proc;
|
||
|
+ }
|
||
|
+
|
||
|
+#endif /* CONFIG_PROC_FS */
|
||
|
+#endif /* GENETIC_DEBUG */
|
||
|
+
|
||
|
+
|
||
|
+ list_add_tail(&pt->phenotype, &genetic->phenotype);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+void __init genetic_start(genetic_t * genetic)
|
||
|
+{
|
||
|
+ if (!genetic_lib_enabled)
|
||
|
+ return;
|
||
|
+
|
||
|
+ genetic_run_child(genetic);
|
||
|
+ printk(KERN_INFO "%ld children started in %s genetic library\n", genetic->num_children, genetic->name);
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+
|
||
|
+/* create some children, it is up to the lib user to come up w/ a good
|
||
|
+ distro of genes for it's children */
|
||
|
+static int genetic_create_children(phenotype_t * pt)
|
||
|
+{
|
||
|
+ unsigned long i;
|
||
|
+ genetic_child_t * child;
|
||
|
+
|
||
|
+ for (i = 0; i < pt->num_children; i++) {
|
||
|
+ pt->child_ranking[i] = (genetic_child_t *)kmalloc(sizeof(genetic_child_t), GFP_KERNEL);
|
||
|
+ if (!pt->child_ranking[i]) {
|
||
|
+ printk(KERN_ERR "genetic_create_child: not enough memory\n");
|
||
|
+ for (i = i - 1; i >= 0; i--)
|
||
|
+ kfree(pt->child_ranking[i]);
|
||
|
+
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ child = pt->child_ranking[i];
|
||
|
+
|
||
|
+ child->id = i;
|
||
|
+
|
||
|
+ pt->ops->create_child(child);
|
||
|
+
|
||
|
+ list_add_tail(&child->list, pt->run_queue);
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/* See how well child did and run the next one */
|
||
|
+void genetic_switch_child(unsigned long data)
|
||
|
+{
|
||
|
+ genetic_t * genetic = (genetic_t *)data;
|
||
|
+ genetic_child_t * child;
|
||
|
+
|
||
|
+ struct list_head * p;
|
||
|
+ phenotype_t * pt;
|
||
|
+
|
||
|
+ int new_generation = 0;
|
||
|
+
|
||
|
+ list_for_each(p, &genetic->phenotype) {
|
||
|
+ pt = list_entry(p, phenotype_t, phenotype);
|
||
|
+
|
||
|
+ child = list_entry(pt->run_queue->next, genetic_child_t, list);
|
||
|
+
|
||
|
+ list_del(&child->list);
|
||
|
+
|
||
|
+ list_add_tail(&child->list, pt->finished_queue);
|
||
|
+
|
||
|
+ if (pt->ops->calc_fitness)
|
||
|
+ pt->ops->calc_fitness(child);
|
||
|
+
|
||
|
+ pt->child_ranking[pt->child_number++] = child;
|
||
|
+
|
||
|
+ /* See if need more children */
|
||
|
+ if (list_empty(pt->run_queue))
|
||
|
+ new_generation = 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ genetic->child_number++;
|
||
|
+
|
||
|
+ if (new_generation)
|
||
|
+ genetic_new_generation(genetic);
|
||
|
+
|
||
|
+ genetic_run_child(genetic);
|
||
|
+
|
||
|
+}
|
||
|
+
|
||
|
+/* Set the childs genes for run */
|
||
|
+void genetic_run_child(genetic_t * genetic)
|
||
|
+{
|
||
|
+ struct list_head * p;
|
||
|
+ phenotype_t * pt;
|
||
|
+
|
||
|
+ genetic_child_t * child;
|
||
|
+ void * genes;
|
||
|
+
|
||
|
+ list_for_each(p, &genetic->phenotype) {
|
||
|
+ pt = list_entry(p, phenotype_t, phenotype);
|
||
|
+
|
||
|
+ child = list_entry(pt->run_queue->next, genetic_child_t, list);
|
||
|
+
|
||
|
+ genes = child->genes;
|
||
|
+
|
||
|
+ if (pt->ops->set_child_genes)
|
||
|
+ pt->ops->set_child_genes(genes);
|
||
|
+
|
||
|
+ if (pt->ops->take_snapshot)
|
||
|
+ pt->ops->take_snapshot(pt);
|
||
|
+ }
|
||
|
+
|
||
|
+ /* set a timer interrupt */
|
||
|
+ genetic->timer.expires = jiffies + genetic->child_life_time;
|
||
|
+ add_timer(&genetic->timer);
|
||
|
+
|
||
|
+}
|
||
|
+
|
||
|
+/* This natural selection routine will take the top
|
||
|
+ * natural_select_cutoff and use them to make children for the next
|
||
|
+ * generation and keep the top half perfomers
|
||
|
+ *
|
||
|
+ * This assumes natural_select_cutoff is exactly half of num_children
|
||
|
+ * and num_children is a multable of 4.
|
||
|
+ */
|
||
|
+static void genetic_ns_top_parents(phenotype_t * pt)
|
||
|
+{
|
||
|
+ unsigned long i,j,k = 0;
|
||
|
+ unsigned long num_children = pt->num_children;
|
||
|
+ unsigned long cutoff = num_children - pt->natural_selection_cutoff;
|
||
|
+
|
||
|
+ for (i = cutoff, j = num_children - 1; i < j; i++, j--, k += 2) {
|
||
|
+ /* create child A */
|
||
|
+ pt->ops->combine_genes(pt->child_ranking[i],
|
||
|
+ pt->child_ranking[j],
|
||
|
+ pt->child_ranking[k]);
|
||
|
+
|
||
|
+ /* create child B */
|
||
|
+ pt->ops->combine_genes(pt->child_ranking[i],
|
||
|
+ pt->child_ranking[j],
|
||
|
+ pt->child_ranking[k+1]);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+/* This natural selection routine just has top parents populating
|
||
|
+ bottom performers. */
|
||
|
+static void genetic_ns_award_top_parents(phenotype_t * pt)
|
||
|
+{
|
||
|
+ unsigned long i;
|
||
|
+ unsigned long num_children = pt->num_children;
|
||
|
+ unsigned long cutoff = num_children - pt->natural_selection_cutoff;
|
||
|
+
|
||
|
+ for (i = 0; i < cutoff; i += 2) {
|
||
|
+ pt->ops->combine_genes(pt->child_ranking[num_children - 1],
|
||
|
+ pt->child_ranking[num_children - 2],
|
||
|
+ pt->child_ranking[i]);
|
||
|
+
|
||
|
+ pt->ops->combine_genes(pt->child_ranking[num_children - 1],
|
||
|
+ pt->child_ranking[num_children - 2],
|
||
|
+ pt->child_ranking[i+1]);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static inline void genetic_swap(genetic_child_t ** a, genetic_child_t ** b)
|
||
|
+{
|
||
|
+ genetic_child_t * tmp = *a;
|
||
|
+
|
||
|
+ *a = *b;
|
||
|
+ *b = tmp;
|
||
|
+}
|
||
|
+
|
||
|
+/* bubble sort */
|
||
|
+/* XXX change this to quick sort */
|
||
|
+static void genetic_split_performers(phenotype_t * pt)
|
||
|
+{
|
||
|
+ int i, j;
|
||
|
+
|
||
|
+ for (i = pt->num_children; i > 1; i--)
|
||
|
+ for (j = 0; j < i - 1; j++)
|
||
|
+ if (pt->child_ranking[j]->fitness > pt->child_ranking[j+1]->fitness)
|
||
|
+ genetic_swap(&pt->child_ranking[j], &pt->child_ranking[j+1]);
|
||
|
+}
|
||
|
+
|
||
|
+static void genetic_mutate(phenotype_t * pt)
|
||
|
+{
|
||
|
+ long child_entry = -1;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ if (!pt->num_genes)
|
||
|
+ return;
|
||
|
+
|
||
|
+ for (i = 0; i < pt->num_mutations; i++) {
|
||
|
+ get_random_bytes(&child_entry, sizeof(child_entry));
|
||
|
+ child_entry = child_entry % pt->num_children;
|
||
|
+
|
||
|
+ pt->ops->mutate_child(pt->child_ranking[child_entry]);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+/* XXX This will either aid in handling new workloads, or send us on a
|
||
|
+ downward spiral */
|
||
|
+static void genetic_shift_mutation_rate(phenotype_t * pt, long long prev_gen_avg_fitness, long long avg_fitness)
|
||
|
+{
|
||
|
+
|
||
|
+ long low_bound;
|
||
|
+ long high_bound;
|
||
|
+ long dummy;
|
||
|
+
|
||
|
+ if (mutation_rate_change && pt->genetic->generation_number > 1) {
|
||
|
+
|
||
|
+ if (pt->ops->shift_mutation_rate) {
|
||
|
+ pt->ops->shift_mutation_rate(pt);
|
||
|
+ } else {
|
||
|
+
|
||
|
+ low_bound = avg_fitness * 90;
|
||
|
+ divll(&low_bound, 100, &dummy);
|
||
|
+
|
||
|
+ high_bound = avg_fitness * 110;
|
||
|
+ divll(&high_bound, 100, &dummy);
|
||
|
+
|
||
|
+ if (high_bound > prev_gen_avg_fitness)
|
||
|
+ pt->mutation_rate -= mutation_rate_change;
|
||
|
+ else if (low_bound < prev_gen_avg_fitness)
|
||
|
+ pt->mutation_rate += mutation_rate_change;
|
||
|
+
|
||
|
+ if (pt->mutation_rate > GENETIC_MAX_MUTATION_RATE)
|
||
|
+ pt->mutation_rate = GENETIC_MAX_MUTATION_RATE;
|
||
|
+ else if (pt->mutation_rate < GENETIC_MIN_MUTATION_RATE)
|
||
|
+ pt->mutation_rate = GENETIC_MIN_MUTATION_RATE;
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+void genetic_general_shift_mutation_rate(phenotype_t * in_pt)
|
||
|
+{
|
||
|
+ struct list_head * p;
|
||
|
+ phenotype_t * pt;
|
||
|
+ int count = 0;
|
||
|
+ long rate = 0;
|
||
|
+
|
||
|
+ list_for_each(p, &in_pt->genetic->phenotype) {
|
||
|
+ pt = list_entry(p, phenotype_t, phenotype);
|
||
|
+
|
||
|
+ if (in_pt->uid & pt->uid && in_pt->uid != pt->uid) {
|
||
|
+ rate += pt->mutation_rate;
|
||
|
+ count++;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ /* If we are a general phenotype that is made up of other
|
||
|
+ phenotypes then we take the average */
|
||
|
+ if (count)
|
||
|
+ in_pt->mutation_rate = (rate / count);
|
||
|
+ else
|
||
|
+ in_pt->mutation_rate = mutation_rate_change;
|
||
|
+}
|
||
|
+
|
||
|
+static void genetic_calc_stats(phenotype_t * pt)
|
||
|
+{
|
||
|
+ long long total_fitness = 0;
|
||
|
+ long long prev_gen_avg_fitness = pt->last_gen_avg_fitness;
|
||
|
+ long long tmp_fitness;
|
||
|
+ long dummy;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ /* calculate the avg fitness for this generation and avg fitness
|
||
|
+ * so far */
|
||
|
+ for (i = 0; i < pt->num_children; i++)
|
||
|
+ total_fitness += pt->child_ranking[i]->fitness;
|
||
|
+
|
||
|
+ pt->last_gen_avg_fitness = total_fitness >> long_log2(pt->num_children);
|
||
|
+
|
||
|
+ /* Mutation rate calibration */
|
||
|
+ genetic_shift_mutation_rate(pt, prev_gen_avg_fitness, pt->last_gen_avg_fitness);
|
||
|
+
|
||
|
+ pt->num_mutations = ((pt->num_children * pt->num_genes) * pt->mutation_rate) / 100;
|
||
|
+
|
||
|
+ /* calc new avg fitness */
|
||
|
+ tmp_fitness = pt->last_gen_avg_fitness - pt->avg_fitness;
|
||
|
+ divll(&tmp_fitness, pt->genetic->generation_number, &dummy);
|
||
|
+ pt->avg_fitness += tmp_fitness;
|
||
|
+
|
||
|
+ pt->fitness_history[pt->fitness_history_index++ & GENETIC_HISTORY_MASK] =
|
||
|
+ pt->last_gen_avg_fitness;
|
||
|
+
|
||
|
+}
|
||
|
+
|
||
|
+#if GENETIC_DEBUG
|
||
|
+/* Stores attributes into an array in the following format
|
||
|
+ * child_num fitness gene[0] gene[1] .... gene[num_genes-1]
|
||
|
+ * Add +1 to GENETIC_NUM_DEBUG_POINTS if add another dump_children
|
||
|
+ * call
|
||
|
+ */
|
||
|
+void dump_children(phenotype_t * pt)
|
||
|
+{
|
||
|
+ int i, j;
|
||
|
+ long * genes;
|
||
|
+ unsigned long debug_size = pt->debug_size;
|
||
|
+
|
||
|
+ for (i = 0; i < pt->num_children; i++) {
|
||
|
+ pt->debug_history[pt->debug_index++ % debug_size] = pt->child_ranking[i]->id;
|
||
|
+ pt->debug_history[pt->debug_index++ % debug_size] = pt->child_ranking[i]->fitness;
|
||
|
+
|
||
|
+ genes = (long *)pt->child_ranking[i]->genes;
|
||
|
+
|
||
|
+ for (j = 0; j < pt->child_ranking[i]->num_genes; j++) {
|
||
|
+ pt->debug_history[pt->debug_index++ % debug_size] = genes[j];
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+#else
|
||
|
+void dump_children(genetic_t * genetic) { return; }
|
||
|
+#endif
|
||
|
+
|
||
|
+void genetic_new_generation(genetic_t * genetic)
|
||
|
+{
|
||
|
+ struct list_head * tmp;
|
||
|
+
|
||
|
+ struct list_head * p;
|
||
|
+ phenotype_t * pt;
|
||
|
+
|
||
|
+ list_for_each(p, &genetic->phenotype) {
|
||
|
+ pt = list_entry(p, phenotype_t, phenotype);
|
||
|
+
|
||
|
+ /* Check to see if need to recalibrate fitness to take
|
||
|
+ other phenotypes' rankings into account. This
|
||
|
+ should be ran after all phenotypes that have input
|
||
|
+ have been ran. */
|
||
|
+ if (pt->ops->calc_post_fitness)
|
||
|
+ pt->ops->calc_post_fitness(pt);
|
||
|
+
|
||
|
+ dump_children(pt);
|
||
|
+
|
||
|
+ /* figure out top performers */
|
||
|
+ genetic_split_performers(pt);
|
||
|
+
|
||
|
+ /* calc stats */
|
||
|
+ genetic_calc_stats(pt);
|
||
|
+
|
||
|
+ dump_children(pt);
|
||
|
+
|
||
|
+ /* make some new children */
|
||
|
+ if (pt->num_genes)
|
||
|
+ pt->natural_selection(pt);
|
||
|
+
|
||
|
+ dump_children(pt);
|
||
|
+
|
||
|
+ /* mutate a couple of the next generation */
|
||
|
+ genetic_mutate(pt);
|
||
|
+
|
||
|
+ dump_children(pt);
|
||
|
+
|
||
|
+ /* Move the new children still sitting in the finished queue to
|
||
|
+ the run queue */
|
||
|
+ tmp = pt->run_queue;
|
||
|
+ pt->run_queue = pt->finished_queue;
|
||
|
+ pt->finished_queue = tmp;
|
||
|
+
|
||
|
+ pt->child_number = 0;
|
||
|
+ pt->debug_index = 0;
|
||
|
+
|
||
|
+ }
|
||
|
+
|
||
|
+ genetic->child_number = 0;
|
||
|
+ genetic->generation_number++;
|
||
|
+
|
||
|
+}
|
||
|
+
|
||
|
+/* Mutate a gene picking a random value within the gene range */
|
||
|
+void genetic_generic_random_mutate_gene(genetic_child_t * child, long gene_num)
|
||
|
+{
|
||
|
+ unsigned long *genes = (unsigned long *)child->genes;
|
||
|
+ unsigned long min = child->gene_param[gene_num].min;
|
||
|
+ unsigned long max = child->gene_param[gene_num].max;
|
||
|
+ unsigned long gene_value;
|
||
|
+ unsigned long range = max - min + 1;
|
||
|
+
|
||
|
+ /* create a mutation value */
|
||
|
+ get_random_bytes(&gene_value, sizeof(gene_value));
|
||
|
+
|
||
|
+ gene_value = gene_value % range;
|
||
|
+
|
||
|
+ genes[gene_num] = min + gene_value;
|
||
|
+}
|
||
|
+
|
||
|
+void genetic_generic_iterative_mutate_gene(genetic_child_t * child, long gene_num)
|
||
|
+{
|
||
|
+ unsigned long *genes = (unsigned long *)child->genes;
|
||
|
+ long min = child->gene_param[gene_num].min;
|
||
|
+ long max = child->gene_param[gene_num].max;
|
||
|
+ long change;
|
||
|
+ long old_value = genes[gene_num];
|
||
|
+ long new_value;
|
||
|
+ unsigned long range = max - min + 1;
|
||
|
+
|
||
|
+ /* If under 5, random might work better */
|
||
|
+ if (range < 5)
|
||
|
+ return genetic_generic_random_mutate_gene(child, gene_num);
|
||
|
+
|
||
|
+ /* get the % of change */
|
||
|
+ get_random_bytes(&change, sizeof(change));
|
||
|
+
|
||
|
+ change = change % GENETIC_ITERATIVE_MUTATION_RANGE;
|
||
|
+
|
||
|
+ new_value = ((long)(change * range) / (long)100) + old_value;
|
||
|
+
|
||
|
+ if (new_value > max)
|
||
|
+ new_value = max;
|
||
|
+ else if (new_value < min)
|
||
|
+ new_value = min;
|
||
|
+
|
||
|
+ genes[gene_num] = new_value;
|
||
|
+}
|
||
|
+
|
||
|
+void genetic_iterative_from_default_mutate_gene(genetic_child_t * child, long gene_num)
|
||
|
+{
|
||
|
+ unsigned long *genes = (unsigned long *)child->genes;
|
||
|
+ long min = child->gene_param[gene_num].min;
|
||
|
+ long max = child->gene_param[gene_num].max;
|
||
|
+ long initial = child->gene_param[gene_num].initial;
|
||
|
+ long change;
|
||
|
+ long old_value = genes[gene_num];
|
||
|
+ long new_value;
|
||
|
+ unsigned long range = initial - min + 1;
|
||
|
+
|
||
|
+ /* If under 5, random might work better */
|
||
|
+ if (range < 5)
|
||
|
+ return genetic_generic_random_mutate_gene(child, gene_num);
|
||
|
+
|
||
|
+ /* get the % of change */
|
||
|
+ get_random_bytes(&change, sizeof(change));
|
||
|
+
|
||
|
+ change = change % GENETIC_ITERATIVE_MUTATION_RANGE;
|
||
|
+
|
||
|
+ new_value = ((long)(change * range) / (long)100) + old_value;
|
||
|
+
|
||
|
+ if (new_value > max)
|
||
|
+ new_value = max;
|
||
|
+ else if (new_value < min)
|
||
|
+ new_value = min;
|
||
|
+
|
||
|
+ genes[gene_num] = new_value;
|
||
|
+}
|
||
|
+
|
||
|
+/* This assumes that all genes are a unsigned long array of size
|
||
|
+ num_genes */
|
||
|
+void genetic_generic_mutate_child(genetic_child_t * child)
|
||
|
+{
|
||
|
+ long gene_num = -1;
|
||
|
+
|
||
|
+ /* pick a random gene */
|
||
|
+ get_random_bytes(&gene_num, sizeof(gene_num));
|
||
|
+
|
||
|
+ if (gene_num < 0)
|
||
|
+ gene_num = -gene_num;
|
||
|
+
|
||
|
+ gene_num = gene_num % child->num_genes;
|
||
|
+
|
||
|
+ if (child->gene_param[gene_num].mutate_gene)
|
||
|
+ child->gene_param[gene_num].mutate_gene(child, gene_num);
|
||
|
+ else
|
||
|
+ genetic_generic_random_mutate_gene(child, gene_num);
|
||
|
+}
|
||
|
+
|
||
|
+void genetic_create_child_defaults(genetic_child_t * child)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+ unsigned long * genes = child->genes;
|
||
|
+
|
||
|
+ for (i = 0; i < child->num_genes; i++) {
|
||
|
+ genes[i] = child->gene_param[i].initial;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+void genetic_create_child_spread(genetic_child_t * child, unsigned long num_children)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+ unsigned long range;
|
||
|
+ int range_incr;
|
||
|
+ int child_num = child->id;
|
||
|
+ long num_genes = child->num_genes;
|
||
|
+ unsigned long * genes = child->genes;
|
||
|
+
|
||
|
+ for (i = 0; i < num_genes; i++) {
|
||
|
+ range = child->gene_param[i].max - child->gene_param[i].min + 1;
|
||
|
+ range_incr = range / num_children;
|
||
|
+ if (range_incr)
|
||
|
+ genes[i] = child->gene_param[i].min +
|
||
|
+ (range_incr * child_num);
|
||
|
+ else
|
||
|
+ genes[i] = child->gene_param[i].min +
|
||
|
+ (child_num / (num_children / range));
|
||
|
+ }
|
||
|
+
|
||
|
+}
|
||
|
+
|
||
|
+#if 0
|
||
|
+/* Randomly pick which parent to use for each gene to create a child */
|
||
|
+void genetic_generic_combine_genes(genetic_child_t * parent_a,
|
||
|
+ genetic_child_t * parent_b,
|
||
|
+ genetic_child_t * child)
|
||
|
+{
|
||
|
+ unsigned long * genes_a = (unsigned long *)parent_a->genes;
|
||
|
+ unsigned long * genes_b = (unsigned long *)parent_b->genes;
|
||
|
+ unsigned long * child_genes = (unsigned long *)child->genes;
|
||
|
+
|
||
|
+ /* Assume parent_a and parent_b have same num_genes */
|
||
|
+ unsigned long num_genes = parent_a->num_genes;
|
||
|
+ int parent_selector;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ get_random_bytes(&parent_selector, sizeof(parent_selector));
|
||
|
+
|
||
|
+ if ((sizeof(parent_selector) * 8) < num_genes)
|
||
|
+ BUG();
|
||
|
+
|
||
|
+ for (i = 0; i < num_genes; i++) {
|
||
|
+ /* Look at each bit to determine which parent to use */
|
||
|
+ if (parent_selector & 1) {
|
||
|
+ child_genes[i] = genes_a[i];
|
||
|
+ } else {
|
||
|
+ child_genes[i] = genes_b[i];
|
||
|
+ }
|
||
|
+ parent_selector >>= 1;
|
||
|
+ }
|
||
|
+}
|
||
|
+#else
|
||
|
+
|
||
|
+/* Randomly pick a percentage of each parent to use for each gene to create a child */
|
||
|
+void genetic_generic_combine_genes(genetic_child_t * parent_a,
|
||
|
+ genetic_child_t * parent_b,
|
||
|
+ genetic_child_t * child)
|
||
|
+{
|
||
|
+ unsigned long * genes_a = (unsigned long *)parent_a->genes;
|
||
|
+ unsigned long * genes_b = (unsigned long *)parent_b->genes;
|
||
|
+ unsigned long * child_genes = (unsigned long *)child->genes;
|
||
|
+
|
||
|
+ /* Assume parent_a and parent_b have same num_genes */
|
||
|
+ unsigned long num_genes = parent_a->num_genes;
|
||
|
+ int percentage;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ for (i = 0; i < num_genes; i++) {
|
||
|
+ get_random_bytes(&percentage, sizeof(percentage));
|
||
|
+
|
||
|
+ /* Get percentage */
|
||
|
+ percentage = percentage % 100;
|
||
|
+
|
||
|
+ if (percentage < 0)
|
||
|
+ percentage = -percentage;
|
||
|
+
|
||
|
+ /* Give child x% of parent A's genes value, plus
|
||
|
+ 100-x% of parent B's genes value */
|
||
|
+ child_genes[i] = (((genes_a[i]+1) * percentage) +
|
||
|
+ (genes_b[i] * (100 - percentage))) / 100;
|
||
|
+ }
|
||
|
+}
|
||
|
+#endif
|
||
|
+
|
||
|
+static int __init genetic_boot_setup(char *str)
|
||
|
+{
|
||
|
+ if (strcmp(str, "on") == 0)
|
||
|
+ genetic_lib_enabled = 1;
|
||
|
+ else if (strcmp(str, "off") == 0)
|
||
|
+ genetic_lib_enabled = 0;
|
||
|
+
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+static int __init genetic_mutation_rate_change_setup(char *str)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+
|
||
|
+ if (get_option(&str,&i)) {
|
||
|
+
|
||
|
+ if (i > GENETIC_MAX_MUTATION_RATE)
|
||
|
+ i = GENETIC_MAX_MUTATION_RATE;
|
||
|
+ else if (i < 0)
|
||
|
+ i = 0;
|
||
|
+
|
||
|
+ mutation_rate_change = i;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 1;
|
||
|
+
|
||
|
+}
|
||
|
+__setup("genetic=", genetic_boot_setup);
|
||
|
+__setup("genetic_mutate_rate=", genetic_mutation_rate_change_setup);
|