mirror of
https://codeup.aliyun.com/64f7d6b8ce01efaafef1e678/coal/coal.git
synced 2026-01-25 07:46:40 +08:00
完善
This commit is contained in:
27
pom.xml
27
pom.xml
@@ -16,6 +16,33 @@
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>aliyun</id>
|
||||
<url>https://maven.aliyun.com/repository/public</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
|
||||
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>aliyun</id>
|
||||
<url>https://maven.aliyun.com/repository/public</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -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<CoalInfo> coals;
|
||||
private List<CoalInfo> coals = new ArrayList<>();
|
||||
private int totalCount;
|
||||
|
||||
public String tableString() {
|
||||
|
||||
@@ -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.)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<IntVar> 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<IntVar> 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<CoalConstraint> 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<IntVar> createPercentVars(CoalBlendRequest request, CpModel model) {
|
||||
int index = 0;
|
||||
|
||||
List<IntVar> 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<IntVar> 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<IntVar> 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()) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
}]
|
||||
|
||||
Reference in New Issue
Block a user