package com.aps.entity.Algorithm;

import com.aps.common.util.FileHelper;

import java.text.DecimalFormat;
import java.time.LocalDateTime;

/**
 * 自适应遗传算法参数类（支持根据工序数量动态调整）
 * @author AutoGenerated
 */
public class ScheduleParams {

    private LocalDateTime baseTime ; // 当前基准时间

    // 基础参数（自适应调整的基准值）
    private static final int MIN_POPULATION_SIZE = 10;
    private static final int MAX_POPULATION_SIZE = 20;
    private static final int MIN_MAX_ITERATIONS = 10;
    private static final int MAX_MAX_ITERATIONS = 30;
    private static final float MIN_CROSSOVER_PROB = 0.6f;
    private static final float MAX_CROSSOVER_PROB = 0.9f;
    private static final float MIN_MUTATION_PROB = 0.2f;
    private static final float MAX_MUTATION_PROB = 0.5f;
    private static final int MIN_TOURNAMENT_SIZE = 3;
    private static final int MAX_TOURNAMENT_SIZE = 7;


    // 自适应调整后的参数（私有变量+公共访问方法）
    private int populationSize;
    private int maxIterations;
    private float crossoverProb;
    private float mutationProb;
    private int tournamentSize;

    /// <summary>
    /// 精英保留计数
    /// </summary>
    private int elitismCount = 5;

    /// <summary>
    /// 全局选择占比
    /// </summary>
    private double gsRatio = 0.4; // 全局选择占比

    /// <summary>
    /// 局部选择占比
    /// </summary>
    private double lsRatio = 0.4; // 局部选择占比

    /// <summary>
    /// 随机选择占比
    /// </summary>
    private double rsRatio = 0.2; // 随机选择占比

    // 自适应调整系数
    private float populationSizeCoeff = 0.01f; // 种群大小对工序数的敏感系数
    private float maxIterationsCoeff = 0.08f; // 迭代次数对工序数的敏感系数
    private float crossoverProbCoeff = 0.0001f; // 交叉概率对工序数的敏感系数
    private float mutationProbCoeff = 0.00005f; // 变异概率对工序数的敏感系数
    private float tournamentSizeCoeff = 200f; // 锦标赛规模对工序数的敏感系数（分母越大越不敏感）

    /// <summary>
    /// 基准时间
    /// </summary>
    public LocalDateTime getBaseTime() {
        return baseTime;
    }

    /// <summary>
    /// 种群规模
    /// </summary>
    public int getPopulationSize() {
        return populationSize;
    }

    /// <summary>
    /// 种群规模
    /// </summary>
    public void setPopulationSize(int populationSize) {
         populationSize=populationSize;
    }

    /// <summary>
    /// 最大迭代次数
    /// </summary>
    public int getMaxIterations() {
        return maxIterations;
    }

    /// <summary>
    /// 交叉概率
    /// </summary>
    public float setCrossoverProb(float crossoverProb) {
        return this.crossoverProb=crossoverProb;
    }

    /// <summary>
    /// 交叉概率
    /// </summary>
    public float getCrossoverProb() {
        return crossoverProb;
    }

    /// <summary>
    /// 变异概率
    /// </summary>
    public float getMutationProb() {
        return mutationProb;
    }
    /// <summary>
    /// 锦标赛规模
    /// </summary>
    public int getTournamentSize() {
        return tournamentSize;
    }

    /// <summary>
    /// 精英保留
    /// </summary>
    public int getElitismCount() {
        return elitismCount;
    }
    /// <summary>
    /// 全局选择占比
    /// </summary>
    public double getGsRatio() {
        return gsRatio;
    }
    /// <summary>
    /// 局部选择占比
    /// </summary>
    public double getLsRatio() {
        return lsRatio;
    }
    /// <summary>
    /// 随机选择占比
    /// </summary>
    public double getRsRatio() {
        return rsRatio;
    }

    /// <summary>
    /// 基准时间
    /// </summary>
    public void setBaseTime(LocalDateTime baseTime) {

        this.baseTime = baseTime;
    }

    // Setter方法（调整系数）
    public void setPopulationSizeCoeff(float populationSizeCoeff) {
        this.populationSizeCoeff = populationSizeCoeff;
    }

    public void setMaxIterationsCoeff(float maxIterationsCoeff) {
        this.maxIterationsCoeff = maxIterationsCoeff;
    }

    public void setCrossoverProbCoeff(float crossoverProbCoeff) {
        this.crossoverProbCoeff = crossoverProbCoeff;
    }

    public void setMutationProbCoeff(float mutationProbCoeff) {
        this.mutationProbCoeff = mutationProbCoeff;
    }

    public void setTournamentSizeCoeff(float tournamentSizeCoeff) {
        this.tournamentSizeCoeff = tournamentSizeCoeff;
    }



