遗传算法:go语言实现

来源:互联网 发布:才子网络电话录音 编辑:程序博客网 时间:2024/05/14 07:55

tips:写这个遗传算法的另一个目的是为了练习go语言,如有缺陷,请不吝赐教。

下面算法用来求解函数y=x^7+x^6-100x^5+200x^4-300x^3-13579x^2-2468x+123456789函数再(-8,8)上的最小值

对于该问题解空间是非常明确的。对于结果偏差小于0.001则视为未改变。为了方便采用二进制编码我们将解空间换算为(8-(-8))*1000=1600因此每条染色体的基因数可以设为14
种群规模设为20。
执行步骤
1.初始化操作
该步骤主要用来初始化算法需要的一些基础资源。包括设置随机数种子,初始化第一代种群等数据。
2.计算出第一代种群的适应度,这里指函数的值。
3.对适应度进行排序
4.迭代种群,达到最优
4.1 父种群按概率进行交叉操作,交叉位置随机生成。产生子代种群。
4.2 对子种群进行适应度计算。
4.3 对子种群按适应度进行排序
4.4 在父子种群中选择适应度最高的20个作为父种群遗传下去
4.5 是否达到最优
4.6 记录最优值
4.7 按概率进行变异操作。
4.8 对变异后的种群进行计算
4.9 对变异后的种群进行排序
注意:
1.这里变异操作并没有进行每一个基因的按概率变异,而是计算出某个染色体变异的概率,然后按概概率判断当前染色体是否变异,若变异则随机生成变异位进行变异。
2.终止条件即为100次迭代中种群的相邻两代最优适应度的值相差小于0.001的次数达到100次则视为最优。当然这可以根据实际情况进行调整。如果达到最大循环次数任然未达到最优则视为失败。在记录文件末尾打印error。

可以先用该算法进行一个小小的测试,计算y=x^2-4在(-8,8)上的最小值,每一代的最优值记录在GeneticLog文件中。结果贴在代码后面。

