package com.aps.service.Algorithm;

import com.aps.common.util.*;
import com.aps.entity.Algorithm.*;
        import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
        import com.aps.entity.basic.*;
        import com.aps.service.plan.MachineSchedulerService;
        import com.aps.service.plan.SceneService;
        import org.springframework.beans.factory.annotation.Autowired;

        import java.time.LocalDateTime;
        import java.util.*;
        import java.util.concurrent.*;
        import java.util.concurrent.atomic.AtomicInteger;
        import java.util.stream.Collectors;
        import java.util.stream.IntStream;

/**
 * 作者：佟礼
 * 时间：2026-03-23
 */

public class HybridAlgorithm {
    private final Random rnd = new Random();
    private List<Machine> machines;
    private final MachineSchedulerService machineScheduler;
    private final List<Order> orders;
    private final TreeMap<String, Material> materials;

    private final List<String> materialIds;

    private static GlobalParam _GlobalParam;
    private  List<GroupResult> _entryRel;

    FitnessCalculator _fitnessCalculator = new FitnessCalculator();

    private NSGAIIUtils _nsgaIIUtils = new NSGAIIUtils();

    private ObjectiveWeights _objectiveWeights = new ObjectiveWeights();


    private MaterialRequirementService materialRequirementService;

    private List<OrderMaterialRequirement> orderMaterials;


    private SceneService _sceneService;

    private String sceneId;

    private VariableNeighborhoodSearch _vns;

    private AdaptiveLargeNeighborhoodSearch _ALNS;
    // 初始化算法实例
    private HillClimbing _hillClimbing;
    private SimulatedAnnealing _simulatedAnnealing;


    // 初始化算法实例
    private TabuSearch _tabuSearch;



    public HybridAlgorithm(GlobalParam globalParam,List<Machine> machines, List<Order> orders,
                           TreeMap<String, Material> materials,List<String> _materialIds, MachineSchedulerService machineScheduler,List<GroupResult> entryRel,MaterialRequirementService _materialRequirementService,SceneService sceneService,String _sceneId) {
        this.machines = machines;
        this.orders = orders;
        this.materials = materials;
        this.machineScheduler = machineScheduler;
        _GlobalParam=globalParam;
        _entryRel=entryRel;
        materialRequirementService=_materialRequirementService;
        _sceneService=sceneService;
        sceneId=_sceneId;
        materialIds=_materialIds;
    }

    public void Init() {
        // 自定义权重配置

        _nsgaIIUtils.init(_GlobalParam);
    }

    public Chromosome Run(ScheduleParams param, List<Entry> allOperations) {

        if(allOperations==null||allOperations.size()==0)
        {
            throw new RuntimeException("没有待排产工单");
        }
        if (_GlobalParam.isIsMultipleMachine()) {
            allOperations = OperationSplitService.splitMultiMachineOperations(allOperations, _GlobalParam, machines, _entryRel);
        }
//        if(materials!=null&&materials.size()>0) {
//
//            materialRequirementService.init(materials, orders, allOperations, _entryRel, machineScheduler, machines,_GlobalParam);
//
//            orderMaterials = materialRequirementService.buildMultiLevelRequirementNetwork(param.getBaseTime());
//            Set<Long> existIds = new HashSet<>();
//            machines=machines.stream()
//                    .filter(t->existIds.add(t.getId()))//HashSet.add() 方法：添加成功返回 true，重复返回 false；
//                    .collect(Collectors.toList());
//        }


        LocalDateTime starttime=LocalDateTime.now();
        FileHelper.writeLogFile("排产-----------开始-----" + (_GlobalParam.isJit() ? "倒排" : "正排")
                + "-----优化器" + (_GlobalParam.isOptimizer() ? "启用" : "关闭")
                + "------" + allOperations.get(0).getSceneId());
        // 在整个流程开始时创建一个全局 shared decoder，所有阶段共享解码缓存
        GeneticDecoder sharedDecoder = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler, materialRequirementService, sceneId);

        Initialization initialization = new Initialization(_GlobalParam,allOperations,orders,machines,_objectiveWeights);

