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
dce9abd3
Commit
dce9abd3
authored
Jan 07, 2026
by
DESKTOP-VKRD9QF\Administration
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
http://39.100.78.207:1213/tongli/hyh.apsj
parents
929bfe94
beead0fd
Show whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
1002 additions
and
315 deletions
+1002
-315
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
DiscreteParameterDurationTest.java
...test/java/com/aps/demo/DiscreteParameterDurationTest.java
+1
-1
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 @
dce9abd3
...
@@ -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 @
dce9abd3
...
@@ -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 @
dce9abd3
...
@@ -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 @
dce9abd3
...
@@ -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 @
dce9abd3
...
@@ -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 @
dce9abd3
...
@@ -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 @
dce9abd3
...
@@ -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 @
dce9abd3
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 @
dce9abd3
...
@@ -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 @
dce9abd3
...
@@ -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. 机器负载均衡
...
@@ -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:
:
get
End
Time
)
.
mapToInt
(
GAScheduleResult:
:
get
Flow
Time
)
.
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 @
dce9abd3
...
@@ -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,25 +218,33 @@ public class GeneticOperations {
...
@@ -239,25 +218,33 @@ public class GeneticOperations {
* 变异操作
* 变异操作
*/
*/
public
void
mutate
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
,
double
baseMutationProb
)
{
public
void
mutate
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
,
double
baseMutationProb
)
{
int
i
=
rnd
.
nextInt
(
2
);
if
(
i
==
0
)
{
// 1. 机器选择部分变异
// 1. 机器选择部分变异
mutateMachineSelection
(
chromosome
,
globalOpList
,
baseMutationProb
);
boolean
state
=
mutateMachineSelection
(
chromosome
,
globalOpList
,
baseMutationProb
);
if
(!
state
)
{
i
=
1
;
}
}
if
(
i
==
1
)
{
// 2. 工序排序部分变异
// 2. 工序排序部分变异
mutateOperationSequencing
(
chromosome
);
mutateOperationSequencing
(
chromosome
);
}
}
}
// 重载,使用默认变异概率
// 重载,使用默认变异概率
public
void
mutate
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
public
void
mutate
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
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 @
dce9abd3
...
@@ -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 @
dce9abd3
...
@@ -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 @
dce9abd3
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 @
dce9abd3
...
@@ -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,16 +49,14 @@ public class NSGAIIUtils {
...
@@ -40,16 +49,14 @@ 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:预处理 - 计算归一化目标值和加权目标值
// 步骤1:预处理 - 计算归一化目标值和加权目标值
preprocessObjectives
(
population
);
preprocessObjectives
(
population
);
return
fastNonDominatedSort
(
population
);
if
(
popSize
<=
taskCount
*
10
)
{
// 小规模种群直接串行
}
fronts
=
fastNonDominatedSort
(
population
);
}
else
{
// 步骤1:预处理 - 计算归一化目标值和加权目标值
preprocessObjectives
(
population
);
// 步骤2:拆分种群为多个块,并行计算支配关系
// 步骤2:拆分种群为多个块,并行计算支配关系
List
<
List
<
Chromosome
>>
chunks
=
splitPopulation
(
population
,
taskCount
);
List
<
List
<
Chromosome
>>
chunks
=
splitPopulation
(
population
,
taskCount
);
...
@@ -78,12 +85,12 @@ public class NSGAIIUtils {
...
@@ -78,12 +85,12 @@ public class NSGAIIUtils {
});
});
// 步骤3:生成前沿
// 步骤3:生成前沿
List
<
List
<
Chromosome
>>
fronts
=
new
ArrayList
<>();
List
<
Chromosome
>
front1
=
new
ArrayList
<>();
List
<
Chromosome
>
front1
=
new
ArrayList
<>();
for
(
Chromosome
p
:
population
)
{
for
(
Chromosome
p
:
population
)
{
if
(
dominatedCount
.
get
(
p
).
get
()
==
0
)
{
if
(
dominatedCount
.
get
(
p
).
get
()
==
0
)
{
p
.
setRank
(
1
);
front1
.
add
(
p
);
front1
.
add
(
p
);
}
}
}
}
...
@@ -97,7 +104,7 @@ public class NSGAIIUtils {
...
@@ -97,7 +104,7 @@ public class NSGAIIUtils {
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
);
}
}
}
}
...
@@ -107,10 +114,36 @@ public class NSGAIIUtils {
...
@@ -107,10 +114,36 @@ public class NSGAIIUtils {
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,42 +257,55 @@ public class NSGAIIUtils {
...
@@ -212,42 +257,55 @@ 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
;
}
}
}
}
...
@@ -257,39 +315,67 @@ public class NSGAIIUtils {
...
@@ -257,39 +315,67 @@ public class NSGAIIUtils {
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));
// 计算每个目标的最大/最小值
double
[]
idealPoint
=
new
double
[
kpisize
];
for
(
int
i
=
0
;
i
<
kpisize
;
i
++)
{
final
int
idx
=
i
;
if
(
isMinimize
[
i
])
{
idealPoint
[
i
]
=
front
.
stream
().
mapToDouble
(
c
->
c
.
getObjectives
()[
idx
]).
min
().
orElse
(
0
);
}
else
{
idealPoint
[
i
]
=
front
.
stream
().
mapToDouble
(
c
->
c
.
getObjectives
()[
idx
]).
max
().
orElse
(
0
);
}
}
if
(
popSize
>
taskCount
*
10
)
{
// 对每个目标维度并行计算距离
// 对每个目标维度并行计算距离
IntStream
.
range
(
0
,
objCount
).
parallel
().
forEach
(
m
->
{
IntStream
.
range
(
0
,
popSize
).
parallel
().
forEach
(
m
->
{
// 按当前目标排序
// 按当前目标排序
List
<
Chromosome
>
sorted
=
front
.
stream
()
Chromosome
chromo
=
front
.
get
(
m
);
.
sorted
(
Comparator
.
comparingDouble
(
c
->
c
.
getObjectives
()[
m
]))
double
[]
idealPoint1
=
idealPoint
;
.
collect
(
Collectors
.
toList
());
double
[]
objectives
=
chromo
.
getObjectives
();
double
distance
=
calculateEuclideanDistance
(
objectives
,
idealPoint1
);
// 边界个体距离设为无穷大
chromo
.
setCrowdingDistance
(
distance
);
sorted
.
get
(
0
).
setCrowdingDistance
(
Double
.
POSITIVE_INFINITY
);
});
sorted
.
get
(
popSize
-
1
).
setCrowdingDistance
(
Double
.
POSITIVE_INFINITY
);
}
else
{
front
.
forEach
(
chromo
->
{
double
maxObj
=
sorted
.
get
(
popSize
-
1
).
getObjectives
()[
m
];
double
minObj
=
sorted
.
get
(
0
).
getObjectives
()[
m
];
if
(
maxObj
-
minObj
==
0
)
return
;
double
[]
idealPoint1
=
idealPoint
;
double
[]
objectives
=
chromo
.
getObjectives
();
double
distance
=
calculateEuclideanDistance
(
objectives
,
idealPoint1
);
// 计算中间个体的拥挤距离
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
);
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 @
dce9abd3
...
@@ -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 @
dce9abd3
...
@@ -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 @
dce9abd3
...
@@ -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
)
{
if
(
timeline
==
null
)
{
timeline
=
new
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
());
timeline
.
setSegments
(
new
ArrayList
<>());
timeline
.
setSegments
(
new
ArrayList
<>());
}
else
{
}
else
{
timeline
.
setValidTo
(
currentTime
.
plusDays
(
60
));
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
);
}
else
{
timeline
.
setValidTo
(
currentTime
.
plusDays
(
200
));
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
);
long
days
=
Math
.
abs
(
ChronoUnit
.
DAYS
.
between
(
LocalDate
.
now
(),
date
));
if
(
days
>
600
)
{
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
()
shifts
=
machine
.
getShifts
().
stream
()
.
filter
(
s
->
sd
.
compareTo
(
s
.
getStartDate
().
toLocalDate
())==
0
&&
s
.
getDays
()
!=
null
.
filter
(
s
->
sd
.
compareTo
(
s
.
getStartDate
().
toLocalDate
())
==
0
&&
s
.
getDays
()
!=
null
&&
containsDay
(
s
.
getDays
(),
date
.
getDayOfWeek
()))
&&
containsDay
(
s
.
getDays
(),
date
.
getDayOfWeek
()))
.
collect
(
Collectors
.
toList
());
.
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 @
dce9abd3
...
@@ -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
(
"初始化设备日历-----------开始-------"
);
if
(!
IsUseCalendar
)
{
ScheduleParams
param
=
InitScheduleParams
();
ScheduleParams
param
=
InitScheduleParams
();
List
<
Machine
>
machines
=
new
ArrayList
<>();
if
(!
IsUseCalendar
)
{
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,12 +812,13 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
...
@@ -805,12 +812,13 @@ 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/DiscreteParameterDurationTest.java
View file @
dce9abd3
...
@@ -295,7 +295,7 @@ public class DiscreteParameterDurationTest {
...
@@ -295,7 +295,7 @@ public class DiscreteParameterDurationTest {
task
.
setStartTime
(
startTime
);
task
.
setStartTime
(
startTime
);
task
.
setEndTime
(
endTime
);
task
.
setEndTime
(
endTime
);
task
.
setMachineId
(
machineId
);
task
.
setMachineId
(
machineId
);
task
.
setChangeoverTime
(
0
);
//
task.setChangeoverTime(0);
// 注意:GAScheduleResult的quantity字段也需要是Double类型
// 注意:GAScheduleResult的quantity字段也需要是Double类型
// 如果GAScheduleResult的quantity是BigDecimal,需要转换
// 如果GAScheduleResult的quantity是BigDecimal,需要转换
// task.setQuantity(new BigDecimal(quantity.toString()));
// task.setQuantity(new BigDecimal(quantity.toString()));
...
...
src/test/java/com/aps/demo/PlanResultServiceTest.java
View file @
dce9abd3
...
@@ -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