//用于求解函数y=x^7+x^6-100x^5+200x^4-300x^3-13579x^2-2468x+123456789在(-8,8)之间的最小值package mainimport (    "math/rand"    "fmt"    "time"    "os"    "strconv")//染色体数量const COUNT int = 20//最大循环次数,若超过该次数程序仍然没有终止则退出程序并未达到最优const MAXLOOP int = 1500//两次结果小于该值则认为结果没有改变const MINIMAL_SUB float32 = 0.01//交叉概率const CROSS_PROBABILITY float32 = 0.2//变异概率const CHANGE_PROBABILITY float32 = 0.2type chromosome struct {    //用int的后十四位表示染色体的二进制编码    value uint16    //该染色体对应的适应度函数值    suitability float32}type log struct {    value       uint16    suitability float32    Next        *log}//定义染色体组var chromosome_group [COUNT] chromosome//定义子染色体组var chromosome_new_group [COUNT] chromosome//最优染色体var chromosome_most_suitable chromosome//适应度没有改变的次数,达到二十次则认为结果已经最优var suitability_unchange_count int = 0var head, end *logfunc main() {    isParent := 1    initialization()    calculateSuit(isParent)    sortSuit(isParent)    for i := 0; i < MAXLOOP; i++ {        cross()        calculateSuit(0)        sortSuit(0)        selection()        if complete() {            break        }        record()        variation()        calculateSuit(1)        sortSuit(1)    }    writeLog()    fmt.Println("取值为", Binary_to_Decimal(chromosome_most_suitable.value), "时,达到最大适应度", chromosome_most_suitable.suitability, "。")}//将寻找最优解的过程写入文件func writeLog() {    file, err := os.Create("./src/main/GeneticLog")    if err != nil {        fmt.Println(file, err)    }    defer file.Close()    i := 1    for ; head.Next != nil; i++ {        d := strconv.FormatFloat(float64(head.Next.suitability), 'f', -1, 32)        file.WriteString(d + "  ")        if i%10 == 0 {            file.WriteString("\n")        }        head = head.Next    }    d := strconv.FormatFloat(float64(head.suitability), 'f', -1, 32)    file.WriteString(d + "  ")    if i%10 == 0 {        file.WriteString("\n")    }    if complete() {        file.WriteString("complete!")    } else {        file.WriteString("error")    }}//检查是否达到最优func complete() bool {    if chromosome_group[0].suitability-end.suitability < MINIMAL_SUB && chromosome_group[0].suitability-end.suitability > -MINIMAL_SUB {        suitability_unchange_count++    } else {        suitability_unchange_count = 0    }    if suitability_unchange_count >= UNCHANGE_COUNT_MAX {        return true    } else {        return false    }}//变异操作func variation() {    for i := 0; i < COUNT; i++ {        //判断该染色体是否变异        if rand_ByProbability(1-power(1-CHANGE_PROBABILITY, 14)) == 1 {            //选择具体的变异位置            point := rand_Between_TwoNumber(0, 13)            mark := uint16(1 << point)            chromosome_group[i].value = chromosome_group[i].value ^ mark        }    }}//记录每次的最优情况func record() {    logx := log{}    logx.suitability = chromosome_group[0].suitability    logx.value = chromosome_group[0].value    logx.Next = nil    end.Next = &logx    end = end.Next    chromosome_most_suitable = chromosome_group[0]}//选择适应度最高的COUNT个染色体作为父总群func selection() {    for i, j, k := 0, 0, 0; i < COUNT; i++ {        if chromosome_group[j].suitability <= chromosome_new_group[k].suitability {            chromosome_group[i] = chromosome_group[j]            j++        } else {            chromosome_group[i] = chromosome_new_group[k]            k++        }    }}//交叉产生新种群func cross() {    var flag [COUNT] int    for i, j := 0, 0; i < COUNT; i++ {        //随机选择另一条染色体        if flag[i] == 0 {            for {                j = int(rand_Between_TwoNumber(i, COUNT-1))                if flag[j] == 0 {                    break                }            }        }        //按概率对染色体i,j进行交叉        if rand_ByProbability(CROSS_PROBABILITY) == 1 {            mark1 := create_mark(uint16(rand_Between_TwoNumber(0, 13)))            mark2 := ^mark1            chromosome_new_group[i].value = (chromosome_group[i].value)&mark1 + (chromosome_group[j].value)&mark2            chromosome_new_group[j].value = (chromosome_group[i].value)&mark2 + (chromosome_group[j].value)&mark1        } else {            chromosome_new_group[i] = chromosome_group[i]            chromosome_new_group[j] = chromosome_group[j]        }    }}//按适应度对中群内个体进行排序func sortSuit(isParent int) {    if isParent == 1 {        for i := 0; i < COUNT; i++ {            for j := i + 1; j < COUNT; j++ {                if chromosome_group[i].suitability > chromosome_group[j].suitability {                    temp := chromosome_group[i]                    chromosome_group[i] = chromosome_group[j]                    chromosome_group[j] = temp                }            }        }    } else {        for i := 0; i < COUNT; i++ {            for j := i + 1; j < COUNT; j++ {                if chromosome_new_group[i].suitability > chromosome_new_group[j].suitability {                    temp := chromosome_new_group[i]                    chromosome_new_group[i] = chromosome_new_group[j]                    chromosome_new_group[j] = temp                }            }        }    }}//计算种群每个个体的适应度func calculateSuit(isParent int) {    if isParent == 1 {        for i := 0; i < COUNT; i++ {            x := Binary_to_Decimal(chromosome_group[i].value)            //x^7-600x^6-100x^5+200x^4-300x^3-13579x^2-2468x+123456789            chromosome_group[i].suitability = x*(x*(x*(x*(x*(x*(x*(x-600))-100)+200)-300)-13579)-2468) + 123456789            //chromosome_group[i].suitability = (x + 2) * (x - 2)        }    } else {        for i := 0; i < COUNT; i++ {            x := Binary_to_Decimal(chromosome_new_group[i].value)            //用于求解函数y=x^7+600x^6-100x^5+200x^4-300x^3-13579x^2-2468x+123456789在(-8,8)之间的最小值            chromosome_new_group[i].suitability = x*(x*(x*(x*(x*(x*(x*(x-600))-100)+200)-300)-13579)-2468) + 123456789            //chromosome_new_group[i].suitability = (x + 2) * (x - 2)        }    }}//初始化染色体func initialization() {    //随机数种子,防止每次产生的随机数一样    rand.Seed(int64(time.Now().Nanosecond()))    for i := 0; i < COUNT; i++ {        chromosome_group[i].value = rand_generate_chromosome()    }    chromosome_most_suitable.suitability = -100000    suitability_unchange_count = 0    //初始化记录链表    log0 := log{0, 0, nil}    head = &log0    end = head    head = end}//随机初始化种群,产生0-16000之间的随机数func rand_generate_chromosome() uint16 {    return uint16(rand.Intn(16000) + 1)}//实际值转化为二进制表示func Decimal_to_Binary(x float32) uint16 {    var y int = int(x)    return uint16(y*1000 + 8000)}//二进制值转化为实际值func Binary_to_Decimal(x uint16) float32 {    var y float32 = float32(x)    return (y - 8000) / 1000}//随机产生具体数字之间的一个数,不包括i包括jfunc rand_Between_TwoNumber(i int, j int) uint16 {    if i == j {        return uint16(i)    }    return uint16(i + 1 + rand.Intn(j-i))}//根据概率返回1func rand_ByProbability(p float32) int {    if float32(rand.Intn(100)) > 99*p {        return 0    } else {        return 1    }}//根据交叉位置生成相应的二进制操作数func create_mark(number uint16) uint16 {    return (1 << (number + 1)) - 1}//func power(x float32, y int) float32 {    result := x    for y > 1 {        result = result * x        y--    }    return result}

