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
eb9004a2
Commit
eb9004a2
authored
Jan 20, 2026
by
Tong Li
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
换型,拖动
parent
18420541
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
742 additions
and
141 deletions
+742
-141
Entry.java
src/main/java/com/aps/entity/basic/Entry.java
+3
-1
GlobalParam.java
src/main/java/com/aps/entity/basic/GlobalParam.java
+5
-1
GeneticAlgorithm.java
...main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
+13
-12
GeneticDecoder.java
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
+172
-79
GeneticOperations.java
...ain/java/com/aps/service/Algorithm/GeneticOperations.java
+1
-1
MachineCalculator.java
...ain/java/com/aps/service/Algorithm/MachineCalculator.java
+325
-28
NSGAIIUtils.java
src/main/java/com/aps/service/Algorithm/NSGAIIUtils.java
+4
-0
RoutingDataService.java
...in/java/com/aps/service/Algorithm/RoutingDataService.java
+4
-0
ScheduleOperationService.java
...a/com/aps/service/Algorithm/ScheduleOperationService.java
+191
-14
PlanResultService.java
src/main/java/com/aps/service/plan/PlanResultService.java
+19
-2
PlanResultServiceTest.java
src/test/java/com/aps/demo/PlanResultServiceTest.java
+5
-3
No files found.
src/main/java/com/aps/entity/basic/Entry.java
View file @
eb9004a2
...
...
@@ -142,7 +142,9 @@ public class Entry {
private
BigDecimal
runtime
;
//持续时间
private
BigDecimal
singleOut
;
//单件产出
private
double
changeLineTime
;
//换模时间
private
BigDecimal
setupTime
;
private
BigDecimal
setupTime
;
//准备时间
private
int
teardownTime
;
// 收尾时间(后处理时间)
//常数时间
private
int
constTime
;
private
String
equipCode
;
//设备编码
private
String
equipName
;
//设备编码
...
...
src/main/java/com/aps/entity/basic/GlobalParam.java
View file @
eb9004a2
...
...
@@ -38,5 +38,9 @@ public class GlobalParam {
/// </summary>
private
boolean
IsOverlap
=
false
;
private
boolean
_smoothSetup
=
false
;
// 默认true,不占用设备时长
private
boolean
_smoothSetup
=
false
;
// 设置时间平滑 工序的前处理是否提前
private
boolean
_smoothChangeOver
=
true
;
// 默认true,设置时间 是否考虑换型时间
private
boolean
_smoothChangeOverInWeek
=
true
;
// 默认true,后台任务设置 休息时间是否换型
}
src/main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
View file @
eb9004a2
...
...
@@ -13,10 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import
java.time.LocalDateTime
;
import
java.util.*
;
import
java.util.concurrent.CompletableFuture
;
import
java.util.concurrent.CopyOnWriteArrayList
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.*
;
import
java.util.stream.Collectors
;
/**
...
...
@@ -361,29 +358,33 @@ return population;
FileHelper
.
writeLogFile
(
String
.
format
(
" KPI---%f-------"
,
d
));
}
}
private
ExecutorService
decodeExecutor
=
Executors
.
newFixedThreadPool
(
Runtime
.
getRuntime
().
availableProcessors
()
*
2
);
//private ExecutorService decodeExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
private
final
ExecutorService
decodeExecutor
=
new
ThreadPoolExecutor
(
Runtime
.
getRuntime
().
availableProcessors
()
-
1
,
// 核心线程数=CPU-1,无切换开销
Runtime
.
getRuntime
().
availableProcessors
()
-
1
,
// 最大线程数=核心数
0L
,
TimeUnit
.
MILLISECONDS
,
new
ArrayBlockingQueue
<>(
200
),
// 有界队列,避免内存溢出
new
ThreadPoolExecutor
.
CallerRunsPolicy
()
// 任务满了主线程执行,不丢失任务
);
private
void
Chromosomedecode
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
,
List
<
GlobalOperationInfo
>
globalOpList
,
List
<
Chromosome
>
population
)
{
FileHelper
.
writeLogFile
(
"解码---------------"
+
population
.
size
()
);
GeneticDecoder
decoder
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
orderMaterials
);
boolean
ismore
=
true
;
if
(
ismore
)
{
CompletableFuture
.
allOf
(
population
.
stream
()
.
map
(
chromosome
->
CompletableFuture
.
runAsync
(()
->
decode
(
decoder
,
chromosome
,
param
,
allOperations
,
globalOpList
),
decodeExecutor
))
.
toArray
(
CompletableFuture
[]::
new
))
.
join
();
if
(
1
==
2
)
{
}
else
{
if
(
population
!=
null
&&
population
.
size
()
>
0
)
{
population
.
parallelStream
().
forEach
(
chromosome
->
{
decode
(
decoder
,
chromosome
,
param
,
allOperations
,
globalOpList
);
});
}
}
...
...
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
View file @
eb9004a2
...
...
@@ -329,7 +329,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
.
orElse
(
null
);
int
prevtime
=
0
;
//后处理时间
int
teardownTime
=
currentOp
.
getTeardownTime
();
if
(!
currentOp
.
getPrevEntryIds
().
isEmpty
())
{
// 处理多个前工序
prevtime
=
CalPrevtime
(
prevtime
,
currentOp
,
chromosome
,
processTime
,
targetMachine
);
...
...
@@ -363,9 +364,16 @@ if(finishedOrder==null||finishedOrder.size()==0)
private
int
processWithSingleMachine
(
Entry
operation
,
Machine
machine
,
double
processingTime
,
int
prevOperationEndTime
,
Chromosome
chromosome
)
{
int
processingTimeTotal
=(
int
)(
processingTime
*
operation
.
getQuantity
());
int
prevOperationEndTime
,
Chromosome
chromosome
)
{
int
processingTimeTotal
=
0
;
int
earliestStartTime
=
prevOperationEndTime
;
if
(
operation
.
getConstTime
()==
1
)
//常数时间
{
processingTimeTotal
=(
int
)
Math
.
ceil
(
processingTime
);
}
else
{
processingTimeTotal
=(
int
)
Math
.
ceil
(
processingTime
*
operation
.
getQuantity
());
}
if
(
machine
==
null
||
operation
.
getMachineOptions
()==
null
)
{
...
...
@@ -380,21 +388,75 @@ if(finishedOrder==null||finishedOrder.size()==0)
operation
.
setEquipCode
(
machine
.
getCode
());
operation
.
setEquipName
(
machine
.
getName
());
int
teardownTime
=
machineOption
.
getTeardownTime
();
if
(
setTime
>
0
)
{
processingTimeTotal
+=
setTime
;
//加上准备工时
}
//后处理时间
int
teardownTime
=
operation
.
getTeardownTime
();
//前处理时间
int
preTime
=
machineOption
.
getPreTime
();
//设置时间平滑 是 不考虑设置时间
//前处理,是否可以在相同任务前序未完工就开始设置时间,
// 就是 最早开工时间是否+前处理时间,总的加工工时不考虑前处理
if
(!
_globalParam
.
is_smoothSetup
())
{
// 工序的前处理不能提前,则要在前处理完成后才能开工,所以要在前一工序的结束时间基础上+前处理
earliestStartTime
+=
preTime
;
}
int
setupTime
=
0
;
CopyOnWriteArrayList
<
GAScheduleResult
>
machineTasks
=
chromosome
.
getResult
().
stream
()
.
filter
(
t
->
t
.
getMachineId
()
==
machine
.
getId
())
.
sorted
(
Comparator
.
comparingInt
(
GAScheduleResult:
:
getStartTime
))
.
collect
(
Collectors
.
toCollection
(
CopyOnWriteArrayList:
:
new
));
// _globalParam.set_smoothChangeOver(false);
CopyOnWriteArrayList
<
ScheduleResultDetail
>
geneDetails
=
new
CopyOnWriteArrayList
<>();
if
(
_globalParam
.
is_smoothChangeOver
())
{
//是否考虑换型时间
Map
<
Integer
,
Object
>
reslte
=
calculateSetupTime
(
machineTasks
,
operation
,
machine
,
earliestStartTime
,
processingTimeTotal
,
_globalParam
.
is_smoothChangeOverInWeek
(),
""
,
null
);
setupTime
=(
int
)
reslte
.
get
(
1
);
//换型时间
int
setupStartTime
=(
int
)
reslte
.
get
(
2
);
//换型开始时间
//earliestStartTime=(int)reslte.get(3);//上个任务的结束时间
earliestStartTime
=(
int
)
reslte
.
get
(
4
);
//最早开工时间
processingTimeTotal
=(
int
)
reslte
.
get
(
5
);
//processingTimeTotal
if
(
setupTime
==
0
)
{
geneDetails
=
machineCalculator
.
getNextAvailableTime
(
machine
,
earliestStartTime
,
-
1
,
processingTimeTotal
,
chromosome
.
getResult
(),
operation
.
IsInterrupt
!=
1
,
true
,
processingTime
,
operation
.
getQuantity
(),
true
);
}
else
{
CopyOnWriteArrayList
<
TimeSegment
>
AvailableTimeSegment
=
(
CopyOnWriteArrayList
<
TimeSegment
>)
reslte
.
get
(
6
);
int
setupTime
=
calculateSetupTime
(
chromosome
.
getResult
(),
operation
,
machine
,
machineOption
);
GAScheduleResult
existingResult
=
chromosome
.
getResultOld
().
stream
().
filter
(
r
->
r
.
getOperationId
()
==
operation
.
getId
()).
findFirst
().
orElse
(
null
);
if
(
existingResult
!=
null
)
{
earliestStartTime
=
Math
.
max
(
earliestStartTime
,
existingResult
.
getDesignatedStartTime
());
}
//准备工时
int
setTime
=
operation
.
getSetupTime
().
intValue
();
Map
<
Integer
,
Object
>
result
=
machineCalculator
.
CreateScheduleResult
(
machine
,
processingTimeTotal
,
earliestStartTime
,
AvailableTimeSegment
,
processingTime
,
operation
.
getQuantity
(),
operation
.
IsInterrupt
!=
1
,
setupTime
,
_globalParam
.
is_smoothChangeOverInWeek
(),
setupStartTime
);
geneDetails
=
machineCalculator
.
getNextAvailableTime
(
machine
,
earliestStartTime
,
-
1
,
processingTimeTotal
,
chromosome
.
getResult
(),
operation
.
IsInterrupt
!=
1
,
true
,
processingTime
,
operation
.
getQuantity
(),
true
);
// FileHelper.writeLogFile(" 开始 "+operation.getGroupId()+" : "+operation.getId()+",处理时间: " + processingTime + ", 后处理: " + teardownTime +
}
setupTime
=(
int
)
result
.
get
(
1
);
operation
.
setChangeLineTime
(
setupTime
);
geneDetails
=(
CopyOnWriteArrayList
<
ScheduleResultDetail
>)
result
.
get
(
2
);
}
}
else
{
// FileHelper.writeLogFile(" 开始 "+operation.getGroupId()+" : "+operation.getId()+",处理时间: " + processingTime + ", 后处理: " + teardownTime +
// ", 前处理: " + preTime + ", 换型: " + setupTime+ ", 数量: " + operation.getQuantity()+ ", 设备: "+machine.getId()+ ", 是否可中断: "+operation.getIsInterrupt());
// 确定任务的最早开始时间(基于前一道工序的完整结束时间,包含后处理)
int
earliestStartTime
=
prevOperationEndTime
;
// System.out.println(" 最终最早开始时间: " + earliestStartTime +
...
...
@@ -402,28 +464,10 @@ if(finishedOrder==null||finishedOrder.size()==0)
// (lastGeneOnMachine != null ? lastGeneOnMachine.getEndTime() : 0) +
// ", 换型: " + setupTime + ")");
// 根据换型模式调整处理时间
// int processingTimeForScheduling;
if
(
_globalParam
.
is_smoothSetup
())
{
// 平滑模式:只需要安排主处理时间
// processingTimeForScheduling = processingTimeTotal;
// System.out.println(" 平滑模式:安排主处理时间 " + processingTime + " 分钟");
}
else
{
// 标准模式:需要安排主处理时间+换型时间
processingTimeTotal
=
processingTimeTotal
+
setupTime
;
// System.out.println(" 标准模式:安排主处理+" + setupTime + "分钟换型=" + processingTimeTotal + "分钟");
}
GAScheduleResult
existingResult
=
chromosome
.
getResultOld
().
stream
().
filter
(
r
->
r
.
getOperationId
()
==
operation
.
getId
()).
findFirst
().
orElse
(
null
);
if
(
existingResult
!=
null
)
{
earliestStartTime
=
Math
.
max
(
earliestStartTime
,
existingResult
.
getDesignatedStartTime
());
}
CopyOnWriteArrayList
<
ScheduleResultDetail
>
geneDetails
=
machineCalculator
.
getNextAvailableTime
(
machine
,
earliestStartTime
,
-
1
,
processingTimeTotal
,
chromosome
.
getResult
(),
operation
.
IsInterrupt
!=
1
,
true
,
processingTime
,
operation
.
getQuantity
(),
true
);
...
...
@@ -436,52 +480,17 @@ if(finishedOrder==null||finishedOrder.size()==0)
.
mapToInt
(
ScheduleResultDetail:
:
getEndTime
)
.
max
()
.
orElse
(
0
);
//换型时间是否占用设备加工时间
//10:00 开始上班 前面的任务:24:00 结束 开始换型 休息时间 10小时
// 换型时间 12小时
// 换型时间 - 中间休息时间 =2小时
//开工时间需往后延 2小时
//设置时间平滑
//前处理,准备工时 是否可以在前序未完工就开始时间, 就是
// 冲突检测和解决
final
int
finalStartTime
=
startTime
;
//10:00 12
final
int
finalEndTime
=
endTime
;
//15:00
// 7:00-9:00 1
//7:00-11:00 2
// 10<9&&15>7 1
// 10<11&&15>7 2 有任务
GAScheduleResult
conflictingGene
=
chromosome
.
getResult
().
stream
()
.
filter
(
g
->
g
.
getMachineId
()
==
machine
.
getId
())
.
filter
(
g
->
(
finalStartTime
<
g
.
getEndTime
()
&&
finalEndTime
>
g
.
getStartTime
()))
.
findFirst
()
.
orElse
(
null
);
if
(
conflictingGene
!=
null
)
{
// System.out.println(" ⚠️ 检测到时间冲突,重新调度");
int
conflictSetupStartTime
=
conflictingGene
.
getEndTime
();
//11:00
int
conflictSetupTime
=
calculateSetupTimeForConflict
(
chromosome
.
getResult
(),
operation
,
machine
,
machineOption
,
conflictingGene
);
int
conflictEarliestStartTime
=
conflictSetupStartTime
+
conflictSetupTime
;
machineCalculator
.
AddMachineAvailable
(
machine
,
geneDetails
);
/// 时间安排
geneDetails
=
machineCalculator
.
getNextAvailableTime
(
machine
,
conflictEarliestStartTime
,
-
1
,
processingTimeTotal
,
chromosome
.
getResult
(),
false
,
true
,
processingTime
,
operation
.
getQuantity
(),
true
);
if
(!
geneDetails
.
isEmpty
())
{
startTime
=
geneDetails
.
stream
()
.
mapToInt
(
ScheduleResultDetail:
:
getStartTime
)
.
min
()
.
orElse
(
0
);
endTime
=
geneDetails
.
stream
()
.
mapToInt
(
ScheduleResultDetail:
:
getEndTime
)
.
max
()
.
orElse
(
0
);
// System.out.println(" 重新安排时间: " + ConvertTime(startTime) + " - " + ConvertTime(endTime));
}
}
// 准备工时 加入到加工时间里
// 后处理时间 相同任务的前一工序的结束时间+后处理时间 =当前工序最早开工时间
GAScheduleResult
result
=
new
GAScheduleResult
();
...
...
@@ -541,7 +550,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
.
filter
(
t
->
t
.
getGroupId
()
==
currentOp
.
GroupId
&&
t
.
getOperationId
()
==
opid
.
getPrevOperationId
())
.
collect
(
Collectors
.
toList
());
//多台
for
(
GAScheduleResult
prevOp
:
prevOperations
)
{
prevtime
=
Math
.
max
(
prevtime
,
prevOp
.
getEndTime
()
+
prevOp
.
getTeardownTime
());
//加上后处理时间
prevtime
=
Math
.
max
(
prevtime
,
prevOp
.
getEndTime
()
+
currentOp
.
getTeardownTime
());
}
}
}
...
...
@@ -560,9 +570,6 @@ if(finishedOrder==null||finishedOrder.size()==0)
for
(
GAScheduleResult
prevOp
:
prevOperations
)
{
newScheduleResult
.
add
(
prevOp
);
newScheduleResultDetails
.
addAll
(
prevOp
.
getGeneDetails
());
}
}
...
...
@@ -832,19 +839,71 @@ if(finishedOrder==null||finishedOrder.size()==0)
private
String
ConvertTime
(
int
minute
)
{
return
baseTime
.
plusSeconds
(
minute
).
format
(
java
.
time
.
format
.
DateTimeFormatter
.
ofPattern
(
"YYYY-MM-dd HH:mm"
));
}
private
int
calculateSetupTime
(
List
<
GAScheduleResult
>
existingGenes
,
Entry
operation
,
Machine
machine
,
MachineOption
machineOption
)
{
private
Map
<
Integer
,
Object
>
calculateSetupTime
(
CopyOnWriteArrayList
<
GAScheduleResult
>
machineTasks
,
Entry
operation
,
Machine
machine
,
int
earliestStartTime
,
int
processingTimeTotal
,
boolean
changeOverInWeek
,
String
lastExecId
,
Map
<
Integer
,
Object
>
lastsetupTime
)
{
Map
<
Integer
,
Object
>
reslte
=
new
HashMap
<>();
reslte
.
put
(
1
,
0
);
//换型时间
reslte
.
put
(
2
,
0
);
//换型开始时间
reslte
.
put
(
3
,
0
);
//上个任务的结束时间
reslte
.
put
(
4
,
earliestStartTime
);
//最早开工时间
reslte
.
put
(
5
,
processingTimeTotal
);
//总加工时长
if
(
machineTasks
==
null
||
machineTasks
.
size
()==
0
)
{
return
reslte
;
}
// LocalDateTime startTime = baseTime.plus(earliestStartTime, ChronoUnit.SECONDS);
GAScheduleResult
lastGeneOnMachine
=
machineTasks
.
get
(
machineTasks
.
size
()-
1
);
if
(
lastGeneOnMachine
.
getEndTime
()>
earliestStartTime
)
{
CopyOnWriteArrayList
<
TimeSegment
>
AvailableTimeSegment
=
machineCalculator
.
getMachineAvailableTime
(
machine
,
earliestStartTime
,
processingTimeTotal
,
machineTasks
,
operation
.
IsInterrupt
!=
1
);
if
(
AvailableTimeSegment
!=
null
)
{
reslte
.
put
(
6
,
AvailableTimeSegment
);
int
start
=
(
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
AvailableTimeSegment
.
get
(
0
).
getStart
());
earliestStartTime
=
earliestStartTime
>
start
?
earliestStartTime:
start
;
int
earliestStartTime1
=
earliestStartTime
;
reslte
.
put
(
4
,
earliestStartTime
);
//最早开工时间
CopyOnWriteArrayList
<
GAScheduleResult
>
machineTasks1
=
machineTasks
.
stream
()
.
filter
(
t
->
t
.
getEndTime
()<=
earliestStartTime1
)
.
collect
(
Collectors
.
toCollection
(
CopyOnWriteArrayList:
:
new
));
if
(
machineTasks1
!=
null
&&
machineTasks1
.
size
()>
0
)
{
lastGeneOnMachine
=
machineTasks1
.
get
(
machineTasks1
.
size
()-
1
);
}
else
{
GAScheduleResult
lastGeneOnMachine
=
existingGenes
.
stream
()
.
filter
(
g
->
g
.
getMachineId
()
==
machine
.
getId
())
.
max
(
Comparator
.
comparingInt
(
GAScheduleResult:
:
getEndTime
))
.
orElse
(
null
);
return
reslte
;
}
}
}
else
{
CopyOnWriteArrayList
<
TimeSegment
>
AvailableTimeSegment
=
machineCalculator
.
getMachineAvailableTime
(
machine
,
earliestStartTime
,
processingTimeTotal
,
machineTasks
,
operation
.
IsInterrupt
!=
1
);
if
(
AvailableTimeSegment
!=
null
)
{
reslte
.
put
(
6
,
AvailableTimeSegment
);
int
start
=
(
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
AvailableTimeSegment
.
get
(
0
).
getStart
());
earliestStartTime
=
earliestStartTime
>
start
?
earliestStartTime
:
start
;
if
(
lastGeneOnMachine
==
null
)
{
// System.out.println("设备 " + machine.getId() + " 上无历史任务,换型时间为0");
return
0
;
reslte
.
put
(
4
,
earliestStartTime
);
//最早开工时间
}
}
reslte
.
put
(
3
,
lastGeneOnMachine
.
getEndTime
());
//换型开始时间
String
ExecId
=
lastGeneOnMachine
.
getExecId
();
if
(
lastExecId
.
equals
(
ExecId
))
{
reslte
.
put
(
1
,
lastsetupTime
.
get
(
1
));
//换型时间
if
(
changeOverInWeek
)
{
reslte
.
put
(
2
,
earliestStartTime
-
(
int
)
lastsetupTime
.
get
(
1
)-
1
);
}
return
reslte
;
}
Entry
prev
=
_allOperations
.
stream
().
filter
(
t
->
t
.
getExecId
().
equals
(
lastGeneOnMachine
.
getExecId
()
))
filter
(
t
->
t
.
getExecId
().
equals
(
ExecId
))
.
findFirst
().
orElse
(
null
);
int
setupTime
=
0
;
if
(
prev
!=
null
)
...
...
@@ -869,11 +928,45 @@ if(finishedOrder==null||finishedOrder.size()==0)
}
// setupTime=20*3600;
operation
.
setChangeLineTime
(
setupTime
);
if
(
setupTime
==
0
)
{
return
reslte
;
}
reslte
.
put
(
1
,
setupTime
);
//换型时间
if
(
changeOverInWeek
)
//可以放到休息时间
{
//01 16:00 +20 -01 16:00 02 12:00 08:00 -18:00 01 16:18 02 08:00-12:00
//01 16:00 +10 -01 16:00 换型10:00 08:00
//01 18:00 +10 -02 08:00<0 换型 休息时间满足
//01 18:00 +20 -02 08:00>0
//01 18:00 +10 -02 00:00>0
int
cha
=(
lastGeneOnMachine
.
getEndTime
()+
setupTime
)-
earliestStartTime
;
if
(
cha
>
0
)
{
cha
=
cha
+
1
;
//加1是工序开始加工时间
reslte
.
put
(
2
,
lastGeneOnMachine
.
getEndTime
());
//换型开始时间
reslte
=
calculateSetupTime
(
machineTasks
,
operation
,
machine
,
earliestStartTime
+
cha
,
processingTimeTotal
,
_globalParam
.
is_smoothChangeOverInWeek
(),
ExecId
,
reslte
);
}
else
{
reslte
.
put
(
2
,
earliestStartTime
-
setupTime
);
//换型开始时间
//如果空余时间足够
//可能会往前或后暂用设备时间
return
reslte
;
}
}
else
{
//开始时间加上设置时间重新算
//如果是前提供任务是相同的则跳出
reslte
=
calculateSetupTime
(
machineTasks
,
operation
,
machine
,
earliestStartTime
,
processingTimeTotal
+
setupTime
,
_globalParam
.
is_smoothChangeOverInWeek
(),
ExecId
,
reslte
);
}
// System.out.println("换型时间111"+setupTime);
return
setupTim
e
;
return
reslt
e
;
}
private
int
calculateSetupTimeForConflict
(
List
<
GAScheduleResult
>
existingGenes
,
Entry
operation
,
Machine
machine
,
...
...
src/main/java/com/aps/service/Algorithm/GeneticOperations.java
View file @
eb9004a2
...
...
@@ -37,7 +37,7 @@ public class GeneticOperations {
if
(
population
==
null
||
population
.
isEmpty
())
{
return
new
ArrayList
<>();
}
int
populationSize
=
population
.
size
();
int
populationSize
=
population
.
size
()
>
100
?((
int
)(
population
.
size
()*
0.8
)):
population
.
size
()
;
// 预计算需要选中的个体数量,避免动态判断
int
needSelectCount
=
populationSize
-
Math
.
max
(
1
,
Math
.
min
(
tournamentSize
,
populationSize
));
List
<
Chromosome
>
selected
=
new
ArrayList
<>(
needSelectCount
);
// 预初始化容量
...
...
src/main/java/com/aps/service/Algorithm/MachineCalculator.java
View file @
eb9004a2
...
...
@@ -59,6 +59,194 @@ public class MachineCalculator {
existingTasks
,
oneTime
,
quantity
,
istask
,
islockMachineTime
,
isInterrupt
);
}
public
CopyOnWriteArrayList
<
TimeSegment
>
getMachineAvailableTime
(
Machine
machine
,
int
proposedStartTime
,
int
processingTime
,
CopyOnWriteArrayList
<
GAScheduleResult
>
existingTasks
,
boolean
isInterrupt
)
{
LocalDateTime
startTime
=
baseTime
.
plus
(
proposedStartTime
,
ChronoUnit
.
SECONDS
);
// 查找合适的班次窗口
return
findAvailableSegments
(
machine
,
startTime
,
existingTasks
,
processingTime
,
isInterrupt
);
}
public
Map
<
Integer
,
Object
>
CreateScheduleResult
(
Machine
machine
,
int
processingTime
,
int
proposedStartTime
,
CopyOnWriteArrayList
<
TimeSegment
>
timeSegments
,
double
oneTime
,
double
quantity
,
boolean
isInterrupt
,
int
changeOvertTime
,
boolean
changeOverInWeek
,
int
setupStartTime
)
{
LocalDateTime
startTime
=
baseTime
.
plus
(
proposedStartTime
,
ChronoUnit
.
SECONDS
);
Map
<
Integer
,
Object
>
result
=
new
HashMap
<>(
2
);
CopyOnWriteArrayList
<
ScheduleResultDetail
>
times
=
new
CopyOnWriteArrayList
<>();
int
ChangeOverTimenew
=
0
;
CopyOnWriteArrayList
<
TimeSegment
>
usedSegments
=
new
CopyOnWriteArrayList
<>();
if
(
changeOverInWeek
)
{
// 换型时间完全在休息时间
LocalDateTime
setupStartTime1
=
baseTime
.
plusSeconds
(
setupStartTime
);
ChangeOverTimenew
=
changeOvertTime
;
int
changeOvertTime_end
=
setupStartTime
+
changeOvertTime
;
LocalDateTime
setupendTime1
=
baseTime
.
plusSeconds
(
changeOvertTime_end
);
List
<
TimeSegment
>
setuptime
=
machine
.
getAvailability
()
.
stream
()
.
filter
(
t
->((
t
.
getStart
().
compareTo
(
setupStartTime1
)>=
0
)
&&
t
.
getEnd
().
compareTo
(
setupendTime1
)<=
0
)||((
t
.
getStart
().
compareTo
(
setupStartTime1
)<=
0
)
&&
t
.
getEnd
().
compareTo
(
setupStartTime1
)>
0
))
.
sorted
(
Comparator
.
comparing
(
TimeSegment:
:
getStart
))
.
collect
(
Collectors
.
toList
());
if
(
setuptime
!=
null
&&
setuptime
.
size
()>
0
)
{
TimeSegment
shift1
=
setuptime
.
get
(
0
);
LocalDateTime
shiftStart1
=
shift1
.
getStart
();
//判断换型开始时间是否在工作时间段内,要占用工作时间,分割工作时间
if
(
setupStartTime1
.
compareTo
(
shiftStart1
)>
0
)
{
ScheduleResultDetail
time
=
new
ScheduleResultDetail
();
time
.
setStartTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
setupStartTime1
));
time
.
setEndTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
shift1
.
getEnd
()));
CopyOnWriteArrayList
<
TimeSegment
>
usedSegments1
=
RemoveMachineAvailable
(
machine
,
time
,
shift1
);
if
(
usedSegments1
!=
null
&&
usedSegments1
.
size
()
>
0
)
{
usedSegments
.
addAll
(
usedSegments1
);
}
for
(
int
i
=
1
;
i
<
setuptime
.
size
()
;
i
++)
{
TimeSegment
se
=
setuptime
.
get
(
i
);
se
.
setUsed
(
true
);
}
}
else
{
for
(
TimeSegment
se:
setuptime
)
{
se
.
setUsed
(
true
);
}
}
// int i = 0;
// while (changeOvertTime > 0) {
// TimeSegment shift = setuptime.get(i);
// LocalDateTime shiftStart = shift.getStart();
// LocalDateTime shiftEnd = shift.getEnd();
// long availableSeconds = ChronoUnit.SECONDS.between(shiftStart, shiftEnd);
// int processable = Math.min(changeOvertTime, (int) availableSeconds);
//
// changeOvertTime-=processable;
// if(changeOvertTime>0)
// {
// shift.setUsed(true);
// }else {
// ScheduleResultDetail time =new ScheduleResultDetail();
// time.setStartTime((int) ChronoUnit.SECONDS.between(baseTime, shiftEnd.plusSeconds(-processable)));
// time.setEndTime((int) ChronoUnit.SECONDS.between(baseTime, shiftEnd));
//
// CopyOnWriteArrayList<TimeSegment> usedSegments1= RemoveMachineAvailable(machine, time,shift);
// if (usedSegments1 != null && usedSegments1.size() > 0) {
// usedSegments.addAll(usedSegments1);
// }
// }
// if(i!=setuptime.size()-1)
// {
// TimeSegment shift2 = setuptime.get(i+1);
// LocalDateTime shiftEnd2 = shift2.getEnd();
// long availableSeconds2 = ChronoUnit.SECONDS.between(shiftEnd2, shiftStart);
//
// changeOvertTime-=availableSeconds2;
// }
// i++;
// }
}
if
(
usedSegments
!=
null
&&
usedSegments
.
size
()
>
0
)
{
machine
.
getAvailability
().
addAll
(
usedSegments
);
machine
.
getAvailability
().
sort
(
Comparator
.
comparing
(
TimeSegment:
:
getStart
));
}
times
=
CaldScheduleResult
(
machine
,
processingTime
,
startTime
,
timeSegments
,
oneTime
,
quantity
);
}
else
{
//换型时间在工作时间
int
i
=
0
;
//要先把换型时间占用的工作时间占用
LocalDateTime
ChangeOverstartTime
=
startTime
;
LocalDateTime
ChangeOverendTime
=
startTime
;
int
changeOvertTimeold
=
changeOvertTime
;
while
(
changeOvertTime
>
0
)
{
TimeSegment
shift
=
timeSegments
.
get
(
i
);
LocalDateTime
shiftStart
=
shift
.
getStart
();
LocalDateTime
shiftEnd
=
shift
.
getEnd
();
// 计算有效时间
LocalDateTime
effectiveStart
=
startTime
.
isAfter
(
shiftStart
)
?
startTime
:
shiftStart
;
long
availableSeconds
=
ChronoUnit
.
SECONDS
.
between
(
effectiveStart
,
shiftEnd
);
// 处理当前班次
int
processable
=
Math
.
min
(
changeOvertTime
,
(
int
)
availableSeconds
);
changeOvertTime
-=
processable
;
startTime
=
effectiveStart
.
plusSeconds
(
processable
);
ChangeOverendTime
=
startTime
;
ScheduleResultDetail
time
=
new
ScheduleResultDetail
();
time
.
setStartTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
effectiveStart
));
time
.
setEndTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
startTime
));
CopyOnWriteArrayList
<
TimeSegment
>
usedSegments1
=
RemoveMachineAvailable
(
machine
,
time
,
shift
);
if
(
usedSegments1
!=
null
&&
usedSegments1
.
size
()
>
0
)
{
usedSegments
.
addAll
(
usedSegments1
);
}
if
(
processable
>=
availableSeconds
)
{
i
++;
}
}
ChangeOverTimenew
=(
int
)
ChronoUnit
.
SECONDS
.
between
(
ChangeOverstartTime
,
ChangeOverendTime
);
processingTime
=
processingTime
-
changeOvertTimeold
;
TimeSegment
slot
=
timeSegments
.
get
(
i
);
LocalDateTime
startCandidate
=
slot
.
getStart
().
isAfter
(
startTime
)
?
slot
.
getStart
()
:
startTime
;
LocalDateTime
endCandidate
=
startCandidate
.
plusSeconds
(
processingTime
);
if
(
endCandidate
.
isAfter
(
slot
.
getEnd
()))
{
CopyOnWriteArrayList
<
TimeSegment
>
timeSegments1
=
timeSegments
.
stream
()
.
filter
(
t
->
t
.
getStart
().
compareTo
(
startCandidate
)>=
0
)
.
collect
(
Collectors
.
toCollection
(
CopyOnWriteArrayList:
:
new
));
times
=
CaldScheduleResult
(
machine
,
processingTime
,
startTime
,
timeSegments1
,
oneTime
,
quantity
);
}
else
{
ScheduleResultDetail
time
=
new
ScheduleResultDetail
();
time
.
setKey
(
slot
.
getKey
());
time
.
setStartTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
startCandidate
));
time
.
setEndTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
endCandidate
));
time
.
setOneTime
(
oneTime
);
time
.
setQuantity
(
quantity
);
times
.
add
(
time
);
CopyOnWriteArrayList
<
TimeSegment
>
usedSegments1
=
RemoveMachineAvailable
(
machine
,
time
,
slot
);
if
(
usedSegments1
!=
null
&&
usedSegments1
.
size
()
>
0
)
{
usedSegments
.
addAll
(
usedSegments1
);
}
}
if
(
usedSegments
!=
null
&&
usedSegments
.
size
()
>
0
)
{
machine
.
getAvailability
().
addAll
(
usedSegments
);
machine
.
getAvailability
().
sort
(
Comparator
.
comparing
(
TimeSegment:
:
getStart
));
}
}
result
.
put
(
1
,
ChangeOverTimenew
);
result
.
put
(
2
,
times
);
return
result
;
}
// 查找最早可用开始时间
...
...
@@ -80,6 +268,10 @@ public class MachineCalculator {
LocalDateTime
startCandidate
=
slot
.
getStart
().
isAfter
(
prevTimeDateTime
!=
null
?
prevTimeDateTime
:
currentTime
)
?
slot
.
getStart
()
:
(
prevTimeDateTime
!=
null
?
prevTimeDateTime
:
currentTime
);
if
(
slot
.
getStart
().
isBefore
(
startCandidate
))
{
int
i
=
0
;
}
LocalDateTime
endCandidate
=
startCandidate
.
plusSeconds
(
processingTime
);
if
(
endCandidate
.
isAfter
(
slot
.
getEnd
()))
{
...
...
@@ -92,8 +284,11 @@ public class MachineCalculator {
time
.
setOneTime
(
oneTime
);
time
.
setQuantity
(
quantity
);
times
.
add
(
time
);
if
(
islockMachineTime
)
{
RemoveMachineAvailable
(
machine
,
time
,
slot
);
CopyOnWriteArrayList
<
TimeSegment
>
usedSegments
=
RemoveMachineAvailable
(
machine
,
time
,
slot
);
if
(
usedSegments
!=
null
&&
usedSegments
.
size
()
>
0
)
{
machine
.
getAvailability
().
addAll
(
usedSegments
);
machine
.
getAvailability
().
sort
(
Comparator
.
comparing
(
TimeSegment:
:
getStart
));
}
return
times
;
}
...
...
@@ -183,28 +378,89 @@ public class MachineCalculator {
CopyOnWriteArrayList
<
ScheduleResultDetail
>
times
=
new
CopyOnWriteArrayList
<>();
CopyOnWriteArrayList
<
TimeSegment
>
timeSegments
=
findAvailableSegments
(
machine
,
currentTime
,
machineTasks
,
remainingTime
,
isInterrupt
);
times
=
CaldScheduleResult
(
machine
,
processingTime
,
currentTime
,
timeSegments
,
oneTime
,
quantity
);
// int estimateIndex= (int) Math.ceil(remainingTime / (double) ONE_DAY_MINUTES);
// CopyOnWriteArrayList<TimeSegment> timeSegments1=null;
// if(estimateIndex>10)
// {
// timeSegments1= getEnoughSegmentsByEstimateIndex(timeSegments,currentTime,remainingTime);
// }
//
// if(timeSegments1==null) {
// int i = 0;
// CopyOnWriteArrayList<TimeSegment> usedSegments =new CopyOnWriteArrayList<>();
// while (remainingTime > 0) {
// TimeSegment shift = timeSegments.get(i);
//
// Map<Integer, Object> outMap = CreateScheduleResultDetail(shift, st, remainingTime, oneTime);
// remainingTime = (int) outMap.get(1);
// ScheduleResultDetail time = (ScheduleResultDetail) outMap.get(2);
// times.add(time);
// // 还原未使用的时间段
// CopyOnWriteArrayList<TimeSegment> usedSegments1= RemoveMachineAvailable(machine, time,shift);
// if(usedSegments1!=null&&usedSegments1.size()>0)
// {
// usedSegments.addAll(usedSegments1);
// }
// i++;
// }
//
// if (usedSegments != null && usedSegments.size() > 0) {
// machine.getAvailability().addAll(usedSegments);
// machine.getAvailability().sort(Comparator.comparing(TimeSegment::getStart));
// }
// }else {
// times= CaldScheduleResultDetail(timeSegments1,machine,st,remainingTime,oneTime);
// }
return
times
;
}
private
CopyOnWriteArrayList
<
ScheduleResultDetail
>
CaldScheduleResult
(
Machine
machine
,
int
processingTime
,
LocalDateTime
currentTime
,
CopyOnWriteArrayList
<
TimeSegment
>
timeSegments
,
double
oneTime
,
double
quantity
)
{
int
remainingTime
=
processingTime
;
CopyOnWriteArrayList
<
ScheduleResultDetail
>
times
=
new
CopyOnWriteArrayList
<>();
int
estimateIndex
=
(
int
)
Math
.
ceil
(
remainingTime
/
(
double
)
ONE_DAY_MINUTES
);
CopyOnWriteArrayList
<
TimeSegment
>
timeSegments1
=
null
;
if
(
estimateIndex
>
10
)
{
{
timeSegments1
=
getEnoughSegmentsByEstimateIndex
(
timeSegments
,
currentTime
,
remainingTime
);
}
if
(
timeSegments1
==
null
)
{
int
i
=
0
;
CopyOnWriteArrayList
<
TimeSegment
>
usedSegments
=
new
CopyOnWriteArrayList
<>();
while
(
remainingTime
>
0
)
{
TimeSegment
shift
=
timeSegments
.
get
(
i
);
Map
<
Integer
,
Object
>
outMap
=
CreateScheduleResultDetail
(
shift
,
st
,
remainingTime
,
oneTime
);
Map
<
Integer
,
Object
>
outMap
=
CreateScheduleResultDetail
(
shift
,
currentTime
,
remainingTime
,
oneTime
);
remainingTime
=
(
int
)
outMap
.
get
(
1
);
ScheduleResultDetail
time
=
(
ScheduleResultDetail
)
outMap
.
get
(
2
);
times
.
add
(
time
);
// 还原未使用的时间段
RemoveMachineAvailable
(
machine
,
time
,
shift
);
CopyOnWriteArrayList
<
TimeSegment
>
usedSegments1
=
RemoveMachineAvailable
(
machine
,
time
,
shift
);
if
(
usedSegments1
!=
null
&&
usedSegments1
.
size
()>
0
)
{
usedSegments
.
addAll
(
usedSegments1
);
}
i
++;
}
if
(
usedSegments
!=
null
&&
usedSegments
.
size
()
>
0
)
{
machine
.
getAvailability
().
addAll
(
usedSegments
);
machine
.
getAvailability
().
sort
(
Comparator
.
comparing
(
TimeSegment:
:
getStart
));
}
}
else
{
times
=
CaldScheduleResultDetail
(
timeSegments1
,
machine
,
st
,
remainingTime
,
oneTime
);
times
=
CaldScheduleResultDetail
(
timeSegments1
,
machine
,
currentTime
,
remainingTime
,
oneTime
);
}
return
times
;
...
...
@@ -214,6 +470,7 @@ public class MachineCalculator {
{
int
processable1
=(
int
)
calculateTotalAvailableSecond
(
timeSegments
,
st
);
CopyOnWriteArrayList
<
TimeSegment
>
usedSegments
=
new
CopyOnWriteArrayList
<>();
CopyOnWriteArrayList
<
ScheduleResultDetail
>
times
=
new
CopyOnWriteArrayList
<>();
...
...
@@ -224,8 +481,10 @@ public class MachineCalculator {
remainingTime
=(
int
)
outMap
.
get
(
1
);
ScheduleResultDetail
time1
=(
ScheduleResultDetail
)
outMap
.
get
(
2
);
times
.
add
(
time1
);
RemoveMachineAvailable
(
machine
,
time1
,
shiftfrist
);
CopyOnWriteArrayList
<
TimeSegment
>
usedSegments1
=
RemoveMachineAvailable
(
machine
,
time1
,
shiftfrist
);
if
(
usedSegments1
!=
null
&&
usedSegments1
.
size
()
>
0
)
{
usedSegments
.
addAll
(
usedSegments1
);
}
// 计算有效时间
CopyOnWriteArrayList
<
TimeSegment
>
timeSegments2
=
new
CopyOnWriteArrayList
<>(
timeSegments
.
subList
(
1
,
timeSegments
.
size
()-
1
));
...
...
@@ -252,7 +511,14 @@ public class MachineCalculator {
remainingTime
=(
int
)
outMaplast
.
get
(
1
);
ScheduleResultDetail
timelast
=(
ScheduleResultDetail
)
outMaplast
.
get
(
2
);
times
.
add
(
timelast
);
RemoveMachineAvailable
(
machine
,
timelast
,
shiftlast
);
CopyOnWriteArrayList
<
TimeSegment
>
usedSegments2
=
RemoveMachineAvailable
(
machine
,
timelast
,
shiftlast
);
if
(
usedSegments2
!=
null
&&
usedSegments2
.
size
()
>
0
)
{
usedSegments
.
addAll
(
usedSegments2
);
}
if
(
usedSegments
!=
null
&&
usedSegments
.
size
()
>
0
)
{
machine
.
getAvailability
().
addAll
(
usedSegments
);
machine
.
getAvailability
().
sort
(
Comparator
.
comparing
(
TimeSegment:
:
getStart
));
}
return
times
;
}
...
...
@@ -978,42 +1244,73 @@ public class MachineCalculator {
return
times
;
}
private
void
RemoveMachineAvailable
(
Machine
machine
,
ScheduleResultDetail
geneDetails
,
TimeSegment
targetSegment
)
{
private
CopyOnWriteArrayList
<
TimeSegment
>
RemoveMachineAvailable
(
Machine
machine
,
ScheduleResultDetail
geneDetails
,
TimeSegment
targetSegment
)
{
// 关键修复2:加锁(若多线程访问),避免并发修改
LocalDateTime
geneStartTime
=
baseTime
.
plusSeconds
(
geneDetails
.
getStartTime
());
LocalDateTime
geneEndTime
=
baseTime
.
plusSeconds
(
geneDetails
.
getEndTime
());
CopyOnWriteArrayList
<
TimeSegment
>
usedSegments
=
new
CopyOnWriteArrayList
<>();
if
(
targetSegment
.
getStart
().
isBefore
(
geneStartTime
)&&
targetSegment
.
getEnd
().
isAfter
(
geneEndTime
))
{
TimeSegment
usedSegment
=
new
TimeSegment
();
usedSegment
.
setStart
(
targetSegment
.
getStart
());
usedSegment
.
setEnd
(
geneStartTime
);
usedSegment
.
setHoliday
(
false
);
usedSegment
.
setKey
(
UUID
.
randomUUID
().
toString
());
usedSegment
.
setType
(
SegmentType
.
REGULAR
);
usedSegment
.
setUsed
(
false
);
usedSegment
.
setKey
(
UUID
.
randomUUID
().
toString
());
usedSegments
.
add
(
usedSegment
);
TimeSegment
usedSegment2
=
new
TimeSegment
();
usedSegment2
.
setStart
(
geneStartTime
);
usedSegment2
.
setEnd
(
geneEndTime
);
usedSegment2
.
setHoliday
(
false
);
usedSegment2
.
setKey
(
UUID
.
randomUUID
().
toString
());
usedSegment2
.
setType
(
SegmentType
.
REGULAR
);
usedSegment2
.
setUsed
(
true
);
usedSegments
.
add
(
usedSegment2
);
LocalDateTime
geneEndTime
=
baseTime
.
plusSeconds
(
geneDetails
.
getEndTime
());
TimeSegment
usedSegment
=
null
;
if
(
targetSegment
.
getEnd
().
isAfter
(
geneEndTime
))
{
usedSegment
=
new
TimeSegment
();
geneDetails
.
setKey
(
usedSegment2
.
getKey
());
targetSegment
.
setStart
(
geneEndTime
);
}
else
if
(
targetSegment
.
getEnd
().
isAfter
(
geneEndTime
))
{
TimeSegment
usedSegment
=
new
TimeSegment
();
usedSegment
.
setStart
(
baseTime
.
plusSeconds
(
geneDetails
.
getStartTime
()));
usedSegment
.
setEnd
(
geneEndTime
);
usedSegment
.
setHoliday
(
false
);
usedSegment
.
setKey
(
UUID
.
randomUUID
().
toString
());
usedSegment
.
setType
(
SegmentType
.
REGULAR
);
usedSegment
.
setUsed
(
true
);
usedSegments
.
add
(
usedSegment
);
geneDetails
.
setKey
(
usedSegment
.
getKey
());
targetSegment
.
setStart
(
geneEndTime
);
}
else
{
}
else
if
(
targetSegment
.
getStart
().
isBefore
(
geneStartTime
))
{
//换型时可能需要把前面的时间分割处理
TimeSegment
usedSegment
=
new
TimeSegment
();
usedSegment
.
setStart
(
targetSegment
.
getStart
());
usedSegment
.
setEnd
(
geneStartTime
);
usedSegment
.
setHoliday
(
false
);
usedSegment
.
setKey
(
UUID
.
randomUUID
().
toString
());
usedSegment
.
setType
(
SegmentType
.
REGULAR
);
usedSegment
.
setUsed
(
false
);
usedSegment
.
setKey
(
UUID
.
randomUUID
().
toString
());
usedSegments
.
add
(
usedSegment
);
geneDetails
.
setKey
(
targetSegment
.
getKey
());
targetSegment
.
setStart
(
geneStartTime
);
targetSegment
.
setUsed
(
true
);
}
else
{
targetSegment
.
setUsed
(
true
);
}
if
(
usedSegment
!=
null
)
{
machine
.
getAvailability
().
add
(
usedSegment
);
machine
.
getAvailability
().
sort
(
Comparator
.
comparing
(
TimeSegment:
:
getStart
));
}
return
usedSegments
;
// if(usedSegments!=null&&usedSegments.size()>0)
// {
// machine.getAvailability().addAll(usedSegments);
// machine.getAvailability().sort(Comparator.comparing(TimeSegment::getStart));
// }
}
private
void
RemoveMachineAvailable1
(
Machine
machine
,
ScheduleResultDetail
geneDetails
,
TimeSegment
targetSegment1
)
{
...
...
src/main/java/com/aps/service/Algorithm/NSGAIIUtils.java
View file @
eb9004a2
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.common.util.FileHelper
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.ObjectiveWeights
;
...
...
@@ -48,7 +49,10 @@ public class NSGAIIUtils {
* 并行快速非支配排序(大规模种群提速50%+)
*/
public
List
<
List
<
Chromosome
>>
parallelFastNonDominatedSort
(
List
<
Chromosome
>
population
)
{
int
popSize
=
population
.
size
();
FileHelper
.
writeLogFile
(
"非支配排序---------------"
+
popSize
);
List
<
List
<
Chromosome
>>
fronts
=
new
ArrayList
<>();
// 步骤1:预处理 - 计算归一化目标值和加权目标值
...
...
src/main/java/com/aps/service/Algorithm/RoutingDataService.java
View file @
eb9004a2
...
...
@@ -213,7 +213,10 @@ public class RoutingDataService {
entry
.
setEquipTypeCode
(
op
.
getEquipTypeCode
());
entry
.
setRuntime
(
op
.
getRuntime
());
entry
.
setSingleOut
(
op
.
getSingleOut
());
//生产准备
entry
.
setSetupTime
(
op
.
getSetupTime
());
//后处理
entry
.
setTeardownTime
(
op
.
getPostprocessingTime
());
entry
.
setConstTime
(
op
.
getConstTime
());
entry
.
setOrderId
(
op
.
getOrderId
());
entry
.
setOrderCode
(
op
.
getOrderCode
());
...
...
@@ -248,6 +251,7 @@ public class RoutingDataService {
machineIds
.
replace
(
e
.
getEquipId
(),
totalprocessTime
);
}
}
else
{
//大概记录要用到的设备的加工时间,用于生成设备日历
machineIds
.
put
(
e
.
getEquipId
(),
totalprocessTime
);
}
...
...
src/main/java/com/aps/service/Algorithm/ScheduleOperationService.java
View file @
eb9004a2
...
...
@@ -23,6 +23,183 @@ import java.util.stream.IntStream;
*/
public
class
ScheduleOperationService
{
/**
* 移动工序方法
* @param chromosome 染色体对象
* @param opIds 工序ID
* @param targetopId 目标工序ID
* @param isfront 目标工序ID的前面
* @param newMachineId 新设备ID
*/
public
void
dragOperation
(
Chromosome
chromosome
,
List
<
Integer
>
opIds
,
int
targetopId
,
Boolean
isfront
,
Long
newMachineId
,
GlobalParam
globalParam
)
{
List
<
Entry
>
allOperations
=
chromosome
.
getAllOperations
();
int
newStartTime
=
0
;
List
<
Integer
>
ordersIds
=
new
ArrayList
<>();
List
<
Integer
>
opsIndexs
=
new
ArrayList
<>();
Map
<
Integer
,
Integer
>
opTimeMap
=
chromosome
.
getResult
().
stream
()
.
collect
(
Collectors
.
toMap
(
GAScheduleResult:
:
getOperationId
,
r
->
r
.
getStartTime
()
));
List
<
OperationSort
>
opGroupMap
=
allOperations
.
stream
()
.
map
(
data
->
new
OperationSort
(
data
.
getId
(),
0
,
data
.
getGroupId
(),
data
.
getSequence
()))
// 再提取字段
.
collect
(
Collectors
.
toList
());
Integer
newMachineId1
=
newMachineId
.
intValue
();
List
<
Integer
>
OperationSequencing
=
chromosome
.
getOperationSequencing
();
GAScheduleResult
targetResult1
=
null
;
Entry
targetOp1
=
null
;
int
targetopIndex1
=
0
;
if
(
targetopId
!=
0
)
{
targetResult1
=
chromosome
.
getResult
().
stream
()
.
filter
(
r
->
r
.
getOperationId
()
==
targetopId
)
.
findFirst
()
.
orElseThrow
(()
->
new
NoSuchElementException
(
"Operation not found: "
+
targetopId
));
targetOp1
=
allOperations
.
stream
()
.
filter
(
o
->
o
.
getId
()
==
targetopId
)
.
findFirst
()
.
orElseThrow
(()
->
new
NoSuchElementException
(
"Operation not found: "
+
targetopId
));
int
GroupId
=
targetOp1
.
GroupId
;
OptionalInt
OperationIndex
=
IntStream
.
range
(
0
,
OperationSequencing
.
size
())
.
filter
(
i
->
OperationSequencing
.
get
(
i
).
equals
(
GroupId
))
// 过滤出值为1的索引
.
skip
(
targetOp1
.
Sequence
-
1
)
// 跳过第一个匹配项
.
findFirst
();
// 取第二个匹配项
targetopIndex1
=
OperationIndex
.
getAsInt
();
if
(
isfront
)
{
newStartTime
=
targetResult1
.
getStartTime
();
}
else
{
newStartTime
=
targetResult1
.
getEndTime
();
}
}
for
(
Integer
opId:
opIds
)
{
// 获取目标结果和工序
GAScheduleResult
targetResult
=
chromosome
.
getResult
().
stream
()
.
filter
(
r
->
r
.
getOperationId
()
==
opId
)
.
findFirst
()
.
orElseThrow
(()
->
new
NoSuchElementException
(
"Operation not found: "
+
targetopId
));
Entry
targetOp
=
allOperations
.
stream
()
.
filter
(
o
->
o
.
getId
()
==
opId
)
.
findFirst
()
.
orElseThrow
(()
->
new
NoSuchElementException
(
"Operation not found: "
+
opId
));
if
(
targetOp
.
getSequence
()
>
1
)
{
Entry
targetOp2
=
allOperations
.
stream
()
.
filter
(
o
->
o
.
getGroupId
()
==
targetOp
.
getGroupId
()
&&
o
.
getSequence
()
==
targetOp
.
getSequence
()
-
1
)
.
findFirst
()
.
orElseThrow
(()
->
new
NoSuchElementException
(
"Operation not found: "
+
opId
));
GAScheduleResult
targetResult2
=
chromosome
.
getResult
().
stream
()
.
filter
(
r
->
r
.
getOperationId
()
==
targetOp2
.
getId
())
.
findFirst
()
.
orElseThrow
(()
->
new
NoSuchElementException
(
"Operation not found: "
+
opId
));
if
(
targetResult2
.
getEndTime
()
<
newStartTime
)
{
throw
new
RuntimeException
(
"不能早于前一工序的结束时间"
);
}
}
if
(
targetopId
!=
0
)
{
OptionalInt
OperationIndex
=
IntStream
.
range
(
0
,
OperationSequencing
.
size
())
.
filter
(
i
->
OperationSequencing
.
get
(
i
).
equals
(
targetOp
.
GroupId
))
// 过滤出值为1的索引
.
skip
(
targetOp
.
Sequence
-
1
)
// 跳过第一个匹配项
.
findFirst
();
// 取第二个匹配项
int
targetOpIndex
=
OperationIndex
.
getAsInt
();
opsIndexs
.
add
(
targetOpIndex
);
ordersIds
.
add
(
targetOp
.
GroupId
);
List
<
Entry
>
targetOp2s
=
allOperations
.
stream
()
.
filter
(
o
->
o
.
getGroupId
()
==
targetOp
.
getGroupId
()
&&
o
.
getSequence
()
>
targetOp
.
getSequence
()).
collect
(
Collectors
.
toList
());
if
(
targetOp2s
!=
null
&&
targetOp2s
.
size
()>
0
)
{
for
(
Entry
targetOp4:
targetOp2s
)
{
OptionalInt
OperationIndex1
=
IntStream
.
range
(
0
,
OperationSequencing
.
size
())
.
filter
(
i
->
OperationSequencing
.
get
(
i
).
equals
(
targetOp
.
GroupId
))
// 过滤出值为1的索引
.
skip
(
targetOp4
.
Sequence
-
1
)
// 跳过第一个匹配项
.
findFirst
();
// 取第二个匹配项
int
targetOpIndex2
=
OperationIndex1
.
getAsInt
();
if
(
targetOpIndex2
<
targetopIndex1
)
//后面的工序位置比目标位置靠前
{
//后面的工序也要往后挪
opsIndexs
.
add
(
targetOpIndex2
);
ordersIds
.
add
(
targetOp
.
GroupId
);
}
}
}
}
if
(
newMachineId1
!=
0
)
{
int
machineOptionIndex
=
targetOp
.
getMachineOptions
().
stream
()
.
map
(
MachineOption:
:
getMachineId
)
.
collect
(
Collectors
.
toList
())
.
indexOf
(
newMachineId
)
+
1
;
if
(
machineOptionIndex
==
0
)
{
throw
new
NoSuchElementException
(
"Machine not found: "
+
newMachineId
);
}
// 更新设备选择序列
int
globalOpIndex
=
chromosome
.
getGlobalOpList
().
stream
()
.
filter
(
g
->
g
.
getOp
().
getId
()
==
opId
)
.
findFirst
()
.
map
(
GlobalOperationInfo:
:
getGlobalOpId
)
.
orElseThrow
(()
->
new
NoSuchElementException
(
"Global operation not found: "
+
opId
));
chromosome
.
getMachineSelection
().
set
(
globalOpIndex
,
machineOptionIndex
);
targetResult
.
setForcedMachineId
(
newMachineId
);
}
else
{
newMachineId1
=(
int
)
targetResult
.
getMachineId
();
}
}
if
(
targetopId
!=
0
)
{
opsIndexs
.
sort
(
Comparator
.
reverseOrder
());
for
(
int
i
=
0
;
i
<
opsIndexs
.
size
();
i
++)
{
Integer
in
=
opsIndexs
.
get
(
i
);
// 安全校验:防止索引越界
if
(
in
>=
0
&&
in
<
OperationSequencing
.
size
())
{
OperationSequencing
.
remove
((
int
)
in
);
}
}
int
GroupId
=
targetOp1
.
GroupId
;
OptionalInt
OperationIndex
=
IntStream
.
range
(
0
,
OperationSequencing
.
size
())
.
filter
(
i
->
OperationSequencing
.
get
(
i
).
equals
(
GroupId
))
// 过滤出值为1的索引
.
skip
(
targetOp1
.
Sequence
-
1
)
// 跳过第一个匹配项
.
findFirst
();
// 取第二个匹配项
int
targetOpIndex
=
OperationIndex
.
getAsInt
();
if
(!
isfront
)
{
targetOpIndex
+=
1
;
}
for
(
Integer
orderid:
ordersIds
)
{
OperationSequencing
.
add
(
targetOpIndex
,
orderid
);
targetOpIndex
++;
}
}
chromosome
.
setOperationSequencing
(
OperationSequencing
);
// 重新解码
redecode
(
chromosome
,
chromosome
.
getBaseTime
(),
globalParam
);
}
/**
...
...
@@ -317,7 +494,7 @@ if(targetOp.getSequence()>1) {
.
findFirst
();
if
(
index
.
isPresent
())
{
machine
.
getMaintenanceWindows
().
remove
(
index
.
getAsInt
());
machine
.
getMaintenanceWindows
().
remove
(
(
int
)
index
.
getAsInt
());
MachineSchedulerService
machineScheduler
=
new
MachineSchedulerService
(
chromosome
.
getBaseTime
());
machineScheduler
.
ClearMachineCache
(
machineId
);
...
...
@@ -746,27 +923,27 @@ if(targetOp.getSequence()>1) {
OptionalInt
index
=
IntStream
.
range
(
0
,
allOperations
.
size
())
.
filter
(
h
->
entry
.
getId
()==
allOperations
.
get
(
h
).
getId
())
.
findFirst
();
allOperations
.
remove
(
index
.
orElse
(
0
));
allOperations
.
remove
(
(
int
)
index
.
orElse
(
0
));
OptionalInt
index1
=
IntStream
.
range
(
0
,
globalOpList
.
size
())
.
filter
(
h
->
entry
.
getId
()==
globalOpList
.
get
(
h
).
getOp
().
getId
())
.
findFirst
();
globalOpList
.
remove
(
index1
.
orElse
(
0
));
globalOpList
.
remove
(
(
int
)
index1
.
orElse
(
0
));
chromosome
.
getMachineSelection
().
remove
(
index1
.
orElse
(
0
));
chromosome
.
getMachineSelection
().
remove
(
(
int
)
index1
.
orElse
(
0
));
OptionalInt
OperationIndex
=
IntStream
.
range
(
0
,
OperationSequencing
.
size
())
.
filter
(
i
->
OperationSequencing
.
get
(
i
).
equals
(
entry
.
GroupId
))
// 过滤出值为1的索引
.
findFirst
();
int
targetOpIndex
=
OperationIndex
.
getAsInt
();
OperationSequencing
.
remove
(
targetOpIndex
);
OperationSequencing
.
remove
(
(
int
)
targetOpIndex
);
OptionalInt
OperationIndex1
=
IntStream
.
range
(
0
,
ScheduleResults
.
size
())
.
filter
(
i
->
ScheduleResults
.
get
(
i
).
getOperationId
()==
entry
.
getId
())
// 过滤出值为1的索引
.
findFirst
();
//锁定需要删除
ScheduleResults
.
remove
(
OperationIndex1
.
getAsInt
());
ScheduleResults
.
remove
(
(
int
)
OperationIndex1
.
getAsInt
());
}
AtomicInteger
globalOpId
=
new
AtomicInteger
(
0
);
...
...
@@ -892,7 +1069,7 @@ if(targetOp.getSequence()>1) {
.
filter
(
i
->
OperationSequencing
.
get
(
i
).
equals
(
targetOp
.
GroupId
))
// 过滤出值为1的索引
.
skip
(
targetOp
.
Sequence
-
1
)
// 跳过第一个匹配项
.
findFirst
();
chromosome
.
getOperationSequencing
().
remove
(
OperationIndex
.
getAsInt
());
chromosome
.
getOperationSequencing
().
remove
(
(
int
)
OperationIndex
.
getAsInt
());
...
...
@@ -902,8 +1079,8 @@ if(targetOp.getSequence()>1) {
.
orElseThrow
(()
->
new
NoSuchElementException
(
"Global operation not found: "
+
opId
));
chromosome
.
getMachineSelection
().
remove
(
globalOpIndex
);
globalOpList
.
remove
(
globalOpIndex
);
chromosome
.
getMachineSelection
().
add
((
int
)
globalOpIndex
);
globalOpList
.
remove
(
(
int
)
globalOpIndex
);
AtomicInteger
globalOpId
=
new
AtomicInteger
(
0
);
...
...
@@ -953,27 +1130,27 @@ if(targetOp.getSequence()>1) {
OptionalInt
index
=
IntStream
.
range
(
0
,
allOperations
.
size
())
.
filter
(
h
->
entry
.
getId
()==
allOperations
.
get
(
h
).
getId
())
.
findFirst
();
allOperations
.
remove
(
index
.
orElse
(
0
));
allOperations
.
remove
(
(
int
)
index
.
orElse
(
0
));
OptionalInt
index1
=
IntStream
.
range
(
0
,
globalOpList
.
size
())
.
filter
(
h
->
entry
.
getId
()==
globalOpList
.
get
(
h
).
getOp
().
getId
())
.
findFirst
();
globalOpList
.
remove
(
index1
.
orElse
(
0
));
globalOpList
.
remove
(
(
int
)
index1
.
orElse
(
0
));
chromosome
.
getMachineSelection
().
remove
(
index1
.
orElse
(
0
));
chromosome
.
getMachineSelection
().
remove
(
(
int
)
index1
.
orElse
(
0
));
OptionalInt
OperationIndex
=
IntStream
.
range
(
0
,
OperationSequencing
.
size
())
.
filter
(
i
->
OperationSequencing
.
get
(
i
).
equals
(
entry
.
GroupId
))
// 过滤出值为1的索引
.
findFirst
();
int
targetOpIndex
=
OperationIndex
.
getAsInt
();
OperationSequencing
.
remove
(
targetOpIndex
);
OperationSequencing
.
remove
(
(
int
)
targetOpIndex
);
OptionalInt
OperationIndex1
=
IntStream
.
range
(
0
,
ScheduleResults
.
size
())
.
filter
(
i
->
ScheduleResults
.
get
(
i
).
getOperationId
()==
entry
.
getId
())
// 过滤出值为1的索引
.
findFirst
();
//锁定需要删除
ScheduleResults
.
remove
(
OperationIndex1
.
getAsInt
());
ScheduleResults
.
remove
(
(
int
)
OperationIndex1
.
getAsInt
());
}
...
...
src/main/java/com/aps/service/plan/PlanResultService.java
View file @
eb9004a2
...
...
@@ -540,6 +540,23 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
return
chromosome
;
}
public
Chromosome
Drag
(
String
SceneId
,
List
<
Integer
>
opId
,
int
targetopId
,
Boolean
isfront
,
Long
newMachineId
)
{
GlobalParam
globalParam
=
new
GlobalParam
();
Chromosome
chromosome
=
_sceneService
.
loadChromosomeFromFile
(
SceneId
);
// WriteScheduleSummary(chromosome);
ScheduleOperationService
ScheduleOperation
=
new
ScheduleOperationService
();
// WriteScheduleSummary(chromosome);
ScheduleOperation
.
dragOperation
(
chromosome
,
opId
,
targetopId
,
isfront
,
newMachineId
,
globalParam
);
// WriteScheduleSummary(chromosome);
_sceneService
.
saveChromosomeToFile
(
chromosome
,
SceneId
);
return
chromosome
;
}
public
Chromosome
Move
(
String
SceneId
,
List
<
Integer
>
opId
,
LocalDateTime
newStartTime
,
Long
newMachineId
,
int
lockStartTime
)
{
...
...
@@ -583,11 +600,11 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
{
Chromosome
chromosome
=
_sceneService
.
loadChromosomeFromFile
(
SceneId
);
ScheduleOperationService
ScheduleOperation
=
new
ScheduleOperationService
();
WriteScheduleSummary
(
chromosome
);
//
WriteScheduleSummary(chromosome);
GlobalParam
globalParam
=
new
GlobalParam
();
ScheduleOperation
.
redecode
(
chromosome
,
chromosome
.
getBaseTime
(),
globalParam
);
WriteScheduleSummary
(
chromosome
);
//
WriteScheduleSummary(chromosome);
}
...
...
src/test/java/com/aps/demo/PlanResultServiceTest.java
View file @
eb9004a2
...
...
@@ -37,14 +37,16 @@ public class PlanResultServiceTest {
// NSGAIIUtils nsgaiiUtils=new NSGAIIUtils();
// nsgaiiUtils.Test();
planResultService
.
execute2
(
"C5FB5EF2A7334A0A92F826F4937E100
8"
);
// planResultService.execute2("FFAC5AA2E0B943D292933B28BDAB906
8");
// planResultService.execute2("726D4C1A712B4B1393175BD44B775B66");
// planResultService.execute2("265F24B6DF3C40E4B17D193B0CC8AAF2");
// LocalDateTime t= LocalDateTime.of(2026, 02, 14, 1, 25, 52);
//
List<Integer> opids=new ArrayList<>();//BCA6FA43FFA444D3952CF8F6E1EA291B
// opids.add(9
);
List
<
Integer
>
opids
=
new
ArrayList
<>();
//BCA6FA43FFA444D3952CF8F6E1EA291B
opids
.
add
(
7
);
// planResultService.Move("27065EA0ECD14A81B7FAAFEF52273F93",opids,t,1265l,0);
// planResultService.Redecode("27065EA0ECD14A81B7FAAFEF52273F93");
// planResultService.Redecode("CA71321FE55B4437A3900315692F9220");
planResultService
.
Drag
(
"27065EA0ECD14A81B7FAAFEF52273F93"
,
opids
,
6
,
false
,
0
l
);
// MaintenanceWindow maintenanceWindow=new MaintenanceWindow();
// maintenanceWindow.setStartTime(LocalDateTime.of(2025, 10, 21, 0, 0, 0));
// maintenanceWindow.setEndTime(LocalDateTime.of(2025, 10, 31, 0, 0, 0));
...
...
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