diff --git a/pom.xml b/pom.xml
index 0d703482..8eefb33b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,6 +16,33 @@
17
+
+
+ aliyun
+ https://maven.aliyun.com/repository/public
+
+ true
+
+
+ true
+
+
+
+
+
+
+
+
+ aliyun
+ https://maven.aliyun.com/repository/public
+
+ true
+
+
+ true
+
+
+
org.springframework.boot
diff --git a/src/main/java/cn/lihongjie/coal/dto/CoalBlendResult.java b/src/main/java/cn/lihongjie/coal/dto/CoalBlendResult.java
index a40c5eef..f50469d6 100644
--- a/src/main/java/cn/lihongjie/coal/dto/CoalBlendResult.java
+++ b/src/main/java/cn/lihongjie/coal/dto/CoalBlendResult.java
@@ -2,6 +2,7 @@ package cn.lihongjie.coal.dto;
import lombok.Data;
+import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -11,7 +12,7 @@ public class CoalBlendResult {
private long numConflicts = 0;
private long wallTime = 0;
private long userTime = 0;
- private List coals;
+ private List coals = new ArrayList<>();
private int totalCount;
public String tableString() {
diff --git a/src/main/java/cn/lihongjie/coal/dto/CoalInfo.java b/src/main/java/cn/lihongjie/coal/dto/CoalInfo.java
index cc393d3e..6dfdb955 100644
--- a/src/main/java/cn/lihongjie/coal/dto/CoalInfo.java
+++ b/src/main/java/cn/lihongjie/coal/dto/CoalInfo.java
@@ -62,5 +62,12 @@ public class CoalInfo {
return String.format("%s\t%20s\t%s", name, percentString, paramString);
+ }
+
+ public void calPercent2() {
+
+
+// percents.stream().reduce(x -> x.)
+
}
}
diff --git a/src/main/java/cn/lihongjie/coal/service/CoalService.java b/src/main/java/cn/lihongjie/coal/service/CoalService.java
index 8aced3e5..f5410bed 100644
--- a/src/main/java/cn/lihongjie/coal/service/CoalService.java
+++ b/src/main/java/cn/lihongjie/coal/service/CoalService.java
@@ -1,13 +1,11 @@
package cn.lihongjie.coal.service;
-import ch.qos.logback.core.BasicStatusManager;
import cn.lihongjie.coal.dto.*;
import com.google.ortools.Loader;
import com.google.ortools.sat.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.math3.util.ArithmeticUtils;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
@@ -30,34 +28,82 @@ public class CoalService {
public CoalBlendResult blend(CoalBlendRequest request) {
Loader.loadNativeLibraries();
CoalBlendResult result = new CoalBlendResult();
- result.setCoals(new ArrayList<>());
CpModel model = new CpModel();
- int index = 0;
- List vars = new ArrayList<>();
- for (CoalInfo coal : request.getCoals()) {
- IntVar x = model.newIntVar(Math.max(coal.getMin(), 0), Math.min(coal.getMax(), 100), "x" + index++);
- vars.add(x);
- }
+ List vars = createPercentVars(request, model);
+ // 添加各种约束条件
addConstrains(request, model, vars);
- // 各种煤比例之和为 100
- model.addEquality(LinearExpr.sum(vars.toArray(new LinearArgument[0])), 100);
-
+ // 初始化求解器
CpSolver cpSolver = new CpSolver();
cpSolver.setLogCallback(x -> log.info(x));
SatParameters.Builder parameters = cpSolver.getParameters();
- parameters.setEnumerateAllSolutions(true);
+ parameters.setEnumerateAllSolutions(false);
parameters.setMaxTimeInSeconds(request.getMaxTime());
-
- parameters.setLogSearchProgress(true);
- parameters.setSearchBranching(SatParameters.SearchBranching.FIXED_SEARCH);
+ parameters.setLogSearchProgress(false);
parameters.setFillAdditionalSolutionsInResponse(true);
+
+
+ // 开始求最优解
+
+ List sorted = request.getConstraints().stream().filter(x -> x.getPriority()!=null).sorted(Comparator.comparing(CoalConstraint::getPriority)).toList();
+
+
+ for (CoalConstraint constraint : sorted) {
+
+ log.info("使用约束 {}", constraint);
+
+ LinearExpr weightedSum = LinearExpr.weightedSum(vars.toArray(new IntVar[0]), request.getCoals().stream().mapToLong(x -> (long) (x.getParamVal(constraint.getCode()) * 100)).toArray());
+ if (constraint.getOrder() == -1) {
+ model.maximize(weightedSum);
+
+ } else {
+ model.minimize(weightedSum);
+ }
+
+
+ CpSolverStatus status = cpSolver.solve(model);
+
+
+ if (status == CpSolverStatus.FEASIBLE || status == CpSolverStatus.OPTIMAL) {
+
+ double constrainVal = cpSolver.objectiveValue();
+
+// model.clearHints();
+//
+// for (IntVar var : vars) {
+// model.addHint(var, cpSolver.value(var));
+//
+// }
+ if (constraint.getOrder() == -1) {
+ model.addLessOrEqual(weightedSum, (long) constrainVal);
+ log.info("添加新的条件 sum({}) <= {}", constraint.getCode(), constrainVal);
+ } else {
+ model.addGreaterOrEqual(weightedSum, (long) constrainVal);
+ log.info("添加新的条件 sum({}) >= {}", constraint.getCode(), constrainVal);
+ }
+
+ String validate = model.validate();
+ log.info(validate);
+
+ } else {
+ log.warn("无法求解: " + status);
+ }
+ }
+
+
+
+
+
// 记录结果
+
+
+ //
+ cpSolver.getParameters().setEnumerateAllSolutions(true);
CpSolverStatus solverStatus = cpSolver.solve(model, new CpSolverSolutionCallback() {
@Override
public void onSolutionCallback() {
@@ -100,21 +146,28 @@ public class CoalService {
}
+
});
- int totalCount = result.getCoals().size();
sortAndSelect(request, result);
- result.setTotalCount(totalCount);
- result.setNumBranches(cpSolver.numBranches());
- result.setNumConflicts(cpSolver.numConflicts());
- result.setUserTime((long) cpSolver.userTime());
- result.setWallTime((long) cpSolver.wallTime());
+
return result;
}
+ private static List createPercentVars(CoalBlendRequest request, CpModel model) {
+ int index = 0;
+
+ List vars = new ArrayList<>();
+ for (CoalInfo coal : request.getCoals()) {
+ IntVar x = model.newIntVar(Math.max(coal.getMin(), 0), Math.min(coal.getMax(), 100), "x" + index++);
+ vars.add(x);
+ }
+ return vars;
+ }
+
private void sortAndSelect(CoalBlendRequest request, CoalBlendResult result) {
@@ -145,6 +198,7 @@ public class CoalService {
}
result.setCoals(result.getCoals().stream().sorted(c).limit(request.getCount()).collect(Collectors.toList()));
+ result.getCoals().forEach(x -> x.calPercent2());
}
@@ -187,11 +241,13 @@ public class CoalService {
}
private void addConstrains(CoalBlendRequest request, CpModel model, List vars) {
+ // 各种煤比例之和为 100
+ model.addEquality(LinearExpr.sum(vars.toArray(new LinearArgument[0])), 100);
if (request.getType() == 2) {
- IntVar gcd = model.newIntVar(2, request.getPercent2Sum(), "gcd");
+ IntVar gcd = model.newIntVar(1, 100, "gcd");
List varGcdList = new ArrayList<>();
for (IntVar var : vars) {
@@ -211,8 +267,6 @@ public class CoalService {
model.addLessOrEqual(LinearExpr.sum(varGcdList.toArray(new IntVar[0])), request.getPercent2Sum());
-
-
}
for (CoalConstraint constrain : request.getConstraints()) {
diff --git a/src/test/resources/request1.json b/src/test/resources/request1.json
index 0edf0a09..e9343505 100644
--- a/src/test/resources/request1.json
+++ b/src/test/resources/request1.json
@@ -1,5 +1,6 @@
{
"type": 1,
+ "percent2Sum": 5,
"maxTime": 100,
"constraints": [
{
@@ -67,15 +68,15 @@
"parameters": [
{
"code": "param1",
- "value": 2
- },
- {
- "code": "param2",
"value": 3
},
{
- "code": "param3",
+ "code": "param2",
"value": 5
+ },
+ {
+ "code": "param3",
+ "value": 8
}
]
}]