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
d4ace4ca
Commit
d4ace4ca
authored
Dec 30, 2025
by
Tong Li
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
遗传算法-优化
parent
4fb0ebb2
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
251 additions
and
83 deletions
+251
-83
ObjectiveWeights.java
src/main/java/com/aps/entity/Algorithm/ObjectiveWeights.java
+49
-12
GeneticAlgorithm.java
...main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
+28
-7
GeneticDecoder.java
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
+1
-1
GeneticOperations.java
...ain/java/com/aps/service/Algorithm/GeneticOperations.java
+43
-31
MachineCalculator.java
...ain/java/com/aps/service/Algorithm/MachineCalculator.java
+12
-5
NSGAIIUtils.java
src/main/java/com/aps/service/Algorithm/NSGAIIUtils.java
+8
-7
RoutingDataService.java
...in/java/com/aps/service/Algorithm/RoutingDataService.java
+28
-4
ScheduleOperationService.java
...a/com/aps/service/Algorithm/ScheduleOperationService.java
+10
-0
MachineSchedulerService.java
...in/java/com/aps/service/plan/MachineSchedulerService.java
+72
-16
No files found.
src/main/java/com/aps/entity/Algorithm/ObjectiveWeights.java
View file @
d4ace4ca
...
@@ -36,27 +36,64 @@ public class ObjectiveWeights {
...
@@ -36,27 +36,64 @@ public class ObjectiveWeights {
}
}
/**
/**
* 归一化目标值(消除量纲影响)
* 优化版归一化目标值(消除量纲影响,解决WeightedObjective为0的问题)
* @param objectives 待归一化的目标值数组
* @param minValues 各维度目标值的最小值
* @param maxValues 各维度目标值的最大值
* @param isMinimize 各维度是否为最小化目标(true:值越小越优;false:值越大越优)
* @return 归一化后目标值(范围:[0,1],无0值兜底)
*/
*/
public
double
[]
normalizeObjectives
(
double
[]
objectives
,
double
[]
minValues
,
double
[]
maxValues
)
{
public
double
[]
normalizeObjectives
(
double
[]
objectives
,
double
[]
minValues
,
double
[]
maxValues
,
boolean
[]
isMinimize
)
{
if
(
objectives
==
null
||
objectives
.
length
==
0
)
{
return
new
double
[
0
];
}
double
[]
normalized
=
new
double
[
objectives
.
length
];
double
[]
normalized
=
new
double
[
objectives
.
length
];
if
(
minValues
==
null
||
minValues
.
length
==
0
)
// 浮点精度容错(避免因精度误差误判分母为0)
{
final
double
EPS
=
1
e
-
10
;
if
(
minValues
==
null
||
minValues
.
length
==
0
||
maxValues
==
null
||
maxValues
.
length
!=
objectives
.
length
)
{
// 分支1:无min/max时,采用线性归一化(统一范围[0,1],避免趋近0)
for
(
int
i
=
0
;
i
<
objectives
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
objectives
.
length
;
i
++)
{
normalized
[
i
]=
1
/
(
1
+(
double
)
objectives
[
i
]);
double
obj
=
objectives
[
i
];
// 防御:处理负数(目标值应为非负,若为负则兜底为0)
obj
=
Math
.
max
(
0
,
obj
);
// 优化:动态缩放,避免大数值趋近0(可根据业务调整缩放系数)
double
scale
=
Math
.
max
(
1
,
obj
);
// 缩放系数≥1
if
(
isMinimize
!=
null
&&
isMinimize
.
length
>
i
&&
isMinimize
[
i
])
{
// 最小化目标:值越小越优,归一化后值越小越优(范围[0,1])
normalized
[
i
]
=
1.0
/
(
1.0
+
obj
/
scale
);
}
else
{
// 最大化目标:值越大越优,归一化后值越大越优(范围[0,1])
normalized
[
i
]
=
obj
/
(
1.0
+
obj
);
}
// 兜底:避免极端情况归一化值为0(最小设为1e-6)
normalized
[
i
]
=
Math
.
max
(
normalized
[
i
],
1
e
-
6
);
}
}
}
else
{
}
else
{
// 分支2:有min/max时,标准线性归一化(增加浮点容错)
for
(
int
i
=
0
;
i
<
objectives
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
objectives
.
length
;
i
++)
{
if
(
maxValues
[
i
]
-
minValues
[
i
]
==
0
)
double
min
=
minValues
[
i
];
normalized
[
i
]
=
0
;
double
max
=
maxValues
[
i
];
else
double
obj
=
objectives
[
i
];
normalized
[
i
]
=
(
objectives
[
i
]
-
minValues
[
i
])
/
(
maxValues
[
i
]
-
minValues
[
i
]);
// 浮点精度容错:判断分母是否接近0(而非硬相等)
if
(
Math
.
abs
(
max
-
min
)
<
EPS
)
{
// 分母接近0时:归一化值设为1(而非0),保证加权后不为0
normalized
[
i
]
=
1.0
;
}
else
{
// 标准归一化公式
normalized
[
i
]
=
(
obj
-
min
)
/
(
max
-
min
);
// 若为最小化目标,反转归一化值(值越小,归一化后越大)
if
(
isMinimize
!=
null
&&
isMinimize
.
length
>
i
&&
isMinimize
[
i
])
{
normalized
[
i
]
=
1.0
-
normalized
[
i
];
}
}
// 兜底:限制范围[1e-6,1],彻底避免0值
normalized
[
i
]
=
Math
.
max
(
Math
.
min
(
normalized
[
i
],
1.0
),
1
e
-
6
);
}
}
}
}
return
normalized
;
return
normalized
;
}
}
/**
/**
* 计算加权目标值
* 计算加权目标值
*/
*/
...
...
src/main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
View file @
d4ace4ca
...
@@ -77,6 +77,7 @@ public class GeneticAlgorithm {
...
@@ -77,6 +77,7 @@ public class GeneticAlgorithm {
// 预生成全局工序列表(所有初始化方法共享同一顺序)
// 预生成全局工序列表(所有初始化方法共享同一顺序)
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
);
...
@@ -94,13 +95,12 @@ public class GeneticAlgorithm {
...
@@ -94,13 +95,12 @@ public class GeneticAlgorithm {
// 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
()
best
=
fronts
.
get
(
0
).
stream
()
.
sorted
((
c1
,
c2
)
->
Double
.
compare
(
c
2
.
getWeightedObjective
(),
c1
.
getWeightedObjective
()))
.
sorted
((
c1
,
c2
)
->
Double
.
compare
(
c
1
.
getWeightedObjective
(),
c2
.
getWeightedObjective
()))
.
findFirst
()
.
findFirst
()
.
orElse
(
null
);
.
orElse
(
null
);
FileHelper
.
writeLogFile
(
String
.
format
(
"KPI---%f-----初始-----%s----"
,
best
.
getWeightedObjective
(),
best
.
getID
()));
WriteKpi
(
best
);
double
bestFitness
=
best
.
getWeightedObjective
();
double
bestFitness
=
best
.
getWeightedObjective
();
int
Iteration
=
0
;
int
Iteration
=
0
;
// 步骤2:迭代进化
// 步骤2:迭代进化
...
@@ -182,12 +182,13 @@ public class GeneticAlgorithm {
...
@@ -182,12 +182,13 @@ public class GeneticAlgorithm {
fronts
=
_nsgaIIUtils
.
parallelFastNonDominatedSort
(
population
);
fronts
=
_nsgaIIUtils
.
parallelFastNonDominatedSort
(
population
);
WriteKpis
(
fronts
,
String
.
valueOf
(
iter
));
best
=
fronts
.
get
(
0
).
stream
()
best
=
fronts
.
get
(
0
).
stream
()
.
sorted
((
c1
,
c2
)
->
Double
.
compare
(
c
2
.
getWeightedObjective
(),
c1
.
getWeightedObjective
()))
.
sorted
((
c1
,
c2
)
->
Double
.
compare
(
c
1
.
getWeightedObjective
(),
c2
.
getWeightedObjective
()))
.
findFirst
()
.
findFirst
()
.
orElse
(
null
);
.
orElse
(
null
);
FileHelper
.
writeLogFile
(
String
.
format
(
"KPI---%f-----"
+
iter
+
"-----%s----"
,
best
.
getWeightedObjective
(),
best
.
getID
())
);
WriteKpi
(
best
);
if
(
bestFitness
<
best
.
getWeightedObjective
())
if
(
bestFitness
>
best
.
getWeightedObjective
())
{
{
bestFitness
=
best
.
getWeightedObjective
();
bestFitness
=
best
.
getWeightedObjective
();
...
@@ -220,6 +221,26 @@ public class GeneticAlgorithm {
...
@@ -220,6 +221,26 @@ public class GeneticAlgorithm {
return
best
;
return
best
;
}
}
private
void
WriteKpis
(
List
<
List
<
Chromosome
>>
fronts
,
String
index
)
{
for
(
int
i
=
0
;
i
<
fronts
.
size
();
i
++)
{
FileHelper
.
writeLogFile
(
String
.
format
(
"KPI---%s--------%d----"
,
index
,
i
));
for
(
Chromosome
chromosome:
fronts
.
get
(
i
))
{
WriteKpi
(
chromosome
);
}
}
}
private
void
WriteKpi
(
Chromosome
chromosome
)
{
FileHelper
.
writeLogFile
(
String
.
format
(
"KPI---%f--------%s----"
,
chromosome
.
getWeightedObjective
(),
chromosome
.
getID
()));
for
(
double
d:
chromosome
.
getObjectives
())
{
FileHelper
.
writeLogFile
(
String
.
format
(
" KPI---%f-------"
,
d
));
}
}
private
void
Chromosomedecode
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
,
List
<
GlobalOperationInfo
>
globalOpList
,
List
<
Chromosome
>
population
)
private
void
Chromosomedecode
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
,
List
<
GlobalOperationInfo
>
globalOpList
,
List
<
Chromosome
>
population
)
{
{
GeneticDecoder
decoder
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
orderMaterials
);
GeneticDecoder
decoder
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
orderMaterials
);
...
...
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
View file @
d4ace4ca
...
@@ -372,7 +372,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
...
@@ -372,7 +372,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
());
", 前处理: "
+
preTime
+
", 换型: "
+
setupTime
+
", 数量: "
+
operation
.
getQuantity
()
+
", 设备: "
+
machine
.
getId
()
);
// 确定任务的最早开始时间(基于前一道工序的完整结束时间,包含后处理)
// 确定任务的最早开始时间(基于前一道工序的完整结束时间,包含后处理)
...
...
src/main/java/com/aps/service/Algorithm/GeneticOperations.java
View file @
d4ace4ca
...
@@ -33,42 +33,54 @@ public class GeneticOperations {
...
@@ -33,42 +33,54 @@ public class GeneticOperations {
* 锦标赛选择
* 锦标赛选择
*/
*/
public
List
<
Chromosome
>
tournamentSelection
(
List
<
Chromosome
>
population
,
int
tournamentSize
)
{
public
List
<
Chromosome
>
tournamentSelection
(
List
<
Chromosome
>
population
,
int
tournamentSize
)
{
List
<
Chromosome
>
selected
=
new
ArrayList
<>();
int
populationSize
=
population
.
size
();
while
(
selected
.
size
()
<
population
.
size
())
{
List
<
Chromosome
>
selected
=
new
ArrayList
<>(
populationSize
);
// 预初始化容量
// 随机选择k个个体
// 边界值处理:锦标赛规模不能超过种群规模,且至少为1
// List<Chromosome> candidates = population.stream()
int
effectiveTournamentSize
=
Math
.
max
(
1
,
Math
.
min
(
tournamentSize
,
populationSize
));
// .sorted((a, b) -> rnd.nextInt())
// .limit(tournamentSize)
while
(
selected
.
size
()
<
populationSize
)
{
// .collect(Collectors.toList());
// 优化1:不复制整个种群,直接随机抽取有效锦标赛规模的个体,避免大量内存拷贝和shuffle开销
// 步骤1: 创建一个临时列表用于存放候选者
Chromosome
bestCandidate
=
null
;
List
<
Chromosome
>
candidates
=
new
ArrayList
<>(
population
);
int
bestRank
=
Integer
.
MAX_VALUE
;
// 步骤2: 随机打乱候选者列表
double
bestCrowdingDistance
=
-
Double
.
MAX_VALUE
;
Collections
.
shuffle
(
candidates
,
rnd
);
// 步骤3: 截取前 tournamentSize 个元素作为本次锦标赛的参与者
// 优化2:单次循环随机抽取+实时比较,无需创建候选列表、无需排序,O(k)时间复杂度(k为锦标赛规模)
if
(
tournamentSize
<
candidates
.
size
())
{
for
(
int
i
=
0
;
i
<
effectiveTournamentSize
;
i
++)
{
candidates
=
candidates
.
subList
(
0
,
tournamentSize
);
// 随机获取一个种群个体(直接通过索引访问,无需打乱整个列表)
int
randomIndex
=
rnd
.
nextInt
(
populationSize
);
Chromosome
current
=
population
.
get
(
randomIndex
);
// 优化3:手动实现排序逻辑的比较,避免Stream API的额外开销
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
);
}
}
}
}
}
// 深拷贝最优个体并加入选中列表(确保线程安全和种群独立性)
// 步骤4: 从参与者中选择适应度最高的个体
if
(
bestCandidate
!=
null
)
{
// Chromosome best = candidates.stream()
selected
.
add
(
ProductionDeepCopyUtil
.
deepCopy
(
bestCandidate
,
Chromosome
.
class
));
// .max(Comparator.comparingDouble(Chromosome::getFitness))
}
// .orElseThrow(() -> new IllegalStateException("候选列表为空,无法选择最佳个体。"));
// // 复制个体(假设Chromosome有复制方法或通过构造函数复制)
Chromosome
best
=
candidates
.
stream
()
// 第一步:按Rank升序排序(与OrderBy对应)
.
sorted
(
Comparator
.
comparingInt
(
Chromosome:
:
getRank
)
// 第二步:按拥挤距离降序排序(与ThenByDescending对应)
.
thenComparing
(
Comparator
.
comparingDouble
(
Chromosome:
:
getCrowdingDistance
).
reversed
()))
// 取第一个元素(与First()对应)
.
findFirst
()
// 处理空列表情况(避免NoSuchElementException)
.
orElse
(
null
);
selected
.
add
(
ProductionDeepCopyUtil
.
deepCopy
(
best
,
Chromosome
.
class
));
}
}
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
());
...
...
src/main/java/com/aps/service/Algorithm/MachineCalculator.java
View file @
d4ace4ca
...
@@ -197,16 +197,23 @@ public class MachineCalculator {
...
@@ -197,16 +197,23 @@ public class MachineCalculator {
private
TimeSegment
GetCurrentOrNextShift
(
Machine
machine
,
LocalDateTime
time
,
String
prevtime
,
boolean
checkprevtime
)
{
private
TimeSegment
GetCurrentOrNextShift
(
Machine
machine
,
LocalDateTime
time
,
String
prevtime
,
boolean
checkprevtime
)
{
TimeSegment
start
=
null
;
TimeSegment
start
=
null
;
if
(
machine
.
getAvailability
()!=
null
)
{
start
=
machine
.
getAvailability
().
stream
()
.
filter
(
slot
->
!
slot
.
isUsed
()
&&
slot
.
getType
()
!=
SegmentType
.
MAINTENANCE
)
.
filter
(
slot
->
slot
.
getStart
().
isAfter
(
time
)
||
slot
.
getEnd
().
isAfter
(
time
))
.
findFirst
()
.
orElse
(
null
);
}
else
{
machine
.
setAvailability
(
new
ArrayList
<>());
}
// 查找有效班次
// 查找有效班次
start
=
machine
.
getAvailability
().
stream
()
.
filter
(
slot
->
!
slot
.
isUsed
()
&&
slot
.
getType
()
!=
SegmentType
.
MAINTENANCE
)
.
filter
(
slot
->
slot
.
getStart
().
isAfter
(
time
)
||
slot
.
getEnd
().
isAfter
(
time
))
.
findFirst
()
.
orElse
(
null
);
if
(
start
==
null
)
{
if
(
start
==
null
)
{
// 生成新时间段
// 生成新时间段
List
<
TimeSegment
>
timeSegments
=
machineScheduler
.
generateTimeSegment
(
machine
,
time
.
plusDays
(
1
));
List
<
TimeSegment
>
timeSegments
=
machineScheduler
.
generateTimeSegment
(
machine
,
time
.
plusDays
(
1
));
machine
.
getAvailability
().
addAll
(
timeSegments
);
machine
.
getAvailability
().
addAll
(
timeSegments
);
// 更新设备时间线
// 更新设备时间线
...
...
src/main/java/com/aps/service/Algorithm/NSGAIIUtils.java
View file @
d4ace4ca
...
@@ -40,10 +40,11 @@ public class NSGAIIUtils {
...
@@ -40,10 +40,11 @@ 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
();
// 步骤1:预处理 - 计算归一化目标值和加权目标值
preprocessObjectives
(
population
);
if
(
popSize
<=
taskCount
*
10
)
{
// 小规模种群直接串行
if
(
popSize
<=
taskCount
*
10
)
{
// 小规模种群直接串行
// 步骤1:预处理 - 计算归一化目标值和加权目标值
preprocessObjectives
(
population
);
return
fastNonDominatedSort
(
population
);
return
fastNonDominatedSort
(
population
);
}
}
...
@@ -110,6 +111,8 @@ public class NSGAIIUtils {
...
@@ -110,6 +111,8 @@ public class NSGAIIUtils {
return
fronts
;
return
fronts
;
}
}
/**
/**
* 串行快速非支配排序(兼容小规模种群)
* 串行快速非支配排序(兼容小规模种群)
*/
*/
...
@@ -129,7 +132,7 @@ public class NSGAIIUtils {
...
@@ -129,7 +132,7 @@ public class NSGAIIUtils {
for
(
Chromosome
p
:
population
)
{
for
(
Chromosome
p
:
population
)
{
for
(
Chromosome
q
:
population
)
{
for
(
Chromosome
q
:
population
)
{
if
(
p
==
q
)
continue
;
if
(
p
==
q
)
continue
;
// p.getWeightedObjective() < q.getWeightedObjective();
if
(
dominates
(
p
,
q
))
{
if
(
dominates
(
p
,
q
))
{
// p支配q,将q加入p的被支配集合S
// p支配q,将q加入p的被支配集合S
S
.
get
(
p
).
add
(
q
);
S
.
get
(
p
).
add
(
q
);
...
@@ -167,8 +170,6 @@ public class NSGAIIUtils {
...
@@ -167,8 +170,6 @@ public class NSGAIIUtils {
return
fronts
;
return
fronts
;
}
}
/**
/**
* 预处理目标值(归一化+加权)
* 预处理目标值(归一化+加权)
*/
*/
...
@@ -183,10 +184,10 @@ public class NSGAIIUtils {
...
@@ -183,10 +184,10 @@ public class NSGAIIUtils {
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
);
double
[]
normalized
=
objectiveWeights
.
normalizeObjectives
(
chromo
.
getObjectives
(),
minValues
,
maxValues
,
isMinimize
);
if
(
objectiveWeights
.
isPureNSGAIIMode
())
{
if
(
objectiveWeights
.
isPureNSGAIIMode
())
{
chromo
.
setWeightedObjective
(
objectiveWeights
.
calculateObjective
(
normalized
));
chromo
.
setWeightedObjective
(
objectiveWeights
.
calculateObjective
(
normalized
));
}
else
{
}
else
{
...
...
src/main/java/com/aps/service/Algorithm/RoutingDataService.java
View file @
d4ace4ca
...
@@ -534,10 +534,7 @@ public class RoutingDataService {
...
@@ -534,10 +534,7 @@ public class RoutingDataService {
machine
.
setHolidays
(
Holidays1
);
machine
.
setHolidays
(
Holidays1
);
List
<
MaintenanceWindow
>
maintenanceWindows
=
new
ArrayList
<>();
List
<
MaintenanceWindow
>
maintenanceWindows
=
new
ArrayList
<>();
if
(
machine
.
getName
().
contains
(
"铲车"
))
{
int
i
=
1
+
2
;
}
List
<
EquipMaintainTask
>
EquipMaintainTasks1
=
EquipMaintainTasks
.
stream
()
List
<
EquipMaintainTask
>
EquipMaintainTasks1
=
EquipMaintainTasks
.
stream
()
.
filter
(
t
->
t
.
getEquipId
().
equals
(
resource
.
getReferenceId
())
)
.
filter
(
t
->
t
.
getEquipId
().
equals
(
resource
.
getReferenceId
())
)
.
collect
(
Collectors
.
toList
());
.
collect
(
Collectors
.
toList
());
...
@@ -560,9 +557,12 @@ if(machine.getName().contains("铲车"))
...
@@ -560,9 +557,12 @@ if(machine.getName().contains("铲车"))
// 4. 初始化机器时间线
// 4. 初始化机器时间线
for
(
Machine
machine
:
machines
)
{
for
(
Machine
machine
:
machines
)
{
MachineTimeline
timeline
=
machineScheduler
.
getOrCreateTimeline
(
machine
);
MachineTimeline
timeline
=
machineScheduler
.
getOrCreateTimeline
(
machine
);
machine
.
setAvailability
(
timeline
.
getSegments
());
machine
.
setAvailability
(
timeline
.
getSegments
());
}
}
return
machines
;
return
machines
;
...
@@ -579,6 +579,13 @@ if(machine.getName().contains("铲车"))
...
@@ -579,6 +579,13 @@ if(machine.getName().contains("铲车"))
.
list
();
.
list
();
//设备能力
//设备能力
//维修记录
LambdaQueryWrapper
<
EquipMaintainTask
>
EquipMaintainTaskWrapper
=
new
LambdaQueryWrapper
<>();
EquipMaintainTaskWrapper
.
eq
(
EquipMaintainTask:
:
getIsdeleted
,
0
);
EquipMaintainTaskWrapper
.
eq
(
EquipMaintainTask:
:
getStatus
,
0
);
EquipMaintainTaskWrapper
.
ge
(
EquipMaintainTask:
:
getPlanFinishTime
,
baseTime
);
List
<
EquipMaintainTask
>
EquipMaintainTasks
=
_equipMaintainTaskService
.
list
(
EquipMaintainTaskWrapper
);
for
(
PlanResource
resource
:
PlanResources
)
{
for
(
PlanResource
resource
:
PlanResources
)
{
Machine
machine
=
new
Machine
();
Machine
machine
=
new
Machine
();
...
@@ -606,6 +613,23 @@ if(machine.getName().contains("铲车"))
...
@@ -606,6 +613,23 @@ if(machine.getName().contains("铲车"))
shifts1
.
add
(
shift
);
shifts1
.
add
(
shift
);
machine
.
setShifts
(
shifts1
);
machine
.
setShifts
(
shifts1
);
List
<
MaintenanceWindow
>
maintenanceWindows
=
new
ArrayList
<>();
List
<
EquipMaintainTask
>
EquipMaintainTasks1
=
EquipMaintainTasks
.
stream
()
.
filter
(
t
->
t
.
getEquipId
().
equals
(
resource
.
getReferenceId
())
)
.
collect
(
Collectors
.
toList
());
for
(
EquipMaintainTask
equipMaintainTask
:
EquipMaintainTasks1
)
{
MaintenanceWindow
maintenanceWindow
=
new
MaintenanceWindow
();
maintenanceWindow
.
setId
(
equipMaintainTask
.
getId
().
toString
());
maintenanceWindow
.
setStartTime
(
equipMaintainTask
.
getPlanStartTime
());
maintenanceWindow
.
setEndTime
(
equipMaintainTask
.
getPlanFinishTime
());
maintenanceWindow
.
setReason
(
""
);
maintenanceWindows
.
add
(
maintenanceWindow
);
}
machine
.
setMaintenanceWindows
(
maintenanceWindows
);
machines
.
add
(
machine
);
machines
.
add
(
machine
);
}
}
...
...
src/main/java/com/aps/service/Algorithm/ScheduleOperationService.java
View file @
d4ace4ca
...
@@ -158,6 +158,11 @@ Integer newMachineId1=newMachineId.intValue();
...
@@ -158,6 +158,11 @@ Integer newMachineId1=newMachineId.intValue();
maintenanceWindow
.
setId
(
UUID
.
randomUUID
().
toString
());
maintenanceWindow
.
setId
(
UUID
.
randomUUID
().
toString
());
machine
.
getMaintenanceWindows
().
add
(
maintenanceWindow
);
machine
.
getMaintenanceWindows
().
add
(
maintenanceWindow
);
MachineSchedulerService
machineScheduler
=
new
MachineSchedulerService
(
chromosome
.
getBaseTime
());
MachineTimeline
machineTimeline
=
machineScheduler
.
getOrCreateTimeline
(
machine
);
machine
.
setAvailability
(
machineTimeline
.
getSegments
());
}
else
{
}
else
{
throw
new
RuntimeException
(
"未找到设备"
);
throw
new
RuntimeException
(
"未找到设备"
);
...
@@ -207,6 +212,11 @@ Integer newMachineId1=newMachineId.intValue();
...
@@ -207,6 +212,11 @@ Integer newMachineId1=newMachineId.intValue();
.
findFirst
();
.
findFirst
();
machine
.
getMaintenanceWindows
().
remove
(
index
);
machine
.
getMaintenanceWindows
().
remove
(
index
);
MachineSchedulerService
machineScheduler
=
new
MachineSchedulerService
(
chromosome
.
getBaseTime
());
MachineTimeline
machineTimeline
=
machineScheduler
.
getOrCreateTimeline
(
machine
);
machine
.
setAvailability
(
machineTimeline
.
getSegments
());
}
else
{
}
else
{
throw
new
RuntimeException
(
"未找到设备"
);
throw
new
RuntimeException
(
"未找到设备"
);
...
...
src/main/java/com/aps/service/plan/MachineSchedulerService.java
View file @
d4ace4ca
...
@@ -44,7 +44,9 @@ public class MachineSchedulerService {
...
@@ -44,7 +44,9 @@ public class MachineSchedulerService {
// 创建新时间线(60天范围)
// 创建新时间线(60天范围)
MachineTimeline
newTimeline
=
generateTimeline
(
machine
);
MachineTimeline
newTimeline
=
generateTimeline
(
machine
);
// timelineCache.put(machineId, newTimeline);
newTimeline
.
setSegments
(
mergeSegments
(
newTimeline
.
getSegments
()));
// timelineCache.put(machineId, newTimeline);
return
newTimeline
;
return
newTimeline
;
}
}
...
@@ -76,18 +78,31 @@ public class MachineSchedulerService {
...
@@ -76,18 +78,31 @@ public class MachineSchedulerService {
timeline
.
setSegments
(
mergeSegments
(
allSegments
));
timeline
.
setSegments
(
mergeSegments
(
allSegments
));
// 处理维护窗口
// 处理维护窗口
if
(
machine
.
getMaintenanceWindows
()
!=
null
&&
!
timeline
.
getSegments
().
isEmpty
())
{
if
(
machine
.
getMaintenanceWindows
()
!=
null
&&
machine
.
getMaintenanceWindows
().
size
()>
0
&&
!
timeline
.
getSegments
().
isEmpty
())
{
LocalDateTime
maxEnd
=
timeline
.
getSegments
().
stream
()
LocalDateTime
maxEnd
=
timeline
.
getSegments
().
stream
()
.
map
(
TimeSegment:
:
getEnd
)
.
map
(
TimeSegment:
:
getEnd
)
.
max
(
LocalDateTime:
:
compareTo
)
.
max
(
LocalDateTime:
:
compareTo
)
.
orElse
(
LocalDateTime
.
MIN
);
.
orElse
(
LocalDateTime
.
MIN
);
for
(
MaintenanceWindow
maintenanceWindow
:
machine
.
getMaintenanceWindows
())
{
if
(
maintenanceWindow
.
getStartTime
().
isAfter
(
maxEnd
))
{
List
<
MaintenanceWindow
>
MaintenanceWindow
=
mergeMaintenanceWindows
(
machine
.
getMaintenanceWindows
());
for
(
MaintenanceWindow
maintenanceWindow
:
MaintenanceWindow
)
{
if
(
maintenanceWindow
.
getStartTime
().
isAfter
(
maxEnd
)
||
maintenanceWindow
.
getEndTime
().
isBefore
(
currentTime
))
{
continue
;
continue
;
}
}
updateSegmentsForMaintenance
(
timeline
.
getSegments
(),
if
(
maintenanceWindow
.
getStartTime
().
isBefore
(
currentTime
)&&
maintenanceWindow
.
getEndTime
().
isAfter
(
maxEnd
))
maintenanceWindow
.
getStartTime
(),
maintenanceWindow
.
getEndTime
());
{
timeline
.
setSegments
(
new
ArrayList
<>());
currentTime
=
maintenanceWindow
.
getEndTime
();
timeline
=
generateTimeline
(
machine
);
break
;
}
else
{
updateSegmentsForMaintenance
(
timeline
.
getSegments
(),
maintenanceWindow
.
getStartTime
(),
maintenanceWindow
.
getEndTime
());
}
}
}
}
}
...
@@ -128,18 +143,26 @@ public class MachineSchedulerService {
...
@@ -128,18 +143,26 @@ public class MachineSchedulerService {
}
}
// 处理维护窗口
// 处理维护窗口
if
(
machine
.
getMaintenanceWindows
()
!=
null
&&
!
segments
.
isEmpty
())
{
if
(
machine
.
getMaintenanceWindows
()
!=
null
&&
machine
.
getMaintenanceWindows
().
size
()>
0
&&
!
segments
.
isEmpty
())
{
LocalDateTime
maxEnd
=
segments
.
stream
()
LocalDateTime
maxEnd
=
segments
.
stream
()
.
map
(
TimeSegment:
:
getEnd
)
.
map
(
TimeSegment:
:
getEnd
)
.
max
(
LocalDateTime:
:
compareTo
)
.
max
(
LocalDateTime:
:
compareTo
)
.
orElse
(
LocalDateTime
.
MIN
);
.
orElse
(
LocalDateTime
.
MIN
);
for
(
MaintenanceWindow
maintenanceWindow
:
machine
.
getMaintenanceWindows
())
{
List
<
MaintenanceWindow
>
MaintenanceWindow
=
mergeMaintenanceWindows
(
machine
.
getMaintenanceWindows
());
for
(
MaintenanceWindow
maintenanceWindow
:
MaintenanceWindow
)
{
if
(
maintenanceWindow
.
getStartTime
().
isAfter
(
maxEnd
)
||
if
(
maintenanceWindow
.
getStartTime
().
isAfter
(
maxEnd
)
||
maintenanceWindow
.
get
Start
Time
().
isBefore
(
currentTime
))
{
maintenanceWindow
.
get
End
Time
().
isBefore
(
currentTime
))
{
continue
;
continue
;
}
}
updateSegmentsForMaintenance
(
segments
,
maintenanceWindow
.
getStartTime
(),
maintenanceWindow
.
getEndTime
());
if
(
maintenanceWindow
.
getStartTime
().
isBefore
(
currentTime
)&&
maintenanceWindow
.
getEndTime
().
isAfter
(
maxEnd
))
{
currentTime
=
maintenanceWindow
.
getEndTime
();
segments
=
generateTimeSegment
(
machine
,
currentTime
);
break
;
}
else
{
updateSegmentsForMaintenance
(
segments
,
maintenanceWindow
.
getStartTime
(),
maintenanceWindow
.
getEndTime
());
}
}
}
}
}
...
@@ -302,6 +325,39 @@ if(shifts==null||shifts.size()==0) {
...
@@ -302,6 +325,39 @@ if(shifts==null||shifts.size()==0) {
return
result
;
return
result
;
}
}
private
List
<
MaintenanceWindow
>
mergeMaintenanceWindows
(
List
<
MaintenanceWindow
>
segments1
)
{
List
<
MaintenanceWindow
>
segments
=
ProductionDeepCopyUtil
.
deepCopyList
(
segments1
,
MaintenanceWindow
.
class
);
if
(
segments
==
null
||
segments
.
size
()==
0
)
{
return
null
;
}
// 按开始时间排序
segments
.
sort
(
Comparator
.
comparing
(
MaintenanceWindow:
:
getStartTime
));
Stack
<
MaintenanceWindow
>
merged
=
new
Stack
<>();
for
(
MaintenanceWindow
seg
:
segments
)
{
if
(!
merged
.
isEmpty
()
&&
!
merged
.
peek
().
getEndTime
().
isBefore
(
seg
.
getStartTime
()))
{
MaintenanceWindow
top
=
merged
.
peek
();
if
(
top
.
getEndTime
().
isBefore
(
seg
.
getEndTime
()))
{
top
.
setEndTime
(
seg
.
getEndTime
());
}
}
else
{
merged
.
push
(
seg
);
}
}
List
<
MaintenanceWindow
>
result
=
new
ArrayList
<>(
merged
);
// 按开始时间排序
result
.
sort
(
Comparator
.
comparing
(
MaintenanceWindow:
:
getStartTime
));
return
result
;
}
private
void
updateSegmentsForMaintenance
(
List
<
TimeSegment
>
segments
,
LocalDateTime
maintenanceStart
,
LocalDateTime
maintenanceEnd
)
{
private
void
updateSegmentsForMaintenance
(
List
<
TimeSegment
>
segments
,
LocalDateTime
maintenanceStart
,
LocalDateTime
maintenanceEnd
)
{
if
(
segments
.
isEmpty
())
return
;
if
(
segments
.
isEmpty
())
return
;
...
@@ -356,12 +412,12 @@ if(shifts==null||shifts.size()==0) {
...
@@ -356,12 +412,12 @@ if(shifts==null||shifts.size()==0) {
}
}
}
}
segments
.
add
(
new
TimeSegment
(
//
segments.add(new TimeSegment(
maintenanceStart
,
//
maintenanceStart,
maintenanceEnd
,
//
maintenanceEnd,
SegmentType
.
MAINTENANCE
,
//
SegmentType.MAINTENANCE,
false
//
false
));
//
));
}
}
private
int
binarySearchSegment
(
List
<
TimeSegment
>
segments
,
LocalDateTime
maintenanceStart
)
{
private
int
binarySearchSegment
(
List
<
TimeSegment
>
segments
,
LocalDateTime
maintenanceStart
)
{
...
...
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