        GeneticOperations geneticOps = new GeneticOperations(_GlobalParam,allOperations,param);
        int opcount=allOperations.size();
        // 预生成全局工序列表（所有初始化方法共享同一顺序）
        List<GlobalOperationInfo> globalOpList =new ArrayList<>();// initialization.generateGlobalOpList();
        // 初始化变邻域搜索
        _vns = new VariableNeighborhoodSearch( allOperations,orders,materials,_entryRel,  _fitnessCalculator );
        _vns.initMachineSelectFrequency();
        _ALNS = new AdaptiveLargeNeighborhoodSearch( allOperations,orders,materials,_entryRel,  _fitnessCalculator );
        _hillClimbing = new HillClimbing(allOperations,orders,materials,_entryRel,  _fitnessCalculator);
        _simulatedAnnealing = new SimulatedAnnealing( allOperations,orders,materials,_entryRel,  _fitnessCalculator);
        _tabuSearch = new TabuSearch(allOperations,orders,materials,_entryRel,  _fitnessCalculator);
        FileHelper.writeLogFile("初始化种群-----------开始-------");


        // 步骤1：使用构造启发式算法生成初始种群
        FileHelper.writeLogFile("构造启发式初始化-----------开始-------");
        List<Chromosome> population = _GlobalParam.isOptimizer()
                ? initialization.generateHybridInitialPopulation(param)
                : initialization.generateHeuristicInitialPopulation(param,param.getPopulationSize());

        FileHelper.writeLogFile("构造启发式初始化-----------结束-------");


        population= chromosomeDistinct(population);



        FileHelper.writeLogFile("初始化种群-----------结束-------");
        FileHelper.writeLogFile("初始化批量解码-----------开始-------");
        Chromosomedecode(sharedDecoder,param,allOperations,globalOpList,population);

        FileHelper.writeLogFile("初始化批量解码-----------结束-------");

        // 按Objectives去重，减少重复方案
        FileHelper.writeLogFile("按Objectives去重-----------开始-------" + population.size());
        population = chromosomeDistinctByObjectives(population);
        FileHelper.writeLogFile("按Objectives去重-----------结束-------" + population.size());
        if (population == null || population.isEmpty()) {
            throw new RuntimeException("初始种群为空，请检查 populationSize、种群初始化和解码结果");
        }
        if (_GlobalParam.isOptimizer()) {
            FileHelper.writeLogFile("LNS-CPSAT 邻域重优化-----------开始-------种群=" + population.size());
            try {

                CpSatLnsNeighborhood lns = new CpSatLnsNeighborhood(
                        allOperations, machines,orders,materials,_entryRel,_fitnessCalculator);
                List<Chromosome> lnsResult = lns.runLnsOnParetoFront(population, sharedDecoder);
                if (lnsResult != null && !lnsResult.isEmpty()) {
                  //  Chromosomedecode(sharedDecoder, param, allOperations, globalOpList, lnsResult);
                    population = chromosomeDistinctByObjectives(lnsResult);
                    if (population == null || population.isEmpty()) {
                        population = lnsResult;
                    }
                }
            } catch (Throwable t) {
                FileHelper.writeLogFile("LNS-CPSAT 失败，跳过：" + t.getMessage());
            }
            FileHelper.writeLogFile("LNS-CPSAT 邻域重优化-----------结束-------种群="
                    + (population == null ? 0 : population.size()));
        }
      //  if(1==1)
      //  return getBestChromosome(population.get(0), param.getBaseTime(), starttime);
        // 步骤2：对初始种群进行爬山法局部优化


        if(opcount<100 ) {
            Chromosome best=population.get(0);

            FileHelper.writeLogFile("爬山法局部优化-----------开始-------");

            Chromosome optimized = _hillClimbing.searchAll(best,machines,sharedDecoder);
            FileHelper.writeLogFile("爬山法局部优化-----------结束-------");
            return getBestChromosome(optimized, param.getBaseTime(), starttime);
        }



        // 步骤2：对初始种群进行模拟退火+爬山法优化



