package com.aps.service.Algorithm;

import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.ObjectiveWeights;
import com.aps.entity.basic.GlobalParam;
import com.aps.entity.basic.ObjectiveConfig;

import java.util.ArrayList;
import java.util.List;

/**
 * 作者：佟礼
 * 时间：2025-11-24
 */
public class FitnessCalculator {

    /**
     * 多目标适应度计算（加权求和）
     */
    public double[] calculateFitness(Chromosome chromosome, GlobalParam param) {

        ArrayList<Double> list = new ArrayList<>();
        double fitness=0;
        double total=0;
        int i=0;
        int level=-1;
       double[] weightedObjectives=new double[chromosome.getObjectives().length];
        for (ObjectiveConfig config : param.getObjectiveConfigs()) {
            if( config.isEnabled()) {

                if(level==-1)
                {
                    level=config.getLevel();
                }else if(level!=config.getLevel())
                {
                    list.add(fitness);
                    fitness=0;
                    level=config.getLevel();
                }


                double obj = chromosome.getObjectives()[i];
                // 防御：处理负数（目标值应为非负，若为负则兜底为0）
                obj = Math.max(0, obj);
                //转化为0,1 越靠近1 越优
                double val = 0;
                if (config.isMinimize()) {
                    // ============================
                    // 最小化目标：越小越优 → 归一化后越大越优，越优
                    // ============================
                    //0/1+ 0 =0 min max 最优
                    //1/1+ 1 =0.5 min max 最优
                    //1/1+ 2 =0.33
                    //1/1+ 3 =0.25
                    val = 1.0 / (1.0 + obj);
                } else {
                    // ============================
                    // 最大化目标：越大越优 → 反转成 越大越优
                    // ============================
                    //  1/1+ 1 = 0.5
                    //  2/1+ 2 = 0.66
                    //  3/1+ 3 =  0.75 max  max 最优
                    val = obj / (1.0 + obj);
                }
                // 兜底：避免极端情况归一化值为0（最小设为1e-6）
               // val = Math.max(val, 1e-6);
                if (!param.isPureNSGAIIMode()) {
                    val = val * config.getWeight();
                }
                weightedObjectives[i]=val;
                fitness += val;
                total+=val;
                i++;
            }
        }
        list.add(fitness);
            // 归一化（假设最大可能值，实际应根据问题规模调整）

            //  makespan = 10 → val = 1/11 = 0.09
            //  makespan = 20 → val = 1/21 = 0.045
            //  makespan = 100 → val = 1/101 = 0.009
            // 值越大 归一化 后越小, 越大越好
            //原目标（工期、延迟、负载）越小 → 生产越好
            //原目标越小，归一化后 → f1、f2、f3 越大

//            方案 A：工期短、延迟小 → 很好
//                makespan=10 → f1=1/(11)=0.09
//            fitness ≈ 0.08
//            方案 B：工期长、延迟大 → 很差
//                makespan=100 → f1=1/(101)=0.009
//            fitness ≈ 0.01

        // 适应度值（越大越好）
        chromosome.setFitness(total);
        chromosome.setWeightedObjectives(weightedObjectives);
        return list.stream().mapToDouble(Double::doubleValue).toArray();
    }


    /**
     * 多目标适应度计算（加权求和）
     */
    public double calculateFitness(Chromosome chromosome,ObjectiveWeights objectiveWeights) {


        double fitness=0;
        for(int i=0;i<chromosome.getObjectives().length;i++)
        {
            // 归一化（假设最大可能值，实际应根据问题规模调整）
            double val=1/ (1 +chromosome.getObjectives()[i]);
            if(!objectiveWeights.isPureNSGAIIMode())
            {
                val=val*objectiveWeights.getWeights()[i];
            }
            fitness+=val;
           // 1/1+1 0.5
           // 1/1+2 0.3
           // 1/1+3  0.25

          //  makespan = 10 → val = 1/11 = 0.09
          //  makespan = 20 → val = 1/21 = 0.045
          //  makespan = 100 → val = 1/101 = 0.009
            // 值越大 归一化 后越小, 越大越好
            //原目标（工期、延迟、负载）越小 → 生产越好
            //原目标越小，归一化后 → f1、f2、f3 越大

//            方案 A：工期短、延迟小 → 很好
//                makespan=10 → f1=1/(11)=0.09
//            fitness ≈ 0.08
//            方案 B：工期长、延迟大 → 很差
//                makespan=100 → f1=1/(101)=0.009
//            fitness ≈ 0.01
        }
        // 适应度值（越大越好）
        return fitness;
    }

    /**
     * 计算种群适应度标准差（用于参数微调）
     * @param population 染色体种群数组
     * @return 适应度标准差
     */
    public double calculateFitnessStd(List<Chromosome> population) {
        int popSize = population.size();

        // 1. 计算平均适应度
        double avgFitness = 0.0f;
        for (Chromosome chromosome : population) {
            avgFitness += chromosome.getFitness();
        }
        avgFitness /= popSize;

        // 2. 计算每个个体与平均值的平方差之和
        float sumSqDiff = 0.0f;
        for (Chromosome chromosome : population) {
            double diff = chromosome.getFitness() - avgFitness;
            sumSqDiff += diff * diff;
        }

        // 3. 计算标准差
        return (double) Math.sqrt(sumSqDiff / popSize);
    }

    /**
     * 比较两个染色体的优劣（基于fitnessLevel多层次比较）
     */
    public boolean isBetter(Chromosome c1, Chromosome c2) {
        double[] fitness1 = c1.getFitnessLevel();
        double[] fitness2 = c2.getFitnessLevel();

        // 处理null或空数组的情况
        if (fitness1 == null || fitness1.length == 0) {
            return false; // c1没有fitness，认为c2更优
        }
        if (fitness2 == null || fitness2.length == 0) {
            return true; // c2没有fitness，认为c1更优
        }

        // 取两个数组中较小的长度进行比较
        int minLength = Math.min(fitness1.length, fitness2.length);
        for (int i = 0; i < minLength; i++) {
            if (fitness1[i] > fitness2[i]) {
                return true;
            } else if (fitness1[i] < fitness2[i]) {
                return false;
            }
        }

        // 如果前面都相等，长度更长的视为更优（有更多维度）
        return fitness1.length > fitness2.length;
    }



}
