package com.aps.entity.Algorithm;

/**
 * 作者：佟礼
 * 时间：2025-12-09
 * 多目标权重配置
 */
public class ObjectiveWeights {
    /**
     * 目标权重（默认值：[0.3, 0.2, 0.15, 0.2, 0.15, 0.01]）
     * 对应：完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间、半成品JIT
     */
    private double[] weights = new double[] { 0.3, 0.2, 0.15, 0.2, 0.15, 0.01 };

    /**
     * NSGA-II模式：true=纯帕累托（无视权重），false=加权帕累托
     */
    private boolean pureNSGAIIMode = true;

    // Getter and Setter for weights
    public double[] getWeights() {
        return weights;
    }

    public void setWeights(double[] weights) {
        this.weights = weights;
    }

    // Getter and Setter for pureNSGAIIMode
    public boolean isPureNSGAIIMode() {
        return pureNSGAIIMode;
    }

    public void setPureNSGAIIMode(boolean pureNSGAIIMode) {
        this.pureNSGAIIMode = pureNSGAIIMode;
    }

    /**
     * 优化版归一化目标值（消除量纲影响，解决WeightedObjective为0的问题）
     * @param objectives 待归一化的目标值数组
     * @param minValues  各维度目标值的最小值
     * @param maxValues  各维度目标值的最大值
     * @param isMinimize 各维度是否为最小化目标（true：值越小越优；false：值越大越优）
     * @return 归一化后目标值（范围：[0,1]，无0值兜底） 越靠近1越优
     */
    public double[] normalizeObjectives(double[] objectives, double[] minValues, double[] maxValues, boolean[] isMinimize) {
        if (objectives == null || objectives.length == 0) {
            return new double[0];
        }
        double[] normalized = new double[objectives.length];
        // 浮点精度容错（避免因精度误差误判分母为0）
        final double EPS = 1e-10;

        if (minValues == null || minValues.length == 0 || maxValues == null || maxValues.length != objectives.length) {
            // 分支1：无min/max时，采用线性归一化（统一范围[0,1]，避免趋近0）
            for (int i = 0; i < objectives.length; i++) {
                double obj = objectives[i];
                // 防御：处理负数（目标值应为非负，若为负则兜底为0）
                obj = Math.max(0, obj);
                // 优化：动态缩放，避免大数值趋近0（可根据业务调整缩放系数）
                double scale = Math.max(1, obj); // 缩放系数≥1
                if (isMinimize != null && isMinimize.length > i && isMinimize[i]) {
                    // 最小化目标：值越小越优，归一化后值越小越优（范围[0,1]）
                    normalized[i] = 1.0 / (1.0 + obj / scale);
                } else {
                    // 最大化目标：值越大越优，归一化后值越大越优（范围[0,1]）
                    normalized[i] = obj / (1.0 + obj);
                }
                // 兜底：避免极端情况归一化值为0（最小设为1e-6）
                normalized[i] = Math.max(normalized[i], 1e-6);
            }
        } else {
            // 分支2：有min/max时，标准线性归一化（增加浮点容错）
            for (int i = 0; i < objectives.length; i++) {
                double min = minValues[i];
                double max = maxValues[i];
                double obj = objectives[i];

                // 浮点精度容错：判断分母是否接近0（而非硬相等）
                if (Math.abs(max - min) < EPS) {
                    // 分母接近0时：归一化值设为1（而非0），保证加权后不为0
                    normalized[i] = 1.0;
                } else {
                    // 标准归一化公式
                    normalized[i] = (obj - min) / (max - min);
                    // 若为最小化目标，反转归一化值（值越小，归一化后越大）
                    if (isMinimize != null && isMinimize.length > i && isMinimize[i]) {
                        normalized[i] = 1.0 - normalized[i];
                    }
                }
                // 兜底：限制范围[1e-6,1]，彻底避免0值
                normalized[i] = Math.max(Math.min(normalized[i], 1.0), 0.0001);
            }
        }
        return normalized;
    }
    /**
     * 计算加权目标值
     */
    public double calculateWeightedObjective(double[] normalizedObjectives) {
        double sum = 0;
        for (int i = 0; i < normalizedObjectives.length; i++)
            sum += normalizedObjectives[i] * weights[i];
        return sum;
    }

    /**
     * 计算加权目标值
     */
    public double calculateObjective(double[] normalizedObjectives) {
        double sum = 0;
        for (int i = 0; i < normalizedObjectives.length; i++)
            sum += normalizedObjectives[i];
        return sum;
    }
}
