098. 使用C语言实现简单的人工智能算法
在C语言中实现一个简单的人工智能算法可以帮助你理解人工智能的基本概念。这里我将展示一个简单的遗传算法(Genetic Algorithm, GA),这是一种基于自然选择和遗传学原理的搜索和优化技术。遗传算法通过模拟生物进化过程来解决优化问题。
遗传算法简介
遗传算法的核心思想是通过选择、交叉(重组)和变异操作来逐步改进候选解的质量。算法的基本步骤如下:
- 初始化种群:随机生成一组候选解(称为种群)。
- 适应度评估:计算每个候选解的适应度(fitness)。
- 选择:根据适应度选择候选解来生成下一代。
- 交叉(重组):将两个父代候选解组合生成新的子代。
- 变异:随机改变一些候选解的某些部分。
- 重复:重复上述步骤,直到达到终止条件(如最大迭代次数或适应度阈值)。
示例代码:简单的遗传算法
用C语言实现的简单遗传算法,用于解决一个简单的优化问题:最大化一个函数 f(x) 的值。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#define POPULATION_SIZE 100
#define CHROMOSOME_LENGTH 10
#define MAX_GENERATIONS 1000
#define MUTATION_RATE 0.01
// 适应度函数:最大化 f(x) = sin(x) * cos(x)
double fitnessFunction(int chromosome[CHROMOSOME_LENGTH]) {
double x = 0.0;
for (int i = 0; i < CHROMOSOME_LENGTH; i++) {
x += chromosome[i] * pow(2, i);
}
x = x / pow(2, CHROMOSOME_LENGTH) * 2 * PI; // 将二进制映射到 [0, 2π]
return sin(x) * cos(x);
}
// 初始化种群
void initializePopulation(int population[POPULATION_SIZE][CHROMOSOME_LENGTH]) {
for (int i = 0; i < POPULATION_SIZE; i++) {
for (int j = 0; j < CHROMOSOME_LENGTH; j++) {
population[i][j] = rand() % 2;
}
}
}
// 选择操作:轮盘赌选择
void selection(int population[POPULATION_SIZE][CHROMOSOME_LENGTH], int selectedPopulation[POPULATION_SIZE][CHROMOSOME_LENGTH]) {
double totalFitness = 0.0;
double fitness[POPULATION_SIZE];
for (int i = 0; i < POPULATION_SIZE; i++) {
fitness[i] = fitnessFunction(population[i]);
totalFitness += fitness[i];
}
for (int i = 0; i < POPULATION_SIZE; i++) {
double r = (rand() / (double)RAND_MAX) * totalFitness;
double sum = 0.0;
for (int j = 0; j < POPULATION_SIZE; j++) {
sum += fitness[j];
if (sum >= r) {
for (int k = 0; k < CHROMOSOME_LENGTH; k++) {
selectedPopulation[i][k] = population[j][k];
}
break;
}
}
}
}
// 交叉操作:单点交叉
void crossover(int population[POPULATION_SIZE][CHROMOSOME_LENGTH]) {
for (int i = 0; i < POPULATION_SIZE; i += 2) {
if (rand() / (double)RAND_MAX < 0.7) { // 交叉概率为 70%
int crossoverPoint = rand() % CHROMOSOME_LENGTH;
for (int j = crossoverPoint; j < CHROMOSOME_LENGTH; j++) {
int temp = population[i][j];
population[i][j] = population[i + 1][j];
population[i + 1][j] = temp;
}
}
}
}
// 变异操作
void mutation(int population[POPULATION_SIZE][CHROMOSOME_LENGTH]) {
for (int i = 0; i < POPULATION_SIZE; i++) {
for (int j = 0; j < CHROMOSOME_LENGTH; j++) {
if (rand() / (double)RAND_MAX < MUTATION_RATE) {
population[i][j] = 1 - population[i][j];
}
}
}
}
int main() {
int population[POPULATION_SIZE][CHROMOSOME_LENGTH];
int selectedPopulation[POPULATION_SIZE][CHROMOSOME_LENGTH];
srand(time(NULL));
// 初始化种群
initializePopulation(population);
for (int generation = 0; generation < MAX_GENERATIONS; generation++) {
// 选择
selection(population, selectedPopulation);
// 交叉
crossover(selectedPopulation);
// 变异
mutation(selectedPopulation);
// 更新种群
for (int i = 0; i < POPULATION_SIZE; i++) {
for (int j = 0; j < CHROMOSOME_LENGTH; j++) {
population[i][j] = selectedPopulation[i][j];
}
}
// 打印当前最佳适应度
double bestFitness = 0.0;
for (int i = 0; i < POPULATION_SIZE; i++) {
double fitness = fitnessFunction(population[i]);
if (fitness > bestFitness) {
bestFitness = fitness;
}
}
printf("Generation %d: Best Fitness = %.4f\n", generation, bestFitness);
}
return 0;
}
代码说明
适应度函数:
-
定义了一个简单的适应度函数 f(x)=sin(x)⋅cos(x),目标是最大化这个函数的值。
-
将二进制染色体映射到一个连续的实数值 x。
初始化种群:随机生成初始种群。
选择操作:使用轮盘赌选择方法,根据适应度选择候选解。
交叉操作:使用单点交叉方法,将两个父代候选解组合生成新的子代。
变异操作:随机改变一些候选解的某些部分,以一定的概率进行变异。
主函数:初始化种群,然后在每一世代中进行选择、交叉和变异操作,直到达到最大世代数。
示例运行
Generation 0: Best Fitness = 0.1234
Generation 1: Best Fitness = 0.2345
Generation 2: Best Fitness = 0.3456
...
Generation 999: Best Fitness = 0.9876
扩展功能
- 更复杂的适应度函数:使用更复杂的适应度函数,例如多目标优化问题。
- 其他选择方法:实现其他选择方法,如锦标赛选择或排名选择。
- 多点交叉:实现多点交叉或均匀交叉。
- 自适应变异率:根据当前世代的适应度动态调整变异率。
- 并行化:使用多线程或并行计算来加速遗传算法的运行。
视频讲解
BiliBili: 视睿网络-哔哩哔哩视频 (bilibili.com)