Genetic Algorithms with python 学习笔记ch10

Solving Linear Equations

这个问题要我们求解线性方程组。
linearEquationTests.py 完整代码如下:

import unittest
import datetime
import genetic
import fractions
import random

class LinearEquationTests(unittest.TestCase):
    def solve_unknowns(self, numUnknowns, geneset, equations, fnGenesToInputs):
        startTime = datetime.datetime.now()
        maxAge = 50
        window = Window(max(1, int(len(geneset) / (2 * maxAge))),
                        max(1, int(len(geneset) / 3)),
                        int(len(geneset) / 2))
        geneIndexes = [i for i in range(numUnknowns)]
        sortedGeneset = sorted(geneset)

        def fnMutate(genes):
            mutate(genes, sortedGeneset, window, geneIndexes)


        def fnDisplay(candidate):
            display(candidate, startTime, fnGenesToInputs)

        def fnGetFitness(genes):
            return  get_fitness(genes, equations)

        optimalFitness = Fitness(0)
        best = genetic.get_best(fnGetFitness, numUnknowns, optimalFitness,
                                geneset, fnDisplay, fnMutate, maxAge=maxAge)
        self.assertTrue(not optimalFitness > best.Fitness)


    def test_4_unknowns(self):
        geneRange = [i for i in range(-13, 13) if i != 0]
        geneset = [i for i in set(
            fractions.Fraction(d, e)
            for d in geneRange
            for e in geneRange if e != 0)]

        def fnGenesToInputs(genes):
            return genes

        def e1(genes):
            x, y, z, a= genes
            return fractions.Fraction(1, 15) * x \
                    - 2 * y \
                    - 15 * z \
                    - fractions.Fraction(4,5) * a \
                    - 3

        def e2(genes):
            x,y,z,a  = genes
            return - fractions.Fraction(5,2) * x \
                    - fractions.Fraction(9,4) * y \
                    + 12 * z \
                    - a \
                    - 17


        def e3(genes):
            x,y,z,a = genes
            return -13 * x \
                    + fractions.Fraction(3,10) * y \
                    - 6 * z \
                    - fractions.Fraction(2,5) * a \
                    - 17

        def e4(genes):
            x,y,z,a = genes
            return fractions.Fraction(1,2) * x \
                    + 2 * y \
                    + fractions.Fraction(7, 4) * z \
                    + fractions.Fraction(4, 3) * a \
                    + 9

        equations = [e1, e2, e3, e4]
        self.solve_unknowns(4, geneset, equations, fnGenesToInputs)

    def test_benchmark(self):
        genetic.Benchmark.run(lambda :self.test_4_unknowns())

    def test_3_unknowns(self):
        geneRange = [i for i in range(-5, 5) if i != 0]
        geneset = [i for i in set(
            fractions.Fraction(d, e)
            for d in geneRange
            for e in geneRange if e!=0)]

        def fnGenesToInputs(genes):
            return genes

        def e1(genes):
            x, y, z = genes
            return 6 * x - 2 * y + 8 * z - 20

        def e2(genes):
            x,y,z = genes
            return y + 8 * x * z  + 1

        def e3(genes):
            x,y,z = genes
            return 2 * z * fractions.Fraction(6, x) + 3* fractions.Fraction(y, 2) - 6

        equations = [e1,e2,e3]

        self.solve_unknowns(3, geneset, equations, fnGenesToInputs)


def get_fitness(genes, equations):
    fitness = Fitness(sum(abs(e(genes)) for e in equations))
    return fitness

class Fitness:
    def __init__(self, totalDifference):
        self.TotalDifference = totalDifference

    def __gt__(self, other):
        return self.TotalDifference < other.TotalDifference

    def __str__(self):
        return "diff: {:0.2f}".format(float(self.TotalDifference))

def display(candidate, startTime, fnGenesToInputs):
    timeDiff = datetime.datetime.now() - startTime
    symbols = "xyza"
    result = ', '.join("{} = {}".format(s,v)
                       for s, v in zip(symbols, fnGenesToInputs(candidate.Genes)))
    print("{}\t{}\t{}".format(
        result,
        candidate.Fitness,
        timeDiff))

class Window:
    def __init__(self, minimum, maximum, size):
        self.Min = minimum
        self.Max = maximum
        self.Size = size

    def slide(self):
        self.Size = self.Size - 1 \
            if self.Size > self.Min else self.Max

def mutate(genes, sortedGeneset, window, geneIndexes):
    indexes = random.sample(geneIndexes, random.randint(1, len(genes))) \
        if random.randint(0, 10) == 0 else [random.choice(geneIndexes)]
    window.slide()
    while len(indexes) > 0:
        index = indexes.pop()
        genesetIndex = sortedGeneset.index(genes[index])
        start = max(0, genesetIndex - window.Size)
        stop = min(len(sortedGeneset)- 1, genesetIndex + window.Size)
        genesetIndex = random.randint(start, stop)
        genes[index] = sortedGeneset[genesetIndex]

需要注意的是这里使用maxAge来防止进入局部解,利用滑窗的方法提高效率,基因采用分数的形式,适应值计算的是等式的值,目标适应值为0.

posted @ 2020-08-24 19:17  idella  阅读(178)  评论(0编辑  收藏  举报