        if(opcount<800 ) {
            Chromosome best=population.get(0);

            FileHelper.writeLogFile("模拟退火+爬山法优化-----------开始-------");
            Chromosome saHcOptimized = _simulatedAnnealing.searchWithHillClimbing(best,_vns, sharedDecoder, machines);
            FileHelper.writeLogFile("模拟退火+爬山法优化-----------结束-------");

            return getBestChromosome(saHcOptimized, param.getBaseTime(), starttime);
        }
        if(opcount>800 ) {
            Chromosome best=population.get(0);
            best = _ALNS.search(best,_tabuSearch,_vns, sharedDecoder, machines);
            best = _simulatedAnnealing.search(best, _tabuSearch, _vns, sharedDecoder, machines);

            best = _vns.search(best,_tabuSearch, sharedDecoder, machines);

          //  best = _tabuSearch.search(best, _vns, sharedDecoder, machines);

            return getBestChromosome(best, param.getBaseTime(), starttime);

        }else {
            Chromosome best=population.get(0);
            int topN = Math.min(3, population.size());
            for (int iter = 0; iter < topN; iter++) {
                FileHelper.writeLogFile("迭代进化------"+iter+"-----开始-------");

                 System.gc();

                Chromosome chromosome=population.get(iter);
                chromosome = _ALNS.search(chromosome,_tabuSearch,_vns, sharedDecoder, machines);
                chromosome = _simulatedAnnealing.search(chromosome, _tabuSearch, _vns, sharedDecoder, machines);

                chromosome = _vns.search(chromosome,_tabuSearch, sharedDecoder, machines);

                if(_fitnessCalculator.isBetter(chromosome,best)) {
                    FileHelper.writeLogFile("迭代进化------发现更优解-----------");
                    writeKpi(chromosome);
                    best= chromosome;
                }
                FileHelper.writeLogFile("迭代进化------"+iter+"-----结束-------");
                // 周期性 GC 释放内存
                System.gc();
            }
        }




        Chromosome best=ProductionDeepCopyUtil.deepCopy(population.get(0), Chromosome.class); // GetBest(combinedFronts,"初始");
        int ordercount = globalOpList.stream()
                .mapToInt(GlobalOperationInfo::getGroupId)
                .max()
                .orElse(0);

        if(population.size()<param.getTournamentSize())
        {
            return getBestChromosome(best, param.getBaseTime(), starttime);

        }


        int noImproveCount = 0;
        int maxNoImprove = 10;
        // 步骤2：迭代进化
        FileHelper.writeLogFile("迭代进化-----------开始-------"+param.getMaxIterations());