    /**
     * 根据总工序数初始化自适应参数（一次性调整）
     * @param totalOps 总工序数
     */
    public void initAdaptiveParams(int totalOps) {
        // 1. 种群大小：50 ~ 500，随工序数线性增加
        populationSize = (int) Math.max(MIN_POPULATION_SIZE,
                Math.min(MAX_POPULATION_SIZE, MIN_POPULATION_SIZE + totalOps * populationSizeCoeff));

        int maxthead = Math.max(1, Runtime.getRuntime().availableProcessors() - 1);
        if (populationSize >= maxthead) {
            populationSize = populationSize / maxthead * maxthead;
        }
        populationSize = Math.max(MIN_POPULATION_SIZE, populationSize);

        // 确保偶数（方便交叉）
//        if (populationSize % 2 != 0) {
//            populationSize += 1;
//        }

        // 2. 最大迭代次数：50 ~ 200，随工序数线性减少
        maxIterations = (int) Math.max(MIN_MAX_ITERATIONS,
                Math.min(MAX_MAX_ITERATIONS, MAX_MAX_ITERATIONS - totalOps * maxIterationsCoeff));

        // 3. 交叉概率：0.6 ~ 0.9，随工序数轻微减少
        crossoverProb = Math.max(MIN_CROSSOVER_PROB,
                Math.min(MAX_CROSSOVER_PROB, MAX_CROSSOVER_PROB - totalOps * crossoverProbCoeff));

        // 4. 变异概率：0.05 ~ 0.2，随工序数轻微增加
        mutationProb = Math.max(MIN_MUTATION_PROB,
                Math.min(MAX_MUTATION_PROB, MIN_MUTATION_PROB + totalOps * mutationProbCoeff));

        // 5. 锦标赛规模：3 ~ 7，随工序数阶梯式增加
        tournamentSize = (int) Math.max(MIN_TOURNAMENT_SIZE,
                Math.min(MAX_TOURNAMENT_SIZE, MIN_TOURNAMENT_SIZE + totalOps / tournamentSizeCoeff));



    }

    /**
     * 迭代中动态微调参数（根据种群收敛情况）
     * @param currentIter 当前迭代次数
     * @param fitnessStd 当前种群适应度标准差（越小收敛越好）
     */
    public void fineTuneParams(int currentIter, double fitnessStd) {
        // 每10代微调一次，避免频繁调整
        if (currentIter % 10 != 0) {
            return;
        }

        // 适应度标准差阈值（可调整）：小于0.05视为收敛过慢，大于0.2视为收敛过快
        final float LOW_STD_THRESHOLD = 0.05f;
        final float HIGH_STD_THRESHOLD = 0.2f;
        final float ADJUST_STEP = 0.05f; // 调整步长

        DecimalFormat df = new DecimalFormat("#.000");
        // 1. 收敛过慢（适应度方差小）：增加变异概率，降低交叉概率
        if (fitnessStd < LOW_STD_THRESHOLD) {
            mutationProb = Math.max(MIN_MUTATION_PROB,
                    Math.min(MAX_MUTATION_PROB, mutationProb + ADJUST_STEP * 0.5f));
            crossoverProb = Math.max(MIN_CROSSOVER_PROB,
                    Math.min(MAX_CROSSOVER_PROB, crossoverProb - ADJUST_STEP * 0.3f));
            System.out.println("迭代" + currentIter + "：收敛过慢，微调参数→变异概率："
                    + df.format(mutationProb) + "，交叉概率：" + df.format(crossoverProb));
        }
        // 2. 收敛过快（适应度方差大）：降低变异概率，增加交叉概率
        else if (fitnessStd > HIGH_STD_THRESHOLD) {
            mutationProb = Math.max(MIN_MUTATION_PROB,
                    Math.min(MAX_MUTATION_PROB, mutationProb - ADJUST_STEP * 0.5f));
            crossoverProb = Math.max(MIN_CROSSOVER_PROB,
                    Math.min(MAX_CROSSOVER_PROB, crossoverProb + ADJUST_STEP * 0.3f));
            System.out.println("迭代" + currentIter + "：收敛过快，微调参数→变异概率："
                    + df.format(mutationProb) + "，交叉概率：" + df.format(crossoverProb));
        }

        // 3. 后期迭代（超过80%迭代次数）：降低变异概率，稳定最优解
        if (currentIter > maxIterations * 0.8f) {
            mutationProb = Math.max(MIN_MUTATION_PROB,
                    Math.min(MAX_MUTATION_PROB, mutationProb * 0.8f));
            System.out.println("迭代" + currentIter + "：后期迭代，微调参数→变异概率："
                    + df.format(mutationProb));
        }
    }

    public void fineTuneParams() {


        // 适应度标准差阈值（可调整）：小于0.05视为收敛过慢，大于0.2视为收敛过快
        final float LOW_STD_THRESHOLD = 0.05f;
        final float HIGH_STD_THRESHOLD = 0.2f;
        final float ADJUST_STEP = 0.05f; // 调整步长

        DecimalFormat df = new DecimalFormat("#.000");
        // 1. 收敛过慢（适应度方差小）：增加变异概率，降低交叉概率

            mutationProb = Math.max(MIN_MUTATION_PROB,
                    Math.min(MAX_MUTATION_PROB, mutationProb +  0.05f));
            crossoverProb = Math.max(MIN_CROSSOVER_PROB,
                    Math.min(MAX_CROSSOVER_PROB, crossoverProb - 0.1f));



    }

    // 测试示例
    public  void test() {
        ScheduleParams params = new ScheduleParams();
        // 初始化参数（模拟1000道工序）
        params.initAdaptiveParams(1000);

        // 模拟迭代微调（第10代，适应度标准差0.04）
        params.fineTuneParams(10, 0.04f);

        // 模拟迭代微调（第80代，适应度标准差0.25）
        params.fineTuneParams(80, 0.25f);

        // 模拟迭代微调（第160代，适应度标准差0.1）
        params.fineTuneParams(160, 0.1f);
    }
}
