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
47286670
Commit
47286670
authored
Mar 26, 2026
by
Tong Li
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
算法优化
parent
e56eef9d
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1871 additions
and
412 deletions
+1871
-412
Chromosome.java
src/main/java/com/aps/entity/Algorithm/Chromosome.java
+7
-1
GlobalParam.java
src/main/java/com/aps/entity/basic/GlobalParam.java
+7
-4
ObjectiveConfig.java
src/main/java/com/aps/entity/basic/ObjectiveConfig.java
+10
-0
FitnessCalculator.java
...ain/java/com/aps/service/Algorithm/FitnessCalculator.java
+96
-1
GeneticAlgorithm.java
...main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
+41
-143
GeneticDecoder.java
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
+68
-23
HillClimbing.java
src/main/java/com/aps/service/Algorithm/HillClimbing.java
+519
-26
HybridAlgorithm.java
src/main/java/com/aps/service/Algorithm/HybridAlgorithm.java
+566
-0
Initialization.java
src/main/java/com/aps/service/Algorithm/Initialization.java
+355
-122
ParallelLocalSearch.java
...n/java/com/aps/service/Algorithm/ParallelLocalSearch.java
+4
-4
SimulatedAnnealing.java
...in/java/com/aps/service/Algorithm/SimulatedAnnealing.java
+194
-86
PlanResultService.java
src/main/java/com/aps/service/plan/PlanResultService.java
+1
-1
PlanResultServiceTest.java
src/test/java/com/aps/demo/PlanResultServiceTest.java
+3
-1
No files found.
src/main/java/com/aps/entity/Algorithm/Chromosome.java
View file @
47286670
...
@@ -23,7 +23,7 @@ public class Chromosome {
...
@@ -23,7 +23,7 @@ public class Chromosome {
private
String
ID
=
UUID
.
randomUUID
().
toString
();
private
String
ID
=
UUID
.
randomUUID
().
toString
();
private
String
generateType
;
private
Integer
version
=
0
;
private
Integer
version
=
0
;
...
@@ -117,6 +117,12 @@ public class Chromosome {
...
@@ -117,6 +117,12 @@ public class Chromosome {
*/
*/
private
double
[]
WeightedObjectives
;
//越靠近1越优
private
double
[]
WeightedObjectives
;
//越靠近1越优
private
double
WeightedObjective
=
0
;
// 加权目标值(用于自定义权重)
private
double
WeightedObjective
=
0
;
// 加权目标值(用于自定义权重)
/// <summary>
/// 适应度值
/// </summary>
private
double
[]
fitnessLevel
;
/// <summary>
/// <summary>
/// 适应度值
/// 适应度值
/// </summary>
/// </summary>
...
...
src/main/java/com/aps/entity/basic/GlobalParam.java
View file @
47286670
...
@@ -2,10 +2,7 @@ package com.aps.entity.basic;
...
@@ -2,10 +2,7 @@ package com.aps.entity.basic;
import
lombok.Data
;
import
lombok.Data
;
import
java.util.ArrayList
;
import
java.util.*
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
/**
/**
* 作者:佟礼
* 作者:佟礼
...
@@ -81,6 +78,8 @@ public class GlobalParam {
...
@@ -81,6 +78,8 @@ public class GlobalParam {
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_SETUP_TIME
,
true
,
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_MACHINE_LOAD
,
false
,
3
,
0.1
));
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_TARDINESS
,
true
,
1
,
0.3
));
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_TARDINESS
,
true
,
1
,
0.3
));
objectiveConfigs
.
sort
(
Comparator
.
comparing
((
ObjectiveConfig
op
)
->
op
.
getLevel
()));
}
}
/// <summary>
/// <summary>
...
@@ -146,6 +145,8 @@ public class GlobalParam {
...
@@ -146,6 +145,8 @@ public class GlobalParam {
/// </summary>
/// </summary>
public
void
addObjectiveConfig
(
ObjectiveConfig
config
)
{
public
void
addObjectiveConfig
(
ObjectiveConfig
config
)
{
objectiveConfigs
.
add
(
config
);
objectiveConfigs
.
add
(
config
);
objectiveConfigs
.
sort
(
Comparator
.
comparing
((
ObjectiveConfig
op
)
->
op
.
getLevel
()));
}
}
/// <summary>
/// <summary>
...
@@ -158,6 +159,8 @@ public class GlobalParam {
...
@@ -158,6 +159,8 @@ public class GlobalParam {
return
;
return
;
}
}
}
}
objectiveConfigs
.
sort
(
Comparator
.
comparing
((
ObjectiveConfig
op
)
->
op
.
getLevel
()));
}
}
/// <summary>
/// <summary>
...
...
src/main/java/com/aps/entity/basic/ObjectiveConfig.java
View file @
47286670
...
@@ -18,6 +18,11 @@ public class ObjectiveConfig {
...
@@ -18,6 +18,11 @@ public class ObjectiveConfig {
*/
*/
private
boolean
enabled
;
private
boolean
enabled
;
/**
* 越小越好
*/
private
boolean
isMinimize
;
/**
/**
* 层级,层级越低优先级越高,1为最高
* 层级,层级越低优先级越高,1为最高
*/
*/
...
@@ -28,6 +33,11 @@ public class ObjectiveConfig {
...
@@ -28,6 +33,11 @@ public class ObjectiveConfig {
*/
*/
private
double
weight
;
private
double
weight
;
/**
* 值
*/
private
double
val
;
/**
/**
* 构造函数
* 构造函数
*/
*/
...
...
src/main/java/com/aps/service/Algorithm/FitnessCalculator.java
View file @
47286670
...
@@ -2,7 +2,10 @@ package com.aps.service.Algorithm;
...
@@ -2,7 +2,10 @@ package com.aps.service.Algorithm;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.ObjectiveWeights
;
import
com.aps.entity.Algorithm.ObjectiveWeights
;
import
com.aps.entity.basic.GlobalParam
;
import
com.aps.entity.basic.ObjectiveConfig
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
/**
/**
...
@@ -10,6 +13,84 @@ import java.util.List;
...
@@ -10,6 +13,84 @@ import java.util.List;
* 时间:2025-11-24
* 时间:2025-11-24
*/
*/
public
class
FitnessCalculator
{
public
class
FitnessCalculator
{
/**
* 多目标适应度计算(加权求和)
*/
public
double
[]
calculateFitness
(
Chromosome
chromosome
,
GlobalParam
param
)
{
ArrayList
<
Double
>
list
=
new
ArrayList
<>();
double
fitness
=
0
;
int
i
=
0
;
int
level
=-
1
;
for
(
ObjectiveConfig
config
:
param
.
getObjectiveConfigs
())
{
if
(
config
.
isEnabled
())
{
if
(
level
==-
1
)
{
level
=
config
.
getLevel
();
}
else
if
(
level
!=
config
.
getLevel
())
{
list
.
add
(
fitness
);
fitness
=
0
;
level
=
config
.
getLevel
();
}
double
obj
=
chromosome
.
getObjectives
()[
i
];
// 防御:处理负数(目标值应为非负,若为负则兜底为0)
obj
=
Math
.
max
(
0
,
obj
);
//转化为0,1 越靠近1 越优
double
val
=
0
;
if
(
config
.
isMinimize
())
{
// ============================
// 最小化目标:越小越优 → 归一化后越大越优,越优
// ============================
//0/1+ 0 =0 min max 最优
//1/1+ 1 =0.5 min max 最优
//1/1+ 2 =0.33
//1/1+ 3 =0.25
val
=
1.0
/
(
1.0
+
obj
);
}
else
{
// ============================
// 最大化目标:越大越优 → 反转成 越大越优
// ============================
// 1/1+ 1 = 0.5
// 2/1+ 2 = 0.66
// 3/1+ 3 = 0.75 max max 最优
val
=
obj
/
(
1.0
+
obj
);
}
// 兜底:避免极端情况归一化值为0(最小设为1e-6)
// val = Math.max(val, 1e-6);
if
(!
param
.
isPureNSGAIIMode
())
{
val
=
val
*
config
.
getWeight
();
}
fitness
+=
val
;
i
++;
}
}
list
.
add
(
fitness
);
// 归一化(假设最大可能值,实际应根据问题规模调整)
// makespan = 10 → val = 1/11 = 0.09
// makespan = 20 → val = 1/21 = 0.045
// makespan = 100 → val = 1/101 = 0.009
// 值越大 归一化 后越小, 越大越好
//原目标(工期、延迟、负载)越小 → 生产越好
//原目标越小,归一化后 → f1、f2、f3 越大
// 方案 A:工期短、延迟小 → 很好
// makespan=10 → f1=1/(11)=0.09
// fitness ≈ 0.08
// 方案 B:工期长、延迟大 → 很差
// makespan=100 → f1=1/(101)=0.009
// fitness ≈ 0.01
// 适应度值(越大越好)
return
list
.
stream
().
mapToDouble
(
Double:
:
doubleValue
).
toArray
();
}
/**
/**
* 多目标适应度计算(加权求和)
* 多目标适应度计算(加权求和)
*/
*/
...
@@ -29,11 +110,25 @@ public class FitnessCalculator {
...
@@ -29,11 +110,25 @@ public class FitnessCalculator {
// 1/1+1 0.5
// 1/1+1 0.5
// 1/1+2 0.3
// 1/1+2 0.3
// 1/1+3 0.25
// 1/1+3 0.25
// 值越大 归一化 后越小
// makespan = 10 → val = 1/11 = 0.09
// makespan = 20 → val = 1/21 = 0.045
// makespan = 100 → val = 1/101 = 0.009
// 值越大 归一化 后越小, 越大越好
//原目标(工期、延迟、负载)越小 → 生产越好
//原目标越小,归一化后 → f1、f2、f3 越大
// 方案 A:工期短、延迟小 → 很好
// makespan=10 → f1=1/(11)=0.09
// fitness ≈ 0.08
// 方案 B:工期长、延迟大 → 很差
// makespan=100 → f1=1/(101)=0.009
// fitness ≈ 0.01
}
}
// 适应度值(越大越好)
// 适应度值(越大越好)
return
fitness
;
return
fitness
;
}
}
/**
/**
* 计算种群适应度标准差(用于参数微调)
* 计算种群适应度标准差(用于参数微调)
* @param population 染色体种群数组
* @param population 染色体种群数组
...
...
src/main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
View file @
47286670
package
com
.
aps
.
service
.
Algorithm
;
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.common.util.DateTimeUtil
;
import
com.aps.common.util.*
;
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.entity.Algorithm.*
;
import
com.aps.entity.Algorithm.IDAndChildID.GroupResult
;
import
com.aps.entity.Algorithm.IDAndChildID.GroupResult
;
import
com.aps.entity.basic.*
;
import
com.aps.entity.basic.*
;
...
@@ -51,19 +48,8 @@ public class GeneticAlgorithm {
...
@@ -51,19 +48,8 @@ public class GeneticAlgorithm {
private
String
sceneId
;
private
String
sceneId
;
private
VariableNeighborhoodSearch
_vns
;
// 初始化算法实例
private
HillClimbing
_hillClimbing
;
private
SimulatedAnnealing
_simulatedAnnealing
;
private
ParallelLocalSearch
_parallelLocalSearch
;
// 初始化算法实例
private
TabuSearch
_tabuSearch
;
private
TabuSearchWithSA
_tabuSearchWithSA
;
public
GeneticAlgorithm
(
GlobalParam
globalParam
,
List
<
Machine
>
machines
,
List
<
Order
>
orders
,
public
GeneticAlgorithm
(
GlobalParam
globalParam
,
List
<
Machine
>
machines
,
List
<
Order
>
orders
,
List
<
Material
>
materials
,
List
<
String
>
_materialIds
,
MachineSchedulerService
machineScheduler
,
List
<
GroupResult
>
entryRel
,
MaterialRequirementService
_materialRequirementService
,
SceneService
sceneService
,
String
_sceneId
)
{
List
<
Material
>
materials
,
List
<
String
>
_materialIds
,
MachineSchedulerService
machineScheduler
,
List
<
GroupResult
>
entryRel
,
MaterialRequirementService
_materialRequirementService
,
SceneService
sceneService
,
String
_sceneId
)
{
this
.
machines
=
machines
;
this
.
machines
=
machines
;
this
.
orders
=
orders
;
this
.
orders
=
orders
;
this
.
materials
=
materials
;
this
.
materials
=
materials
;
...
@@ -71,9 +57,9 @@ public class GeneticAlgorithm {
...
@@ -71,9 +57,9 @@ public class GeneticAlgorithm {
_GlobalParam
=
globalParam
;
_GlobalParam
=
globalParam
;
_entryRel
=
entryRel
;
_entryRel
=
entryRel
;
materialRequirementService
=
_materialRequirementService
;
materialRequirementService
=
_materialRequirementService
;
_sceneService
=
sceneService
;
_sceneService
=
sceneService
;
sceneId
=
_sceneId
;
sceneId
=
_sceneId
;
materialIds
=
_materialIds
;
materialIds
=
_materialIds
;
}
}
public
void
Init
()
{
public
void
Init
()
{
...
@@ -89,16 +75,6 @@ public class GeneticAlgorithm {
...
@@ -89,16 +75,6 @@ public class GeneticAlgorithm {
throw
new
RuntimeException
(
"没有待排产工单"
);
throw
new
RuntimeException
(
"没有待排产工单"
);
}
}
// if(materials!=null&&materials.size()>0) {
//
// materialRequirementService.init(materials, orders, allOperations, _entryRel, machineScheduler, machines,_GlobalParam);
//
// orderMaterials = materialRequirementService.buildMultiLevelRequirementNetwork(param.getBaseTime());
// Set<Long> existIds = new HashSet<>();
// machines=machines.stream()
// .filter(t->existIds.add(t.getId()))//HashSet.add() 方法:添加成功返回 true,重复返回 false;
// .collect(Collectors.toList());
// }
LocalDateTime
starttime
=
LocalDateTime
.
now
();
LocalDateTime
starttime
=
LocalDateTime
.
now
();
FileHelper
.
writeLogFile
(
"排产-----------开始-----------"
+
allOperations
.
get
(
0
).
getSceneId
());
FileHelper
.
writeLogFile
(
"排产-----------开始-----------"
+
allOperations
.
get
(
0
).
getSceneId
());
...
@@ -108,23 +84,11 @@ public class GeneticAlgorithm {
...
@@ -108,23 +84,11 @@ public class GeneticAlgorithm {
// 预生成全局工序列表(所有初始化方法共享同一顺序)
// 预生成全局工序列表(所有初始化方法共享同一顺序)
List
<
GlobalOperationInfo
>
globalOpList
=
initialization
.
generateGlobalOpList
();
List
<
GlobalOperationInfo
>
globalOpList
=
initialization
.
generateGlobalOpList
();
// 初始化变邻域搜索
_vns
=
new
VariableNeighborhoodSearch
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
_hillClimbing
=
new
HillClimbing
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
_simulatedAnnealing
=
new
SimulatedAnnealing
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
_parallelLocalSearch
=
new
ParallelLocalSearch
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
_tabuSearch
=
new
TabuSearch
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
_tabuSearchWithSA
=
new
TabuSearchWithSA
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
FileHelper
.
writeLogFile
(
"初始化种群-----------开始-------"
);
FileHelper
.
writeLogFile
(
"初始化种群-----------开始-------"
);
// 步骤1:初始化种群
// 步骤1:初始化种群
List
<
Chromosome
>
population
=
initialization
.
generateInitialPopulation
(
param
,
globalOpList
);
List
<
Chromosome
>
population
=
initialization
.
generateInitialPopulation
(
param
,
globalOpList
);
// 步骤1:使用构造启发式算法生成初始种群
FileHelper
.
writeLogFile
(
"构造启发式初始化-----------开始-------"
);
// List<Chromosome> population = initialization.generateHeuristicInitialPopulation(param, globalOpList);
FileHelper
.
writeLogFile
(
"构造启发式初始化-----------结束-------"
);
population
=
chromosomeDistinct
(
population
);
population
=
chromosomeDistinct
(
population
);
...
@@ -133,31 +97,7 @@ public class GeneticAlgorithm {
...
@@ -133,31 +97,7 @@ public class GeneticAlgorithm {
FileHelper
.
writeLogFile
(
"初始化种群-----------结束-------"
);
FileHelper
.
writeLogFile
(
"初始化种群-----------结束-------"
);
FileHelper
.
writeLogFile
(
"初始化批量解码-----------开始-------"
);
FileHelper
.
writeLogFile
(
"初始化批量解码-----------开始-------"
);
Chromosomedecode
(
param
,
allOperations
,
globalOpList
,
population
);
Chromosomedecode
(
param
,
allOperations
,
globalOpList
,
population
);
FileHelper
.
writeLogFile
(
"初始化批量解码-----------结束-------"
);
FileHelper
.
writeLogFile
(
"初始化批量解码-----------结束-------"
);
// 步骤2:对初始种群进行爬山法局部优化
FileHelper
.
writeLogFile
(
"爬山法局部优化-----------开始-------"
);
GeneticDecoder
hillClimbingDecoder
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
List
<
Chromosome
>
optimizedPopulation
=
new
ArrayList
<>();
for
(
Chromosome
chromosome
:
population
)
{
Chromosome
optimized
=
_hillClimbing
.
search
(
chromosome
,
hillClimbingDecoder
,
param
);
optimizedPopulation
.
add
(
optimized
);
}
population
=
optimizedPopulation
;
FileHelper
.
writeLogFile
(
"爬山法局部优化-----------结束-------"
);
// 步骤2:对初始种群进行模拟退火+爬山法优化
FileHelper
.
writeLogFile
(
"模拟退火+爬山法优化-----------开始-------"
);
GeneticDecoder
saDecoder1
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
List
<
Chromosome
>
saHcOptimized
=
new
ArrayList
<>();
for
(
Chromosome
chromosome
:
population
)
{
Chromosome
optimized
=
_simulatedAnnealing
.
searchWithHillClimbing
(
chromosome
,
saDecoder1
,
param
);
saHcOptimized
.
add
(
optimized
);
}
population
=
saHcOptimized
;
FileHelper
.
writeLogFile
(
"模拟退火+爬山法优化-----------结束-------"
);
List
<
List
<
Chromosome
>>
combinedFronts
=
_nsgaIIUtils
.
parallelFastNonDominatedSort
(
population
);
List
<
List
<
Chromosome
>>
combinedFronts
=
_nsgaIIUtils
.
parallelFastNonDominatedSort
(
population
);
int
ordercount
=
globalOpList
.
stream
()
int
ordercount
=
globalOpList
.
stream
()
.
mapToInt
(
GlobalOperationInfo:
:
getGroupId
)
.
mapToInt
(
GlobalOperationInfo:
:
getGroupId
)
...
@@ -174,11 +114,11 @@ public class GeneticAlgorithm {
...
@@ -174,11 +114,11 @@ public class GeneticAlgorithm {
if
(
population
.
size
()<
param
.
getTournamentSize
())
if
(
population
.
size
()<
param
.
getTournamentSize
())
{
{
best
.
setBaseTime
(
param
.
getBaseTime
());
best
.
setBaseTime
(
param
.
getBaseTime
());
// best.setOrderMaterials(orderMaterials);
// best.setOrderMaterials(orderMaterials);
best
.
setMaterialIds
(
materialIds
);
best
.
setMaterialIds
(
materialIds
);
best
.
setMaterials
(
null
);
best
.
setMaterials
(
null
);
best
.
setScenarioID
(
sceneId
);
best
.
setScenarioID
(
sceneId
);
// best.setOperatRel(_entryRel);
// best.setOperatRel(_entryRel);
if
(
best
.
getInitMachines
()==
null
)
if
(
best
.
getInitMachines
()==
null
)
{
{
...
@@ -209,7 +149,7 @@ public class GeneticAlgorithm {
...
@@ -209,7 +149,7 @@ public class GeneticAlgorithm {
}
}
FileHelper
.
writeLogFile
(
"选择操作-----------开始-------"
);
FileHelper
.
writeLogFile
(
"选择操作-----------开始-------"
);
// 选择前移除适应度为 0 或明显劣于当前最优解的个体,减少选择池规模:
// 选择前移除适应度为 0 或明显劣于当前最优解的个体,减少选择池规模:
double
minValidFitness
=
bestFitness
*
0.5
;
// 保留最优解50%以上的个体
double
minValidFitness
=
bestFitness
*
0.5
;
// 保留最优解50%以上的个体
List
<
Chromosome
>
validPopulation
=
population
.
stream
()
List
<
Chromosome
>
validPopulation
=
population
.
stream
()
.
filter
(
c
->
c
.
getFitness
()
>=
minValidFitness
)
.
filter
(
c
->
c
.
getFitness
()
>=
minValidFitness
)
...
@@ -218,57 +158,6 @@ public class GeneticAlgorithm {
...
@@ -218,57 +158,6 @@ public class GeneticAlgorithm {
// 选择操作
// 选择操作
List
<
Chromosome
>
selected
=
geneticOps
.
tournamentSelection
(
validPopulation
);
List
<
Chromosome
>
selected
=
geneticOps
.
tournamentSelection
(
validPopulation
);
FileHelper
.
writeLogFile
(
"选择操作-----------结束-------"
);
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
(
"爬山法局部优化-----------开始-------"
);
List
<
Chromosome
>
hcImproved
=
new
ArrayList
<>();
for
(
Chromosome
chromosome
:
selected
)
{
Chromosome
hcOptimized
=
_hillClimbing
.
search
(
chromosome
,
saDecoder
,
param
);
hcImproved
.
add
(
hcOptimized
);
}
selected
.
addAll
(
hcImproved
);
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
(
"交叉操作-----------开始-------"
);
FileHelper
.
writeLogFile
(
"交叉操作-----------开始-------"
);
...
@@ -329,7 +218,7 @@ public class GeneticAlgorithm {
...
@@ -329,7 +218,7 @@ public class GeneticAlgorithm {
newPopulation
=
chromosomeDistinct1
(
newPopulation
);
newPopulation
=
chromosomeDistinct1
(
newPopulation
);
FileHelper
.
writeLogFile
(
"非支配排序-----------开始-------"
);
FileHelper
.
writeLogFile
(
"非支配排序-----------开始-------"
);
// 2.7 非支配排序
// 2.7 非支配排序
combinedFronts
=
_nsgaIIUtils
.
parallelFastNonDominatedSort
(
newPopulation
);
combinedFronts
=
_nsgaIIUtils
.
parallelFastNonDominatedSort
(
newPopulation
);
FileHelper
.
writeLogFile
(
"非支配排序-----------结束-------"
);
FileHelper
.
writeLogFile
(
"非支配排序-----------结束-------"
);
// 2.8 选择下一代种群
// 2.8 选择下一代种群
population
=
_nsgaIIUtils
.
selectNextPopulation
(
combinedFronts
,
param
.
getPopulationSize
());
population
=
_nsgaIIUtils
.
selectNextPopulation
(
combinedFronts
,
param
.
getPopulationSize
());
...
@@ -348,7 +237,7 @@ public class GeneticAlgorithm {
...
@@ -348,7 +237,7 @@ public class GeneticAlgorithm {
Iteration
++;
Iteration
++;
if
(
Iteration
>
5
)
{
if
(
Iteration
>
5
)
{
// 当连续 5 代无最优解提升时,降低交叉概率(如从 0.8 降至 0.5)、提高变异概率(如从 0.1 升至 0.2)
// 当连续 5 代无最优解提升时,降低交叉概率(如从 0.8 降至 0.5)、提高变异概率(如从 0.1 升至 0.2)
param
.
fineTuneParams
();
param
.
fineTuneParams
();
}
}
}
}
...
@@ -356,8 +245,8 @@ public class GeneticAlgorithm {
...
@@ -356,8 +245,8 @@ public class GeneticAlgorithm {
{
{
break
;
break
;
}
}
// 当种群适应度标准差小于阈值(如 0.001)时,说明种群已收敛,提前终止迭代
// 当种群适应度标准差小于阈值(如 0.001)时,说明种群已收敛,提前终止迭代
fitnessStd
=
_fitnessCalculator
.
calculateFitnessStd
(
population
);
fitnessStd
=
_fitnessCalculator
.
calculateFitnessStd
(
population
);
if
(
fitnessStd
<
0.001
)
{
if
(
fitnessStd
<
0.001
)
{
FileHelper
.
writeLogFile
(
"种群已收敛,提前终止迭代"
);
FileHelper
.
writeLogFile
(
"种群已收敛,提前终止迭代"
);
break
;
break
;
...
@@ -371,7 +260,7 @@ public class GeneticAlgorithm {
...
@@ -371,7 +260,7 @@ public class GeneticAlgorithm {
best
.
setMaterialIds
(
materialIds
);
best
.
setMaterialIds
(
materialIds
);
best
.
setMaterials
(
null
);
best
.
setMaterials
(
null
);
best
.
setScenarioID
(
sceneId
);
best
.
setScenarioID
(
sceneId
);
// best.setOperatRel(_entryRel);
// best.setOperatRel(_entryRel);
if
(
best
.
getInitMachines
()==
null
)
if
(
best
.
getInitMachines
()==
null
)
{
{
...
@@ -389,14 +278,14 @@ public class GeneticAlgorithm {
...
@@ -389,14 +278,14 @@ public class GeneticAlgorithm {
private
Chromosome
GetBest
(
List
<
List
<
Chromosome
>>
fronts
,
String
msg
)
private
Chromosome
GetBest
(
List
<
List
<
Chromosome
>>
fronts
,
String
msg
)
{
{
// WriteKpis(fronts,msg);
// WriteKpis(fronts,msg);
List
<
Chromosome
>
fChromosomes
=
fronts
.
get
(
0
);
List
<
Chromosome
>
fChromosomes
=
fronts
.
get
(
0
);
fChromosomes
.
sort
((
c1
,
c2
)
->
{
fChromosomes
.
sort
((
c1
,
c2
)
->
{
int
rankCompare
=
Double
.
compare
(
c1
.
getCrowdingDistance
(),
c2
.
getCrowdingDistance
());
int
rankCompare
=
Double
.
compare
(
c1
.
getCrowdingDistance
(),
c2
.
getCrowdingDistance
());
return
rankCompare
!=
0
?
rankCompare
:
Double
.
compare
(
c1
.
getFitness
(),
c2
.
getFitness
());
return
rankCompare
!=
0
?
rankCompare
:
Double
.
compare
(
c1
.
getFitness
(),
c2
.
getFitness
());
});
});
Chromosome
best
=
fChromosomes
.
get
(
0
);
Chromosome
best
=
fChromosomes
.
get
(
0
);
// WriteKpi(best,"最大");
// WriteKpi(best,"最大");
return
best
;
return
best
;
}
}
private
List
<
Chromosome
>
chromosomeDistinct
(
List
<
Chromosome
>
population
)
private
List
<
Chromosome
>
chromosomeDistinct
(
List
<
Chromosome
>
population
)
...
@@ -404,7 +293,7 @@ public class GeneticAlgorithm {
...
@@ -404,7 +293,7 @@ public class GeneticAlgorithm {
if
(
population
==
null
)
if
(
population
==
null
)
{
{
FileHelper
.
writeLogFile
(
String
.
format
(
"排产-----------方案数量---%d-------"
,
0
));
FileHelper
.
writeLogFile
(
String
.
format
(
"排产-----------方案数量---%d-------"
,
0
));
return
population
;
return
population
;
}
}
population
=
population
.
stream
()
population
=
population
.
stream
()
.
filter
(
chromosome
->
chromosome
!=
null
&&
chromosome
.
getGeneStr
()
!=
null
)
.
filter
(
chromosome
->
chromosome
!=
null
&&
chromosome
.
getGeneStr
()
!=
null
)
...
@@ -429,17 +318,17 @@ return population;
...
@@ -429,17 +318,17 @@ return population;
// List<Chromosome> population1 = population.stream().filter(t->t.getGeneStr()==null).collect(Collectors.toList());
// List<Chromosome> population1 = population.stream().filter(t->t.getGeneStr()==null).collect(Collectors.toList());
population
=
population
.
stream
()
population
=
population
.
stream
()
.
collect
(
Collectors
.
toMap
(
.
collect
(
Collectors
.
toMap
(
Chromosome:
:
getGeneStr
,
// key:去重的字段(GeneStr)
Chromosome:
:
getGeneStr
,
// key:去重的字段(GeneStr)
u
->
u
,
// value:Chromosome对象
u
->
u
,
// value:Chromosome对象
(
u1
,
u2
)
->
u1
.
getFitness
()
>
u2
.
getFitness
()
?
u1
:
u2
// 重复时保留第一个元素
(
u1
,
u2
)
->
u1
.
getFitness
()
>
u2
.
getFitness
()
?
u1
:
u2
// 重复时保留第一个元素
))
))
.
values
()
// 获取去重后的
.
values
()
// 获取去重后的
.
stream
()
.
stream
()
.
collect
(
Collectors
.
toList
());
.
collect
(
Collectors
.
toList
());
return
population
;
return
population
;
}
}
...
@@ -474,10 +363,10 @@ return population;
...
@@ -474,10 +363,10 @@ return population;
private
void
Chromosomedecode
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
,
List
<
GlobalOperationInfo
>
globalOpList
,
List
<
Chromosome
>
population
)
private
void
Chromosomedecode
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
,
List
<
GlobalOperationInfo
>
globalOpList
,
List
<
Chromosome
>
population
)
{
{
FileHelper
.
writeLogFile
(
"解码---------------"
+
population
.
size
()
);
FileHelper
.
writeLogFile
(
"解码---------------"
+
population
.
size
()
);
GeneticDecoder
decoder
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
GeneticDecoder
decoder
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
boolean
ismore
=
fals
e
;
boolean
ismore
=
tru
e
;
if
(
ismore
)
{
if
(
ismore
)
{
CompletableFuture
.
allOf
(
population
.
stream
()
CompletableFuture
.
allOf
(
population
.
stream
()
.
map
(
chromosome
->
CompletableFuture
.
runAsync
(()
->
decode
(
decoder
,
chromosome
,
param
,
allOperations
,
globalOpList
),
decodeExecutor
))
.
map
(
chromosome
->
CompletableFuture
.
runAsync
(()
->
decode
(
decoder
,
chromosome
,
param
,
allOperations
,
globalOpList
),
decodeExecutor
))
...
@@ -497,10 +386,10 @@ return population;
...
@@ -497,10 +386,10 @@ return population;
private
void
decode
(
GeneticDecoder
decoder
,
Chromosome
chromosome
,
ScheduleParams
param
,
List
<
Entry
>
allOperations
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
private
void
decode
(
GeneticDecoder
decoder
,
Chromosome
chromosome
,
ScheduleParams
param
,
List
<
Entry
>
allOperations
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
if
(
chromosome
==
null
){
if
(
chromosome
==
null
){
System
.
out
.
println
(
"chromosome==null"
);
System
.
out
.
println
(
"chromosome==null"
);
return
;
return
;
}
}
chromosome
.
setResult
(
new
CopyOnWriteArrayList
<>());
chromosome
.
setResult
(
new
CopyOnWriteArrayList
<>());
...
@@ -516,7 +405,16 @@ return population;
...
@@ -516,7 +405,16 @@ return population;
//chromosome.setObjectiveWeights(_objectiveWeights);
//chromosome.setObjectiveWeights(_objectiveWeights);
chromosome
.
setBaseTime
(
param
.
getBaseTime
());
chromosome
.
setBaseTime
(
param
.
getBaseTime
());
// chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝
// chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝
// _sceneService.saveChromosomeToFile(chromosome, "12345679");
// _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
<>());
}
decoder
.
decodeChromosomeWithCache
(
chromosome
);
decoder
.
decodeChromosomeWithCache
(
chromosome
);
if
(
chromosome
.
getFitness
()
==
0
)
{
if
(
chromosome
.
getFitness
()
==
0
)
{
...
...
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
View file @
47286670
...
@@ -21,9 +21,7 @@ import java.time.Duration;
...
@@ -21,9 +21,7 @@ import java.time.Duration;
import
java.time.LocalDateTime
;
import
java.time.LocalDateTime
;
import
java.time.temporal.ChronoUnit
;
import
java.time.temporal.ChronoUnit
;
import
java.util.*
;
import
java.util.*
;
import
java.util.concurrent.CompletableFuture
;
import
java.util.concurrent.*
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.CopyOnWriteArrayList
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.stream.Collectors
;
import
java.util.stream.Collectors
;
import
java.util.concurrent.locks.ReentrantLock
;
import
java.util.concurrent.locks.ReentrantLock
;
...
@@ -78,6 +76,36 @@ public class GeneticDecoder {
...
@@ -78,6 +76,36 @@ public class GeneticDecoder {
// 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
(
Runtime
.
getRuntime
().
availableProcessors
()
-
1
,
// 核心线程数=CPU-1,无切换开销
Runtime
.
getRuntime
().
availableProcessors
()
-
1
,
// 最大线程数=核心数
0L
,
TimeUnit
.
MILLISECONDS
,
new
ArrayBlockingQueue
<>(
200
),
// 有界队列,避免内存溢出
new
ThreadPoolExecutor
.
CallerRunsPolicy
()
// 任务满了主线程执行,不丢失任务
);
public
void
Chromosomedecode
(
List
<
Chromosome
>
population
)
{
FileHelper
.
writeLogFile
(
"解码---------------"
+
population
.
size
()
);
boolean
ismore
=
false
;
if
(
ismore
)
{
CompletableFuture
.
allOf
(
population
.
stream
()
.
map
(
chromosome
->
CompletableFuture
.
runAsync
(()
->
decodeChromosomeWithCache
(
chromosome
),
decodeExecutor
))
.
toArray
(
CompletableFuture
[]::
new
))
.
join
();
}
else
{
if
(
population
!=
null
&&
population
.
size
()
>
0
)
{
population
.
forEach
(
chromosome
->
{
decodeChromosomeWithCache
(
chromosome
);
});
}
}
}
// public Chromosome decodeChromosomeWithCache(Chromosome chromosome) {
// public Chromosome decodeChromosomeWithCache(Chromosome chromosome) {
// String cacheKey = createCacheKey(chromosome);
// String cacheKey = createCacheKey(chromosome);
// // FileHelper.writeLogFile("解码-----------开始-------"+chromosome.getID()+":"+cacheKey );
// // FileHelper.writeLogFile("解码-----------开始-------"+chromosome.getID()+":"+cacheKey );
...
@@ -345,18 +373,18 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -345,18 +373,18 @@ if(finishedOrder==null||finishedOrder.size()==0)
//
//
// // 根据工序数量和CPU核心数决定是否使用内部并行
// // 根据工序数量和CPU核心数决定是否使用内部并行
if
(
operationCount
>
500
&&
cpuCores
>
4
)
{
if
(
operationCount
>
500
&&
cpuCores
>
4
)
{
// 使用并行处理
// 使用
设备
并行处理
FileHelper
.
writeLogFile
(
"使用并行处理 _s"
);
//
FileHelper.writeLogFile("使用并行处理 _s");
parallelDecodeByMachine
(
chromosome
);
parallelDecodeByMachine
(
chromosome
);
FileHelper
.
writeLogFile
(
"使用并行处理 _e"
);
//
FileHelper.writeLogFile("使用并行处理 _e");
}
}
//
else {
else
{
// 使用串行处理
// 使用串行处理
// FileHelper.writeLogFile("使用串行处理 _s");
// FileHelper.writeLogFile("使用串行处理 _s");
//
serialDecode(chromosome);
serialDecode
(
chromosome
);
// FileHelper.writeLogFile("使用串行处理 _e");
// FileHelper.writeLogFile("使用串行处理 _e");
//
}
}
}
}
/**
/**
* 染色体解码为调度方案
* 染色体解码为调度方案
...
@@ -555,6 +583,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -555,6 +583,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
=
new
HashMap
<>();
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
=
new
HashMap
<>();
Map
<
Long
,
Machine
>
machineIdMap
=
chromosome
.
getMachines
().
stream
()
Map
<
Long
,
Machine
>
machineIdMap
=
chromosome
.
getMachines
().
stream
()
.
collect
(
Collectors
.
toMap
(
Machine:
:
getId
,
m
->
m
));
.
collect
(
Collectors
.
toMap
(
Machine:
:
getId
,
m
->
m
));
// 构建工序ID索引:opId -> Entry(O(1)查找)
Map
<
Integer
,
Entry
>
opIdIndex
=
buildOpIdIndex
(
chromosome
);
for
(
GlobalOperationInfo
globalOp
:
globalOpList
)
{
for
(
GlobalOperationInfo
globalOp
:
globalOpList
)
{
int
globalOpId
=
globalOp
.
getGlobalOpId
();
int
globalOpId
=
globalOp
.
getGlobalOpId
();
...
@@ -590,7 +620,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -590,7 +620,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
FileHelper
.
writeLogFile
(
"预处理工序信息 _s"
);
FileHelper
.
writeLogFile
(
"预处理工序信息 _s"
);
// 预处理工序信息
// 预处理工序信息
for
(
int
opId
:
topologicalOrder
)
{
for
(
int
opId
:
topologicalOrder
)
{
Entry
op
=
findOperationById
(
chromosome
,
opId
);
// Entry op = findOperationById(chromosome, opId);
Entry
op
=
opIdIndex
.
get
(
opId
);
if
(
op
!=
null
)
{
if
(
op
!=
null
)
{
// 假设已经为工序分配了设备
// 假设已经为工序分配了设备
...
@@ -610,7 +641,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -610,7 +641,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
FileHelper
.
writeLogFile
(
"并行处理 _s"
);
FileHelper
.
writeLogFile
(
"并行处理 _s"
);
for
(
int
opId
:
topologicalOrder
)
{
for
(
int
opId
:
topologicalOrder
)
{
// 获取当前工序的依赖
// 获取当前工序的依赖
Entry
op
=
findOperationById
(
chromosome
,
opId
);
// Entry op = findOperationById(chromosome, opId);
Entry
op
=
opIdIndex
.
get
(
opId
);
List
<
Integer
>
dependencies
=
dependencyGraph
.
getOrDefault
(
opId
,
Collections
.
emptyList
());
List
<
Integer
>
dependencies
=
dependencyGraph
.
getOrDefault
(
opId
,
Collections
.
emptyList
());
// 等待所有依赖完成
// 等待所有依赖完成
...
@@ -661,10 +693,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -661,10 +693,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
// 1. 获取工序处理顺序
// 1. 获取工序处理顺序
List
<
Integer
>
operationSequencing
=
chromosome
.
getOperationSequencing
();
List
<
Integer
>
operationSequencing
=
chromosome
.
getOperationSequencing
();
List
<
GlobalOperationInfo
>
globalOpList
=
chromosome
.
getGlobalOpList
();
List
<
GlobalOperationInfo
>
globalOpList
=
chromosome
.
getGlobalOpList
();
List
<
Entry
>
allOperations
=
chromosome
.
getAllOperations
();
List
<
Entry
>
allOperations
=
chromosome
.
getAllOperations
();
// 2. 构建工序依赖图
// 2. 构建工序依赖图
...
@@ -696,7 +726,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -696,7 +726,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
// 获取选择的设备ID和加工时间
// 获取选择的设备ID和加工时间
MachineOption
selectedMachine
=
optionalMachines
.
get
(
machineSeq
-
1
);
MachineOption
selectedMachine
=
optionalMachines
.
get
(
machineSeq
-
1
);
OpMachine
opMachine
=
new
OpMachine
();
OpMachine
opMachine
=
new
OpMachine
();
opMachine
.
setGroupId
(
groupId
);
opMachine
.
setGroupId
(
groupId
);
opMachine
.
setSequence
(
sequence
);
opMachine
.
setSequence
(
sequence
);
opMachine
.
setMachineId
(
selectedMachine
.
getMachineId
());
opMachine
.
setMachineId
(
selectedMachine
.
getMachineId
());
...
@@ -849,12 +879,12 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -849,12 +879,12 @@ if(finishedOrder==null||finishedOrder.size()==0)
// 工序超过500的设备直接在主线程串行处理
// 工序超过500的设备直接在主线程串行处理
if
(
ops
.
size
()
>
500
)
{
if
(
ops
.
size
()
>
500
)
{
// FileHelper.writeLogFile("设备 " + machineId + " 有 " + ops.size() + " 个工序,直接串行处理");
// 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
);
}
else
{
}
else
{
// 工序少的设备创建线程处理
// 工序少的设备创建线程处理
Thread
thread
=
new
Thread
(()
->
{
Thread
thread
=
new
Thread
(()
->
{
processMachineOps
(
chromosome
,
machineId
,
ops
,
dependencyGraph
,
opCompleted
,
lock
,
opMachineKeyMap
,
machineIdMap
,
machineTasksCache
);
processMachineOps
(
chromosome
,
machineId
,
ops
,
dependencyGraph
,
opCompleted
,
lock
,
opMachineKeyMap
,
machineIdMap
,
machineTasksCache
);
});
});
thread
.
start
();
thread
.
start
();
threads
.
add
(
thread
);
threads
.
add
(
thread
);
...
@@ -870,14 +900,14 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -870,14 +900,14 @@ if(finishedOrder==null||finishedOrder.size()==0)
}
}
}
}
// 9. 等待所有设备处理完成
// 9. 等待所有设备处理完成
// CompletableFuture.allOf(allMachineFutures.toArray(new CompletableFuture[0])).join();
// CompletableFuture.allOf(allMachineFutures.toArray(new CompletableFuture[0])).join();
if
(
chromosome
.
getReOrderids
()!=
null
&&
chromosome
.
getReOrderids
().
size
()>
0
)
{
if
(
chromosome
.
getReOrderids
()
!=
null
&&
chromosome
.
getReOrderids
().
size
()
>
0
)
{
chromosome
.
getOperationSequencing
().
removeIf
(
t
->
chromosome
.
getReOrderids
().
contains
(
t
));
chromosome
.
getOperationSequencing
().
removeIf
(
t
->
chromosome
.
getReOrderids
().
contains
(
t
));
}
}
calculateScheduleResult
(
chromosome
);
calculateScheduleResult
(
chromosome
);
}
}
/**
/**
* 处理单个设备的工序
* 处理单个设备的工序
...
@@ -1051,8 +1081,19 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -1051,8 +1081,19 @@ if(finishedOrder==null||finishedOrder.size()==0)
return
result
;
return
result
;
}
}
/**
* 构建工序ID索引:opId -> Entry(O(1)查找)
*/
private
Map
<
Integer
,
Entry
>
buildOpIdIndex
(
Chromosome
chromosome
)
{
Map
<
Integer
,
Entry
>
index
=
new
HashMap
<>();
for
(
Entry
op
:
chromosome
.
getAllOperations
())
{
index
.
put
(
op
.
getId
(),
op
);
}
return
index
;
}
/**
/**
* 根据工序ID查找工序
* 根据工序ID查找工序
*/
*/
...
@@ -2367,7 +2408,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
...
@@ -2367,7 +2408,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
if
(
config
.
getName
()==
GlobalParam
.
OBJECTIVE_MAKESPAN
)
if
(
config
.
getName
()==
GlobalParam
.
OBJECTIVE_MAKESPAN
)
{
{
// 1. 最早完工时间(最小化)
// 1. 最早完工时间(最小化)
double
makespan
=
chromosome
.
getResult
().
stream
()
double
makespan
=
chromosome
.
getResult
().
stream
()
.
mapToInt
(
GAScheduleResult:
:
getEndTime
)
.
mapToInt
(
GAScheduleResult:
:
getEndTime
)
.
max
()
.
max
()
.
orElse
(
0
);
.
orElse
(
0
);
...
@@ -2444,6 +2485,10 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
...
@@ -2444,6 +2485,10 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
}
}
chromosome
.
setObjectives
(
Objectives
);
chromosome
.
setObjectives
(
Objectives
);
FitnessCalculator
fitnessCalculator
=
new
FitnessCalculator
();
if
(
chromosome
.
getFitnessLevel
()==
null
)
{
chromosome
.
setFitnessLevel
(
fitnessCalculator
.
calculateFitness
(
chromosome
,
_globalParam
));
}
}
}
private
double
calculateTotalFlowTime
(
Chromosome
chromosome
)
{
private
double
calculateTotalFlowTime
(
Chromosome
chromosome
)
{
...
...
src/main/java/com/aps/service/Algorithm/HillClimbing.java
View file @
47286670
...
@@ -4,10 +4,12 @@ import com.aps.common.util.ProductionDeepCopyUtil;
...
@@ -4,10 +4,12 @@ import com.aps.common.util.ProductionDeepCopyUtil;
import
com.aps.entity.Algorithm.*
;
import
com.aps.entity.Algorithm.*
;
import
com.aps.entity.basic.Entry
;
import
com.aps.entity.basic.Entry
;
import
com.aps.entity.basic.GlobalParam
;
import
com.aps.entity.basic.GlobalParam
;
import
com.aps.entity.basic.MachineOption
;
import
java.util.ArrayList
;
import
java.util.*
;
import
java.util.List
;
import
java.util.concurrent.CompletableFuture
;
import
java.util.Random
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
/**
/**
* 爬山法算法
* 爬山法算法
...
@@ -28,39 +30,487 @@ public class HillClimbing {
...
@@ -28,39 +30,487 @@ public class HillClimbing {
this
.
objectiveWeights
=
objectiveWeights
;
this
.
objectiveWeights
=
objectiveWeights
;
}
}
public
Chromosome
BatchSearchAll
(
List
<
Chromosome
>
population
,
GeneticDecoder
decoder
,
ScheduleParams
param
)
{
List
<
Chromosome
>
optimizedPopulation
=
new
ArrayList
<>();
for
(
Chromosome
chromosome
:
population
)
{
Chromosome
optimized
=
searchAll
(
chromosome
,
decoder
,
param
);
optimizedPopulation
.
add
(
optimized
);
}
int
bestidx
=
Getbest
(
optimizedPopulation
,
null
);
if
(
bestidx
>-
1
)
{
return
optimizedPopulation
.
get
(
bestidx
);
}
return
null
;
}
/**
/**
*
爬山法
搜索
*
穷举
搜索
*/
*/
public
Chromosome
search
(
Chromosome
chromosome
,
GeneticDecoder
decoder
,
ScheduleParams
param
)
{
public
Chromosome
search
All
(
Chromosome
chromosome
,
GeneticDecoder
decoder
,
ScheduleParams
param
)
{
Chromosome
current
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
Chromosome
current
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
Chromosome
best
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
Chromosome
best
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
boolean
improved
=
true
;
// 按优先级分组工序
int
iterations
=
0
;
Map
<
Double
,
List
<
Entry
>>
priorityGroups
=
groupOperationsByPriority
();
int
maxIterations
=
100
;
// 按优先级从高到低处理
List
<
Double
>
sortedPriorities
=
new
ArrayList
<>(
priorityGroups
.
keySet
());
// 构建位置索引映射:groupId_sequence -> position
Map
<
String
,
Integer
>
positionIndex
=
buildPositionIndex
(
current
);
Map
<
String
,
Integer
>
MachinePositionIndex
=
buildEntryMachinePositionIndex
(
current
);
Map
<
String
,
Entry
>
Entrys
=
buildEntryKey
(
current
);
// 构建位置到Entry的映射:position -> Entry
Map
<
Integer
,
Entry
>
entryIndex
=
buildEntryIndex
(
current
,
Entrys
);
for
(
Double
priority
:
sortedPriorities
)
{
List
<
Entry
>
priorityOps
=
priorityGroups
.
get
(
priority
);
if
(
priorityOps
.
isEmpty
())
{
continue
;
}
// 根据当前优先级的工序数确定迭代次数和step
int
priorityIterations
=
Math
.
max
(
5
,
priorityOps
.
size
()/
2
);
// 200/10 =20
// 1
int
step
=
Math
.
max
(
1
,
(
int
)
Math
.
ceil
(
priorityOps
.
size
()
/
10.0
));
// 200/20=10;
//
int
stepCount
=
Math
.
max
(
1
,
(
int
)
Math
.
ceil
(
priorityOps
.
size
()
/
step
));
Set
<
Integer
>
Groupid
=
new
HashSet
<>();
for
(
int
pi
=
0
;
pi
<
priorityIterations
;
pi
++)
{
// 随机取该优先级的工序
Entry
randomOp
=
priorityOps
.
get
(
rnd
.
nextInt
(
priorityOps
.
size
()));
if
(
Groupid
.
contains
(
randomOp
.
getGroupId
()))
{
continue
;
}
Groupid
.
add
(
randomOp
.
getGroupId
());
// 从索引中快速查找位置(O(1)复杂度)
String
key
=
randomOp
.
getGroupId
()
+
"_"
+
randomOp
.
getSequence
();
Integer
opPos
=
positionIndex
.
get
(
key
);
Integer
maPos
=
MachinePositionIndex
.
get
(
key
);
List
<
MachineOption
>
MachineOptions
=
randomOp
.
getMachineOptions
();
if
(
opPos
==
null
)
{
continue
;
}
List
<
Integer
>
os
=
current
.
getOperationSequencing
();
// 生成多个候选方案
List
<
Chromosome
>
candidates
=
new
ArrayList
<>();
List
<
Chromosome
>
candidates1
=
new
ArrayList
<>();
if
(
MachineOptions
.
size
()>
1
)
{
Chromosome
machineChange
=
generateMachineChange
(
current
,
MachineOptions
,
maPos
);
if
(
machineChange
!=
null
)
{
candidates
.
add
(
machineChange
);
candidates1
.
add
(
machineChange
);
}
}
// 向左多次移动(step 1, 2, 3...)
for
(
int
s
=
1
;
s
<=
stepCount
;
s
++)
{
Entry
leftOp
=
entryIndex
.
get
(
opPos
-
s
*
step
);
if
(
leftOp
!=
null
&&
randomOp
.
getGroupId
()!=
leftOp
.
getGroupId
()
&&
Math
.
abs
(
leftOp
.
getPriority
()
-
priority
)
<=
0.001
)
{
while
(
improved
&&
iterations
<
maxIterations
)
{
Chromosome
newChromosome
=
swapAtDistance
(
current
,
opPos
,
-
s
*
step
);
improved
=
false
;
candidates
.
add
(
newChromosome
);
candidates1
.
add
(
newChromosome
);
if
(
MachineOptions
.
size
()>
1
)
{
Chromosome
machineChange
=
generateMachineChange
(
newChromosome
,
MachineOptions
,
maPos
);
if
(
machineChange
!=
null
)
{
candidates
.
add
(
machineChange
);
candidates1
.
add
(
machineChange
);
}
}
// 生成邻域解
List
<
Chromosome
>
neighbors
=
generateNeighbors
(
current
);
// 评估所有邻域解
}
else
{
for
(
Chromosome
neighbor
:
neighbors
)
{
break
;
decode
(
decoder
,
neighbor
,
param
);
}
if
(
isBetter
(
neighbor
,
best
))
{
if
(
candidates1
.
size
()
>
5
)
{
best
=
neighbor
;
batchDecode
(
decoder
,
candidates1
);
current
=
neighbor
;
candidates1
.
clear
();
improved
=
true
;
}
}
// 向右多次移动(step 1, 2, 3...)
for
(
int
s
=
1
;
s
<=
stepCount
;
s
++)
{
Entry
rightOp
=
entryIndex
.
get
(
opPos
+
s
*
step
);
if
(
rightOp
!=
null
&&
randomOp
.
getGroupId
()
!=
rightOp
.
getGroupId
()
&&
Math
.
abs
(
rightOp
.
getPriority
()
-
priority
)
<=
0.001
)
{
Chromosome
newChromosome
=
swapAtDistance
(
current
,
opPos
,
s
*
step
);
candidates
.
add
(
newChromosome
);
candidates1
.
add
(
newChromosome
);
if
(
MachineOptions
.
size
()>
1
)
{
Chromosome
machineChange
=
generateMachineChange
(
newChromosome
,
MachineOptions
,
maPos
);
if
(
machineChange
!=
null
)
{
candidates
.
add
(
machineChange
);
candidates1
.
add
(
machineChange
);
}
}
}
else
{
break
;
}
if
(
candidates1
.
size
()
>
5
)
{
batchDecode
(
decoder
,
candidates1
);
candidates1
.
clear
();
}
}
// 限制最多5个方案并行
if
(
candidates1
.
size
()
>
0
)
{
batchDecode
(
decoder
,
candidates1
);
}
if
(
candidates
.
size
()==
0
)
{
break
;
}
int
bestidx
=
Getbest
(
candidates
,
best
);
if
(
bestidx
>-
1
)
{
best
=
candidates
.
get
(
bestidx
);
current
=
best
;
positionIndex
=
buildPositionIndex
(
current
);
entryIndex
=
buildEntryIndex
(
current
,
Entrys
);
}
}
}
}
return
best
;
}
public
Chromosome
search
(
Chromosome
chromosome
,
GeneticDecoder
decoder
,
ScheduleParams
param
)
{
Chromosome
current
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
Chromosome
best
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
// 按优先级分组工序
Map
<
Double
,
List
<
Entry
>>
priorityGroups
=
groupOperationsByPriority
();
// 按优先级从高到低处理
List
<
Double
>
sortedPriorities
=
new
ArrayList
<>(
priorityGroups
.
keySet
());
// 构建位置索引映射:groupId_sequence -> position
Map
<
String
,
Integer
>
positionIndex
=
buildPositionIndex
(
current
);
Map
<
String
,
Integer
>
MachinePositionIndex
=
buildEntryMachinePositionIndex
(
current
);
Map
<
String
,
Entry
>
Entrys
=
buildEntryKey
(
current
);
// 构建位置到Entry的映射:position -> Entry
Map
<
Integer
,
Entry
>
entryIndex
=
buildEntryIndex
(
current
,
Entrys
);
boolean
improved
=
true
;
for
(
Double
priority
:
sortedPriorities
)
{
List
<
Entry
>
priorityOps
=
priorityGroups
.
get
(
priority
);
if
(
priorityOps
.
isEmpty
())
{
continue
;
}
}
iterations
++;
// 根据当前优先级的工序数确定迭代次数和step
int
priorityIterations
=
Math
.
max
(
5
,
priorityOps
.
size
()/
2
);
// 200/10 =20
// 1
int
step
=
Math
.
max
(
1
,
(
int
)
Math
.
ceil
(
priorityOps
.
size
()
/
10.0
));
// 200/20=10;
//
int
stepCount
=
Math
.
max
(
1
,
(
int
)
Math
.
ceil
(
priorityOps
.
size
()
/
step
));
Set
<
Integer
>
Groupid
=
new
HashSet
<>();
for
(
int
pi
=
0
;
pi
<
priorityIterations
;
pi
++)
{
improved
=
false
;
// 随机取该优先级的工序
Entry
randomOp
=
priorityOps
.
get
(
rnd
.
nextInt
(
priorityOps
.
size
()));
// 从索引中快速查找位置(O(1)复杂度)
String
key
=
randomOp
.
getGroupId
()
+
"_"
+
randomOp
.
getSequence
();
Integer
opPos
=
positionIndex
.
get
(
key
);
Integer
maPos
=
MachinePositionIndex
.
get
(
key
);
List
<
MachineOption
>
MachineOptions
=
randomOp
.
getMachineOptions
();
if
(
opPos
==
null
)
{
continue
;
}
List
<
Integer
>
os
=
current
.
getOperationSequencing
();
// 生成多个候选方案
List
<
Chromosome
>
candidates
=
new
ArrayList
<>();
if
(
MachineOptions
.
size
()>
1
)
{
Chromosome
machineChange
=
generateMachineChange
(
current
,
MachineOptions
,
maPos
);
if
(
machineChange
!=
null
)
{
candidates
.
add
(
machineChange
);
}
}
// 向左多次移动(step 1, 2, 3...)
for
(
int
s
=
1
;
s
<=
stepCount
;
s
++)
{
Entry
leftOp
=
entryIndex
.
get
(
opPos
-
s
*
step
);
if
(
leftOp
!=
null
&&
randomOp
.
getGroupId
()!=
leftOp
.
getGroupId
()
&&
Math
.
abs
(
leftOp
.
getPriority
()
-
priority
)
<=
0.001
)
{
Chromosome
newChromosome
=
swapAtDistance
(
current
,
opPos
,
-
s
*
step
);
candidates
.
add
(
newChromosome
);
if
(
MachineOptions
.
size
()>
1
)
{
Chromosome
machineChange
=
generateMachineChange
(
newChromosome
,
MachineOptions
,
maPos
);
if
(
machineChange
!=
null
)
{
candidates
.
add
(
machineChange
);
}
}
}
else
{
break
;
}
if
(
candidates
.
size
()
>
5
)
{
batchDecode
(
decoder
,
candidates
);
int
bestidx
=
Getbest
(
candidates
,
best
);
if
(
bestidx
>-
1
)
{
best
=
candidates
.
get
(
bestidx
);
current
=
best
;
improved
=
true
;
// 更新索引
positionIndex
=
buildPositionIndex
(
current
);
entryIndex
=
buildEntryIndex
(
current
,
Entrys
);
break
;
}
candidates
.
clear
();
}
}
if
(
improved
)
{
break
;
}
// 向右多次移动(step 1, 2, 3...)
for
(
int
s
=
1
;
s
<=
stepCount
;
s
++)
{
Entry
rightOp
=
entryIndex
.
get
(
opPos
+
s
*
step
);
if
(
rightOp
!=
null
&&
randomOp
.
getGroupId
()
!=
rightOp
.
getGroupId
()
&&
Math
.
abs
(
rightOp
.
getPriority
()
-
priority
)
<=
0.001
)
{
Chromosome
newChromosome
=
swapAtDistance
(
current
,
opPos
,
s
*
step
);
candidates
.
add
(
newChromosome
);
if
(
MachineOptions
.
size
()>
1
)
{
Chromosome
machineChange
=
generateMachineChange
(
newChromosome
,
MachineOptions
,
maPos
);
if
(
machineChange
!=
null
)
{
candidates
.
add
(
machineChange
);
}
}
}
else
{
break
;
}
if
(
candidates
.
size
()
>
5
)
{
batchDecode
(
decoder
,
candidates
);
int
bestidx
=
Getbest
(
candidates
,
best
);
if
(
bestidx
>-
1
)
{
best
=
candidates
.
get
(
bestidx
);
current
=
best
;
// 更新索引
positionIndex
=
buildPositionIndex
(
current
);
entryIndex
=
buildEntryIndex
(
current
,
Entrys
);
improved
=
true
;
break
;
}
candidates
.
clear
();
}
}
if
(
improved
)
{
break
;
}
if
(
candidates
.
size
()==
0
)
{
break
;
}
else
{
batchDecode
(
decoder
,
candidates
);
}
int
bestidx
=
Getbest
(
candidates
,
best
);
if
(
bestidx
>-
1
)
{
best
=
candidates
.
get
(
bestidx
);
current
=
best
;
// 更新索引
positionIndex
=
buildPositionIndex
(
current
);
entryIndex
=
buildEntryIndex
(
current
,
Entrys
);
improved
=
true
;
break
;
}
}
}
}
return
best
;
return
best
;
}
}
private
int
Getbest
(
List
<
Chromosome
>
candidates
,
Chromosome
best
)
{
// 找出最佳候选方案
int
bestidx
=
-
1
;
if
(
best
==
null
)
{
best
=
candidates
.
get
(
0
);
bestidx
=
0
;
}
for
(
int
i
=
0
;
i
<
candidates
.
size
();
i
++)
{
Chromosome
candidate
=
candidates
.
get
(
i
);
if
(
isBetter
(
candidate
,
best
))
{
bestidx
=
i
;
}
}
return
bestidx
;
}
/**
* 构建位置索引: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索引:position -> Entry
*/
private
Map
<
Integer
,
Entry
>
buildEntryIndex
(
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
*/
private
Map
<
String
,
Entry
>
buildEntryKey
(
Chromosome
chromosome
)
{
Map
<
String
,
Entry
>
index
=
new
HashMap
<>();
List
<
Entry
>
allOps
=
chromosome
.
getAllOperations
();
for
(
Entry
op
:
allOps
)
{
String
key
=
op
.
getGroupId
()
+
"_"
+
op
.
getSequence
();
index
.
put
(
key
,
op
);
}
return
index
;
}
/**
* 按优先级分组工序
*/
private
Map
<
Double
,
List
<
Entry
>>
groupOperationsByPriority
()
{
Map
<
Double
,
List
<
Entry
>>
groups
=
new
HashMap
<>();
for
(
Entry
op
:
allOperations
)
{
double
priority
=
op
.
getPriority
();
groups
.
computeIfAbsent
(
priority
,
k
->
new
ArrayList
<>()).
add
(
op
);
}
return
groups
;
}
/**
* 将指定位置的工序与间隔distance的工序交换
* distance为负表示向左,为正表示向右
*/
private
Chromosome
swapAtDistance
(
Chromosome
chromosome
,
int
pos
,
int
distance
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
int
targetPos
=
pos
+
distance
;
if
(
targetPos
>=
0
&&
targetPos
<
os
.
size
()
&&
pos
>=
0
&&
pos
<
os
.
size
())
{
java
.
util
.
Collections
.
swap
(
os
,
pos
,
targetPos
);
neighbor
.
setOperationSequencing
(
os
);
}
return
neighbor
;
}
/**
/**
* 生成邻域解
* 生成邻域解
*/
*/
...
@@ -167,21 +617,64 @@ public class HillClimbing {
...
@@ -167,21 +617,64 @@ public class HillClimbing {
return
neighbor
;
return
neighbor
;
}
}
/**
* 生成机器选择邻域解
*/
private
Chromosome
generateMachineChange
(
Chromosome
chromosome
,
List
<
MachineOption
>
MachineOptions
,
int
idx
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
ms
=
neighbor
.
getMachineSelection
();
if
(!
ms
.
isEmpty
())
{
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
null
;
}
return
neighbor
;
}
private
void
batchDecode
(
GeneticDecoder
decoder
,
List
<
Chromosome
>
chromosomes
)
{
// 并行解码所有候选方案
decoder
.
Chromosomedecode
(
chromosomes
);
}
/**
/**
* 解码染色体
* 解码染色体
*/
*/
private
void
decode
(
GeneticDecoder
decoder
,
Chromosome
chromosome
,
ScheduleParams
param
)
{
private
void
decode
(
GeneticDecoder
decoder
,
Chromosome
chromosome
)
{
chromosome
.
setResult
(
new
java
.
util
.
concurrent
.
CopyOnWriteArrayList
<>());
//
chromosome.setResult(new java.util.concurrent.CopyOnWriteArrayList<>());
decoder
.
decodeChromosomeWithCache
(
chromosome
);
decoder
.
decodeChromosomeWithCache
(
chromosome
);
if
(
chromosome
.
getFitness
()
==
0
)
{
chromosome
.
setFitness
(
fitnessCalculator
.
calculateFitness
(
chromosome
,
objectiveWeights
));
}
}
}
/**
/**
* 比较两个染色体的优劣
* 比较两个染色体的优劣
*/
*/
private
boolean
isBetter
(
Chromosome
c1
,
Chromosome
c2
)
{
private
boolean
isBetter
(
Chromosome
c1
,
Chromosome
c2
)
{
return
c1
.
getFitness
()
>
c2
.
getFitness
();
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
;
}
}
}
}
\ No newline at end of file
src/main/java/com/aps/service/Algorithm/HybridAlgorithm.java
0 → 100644
View file @
47286670
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.entity.Algorithm.IDAndChildID.GroupResult
;
import
com.aps.entity.basic.*
;
import
com.aps.service.plan.MachineSchedulerService
;
import
com.aps.service.plan.SceneService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
java.time.LocalDateTime
;
import
java.util.*
;
import
java.util.concurrent.*
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.stream.Collectors
;
import
java.util.stream.IntStream
;
/**
* 作者:佟礼
* 时间:2026-03-23
*/
public
class
HybridAlgorithm
{
private
final
Random
rnd
=
new
Random
();
private
List
<
Machine
>
machines
;
private
final
MachineSchedulerService
machineScheduler
;
private
final
List
<
Order
>
orders
;
private
final
List
<
Material
>
materials
;
private
final
List
<
String
>
materialIds
;
private
static
GlobalParam
_GlobalParam
;
private
List
<
GroupResult
>
_entryRel
;
FitnessCalculator
_fitnessCalculator
=
new
FitnessCalculator
();
private
NSGAIIUtils
_nsgaIIUtils
=
new
NSGAIIUtils
();
private
ObjectiveWeights
_objectiveWeights
=
new
ObjectiveWeights
();
private
MaterialRequirementService
materialRequirementService
;
private
List
<
OrderMaterialRequirement
>
orderMaterials
;
private
SceneService
_sceneService
;
private
String
sceneId
;
private
VariableNeighborhoodSearch
_vns
;
// 初始化算法实例
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
,
List
<
Material
>
materials
,
List
<
String
>
_materialIds
,
MachineSchedulerService
machineScheduler
,
List
<
GroupResult
>
entryRel
,
MaterialRequirementService
_materialRequirementService
,
SceneService
sceneService
,
String
_sceneId
)
{
this
.
machines
=
machines
;
this
.
orders
=
orders
;
this
.
materials
=
materials
;
this
.
machineScheduler
=
machineScheduler
;
_GlobalParam
=
globalParam
;
_entryRel
=
entryRel
;
materialRequirementService
=
_materialRequirementService
;
_sceneService
=
sceneService
;
sceneId
=
_sceneId
;
materialIds
=
_materialIds
;
}
public
void
Init
()
{
// 自定义权重配置
_nsgaIIUtils
.
init
(
_GlobalParam
);
}
public
Chromosome
Run
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
)
{
if
(
allOperations
==
null
||
allOperations
.
size
()==
0
)
{
throw
new
RuntimeException
(
"没有待排产工单"
);
}
// if(materials!=null&&materials.size()>0) {
//
// materialRequirementService.init(materials, orders, allOperations, _entryRel, machineScheduler, machines,_GlobalParam);
//
// orderMaterials = materialRequirementService.buildMultiLevelRequirementNetwork(param.getBaseTime());
// Set<Long> existIds = new HashSet<>();
// machines=machines.stream()
// .filter(t->existIds.add(t.getId()))//HashSet.add() 方法:添加成功返回 true,重复返回 false;
// .collect(Collectors.toList());
// }
LocalDateTime
starttime
=
LocalDateTime
.
now
();
FileHelper
.
writeLogFile
(
"排产-----------开始-----------"
+
allOperations
.
get
(
0
).
getSceneId
());
Initialization
initialization
=
new
Initialization
(
_GlobalParam
,
allOperations
,
orders
,
machines
,
_objectiveWeights
);
GeneticOperations
geneticOps
=
new
GeneticOperations
(
_GlobalParam
,
allOperations
,
param
);
int
opcount
=
allOperations
.
size
();
// 预生成全局工序列表(所有初始化方法共享同一顺序)
List
<
GlobalOperationInfo
>
globalOpList
=
initialization
.
generateGlobalOpList
();
// 初始化变邻域搜索
_vns
=
new
VariableNeighborhoodSearch
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
_hillClimbing
=
new
HillClimbing
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
_simulatedAnnealing
=
new
SimulatedAnnealing
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
_parallelLocalSearch
=
new
ParallelLocalSearch
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
_tabuSearch
=
new
TabuSearch
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
_tabuSearchWithSA
=
new
TabuSearchWithSA
(
_GlobalParam
,
allOperations
,
globalOpList
,
_fitnessCalculator
,
_objectiveWeights
);
FileHelper
.
writeLogFile
(
"初始化种群-----------开始-------"
);
// 步骤1:使用构造启发式算法生成初始种群
FileHelper
.
writeLogFile
(
"构造启发式初始化-----------开始-------"
);
List
<
Chromosome
>
population
=
initialization
.
generateHeuristicInitialPopulation
(
param
,
globalOpList
);
FileHelper
.
writeLogFile
(
"构造启发式初始化-----------结束-------"
);
population
=
chromosomeDistinct
(
population
);
FileHelper
.
writeLogFile
(
"初始化种群-----------结束-------"
);
FileHelper
.
writeLogFile
(
"初始化批量解码-----------开始-------"
);
Chromosomedecode
(
param
,
allOperations
,
globalOpList
,
population
);
FileHelper
.
writeLogFile
(
"初始化批量解码-----------结束-------"
);
// 按Objectives去重,减少重复方案
FileHelper
.
writeLogFile
(
"按Objectives去重-----------开始-------"
+
population
.
size
());
population
=
chromosomeDistinctByObjectives
(
population
);
FileHelper
.
writeLogFile
(
"按Objectives去重-----------结束-------"
+
population
.
size
());
// 步骤2:对初始种群进行爬山法局部优化
if
(
population
.
size
()<
5
||
opcount
<
10
)
{
FileHelper
.
writeLogFile
(
"爬山法局部优化-----------开始-------"
);
GeneticDecoder
hillClimbingDecoder
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
Chromosome
optimized
=
_hillClimbing
.
BatchSearchAll
(
population
,
hillClimbingDecoder
,
param
);
FileHelper
.
writeLogFile
(
"爬山法局部优化-----------结束-------"
);
return
getBestChromosome
(
optimized
,
param
.
getBaseTime
(),
starttime
);
}
// 步骤2:对初始种群进行模拟退火+爬山法优化
FileHelper
.
writeLogFile
(
"模拟退火+爬山法优化-----------开始-------"
);
GeneticDecoder
saDecoder1
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
List
<
Chromosome
>
saHcOptimized
=
_simulatedAnnealing
.
batchSearch
(
population
,
saDecoder1
,
param
);
population
=
saHcOptimized
;
FileHelper
.
writeLogFile
(
"模拟退火+爬山法优化-----------结束-------"
);
List
<
List
<
Chromosome
>>
combinedFronts
=
_nsgaIIUtils
.
parallelFastNonDominatedSort
(
population
);
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
())
{
return
getBestChromosome
(
best
,
param
.
getBaseTime
(),
starttime
);
}
int
Iteration
=
0
;
// 步骤2:迭代进化
FileHelper
.
writeLogFile
(
"迭代进化-----------开始-------"
+
param
.
getMaxIterations
());
for
(
int
iter
=
0
;
iter
<
param
.
getMaxIterations
();
iter
++)
{
// 解码并计算适应度
FileHelper
.
writeLogFile
(
"迭代进化------"
+
iter
+
"-----开始-------"
);
// 计算种群适应度标准差,微调参数
double
fitnessStd
=
_fitnessCalculator
.
calculateFitnessStd
(
population
);
param
.
fineTuneParams
(
iter
,
fitnessStd
);
// 检查终止条件(此处简化为迭代次数)
if
(
iter
==
param
.
getMaxIterations
()
-
1
)
{
break
;
}
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
(
validPopulation
);
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
(
"爬山法局部优化-----------开始-------"
);
List
<
Chromosome
>
hcImproved
=
new
ArrayList
<>();
for
(
Chromosome
chromosome
:
selected
)
{
Chromosome
hcOptimized
=
_hillClimbing
.
search
(
chromosome
,
saDecoder
,
param
);
hcImproved
.
add
(
hcOptimized
);
}
selected
.
addAll
(
hcImproved
);
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());
best
=
GetBest
(
combinedFronts
,
String
.
valueOf
(
iter
));
if
(
bestFitness
<
best
.
getFitness
())
{
bestFitness
=
best
.
getFitness
();
Iteration
=
1
;
}
else
{
Iteration
++;
if
(
Iteration
>
5
)
{
// 当连续 5 代无最优解提升时,降低交叉概率(如从 0.8 降至 0.5)、提高变异概率(如从 0.1 升至 0.2)
param
.
fineTuneParams
();
}
}
if
(
Iteration
>
10
)
{
break
;
}
// 当种群适应度标准差小于阈值(如 0.001)时,说明种群已收敛,提前终止迭代
fitnessStd
=
_fitnessCalculator
.
calculateFitnessStd
(
population
);
if
(
fitnessStd
<
0.001
)
{
FileHelper
.
writeLogFile
(
"种群已收敛,提前终止迭代"
);
break
;
}
FileHelper
.
writeLogFile
(
"迭代进化------"
+
iter
+
"-----结束-------"
);
}
FileHelper
.
writeLogFile
(
"迭代进化-----------结束-------"
);
best
=
getBestChromosome
(
best
,
param
.
getBaseTime
(),
starttime
);
// 步骤3:返回最优解
return
best
;
}
private
Chromosome
getBestChromosome
(
Chromosome
best
,
LocalDateTime
BaseTime
,
LocalDateTime
starttime
)
{
best
.
setBaseTime
(
BaseTime
);
// best.setOrderMaterials(orderMaterials);
best
.
setMaterialIds
(
materialIds
);
best
.
setMaterials
(
null
);
best
.
setScenarioID
(
sceneId
);
// best.setOperatRel(_entryRel);
if
(
best
.
getInitMachines
()==
null
)
{
best
.
setInitMachines
(
ProductionDeepCopyUtil
.
deepCopyList
(
machines
,
Machine
.
class
));
}
LocalDateTime
endtime
=
LocalDateTime
.
now
();
FileHelper
.
writeLogFile
(
String
.
format
(
"排产----------结束---%s----耗时%d----"
,
sceneId
,
DateTimeUtil
.
diffDuration
(
starttime
,
endtime
).
getSeconds
())
);
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
)
{
FileHelper
.
writeLogFile
(
String
.
format
(
"排产-----------方案数量---%d-------"
,
0
));
return
population
;
}
population
=
population
.
stream
()
.
filter
(
chromosome
->
chromosome
!=
null
&&
chromosome
.
getGeneStr
()
!=
null
)
.
collect
(
Collectors
.
toMap
(
Chromosome:
:
getGeneStr
,
// key:去重的字段(GeneStr)
u
->
u
,
// value:Chromosome对象
(
u1
,
u2
)
->
u1
// 重复时保留第一个元素
))
.
values
()
// 获取去重后的
.
stream
()
.
collect
(
Collectors
.
toList
());
return
population
;
}
/**
* 按Objectives去重,相同目标值的方案只保留一个(保留fitness最大的)
*/
private
List
<
Chromosome
>
chromosomeDistinctByObjectives
(
List
<
Chromosome
>
population
)
{
if
(
population
==
null
||
population
.
isEmpty
())
{
return
population
;
}
// 使用Objectives数组的哈希值作为key
Map
<
String
,
Chromosome
>
objectivesMap
=
new
HashMap
<>();
for
(
Chromosome
chromosome
:
population
)
{
if
(
chromosome
==
null
||
chromosome
.
getObjectives
()
==
null
)
{
continue
;
}
// 将Objectives数组转换为字符串作为key
String
objectivesKey
=
Arrays
.
toString
(
chromosome
.
getObjectives
());
Chromosome
existing
=
objectivesMap
.
get
(
objectivesKey
);
if
(
existing
==
null
)
{
// 第一次遇到这个Objectives,直接添加
objectivesMap
.
put
(
objectivesKey
,
chromosome
);
}
else
{
// 已经存在,保留fitness更大的那个
if
(
chromosome
.
getFitness
()
>
existing
.
getFitness
())
{
objectivesMap
.
put
(
objectivesKey
,
chromosome
);
}
}
}
return
new
ArrayList
<>(
objectivesMap
.
values
());
}
private
List
<
Chromosome
>
chromosomeDistinct1
(
List
<
Chromosome
>
population
)
{
if
(
population
==
null
)
{
FileHelper
.
writeLogFile
(
String
.
format
(
"排产-----------方案数量---%d-------"
,
0
));
return
population
;
}
// 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
++)
{
FileHelper
.
writeLogFile
(
String
.
format
(
"KPI---%s--------%d----"
,
index
,
i
));
for
(
Chromosome
chromosome:
fronts
.
get
(
i
))
{
WriteKpi
(
chromosome
,
""
);
}
}
}
private
void
WriteKpi
(
Chromosome
chromosome
,
String
desc
)
{
FileHelper
.
writeLogFile
(
String
.
format
(
"KPI---%f----%f----%s----%s"
,
chromosome
.
getWeightedObjective
(),
chromosome
.
getFitness
(),
chromosome
.
getID
(),
desc
));
for
(
double
d:
chromosome
.
getObjectives
())
{
FileHelper
.
writeLogFile
(
String
.
format
(
" KPI---%f-------"
,
d
));
}
}
//private ExecutorService decodeExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
private
final
ExecutorService
decodeExecutor
=
new
ThreadPoolExecutor
(
Runtime
.
getRuntime
().
availableProcessors
()
-
1
,
// 核心线程数=CPU-1,无切换开销
Runtime
.
getRuntime
().
availableProcessors
()
-
1
,
// 最大线程数=核心数
0L
,
TimeUnit
.
MILLISECONDS
,
new
ArrayBlockingQueue
<>(
200
),
// 有界队列,避免内存溢出
new
ThreadPoolExecutor
.
CallerRunsPolicy
()
// 任务满了主线程执行,不丢失任务
);
private
void
Chromosomedecode
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
,
List
<
GlobalOperationInfo
>
globalOpList
,
List
<
Chromosome
>
population
)
{
FileHelper
.
writeLogFile
(
"解码---------------"
+
population
.
size
()
);
GeneticDecoder
decoder
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
boolean
ismore
=
true
;
if
(
ismore
)
{
CompletableFuture
.
allOf
(
population
.
stream
()
.
map
(
chromosome
->
CompletableFuture
.
runAsync
(()
->
decode
(
decoder
,
chromosome
,
param
,
allOperations
,
globalOpList
),
decodeExecutor
))
.
toArray
(
CompletableFuture
[]::
new
))
.
join
();
}
else
{
if
(
population
!=
null
&&
population
.
size
()
>
0
)
{
population
.
forEach
(
chromosome
->
{
decode
(
decoder
,
chromosome
,
param
,
allOperations
,
globalOpList
);
});
}
}
}
private
void
decode
(
GeneticDecoder
decoder
,
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");
decoder
.
decodeChromosomeWithCache
(
chromosome
);
if
(
chromosome
.
getFitness
()
==
0
)
{
chromosome
.
setFitness
(
_fitnessCalculator
.
calculateFitness
(
chromosome
,
_objectiveWeights
));
}
}
}
src/main/java/com/aps/service/Algorithm/Initialization.java
View file @
47286670
...
@@ -5,6 +5,7 @@ import com.aps.entity.Algorithm.Chromosome;
...
@@ -5,6 +5,7 @@ import com.aps.entity.Algorithm.Chromosome;
import
com.aps.entity.Algorithm.GlobalOperationInfo
;
import
com.aps.entity.Algorithm.GlobalOperationInfo
;
import
com.aps.entity.Algorithm.ObjectiveWeights
;
import
com.aps.entity.Algorithm.ObjectiveWeights
;
import
com.aps.entity.Algorithm.ScheduleParams
;
import
com.aps.entity.Algorithm.ScheduleParams
;
import
com.aps.entity.RoutingDiscreteParam
;
import
com.aps.entity.basic.*
;
import
com.aps.entity.basic.*
;
import
java.time.LocalDateTime
;
import
java.time.LocalDateTime
;
...
@@ -27,6 +28,8 @@ public class Initialization {
...
@@ -27,6 +28,8 @@ public class Initialization {
private
ObjectiveWeights
_objectiveWeights
=
new
ObjectiveWeights
();
private
ObjectiveWeights
_objectiveWeights
=
new
ObjectiveWeights
();
private
LocalDateTime
baseTime
;
// 当前基准时间
public
Initialization
()
{
public
Initialization
()
{
}
}
...
@@ -38,6 +41,7 @@ public class Initialization {
...
@@ -38,6 +41,7 @@ public class Initialization {
machines
=
_machines
;
machines
=
_machines
;
_objectiveWeights
=
objectiveWeights
;
_objectiveWeights
=
objectiveWeights
;
}
}
/**
/**
* 预生成全局工序列表(按“订单0→订单1→…+订单内工序1→2→…”排序,分配GlobalOpId)
* 预生成全局工序列表(按“订单0→订单1→…+订单内工序1→2→…”排序,分配GlobalOpId)
*/
*/
...
@@ -342,14 +346,14 @@ chromo.setOrders(new CopyOnWriteArrayList<>(orders));
...
@@ -342,14 +346,14 @@ chromo.setOrders(new CopyOnWriteArrayList<>(orders));
public
List
<
Chromosome
>
generateHeuristicInitialPopulation
(
ScheduleParams
param
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
public
List
<
Chromosome
>
generateHeuristicInitialPopulation
(
ScheduleParams
param
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
List
<
Chromosome
>
population
=
new
ArrayList
<>();
List
<
Chromosome
>
population
=
new
ArrayList
<>();
int
populationSize
=
param
.
getPopulationSize
();
int
populationSize
=
param
.
getPopulationSize
();
this
.
baseTime
=
param
.
getBaseTime
();
// 按比例生成不同启发式规则的个体
// 按比例生成不同启发式规则的个体
int
sptCount
=
(
int
)
(
populationSize
*
0.2
);
int
sptCount
=
(
int
)
(
populationSize
*
0.2
);
int
lptCount
=
sptCount
+
(
int
)
(
populationSize
*
0.
2
);
int
lptCount
=
sptCount
+
(
int
)
(
populationSize
*
0.
1
);
int
eddCount
=
lptCount
+
(
int
)
(
populationSize
*
0.2
);
int
eddCount
=
lptCount
+
(
int
)
(
populationSize
*
0.2
);
int
crCount
=
eddCount
+
(
int
)
(
populationSize
*
0.2
);
int
crCount
=
eddCount
+
(
int
)
(
populationSize
*
0.2
);
int
sstCount
=
populationSize
-
crCount
;
int
sstCount
=
crCount
+
(
int
)
(
populationSize
*
0.2
)
;
int
lsCount
=
populationSize
-
sstCount
;
IntStream
.
range
(
0
,
populationSize
)
IntStream
.
range
(
0
,
populationSize
)
.
parallel
()
.
parallel
()
.
forEach
(
i
->
{
.
forEach
(
i
->
{
...
@@ -358,123 +362,216 @@ chromo.setOrders(new CopyOnWriteArrayList<>(orders));
...
@@ -358,123 +362,216 @@ chromo.setOrders(new CopyOnWriteArrayList<>(orders));
if
(
i
<
sptCount
)
{
if
(
i
<
sptCount
)
{
// SPT规则
// SPT规则
generateSPTChromosome
(
chromo
,
globalOpList
);
chromo
.
setGenerateType
(
"SPT"
);
generateChromosomeByType
(
chromo
,
1
);
}
else
if
(
i
<
lptCount
)
{
}
else
if
(
i
<
lptCount
)
{
// LPT规则
// LPT规则
generateLPTChromosome
(
chromo
,
globalOpList
);
chromo
.
setGenerateType
(
"LPT"
);
generateChromosomeByType
(
chromo
,
2
);
}
else
if
(
i
<
eddCount
)
{
}
else
if
(
i
<
eddCount
)
{
// EDD规则
// EDD规则
generateEDDChromosome
(
chromo
,
globalOpList
);
chromo
.
setGenerateType
(
"EDD"
);
generateChromosomeByType
(
chromo
,
3
);
}
else
if
(
i
<
crCount
)
{
}
else
if
(
i
<
crCount
)
{
// CR规则
// CR规则
// generateCRChromosome(chromo, globalOpList);
chromo
.
setGenerateType
(
"CR"
);
}
else
{
generateCRChromosome
(
chromo
);
}
else
if
(
i
<
sstCount
)
{
// SST规则
// SST规则
// generateSSTChromosome(chromo, globalOpList);
chromo
.
setGenerateType
(
"SST"
);
generateSSTChromosome
(
chromo
);
}
else
{
// 随机规则
chromo
.
setGenerateType
(
"LS"
);
generateLsChromosome
(
chromo
);
}
}
population
.
add
(
chromo
);
population
.
add
(
chromo
);
});
});
return
population
;
return
population
;
}
/**
}
* 使用贪心算法生成染色体
/**
* SPT(最短加工时间)
*/
*/
private
Chromosome
generate
GreedyChromosome
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
private
Chromosome
generate
ChromosomeByType
(
Chromosome
chromosome
,
int
sortType
)
{
List
<
Integer
>
ms
=
new
ArrayList
<>();
List
<
Integer
>
ms
=
new
ArrayList
<>();
List
<
Integer
>
os
=
new
ArrayList
<>();
List
<
Integer
>
os
=
new
ArrayList
<>();
Map
<
Long
,
Double
>
machineLoad
=
new
HashMap
<>();
Map
<
Long
,
Double
>
machineLoad
=
new
HashMap
<>();
Map
<
Long
,
String
>
lastDiscreteParam
=
new
HashMap
<>();
Random
rnd
=
new
Random
();
List
<
GlobalOperationInfo
>
globalOpList
=
new
ArrayList
<>();
// 按优先级排序工序
List
<
GlobalOperationInfo
>
sortedOps
=
new
ArrayList
<>(
globalOpList
);
sortedOps
.
sort
((
o1
,
o2
)
->
{
int
priorityCompare
=
Double
.
compare
(
o2
.
getOp
().
getPriority
(),
o1
.
getOp
().
getPriority
());
if
(
priorityCompare
!=
0
)
return
priorityCompare
;
// 同优先级按加工时间排序
return
Double
.
compare
(
o1
.
getOp
().
getMachineOptions
().
get
(
0
).
getProcessingTime
(),
o2
.
getOp
().
getMachineOptions
().
get
(
0
).
getProcessingTime
());
});
for
(
GlobalOperationInfo
globalOp
:
sortedOps
)
{
Entry
op
=
globalOp
.
getOp
();
int
groupId
=
globalOp
.
getGroupId
();
// 贪心选择机器:综合考虑负载、换型时间和加工时间
// 1 SPT(最短加工时间) 2 LPT(最长加工时间)
Map
<
Integer
,
LocalDateTime
>
dueDateMap
=
new
HashMap
<>();
for
(
Order
order
:
orders
)
{
dueDateMap
.
put
(
order
.
getId
(),
order
.
getDueDate
());
}
Map
<
Entry
,
Integer
>
randomIds
=
new
HashMap
<>();
List
<
Integer
>
indices
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
allOperations
.
size
();
i
++)
{
indices
.
add
(
i
);
}
Collections
.
shuffle
(
indices
,
rnd
);
for
(
int
i
=
0
;
i
<
allOperations
.
size
();
i
++)
{
randomIds
.
put
(
allOperations
.
get
(
i
),
indices
.
get
(
i
));
}
boolean
considerSequence
=
rnd
.
nextBoolean
();
List
<
Entry
>
sortedOps
=
new
ArrayList
<>(
allOperations
);
if
(
sortType
==
1
||
sortType
==
2
)
{
if
(
considerSequence
)
{
sortedOps
.
sort
(
Comparator
.
comparing
((
Entry
op
)
->
op
.
getPriority
())
.
thenComparing
(
Entry:
:
getSequence
)
.
thenComparing
(
op
->
{
if
(
op
.
getMachineOptions
()
==
null
||
op
.
getMachineOptions
().
isEmpty
())
{
return
sortType
==
1
?
0.0
:
Double
.
MAX_VALUE
;
// 空值默认排最前/最后
}
double
time
=
op
.
getMachineOptions
().
get
(
0
).
getProcessingTime
()
*
op
.
getQuantity
();
return
sortType
==
1
?
time
:
-
time
;
})
.
thenComparing
(
randomIds:
:
get
));
}
else
{
sortedOps
.
sort
(
Comparator
.
comparing
((
Entry
op
)
->
op
.
getPriority
())
.
thenComparing
(
op
->
{
if
(
op
.
getMachineOptions
()
==
null
||
op
.
getMachineOptions
().
isEmpty
())
{
return
sortType
==
1
?
0.0
:
Double
.
MAX_VALUE
;
// 空值默认排最前/最后
}
double
time
=
op
.
getMachineOptions
().
get
(
0
).
getProcessingTime
()
*
op
.
getQuantity
();
return
sortType
==
1
?
time
:
-
time
;
})
.
thenComparing
(
randomIds:
:
get
));
}
}
else
if
(
sortType
==
3
)
{
if
(
considerSequence
)
{
sortedOps
.
sort
(
Comparator
.
comparing
((
Entry
op
)
->
op
.
getPriority
())
.
thenComparing
(
Entry:
:
getSequence
)
.
thenComparing
(
op
->
dueDateMap
.
get
(
op
.
getGroupId
()),
Comparator
.
nullsLast
(
Comparator
.
naturalOrder
()))
.
thenComparing
(
randomIds:
:
get
));
}
else
{
sortedOps
.
sort
(
Comparator
.
comparing
((
Entry
op
)
->
op
.
getPriority
())
.
thenComparing
(
op
->
dueDateMap
.
get
(
op
.
getGroupId
()),
Comparator
.
nullsLast
(
Comparator
.
naturalOrder
()))
.
thenComparing
(
randomIds:
:
get
));
}
}
int
globalOpId
=
0
;
// 为每个工序选择机器
for
(
Entry
op
:
sortedOps
)
{
int
groupId
=
op
.
getGroupId
();
// 选择负载最小的机器
List
<
MachineOption
>
optionalMachines
=
op
.
getMachineOptions
();
List
<
MachineOption
>
optionalMachines
=
op
.
getMachineOptions
();
MachineOption
bestMachine
=
optionalMachines
.
stream
()
double
minLoad
=
optionalMachines
.
stream
()
.
min
((
m1
,
m2
)
->
{
.
mapToDouble
(
m
->
machineLoad
.
getOrDefault
(
m
.
getMachineId
(),
0.0
)
+
m
.
getProcessingTime
())
// 计算综合成本
.
min
()
double
cost1
=
calculateMachineCost
(
m1
,
machineLoad
,
lastDiscreteParam
,
op
);
.
orElse
(
Double
.
MAX_VALUE
);
double
cost2
=
calculateMachineCost
(
m2
,
machineLoad
,
lastDiscreteParam
,
op
);
return
Double
.
compare
(
cost1
,
cost2
);
// 找到所有负载最小的机器
})
List
<
MachineOption
>
minLoadMachines
=
optionalMachines
.
stream
()
.
orElseThrow
(()
->
new
NoSuchElementException
(
"MachineOption not found"
));
.
filter
(
m
->
machineLoad
.
getOrDefault
(
m
.
getMachineId
(),
0.0
)
+
m
.
getProcessingTime
()
==
minLoad
)
.
collect
(
Collectors
.
toList
());
// 随机选择一个负载最小的机器
MachineOption
selectedMachine
=
minLoadMachines
.
get
(
rnd
.
nextInt
(
minLoadMachines
.
size
()));
// 计算机器顺序号
OptionalInt
index
=
IntStream
.
range
(
0
,
optionalMachines
.
size
())
OptionalInt
index
=
IntStream
.
range
(
0
,
optionalMachines
.
size
())
.
filter
(
i
->
best
Machine
.
getMachineId
()
==
optionalMachines
.
get
(
i
).
getMachineId
())
.
filter
(
i
->
selected
Machine
.
getMachineId
()
==
optionalMachines
.
get
(
i
).
getMachineId
())
.
findFirst
();
.
findFirst
();
int
machineSeq
=
index
.
orElse
(
0
)
+
1
;
int
machineSeq
=
index
.
orElse
(
0
)
+
1
;
ms
.
add
(
machineSeq
);
ms
.
add
(
machineSeq
);
// 更新机器状态
// 更新负载
machineLoad
.
put
(
bestMachine
.
getMachineId
(),
machineLoad
.
put
(
selectedMachine
.
getMachineId
(),
machineLoad
.
getOrDefault
(
bestMachine
.
getMachineId
(),
0.0
)
+
bestMachine
.
getProcessingTime
());
machineLoad
.
getOrDefault
(
selectedMachine
.
getMachineId
(),
0.0
)
+
selectedMachine
.
getProcessingTime
());
//lastDiscreteParam.put(bestMachine.getMachineId(), op.getDiscreteParameter());
os
.
add
(
groupId
);
os
.
add
(
groupId
);
}
GlobalOperationInfo
info
=
new
GlobalOperationInfo
();
info
.
setGlobalOpId
(
globalOpId
);
info
.
setGroupId
(
op
.
getGroupId
());
info
.
setSequence
(
op
.
getSequence
());
info
.
setOp
(
op
);
globalOpList
.
add
(
info
);
globalOpId
++;
}
chromosome
.
setGlobalOpList
(
globalOpList
);
chromosome
.
setOperationSequencing
(
os
);
chromosome
.
setOperationSequencing
(
os
);
chromosome
.
setMachineSelection
(
ms
);
chromosome
.
setMachineSelection
(
ms
);
return
chromosome
;
return
chromosome
;
}
}
/**
/**
* 计算机器综合成本
* CR(关键比率)规则:关键比率 = (截止日期 - 当前日期) / 剩余加工时间
* 比率越小,优先级越高
*/
*/
private
double
calculateMachineCost
(
MachineOption
machine
,
Map
<
Long
,
Double
>
machineLoad
,
private
Chromosome
generateCRChromosome
(
Chromosome
chromosome
)
{
Map
<
Long
,
String
>
lastDiscreteParam
,
Entry
op
)
{
double
loadCost
=
machineLoad
.
getOrDefault
(
machine
.
getMachineId
(),
0.0
);
double
processingCost
=
machine
.
getProcessingTime
();
// 计算换型成本
double
setupCost
=
0
;
String
lastParam
=
lastDiscreteParam
.
get
(
machine
.
getMachineId
());
if
(
lastParam
!=
null
&&
!
lastParam
.
equals
(
op
.
getDiscreteParameter
()))
{
setupCost
=
op
.
getSetupTime
().
doubleValue
();
}
// 综合成本:负载 + 加工时间 + 换型成本
return
loadCost
+
processingCost
+
setupCost
;
}
/**
* SPT(最短加工时间)
*/
private
Chromosome
generateSPTChromosome
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
List
<
Integer
>
ms
=
new
ArrayList
<>();
List
<
Integer
>
ms
=
new
ArrayList
<>();
List
<
Integer
>
os
=
new
ArrayList
<>();
List
<
Integer
>
os
=
new
ArrayList
<>();
Map
<
Long
,
Double
>
machineLoad
=
new
HashMap
<>();
Map
<
Long
,
Double
>
machineLoad
=
new
HashMap
<>();
Random
rnd
=
new
Random
();
Random
rnd
=
new
Random
();
List
<
GlobalOperationInfo
>
globalOpList
=
new
ArrayList
<>();
Map
<
Integer
,
Order
>
orderMap
=
new
HashMap
<>();
for
(
Order
order
:
orders
)
{
orderMap
.
put
(
order
.
getId
(),
order
);
}
Map
<
Integer
,
Double
>
remainingProcessingTime
=
new
HashMap
<>();
for
(
Entry
op
:
allOperations
)
{
int
groupId
=
op
.
getGroupId
();
double
quantity
=
op
.
getQuantity
();
double
processTime
=
op
.
getMachineOptions
().
get
(
0
).
getProcessingTime
()*
quantity
;
remainingProcessingTime
.
put
(
groupId
,
remainingProcessingTime
.
getOrDefault
(
groupId
,
0.0
)
+
processTime
);
}
List
<
Entry
>
sortedOps
=
new
ArrayList
<>(
allOperations
);
Map
<
Entry
,
Integer
>
randomIds
=
new
HashMap
<>();
List
<
Integer
>
indices
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
allOperations
.
size
();
i
++)
{
indices
.
add
(
i
);
}
Collections
.
shuffle
(
indices
,
rnd
);
for
(
int
i
=
0
;
i
<
allOperations
.
size
();
i
++)
{
randomIds
.
put
(
allOperations
.
get
(
i
),
indices
.
get
(
i
));
}
boolean
considerSequence
=
rnd
.
nextBoolean
();
if
(
considerSequence
)
{
sortedOps
.
sort
(
Comparator
.
comparing
((
Entry
op
)
->
-
op
.
getPriority
())
.
thenComparing
(
Entry:
:
getSequence
)
.
thenComparing
(
op
->
{
Order
order
=
orderMap
.
get
(
op
.
getGroupId
());
return
calculateCriticalRatio
(
order
,
remainingProcessingTime
.
getOrDefault
(
op
.
getGroupId
(),
0.0
));
})
.
thenComparing
(
randomIds:
:
get
));
}
else
{
sortedOps
.
sort
(
Comparator
.
comparing
((
Entry
op
)
->
-
op
.
getPriority
())
.
thenComparing
(
op
->
{
Order
order
=
orderMap
.
get
(
op
.
getGroupId
());
return
calculateCriticalRatio
(
order
,
remainingProcessingTime
.
getOrDefault
(
op
.
getGroupId
(),
0.0
));
})
.
thenComparing
(
randomIds:
:
get
));
}
// 按加工时间排序工序,加工时间相同时随机排序
List
<
GlobalOperationInfo
>
sortedOps
=
new
ArrayList
<>(
globalOpList
);
sortedOps
.
sort
((
o1
,
o2
)
->
{
double
time1
=
o1
.
getOp
().
getMachineOptions
().
get
(
0
).
getProcessingTime
();
double
time2
=
o2
.
getOp
().
getMachineOptions
().
get
(
0
).
getProcessingTime
();
int
timeCompare
=
Double
.
compare
(
time1
,
time2
);
if
(
timeCompare
!=
0
)
{
return
timeCompare
;
}
// 加工时间相同时随机排序
return
rnd
.
nextInt
(
2
)
*
2
-
1
;
});
int
globalOpId
=
0
;
// 为每个工序选择机器
// 为每个工序选择机器
for
(
GlobalOperationInfo
globalO
p
:
sortedOps
)
{
for
(
Entry
o
p
:
sortedOps
)
{
Entry
op
=
globalOp
.
getOp
();
int
groupId
=
globalO
p
.
getGroupId
();
int
groupId
=
o
p
.
getGroupId
();
// 选择负载最小的机器
// 选择负载最小的机器
List
<
MachineOption
>
optionalMachines
=
op
.
getMachineOptions
();
List
<
MachineOption
>
optionalMachines
=
op
.
getMachineOptions
();
...
@@ -502,94 +599,230 @@ chromo.setOrders(new CopyOnWriteArrayList<>(orders));
...
@@ -502,94 +599,230 @@ chromo.setOrders(new CopyOnWriteArrayList<>(orders));
machineLoad
.
getOrDefault
(
selectedMachine
.
getMachineId
(),
0.0
)
+
selectedMachine
.
getProcessingTime
());
machineLoad
.
getOrDefault
(
selectedMachine
.
getMachineId
(),
0.0
)
+
selectedMachine
.
getProcessingTime
());
os
.
add
(
groupId
);
os
.
add
(
groupId
);
}
GlobalOperationInfo
info
=
new
GlobalOperationInfo
();
info
.
setGlobalOpId
(
globalOpId
);
info
.
setGroupId
(
op
.
getGroupId
());
info
.
setSequence
(
op
.
getSequence
());
info
.
setOp
(
op
);
globalOpList
.
add
(
info
);
globalOpId
++;
}
chromosome
.
setGlobalOpList
(
globalOpList
);
chromosome
.
setOperationSequencing
(
os
);
chromosome
.
setOperationSequencing
(
os
);
chromosome
.
setMachineSelection
(
ms
);
chromosome
.
setMachineSelection
(
ms
);
return
chromosome
;
return
chromosome
;
}
}
private
double
calculateCriticalRatio
(
Order
order
,
double
remainingTime
)
{
if
(
order
==
null
||
order
.
getDueDate
()
==
null
||
remainingTime
<=
0
)
{
return
Double
.
MAX_VALUE
;
}
long
daysUntilDue
=
java
.
time
.
Duration
.
between
(
this
.
baseTime
,
order
.
getDueDate
()).
toDays
();
if
(
daysUntilDue
<=
0
)
{
return
0
;
}
return
(
double
)
daysUntilDue
/
remainingTime
;
}
/**
/**
*
EDD(最早截止日期)
*
SST(最短准备时间)规则:优先选择准备时间最短的工序
*/
*/
private
Chromosome
generate
EDDChromosome
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
private
Chromosome
generate
SSTChromosome
(
Chromosome
chromosome
)
{
List
<
Integer
>
ms
=
new
ArrayList
<>();
List
<
Integer
>
ms
=
new
ArrayList
<>();
List
<
Integer
>
os
=
new
ArrayList
<>();
List
<
Integer
>
os
=
new
ArrayList
<>();
Map
<
Long
,
Double
>
machineLoad
=
new
HashMap
<>();
Map
<
Long
,
Double
>
machineLoad
=
new
HashMap
<>();
Map
<
Long
,
List
<
RoutingDiscreteParam
>>
lastDiscreteParams
=
new
HashMap
<>();
Random
rnd
=
new
Random
();
List
<
GlobalOperationInfo
>
globalOpList
=
new
ArrayList
<>();
// 按截止日期排序订单
List
<
Entry
>
sortedOps
=
new
ArrayList
<>(
allOperations
);
Map
<
Integer
,
LocalDateTime
>
orderDueDates
=
new
HashMap
<>();
Map
<
Entry
,
Integer
>
randomIds
=
new
HashMap
<>();
for
(
Order
order
:
orders
)
{
List
<
Integer
>
indices
=
new
ArrayList
<>();
orderDueDates
.
put
(
order
.
getId
(),
order
.
getDueDate
());
for
(
int
i
=
0
;
i
<
allOperations
.
size
();
i
++)
{
indices
.
add
(
i
);
}
Collections
.
shuffle
(
indices
,
rnd
);
for
(
int
i
=
0
;
i
<
allOperations
.
size
();
i
++)
{
randomIds
.
put
(
allOperations
.
get
(
i
),
indices
.
get
(
i
));
}
}
List
<
GlobalOperationInfo
>
sortedOps
=
new
ArrayList
<>(
globalOpList
);
sortedOps
.
sort
(
Comparator
.
comparing
((
Entry
op
)
->
-
op
.
getPriority
())
sortedOps
.
sort
((
o1
,
o2
)
->
{
.
thenComparing
(
op
->
op
.
getProductId
()
!=
null
?
op
.
getProductId
()
:
""
)
LocalDateTime
due1
=
orderDueDates
.
get
(
o1
.
getGroupId
());
.
thenComparing
(
op
->
op
.
getMachineOptions
().
get
(
0
).
getProcessingTime
()
*
op
.
getQuantity
())
LocalDateTime
due2
=
orderDueDates
.
get
(
o2
.
getGroupId
());
.
thenComparing
(
randomIds:
:
get
));
if
(
due1
==
null
||
due2
==
null
)
return
0
;
return
due1
.
compareTo
(
due2
);
});
// 为每个工序选择机器
for
(
GlobalOperationInfo
globalOp
:
sortedOps
)
{
Entry
op
=
globalOp
.
getOp
();
int
groupId
=
globalOp
.
getGroupId
();
// 选择负载最小的机器
int
globalOpId
=
0
;
for
(
Entry
op
:
sortedOps
)
{
int
groupId
=
op
.
getGroupId
();
List
<
MachineOption
>
optionalMachines
=
op
.
getMachineOptions
();
List
<
MachineOption
>
optionalMachines
=
op
.
getMachineOptions
();
MachineOption
minLoadMachine
=
optionalMachines
.
stream
()
.
min
(
Comparator
.
comparingDouble
(
m
->
machineLoad
.
getOrDefault
(
m
.
getMachineId
(),
0.0
)
+
m
.
getProcessingTime
()))
MachineOption
bestMachine
=
optionalMachines
.
stream
()
.
min
((
m1
,
m2
)
->
{
double
cost1
=
calculateSSTCost
(
m1
,
machineLoad
,
lastDiscreteParams
,
op
);
double
cost2
=
calculateSSTCost
(
m2
,
machineLoad
,
lastDiscreteParams
,
op
);
return
Double
.
compare
(
cost1
,
cost2
);
})
.
orElseThrow
(()
->
new
NoSuchElementException
(
"MachineOption not found"
));
.
orElseThrow
(()
->
new
NoSuchElementException
(
"MachineOption not found"
));
OptionalInt
index
=
IntStream
.
range
(
0
,
optionalMachines
.
size
())
OptionalInt
index
=
IntStream
.
range
(
0
,
optionalMachines
.
size
())
.
filter
(
i
->
minLoad
Machine
.
getMachineId
()
==
optionalMachines
.
get
(
i
).
getMachineId
())
.
filter
(
i
->
best
Machine
.
getMachineId
()
==
optionalMachines
.
get
(
i
).
getMachineId
())
.
findFirst
();
.
findFirst
();
int
machineSeq
=
index
.
orElse
(
0
)
+
1
;
int
machineSeq
=
index
.
orElse
(
0
)
+
1
;
ms
.
add
(
machineSeq
);
ms
.
add
(
machineSeq
);
// 更新负载
machineLoad
.
put
(
bestMachine
.
getMachineId
(),
machineLoad
.
put
(
minLoadMachine
.
getMachineId
(),
machineLoad
.
getOrDefault
(
bestMachine
.
getMachineId
(),
0.0
)
+
bestMachine
.
getProcessingTime
());
machineLoad
.
getOrDefault
(
minLoadMachine
.
getMachineId
(),
0.0
)
+
minLoadMachine
.
getProcessingTime
());
if
(
op
.
getDiscreteParameter
()
!=
null
&&
!
op
.
getDiscreteParameter
().
isEmpty
())
{
lastDiscreteParams
.
put
(
bestMachine
.
getMachineId
(),
op
.
getDiscreteParameter
());
}
os
.
add
(
groupId
);
os
.
add
(
groupId
);
}
GlobalOperationInfo
info
=
new
GlobalOperationInfo
();
info
.
setGlobalOpId
(
globalOpId
);
info
.
setGroupId
(
op
.
getGroupId
());
info
.
setSequence
(
op
.
getSequence
());
info
.
setOp
(
op
);
globalOpList
.
add
(
info
);
globalOpId
++;
}
chromosome
.
setGlobalOpList
(
globalOpList
);
chromosome
.
setOperationSequencing
(
os
);
chromosome
.
setOperationSequencing
(
os
);
chromosome
.
setMachineSelection
(
ms
);
chromosome
.
setMachineSelection
(
ms
);
return
chromosome
;
return
chromosome
;
}
}
private
String
getDiscreteParamsKey
(
Entry
op
)
{
List
<
RoutingDiscreteParam
>
params
=
op
.
getDiscreteParameter
();
if
(
params
==
null
||
params
.
isEmpty
())
{
return
""
;
}
List
<
RoutingDiscreteParam
>
sortedParams
=
new
ArrayList
<>(
params
);
sortedParams
.
sort
(
Comparator
.
comparing
(
RoutingDiscreteParam:
:
getParameterName
));
StringBuilder
sb
=
new
StringBuilder
();
for
(
RoutingDiscreteParam
p
:
sortedParams
)
{
sb
.
append
(
p
.
getGroupName
()
!=
null
?
p
.
getGroupName
()
:
""
)
.
append
(
"|"
)
.
append
(
p
.
getParameterName
()
!=
null
?
p
.
getParameterName
()
:
""
)
.
append
(
"|"
)
.
append
(
";"
);
}
return
sb
.
toString
();
}
private
double
calculateSSTCost
(
MachineOption
machine
,
Map
<
Long
,
Double
>
machineLoad
,
Map
<
Long
,
List
<
RoutingDiscreteParam
>>
lastDiscreteParams
,
Entry
op
)
{
double
loadCost
=
machineLoad
.
getOrDefault
(
machine
.
getMachineId
(),
0.0
);
double
processingCost
=
machine
.
getProcessingTime
()
*
op
.
getQuantity
();
double
setupCost
=
0
;
List
<
RoutingDiscreteParam
>
lastParams
=
lastDiscreteParams
.
get
(
machine
.
getMachineId
());
if
(
lastParams
!=
null
&&
op
.
getDiscreteParameter
()
!=
null
)
{
boolean
needSetup
=
false
;
for
(
RoutingDiscreteParam
param
:
op
.
getDiscreteParameter
())
{
boolean
foundMatch
=
false
;
for
(
RoutingDiscreteParam
lastParam
:
lastParams
)
{
if
(
param
.
getGroupName
().
equals
(
lastParam
.
getGroupName
())
&&
param
.
getParameterName
().
equals
(
lastParam
.
getParameterName
()))
{
foundMatch
=
true
;
break
;
}
}
if
(!
foundMatch
)
{
needSetup
=
true
;
break
;
}
}
if
(
needSetup
)
{
setupCost
=
3600
;
}
}
return
loadCost
+
processingCost
+
setupCost
;
}
/**
/**
*
LPT(最长加工时间)启发式
*
随机
*/
*/
private
Chromosome
generateLPTChromosome
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
private
Chromosome
generateLsChromosome
(
Chromosome
chromosome
)
{
// 类似SPT,但排序顺序相反
List
<
Integer
>
ms
=
new
ArrayList
<>();
List
<
Integer
>
ms
=
new
ArrayList
<>();
List
<
Integer
>
os
=
new
ArrayList
<>();
List
<
Integer
>
os
=
new
ArrayList
<>();
Map
<
Long
,
Double
>
machineLoad
=
new
HashMap
<>();
Map
<
Long
,
Double
>
machineLoad
=
new
HashMap
<>();
Random
rnd
=
new
Random
();
Random
rnd
=
new
Random
();
List
<
GlobalOperationInfo
>
globalOpList
=
new
ArrayList
<>();
// 按加工时间排序工序,加工时间相同时随机排序
// 按加工时间排序工序,加工时间相同时随机排序
List
<
GlobalOperationInfo
>
sortedOps
=
new
ArrayList
<>(
globalOpList
);
List
<
Entry
>
sortedOps
=
new
ArrayList
<>(
allOperations
);
sortedOps
.
sort
((
o1
,
o2
)
->
{
Map
<
Entry
,
Integer
>
randomIds
=
new
HashMap
<>();
double
time1
=
o1
.
getOp
().
getMachineOptions
().
get
(
0
).
getProcessingTime
();
List
<
Integer
>
indices
=
new
ArrayList
<>();
double
time2
=
o2
.
getOp
().
getMachineOptions
().
get
(
0
).
getProcessingTime
();
for
(
int
i
=
0
;
i
<
allOperations
.
size
();
i
++)
{
int
timeCompare
=
Double
.
compare
(
time2
,
time1
);
// 注意这里是降序
indices
.
add
(
i
);
if
(
timeCompare
!=
0
)
{
}
return
timeCompare
;
Collections
.
shuffle
(
indices
,
rnd
);
}
for
(
int
i
=
0
;
i
<
allOperations
.
size
();
i
++)
{
// 加工时间相同时随机排序
randomIds
.
put
(
allOperations
.
get
(
i
),
indices
.
get
(
i
));
return
rnd
.
nextInt
(
2
)
*
2
-
1
;
}
});
sortedOps
.
sort
(
Comparator
.
comparing
((
Entry
op
)
->
-
op
.
getPriority
())
.
thenComparing
(
randomIds:
:
get
));
int
globalOpId
=
0
;
// 为每个工序选择机器
for
(
Entry
op
:
sortedOps
)
{
int
groupId
=
op
.
getGroupId
();
// 选择负载最小的机器
List
<
MachineOption
>
optionalMachines
=
op
.
getMachineOptions
();
double
minLoad
=
optionalMachines
.
stream
()
.
mapToDouble
(
m
->
machineLoad
.
getOrDefault
(
m
.
getMachineId
(),
0.0
)
+
m
.
getProcessingTime
())
.
min
()
.
orElse
(
Double
.
MAX_VALUE
);
// 找到所有负载最小的机器
List
<
MachineOption
>
minLoadMachines
=
optionalMachines
.
stream
()
.
filter
(
m
->
machineLoad
.
getOrDefault
(
m
.
getMachineId
(),
0.0
)
+
m
.
getProcessingTime
()
==
minLoad
)
.
collect
(
Collectors
.
toList
());
// 随机选择一个负载最小的机器
MachineOption
selectedMachine
=
minLoadMachines
.
get
(
rnd
.
nextInt
(
minLoadMachines
.
size
()));
OptionalInt
index
=
IntStream
.
range
(
0
,
optionalMachines
.
size
())
.
filter
(
i
->
selectedMachine
.
getMachineId
()
==
optionalMachines
.
get
(
i
).
getMachineId
())
.
findFirst
();
int
machineSeq
=
index
.
orElse
(
0
)
+
1
;
ms
.
add
(
machineSeq
);
// 更新负载
machineLoad
.
put
(
selectedMachine
.
getMachineId
(),
machineLoad
.
getOrDefault
(
selectedMachine
.
getMachineId
(),
0.0
)
+
selectedMachine
.
getProcessingTime
());
os
.
add
(
groupId
);
// 为每个工序选择机器(与SPT相同)
// ...
GlobalOperationInfo
info
=
new
GlobalOperationInfo
();
info
.
setGlobalOpId
(
globalOpId
);
info
.
setGroupId
(
op
.
getGroupId
());
info
.
setSequence
(
op
.
getSequence
());
info
.
setOp
(
op
);
globalOpList
.
add
(
info
);
globalOpId
++;
}
chromosome
.
setGlobalOpList
(
globalOpList
);
chromosome
.
setOperationSequencing
(
os
);
chromosome
.
setOperationSequencing
(
os
);
chromosome
.
setMachineSelection
(
ms
);
chromosome
.
setMachineSelection
(
ms
);
return
chromosome
;
return
chromosome
;
}
}
/**
/**
* 按优先级加权打乱工序排序(高优先级订单的工序更可能靠前)
* 按优先级加权打乱工序排序(高优先级订单的工序更可能靠前)
*/
*/
...
...
src/main/java/com/aps/service/Algorithm/ParallelLocalSearch.java
View file @
47286670
...
@@ -48,10 +48,10 @@ public class ParallelLocalSearch {
...
@@ -48,10 +48,10 @@ public class ParallelLocalSearch {
});
});
// 添加模拟退火任务
// 添加模拟退火任务
tasks
.
add
(()
->
{
//
tasks.add(() -> {
SimulatedAnnealing
sa
=
new
SimulatedAnnealing
(
globalParam
,
allOperations
,
globalOpList
,
fitnessCalculator
,
objectiveWeights
);
//
SimulatedAnnealing sa = new SimulatedAnnealing(globalParam, allOperations, globalOpList, fitnessCalculator, objectiveWeights);
return
sa
.
search
(
chromosome
,
decoder
,
param
);
//
return sa.search(chromosome, decoder, param);
});
//
});
// 执行所有任务
// 执行所有任务
List
<
Chromosome
>
results
=
new
ArrayList
<>();
List
<
Chromosome
>
results
=
new
ArrayList
<>();
...
...
src/main/java/com/aps/service/Algorithm/SimulatedAnnealing.java
View file @
47286670
...
@@ -5,9 +5,8 @@ import com.aps.entity.Algorithm.*;
...
@@ -5,9 +5,8 @@ import com.aps.entity.Algorithm.*;
import
com.aps.entity.basic.Entry
;
import
com.aps.entity.basic.Entry
;
import
com.aps.entity.basic.GlobalParam
;
import
com.aps.entity.basic.GlobalParam
;
import
java.util.ArrayList
;
import
java.util.*
;
import
java.util.List
;
import
java.util.concurrent.*
;
import
java.util.Random
;
/**
/**
* 模拟退火算法
* 模拟退火算法
...
@@ -27,167 +26,270 @@ public class SimulatedAnnealing {
...
@@ -27,167 +26,270 @@ public class SimulatedAnnealing {
this
.
fitnessCalculator
=
fitnessCalculator
;
this
.
fitnessCalculator
=
fitnessCalculator
;
this
.
objectiveWeights
=
objectiveWeights
;
this
.
objectiveWeights
=
objectiveWeights
;
}
}
private
final
ExecutorService
decodeExecutor
=
new
ThreadPoolExecutor
(
Runtime
.
getRuntime
().
availableProcessors
()
-
1
,
// 核心线程数=CPU-1,无切换开销
Runtime
.
getRuntime
().
availableProcessors
()
-
1
,
// 最大线程数=核心数
0L
,
TimeUnit
.
MILLISECONDS
,
new
ArrayBlockingQueue
<>(
200
),
// 有界队列,避免内存溢出
new
ThreadPoolExecutor
.
CallerRunsPolicy
()
// 任务满了主线程执行,不丢失任务
);
public
List
<
Chromosome
>
batchSearch
(
List
<
Chromosome
>
chromosomes
,
GeneticDecoder
decoder
,
ScheduleParams
param
)
{
List
<
Chromosome
>
saHcOptimized
=
new
ArrayList
<>();
CompletableFuture
.
allOf
(
chromosomes
.
stream
()
.
map
(
chromosome
->
CompletableFuture
.
runAsync
(()
->
{
Chromosome
optimized
=
searchWithHillClimbing
(
chromosome
,
decoder
,
param
);
saHcOptimized
.
add
(
optimized
);
},
decodeExecutor
))
.
toArray
(
CompletableFuture
[]::
new
))
.
join
();
return
saHcOptimized
;
}
/**
/**
* 模拟退火搜索
* 模拟退火搜索,当温度降低到一定程度后切换到爬山法
*/
* 流程:模拟退火迭代 → 随机生成新排产 → 按概率接受 → 降温 → 温度低时爬山法求精 → 输出最优
public
Chromosome
search
(
Chromosome
chromosome
,
GeneticDecoder
decoder
,
ScheduleParams
param
)
{
*/
public
Chromosome
searchWithHillClimbing
(
Chromosome
chromosome
,
GeneticDecoder
decoder
,
ScheduleParams
param
)
{
Chromosome
current
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
Chromosome
current
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
Chromosome
best
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
Chromosome
best
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
// 初始化温度
// 初始化解码
// decode(decoder, best, param);
// decode(decoder, current, param);
Map
<
String
,
Entry
>
Entrys
=
buildEntryKey
(
current
);
// 初始化温度 - 优化速度:更快降温,更快切换到爬山法
double
temperature
=
100.0
;
double
temperature
=
100.0
;
double
coolingRate
=
0.95
;
double
coolingRate
=
0.95
;
int
maxIterations
=
1000
;
double
temperatureThreshold
=
1.0
;
// 提高阈值,更快切换到爬山法
int
maxIterations
=
300
;
// 减少最大迭代次数
int
noImproveCount
=
0
;
int
maxNoImprove
=
50
;
// 连续50次没改进就提前停止
for
(
int
i
=
0
;
i
<
maxIterations
;
i
++)
{
for
(
int
i
=
0
;
i
<
maxIterations
;
i
++)
{
// 生成邻域解
boolean
improved
=
false
;
Chromosome
neighbor
=
generateNeighbor
(
current
);
// 1. 随机生成新排产(邻域解)
Chromosome
neighbor
=
generateNeighbor
(
current
,
Entrys
);
// 解码并计算适应度
// 2. 解码并计算适应度(只解码neighbor,current已经解码过了)
decode
(
decoder
,
current
,
param
);
decode
(
decoder
,
neighbor
,
param
);
decode
(
decoder
,
neighbor
,
param
);
//
计算能量差
//
3. 计算能量差(fitness差)
double
energyDifference
=
neighbor
.
getFitness
()
-
current
.
getFitness
(
);
double
energyDifference
=
calculateEnergyDifference
(
neighbor
,
current
);
// 接受新解的概率
// 4. 按概率接受新解
// - 更优:直接接受
// - 较差:概率接受(高温更容易接受)
if
(
energyDifference
>
0
||
rnd
.
nextDouble
()
<
Math
.
exp
(
energyDifference
/
temperature
))
{
if
(
energyDifference
>
0
||
rnd
.
nextDouble
()
<
Math
.
exp
(
energyDifference
/
temperature
))
{
current
=
neighbor
;
current
=
neighbor
;
// 更新全局最优
if
(
isBetter
(
current
,
best
))
{
if
(
isBetter
(
current
,
best
))
{
best
=
current
;
best
=
ProductionDeepCopyUtil
.
deepCopy
(
current
,
Chromosome
.
class
);
improved
=
true
;
noImproveCount
=
0
;
}
}
}
}
// 降温
if
(!
improved
)
{
noImproveCount
++;
}
// 5. 降温
temperature
*=
coolingRate
;
temperature
*=
coolingRate
;
if
(
temperature
<
0.1
)
{
break
;
// 6. 提前停止条件:温度低于阈值 或 连续多次没改进
if
(
temperature
<
temperatureThreshold
||
noImproveCount
>=
maxNoImprove
)
{
HillClimbing
hillClimbing
=
new
HillClimbing
(
globalParam
,
allOperations
,
globalOpList
,
fitnessCalculator
,
objectiveWeights
);
Chromosome
refined
=
hillClimbing
.
search
(
best
,
decoder
,
param
);
// 返回爬山法求精后的结果
return
refined
;
}
}
}
}
// 7. 输出全局最优排产
return
best
;
return
best
;
}
}
/**
/**
*
模拟退火搜索,当温度降低到一定程度后切换到爬山法
*
计算能量差(基于fitnessLevel数组的比较)
*/
*/
p
ublic
Chromosome
searchWithHillClimbing
(
Chromosome
chromosome
,
GeneticDecoder
decoder
,
ScheduleParams
param
)
{
p
rivate
double
calculateEnergyDifference
(
Chromosome
neighbor
,
Chromosome
current
)
{
Chromosome
current
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
double
[]
neighborFitness
=
neighbor
.
getFitnessLevel
(
);
Chromosome
best
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
double
[]
currentFitness
=
current
.
getFitnessLevel
(
);
// 初始化温度
// 计算加权能量差
double
temperature
=
100.0
;
double
diff
=
0
;
double
coolingRate
=
0.95
;
for
(
int
i
=
0
;
i
<
neighborFitness
.
length
;
i
++)
{
double
temperatureThreshold
=
1.0
;
// 温度阈值
diff
+=
(
neighborFitness
[
i
]
-
currentFitness
[
i
]);
int
maxIterations
=
500
;
}
return
diff
;
}
/**
* 构建位置->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
<
maxIterations
;
i
++)
{
for
(
int
i
=
0
;
i
<
os
.
size
();
i
++)
{
// 生成邻域解
int
groupId
=
os
.
get
(
i
);
Chromosome
neighbor
=
generateNeighbor
(
current
);
int
count
=
orderProcessCounter
.
getOrDefault
(
groupId
,
0
)
+
1
;
orderProcessCounter
.
put
(
groupId
,
count
);
// 解码并计算适应度
String
key
=
groupId
+
"_"
+
count
;
decode
(
decoder
,
current
,
param
);
Entry
op
=
entrys
.
get
(
key
);
decode
(
decoder
,
neighbor
,
param
);
// 计算能量差
if
(
op
!=
null
)
{
double
energyDifference
=
neighbor
.
getFitness
()
-
current
.
getFitness
();
index
.
put
(
i
,
op
);
// 接受新解的概率
if
(
energyDifference
>
0
||
rnd
.
nextDouble
()
<
Math
.
exp
(
energyDifference
/
temperature
))
{
current
=
neighbor
;
if
(
isBetter
(
current
,
best
))
{
best
=
current
;
}
}
}
}
return
index
;
}
/**
* 构建Entry索引:op.getGroupId() + "_" + op.getSequence() -> Entry
*/
private
Map
<
String
,
Entry
>
buildEntryKey
(
Chromosome
chromosome
)
{
Map
<
String
,
Entry
>
index
=
new
HashMap
<>();
// 降温
List
<
Entry
>
allOps
=
chromosome
.
getAllOperations
();
temperature
*=
coolingRate
;
// 当温度降低到阈值以下,切换到爬山法
for
(
Entry
op
:
allOps
)
{
if
(
temperature
<
temperatureThreshold
)
{
String
key
=
op
.
getGroupId
()
+
"_"
+
op
.
getSequence
();
HillClimbing
hillClimbing
=
new
HillClimbing
(
globalParam
,
allOperations
,
globalOpList
,
fitnessCalculator
,
objectiveWeights
);
return
hillClimbing
.
search
(
best
,
decoder
,
param
);
index
.
put
(
key
,
op
);
}
}
}
return
best
;
return
index
;
}
}
/**
/**
* 生成邻域解
* 生成邻域解
*/
*/
private
Chromosome
generateNeighbor
(
Chromosome
chromosome
)
{
private
Chromosome
generateNeighbor
(
Chromosome
chromosome
,
Map
<
String
,
Entry
>
entrys
)
{
int
neighborType
=
rnd
.
nextInt
(
4
);
int
neighborType
=
rnd
.
nextInt
(
4
);
switch
(
neighborType
)
{
switch
(
neighborType
)
{
case
0
:
case
0
:
return
generateSwapNeighbor
(
chromosome
);
return
generateSwapNeighbor
(
chromosome
,
entrys
);
case
1
:
case
1
:
return
generateReverseNeighbor
(
chromosome
);
return
generateReverseNeighbor
(
chromosome
,
entrys
);
case
2
:
case
2
:
return
generateInsertNeighbor
(
chromosome
);
return
generateInsertNeighbor
(
chromosome
,
entrys
);
case
3
:
case
3
:
return
generateMachineChangeNeighbor
(
chromosome
);
return
generateMachineChangeNeighbor
(
chromosome
);
default
:
default
:
return
generateSwapNeighbor
(
chromosome
);
return
generateSwapNeighbor
(
chromosome
,
entrys
);
}
}
}
}
/**
/**
* 生成交换邻域解
* 生成交换邻域解
- 只在相同优先级的工序之间交换
*/
*/
private
Chromosome
generateSwapNeighbor
(
Chromosome
chromosome
)
{
private
Chromosome
generateSwapNeighbor
(
Chromosome
chromosome
,
Map
<
String
,
Entry
>
entrys
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
os
.
size
()
>=
2
)
{
if
(
os
.
size
()
>=
2
)
{
int
idx1
=
rnd
.
nextInt
(
os
.
size
());
Map
<
Integer
,
Entry
>
positionIndex
=
buildPositionToEntryIndex
(
neighbor
,
entrys
);
int
idx2
=
rnd
.
nextInt
(
os
.
size
());
while
(
idx2
==
idx1
)
{
int
maxAttempts
=
50
;
idx2
=
rnd
.
nextInt
(
os
.
size
());
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
;
}
}
}
}
java
.
util
.
Collections
.
swap
(
os
,
idx1
,
idx2
);
neighbor
.
setOperationSequencing
(
os
);
}
}
return
neighbor
;
return
neighbor
;
}
}
/**
/**
* 生成反转邻域解
* 生成反转邻域解
- 只反转相同优先级的连续工序
*/
*/
private
Chromosome
generateReverseNeighbor
(
Chromosome
chromosome
)
{
private
Chromosome
generateReverseNeighbor
(
Chromosome
chromosome
,
Map
<
String
,
Entry
>
entrys
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
os
.
size
()
>=
2
)
{
if
(
os
.
size
()
>=
2
)
{
int
start
=
rnd
.
nextInt
(
os
.
size
());
Map
<
Integer
,
Entry
>
positionIndex
=
buildPositionToEntryIndex
(
neighbor
,
entrys
);
int
end
=
rnd
.
nextInt
(
os
.
size
());
while
(
end
<=
start
)
{
int
maxAttempts
=
50
;
end
=
rnd
.
nextInt
(
os
.
size
());
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
;
}
}
}
java
.
util
.
Collections
.
reverse
(
os
.
subList
(
start
,
end
+
1
));
neighbor
.
setOperationSequencing
(
os
);
}
}
return
neighbor
;
return
neighbor
;
}
}
/**
/**
* 生成插入邻域解
* 生成插入邻域解
- 只插入到相同优先级的位置
*/
*/
private
Chromosome
generateInsertNeighbor
(
Chromosome
chromosome
)
{
private
Chromosome
generateInsertNeighbor
(
Chromosome
chromosome
,
Map
<
String
,
Entry
>
entrys
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
List
<
Integer
>
os
=
neighbor
.
getOperationSequencing
();
if
(
os
.
size
()
>=
2
)
{
if
(
os
.
size
()
>=
2
)
{
int
idx1
=
rnd
.
nextInt
(
os
.
size
());
Map
<
Integer
,
Entry
>
positionIndex
=
buildPositionToEntryIndex
(
neighbor
,
entrys
);
int
idx2
=
rnd
.
nextInt
(
os
.
size
());
while
(
idx2
==
idx1
)
{
int
maxAttempts
=
50
;
idx2
=
rnd
.
nextInt
(
os
.
size
());
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
;
}
}
}
}
int
value
=
os
.
remove
(
idx1
);
os
.
add
(
idx2
,
value
);
neighbor
.
setOperationSequencing
(
os
);
}
}
return
neighbor
;
return
neighbor
;
}
}
/**
/**
* 生成机器选择邻域解
* 生成机器选择邻域解
- 不受优先级限制
*/
*/
private
Chromosome
generateMachineChangeNeighbor
(
Chromosome
chromosome
)
{
private
Chromosome
generateMachineChangeNeighbor
(
Chromosome
chromosome
)
{
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
Chromosome
neighbor
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
...
@@ -220,7 +322,6 @@ public class SimulatedAnnealing {
...
@@ -220,7 +322,6 @@ public class SimulatedAnnealing {
* 解码染色体
* 解码染色体
*/
*/
private
void
decode
(
GeneticDecoder
decoder
,
Chromosome
chromosome
,
ScheduleParams
param
)
{
private
void
decode
(
GeneticDecoder
decoder
,
Chromosome
chromosome
,
ScheduleParams
param
)
{
chromosome
.
setResult
(
new
java
.
util
.
concurrent
.
CopyOnWriteArrayList
<>());
decoder
.
decodeChromosomeWithCache
(
chromosome
);
decoder
.
decodeChromosomeWithCache
(
chromosome
);
if
(
chromosome
.
getFitness
()
==
0
)
{
if
(
chromosome
.
getFitness
()
==
0
)
{
chromosome
.
setFitness
(
fitnessCalculator
.
calculateFitness
(
chromosome
,
objectiveWeights
));
chromosome
.
setFitness
(
fitnessCalculator
.
calculateFitness
(
chromosome
,
objectiveWeights
));
...
@@ -228,9 +329,16 @@ public class SimulatedAnnealing {
...
@@ -228,9 +329,16 @@ public class SimulatedAnnealing {
}
}
/**
/**
* 比较两个染色体的优劣
* 比较两个染色体的优劣
(基于fitnessLevel多层次比较)
*/
*/
private
boolean
isBetter
(
Chromosome
c1
,
Chromosome
c2
)
{
private
boolean
isBetter
(
Chromosome
c1
,
Chromosome
c2
)
{
return
c1
.
getFitness
()
>
c2
.
getFitness
();
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
;
}
}
}
}
\ No newline at end of file
src/main/java/com/aps/service/plan/PlanResultService.java
View file @
47286670
...
@@ -210,7 +210,7 @@ public class PlanResultService {
...
@@ -210,7 +210,7 @@ public class PlanResultService {
.
collect
(
Collectors
.
toList
());
.
collect
(
Collectors
.
toList
());
globalParam
.
setPureNSGAIIMode
(
false
);
globalParam
.
setPureNSGAIIMode
(
false
);
// 5. 执行调度算法
// 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
());
param
.
initAdaptiveParams
(
entrys
.
size
());
double
[]
customWeights
=
new
double
[]
{
0.4
,
0.1
,
0.1
,
0.1
,
0.3
};
// 延迟时间权重提升到0.5
double
[]
customWeights
=
new
double
[]
{
0.4
,
0.1
,
0.1
,
0.1
,
0.3
};
// 延迟时间权重提升到0.5
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
...
...
src/test/java/com/aps/demo/PlanResultServiceTest.java
View file @
47286670
...
@@ -39,7 +39,9 @@ public class PlanResultServiceTest {
...
@@ -39,7 +39,9 @@ public class PlanResultServiceTest {
// TestSortService sortService=new TestSortService();
// TestSortService sortService=new TestSortService();
// sortService.test1();
// sortService.test1();
// nsgaiiUtils.Test();
// nsgaiiUtils.Test();
planResultService
.
execute2
(
"0428340BB4F540938F1FB5599F03E8A4"
);
// planResultService.execute2("0428340BB4F540938F1FB5599F03E8A4");//2000
planResultService
.
execute2
(
"C8B533BD8944405B9A2F8823C575C204"
);
//500
// planResultService.execute2("EFDD34E4B5BC434BAEAE6A84DFCD4E7B");//20
// planResultService.execute2("00E0C5D3E4AD4F36B56C39395906618D");
// planResultService.execute2("00E0C5D3E4AD4F36B56C39395906618D");
// planResultService.execute2("92BB773E1E2447C99D8176C991D5C9D2");
// planResultService.execute2("92BB773E1E2447C99D8176C991D5C9D2");
...
...
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