        for (int iter = 0; iter < param.getMaxIterations(); iter++) {
            // 解码并计算适应度
            FileHelper.writeLogFile("迭代进化------"+iter+"-----开始-------");


            // 计算种群适应度标准差，微调参数
            double fitnessStd = _fitnessCalculator.calculateFitnessStd(population);
            param.fineTuneParams(iter, fitnessStd);


            // 检查终止条件（此处简化为迭代次数）
            if (iter == param.getMaxIterations() - 1) {
                break;
            }
            FileHelper.writeLogFile("选择操作-----------开始-------");

            // 选择操作
            List<Chromosome> selected = geneticOps.tournamentSelection2(population);
            FileHelper.writeLogFile("选择操作-----------结束-------");


            // 交叉操作
            FileHelper.writeLogFile("交叉操作-----------开始-------");

            List<Chromosome> newPopulation = new ArrayList<>();
            newPopulation.add(best);
            int n=0;
            while (newPopulation.size() < param.getPopulationSize()) {
                // 选择父代
                FileHelper.writeLogFile("交叉-----------开始-------"+n);

                Chromosome parent1 = selected.get(rnd.nextInt(selected.size()));
                Chromosome parent2 = selected.get(rnd.nextInt(selected.size()));
                // 交叉
                Chromosome child = parent1;
                if (rnd.nextDouble() < param.getCrossoverProb()) {
                    // 假设PoxCrossover返回包含两个子染色体的数组
                    Pair<Chromosome, Chromosome> children = geneticOps.poxCrossover(parent1, parent2, ordercount);
                    child=children.getFirst();
                   // initDataToChromosome(child,param, allOperations,globalOpList);
                    child.setID(UUID.randomUUID().toString());
                }
//                // 变异
//                if (rnd.nextDouble() < param.getMutationProb()) {
//                    geneticOps.mutate(child, globalOpList);
//                }
                // 核心融合链（工业级标准顺序：GA生成子代 → SA跳坑 → VNS扩邻域 → TS精优化）
                child = _simulatedAnnealing.search(child,_tabuSearch,_vns, sharedDecoder, machines);
                child = _vns.search(child,_tabuSearch, sharedDecoder, machines);
             //  child = _tabuSearch.search(child, _vns,sharedDecoder, machines);

                newPopulation.add(child);

                FileHelper.writeLogFile("交叉-----------结束-------"+n);
                n++;
            }
            population= chromosomeDistinctByObjectives(newPopulation);;

            if(_fitnessCalculator.isBetter(population.get(0),best))
            {
                best=ProductionDeepCopyUtil.deepCopy(population.get(0), Chromosome.class); // GetBest(combinedFronts,"初始");

                noImproveCount=1;
            }else {

                noImproveCount++;
                if (noImproveCount > 5) {
                    // 当连续 5 代无最优解提升时，降低交叉概率（如从 0.8 降至 0.5）、提高变异概率（如从 0.1 升至 0.2）
                    param.fineTuneParams();
                }
            }
            if(noImproveCount>maxNoImprove)
            {
                break;
            }
            // 当种群适应度标准差小于阈值（如 0.001）时，说明种群已收敛，提前终止迭代
            fitnessStd = _fitnessCalculator.calculateFitnessStd(population);
            if (fitnessStd < 0.001) {
                FileHelper.writeLogFile("种群已收敛，提前终止迭代");
                break;
            }
            FileHelper.writeLogFile("迭代进化------"+iter+"-----结束-------");

        }

        FileHelper.writeLogFile("迭代进化-----------结束-------");


