コード例 #1
0
ファイル: neatHandler.py プロジェクト: Hippoglyph/WireNet
class neatHandler:
    def __init__(self):
        local_dir = os.path.dirname(__file__)
        config_path = os.path.join(local_dir, 'config')
        self.circuit = Circuit()
        self.circuit.start()
        self.wireNames = self.circuit.getWires()
        self.numInputs = self.circuit.getPathMatrixSize() + len(
            self.wireNames) * 4
        self.numOutputs = len(self.wireNames) * 4
        self.editConfig(config_path)
        self.bestFitness = -999999
        self.stats = None
        self.run(config_path)

    def editConfig(self, config_path):
        inputSearch = "^num_inputs\s+=\s+(\d)+(\n)?$"
        inputReplace = "num_inputs              = " + str(
            self.numInputs) + "\n"
        outputSearch = "^num_outputs\s+=\s+(\d)+(\n)?$"
        outputReplace = "num_outputs             = " + str(
            self.numOutputs) + "\n"
        for line in fileinput.input(config_path, inplace=1):
            line = re.sub(inputSearch, inputReplace, line)
            line = re.sub(outputSearch, outputReplace, line)
            sys.stdout.write(line)
        print("Config file edited")

    def eval_genomes(self, genomes, config):
        for genome_id, genome in genomes:
            net = neat.nn.FeedForwardNetwork.create(genome, config)
            genome.fitness = self.evalNet(net)
            if self.bestFitness < genome.fitness:
                self.bestFitness = genome.fitness
                print("New Best Fitness: " + str(self.circuit.getFitness()))
                self.circuit.drawResult()
                visualize.plot_stats(self.stats, ylog=False, view=True)

    def evalNet(self, net):
        self.circuit.restart()
        while not (self.circuit.isDone()):
            output = net.activate(self.getInputsForCircuit())
            if not self.makeMove(output):
                break
        return self.circuit.getFitness()

    def makeMove(self, output):
        moves = self.getMoveList(output)
        for move in moves:
            if move[0](move[2]):
                return True
        return False

    def getMoveList(self, output):
        i = 0
        moves = []
        for wire in self.wireNames:
            moves.append((self.circuit.moveNorth, output[i], wire))
            i += 1
            moves.append((self.circuit.moveEast, output[i], wire))
            i += 1
            moves.append((self.circuit.moveSouth, output[i], wire))
            i += 1
            moves.append((self.circuit.moveWest, output[i], wire))
            i += 1
        moves.sort(key=lambda tup: tup[1])
        return moves

    def getInputsForCircuit(self):
        inputs = []
        for row in self.circuit.getPathMatrix():
            for i in row:
                inputs.append(i)
        for wire in self.wireNames:
            srow, scol = self.circuit.getWirePosition(wire)
            inputs.append(srow / self.circuit.getRows())
            inputs.append(scol / self.circuit.getCols())
            grow, gcol = self.circuit.getWireGoal(wire)
            inputs.append(grow / self.circuit.getRows())
            inputs.append(gcol / self.circuit.getCols())
        return inputs

    def run(self, config_file):
        # Load configuration.
        config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
                             neat.DefaultSpeciesSet, neat.DefaultStagnation,
                             config_file)

        # Create the population, which is the top-level object for a NEAT run.
        p = neat.Population(config)

        # Add a stdout reporter to show progress in the terminal.
        p.add_reporter(neat.StdOutReporter(True))
        self.stats = neat.StatisticsReporter()
        p.add_reporter(self.stats)

        # Run for up to 300 generations.
        winner = p.run(self.eval_genomes, 1000)
        self.evalNet(neat.nn.FeedForwardNetwork.create(winner, config))
        #os.system("/usr/bin/canberra-gtk-play --id='bell'")

        #visualize.draw_net(config, winner, True)
        visualize.plot_stats(self.stats, ylog=False, view=True)
        #visualize.plot_species(stats, view=True)

        print("Turns: " + str(self.circuit.getTotalTurns()))
        print("WireLength: " + str(self.circuit.getWireLength()))
        print("Completed Wires: " + str(self.circuit.getCompletedWires()))
        print("Fitness: " + str(self.circuit.getFitness()))
        self.circuit.drawResult()