Java适应度函数案例

wen java案例 2

本文目录导读:

Java适应度函数案例

  1. 基本函数优化案例
  2. 旅行商问题(TSP)
  3. 背包问题(Knapsack Problem)
  4. 通用适应度函数框架
  5. 使用建议

我来为您提供几个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;
    }
}

使用建议

  1. 标准化:将适应度值标准化到[0,1]范围,有助于算法稳定
  2. 惩罚函数:对于约束问题,合理使用惩罚函数
  3. 多样性:保持种群多样性,避免过早收敛
  4. 并行化:对于复杂问题,考虑并行计算适应度

这些案例涵盖了常见的优化问题类型,您可以根据具体需求进行修改和扩展。

抱歉,评论功能暂时关闭!