        best= getBestChromosome(best,param.getBaseTime(),starttime);
        // 步骤3：返回最优解
        return best;

    }

    private Chromosome getBestChromosome(Chromosome best,LocalDateTime BaseTime,LocalDateTime starttime)
    {
        best.setBaseTime(BaseTime);
        // best.setOrderMaterials(orderMaterials);
        best.setMaterialIds(materialIds);
        best.setMaterials(null);
        best.setScenarioID(sceneId);
        // best.setOperatRel(_entryRel);

        if(best.getInitMachines()==null||best.getInitMachines().size()==0)
        {
            best.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class));
        }
        LocalDateTime endtime=LocalDateTime.now();
        FileHelper.writeLogFile(String.format("排产----------结束---%s----耗时%d----",sceneId, DateTimeUtil.diffDuration(starttime,endtime).getSeconds()) );
        return best;
    }


    private List<Chromosome> chromosomeDistinct(List<Chromosome> population)
    {
        if(population==null)
        {
            FileHelper.writeLogFile(String.format("排产-----------方案数量---%d-------",0 ));
            return population;
        }
        population = population.stream()
                .filter(chromosome -> chromosome != null && chromosome.getGeneStr() != null)
                .collect(Collectors.toMap(
                        Chromosome::getGeneStr, // key：去重的字段（GeneStr）
                        u -> u,        // value：Chromosome对象
                        (u1, u2) ->  u1 // 重复时保留第一个元素
                ))
                .values() // 获取去重后的
                .stream()
                .collect(Collectors.toList());

        return  population;
    }

    /**
     * 按Objectives去重
     */
    private List<Chromosome> chromosomeDistinctByObjectives(List<Chromosome> population)
    {
        if(population==null || population.isEmpty())
        {
            return population;
        }

        // 使用Objectives数组的哈希值作为key
        Map<String, Chromosome> objectivesMap = new HashMap<>();

        for (Chromosome chromosome : population) {
            if (chromosome == null || chromosome.getObjectives() == null) {
                continue;
            }

            // 将Objectives数组转换为字符串作为key
            String objectivesKey = Arrays.toString(chromosome.getObjectives());

            Chromosome existing = objectivesMap.get(objectivesKey);
            if (existing == null) {
                // 第一次遇到这个Objectives，直接添加
                objectivesMap.put(objectivesKey, chromosome);
            }
        }

        // 按 fitnessLevel 倒序排序（多层次比较）
        List<Chromosome> result = new ArrayList<>(objectivesMap.values());
        result.sort((c1, c2) -> {
            if (isBetter(c1, c2)) {
                return -1; // c1 比 c2 好，c1 应该排在前面
            } else if (isBetter(c2, c1)) {
                return 1; // c2 比 c1 好，c2 应该排在前面
            } else {
                return 0; // 两者相等
            }
        });

        return result;
    }
    /**
     * 比较两个染色体的优劣（基于fitnessLevel多层次比较）
     */
    private boolean isBetter(Chromosome c1, Chromosome c2) {
       return  _fitnessCalculator.isBetter(c1,c2);
    }



    private void  WriteKpis(List<List<Chromosome>> fronts,String index) {
        for (int i=0;i<fronts.size();i++)
        {
            FileHelper.writeLogFile(String.format("KPI---%s--------%d----",index,i));

            for (Chromosome chromosome:fronts.get(i)) {
                WriteKpi(chromosome,"");
            }
        }
    }

    private void  WriteKpi(Chromosome chromosome,String desc)
    {
        FileHelper.writeLogFile(String.format("KPI---%f----%f----%s----%s",chromosome.getWeightedObjective(),chromosome.getFitness(), chromosome.getID(),desc));
        for (double d: chromosome.getObjectives()) {
            FileHelper.writeLogFile(String.format("    KPI---%f-------",d));
        }
    }
    //private ExecutorService decodeExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);

    private final ExecutorService decodeExecutor = new ThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors() - 1, // 核心线程数=CPU-1，无切换开销
            Runtime.getRuntime().availableProcessors() - 1, // 最大线程数=核心数
            0L, TimeUnit.MILLISECONDS,
            new ArrayBlockingQueue<>(200), // 有界队列，避免内存溢出
            new ThreadPoolExecutor.CallerRunsPolicy() // 任务满了主线程执行，不丢失任务
    );

    private  void  initDataToChromosome(Chromosome chromosome,ScheduleParams param, List<Entry> allOperations,List<GlobalOperationInfo> globalOpList) {

        if (chromosome==null){
            System.out.println("chromosome==null");
            return;
        }

        chromosome.setResult(new CopyOnWriteArrayList<>());

        // 假设Machine类有拷贝方法，或使用MapStruct等工具进行映射

        chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝，实际可能需要深拷贝
        chromosome.setOrders(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(orders), Order.class) ); // 简单拷贝，实际可能需要深拷贝
        chromosome.setOperatRel(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(_entryRel), GroupResult.class) ); // 简单拷贝，实际可能需要深拷贝
        chromosome.setMaterials(ProductionDeepCopyUtil.deepCopyTreeMap(materials, String.class, Material.class)); // 简单拷贝，实际可能需要深拷贝

        chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(allOperations), Entry.class) ); // 简单拷贝，实际可能需要深拷贝

        chromosome.setGlobalOpList(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(globalOpList), GlobalOperationInfo.class) ); // 简单拷贝，实际可能需要深拷贝
        //chromosome.setObjectiveWeights(_objectiveWeights);
        chromosome.setBaseTime(param.getBaseTime());
        //  chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝，实际可能需要深拷贝
        //   _sceneService.saveChromosomeToFile(chromosome, "12345679");

        // 加载锁定工单到ResultOld
        List<GAScheduleResult> lockedOrders = GlobalCacheUtil.get("locked_orders_" + sceneId);
        if (lockedOrders != null && !lockedOrders.isEmpty()) {
            chromosome.setResultOld(ProductionDeepCopyUtil.deepCopyList(lockedOrders, GAScheduleResult.class));
            FileHelper.writeLogFile("将 " + lockedOrders.size() + " 个锁定工单加载到初始种群中");
        } else {
            chromosome.setResultOld(new CopyOnWriteArrayList<>());
        }
    }


    private  void  Chromosomedecode(GeneticDecoder sharedDecoder,ScheduleParams param, List<Entry> allOperations,List<GlobalOperationInfo> globalOpList,List<Chromosome> population)
    {
        FileHelper.writeLogFile("解码---------------"+population.size() );

       // GeneticDecoder decoder = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler,materialRequirementService, sceneId);
        boolean ismore=false;
        if(ismore) {
            CompletableFuture.allOf(population.stream()
                            .map(chromosome -> CompletableFuture.runAsync(() -> decode(sharedDecoder, chromosome, param, allOperations, globalOpList), decodeExecutor))
                            .toArray(CompletableFuture[]::new))
                    .join();

        } else  {
            if (population != null && population.size() > 0) {
                population.forEach(chromosome -> {
                    decode(sharedDecoder, chromosome, param, allOperations, globalOpList);
                });
            }
        }


    }

    private  void  decode(GeneticDecoder decoder,Chromosome chromosome,ScheduleParams param, List<Entry> allOperations,List<GlobalOperationInfo> globalOpList) {

        if (chromosome==null){
            System.out.println("chromosome==null");
            return;
        }

        chromosome.setResult(new CopyOnWriteArrayList<>());

        // 假设Machine类有拷贝方法，或使用MapStruct等工具进行映射

        chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝，实际可能需要深拷贝
        chromosome.setOrders(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(orders), Order.class) ); // 简单拷贝，实际可能需要深拷贝
        chromosome.setOperatRel(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(_entryRel), GroupResult.class) ); // 简单拷贝，实际可能需要深拷贝

        chromosome.setMaterials(ProductionDeepCopyUtil.deepCopyTreeMap(materials, String.class, Material.class)); // 简单拷贝，实际可能需要深拷贝

        if (chromosome.getAllOperations() == null || chromosome.getAllOperations().isEmpty()) {
            chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(allOperations), Entry.class) );
        }       // chromosome.setGlobalOpList(ProductionDeepCopyUtil.deepCopyList(globalOpList, GlobalOperationInfo.class) ); // 简单拷贝，实际可能需要深拷贝
        //chromosome.setObjectiveWeights(_objectiveWeights);
        chromosome.setBaseTime(param.getBaseTime());
        //  chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝，实际可能需要深拷贝
        //   _sceneService.saveChromosomeToFile(chromosome, "12345679");

        decoder.decodeChromosomeWithCache(chromosome,false);
//        if (chromosome.getFitness() == 0) {
//            chromosome.setFitness(_fitnessCalculator.calculateFitness(chromosome, _objectiveWeights));
//        }
    }

    private  void  writeKpi(Chromosome chromosome) {
        String fitness = "";
        double[] fitness1 = chromosome.getFitnessLevel();
        if (fitness1 != null) {
            for (int i = 0; i < fitness1.length; i++) {
                fitness += fitness1[i] + ",";
            }
        } else {
            fitness = "null (未计算)";
        }

        log(String.format("变邻域搜索 - kpi：%s", fitness),true);
        if(chromosome.getMakespan()!=0) {
            log(String.format("变邻域搜索 - kpi-Makespan: %f",  chromosome.getMakespan()));
        }
        if(chromosome.getDelayTime()!=0) {
            log(String.format("变邻域搜索 - kpi-DelayTime: %f",  chromosome.getDelayTime()));
        }
        if(chromosome.getTotalChangeoverTime()!=0) {

            log(String.format("变邻域搜索 - kpi-ChangeoverTime: %f", chromosome.getTotalChangeoverTime()));
        }
        if(chromosome.getMachineLoadStd()!=0) {
            log(String.format("变邻域搜索 - kpi-MachineLoad: %f", chromosome.getMachineLoadStd()));
        }
        if(chromosome.getTotalFlowTime()!=0) {
            log(String.format("变邻域搜索 - kpi-FlowTime: %f",chromosome.getTotalFlowTime()));
        }

        // ==================== 打印各 KPI 的 Gap ====================
        log(KpiLowerBoundCalculator.generateGapReport(chromosome));

    }
    private void log(String message) {
        log( message,  true);
    }
    private void log(String message, boolean enableLogging) {
        if (enableLogging ) {
            FileHelper.writeLogFile(message);
        }
    }

}

