Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
H
HYH.APSJ
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
佟礼
HYH.APSJ
Commits
f2a1529b
Commit
f2a1529b
authored
Apr 12, 2026
by
Tong Li
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/tl'
parents
bb00017a
f1998b61
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
3554 additions
and
2122 deletions
+3554
-2122
Chromosome.java
src/main/java/com/aps/entity/Algorithm/Chromosome.java
+44
-18
ScheduleParams.java
src/main/java/com/aps/entity/Algorithm/ScheduleParams.java
+8
-4
GlobalParam.java
src/main/java/com/aps/entity/basic/GlobalParam.java
+4
-4
KpiTargetConfig.java
src/main/java/com/aps/entity/basic/KpiTargetConfig.java
+8
-0
Order.java
src/main/java/com/aps/entity/basic/Order.java
+5
-0
FitnessCalculator.java
...ain/java/com/aps/service/Algorithm/FitnessCalculator.java
+20
-1
GeneticAlgorithm.java
...main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
+1
-1
GeneticDecoder.java
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
+151
-262
GeneticOperations.java
...ain/java/com/aps/service/Algorithm/GeneticOperations.java
+7
-1
HillClimbing.java
src/main/java/com/aps/service/Algorithm/HillClimbing.java
+55
-124
HybridAlgorithm.java
src/main/java/com/aps/service/Algorithm/HybridAlgorithm.java
+135
-182
Initialization.java
src/main/java/com/aps/service/Algorithm/Initialization.java
+1
-1
MaterialRequirementService.java
...com/aps/service/Algorithm/MaterialRequirementService.java
+216
-218
MaterialRequirementServicebf.java
...m/aps/service/Algorithm/MaterialRequirementServicebf.java
+1
-1
ParallelLocalSearch.java
...n/java/com/aps/service/Algorithm/ParallelLocalSearch.java
+0
-91
ScheduleOperationService.java
...a/com/aps/service/Algorithm/ScheduleOperationService.java
+1
-1
SimulatedAnnealing.java
...in/java/com/aps/service/Algorithm/SimulatedAnnealing.java
+304
-644
TabuSearch.java
src/main/java/com/aps/service/Algorithm/TabuSearch.java
+247
-173
TabuSearchWithSA.java
...main/java/com/aps/service/Algorithm/TabuSearchWithSA.java
+0
-271
VariableNeighborhoodSearch.java
...com/aps/service/Algorithm/VariableNeighborhoodSearch.java
+2340
-120
PlanResultService.java
src/main/java/com/aps/service/plan/PlanResultService.java
+2
-2
SceneService.java
src/main/java/com/aps/service/plan/SceneService.java
+2
-2
PlanResultServiceTest.java
src/test/java/com/aps/demo/PlanResultServiceTest.java
+2
-1
No files found.
src/main/java/com/aps/entity/Algorithm/Chromosome.java
View file @
f2a1529b
...
...
@@ -32,6 +32,11 @@ public class Chromosome {
/// </summary>
private
List
<
Integer
>
machineSelection
;
// 缓存标记
private
transient
boolean
machineStrDirty
=
true
;
private
transient
boolean
operationStrDirty
=
true
;
private
transient
boolean
geneStrDirty
=
true
;
/// <summary>
/// 工序排序部分(工件/订单ID)
/// </summary>
...
...
@@ -43,32 +48,53 @@ public class Chromosome {
private
String
geneStr
;
public
String
getGeneStr
()
{
geneStr
=
getMachineStr
()+
"_"
+
getOperationStr
();
return
geneStr
;
if
(
geneStrDirty
||
machineStrDirty
||
operationStrDirty
)
{
geneStr
=
getMachineStr
()
+
"_"
+
getOperationStr
();
geneStrDirty
=
false
;
}
return
geneStr
;
}
private
Integer
gsOrls
=
0
;
public
String
getMachineStr
()
{
machineStr
=
Optional
.
ofNullable
(
machineSelection
)
.
orElse
(
Collections
.
emptyList
())
.
stream
()
.
map
(
String:
:
valueOf
)
// Integer转String
.
collect
(
Collectors
.
joining
(
","
));
return
machineStr
;
if
(
machineStrDirty
)
{
machineStr
=
Optional
.
ofNullable
(
machineSelection
)
.
orElse
(
Collections
.
emptyList
())
.
stream
()
.
map
(
String:
:
valueOf
)
.
collect
(
Collectors
.
joining
(
","
));
machineStrDirty
=
false
;
geneStrDirty
=
true
;
}
return
machineStr
;
}
public
String
getOperationStr
()
{
if
(
operationStrDirty
)
{
operationStr
=
Optional
.
ofNullable
(
operationSequencing
)
.
orElse
(
Collections
.
emptyList
())
.
stream
()
.
map
(
String:
:
valueOf
)
.
collect
(
Collectors
.
joining
(
","
));
operationStrDirty
=
false
;
geneStrDirty
=
true
;
}
return
operationStr
;
}
// 重写 setter 方法,在设置时标记为脏
public
void
setMachineSelection
(
List
<
Integer
>
machineSelection
)
{
this
.
machineSelection
=
machineSelection
;
this
.
machineStrDirty
=
true
;
this
.
geneStrDirty
=
true
;
}
operationStr
=
Optional
.
ofNullable
(
operationSequencing
)
.
orElse
(
Collections
.
emptyList
())
.
stream
()
.
map
(
String:
:
valueOf
)
// Integer转String
.
collect
(
Collectors
.
joining
(
","
));
return
operationStr
;
public
void
setOperationSequencing
(
List
<
Integer
>
operationSequencing
)
{
this
.
operationSequencing
=
operationSequencing
;
this
.
operationStrDirty
=
true
;
this
.
geneStrDirty
=
true
;
}
...
...
@@ -105,7 +131,7 @@ public class Chromosome {
private
List
<
String
>
materialIds
;
/*
* 最早完工时间(最小化) 最小化总加工时间 最小总换型时间
* 最早完工时间(最小化) 最小化总加工时间 最小总换型时间
*/
private
double
[]
Objectives
;
// 多目标值:[Makespan, TotalFlowTime, TotalChangeover, LoadStd, Delay]
private
double
[]
MaxObjectives
;
//
...
...
@@ -113,8 +139,8 @@ public class Chromosome {
private
int
Rank
;
// 非支配排序等级(1最优)
private
double
CrowdingDistance
=
0
;
// 拥挤距离 越小越优
/*
*(Objectives - min) / (max - min);
*/
*(Objectives - min) / (max - min);
*/
private
double
[]
WeightedObjectives
;
//越靠近1越优
private
double
WeightedObjective
=
0
;
// 加权目标值(用于自定义权重)
...
...
src/main/java/com/aps/entity/Algorithm/ScheduleParams.java
View file @
f2a1529b
...
...
@@ -15,7 +15,7 @@ public class ScheduleParams {
// 基础参数(自适应调整的基准值)
private
static
final
int
MIN_POPULATION_SIZE
=
10
;
private
static
final
int
MAX_POPULATION_SIZE
=
5
0
;
private
static
final
int
MAX_POPULATION_SIZE
=
2
0
;
private
static
final
int
MIN_MAX_ITERATIONS
=
50
;
private
static
final
int
MAX_MAX_ITERATIONS
=
100
;
private
static
final
float
MIN_CROSSOVER_PROB
=
0.6f
;
...
...
@@ -172,10 +172,14 @@ public class ScheduleParams {
// 1. 种群大小:50 ~ 500,随工序数线性增加
populationSize
=
(
int
)
Math
.
max
(
MIN_POPULATION_SIZE
,
Math
.
min
(
MAX_POPULATION_SIZE
,
MIN_POPULATION_SIZE
+
totalOps
*
populationSizeCoeff
));
int
maxthead
=
Runtime
.
getRuntime
().
availableProcessors
()
-
1
;
populationSize
=
populationSize
/
maxthead
*
maxthead
;
// 确保偶数(方便交叉)
if
(
populationSize
%
2
!=
0
)
{
populationSize
+=
1
;
}
//
if (populationSize % 2 != 0) {
//
populationSize += 1;
//
}
// 2. 最大迭代次数:50 ~ 200,随工序数线性减少
maxIterations
=
(
int
)
Math
.
max
(
MIN_MAX_ITERATIONS
,
...
...
src/main/java/com/aps/entity/basic/GlobalParam.java
View file @
f2a1529b
...
...
@@ -73,11 +73,11 @@ public class GlobalParam {
public
GlobalParam
()
{
// 初始化默认目标值配置
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_MAKESPAN
,
true
,
1
,
0.
6
));
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_FLOW_TIME
,
fals
e
,
2
,
0.1
));
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_MAKESPAN
,
true
,
1
,
0.
3
));
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_FLOW_TIME
,
tru
e
,
2
,
0.1
));
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_SETUP_TIME
,
true
,
2
,
0.1
));
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_MACHINE_LOAD
,
false
,
3
,
0.1
));
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_TARDINESS
,
true
,
1
,
0.
3
));
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_MACHINE_LOAD
,
true
,
1
,
0.1
));
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_TARDINESS
,
true
,
1
,
0.
6
));
objectiveConfigs
.
sort
(
Comparator
.
comparing
((
ObjectiveConfig
op
)
->
op
.
getLevel
()));
}
...
...
src/main/java/com/aps/entity/basic/KpiTargetConfig.java
0 → 100644
View file @
f2a1529b
package
com
.
aps
.
entity
.
basic
;
/**
* 作者:佟礼
* 时间:2026-04-09
*/
public
class
KpiTargetConfig
{
}
src/main/java/com/aps/entity/basic/Order.java
View file @
f2a1529b
...
...
@@ -156,6 +156,11 @@ public class Order {
* 是否新创建,默认值:false
*/
private
boolean
newCreate
=
false
;
/**
* 是否新创建半成品,默认值:false
*/
private
boolean
newSfCreate
=
false
;
/**
* 是否创建BOM,默认值:false
...
...
src/main/java/com/aps/service/Algorithm/FitnessCalculator.java
View file @
f2a1529b
...
...
@@ -21,8 +21,10 @@ public class FitnessCalculator {
ArrayList
<
Double
>
list
=
new
ArrayList
<>();
double
fitness
=
0
;
double
total
=
0
;
int
i
=
0
;
int
level
=-
1
;
double
[]
weightedObjectives
=
new
double
[
chromosome
.
getObjectives
().
length
];
for
(
ObjectiveConfig
config
:
param
.
getObjectiveConfigs
())
{
if
(
config
.
isEnabled
())
{
...
...
@@ -65,7 +67,9 @@ public class FitnessCalculator {
if
(!
param
.
isPureNSGAIIMode
())
{
val
=
val
*
config
.
getWeight
();
}
weightedObjectives
[
i
]=
val
;
fitness
+=
val
;
total
+=
val
;
i
++;
}
}
...
...
@@ -87,6 +91,8 @@ public class FitnessCalculator {
// fitness ≈ 0.01
// 适应度值(越大越好)
chromosome
.
setFitness
(
total
);
chromosome
.
setWeightedObjectives
(
weightedObjectives
);
return
list
.
stream
().
mapToDouble
(
Double:
:
doubleValue
).
toArray
();
}
...
...
@@ -147,7 +153,7 @@ public class FitnessCalculator {
// 2. 计算每个个体与平均值的平方差之和
float
sumSqDiff
=
0.0f
;
for
(
Chromosome
chromosome
:
population
)
{
double
diff
=
chromosome
.
get
WeightedObjective
()
-
avgFitness
;
double
diff
=
chromosome
.
get
Fitness
()
-
avgFitness
;
sumSqDiff
+=
diff
*
diff
;
}
...
...
@@ -155,6 +161,19 @@ public class FitnessCalculator {
return
(
double
)
Math
.
sqrt
(
sumSqDiff
/
popSize
);
}
/**
* 比较两个染色体的优劣(基于fitnessLevel多层次比较)
*/
public
boolean
isBetter
(
Chromosome
c1
,
Chromosome
c2
)
{
for
(
int
i
=
0
;
i
<
c1
.
getFitnessLevel
().
length
;
i
++)
{
double
[]
Fitness1
=
c1
.
getFitnessLevel
();
double
[]
Fitness2
=
c2
.
getFitnessLevel
();
if
(
Fitness1
[
i
]
>
Fitness2
[
i
])
{
return
true
;
}
}
return
false
;
}
...
...
src/main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
View file @
f2a1529b
...
...
@@ -425,7 +425,7 @@ public class GeneticAlgorithm {
// chromosome.setResultOld(new CopyOnWriteArrayList<>());
// }
decoder
.
decodeChromosomeWithCache
(
chromosome
);
decoder
.
decodeChromosomeWithCache
(
chromosome
,
false
);
if
(
chromosome
.
getFitness
()
==
0
)
{
chromosome
.
setFitness
(
_fitnessCalculator
.
calculateFitness
(
chromosome
,
_objectiveWeights
));
}
...
...
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
View file @
f2a1529b
...
...
@@ -35,13 +35,13 @@ import java.util.stream.IntStream;
public
class
GeneticDecoder
{
// private final Map<String, Chromosome> decodingCache = new HashMap<>();
// private final Map<String, Chromosome> decodingCache = new HashMap<>();
private
final
ConcurrentHashMap
<
String
,
Chromosome
>
decodingCache
=
new
ConcurrentHashMap
<>();
// 缓存大小限制
private
static
final
int
MAX_CACHE_SIZE
=
3000
;
// 线程安全锁:避免多线程下缓存操作冲突(可选,若单线程可移除)
// private final ReentrantLock cacheLock = new ReentrantLock();
// private final ReentrantLock cacheLock = new ReentrantLock();
private
LocalDateTime
baseTime
;
private
final
List
<
Machine
>
machines
;
private
final
MachineSchedulerService
machineScheduler
;
...
...
@@ -70,10 +70,10 @@ public class GeneticDecoder {
this
.
materials
=
materials
;
this
.
machineScheduler
=
machineScheduler
;
_globalParam
=
globalParam
;
machineCalculator
=
new
MachineCalculator
(
baseTime
,
machines
,
machineScheduler
);
machineCalculator
=
new
MachineCalculator
(
baseTime
,
machines
,
machineScheduler
);
materialRequirementService
=
_materialRequirementService
;
sceneId
=
_sceneId
;
// this.orderMaxID = orders.stream().mapToInt(Order::getId).max().orElse(0);
// this.orderMaxID = orders.stream().mapToInt(Order::getId).max().orElse(0);
}
private
final
ExecutorService
decodeExecutor
=
new
ThreadPoolExecutor
(
...
...
@@ -88,17 +88,17 @@ public class GeneticDecoder {
{
FileHelper
.
writeLogFile
(
"解码---------------"
+
population
.
size
()
);
boolean
ismore
=
fals
e
;
boolean
ismore
=
tru
e
;
if
(
ismore
)
{
CompletableFuture
.
allOf
(
population
.
stream
()
.
map
(
chromosome
->
CompletableFuture
.
runAsync
(()
->
decodeChromosomeWithCache
(
chromosome
),
decodeExecutor
))
.
map
(
chromosome
->
CompletableFuture
.
runAsync
(()
->
decodeChromosomeWithCache
(
chromosome
,
false
),
decodeExecutor
))
.
toArray
(
CompletableFuture
[]::
new
))
.
join
();
}
else
{
if
(
population
!=
null
&&
population
.
size
()
>
0
)
{
population
.
forEach
(
chromosome
->
{
decodeChromosomeWithCache
(
chromosome
);
decodeChromosomeWithCache
(
chromosome
,
false
);
});
}
}
...
...
@@ -176,7 +176,7 @@ public class GeneticDecoder {
// return chromosome;
// }
public
Chromosome
decodeChromosomeWithCache
(
Chromosome
chromosome
)
{
public
Chromosome
decodeChromosomeWithCache
(
Chromosome
chromosome
,
boolean
isParallel
)
{
String
cacheKey
=
createCacheKey
(
chromosome
);
// FileHelper.writeLogFile("解码-----------开始-------"+chromosome.getID()+":"+cacheKey );
...
...
@@ -214,7 +214,7 @@ public class GeneticDecoder {
return
chromosome
;
}
// 3. 缓存未命中:执行解码逻辑
decode
(
chromosome
);
decode
(
chromosome
,
isParallel
);
// 4. 将解码结果存入缓存(无锁,ConcurrentHashMap 线程安全)
decodingCache
.
putIfAbsent
(
cacheKey
,
chromosome
);
...
...
@@ -266,7 +266,7 @@ public class GeneticDecoder {
Initialization
initialization
=
new
Initialization
();
initialization
.
generateInitialSFPopulation
(
chromosome
,
globalOpList
);
chromosome
.
getGlobalOpList
().
addAll
(
globalOpList
);
return
1
;
return
1
;
}
private
void
CreateNewOpSequence
(
Chromosome
chromosome
)
...
...
@@ -279,10 +279,10 @@ return 1;
.
distinct
()
.
collect
(
Collectors
.
toList
());
if
(
finishedOrder
==
null
||
finishedOrder
.
size
()==
0
)
{
return
;
}
if
(
finishedOrder
==
null
||
finishedOrder
.
size
()==
0
)
{
return
;
}
List
<
Integer
>
oldSequence
=
chromosome
.
getOperationSequencing
();
List
<
Integer
>
finalSequence
=
new
ArrayList
<>();
...
...
@@ -359,7 +359,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
}
finalSequence
.
add
(
orderid
);
}
else
{
int
insertPos
=
Math
.
max
(
0
,
finalSequence
.
size
());
int
insertPos
=
Math
.
max
(
0
,
finalSequence
.
size
());
// int insertPos = Math.max(0, finalSequence.size() - rnd.nextInt(2));
finalSequence
.
add
(
insertPos
,
orderid
);
...
...
@@ -367,17 +367,16 @@ if(finishedOrder==null||finishedOrder.size()==0)
orderProcessCounter
.
put
(
orderid
,
scheduledCount
);
}
public
void
decode
(
Chromosome
chromosome
)
{
int
operationCount
=
chromosome
.
getAllOperations
().
size
();
int
cpuCores
=
Runtime
.
getRuntime
().
availableProcessors
();
public
void
decode
(
Chromosome
chromosome
,
boolean
isParallel
)
{
//
// // 根据工序数量和CPU核心数决定是否使用内部并行
if
(
operationCount
>
5000
&&
cpuCores
>
4
)
{
if
(
isParallel
)
{
// 使用设备并行处理
// FileHelper.writeLogFile("使用并行处理 _s");
// FileHelper.writeLogFile("使用并行处理 _s");
parallelDecodeByMachine
(
chromosome
);
// FileHelper.writeLogFile("使用并行处理 _e");
}
// FileHelper.writeLogFile("使用并行处理 _e");
}
else
{
// 使用串行处理
// FileHelper.writeLogFile("使用串行处理 _s");
...
...
@@ -392,14 +391,14 @@ if(finishedOrder==null||finishedOrder.size()==0)
public
void
serialDecode
(
Chromosome
chromosome
)
{
//
List<OrderMaterialRequirement> orderMaterials = materialRequirementService.buildMultiLevelRequirementNetwork(chromosome, sceneId, baseTime,_globalParam);
List
<
OrderMaterialRequirement
>
orderMaterials
=
materialRequirementService
.
buildMultiLevelRequirementNetwork
(
chromosome
,
sceneId
,
baseTime
,
_globalParam
);
chromosome
.
setScenarioID
(
sceneId
);
if
(
_globalParam
.
isIsCheckSf
())
{
int
isnew
=
generateGlobalOpList
(
chromosome
);
int
isnew
=
generateGlobalOpList
(
chromosome
);
if
(
isnew
==
1
)
{
CreateNewOpSequence
(
chromosome
);
}
if
(
isnew
==
1
)
{
CreateNewOpSequence
(
chromosome
);
}
}
List
<
GlobalOperationInfo
>
globalOpList
=
chromosome
.
getGlobalOpList
();
...
...
@@ -473,23 +472,24 @@ if(finishedOrder==null||finishedOrder.size()==0)
Map
<
Integer
,
Integer
>
orderLastEndTime
=
new
HashMap
<>();
Map
<
Integer
,
Entry
>
entryIndexById
=
new
HashMap
<>();
Map
<
Integer
,
List
<
Entry
>>
entrysBygroupId
=
new
HashMap
<>();
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
=
new
ConcurrentHashMap
<>();
for
(
Entry
op
:
allOperations
)
{
int
groupId
=
op
.
getGroupId
();
orderProcessCounter
.
putIfAbsent
(
groupId
,
0
);
orderLastEndTime
.
putIfAbsent
(
groupId
,
0
);
entryIndexById
.
put
(
op
.
getId
(),
op
);
entrysBygroupId
.
computeIfAbsent
(
groupId
,
k
->
new
ArrayList
<>()).
add
(
op
);
//scheduleIndexById.put(op.getId(),null);
}
// Map<Long, String> machineState = chromosome.getMachines().stream()
// .collect(Collectors.toMap(Machine::getId, m -> ""));
// List<Entry> allScheduledOps = new ArrayList<>();
// List<Entry> allScheduledOps = new ArrayList<>();
// 缓存机器任务
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
=
new
HashMap
<>();
for
(
Entry
op
:
allOperations
)
{
}
for
(
int
groupId
:
chromosome
.
getOperationSequencing
())
{
int
scheduledCount
=
orderProcessCounter
.
get
(
groupId
);
List
<
Entry
>
orderOps
=
entrysBygroupId
.
get
(
groupId
).
stream
()
...
...
@@ -541,26 +541,26 @@ if(finishedOrder==null||finishedOrder.size()==0)
// }
// 上个离散参数
// String lastDiscreteParameter = machineState.get(machineId);
// String lastDiscreteParameter = machineState.get(machineId);
// int bomtime = getOperationBOMTime(currentOp,chromosome);
// int bomtime = getOperationBOMTime(currentOp,chromosome);
// int prevendtime=prevtime;
// prevtime = Math.max(prevtime, bomtime);
// int prevendtime=prevtime;
// prevtime = Math.max(prevtime, bomtime);
// Machine machine = chromosome.getMachines().stream()
// .filter(m -> m.getId() == machineId)
// .findFirst()
// .orElse(null);
// Machine machine = machineIdMap.get(machineId);
// int changeoverTime =0; //(lastDiscreteParameter.isEmpty() ||
// lastDiscreteParameter.equals(currentOp.getDiscreteParameter())) ? 0 : 0;
int
actualEndTime
=
processOperation
(
currentOp
,
machineId
,
processTime
,
machineOption
,
chromosome
,
machineIdMap
,
machineTasksCache
);
// int actualEndTime = processWithSingleMachine(currentOp, machine, processTime, prevtime,machineOption, chromosome,false,prevendtime,machineTasksCache);
// Machine machine = machineIdMap.get(machineId);
// int changeoverTime =0; //(lastDiscreteParameter.isEmpty() ||
// lastDiscreteParameter.equals(currentOp.getDiscreteParameter())) ? 0 : 0;
int
actualEndTime
=
processOperation
(
currentOp
,
machineId
,
processTime
,
machineOption
,
chromosome
,
machineIdMap
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
);
// int actualEndTime = processWithSingleMachine(currentOp, machine, processTime, prevtime,machineOption, chromosome,false,prevendtime,machineTasksCache);
orderProcessCounter
.
put
(
groupId
,
orderProcessCounter
.
get
(
groupId
)
+
1
);
orderLastEndTime
.
put
(
groupId
,
actualEndTime
);
// machineState.put(machineId, currentOp.getDiscreteParameter());
// machineState.put(machineId, currentOp.getDiscreteParameter());
}
if
(
chromosome
.
getReOrderids
()!=
null
&&
chromosome
.
getReOrderids
().
size
()>
0
)
{
chromosome
.
getOperationSequencing
().
removeIf
(
t
->
chromosome
.
getReOrderids
().
contains
(
t
));
...
...
@@ -570,131 +570,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
calculateScheduleResult
(
chromosome
);
}
public
void
parallelDecode
(
Chromosome
chromosome
)
{
FileHelper
.
writeLogFile
(
"构建工序依赖图 _s"
);
// 1. 构建工序依赖图
Map
<
Integer
,
List
<
Integer
>>
dependencyGraph
=
buildDependencyGraph
(
chromosome
);
FileHelper
.
writeLogFile
(
"拓扑排序 _s"
);
// 2. 拓扑排序
List
<
Integer
>
topologicalOrder
=
topologicalSort
(
dependencyGraph
,
chromosome
);
FileHelper
.
writeLogFile
(
"按设备分组 _s"
);
// 3. 按设备分组
Map
<
Long
,
List
<
Integer
>>
machineToOpsMap
=
new
HashMap
<>();
Map
<
Integer
,
Integer
>
opToGroupIdMap
=
new
HashMap
<>();
Map
<
Integer
,
Long
>
opToMachineMap
=
new
HashMap
<>();
List
<
GlobalOperationInfo
>
globalOpList
=
chromosome
.
getGlobalOpList
();
// 步骤1:生成“工序→机器/加工时间”映射
List
<
OpMachine
>
opMachineMap
=
new
ArrayList
<>();
Map
<
String
,
OpMachine
>
opMachineKeyMap
=
new
HashMap
<>();
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
=
new
HashMap
<>();
Map
<
Long
,
Machine
>
machineIdMap
=
chromosome
.
getMachines
().
stream
()
.
collect
(
Collectors
.
toMap
(
Machine:
:
getId
,
m
->
m
));
// 构建工序ID索引:opId -> Entry(O(1)查找)
Map
<
Integer
,
Entry
>
opIdIndex
=
buildOpIdIndex
(
chromosome
);
for
(
GlobalOperationInfo
globalOp
:
globalOpList
)
{
int
globalOpId
=
globalOp
.
getGlobalOpId
();
Entry
op
=
globalOp
.
getOp
();
int
groupId
=
globalOp
.
getGroupId
();
int
sequence
=
globalOp
.
getSequence
();
// 从MachineSelection中获取当前工序的机器选择顺序号
int
machineSeq
=
chromosome
.
getMachineSelection
().
get
(
globalOpId
);
List
<
MachineOption
>
optionalMachines
=
op
.
getMachineOptions
();
// 验证:机器顺序号必须在可选范围内
if
(
machineSeq
<
1
||
machineSeq
>
optionalMachines
.
size
())
{
throw
new
IllegalStateException
(
String
.
format
(
"全局工序%d(订单%d工序%d)的机器顺序号%d超出范围(1-%d)"
,
globalOpId
,
groupId
,
sequence
,
machineSeq
,
optionalMachines
.
size
()));
}
// 获取选择的设备ID和加工时间
MachineOption
selectedMachine
=
optionalMachines
.
get
(
machineSeq
-
1
);
OpMachine
opMachine
=
new
OpMachine
();
opMachine
.
setGroupId
(
groupId
);
opMachine
.
setSequence
(
sequence
);
opMachine
.
setMachineId
(
selectedMachine
.
getMachineId
());
opMachine
.
setProcessingTime
(
selectedMachine
.
getProcessingTime
());
opMachine
.
setRuntime
(
selectedMachine
.
getRuntime
());
opMachine
.
setSingleOut
(
selectedMachine
.
getSingleOut
());
opMachineMap
.
add
(
opMachine
);
String
key
=
opMachine
.
getGroupId
()
+
"_"
+
opMachine
.
getSequence
();
opMachineKeyMap
.
put
(
key
,
opMachine
);
}
FileHelper
.
writeLogFile
(
"预处理工序信息 _s"
);
// 预处理工序信息
for
(
int
opId
:
topologicalOrder
)
{
// Entry op = findOperationById(chromosome, opId);
Entry
op
=
opIdIndex
.
get
(
opId
);
if
(
op
!=
null
)
{
// 假设已经为工序分配了设备
String
opMachineKey
=
op
.
getGroupId
()
+
"_"
+
op
.
getSequence
();
OpMachine
machineOption
=
opMachineKeyMap
.
get
(
opMachineKey
);
if
(
machineOption
!=
null
)
{
machineToOpsMap
.
computeIfAbsent
(
machineOption
.
getMachineId
(),
k
->
new
ArrayList
<>()).
add
(
opId
);
opToGroupIdMap
.
put
(
opId
,
op
.
getGroupId
());
opToMachineMap
.
put
(
opId
,
machineOption
.
getMachineId
());
}
}
}
// 4. 并行处理
Map
<
Integer
,
CompletableFuture
<
Void
>>
opFutures
=
new
HashMap
<>();
Map
<
Long
,
CompletableFuture
<
Void
>>
machineFutures
=
new
HashMap
<>();
FileHelper
.
writeLogFile
(
"并行处理 _s"
);
for
(
int
opId
:
topologicalOrder
)
{
// 获取当前工序的依赖
// Entry op = findOperationById(chromosome, opId);
Entry
op
=
opIdIndex
.
get
(
opId
);
List
<
Integer
>
dependencies
=
dependencyGraph
.
getOrDefault
(
opId
,
Collections
.
emptyList
());
// 等待所有依赖完成
List
<
CompletableFuture
<
Void
>>
dependencyFutures
=
dependencies
.
stream
()
.
map
(
opFutures:
:
get
)
.
filter
(
Objects:
:
nonNull
)
.
collect
(
Collectors
.
toList
());
String
opMachineKey
=
op
.
getGroupId
()
+
"_"
+
op
.
getSequence
();
OpMachine
machineOption
=
opMachineKeyMap
.
get
(
opMachineKey
);
Long
machineId
=
machineOption
.
getMachineId
();
double
processTime
=
machineOption
.
getProcessingTime
();
// 等待当前设备的上一个工序完成
CompletableFuture
<
Void
>
machineFuture
=
machineFutures
.
getOrDefault
(
machineId
,
CompletableFuture
.
completedFuture
(
null
));
// 合并所有依赖
List
<
CompletableFuture
<
Void
>>
allDependencies
=
new
ArrayList
<>(
dependencyFutures
);
allDependencies
.
add
(
machineFuture
);
// 创建当前工序的处理任务
CompletableFuture
<
Void
>
currentFuture
=
CompletableFuture
.
allOf
(
allDependencies
.
toArray
(
new
CompletableFuture
[
0
]))
.
thenRunAsync
(()
->
{
// 处理当前工序
int
actualEndTime
=
processOperation
(
op
,
machineId
,
processTime
,
machineOption
,
chromosome
,
machineIdMap
,
machineTasksCache
);
});
// 保存当前工序的Future
opFutures
.
put
(
opId
,
currentFuture
);
// 更新设备的Future
machineFutures
.
put
(
machineId
,
currentFuture
);
}
// 等待所有工序完成
CompletableFuture
.
allOf
(
opFutures
.
values
().
toArray
(
new
CompletableFuture
[
0
])).
join
();
FileHelper
.
writeLogFile
(
"calculateScheduleResult _s"
);
if
(
chromosome
.
getReOrderids
()!=
null
&&
chromosome
.
getReOrderids
().
size
()>
0
)
{
chromosome
.
getOperationSequencing
().
removeIf
(
t
->
chromosome
.
getReOrderids
().
contains
(
t
));
}
calculateScheduleResult
(
chromosome
);
}
public
void
parallelDecodeByMachine
(
Chromosome
chromosome
)
{
// 1. 获取工序处理顺序
List
<
Integer
>
operationSequencing
=
chromosome
.
getOperationSequencing
();
...
...
@@ -748,9 +624,15 @@ if(finishedOrder==null||finishedOrder.size()==0)
// 初始化订单处理计数器
Map
<
Integer
,
Integer
>
orderProcessCounter
=
new
HashMap
<>();
Map
<
Integer
,
Entry
>
entryIndexById
=
new
HashMap
<>();
Map
<
Integer
,
List
<
Entry
>>
entrysBygroupId
=
new
HashMap
<>();
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
=
new
ConcurrentHashMap
<>();
for
(
Entry
op
:
allOperations
)
{
int
groupId
=
op
.
getGroupId
();
orderProcessCounter
.
putIfAbsent
(
groupId
,
0
);
entryIndexById
.
put
(
op
.
getId
(),
op
);
entrysBygroupId
.
computeIfAbsent
(
groupId
,
k
->
new
ArrayList
<>()).
add
(
op
);
}
Map
<
Long
,
List
<
Entry
>>
machineToOpsMap
=
new
HashMap
<>();
//按照 OperationSequencing 顺序生成 machineToOpsMap
...
...
@@ -886,11 +768,11 @@ if(finishedOrder==null||finishedOrder.size()==0)
// 工序超过500的设备直接在主线程串行处理
if
(
ops
.
size
()
>
500
)
{
// FileHelper.writeLogFile("设备 " + machineId + " 有 " + ops.size() + " 个工序,直接串行处理");
processMachineOps
(
chromosome
,
machineId
,
ops
,
dependencyGraph
,
opCompleted
,
lock
,
opMachineKeyMap
,
machineIdMap
,
machineTasksCache
);
processMachineOps
(
chromosome
,
machineId
,
ops
,
dependencyGraph
,
opCompleted
,
lock
,
opMachineKeyMap
,
machineIdMap
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
);
}
else
{
// 工序少的设备创建线程处理
Thread
thread
=
new
Thread
(()
->
{
processMachineOps
(
chromosome
,
machineId
,
ops
,
dependencyGraph
,
opCompleted
,
lock
,
opMachineKeyMap
,
machineIdMap
,
machineTasksCache
);
processMachineOps
(
chromosome
,
machineId
,
ops
,
dependencyGraph
,
opCompleted
,
lock
,
opMachineKeyMap
,
machineIdMap
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
);
});
thread
.
start
();
threads
.
add
(
thread
);
...
...
@@ -920,7 +802,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
*/
private
void
processMachineOps
(
Chromosome
chromosome
,
Long
machineId
,
List
<
Entry
>
ops
,
Map
<
Integer
,
List
<
Integer
>>
dependencyGraph
,
Map
<
Integer
,
Boolean
>
opCompleted
,
Object
lock
,
Map
<
String
,
OpMachine
>
opMachineKeyMap
,
Map
<
Long
,
Machine
>
machineIdMap
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
)
{
Map
<
Integer
,
Boolean
>
opCompleted
,
Object
lock
,
Map
<
String
,
OpMachine
>
opMachineKeyMap
,
Map
<
Long
,
Machine
>
machineIdMap
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
,
Map
<
Integer
,
Entry
>
entryIndexById
,
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
)
{
//long machineStartTime = System.currentTimeMillis();
for
(
int
i
=
0
;
i
<
ops
.
size
();
i
++)
{
...
...
@@ -955,17 +837,17 @@ if(finishedOrder==null||finishedOrder.size()==0)
double
processTime
=
machineOption
.
getProcessingTime
();
// 处理当前工序
// long processStartTime = System.currentTimeMillis();
int
actualEndTime
=
processOperation
(
op
,
machineId
,
processTime
,
machineOption
,
chromosome
,
machineIdMap
,
machineTasksCache
);
// long processStartTime = System.currentTimeMillis();
int
actualEndTime
=
processOperation
(
op
,
machineId
,
processTime
,
machineOption
,
chromosome
,
machineIdMap
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
);
// long processEndTime = System.currentTimeMillis();
// long processEndTime = System.currentTimeMillis();
// 标记工序完成
synchronized
(
lock
)
{
opCompleted
.
put
(
opId
,
true
);
}
// long opEndTime = System.currentTimeMillis();
// long opEndTime = System.currentTimeMillis();
// if (i % 100 == 0 || i == ops.size() - 1) {
// FileHelper.writeLogFile("设备 " + machineId + " 工序 " + i + "/" + ops.size() +
// " 完成,总耗时:" + (opEndTime - machineStartTime) + "ms,本工序耗时:" + (opEndTime - opStartTime) + "ms");
...
...
@@ -1091,8 +973,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
return
result
;
}
/**
* 构建工序ID索引:opId -> Entry(O(1)查找)
*/
* 构建工序ID索引:opId -> Entry(O(1)查找)
*/
private
Map
<
Integer
,
Entry
>
buildOpIdIndex
(
Chromosome
chromosome
)
{
Map
<
Integer
,
Entry
>
index
=
new
HashMap
<>();
for
(
Entry
op
:
chromosome
.
getAllOperations
())
{
...
...
@@ -1114,7 +996,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
private
int
processOperation
(
Entry
currentOp
,
Long
machineId
,
double
processTime
,
OpMachine
machineOption
,
Chromosome
chromosome
,
Map
<
Long
,
Machine
>
machineIdMap
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
)
private
int
processOperation
(
Entry
currentOp
,
Long
machineId
,
double
processTime
,
OpMachine
machineOption
,
Chromosome
chromosome
,
Map
<
Long
,
Machine
>
machineIdMap
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
,
Map
<
Integer
,
Entry
>
entryIndexById
,
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
)
{
Machine
targetMachine
=
machineIdMap
.
get
(
machineId
);
...
...
@@ -1123,7 +1005,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
int
teardownTime
=
currentOp
.
getTeardownTime
();
if
(!
currentOp
.
getPrevEntryIds
().
isEmpty
())
{
// 处理多个前工序
prevtime
=
CalPrevtime
(
prevtime
,
currentOp
,
chromosome
,
processTime
,
targetMachine
);
prevtime
=
CalPrevtime
(
prevtime
,
currentOp
,
chromosome
,
processTime
,
targetMachine
,
entryIndexById
,
scheduleIndexById
);
}
int
bomtime
=
getOperationBOMTime
(
currentOp
,
chromosome
);
...
...
@@ -1131,14 +1013,14 @@ if(finishedOrder==null||finishedOrder.size()==0)
int
prevendtime
=
prevtime
;
prevtime
=
Math
.
max
(
prevtime
,
bomtime
);
Machine
machine
=
machineIdMap
.
get
(
machineId
);
int
actualEndTime
=
processWithSingleMachine
(
currentOp
,
machine
,
processTime
,
prevtime
,
machineOption
,
chromosome
,
false
,
prevendtime
,
machineTasksCache
);
return
actualEndTime
;
int
actualEndTime
=
processWithSingleMachine
(
currentOp
,
machine
,
processTime
,
prevtime
,
machineOption
,
chromosome
,
false
,
prevendtime
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
);
return
actualEndTime
;
}
private
int
processWithSingleMachine
(
Entry
operation
,
Machine
machine
,
double
processingTime
,
int
prevOperationEndTime
,
OpMachine
machineOption
,
Chromosome
chromosome
,
boolean
calbom
,
int
prevendtime
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
)
{
int
prevOperationEndTime
,
OpMachine
machineOption
,
Chromosome
chromosome
,
boolean
calbom
,
int
prevendtime
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
,
Map
<
Integer
,
Entry
>
entryIndexById
,
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
)
{
int
processingTimeTotal
=
0
;
int
earliestStartTime
=
prevOperationEndTime
;
if
(
operation
.
getConstTime
()==
1
)
//常数时间
...
...
@@ -1155,7 +1037,7 @@ return actualEndTime;
}
if
(
machine
==
null
||
operation
.
getMachineOptions
()==
null
)
{
return
0
;
return
0
;
}
// MachineOption machineOption= operation.getMachineOptions().stream()
...
...
@@ -1181,7 +1063,7 @@ return actualEndTime;
//前处理,是否可以在相同任务前序未完工就开始设置时间,
// 就是 最早开工时间是否+前处理时间,总的加工工时不考虑前处理
if
(!
_globalParam
.
is_smoothSetup
())
{
// 工序的前处理不能提前,则要在前处理完成后才能开工,所以要在前一工序的结束时间基础上+前处理
// 工序的前处理不能提前,则要在前处理完成后才能开工,所以要在前一工序的结束时间基础上+前处理
earliestStartTime
+=
preTime
;
}
GAScheduleResult
existingResult
=
chromosome
.
getResultOld
().
stream
().
filter
(
r
->
r
.
getOperationId
()
==
operation
.
getId
()).
findFirst
().
orElse
(
null
);
...
...
@@ -1195,18 +1077,18 @@ return actualEndTime;
if
(
machineTasksCache
.
containsKey
(
machine
.
getId
()))
{
machineTasks
=
machineTasksCache
.
get
(
machine
.
getId
());
}
else
{
machineTasks
=
chromosome
.
getResult
().
stream
()
machineTasks
=
chromosome
.
getResult
().
stream
()
.
filter
(
t
->
t
.
getMachineId
()
==
machine
.
getId
())
.
sorted
(
Comparator
.
comparingInt
(
GAScheduleResult:
:
getStartTime
))
.
collect
(
Collectors
.
toCollection
(
CopyOnWriteArrayList:
:
new
));
machineTasksCache
.
put
(
machine
.
getId
(),
machineTasks
);
}
GAScheduleResult
lastGeneOnMachine
=
null
;
if
(
machineTasks
!=
null
&&
machineTasks
.
size
()>
0
)
{
lastGeneOnMachine
=
machineTasks
.
get
(
machineTasks
.
size
()-
1
);
}
GAScheduleResult
lastGeneOnMachine
=
null
;
if
(
machineTasks
!=
null
&&
machineTasks
.
size
()>
0
)
{
lastGeneOnMachine
=
machineTasks
.
get
(
machineTasks
.
size
()-
1
);
}
if
(
lastGeneOnMachine
!=
null
&&
_globalParam
.
is_smoothChangeOver
())
{
earliestStartTime
=
Math
.
max
(
earliestStartTime
,
lastGeneOnMachine
.
getEndTime
());
...
...
@@ -1223,8 +1105,8 @@ return actualEndTime;
if
(
_globalParam
.
is_smoothChangeOver
())
{
Map
<
Integer
,
Object
>
reslte
=
calculateSetupTime
(
lastGeneOnMachine
,
operation
,
machine
,
earliestStartTime
,
processingTimeTotal
,
_globalParam
.
is_smoothChangeOverInWeek
(),
chromosome
.
getAllOperations
());
// setupTime = (int) reslte.get(1);//换型时间
// int setupStartTime = (int) reslte.get(2);//换型开始时间
// setupTime = (int) reslte.get(1);//换型时间
// int setupStartTime = (int) reslte.get(2);//换型开始时间
//earliestStartTime=(int)reslte.get(3);//上个任务的结束时间
earliestStartTime
=
(
int
)
reslte
.
get
(
4
);
//最早开工时间
}
...
...
@@ -1239,7 +1121,7 @@ return actualEndTime;
:
earliestStartTime
;
}
bomtime
=
EditOperationBOMTime
(
operation
,
chromosome
,
earliestStartTime
,
machineTasksCache
);
bomtime
=
EditOperationBOMTime
(
operation
,
chromosome
,
earliestStartTime
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
);
if
(
bomtime
>
prevendtime
&&
bomtime
<
earliestStartTimeold
)
...
...
@@ -1329,9 +1211,9 @@ return actualEndTime;
//开工时间需往后延 2小时
// 准备工时 加入到加工时间里
// 准备工时 加入到加工时间里
// 后处理时间 相同任务的前一工序的结束时间+后处理时间 =当前工序最早开工时间
// 后处理时间 相同任务的前一工序的结束时间+后处理时间 =当前工序最早开工时间
GAScheduleResult
result
=
new
GAScheduleResult
();
...
...
@@ -1368,17 +1250,17 @@ return actualEndTime;
processingTimeTotal1
=(
int
)
geneDetails
.
stream
().
filter
(
t
->
t
.
getUsedSegment
()==
null
).
mapToDouble
(
ScheduleResultDetail:
:
getProcessingTime
)
// 替换为实际字段名
.
sum
();
List
<
TimeSegment
>
UsedSegments
=
geneDetails
.
stream
().
List
<
TimeSegment
>
UsedSegments
=
geneDetails
.
stream
().
filter
(
t
->
t
.
getUsedSegment
()!=
null
)
.
map
(
ScheduleResultDetail:
:
getUsedSegment
).
flatMap
(
List:
:
stream
)
// 收集为最终的 List
.
collect
(
Collectors
.
toList
());
// 收集为最终的 List
.
collect
(
Collectors
.
toList
());
if
(
UsedSegments
!=
null
&&
UsedSegments
.
size
()>
0
)
{
processingTimeTotal1
+=(
int
)
UsedSegments
.
stream
().
mapToDouble
(
TimeSegment:
:
getProcessingTime
)
// 替换为实际字段名
.
sum
();
}
if
(
UsedSegments
!=
null
&&
UsedSegments
.
size
()>
0
)
{
processingTimeTotal1
+=(
int
)
UsedSegments
.
stream
().
mapToDouble
(
TimeSegment:
:
getProcessingTime
)
// 替换为实际字段名
.
sum
();
}
result
.
setProcessingTime
(
processingTimeTotal1
);
...
...
@@ -1386,15 +1268,15 @@ return actualEndTime;
// System.out.println("huanxingshijian="+result.getChangeOverTime()+"-------------------"+result.getOrderId()+"--------"+result.getExecId()+"---------"+prev.getOrderId()+"--------"+prev.getExecId());
chromosome
.
getResult
().
add
(
result
);
machine
.
setLastGene
(
result
);
chromosome
.
getResult
().
add
(
result
);
machine
.
setLastGene
(
result
);
// FileHelper.writeLogFile(" 结束 "+ConvertTime(startTime)+"--"+ConvertTime(endTime)+" "+operation.getGroupId()+" : "+operation.getId()+",处理时间: " + processingTime + ", 后处理: " + teardownTime +
// ", 前处理: " + preTime + ", 换型: " + setupTime+ ", 数量: " + operation.getQuantity()+ ", 设备: "+machine.getId()+ ", 是否可中断: "+operation.getIsInterrupt());
if
(
machineTasks
!=
null
)
{
machineTasks
.
add
(
result
);
}
scheduleIndexById
.
put
(
operation
.
getId
(),
result
);
return
endTime
;
}
...
...
@@ -1405,16 +1287,18 @@ return actualEndTime;
* @param chromosome
* @return
*/
private
int
CalPrevtime
(
int
prevtime
,
Entry
currentOp
,
Chromosome
chromosome
,
double
processTime
,
Machine
machine
)
{
private
int
CalPrevtime
(
int
prevtime
,
Entry
currentOp
,
Chromosome
chromosome
,
double
processTime
,
Machine
machine
,
Map
<
Integer
,
Entry
>
entryIndexById
,
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
)
{
List
<
OperationDependency
>
FsOperations
=
currentOp
.
getPrevEntryIds
().
stream
()
.
filter
(
t
->
t
.
getDependencyType
()
==
DependencyType
.
FinishToStart
)
.
collect
(
Collectors
.
toList
());
//串行
if
(
FsOperations
!=
null
&&
FsOperations
.
size
()
>
0
)
{
for
(
OperationDependency
opid
:
FsOperations
)
{
List
<
GAScheduleResult
>
prevOperations
=
chromosome
.
getResult
().
stream
()
.
filter
(
t
->
t
.
getGroupId
()
==
currentOp
.
getGroupId
()
&&
t
.
getOperationId
()
==
opid
.
getPrevOperationId
())
.
collect
(
Collectors
.
toList
());
//多台
for
(
GAScheduleResult
prevOp
:
prevOperations
)
{
// List<GAScheduleResult> prevOperations = chromosome.getResult().stream()
// .filter(t -> t.getOperationId() == opid.getPrevOperationId())
// .collect(Collectors.toList());//
GAScheduleResult
prevOp
=
scheduleIndexById
.
get
(
opid
.
getPrevOperationId
());
// for (GAScheduleResult prevOp : prevOperations) {
if
(
prevOp
!=
null
){
//加上后处理时间
prevtime
=
Math
.
max
(
prevtime
,
prevOp
.
getEndTime
()
+
currentOp
.
getTeardownTime
());
}
...
...
@@ -1431,31 +1315,36 @@ return actualEndTime;
for
(
int
j
=
0
;
j
<
SSOperations
.
size
();
j
++)
{
OperationDependency
opid
=
SSOperations
.
get
(
j
);
List
<
GAScheduleResult
>
prevOperations
=
chromosome
.
getResult
().
stream
()
.
filter
(
t
->
t
.
getGroupId
()
==
currentOp
.
getGroupId
()
&&
t
.
getOperationId
()
==
opid
.
getPrevOperationId
())
.
collect
(
Collectors
.
toList
());
//多台
for
(
GAScheduleResult
prevOp
:
prevOperations
)
{
// List<GAScheduleResult> prevOperations = chromosome.getResult().stream()
// .filter(t -> t.getOperationId() == opid.getPrevOperationId())
// .collect(Collectors.toList());//多台
GAScheduleResult
prevOp
=
scheduleIndexById
.
get
(
opid
.
getPrevOperationId
());
// for (GAScheduleResult prevOp : prevOperations) {
if
(
prevOp
!=
null
){
newScheduleResult
.
add
(
prevOp
);
newScheduleResultDetails
.
addAll
(
prevOp
.
getGeneDetails
());
}
if
(
j
==
SSOperations
.
size
()-
1
)
{
int
prevtime1
=
CalSSPrevtime
(
newScheduleResult
,
newScheduleResultDetails
,
prevtime
,
currentOp
,
chromosome
,
processTime
,
machine
);
int
prevtime1
=
CalSSPrevtime
(
newScheduleResult
,
newScheduleResultDetails
,
prevtime
,
currentOp
,
chromosome
,
processTime
,
machine
);
prevtime
=
Math
.
max
(
prevtime
,
prevtime1
);
}
else
{
Entry
entry
=
chromosome
.
getAllOperations
().
stream
()
.
filter
(
t
->
t
.
getId
()==
opid
.
getPrevOperationId
())
.
findFirst
().
orElse
(
null
);
// Entry entry= chromosome.getAllOperations().stream()
// .filter(t->t.getId()==opid.getPrevOperationId())
// .findFirst().orElse(null);
Entry
entry
=
entryIndexById
.
get
(
opid
.
getPrevOperationId
());
OperationDependency
opid2
=
SSOperations
.
get
(
j
+
1
);
Entry
entry1
=
chromosome
.
getAllOperations
().
stream
()
.
filter
(
t
->
t
.
getId
()==
opid2
.
getPrevOperationId
())
.
findFirst
().
orElse
(
null
);
if
(
entry
.
getRoutingDetailId
()!=
entry1
.
getRoutingDetailId
())
// Entry entry1= chromosome.getAllOperations().stream()
// .filter(t->t.getId()==opid2.getPrevOperationId())
// .findFirst().orElse(null);
Entry
entry1
=
entryIndexById
.
get
(
opid2
.
getPrevOperationId
());
//不是同一前工序,效率不能合并 newScheduleResult 清空,如何是一个工序就合并计算
if
(
entry
!=
null
&&
entry1
!=
null
&&
entry
.
getRoutingDetailId
()!=
entry1
.
getRoutingDetailId
())
{
int
prevtime1
=
CalSSPrevtime
(
newScheduleResult
,
newScheduleResultDetails
,
prevtime
,
currentOp
,
chromosome
,
processTime
,
machine
);
int
prevtime1
=
CalSSPrevtime
(
newScheduleResult
,
newScheduleResultDetails
,
prevtime
,
currentOp
,
chromosome
,
processTime
,
machine
);
prevtime
=
Math
.
max
(
prevtime
,
prevtime1
);
newScheduleResult
.
clear
();
...
...
@@ -1525,13 +1414,13 @@ return actualEndTime;
if
(
opboms
!=
null
&&
!
opboms
.
isEmpty
())
{
// 计算RawTime
Optional
<
LocalDateTime
>
rawDateOpt
=
opboms
.
stream
()
.
filter
(
t
->
t
.
getMaterialTypeName
().
equals
(
"MP"
))
.
map
(
OrderMaterialRequirement:
:
getUseTime
)
.
max
(
LocalDateTime:
:
compareTo
);
if
(
rawDateOpt
.
isPresent
())
{
rawTime
=
(
int
)
Duration
.
between
(
baseTime
,
rawDateOpt
.
get
()).
getSeconds
();
}
Optional
<
LocalDateTime
>
rawDateOpt
=
opboms
.
stream
()
.
filter
(
t
->
t
.
getMaterialTypeName
().
equals
(
"MP"
))
.
map
(
OrderMaterialRequirement:
:
getUseTime
)
.
max
(
LocalDateTime:
:
compareTo
);
if
(
rawDateOpt
.
isPresent
())
{
rawTime
=
(
int
)
Duration
.
between
(
baseTime
,
rawDateOpt
.
get
()).
getSeconds
();
}
...
...
@@ -1577,7 +1466,7 @@ return actualEndTime;
return
Math
.
max
(
rawTime
,
sfTime
);
}
private
int
EditOperationBOMTime
(
Entry
currentOp
,
Chromosome
chromosome
,
int
earliestStartTime
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
)
{
private
int
EditOperationBOMTime
(
Entry
currentOp
,
Chromosome
chromosome
,
int
earliestStartTime
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
,
Map
<
Integer
,
Entry
>
entryIndexById
,
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
)
{
List
<
OrderMaterialRequirement
>
opboms
=
currentOp
.
getMaterialRequirements
();
...
...
@@ -1585,13 +1474,13 @@ return actualEndTime;
{
return
0
;
}
LocalDateTime
earliestStartTime1
=
baseTime
.
plusSeconds
(
earliestStartTime
);
materialRequirementService
.
EditOperationBOM
(
currentOp
,
chromosome
,
earliestStartTime1
,
this
,
machineTasksCache
);
return
getOperationBOMTime
(
currentOp
,
chromosome
);
LocalDateTime
earliestStartTime1
=
baseTime
.
plusSeconds
(
earliestStartTime
);
materialRequirementService
.
EditOperationBOM
(
currentOp
,
chromosome
,
earliestStartTime1
,
this
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
,
baseTime
);
return
getOperationBOMTime
(
currentOp
,
chromosome
);
}
public
void
EditorderOperation
(
Chromosome
chromosome
,
int
groupId
,
double
needed
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
){
public
void
EditorderOperation
(
Chromosome
chromosome
,
int
groupId
,
double
needed
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
,
Map
<
Integer
,
Entry
>
entryIndexById
,
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
){
List
<
Entry
>
orderOps
=
chromosome
.
getAllOperations
().
stream
()
.
filter
(
t
->
t
.
getGroupId
()
==
groupId
)
.
sorted
(
Comparator
.
comparing
(
Entry:
:
getSequence
))
...
...
@@ -1635,7 +1524,7 @@ return getOperationBOMTime(currentOp, chromosome);
int
teardownTime
=
currentOp
.
getTeardownTime
();
if
(!
currentOp
.
getPrevEntryIds
().
isEmpty
())
{
// 处理多个前工序
prevtime
=
CalPrevtime
(
prevtime
,
currentOp
,
chromosome
,
processTime
,
targetMachine
);
prevtime
=
CalPrevtime
(
prevtime
,
currentOp
,
chromosome
,
processTime
,
targetMachine
,
entryIndexById
,
scheduleIndexById
);
}
// 上个离散参数
...
...
@@ -1650,7 +1539,7 @@ return getOperationBOMTime(currentOp, chromosome);
.
findFirst
()
.
orElse
(
null
);
// 缓存机器任务
int
actualEndTime
=
processWithSingleMachine
(
currentOp
,
machine
,
processTime
,
prevtime
,
opMachine
,
chromosome
,
true
,
prevendtime
,
machineTasksCache
);
int
actualEndTime
=
processWithSingleMachine
(
currentOp
,
machine
,
processTime
,
prevtime
,
opMachine
,
chromosome
,
true
,
prevendtime
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
);
}
...
...
@@ -1685,12 +1574,12 @@ return getOperationBOMTime(currentOp, chromosome);
List
<
OrderMaterialRequirement
>
MaterialRequirements
=
currentOp
.
getMaterialRequirements
().
stream
()
.
filter
(
t
->!
"MP"
.
equals
(
t
.
getMaterialTypeName
())
&&
t
.
getProductOrderID
()
!=
null
&&
!
t
.
getProductOrderID
().
isEmpty
()
)
)
.
collect
(
Collectors
.
toList
());
if
(
MaterialRequirements
==
null
||
MaterialRequirements
.
size
()==
0
)
{
continue
;
}
if
(
MaterialRequirements
==
null
||
MaterialRequirements
.
size
()==
0
)
{
continue
;
}
for
(
OrderMaterialRequirement
orderMaterial:
MaterialRequirements
)
{
List
<
Integer
>
orderids
=
orderMaterial
.
getProductOrderID
();
if
(
orderids
!=
null
&&
orderids
.
size
()>
0
)
{
...
...
@@ -1730,7 +1619,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
}
List
<
OrderMaterialRequirement
>
orderMaterialRequirements
=
entry
.
getMaterialRequirements
().
stream
().
filter
(
t
->
!
"MP"
.
equals
(
t
.
getMaterialTypeName
())
&&
t
.
getProductOrderID
()
!=
null
&&
!
t
.
getProductOrderID
().
isEmpty
()
).
collect
(
Collectors
.
toList
());
).
collect
(
Collectors
.
toList
());
for
(
OrderMaterialRequirement
mr:
orderMaterialRequirements
)
{
List
<
Integer
>
orderids
=
mr
.
getProductOrderID
();
if
(
orderids
!=
null
&&
orderids
.
size
()>
0
)
{
...
...
@@ -1794,7 +1683,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
* @return 可开工时间
*/
private
int
calculateNextOperationStartTime
(
List
<
GAScheduleResult
>
results
,
List
<
ScheduleResultDetail
>
details
,
int
startindex
,
double
time2
)
{
double
qty
=
results
.
stream
().
mapToDouble
(
GAScheduleResult:
:
getQuantity
)
// 替换为实际字段名
double
qty
=
results
.
stream
().
mapToDouble
(
GAScheduleResult:
:
getQuantity
)
// 替换为实际字段名
.
sum
();
double
time1
=
0.0
;
...
...
@@ -1816,7 +1705,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
}
if
(
results
.
size
()>
1
)
{
//多前置工序
calculateWithMoreMachine
(
details
,
leadCount
);
}
}
// 单设备时使用原逻辑
return
(
int
)
calculateWithSingleMachine
(
details
,
leadCount
,
time1
);
}
...
...
@@ -1873,10 +1762,10 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
//
// int minEndTimeForContinuity = prevEndTime - (int) ((qty - leadCount) * prevTimePerUnit);
// int adjustedStartTime = Math.max(productionTimeForLeadCount, minEndTimeForContinuity);
// int adjustedStartTime = Math.max(productionTimeForLeadCount, prevtime);
// int adjustedStartTime = Math.max(productionTimeForLeadCount, minEndTimeForContinuity);
// int adjustedStartTime = Math.max(productionTimeForLeadCount, prevtime);
// int totalProcessingTime = (int) (currentTimePerUnit * qty);
// int totalProcessingTime = (int) (currentTimePerUnit * qty);
// int continuityAdjustedTime = ensureContinuousProduction(machine, adjustedStartTime,
// totalProcessingTime, currentOp);
...
...
@@ -1960,7 +1849,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
}
}
alldetails
.
stream
().
sorted
(
Comparator
.
comparingInt
(
ScheduleResultDetail:
:
getStartTime
));
int
EndTime
=
0
;
int
EndTime
=
0
;
double
accumulatedQty
=
0.0
;
for
(
ScheduleResultDetail
detail
:
alldetails
)
{
...
...
@@ -1989,7 +1878,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
return
EndTime
;
}
/**
/**
* 多设备并行时计算满足提前量的最早时间
*/
private
int
calculateWithParallelMachines
(
List
<
ScheduleResultDetail
>
details
,
int
leadCount
,
int
time1
)
{
...
...
@@ -2208,12 +2097,12 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
}
//01 16:00 +20 -01 16:00 02 12:00 08:00 -18:00 01 16:18 02 08:00-12:00
//01 16:00 +20 -01 16:00 02 12:00 08:00 -18:00 01 16:18 02 08:00-12:00
//01 16:00 +10 -01 16:00 换型10:00 08:00
//01 18:00 +10 -02 08:00<0 换型 休息时间满足
//01 18:00 +20 -02 08:00>0
//01 18:00 +10 -02 00:00>0
return
reslte
;
return
reslte
;
}
else
{
//开始时间加上设置时间重新算
//如果是前提供任务是相同的则跳出
...
...
@@ -2252,7 +2141,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
{
return
reslte
;
}
// LocalDateTime startTime = baseTime.plus(earliestStartTime, ChronoUnit.SECONDS);
// LocalDateTime startTime = baseTime.plus(earliestStartTime, ChronoUnit.SECONDS);
GAScheduleResult
lastGeneOnMachine
=
machineTasks
.
get
(
machineTasks
.
size
()-
1
);
...
...
@@ -2266,7 +2155,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
if
(
AvailableTimeSegment
!=
null
)
{
reslte
.
put
(
6
,
AvailableTimeSegment
);
int
start
=
(
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
AvailableTimeSegment
.
get
(
0
).
getStart
());
int
start
=
(
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
AvailableTimeSegment
.
get
(
0
).
getStart
());
earliestStartTime
=
earliestStartTime
>
start
?
earliestStartTime:
start
;
int
earliestStartTime1
=
earliestStartTime
;
...
...
@@ -2307,14 +2196,14 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
}
Entry
prev
=
_allOperations
.
stream
().
Entry
prev
=
_allOperations
.
stream
().
filter
(
t
->
t
.
getExecId
().
equals
(
ExecId
))
.
findFirst
().
orElse
(
null
);
int
setupTime
=
0
;
if
(
prev
!=
null
)
{
//离散参数
// prev.getDiscreteParameter()
// prev.getDiscreteParameter()
// setupTime = (prev.getProductId() != operation.getProductId())
// ? (int) discreteParameterMatrixService.getDiscreteParameterMatrixValue(prev, operation)
...
...
@@ -2336,7 +2225,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
}
// setupTime=20*3600;
// setupTime=20*3600;
operation
.
setChangeLineTime
(
setupTime
);
if
(
setupTime
==
0
)
{
...
...
@@ -2355,20 +2244,20 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
{
cha
=
cha
+
1
;
//加1是工序开始加工时间
reslte
.
put
(
2
,
lastGeneOnMachine
.
getEndTime
());
//换型开始时间
// reslte = calculateSetupTime(machineTasks, operation, machine,earliestStartTime+cha,processingTimeTotal, _globalParam.is_smoothChangeOverInWeek(), ExecId,reslte);
// reslte = calculateSetupTime(machineTasks, operation, machine,earliestStartTime+cha,processingTimeTotal, _globalParam.is_smoothChangeOverInWeek(), ExecId,reslte);
}
else
{
reslte
.
put
(
2
,
earliestStartTime
-
setupTime
);
//换型开始时间
//如果空余时间足够
//可能会往前或后暂用设备时间
return
reslte
;
return
reslte
;
}
}
else
{
//开始时间加上设置时间重新算
//如果是前提供任务是相同的则跳出
// reslte = calculateSetupTime(machineTasks, operation, machine,earliestStartTime,processingTimeTotal+setupTime, _globalParam.is_smoothChangeOverInWeek(),ExecId,reslte);
// reslte = calculateSetupTime(machineTasks, operation, machine,earliestStartTime,processingTimeTotal+setupTime, _globalParam.is_smoothChangeOverInWeek(),ExecId,reslte);
}
...
...
@@ -2443,7 +2332,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
.
filter
(
t
->
orderIds
.
contains
(
t
.
getOrderId
()))
.
max
(
Comparator
.
comparing
(
Order:
:
getDueDate
))
.
orElse
(
null
);
if
(
order
.
isNewCreate
())
{
if
(
order
.
isNew
Sf
Create
())
{
continue
;
}
LocalDateTime
dueDateTime
=
order
.
getDueDate
();
...
...
@@ -2549,13 +2438,13 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
return
chromosome
.
getGeneStr
();
// 拼接机器选择:用 "," 分隔(例:1,3,2,4)
// String machineStr = chromosome.getMachineStr();
// String machineStr = chromosome.getMachineStr();
// 拼接工序排序:用 "|" 分隔(例:2|1|3|4)
// String operationStr = chromosome.getOperationStr();
// String operationStr = chromosome.getOperationStr();
// 组合最终键(用 "_" 分隔两部分,避免冲突)
// return machineStr + "_" + operationStr;
// return machineStr + "_" + operationStr;
}
}
src/main/java/com/aps/service/Algorithm/GeneticOperations.java
View file @
f2a1529b
...
...
@@ -25,6 +25,10 @@ public class GeneticOperations {
private
static
ScheduleParams
param
;
public
GeneticOperations
()
{
}
public
GeneticOperations
(
GlobalParam
globalParam
,
List
<
Entry
>
_allOperations
,
ScheduleParams
_param
)
{
_GlobalParam
=
globalParam
;
allOperations
=
_allOperations
;
...
...
@@ -424,10 +428,12 @@ public class GeneticOperations {
public
void
DelOrder
(
Chromosome
chromosome
)
{
List
<
Entry
>
allOperations
=
chromosome
.
getAllOperations
();
List
<
GlobalOperationInfo
>
globalOpList
=
chromosome
.
getGlobalOpList
();
if
(
chromosome
.
getOrders
()==
null
||
chromosome
.
getOrders
().
size
()==
0
)
return
;
List
<
Order
>
orders
=
chromosome
.
getOrders
();
List
<
Integer
>
OperationSequencing
=
chromosome
.
getOperationSequencing
();
List
<
Integer
>
newoorderids
=
orders
.
stream
()
.
filter
(
t
->
t
.
isNewCreate
())
.
filter
(
t
->
t
.
isNew
Sf
Create
())
.
map
(
Order:
:
getId
)
.
sorted
(
Comparator
.
reverseOrder
())
.
collect
(
Collectors
.
toList
());
...
...
src/main/java/com/aps/service/Algorithm/HillClimbing.java
View file @
f2a1529b
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.common.util.FileHelper
;
import
com.aps.common.util.GlobalCacheUtil
;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.entity.Algorithm.*
;
import
com.aps.entity.Algorithm.IDAndChildID.GroupResult
;
...
...
@@ -21,6 +22,11 @@ public class HillClimbing {
private
List
<
Entry
>
allOperations
;
private
List
<
Order
>
orders
;
private
List
<
Material
>
materials
;
private
List
<
GroupResult
>
_entryRel
;
//按优先级分组工序
private
Map
<
Double
,
List
<
Entry
>>
priorityGroups
;
...
...
@@ -30,10 +36,17 @@ public class HillClimbing {
// 从List转为Map op.getGroupId() + "_" + op.getSequence(); 做主键
private
Map
<
String
,
Entry
>
entrys
;
public
HillClimbing
(
List
<
Entry
>
allOperations
)
{
private
FitnessCalculator
fitnessCalculator
;
public
HillClimbing
(
List
<
Entry
>
allOperations
,
List
<
Order
>
orders
,
List
<
Material
>
materials
,
List
<
GroupResult
>
entryRel
,
FitnessCalculator
_fitnessCalculator
)
{
this
.
allOperations
=
allOperations
;
this
.
orders
=
orders
;
this
.
materials
=
materials
;
_entryRel
=
entryRel
;
fitnessCalculator
=
_fitnessCalculator
;
// 按优先级分组工序
priorityGroups
=
groupOperationsByPriority
();
...
...
@@ -92,7 +105,7 @@ public class HillClimbing {
Chromosome
machineChange
=
generateMachineChange
(
current
,
op
.
getMachineOptions
(),
maPos
);
if
(
machineChange
!=
null
)
{
decode
(
decoder
,
machineChange
);
decode
(
decoder
,
machineChange
,
machines
);
if
(
isBetter
(
machineChange
,
current
))
{
current
=
machineChange
;
if
(
isBetter
(
current
,
best
))
{
...
...
@@ -263,7 +276,7 @@ public class HillClimbing {
Chromosome
machineChange
=
generateMachineChange
(
current
,
op
.
getMachineOptions
(),
maPos
);
if
(
machineChange
!=
null
)
{
decode
(
decoder
,
machineChange
);
decode
(
decoder
,
machineChange
,
machines
);
if
(
isBetter
(
machineChange
,
current
))
{
current
=
machineChange
;
if
(
isBetter
(
current
,
best
))
{
...
...
@@ -328,7 +341,7 @@ public class HillClimbing {
}
Chromosome
newChromosome
=
swapAtDistance
(
current
,
opPos
,
-
s
*
step
);
decode
(
decoder
,
newChromosome
);
decode
(
decoder
,
newChromosome
,
machines
);
if
(
isBetter
(
newChromosome
,
current
))
{
current
=
newChromosome
;
...
...
@@ -357,7 +370,7 @@ public class HillClimbing {
}
Chromosome
newChromosome
=
swapAtDistance
(
current
,
opPos
,
s
*
step
);
decode
(
decoder
,
newChromosome
);
decode
(
decoder
,
newChromosome
,
machines
);
if
(
isBetter
(
newChromosome
,
current
))
{
current
=
newChromosome
;
...
...
@@ -411,21 +424,24 @@ public class HillClimbing {
}
/**
* 构建位置索引:groupId_sequence -> position
*/
private
Map
<
String
,
Integer
>
buildPositionIndex
(
Chromosome
chromosome
)
{
String
fitness
=
""
;
private
void
writeKpi
(
Chromosome
chromosome
)
{
String
fitness
=
""
;
double
[]
fitness1
=
chromosome
.
getFitnessLevel
();
for
(
int
i
=
0
;
i
<
fitness1
.
length
;
i
++)
{
fitness
+=
fitness1
[
i
]+
","
;
fitness
+=
fitness1
[
i
]
+
","
;
}
FileHelper
.
writeLogFile
(
String
.
format
(
"爬山法 - kpi:%s"
,
fitness
));
}
/**
* 构建位置索引:groupId_sequence -> position
*/
private
Map
<
String
,
Integer
>
buildPositionIndex
(
Chromosome
chromosome
)
{
writeKpi
(
chromosome
);
Map
<
String
,
Integer
>
index
=
new
HashMap
<>();
List
<
Integer
>
os
=
chromosome
.
getOperationSequencing
();
...
...
@@ -546,114 +562,6 @@ public class HillClimbing {
}
return
neighbor
;
}
/**
* 生成邻域解
*/
private
List
<
Chromosome
>
generateNeighbors
(
Chromosome
chromosome
)
{
List
<
Chromosome
>
neighbors
=
new
ArrayList
<>();
// 生成交换邻域
neighbors
.
add
(
generateSwapNeighbor
(
chromosome
));
// 生成反转邻域
neighbors
.
add
(
generateReverseNeighbor
(
chromosome
));
// 生成插入邻域
neighbors
.
add
(
generateInsertNeighbor
(
chromosome
));
// 生成机器选择邻域
neighbors
.
add
(
generateMachineChangeNeighbor
(
chromosome
));
return
neighbors
;
}
/**
* 生成交换邻域解
*/
private
Chromosome
generateSwapNeighbor
(
Chromosome
chromosome
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
os
.
size
()
>=
2
)
{
int
idx1
=
rnd
.
nextInt
(
os
.
size
());
int
idx2
=
rnd
.
nextInt
(
os
.
size
());
while
(
idx2
==
idx1
)
{
idx2
=
rnd
.
nextInt
(
os
.
size
());
}
java
.
util
.
Collections
.
swap
(
os
,
idx1
,
idx2
);
neighbor
.
setOperationSequencing
(
os
);
}
return
neighbor
;
}
/**
* 生成反转邻域解
*/
private
Chromosome
generateReverseNeighbor
(
Chromosome
chromosome
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
os
.
size
()
>=
2
)
{
int
start
=
rnd
.
nextInt
(
os
.
size
());
int
end
=
rnd
.
nextInt
(
os
.
size
());
while
(
end
<=
start
)
{
end
=
rnd
.
nextInt
(
os
.
size
());
}
java
.
util
.
Collections
.
reverse
(
os
.
subList
(
start
,
end
+
1
));
neighbor
.
setOperationSequencing
(
os
);
}
return
neighbor
;
}
/**
* 生成插入邻域解
*/
private
Chromosome
generateInsertNeighbor
(
Chromosome
chromosome
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
os
.
size
()
>=
2
)
{
int
idx1
=
rnd
.
nextInt
(
os
.
size
());
int
idx2
=
rnd
.
nextInt
(
os
.
size
());
while
(
idx2
==
idx1
)
{
idx2
=
rnd
.
nextInt
(
os
.
size
());
}
int
value
=
os
.
remove
(
idx1
);
os
.
add
(
idx2
,
value
);
neighbor
.
setOperationSequencing
(
os
);
}
return
neighbor
;
}
/**
* 生成机器选择邻域解
*/
private
Chromosome
generateMachineChangeNeighbor
(
Chromosome
chromosome
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
ms
=
neighbor
.
getMachineSelection
();
List
<
GlobalOperationInfo
>
globalOpList
=
chromosome
.
getGlobalOpList
();
if
(!
ms
.
isEmpty
())
{
int
idx
=
rnd
.
nextInt
(
ms
.
size
());
GlobalOperationInfo
globalOp
=
globalOpList
.
get
(
idx
);
Entry
op
=
globalOp
.
getOp
();
if
(
op
.
getMachineOptions
().
size
()
>
1
)
{
int
currentMachineSeq
=
ms
.
get
(
idx
);
List
<
Integer
>
availableMachines
=
new
ArrayList
<>();
for
(
int
i
=
1
;
i
<=
op
.
getMachineOptions
().
size
();
i
++)
{
if
(
i
!=
currentMachineSeq
)
{
availableMachines
.
add
(
i
);
}
}
if
(!
availableMachines
.
isEmpty
())
{
int
newMachineSeq
=
availableMachines
.
get
(
rnd
.
nextInt
(
availableMachines
.
size
()));
ms
.
set
(
idx
,
newMachineSeq
);
neighbor
.
setMachineSelection
(
ms
);
}
}
}
return
neighbor
;
}
/**
* 生成机器选择邻域解
*/
...
...
@@ -703,12 +611,35 @@ public class HillClimbing {
/**
* 解码染色体
*/
private
void
decode
(
GeneticDecoder
decoder
,
Chromosome
chromosome
)
{
// chromosome.setResult(new java.util.concurrent.CopyOnWriteArrayList<>());
decoder
.
decodeChromosomeWithCache
(
chromosome
);
private
void
decode
(
GeneticDecoder
decoder
,
Chromosome
chromosome
,
List
<
Machine
>
machines
)
{
chromosome
.
setResult
(
new
CopyOnWriteArrayList
<>());
// 假设Machine类有拷贝方法,或使用MapStruct等工具进行映射
chromosome
.
setMachines
(
ProductionDeepCopyUtil
.
deepCopyList
(
machines
,
Machine
.
class
));
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setOrders
(
ProductionDeepCopyUtil
.
deepCopyList
(
new
CopyOnWriteArrayList
<>(
orders
),
Order
.
class
)
);
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setOperatRel
(
ProductionDeepCopyUtil
.
deepCopyList
(
new
CopyOnWriteArrayList
<>(
_entryRel
),
GroupResult
.
class
)
);
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setMaterials
(
ProductionDeepCopyUtil
.
deepCopyList
(
materials
,
Material
.
class
));
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setAllOperations
(
ProductionDeepCopyUtil
.
deepCopyList
(
new
CopyOnWriteArrayList
<>(
allOperations
),
Entry
.
class
)
);
// 简单拷贝,实际可能需要深拷贝
//chromosome.setObjectiveWeights(_objectiveWeights);
// chromosome.setBaseTime(param.getBaseTime());
// chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝
// _sceneService.saveChromosomeToFile(chromosome, "12345679");
// 加载锁定工单到ResultOld
List
<
GAScheduleResult
>
lockedOrders
=
GlobalCacheUtil
.
get
(
"locked_orders_"
+
chromosome
.
getScenarioID
());
if
(
lockedOrders
!=
null
&&
!
lockedOrders
.
isEmpty
())
{
chromosome
.
setResultOld
(
ProductionDeepCopyUtil
.
deepCopyList
(
lockedOrders
,
GAScheduleResult
.
class
));
FileHelper
.
writeLogFile
(
"将 "
+
lockedOrders
.
size
()
+
" 个锁定工单加载到初始种群中"
);
}
else
{
chromosome
.
setResultOld
(
new
CopyOnWriteArrayList
<>());
}
decoder
.
decodeChromosomeWithCache
(
chromosome
,
false
);
}
/**
* 比较两个染色体的优劣
*/
...
...
src/main/java/com/aps/service/Algorithm/HybridAlgorithm.java
View file @
f2a1529b
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.common.util.DateTimeUtil
;
import
com.aps.common.util.DeepCopyUtil
;
import
com.aps.common.util.FileHelper
;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.entity.Algorithm.*
;
import
com.aps.common.util.*
;
import
com.aps.entity.Algorithm.*
;
import
com.aps.entity.Algorithm.IDAndChildID.GroupResult
;
import
com.aps.entity.basic.*
;
import
com.aps.service.plan.MachineSchedulerService
;
...
...
@@ -55,11 +52,11 @@ public class HybridAlgorithm {
// 初始化算法实例
private
HillClimbing
_hillClimbing
;
private
SimulatedAnnealing
_simulatedAnnealing
;
private
ParallelLocalSearch
_parallelLocalSearch
;
// 初始化算法实例
private
TabuSearch
_tabuSearch
;
private
TabuSearchWithSA
_tabuSearchWithSA
;
public
HybridAlgorithm
(
GlobalParam
globalParam
,
List
<
Machine
>
machines
,
List
<
Order
>
orders
,
...
...
@@ -109,18 +106,16 @@ int opcount=allOperations.size();
// 预生成全局工序列表(所有初始化方法共享同一顺序)
List
<
GlobalOperationInfo
>
globalOpList
=
initialization
.
generateGlobalOpList
();
// 初始化变邻域搜索
_vns
=
new
VariableNeighborhoodSearch
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
_hillClimbing
=
new
HillClimbing
(
allOperations
);
_simulatedAnnealing
=
new
SimulatedAnnealing
(
allOperations
);
_parallelLocalSearch
=
new
ParallelLocalSearch
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
_tabuSearch
=
new
TabuSearch
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
_tabuSearchWithSA
=
new
TabuSearchWithSA
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
_vns
=
new
VariableNeighborhoodSearch
(
allOperations
,
orders
,
materials
,
_entryRel
,
_fitnessCalculator
);
_hillClimbing
=
new
HillClimbing
(
allOperations
,
orders
,
materials
,
_entryRel
,
_fitnessCalculator
);
_simulatedAnnealing
=
new
SimulatedAnnealing
(
allOperations
,
orders
,
materials
,
_entryRel
,
_fitnessCalculator
);
_tabuSearch
=
new
TabuSearch
(
allOperations
,
orders
,
materials
,
_entryRel
,
_fitnessCalculator
);
FileHelper
.
writeLogFile
(
"初始化种群-----------开始-------"
);
// 步骤1:使用构造启发式算法生成初始种群
FileHelper
.
writeLogFile
(
"构造启发式初始化-----------开始-------"
);
List
<
Chromosome
>
population
=
initialization
.
generateHeuristicInitialPopulation
(
param
,
globalOpList
);
List
<
Chromosome
>
population
=
initialization
.
generateHeuristicInitialPopulation
(
param
);
FileHelper
.
writeLogFile
(
"构造启发式初始化-----------结束-------"
);
...
...
@@ -138,15 +133,15 @@ int opcount=allOperations.size();
FileHelper
.
writeLogFile
(
"按Objectives去重-----------开始-------"
+
population
.
size
());
population
=
chromosomeDistinctByObjectives
(
population
);
FileHelper
.
writeLogFile
(
"按Objectives去重-----------结束-------"
+
population
.
size
());
// if(1==1)
// return getBestChromosome(population.get(0), param.getBaseTime(), starttime);
// 步骤2:对初始种群进行爬山法局部优化
if
(
opcount
<
20
)
{
FileHelper
.
writeLogFile
(
"爬山法局部优化-----------开始-------"
);
GeneticDecoder
hillClimbingDecoder
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
Chromosome
optimized
=
_hillClimbing
.
BatchSearchAll
(
population
,
machines
,
hillClimbingDecoder
);
Chromosome
optimized
=
_hillClimbing
.
search
(
population
.
get
(
0
),
hillClimbingDecoder
,
machines
);
FileHelper
.
writeLogFile
(
"爬山法局部优化-----------结束-------"
);
return
getBestChromosome
(
optimized
,
param
.
getBaseTime
(),
starttime
);
}
...
...
@@ -156,27 +151,37 @@ int opcount=allOperations.size();
// 步骤2:对初始种群进行模拟退火+爬山法优化
GeneticDecoder
saDecoder1
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
GeneticDecoder
vnsDecoder1
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
GeneticDecoder
tabuDecoder1
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
if
(
opcount
<
800
)
{
FileHelper
.
writeLogFile
(
"模拟退火+爬山法优化-----------开始-------"
);
Chromosome
saHcOptimized
=
_simulatedAnnealing
.
batchSearchGetMax
(
population
,
saDecoder1
,
machines
);
Chromosome
saHcOptimized
=
_simulatedAnnealing
.
searchWithHillClimbing
(
population
.
get
(
0
),
_vns
,
saDecoder1
,
machines
);
FileHelper
.
writeLogFile
(
"模拟退火+爬山法优化-----------结束-------"
);
return
getBestChromosome
(
saHcOptimized
,
param
.
getBaseTime
(),
starttime
);
}
if
(
opcount
>=
800
)
{
Chromosome
best
=
population
.
get
(
0
);
best
=
_simulatedAnnealing
.
search
(
best
,
_tabuSearch
,
_vns
,
saDecoder1
,
machines
);
best
=
_vns
.
search
(
best
,
vnsDecoder1
,
machines
);
best
=
_tabuSearch
.
search
(
best
,
_vns
,
tabuDecoder1
,
machines
);
return
getBestChromosome
(
best
,
param
.
getBaseTime
(),
starttime
);
}
List
<
List
<
Chromosome
>>
combinedFronts
=
_nsgaIIUtils
.
parallelFastNonDominatedSort
(
population
);
Chromosome
best
=
ProductionDeepCopyUtil
.
deepCopy
(
population
.
get
(
0
),
Chromosome
.
class
);
// GetBest(combinedFronts,"初始");
int
ordercount
=
globalOpList
.
stream
()
.
mapToInt
(
GlobalOperationInfo:
:
getGroupId
)
.
max
()
.
orElse
(
0
);
Chromosome
best
=
GetBest
(
combinedFronts
,
"初始"
);
// best=fronts.get(0).stream()
// .max(Comparator.comparingDouble(Chromosome::getFitness))
// .orElse(null);
double
bestFitness
=
best
.
getFitness
();
if
(
population
.
size
()<
param
.
getTournamentSize
())
{
...
...
@@ -185,7 +190,8 @@ int opcount=allOperations.size();
}
int
Iteration
=
0
;
int
noImproveCount
=
0
;
int
maxNoImprove
=
10
;
// 步骤2:迭代进化
FileHelper
.
writeLogFile
(
"迭代进化-----------开始-------"
+
param
.
getMaxIterations
());
for
(
int
iter
=
0
;
iter
<
param
.
getMaxIterations
();
iter
++)
{
...
...
@@ -193,6 +199,7 @@ int opcount=allOperations.size();
FileHelper
.
writeLogFile
(
"迭代进化------"
+
iter
+
"-----开始-------"
);
// 计算种群适应度标准差,微调参数
double
fitnessStd
=
_fitnessCalculator
.
calculateFitnessStd
(
population
);
param
.
fineTuneParams
(
iter
,
fitnessStd
);
...
...
@@ -204,141 +211,62 @@ int opcount=allOperations.size();
}
FileHelper
.
writeLogFile
(
"选择操作-----------开始-------"
);
// 选择前移除适应度为 0 或明显劣于当前最优解的个体,减少选择池规模:
double
minValidFitness
=
bestFitness
*
0.5
;
// 保留最优解50%以上的个体
List
<
Chromosome
>
validPopulation
=
population
.
stream
()
.
filter
(
c
->
c
.
getFitness
()
>=
minValidFitness
)
.
collect
(
Collectors
.
toList
());
// 选择操作
List
<
Chromosome
>
selected
=
geneticOps
.
tournamentSelection
(
validP
opulation
);
List
<
Chromosome
>
selected
=
geneticOps
.
tournamentSelection
(
p
opulation
);
FileHelper
.
writeLogFile
(
"选择操作-----------结束-------"
);
// 变邻域搜索
FileHelper
.
writeLogFile
(
"变邻域搜索-----------开始-------"
);
GeneticDecoder
vnsDecoder
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
List
<
Chromosome
>
vnsImproved
=
_vns
.
search
(
selected
,
vnsDecoder
,
param
);
selected
.
addAll
(
vnsImproved
);
FileHelper
.
writeLogFile
(
"变邻域搜索-----------结束-------"
);
// 模拟退火全局搜索
FileHelper
.
writeLogFile
(
"模拟退火搜索-----------开始-------"
);
GeneticDecoder
saDecoder
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
List
<
Chromosome
>
saImproved
=
new
ArrayList
<>();
for
(
Chromosome
chromosome
:
selected
)
{
// Chromosome saOptimized = _simulatedAnnealing.search(chromosome, saDecoder, param);
// saImproved.add(saOptimized);
}
selected
.
addAll
(
saImproved
);
FileHelper
.
writeLogFile
(
"模拟退火搜索-----------结束-------"
);
// 多种局部搜索算法并行
FileHelper
.
writeLogFile
(
"并行局部搜索-----------开始-------"
);
GeneticDecoder
parallelDecoder
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
List
<
Chromosome
>
parallelImproved
=
new
ArrayList
<>();
for
(
Chromosome
chromosome
:
selected
)
{
Chromosome
parallelOptimized
=
_parallelLocalSearch
.
search
(
chromosome
,
parallelDecoder
,
param
);
parallelImproved
.
add
(
parallelOptimized
);
}
selected
.
addAll
(
parallelImproved
);
FileHelper
.
writeLogFile
(
"并行局部搜索-----------结束-------"
);
// 禁忌搜索+模拟退火
FileHelper
.
writeLogFile
(
"禁忌搜索+模拟退火-----------开始-------"
);
GeneticDecoder
tsDecoder
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
List
<
Chromosome
>
tsImproved
=
new
ArrayList
<>();
for
(
Chromosome
chromosome
:
selected
)
{
Chromosome
tsOptimized
=
_tabuSearchWithSA
.
search
(
chromosome
,
tsDecoder
,
param
);
tsImproved
.
add
(
tsOptimized
);
}
selected
.
addAll
(
tsImproved
);
FileHelper
.
writeLogFile
(
"禁忌搜索+模拟退火-----------结束-------"
);
// 交叉操作
FileHelper
.
writeLogFile
(
"交叉操作-----------开始-------"
);
List
<
Chromosome
>
nextPopulation
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
selected
.
size
();
i
+=
2
)
{
if
(
i
+
1
>=
selected
.
size
())
{
selected
.
get
(
i
).
setID
(
UUID
.
randomUUID
().
toString
());
nextPopulation
.
add
(
selected
.
get
(
i
));
break
;
}
Chromosome
parent1
=
selected
.
get
(
i
);
Chromosome
parent2
=
selected
.
get
(
i
+
1
);
if
(
rnd
.
nextDouble
()
<
param
.
getCrossoverProb
())
{
// 假设PoxCrossover返回包含两个子染色体的数组
Pair
<
Chromosome
,
Chromosome
>
children
=
geneticOps
.
poxCrossover
(
parent1
,
parent2
,
ordercount
);
nextPopulation
.
add
(
children
.
getFirst
());
nextPopulation
.
add
(
children
.
getSecond
());
}
else
{
nextPopulation
.
add
(
parent1
);
nextPopulation
.
add
(
parent2
);
}
}
FileHelper
.
writeLogFile
(
"交叉操作-----------结束-------"
);
FileHelper
.
writeLogFile
(
"变异操作-----------开始-------"
);
// 变异操作
List
<
Chromosome
>
nextPopulation1
=
new
ArrayList
<>();
for
(
Chromosome
chromosome
:
nextPopulation
)
{
if
(
rnd
.
nextDouble
()
<
param
.
getMutationProb
())
{
Chromosome
chromosome1
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
chromosome1
.
setID
(
UUID
.
randomUUID
().
toString
());
geneticOps
.
mutate
(
chromosome1
,
globalOpList
);
nextPopulation1
.
add
(
chromosome1
);
}
}
nextPopulation
.
addAll
(
nextPopulation1
);
FileHelper
.
writeLogFile
(
"变异操作-----------结束-------"
);
FileHelper
.
writeLogFile
(
"变异批量解码-----------开始-------"
);
Chromosomedecode
(
param
,
allOperations
,
globalOpList
,
nextPopulation
);
FileHelper
.
writeLogFile
(
"变异批量解码-----------结束-------"
);
// // 精英保留
// List<Chromosome> population1 = population.stream()
// .sorted((c1, c2) -> Double.compare(c2.getFitness(), c1.getFitness()))
// .collect(Collectors.toList()); // 降序排序
//
//
// List<Chromosome> elites = population1.subList(0, param.getElitismCount());
List
<
Chromosome
>
newPopulation
=
new
ArrayList
<>();
//保留一定数量的上一代
List
<
Chromosome
>
populationcopy
=
_nsgaIIUtils
.
selectNextPopulation
(
combinedFronts
,
param
.
getPopulationSize
()/
5
);
newPopulation
.
addAll
(
populationcopy
);
newPopulation
.
addAll
(
nextPopulation
);
newPopulation
=
chromosomeDistinct1
(
newPopulation
);
FileHelper
.
writeLogFile
(
"非支配排序-----------开始-------"
);
// 2.7 非支配排序
combinedFronts
=
_nsgaIIUtils
.
parallelFastNonDominatedSort
(
newPopulation
);
FileHelper
.
writeLogFile
(
"非支配排序-----------结束-------"
);
// 2.8 选择下一代种群
population
=
_nsgaIIUtils
.
selectNextPopulation
(
combinedFronts
,
param
.
getPopulationSize
());
// 更新种群
// population = newPopulation.stream()
// .limit(param.getPopulationSize() )
// .collect(Collectors.toList());
newPopulation
.
add
(
best
);
int
n
=
0
;
while
(
newPopulation
.
size
()
<
param
.
getPopulationSize
())
{
// 选择父代
FileHelper
.
writeLogFile
(
"交叉-----------开始-------"
+
n
);
Chromosome
parent1
=
selected
.
get
(
rnd
.
nextInt
(
selected
.
size
()));
Chromosome
parent2
=
selected
.
get
(
rnd
.
nextInt
(
selected
.
size
()));
// 交叉
Chromosome
child
=
parent1
;
// if (rnd.nextDouble() < param.getCrossoverProb()) {
// // 假设PoxCrossover返回包含两个子染色体的数组
// Pair<Chromosome, Chromosome> children = geneticOps.poxCrossover(parent1, parent2, ordercount);
// child=children.getFirst();
// initDataToChromosome(child,param, allOperations,globalOpList);
// child.setID(UUID.randomUUID().toString());
// }
// // 变异
// if (rnd.nextDouble() < param.getMutationProb()) {
// geneticOps.mutate(child, globalOpList);
// }
// 核心融合链(工业级标准顺序:GA生成子代 → SA跳坑 → VNS扩邻域 → TS精优化)
child
=
_simulatedAnnealing
.
search
(
child
,
_tabuSearch
,
_vns
,
saDecoder1
,
machines
);
child
=
_vns
.
search
(
child
,
vnsDecoder1
,
machines
);
child
=
_tabuSearch
.
search
(
child
,
_vns
,
tabuDecoder1
,
machines
);
newPopulation
.
add
(
child
);
FileHelper
.
writeLogFile
(
"交叉-----------结束-------"
+
n
);
}
population
=
chromosomeDistinctByObjectives
(
newPopulation
);;
best
=
GetBest
(
combinedFronts
,
String
.
valueOf
(
iter
));
if
(
bestFitness
<
best
.
getFitness
())
if
(
_fitnessCalculator
.
isBetter
(
population
.
get
(
0
),
best
))
{
bestFitness
=
best
.
getFitness
();
Iteration
=
1
;
best
=
ProductionDeepCopyUtil
.
deepCopy
(
population
.
get
(
0
),
Chromosome
.
class
);
// GetBest(combinedFronts,"初始");
noImproveCount
=
1
;
}
else
{
Iteration
++;
if
(
Iteration
>
5
)
{
noImproveCount
++;
if
(
noImproveCount
>
5
)
{
// 当连续 5 代无最优解提升时,降低交叉概率(如从 0.8 降至 0.5)、提高变异概率(如从 0.1 升至 0.2)
param
.
fineTuneParams
();
}
}
if
(
Iteration
>
10
)
if
(
noImproveCount
>
maxNoImprove
)
{
break
;
}
...
...
@@ -379,18 +307,7 @@ int opcount=allOperations.size();
return
best
;
}
private
Chromosome
GetBest
(
List
<
List
<
Chromosome
>>
fronts
,
String
msg
)
{
// WriteKpis(fronts,msg);
List
<
Chromosome
>
fChromosomes
=
fronts
.
get
(
0
);
fChromosomes
.
sort
((
c1
,
c2
)
->
{
int
rankCompare
=
Double
.
compare
(
c1
.
getCrowdingDistance
(),
c2
.
getCrowdingDistance
());
return
rankCompare
!=
0
?
rankCompare
:
Double
.
compare
(
c1
.
getFitness
(),
c2
.
getFitness
());
});
Chromosome
best
=
fChromosomes
.
get
(
0
);
// WriteKpi(best,"最大");
return
best
;
}
private
List
<
Chromosome
>
chromosomeDistinct
(
List
<
Chromosome
>
population
)
{
if
(
population
==
null
)
...
...
@@ -413,7 +330,7 @@ int opcount=allOperations.size();
}
/**
* 按Objectives去重
,相同目标值的方案只保留一个(保留fitness最大的)
* 按Objectives去重
*/
private
List
<
Chromosome
>
chromosomeDistinctByObjectives
(
List
<
Chromosome
>
population
)
{
...
...
@@ -440,34 +357,36 @@ int opcount=allOperations.size();
}
}
return
new
ArrayList
<>(
objectivesMap
.
values
());
}
// 按 fitnessLevel 倒序排序(多层次比较)
List
<
Chromosome
>
result
=
new
ArrayList
<>(
objectivesMap
.
values
());
result
.
sort
((
c1
,
c2
)
->
{
if
(
isBetter
(
c1
,
c2
))
{
return
-
1
;
// c1 比 c2 好,c1 应该排在前面
}
else
if
(
isBetter
(
c2
,
c1
))
{
return
1
;
// c2 比 c1 好,c2 应该排在前面
}
else
{
return
0
;
// 两者相等
}
});
private
List
<
Chromosome
>
chromosomeDistinct1
(
List
<
Chromosome
>
population
)
{
if
(
population
==
null
)
{
FileHelper
.
writeLogFile
(
String
.
format
(
"排产-----------方案数量---%d-------"
,
0
));
return
population
;
return
result
;
}
/**
* 比较两个染色体的优劣(基于fitnessLevel多层次比较)
*/
private
boolean
isBetter
(
Chromosome
c1
,
Chromosome
c2
)
{
for
(
int
i
=
0
;
i
<
c1
.
getFitnessLevel
().
length
;
i
++)
{
double
[]
Fitness1
=
c1
.
getFitnessLevel
();
double
[]
Fitness2
=
c2
.
getFitnessLevel
();
if
(
Fitness1
[
i
]
>
Fitness2
[
i
])
{
return
true
;
}
}
return
false
;
}
// List<Chromosome> population1 = population.stream().filter(t->t.getGeneStr()==null).collect(Collectors.toList());
population
=
population
.
stream
()
.
collect
(
Collectors
.
toMap
(
Chromosome:
:
getGeneStr
,
// key:去重的字段(GeneStr)
u
->
u
,
// value:Chromosome对象
(
u1
,
u2
)
->
u1
.
getFitness
()
>
u2
.
getFitness
()
?
u1
:
u2
// 重复时保留第一个元素
))
.
values
()
// 获取去重后的
.
stream
()
.
collect
(
Collectors
.
toList
());
return
population
;
}
private
void
WriteKpis
(
List
<
List
<
Chromosome
>>
fronts
,
String
index
)
{
for
(
int
i
=
0
;
i
<
fronts
.
size
();
i
++)
{
...
...
@@ -496,6 +415,40 @@ int opcount=allOperations.size();
new
ThreadPoolExecutor
.
CallerRunsPolicy
()
// 任务满了主线程执行,不丢失任务
);
private
void
initDataToChromosome
(
Chromosome
chromosome
,
ScheduleParams
param
,
List
<
Entry
>
allOperations
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
if
(
chromosome
==
null
){
System
.
out
.
println
(
"chromosome==null"
);
return
;
}
chromosome
.
setResult
(
new
CopyOnWriteArrayList
<>());
// 假设Machine类有拷贝方法,或使用MapStruct等工具进行映射
chromosome
.
setMachines
(
ProductionDeepCopyUtil
.
deepCopyList
(
machines
,
Machine
.
class
));
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setOrders
(
ProductionDeepCopyUtil
.
deepCopyList
(
new
CopyOnWriteArrayList
<>(
orders
),
Order
.
class
)
);
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setOperatRel
(
ProductionDeepCopyUtil
.
deepCopyList
(
new
CopyOnWriteArrayList
<>(
_entryRel
),
GroupResult
.
class
)
);
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setMaterials
(
ProductionDeepCopyUtil
.
deepCopyList
(
materials
,
Material
.
class
));
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setAllOperations
(
ProductionDeepCopyUtil
.
deepCopyList
(
new
CopyOnWriteArrayList
<>(
allOperations
),
Entry
.
class
)
);
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setGlobalOpList
(
ProductionDeepCopyUtil
.
deepCopyList
(
globalOpList
,
GlobalOperationInfo
.
class
)
);
// 简单拷贝,实际可能需要深拷贝
//chromosome.setObjectiveWeights(_objectiveWeights);
chromosome
.
setBaseTime
(
param
.
getBaseTime
());
// chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝
// _sceneService.saveChromosomeToFile(chromosome, "12345679");
// 加载锁定工单到ResultOld
List
<
GAScheduleResult
>
lockedOrders
=
GlobalCacheUtil
.
get
(
"locked_orders_"
+
sceneId
);
if
(
lockedOrders
!=
null
&&
!
lockedOrders
.
isEmpty
())
{
chromosome
.
setResultOld
(
ProductionDeepCopyUtil
.
deepCopyList
(
lockedOrders
,
GAScheduleResult
.
class
));
FileHelper
.
writeLogFile
(
"将 "
+
lockedOrders
.
size
()
+
" 个锁定工单加载到初始种群中"
);
}
else
{
chromosome
.
setResultOld
(
new
CopyOnWriteArrayList
<>());
}
}
private
void
Chromosomedecode
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
,
List
<
GlobalOperationInfo
>
globalOpList
,
List
<
Chromosome
>
population
)
{
FileHelper
.
writeLogFile
(
"解码---------------"
+
population
.
size
()
);
...
...
@@ -542,7 +495,7 @@ int opcount=allOperations.size();
// chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝
// _sceneService.saveChromosomeToFile(chromosome, "12345679");
decoder
.
decodeChromosomeWithCache
(
chromosome
);
decoder
.
decodeChromosomeWithCache
(
chromosome
,
false
);
// if (chromosome.getFitness() == 0) {
// chromosome.setFitness(_fitnessCalculator.calculateFitness(chromosome, _objectiveWeights));
// }
...
...
src/main/java/com/aps/service/Algorithm/Initialization.java
View file @
f2a1529b
...
...
@@ -343,7 +343,7 @@ chromo.setOrders(new CopyOnWriteArrayList<>(orders));
/**
* 使用构造启发式算法生成初始种群
*/
public
List
<
Chromosome
>
generateHeuristicInitialPopulation
(
ScheduleParams
param
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
public
List
<
Chromosome
>
generateHeuristicInitialPopulation
(
ScheduleParams
param
)
{
List
<
Chromosome
>
population
=
new
ArrayList
<>();
int
populationSize
=
param
.
getPopulationSize
();
this
.
baseTime
=
param
.
getBaseTime
();
...
...
src/main/java/com/aps/service/Algorithm/MaterialRequirementService.java
View file @
f2a1529b
...
...
@@ -102,20 +102,20 @@ public class MaterialRequirementService {
.
collect
(
Collectors
.
toList
());
List
<
RoutingHeader
>
routingHeaders
=
null
;
LambdaQueryWrapper
<
RoutingHeader
>
wrapper
=
new
LambdaQueryWrapper
<>();
wrapper
.
in
(
RoutingHeader:
:
getId
,
routingIds
);
LambdaQueryWrapper
<
RoutingHeader
>
wrapper
=
new
LambdaQueryWrapper
<>();
wrapper
.
in
(
RoutingHeader:
:
getId
,
routingIds
);
// .eq(RoutingHeader::getIsDeleted, 0)
// .eq(RoutingHeader::getApprovalStatus, 1);
routingHeaders
=
routingHeaderMapper
.
selectList
(
wrapper
);
routingHeaders
=
routingHeaderMapper
.
selectList
(
wrapper
);
List
<
Routingsupporting
>
routingsupportings
=
null
;
// 查询并缓存Routingsupporting
LambdaQueryWrapper
<
Routingsupporting
>
routingsupportingwrapper
=
new
LambdaQueryWrapper
<>();
routingsupportingwrapper
.
in
(
Routingsupporting:
:
getRoutingHeaderId
,
routingIds
)
.
eq
(
Routingsupporting:
:
getIsdeleted
,
0
);
routingsupportings
=
routingsupportingMapper
.
selectList
(
routingsupportingwrapper
);
LambdaQueryWrapper
<
Routingsupporting
>
routingsupportingwrapper
=
new
LambdaQueryWrapper
<>();
routingsupportingwrapper
.
in
(
Routingsupporting:
:
getRoutingHeaderId
,
routingIds
)
.
eq
(
Routingsupporting:
:
getIsdeleted
,
0
);
routingsupportings
=
routingsupportingMapper
.
selectList
(
routingsupportingwrapper
);
// 查询并缓存RoutingSupportingReplace
...
...
@@ -126,10 +126,10 @@ public class MaterialRequirementService {
.
distinct
()
.
collect
(
Collectors
.
toList
());
LambdaQueryWrapper
<
RoutingSupportingReplace
>
routingsupportingreplacewrapper
=
new
LambdaQueryWrapper
<>();
routingsupportingreplacewrapper
.
in
(
RoutingSupportingReplace:
:
getStrsupid
,
routingsupportingids
)
.
eq
(
RoutingSupportingReplace:
:
getIsdeleted
,
0
);
replaces
=
routingSupportingReplaceMapper
.
selectList
(
routingsupportingreplacewrapper
);
LambdaQueryWrapper
<
RoutingSupportingReplace
>
routingsupportingreplacewrapper
=
new
LambdaQueryWrapper
<>();
routingsupportingreplacewrapper
.
in
(
RoutingSupportingReplace:
:
getStrsupid
,
routingsupportingids
)
.
eq
(
RoutingSupportingReplace:
:
getIsdeleted
,
0
);
replaces
=
routingSupportingReplaceMapper
.
selectList
(
routingsupportingreplacewrapper
);
}
List
<
Material
>
useMaterials
=
new
ArrayList
<>();
...
...
@@ -145,7 +145,7 @@ public class MaterialRequirementService {
.
collect
(
Collectors
.
toList
());
String
orderId
=
order
.
getOrderId
();
String
orderId
=
order
.
getOrderId
();
if
(
MaterialRequirements
!=
null
)
{
...
...
@@ -174,12 +174,12 @@ public class MaterialRequirementService {
}
if
(
component
.
getSpentQty
()==
null
)
{
throw
new
RuntimeException
(
"配套数据有问题,需求数量为空,请检查数据,"
+
component
.
getMaterialNumber
());
throw
new
RuntimeException
(
"配套数据有问题,需求数量为空,请检查数据,"
+
component
.
getMaterialNumber
());
}
double
allneeded
=
component
.
getSpentQty
().
doubleValue
()/
component
.
getMainQty
().
doubleValue
()
*
operation
.
getQuantity
();
OrderMaterialRequirement
orderMaterialRequirement
=
CreateMaterialRequirement
(
material
,
orderId
,
""
,
operation
,
allneeded
,
component
.
getSpentQty
().
doubleValue
(),
component
.
getMainQty
().
doubleValue
(),
operation
.
getQuantity
());
allneeded
,
component
.
getSpentQty
().
doubleValue
(),
component
.
getMainQty
().
doubleValue
(),
operation
.
getQuantity
()
,
baseTime
);
orderMaterialRequirement
.
setBomId
(
component
.
getStrId
());
if
(!
material
.
getMaterialTypeName
().
equals
(
"MP"
)
&&
isIsCheckSf
)
{
materialIds
.
add
(
materialId
);
//半成品ID
...
...
@@ -276,76 +276,76 @@ public class MaterialRequirementService {
LambdaQueryWrapper
<
Routingsupporting
>
routingsupportingwrapper
=
new
LambdaQueryWrapper
<>();
routingsupportingwrapper
.
in
(
Routingsupporting:
:
getRoutingHeaderId
,
routingIds
)
.
eq
(
Routingsupporting:
:
getIsdeleted
,
0
);
LambdaQueryWrapper
<
Routingsupporting
>
routingsupportingwrapper
=
new
LambdaQueryWrapper
<>();
routingsupportingwrapper
.
in
(
Routingsupporting:
:
getRoutingHeaderId
,
routingIds
)
.
eq
(
Routingsupporting:
:
getIsdeleted
,
0
);
routingsupportings1
=
routingsupportingMapper
.
selectList
(
routingsupportingwrapper
);
if
(
routingsupportings1
!=
null
&&
routingsupportings1
.
size
()>
0
)
{
routingsupportings1
=
routingsupportingMapper
.
selectList
(
routingsupportingwrapper
);
if
(
routingsupportings1
!=
null
&&
routingsupportings1
.
size
()>
0
)
{
routingsupportings
.
addAll
(
routingsupportings1
);
List
<
String
>
routingsupportingids
=
routingsupportings1
.
stream
()
.
map
(
Routingsupporting:
:
getStrId
)
.
distinct
()
.
collect
(
Collectors
.
toList
());
List
<
String
>
routingsupportingids
=
routingsupportings1
.
stream
()
.
map
(
Routingsupporting:
:
getStrId
)
.
distinct
()
.
collect
(
Collectors
.
toList
());
LambdaQueryWrapper
<
RoutingSupportingReplace
>
routingsupportingreplacewrapper
=
new
LambdaQueryWrapper
<>();
routingsupportingreplacewrapper
.
in
(
RoutingSupportingReplace:
:
getStrsupid
,
routingsupportingids
)
.
eq
(
RoutingSupportingReplace:
:
getIsdeleted
,
0
);
LambdaQueryWrapper
<
RoutingSupportingReplace
>
routingsupportingreplacewrapper
=
new
LambdaQueryWrapper
<>();
routingsupportingreplacewrapper
.
in
(
RoutingSupportingReplace:
:
getStrsupid
,
routingsupportingids
)
.
eq
(
RoutingSupportingReplace:
:
getIsdeleted
,
0
);
routingsupportingreplaces1
=
routingSupportingReplaceMapper
.
selectList
(
routingsupportingreplacewrapper
);
routingsupportingreplaces1
=
routingSupportingReplaceMapper
.
selectList
(
routingsupportingreplacewrapper
);
routingsupportingreplaces
.
addAll
(
routingsupportingreplaces1
);
routingsupportingreplaces
.
addAll
(
routingsupportingreplaces1
);
List
<
String
>
materialIds
=
new
ArrayList
<>();
for
(
Routingsupporting
routingsupporting:
routingsupportings1
)
{
String
materialID1
=
routingsupporting
.
getMaterialId
();
Material
material
=
_materials
.
stream
()
.
filter
(
m
->
m
.
getId
().
equals
(
materialID1
))
.
findFirst
()
.
orElse
(
null
);
if
(
material
!=
null
)
{
if
(!
useMaterialids
.
contains
(
materialID1
))
{
useMaterials
.
add
(
material
);
useMaterialids
.
add
(
materialID1
);
}
if
(!
material
.
getMaterialTypeName
().
equals
(
"MP"
))
{
materialIds
.
add
(
materialID1
);
}
}
}
for
(
RoutingSupportingReplace
routingSupportingReplace:
routingsupportingreplaces1
)
{
String
materialID1
=
routingSupportingReplace
.
getMaterialid
();
if
(!
useMaterialids
.
contains
(
materialID1
))
{
List
<
String
>
materialIds
=
new
ArrayList
<>();
for
(
Routingsupporting
routingsupporting:
routingsupportings1
)
{
String
materialID1
=
routingsupporting
.
getMaterialId
();
Material
material
=
_materials
.
stream
()
.
filter
(
m
->
m
.
getId
().
equals
(
materialID1
))
.
findFirst
()
.
orElse
(
null
);
if
(
material
!=
null
)
{
useMaterials
.
add
(
material
);
useMaterialids
.
add
(
materialID1
);
if
(!
useMaterialids
.
contains
(
materialID1
))
{
useMaterials
.
add
(
material
);
useMaterialids
.
add
(
materialID1
);
}
if
(!
material
.
getMaterialTypeName
().
equals
(
"MP"
))
{
materialIds
.
add
(
materialID1
);
}
}
}
}
Map
<
Integer
,
Object
>
r1
=
preloadSfRoutingBomCache
(
materialIds
,
headers
,
routingsupportings
,
routingsupportingreplaces
);
List
<
Long
>
routingIds2
=(
List
<
Long
>)
r1
.
get
(
1
);
List
<
Material
>
useMaterials2
=(
List
<
Material
>)
r1
.
get
(
2
);
if
(
routingIds2
!=
null
)
{
routingIds
.
addAll
(
routingIds2
);
}
if
(
useMaterials2
!=
null
&&
useMaterials2
.
size
()>
0
)
{
for
(
Material
m:
useMaterials2
)
{
String
materialID1
=
m
.
getId
();
for
(
RoutingSupportingReplace
routingSupportingReplace:
routingsupportingreplaces1
)
{
String
materialID1
=
routingSupportingReplace
.
getMaterialid
();
if
(!
useMaterialids
.
contains
(
materialID1
))
{
useMaterials
.
add
(
m
);
useMaterialids
.
add
(
materialID1
);
Material
material
=
_materials
.
stream
()
.
filter
(
m
->
m
.
getId
().
equals
(
materialID1
))
.
findFirst
()
.
orElse
(
null
);
if
(
material
!=
null
)
{
useMaterials
.
add
(
material
);
useMaterialids
.
add
(
materialID1
);
}
}
}
Map
<
Integer
,
Object
>
r1
=
preloadSfRoutingBomCache
(
materialIds
,
headers
,
routingsupportings
,
routingsupportingreplaces
);
List
<
Long
>
routingIds2
=(
List
<
Long
>)
r1
.
get
(
1
);
List
<
Material
>
useMaterials2
=(
List
<
Material
>)
r1
.
get
(
2
);
if
(
routingIds2
!=
null
)
{
routingIds
.
addAll
(
routingIds2
);
}
if
(
useMaterials2
!=
null
&&
useMaterials2
.
size
()>
0
)
{
for
(
Material
m:
useMaterials2
)
{
String
materialID1
=
m
.
getId
();
if
(!
useMaterialids
.
contains
(
materialID1
))
{
useMaterials
.
add
(
m
);
useMaterialids
.
add
(
materialID1
);
}
}
}
}
}
}
if
(
routingIds1
!=
null
)
{
...
...
@@ -392,7 +392,7 @@ public class MaterialRequirementService {
List
<
PlanResource
>
list
=
GetPlanResources
();
Map
<
Integer
,
PlanResource
>
planResourceByReferenceIdMap
=
list
.
stream
()
Map
<
Integer
,
PlanResource
>
planResourceByReferenceIdMap
=
list
.
stream
()
.
filter
(
pr
->
pr
.
getReferenceId
()
!=
null
)
.
collect
(
Collectors
.
toMap
(
PlanResource:
:
getReferenceId
,
Function
.
identity
()));
...
...
@@ -416,7 +416,7 @@ public class MaterialRequirementService {
List
<
Equipinfo
>
matchedEquipments
=
equipinfoByEquipTypeMap
.
get
(
machineId
.
intValue
());
if
(
matchedEquipments
==
null
||
matchedEquipments
.
isEmpty
())
{
throw
new
RuntimeException
(
String
.
format
(
"未找到machineId=%d对应的设备信息"
,
machineId
));
throw
new
RuntimeException
(
String
.
format
(
"未找到machineId=%d对应的设备信息"
,
machineId
));
}
...
...
@@ -477,7 +477,7 @@ public class MaterialRequirementService {
.
distinct
()
.
collect
(
Collectors
.
toList
());
routingDiscreteParams
=
_routingDiscreteParamService
.
lambdaQuery
()
routingDiscreteParams
=
_routingDiscreteParamService
.
lambdaQuery
()
.
in
(
RoutingDiscreteParam:
:
getRoutingDetailId
,
routingDetailIds
)
.
eq
(
RoutingDiscreteParam:
:
getIsDeleted
,
0
)
.
list
();
...
...
@@ -503,8 +503,6 @@ public class MaterialRequirementService {
* @return 所有物料需求列表
*/
public
List
<
OrderMaterialRequirement
>
buildMultiLevelRequirementNetwork
(
Chromosome
chromosome
,
String
sceneId
,
LocalDateTime
_baseTime
,
GlobalParam
_globalParam
)
{
baseTime
=
_baseTime
;
globalParam
=
_globalParam
;
List
<
OrderMaterialRequirement
>
allRequirements
=
new
ArrayList
<>();
List
<
Order
>
childorders
=
new
ArrayList
<>();
List
<
Entry
>
_newEntrys
=
new
ArrayList
<>();
...
...
@@ -519,13 +517,13 @@ public class MaterialRequirementService {
.
entrySet
().
stream
()
.
collect
(
Collectors
.
toMap
(
Map
.
Entry
::
getKey
,
e
->
0
));
List
<
Integer
>
operationSequencing
=
chromosome
.
getOperationSequencing
(
);
List
<
Integer
>
operationSequencing
=
new
ArrayList
<>(
chromosome
.
getOperationSequencing
()
);
orders
.
forEach
(
t
->
clearFinishOrder
(
t
));
for
(
Integer
groupId
:
operationSequencing
)
{
Order
demand
=
orders
.
stream
().
filter
(
t
->
t
.
getId
()==
groupId
).
findFirst
().
orElse
(
null
);
Order
demand
=
orders
.
stream
().
filter
(
t
->
t
.
getId
()==
groupId
).
findFirst
().
orElse
(
null
);
if
(
demand
.
getFinishOrderId
()
!=
null
&&
!
demand
.
getFinishOrderId
().
isEmpty
())
{
continue
;
...
...
@@ -546,7 +544,7 @@ public class MaterialRequirementService {
// 调用BuildOperationBOM方法(返回结果对象替代out参数)
BOMBuildResult
operationResult
=
buildOperationSFBOM
(
operation
.
getOrderId
(),
""
,
operation
.
getQuantity
(),
operation
,
1
,
demand
,
sceneId
,
chromosome
);
operation
.
getQuantity
(),
operation
,
1
,
demand
,
sceneId
,
chromosome
,
_baseTime
,
_globalParam
);
// // 合并物料需求和子订单
if
(
operationResult
!=
null
)
{
allRequirements
.
addAll
(
operationResult
.
getMaterialRequirements
());
...
...
@@ -567,13 +565,13 @@ public class MaterialRequirementService {
return
allRequirements
;
}
private
void
clearFinishOrder
(
Order
order
)
{
if
(
order
.
getFinishOrderId
()
==
null
)
{
order
.
setFinishOrderId
(
new
ArrayList
<>());
order
.
setTargetFinishedOperationId
(
new
ArrayList
<>());
private
void
clearFinishOrder
(
Order
order
)
{
if
(
order
.
getFinishOrderId
()
==
null
)
{
order
.
setFinishOrderId
(
new
ArrayList
<>());
order
.
setTargetFinishedOperationId
(
new
ArrayList
<>());
}
}
}
/**
* 构建订单BOM
...
...
@@ -586,10 +584,10 @@ private void clearFinishOrder (Order order)
* @return 包含物料需求列表和子订单列表的结果对象
*/
public
BOMBuildResult
buildOrderBOM
(
String
sceneId
,
int
parent
,
String
materialID
,
String
mainorderId
,
String
childorderId
,
double
parentQuantity
,
int
level
,
Order
forder
,
int
finishOpertionID
,
Chromosome
chromosome
)
{
String
childorderId
,
double
parentQuantity
,
int
level
,
Order
forder
,
int
finishOpertionID
,
Chromosome
chromosome
,
LocalDateTime
baseTime
,
GlobalParam
globalParam
)
{
forder
.
setCreateBom
(
true
);
List
<
RoutingHeader
>
headers
=
GetRoutingHeader
(
sceneId
);
List
<
RoutingHeader
>
headers
=
GetRoutingHeader
(
sceneId
);
RoutingHeader
routingHeaders
=
headers
.
stream
()
.
filter
(
t
->
t
.
getId
()==
parent
||
t
.
getMaterialId
().
equals
(
materialID
))
.
findFirst
()
...
...
@@ -604,7 +602,7 @@ private void clearFinishOrder (Order order)
List
<
Order
>
childorders2
=
new
ArrayList
<>();
List
<
Entry
>
_newEntrys
=
new
ArrayList
<>();
List
<
Machine
>
_newMachines
=
new
ArrayList
<>();
// 遍历产品的工序,递归构建工序BOM
// 遍历产品的工序,递归构建工序BOM
List
<
Entry
>
_allOperations
=
chromosome
.
getAllOperations
();
...
...
@@ -615,7 +613,7 @@ private void clearFinishOrder (Order order)
if
(
Operations
!=
null
)
{
if
(
Operations
!=
null
)
{
for
(
Entry
operation
:
Operations
)
{
if
(
finishOpertionID
!=
0
)
{
...
...
@@ -627,7 +625,7 @@ private void clearFinishOrder (Order order)
}
// 调用BuildOperationBOM方法(返回结果对象替代out参数)
BOMBuildResult
operationResult
=
buildOperationBOM
(
mainorderId
,
childorderId
,
parentQuantity
,
operation
,
level
,
forder
,
sceneId
,
chromosome
);
parentQuantity
,
operation
,
level
,
forder
,
sceneId
,
chromosome
,
baseTime
,
globalParam
);
// // 合并物料需求和子订单
if
(
operationResult
!=
null
)
{
materialRequirements
.
addAll
(
operationResult
.
getMaterialRequirements
());
...
...
@@ -650,7 +648,7 @@ private void clearFinishOrder (Order order)
* @return 包含物料需求列表和子订单列表的结果对象(替代C#的out参数)
*/
public
BOMBuildResult
buildOperationBOM
(
String
orderId
,
String
childorderId
,
double
parentQuantity
,
Entry
operation
,
int
level
,
Order
forder
,
String
sceneId
,
Chromosome
chromosome
)
{
Entry
operation
,
int
level
,
Order
forder
,
String
sceneId
,
Chromosome
chromosome
,
LocalDateTime
baseTime
,
GlobalParam
globalParam
)
{
List
<
OrderMaterialRequirement
>
materialRequirements
=
new
ArrayList
<>();
List
<
Order
>
_childorders
=
new
ArrayList
<>();
List
<
Entry
>
_newEntrys
=
new
ArrayList
<>();
...
...
@@ -678,8 +676,8 @@ private void clearFinishOrder (Order order)
return
null
;
}
OrderMaterialRequirement
orderMaterial
=
CreateMaterialRequirement
(
material
,
orderId
,
childorderId
,
operation
,
allneeded
,
component
.
getSpentQty
().
doubleValue
(),
component
.
getMainQty
().
doubleValue
()
,
parentQuantity
);
orderMaterial
.
setLevel
(
level
);
OrderMaterialRequirement
orderMaterial
=
CreateMaterialRequirement
(
material
,
orderId
,
childorderId
,
operation
,
allneeded
,
component
.
getSpentQty
().
doubleValue
(),
component
.
getMainQty
().
doubleValue
()
,
parentQuantity
,
baseTime
);
orderMaterial
.
setLevel
(
level
);
orderMaterial
.
setBomId
(
component
.
getStrId
());
materialRequirements
.
add
(
orderMaterial
);
...
...
@@ -713,8 +711,8 @@ private void clearFinishOrder (Order order)
BOMBuildResult
childResult
=
buildOrderBOM
(
sceneId
,
0
,
orderMaterial
.
getMaterialId
(),
orderId
,
order
.
getOrderId
(),
order
.
getQuantity
(),
l
,
order
,
operation
.
getId
(),
chromosome
);
// materialRequirements.addAll(childResult.getMaterialRequirements());
order
.
getQuantity
(),
l
,
order
,
operation
.
getId
(),
chromosome
,
baseTime
,
globalParam
);
// materialRequirements.addAll(childResult.getMaterialRequirements());
_childorders
.
addAll
(
childResult
.
getChildOrders
());
_newEntrys
.
addAll
(
childResult
.
getNewEntrys
());
operation
.
getDependentOnOrderIds
().
add
(
order
.
getId
());
...
...
@@ -743,7 +741,7 @@ private void clearFinishOrder (Order order)
childorder
.
setQuantity
((
int
)
orderMaterial
.
getQjQty
());
childorder
.
setFinishOrderId
(
new
ArrayList
<>());
childorder
.
getFinishOrderId
().
add
(
forder
.
getId
());
childorder
.
setNewCreate
(
true
);
childorder
.
setNew
Sf
Create
(
true
);
childorder
.
setTargetFinishedOperationId
(
new
ArrayList
<>());
childorder
.
getTargetFinishedOperationId
().
add
(
operation
.
getId
());
childorder
.
setSerie
(
forder
.
getSerie
());
...
...
@@ -769,8 +767,8 @@ private void clearFinishOrder (Order order)
int
l
=
level
+
1
;
BOMBuildResult
childResult
=
buildOrderBOM
(
sceneId
,
0
,
orderMaterial
.
getMaterialId
(),
orderId
,
childorder
.
getOrderId
(),
childorder
.
getQuantity
(),
l
,
childorder
,
0
,
chromosome
);
// materialRequirements.addAll(childResult.getMaterialRequirements());
childorder
.
getQuantity
(),
l
,
childorder
,
0
,
chromosome
,
baseTime
,
globalParam
);
// materialRequirements.addAll(childResult.getMaterialRequirements());
_childorders
.
addAll
(
childResult
.
getChildOrders
());
_newEntrys
.
addAll
(
childResult
.
getNewEntrys
());
}
...
...
@@ -792,10 +790,10 @@ private void clearFinishOrder (Order order)
RoutingHeader
headers1
=
headers
.
stream
()
.
filter
(
t
->
t
.
getMaterialId
().
equals
(
materialID
))
.
findFirst
().
orElse
(
null
);
if
(
headers1
==
null
)
{
return
null
;
}
if
(
headers1
==
null
)
{
return
null
;
}
routingIds
=
headers1
.
getId
().
longValue
();
...
...
@@ -811,8 +809,8 @@ if(headers1==null)
}
List
<
RoutingDetailEquip
>
allroutingDetailEquips
=
GetRoutingDetailEquips
(
sceneId
);
List
<
RoutingDetailEquip
>
routingDetailEquips
=
allroutingDetailEquips
.
stream
()
.
filter
(
t
->
t
.
getRoutingHeaderId
().
equals
(
headersid
))
.
collect
(
Collectors
.
toList
());
.
filter
(
t
->
t
.
getRoutingHeaderId
().
equals
(
headersid
))
.
collect
(
Collectors
.
toList
());
...
...
@@ -842,9 +840,9 @@ if(headers1==null)
List
<
RoutingDetailConnect
>
allroutingDetailconnections
=
GetRoutingDetailConnect
(
sceneId
);
connections
=
allroutingDetailconnections
.
stream
()
.
filter
(
t
->
t
.
getRoutingHeaderId
().
equals
(
headersid
))
.
collect
(
Collectors
.
toList
());
connections
=
allroutingDetailconnections
.
stream
()
.
filter
(
t
->
t
.
getRoutingHeaderId
().
equals
(
headersid
))
.
collect
(
Collectors
.
toList
());
List
<
ProdOrderProcess
>
ProdOrderProcesslist
=
connections
.
stream
()
...
...
@@ -921,7 +919,7 @@ if(headers1==null)
* @return 包含物料需求列表和子订单列表的结果对象(替代C#的out参数)
*/
public
BOMBuildResult
buildOperationSFBOM
(
String
orderId
,
String
childorderId
,
double
parentQuantity
,
Entry
operation
,
int
level
,
Order
forder
,
String
sceneId
,
Chromosome
chromosome
)
{
Entry
operation
,
int
level
,
Order
forder
,
String
sceneId
,
Chromosome
chromosome
,
LocalDateTime
baseTime
,
GlobalParam
globalParam
)
{
List
<
OrderMaterialRequirement
>
materialRequirements
=
new
ArrayList
<>();
List
<
Order
>
_childorders
=
new
ArrayList
<>();
List
<
Entry
>
_newEntrys
=
new
ArrayList
<>();
...
...
@@ -949,99 +947,99 @@ if(headers1==null)
// 查找物料(流式处理替代First)
if
(!
orderMaterial
.
getMaterialTypeName
().
equals
(
"MP"
)
)
{
if
(!
orderMaterial
.
getMaterialTypeName
().
equals
(
"MP"
)
)
{
// 处理半成品/成品的现有订单
// 为什么要先找现有订单,绑定上,因为要把它排在成品工单前面,才能有时间
List
<
Order
>
orders2
=
orders
.
stream
()
.
filter
(
t
->
t
.
getMaterialId
().
equals
(
orderMaterial
.
getMaterialId
())
&&
t
.
getSYQuantity
()
>
0
)
.
sorted
(
Comparator
.
comparing
(
Order:
:
getDueDate
))
.
collect
(
Collectors
.
toList
());
// 处理半成品/成品的现有订单
// 为什么要先找现有订单,绑定上,因为要把它排在成品工单前面,才能有时间
List
<
Order
>
orders2
=
orders
.
stream
()
.
filter
(
t
->
t
.
getMaterialId
().
equals
(
orderMaterial
.
getMaterialId
())
&&
t
.
getSYQuantity
()
>
0
)
.
sorted
(
Comparator
.
comparing
(
Order:
:
getDueDate
))
.
collect
(
Collectors
.
toList
());
if
(!
orders2
.
isEmpty
())
{
for
(
Order
order
:
orders2
)
{
if
(
order
.
getFinishOrderId
()
==
null
)
{
order
.
setFinishOrderId
(
new
ArrayList
<>());
order
.
setTargetFinishedOperationId
(
new
ArrayList
<>());
}
order
.
getFinishOrderId
().
add
(
forder
.
getId
());
order
.
getTargetFinishedOperationId
().
add
(
operation
.
getId
());
orderMaterial
.
getProductOrderID
().
add
(
order
.
getId
());
double
useq
=
Math
.
min
(
needed
,
order
.
getSYQuantity
());
needed
-=
useq
;
order
.
setSYQuantity
(
order
.
getSYQuantity
()
-
useq
);
//防止已经生成过一次
if
(!
order
.
isCreateBom
())
{
// 递归构建BOM
int
l
=
level
+
1
;
BOMBuildResult
childResult
=
buildOrderBOM
(
sceneId
,
0
,
orderMaterial
.
getMaterialId
(),
orderId
,
order
.
getOrderId
(),
order
.
getQuantity
(),
l
,
order
,
operation
.
getId
(),
chromosome
);
materialRequirements
.
addAll
(
childResult
.
getMaterialRequirements
());
_childorders
.
addAll
(
childResult
.
getChildOrders
());
_newEntrys
.
addAll
(
childResult
.
getNewEntrys
());
operation
.
getDependentOnOrderIds
().
add
(
order
.
getId
());
}
if
(!
orders2
.
isEmpty
())
{
for
(
Order
order
:
orders2
)
{
if
(
order
.
getFinishOrderId
()
==
null
)
{
order
.
setFinishOrderId
(
new
ArrayList
<>());
order
.
setTargetFinishedOperationId
(
new
ArrayList
<>());
}
order
.
getFinishOrderId
().
add
(
forder
.
getId
());
order
.
getTargetFinishedOperationId
().
add
(
operation
.
getId
());
if
(
needed
<=
0
)
{
break
;
}
orderMaterial
.
getProductOrderID
().
add
(
order
.
getId
());
double
useq
=
Math
.
min
(
needed
,
order
.
getSYQuantity
());
needed
-=
useq
;
order
.
setSYQuantity
(
order
.
getSYQuantity
()
-
useq
);
//防止已经生成过一次
if
(!
order
.
isCreateBom
())
{
// 递归构建BOM
int
l
=
level
+
1
;
BOMBuildResult
childResult
=
buildOrderBOM
(
sceneId
,
0
,
orderMaterial
.
getMaterialId
(),
orderId
,
order
.
getOrderId
(),
order
.
getQuantity
(),
l
,
order
,
operation
.
getId
(),
chromosome
,
baseTime
,
globalParam
);
materialRequirements
.
addAll
(
childResult
.
getMaterialRequirements
());
_childorders
.
addAll
(
childResult
.
getChildOrders
());
_newEntrys
.
addAll
(
childResult
.
getNewEntrys
());
operation
.
getDependentOnOrderIds
().
add
(
order
.
getId
());
}
}
// 更新已配和缺件数量
orderMaterial
.
setYpQty
(
allneeded
-
needed
);
orderMaterial
.
setQjQty
(
needed
);
if
(
needed
>
0
&&
globalParam
.
isIsCheckSf
())
{
// 创建新的子订单
Order
childorder
=
new
Order
();
String
OrderId
=
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
);
childorder
.
setOrderId
(
OrderId
);
childorder
.
setMaterialId
(
orderMaterial
.
getMaterialId
());
childorder
.
setMaterialCode
(
orderMaterial
.
getMaterialCode
());
childorder
.
setMaterialName
(
orderMaterial
.
getMaterialTypeName
());
childorder
.
setOrderCode
(
"M_"
+
orderMaterial
.
getMaterialCode
());
childorder
.
setQuantity
((
int
)
orderMaterial
.
getQjQty
());
childorder
.
setFinishOrderId
(
new
ArrayList
<>());
childorder
.
getFinishOrderId
().
add
(
forder
.
getId
());
childorder
.
setNewCreate
(
true
);
childorder
.
setTargetFinishedOperationId
(
new
ArrayList
<>());
childorder
.
getTargetFinishedOperationId
().
add
(
operation
.
getId
());
childorder
.
setSerie
(
forder
.
getSerie
());
childorder
.
setStartDate
(
forder
.
getStartDate
());
childorder
.
setDueDate
(
forder
.
getDueDate
());
childorder
.
setPriority
(
forder
.
getPriority
());
childorder
.
setActualPriority
(
forder
.
getActualPriority
());
Map
<
Integer
,
Object
>
list
=
CreateChild
(
sceneId
,
childorder
,
orderMaterial
.
getMaterialId
(),
operation
.
getId
(),
chromosome
);
if
(
list
==
null
)
{
continue
;
if
(
needed
<=
0
)
{
break
;
}
_childorders
.
add
(
childorder
);
List
<
Entry
>
newentrys
=(
List
<
Entry
>)
list
.
get
(
1
);
_newEntrys
.
addAll
(
newentrys
);
orderMaterial
.
getProductOrderID
().
add
(
childorder
.
getId
());
operation
.
getDependentOnOrderIds
().
add
(
childorder
.
getId
());
// 递归构建BOM
int
l
=
level
+
1
;
BOMBuildResult
childResult
=
buildOrderBOM
(
sceneId
,
0
,
orderMaterial
.
getMaterialId
(),
orderId
,
childorder
.
getOrderId
(),
childorder
.
getQuantity
(),
l
,
childorder
,
0
,
chromosome
);
materialRequirements
.
addAll
(
childResult
.
getMaterialRequirements
());
_childorders
.
addAll
(
childResult
.
getChildOrders
());
_newEntrys
.
addAll
(
childResult
.
getNewEntrys
());
}
}
// 更新已配和缺件数量
orderMaterial
.
setYpQty
(
allneeded
-
needed
);
orderMaterial
.
setQjQty
(
needed
);
if
(
needed
>
0
&&
globalParam
.
isIsCheckSf
())
{
// 创建新的子订单
Order
childorder
=
new
Order
();
String
OrderId
=
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
);
childorder
.
setOrderId
(
OrderId
);
childorder
.
setMaterialId
(
orderMaterial
.
getMaterialId
());
childorder
.
setMaterialCode
(
orderMaterial
.
getMaterialCode
());
childorder
.
setMaterialName
(
orderMaterial
.
getMaterialTypeName
());
childorder
.
setOrderCode
(
"M_"
+
orderMaterial
.
getMaterialCode
());
childorder
.
setQuantity
((
int
)
orderMaterial
.
getQjQty
());
childorder
.
setFinishOrderId
(
new
ArrayList
<>());
childorder
.
getFinishOrderId
().
add
(
forder
.
getId
());
childorder
.
setNewSfCreate
(
true
);
childorder
.
setTargetFinishedOperationId
(
new
ArrayList
<>());
childorder
.
getTargetFinishedOperationId
().
add
(
operation
.
getId
());
childorder
.
setSerie
(
forder
.
getSerie
());
childorder
.
setStartDate
(
forder
.
getStartDate
());
childorder
.
setDueDate
(
forder
.
getDueDate
());
childorder
.
setPriority
(
forder
.
getPriority
());
childorder
.
setActualPriority
(
forder
.
getActualPriority
());
Map
<
Integer
,
Object
>
list
=
CreateChild
(
sceneId
,
childorder
,
orderMaterial
.
getMaterialId
(),
operation
.
getId
(),
chromosome
);
if
(
list
==
null
)
{
continue
;
}
_childorders
.
add
(
childorder
);
List
<
Entry
>
newentrys
=(
List
<
Entry
>)
list
.
get
(
1
);
_newEntrys
.
addAll
(
newentrys
);
orderMaterial
.
getProductOrderID
().
add
(
childorder
.
getId
());
operation
.
getDependentOnOrderIds
().
add
(
childorder
.
getId
());
// 递归构建BOM
int
l
=
level
+
1
;
BOMBuildResult
childResult
=
buildOrderBOM
(
sceneId
,
0
,
orderMaterial
.
getMaterialId
(),
orderId
,
childorder
.
getOrderId
(),
childorder
.
getQuantity
(),
l
,
childorder
,
0
,
chromosome
,
baseTime
,
globalParam
);
materialRequirements
.
addAll
(
childResult
.
getMaterialRequirements
());
_childorders
.
addAll
(
childResult
.
getChildOrders
());
_newEntrys
.
addAll
(
childResult
.
getNewEntrys
());
}
}
}
}
...
...
@@ -1061,7 +1059,7 @@ if(headers1==null)
orderMaterial
.
setMaterialName
(
material
.
getName
());
orderMaterial
.
setMaterialTypeName
(
material
.
getMaterialTypeName
());
orderMaterial
.
setMaterialId
(
material
.
getId
());
// orderMaterial.setCheckLeadTime(material.getCkeckLeadTime());
// orderMaterial.setCheckLeadTime(material.getCkeckLeadTime());
double
useStock
=
0
;
// 扣减现有库存
List
<
Stock
>
stocks
=
material
.
getMaterialStocks
().
stream
()
...
...
@@ -1089,7 +1087,7 @@ if(headers1==null)
}
private
OrderMaterialRequirement
CreateMaterialRequirement
(
Material
material
,
String
orderId
,
String
childorderId
,
Entry
operation
,
double
need
,
double
spentQty
,
double
mainQty
,
double
qty
)
{
private
OrderMaterialRequirement
CreateMaterialRequirement
(
Material
material
,
String
orderId
,
String
childorderId
,
Entry
operation
,
double
need
,
double
spentQty
,
double
mainQty
,
double
qty
,
LocalDateTime
baseTime
)
{
OrderMaterialRequirement
orderMaterial
=
new
OrderMaterialRequirement
();
orderMaterial
.
setOrderId
(
orderId
);
...
...
@@ -1140,14 +1138,14 @@ if(headers1==null)
* @return 包含物料需求列表和子订单列表的结果对象(替代C#的out参数)
*/
public
void
EditOperationBOM
(
Entry
operation
,
Chromosome
chromosome
,
LocalDateTime
earliestStartTime
,
GeneticDecoder
coder
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
)
{
public
void
EditOperationBOM
(
Entry
operation
,
Chromosome
chromosome
,
LocalDateTime
earliestStartTime
,
GeneticDecoder
coder
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
,
Map
<
Integer
,
Entry
>
entryIndexById
,
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
,
LocalDateTime
baseTime
)
{
List
<
OrderMaterialRequirement
>
materialRequirements
=
new
ArrayList
<>();
String
sceneId
=
chromosome
.
getScenarioID
();
Random
rnd
=
new
Random
();
List
<
OrderMaterialRequirement
>
MaterialRequirements
=
operation
.
getMaterialRequirements
();
MaterialRequirements
=
MaterialRequirements
.
stream
()
MaterialRequirements
=
MaterialRequirements
.
stream
()
.
sorted
((
a
,
b
)
->
{
// 定义判断条件:是否满足 非MP + 生产订单ID非空非空串
boolean
aMatch
=
!
"MP"
.
equals
(
a
.
getMaterialTypeName
())
...
...
@@ -1228,12 +1226,12 @@ if(headers1==null)
if
(
orderMaterial1
!=
null
)
{
useStock
=
orderMaterial1
.
getUseStock
();
needed
-=
useStock
;
orderMaterial
.
setUseStock
(
orderMaterial
.
getUseStock
()
+
useStock
);
orderMaterial
.
getReplaceMaterial
().
add
(
orderMaterial1
);
if
(
needed
<=
0
)
{
break
;
}
needed
-=
useStock
;
orderMaterial
.
setUseStock
(
orderMaterial
.
getUseStock
()
+
useStock
);
orderMaterial
.
getReplaceMaterial
().
add
(
orderMaterial1
);
if
(
needed
<=
0
)
{
break
;
}
}
}
...
...
@@ -1247,7 +1245,7 @@ if(headers1==null)
continue
;
}
MaterialInTransit
(
material
,
""
,
orderMaterial
,
needed
,
earliestStartTime
);
MaterialInTransit
(
material
,
""
,
orderMaterial
,
needed
,
earliestStartTime
,
materials
);
needed
-=
orderMaterial
.
getUseTransit
();
...
...
@@ -1268,7 +1266,7 @@ if(headers1==null)
break
;
}
MaterialInTransit
(
material1
,
rsr
.
getMaterialid
(),
orderMaterial1
,
needed
,
earliestStartTime
);
MaterialInTransit
(
material1
,
rsr
.
getMaterialid
(),
orderMaterial1
,
needed
,
earliestStartTime
,
materials
);
needed
-=
orderMaterial1
.
getUseTransit
();
...
...
@@ -1315,27 +1313,27 @@ if(headers1==null)
// 处理半成品/成品的现有订单
List
<
Integer
>
orderids
=
orderMaterial
.
getProductOrderID
();
if
(
orderids
!=
null
&&
orderids
.
size
()>
0
)
{
if
(
orderids
!=
null
&&
orderids
.
size
()>
0
)
{
for
(
Integer
orderid
:
orderids
)
{
coder
.
ClearorderOperationResult
(
chromosome
,
orderid
);
coder
.
EditorderOperation
(
chromosome
,
orderid
,
needed
,
machineTasksCache
);
}
for
(
Integer
orderid
:
orderids
)
{
coder
.
ClearorderOperationResult
(
chromosome
,
orderid
);
coder
.
EditorderOperation
(
chromosome
,
orderid
,
needed
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
);
}
}
else
{
List
<
MaterialPurchase
>
materialPurchaseList
=
material
.
getMaterialPurchases
();
if
(
materialPurchaseList
!=
null
&&
materialPurchaseList
.
size
()>
0
)
{
}
else
{
List
<
MaterialPurchase
>
materialPurchaseList
=
material
.
getMaterialPurchases
();
if
(
materialPurchaseList
!=
null
&&
materialPurchaseList
.
size
()>
0
)
{
int
randomSeq
=
rnd
.
nextInt
(
materialPurchaseList
.
size
());
int
randomSeq
=
rnd
.
nextInt
(
materialPurchaseList
.
size
());
MaterialPurchase
result
=
materialPurchaseList
.
get
(
randomSeq
);
MaterialPurchase
result
=
materialPurchaseList
.
get
(
randomSeq
);
orderMaterial
.
setCheckLeadTime
(
result
.
getPurchaseCycle
());
orderMaterial
.
setPurchaseTime
(
result
.
getInspectionCycle
());
LocalDateTime
purchaseEndTime
=
baseTime
.
plusDays
(
orderMaterial
.
getPurchaseTime
()
+
orderMaterial
.
getCheckLeadTime
());
orderMaterial
.
setPurchaseEndTime
(
purchaseEndTime
);
}
}
orderMaterial
.
setCheckLeadTime
(
result
.
getPurchaseCycle
());
orderMaterial
.
setPurchaseTime
(
result
.
getInspectionCycle
());
LocalDateTime
purchaseEndTime
=
baseTime
.
plusDays
(
orderMaterial
.
getPurchaseTime
()
+
orderMaterial
.
getCheckLeadTime
());
orderMaterial
.
setPurchaseEndTime
(
purchaseEndTime
);
}
}
}
orderMaterial
.
getReplaceMaterial
().
removeIf
(
t
->
t
.
getUseStock
()==
0
&&
t
.
getUseTransit
()==
0
);
}
...
...
@@ -1376,14 +1374,14 @@ if(headers1==null)
private
void
MaterialInTransit
(
Material
material
,
String
materialId
,
OrderMaterialRequirement
orderMaterial
,
double
needed
,
LocalDateTime
earliestStartTime
){
private
void
MaterialInTransit
(
Material
material
,
String
materialId
,
OrderMaterialRequirement
orderMaterial
,
double
needed
,
LocalDateTime
earliestStartTime
,
List
<
Material
>
materials
){
// 处理在途物料
double
accumulated
=
0
;
LocalDateTime
earliestTime
=
LocalDateTime
.
of
(
2000
,
1
,
1
,
0
,
0
,
0
);
double
useTransit
=
0
;
if
(
material
==
null
)
{
material
=
_
materials
.
stream
()
material
=
materials
.
stream
()
.
filter
(
m
->
m
.
getId
().
equals
(
materialId
))
.
findFirst
()
.
orElse
(
null
);
...
...
src/main/java/com/aps/service/Algorithm/MaterialRequirementServicebf.java
View file @
f2a1529b
...
...
@@ -894,7 +894,7 @@ public class MaterialRequirementServicebf {
childorder
.
setQuantity
((
int
)
orderMaterial
.
getQjQty
());
childorder
.
setFinishOrderId
(
new
ArrayList
<>());
childorder
.
getFinishOrderId
().
add
(
forder
.
getId
());
childorder
.
setNewCreate
(
true
);
childorder
.
setNew
Sf
Create
(
true
);
childorder
.
setTargetFinishedOperationId
(
new
ArrayList
<>());
childorder
.
getTargetFinishedOperationId
().
add
(
operation
.
getId
());
childorder
.
setSerie
(
forder
.
getSerie
());
...
...
src/main/java/com/aps/service/Algorithm/ParallelLocalSearch.java
deleted
100644 → 0
View file @
bb00017a
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.entity.Algorithm.*
;
import
com.aps.entity.basic.Entry
;
import
com.aps.entity.basic.GlobalParam
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.concurrent.*
;
/**
* 多种局部搜索算法并行
*/
public
class
ParallelLocalSearch
{
private
final
ExecutorService
executor
;
private
GlobalParam
globalParam
;
private
List
<
Entry
>
allOperations
;
private
List
<
GlobalOperationInfo
>
globalOpList
;
private
FitnessCalculator
fitnessCalculator
;
private
ObjectiveWeights
objectiveWeights
;
public
ParallelLocalSearch
(
GlobalParam
globalParam
,
List
<
Entry
>
allOperations
,
List
<
GlobalOperationInfo
>
globalOpList
,
FitnessCalculator
fitnessCalculator
,
ObjectiveWeights
objectiveWeights
)
{
this
.
globalParam
=
globalParam
;
this
.
allOperations
=
allOperations
;
this
.
globalOpList
=
globalOpList
;
this
.
fitnessCalculator
=
fitnessCalculator
;
this
.
objectiveWeights
=
objectiveWeights
;
this
.
executor
=
Executors
.
newFixedThreadPool
(
Runtime
.
getRuntime
().
availableProcessors
());
}
/**
* 并行局部搜索
*/
public
Chromosome
search
(
Chromosome
chromosome
,
GeneticDecoder
decoder
,
ScheduleParams
param
)
{
List
<
Callable
<
Chromosome
>>
tasks
=
new
ArrayList
<>();
// 添加爬山法任务
// tasks.add(() -> {
// HillClimbing hillClimbing = new HillClimbing(globalParam, allOperations, globalOpList, fitnessCalculator, objectiveWeights);
// return hillClimbing.search(chromosome, decoder, param);
// });
// 添加变邻域搜索任务
tasks
.
add
(()
->
{
VariableNeighborhoodSearch
vns
=
new
VariableNeighborhoodSearch
(
globalParam
,
allOperations
,
globalOpList
,
fitnessCalculator
,
objectiveWeights
);
return
vns
.
search
(
chromosome
,
decoder
,
param
);
});
// 添加模拟退火任务
// tasks.add(() -> {
// SimulatedAnnealing sa = new SimulatedAnnealing(globalParam, allOperations, globalOpList, fitnessCalculator, objectiveWeights);
// return sa.search(chromosome, decoder, param);
// });
// 执行所有任务
List
<
Chromosome
>
results
=
new
ArrayList
<>();
try
{
List
<
Future
<
Chromosome
>>
futures
=
executor
.
invokeAll
(
tasks
);
for
(
Future
<
Chromosome
>
future
:
futures
)
{
results
.
add
(
future
.
get
());
}
}
catch
(
InterruptedException
|
ExecutionException
e
)
{
e
.
printStackTrace
();
}
// 选择最优解
Chromosome
best
=
chromosome
;
for
(
Chromosome
result
:
results
)
{
if
(
isBetter
(
result
,
best
))
{
best
=
result
;
}
}
return
best
;
}
/**
* 比较两个染色体的优劣
*/
private
boolean
isBetter
(
Chromosome
c1
,
Chromosome
c2
)
{
return
c1
.
getFitness
()
>
c2
.
getFitness
();
}
/**
* 关闭线程池
*/
public
void
shutdown
()
{
executor
.
shutdown
();
}
}
\ No newline at end of file
src/main/java/com/aps/service/Algorithm/ScheduleOperationService.java
View file @
f2a1529b
...
...
@@ -1885,7 +1885,7 @@ if(targetOp.getSequence()>1) {
decoder
.
decode
(
chromosome
);
decoder
.
decode
(
chromosome
,
false
);
KpiCalculator
kpiCalculator
=
new
KpiCalculator
(
chromosome
);
kpiCalculator
.
calculatekpi
();
...
...
src/main/java/com/aps/service/Algorithm/SimulatedAnnealing.java
View file @
f2a1529b
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.common.util.FileHelper
;
import
com.aps.common.util.GlobalCacheUtil
;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.entity.Algorithm.*
;
import
com.aps.entity.basic.Entry
;
import
com.aps.entity.basic.GlobalParam
;
import
com.aps.entity.basic.Machine
;
import
com.aps.entity.basic.MachineOption
;
import
com.aps.entity.Algorithm.IDAndChildID.GroupResult
;
import
com.aps.entity.basic.*
;
import
java.util.*
;
import
java.util.concurrent.*
;
...
...
@@ -18,19 +17,41 @@ import java.util.stream.Collectors;
public
class
SimulatedAnnealing
{
private
final
Random
rnd
=
new
Random
();
private
void
log
(
String
message
)
{
log
(
message
,
false
);
}
private
void
log
(
String
message
,
boolean
enableLogging
)
{
if
(
enableLogging
)
{
FileHelper
.
writeLogFile
(
message
);
}
}
private
List
<
Entry
>
allOperations
;
private
Map
<
String
,
Entry
>
entrys
;
private
List
<
Order
>
orders
;
private
List
<
Material
>
materials
;
private
List
<
GroupResult
>
_entryRel
;
private
FitnessCalculator
fitnessCalculator
;
private
Map
<
String
,
Entry
>
entrys
;
private
Map
<
Integer
,
Entry
>
entrybyids
;
public
SimulatedAnnealing
(
List
<
Entry
>
allOperations
)
{
public
SimulatedAnnealing
(
List
<
Entry
>
allOperations
,
List
<
Order
>
orders
,
List
<
Material
>
materials
,
List
<
GroupResult
>
entryRel
,
FitnessCalculator
_fitnessCalculator
)
{
this
.
allOperations
=
allOperations
;
this
.
orders
=
orders
;
this
.
materials
=
materials
;
Map
<
Integer
,
Object
>
mp
=
buildEntryKey
()
;
_entryRel
=
entryRel
;
entrys
=(
Map
<
String
,
Entry
>)
mp
.
get
(
1
);
entrybyids
=(
Map
<
Integer
,
Entry
>)
mp
.
get
(
2
);
Map
<
Integer
,
Object
>
mp
=
buildEntryKey
();
this
.
fitnessCalculator
=
_fitnessCalculator
;
entrys
=(
Map
<
String
,
Entry
>)
mp
.
get
(
1
);
entrybyids
=(
Map
<
Integer
,
Entry
>)
mp
.
get
(
2
);
}
private
final
ExecutorService
decodeExecutor
=
new
ThreadPoolExecutor
(
...
...
@@ -40,7 +61,7 @@ private Map<String, Entry> entrys;
new
ArrayBlockingQueue
<>(
200
),
// 有界队列,避免内存溢出
new
ThreadPoolExecutor
.
CallerRunsPolicy
()
// 任务满了主线程执行,不丢失任务
);
public
List
<
Chromosome
>
batchSearch
(
List
<
Chromosome
>
chromosomes
,
GeneticDecoder
decoder
,
List
<
Machine
>
machines
)
{
public
List
<
Chromosome
>
batchSearch
(
List
<
Chromosome
>
chromosomes
,
VariableNeighborhoodSearch
vns
,
GeneticDecoder
decoder
,
List
<
Machine
>
machines
)
{
List
<
Chromosome
>
saHcOptimized
=
new
ArrayList
<>();
// CompletableFuture.allOf(chromosomes.stream()
// .map(chromosome -> CompletableFuture.runAsync(() -> {
...
...
@@ -50,15 +71,15 @@ private Map<String, Entry> entrys;
// .toArray(CompletableFuture[]::new))
// .join();
for
(
Chromosome
chromosome:
chromosomes
)
{
Chromosome
optimized
=
searchWithHillClimbing
(
chromosome
,
decoder
,
machines
);
saHcOptimized
.
add
(
optimized
);
Chromosome
optimized
=
searchWithHillClimbing
(
chromosome
,
vns
,
decoder
,
machines
);
saHcOptimized
.
add
(
optimized
);
}
return
saHcOptimized
;
}
public
Chromosome
batchSearchGetMax
(
List
<
Chromosome
>
chromosomes
,
GeneticDecoder
decoder
,
List
<
Machine
>
machines
)
{
List
<
Chromosome
>
saHcOptimized
=
batchSearch
(
chromosomes
,
decoder
,
machines
);
public
Chromosome
batchSearchGetMax
(
List
<
Chromosome
>
chromosomes
,
VariableNeighborhoodSearch
vns
,
GeneticDecoder
decoder
,
List
<
Machine
>
machines
)
{
List
<
Chromosome
>
saHcOptimized
=
batchSearch
(
chromosomes
,
vns
,
decoder
,
machines
);
int
bestidx
=
Getbest
(
saHcOptimized
,
null
);
if
(
bestidx
>-
1
)
{
...
...
@@ -72,17 +93,18 @@ private Map<String, Entry> entrys;
* 模拟退火搜索,当温度降低到一定程度后切换到爬山法
* 流程:模拟退火全局探索(按概率接受劣解)→ 降温 → 温度低时爬山法局部求精 → 输出最优
*/
public
Chromosome
searchWithHillClimbing
(
Chromosome
chromosome
,
GeneticDecoder
decoder
,
List
<
Machine
>
machines
)
{
FileHelper
.
writeLogFile
(
"模拟退火+爬山法 - 开始执行"
);
public
Chromosome
searchWithHillClimbing
(
Chromosome
chromosome
,
VariableNeighborhoodSearch
vns
,
GeneticDecoder
decoder
,
List
<
Machine
>
machines
)
{
log
(
"模拟退火+爬山法 - 开始执行"
,
true
);
Chromosome
current
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
Chromosome
best
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
writeKpi
(
best
);
// 初始化解码
// 记录初始KPI用于计算改进率
double
[]
initialFitnessLevel
=
best
.
getFitnessLevel
().
clone
();
double
initialFitness
=
best
.
getFitness
();
// FileHelper.writeLogFile
("模拟退火+爬山法 - 初始化解码完成");
// log
("模拟退火+爬山法 - 初始化解码完成");
// 初始化温度
double
temperature
=
100.0
;
...
...
@@ -90,19 +112,26 @@ private Map<String, Entry> entrys;
double
temperatureThreshold
=
1.0
;
int
maxIterations
=
300
;
int
noImproveCount
=
0
;
int
maxNoImprove
=
50
;
int
maxNoImprove
=
30
;
// 降低最大无改进次数
// 新增:改进率监控参数
int
stagnantWindow
=
15
;
// 观察窗口大小
int
[]
recentImprovements
=
new
int
[
stagnantWindow
];
// 记录最近窗口内的改进情况
double
improvementRateThreshold
=
0.05
;
// 改进率阈值(5%)
FileHelper
.
writeLogFile
(
String
.
format
(
"模拟退火+爬山法 - 参数配置:温度=%.1f, 降温率=%.2f, 阈值=%.1f, 最大迭代
=%d"
,
temperature
,
coolingRate
,
temperatureThreshold
,
maxIterations
));
log
(
String
.
format
(
"模拟退火+爬山法 - 参数配置:温度=%.1f, 降温率=%.2f, 阈值=%.1f, 最大迭代=%d, 最大无改进
=%d"
,
temperature
,
coolingRate
,
temperatureThreshold
,
maxIterations
,
maxNoImprove
));
int
acceptCount
=
0
;
int
improveCount
=
0
;
int
totalIterations
=
0
;
for
(
int
i
=
0
;
i
<
maxIterations
;
i
++)
{
totalIterations
=
i
+
1
;
boolean
improved
=
false
;
// 1. 使用智能策略生成邻域解(找瓶颈工序/设备)
Chromosome
neighbor
=
generateNeighbor
(
current
);
Chromosome
neighbor
=
vns
.
generateNeighbor
(
current
);
// 2. 解码
decode
(
decoder
,
neighbor
,
machines
);
...
...
@@ -124,7 +153,10 @@ private Map<String, Entry> entrys;
improved
=
true
;
improveCount
++;
noImproveCount
=
0
;
FileHelper
.
writeLogFile
(
String
.
format
(
"模拟退火+爬山法 - 迭代%d:找到更优解,fitness=%.4f"
,
i
,
best
.
getFitness
()));
// 记录改进详情
logImprovementDetails
(
best
,
initialFitnessLevel
,
initialFitness
,
totalIterations
);
log
(
String
.
format
(
"模拟退火+爬山法 - 迭代%d:找到更优解,fitness=%.4f"
,
totalIterations
,
best
.
getFitness
()),
true
);
}
}
...
...
@@ -132,36 +164,247 @@ private Map<String, Entry> entrys;
noImproveCount
++;
}
// 记录本次改进情况
if
(
totalIterations
<=
stagnantWindow
)
{
recentImprovements
[
totalIterations
-
1
]
=
improved
?
1
:
0
;
}
// 5. 降温
temperature
*=
coolingRate
;
// 每50次迭代输出一次状态
if
((
i
+
1
)
%
50
==
0
)
{
FileHelper
.
writeLogFile
(
String
.
format
(
"模拟退火+爬山法 - 迭代%d/%d:温度=%.4f, 接受数=%d, 改进数=%d, 无改进连续=%d"
,
i
+
1
,
maxIterations
,
temperature
,
acceptCount
,
improveCount
,
noImproveCount
));
// 每30次迭代输出一次状态
if
((
totalIterations
)
%
30
==
0
)
{
log
(
String
.
format
(
"模拟退火+爬山法 - 迭代%d/%d:温度=%.4f, 接受数=%d, 改进数=%d, 无改进连续=%d, 总改进率=%.2f%%"
,
totalIterations
,
maxIterations
,
temperature
,
acceptCount
,
improveCount
,
noImproveCount
,
totalIterations
>
0
?
(
double
)
improveCount
/
totalIterations
*
100
:
0
));
}
// 6. 提前停止条件
boolean
shouldStop
=
false
;
String
stopReason
=
""
;
if
(
temperature
<
temperatureThreshold
)
{
shouldStop
=
true
;
stopReason
=
"温度低于阈值"
;
}
else
if
(
noImproveCount
>=
maxNoImprove
)
{
shouldStop
=
true
;
stopReason
=
String
.
format
(
"连续无改进达到上限(%d次)"
,
maxNoImprove
);
}
else
if
(
totalIterations
>=
stagnantWindow
)
{
// 检查改进率是否过低
double
recentImproveRate
=
calculateRecentImprovementRate
(
recentImprovements
,
stagnantWindow
);
if
(
recentImproveRate
<
improvementRateThreshold
)
{
shouldStop
=
true
;
stopReason
=
String
.
format
(
"最近%d次迭代改进率过低(%.2f%%)"
,
stagnantWindow
,
recentImproveRate
*
100
);
}
}
// 6. 提前停止条件:温度低于阈值 或 连续多次没改进
if
(
temperature
<
temperatureThreshold
||
noImproveCount
>=
maxNoImprove
)
{
String
stopReason
=
temperature
<
temperatureThreshold
?
"温度低于阈值"
:
"连续无改进达到上限"
;
FileHelper
.
writeLogFile
(
String
.
format
(
"模拟退火+爬山法 - 提前停止:%s,迭代%d次,最终温度=%.4f"
,
stopReason
,
i
+
1
,
temperature
));
if
(
shouldStop
)
{
log
(
String
.
format
(
"模拟退火+爬山法 - 提前停止:%s,迭代%d次,最终温度=%.4f"
,
stopReason
,
totalIterations
,
temperature
));
logFinalSummary
(
best
,
initialFitnessLevel
,
initialFitness
,
improveCount
,
totalIterations
);
FileHelper
.
writeLogFile
(
"模拟退火+爬山法 - 切换到爬山法求精"
);
HillClimbing
hillClimbing
=
new
HillClimbing
(
allOperations
);
log
(
"模拟退火+爬山法 - 切换到爬山法求精"
);
HillClimbing
hillClimbing
=
new
HillClimbing
(
allOperations
,
orders
,
materials
,
_entryRel
,
fitnessCalculator
);
Chromosome
refined
=
hillClimbing
.
search
(
best
,
decoder
,
machines
);
FileHelper
.
writeLogFile
(
"模拟退火+爬山法 - 爬山法求精完成"
);
log
(
"模拟退火+爬山法 - 爬山法求精完成"
);
return
refined
;
}
}
FileHelper
.
writeLogFile
(
String
.
format
(
"模拟退火+爬山法 - 完成所有%d次迭代,最终fitness=%.4f"
,
maxIterations
,
best
.
getFitness
()));
log
(
String
.
format
(
"模拟退火+爬山法 - 完成所有%d次迭代,最终fitness=%.4f"
,
maxIterations
,
best
.
getFitness
()),
true
);
logFinalSummary
(
best
,
initialFitnessLevel
,
initialFitness
,
improveCount
,
totalIterations
);
// 7. 输出全局最优排产
return
best
;
}
/**
* 模拟退火搜索
* 流程:模拟退火全局探索(按概率接受劣解)→ 降温 → 输出最优
*/
public
Chromosome
search
(
Chromosome
chromosome
,
TabuSearch
tabusearch
,
VariableNeighborhoodSearch
vns
,
GeneticDecoder
decoder
,
List
<
Machine
>
machines
)
{
log
(
"模拟退火 - 开始执行"
,
true
);
Chromosome
current
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
decode
(
decoder
,
current
,
machines
);
Chromosome
best
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
writeKpi
(
best
);
// 初始化解码
// 记录初始KPI用于计算改进率
double
[]
initialFitnessLevel
=
best
.
getFitnessLevel
().
clone
();
double
initialFitness
=
best
.
getFitness
();
// log("模拟退火+爬山法 - 初始化解码完成");
// 初始化温度
double
temperature
=
100.0
;
double
coolingRate
=
0.95
;
double
temperatureThreshold
=
1.0
;
int
maxIterations
=
300
;
int
noImproveCount
=
0
;
int
maxNoImprove
=
20
;
// 降低最大无改进次数,更快提前结束
// 新增:改进率监控参数
int
stagnantWindow
=
10
;
// 观察窗口大小
int
[]
recentImprovements
=
new
int
[
stagnantWindow
];
// 记录最近窗口内的改进情况
double
improvementRateThreshold
=
0.001
;
// 改进率阈值
log
(
String
.
format
(
"模拟退火 - 参数配置:温度=%.1f, 降温率=%.2f, 阈值=%.1f, 最大迭代=%d, 最大无改进=%d"
,
temperature
,
coolingRate
,
temperatureThreshold
,
maxIterations
,
maxNoImprove
));
int
acceptCount
=
0
;
int
improveCount
=
0
;
int
totalIterations
=
0
;
for
(
int
i
=
0
;
i
<
maxIterations
;
i
++)
{
totalIterations
=
i
+
1
;
boolean
improved
=
false
;
log
(
String
.
format
(
"模拟退火 - 迭代%d:"
,
totalIterations
));
// 1. 使用智能策略生成邻域解(找瓶颈工序/设备)
Chromosome
neighbor
=
vns
.
generateNeighbor
(
current
);
// 2. 解码
decode
(
decoder
,
neighbor
,
machines
);
// 跳过禁忌解(除非是最优解)
if
(
tabusearch
.
isTabu
(
neighbor
.
getGeneStr
())
&&
!
isBetter
(
current
,
best
))
{
temperature
*=
coolingRate
;
noImproveCount
++;
// 记录本次无改进
if
(
totalIterations
<=
stagnantWindow
)
{
recentImprovements
[
totalIterations
-
1
]
=
0
;
}
continue
;
}
// 3. 计算能量差
double
energyDifference
=
calculateEnergyDifference
(
neighbor
,
current
);
// 4. 按概率接受新解(模拟退火核心:有概率接受劣解)
boolean
accepted
=
false
;
if
(
energyDifference
>
0
||
rnd
.
nextDouble
()
<
Math
.
exp
(
energyDifference
/
temperature
))
{
current
=
neighbor
;
acceptCount
++;
if
(
isBetter
(
current
,
best
))
{
best
=
ProductionDeepCopyUtil
.
deepCopy
(
current
,
Chromosome
.
class
);
tabusearch
.
addToTabuList
(
best
.
getGeneStr
());
writeKpi
(
best
);
improved
=
true
;
improveCount
++;
noImproveCount
=
0
;
// 记录改进详情
logImprovementDetails
(
best
,
initialFitnessLevel
,
initialFitness
,
totalIterations
);
log
(
String
.
format
(
"模拟退火 - 迭代%d:找到更优解,fitness=%.4f"
,
totalIterations
,
best
.
getFitness
()));
}
}
if
(!
improved
)
{
noImproveCount
++;
}
// 记录本次改进情况
if
(
totalIterations
<=
stagnantWindow
)
{
recentImprovements
[
totalIterations
-
1
]
=
improved
?
1
:
0
;
}
// 5. 降温
temperature
*=
coolingRate
;
// 每次迭代都输出状态
log
(
String
.
format
(
"模拟退火 - 迭代%d/%d:温度=%.4f, 接受数=%d, 改进数=%d, 无改进连续=%d, 总改进率=%.2f%%"
,
totalIterations
,
maxIterations
,
temperature
,
acceptCount
,
improveCount
,
noImproveCount
,
totalIterations
>
0
?
(
double
)
improveCount
/
totalIterations
*
100
:
0
));
// 6. 检查提前停止条件
boolean
shouldStop
=
false
;
String
stopReason
=
""
;
if
(
temperature
<
temperatureThreshold
)
{
shouldStop
=
true
;
stopReason
=
"温度低于阈值"
;
}
else
if
(
noImproveCount
>=
maxNoImprove
)
{
shouldStop
=
true
;
stopReason
=
String
.
format
(
"连续无改进达到上限(%d次)"
,
maxNoImprove
);
}
else
if
(
totalIterations
>=
stagnantWindow
)
{
// 检查改进率是否过低
double
recentImproveRate
=
calculateRecentImprovementRate
(
recentImprovements
,
stagnantWindow
);
if
(
recentImproveRate
<
improvementRateThreshold
)
{
shouldStop
=
true
;
stopReason
=
String
.
format
(
"最近%d次迭代改进率过低(%.2f%%)"
,
stagnantWindow
,
recentImproveRate
*
100
);
}
}
if
(
shouldStop
)
{
log
(
String
.
format
(
"模拟退火 - 提前停止:%s,迭代%d次,最终温度=%.4f"
,
stopReason
,
totalIterations
,
temperature
));
logFinalSummary
(
best
,
initialFitnessLevel
,
initialFitness
,
improveCount
,
totalIterations
);
return
best
;
}
}
log
(
String
.
format
(
"模拟退火 - 完成所有%d次迭代,最终fitness=%.4f"
,
maxIterations
,
best
.
getFitness
()),
true
);
logFinalSummary
(
best
,
initialFitnessLevel
,
initialFitness
,
improveCount
,
totalIterations
);
// 7. 输出全局最优排产
return
best
;
}
/**
* 记录改进详情
*/
private
void
logImprovementDetails
(
Chromosome
best
,
double
[]
initialFitnessLevel
,
double
initialFitness
,
int
iteration
)
{
StringBuilder
sb
=
new
StringBuilder
(
"模拟退火 - 改进详情: 迭代"
+
iteration
+
", "
);
double
[]
currentFitness
=
best
.
getFitnessLevel
();
for
(
int
i
=
0
;
i
<
currentFitness
.
length
;
i
++)
{
double
improvement
=
currentFitness
[
i
]
-
initialFitnessLevel
[
i
];
sb
.
append
(
String
.
format
(
"KPI%d: %.4f→%.4f(+%.4f) "
,
i
+
1
,
initialFitnessLevel
[
i
],
currentFitness
[
i
],
improvement
));
}
double
totalImprovement
=
best
.
getFitness
()
-
initialFitness
;
sb
.
append
(
String
.
format
(
"总Fitness: %.4f→%.4f(+%.4f)"
,
initialFitness
,
best
.
getFitness
(),
totalImprovement
));
log
(
sb
.
toString
());
}
/**
* 计算最近改进率
*/
private
double
calculateRecentImprovementRate
(
int
[]
recentImprovements
,
int
windowSize
)
{
int
improveCount
=
0
;
for
(
int
i
=
0
;
i
<
windowSize
;
i
++)
{
improveCount
+=
recentImprovements
[
i
];
}
return
(
double
)
improveCount
/
windowSize
;
}
/**
* 记录最终总结
*/
private
void
logFinalSummary
(
Chromosome
best
,
double
[]
initialFitnessLevel
,
double
initialFitness
,
int
improveCount
,
int
totalIterations
)
{
StringBuilder
sb
=
new
StringBuilder
(
"模拟退火 - 最终总结: "
);
double
[]
currentFitness
=
best
.
getFitnessLevel
();
sb
.
append
(
String
.
format
(
"总迭代%d次, 成功改进%d次, 改进率%.2f%%. "
,
totalIterations
,
improveCount
,
totalIterations
>
0
?
(
double
)
improveCount
/
totalIterations
*
100
:
0
));
for
(
int
i
=
0
;
i
<
currentFitness
.
length
;
i
++)
{
double
improvement
=
currentFitness
[
i
]
-
initialFitnessLevel
[
i
];
sb
.
append
(
String
.
format
(
"KPI%d: %.4f→%.4f(%.2f%%) "
,
i
+
1
,
initialFitnessLevel
[
i
],
currentFitness
[
i
],
initialFitnessLevel
[
i
]
>
0
?
improvement
/
initialFitnessLevel
[
i
]
*
100
:
0
));
}
double
totalImprovement
=
best
.
getFitness
()
-
initialFitness
;
sb
.
append
(
String
.
format
(
"总Fitness: %.4f→%.4f(%.2f%%)"
,
initialFitness
,
best
.
getFitness
(),
initialFitness
>
0
?
totalImprovement
/
initialFitness
*
100
:
0
));
log
(
sb
.
toString
());
}
private
void
writeKpi
(
Chromosome
chromosome
)
{
String
fitness
=
""
;
double
[]
fitness1
=
chromosome
.
getFitnessLevel
();
...
...
@@ -170,7 +413,7 @@ private Map<String, Entry> entrys;
fitness
+=
fitness1
[
i
]
+
","
;
}
FileHelper
.
writeLogFile
(
String
.
format
(
"爬山法 - kpi:%s"
,
fitness
)
);
log
(
String
.
format
(
"模拟退火 - kpi:%s"
,
fitness
),
true
);
}
...
...
@@ -221,66 +464,7 @@ private Map<String, Entry> entrys;
return
filteredGroups
;
}
/**
* 构建位置索引:groupId_sequence -> position
*/
private
Map
<
String
,
Integer
>
buildPositionIndex
(
Chromosome
chromosome
)
{
Map
<
String
,
Integer
>
index
=
new
HashMap
<>();
List
<
Integer
>
os
=
chromosome
.
getOperationSequencing
();
Map
<
Integer
,
Integer
>
orderProcessCounter
=
new
HashMap
<>();
for
(
int
i
=
0
;
i
<
os
.
size
();
i
++)
{
int
groupId
=
os
.
get
(
i
);
int
count
=
orderProcessCounter
.
getOrDefault
(
groupId
,
0
)
+
1
;
orderProcessCounter
.
put
(
groupId
,
count
);
String
key
=
groupId
+
"_"
+
count
;
index
.
put
(
key
,
i
);
}
return
index
;
}
/**
* 构建位置索引:groupId_sequence -> Machines position
*/
private
Map
<
String
,
Integer
>
buildEntryMachinePositionIndex
(
Chromosome
chromosome
)
{
Map
<
String
,
Integer
>
index
=
new
HashMap
<>();
List
<
GlobalOperationInfo
>
globalOpList
=
chromosome
.
getGlobalOpList
();
for
(
int
i
=
0
;
i
<
globalOpList
.
size
();
i
++)
{
GlobalOperationInfo
globalOp
=
globalOpList
.
get
(
i
);
Entry
op
=
globalOp
.
getOp
();
int
groupId
=
op
.
getGroupId
();
int
count
=
op
.
getSequence
();
String
key
=
groupId
+
"_"
+
count
;
index
.
put
(
key
,
i
);
}
return
index
;
}
/**
* 构建位置->Entry索引
*/
private
Map
<
Integer
,
Entry
>
buildPositionToEntryIndex
(
Chromosome
chromosome
,
Map
<
String
,
Entry
>
entrys
)
{
Map
<
Integer
,
Entry
>
index
=
new
HashMap
<>();
List
<
Integer
>
os
=
chromosome
.
getOperationSequencing
();
Map
<
Integer
,
Integer
>
orderProcessCounter
=
new
HashMap
<>();
for
(
int
i
=
0
;
i
<
os
.
size
();
i
++)
{
int
groupId
=
os
.
get
(
i
);
int
count
=
orderProcessCounter
.
getOrDefault
(
groupId
,
0
)
+
1
;
orderProcessCounter
.
put
(
groupId
,
count
);
String
key
=
groupId
+
"_"
+
count
;
Entry
op
=
entrys
.
get
(
key
);
if
(
op
!=
null
)
{
index
.
put
(
i
,
op
);
}
}
return
index
;
}
/**
* 构建Entry索引:op.getGroupId() + "_" + op.getSequence() -> Entry
*/
...
...
@@ -302,543 +486,8 @@ private Map<String, Entry> entrys;
}
/**
* 生成邻域解 - 智能策略:优先处理瓶颈工序/设备
* 策略:
* 1. 优先处理瓶颈设备上的工序(换设备)
* 2. 瓶颈设备上的工序往前移动
* 3. 非瓶颈设备上的工序往后移动(给瓶颈工序腾位置)
*/
private
Chromosome
generateNeighbor
(
Chromosome
chromosome
)
{
List
<
GAScheduleResult
>
results
=
chromosome
.
getResult
();
if
(
results
==
null
||
results
.
isEmpty
())
{
return
generateRandomNeighbor
(
chromosome
,
entrys
);
}
// 构建位置索引
Map
<
String
,
Integer
>
positionIndex
=
buildPositionIndex
(
chromosome
);
Map
<
Integer
,
Entry
>
positionToEntryIndex
=
buildPositionToEntryIndex
(
chromosome
,
entrys
);
Map
<
String
,
Integer
>
MachinePositionIndex
=
buildEntryMachinePositionIndex
(
chromosome
);
// 1. 找出瓶颈设备
Long
bottleneckMachineId
=
findBottleneckMachine
(
chromosome
);
if
(
bottleneckMachineId
!=
null
)
{
// 找出瓶颈设备上的工序
List
<
GAScheduleResult
>
bottleneckOps
=
findOpsOnBottleneckMachine
(
chromosome
,
bottleneckMachineId
);
if
(!
bottleneckOps
.
isEmpty
())
{
// 70%概率优先处理瓶颈设备
if
(
rnd
.
nextDouble
()
<
0.7
)
{
int
strategy
=
rnd
.
nextInt
(
10
);
if
(
strategy
<=
3
)
{
// 策略1:瓶颈设备上的工序换设备
return
tryChangeMachineForBottleneckOp
(
chromosome
,
bottleneckOps
,
entrys
,
MachinePositionIndex
);
}
else
if
(
strategy
<=
8
)
{
// 策略2:瓶颈设备上的工序往前移动
return
tryMoveBottleneckOpForward
(
chromosome
,
bottleneckOps
,
positionIndex
,
positionToEntryIndex
,
entrys
);
}
else
if
(
strategy
<=
10
)
{
// 策略3:非瓶颈设备上的工序往后移动
return
tryMoveNonBottleneckOpBackward
(
chromosome
,
bottleneckMachineId
,
positionIndex
,
positionToEntryIndex
,
entrys
);
}
}
}
}
// 默认策略:随机邻域
return
generateRandomNeighbor
(
chromosome
,
entrys
);
}
/**
* 识别瓶颈设备(利用率最高的设备)
*/
private
Long
findBottleneckMachine
(
Chromosome
chromosome
)
{
Map
<
Long
,
Double
>
utilization
=
calculateMachineUtilization
(
chromosome
);
if
(
utilization
.
isEmpty
())
{
return
null
;
}
return
utilization
.
entrySet
().
stream
()
.
max
(
Map
.
Entry
.
comparingByValue
())
.
map
(
Map
.
Entry
::
getKey
)
.
orElse
(
null
);
}
/**
* 查找在瓶颈设备上的工序
*/
private
List
<
GAScheduleResult
>
findOpsOnBottleneckMachine
(
Chromosome
chromosome
,
Long
bottleneckMachineId
)
{
if
(
bottleneckMachineId
==
null
)
{
return
new
ArrayList
<>();
}
return
chromosome
.
getResult
().
stream
()
.
filter
(
r
->
r
.
getMachineId
()
==
bottleneckMachineId
)
.
collect
(
Collectors
.
toList
());
}
/**
* 计算设备利用率
*/
private
Map
<
Long
,
Double
>
calculateMachineUtilization
(
Chromosome
chromosome
)
{
Map
<
Long
,
Double
>
utilization
=
new
HashMap
<>();
List
<
GAScheduleResult
>
results
=
chromosome
.
getResult
();
if
(
results
==
null
||
results
.
isEmpty
())
{
return
utilization
;
}
int
maxEndTime
=
results
.
stream
()
.
mapToInt
(
GAScheduleResult:
:
getEndTime
)
.
max
()
.
orElse
(
1
);
Map
<
Long
,
List
<
GAScheduleResult
>>
machineResults
=
results
.
stream
()
.
collect
(
Collectors
.
groupingBy
(
GAScheduleResult:
:
getMachineId
));
for
(
Map
.
Entry
<
Long
,
List
<
GAScheduleResult
>>
entry
:
machineResults
.
entrySet
())
{
long
machineId
=
entry
.
getKey
();
List
<
GAScheduleResult
>
machineOps
=
entry
.
getValue
();
int
totalProcessingTime
=
machineOps
.
stream
()
.
mapToInt
(
r
->
r
.
getEndTime
()
-
r
.
getStartTime
())
.
sum
();
double
util
=
(
double
)
totalProcessingTime
/
maxEndTime
;
utilization
.
put
(
machineId
,
util
);
}
return
utilization
;
}
/**
* 尝试给瓶颈设备上的工序换设备
*/
private
Chromosome
tryChangeMachineForBottleneckOp
(
Chromosome
chromosome
,
List
<
GAScheduleResult
>
bottleneckOps
,
Map
<
String
,
Entry
>
entrys
,
Map
<
String
,
Integer
>
MachinePositionIndex
)
{
// 优先选择有多设备选项的工序
List
<
GAScheduleResult
>
candidates
=
bottleneckOps
.
stream
()
.
filter
(
op
->
{
Entry
entry
=
entrybyids
.
get
(
op
.
getOperationId
());
return
entry
!=
null
&&
entry
.
getMachineOptions
().
size
()
>
1
;
})
.
collect
(
Collectors
.
toList
());
if
(
candidates
.
isEmpty
())
{
return
generateRandomNeighbor
(
chromosome
,
entrys
);
}
// 从候选中随机选择一个工序,给它换设备
GAScheduleResult
selectedOp
=
candidates
.
get
(
rnd
.
nextInt
(
candidates
.
size
()));
// 找到这个工序在globalOpList中的位置
int
maPos
=
-
1
;
Entry
entry
=
entrybyids
.
get
(
selectedOp
.
getOperationId
());
if
(
entry
!=
null
&&
entry
.
getMachineOptions
().
size
()
>
1
)
{
maPos
=
MachinePositionIndex
.
get
(
entry
.
getGroupId
()
+
"_"
+
entry
.
getSequence
());
if
(
maPos
>=
0
)
{
return
generateMachineChangeForSpecificOp
(
chromosome
,
entry
.
getMachineOptions
(),
maPos
);
}
}
// 直接换设备
return
generateMachineChangeNeighbor
(
chromosome
);
}
/**
* 给指定位置的工序换设备
*/
private
Chromosome
generateMachineChangeForSpecificOp
(
Chromosome
chromosome
,
List
<
MachineOption
>
machineOptions
,
int
idx
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
ms
=
neighbor
.
getMachineSelection
();
if
(!
ms
.
isEmpty
()
&&
idx
>=
0
&&
idx
<
ms
.
size
())
{
if
(
machineOptions
.
size
()
>
1
)
{
int
currentMachineSeq
=
ms
.
get
(
idx
);
List
<
Integer
>
availableMachines
=
new
ArrayList
<>();
for
(
int
i
=
1
;
i
<=
machineOptions
.
size
();
i
++)
{
if
(
i
!=
currentMachineSeq
)
{
availableMachines
.
add
(
i
);
}
}
if
(!
availableMachines
.
isEmpty
())
{
int
newMachineSeq
=
availableMachines
.
get
(
rnd
.
nextInt
(
availableMachines
.
size
()));
ms
.
set
(
idx
,
newMachineSeq
);
neighbor
.
setMachineSelection
(
ms
);
}
}
}
return
neighbor
;
}
/**
* 尝试将瓶颈设备上的工序往前移动
*/
private
Chromosome
tryMoveBottleneckOpForward
(
Chromosome
chromosome
,
List
<
GAScheduleResult
>
bottleneckOps
,
Map
<
String
,
Integer
>
positionIndex
,
Map
<
Integer
,
Entry
>
positionToEntryIndex
,
Map
<
String
,
Entry
>
entrys
)
{
if
(
bottleneckOps
.
isEmpty
())
{
return
generateSwapNeighbor
(
chromosome
,
entrys
);
}
// 随机选择一个瓶颈工序
// GAScheduleResult randomOp = bottleneckOps.get(rnd.nextInt(bottleneckOps.size()));
// 计算所有订单的完成时间
List
<
GAScheduleResult
>
allResults
=
chromosome
.
getResult
();
Map
<
Integer
,
Integer
>
orderCompletionTimes
=
calculateOrderCompletionTimes
(
allResults
);
// 找出最晚完成的订单(延期候选)
int
latestCompletionTime
=
orderCompletionTimes
.
values
().
stream
()
.
mapToInt
(
Integer:
:
intValue
)
.
max
()
.
orElse
(
0
);
// 按优先级和订单完成时间排序:优先选择高优先级+延期订单的工序
List
<
GAScheduleResult
>
sortedBottleneckOps
=
new
ArrayList
<>(
bottleneckOps
);
sortedBottleneckOps
.
sort
((
a
,
b
)
->
{
Entry
entryA
=
entrybyids
.
get
(
a
.
getOperationId
());
Entry
entryB
=
entrybyids
.
get
(
b
.
getOperationId
());
if
(
entryA
!=
null
&&
entryB
!=
null
)
{
// 首先比较优先级(高优先级在前)
int
priorityCompare
=
Double
.
compare
(
entryB
.
getPriority
(),
entryA
.
getPriority
());
if
(
priorityCompare
!=
0
)
{
return
priorityCompare
;
}
// 优先级相同,比较订单完成时间(晚完成的在前,即更可能延期)
int
endTimeA
=
orderCompletionTimes
.
getOrDefault
(
a
.
getGroupId
(),
0
);
int
endTimeB
=
orderCompletionTimes
.
getOrDefault
(
b
.
getGroupId
(),
0
);
return
Integer
.
compare
(
endTimeB
,
endTimeA
);
}
return
0
;
});
GAScheduleResult
selectedOp
=
sortedBottleneckOps
.
get
(
rnd
.
nextInt
(
Math
.
min
(
5
,
sortedBottleneckOps
.
size
())));
Entry
entry
=
entrybyids
.
get
(
selectedOp
.
getOperationId
())
;
String
key
=
entry
.
getGroupId
()
+
"_"
+
entry
.
getSequence
();
Integer
opPos
=
positionIndex
.
get
(
key
);
if
(
opPos
==
null
||
opPos
<=
0
)
{
return
generateSwapNeighbor
(
chromosome
,
entrys
);
}
// 往前移动1-3步
// int steps = rnd.nextInt(3) + 1;
// return moveOperationForward(chromosome,positionToEntryIndex, opPos, steps);
// 使用插入方式往前移动(1-5步)
int
steps
=
rnd
.
nextInt
(
5
)
+
1
;
return
insertOperationForward
(
chromosome
,
opPos
,
steps
,
entrys
);
}
/**
* 计算每个订单的最后完成时间
*/
private
Map
<
Integer
,
Integer
>
calculateOrderCompletionTimes
(
List
<
GAScheduleResult
>
allResults
)
{
Map
<
Integer
,
Integer
>
orderEndTimes
=
new
HashMap
<>();
for
(
GAScheduleResult
result
:
allResults
)
{
int
groupId
=
result
.
getGroupId
();
int
endTime
=
result
.
getEndTime
();
orderEndTimes
.
put
(
groupId
,
Math
.
max
(
orderEndTimes
.
getOrDefault
(
groupId
,
0
),
endTime
));
}
return
orderEndTimes
;
}
/**
* 尝试将非瓶颈设备上的工序往后移动(给瓶颈工序腾位置)
*/
private
Chromosome
tryMoveNonBottleneckOpBackward
(
Chromosome
chromosome
,
Long
bottleneckMachineId
,
Map
<
String
,
Integer
>
positionIndex
,
Map
<
Integer
,
Entry
>
positionToEntryIndex
,
Map
<
String
,
Entry
>
entrys
)
{
List
<
GAScheduleResult
>
results
=
chromosome
.
getResult
();
if
(
results
==
null
)
{
return
generateSwapNeighbor
(
chromosome
,
entrys
);
}
// 找出非瓶颈设备上的工序
List
<
GAScheduleResult
>
nonBottleneckOps
=
results
.
stream
()
.
filter
(
r
->
r
.
getMachineId
()
!=
bottleneckMachineId
)
.
collect
(
Collectors
.
toList
());
if
(
nonBottleneckOps
.
isEmpty
())
{
return
generateSwapNeighbor
(
chromosome
,
entrys
);
}
// 随机选择一个非瓶颈工序
GAScheduleResult
randomOp
=
nonBottleneckOps
.
get
(
rnd
.
nextInt
(
nonBottleneckOps
.
size
()));
Entry
entry
=
entrybyids
.
get
(
randomOp
.
getOperationId
());
String
key
=
entry
.
getGroupId
()+
"_"
+
entry
.
getSequence
();
Integer
opPos
=
positionIndex
.
get
(
key
);
if
(
opPos
==
null
||
opPos
>=
chromosome
.
getOperationSequencing
().
size
()
-
1
)
{
return
generateSwapNeighbor
(
chromosome
,
entrys
);
}
// 往后移动1-3步
int
steps
=
rnd
.
nextInt
(
3
)
+
1
;
return
moveOperationBackward
(
chromosome
,
positionToEntryIndex
,
opPos
,
steps
);
}
/**
* 将工序往前移动
*/
private
Chromosome
moveOperationForward
(
Chromosome
chromosome
,
Map
<
Integer
,
Entry
>
originalPositionIndex
,
int
pos
,
int
steps
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
pos
<=
0
||
pos
>=
os
.
size
())
{
return
neighbor
;
}
// 获取要移动的工序和目标位置的工序(基于原始chromosome)
Entry
opToMove
=
originalPositionIndex
.
get
(
pos
);
if
(
opToMove
==
null
)
{
return
neighbor
;
}
int
targetPos
=
Math
.
max
(
0
,
pos
-
steps
);
Entry
targetOp
=
originalPositionIndex
.
get
(
targetPos
);
// 检查是否可以交换
if
(
targetOp
!=
null
&&
opToMove
.
getGroupId
()
==
targetOp
.
getGroupId
())
{
return
neighbor
;
}
if
(
targetOp
!=
null
&&
Math
.
abs
(
targetOp
.
getPriority
()
-
opToMove
.
getPriority
())
>
0.001
)
{
return
neighbor
;
}
// 直接交换到目标位置
java
.
util
.
Collections
.
swap
(
os
,
pos
,
targetPos
);
neighbor
.
setOperationSequencing
(
os
);
return
neighbor
;
}
/**
* 将工序往后移动
*/
private
Chromosome
moveOperationBackward
(
Chromosome
chromosome
,
Map
<
Integer
,
Entry
>
originalPositionIndex
,
int
pos
,
int
steps
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
pos
<
0
||
pos
>=
os
.
size
()
-
1
)
{
return
neighbor
;
}
// 获取要移动的工序和目标位置的工序(基于原始chromosome)
Entry
opToMove
=
originalPositionIndex
.
get
(
pos
);
if
(
opToMove
==
null
)
{
return
neighbor
;
}
int
targetPos
=
Math
.
min
(
os
.
size
()
-
1
,
pos
+
steps
);
Entry
targetOp
=
originalPositionIndex
.
get
(
targetPos
);
// 检查是否可以交换
if
(
targetOp
!=
null
&&
opToMove
.
getGroupId
()
==
targetOp
.
getGroupId
())
{
return
neighbor
;
}
if
(
targetOp
!=
null
&&
Math
.
abs
(
targetOp
.
getPriority
()
-
opToMove
.
getPriority
())
>
0.001
)
{
return
neighbor
;
}
// 直接交换到目标位置
java
.
util
.
Collections
.
swap
(
os
,
pos
,
targetPos
);
neighbor
.
setOperationSequencing
(
os
);
return
neighbor
;
}
/**
* 将工序往前插入(不交换,直接插入到目标位置)
*/
private
Chromosome
insertOperationForward
(
Chromosome
chromosome
,
int
pos
,
int
steps
,
Map
<
String
,
Entry
>
entrys
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
pos
<=
0
||
pos
>=
os
.
size
())
{
return
neighbor
;
}
// 获取要移动的工序(基于原始chromosome)
Map
<
Integer
,
Entry
>
originalPositionIndex
=
buildPositionToEntryIndex
(
chromosome
,
entrys
);
Entry
opToMove
=
originalPositionIndex
.
get
(
pos
);
if
(
opToMove
==
null
)
{
return
neighbor
;
}
// 找到最远可以插入的位置(不打破优先级)
int
targetPos
=
Math
.
max
(
0
,
pos
-
steps
);
int
finalTargetPos
=
pos
;
for
(
int
i
=
pos
-
1
;
i
>=
targetPos
;
i
--)
{
Entry
leftOp
=
originalPositionIndex
.
get
(
i
);
if
(
leftOp
!=
null
&&
opToMove
.
getGroupId
()
==
leftOp
.
getGroupId
())
{
break
;
}
if
(
leftOp
!=
null
&&
Math
.
abs
(
leftOp
.
getPriority
()
-
opToMove
.
getPriority
())
>
0.001
)
{
break
;
}
finalTargetPos
=
i
;
}
if
(
finalTargetPos
==
pos
)
{
return
neighbor
;
}
// 执行插入:移除原位置,插入到目标位置
int
value
=
os
.
remove
(
pos
);
os
.
add
(
finalTargetPos
,
value
);
neighbor
.
setOperationSequencing
(
os
);
return
neighbor
;
}
/**
* 随机生成邻域解(兜底策略)
*/
private
Chromosome
generateRandomNeighbor
(
Chromosome
chromosome
,
Map
<
String
,
Entry
>
entrys
)
{
int
neighborType
=
rnd
.
nextInt
(
4
);
switch
(
neighborType
)
{
case
0
:
return
generateSwapNeighbor
(
chromosome
,
entrys
);
case
1
:
return
generateReverseNeighbor
(
chromosome
,
entrys
);
case
2
:
return
generateInsertNeighbor
(
chromosome
,
entrys
);
case
3
:
return
generateMachineChangeNeighbor
(
chromosome
);
default
:
return
generateSwapNeighbor
(
chromosome
,
entrys
);
}
}
/**
* 生成交换邻域解 - 只在相同优先级的工序之间交换
*/
private
Chromosome
generateSwapNeighbor
(
Chromosome
chromosome
,
Map
<
String
,
Entry
>
entrys
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
os
.
size
()
>=
2
)
{
Map
<
Integer
,
Entry
>
positionIndex
=
buildPositionToEntryIndex
(
neighbor
,
entrys
);
int
maxAttempts
=
50
;
for
(
int
attempt
=
0
;
attempt
<
maxAttempts
;
attempt
++)
{
int
idx1
=
rnd
.
nextInt
(
os
.
size
());
int
idx2
=
rnd
.
nextInt
(
os
.
size
());
if
(
idx1
==
idx2
)
continue
;
Entry
op1
=
positionIndex
.
get
(
idx1
);
Entry
op2
=
positionIndex
.
get
(
idx2
);
if
(
op1
!=
null
&&
op2
!=
null
)
{
if
(
Math
.
abs
(
op1
.
getPriority
()
-
op2
.
getPriority
())
<
0.001
)
{
java
.
util
.
Collections
.
swap
(
os
,
idx1
,
idx2
);
neighbor
.
setOperationSequencing
(
os
);
break
;
}
}
}
}
return
neighbor
;
}
/**
* 生成反转邻域解 - 只反转相同优先级的连续工序
*/
private
Chromosome
generateReverseNeighbor
(
Chromosome
chromosome
,
Map
<
String
,
Entry
>
entrys
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
os
.
size
()
>=
2
)
{
Map
<
Integer
,
Entry
>
positionIndex
=
buildPositionToEntryIndex
(
neighbor
,
entrys
);
int
maxAttempts
=
50
;
for
(
int
attempt
=
0
;
attempt
<
maxAttempts
;
attempt
++)
{
int
start
=
rnd
.
nextInt
(
os
.
size
());
int
end
=
rnd
.
nextInt
(
os
.
size
());
if
(
end
<=
start
)
continue
;
Entry
startOp
=
positionIndex
.
get
(
start
);
if
(
startOp
==
null
)
continue
;
double
priority
=
startOp
.
getPriority
();
boolean
allSamePriority
=
true
;
for
(
int
i
=
start
;
i
<=
end
;
i
++)
{
Entry
op
=
positionIndex
.
get
(
i
);
if
(
op
==
null
||
Math
.
abs
(
op
.
getPriority
()
-
priority
)
>
0.001
)
{
allSamePriority
=
false
;
break
;
}
}
if
(
allSamePriority
)
{
java
.
util
.
Collections
.
reverse
(
os
.
subList
(
start
,
end
+
1
));
neighbor
.
setOperationSequencing
(
os
);
break
;
}
}
}
return
neighbor
;
}
/**
* 生成插入邻域解 - 只插入到相同优先级的位置
*/
private
Chromosome
generateInsertNeighbor
(
Chromosome
chromosome
,
Map
<
String
,
Entry
>
entrys
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
os
.
size
()
>=
2
)
{
Map
<
Integer
,
Entry
>
positionIndex
=
buildPositionToEntryIndex
(
neighbor
,
entrys
);
int
maxAttempts
=
50
;
for
(
int
attempt
=
0
;
attempt
<
maxAttempts
;
attempt
++)
{
int
idx1
=
rnd
.
nextInt
(
os
.
size
());
int
idx2
=
rnd
.
nextInt
(
os
.
size
());
if
(
idx1
==
idx2
)
continue
;
Entry
op1
=
positionIndex
.
get
(
idx1
);
Entry
op2
=
positionIndex
.
get
(
idx2
);
if
(
op1
!=
null
&&
op2
!=
null
)
{
if
(
Math
.
abs
(
op1
.
getPriority
()
-
op2
.
getPriority
())
<
0.001
)
{
int
value
=
os
.
remove
(
idx1
);
os
.
add
(
idx2
,
value
);
neighbor
.
setOperationSequencing
(
os
);
break
;
}
}
}
}
return
neighbor
;
}
/**
* 生成机器选择邻域解 - 不受优先级限制
* 解码染色体
*/
private
Chromosome
generateMachineChangeNeighbor
(
Chromosome
chromosome
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
ms
=
neighbor
.
getMachineSelection
();
if
(!
ms
.
isEmpty
())
{
int
idx
=
rnd
.
nextInt
(
ms
.
size
());
GlobalOperationInfo
globalOp
=
chromosome
.
getGlobalOpList
().
get
(
idx
);
Entry
op
=
globalOp
.
getOp
();
if
(
op
.
getMachineOptions
().
size
()
>
1
)
{
int
currentMachineSeq
=
ms
.
get
(
idx
);
List
<
Integer
>
availableMachines
=
new
ArrayList
<>();
for
(
int
i
=
1
;
i
<=
op
.
getMachineOptions
().
size
();
i
++)
{
if
(
i
!=
currentMachineSeq
)
{
availableMachines
.
add
(
i
);
}
}
if
(!
availableMachines
.
isEmpty
())
{
int
newMachineSeq
=
availableMachines
.
get
(
rnd
.
nextInt
(
availableMachines
.
size
()));
ms
.
set
(
idx
,
newMachineSeq
);
neighbor
.
setMachineSelection
(
ms
);
}
}
}
return
neighbor
;
}
/**
* 解码染色体
*/
...
...
@@ -847,24 +496,35 @@ private Map<String, Entry> entrys;
// 假设Machine类有拷贝方法,或使用MapStruct等工具进行映射
chromosome
.
setMachines
(
ProductionDeepCopyUtil
.
deepCopyList
(
machines
,
Machine
.
class
));
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setMachines
(
ProductionDeepCopyUtil
.
deepCopyList
(
machines
,
Machine
.
class
));
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setOrders
(
ProductionDeepCopyUtil
.
deepCopyList
(
new
CopyOnWriteArrayList
<>(
orders
),
Order
.
class
)
);
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setOperatRel
(
ProductionDeepCopyUtil
.
deepCopyList
(
new
CopyOnWriteArrayList
<>(
_entryRel
),
GroupResult
.
class
)
);
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setMaterials
(
ProductionDeepCopyUtil
.
deepCopyList
(
materials
,
Material
.
class
));
// 简单拷贝,实际可能需要深拷贝
decoder
.
decodeChromosomeWithCache
(
chromosome
);
chromosome
.
setAllOperations
(
ProductionDeepCopyUtil
.
deepCopyList
(
new
CopyOnWriteArrayList
<>(
allOperations
),
Entry
.
class
)
);
// 简单拷贝,实际可能需要深拷贝
//chromosome.setObjectiveWeights(_objectiveWeights);
// chromosome.setBaseTime(param.getBaseTime());
// chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝
// _sceneService.saveChromosomeToFile(chromosome, "12345679");
// 加载锁定工单到ResultOld
List
<
GAScheduleResult
>
lockedOrders
=
GlobalCacheUtil
.
get
(
"locked_orders_"
+
chromosome
.
getScenarioID
());
if
(
lockedOrders
!=
null
&&
!
lockedOrders
.
isEmpty
())
{
chromosome
.
setResultOld
(
ProductionDeepCopyUtil
.
deepCopyList
(
lockedOrders
,
GAScheduleResult
.
class
));
log
(
"将 "
+
lockedOrders
.
size
()
+
" 个锁定工单加载到初始种群中"
);
}
else
{
chromosome
.
setResultOld
(
new
CopyOnWriteArrayList
<>());
}
decoder
.
decodeChromosomeWithCache
(
chromosome
,
true
);
}
/**
* 比较两个染色体的优劣(基于fitnessLevel多层次比较)
*/
private
boolean
isBetter
(
Chromosome
c1
,
Chromosome
c2
)
{
for
(
int
i
=
0
;
i
<
c1
.
getFitnessLevel
().
length
;
i
++)
{
double
[]
Fitness1
=
c1
.
getFitnessLevel
();
double
[]
Fitness2
=
c2
.
getFitnessLevel
();
if
(
Fitness1
[
i
]
>
Fitness2
[
i
])
{
return
true
;
}
}
return
false
;
return
fitnessCalculator
.
isBetter
(
c1
,
c2
);
}
private
int
Getbest
(
List
<
Chromosome
>
candidates
,
Chromosome
best
)
{
// 找出最佳候选方案
...
...
src/main/java/com/aps/service/Algorithm/TabuSearch.java
View file @
f2a1529b
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.common.util.FileHelper
;
import
com.aps.common.util.GlobalCacheUtil
;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.entity.Algorithm.*
;
import
com.aps.entity.
basic.Entry
;
import
com.aps.entity.basic.
GlobalParam
;
import
com.aps.entity.
Algorithm.IDAndChildID.GroupResult
;
import
com.aps.entity.basic.
*
;
import
java.util.*
;
import
java.util.concurrent.CopyOnWriteArrayList
;
/**
* 禁忌搜索算法
*/
public
class
TabuSearch
{
private
final
Random
rnd
=
new
Random
();
private
GlobalParam
globalParam
;
private
List
<
Entry
>
allOperations
;
private
List
<
GlobalOperationInfo
>
globalOpList
;
private
FitnessCalculator
fitnessCalculator
;
private
ObjectiveWeights
objectiveWeights
;
private
void
log
(
String
message
)
{
log
(
message
,
false
);
}
private
void
log
(
String
message
,
boolean
enableLogging
)
{
if
(
enableLogging
)
{
FileHelper
.
writeLogFile
(
message
);
}
}
private
FitnessCalculator
fitnessCalculator
;
// 禁忌表
private
List
<
Chromosome
>
tabuList
;
private
List
<
String
>
tabuList
;
private
int
tabuListSize
=
50
;
public
TabuSearch
(
GlobalParam
globalParam
,
List
<
Entry
>
allOperations
,
List
<
GlobalOperationInfo
>
globalOpList
,
FitnessCalculator
fitnessCalculator
,
ObjectiveWeights
objectiveWeights
)
{
this
.
globalParam
=
globalParam
;
this
.
allOperations
=
allOperations
;
this
.
globalOpList
=
globalOpList
;
this
.
fitnessCalculator
=
fitnessCalculator
;
this
.
objectiveWeights
=
objectiveWeights
;
private
List
<
Machine
>
cachedMachines
;
private
List
<
Order
>
cachedOrders
;
private
List
<
GroupResult
>
cachedEntryRel
;
private
List
<
Material
>
cachedMaterials
;
private
List
<
Entry
>
cachedAllOperations
;
// 渴望准则:记录最优解的 fitness
private
double
[]
bestFitness
;
public
TabuSearch
(
List
<
Entry
>
allOperations
,
List
<
Order
>
orders
,
List
<
Material
>
materials
,
List
<
GroupResult
>
entryRel
,
FitnessCalculator
_fitnessCalculator
)
{
this
.
tabuList
=
new
ArrayList
<>();
// 工序越多,禁忌表越长(适配1000+工序)
this
.
tabuListSize
=
Math
.
min
(
50
,
allOperations
.
size
()
/
30
);
fitnessCalculator
=
_fitnessCalculator
;
// 预缓存解码需要的深拷贝列表,避免重复拷贝
cachedAllOperations
=
ProductionDeepCopyUtil
.
deepCopyList
(
new
CopyOnWriteArrayList
<>(
allOperations
),
Entry
.
class
);
cachedOrders
=
ProductionDeepCopyUtil
.
deepCopyList
(
new
CopyOnWriteArrayList
<>(
orders
),
Order
.
class
);
cachedEntryRel
=
ProductionDeepCopyUtil
.
deepCopyList
(
new
CopyOnWriteArrayList
<>(
entryRel
),
GroupResult
.
class
);
cachedMaterials
=
ProductionDeepCopyUtil
.
deepCopyList
(
materials
,
Material
.
class
);
}
/**
* 禁忌搜索
* 禁忌搜索
(优化版)
*/
public
Chromosome
search
(
Chromosome
chromosome
,
GeneticDecoder
decoder
,
ScheduleParams
param
)
{
public
Chromosome
search
(
Chromosome
chromosome
,
VariableNeighborhoodSearch
vns
,
GeneticDecoder
decoder
,
List
<
Machine
>
machines
)
{
log
(
"禁忌搜索 - 开始执行"
,
true
);
Chromosome
current
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
Chromosome
best
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
this
.
bestFitness
=
best
.
getFitnessLevel
().
clone
();
writeKpi
(
best
);
// 记录初始KPI用于计算改进率
double
[]
initialFitnessLevel
=
best
.
getFitnessLevel
().
clone
();
double
initialFitness
=
best
.
getFitness
();
int
iterations
=
0
;
int
maxIterations
=
100
0
;
int
improveCount
=
0
;
int
noImprovementCount
=
0
;
int
maxNoImprovement
=
100
;
int
maxNoImprovement
=
15
;
// 降低到15次无改进则停止
int
maxIterations
=
Math
.
min
(
cachedAllOperations
.
size
(),
80
);
// 降低到最多80次
// 改进率监控
int
stagnantWindow
=
10
;
int
[]
recentImprovements
=
new
int
[
stagnantWindow
];
double
improvementRateThreshold
=
0.1
;
// 10%改进率阈值
// 多样性参数
int
diversificationInterval
=
20
;
// 每20次迭代尝试一次多样化
int
lastDiversificationIteration
=
0
;
while
(
iterations
<
maxIterations
&&
noImprovementCount
<
maxNoImprovement
)
{
// 生成邻域解
List
<
Chromosome
>
neighbors
=
generateNeighbors
(
current
);
log
(
String
.
format
(
"禁忌搜索 - 参数:最大迭代=%d, 最大无改进=%d"
,
maxIterations
,
maxNoImprovement
));
// 过滤禁忌解
List
<
Chromosome
>
validNeighbors
=
filterTabuSolutions
(
neighbors
)
;
for
(
int
i
=
0
;
i
<
maxIterations
;
i
++)
{
iterations
++
;
// 评估所有邻域解
Chromosome
bestNeighbor
=
null
;
double
bestNeighborFitness
=
Double
.
NEGATIVE_INFINITY
;
// 使用 VNS 生成邻域解(成功率排序后的策略)
Chromosome
neighbor
=
vns
.
generateNeighbor
(
current
);
for
(
Chromosome
neighbor
:
validNeighbors
)
{
decode
(
decoder
,
neighbor
,
param
);
if
(
neighbor
.
getFitness
()
>
bestNeighborFitness
)
{
bestNeighborFitness
=
neighbor
.
getFitness
();
bestNeighbor
=
neighbor
;
if
(
neighbor
==
null
)
{
log
(
"禁忌搜索 - 生成邻居失败,跳过"
);
noImprovementCount
++;
// 记录无改进
if
(
iterations
<=
stagnantWindow
)
{
recentImprovements
[
iterations
-
1
]
=
0
;
}
continue
;
}
// 先检查禁忌(不需要解码!只需要 machineSelection 和 operationSequencing)
String
neighborGeneStr
=
neighbor
.
getGeneStr
();
String
currentGeneStr
=
current
.
getGeneStr
();
boolean
isTabu
=
isTabu
(
neighborGeneStr
);
// 方案 1:快速跳过和 current 一样的解(不用解码!)
if
(
neighborGeneStr
.
equals
(
currentGeneStr
))
{
// 和当前解一样,跳过,不用解码
addToTabuList
(
neighborGeneStr
);
noImprovementCount
++;
if
(
iterations
<=
stagnantWindow
)
{
recentImprovements
[
iterations
-
1
]
=
0
;
}
continue
;
}
// 添加到禁忌表(无论是否接受都先记下来)
addToTabuList
(
neighborGeneStr
);
boolean
accept
=
false
;
boolean
isBetterThanBest
=
false
;
boolean
isBetterThanCurrent
=
false
;
// 解码(需要比较 fitness)
decode
(
decoder
,
neighbor
,
machines
);
isBetterThanBest
=
isBetter
(
neighbor
,
best
);
isBetterThanCurrent
=
isBetter
(
neighbor
,
current
);
// 判断是否接受这个邻居
if
(!
isTabu
)
{
// 非禁忌,接受
accept
=
true
;
}
else
if
(
isBetterThanBest
)
{
// 禁忌但比最优解好(渴望准则),接受
log
(
"禁忌搜索 - 触发渴望准则,接受禁忌解"
);
accept
=
true
;
}
// else:禁忌且没有比最优解好,不接受
if
(
bestNeighbor
!=
null
)
{
// 更新当前解
current
=
bestNeighbor
;
boolean
improvedThisIteration
=
false
;
// 更新禁忌表
addToTabuList
(
current
);
if
(
accept
)
{
// 接受这个邻居
current
=
ProductionDeepCopyUtil
.
deepCopy
(
neighbor
,
Chromosome
.
class
);
// 更新最优解
if
(
isBetter
(
current
,
best
))
{
best
=
current
;
if
(
isBetterThanBest
)
{
best
=
ProductionDeepCopyUtil
.
deepCopy
(
current
,
Chromosome
.
class
);
this
.
bestFitness
=
best
.
getFitnessLevel
().
clone
();
writeKpi
(
best
);
noImprovementCount
=
0
;
improveCount
++;
improvedThisIteration
=
true
;
logTabuImprovement
(
best
,
initialFitnessLevel
,
initialFitness
,
iterations
);
log
(
String
.
format
(
"禁忌搜索 - 找到更好解,迭代=%d"
,
iterations
),
true
);
}
else
if
(
isBetterThanCurrent
)
{
// 比当前解好但没有比最优解好
noImprovementCount
=
0
;
improvedThisIteration
=
true
;
}
else
{
// 没有改进
noImprovementCount
++;
}
}
else
{
// 不接受,无改进计数+1
noImprovementCount
++;
}
iterations
++;
}
// 记录本次改进情况
if
(
iterations
<=
stagnantWindow
)
{
recentImprovements
[
iterations
-
1
]
=
improvedThisIteration
?
1
:
0
;
}
return
best
;
}
// 每10次迭代输出一次状态
if
(
iterations
%
10
==
0
)
{
log
(
String
.
format
(
"禁忌搜索 - 迭代%d/%d, 改进数=%d, 无改进连续=%d, 改进率=%.2f%%"
,
iterations
,
maxIterations
,
improveCount
,
noImprovementCount
,
iterations
>
0
?
(
double
)
improveCount
/
iterations
*
100
:
0
));
}
/**
* 生成邻域解
*/
private
List
<
Chromosome
>
generateNeighbors
(
Chromosome
chromosome
)
{
List
<
Chromosome
>
neighbors
=
new
ArrayList
<>();
// 生成多个邻域解
for
(
int
i
=
0
;
i
<
10
;
i
++)
{
int
neighborType
=
rnd
.
nextInt
(
4
);
switch
(
neighborType
)
{
case
0
:
neighbors
.
add
(
generateSwapNeighbor
(
chromosome
));
break
;
case
1
:
neighbors
.
add
(
generateReverseNeighbor
(
chromosome
));
break
;
case
2
:
neighbors
.
add
(
generateInsertNeighbor
(
chromosome
));
break
;
case
3
:
neighbors
.
add
(
generateMachineChangeNeighbor
(
chromosome
));
break
;
// 检查提前停止条件
boolean
shouldStop
=
false
;
String
stopReason
=
""
;
if
(
noImprovementCount
>=
maxNoImprovement
)
{
shouldStop
=
true
;
stopReason
=
String
.
format
(
"连续%d次无改进"
,
maxNoImprovement
);
}
else
if
(
iterations
>=
stagnantWindow
)
{
double
recentImproveRate
=
calculateRecentImprovementRate
(
recentImprovements
,
stagnantWindow
);
if
(
recentImproveRate
<
improvementRateThreshold
)
{
shouldStop
=
true
;
stopReason
=
String
.
format
(
"最近%d次迭代改进率过低(%.2f%%)"
,
stagnantWindow
,
recentImproveRate
*
100
);
}
}
if
(
shouldStop
)
{
log
(
String
.
format
(
"禁忌搜索 - 提前停止:%s"
,
stopReason
));
logTabuFinalSummary
(
best
,
initialFitnessLevel
,
initialFitness
,
iterations
,
improveCount
);
break
;
}
}
return
neighbors
;
logTabuFinalSummary
(
best
,
initialFitnessLevel
,
initialFitness
,
iterations
,
improveCount
);
log
(
String
.
format
(
"禁忌搜索 - 结束,总迭代=%d"
,
iterations
),
true
);
return
best
;
}
private
void
writeKpi
(
Chromosome
chromosome
)
{
String
fitness
=
""
;
double
[]
fitness1
=
chromosome
.
getFitnessLevel
();
for
(
int
i
=
0
;
i
<
fitness1
.
length
;
i
++)
{
/**
* 过滤禁忌解
*/
private
List
<
Chromosome
>
filterTabuSolutions
(
List
<
Chromosome
>
neighbors
)
{
List
<
Chromosome
>
validNeighbors
=
new
ArrayList
<>();
for
(
Chromosome
neighbor
:
neighbors
)
{
if
(!
isTabu
(
neighbor
))
{
validNeighbors
.
add
(
neighbor
);
}
fitness
+=
fitness1
[
i
]
+
","
;
}
// 如果没有有效邻域解,返回所有邻域解
if
(
validNeighbors
.
isEmpty
())
{
return
neighbors
;
}
log
(
String
.
format
(
"变邻域搜索 - kpi:%s"
,
fitness
),
true
);
return
validNeighbors
;
}
/**
*
检查解是否在禁忌表中
*
记录禁忌搜索改进详情
*/
private
boolean
isTabu
(
Chromosome
chromosome
)
{
for
(
Chromosome
tabuChromosome
:
tabuList
)
{
if
(
chromosome
.
getGeneStr
().
equals
(
tabuChromosome
.
getGeneStr
()))
{
return
true
;
}
private
void
logTabuImprovement
(
Chromosome
best
,
double
[]
initialFitnessLevel
,
double
initialFitness
,
int
iteration
)
{
StringBuilder
sb
=
new
StringBuilder
(
"禁忌搜索 - 改进详情: 迭代"
+
iteration
+
", "
);
double
[]
currentFitness
=
best
.
getFitnessLevel
();
for
(
int
i
=
0
;
i
<
currentFitness
.
length
;
i
++)
{
double
improvement
=
currentFitness
[
i
]
-
initialFitnessLevel
[
i
];
sb
.
append
(
String
.
format
(
"KPI%d: %.4f→%.4f(+%.4f) "
,
i
+
1
,
initialFitnessLevel
[
i
],
currentFitness
[
i
],
improvement
));
}
return
false
;
double
totalImprovement
=
best
.
getFitness
()
-
initialFitness
;
sb
.
append
(
String
.
format
(
"总Fitness: %.4f→%.4f(+%.4f)"
,
initialFitness
,
best
.
getFitness
(),
totalImprovement
));
log
(
sb
.
toString
());
}
/**
*
添加解到禁忌表
*
计算最近改进率
*/
private
void
addToTabuList
(
Chromosome
chromosom
e
)
{
tabuList
.
add
(
chromosome
)
;
if
(
tabuList
.
size
()
>
tabuListSize
)
{
tabuList
.
remove
(
0
)
;
private
double
calculateRecentImprovementRate
(
int
[]
recentImprovements
,
int
windowSiz
e
)
{
int
improveCount
=
0
;
for
(
int
i
=
0
;
i
<
windowSize
;
i
++
)
{
improveCount
+=
recentImprovements
[
i
]
;
}
return
(
double
)
improveCount
/
windowSize
;
}
/**
*
生成交换邻域解
*
记录禁忌搜索最终总结
*/
private
Chromosome
generateSwapNeighbor
(
Chromosome
chromosome
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
os
.
size
()
>=
2
)
{
int
idx1
=
rnd
.
nextInt
(
os
.
size
());
int
idx2
=
rnd
.
nextInt
(
os
.
size
());
while
(
idx2
==
idx1
)
{
idx2
=
rnd
.
nextInt
(
os
.
size
());
}
Collections
.
swap
(
os
,
idx1
,
idx2
);
neighbor
.
setOperationSequencing
(
os
);
private
void
logTabuFinalSummary
(
Chromosome
best
,
double
[]
initialFitnessLevel
,
double
initialFitness
,
int
totalIterations
,
int
improveCount
)
{
StringBuilder
sb
=
new
StringBuilder
(
"禁忌搜索 - 最终总结: "
);
double
[]
currentFitness
=
best
.
getFitnessLevel
();
sb
.
append
(
String
.
format
(
"总迭代%d次, 成功改进%d次, 改进率%.2f%%. "
,
totalIterations
,
improveCount
,
totalIterations
>
0
?
(
double
)
improveCount
/
totalIterations
*
100
:
0
));
for
(
int
i
=
0
;
i
<
currentFitness
.
length
;
i
++)
{
double
improvement
=
currentFitness
[
i
]
-
initialFitnessLevel
[
i
];
sb
.
append
(
String
.
format
(
"KPI%d: %.4f→%.4f(%.2f%%) "
,
i
+
1
,
initialFitnessLevel
[
i
],
currentFitness
[
i
],
initialFitnessLevel
[
i
]
>
0
?
improvement
/
initialFitnessLevel
[
i
]
*
100
:
0
));
}
return
neighbor
;
}
double
totalImprovement
=
best
.
getFitness
()
-
initialFitness
;
sb
.
append
(
String
.
format
(
"总Fitness: %.4f→%.4f(%.2f%%)"
,
initialFitness
,
best
.
getFitness
(),
initialFitness
>
0
?
totalImprovement
/
initialFitness
*
100
:
0
));
log
(
sb
.
toString
());
}
/**
*
生成反转邻域解
*
检查解是否在禁忌表中
*/
private
Chromosome
generateReverseNeighbor
(
Chromosome
chromosome
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
os
.
size
()
>=
2
)
{
int
start
=
rnd
.
nextInt
(
os
.
size
());
int
end
=
rnd
.
nextInt
(
os
.
size
());
while
(
end
<=
start
)
{
end
=
rnd
.
nextInt
(
os
.
size
());
}
Collections
.
reverse
(
os
.
subList
(
start
,
end
+
1
));
neighbor
.
setOperationSequencing
(
os
);
}
return
neighbor
;
public
boolean
isTabu
(
String
GeneStr
)
{
return
tabuList
.
contains
(
GeneStr
);
}
/**
*
生成插入邻域解
*
添加解到禁忌表(FIFO策略)
*/
private
Chromosome
generateInsertNeighbor
(
Chromosome
chromosome
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
os
.
size
()
>=
2
)
{
int
idx1
=
rnd
.
nextInt
(
os
.
size
());
int
idx2
=
rnd
.
nextInt
(
os
.
size
());
while
(
idx2
==
idx1
)
{
idx2
=
rnd
.
nextInt
(
os
.
size
());
}
int
value
=
os
.
remove
(
idx1
);
os
.
add
(
idx2
,
value
);
neighbor
.
setOperationSequencing
(
os
);
public
void
addToTabuList
(
String
geneStr
)
{
tabuList
.
add
(
geneStr
);
if
(
tabuList
.
size
()
>
tabuListSize
)
{
// 移除最早加入的禁忌解
tabuList
.
remove
(
0
);
}
return
neighbor
;
}
/**
* 生成机器选择邻域解
*/
private
Chromosome
generateMachineChangeNeighbor
(
Chromosome
chromosome
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
ms
=
neighbor
.
getMachineSelection
();
if
(!
ms
.
isEmpty
())
{
int
idx
=
rnd
.
nextInt
(
ms
.
size
());
GlobalOperationInfo
globalOp
=
globalOpList
.
get
(
idx
);
Entry
op
=
globalOp
.
getOp
();
if
(
op
.
getMachineOptions
().
size
()
>
1
)
{
int
currentMachineSeq
=
ms
.
get
(
idx
);
List
<
Integer
>
availableMachines
=
new
ArrayList
<>();
for
(
int
i
=
1
;
i
<=
op
.
getMachineOptions
().
size
();
i
++)
{
if
(
i
!=
currentMachineSeq
)
{
availableMachines
.
add
(
i
);
}
}
if
(!
availableMachines
.
isEmpty
()
)
{
int
newMachineSeq
=
availableMachines
.
get
(
rnd
.
nextInt
(
availableMachines
.
size
()
));
ms
.
set
(
idx
,
newMachineSeq
);
neighbor
.
setMachineSelection
(
ms
);
}
}
private
void
decode
(
GeneticDecoder
decoder
,
Chromosome
chromosome
,
List
<
Machine
>
machines
)
{
chromosome
.
setResult
(
new
CopyOnWriteArrayList
<>(
));
// 缓存 Machine 列表(第一次调用时缓存)
if
(
cachedMachines
==
null
)
{
cachedMachines
=
ProductionDeepCopyUtil
.
deepCopyList
(
machines
,
Machine
.
class
);
}
return
neighbor
;
}
/**
* 解码染色体
*/
private
void
decode
(
GeneticDecoder
decoder
,
Chromosome
chromosome
,
ScheduleParams
param
)
{
chromosome
.
setResult
(
new
java
.
util
.
concurrent
.
CopyOnWriteArrayList
<>());
decoder
.
decodeChromosomeWithCache
(
chromosome
);
if
(
chromosome
.
getFitness
()
==
0
)
{
chromosome
.
setFitness
(
fitnessCalculator
.
calculateFitness
(
chromosome
,
objectiveWeights
));
// 使用缓存的列表,避免重复深拷贝
chromosome
.
setMachines
(
ProductionDeepCopyUtil
.
deepCopyList
(
cachedMachines
,
Machine
.
class
));
chromosome
.
setOrders
(
ProductionDeepCopyUtil
.
deepCopyList
(
new
CopyOnWriteArrayList
<>(
cachedOrders
),
Order
.
class
));
chromosome
.
setOperatRel
(
ProductionDeepCopyUtil
.
deepCopyList
(
new
CopyOnWriteArrayList
<>(
cachedEntryRel
),
GroupResult
.
class
));
chromosome
.
setMaterials
(
ProductionDeepCopyUtil
.
deepCopyList
(
cachedMaterials
,
Material
.
class
));
chromosome
.
setAllOperations
(
ProductionDeepCopyUtil
.
deepCopyList
(
new
CopyOnWriteArrayList
<>(
cachedAllOperations
),
Entry
.
class
));
// 加载锁定工单到ResultOld
List
<
GAScheduleResult
>
lockedOrders
=
GlobalCacheUtil
.
get
(
"locked_orders_"
+
chromosome
.
getScenarioID
());
if
(
lockedOrders
!=
null
&&
!
lockedOrders
.
isEmpty
())
{
chromosome
.
setResultOld
(
ProductionDeepCopyUtil
.
deepCopyList
(
lockedOrders
,
GAScheduleResult
.
class
));
}
else
{
chromosome
.
setResultOld
(
new
CopyOnWriteArrayList
<>());
}
decoder
.
decodeChromosomeWithCache
(
chromosome
,
true
);
}
/**
* 比较两个染色体的优劣
* 比较两个染色体的优劣
(基于fitnessLevel多层次比较)
*/
private
boolean
isBetter
(
Chromosome
c1
,
Chromosome
c2
)
{
return
c1
.
getFitness
()
>
c2
.
getFitness
(
);
return
fitnessCalculator
.
isBetter
(
c1
,
c2
);
}
}
\ No newline at end of file
src/main/java/com/aps/service/Algorithm/TabuSearchWithSA.java
deleted
100644 → 0
View file @
bb00017a
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.entity.Algorithm.*
;
import
com.aps.entity.basic.Entry
;
import
com.aps.entity.basic.GlobalParam
;
import
java.util.*
;
/**
* 禁忌搜索+模拟退火混合算法
*/
public
class
TabuSearchWithSA
{
private
final
Random
rnd
=
new
Random
();
private
GlobalParam
globalParam
;
private
List
<
Entry
>
allOperations
;
private
List
<
GlobalOperationInfo
>
globalOpList
;
private
FitnessCalculator
fitnessCalculator
;
private
ObjectiveWeights
objectiveWeights
;
// 禁忌表
private
List
<
Chromosome
>
tabuList
;
private
int
tabuListSize
=
50
;
public
TabuSearchWithSA
(
GlobalParam
globalParam
,
List
<
Entry
>
allOperations
,
List
<
GlobalOperationInfo
>
globalOpList
,
FitnessCalculator
fitnessCalculator
,
ObjectiveWeights
objectiveWeights
)
{
this
.
globalParam
=
globalParam
;
this
.
allOperations
=
allOperations
;
this
.
globalOpList
=
globalOpList
;
this
.
fitnessCalculator
=
fitnessCalculator
;
this
.
objectiveWeights
=
objectiveWeights
;
this
.
tabuList
=
new
ArrayList
<>();
}
/**
* 禁忌搜索+模拟退火混合搜索
*/
public
Chromosome
search
(
Chromosome
chromosome
,
GeneticDecoder
decoder
,
ScheduleParams
param
)
{
Chromosome
current
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
Chromosome
best
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
// 初始化温度
double
temperature
=
100.0
;
double
coolingRate
=
0.95
;
int
iterations
=
0
;
int
maxIterations
=
1000
;
int
noImprovementCount
=
0
;
int
maxNoImprovement
=
100
;
while
(
iterations
<
maxIterations
&&
noImprovementCount
<
maxNoImprovement
)
{
// 生成邻域解
List
<
Chromosome
>
neighbors
=
generateNeighbors
(
current
);
// 过滤禁忌解
List
<
Chromosome
>
validNeighbors
=
filterTabuSolutions
(
neighbors
);
// 评估所有邻域解
Chromosome
bestNeighbor
=
null
;
double
bestNeighborFitness
=
Double
.
NEGATIVE_INFINITY
;
for
(
Chromosome
neighbor
:
validNeighbors
)
{
decode
(
decoder
,
neighbor
,
param
);
if
(
neighbor
.
getFitness
()
>
bestNeighborFitness
)
{
bestNeighborFitness
=
neighbor
.
getFitness
();
bestNeighbor
=
neighbor
;
}
}
if
(
bestNeighbor
!=
null
)
{
// 计算能量差
decode
(
decoder
,
current
,
param
);
double
energyDifference
=
bestNeighbor
.
getFitness
()
-
current
.
getFitness
();
// 结合模拟退火的概率接受机制
if
(
energyDifference
>
0
||
rnd
.
nextDouble
()
<
Math
.
exp
(
energyDifference
/
temperature
))
{
// 更新当前解
current
=
bestNeighbor
;
// 更新禁忌表
addToTabuList
(
current
);
// 更新最优解
if
(
isBetter
(
current
,
best
))
{
best
=
current
;
noImprovementCount
=
0
;
}
else
{
noImprovementCount
++;
}
}
}
// 降温
temperature
*=
coolingRate
;
iterations
++;
}
return
best
;
}
/**
* 生成邻域解
*/
private
List
<
Chromosome
>
generateNeighbors
(
Chromosome
chromosome
)
{
List
<
Chromosome
>
neighbors
=
new
ArrayList
<>();
// 生成多个邻域解
for
(
int
i
=
0
;
i
<
10
;
i
++)
{
int
neighborType
=
rnd
.
nextInt
(
4
);
switch
(
neighborType
)
{
case
0
:
neighbors
.
add
(
generateSwapNeighbor
(
chromosome
));
break
;
case
1
:
neighbors
.
add
(
generateReverseNeighbor
(
chromosome
));
break
;
case
2
:
neighbors
.
add
(
generateInsertNeighbor
(
chromosome
));
break
;
case
3
:
neighbors
.
add
(
generateMachineChangeNeighbor
(
chromosome
));
break
;
}
}
return
neighbors
;
}
/**
* 过滤禁忌解
*/
private
List
<
Chromosome
>
filterTabuSolutions
(
List
<
Chromosome
>
neighbors
)
{
List
<
Chromosome
>
validNeighbors
=
new
ArrayList
<>();
for
(
Chromosome
neighbor
:
neighbors
)
{
if
(!
isTabu
(
neighbor
))
{
validNeighbors
.
add
(
neighbor
);
}
}
// 如果没有有效邻域解,返回所有邻域解
if
(
validNeighbors
.
isEmpty
())
{
return
neighbors
;
}
return
validNeighbors
;
}
/**
* 检查解是否在禁忌表中
*/
private
boolean
isTabu
(
Chromosome
chromosome
)
{
for
(
Chromosome
tabuChromosome
:
tabuList
)
{
if
(
chromosome
.
getGeneStr
().
equals
(
tabuChromosome
.
getGeneStr
()))
{
return
true
;
}
}
return
false
;
}
/**
* 添加解到禁忌表
*/
private
void
addToTabuList
(
Chromosome
chromosome
)
{
tabuList
.
add
(
chromosome
);
if
(
tabuList
.
size
()
>
tabuListSize
)
{
tabuList
.
remove
(
0
);
}
}
/**
* 生成交换邻域解
*/
private
Chromosome
generateSwapNeighbor
(
Chromosome
chromosome
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
os
.
size
()
>=
2
)
{
int
idx1
=
rnd
.
nextInt
(
os
.
size
());
int
idx2
=
rnd
.
nextInt
(
os
.
size
());
while
(
idx2
==
idx1
)
{
idx2
=
rnd
.
nextInt
(
os
.
size
());
}
Collections
.
swap
(
os
,
idx1
,
idx2
);
neighbor
.
setOperationSequencing
(
os
);
}
return
neighbor
;
}
/**
* 生成反转邻域解
*/
private
Chromosome
generateReverseNeighbor
(
Chromosome
chromosome
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
os
.
size
()
>=
2
)
{
int
start
=
rnd
.
nextInt
(
os
.
size
());
int
end
=
rnd
.
nextInt
(
os
.
size
());
while
(
end
<=
start
)
{
end
=
rnd
.
nextInt
(
os
.
size
());
}
Collections
.
reverse
(
os
.
subList
(
start
,
end
+
1
));
neighbor
.
setOperationSequencing
(
os
);
}
return
neighbor
;
}
/**
* 生成插入邻域解
*/
private
Chromosome
generateInsertNeighbor
(
Chromosome
chromosome
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
os
.
size
()
>=
2
)
{
int
idx1
=
rnd
.
nextInt
(
os
.
size
());
int
idx2
=
rnd
.
nextInt
(
os
.
size
());
while
(
idx2
==
idx1
)
{
idx2
=
rnd
.
nextInt
(
os
.
size
());
}
int
value
=
os
.
remove
(
idx1
);
os
.
add
(
idx2
,
value
);
neighbor
.
setOperationSequencing
(
os
);
}
return
neighbor
;
}
/**
* 生成机器选择邻域解
*/
private
Chromosome
generateMachineChangeNeighbor
(
Chromosome
chromosome
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
ms
=
neighbor
.
getMachineSelection
();
if
(!
ms
.
isEmpty
())
{
int
idx
=
rnd
.
nextInt
(
ms
.
size
());
GlobalOperationInfo
globalOp
=
globalOpList
.
get
(
idx
);
Entry
op
=
globalOp
.
getOp
();
if
(
op
.
getMachineOptions
().
size
()
>
1
)
{
int
currentMachineSeq
=
ms
.
get
(
idx
);
List
<
Integer
>
availableMachines
=
new
ArrayList
<>();
for
(
int
i
=
1
;
i
<=
op
.
getMachineOptions
().
size
();
i
++)
{
if
(
i
!=
currentMachineSeq
)
{
availableMachines
.
add
(
i
);
}
}
if
(!
availableMachines
.
isEmpty
())
{
int
newMachineSeq
=
availableMachines
.
get
(
rnd
.
nextInt
(
availableMachines
.
size
()));
ms
.
set
(
idx
,
newMachineSeq
);
neighbor
.
setMachineSelection
(
ms
);
}
}
}
return
neighbor
;
}
/**
* 解码染色体
*/
private
void
decode
(
GeneticDecoder
decoder
,
Chromosome
chromosome
,
ScheduleParams
param
)
{
chromosome
.
setResult
(
new
java
.
util
.
concurrent
.
CopyOnWriteArrayList
<>());
decoder
.
decodeChromosomeWithCache
(
chromosome
);
if
(
chromosome
.
getFitness
()
==
0
)
{
chromosome
.
setFitness
(
fitnessCalculator
.
calculateFitness
(
chromosome
,
objectiveWeights
));
}
}
/**
* 比较两个染色体的优劣
*/
private
boolean
isBetter
(
Chromosome
c1
,
Chromosome
c2
)
{
return
c1
.
getFitness
()
>
c2
.
getFitness
();
}
}
\ No newline at end of file
src/main/java/com/aps/service/Algorithm/VariableNeighborhoodSearch.java
View file @
f2a1529b
This source diff could not be displayed because it is too large. You can
view the blob
instead.
src/main/java/com/aps/service/plan/PlanResultService.java
View file @
f2a1529b
...
...
@@ -222,7 +222,7 @@ public class PlanResultService {
lockedOrderProcessorService
.
markLockedOrdersOccupiedTime
(
machines
,
timeConfig
.
getBaseTime
());
// 5. 执行调度算法
GeneticAlgorithm
scheduler
=
new
Genetic
Algorithm
(
globalParam
,
machines
,
orders
,
Materials1
,
materialIds
,
machineScheduler
,
entryRel
,
materialRequirementService
,
_sceneService
,
SceneId
);
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
HybridAlgorithm
scheduler
=
new
Hybrid
Algorithm
(
globalParam
,
machines
,
orders
,
Materials1
,
materialIds
,
machineScheduler
,
entryRel
,
materialRequirementService
,
_sceneService
,
SceneId
);
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
param
.
initAdaptiveParams
(
entrys
.
size
());
double
[]
customWeights
=
new
double
[]
{
0.4
,
0.1
,
0.1
,
0.1
,
0.3
};
// 延迟时间权重提升到0.5
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
...
...
@@ -238,7 +238,7 @@ public class PlanResultService {
_sceneService
.
saveChromosomeToFile
(
chromosome
,
SceneId
);
WriteScheduleSummary
(
chromosome
);
//
WriteScheduleSummary(chromosome);
return
chromosome
;
...
...
src/main/java/com/aps/service/plan/SceneService.java
View file @
f2a1529b
...
...
@@ -132,7 +132,7 @@ public class SceneService {
try
{
ObjectMapper
objectMapper
=
createObjectMapper
();
SceneChromsome
sceneChromsome
=(
SceneChromsome
)
redisUtils
.
get
(
"SceneId."
+
sceneId
);
SceneChromsome
sceneChromsome
=
null
;
//
(SceneChromsome)redisUtils.get("SceneId."+sceneId);
if
(
sceneChromsome
==
null
)
{
sceneChromsome
=
new
SceneChromsome
();
...
...
@@ -163,7 +163,7 @@ public class SceneService {
sceneChromsome
.
getSceneDetails
().
add
(
sceneDetail
);
redisUtils
.
set
(
"SceneId."
+
sceneId
,
sceneChromsome
);
//
redisUtils.set("SceneId."+sceneId,sceneChromsome);
File
file
=
getChromosomeFile
(
sceneId
,
sceneChromsome
.
getVersion
().
toString
());
...
...
src/test/java/com/aps/demo/PlanResultServiceTest.java
View file @
f2a1529b
...
...
@@ -39,7 +39,8 @@ public class PlanResultServiceTest {
// TestSortService sortService=new TestSortService();
// sortService.test1();
// nsgaiiUtils.Test();
planResultService
.
execute2
(
"0428340BB4F540938F1FB5599F03E8A4"
);
//2000
planResultService
.
execute2
(
"08B1D87FE1B84ECDBAC2E546DDB6FB81"
);
//2000
// planResultService.execute2("0428340BB4F540938F1FB5599F03E8A4");//2000
// planResultService.execute2("C8B533BD8944405B9A2F8823C575C204");//500
// planResultService.execute2("EFDD34E4B5BC434BAEAE6A84DFCD4E7B");//20
// planResultService.execute2("00E0C5D3E4AD4F36B56C39395906618D");
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment