package com.zy.asrs.utils; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import lombok.Data; public class SchedulingCarUtil { private static final Map STATION_PRIORITIES = Collections.unmodifiableMap(new HashMap() {{ put(5101, 0.8); put(5120, 0.9); // ... }}); private static final Map AREA_WEIGHTS = Collections.unmodifiableMap(new HashMap() {{ put("A", 1.2); put("B", 1.0); put("C", 0.8); // ... }}); // 常量配置 private static final double WAIT_THRESHOLD = 120.0; // 等待临界点(秒) private static final double MAX_DISTANCE = 1000.0; // 轨道最大长度 private static final double DIST_PENALTY = -0.5; // 最低距离系数 // 新增线性增长阈值和系数 private static final double LINEAR_THRESHOLD = 300.0; // 线性增长起点(秒) private static final double LINEAR_FACTOR = 0.0083; // 线性增长系数(≈0.5/60) private static final double LOAD_THRESHOLD = 0.7; private static final double ADJUSTMENT_STEP = 0.01; // 权重参数 (可动态调整) private double baseWeight = 0.40; private double waitWeight = 0.35; private double distWeight = 0.25; private static final double[] EXP_CACHE = new double[1800]; // 缓存0~1800秒(30分钟) static { for (int i = 0; i < EXP_CACHE.length; i++) { EXP_CACHE[i] = 0.8 * (1 - Math.exp(-0.02 * i)); } } // 预计算常量 private static final double EXP_BASE = 0.5; private static final double EXP_FACTOR = 3.0; private static class Weights { double base = 0.40, wait = 0.35, dist = 0.25; } private final AtomicReference weightsRef = new AtomicReference<>(new Weights()); // // 复用对象(线程安全) // private final ThreadLocal distanceCache = ThreadLocal.withInitial(() -> 0.0); /** * 计算任务综合优先级 * @param task 当前任务对象 * @param agv 当前小车对象 * @return 综合优先级得分(0.0 - 1.0 ~ ∞) */ public double calculatePriority(Task task, AGV agv) { // 1. 站点基础优先级计算 double stationPriority = calculateStationPriority(task.getStationId()); // 2. 任务等待时间优先级 double waitPriority = calculateWaitPriority(task.getWaitSeconds()); // 3. 小车距离优先级 double distancePriority = calculateDistancePriority( agv.getPosition(), task.getTargetPosition() ); applyDynamicWeightAdjustment(); return (stationPriority * baseWeight) + (waitPriority * waitWeight) + (distancePriority * distWeight); } private void applyDynamicWeightAdjustment() { Weights current = weightsRef.get(); Weights updated = new Weights(); double loadFactor = SystemMonitor.getLoadFactor(); if (loadFactor > LOAD_THRESHOLD) { waitWeight = Math.min(0.55, waitWeight + ADJUSTMENT_STEP); distWeight = Math.max(0.10, distWeight - ADJUSTMENT_STEP/2); } else if (loadFactor < LOAD_THRESHOLD - 0.05) { // 负载降低时逐步恢复权重 waitWeight = Math.max(0.35, waitWeight - ADJUSTMENT_STEP); distWeight = Math.min(0.25, distWeight + ADJUSTMENT_STEP/2); } weightsRef.compareAndSet(current, updated); // CAS更新 } /** * 站点基础优先级(固定值+区域权重) */ private double calculateStationPriority(int stationId) { double basePriority = STATION_PRIORITIES.getOrDefault(stationId, 0.5); String area = "A"; return basePriority * AREA_WEIGHTS.getOrDefault(area, 1.0); } /** * 等待时间优先级(非线性增长) */ private double calculateWaitPriority(double waitSeconds) { // if (waitSeconds <= WAIT_THRESHOLD) { // return 0.2; // 基础值 // } // // 等待超时后的指数增长(无峰值上限) // return Math.min(1.0, 0.2 + 0.8 * (1 - Math.exp(-0.02*(waitSeconds-WAIT_THRESHOLD)))); if (waitSeconds <= WAIT_THRESHOLD) { return 0.2; // 基础值 } double exceedSeconds = waitSeconds - WAIT_THRESHOLD; double expPart = (exceedSeconds < EXP_CACHE.length) ? EXP_CACHE[(int) exceedSeconds] : 0.8 * (1 - Math.exp(-0.02 * exceedSeconds)); // double exceedSeconds = waitSeconds - WAIT_THRESHOLD; // // 指数增长阶段(0~300秒) // double expPart = 0.8 * (1 - Math.exp(-0.02 * exceedSeconds)); // 线性增长阶段(300秒后) double linearPart = (exceedSeconds > LINEAR_THRESHOLD) ? LINEAR_FACTOR * (exceedSeconds - LINEAR_THRESHOLD) : 0; return 0.2 + expPart + linearPart; // 突破1.0上限 } /** * 小车距离优先级(含负向调节) */ private double calculateDistancePriority(double agvPos, double stationPos) { // 计算轨道有效距离(考虑单向移动) double distance = calculateEffectiveDistance(agvPos, stationPos); // // double distance = distanceCache.get(); // if (distance == 0.0) { // 0表示未计算 // distance = calculateEffectiveDistance(agvPos, stationPos); // distanceCache.set(distance); // } // 非线性衰减公式(近距离奖励,远距离惩罚) double ratio = distance / MAX_DISTANCE; // return Math.max(DIST_PENALTY, 0.5 * (Math.pow(0.5, ratio * 3) - 0.5)); double exponentValue = Math.pow(EXP_BASE, ratio * EXP_FACTOR); return Math.max(DIST_PENALTY, 0.5 * (exponentValue - 0.5)); } /** * 计算有效距离(单方向轨道逻辑) */ private double calculateEffectiveDistance(double agvPos, double stationPos) { // 单向轨道场景:若小车已过站点,需绕行至终点再返回起点 // if (agvPos > stationPos) { // return (MAX_DISTANCE - agvPos) + stationPos; // } // return stationPos - agvPos; return (stationPos - agvPos + MAX_DISTANCE) % MAX_DISTANCE; } } @Data class Task { private int taskId; private int stationId; private double targetPosition; private long createTime; // 任务创建时间戳 private static final long THIRTY_DAYS_MS = 30L * 24 * 60 * 60 * 1000; public double getWaitSeconds() { long elapsed = (System.currentTimeMillis() - createTime) ; // 固定为30天 return (elapsed > THIRTY_DAYS_MS) ? (THIRTY_DAYS_MS / 1000.0) : (elapsed / 1000.0); } } @Data class AGV { private int agvId; private double position; // 当前轨道位置(0-MAX_DISTANCE) } // 系统监控类(示例) @Data class SystemMonitor { public static double getLoadFactor() { // 实际实现中读取系统负载率 return 0.1; // return LoadHolder.cachedLoad; // 定时更新,非实时读取 } // private static class LoadHolder { // static double cachedLoad = 0.1; // static { ScheduledExecutorService.scheduleAtFixedRate(() -> // cachedLoad = realTimeLoad(), 5, 5, TimeUnit.SECONDS); } // } }