本文目录导读:

我来为您提供几个Java适应度函数(Fitness Function)的典型案例,这些案例常用于遗传算法等进化计算中。
基本函数优化案例
案例1:求函数最大值
import java.util.Random;
public class FunctionOptimizationFitness {
// 求 f(x) = x * sin(10πx) + 1 的最大值,x ∈ [-1, 2]
public static double evaluateFunction(double x) {
return x * Math.sin(10 * Math.PI * x) + 1;
}
// 适应度函数:直接使用函数值作为适应度
public static double fitnessFunction(double x) {
double result = evaluateFunction(x);
// 如果超出范围,返回极小的适应度值
if (x < -1 || x > 2) {
return -Double.MAX_VALUE;
}
return result;
}
// 测试代码
public static void main(String[] args) {
Random rand = new Random();
// 生成一些随机解并计算适应度
for (int i = 0; i < 10; i++) {
double x = -1 + rand.nextDouble() * 3; // 在[-1, 2]范围内
double fitness = fitnessFunction(x);
System.out.printf("x = %.4f, f(x) = %.4f, Fitness = %.4f%n",
x, evaluateFunction(x), fitness);
}
}
}
案例2:多峰函数优化(Rastrigin函数)
public class RastriginFitness {
// Rastrigin函数:常用于测试优化算法
private static double rastrigin(double[] x) {
int n = x.length;
double sum = 10 * n;
for (int i = 0; i < n; i++) {
sum += x[i] * x[i] - 10 * Math.cos(2 * Math.PI * x[i]);
}
return sum;
}
// 适应度函数(最小化问题,取负数)
public static double fitnessFunction(double[] solution) {
double result = rastrigin(solution);
return -result; // 转换成最大化问题
}
// 检查约束
private static boolean isFeasible(double[] solution) {
double range = 5.12;
for (double x : solution) {
if (x < -range || x > range) {
return false;
}
}
return true;
}
}
旅行商问题(TSP)
import java.util.*;
public class TSPFitness {
private double[][] distanceMatrix;
private int numCities;
public TSPFitness(double[][] distanceMatrix) {
this.distanceMatrix = distanceMatrix;
this.numCities = distanceMatrix.length;
}
// 计算路径总距离
public double calculateTotalDistance(int[] path) {
double totalDistance = 0;
for (int i = 0; i < path.length - 1; i++) {
totalDistance += distanceMatrix[path[i]][path[i + 1]];
}
// 返回起点
totalDistance += distanceMatrix[path[path.length - 1]][path[0]];
return totalDistance;
}
// TSP适应度函数(距离越短,适应度越高)
public double fitnessFunction(int[] path) {
// 验证路径有效性
if (!isValidPath(path)) {
return 0; // 无效路径返回0适应度
}
double totalDistance = calculateTotalDistance(path);
// 适应度 = 1 / 总距离 (避免除以0)
return 1.0 / (totalDistance + 1e-10);
}
private boolean isValidPath(int[] path) {
Set<Integer> visited = new HashSet<>();
for (int city : path) {
if (city < 0 || city >= numCities || visited.contains(city)) {
return false;
}
visited.add(city);
}
return visited.size() == numCities;
}
// 示例:创建距离矩阵并测试
public static void main(String[] args) {
// 创建5个城市的距离矩阵示例
double[][] distances = {
{0, 10, 15, 20, 25},
{10, 0, 35, 25, 30},
{15, 35, 0, 30, 20},
{20, 25, 30, 0, 15},
{25, 30, 20, 15, 0}
};
TSPFitness tspFitness = new TSPFitness(distances);
// 测试一个路径
int[] path = {0, 1, 2, 3, 4};
double fitness = tspFitness.fitnessFunction(path);
double distance = tspFitness.calculateTotalDistance(path);
System.out.println("路径: " + Arrays.toString(path));
System.out.println("总距离: " + distance);
System.out.println("适应度: " + fitness);
}
}
背包问题(Knapsack Problem)
import java.util.Random;
public class KnapsackFitness {
private int[] weights;
private int[] values;
private int capacity;
public KnapsackFitness(int[] weights, int[] values, int capacity) {
this.weights = weights;
this.values = values;
this.capacity = capacity;
}
// 背包问题适应度函数
public double fitnessFunction(boolean[] solution) {
int totalWeight = 0;
int totalValue = 0;
// 计算总重量和总价值
for (int i = 0; i < solution.length; i++) {
if (solution[i]) {
totalWeight += weights[i];
totalValue += values[i];
}
}
// 如果超过容量,使用惩罚函数
if (totalWeight > capacity) {
// 惩罚过重的解决方案
double penalty = (totalWeight - capacity) * 100.0;
return Math.max(0, totalValue - penalty);
}
return totalValue; // 返回总价值作为适应度
}
// 带约束条件的适应度函数
public double fitnessFunctionWithConstraints(boolean[] solution) {
int totalWeight = 0;
int totalValue = 0;
for (int i = 0; i < solution.length; i++) {
if (solution[i]) {
totalWeight += weights[i];
totalValue += values[i];
}
}
if (totalWeight > capacity) {
// 严重惩罚不可行解(指数惩罚)
return totalValue / Math.pow(1 + (totalWeight - capacity), 2);
}
// 奖励高效利用容量的解
double efficiencyBonus = (double) totalValue / totalWeight;
return totalValue + efficiencyBonus;
}
// 测试
public static void main(String[] args) {
int[] weights = {2, 3, 4, 5, 9};
int[] values = {3, 4, 5, 8, 10};
int capacity = 10;
KnapsackFitness knapsack = new KnapsackFitness(weights, values, capacity);
// 测试一个解
boolean[] solution = {true, true, false, true, false};
double fitness = knapsack.fitnessFunction(solution);
System.out.println("背包容量: " + capacity);
System.out.println("物品选择: " + Arrays.toString(solution));
System.out.println("适应度值: " + fitness);
}
}
通用适应度函数框架
public abstract class GenericFitnessFunction<T> {
// 抽象方法:计算个体适应度
public abstract double calculateFitness(T individual);
// 标准化适应度值到[0,1]范围
public double normalizeFitness(double fitness, double minFitness, double maxFitness) {
if (maxFitness == minFitness) {
return 1.0;
}
return (fitness - minFitness) / (maxFitness - minFitness);
}
// 带惩罚项的适应度计算
public double calculatePenalizedFitness(T individual, double penaltyFactor) {
double baseFitness = calculateFitness(individual);
double penalty = calculatePenalty(individual);
return baseFitness - penaltyFactor * penalty;
}
// 计算惩罚项(子类可重写)
protected double calculatePenalty(T individual) {
return 0.0;
}
// 检查解是否可行
public abstract boolean isFeasible(T individual);
}
// 示例:使用通用框架实现优化问题
public class SphereFunctionFitness extends GenericFitnessFunction<double[]> {
@Override
public double calculateFitness(double[] x) {
// 球面函数:f(x) = sum(xi^2),最小化问题
double sum = 0;
for (double xi : x) {
sum += xi * xi;
}
return -sum; // 转换成最大化问题
}
@Override
public boolean isFeasible(double[] x) {
// 解必须在[-100, 100]范围内
for (double xi : x) {
if (xi < -100 || xi > 100) {
return false;
}
}
return true;
}
@Override
protected double calculatePenalty(double[] x) {
double penalty = 0;
for (double xi : x) {
if (xi < -100) {
penalty += Math.pow(100 + xi, 2);
} else if (xi > 100) {
penalty += Math.pow(xi - 100, 2);
}
}
return penalty;
}
}
使用建议
- 标准化:将适应度值标准化到[0,1]范围,有助于算法稳定
- 惩罚函数:对于约束问题,合理使用惩罚函数
- 多样性:保持种群多样性,避免过早收敛
- 并行化:对于复杂问题,考虑并行计算适应度
这些案例涵盖了常见的优化问题类型,您可以根据具体需求进行修改和扩展。