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
34bcb88f
Commit
34bcb88f
authored
Jan 06, 2026
by
Tong Li
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/tl'
parents
f96d4ca7
4562cda0
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1001 additions
and
314 deletions
+1001
-314
Chromosome.java
src/main/java/com/aps/entity/Algorithm/Chromosome.java
+38
-15
ObjectiveWeights.java
src/main/java/com/aps/entity/Algorithm/ObjectiveWeights.java
+2
-2
ScheduleParams.java
src/main/java/com/aps/entity/Algorithm/ScheduleParams.java
+2
-2
EquipCapacityDef.java
src/main/java/com/aps/entity/EquipCapacityDef.java
+1
-1
ProdEquipSpecialCal.java
src/main/java/com/aps/entity/ProdEquipSpecialCal.java
+1
-1
Shift.java
src/main/java/com/aps/entity/basic/Shift.java
+1
-1
TimeSegment.java
src/main/java/com/aps/entity/basic/TimeSegment.java
+7
-0
FitnessCalculator.java
...ain/java/com/aps/service/Algorithm/FitnessCalculator.java
+19
-15
GeneticAlgorithm.java
...main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
+60
-22
GeneticDecoder.java
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
+23
-22
GeneticOperations.java
...ain/java/com/aps/service/Algorithm/GeneticOperations.java
+30
-42
Initialization.java
src/main/java/com/aps/service/Algorithm/Initialization.java
+6
-1
MachineCalculator.java
...ain/java/com/aps/service/Algorithm/MachineCalculator.java
+410
-4
MaterialRequirementService.java
...com/aps/service/Algorithm/MaterialRequirementService.java
+30
-10
NSGAIIUtils.java
src/main/java/com/aps/service/Algorithm/NSGAIIUtils.java
+256
-125
RoutingDataService.java
...in/java/com/aps/service/Algorithm/RoutingDataService.java
+8
-2
ProdEquipSpecialCalServiceImpl.java
.../com/aps/service/impl/ProdEquipSpecialCalServiceImpl.java
+3
-1
MachineSchedulerService.java
...in/java/com/aps/service/plan/MachineSchedulerService.java
+74
-30
PlanResultService.java
src/main/java/com/aps/service/plan/PlanResultService.java
+23
-15
PlanResultServiceTest.java
src/test/java/com/aps/demo/PlanResultServiceTest.java
+7
-3
No files found.
src/main/java/com/aps/entity/Algorithm/Chromosome.java
View file @
34bcb88f
...
@@ -28,36 +28,49 @@ public class Chromosome {
...
@@ -28,36 +28,49 @@ public class Chromosome {
/// <summary>
/// <summary>
/// 机器选择部分(可选机器集中的顺序号)
/// 机器选择部分(可选机器集中的顺序号)
/// </summary>
/// </summary>
private
List
<
Integer
>
M
achineSelection
;
private
List
<
Integer
>
m
achineSelection
;
/// <summary>
/// <summary>
/// 工序排序部分(工件/订单ID)
/// 工序排序部分(工件/订单ID)
/// </summary>
/// </summary>
private
String
M
achineStr
;
private
String
m
achineStr
;
public
String
getMachineStr
()
{
/// <summary>
if
(
MachineSelection
==
null
)
return
""
;
/// 机器选择部分 + 工序排序部分
return
MachineSelection
.
stream
()
/// </summary>
private
String
geneStr
;
public
void
setMachineSelection
(
List
<
Integer
>
val
)
{
machineSelection
=
val
;
machineStr
=
machineSelection
.
stream
()
.
map
(
String:
:
valueOf
)
// 将每个 Integer 转换为 String
.
map
(
String:
:
valueOf
)
// 将每个 Integer 转换为 String
.
collect
(
Collectors
.
joining
(
","
));
.
collect
(
Collectors
.
joining
(
","
));
};
geneStr
=
machineStr
+
"_"
+
operationStr
;
}
/// <summary>
/// <summary>
/// 工序排序部分(工件/订单ID)
/// 工序排序部分(工件/订单ID)
/// </summary>
/// </summary>
private
List
<
Integer
>
OperationSequencing
;
private
List
<
Integer
>
operationSequencing
;
public
void
setOperationSequencing
(
List
<
Integer
>
val
)
{
operationSequencing
=
val
;
operationStr
=
operationSequencing
.
stream
()
.
map
(
String:
:
valueOf
)
// 将每个 Integer 转换为 String
.
collect
(
Collectors
.
joining
(
","
));
geneStr
=
machineStr
+
"_"
+
operationStr
;
}
/// <summary>
/// <summary>
/// 工序排序部分(工件/订单ID)
/// 工序排序部分(工件/订单ID)
/// </summary>
/// </summary>
private
String
OperationStr
;
private
String
operationStr
;
public
String
getOperationStr
()
{
if
(
OperationSequencing
==
null
)
return
""
;
return
OperationSequencing
.
stream
()
.
map
(
String:
:
valueOf
)
// 将每个 Integer 转换为 String
.
collect
(
Collectors
.
joining
(
"|"
));
};
private
List
<
GlobalOperationInfo
>
globalOpList
;
private
List
<
GlobalOperationInfo
>
globalOpList
;
private
List
<
Entry
>
allOperations
;
private
List
<
Entry
>
allOperations
;
...
@@ -68,9 +81,19 @@ public class Chromosome {
...
@@ -68,9 +81,19 @@ public class Chromosome {
private
List
<
GroupResult
>
OperatRel
;
private
List
<
GroupResult
>
OperatRel
;
private
ObjectiveWeights
objectiveWeights
;
/*
* 最早完工时间(最小化) 最小化总加工时间 最小总换型时间
*/
private
double
[]
Objectives
;
// 多目标值:[Makespan, TotalFlowTime, TotalChangeover, LoadStd, Delay]
private
double
[]
Objectives
;
// 多目标值:[Makespan, TotalFlowTime, TotalChangeover, LoadStd, Delay]
private
double
[]
MaxObjectives
;
//
private
double
[]
MinObjectives
;
//
private
int
Rank
;
// 非支配排序等级(1最优)
private
int
Rank
;
// 非支配排序等级(1最优)
private
double
CrowdingDistance
=
0
;
// 拥挤距离
private
double
CrowdingDistance
=
0
;
// 拥挤距离 越小越优
/*
*(Objectives - min) / (max - min);
*/
private
double
[]
WeightedObjectives
;
//越靠近1越优
private
double
WeightedObjective
=
0
;
// 加权目标值(用于自定义权重)
private
double
WeightedObjective
=
0
;
// 加权目标值(用于自定义权重)
/// <summary>
/// <summary>
/// 适应度值
/// 适应度值
...
...
src/main/java/com/aps/entity/Algorithm/ObjectiveWeights.java
View file @
34bcb88f
...
@@ -41,7 +41,7 @@ public class ObjectiveWeights {
...
@@ -41,7 +41,7 @@ public class ObjectiveWeights {
* @param minValues 各维度目标值的最小值
* @param minValues 各维度目标值的最小值
* @param maxValues 各维度目标值的最大值
* @param maxValues 各维度目标值的最大值
* @param isMinimize 各维度是否为最小化目标(true:值越小越优;false:值越大越优)
* @param isMinimize 各维度是否为最小化目标(true:值越小越优;false:值越大越优)
* @return 归一化后目标值(范围:[0,1],无0值兜底)
* @return 归一化后目标值(范围:[0,1],无0值兜底)
越靠近1越优
*/
*/
public
double
[]
normalizeObjectives
(
double
[]
objectives
,
double
[]
minValues
,
double
[]
maxValues
,
boolean
[]
isMinimize
)
{
public
double
[]
normalizeObjectives
(
double
[]
objectives
,
double
[]
minValues
,
double
[]
maxValues
,
boolean
[]
isMinimize
)
{
if
(
objectives
==
null
||
objectives
.
length
==
0
)
{
if
(
objectives
==
null
||
objectives
.
length
==
0
)
{
...
@@ -89,7 +89,7 @@ public class ObjectiveWeights {
...
@@ -89,7 +89,7 @@ public class ObjectiveWeights {
}
}
}
}
// 兜底:限制范围[1e-6,1],彻底避免0值
// 兜底:限制范围[1e-6,1],彻底避免0值
normalized
[
i
]
=
Math
.
max
(
Math
.
min
(
normalized
[
i
],
1.0
),
1
e
-
6
);
normalized
[
i
]
=
Math
.
max
(
Math
.
min
(
normalized
[
i
],
1.0
),
0.0001
);
}
}
}
}
return
normalized
;
return
normalized
;
...
...
src/main/java/com/aps/entity/Algorithm/ScheduleParams.java
View file @
34bcb88f
...
@@ -20,8 +20,8 @@ public class ScheduleParams {
...
@@ -20,8 +20,8 @@ public class ScheduleParams {
private
static
final
int
MAX_MAX_ITERATIONS
=
200
;
private
static
final
int
MAX_MAX_ITERATIONS
=
200
;
private
static
final
float
MIN_CROSSOVER_PROB
=
0.6f
;
private
static
final
float
MIN_CROSSOVER_PROB
=
0.6f
;
private
static
final
float
MAX_CROSSOVER_PROB
=
0.9f
;
private
static
final
float
MAX_CROSSOVER_PROB
=
0.9f
;
private
static
final
float
MIN_MUTATION_PROB
=
0.
05
f
;
private
static
final
float
MIN_MUTATION_PROB
=
0.
3
f
;
private
static
final
float
MAX_MUTATION_PROB
=
0.
2
f
;
private
static
final
float
MAX_MUTATION_PROB
=
0.
7
f
;
private
static
final
int
MIN_TOURNAMENT_SIZE
=
3
;
private
static
final
int
MIN_TOURNAMENT_SIZE
=
3
;
private
static
final
int
MAX_TOURNAMENT_SIZE
=
7
;
private
static
final
int
MAX_TOURNAMENT_SIZE
=
7
;
...
...
src/main/java/com/aps/entity/EquipCapacityDef.java
View file @
34bcb88f
...
@@ -23,7 +23,7 @@ private LocalDateTime effectiveStartTime;
...
@@ -23,7 +23,7 @@ private LocalDateTime effectiveStartTime;
private
LocalDateTime
effectiveEndTime
;
private
LocalDateTime
effectiveEndTime
;
private
Long
referenceId
;
private
Long
referenceId
;
private
Integer
referenceType
;
private
Integer
referenceType
;
private
BigDecimal
efficiencyCoeff
;
private
Double
efficiencyCoeff
;
private
Integer
minUtilization
;
private
Integer
minUtilization
;
private
Integer
maxUtilization
;
private
Integer
maxUtilization
;
private
String
referenceName
;
private
String
referenceName
;
...
...
src/main/java/com/aps/entity/ProdEquipSpecialCal.java
View file @
34bcb88f
...
@@ -15,7 +15,7 @@ private LocalDateTime endDate;
...
@@ -15,7 +15,7 @@ private LocalDateTime endDate;
private
String
shiftWorkSchedCode
;
private
String
shiftWorkSchedCode
;
private
String
periodDesc
;
private
String
periodDesc
;
private
Integer
equipId
;
private
Integer
equipId
;
private
Long
efficiencyCoeff
;
private
double
efficiencyCoeff
;
private
Long
referenceId
;
private
Long
referenceId
;
private
String
referenceName
;
private
String
referenceName
;
private
Long
creatorUserId
;
private
Long
creatorUserId
;
...
...
src/main/java/com/aps/entity/basic/Shift.java
View file @
34bcb88f
...
@@ -19,7 +19,7 @@ public class Shift {
...
@@ -19,7 +19,7 @@ public class Shift {
private
int
priority
;
private
int
priority
;
private
boolean
isSpecial
;
private
boolean
isSpecial
;
private
Integer
status
;
//0:正常班次 1:临时班次 2:维修
private
Integer
status
;
//0:正常班次 1:临时班次 2:维修
private
double
efficiency
=
1
;
// 添加设备ID和名称字段
// 添加设备ID和名称字段
private
Long
machineId
;
private
Long
machineId
;
private
String
machineName
;
private
String
machineName
;
...
...
src/main/java/com/aps/entity/basic/TimeSegment.java
View file @
34bcb88f
...
@@ -18,10 +18,17 @@ public class TimeSegment {
...
@@ -18,10 +18,17 @@ public class TimeSegment {
private
SegmentType
type
;
// 时间段类型(关联SegmentType枚举)
private
SegmentType
type
;
// 时间段类型(关联SegmentType枚举)
private
boolean
isHoliday
;
// 是否节假日(true=节假日)
private
boolean
isHoliday
;
// 是否节假日(true=节假日)
private
boolean
isUsed
;
// 是否已被占用(true=已分配任务)
private
boolean
isUsed
;
// 是否已被占用(true=已分配任务)
private
double
efficiency
=
1
;
//效率
// 无参构造(Lombok默认生成)
// 无参构造(Lombok默认生成)
public
TimeSegment
()
{}
public
TimeSegment
()
{}
public
TimeSegment
(
LocalDateTime
start
,
LocalDateTime
end
)
{
this
.
start
=
start
;
this
.
end
=
end
;
}
...
...
src/main/java/com/aps/service/Algorithm/FitnessCalculator.java
View file @
34bcb88f
package
com
.
aps
.
service
.
Algorithm
;
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.ObjectiveWeights
;
import
java.util.List
;
import
java.util.List
;
...
@@ -12,23 +13,26 @@ public class FitnessCalculator {
...
@@ -12,23 +13,26 @@ public class FitnessCalculator {
/**
/**
* 多目标适应度计算(加权求和)
* 多目标适应度计算(加权求和)
*/
*/
public
double
calculateFitness
(
Chromosome
chromosome
)
{
public
double
calculateFitness
(
Chromosome
chromosome
,
ObjectiveWeights
objectiveWeights
)
{
// 权重可根据实际需求调整
double
w1
=
0.3
;
// 最早完工时间(越小越好,归一化后取反)
double
w2
=
0.2
;
// 总流程时间(越小越好)
double
w3
=
0.15
;
// 总换型时间(越小越好)
double
w4
=
0.2
;
// 机器负载均衡(标准差越小越好)
double
w5
=
0.15
;
// 交付期延迟(越小越好)
// 归一化(假设最大可能值,实际应根据问题规模调整)
double
normMakespan
=
1
/
(
1
+(
double
)
chromosome
.
getMakespan
());
double
normFlowTime
=
1
/
(
1
+
(
double
)
chromosome
.
getTotalFlowTime
()
);
double
normChangeover
=
1
/
(
1
+
(
double
)
chromosome
.
getTotalChangeoverTime
());
double
normLoadStd
=
chromosome
.
getMachineLoadStd
();
double
normDelay
=
1
/
(
1
+
(
double
)
chromosome
.
getDelayTime
()
);
double
fitness
=
0
;
for
(
int
i
=
0
;
i
<
chromosome
.
getObjectives
().
length
;
i
++)
{
// 归一化(假设最大可能值,实际应根据问题规模调整)
double
val
=
1
/
(
1
+
chromosome
.
getObjectives
()[
i
]);
if
(!
objectiveWeights
.
isPureNSGAIIMode
())
{
val
=
val
*
objectiveWeights
.
getWeights
()[
i
];
}
fitness
+=
val
;
// 1/1+1 0.5
// 1/1+2 0.3
// 1/1+3 0.25
// 值越大 归一化 后越小
}
// 适应度值(越大越好)
// 适应度值(越大越好)
return
w1
*
normMakespan
+
w2
*
normFlowTime
+
w3
*
normChangeover
+
w4
*
normLoadStd
+
w5
*
normDelay
;
return
fitness
;
}
}
/**
/**
* 计算种群适应度标准差(用于参数微调)
* 计算种群适应度标准差(用于参数微调)
...
...
src/main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
View file @
34bcb88f
...
@@ -62,6 +62,12 @@ public class GeneticAlgorithm {
...
@@ -62,6 +62,12 @@ public class GeneticAlgorithm {
}
}
public
Chromosome
Run
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
)
{
public
Chromosome
Run
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
)
{
if
(
allOperations
==
null
||
allOperations
.
size
()==
0
)
{
throw
new
RuntimeException
(
"没有待排产工单"
);
}
if
(
materials
!=
null
&&
materials
.
size
()>
0
)
{
if
(
materials
!=
null
&&
materials
.
size
()>
0
)
{
materialRequirementService
.
init
(
materials
,
orders
,
allOperations
,
_entryRel
,
machineScheduler
,
machines
,
_GlobalParam
);
materialRequirementService
.
init
(
materials
,
orders
,
allOperations
,
_entryRel
,
machineScheduler
,
machines
,
_GlobalParam
);
...
@@ -70,17 +76,22 @@ public class GeneticAlgorithm {
...
@@ -70,17 +76,22 @@ public class GeneticAlgorithm {
LocalDateTime
starttime
=
LocalDateTime
.
now
();
LocalDateTime
starttime
=
LocalDateTime
.
now
();
FileHelper
.
writeLogFile
(
"排产-----------开始-----------"
+
allOperations
.
get
(
0
).
getSceneId
());
FileHelper
.
writeLogFile
(
"排产-----------开始-----------"
+
allOperations
.
get
(
0
).
getSceneId
());
Initialization
initialization
=
new
Initialization
(
_GlobalParam
,
allOperations
,
orders
,
machines
);
Initialization
initialization
=
new
Initialization
(
_GlobalParam
,
allOperations
,
orders
,
machines
,
_objectiveWeights
);
GeneticOperations
geneticOps
=
new
GeneticOperations
(
_GlobalParam
,
allOperations
,
param
);
GeneticOperations
geneticOps
=
new
GeneticOperations
(
_GlobalParam
,
allOperations
,
param
);
// 预生成全局工序列表(所有初始化方法共享同一顺序)
// 预生成全局工序列表(所有初始化方法共享同一顺序)
List
<
GlobalOperationInfo
>
globalOpList
=
initialization
.
generateGlobalOpList
();
List
<
GlobalOperationInfo
>
globalOpList
=
initialization
.
generateGlobalOpList
();
FileHelper
.
writeLogFile
(
"初始化种群-----------开始-------"
);
FileHelper
.
writeLogFile
(
"初始化种群-----------开始-------"
);
Machine
ms
=
machines
.
stream
().
filter
(
t
->
t
.
getName
().
equals
(
"铲车-2"
)).
findFirst
().
orElse
(
null
);
// 步骤1:初始化种群
// 步骤1:初始化种群
List
<
Chromosome
>
population
=
initialization
.
generateInitialPopulation
(
param
,
globalOpList
);
List
<
Chromosome
>
population
=
initialization
.
generateInitialPopulation
(
param
,
globalOpList
);
population
=
chromosomeDistinct
(
population
);
FileHelper
.
writeLogFile
(
"初始化种群-----------结束-------"
);
FileHelper
.
writeLogFile
(
"初始化种群-----------结束-------"
);
FileHelper
.
writeLogFile
(
"初始化批量解码-----------开始-------"
);
FileHelper
.
writeLogFile
(
"初始化批量解码-----------开始-------"
);
Chromosomedecode
(
param
,
allOperations
,
globalOpList
,
population
);
Chromosomedecode
(
param
,
allOperations
,
globalOpList
,
population
);
...
@@ -90,18 +101,13 @@ public class GeneticAlgorithm {
...
@@ -90,18 +101,13 @@ public class GeneticAlgorithm {
.
mapToInt
(
GlobalOperationInfo:
:
getGroupId
)
.
mapToInt
(
GlobalOperationInfo:
:
getGroupId
)
.
max
()
.
max
()
.
orElse
(
0
);
.
orElse
(
0
);
Chromosome
best
=
new
Chromosome
(
);
Chromosome
best
=
GetBest
(
fronts
,
"初始"
);
// best=fronts.get(0).stream()
// best=fronts.get(0).stream()
// .max(Comparator.comparingDouble(Chromosome::getFitness))
// .max(Comparator.comparingDouble(Chromosome::getFitness))
// .orElse(null);
// .orElse(null);
WriteKpis
(
fronts
,
"初始"
);
best
=
fronts
.
get
(
0
).
stream
()
double
bestFitness
=
best
.
getFitness
();
.
sorted
((
c1
,
c2
)
->
Double
.
compare
(
c2
.
getWeightedObjective
(),
c1
.
getWeightedObjective
()))
.
findFirst
()
.
orElse
(
null
);
WriteKpi
(
best
,
"最大"
);
double
bestFitness
=
best
.
getWeightedObjective
();
int
Iteration
=
0
;
int
Iteration
=
0
;
// 步骤2:迭代进化
// 步骤2:迭代进化
FileHelper
.
writeLogFile
(
"迭代进化-----------开始-------"
+
param
.
getMaxIterations
());
FileHelper
.
writeLogFile
(
"迭代进化-----------开始-------"
+
param
.
getMaxIterations
());
...
@@ -149,13 +155,20 @@ public class GeneticAlgorithm {
...
@@ -149,13 +155,20 @@ public class GeneticAlgorithm {
FileHelper
.
writeLogFile
(
"交叉操作-----------结束-------"
);
FileHelper
.
writeLogFile
(
"交叉操作-----------结束-------"
);
FileHelper
.
writeLogFile
(
"变异操作-----------开始-------"
);
FileHelper
.
writeLogFile
(
"变异操作-----------开始-------"
);
// 变异操作
// 变异操作
List
<
Chromosome
>
nextPopulation1
=
new
ArrayList
<>();
for
(
Chromosome
chromosome
:
nextPopulation
)
{
for
(
Chromosome
chromosome
:
nextPopulation
)
{
if
(
rnd
.
nextDouble
()
<
param
.
getMutationProb
())
{
if
(
rnd
.
nextDouble
()
<
param
.
getMutationProb
())
{
geneticOps
.
mutate
(
chromosome
,
globalOpList
);
Chromosome
chromosome1
=
ProductionDeepCopyUtil
.
deepCopy
(
chromosome
,
Chromosome
.
class
);
geneticOps
.
mutate
(
chromosome1
,
globalOpList
);
nextPopulation1
.
add
(
chromosome1
);
}
}
}
}
nextPopulation
.
addAll
(
nextPopulation1
);
FileHelper
.
writeLogFile
(
"变异操作-----------结束-------"
);
FileHelper
.
writeLogFile
(
"变异操作-----------结束-------"
);
FileHelper
.
writeLogFile
(
"变异批量解码-----------开始-------"
);
FileHelper
.
writeLogFile
(
"变异批量解码-----------开始-------"
);
nextPopulation
=
chromosomeDistinct
(
nextPopulation
);
Chromosomedecode
(
param
,
allOperations
,
globalOpList
,
nextPopulation
);
Chromosomedecode
(
param
,
allOperations
,
globalOpList
,
nextPopulation
);
FileHelper
.
writeLogFile
(
"变异批量解码-----------开始-------"
);
FileHelper
.
writeLogFile
(
"变异批量解码-----------开始-------"
);
// // 精英保留
// // 精英保留
...
@@ -169,6 +182,7 @@ public class GeneticAlgorithm {
...
@@ -169,6 +182,7 @@ public class GeneticAlgorithm {
List
<
Chromosome
>
newPopulation
=
new
ArrayList
<>();
List
<
Chromosome
>
newPopulation
=
new
ArrayList
<>();
newPopulation
.
addAll
(
population
);
newPopulation
.
addAll
(
population
);
newPopulation
.
addAll
(
nextPopulation
);
newPopulation
.
addAll
(
nextPopulation
);
newPopulation
=
chromosomeDistinct
(
newPopulation
);
FileHelper
.
writeLogFile
(
"非支配排序-----------开始-------"
);
FileHelper
.
writeLogFile
(
"非支配排序-----------开始-------"
);
// 2.7 非支配排序
// 2.7 非支配排序
List
<
List
<
Chromosome
>>
combinedFronts
=
_nsgaIIUtils
.
parallelFastNonDominatedSort
(
newPopulation
);
List
<
List
<
Chromosome
>>
combinedFronts
=
_nsgaIIUtils
.
parallelFastNonDominatedSort
(
newPopulation
);
...
@@ -181,17 +195,11 @@ public class GeneticAlgorithm {
...
@@ -181,17 +195,11 @@ public class GeneticAlgorithm {
// .collect(Collectors.toList());
// .collect(Collectors.toList());
fronts
=
_nsgaIIUtils
.
parallelFastNonDominatedSort
(
population
);
best
=
GetBest
(
combinedFronts
,
String
.
valueOf
(
iter
));
WriteKpis
(
fronts
,
String
.
valueOf
(
iter
));
if
(
bestFitness
<
best
.
getFitness
())
best
=
fronts
.
get
(
0
).
stream
()
.
sorted
((
c1
,
c2
)
->
Double
.
compare
(
c2
.
getWeightedObjective
(),
c1
.
getWeightedObjective
()))
.
findFirst
()
.
orElse
(
null
);
WriteKpi
(
best
,
"最大"
);
if
(
bestFitness
<
best
.
getWeightedObjective
())
{
{
bestFitness
=
best
.
get
WeightedObjective
();
bestFitness
=
best
.
get
Fitness
();
Iteration
=
1
;
Iteration
=
1
;
...
@@ -222,6 +230,36 @@ public class GeneticAlgorithm {
...
@@ -222,6 +230,36 @@ public class GeneticAlgorithm {
}
}
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
(
orders
.
size
()<
10
)
{
population
=
population
.
stream
()
.
collect
(
Collectors
.
toMap
(
Chromosome:
:
getGeneStr
,
// key:去重的字段(GeneStr)
u
->
u
,
// value:Chromosome对象
(
u1
,
u2
)
->
u1
// 重复时保留第一个元素
))
.
values
()
// 获取去重后的
.
stream
()
.
collect
(
Collectors
.
toList
());
}
return
population
;
}
private
void
WriteKpis
(
List
<
List
<
Chromosome
>>
fronts
,
String
index
)
{
private
void
WriteKpis
(
List
<
List
<
Chromosome
>>
fronts
,
String
index
)
{
for
(
int
i
=
0
;
i
<
fronts
.
size
();
i
++)
for
(
int
i
=
0
;
i
<
fronts
.
size
();
i
++)
{
{
...
@@ -253,10 +291,10 @@ public class GeneticAlgorithm {
...
@@ -253,10 +291,10 @@ public class GeneticAlgorithm {
chromosome
.
setMachines
(
ProductionDeepCopyUtil
.
deepCopyList
(
machines
));
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setMachines
(
ProductionDeepCopyUtil
.
deepCopyList
(
machines
));
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setAllOperations
(
allOperations
);
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setAllOperations
(
allOperations
);
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setGlobalOpList
(
globalOpList
);
// 简单拷贝,实际可能需要深拷贝
chromosome
.
setGlobalOpList
(
globalOpList
);
// 简单拷贝,实际可能需要深拷贝
//chromosome.setObjectiveWeights(_objectiveWeights);
decoder
.
decodeChromosomeWithCache
(
chromosome
);
decoder
.
decodeChromosomeWithCache
(
chromosome
);
if
(
chromosome
.
getFitness
()
==
0
)
{
if
(
chromosome
.
getFitness
()
==
0
)
{
chromosome
.
setFitness
(
_fitnessCalculator
.
calculateFitness
(
chromosome
));
chromosome
.
setFitness
(
_fitnessCalculator
.
calculateFitness
(
chromosome
,
_objectiveWeights
));
}
}
});
});
...
...
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
View file @
34bcb88f
...
@@ -92,6 +92,7 @@ public class GeneticDecoder {
...
@@ -92,6 +92,7 @@ public class GeneticDecoder {
chromosome
.
setDelayTime
(
cachedResult
.
getDelayTime
());
chromosome
.
setDelayTime
(
cachedResult
.
getDelayTime
());
chromosome
.
setResult
(
ProductionDeepCopyUtil
.
deepCopyList
(
cachedResult
.
getResult
(),
GAScheduleResult
.
class
));
chromosome
.
setResult
(
ProductionDeepCopyUtil
.
deepCopyList
(
cachedResult
.
getResult
(),
GAScheduleResult
.
class
));
// Chromosome chromosomen= ProductionDeepCopyUtil.deepCopy(cachedResult);
// Chromosome chromosomen= ProductionDeepCopyUtil.deepCopy(cachedResult);
FileHelper
.
writeLogFile
(
"解码-----------结束-------"
+
chromosome
.
getID
());
return
chromosome
;
return
chromosome
;
}
}
...
@@ -373,7 +374,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -373,7 +374,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
int
setupTime
=
calculateSetupTime
(
chromosome
.
getResult
(),
operation
,
machine
,
machineOption
);
int
setupTime
=
calculateSetupTime
(
chromosome
.
getResult
(),
operation
,
machine
,
machineOption
);
FileHelper
.
writeLogFile
(
" "
+
operation
.
getGroupId
()+
" : "
+
operation
.
getId
()+
",处理时间: "
+
processingTime
+
", 后处理: "
+
teardownTime
+
FileHelper
.
writeLogFile
(
" "
+
operation
.
getGroupId
()+
" : "
+
operation
.
getId
()+
",处理时间: "
+
processingTime
+
", 后处理: "
+
teardownTime
+
", 前处理: "
+
preTime
+
", 换型: "
+
setupTime
+
", 数量: "
+
operation
.
getQuantity
()+
", 设备: "
+
machine
.
getId
());
", 前处理: "
+
preTime
+
", 换型: "
+
setupTime
+
", 数量: "
+
operation
.
getQuantity
()+
", 设备: "
+
machine
.
getId
()
+
", 是否可中断: "
+
operation
.
getIsInterrupt
()
);
// 确定任务的最早开始时间(基于前一道工序的完整结束时间,包含后处理)
// 确定任务的最早开始时间(基于前一道工序的完整结束时间,包含后处理)
...
@@ -429,7 +430,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -429,7 +430,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
List
<
ScheduleResultDetail
>
geneDetails
=
machineCalculator
.
getNextAvailableTime
(
machine
,
earliestStartTime
,
-
1
,
List
<
ScheduleResultDetail
>
geneDetails
=
machineCalculator
.
getNextAvailableTime
(
machine
,
earliestStartTime
,
-
1
,
processingTimeTotal
,
chromosome
.
getResult
(),
false
,
true
,
processingTime
,
operation
.
getQuantity
(),
true
);
processingTimeTotal
,
chromosome
.
getResult
(),
operation
.
IsInterrupt
!=
1
,
true
,
processingTime
,
operation
.
getQuantity
(),
true
);
...
@@ -929,7 +930,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -929,7 +930,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
// 3. 最小总换型时间
// 3. 最小总换型时间
double
totalSetupTime
=
calculateTotalSetupTime
(
chromosome
);
double
totalSetupTime
=
calculateTotalSetupTime
(
chromosome
);
// 4. 最小化总流程时间
// 4. 最小化总流程时间
所有工序加工时间的总和
double
totalFlowTime
=
calculateTotalFlowTime
(
chromosome
);
double
totalFlowTime
=
calculateTotalFlowTime
(
chromosome
);
// 5. 机器负载均衡
// 5. 机器负载均衡
...
@@ -945,7 +946,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -945,7 +946,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
double
[]
Objectives
=
new
double
[
5
];
double
[]
Objectives
=
new
double
[
5
];
Objectives
[
0
]
=
makespan
;
Objectives
[
0
]
=
makespan
;
Objectives
[
1
]
=
totalFlowTime
;
Objectives
[
1
]
=
totalFlowTime
;
Objectives
[
2
]
=
totalSetupTime
;
Objectives
[
2
]
=
totalSetupTime
;
Objectives
[
3
]
=
machineLoadBalance
;
Objectives
[
3
]
=
machineLoadBalance
;
Objectives
[
4
]
=
tardiness
;
Objectives
[
4
]
=
tardiness
;
chromosome
.
setObjectives
(
Objectives
);
chromosome
.
setObjectives
(
Objectives
);
...
@@ -969,36 +970,34 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -969,36 +970,34 @@ if(finishedOrder==null||finishedOrder.size()==0)
// 计算机器负载均衡指标
// 计算机器负载均衡指标
private
double
calculateMachineLoadBalance
(
Chromosome
chromosome
)
{
private
double
calculateMachineLoadBalance
(
Chromosome
chromosome
)
{
Map
<
Long
,
Double
>
machineUtilization
=
new
HashMap
<>();
Map
<
Long
,
Double
>
machineUtilization
=
new
HashMap
<>();
int
maxEndTime
=
chromosome
.
getResult
().
stream
()
int
sumWork
=
chromosome
.
getResult
().
stream
()
.
mapToInt
(
GAScheduleResult:
:
getEndTime
)
.
mapToInt
(
GAScheduleResult:
:
getFlowTime
)
.
max
()
.
sum
();
//总的加工时间
.
orElse
(
0
);
if
(
maxEndTime
==
0
)
return
0
;
if
(
sumWork
==
0
)
return
0
;
for
(
Machine
machine
:
chromosome
.
getMachines
())
{
for
(
Machine
machine
:
chromosome
.
getMachines
())
{
List
<
GAScheduleResult
>
machineGenes
=
chromosome
.
getResult
().
stream
()
double
busyTime
=
chromosome
.
getResult
().
stream
()
.
filter
(
g
->
g
.
getMachineId
()
==
machine
.
getId
())
.
filter
(
g
->
g
.
getMachineId
()
==
machine
.
getId
())
.
collect
(
Collectors
.
toList
());
.
mapToInt
(
g
->
g
.
getFlowTime
())
double
busyTime
=
machineGenes
.
stream
()
.
mapToInt
(
g
->
g
.
getEndTime
()
-
g
.
getStartTime
())
.
sum
();
.
sum
();
machineUtilization
.
put
(
machine
.
getId
(),
busyTime
/
maxEndTime
);
machineUtilization
.
put
(
machine
.
getId
(),
busyTime
/
sumWork
);
}
}
double
avgUtilization
=
machineUtilization
.
values
().
stream
()
double
avgUtilization
=
machineUtilization
.
values
().
stream
()
.
mapToDouble
(
Double:
:
doubleValue
)
.
mapToDouble
(
Double:
:
doubleValue
)
.
average
()
.
sum
()/
chromosome
.
getMachines
().
size
();
.
orElse
(
0
);
double
variance
=
machineUtilization
.
values
().
stream
()
double
variance
=
machineUtilization
.
values
().
stream
()
.
mapToDouble
(
u
->
Math
.
pow
(
u
-
avgUtilization
,
2
))
.
mapToDouble
(
u
->
Math
.
pow
(
u
-
avgUtilization
,
2
))
.
sum
()
/
chromosome
.
getMachines
().
size
();
.
sum
()
/
chromosome
.
getMachines
().
size
();
//
方差越小,负载越均衡
//
标准差与平均值的比值衡量负载离散程度,值越小说明均衡度越高
return
1.0
/
(
1
+
variance
)
;
return
Math
.
sqrt
(
variance
)/
avgUtilization
;
}
}
/**
/**
* 补全:创建缓存键(核心逻辑,需与原 C# CreateCacheKey 一致)
* 补全:创建缓存键(核心逻辑,需与原 C# CreateCacheKey 一致)
...
@@ -1006,13 +1005,15 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -1006,13 +1005,15 @@ if(finishedOrder==null||finishedOrder.size()==0)
*/
*/
private
String
createCacheKey
(
Chromosome
chromosome
)
{
private
String
createCacheKey
(
Chromosome
chromosome
)
{
return
chromosome
.
getGeneStr
();
// 拼接机器选择:用 "," 分隔(例:1,3,2,4)
// 拼接机器选择:用 "," 分隔(例:1,3,2,4)
String
machineStr
=
chromosome
.
getMachineStr
();
//
String machineStr = chromosome.getMachineStr();
// 拼接工序排序:用 "|" 分隔(例:2|1|3|4)
// 拼接工序排序:用 "|" 分隔(例:2|1|3|4)
String
operationStr
=
chromosome
.
getOperationStr
();
//
String operationStr = chromosome.getOperationStr();
// 组合最终键(用 "_" 分隔两部分,避免冲突)
// 组合最终键(用 "_" 分隔两部分,避免冲突)
return
machineStr
+
"_"
+
operationStr
;
//
return machineStr + "_" + operationStr;
}
}
}
}
src/main/java/com/aps/service/Algorithm/GeneticOperations.java
View file @
34bcb88f
...
@@ -34,39 +34,23 @@ public class GeneticOperations {
...
@@ -34,39 +34,23 @@ public class GeneticOperations {
*/
*/
public
List
<
Chromosome
>
tournamentSelection
(
List
<
Chromosome
>
population
,
int
tournamentSize
)
{
public
List
<
Chromosome
>
tournamentSelection
(
List
<
Chromosome
>
population
,
int
tournamentSize
)
{
int
populationSize
=
population
.
size
();
int
populationSize
=
population
.
size
();
List
<
Chromosome
>
selected
=
new
ArrayList
<>(
populationSize
);
// 预初始化容量
List
<
Chromosome
>
selected
=
new
ArrayList
<>();
// 预初始化容量
// 边界值处理:锦标赛规模不能超过种群规模,且至少为1
// 边界值处理:锦标赛规模不能超过种群规模,且至少为1
int
effectiveTournamentSize
=
Math
.
max
(
1
,
Math
.
min
(
tournamentSize
,
populationSize
));
int
effectiveTournamentSize
=
Math
.
max
(
1
,
Math
.
min
(
tournamentSize
,
populationSize
));
while
(
selected
.
size
()
<
populationSize
)
{
while
(
selected
.
size
()
<
populationSize
-
tournamentSize
)
{
// 优化1:不复制整个种群,直接随机抽取有效锦标赛规模的个体,避免大量内存拷贝和shuffle开销
// 优化1:不复制整个种群,直接随机抽取有效锦标赛规模的个体,避免大量内存拷贝和shuffle开销
Chromosome
bestCandidate
=
null
;
int
bestRank
=
Integer
.
MAX_VALUE
;
Collections
.
shuffle
(
population
,
new
Random
());
//随机排序
double
bestCrowdingDistance
=
-
Double
.
MAX_VALUE
;
int
endIndex
=
Math
.
min
(
effectiveTournamentSize
,
population
.
size
());
// 优化2:单次循环随机抽取+实时比较,无需创建候选列表、无需排序,O(k)时间复杂度(k为锦标赛规模)
List
<
Chromosome
>
chromosomes
=
population
.
subList
(
0
,
endIndex
);
for
(
int
i
=
0
;
i
<
effectiveTournamentSize
;
i
++)
{
chromosomes
.
sort
((
c1
,
c2
)
->
{
// 随机获取一个种群个体(直接通过索引访问,无需打乱整个列表)
int
rankCompare
=
Integer
.
compare
(
c1
.
getRank
(),
c2
.
getRank
());
int
randomIndex
=
rnd
.
nextInt
(
populationSize
);
return
rankCompare
!=
0
?
rankCompare
:
Double
.
compare
(
c1
.
getCrowdingDistance
(),
c2
.
getCrowdingDistance
());
Chromosome
current
=
population
.
get
(
randomIndex
);
});
// 优化3:手动实现排序逻辑的比较,避免Stream API的额外开销
Chromosome
bestCandidate
=
chromosomes
.
get
(
0
);
if
(
bestCandidate
==
null
)
{
bestCandidate
=
current
;
bestRank
=
current
.
getRank
();
bestCrowdingDistance
=
current
.
getCrowdingDistance
();
}
else
{
// 先比较Rank(升序:Rank越小越优)
if
(
current
.
getRank
()
<
bestRank
)
{
updateBestCandidate
(
current
,
bestCandidate
,
bestRank
,
bestCrowdingDistance
);
}
else
if
(
current
.
getRank
()
==
bestRank
)
{
// Rank相同时,比较拥挤距离(降序:值越大越优)
if
(
current
.
getCrowdingDistance
()
>
bestCrowdingDistance
)
{
updateBestCandidate
(
current
,
bestCandidate
,
bestRank
,
bestCrowdingDistance
);
}
}
}
}
// 深拷贝最优个体并加入选中列表(确保线程安全和种群独立性)
// 深拷贝最优个体并加入选中列表(确保线程安全和种群独立性)
if
(
bestCandidate
!=
null
)
{
if
(
bestCandidate
!=
null
)
{
...
@@ -75,12 +59,7 @@ public class GeneticOperations {
...
@@ -75,12 +59,7 @@ public class GeneticOperations {
}
}
return
selected
;
return
selected
;
}
}
private
void
updateBestCandidate
(
Chromosome
current
,
Chromosome
bestCandidate
,
int
bestRank
,
double
bestCrowdingDistance
)
{
bestRank
=
current
.
getRank
();
bestCrowdingDistance
=
current
.
getCrowdingDistance
();
bestCandidate
=
current
;
}
// 重载,使用默认锦标赛大小3
// 重载,使用默认锦标赛大小3
public
List
<
Chromosome
>
tournamentSelection
(
List
<
Chromosome
>
population
)
{
public
List
<
Chromosome
>
tournamentSelection
(
List
<
Chromosome
>
population
)
{
return
tournamentSelection
(
population
,
param
.
getTournamentSize
());
return
tournamentSelection
(
population
,
param
.
getTournamentSize
());
...
@@ -239,11 +218,19 @@ public class GeneticOperations {
...
@@ -239,11 +218,19 @@ public class GeneticOperations {
* 变异操作
* 变异操作
*/
*/
public
void
mutate
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
,
double
baseMutationProb
)
{
public
void
mutate
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
,
double
baseMutationProb
)
{
// 1. 机器选择部分变异
int
i
=
rnd
.
nextInt
(
2
);
mutateMachineSelection
(
chromosome
,
globalOpList
,
baseMutationProb
);
if
(
i
==
0
)
{
// 1. 机器选择部分变异
// 2. 工序排序部分变异
boolean
state
=
mutateMachineSelection
(
chromosome
,
globalOpList
,
baseMutationProb
);
mutateOperationSequencing
(
chromosome
);
if
(!
state
)
{
i
=
1
;
}
}
if
(
i
==
1
)
{
// 2. 工序排序部分变异
mutateOperationSequencing
(
chromosome
);
}
}
}
// 重载,使用默认变异概率
// 重载,使用默认变异概率
...
@@ -251,13 +238,13 @@ public class GeneticOperations {
...
@@ -251,13 +238,13 @@ public class GeneticOperations {
mutate
(
chromosome
,
globalOpList
,
0.1
);
mutate
(
chromosome
,
globalOpList
,
0.1
);
}
}
private
void
mutateMachineSelection
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
,
double
baseMutationProb
)
{
private
boolean
mutateMachineSelection
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
,
double
baseMutationProb
)
{
// 计算变异位置数量
// 计算变异位置数量
List
<
Entry
>
entrys
=
allOperations
.
stream
().
filter
(
t
->
t
.
getMachineOptions
().
size
()>
1
).
collect
(
Collectors
.
toList
());
List
<
Entry
>
entrys
=
allOperations
.
stream
().
filter
(
t
->
t
.
getMachineOptions
().
size
()>
1
).
collect
(
Collectors
.
toList
());
if
(
entrys
==
null
||
entrys
.
size
()==
0
)
if
(
entrys
==
null
||
entrys
.
size
()==
0
)
{
{
return
;
return
false
;
}
}
Integer
count
=
entrys
.
size
();
Integer
count
=
entrys
.
size
();
int
r
=
Math
.
max
(
1
,
(
int
)
(
count
*
baseMutationProb
));
int
r
=
Math
.
max
(
1
,
(
int
)
(
count
*
baseMutationProb
));
...
@@ -291,6 +278,7 @@ public class GeneticOperations {
...
@@ -291,6 +278,7 @@ public class GeneticOperations {
i
++;
i
++;
}
}
return
true
;
}
}
/**
/**
...
...
src/main/java/com/aps/service/Algorithm/Initialization.java
View file @
34bcb88f
...
@@ -3,6 +3,7 @@ package com.aps.service.Algorithm;
...
@@ -3,6 +3,7 @@ package com.aps.service.Algorithm;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.entity.Algorithm.Chromosome
;
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.ScheduleParams
;
import
com.aps.entity.Algorithm.ScheduleParams
;
import
com.aps.entity.basic.*
;
import
com.aps.entity.basic.*
;
...
@@ -22,11 +23,14 @@ public class Initialization {
...
@@ -22,11 +23,14 @@ public class Initialization {
private
static
List
<
Machine
>
machines
;
private
static
List
<
Machine
>
machines
;
public
Initialization
(
GlobalParam
globalParam
,
List
<
Entry
>
allOperations
,
List
<
Order
>
_orders
,
List
<
Machine
>
_machines
)
{
private
ObjectiveWeights
_objectiveWeights
=
new
ObjectiveWeights
();
public
Initialization
(
GlobalParam
globalParam
,
List
<
Entry
>
allOperations
,
List
<
Order
>
_orders
,
List
<
Machine
>
_machines
,
ObjectiveWeights
objectiveWeights
)
{
Initialization
.
allOperations
=
allOperations
;
Initialization
.
allOperations
=
allOperations
;
_globalParam
=
globalParam
;
_globalParam
=
globalParam
;
orders
=
_orders
;
orders
=
_orders
;
machines
=
_machines
;
machines
=
_machines
;
_objectiveWeights
=
objectiveWeights
;
}
}
/**
/**
* 预生成全局工序列表(按“订单0→订单1→…+订单内工序1→2→…”排序,分配GlobalOpId)
* 预生成全局工序列表(按“订单0→订单1→…+订单内工序1→2→…”排序,分配GlobalOpId)
...
@@ -60,6 +64,7 @@ int populationSize=param.getPopulationSize();
...
@@ -60,6 +64,7 @@ int populationSize=param.getPopulationSize();
.
parallel
()
// 开启并行
.
parallel
()
// 开启并行
.
forEach
(
i
->
{
.
forEach
(
i
->
{
Chromosome
chromo
=
new
Chromosome
();
// 初始化染色体
Chromosome
chromo
=
new
Chromosome
();
// 初始化染色体
// chromo.setObjectiveWeights(_objectiveWeights);
chromo
.
setInitMachines
(
ProductionDeepCopyUtil
.
deepCopyList
(
machines
));
chromo
.
setInitMachines
(
ProductionDeepCopyUtil
.
deepCopyList
(
machines
));
chromo
.
setOrders
(
orders
);
chromo
.
setOrders
(
orders
);
// 全局选择(GS):按GlobalOpId顺序生成MachineSelection
// 全局选择(GS):按GlobalOpId顺序生成MachineSelection
...
...
src/main/java/com/aps/service/Algorithm/MachineCalculator.java
View file @
34bcb88f
...
@@ -54,7 +54,7 @@ public class MachineCalculator {
...
@@ -54,7 +54,7 @@ public class MachineCalculator {
// 查找合适的班次窗口
// 查找合适的班次窗口
return
findEarliestStart
(
machine
,
processingTime
,
startTime
,
prevtimestr
,
return
findEarliestStart
(
machine
,
processingTime
,
startTime
,
prevtimestr
,
existingTasks
,
oneTime
,
quantity
,
istask
,
islockMachineTime
);
existingTasks
,
oneTime
,
quantity
,
istask
,
islockMachineTime
,
isInterrupt
);
}
}
...
@@ -63,7 +63,7 @@ public class MachineCalculator {
...
@@ -63,7 +63,7 @@ public class MachineCalculator {
private
List
<
ScheduleResultDetail
>
findEarliestStart
(
private
List
<
ScheduleResultDetail
>
findEarliestStart
(
Machine
machine
,
int
processingTime
,
LocalDateTime
currentTime
,
Machine
machine
,
int
processingTime
,
LocalDateTime
currentTime
,
String
prevtime
,
List
<
GAScheduleResult
>
existingTasks
,
double
oneTime
,
double
quantity
,
boolean
checkprevtime
,
boolean
islockMachineTime
String
prevtime
,
List
<
GAScheduleResult
>
existingTasks
,
double
oneTime
,
double
quantity
,
boolean
checkprevtime
,
boolean
islockMachineTime
)
{
,
boolean
isInterrupt
)
{
List
<
GAScheduleResult
>
machineTasks
=
existingTasks
.
stream
()
List
<
GAScheduleResult
>
machineTasks
=
existingTasks
.
stream
()
.
filter
(
t
->
t
.
getMachineId
()
==
machine
.
getId
())
.
filter
(
t
->
t
.
getMachineId
()
==
machine
.
getId
())
.
sorted
(
Comparator
.
comparingInt
(
GAScheduleResult:
:
getStartTime
))
.
sorted
(
Comparator
.
comparingInt
(
GAScheduleResult:
:
getStartTime
))
...
@@ -81,7 +81,7 @@ public class MachineCalculator {
...
@@ -81,7 +81,7 @@ public class MachineCalculator {
LocalDateTime
endCandidate
=
startCandidate
.
plusSeconds
(
processingTime
);
LocalDateTime
endCandidate
=
startCandidate
.
plusSeconds
(
processingTime
);
if
(
endCandidate
.
isAfter
(
slot
.
getEnd
()))
{
if
(
endCandidate
.
isAfter
(
slot
.
getEnd
()))
{
return
CaldEarliestStart
(
machine
,
processingTime
,
currentTime
,
prevtime
,
machineTasks
,
oneTime
,
quantity
,
checkprevtime
,
islockMachineTime
);
return
CaldEarliestStart
(
machine
,
processingTime
,
currentTime
,
prevtime
,
machineTasks
,
oneTime
,
quantity
,
checkprevtime
,
islockMachineTime
,
isInterrupt
);
}
else
{
}
else
{
ScheduleResultDetail
time
=
new
ScheduleResultDetail
();
ScheduleResultDetail
time
=
new
ScheduleResultDetail
();
time
.
setKey
(
slot
.
getKey
());
time
.
setKey
(
slot
.
getKey
());
...
@@ -98,7 +98,7 @@ public class MachineCalculator {
...
@@ -98,7 +98,7 @@ public class MachineCalculator {
}
}
private
List
<
ScheduleResultDetail
>
CaldEarliestStart
(
private
List
<
ScheduleResultDetail
>
CaldEarliestStart
1
(
Machine
machine
,
int
processingTime
,
LocalDateTime
currentTime
,
Machine
machine
,
int
processingTime
,
LocalDateTime
currentTime
,
String
prevtime
,
List
<
GAScheduleResult
>
machineTasks
,
double
oneTime
,
double
quantity
,
boolean
checkprevtime
,
boolean
islockMachineTime
String
prevtime
,
List
<
GAScheduleResult
>
machineTasks
,
double
oneTime
,
double
quantity
,
boolean
checkprevtime
,
boolean
islockMachineTime
)
{
)
{
...
@@ -171,6 +171,372 @@ public class MachineCalculator {
...
@@ -171,6 +171,372 @@ public class MachineCalculator {
return
times
;
return
times
;
}
}
private
List
<
ScheduleResultDetail
>
CaldEarliestStart
(
Machine
machine
,
int
processingTime
,
LocalDateTime
currentTime
,
String
prevtime
,
List
<
GAScheduleResult
>
machineTasks
,
double
oneTime
,
double
quantity
,
boolean
checkprevtime
,
boolean
islockMachineTime
,
boolean
isInterrupt
)
{
int
remainingTime
=
processingTime
;
LocalDateTime
st
=
StringUtils
.
isEmpty
(
prevtime
)
?
currentTime
:
LocalDateTime
.
parse
(
prevtime
);
LocalDateTime
prevEnd
=
LocalDateTime
.
of
(
2000
,
1
,
1
,
0
,
0
,
0
);
List
<
ScheduleResultDetail
>
times
=
new
ArrayList
<>();
List
<
ScheduleResultDetail
>
oldTimes
=
new
ArrayList
<>();
List
<
TimeSegment
>
timeSegments
=
findAvailableSegments
(
machine
,
currentTime
,
machineTasks
,
remainingTime
,
isInterrupt
);
int
i
=
0
;
while
(
remainingTime
>
0
)
{
TimeSegment
shift
=
timeSegments
.
get
(
i
);
if
(
shift
==
null
)
break
;
LocalDateTime
shiftStart
=
shift
.
getStart
();
LocalDateTime
shiftEnd
=
shift
.
getEnd
();
// 计算有效时间
LocalDateTime
effectiveStart
=
st
.
isAfter
(
shiftStart
)
?
st
:
shiftStart
;
long
availableSeconds
=
ChronoUnit
.
SECONDS
.
between
(
effectiveStart
,
shiftEnd
);
long
availableSeconds_e
=
Math
.
round
(
availableSeconds
*
shift
.
getEfficiency
())
;
// 处理当前班次
int
processable
=
Math
.
min
(
remainingTime
,
(
int
)
availableSeconds_e
);
remainingTime
-=
processable
;
currentTime
=
effectiveStart
.
plusSeconds
(
availableSeconds
/
availableSeconds_e
*
processable
);
// 添加时间详情
ScheduleResultDetail
time
=
new
ScheduleResultDetail
();
time
.
setKey
(
shift
.
getKey
());
time
.
setStartTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
effectiveStart
));
time
.
setEndTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
currentTime
));
time
.
setQuantity
((
int
)(
processable
/
oneTime
));
time
.
setOneTime
(
oneTime
);
times
.
add
(
time
);
// 还原未使用的时间段
RemoveMachineAvailable
(
machine
,
time
);
i
++;
}
return
times
;
}
/**
* 查找满足时长要求的无冲突可用时段(对应原C#方法)
* @param machine 设备
* @param start 起始时间
* @param machineTasks 设备已有任务
* @param requiredMinutes 工单所需总时长(分钟)
* @param requireContinuous 是否不可中断(true=不可中断)
* @return 满足条件的可用片段列表
*/
private
List
<
TimeSegment
>
findAvailableSegments
(
Machine
machine
,
LocalDateTime
start
,
List
<
GAScheduleResult
>
machineTasks
,
double
requiredMinutes
,
boolean
requireContinuous
)
{
List
<
TimeSegment
>
availableSegments
=
new
ArrayList
<>();
LocalDateTime
current
=
start
;
// 预先排序设备可用片段,避免后续遍历混乱
List
<
TimeSegment
>
allUseTimeSegment
=
machine
.
getAvailability
().
stream
()
.
filter
(
slot
->
!
slot
.
isUsed
()
&&
slot
.
getType
()
!=
SegmentType
.
MAINTENANCE
)
.
sorted
(
Comparator
.
comparing
(
TimeSegment:
:
getStart
,
(
a
,
b
)
->
a
.
compareTo
(
b
)))
.
collect
(
Collectors
.
toList
());
// 替换while(true),增加明确退出条件(原逻辑保留,可根据业务补充退出判断)
while
(
true
)
{
// 统一过滤逻辑:消除重复的FindAll代码
List
<
TimeSegment
>
useSegments
=
filterValidUseSegments
(
machine
.
getAvailability
(),
current
,
requireContinuous
,
requiredMinutes
);
if
(
useSegments
!=
null
&&
!
useSegments
.
isEmpty
())
{
// 计算可用时间总和(保留原有逻辑)
double
totalUseTime
=
calculateTotalAvailableSecond
(
useSegments
,
current
);
// 不足所需时长时,自动生成未来片段并补充
while
(
totalUseTime
<
requiredMinutes
)
{
// 生成未来1天的片段(基于当前可用片段的最大结束时间)
LocalDateTime
lastSegmentEnd
=
machine
.
getAvailability
().
stream
()
.
max
(
Comparator
.
comparing
(
TimeSegment:
:
getEnd
,
(
a
,
b
)
->
a
.
compareTo
(
b
)))
.
map
(
TimeSegment:
:
getEnd
)
.
orElse
(
current
);
List
<
TimeSegment
>
newSegments
=
machineScheduler
.
generateTimeSegment
(
machine
,
lastSegmentEnd
.
plusDays
(
1
));
addSegmentsWithDeduplication
(
machine
,
newSegments
);
// 重新过滤可用片段
useSegments
=
filterValidUseSegments
(
machine
.
getAvailability
(),
current
,
requireContinuous
,
requiredMinutes
);
// 重新计算总可用时间
totalUseTime
=
calculateTotalAvailableSecond
(
useSegments
,
current
);
}
// 若总可用时间满足要求,处理冲突
if
(
totalUseTime
>=
requiredMinutes
)
{
// 获取当前可用片段范围内的冲突
LocalDateTime
firstSegmentStart
=
useSegments
.
get
(
0
).
getStart
();
LocalDateTime
lastSegmentEnd
=
useSegments
.
get
(
useSegments
.
size
()
-
1
).
getEnd
();
List
<
TimeSegment
>
conflictSegments
=
getConflictIntervals
(
machine
,
machineTasks
,
firstSegmentStart
,
lastSegmentEnd
);
if
(
conflictSegments
==
null
||
conflictSegments
.
isEmpty
())
{
// 无冲突:直接返回可用片段(保留原有逻辑)
if
(
useSegments
.
get
(
0
).
getStart
().
compareTo
(
current
)
<
0
)
{
spiltMachineAvailable
(
machine
,
useSegments
.
get
(
0
),
current
);
useSegments
.
get
(
0
).
setStart
(
current
);
}
return
useSegments
;
}
else
{
// 有冲突:可选返回冲突前足够片段或跳过冲突
List
<
TimeSegment
>
resultSegments
=
handleConflictsWithSumLogic
(
useSegments
,
conflictSegments
,
current
,
requiredMinutes
);
if
(
resultSegments
!=
null
&&
!
resultSegments
.
isEmpty
())
{
if
(
resultSegments
.
get
(
0
).
getStart
().
compareTo
(
current
)
<
0
)
{
spiltMachineAvailable
(
machine
,
resultSegments
.
get
(
0
),
current
);
resultSegments
.
get
(
0
).
setStart
(
current
);
}
return
resultSegments
;
}
else
{
// 冲突前片段不足,重置current为最后一个冲突的结束时间,重新查找
LocalDateTime
lastConflictEnd
=
conflictSegments
.
stream
()
.
max
(
Comparator
.
comparing
(
TimeSegment:
:
getEnd
,
(
a
,
b
)
->
a
.
compareTo
(
b
)))
.
map
(
TimeSegment:
:
getEnd
)
.
orElse
(
current
);
current
=
lastConflictEnd
;
}
}
}
}
else
{
// 无可用片段时,生成未来1天的片段
LocalDateTime
lastSegmentEnd
=
machine
.
getAvailability
().
stream
()
.
max
(
Comparator
.
comparing
(
TimeSegment:
:
getEnd
,
(
a
,
b
)
->
a
.
compareTo
(
b
)))
.
map
(
TimeSegment:
:
getEnd
)
.
orElse
(
current
);
List
<
TimeSegment
>
newSegments
=
machineScheduler
.
generateTimeSegment
(
machine
,
lastSegmentEnd
.
plusDays
(
1
));
addSegmentsWithDeduplication
(
machine
,
newSegments
);
}
}
}
/**
* 统一过滤有效可用片段
*/
private
List
<
TimeSegment
>
filterValidUseSegments
(
List
<
TimeSegment
>
allSegments
,
LocalDateTime
currentTime
,
boolean
requireContinuous
,
double
requiredMinutes
)
{
// 空判断:对应C#的 allSegments == null || allSegments.Count == 0
if
(
allSegments
==
null
||
allSegments
.
isEmpty
())
{
return
new
ArrayList
<>();
}
// 统一过滤条件
List
<
TimeSegment
>
baseValidSegments
=
allSegments
.
stream
()
.
filter
(
slot
->
!
slot
.
isUsed
()
// 对应 !slot.IsUsed
&&
slot
.
getType
()
!=
SegmentType
.
MAINTENANCE
// 对应 slot.Type != SegmentType.Maintenance
&&
slot
.
getEnd
().
compareTo
(
currentTime
)
>
0
)
// 对应 slot.End > currentTime
.
collect
(
Collectors
.
toList
());
// 无需不可中断或所需时长无效时,直接返回基础有效片段
if
(!
requireContinuous
||
requiredMinutes
<=
0
)
{
return
baseValidSegments
;
}
// 要求不可中断时,过滤符合连续时长要求的片段
return
filterContinuousCompliantSegments
(
baseValidSegments
,
currentTime
,
requiredMinutes
);
}
/**
* 计算可用片段的总有效时长
* @param useSegments 可用片段列表
* @param currentTime 当前时间
* @return 总可用时长(分钟)
*/
private
double
calculateTotalAvailableSecond
(
List
<
TimeSegment
>
useSegments
,
LocalDateTime
currentTime
)
{
// 空判断:
if
(
useSegments
==
null
||
useSegments
.
size
()==
0
)
{
return
0.0
;
}
return
useSegments
.
stream
()
.
mapToDouble
(
segment
->
{
// 取片段起始时间和当前时间的最大值,对应C#的 t.Start < currentTime ? currentTime : t.Start
LocalDateTime
effectiveStart
=
segment
.
getStart
().
compareTo
(
currentTime
)
<
0
?
currentTime
:
segment
.
getStart
();
// 计算单个片段的有效时长(分钟),并乘以效率值,对应C#的 (t.End - effectiveStart).TotalMinutes * t.Efficiency
double
segmentSeconds
=
ChronoUnit
.
SECONDS
.
between
(
effectiveStart
,
segment
.
getEnd
());
return
segmentSeconds
*
segment
.
getEfficiency
();
})
.
sum
();
// 累加所有片段的有效时长
}
/**
* 辅助方法:过滤出满足连续时长要求的片段(仅不可中断配置生效时调用)
* 前置剔除零散无效片段,减少后续逻辑处理量
*/
private
List
<
TimeSegment
>
filterContinuousCompliantSegments
(
List
<
TimeSegment
>
baseValidSegments
,
LocalDateTime
currentTime
,
double
requiredContinuous
)
{
// 空判断:对应C#的 baseValidSegments.Count == 0
if
(
baseValidSegments
==
null
||
baseValidSegments
.
isEmpty
())
{
return
new
ArrayList
<>();
}
List
<
TimeSegment
>
continuousCompliantSegments
=
new
ArrayList
<>();
List
<
TimeSegment
>
tempContinuousGroup
=
new
ArrayList
<>();
double
tempContinuous
=
0.0
;
LocalDateTime
lastSegmentEnd
=
currentTime
;
// 遍历基础有效片段,筛选出可拼接成连续时长的片段组(对应C#的foreach)
for
(
TimeSegment
segment
:
baseValidSegments
)
{
// 确定有效起始时间:对应C#的三元表达式 segment.Start > currentTime ? segment.Start : currentTime
LocalDateTime
effectiveStart
=
segment
.
getStart
().
compareTo
(
currentTime
)
>
0
?
segment
.
getStart
()
:
currentTime
;
if
(
effectiveStart
.
compareTo
(
segment
.
getEnd
())
>=
0
)
{
// 该片段无有效时长,跳过
continue
;
}
// 判断是否与临时连续组无缝衔接
if
(!
tempContinuousGroup
.
isEmpty
()
&&
effectiveStart
.
compareTo
(
lastSegmentEnd
)
!=
0
)
{
// 不衔接:先判断临时组是否满足连续时长,满足则加入结果
if
(
tempContinuous
>=
requiredContinuous
)
{
continuousCompliantSegments
.
addAll
(
tempContinuousGroup
);
// 对应C#的AddRange
}
// 重置临时组
tempContinuousGroup
.
clear
();
tempContinuous
=
0.0
;
}
// 加入临时连续组,累加时长
tempContinuousGroup
.
add
(
segment
);
// 计算当前片段有效时长(分钟)并累加
double
segmentEffective
=
ChronoUnit
.
SECONDS
.
between
(
effectiveStart
,
segment
.
getEnd
())
*
segment
.
getEfficiency
();
tempContinuous
+=
segmentEffective
;
// 更新最后一个片段结束时间(加1秒)
lastSegmentEnd
=
segment
.
getEnd
().
plusSeconds
(
1
);
// 临时组满足连续时长,直接加入结果(提前终止当前组遍历)
if
(
tempContinuous
>=
requiredContinuous
)
{
continuousCompliantSegments
.
addAll
(
tempContinuousGroup
);
// 可选择是否继续遍历(此处继续,获取所有符合条件的片段;也可break直接返回第一个组)
tempContinuousGroup
.
clear
();
tempContinuous
=
0.0
;
}
}
// 遍历结束后,检查最后一个临时组是否满足连续时长
if
(
tempContinuous
>=
requiredContinuous
)
{
continuousCompliantSegments
.
addAll
(
tempContinuousGroup
);
}
// 去重并排序(避免重复片段),对应C#的MergeSegments方法
return
MergeSegments
(
continuousCompliantSegments
);
}
/**
* 批量获取冲突区间(优化边界判断,更严谨)
* 依赖:Machine、ScheduleResult、TimeSegment、DateTime 类(已在前序代码中定义,需补充部分属性)
*/
private
List
<
TimeSegment
>
getConflictIntervals
(
Machine
machine
,
List
<
GAScheduleResult
>
machineTasks
,
LocalDateTime
start
,
LocalDateTime
end
)
{
List
<
TimeSegment
>
conflictIntervals
=
new
ArrayList
<>();
// 1. 维护窗口冲突(优化重叠判断,更严谨)
if
(
machine
.
getMaintenanceWindows
()
!=
null
&&
!
machine
.
getMaintenanceWindows
().
isEmpty
())
{
// 过滤重叠的维护窗口并转换为TimeSegment
List
<
TimeSegment
>
maintenanceConflicts
=
machine
.
getMaintenanceWindows
().
stream
()
// 正确的重叠判断:w.StartTime < end && w.EndTime > start
.
filter
(
w
->
w
.
getStartTime
().
compareTo
(
end
)
<
0
&&
w
.
getEndTime
().
compareTo
(
start
)
>
0
)
// 转换为TimeSegment对象
.
map
(
w
->
new
TimeSegment
(
w
.
getStartTime
(),
w
.
getEndTime
()))
.
collect
(
Collectors
.
toList
());
// 批量添加冲突片段
conflictIntervals
.
addAll
(
maintenanceConflicts
);
}
// 2. 已有任务冲突
if
(
machineTasks
!=
null
&&
machineTasks
.
size
()>
0
)
{
// 第一步:转换任务为TimeSegment并过滤重叠冲突
List
<
TimeSegment
>
taskConflicts
=
machineTasks
.
stream
()
.
map
(
w
->
{
// 计算任务起始和结束时间:baseTime.AddMinutes(w.StartTime)/w.EndTime
LocalDateTime
taskStart
=
baseTime
.
plusSeconds
(
w
.
getStartTime
());
LocalDateTime
taskEnd
=
baseTime
.
plusSeconds
(
w
.
getEndTime
());
return
new
TimeSegment
(
taskStart
,
taskEnd
);
})
// 正确的重叠判断:t.Start < end && t.End > start
.
filter
(
t
->
t
.
getStart
().
compareTo
(
end
)
<
0
&&
t
.
getEnd
().
compareTo
(
start
)
>
0
)
.
collect
(
Collectors
.
toList
());
// 批量添加任务冲突片段
conflictIntervals
.
addAll
(
taskConflicts
);
}
// 按开始时间排序
return
conflictIntervals
.
stream
()
.
sorted
(
Comparator
.
comparing
(
TimeSegment:
:
getStart
,
Comparator
.
nullsLast
(
LocalDateTime:
:
compareTo
)))
.
collect
(
Collectors
.
toList
());
}
/**
* 按总和逻辑处理冲突(保留原有冲突处理逻辑,优化严谨性)
* @param useSegments 可用片段列表
* @param conflictSegments 冲突片段列表
* @param currentTime 当前时间
* @param requiredMinutes 所需总时长(分钟)
* @return 满足条件的片段列表,无满足条件时返回null
*/
private
List
<
TimeSegment
>
handleConflictsWithSumLogic
(
List
<
TimeSegment
>
useSegments
,
List
<
TimeSegment
>
conflictSegments
,
LocalDateTime
currentTime
,
double
requiredMinutes
)
{
// 遍历所有冲突片段,对应C#的foreach循环
for
(
TimeSegment
conflict
:
conflictSegments
)
{
LocalDateTime
currentTime1
=
currentTime
;
// 过滤冲突前的可用片段(
List
<
TimeSegment
>
preConflictSegments
=
useSegments
.
stream
()
.
filter
(
slot
->
(
slot
.
getStart
().
compareTo
(
currentTime1
)
>=
0
||
slot
.
getEnd
().
compareTo
(
currentTime1
)
>
0
)
&&
slot
.
getEnd
().
compareTo
(
conflict
.
getStart
())
<=
0
)
.
collect
(
Collectors
.
toList
());
// 计算冲突前片段的总可用时长
double
preConflictTotalTime
=
calculateTotalAvailableSecond
(
preConflictSegments
,
currentTime
);
// 冲突前时长超过所需时长则返回(保留原有判断逻辑),否则更新当前时间跳过冲突
if
(
preConflictTotalTime
>
requiredMinutes
)
{
return
preConflictSegments
;
}
else
{
//更新当前时间为冲突结束时间+1秒
currentTime
=
conflict
.
getEnd
().
plusSeconds
(
1
);
}
}
// 所有冲突前片段均不足所需时长,返回null(与原C#逻辑一致)
return
null
;
}
/**
* 追加片段并去重、排序(避免冗余片段和遍历混乱)
*/
private
void
addSegmentsWithDeduplication
(
Machine
machine
,
List
<
TimeSegment
>
newSegments
)
{
// 空判断:新片段为null或空集合时直接返回,对应C#的 newSegments == null || newSegments.Count == 0
if
(
newSegments
==
null
||
newSegments
.
isEmpty
())
{
return
;
}
// 追加新片段,对应C#的 machine.Availability.AddRange(newSegments)
machine
.
getAvailability
().
addAll
(
newSegments
);
// 合并片段(去重+排序),并重新赋值给设备的可用片段列表,对应C#的 machine.Availability = MergeSegments(...)
List
<
TimeSegment
>
mergedSegments
=
MergeSegments
(
machine
.
getAvailability
());
machine
.
setAvailability
(
mergedSegments
);
}
private
boolean
CheckTask
(
Machine
machine
,
List
<
GAScheduleResult
>
machineTasks
,
LocalDateTime
prevEnd
,
LocalDateTime
shiftStart
)
{
private
boolean
CheckTask
(
Machine
machine
,
List
<
GAScheduleResult
>
machineTasks
,
LocalDateTime
prevEnd
,
LocalDateTime
shiftStart
)
{
LocalDateTime
finalPrevEnd
=
prevEnd
;
LocalDateTime
finalPrevEnd
=
prevEnd
;
boolean
hasTask
=
machineTasks
.
stream
()
boolean
hasTask
=
machineTasks
.
stream
()
...
@@ -484,6 +850,46 @@ public class MachineCalculator {
...
@@ -484,6 +850,46 @@ public class MachineCalculator {
machine
.
setAvailability
(
MergeSegments
(
machine
.
getAvailability
()));
machine
.
setAvailability
(
MergeSegments
(
machine
.
getAvailability
()));
}
}
/**
* 分割设备可用时间段
* @param machine 设备实例
* @param timeSegment 待分割的时间片段
* @param start 分割起始时间
*/
private
void
spiltMachineAvailable
(
Machine
machine
,
TimeSegment
timeSegment
,
LocalDateTime
start
)
{
List
<
TimeSegment
>
timeSegments
=
new
ArrayList
<>();
// 查找待分割片段在设备可用列表中的索引,对应C#的 FindIndex
int
inx
=
machine
.
getAvailability
().
stream
()
.
filter
(
t
->
t
.
getKey
().
equals
(
timeSegment
.
getKey
()))
.
findFirst
()
.
map
(
machine
.
getAvailability
()::
indexOf
)
.
orElse
(-
1
);
if
(
inx
>
-
1
)
{
// 创建分割后的前半段时间片段,对应原C#逻辑
TimeSegment
time
=
new
TimeSegment
();
time
.
setStart
(
timeSegment
.
getStart
());
// 对应C#的 start.AddSeconds(-1)
time
.
setEnd
(
start
.
plusSeconds
(-
1
));
time
.
setHoliday
(
false
);
// 对应C#的 IsHoliday = false
// 对应C#的 Guid.NewGuid().ToString(),生成唯一标识
time
.
setKey
(
UUID
.
randomUUID
().
toString
());
time
.
setType
(
SegmentType
.
REGULAR
);
time
.
setUsed
(
false
);
// 对应C#的 IsUsed = false
timeSegments
.
add
(
time
);
// 更新原片段的起始时间为分割时间,对应C#的 machine.Availability[inx].Start = start
machine
.
getAvailability
().
get
(
inx
).
setStart
(
start
);
}
// 批量添加分割后的片段(空判断优化,符合Java规范)
if
(
timeSegments
!=
null
&&
!
timeSegments
.
isEmpty
())
{
machine
.
getAvailability
().
addAll
(
timeSegments
);
}
// 按起始时间排序,对应C#的 Sort((a, b) => a.Start.CompareTo(b.Start))
machine
.
getAvailability
().
sort
((
a
,
b
)
->
a
.
getStart
().
compareTo
(
b
.
getStart
()));
}
private
List
<
TimeSegment
>
MergeSegments
(
List
<
TimeSegment
>
segments
)
{
private
List
<
TimeSegment
>
MergeSegments
(
List
<
TimeSegment
>
segments
)
{
List
<
TimeSegment
>
maintenanceSegments
=
segments
.
stream
()
List
<
TimeSegment
>
maintenanceSegments
=
segments
.
stream
()
...
...
src/main/java/com/aps/service/Algorithm/MaterialRequirementService.java
View file @
34bcb88f
package
com
.
aps
.
service
.
Algorithm
;
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.common.util.GlobalCacheUtil
;
import
com.aps.common.util.SnowFlackIdWorker
;
import
com.aps.common.util.SnowFlackIdWorker
;
import
com.aps.common.util.redis.RedisUtils
;
import
com.aps.entity.*
;
import
com.aps.entity.*
;
import
com.aps.entity.Algorithm.BOMBuildResult
;
import
com.aps.entity.Algorithm.BOMBuildResult
;
import
com.aps.entity.Algorithm.IDAndChildID.GroupResult
;
import
com.aps.entity.Algorithm.IDAndChildID.GroupResult
;
...
@@ -54,6 +56,8 @@ public class MaterialRequirementService {
...
@@ -54,6 +56,8 @@ public class MaterialRequirementService {
@Autowired
@Autowired
RoutingDetailConnectService
routingDetailConnectService
;
RoutingDetailConnectService
routingDetailConnectService
;
@Autowired
private
RedisUtils
redisUtils
;
private
List
<
Order
>
orders
;
private
List
<
Order
>
orders
;
...
@@ -153,7 +157,7 @@ if(routingIds.size()==0)
...
@@ -153,7 +157,7 @@ if(routingIds.size()==0)
allRequirements
.
addAll
(
result
.
getMaterialRequirements
());
allRequirements
.
addAll
(
result
.
getMaterialRequirements
());
childorders
.
addAll
(
result
.
getChildOrders
());
childorders
.
addAll
(
result
.
getChildOrders
());
_newEntrys
.
addAll
(
result
.
getNewEntrys
());
_newEntrys
.
addAll
(
result
.
getNewEntrys
());
//
_newMachines.addAll(result.getNewMachines());
_newMachines
.
addAll
(
result
.
getNewMachines
());
}
}
...
@@ -163,10 +167,10 @@ if(routingIds.size()==0)
...
@@ -163,10 +167,10 @@ if(routingIds.size()==0)
orders
.
addAll
(
childorders
);
orders
.
addAll
(
childorders
);
// _allOperations.addAll(_newEntrys);
// _allOperations.addAll(_newEntrys);
Set
<
Long
>
existIds
=
new
HashSet
<>();
Set
<
Long
>
existIds
=
new
HashSet
<>();
// _Machines.addAll(_newMachines.stream()
_Machines
.
addAll
(
_newMachines
);
// .filter(t->existIds.add(t.getId()))//HashSet.add() 方法:添加成功返回 true,重复返回 false;
_Machines
=
_Machines
.
stream
()
// .collect(Collectors.toList()));
.
filter
(
t
->
existIds
.
add
(
t
.
getId
()))
//HashSet.add() 方法:添加成功返回 true,重复返回 false;
.
collect
(
Collectors
.
toList
());
}
}
return
allRequirements
;
return
allRequirements
;
...
@@ -227,7 +231,7 @@ if(routingIds.size()==0)
...
@@ -227,7 +231,7 @@ if(routingIds.size()==0)
materialRequirements
.
addAll
(
operationResult
.
getMaterialRequirements
());
materialRequirements
.
addAll
(
operationResult
.
getMaterialRequirements
());
childorders2
.
addAll
(
operationResult
.
getChildOrders
());
childorders2
.
addAll
(
operationResult
.
getChildOrders
());
_newEntrys
.
addAll
(
operationResult
.
getNewEntrys
());
_newEntrys
.
addAll
(
operationResult
.
getNewEntrys
());
//
_newMachines.addAll(operationResult.getNewMachines());
_newMachines
.
addAll
(
operationResult
.
getNewMachines
());
}
}
}
}
}
}
...
@@ -369,9 +373,25 @@ if(routingIds.size()==0)
...
@@ -369,9 +373,25 @@ if(routingIds.size()==0)
ProdLaunchOrders
.
add
(
order
);
ProdLaunchOrders
.
add
(
order
);
Map
<
Integer
,
Object
>
list
=
_routingDataService
.
CreateEntry
(
sceneId
,
ProdEquipmentList
,
ProdLaunchOrders
,
routingDiscreteParams
,
ProdOrderProcesslist
,
processExecList
,
_entryRel
,
finishOpertionID
);
Map
<
Integer
,
Object
>
list
=
_routingDataService
.
CreateEntry
(
sceneId
,
ProdEquipmentList
,
ProdLaunchOrders
,
routingDiscreteParams
,
ProdOrderProcesslist
,
processExecList
,
_entryRel
,
finishOpertionID
);
List
<
Machine
>
machines
=
new
ArrayList
<>();
List
<
Machine
>
allmachines
=
(
List
<
Machine
>)
GlobalCacheUtil
.
get
(
"machines"
);
if
(
allmachines
==
null
||
allmachines
.
size
()
==
0
)
{
allmachines
=
(
List
<
Machine
>)
redisUtils
.
get
(
"machines"
);
if
(
allmachines
==
null
||
allmachines
.
size
()
==
0
)
{
List
<
Long
>
equipIds
=
ProdEquipmentList
.
stream
()
.
map
(
ProdEquipment:
:
getEquipId
)
.
distinct
()
// 提取Exec_ID
.
collect
(
Collectors
.
toList
());
machines
=
allmachines
.
stream
().
filter
(
t
->
equipIds
.
contains
(
t
.
getId
())).
collect
(
Collectors
.
toList
());
}
// List<Machine> machines= _routingDataService.InitCalendarToAllMachines(sceneId,ProdEquipmentList,machineScheduler, globalParam.isIsUseCalendar());
}
if
(
machines
==
null
||
machines
.
size
()
==
0
)
{
machines
=
_routingDataService
.
InitCalendarToAllMachines
(
sceneId
,
ProdEquipmentList
,
machineScheduler
,
globalParam
.
isIsUseCalendar
());
}
if
(
list
.
get
(
1
)!=
null
)
if
(
list
.
get
(
1
)!=
null
)
{
{
...
@@ -380,7 +400,7 @@ if(routingIds.size()==0)
...
@@ -380,7 +400,7 @@ if(routingIds.size()==0)
}
}
Map
<
Integer
,
Object
>
rest
=
new
HashMap
<>();
Map
<
Integer
,
Object
>
rest
=
new
HashMap
<>();
rest
.
put
(
1
,
list
.
get
(
1
));
rest
.
put
(
1
,
list
.
get
(
1
));
//
rest.put(2,machines);
rest
.
put
(
2
,
machines
);
return
rest
;
return
rest
;
}
}
...
@@ -606,7 +626,7 @@ if(routingIds.size()==0)
...
@@ -606,7 +626,7 @@ if(routingIds.size()==0)
_childorders
.
add
(
childorder
);
_childorders
.
add
(
childorder
);
List
<
Entry
>
newentrys
=(
List
<
Entry
>)
list
.
get
(
1
);
List
<
Entry
>
newentrys
=(
List
<
Entry
>)
list
.
get
(
1
);
_newEntrys
.
addAll
(
newentrys
);
_newEntrys
.
addAll
(
newentrys
);
//
_newMachines.addAll((List<Machine>)list.get(2));
_newMachines
.
addAll
((
List
<
Machine
>)
list
.
get
(
2
));
orderMaterial
.
getProductOrderID
().
add
(
childorder
.
getId
());
orderMaterial
.
getProductOrderID
().
add
(
childorder
.
getId
());
operation
.
getDependentOnOrderIds
().
add
(
childorder
.
getId
());
operation
.
getDependentOnOrderIds
().
add
(
childorder
.
getId
());
// 递归构建BOM
// 递归构建BOM
...
@@ -617,7 +637,7 @@ if(routingIds.size()==0)
...
@@ -617,7 +637,7 @@ if(routingIds.size()==0)
materialRequirements
.
addAll
(
childResult
.
getMaterialRequirements
());
materialRequirements
.
addAll
(
childResult
.
getMaterialRequirements
());
_childorders
.
addAll
(
childResult
.
getChildOrders
());
_childorders
.
addAll
(
childResult
.
getChildOrders
());
_newEntrys
.
addAll
(
childResult
.
getNewEntrys
());
_newEntrys
.
addAll
(
childResult
.
getNewEntrys
());
//
_newMachines.addAll(childResult.getNewMachines());
_newMachines
.
addAll
(
childResult
.
getNewMachines
());
}
}
}
}
}
}
...
...
src/main/java/com/aps/service/Algorithm/NSGAIIUtils.java
View file @
34bcb88f
...
@@ -19,6 +19,15 @@ public class NSGAIIUtils {
...
@@ -19,6 +19,15 @@ public class NSGAIIUtils {
private
ObjectiveWeights
objectiveWeights
;
private
ObjectiveWeights
objectiveWeights
;
private
int
taskCount
;
// 并行任务数(默认=CPU核心数)
private
int
taskCount
;
// 并行任务数(默认=CPU核心数)
// true 越小越好
private
boolean
[]
isMinimize
=
{
true
,
true
,
true
,
true
,
true
};
public
void
init
(
ObjectiveWeights
weights
,
int
taskCount
,
boolean
[]
isMinimize
)
{
this
.
objectiveWeights
=
(
weights
!=
null
)
?
weights
:
new
ObjectiveWeights
();
this
.
taskCount
=
(
taskCount
>
0
)
?
taskCount
:
Runtime
.
getRuntime
().
availableProcessors
();
this
.
isMinimize
=
isMinimize
;
}
/**
/**
* 初始化(设置权重和并行任务数)
* 初始化(设置权重和并行任务数)
*/
*/
...
@@ -40,77 +49,101 @@ public class NSGAIIUtils {
...
@@ -40,77 +49,101 @@ public class NSGAIIUtils {
*/
*/
public
List
<
List
<
Chromosome
>>
parallelFastNonDominatedSort
(
List
<
Chromosome
>
population
)
{
public
List
<
List
<
Chromosome
>>
parallelFastNonDominatedSort
(
List
<
Chromosome
>
population
)
{
int
popSize
=
population
.
size
();
int
popSize
=
population
.
size
();
List
<
List
<
Chromosome
>>
fronts
=
new
ArrayList
<>();
if
(
popSize
<=
taskCount
*
10
)
{
// 小规模种群直接串行
// 步骤1:预处理 - 计算归一化目标值和加权目标值
preprocessObjectives
(
population
);
return
fastNonDominatedSort
(
population
);
}
// 步骤1:预处理 - 计算归一化目标值和加权目标值
// 步骤1:预处理 - 计算归一化目标值和加权目标值
preprocessObjectives
(
population
);
preprocessObjectives
(
population
);
if
(
popSize
<=
taskCount
*
10
)
{
// 小规模种群直接串行
fronts
=
fastNonDominatedSort
(
population
);
}
else
{
// 步骤2:拆分种群为多个块,并行计算支配关系
List
<
List
<
Chromosome
>>
chunks
=
splitPopulation
(
population
,
taskCount
);
ConcurrentHashMap
<
Chromosome
,
ConcurrentLinkedQueue
<
Chromosome
>>
dominanceMatrix
=
new
ConcurrentHashMap
<>();
ConcurrentHashMap
<
Chromosome
,
AtomicInteger
>
dominatedCount
=
new
ConcurrentHashMap
<>();
// 初始化字典
// 步骤2:拆分种群为多个块,并行计算支配关系
for
(
Chromosome
chromo
:
population
)
{
List
<
List
<
Chromosome
>>
chunks
=
splitPopulation
(
population
,
taskCount
);
dominanceMatrix
.
putIfAbsent
(
chromo
,
new
ConcurrentLinkedQueue
<>());
ConcurrentHashMap
<
Chromosome
,
ConcurrentLinkedQueue
<
Chromosome
>>
dominanceMatrix
=
new
ConcurrentHashMap
<>();
dominatedCount
.
putIfAbsent
(
chromo
,
new
AtomicInteger
(
0
));
ConcurrentHashMap
<
Chromosome
,
AtomicInteger
>
dominatedCount
=
new
ConcurrentHashMap
<>();
}
// 并行计算支配关系
// 初始化字典
chunks
.
parallelStream
().
forEach
(
chunk
->
{
for
(
Chromosome
chromo
:
population
)
{
for
(
Chromosome
p
:
chunk
)
{
dominanceMatrix
.
putIfAbsent
(
chromo
,
new
ConcurrentLinkedQueue
<>());
for
(
Chromosome
q
:
population
)
{
dominatedCount
.
putIfAbsent
(
chromo
,
new
AtomicInteger
(
0
));
if
(
p
==
q
)
continue
;
}
if
(
dominates
(
p
,
q
))
{
// 并行计算支配关系
dominanceMatrix
.
get
(
p
).
add
(
q
);
chunks
.
parallelStream
().
forEach
(
chunk
->
{
}
else
if
(
dominates
(
q
,
p
))
{
for
(
Chromosome
p
:
chunk
)
{
dominatedCount
.
get
(
p
).
incrementAndGet
();
for
(
Chromosome
q
:
population
)
{
if
(
p
==
q
)
continue
;
if
(
dominates
(
p
,
q
))
{
dominanceMatrix
.
get
(
p
).
add
(
q
);
}
else
if
(
dominates
(
q
,
p
))
{
dominatedCount
.
get
(
p
).
incrementAndGet
();
}
}
}
}
}
}
});
});
// 步骤3:生成前沿
// 步骤3:生成前沿
List
<
List
<
Chromosome
>>
fronts
=
new
ArrayList
<>();
List
<
Chromosome
>
front1
=
new
ArrayList
<>();
for
(
Chromosome
p
:
population
)
{
List
<
Chromosome
>
front1
=
new
ArrayList
<>();
if
(
dominatedCount
.
get
(
p
).
get
()
==
0
)
{
p
.
setRank
(
1
);
for
(
Chromosome
p
:
population
)
{
front1
.
add
(
p
);
if
(
dominatedCount
.
get
(
p
).
get
()
==
0
)
{
front1
.
add
(
p
);
}
}
}
}
fronts
.
add
(
front1
);
fronts
.
add
(
front1
);
int
i
=
0
;
int
i
=
0
;
while
(
fronts
.
get
(
i
).
size
()
>
0
)
{
while
(
fronts
.
get
(
i
).
size
()
>
0
)
{
List
<
Chromosome
>
nextFront
=
new
ArrayList
<>();
List
<
Chromosome
>
nextFront
=
new
ArrayList
<>();
for
(
Chromosome
p
:
fronts
.
get
(
i
))
{
for
(
Chromosome
p
:
fronts
.
get
(
i
))
{
for
(
Chromosome
q
:
dominanceMatrix
.
get
(
p
))
{
for
(
Chromosome
q
:
dominanceMatrix
.
get
(
p
))
{
AtomicInteger
count
=
dominatedCount
.
get
(
q
);
AtomicInteger
count
=
dominatedCount
.
get
(
q
);
if
(
count
.
decrementAndGet
()
==
0
)
{
if
(
count
.
decrementAndGet
()
==
0
)
{
q
.
setRank
(
i
+
2
);
nextFront
.
add
(
q
);
nextFront
.
add
(
q
);
}
}
}
}
}
}
i
++;
i
++;
if
(!
nextFront
.
isEmpty
())
{
if
(!
nextFront
.
isEmpty
())
{
fronts
.
add
(
nextFront
);
fronts
.
add
(
nextFront
);
}
}
}
}
}
assignRankToSolutions
(
fronts
);
return
fronts
;
return
fronts
;
}
}
/**
* 用Stream API为分层后的解批量赋值Rank
*/
public
void
assignRankToSolutions
(
List
<
List
<
Chromosome
>>
result
)
{
if
(
result
==
null
||
result
.
isEmpty
())
{
return
;
}
// 遍历外层List,同时获取索引和对应的解列表
IntStream
.
range
(
0
,
result
.
size
()).
forEach
(
i
->
{
int
rank
=
i
+
1
;
List
<
Chromosome
>
solutionsInRank
=
result
.
get
(
i
);
if
(
solutionsInRank
!=
null
&&
solutionsInRank
.
size
()>
0
)
{
solutionsInRank
.
stream
()
.
filter
(
Objects:
:
nonNull
)
// 过滤null的Solution
.
forEach
(
solution
->
solution
.
setRank
(
rank
));
if
(
solutionsInRank
.
size
()>
1
)
{
parallelCalculateCrowdingDistance
(
solutionsInRank
);
}
}
});
}
/**
/**
...
@@ -118,36 +151,42 @@ public class NSGAIIUtils {
...
@@ -118,36 +151,42 @@ public class NSGAIIUtils {
*/
*/
public
List
<
List
<
Chromosome
>>
fastNonDominatedSort
(
List
<
Chromosome
>
population
)
{
public
List
<
List
<
Chromosome
>>
fastNonDominatedSort
(
List
<
Chromosome
>
population
)
{
// 1. 初始化数据结构:S(被支配集合)、n(支配数)
// 1. 初始化数据结构:S(被支配集合)、n(支配数)
//当前解能支配的其他解的集合。
Map
<
Chromosome
,
List
<
Chromosome
>>
S
=
new
HashMap
<>();
Map
<
Chromosome
,
List
<
Chromosome
>>
S
=
new
HashMap
<>();
//能支配当前解的其他解的数量;
Map
<
Chromosome
,
Integer
>
n
=
new
HashMap
<>();
Map
<
Chromosome
,
Integer
>
n
=
new
HashMap
<>();
List
<
List
<
Chromosome
>>
fronts
=
new
ArrayList
<>();
List
<
List
<
Chromosome
>>
fronts
=
new
ArrayList
<>();
// 为每个个体预先初始化 S 和 n
// 为每个个体预先初始化 S 和 n
for
(
Chromosome
p
:
population
)
{
for
(
Chromosome
p
:
population
)
{
S
.
put
(
p
,
new
ArrayList
<>());
// 初始化空集合,避免null
S
.
put
(
p
,
new
ArrayList
<>());
// 初始化空集合,避免null
当前解能支配的其他解的集合
n
.
put
(
p
,
0
);
// 支配数初始化为0
n
.
put
(
p
,
0
);
// 支配数初始化为0
。能支配当前解的其他解的数量
}
}
//S 当前解能支配的其他解的集合。
//n 能支配当前解的其他解的数量;
// 2. 计算每个个体的支配关系
// 2. 计算每个个体的支配关系
for
(
Chromosome
p
:
population
)
{
for
(
Chromosome
s1
:
population
)
{
for
(
Chromosome
q
:
population
)
{
for
(
Chromosome
s2
:
population
)
{
if
(
p
==
q
)
continue
;
if
(
s1
==
s2
)
continue
;
// p.getWeightedObjective() < q.getWeightedObjective();
// p.getWeightedObjective() < q.getWeightedObjective();
if
(
dominates
(
p
,
q
))
{
//【0,1】 越靠近1 越好
// p支配q,将q加入p的被支配集合S
S
.
get
(
p
).
add
(
q
);
if
(
dominates
(
s1
,
s2
))
{
}
else
if
(
dominates
(
q
,
p
))
{
//s1支配s2 → 更新s1的被支配集合,s2的支配数+1
// q支配p,增加p的支配数n
S
.
get
(
s1
).
add
(
s2
);
n
.
put
(
p
,
n
.
get
(
p
)
+
1
);
}
else
if
(
dominates
(
s2
,
s1
))
{
// s2支配s1 → s1的被支配数+1(避免重复计算)
n
.
put
(
s1
,
n
.
get
(
s1
)
+
1
);
}
}
}
}
// 3. 初始化第一前沿(支配数为0的个体)
// 3. 初始化第一前沿(支配数为0的个体)
if
(
n
.
get
(
p
)
==
0
)
{
if
(
n
.
get
(
s1
)
==
0
)
{
if
(
fronts
.
isEmpty
())
{
if
(
fronts
.
isEmpty
())
{
fronts
.
add
(
new
ArrayList
<>());
fronts
.
add
(
new
ArrayList
<>());
}
}
fronts
.
get
(
0
).
add
(
p
);
// s1.setRank(1);
fronts
.
get
(
0
).
add
(
s1
);
}
}
}
}
...
@@ -160,6 +199,7 @@ public class NSGAIIUtils {
...
@@ -160,6 +199,7 @@ public class NSGAIIUtils {
for
(
Chromosome
q
:
S
.
get
(
p
))
{
for
(
Chromosome
q
:
S
.
get
(
p
))
{
n
.
put
(
q
,
n
.
get
(
q
)
-
1
);
n
.
put
(
q
,
n
.
get
(
q
)
-
1
);
if
(
n
.
get
(
q
)
==
0
)
{
if
(
n
.
get
(
q
)
==
0
)
{
nextFront
.
add
(
q
);
nextFront
.
add
(
q
);
}
}
}
}
...
@@ -170,27 +210,32 @@ public class NSGAIIUtils {
...
@@ -170,27 +210,32 @@ public class NSGAIIUtils {
return
fronts
;
return
fronts
;
}
}
/**
/**
* 预处理目标值(归一化+加权)
* 预处理目标值(归一化+加权)
*/
*/
private
void
preprocessObjectives
(
List
<
Chromosome
>
population
)
{
private
void
preprocessObjectives
(
List
<
Chromosome
>
population
)
{
int
kpisize
=
population
.
get
(
0
).
getObjectives
().
length
;
// 计算每个目标的最大/最小值
// 计算每个目标的最大/最小值
double
[]
minValues
=
new
double
[
5
];
double
[]
minValues
=
new
double
[
kpisize
];
double
[]
maxValues
=
new
double
[
5
];
double
[]
maxValues
=
new
double
[
kpisize
];
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
for
(
int
i
=
0
;
i
<
kpisize
;
i
++)
{
final
int
idx
=
i
;
final
int
idx
=
i
;
minValues
[
i
]
=
population
.
stream
().
mapToDouble
(
c
->
c
.
getObjectives
()[
idx
]).
min
().
orElse
(
0
);
minValues
[
i
]
=
population
.
stream
().
mapToDouble
(
c
->
c
.
getObjectives
()[
idx
]).
min
().
orElse
(
0
);
maxValues
[
i
]
=
population
.
stream
().
mapToDouble
(
c
->
c
.
getObjectives
()[
idx
]).
max
().
orElse
(
0
);
maxValues
[
i
]
=
population
.
stream
().
mapToDouble
(
c
->
c
.
getObjectives
()[
idx
]).
max
().
orElse
(
0
);
}
}
boolean
[]
isMinimize
=
{
true
,
true
,
true
,
false
,
true
};
// 并行计算归一化和加权目标值
// 并行计算归一化和加权目标值
population
.
parallelStream
().
forEach
(
chromo
->
{
population
.
parallelStream
().
forEach
(
chromo
->
{
double
[]
normalized
=
objectiveWeights
.
normalizeObjectives
(
chromo
.
getObjectives
(),
minValues
,
maxValues
,
isMinimize
);
double
[]
normalized
=
objectiveWeights
.
normalizeObjectives
(
chromo
.
getObjectives
(),
minValues
,
maxValues
,
this
.
isMinimize
);
chromo
.
setMaxObjectives
(
maxValues
);
chromo
.
setMinObjectives
(
minValues
);
chromo
.
setWeightedObjectives
(
normalized
);
if
(
objectiveWeights
.
isPureNSGAIIMode
())
{
if
(
objectiveWeights
.
isPureNSGAIIMode
())
{
chromo
.
setWeightedObjective
(
objectiveWeights
.
calculateObjective
(
normalized
));
chromo
.
setWeightedObjective
(
objectiveWeights
.
calculateObjective
(
normalized
));
}
else
{
}
else
{
chromo
.
setWeightedObjective
(
objectiveWeights
.
calculateWeightedObjective
(
normalized
));
chromo
.
setWeightedObjective
(
objectiveWeights
.
calculateWeightedObjective
(
normalized
));
}
}
});
});
...
@@ -212,84 +257,125 @@ public class NSGAIIUtils {
...
@@ -212,84 +257,125 @@ public class NSGAIIUtils {
}
}
/**
/**
* 判断p是否支配q(支持自定义权重)
* 判断p是否支配q(支持自定义权重)
*/
*/
public
boolean
dominates
(
Chromosome
p
,
Chromosome
q
)
{
public
boolean
dominates
(
Chromosome
p
,
Chromosome
q
)
{
// 纯NSGA-II模式:标准帕累托支配
// 纯NSGA-II模式:标准帕累托支配
double
[]
pObjectives
=
p
.
getWeightedObjectives
();
double
[]
qObjectives
=
q
.
getWeightedObjectives
();
if
(
objectiveWeights
.
isPureNSGAIIMode
())
{
if
(
objectiveWeights
.
isPureNSGAIIMode
())
{
boolean
allBetterOrEqual
=
true
;
boolean
hasBetter
=
false
;
// 是否至少有一个目标更优
boolean
oneBetter
=
false
;
boolean
hasWorse
=
false
;
// 是否有任何一个目标更差
double
[]
pObjectives
=
p
.
getObjectives
();
double
[]
qObjectives
=
q
.
getObjectives
();
for
(
int
i
=
0
;
i
<
pObjectives
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
pObjectives
.
length
;
i
++)
{
if
(
pObjectives
[
i
]
>
qObjectives
[
i
])
{
allBetterOrEqual
=
false
;
double
thisObj
=
pObjectives
[
i
];
break
;
double
otherObj
=
qObjectives
[
i
];
}
else
if
(
pObjectives
[
i
]
<
qObjectives
[
i
])
{
oneBetter
=
true
;
// 目标越大越好:当前解 > 另一个解 → 更优
if
(
thisObj
>
otherObj
)
{
hasBetter
=
true
;
}
// 当前解 < 另一个解 → 更差
else
if
(
thisObj
<
otherObj
)
{
hasWorse
=
true
;
}
}
}
}
return
allBetterOrEqual
&&
oneBetter
;
return
hasBetter
&&
!
hasWorse
;
}
}
// 加权NSGA-II模式:融合权重的支配关系
// 加权NSGA-II模式:融合权重的支配关系
else
{
else
{
// 方式1:加权目标值更小则支配(简单高效)
// 方式1:加权目标值更大则支配(简单高效)
return
p
.
getWeightedObjective
()
<
q
.
getWeightedObjective
();
//WeightedObjective 已计算,归一法【0,1】,越靠近1 越好
double
thisScore
=
p
.
getWeightedObjective
();
// 方式2(可选):加权后的帕累托支配
double
otherScore
=
q
.
getWeightedObjective
();
// double pWeightedSum = 0, qWeightedSum = 0;
// - 加权得分严格更优;
// for (int i = 0; i < p.getObjectives().length; i++) {
// - 至少一个权重>0的目标上不劣于对方(避免极端情况)
// pWeightedSum += p.getObjectives()[i] * objectiveWeights.getWeights()[i];
boolean
hasBetterScore
=
thisScore
>
otherScore
;
// qWeightedSum += q.getObjectives()[i] * objectiveWeights.getWeights()[i];
boolean
hasAtLeastOneNotWorse
=
false
;
// }
for
(
int
i
=
0
;
i
<
p
.
getObjectives
().
length
;
i
++)
{
// return pWeightedSum < qWeightedSum;
if
(
objectiveWeights
.
getWeights
()[
i
]
<=
0
)
continue
;
// 跳过权重为0的目标
double
thisObj
=
pObjectives
[
i
];
double
otherObj
=
qObjectives
[
i
];
if
(
thisObj
>=
otherObj
)
{
hasAtLeastOneNotWorse
=
true
;
break
;
}
}
return
hasBetterScore
&&
hasAtLeastOneNotWorse
;
}
}
}
}
/**
/**
* 并行计算拥挤距离
* 并行计算拥挤距离
*/
*/
public
void
parallelCalculateCrowdingDistance
(
List
<
Chromosome
>
front
)
{
public
void
parallelCalculateCrowdingDistance
(
List
<
Chromosome
>
front
)
{
if
(
front
.
isEmpty
())
return
;
if
(
front
.
isEmpty
())
return
;
int
objCount
=
front
.
get
(
0
).
getObjectives
().
length
;
int
kpisize
=
front
.
get
(
0
).
getObjectives
().
length
;
int
popSize
=
front
.
size
();
int
popSize
=
front
.
size
();
// 初始化距离为0
// 初始化距离为0
front
.
parallelStream
().
forEach
(
chromo
->
chromo
.
setCrowdingDistance
(
0.0
));
// front.parallelStream().forEach(chromo -> chromo.setCrowdingDistance(0.0));
// 对每个目标维度并行计算距离
IntStream
.
range
(
0
,
objCount
).
parallel
().
forEach
(
m
->
{
// 计算每个目标的最大/最小值
// 按当前目标排序
double
[]
idealPoint
=
new
double
[
kpisize
];
List
<
Chromosome
>
sorted
=
front
.
stream
()
.
sorted
(
Comparator
.
comparingDouble
(
c
->
c
.
getObjectives
()[
m
]))
for
(
int
i
=
0
;
i
<
kpisize
;
i
++)
{
.
collect
(
Collectors
.
toList
());
final
int
idx
=
i
;
if
(
isMinimize
[
i
])
// 边界个体距离设为无穷大
{
sorted
.
get
(
0
).
setCrowdingDistance
(
Double
.
POSITIVE_INFINITY
);
idealPoint
[
i
]
=
front
.
stream
().
mapToDouble
(
c
->
c
.
getObjectives
()[
idx
]).
min
().
orElse
(
0
);
sorted
.
get
(
popSize
-
1
).
setCrowdingDistance
(
Double
.
POSITIVE_INFINITY
);
}
else
{
double
maxObj
=
sorted
.
get
(
popSize
-
1
).
getObjectives
()[
m
];
idealPoint
[
i
]
=
front
.
stream
().
mapToDouble
(
c
->
c
.
getObjectives
()[
idx
]).
max
().
orElse
(
0
);
double
minObj
=
sorted
.
get
(
0
).
getObjectives
()[
m
];
if
(
maxObj
-
minObj
==
0
)
return
;
// 计算中间个体的拥挤距离
for
(
int
i
=
1
;
i
<
popSize
-
1
;
i
++)
{
Chromosome
chromo
=
sorted
.
get
(
i
);
synchronized
(
chromo
)
{
// 线程安全
double
distance
=
chromo
.
getCrowdingDistance
()
+
(
sorted
.
get
(
i
+
1
).
getObjectives
()[
m
]
-
sorted
.
get
(
i
-
1
).
getObjectives
()[
m
])
/
(
maxObj
-
minObj
);
chromo
.
setCrowdingDistance
(
distance
);
}
}
}
});
}
if
(
popSize
>
taskCount
*
10
)
{
// 对每个目标维度并行计算距离
IntStream
.
range
(
0
,
popSize
).
parallel
().
forEach
(
m
->
{
// 按当前目标排序
Chromosome
chromo
=
front
.
get
(
m
);
double
[]
idealPoint1
=
idealPoint
;
double
[]
objectives
=
chromo
.
getObjectives
();
double
distance
=
calculateEuclideanDistance
(
objectives
,
idealPoint1
);
chromo
.
setCrowdingDistance
(
distance
);
});
}
else
{
front
.
forEach
(
chromo
->
{
double
[]
idealPoint1
=
idealPoint
;
double
[]
objectives
=
chromo
.
getObjectives
();
double
distance
=
calculateEuclideanDistance
(
objectives
,
idealPoint1
);
chromo
.
setCrowdingDistance
(
distance
);
});
}
}
/**
* 计算目标值列表与理想点的欧氏距离
* @param objectives 解的目标值列表
* @param idealPoint 理想点
* @return 欧氏距离(值越小越优)
*/
private
double
calculateEuclideanDistance
(
double
[]
objectives
,
double
[]
idealPoint
)
{
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
objectives
.
length
;
i
++)
{
double
diff
=
objectives
[
i
]
-
idealPoint
[
i
];
//与理想值的差
sum
+=
diff
*
diff
;
// 平方和
}
return
Math
.
sqrt
(
sum
);
// 开平方得到欧氏距离
}
}
/**
/**
...
@@ -304,8 +390,7 @@ public class NSGAIIUtils {
...
@@ -304,8 +390,7 @@ public class NSGAIIUtils {
nextPopulation
.
addAll
(
front
);
nextPopulation
.
addAll
(
front
);
currentSize
+=
front
.
size
();
currentSize
+=
front
.
size
();
}
else
{
}
else
{
// 并行计算拥挤距离
parallelCalculateCrowdingDistance
(
front
);
// 按拥挤距离排序,取前N个
// 按拥挤距离排序,取前N个
List
<
Chromosome
>
sortedByDistance
=
front
.
stream
()
List
<
Chromosome
>
sortedByDistance
=
front
.
stream
()
.
sorted
((
c1
,
c2
)
->
Double
.
compare
(
c2
.
getCrowdingDistance
(),
c1
.
getCrowdingDistance
()))
.
sorted
((
c1
,
c2
)
->
Double
.
compare
(
c2
.
getCrowdingDistance
(),
c1
.
getCrowdingDistance
()))
...
@@ -319,7 +404,53 @@ public class NSGAIIUtils {
...
@@ -319,7 +404,53 @@ public class NSGAIIUtils {
return
nextPopulation
;
return
nextPopulation
;
}
}
public
void
Test
()
{
ObjectiveWeights
weights
=
new
ObjectiveWeights
();
double
[]
weightvs
=
new
double
[]
{
0.5
,
0.5
};
weights
.
setWeights
(
weightvs
);
weights
.
setPureNSGAIIMode
(
false
);
init
(
weights
);
List
<
Chromosome
>
chromosomeList
=
new
ArrayList
<>();
Chromosome
chromosome1
=
new
Chromosome
();
chromosome1
.
setID
(
"A"
);
chromosome1
.
setObjectives
(
new
double
[]{
1
,
3
});
chromosomeList
.
add
(
chromosome1
);
Chromosome
chromosome4
=
new
Chromosome
();
chromosome4
.
setID
(
"B"
);
chromosome4
.
setObjectives
(
new
double
[]{
2
,
2
});
chromosomeList
.
add
(
chromosome4
);
Chromosome
chromosome5
=
new
Chromosome
();
chromosome5
.
setID
(
"C"
);
chromosome5
.
setObjectives
(
new
double
[]{
3
,
1
});
chromosomeList
.
add
(
chromosome5
);
Chromosome
chromosome2
=
new
Chromosome
();
chromosome2
.
setID
(
"D"
);
chromosome2
.
setObjectives
(
new
double
[]{
2
,
3
});
chromosomeList
.
add
(
chromosome2
);
Chromosome
chromosome3
=
new
Chromosome
();
chromosome3
.
setID
(
"E"
);
chromosome3
.
setObjectives
(
new
double
[]{
4
,
4
});
chromosomeList
.
add
(
chromosome3
);
parallelFastNonDominatedSort
(
chromosomeList
);
// 解 A(1,3):
// 支配的解:D(2,3)、E(4,4)→ S (A) = {D,E}
// 被支配的解:无 → n (A) = 0
// 解 B(2,2):
// 支配的解:D(2,3)、E(4,4)→ S (B) = {D,E}
// 被支配的解:无 → n (B) = 0
// 解 C(3,1):
// 支配的解:E(4,4)→ S (C) = {E}
// 被支配的解:无 → n (C) = 0
// 解 D(2,3):
// 支配的解:E(4,4)→ S (D) = {E}
// 被支配的解:A、B → n (D) = 2
// 解 E(4,4):
// 支配的解:无 → S (E) = ∅
// 被支配的解:A、B、C、D → n (E) = 4
}
}
}
src/main/java/com/aps/service/Algorithm/RoutingDataService.java
View file @
34bcb88f
...
@@ -136,7 +136,7 @@ public class RoutingDataService {
...
@@ -136,7 +136,7 @@ public class RoutingDataService {
}
}
List
<
Entry
>
entrys
=
new
ArrayList
<>();
List
<
Entry
>
entrys
=
new
ArrayList
<>();
Set
<
Long
>
machineIds
=
new
HashSet
<>();
for
(
int
i
=
index
;
i
<
results
.
size
();
i
++)
{
for
(
int
i
=
index
;
i
<
results
.
size
();
i
++)
{
GroupResult
groupResult
=
results
.
get
(
i
);
GroupResult
groupResult
=
results
.
get
(
i
);
List
<
NodeInfo
>
nodeInfoList
=
groupResult
.
getNodeInfoList
();
List
<
NodeInfo
>
nodeInfoList
=
groupResult
.
getNodeInfoList
();
...
@@ -234,6 +234,7 @@ public class RoutingDataService {
...
@@ -234,6 +234,7 @@ public class RoutingDataService {
if
(
Equipments
!=
null
&&
Equipments
.
size
()
>
0
)
{
if
(
Equipments
!=
null
&&
Equipments
.
size
()
>
0
)
{
List
<
MachineOption
>
mos
=
new
ArrayList
<>();
List
<
MachineOption
>
mos
=
new
ArrayList
<>();
for
(
ProdEquipment
e
:
Equipments
)
{
for
(
ProdEquipment
e
:
Equipments
)
{
machineIds
.
add
(
e
.
getEquipId
());
MachineOption
mo
=
new
MachineOption
();
MachineOption
mo
=
new
MachineOption
();
mo
.
setMachineId
(
e
.
getEquipId
());
mo
.
setMachineId
(
e
.
getEquipId
());
mo
.
setRuntime
(
e
.
getRuntime
());
mo
.
setRuntime
(
e
.
getRuntime
());
...
@@ -261,7 +262,7 @@ public class RoutingDataService {
...
@@ -261,7 +262,7 @@ public class RoutingDataService {
}
}
list
.
put
(
1
,
entrys
);
list
.
put
(
1
,
entrys
);
list
.
put
(
2
,
results
);
list
.
put
(
2
,
results
);
list
.
put
(
3
,
machineIds
);
return
list
;
return
list
;
}
}
...
@@ -465,7 +466,11 @@ public class RoutingDataService {
...
@@ -465,7 +466,11 @@ public class RoutingDataService {
shift
.
setMachineId
(
machine
.
getId
());
shift
.
setMachineId
(
machine
.
getId
());
shift
.
setStartDate
(
machineProdEquipSpecialCal
.
getEffectiveStartTime
());
shift
.
setStartDate
(
machineProdEquipSpecialCal
.
getEffectiveStartTime
());
shift
.
setEndDate
(
machineProdEquipSpecialCal
.
getEffectiveEndTime
());
shift
.
setEndDate
(
machineProdEquipSpecialCal
.
getEffectiveEndTime
());
if
(
machineProdEquipSpecialCal
.
getEfficiencyCoeff
()!=
null
)
{
shift
.
setEfficiency
(
machineProdEquipSpecialCal
.
getEfficiencyCoeff
());
}
shifts1
.
add
(
shift
);
shifts1
.
add
(
shift
);
}
}
}
}
...
@@ -621,6 +626,7 @@ public class RoutingDataService {
...
@@ -621,6 +626,7 @@ public class RoutingDataService {
days
.
add
(
6
);
days
.
add
(
6
);
days
.
add
(
0
);
days
.
add
(
0
);
shift
.
setDays
(
days
);
shift
.
setDays
(
days
);
shift
.
setStartDate
(
LocalDateTime
.
of
(
2000
,
1
,
1
,
0
,
0
,
0
));
shift
.
setStartDate
(
LocalDateTime
.
of
(
2000
,
1
,
1
,
0
,
0
,
0
));
shift
.
setEndDate
(
LocalDateTime
.
of
(
2000
,
1
,
1
,
0
,
0
,
0
));
shift
.
setEndDate
(
LocalDateTime
.
of
(
2000
,
1
,
1
,
0
,
0
,
0
));
shifts1
.
add
(
shift
);
shifts1
.
add
(
shift
);
...
...
src/main/java/com/aps/service/impl/ProdEquipSpecialCalServiceImpl.java
View file @
34bcb88f
...
@@ -79,7 +79,9 @@ public class ProdEquipSpecialCalServiceImpl extends ServiceImpl<ProdEquipSpecial
...
@@ -79,7 +79,9 @@ public class ProdEquipSpecialCalServiceImpl extends ServiceImpl<ProdEquipSpecial
specialCal
.
setPlanResourceId
(
capacityDef
.
getPlanResourceId
());
specialCal
.
setPlanResourceId
(
capacityDef
.
getPlanResourceId
());
// 处理数值类型转换的空值
// 处理数值类型转换的空值
if
(
capacityDef
.
getEfficiencyCoeff
()
!=
null
)
{
if
(
capacityDef
.
getEfficiencyCoeff
()
!=
null
)
{
specialCal
.
setEfficiencyCoeff
(
capacityDef
.
getEfficiencyCoeff
().
longValue
());
specialCal
.
setEfficiencyCoeff
(
capacityDef
.
getEfficiencyCoeff
().
doubleValue
());
}
else
{
specialCal
.
setEfficiencyCoeff
(
1
);
}
}
specialCal
.
setReferenceId
(
capacityDef
.
getReferenceId
());
specialCal
.
setReferenceId
(
capacityDef
.
getReferenceId
());
...
...
src/main/java/com/aps/service/plan/MachineSchedulerService.java
View file @
34bcb88f
...
@@ -10,14 +10,17 @@ import java.time.DayOfWeek;
...
@@ -10,14 +10,17 @@ import java.time.DayOfWeek;
import
java.time.Duration
;
import
java.time.Duration
;
import
java.time.LocalDate
;
import
java.time.LocalDate
;
import
java.time.LocalDateTime
;
import
java.time.LocalDateTime
;
import
java.time.temporal.ChronoUnit
;
import
java.util.*
;
import
java.util.*
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.locks.ReentrantLock
;
import
java.util.stream.Collectors
;
import
java.util.stream.Collectors
;
public
class
MachineSchedulerService
{
public
class
MachineSchedulerService
{
// 全局缓存(线程安全)
// 全局缓存(线程安全)
private
static
final
ConcurrentHashMap
<
Long
,
MachineTimeline
>
timelineCache
=
new
ConcurrentHashMap
<>();
private
static
final
ConcurrentHashMap
<
Long
,
MachineTimeline
>
timelineCache
=
new
ConcurrentHashMap
<>();
private
final
ReentrantLock
cacheLock
=
new
ReentrantLock
();
private
LocalDateTime
currentTime
;
private
LocalDateTime
currentTime
;
private
List
<
Holiday
>
holidays
;
private
List
<
Holiday
>
holidays
;
...
@@ -34,19 +37,19 @@ public class MachineSchedulerService {
...
@@ -34,19 +37,19 @@ public class MachineSchedulerService {
long
machineId
=
machine
.
getId
();
long
machineId
=
machine
.
getId
();
// 尝试从缓存获取
// 尝试从缓存获取
//
MachineTimeline timeline = timelineCache.get(machineId);
MachineTimeline
timeline
=
timelineCache
.
get
(
machineId
);
//
if (timeline != null) {
if
(
timeline
!=
null
)
{
//
// 检查有效期(4小时刷新)
// 检查有效期(4小时刷新)
// if (Duration.between(timeline.getLastUpdated(), LocalDateTime.now()).toHours() < 4
) {
if
(
Duration
.
between
(
timeline
.
getLastUpdated
(),
LocalDateTime
.
now
()).
toMinutes
()
<
10
)
{
//
return timeline;
return
timeline
;
//
}
}
//
}
}
// 创建新时间线(60天范围)
// 创建新时间线(60天范围)
MachineTimeline
newTimeline
=
generateTimeline
(
machine
);
MachineTimeline
newTimeline
=
generateTimeline
(
machine
);
newTimeline
.
setSegments
(
mergeSegments
(
newTimeline
.
getSegments
()));
newTimeline
.
setSegments
(
mergeSegments
(
newTimeline
.
getSegments
()));
//
timelineCache.put(machineId, newTimeline);
timelineCache
.
put
(
machineId
,
newTimeline
);
return
newTimeline
;
return
newTimeline
;
}
}
...
@@ -54,11 +57,11 @@ public class MachineSchedulerService {
...
@@ -54,11 +57,11 @@ public class MachineSchedulerService {
MachineTimeline
timeline
=
new
MachineTimeline
();
MachineTimeline
timeline
=
new
MachineTimeline
();
timeline
.
setMachineId
(
machine
.
getId
());
timeline
.
setMachineId
(
machine
.
getId
());
timeline
.
setValidFrom
(
currentTime
);
timeline
.
setValidFrom
(
currentTime
);
timeline
.
setValidTo
(
currentTime
.
plusDays
(
6
0
));
timeline
.
setValidTo
(
currentTime
.
plusDays
(
20
0
));
timeline
.
setLastUpdated
(
LocalDateTime
.
now
());
timeline
.
setLastUpdated
(
LocalDateTime
.
now
());
LocalDate
currentDate
=
currentTime
.
toLocalDate
();
LocalDate
currentDate
=
currentTime
.
toLocalDate
();
LocalDate
endDate
=
currentTime
.
plusDays
(
6
0
).
toLocalDate
();
LocalDate
endDate
=
currentTime
.
plusDays
(
20
0
).
toLocalDate
();
List
<
TimeSegment
>
allSegments
=
new
ArrayList
<>();
List
<
TimeSegment
>
allSegments
=
new
ArrayList
<>();
...
@@ -110,23 +113,37 @@ public class MachineSchedulerService {
...
@@ -110,23 +113,37 @@ public class MachineSchedulerService {
}
}
public
List
<
TimeSegment
>
generateTimeSegment
(
Machine
machine
,
LocalDateTime
currentTime
)
{
public
List
<
TimeSegment
>
generateTimeSegment
(
Machine
machine
,
LocalDateTime
currentTime
)
{
cacheLock
.
lock
();
Long
machineId
=
machine
.
getId
();
Long
machineId
=
machine
.
getId
();
MachineTimeline
timeline
=
timelineCache
.
get
(
machineId
);
MachineTimeline
timeline
=
timelineCache
.
get
(
machineId
);
try
{
if
(
timeline
==
null
)
{
timeline
=
new
MachineTimeline
();
timeline
.
setMachineId
(
machine
.
getId
());
timeline
.
setValidFrom
(
currentTime
);
timeline
.
setValidTo
(
currentTime
.
plusDays
(
200
));
timeline
.
setLastUpdated
(
LocalDateTime
.
now
());
timeline
.
setSegments
(
new
ArrayList
<>());
}
else
{
if
(
timeline
.
getValidTo
().
compareTo
(
currentTime
)
>
0
)
{
LocalDateTime
currentTime1
=
currentTime
;
List
<
TimeSegment
>
timeSegments
=
timeline
.
getSegments
().
stream
()
.
filter
(
t
->
t
.
getStart
().
isAfter
(
currentTime1
)||
t
.
getStart
().
isBefore
(
currentTime1
))
.
collect
(
Collectors
.
toList
());
return
ProductionDeepCopyUtil
.
deepCopyList
(
timeSegments
,
TimeSegment
.
class
);
if
(
timeline
==
null
)
{
timeline
=
new
MachineTimeline
();
timeline
.
setMachineId
(
machine
.
getId
());
timeline
.
setValidFrom
(
currentTime
);
timeline
.
setValidTo
(
currentTime
.
plusDays
(
60
));
timeline
.
setLastUpdated
(
LocalDateTime
.
now
());
timeline
.
setSegments
(
new
ArrayList
<>());
}
else
{
}
else
{
timeline
.
setValidTo
(
currentTime
.
plusDays
(
6
0
));
timeline
.
setValidTo
(
currentTime
.
plusDays
(
20
0
));
timeline
.
setLastUpdated
(
LocalDateTime
.
now
());
timeline
.
setLastUpdated
(
LocalDateTime
.
now
());
}
}
}
}
finally
{
cacheLock
.
unlock
();
}
LocalDate
currentDate
=
currentTime
.
toLocalDate
();
LocalDate
currentDate
=
currentTime
.
toLocalDate
();
LocalDate
endDate
=
currentTime
.
plusDays
(
6
0
).
toLocalDate
();
LocalDate
endDate
=
currentTime
.
plusDays
(
20
0
).
toLocalDate
();
List
<
TimeSegment
>
segments
=
new
ArrayList
<>();
List
<
TimeSegment
>
segments
=
new
ArrayList
<>();
...
@@ -173,6 +190,14 @@ public class MachineSchedulerService {
...
@@ -173,6 +190,14 @@ public class MachineSchedulerService {
timeline
.
setSegments
(
mergeSegments
(
timeline
.
getSegments
()));
timeline
.
setSegments
(
mergeSegments
(
timeline
.
getSegments
()));
segments
=
mergeSegments
(
segments
);
segments
=
mergeSegments
(
segments
);
cacheLock
.
lock
();
try
{
timelineCache
.
put
(
machineId
,
timeline
);
}
finally
{
cacheLock
.
unlock
();
}
return
segments
;
return
segments
;
}
}
...
@@ -213,13 +238,14 @@ public class MachineSchedulerService {
...
@@ -213,13 +238,14 @@ public class MachineSchedulerService {
LocalDateTime
shiftEnd
=
shift
.
getEndTime
().
isBefore
(
shift
.
getStartTime
())
?
LocalDateTime
shiftEnd
=
shift
.
getEndTime
().
isBefore
(
shift
.
getStartTime
())
?
date
.
plusDays
(
1
).
atTime
(
shift
.
getEndTime
())
:
date
.
plusDays
(
1
).
atTime
(
shift
.
getEndTime
())
:
date
.
atTime
(
shift
.
getEndTime
());
date
.
atTime
(
shift
.
getEndTime
());
TimeSegment
timeSegment
=
new
TimeSegment
(
segments
.
add
(
new
TimeSegment
(
shiftStart
,
shiftStart
,
shiftEnd
,
shiftEnd
,
shift
.
isTemporaryShift
()
?
SegmentType
.
TEMP
:
SegmentType
.
REGULAR
,
shift
.
isTemporaryShift
()
?
SegmentType
.
TEMP
:
SegmentType
.
REGULAR
,
false
false
));
);
timeSegment
.
setEfficiency
(
shift
.
getEfficiency
());
segments
.
add
(
timeSegment
);
}
}
}
else
{
}
else
{
// 非假期:处理常规班次
// 非假期:处理常规班次
...
@@ -231,24 +257,42 @@ public class MachineSchedulerService {
...
@@ -231,24 +257,42 @@ public class MachineSchedulerService {
&&
containsDay
(
s
.
getDays
(),
date
.
getDayOfWeek
()))
&&
containsDay
(
s
.
getDays
(),
date
.
getDayOfWeek
()))
.
collect
(
Collectors
.
toList
());
.
collect
(
Collectors
.
toList
());
if
(
shifts
==
null
||
shifts
.
size
()==
0
)
{
if
(
shifts
==
null
||
shifts
.
size
()==
0
)
{
LocalDate
sd
=
LocalDate
.
of
(
2000
,
1
,
1
);
shifts
=
machine
.
getShifts
().
stream
()
.
filter
(
s
->
sd
.
compareTo
(
s
.
getStartDate
().
toLocalDate
())==
0
&&
s
.
getDays
()
!=
null
long
days
=
Math
.
abs
(
ChronoUnit
.
DAYS
.
between
(
LocalDate
.
now
(),
date
));
&&
containsDay
(
s
.
getDays
(),
date
.
getDayOfWeek
()))
if
(
days
>
600
)
.
collect
(
Collectors
.
toList
());
{
segments
.
add
(
new
TimeSegment
(
date
.
atTime
(
0
,
0
,
0
),
date
.
atTime
(
23
,
59
,
59
),
SegmentType
.
REGULAR
,
false
));
return
segments
;
}
else
{
LocalDate
sd
=
LocalDate
.
of
(
2000
,
1
,
1
);
shifts
=
machine
.
getShifts
().
stream
()
.
filter
(
s
->
sd
.
compareTo
(
s
.
getStartDate
().
toLocalDate
())
==
0
&&
s
.
getDays
()
!=
null
&&
containsDay
(
s
.
getDays
(),
date
.
getDayOfWeek
()))
.
collect
(
Collectors
.
toList
());
}
}
}
for
(
Shift
shift
:
shifts
)
{
for
(
Shift
shift
:
shifts
)
{
LocalDateTime
shiftStart
=
date
.
atTime
(
shift
.
getStartTime
());
LocalDateTime
shiftStart
=
date
.
atTime
(
shift
.
getStartTime
());
LocalDateTime
shiftEnd
=
shift
.
getEndTime
().
isBefore
(
shift
.
getStartTime
())
?
LocalDateTime
shiftEnd
=
shift
.
getEndTime
().
isBefore
(
shift
.
getStartTime
())
?
date
.
plusDays
(
1
).
atTime
(
shift
.
getEndTime
())
:
date
.
plusDays
(
1
).
atTime
(
shift
.
getEndTime
())
:
date
.
atTime
(
shift
.
getEndTime
());
date
.
atTime
(
shift
.
getEndTime
());
TimeSegment
timeSegment
=
new
TimeSegment
(
segments
.
add
(
new
TimeSegment
(
shiftStart
,
shiftStart
,
shiftEnd
,
shiftEnd
,
shift
.
isTemporaryShift
()
?
SegmentType
.
TEMP
:
SegmentType
.
REGULAR
,
shift
.
isTemporaryShift
()
?
SegmentType
.
TEMP
:
SegmentType
.
REGULAR
,
false
false
));
);
timeSegment
.
setEfficiency
(
shift
.
getEfficiency
());
segments
.
add
(
timeSegment
);
}
}
}
}
...
...
src/main/java/com/aps/service/plan/PlanResultService.java
View file @
34bcb88f
...
@@ -339,13 +339,17 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
...
@@ -339,13 +339,17 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
List
<
GroupResult
>
entryRel
=(
List
<
GroupResult
>)
list
.
get
(
2
);
List
<
GroupResult
>
entryRel
=(
List
<
GroupResult
>)
list
.
get
(
2
);
Set
<
Long
>
machineIds
=(
Set
<
Long
>)
list
.
get
(
3
);
machines
=
machines
.
stream
().
filter
(
t
->
machineIds
.
contains
(
t
.
getId
())).
collect
(
Collectors
.
toList
());
// 5. 执行调度算法
// 5. 执行调度算法
GeneticAlgorithm
scheduler
=
new
GeneticAlgorithm
(
globalParam
,
machines
,
orders
,
Materials
,
machineScheduler
,
entryRel
,
materialRequirementService
);
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
GeneticAlgorithm
scheduler
=
new
GeneticAlgorithm
(
globalParam
,
machines
,
orders
,
Materials
,
machineScheduler
,
entryRel
,
materialRequirementService
);
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
param
.
initAdaptiveParams
(
entrys
.
size
());
param
.
initAdaptiveParams
(
entrys
.
size
());
double
[]
customWeights
=
new
double
[]
{
0.
2
,
0.1
,
0.1
,
0.1
,
0.5
};
// 延迟时间权重提升到0.5
double
[]
customWeights
=
new
double
[]
{
0.
4
,
0.1
,
0.1
,
0.1
,
0.3
};
// 延迟时间权重提升到0.5
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
scheduler
.
Init
(
null
,
false
);
scheduler
.
Init
(
customWeights
,
false
);
Chromosome
chromosome
=
scheduler
.
Run
(
param
,
entrys
);
Chromosome
chromosome
=
scheduler
.
Run
(
param
,
entrys
);
KpiCalculator
kpiCalculator
=
new
KpiCalculator
(
chromosome
);
KpiCalculator
kpiCalculator
=
new
KpiCalculator
(
chromosome
);
...
@@ -648,14 +652,16 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
...
@@ -648,14 +652,16 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
List
<
Entry
>
entrys
=(
List
<
Entry
>)
list
.
get
(
1
);
List
<
Entry
>
entrys
=(
List
<
Entry
>)
list
.
get
(
1
);
List
<
GroupResult
>
entryRel
=(
List
<
GroupResult
>)
list
.
get
(
2
);
List
<
GroupResult
>
entryRel
=(
List
<
GroupResult
>)
list
.
get
(
2
);
Set
<
Long
>
machineIds
=(
Set
<
Long
>)
list
.
get
(
3
);
machines
=
machines
.
stream
().
filter
(
t
->
machineIds
.
contains
(
t
.
getId
())).
collect
(
Collectors
.
toList
());
// 5. 执行调度算法
// 5. 执行调度算法
GeneticAlgorithm
scheduler
=
new
GeneticAlgorithm
(
globalParam
,
machines
,
orders
,
Materials
,
machineScheduler
,
entryRel
,
materialRequirementService
);
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
GeneticAlgorithm
scheduler
=
new
GeneticAlgorithm
(
globalParam
,
machines
,
orders
,
Materials
,
machineScheduler
,
entryRel
,
materialRequirementService
);
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
param
.
initAdaptiveParams
(
entrys
.
size
());
param
.
initAdaptiveParams
(
entrys
.
size
());
// double[] customWeights = new double[] { 0.2, 0.1, 0.1, 0.1, 0.5
}; // 延迟时间权重提升到0.5
double
[]
customWeights
=
new
double
[]
{
0.4
,
0.1
,
0.1
,
0.1
,
0.3
};
// 延迟时间权重提升到0.5
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
scheduler
.
Init
(
null
,
tru
e
);
scheduler
.
Init
(
customWeights
,
fals
e
);
Chromosome
chromosomes
=
scheduler
.
Run
(
param
,
entrys
);
Chromosome
chromosomes
=
scheduler
.
Run
(
param
,
entrys
);
KpiCalculator
kpiCalculator
=
new
KpiCalculator
(
chromosomes
);
KpiCalculator
kpiCalculator
=
new
KpiCalculator
(
chromosomes
);
kpiCalculator
.
calculatekpi
();
kpiCalculator
.
calculatekpi
();
...
@@ -783,14 +789,15 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
...
@@ -783,14 +789,15 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
private
List
<
Machine
>
InitCalendarToAllMachines
(
String
SceneId
,
List
<
ProdEquipment
>
ProdEquipments
,
MachineSchedulerService
machineScheduler
,
boolean
IsUseCalendar
)
{
private
List
<
Machine
>
InitCalendarToAllMachines
(
String
SceneId
,
List
<
ProdEquipment
>
ProdEquipments
,
MachineSchedulerService
machineScheduler
,
boolean
IsUseCalendar
)
{
// 按设备分组
// 按设备分组
FileHelper
.
writeLogFile
(
"初始化设备日历-----------开始-------"
);
FileHelper
.
writeLogFile
(
"初始化设备日历-----------开始-------"
);
ScheduleParams
param
=
InitScheduleParams
();
List
<
Machine
>
machines
=
new
ArrayList
<>();
if
(!
IsUseCalendar
)
{
if
(!
IsUseCalendar
)
{
ScheduleParams
param
=
InitScheduleParams
();
return
_routingDataService
.
InitNoCalendarToAllMachines
(
machineScheduler
,
param
.
getBaseTime
());
machines
=
_routingDataService
.
InitNoCalendarToAllMachines
(
machineScheduler
,
param
.
getBaseTime
());
}
else
{
}
else
{
ScheduleParams
param
=
InitScheduleParams
();
return
_routingDataService
.
InitCalendarToAllMachines
(
machineScheduler
,
param
.
getBaseTime
());
machines
=
_routingDataService
.
InitCalendarToAllMachines
(
machineScheduler
,
param
.
getBaseTime
());
// List<Machine> machines = _routingDataService.InitCalendarToAllMachines(SceneId, ProdEquipments, machineScheduler, IsUseCalendar);
// List<Machine> machines = _routingDataService.InitCalendarToAllMachines(SceneId, ProdEquipments, machineScheduler, IsUseCalendar);
// List<Machine> machines = (List<Machine>) GlobalCacheUtil.get("machines");
// List<Machine> machines = (List<Machine>) GlobalCacheUtil.get("machines");
...
@@ -805,11 +812,12 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
...
@@ -805,11 +812,12 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
// }
// }
// }
// }
//
//
// FileHelper.writeLogFile("初始化设备日历-----------结束-------");
// GlobalCacheUtil.put("machines", machines, 10, TimeUnit.MINUTES);
// return machines;
}
}
FileHelper
.
writeLogFile
(
"初始化设备日历-----------结束-------"
);
redisUtils
.
set
(
"machines"
,
machines
);
GlobalCacheUtil
.
put
(
"machines"
,
machines
,
10
,
TimeUnit
.
MINUTES
);
return
machines
;
}
}
public
List
<
Machine
>
InitCalendarToAllMachines
()
public
List
<
Machine
>
InitCalendarToAllMachines
()
...
...
src/test/java/com/aps/demo/PlanResultServiceTest.java
View file @
34bcb88f
...
@@ -3,8 +3,10 @@ package com.aps.demo;
...
@@ -3,8 +3,10 @@ package com.aps.demo;
import
com.aps.ApsApplication
;
import
com.aps.ApsApplication
;
import
com.aps.common.util.RangeSubtractUtil
;
import
com.aps.common.util.RangeSubtractUtil
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.ObjectiveWeights
;
import
com.aps.entity.Gantt.ProductGanttVO
;
import
com.aps.entity.Gantt.ProductGanttVO
;
import
com.aps.entity.basic.Machine
;
import
com.aps.entity.basic.Machine
;
import
com.aps.service.Algorithm.NSGAIIUtils
;
import
com.aps.service.plan.PlanResultService
;
import
com.aps.service.plan.PlanResultService
;
import
com.aps.service.plan.SceneService
;
import
com.aps.service.plan.SceneService
;
import
org.junit.jupiter.api.Test
;
import
org.junit.jupiter.api.Test
;
...
@@ -30,9 +32,11 @@ public class PlanResultServiceTest {
...
@@ -30,9 +32,11 @@ public class PlanResultServiceTest {
// RangeSubtractUtil.test();
// RangeSubtractUtil.test();
// planResultService.testSceneChromsome("qwerty");
// planResultService.testSceneChromsome("qwerty");
// Chromosome chromosome= planResultService.moveChromosome("qwerty",3);
// Chromosome chromosome= planResultService.moveChromosome("qwerty",3);
planResultService
.
execute2
(
"B7881EF032044B9BA4F6007875510B70"
);
// planResultService.execute2("B7881EF032044B9BA4F6007875510B70");
// planResultService.execute2("BE037838EF074B07B87D7DE763107398");
// NSGAIIUtils nsgaiiUtils=new NSGAIIUtils();
// planResultService.execute2("31EC5BAF7F6B41DFB79AB031D81C53C0");
// nsgaiiUtils.Test();
planResultService
.
execute2
(
"31EC5BAF7F6B41DFB79AB031D81C53C0"
);
// LocalDateTime t= LocalDateTime.of(2025, 11, 15, 6, 51, 11);
// LocalDateTime t= LocalDateTime.of(2025, 11, 15, 6, 51, 11);
// List<Integer> opids=new ArrayList<>();
// List<Integer> opids=new ArrayList<>();
// opids.add(1);
// opids.add(1);
...
...
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