feat(CoalBlend): add reserve fields to DTOs for extended data handling

This commit is contained in:
2025-07-12 22:41:40 +08:00
parent 99152ebf41
commit 2ccf60e304
7 changed files with 1283 additions and 12 deletions

View File

@@ -57,4 +57,19 @@ public class CoalBlendDto extends OrgCommonDto {
@Comment("求目标参数最大值 -1 最小值 1")
private Integer targetOrder = -1;
@Comment("备用字段1")
private String reserve1;
@Comment("备用字段2")
private String reserve2;
@Comment("备用字段3")
private String reserve3;
@Comment("备用字段4")
private String reserve4;
@Comment("备用字段5")
private String reserve5;
}

View File

@@ -35,6 +35,21 @@ public class CoalBlendRequest {
@Comment("煤类型")
private String coalType;
@Comment("备用字段1")
private String reserve1;
@Comment("备用字段2")
private String reserve2;
@Comment("备用字段3")
private String reserve3;
@Comment("备用字段4")
private String reserve4;
@Comment("备用字段5")
private String reserve5;
public Map<String, CoalConstraint> getConstraintMap() {
if (constraintMap == null) {

View File

@@ -52,4 +52,19 @@ public class CreateCoalBlendDto extends OrgCommonDto {
@Comment("求目标参数最大值 -1 最小值 1")
private Integer targetOrder = -1;
@Comment("备用字段1")
private String reserve1;
@Comment("备用字段2")
private String reserve2;
@Comment("备用字段3")
private String reserve3;
@Comment("备用字段4")
private String reserve4;
@Comment("备用字段5")
private String reserve5;
}

View File

@@ -50,4 +50,21 @@ public class UpdateCoalBlendDto extends OrgCommonDto {
@Comment("求目标参数最大值 -1 最小值 1")
private Integer targetOrder = -1;
@Comment("备用字段1")
private String reserve1;
@Comment("备用字段2")
private String reserve2;
@Comment("备用字段3")
private String reserve3;
@Comment("备用字段4")
private String reserve4;
@Comment("备用字段5")
private String reserve5;
}

View File

@@ -27,14 +27,17 @@ import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.IntStream;
@Entity
@Data
@Comment("配煤记录")
@Slf4j
@jakarta.persistence.Table(indexes = @jakarta.persistence.Index(name ="idx_coal_blend_org_id", columnList = "organization_id"))
@jakarta.persistence.Table(
indexes =
@jakarta.persistence.Index(
name = "idx_coal_blend_org_id",
columnList = "organization_id"))
public class CoalBlendEntity extends OrgCommonEntity {
@ElementCollection
@@ -55,13 +58,9 @@ public class CoalBlendEntity extends OrgCommonEntity {
@Comment("煤类型")
private String coalType;
@Comment("配煤类型")
private String blendType;
@Comment("结果个数")
private Integer count = 20;
@@ -77,6 +76,23 @@ public class CoalBlendEntity extends OrgCommonEntity {
@Comment("求目标参数最大值 -1 最小值 1")
private Integer targetOrder = -1;
@Comment("备用字段1")
private String reserve1;
@Comment("备用字段2")
private String reserve2;
@Comment("备用字段3")
private String reserve3;
@Comment("备用字段4")
private String reserve4;
@Comment("备用字段5")
private String reserve5;
public void blend() {
StopWatch stopWatch = new StopWatch();
@@ -267,12 +283,22 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
// 原煤配煤逻辑 / 人工配煤
if (StringUtils.equals(coalType, "2")) {
// 使用新的CpSolver工具类计算原煤配煤
AtomicBoolean[] paramFlags = {
param1, param2, param3, param4, param5, param6, param7, param8, param9, param10,
param11, param12, param13, param14, param15, param16, param17, param18, param19, param20
};
this.results = cn.lihongjie.coal.coalBlend.util.RawCoalBlendCalculator.calculateRawCoalBlend(
coals, constrains, coalType, count, maxTime, paramFlags);
return;
}
if (StringUtils.equals(coalType, "2") || StringUtils.equals(coalType, "3")) {
if (StringUtils.equals(coalType, "3")) {
// 参与配比的煤的可能性 1 到 煤的数量之间
// <editor-fold desc="Description">
int startIndex = StringUtils.equals(coalType, "2") ? 0 : coals.size() - 1;
int startIndex = coals.size() - 1;
for (int i = startIndex; i < coals.size(); i++) {
// todo 这个循环可以删除?
@@ -282,7 +308,7 @@ public class CoalBlendEntity extends OrgCommonEntity {
CoalBlendCoalInfoEntity coalJ = coals.get(j);
int maxP = (int) (coalJ.getYmPercent() * 100);
int startK = StringUtils.equals(coalType, "2") ? 0 : maxP;
int startK = maxP;
for (int k = startK; k <= maxP; k++) {
// 计算各个参数是否满足条件
CoalBlendResultInfoEntity vo = new CoalBlendResultInfoEntity();
@@ -298,6 +324,18 @@ public class CoalBlendEntity extends OrgCommonEntity {
sum += k * coalJ.getParam1() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -319,7 +357,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam2() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -341,7 +389,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam3() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -363,7 +421,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam4() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -385,7 +453,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam5() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -407,7 +485,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam6() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -429,7 +517,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam7() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -451,7 +549,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam8() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -473,7 +581,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam9() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -495,7 +613,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam10() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -517,7 +645,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam11() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -539,7 +677,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam12() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -561,7 +709,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam13() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -583,7 +741,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam14() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -605,7 +773,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam15() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -627,7 +805,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam16() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -649,7 +837,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam17() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -671,7 +869,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam18() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -693,7 +901,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam19() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -715,7 +933,17 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
sum += k * coalJ.getParam20() / 10000.0;
if (StringUtils.equals(coalType, "2")) {
// 截止目前所有比例之和 <=100
double psum =
IntStream.rangeClosed(0, j)
.mapToDouble(x -> coals.get(x).getYmPercent())
.sum()
+ k / 100.0;
sum = sum * 100 / psum;
}
sum =
BigDecimal.valueOf(sum)
.setScale(2, RoundingMode.HALF_UP)
@@ -1566,4 +1794,4 @@ public class CoalBlendEntity extends OrgCommonEntity {
}
public static class BlendGroup {}
}
}

View File

@@ -0,0 +1,358 @@
package cn.lihongjie.coal.coalBlend.util;
import cn.lihongjie.coal.coalBlend.entity.CoalBlendCoalInfoEntity;
import cn.lihongjie.coal.coalBlend.entity.CoalBlendConstrainVo;
import cn.lihongjie.coal.coalBlend.entity.CoalBlendResultInfoEntity;
import cn.lihongjie.coal.coalBlend.entity.CoalPercentVo;
import com.google.ortools.Loader;
import com.google.ortools.sat.*;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* 原煤配煤计算器
* 专门处理coalType=2的原煤配煤逻辑使用CpSolver进行求解
*/
@Slf4j
public class RawCoalBlendCalculator { /**
* 计算原煤配煤方案
*
* @param coals 煤种信息列表
* @param constrains 约束条件
* @param coalType 煤类型
* @param count 结果数量限制
* @param maxTime 最大求解时间(秒)
* @param paramFlags 参数标志位数组 (param1-param20)
* @return 配煤结果列表
*/
public static List<CoalBlendResultInfoEntity> calculateRawCoalBlend(
List<CoalBlendCoalInfoEntity> coals,
CoalBlendConstrainVo constrains,
String coalType,
Integer count,
Integer maxTime,
AtomicBoolean[] paramFlags) {
List<CoalBlendResultInfoEntity> results = new ArrayList<>();
try {
Loader.loadNativeLibraries();
// 创建CP模型
CpModel model = new CpModel();
// 创建决策变量:每种煤的使用比例(整数单位为0.01%)
List<IntVar> coalPercents = new ArrayList<>();
for (int i = 0; i < coals.size(); i++) {
CoalBlendCoalInfoEntity coal = coals.get(i);
int maxPercent = (int) (coal.getYmPercent() * 100); // 转换为0.01%单位
coalPercents.add(model.newIntVar(0, maxPercent, "coal_" + i));
}
// 添加基本约束总和必须大于0至少要有一种煤被使用
model.addGreaterThan(LinearExpr.sum(coalPercents.toArray(new IntVar[0])), 0);
// 添加原煤配煤的核心约束:只有前一种煤完全使用后才能使用下一种煤
addSequentialConstraints(model, coalPercents, coals);
// 添加参数约束
addParameterConstraints(model, coalPercents, coals, constrains, paramFlags);
// 创建求解器
CpSolver solver = new CpSolver();
SatParameters.Builder parameters = solver.getParameters();
parameters.setEnumerateAllSolutions(true);
parameters.setMaxTimeInSeconds(maxTime);
parameters.setLogSearchProgress(false);
HashSet<String> seen = new HashSet<>();
// 求解
solver.solve(model, new CpSolverSolutionCallback() {
@Override
public void onSolutionCallback() {
// 检查解的有效性
if (!isValidSolution(this, coalPercents)) {
return;
}
CoalBlendResultInfoEntity result = createResult(this, coalPercents, coals, paramFlags);
// 去重
String key = generateSolutionKey(result);
if (seen.contains(key)) {
return;
}
seen.add(key);
results.add(result);
if (results.size() >= count) {
stopSearch();
}
}
});
} catch (Exception e) {
log.error("原煤配煤计算失败", e);
}
return results;
} /**
* 添加顺序约束:只有前一种煤完全使用后才能使用下一种煤
*/
private static void addSequentialConstraints(CpModel model, List<IntVar> coalPercents, List<CoalBlendCoalInfoEntity> coals) {
// 实现严格的顺序约束:如果使用后面的煤,前面的煤必须完全使用
for (int i = 1; i < coalPercents.size(); i++) {
IntVar currentCoal = coalPercents.get(i);
IntVar previousCoal = coalPercents.get(i - 1);
// 获取前一种煤的最大使用量ymPercent * 100因为我们用的是百分比*100的整数
Double previousMaxPercent = coals.get(i - 1).getYmPercent();
if (previousMaxPercent == null) {
continue;
}
long previousMaxValue = (long) (previousMaxPercent * 100);
// 创建布尔变量表示当前煤是否被使用
BoolVar isCurrentUsed = model.newBoolVar("is_coal_" + i + "_used");
// 定义当前煤是否被使用的条件
model.addGreaterThan(currentCoal, 0).onlyEnforceIf(isCurrentUsed);
model.addEquality(currentCoal, 0).onlyEnforceIf(isCurrentUsed.not());
// 如果当前煤被使用,前一种煤必须完全使用
model.addEquality(previousCoal, previousMaxValue).onlyEnforceIf(isCurrentUsed);
}
}
/**
* 添加参数约束条件
*/
private static void addParameterConstraints(CpModel model, List<IntVar> coalPercents,
List<CoalBlendCoalInfoEntity> coals, CoalBlendConstrainVo constrains, AtomicBoolean[] paramFlags) {
for (int paramIndex = 1; paramIndex <= 20; paramIndex++) {
if (!paramFlags[paramIndex - 1].get()) {
continue;
}
String paramName = "param" + paramIndex;
try {
// 获取约束的最小值和最大值
Double minValue = getConstraintValue(constrains, paramName, "Min");
Double maxValue = getConstraintValue(constrains, paramName, "Max");
if (minValue != null || maxValue != null) {
addSingleParameterConstraint(model, coalPercents, coals, paramName, minValue, maxValue);
}
} catch (Exception e) {
log.warn("添加参数{}约束失败", paramName, e);
}
}
} /**
* 添加单个参数的约束条件
*/
private static void addSingleParameterConstraint(CpModel model, List<IntVar> coalPercents,
List<CoalBlendCoalInfoEntity> coals, String paramName, Double minValue, Double maxValue) {
try {
// 计算加权参数值 = Σ(煤i的比例 * 煤i的参数值) / 总比例
long[] coefficients = new long[coalPercents.size()];
boolean hasValidCoal = false;
for (int i = 0; i < coals.size(); i++) {
Double paramValue = coals.get(i).getParam(paramName);
if (paramValue != null) {
// 系数需要放大100倍来处理小数比例是百分比*100
coefficients[i] = (long) (paramValue * 100);
hasValidCoal = true;
} else {
coefficients[i] = 0;
}
}
if (!hasValidCoal) {
return;
}
LinearExpr weightedSum = LinearExpr.weightedSum(coalPercents.toArray(new IntVar[0]), coefficients);
LinearExpr totalPercent = LinearExpr.sum(coalPercents.toArray(new IntVar[0]));
// 验证约束是否可能满足
if (minValue != null) {
// 计算所有煤种的参数值范围
double minPossibleValue = Double.MAX_VALUE;
double maxPossibleValue = Double.MIN_VALUE;
for (CoalBlendCoalInfoEntity coal : coals) {
Double paramValue = coal.getParam(paramName);
if (paramValue != null) {
minPossibleValue = Math.min(minPossibleValue, paramValue);
maxPossibleValue = Math.max(maxPossibleValue, paramValue);
}
}
// 如果所有煤种的参数值都小于最小约束值,则无解
if (maxPossibleValue < minValue) {
log.info("参数{}约束无法满足:最大可能值{}小于最小约束值{}", paramName, maxPossibleValue, minValue);
model.addEquality(model.newConstant(0), 1);
return;
}
// 添加最小值约束weightedSum >= minValue * totalPercent
long minBound = (long) (minValue * 100);
LinearExpr minConstraint = LinearExpr.newBuilder()
.addTerm(totalPercent, minBound)
.build();
model.addGreaterOrEqual(weightedSum, minConstraint);
}
if (maxValue != null) {
// 计算所有煤种的参数值范围
double minPossibleValue = Double.MAX_VALUE;
double maxPossibleValue = Double.MIN_VALUE;
for (CoalBlendCoalInfoEntity coal : coals) {
Double paramValue = coal.getParam(paramName);
if (paramValue != null) {
minPossibleValue = Math.min(minPossibleValue, paramValue);
maxPossibleValue = Math.max(maxPossibleValue, paramValue);
}
}
// 如果所有煤种的参数值都大于最大约束值,则无解
if (minPossibleValue > maxValue) {
log.info("参数{}约束无法满足:最小可能值{}大于最大约束值{}", paramName, minPossibleValue, maxValue);
model.addEquality(model.newConstant(0), 1);
return;
}
// 添加最大值约束weightedSum <= maxValue * totalPercent
long maxBound = (long) (maxValue * 100);
LinearExpr maxConstraint = LinearExpr.newBuilder()
.addTerm(totalPercent, maxBound)
.build();
model.addLessOrEqual(weightedSum, maxConstraint);
}
} catch (Exception e) {
log.warn("添加参数{}约束失败", paramName, e);
}
}
/**
* 获取约束值
*/
private static Double getConstraintValue(CoalBlendConstrainVo constrains, String paramName, String type) {
try {
String methodName = "get" + paramName.substring(0, 1).toUpperCase() +
paramName.substring(1) + type;
return (Double) constrains.getClass().getMethod(methodName).invoke(constrains);
} catch (Exception e) {
return null;
}
}
/**
* 检查解的有效性
*/
private static boolean isValidSolution(CpSolverSolutionCallback callback, List<IntVar> coalPercents) {
// 至少要有一种煤被使用
for (IntVar percent : coalPercents) {
if (callback.value(percent) > 0) {
return true;
}
}
return false;
}
/**
* 创建结果对象
*/
private static CoalBlendResultInfoEntity createResult(CpSolverSolutionCallback callback, List<IntVar> coalPercents,
List<CoalBlendCoalInfoEntity> coals, AtomicBoolean[] paramFlags) {
CoalBlendResultInfoEntity result = new CoalBlendResultInfoEntity();
// 设置比例信息
List<CoalPercentVo> percentInfos = new ArrayList<>();
double totalPercent = 0;
for (int i = 0; i < coalPercents.size(); i++) {
long percentValue = callback.value(coalPercents.get(i));
if (percentValue > 0) {
double percent = percentValue / 100.0; // 转换回百分比
percentInfos.add(new CoalPercentVo(
coals.get(i).getName(),
percent,
0.0,
percent));
totalPercent += percent;
}
}
result.setPercentInfos(percentInfos);
result.setPercentSum(totalPercent);
// 计算各参数值
calculateParameterValues(result, coals, callback, coalPercents, paramFlags, totalPercent);
return result;
}
/**
* 计算参数值
*/
private static void calculateParameterValues(CoalBlendResultInfoEntity result,
List<CoalBlendCoalInfoEntity> coals, CpSolverSolutionCallback callback, List<IntVar> coalPercents,
AtomicBoolean[] paramFlags, double totalPercent) {
if (totalPercent <= 0) {
return;
}
for (int paramIndex = 1; paramIndex <= 20; paramIndex++) {
if (!paramFlags[paramIndex - 1].get()) {
continue;
}
String paramName = "param" + paramIndex;
double weightedSum = 0;
for (int i = 0; i < coals.size(); i++) {
long percentValue = callback.value(coalPercents.get(i));
if (percentValue > 0) {
Double paramValue = coals.get(i).getParam(paramName);
if (paramValue != null) {
weightedSum += (percentValue / 100.0) * paramValue;
}
}
}
double averageValue = weightedSum / totalPercent;
try {
String setterName = "setParam" + paramIndex;
result.getClass().getMethod(setterName, Double.class).invoke(result, averageValue);
} catch (Exception e) {
log.warn("设置参数{}值失败", paramName, e);
}
}
}
/**
* 生成解的唯一标识
*/
private static String generateSolutionKey(CoalBlendResultInfoEntity result) {
StringBuilder sb = new StringBuilder();
for (CoalPercentVo percent : result.getPercentInfos()) {
sb.append(percent.getName()).append(":").append(percent.getPercent()).append(";");
}
return sb.toString();
}
}

View File

@@ -0,0 +1,623 @@
package cn.lihongjie.coal.coalBlend.util;
import static org.junit.jupiter.api.Assertions.*;
import cn.lihongjie.coal.coalBlend.entity.CoalBlendCoalInfoEntity;
import cn.lihongjie.coal.coalBlend.entity.CoalBlendConstrainVo;
import cn.lihongjie.coal.coalBlend.entity.CoalBlendResultInfoEntity;
import cn.lihongjie.coal.coalBlend.entity.CoalPercentVo;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* 原煤配煤计算器测试类
* 测试RawCoalBlendCalculator的各种场景
*/
class RawCoalBlendCalculatorTest {
private List<CoalBlendCoalInfoEntity> testCoals;
private CoalBlendConstrainVo testConstrains;
private AtomicBoolean[] testParamFlags;
@BeforeEach
void setUp() {
// 初始化测试数据
testCoals = createTestCoals();
testConstrains = createTestConstrains();
testParamFlags = createTestParamFlags();
}
// 辅助方法:创建测试数据
private List<CoalBlendCoalInfoEntity> createTestCoals() {
List<CoalBlendCoalInfoEntity> coals = new ArrayList<>();
coals.add(createCoal("煤A", 30.0, 12.0, 25.0, 8.0));
coals.add(createCoal("煤B", 40.0, 15.0, 30.0, 10.0));
coals.add(createCoal("煤C", 50.0, 18.0, 35.0, 12.0));
return coals;
}
private List<CoalBlendCoalInfoEntity> createSimpleTestCoals() {
List<CoalBlendCoalInfoEntity> coals = new ArrayList<>();
coals.add(createCoal("煤A", 50.0, 12.0, 25.0, 8.0));
coals.add(createCoal("煤B", 30.0, 15.0, 30.0, 10.0));
return coals;
}
private List<CoalBlendCoalInfoEntity> createTestCoalsWithConstraints() {
List<CoalBlendCoalInfoEntity> coals = new ArrayList<>();
coals.add(createCoal("煤A", 40.0, 10.0, 20.0, 5.0));
coals.add(createCoal("煤B", 30.0, 20.0, 40.0, 15.0));
coals.add(createCoal("煤C", 30.0, 30.0, 60.0, 25.0));
return coals;
}
private List<CoalBlendCoalInfoEntity> createTestCoalsForSequentialTest() {
List<CoalBlendCoalInfoEntity> coals = new ArrayList<>();
coals.add(createCoal("煤A", 25.0, 10.0, 20.0, 5.0));
coals.add(createCoal("煤B", 35.0, 15.0, 30.0, 8.0));
coals.add(createCoal("煤C", 40.0, 20.0, 40.0, 10.0));
return coals;
}
private List<CoalBlendCoalInfoEntity> createLargeCoalList() {
List<CoalBlendCoalInfoEntity> coals = new ArrayList<>();
for (int i = 0; i < 10; i++) {
coals.add(createCoal("" + i, 20.0 + i * 5, 10.0 + i * 2, 20.0 + i * 3, 5.0 + i));
}
return coals;
}
private List<CoalBlendCoalInfoEntity> createCoalsWithExtremeValues() {
List<CoalBlendCoalInfoEntity> coals = new ArrayList<>();
coals.add(createCoal("极小值煤", 10.0, 0.1, 1.0, 0.1));
coals.add(createCoal("极大值煤", 90.0, 99.9, 100.0, 50.0));
return coals;
}
private CoalBlendCoalInfoEntity createCoal(String name, Double ymPercent, Double param1, Double param2, Double param3) {
CoalBlendCoalInfoEntity coal = new CoalBlendCoalInfoEntity();
coal.setName(name);
coal.setYmPercent(ymPercent);
coal.setParam1(param1);
coal.setParam2(param2);
coal.setParam3(param3);
return coal;
}
private CoalBlendConstrainVo createTestConstrains() {
CoalBlendConstrainVo constrains = new CoalBlendConstrainVo();
constrains.setParam1Min(10.0);
constrains.setParam1Max(20.0);
constrains.setParam2Min(20.0);
constrains.setParam2Max(40.0);
constrains.setParam3Min(5.0);
constrains.setParam3Max(15.0);
return constrains;
}
private CoalBlendConstrainVo createSimpleConstrains() {
CoalBlendConstrainVo constrains = new CoalBlendConstrainVo();
constrains.setParam1Min(5.0);
constrains.setParam1Max(25.0);
return constrains;
}
private CoalBlendConstrainVo createStrictConstrains() {
CoalBlendConstrainVo constrains = new CoalBlendConstrainVo();
constrains.setParam1Min(12.0);
constrains.setParam1Max(18.0);
constrains.setParam2Min(25.0);
constrains.setParam2Max(35.0);
return constrains;
}
private CoalBlendConstrainVo createImpossibleConstrains() {
CoalBlendConstrainVo constrains = new CoalBlendConstrainVo();
constrains.setParam1Min(100.0);
constrains.setParam1Max(200.0);
return constrains;
}
private AtomicBoolean[] createTestParamFlags() {
AtomicBoolean[] flags = new AtomicBoolean[20];
for (int i = 0; i < 20; i++) {
flags[i] = new AtomicBoolean(i < 3); // 只开启前3个参数
}
return flags;
}
private AtomicBoolean[] createSimpleParamFlags() {
AtomicBoolean[] flags = new AtomicBoolean[20];
for (int i = 0; i < 20; i++) {
flags[i] = new AtomicBoolean(i == 0); // 只开启第一个参数
}
return flags;
} // 验证方法
private void verifySequentialConstraints(CoalBlendResultInfoEntity result, List<CoalBlendCoalInfoEntity> coals) {
List<CoalPercentVo> percentInfos = result.getPercentInfos();
// 构建煤种名称到索引的映射
java.util.Map<String, Integer> coalIndexMap = new java.util.HashMap<>();
for (int i = 0; i < coals.size(); i++) {
coalIndexMap.put(coals.get(i).getName(), i);
}
// 检查顺序约束
for (CoalPercentVo percentInfo : percentInfos) {
int currentIndex = coalIndexMap.get(percentInfo.getName());
// 如果当前煤种被使用,检查前面的煤种是否完全使用
if (percentInfo.getPercent() > 0) {
for (int i = 0; i < currentIndex; i++) {
String previousCoalName = coals.get(i).getName();
Double previousMaxPercent = coals.get(i).getYmPercent();
// 查找前一种煤的使用情况
CoalPercentVo previousPercent = percentInfos.stream()
.filter(p -> p.getName().equals(previousCoalName))
.findFirst()
.orElse(null);
if (previousPercent != null) {
// 前一种煤应该完全使用(允许小的误差)
double tolerance = 0.01;
assertTrue(Math.abs(previousPercent.getPercent() - previousMaxPercent) < tolerance,
String.format("煤种 %s 被使用时,前一种煤 %s 应该完全使用。期望: %f, 实际: %f",
percentInfo.getName(), previousCoalName, previousMaxPercent, previousPercent.getPercent()));
}
}
}
}
}
private void verifyParameterConstraints(CoalBlendResultInfoEntity result, CoalBlendConstrainVo constrains) {
// 这里可以通过反射获取result的参数值并验证是否满足约束条件
// 由于CoalBlendResultInfoEntity的结构未知这里只做基本验证
assertNotNull(result.getPercentInfos());
assertTrue(result.getPercentSum() > 0);
assertTrue(result.getPercentSum() <= 100);
// 验证每个煤种的比例都在合理范围内
for (CoalPercentVo percentInfo : result.getPercentInfos()) {
assertTrue(percentInfo.getPercent() >= 0);
assertTrue(percentInfo.getPercent() <= 100);
}
}
// 打印方法
private void printCoalInfo(List<CoalBlendCoalInfoEntity> coals) {
System.out.println("--- 煤种信息 ---");
for (int i = 0; i < coals.size(); i++) {
CoalBlendCoalInfoEntity coal = coals.get(i);
System.out.printf("煤种[%d]: %s\n", i, coal.getName());
System.out.printf(" 原煤比例(ymPercent): %.2f%%\n", coal.getYmPercent());
System.out.printf(" 参数1(param1): %.2f\n", coal.getParam1());
System.out.printf(" 参数2(param2): %.2f\n", coal.getParam2());
System.out.printf(" 参数3(param3): %.2f\n", coal.getParam3());
System.out.println();
}
}
private void printConstraints(CoalBlendConstrainVo constrains) {
System.out.println("--- 约束条件 ---");
if (constrains.getParam1Min() != null || constrains.getParam1Max() != null) {
System.out.printf("参数1约束: [%.2f, %.2f]\n",
constrains.getParam1Min(), constrains.getParam1Max());
}
if (constrains.getParam2Min() != null || constrains.getParam2Max() != null) {
System.out.printf("参数2约束: [%.2f, %.2f]\n",
constrains.getParam2Min(), constrains.getParam2Max());
}
if (constrains.getParam3Min() != null || constrains.getParam3Max() != null) {
System.out.printf("参数3约束: [%.2f, %.2f]\n",
constrains.getParam3Min(), constrains.getParam3Max());
}
System.out.println();
}
private void printParamFlags(AtomicBoolean[] paramFlags) {
System.out.println("--- 参数标志 ---");
for (int i = 0; i < Math.min(paramFlags.length, 5); i++) {
System.out.printf("参数%d: %s\n", i + 1, paramFlags[i].get() ? "启用" : "禁用");
}
System.out.println();
}
private void printResults(List<CoalBlendResultInfoEntity> results) {
System.out.println("--- 计算结果 ---");
System.out.printf("找到 %d 个解决方案\n", results.size());
for (int i = 0; i < results.size(); i++) {
CoalBlendResultInfoEntity result = results.get(i);
System.out.printf("\n方案 %d:\n", i + 1);
System.out.printf("总比例: %.2f%%\n", result.getPercentSum());
System.out.println("煤种配比:");
for (CoalPercentVo percentInfo : result.getPercentInfos()) {
System.out.printf(" %s: %.2f%% (原煤比例: %.2f%%)\n",
percentInfo.getName(),
percentInfo.getPercent(),
percentInfo.getYmPercent());
}
// 打印参数值(如果有的话)
printResultParameters(result);
}
System.out.println();
}
private void printResultParameters(CoalBlendResultInfoEntity result) {
System.out.println("计算得到的参数值:");
try {
// 使用反射获取参数值
for (int i = 1; i <= 3; i++) {
String getterName = "getParam" + i;
try {
java.lang.reflect.Method getter = result.getClass().getMethod(getterName);
Object value = getter.invoke(result);
if (value != null) {
System.out.printf(" 参数%d: %.4f\n", i, (Double) value);
}
} catch (Exception e) { // 忽略方法不存在的情况
}
}
} catch (Exception e) {
System.out.println(" 无法获取参数值: " + e.getMessage());
}
}
@Nested
@DisplayName("基本功能测试")
class BasicFunctionTests { @Test
@DisplayName("测试正常的原煤配煤计算")
void testNormalRawCoalBlendCalculation() {
// 准备测试数据
List<CoalBlendCoalInfoEntity> coals = createSimpleTestCoals();
CoalBlendConstrainVo constrains = createSimpleConstrains();
AtomicBoolean[] paramFlags = createSimpleParamFlags();
// 输出测试输入信息
System.out.println("=== 正常原煤配煤计算测试 ===");
printCoalInfo(coals);
printConstraints(constrains);
printParamFlags(paramFlags);
// 执行计算
List<CoalBlendResultInfoEntity> results = RawCoalBlendCalculator.calculateRawCoalBlend(
coals, constrains, "2", 5, 10, paramFlags);
// 输出结果
printResults(results);
// 验证结果
assertNotNull(results);
assertFalse(results.isEmpty());
// 验证第一个结果
CoalBlendResultInfoEntity result = results.get(0);
assertNotNull(result.getPercentInfos());
assertTrue(result.getPercentSum() > 0);
// 验证顺序约束:如果第二种煤被使用,第一种煤必须完全使用
verifySequentialConstraints(result, coals);
}
@Test
@DisplayName("测试空煤种列表")
void testEmptyCoalList() {
List<CoalBlendCoalInfoEntity> emptyCoals = new ArrayList<>();
List<CoalBlendResultInfoEntity> results = RawCoalBlendCalculator.calculateRawCoalBlend(
emptyCoals, testConstrains, "2", 5, 10, testParamFlags);
assertNotNull(results);
assertTrue(results.isEmpty());
} @Test
@DisplayName("测试单一煤种")
void testSingleCoalType() {
List<CoalBlendCoalInfoEntity> singleCoal = new ArrayList<>();
singleCoal.add(createCoal("煤A", 50.0, 12.0, 25.0, 8.0));
System.out.println("=== 单一煤种测试 ===");
printCoalInfo(singleCoal);
printConstraints(testConstrains);
printParamFlags(testParamFlags);
List<CoalBlendResultInfoEntity> results = RawCoalBlendCalculator.calculateRawCoalBlend(
singleCoal, testConstrains, "2", 5, 10, testParamFlags);
printResults(results);
assertNotNull(results);
if (!results.isEmpty()) {
CoalBlendResultInfoEntity result = results.get(0);
assertEquals(1, result.getPercentInfos().size());
assertEquals("煤A", result.getPercentInfos().get(0).getName());
}
}
}
@Nested
@DisplayName("约束条件测试")
class ConstraintTests { @Test
@DisplayName("测试参数约束条件")
void testParameterConstraints() {
// 创建有严格约束的测试数据
List<CoalBlendCoalInfoEntity> coals = createTestCoalsWithConstraints();
CoalBlendConstrainVo constrains = createStrictConstrains();
AtomicBoolean[] paramFlags = createTestParamFlags();
System.out.println("=== 参数约束测试 ===");
printCoalInfo(coals);
printConstraints(constrains);
printParamFlags(paramFlags);
List<CoalBlendResultInfoEntity> results = RawCoalBlendCalculator.calculateRawCoalBlend(
coals, constrains, "2", 5, 10, paramFlags);
printResults(results);
assertNotNull(results);
// 验证结果是否满足约束条件
for (CoalBlendResultInfoEntity result : results) {
verifyParameterConstraints(result, constrains);
}
}@Test
@DisplayName("测试顺序约束")
void testSequentialConstraints() {
List<CoalBlendCoalInfoEntity> coals = createTestCoalsForSequentialTest();
System.out.println("=== 顺序约束测试 ===");
printCoalInfo(coals);
printConstraints(testConstrains);
printParamFlags(testParamFlags);
List<CoalBlendResultInfoEntity> results = RawCoalBlendCalculator.calculateRawCoalBlend(
coals, testConstrains, "2", 10, 10, testParamFlags);
printResults(results);
assertNotNull(results);
// 验证每个结果都满足顺序约束
for (CoalBlendResultInfoEntity result : results) {
verifySequentialConstraints(result, coals);
}
} @Test
@DisplayName("测试无解的约束条件")
void testImpossibleConstraints() {
List<CoalBlendCoalInfoEntity> coals = createSimpleTestCoals();
CoalBlendConstrainVo impossibleConstrains = createImpossibleConstrains();
System.out.println("=== 无解约束测试 ===");
printCoalInfo(coals);
printConstraints(impossibleConstrains);
printParamFlags(testParamFlags);
List<CoalBlendResultInfoEntity> results = RawCoalBlendCalculator.calculateRawCoalBlend(
coals, impossibleConstrains, "2", 5, 5, testParamFlags);
printResults(results);
assertNotNull(results);
// 无解的情况下,结果应该为空
assertTrue(results.isEmpty());
}
}
@Nested
@DisplayName("性能和边界测试")
class PerformanceAndBoundaryTests {
@Test
@DisplayName("测试超时处理")
void testTimeoutHandling() {
List<CoalBlendCoalInfoEntity> largeCoalList = createLargeCoalList();
// 设置很短的超时时间
List<CoalBlendResultInfoEntity> results = RawCoalBlendCalculator.calculateRawCoalBlend(
largeCoalList, testConstrains, "2", 100, 1, testParamFlags);
assertNotNull(results);
// 即使超时,也应该返回部分结果
}
@Test
@DisplayName("测试结果数量限制")
void testResultCountLimit() {
List<CoalBlendCoalInfoEntity> coals = createSimpleTestCoals();
int maxCount = 3;
List<CoalBlendResultInfoEntity> results = RawCoalBlendCalculator.calculateRawCoalBlend(
coals, testConstrains, "2", maxCount, 10, testParamFlags);
assertNotNull(results);
assertTrue(results.size() <= maxCount);
}
@Test
@DisplayName("测试极端参数值")
void testExtremeParameterValues() {
List<CoalBlendCoalInfoEntity> coals = createCoalsWithExtremeValues();
List<CoalBlendResultInfoEntity> results = RawCoalBlendCalculator.calculateRawCoalBlend(
coals, testConstrains, "2", 5, 10, testParamFlags);
assertNotNull(results);
// 验证结果的合理性
for (CoalBlendResultInfoEntity result : results) {
assertTrue(result.getPercentSum() >= 0);
assertTrue(result.getPercentSum() <= 100);
}
}
}
@Nested
@DisplayName("参数标志测试")
class ParamFlagTests {
@Test
@DisplayName("测试所有参数标志关闭")
void testAllParamFlagsOff() {
AtomicBoolean[] allOffFlags = new AtomicBoolean[20];
for (int i = 0; i < 20; i++) {
allOffFlags[i] = new AtomicBoolean(false);
}
List<CoalBlendResultInfoEntity> results = RawCoalBlendCalculator.calculateRawCoalBlend(
testCoals, testConstrains, "2", 5, 10, allOffFlags);
assertNotNull(results);
// 没有参数约束时,应该能找到更多解
}
@Test
@DisplayName("测试部分参数标志开启")
void testPartialParamFlagsOn() {
AtomicBoolean[] partialFlags = new AtomicBoolean[20];
for (int i = 0; i < 20; i++) {
partialFlags[i] = new AtomicBoolean(i < 3); // 只开启前3个参数
}
List<CoalBlendResultInfoEntity> results = RawCoalBlendCalculator.calculateRawCoalBlend(
testCoals, testConstrains, "2", 5, 10, partialFlags);
assertNotNull(results);
// 验证结果中只有前3个参数被计算
for (CoalBlendResultInfoEntity result : results) {
// 这里可以进一步验证只有param1-param3被设置
assertNotNull(result.getPercentInfos());
}
}
}
@Nested
@DisplayName("用户提供数据测试")
class UserProvidedDataTests {
@Test
@DisplayName("测试1参数1约束 [13-13]")
void testCase1_Param1_Constraint_13_13() {
// 准备测试数据
List<CoalBlendCoalInfoEntity> coals = createUserProvidedCoals();
CoalBlendConstrainVo constrains = createConstraint1();
AtomicBoolean[] paramFlags = createParam1OnlyFlags();
System.out.println("=== 测试1参数1约束 [13-13] ===");
printCoalInfo(coals);
printConstraints(constrains);
printParamFlags(paramFlags);
// 执行计算
List<CoalBlendResultInfoEntity> results = RawCoalBlendCalculator.calculateRawCoalBlend(
coals, constrains, "2", 10, 10, paramFlags);
printResults(results);
// 验证结果
assertNotNull(results);
// 验证每个结果都满足约束条件
for (CoalBlendResultInfoEntity result : results) {
// 验证参数1值在约束范围内
Double param1Value = result.getParam1();
assertNotNull(param1Value);
assertTrue(param1Value >= 12.9 && param1Value <= 13.1,
String.format("参数1值 %f 应该在 [13, 13] 范围内", param1Value));
// 验证顺序约束
verifySequentialConstraints(result, coals);
}
}
@Test
@DisplayName("测试2参数1约束 [13-25]")
void testCase2_Param1_Constraint_13_25() {
// 准备测试数据
List<CoalBlendCoalInfoEntity> coals = createUserProvidedCoals();
CoalBlendConstrainVo constrains = createConstraint2();
AtomicBoolean[] paramFlags = createParam1OnlyFlags();
System.out.println("=== 测试2参数1约束 [13-25] ===");
printCoalInfo(coals);
printConstraints(constrains);
printParamFlags(paramFlags);
// 执行计算
List<CoalBlendResultInfoEntity> results = RawCoalBlendCalculator.calculateRawCoalBlend(
coals, constrains, "2", 10, 10, paramFlags);
printResults(results);
// 验证结果
assertNotNull(results);
assertFalse(results.isEmpty());
// 验证每个结果都满足约束条件
for (CoalBlendResultInfoEntity result : results) {
// 验证参数1值在约束范围内
Double param1Value = result.getParam1();
assertNotNull(param1Value);
assertTrue(param1Value >= 12.9 && param1Value <= 25.1,
String.format("参数1值 %f 应该在 [13, 25] 范围内", param1Value));
// 验证顺序约束
verifySequentialConstraints(result, coals);
}
}
/**
* 创建用户提供的煤种数据
*/
private List<CoalBlendCoalInfoEntity> createUserProvidedCoals() {
List<CoalBlendCoalInfoEntity> coals = new ArrayList<>();
coals.add(createCoal("1.4", 1.07, 10.3, null, null));
coals.add(createCoal("1.5", 26.64, 17.89, null, null));
coals.add(createCoal("1.6", 29.41, 25.01, null, null));
coals.add(createCoal("1.8", 32.65, 39.63, null, null));
coals.add(createCoal("矸石", 10.23, 56.8, null, null));
return coals;
}
/**
* 创建测试1的约束条件参数1 [13-13]
*/
private CoalBlendConstrainVo createConstraint1() {
CoalBlendConstrainVo constrains = new CoalBlendConstrainVo();
constrains.setParam1Min(13.0);
constrains.setParam1Max(13.0);
return constrains;
}
/**
* 创建测试2的约束条件参数1 [13-25]
*/
private CoalBlendConstrainVo createConstraint2() {
CoalBlendConstrainVo constrains = new CoalBlendConstrainVo();
constrains.setParam1Min(13.0);
constrains.setParam1Max(25.0);
return constrains;
}
/**
* 创建只启用参数1的标志位
*/ private AtomicBoolean[] createParam1OnlyFlags() {
AtomicBoolean[] flags = new AtomicBoolean[20];
for (int i = 0; i < 20; i++) {
flags[i] = new AtomicBoolean(i == 0); // 只开启第一个参数param1
}
return flags;
}
}
}