Flutter遗传算法与进化计算插件genetic_evolution的使用

发布于 1周前 作者 songsunli 来自 Flutter

Flutter 遗传算法与进化计算插件 genetic_evolution 的使用

简介

genetic_evolution 是一个模拟遗传进化算法的包。

目录

基本用法

首先,你必须定义自己的 GeneService,描述DNA链中的基因。注意我们定义了一个类型为 <String> 的基因。

class MyGeneService extends GeneService<String> {
  // 实现基因服务方法
}

然后,你必须定义自己的 FitnessService,描述实体DNA的表现效果。

class MyFitnessService extends FitnessService<String> {
  // 实现适应度服务方法
}

接下来,你可以初始化一个 GeneticEvolution 对象。

GeneticEvolution geneticEvolution = GeneticEvolution(
  geneticEvolutionConfig: GeneticEvolutionConfig(
    numGenes: 10,
    mutationRate: 0.25
  ),
  fitnessService: MyFitnessService(),
  geneService: MyGeneService(),
);

最后,你可以通过 nextGeneration() 获取下一代。

Generation generation = await geneticEvolution.nextGeneration();

示例

简单单词示例

这个单词示例的代码可以在 /example/word_example 文件夹中找到。

简单单词示例

以下是包含该示例主要源代码的 word_home_page.dart 文件:

import 'package:flutter/material.dart';
import 'package:genetic_evolution/genetic_evolution.dart';
import 'package:word_example/word_fitness_service.dart';
import 'package:word_example/word_gene_service.dart';

// 定义目标单词
const target = 'HELLO WORLD';

/// 通过文本展示遗传进化的一个例子。
class WordHomePage extends StatefulWidget {
  const WordHomePage({
    super.key,
    this.autoPlay = true,
  });

  final bool autoPlay;

  @override
  State<WordHomePage> createState() => _WordHomePageState();
}

class _WordHomePageState extends State<WordHomePage> {
  late GeneticEvolution<String> geneticEvolution;
  Generation<String>? generation;
  bool isPlaying = false;
  int? waveTargetFound;

  @override
  void initState() {
    final numGenes = target.characters.length;
    const populationSize = 30;
    const mutationRate = 0.05; // 5%
    final wordFitnessService = WordFitnessService();
    final wordGeneService = WordGeneService();

    final GeneticEvolutionConfig geneticEvolutionConfig =
        GeneticEvolutionConfig(
      numGenes: numGenes,
      populationSize: populationSize,
      mutationRate: mutationRate,
    );

    geneticEvolution = GeneticEvolution(
      geneticEvolutionConfig: geneticEvolutionConfig,
      fitnessService: wordFitnessService,
      geneService: wordGeneService,
    );

    // 初始化第一代
    geneticEvolution.nextGeneration().then((value) {
      setState(() {
        generation = value;
      });
    });

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final generation = this.generation;
    if (generation == null) {
      return const CircularProgressIndicator();
    }
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
      if (isPlaying) {
        await Future.delayed(const Duration(milliseconds: 100));
        geneticEvolution.nextGeneration().then((value) {
          setState(() {
            this.generation = value;
          });
        });
      }
    });

    // 检查目标是否已被找到
    if (waveTargetFound == null && convertWord(generation.population.topScoringEntity) == target) {
      waveTargetFound = generation.wave;
    }

    // 将所有实体转换为单词
    final List<Widget> wordRows = [
      const Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text('value'),
          SizedBox(width: 72),
          Text('score'),
        ],
      ),
    ];
    final entities = generation.population.entities;
    for (var entity in entities) {
      String word = convertWord(entity);

      wordRows.add(
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(word),
            const SizedBox(width: 24),
            Text(entity.fitnessScore.toString()),
          ],
        ),
      );
    }

    return Scaffold(
      body: SafeArea(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            const Text(
              'Target: $target',
            ),
            Text(
              'Wave: ${generation.wave.toString()}',
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Column(
                  children: [
                    const Text('Top Value'),
                    Text(
                      convertWord(generation.population.topScoringEntity),
                    ),
                  ],
                ),
                const SizedBox(width: 24),
                Column(
                  children: [
                    const Text('Top Score'),
                    Text(
                      generation.population.topScoringEntity.fitnessScore.toString(),
                    ),
                  ],
                ),
              ],
            ),
            if (waveTargetFound != null)
              Text('Target reached at wave: $waveTargetFound'),
            const SizedBox(height: 24),
            const Text('Entities'),
            Flexible(
              child: ListView(
                children: wordRows,
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          if (widget.autoPlay) {
            setState(() {
              isPlaying = !isPlaying;
            });
          } else {
            geneticEvolution.nextGeneration().then((value) {
              setState(() {
                this.generation = value;
              });
            });
          }
        },
        child: (!widget.autoPlay || !isPlaying)
            ? const Icon(Icons.play_arrow)
            : const Icon(Icons.pause),
      ),
    );
  }

  String convertWord(Entity<String> entity) {
    String word = '';
    for (var gene in entity.dna.genes) {
      var value = gene.value;

      word += value;
    }

    return word;
  }
}

文件解析

你可以将特定世代写入文件,并从文件中读取特定世代。

首先,定义自己的 JsonConverter。这个类描述如何将类型 <T> 的对象转换为 JSON。

class GeneJsonConverter extends JsonConverter<String, Map<String, dynamic>> {
  @override
  fromJson(Map<String, dynamic> json) {
    return json['text'];
  }

  @override
  toJson(String object) {
    return {'text': object};
  }
}

接下来,基于上述 JsonConverter 定义你的 FileParser 对象。

final fileParser = FileParser<String>(
  geneJsonConverter: GeneJsonConverter(),
);

GeneticEvolution 构造函数中包含这个 fileParser

final geneticEvolution = GeneticEvolution(
  fileParser: fileParser,
  // 其他参数
)

现在,你可以将当前的 Generation 写入文件。

geneticEvolution.writeGenerationToFile();

最后,你可以从文件中加载特定的 Generation

geneticEvolution.loadGenerationFromFile(wave: 10);

更多关于Flutter遗传算法与进化计算插件genetic_evolution的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter遗传算法与进化计算插件genetic_evolution的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用genetic_evolution插件进行遗传算法与进化计算的代码示例。genetic_evolution是一个假设的插件名称,因为实际中可能没有一个广泛使用的名为genetic_evolution的Flutter插件。不过,我们可以基于遗传算法的基本原理来实现一个简化版本。

首先,确保你在pubspec.yaml文件中添加了必要的依赖项(尽管这个依赖项是假设的,实际使用时需要找到或创建一个合适的库):

dependencies:
  flutter:
    sdk: flutter
  genetic_evolution: ^x.y.z  # 假设的版本号

然后,在你的Flutter项目中,你可以按照以下步骤使用遗传算法来解决一个简单的优化问题,比如寻找一个函数的最大值。

1. 定义一个目标函数

首先,我们定义一个简单的目标函数,比如一个二次函数,我们希望找到它的最大值。

double targetFunction(List<double> genes) {
  // 假设我们有一个简单的二次函数 f(x) = -x^2 + 4x - 3
  double x = genes.single; // 在这个例子中,我们假设只有一个基因
  return -x * x + 4 * x - 3;
}

2. 初始化种群

接下来,我们初始化一个种群,每个个体都是一个可能的解决方案(即一组基因)。

import 'dart:math';

List<List<double>> initializePopulation(int populationSize, int geneLength, double minGene, double maxGene) {
  List<List<double>> population = [];
  for (int i = 0; i < populationSize; i++) {
    List<double> individual = [];
    for (int j = 0; j < geneLength; j++) {
      individual.add(Random().nextDouble() * (maxGene - minGene) + minGene);
    }
    population.add(individual);
  }
  return population;
}

3. 选择、交叉和变异

实现选择、交叉和变异操作是遗传算法的核心。

List<List<double>> selection(List<List<double>> population, List<double> fitnesses) {
  // 轮盘赌选择算法
  double totalFitness = fitnesses.reduce((a, b) => a + b);
  List<double> cumulativeFitness = [0.0];
  for (int i = 0; i < fitnesses.length; i++) {
    cumulativeFitness.add(cumulativeFitness.last + fitnesses[i] / totalFitness);
  }
  
  List<List<double>> newPopulation = [];
  for (int i = 0; i < population.length; i++) {
    double r = Random().nextDouble();
    int selectedIndex = cumulativeFitness.indexWhere((f) => f >= r);
    newPopulation.add(population[selectedIndex]);
  }
  
  return newPopulation;
}

List<List<double>> crossover(List<List<double>> parents, double crossoverRate) {
  List<List<double>> offspring = [];
  for (int i = 0; i < parents.length; i += 2) {
    List<List<double>> pair = parents.sublist(i, i + 2);
    if (Random().nextDouble() < crossoverRate) {
      int crossoverPoint = Random().nextInt(pair[0].length);
      List<double> child1 = pair[0].sublist(0, crossoverPoint) + pair[1].sublist(crossoverPoint);
      List<double> child2 = pair[1].sublist(0, crossoverPoint) + pair[0].sublist(crossoverPoint);
      offspring.add(child1);
      offspring.add(child2);
    } else {
      offspring.addAll(pair);
    }
  }
  return offspring;
}

List<List<double>> mutate(List<List<double>> population, double mutationRate, double minGene, double maxGene) {
  return population.map((individual) => individual.map((gene) {
    if (Random().nextDouble() < mutationRate) {
      return Random().nextDouble() * (maxGene - minGene) + minGene;
    }
    return gene;
  }).toList()).toList();
}

4. 遗传算法主循环

最后,我们将这些组件组合起来,形成一个完整的遗传算法。

void geneticAlgorithm(int populationSize, int generations, int geneLength, double minGene, double maxGene, double crossoverRate, double mutationRate) {
  List<List<double>> population = initializePopulation(populationSize, geneLength, minGene, maxGene);
  
  for (int gen = 0; gen < generations; gen++) {
    List<double> fitnesses = population.map(targetFunction).toList();
    
    List<List<double>> selectedPopulation = selection(population, fitnesses);
    List<List<double>> offspring = crossover(selectedPopulation, crossoverRate);
    population = mutate(offspring, mutationRate, minGene, maxGene);
    
    // 输出每一代的最佳个体和适应度
    double maxFitness = fitnesses.reduce((a, b) => Math.max(a, b));
    int bestIndex = fitnesses.indexWhere((f) => f == maxFitness);
    print("Generation $gen: Best Fitness = $maxFitness, Best Individual = ${population[bestIndex]}");
  }
}

5. 运行遗传算法

在你的Flutter应用的某个地方(比如_MyHomePageStateinitState方法中),调用遗传算法函数。

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    super.initState();
    geneticAlgorithm(
      populationSize: 100,
      generations: 1000,
      geneLength: 1,
      minGene: -10.0,
      maxGene: 10.0,
      crossoverRate: 0.7,
      mutationRate: 0.01
    );
  }
  
  @override
  Widget build(BuildContext context) {
    // ... 构建你的UI
  }
}

请注意,这个代码示例是一个简化的遗传算法实现,并没有使用任何特定的genetic_evolution插件。如果你找到了一个实际的Flutter遗传算法插件,你应该参考该插件的文档来替代或增强这里的代码。

回到顶部