求解y=x^2-4的最小值的结果

-3.733744  -3.999984  -3.999984  -3.9999962  -3.9999962  -3.9999962  -3.9999962  -3.9999962  -3.9999962  -3.999984  -3.9999962  -3.9999962  -3.999984  -3.9999359  -3.999984  -3.9999962  -3.9999962  -3.9999962  -3.9999962  -3.999984  -3.9999359  -3.999984  -3.999984  -3.9999359  -3.999984  -3.9999962  -3.999984  -3.9999962  -3.999984  -3.9999359  -3.9999  -3.9999962  -3.999984  -3.9999962  -3.9999962  -3.9999962  -3.999984  -3.999984  -3.9999962  -3.9999962  -3.999984  -3.9999962  -3.999984  -3.9999962  -3.9999962  -3.9999962  -3.9999962  -3.9999962  -3.9999962  -3.999984  -3.9999962  -3.9999962  -3.9999962  -3.9999962  -3.9999962  -3.9999962  -3.9999962  -3.999964  -3.999964  -3.999964  -3.9999962  -3.999984  -3.9999962  -3.9999962  -3.9999962  -3.9999  -3.9999962  -3.999964  -3.9999962  -3.9999962  -3.9999962  -3.999964  -3.9999962  -3.999964  -3.9999962  -3.9999962  -3.9999962  -3.999984  -3.9999962  -3.9999  -3.9999962  -3.999984  -3.9999962  -3.9999962  -3.999984  -3.9999962  -3.9999962  -3.999984  -3.9999962  -3.9999962  -3.999984  -3.9999962  -3.9999962  -3.9999962  -3.9999962  -3.999964  -3.9999962  -3.9999962  -3.999984  -3.9999962  -3.9999962  -3.9999962  complete!

求解y=x^7+x^6-100x^5+200x^4-300x^3-13579x^2-2468x+123456789在(-8,8)的最小值
对于这种相差较大的适应度应调整结果不变的判断值,这里是调整为10000,变异概率为0.01时的结果

-490958300  -570994200  -570994200  -570994200  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  -1600633000  complete!
原创粉丝点击