KPI优化

parent 365ed564
...@@ -2,6 +2,7 @@ package com.aps.entity.Algorithm; ...@@ -2,6 +2,7 @@ package com.aps.entity.Algorithm;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult; import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.basic.Entry; import com.aps.entity.basic.Entry;
import com.aps.entity.basic.GlobalParam;
import com.aps.entity.basic.Machine; import com.aps.entity.basic.Machine;
import com.aps.entity.basic.Material; import com.aps.entity.basic.Material;
import com.aps.entity.basic.Order; import com.aps.entity.basic.Order;
...@@ -127,6 +128,8 @@ public class Chromosome { ...@@ -127,6 +128,8 @@ public class Chromosome {
private ObjectiveWeights objectiveWeights; private ObjectiveWeights objectiveWeights;
private GlobalParam globalParamSnapshot;
private TreeMap<String, Material> materials = new TreeMap<>(); private TreeMap<String, Material> materials = new TreeMap<>();
// private List<Material> materials = new ArrayList<>(); // private List<Material> materials = new ArrayList<>();
......
...@@ -80,7 +80,6 @@ public class GlobalParam { ...@@ -80,7 +80,6 @@ public class GlobalParam {
public static final String OBJECTIVE_SETUP_TIME = "setupTime"; // 总换型时间 public static final String OBJECTIVE_SETUP_TIME = "setupTime"; // 总换型时间
public static final String OBJECTIVE_MACHINE_LOAD = "machineLoad"; // 机器负载均衡 public static final String OBJECTIVE_MACHINE_LOAD = "machineLoad"; // 机器负载均衡
public static final String OBJECTIVE_TARDINESS = "tardiness"; // 延迟时间 public static final String OBJECTIVE_TARDINESS = "tardiness"; // 延迟时间
public static final String OBJECTIVE_SEMI_JIT = "semiJitSlack"; // 半成品提前完工惩罚
/// <summary> /// <summary>
/// 构造函数,初始化默认值 /// 构造函数,初始化默认值
...@@ -93,7 +92,6 @@ public class GlobalParam { ...@@ -93,7 +92,6 @@ public class GlobalParam {
objectiveConfigs.add(createMinimizeObjectiveConfig(OBJECTIVE_SETUP_TIME, 2, 0.39)); objectiveConfigs.add(createMinimizeObjectiveConfig(OBJECTIVE_SETUP_TIME, 2, 0.39));
objectiveConfigs.add(createMinimizeObjectiveConfig(OBJECTIVE_MACHINE_LOAD, 1, 0.3)); objectiveConfigs.add(createMinimizeObjectiveConfig(OBJECTIVE_MACHINE_LOAD, 1, 0.3));
objectiveConfigs.add(createMinimizeObjectiveConfig(OBJECTIVE_TARDINESS, 1, 0.3)); objectiveConfigs.add(createMinimizeObjectiveConfig(OBJECTIVE_TARDINESS, 1, 0.3));
objectiveConfigs.add(createMinimizeObjectiveConfig(OBJECTIVE_SEMI_JIT, 2, 0.01));
objectiveConfigs.sort(Comparator.comparing((ObjectiveConfig op) -> op.getLevel())); objectiveConfigs.sort(Comparator.comparing((ObjectiveConfig op) -> op.getLevel()));
} }
...@@ -191,4 +189,213 @@ public class GlobalParam { ...@@ -191,4 +189,213 @@ public class GlobalParam {
public void removeObjectiveConfig(String name) { public void removeObjectiveConfig(String name) {
objectiveConfigs.removeIf(config -> config.getName().equals(name)); objectiveConfigs.removeIf(config -> config.getName().equals(name));
} }
public void applyKpiConfig(Object rawConfig) {
List<?> kpiList = extractKpiList(rawConfig);
if (kpiList.isEmpty()) {
return;
}
List<ObjectiveConfig> configs = new ArrayList<>();
int sequence = 1;
for (Object item : kpiList) {
ObjectiveConfig config = toObjectiveConfig(item, sequence++);
if (config != null) {
configs.add(config);
}
}
if (!configs.isEmpty()) {
configs.sort(Comparator.comparing((ObjectiveConfig op) -> op.getLevel()));
objectiveConfigs = configs;
}
}
public GlobalParam copy() {
GlobalParam target = new GlobalParam();
target.IsBreakPriority = this.IsBreakPriority;
target.IsMultipleMachine = this.IsMultipleMachine;
target.IsUseCalendar = this.IsUseCalendar;
target.IsCheckMp = this.IsCheckMp;
target.IsCheckSf = this.IsCheckSf;
target.IsOverlap = this.IsOverlap;
target.isJit = this.isJit;
target._smoothSetup = this._smoothSetup;
target._smoothChangeOver = this._smoothChangeOver;
target._smoothChangeOverInWeek = this._smoothChangeOverInWeek;
target.pureNSGAIIMode = this.pureNSGAIIMode;
target.semiJitBufferMinutes = this.semiJitBufferMinutes;
target.materialSolveMaxIterations = this.materialSolveMaxIterations;
target.objectiveConfigs = copyObjectiveConfigs(this.objectiveConfigs);
return target;
}
private List<?> extractKpiList(Object rawConfig) {
if (rawConfig instanceof List) {
return (List<?>) rawConfig;
}
if (rawConfig instanceof Map) {
Map<?, ?> map = (Map<?, ?>) rawConfig;
Object kpiConfig = map.get("kpiConfig");
if (kpiConfig instanceof List) {
return (List<?>) kpiConfig;
}
Object kpiList = map.get("kpiList");
if (kpiList instanceof List) {
return (List<?>) kpiList;
}
}
return Collections.emptyList();
}
private ObjectiveConfig toObjectiveConfig(Object raw, int sequence) {
if (raw instanceof ObjectiveConfig) {
ObjectiveConfig source = (ObjectiveConfig) raw;
ObjectiveConfig copy = copyObjectiveConfig(source);
copy.setName(normalizeObjectiveName(copy.getName()));
return isKnownObjective(copy.getName()) ? copy : null;
}
if (!(raw instanceof Map)) {
return null;
}
Map<?, ?> map = (Map<?, ?>) raw;
String name = normalizeObjectiveName(asString(firstValue(map, "name", "code", "fieldName")));
if (!isKnownObjective(name)) {
return null;
}
ObjectiveConfig fallback = getObjectiveConfig(name);
ObjectiveConfig config = fallback == null ? createMinimizeObjectiveConfig(name, sequence, 1D) : copyObjectiveConfig(fallback);
config.setName(name);
config.setEnabled(asBoolean(firstValue(map, "enabled", "value"), config.isEnabled()));
config.setMinimize(asBoolean(firstValue(map, "isMinimize", "minimize"), config.isMinimize()));
config.setLevel(asInt(firstValue(map, "level", "sort"), config.getLevel()));
config.setWeight(asDouble(firstValue(map, "weight"), config.getWeight()));
config.setVal(asDouble(firstValue(map, "val", "valueNumber"), config.getVal()));
return config;
}
private List<ObjectiveConfig> copyObjectiveConfigs(List<ObjectiveConfig> source) {
if (source == null) {
return new ArrayList<>();
}
List<ObjectiveConfig> copy = new ArrayList<>();
for (ObjectiveConfig config : source) {
ObjectiveConfig copied = copyObjectiveConfig(config);
if (isKnownObjective(copied.getName())) {
copy.add(copied);
}
}
return copy;
}
private ObjectiveConfig copyObjectiveConfig(ObjectiveConfig source) {
ObjectiveConfig copy = new ObjectiveConfig();
if (source != null) {
copy.setName(source.getName());
copy.setEnabled(source.isEnabled());
copy.setMinimize(source.isMinimize());
copy.setLevel(source.getLevel());
copy.setWeight(source.getWeight());
copy.setVal(source.getVal());
}
return copy;
}
private Object firstValue(Map<?, ?> map, String... keys) {
for (String key : keys) {
if (map.containsKey(key)) {
return map.get(key);
}
}
return null;
}
private String normalizeObjectiveName(String name) {
if (name == null) {
return null;
}
String normalized = name.trim().replace("_", "").replace("-", "").replace(" ", "").toLowerCase(Locale.ROOT);
switch (normalized) {
case "makespan":
return OBJECTIVE_MAKESPAN;
case "flowtime":
case "totalflowtime":
return OBJECTIVE_FLOW_TIME;
case "setuptime":
case "totalsetuptime":
case "changeovertime":
return OBJECTIVE_SETUP_TIME;
case "machineload":
case "machineloadbalance":
case "loadbalance":
return OBJECTIVE_MACHINE_LOAD;
case "tardiness":
case "delaytime":
return OBJECTIVE_TARDINESS;
default:
return name.trim();
}
}
private boolean isKnownObjective(String name) {
return OBJECTIVE_MAKESPAN.equals(name)
|| OBJECTIVE_FLOW_TIME.equals(name)
|| OBJECTIVE_SETUP_TIME.equals(name)
|| OBJECTIVE_MACHINE_LOAD.equals(name)
|| OBJECTIVE_TARDINESS.equals(name);
}
private String asString(Object value) {
return value == null ? null : String.valueOf(value);
}
private boolean asBoolean(Object value, boolean defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Boolean) {
return (Boolean) value;
}
if (value instanceof Number) {
return ((Number) value).intValue() != 0;
}
String text = String.valueOf(value).trim();
if ("1".equals(text)) {
return true;
}
if ("0".equals(text)) {
return false;
}
return text.isEmpty() ? defaultValue : Boolean.parseBoolean(text);
}
private int asInt(Object value, int defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Number) {
return ((Number) value).intValue();
}
try {
return Integer.parseInt(String.valueOf(value).trim());
} catch (Exception e) {
return defaultValue;
}
}
private double asDouble(Object value, double defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
try {
return Double.parseDouble(String.valueOf(value).trim());
} catch (Exception e) {
return defaultValue;
}
}
} }
...@@ -2799,11 +2799,6 @@ if(geneDetails!=null&&geneDetails.size()>0) ...@@ -2799,11 +2799,6 @@ if(geneDetails!=null&&geneDetails.size()>0)
chromosome.setMachineLoadStd(machineLoadBalance); chromosome.setMachineLoadStd(machineLoadBalance);
Objectives[i] = machineLoadBalance; Objectives[i] = machineLoadBalance;
} }
if (GlobalParam.OBJECTIVE_SEMI_JIT.equals(config.getName())) {
double semiJitSlack = calculateSemiJitSlack(chromosome);
chromosome.setSemiJitSlack(semiJitSlack);
Objectives[i] = semiJitSlack;
}
i++; i++;
} }
} }
...@@ -2863,26 +2858,6 @@ if(geneDetails!=null&&geneDetails.size()>0) ...@@ -2863,26 +2858,6 @@ if(geneDetails!=null&&geneDetails.size()>0)
return Math.sqrt(variance)/avgUtilization ; return Math.sqrt(variance)/avgUtilization ;
} }
private double calculateSemiJitSlack(Chromosome chromosome) {
Map<Integer, GAScheduleResult> resultByOperation = chromosome.getResult().stream()
.collect(Collectors.toMap(GAScheduleResult::getOperationId, t -> t, (left, right) -> left));
double semiJitSlack = 0;
for (Entry operation : chromosome.getAllOperations()) {
if (operation.getLatestCompletionTime() == null) {
continue;
}
GAScheduleResult result = resultByOperation.get(operation.getId());
if (result == null) {
continue;
}
LocalDateTime completionTime = baseTime.plusSeconds(result.getEndTime());
if (completionTime.isBefore(operation.getLatestCompletionTime())) {
semiJitSlack += ChronoUnit.MINUTES.between(completionTime, operation.getLatestCompletionTime());
}
}
return semiJitSlack;
}
/** /**
* 补全:创建缓存键(核心逻辑,需与原 C# CreateCacheKey 一致) * 补全:创建缓存键(核心逻辑,需与原 C# CreateCacheKey 一致)
* 思路:将染色体的核心特征(机器选择+工序排序)拼接为字符串,确保相同染色体生成相同键 * 思路:将染色体的核心特征(机器选择+工序排序)拼接为字符串,确保相同染色体生成相同键
......
...@@ -14,9 +14,11 @@ import org.springframework.stereotype.Service; ...@@ -14,9 +14,11 @@ import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -65,6 +67,29 @@ public class ScheduleStrategyService { ...@@ -65,6 +67,29 @@ public class ScheduleStrategyService {
} }
} }
public Object loadEffectiveKpiConfig(Long userId, Long baseRuleId, String sceneId, String userRuleId) {
try {
Map<String, Object> params = new HashMap<>();
Long effectiveUserId = resolveScheduleUserId(sceneId, userId);
if (effectiveUserId != null) {
params.put("userId", effectiveUserId);
}
if (baseRuleId != null) {
params.put("baseRuleId", baseRuleId);
}
if (userRuleId != null && !userRuleId.trim().isEmpty()) {
params.put("userRuleId", userRuleId);
}
Map<String, Object> effectiveRule = userStrategyRuleService.getEffectiveRule(params);
return effectiveRule == null ? null : effectiveRule.get("kpiConfig");
} catch (Exception e) {
log.warn("Load KPI strategy failed, use GlobalParam default KPI. sceneId={}, userId={}, baseRuleId={}, userRuleId={}",
sceneId, userId, baseRuleId, userRuleId, e);
return null;
}
}
public OrderSortRule createMultiConditionRule(List<Order> orders) { public OrderSortRule createMultiConditionRule(List<Order> orders) {
return createMultiConditionRule(orders, Collections.emptyList()); return createMultiConditionRule(orders, Collections.emptyList());
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment