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
c5c9a28b
Commit
c5c9a28b
authored
Jun 02, 2026
by
DESKTOP-VKRD9QF\Administration
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
倒排冲突
parent
2f7a699b
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
218 additions
and
0 deletions
+218
-0
GeneticDecoder.java
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
+218
-0
No files found.
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
View file @
c5c9a28b
...
...
@@ -1612,6 +1612,28 @@ if(groupId==7)
.
mapToInt
(
ScheduleResultDetail:
:
getEndTime
)
.
max
()
.
orElse
(
0
);
// 不可中断工序不能由多段空档拼接;如果试排结果断开,先归还占用,再倒排寻找最近连续窗口。
if
(
operation
.
getIsInterrupt
()
!=
1
&&
hasDiscontinuousDetails
(
geneDetails
))
{
AddMachineAvailable
(
machine
,
geneDetails
);
if
(
isJit
&&
islockMachineTime
)
{
CopyOnWriteArrayList
<
ScheduleResultDetail
>
continuousDetails
=
scheduleLatestContinuousJit
(
machine
,
operation
,
earliestStartTime
,
processingTimeTotal
);
if
(
continuousDetails
==
null
||
continuousDetails
.
isEmpty
())
{
return
OperationScheduleResult
.
success
(
null
);
}
geneDetails
=
continuousDetails
;
startTime
=
geneDetails
.
stream
()
.
mapToInt
(
ScheduleResultDetail:
:
getStartTime
)
.
min
()
.
orElse
(
0
);
endTime
=
geneDetails
.
stream
()
.
mapToInt
(
ScheduleResultDetail:
:
getEndTime
)
.
max
()
.
orElse
(
0
);
}
else
{
return
OperationScheduleResult
.
success
(
null
);
}
}
// if (isJit) {
// FileHelper.writeLogFile(" 半成品 " + operation.getGroupId() + " - " + operation.getSequence() + ",开始时间: " + startTime + ",结束时间: " + endTime + ",处理时间: " + processingTime + ", 后处理: " + teardownTime +
// ", 前处理: " + preTime + ", 换型: " + setupTime + ", 数量: " + operation.getQuantity() + ", 设备: " + machine.getId() + ", 是否可中断: " + operation.getIsInterrupt());
...
...
@@ -1667,6 +1689,202 @@ if(groupId==7)
return
OperationScheduleResult
.
success
(
result
);
}
// 判断排程明细是否存在断档。不可中断工序如果出现断档,页面外层时间会跨住中间任务。
private
boolean
hasDiscontinuousDetails
(
CopyOnWriteArrayList
<
ScheduleResultDetail
>
geneDetails
)
{
if
(
geneDetails
==
null
||
geneDetails
.
size
()
<=
1
)
{
return
false
;
}
List
<
int
[]>
ranges
=
new
ArrayList
<>();
for
(
ScheduleResultDetail
detail
:
geneDetails
)
{
if
(
detail
==
null
)
{
continue
;
}
if
(
detail
.
getUsedSegment
()
!=
null
&&
!
detail
.
getUsedSegment
().
isEmpty
())
{
for
(
TimeSegment
segment
:
detail
.
getUsedSegment
())
{
if
(
segment
==
null
||
segment
.
getStart
()
==
null
||
segment
.
getEnd
()
==
null
)
{
continue
;
}
int
segmentStart
=
(
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
segment
.
getStart
());
int
segmentEnd
=
(
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
segment
.
getEnd
());
if
(
segmentEnd
>
segmentStart
)
{
ranges
.
add
(
new
int
[]{
segmentStart
,
segmentEnd
});
}
}
}
else
if
(
detail
.
getEndTime
()
>
detail
.
getStartTime
())
{
ranges
.
add
(
new
int
[]{
detail
.
getStartTime
(),
detail
.
getEndTime
()});
}
}
if
(
ranges
.
size
()
<=
1
)
{
return
false
;
}
ranges
.
sort
(
Comparator
.
comparingInt
(
range
->
range
[
0
]));
int
lastEnd
=
ranges
.
get
(
0
)[
1
];
for
(
int
i
=
1
;
i
<
ranges
.
size
();
i
++)
{
int
[]
current
=
ranges
.
get
(
i
);
if
(
current
[
0
]
>
lastEnd
+
1
)
{
return
true
;
}
lastEnd
=
Math
.
max
(
lastEnd
,
current
[
1
]);
}
return
false
;
}
// 倒排不可中断兜底:从锚点往前找最近的一整段连续空闲窗口,避免失败后掉到基准日期正排。
private
CopyOnWriteArrayList
<
ScheduleResultDetail
>
scheduleLatestContinuousJit
(
Machine
machine
,
Entry
operation
,
int
latestEndTime
,
int
processingTimeTotal
)
{
if
(
machine
==
null
||
machine
.
getAvailability
()
==
null
||
processingTimeTotal
<=
0
)
{
return
null
;
}
LocalDateTime
latestEnd
=
baseTime
.
plusSeconds
(
latestEndTime
);
List
<
TimeSegment
>
availableSegments
=
machine
.
getAvailability
().
stream
()
.
filter
(
t
->
t
!=
null
&&
!
t
.
isUsed
()
&&
t
.
getStart
()
!=
null
&&
t
.
getEnd
()
!=
null
&&
t
.
getType
()
!=
SegmentType
.
MAINTENANCE
&&
t
.
getStart
().
isBefore
(
latestEnd
)
&&
t
.
getEnd
().
isAfter
(
baseTime
))
.
sorted
(
Comparator
.
comparing
(
TimeSegment:
:
getStart
))
.
collect
(
Collectors
.
toList
());
List
<
TimeSegment
>
group
=
new
ArrayList
<>();
LocalDateTime
groupStart
=
null
;
LocalDateTime
groupEnd
=
null
;
long
groupAvailableSeconds
=
0L
;
for
(
int
i
=
availableSegments
.
size
()
-
1
;
i
>=
0
;
i
--)
{
TimeSegment
segment
=
availableSegments
.
get
(
i
);
LocalDateTime
segmentStart
=
segment
.
getStart
().
isBefore
(
baseTime
)
?
baseTime
:
segment
.
getStart
();
LocalDateTime
segmentEnd
=
segment
.
getEnd
().
isAfter
(
latestEnd
)
?
latestEnd
:
segment
.
getEnd
();
if
(!
segmentEnd
.
isAfter
(
segmentStart
))
{
continue
;
}
boolean
continuous
=
group
.
isEmpty
()
||
!
segmentEnd
.
plusSeconds
(
1
).
isBefore
(
groupStart
);
if
(!
continuous
)
{
group
.
clear
();
groupAvailableSeconds
=
0L
;
groupEnd
=
null
;
}
group
.
add
(
0
,
segment
);
groupStart
=
segmentStart
;
if
(
groupEnd
==
null
)
{
groupEnd
=
segmentEnd
;
}
groupAvailableSeconds
+=
ChronoUnit
.
SECONDS
.
between
(
segmentStart
,
segmentEnd
);
if
(
groupAvailableSeconds
>=
processingTimeTotal
)
{
return
buildContinuousJitDetails
(
machine
,
operation
,
group
,
groupEnd
,
processingTimeTotal
);
}
}
return
null
;
}
// 将选中的连续窗口转成明细,并同步占用设备日历。
private
CopyOnWriteArrayList
<
ScheduleResultDetail
>
buildContinuousJitDetails
(
Machine
machine
,
Entry
operation
,
List
<
TimeSegment
>
group
,
LocalDateTime
latestEnd
,
int
processingTimeTotal
)
{
CopyOnWriteArrayList
<
ScheduleResultDetail
>
details
=
new
CopyOnWriteArrayList
<>();
long
remaining
=
processingTimeTotal
;
LocalDateTime
cursorEnd
=
latestEnd
;
for
(
int
i
=
group
.
size
()
-
1
;
i
>=
0
&&
remaining
>
0
;
i
--)
{
TimeSegment
segment
=
group
.
get
(
i
);
LocalDateTime
useEnd
=
segment
.
getEnd
().
isAfter
(
cursorEnd
)
?
cursorEnd
:
segment
.
getEnd
();
LocalDateTime
useStart
=
segment
.
getStart
();
if
(!
useEnd
.
isAfter
(
useStart
))
{
continue
;
}
long
availableSeconds
=
ChronoUnit
.
SECONDS
.
between
(
useStart
,
useEnd
);
if
(
availableSeconds
>
remaining
)
{
useStart
=
useEnd
.
minusSeconds
(
remaining
);
}
TimeSegment
occupied
=
occupyAvailabilityRange
(
machine
,
segment
,
useStart
,
useEnd
);
if
(
occupied
==
null
)
{
return
null
;
}
ScheduleResultDetail
detail
=
new
ScheduleResultDetail
();
detail
.
setKey
(
occupied
.
getKey
());
detail
.
setStartTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
useStart
));
detail
.
setEndTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
useEnd
));
detail
.
setOneTime
(
1
);
detail
.
setQuantity
(
operation
.
getQuantity
());
detail
.
setEfficiency
(
occupied
.
getEfficiency
());
detail
.
setUsedSegment
(
Collections
.
singletonList
(
occupied
));
details
.
add
(
0
,
detail
);
remaining
-=
ChronoUnit
.
SECONDS
.
between
(
useStart
,
useEnd
);
cursorEnd
=
useStart
.
minusSeconds
(
1
);
}
return
remaining
<=
0
?
details
:
null
;
}
// 从设备可用片段里切出本次占用范围,保留前后未占用部分。
private
TimeSegment
occupyAvailabilityRange
(
Machine
machine
,
TimeSegment
source
,
LocalDateTime
useStart
,
LocalDateTime
useEnd
)
{
if
(
machine
==
null
||
machine
.
getAvailability
()
==
null
||
source
==
null
||
useStart
==
null
||
useEnd
==
null
||
!
useEnd
.
isAfter
(
useStart
))
{
return
null
;
}
int
index
=
machine
.
getAvailability
().
stream
()
.
filter
(
t
->
source
.
getKey
().
equals
(
t
.
getKey
()))
.
findFirst
()
.
map
(
machine
.
getAvailability
()::
indexOf
)
.
orElse
(-
1
);
if
(
index
<
0
)
{
return
null
;
}
TimeSegment
current
=
machine
.
getAvailability
().
remove
(
index
);
List
<
TimeSegment
>
replacement
=
new
ArrayList
<>();
if
(
current
.
getStart
().
isBefore
(
useStart
))
{
TimeSegment
before
=
copyAvailabilitySegment
(
current
,
current
.
getStart
(),
useStart
.
minusSeconds
(
1
),
false
);
if
(
before
.
getEnd
().
isAfter
(
before
.
getStart
()))
{
replacement
.
add
(
before
);
}
}
TimeSegment
occupied
=
copyAvailabilitySegment
(
current
,
useStart
,
useEnd
,
true
);
replacement
.
add
(
occupied
);
if
(
current
.
getEnd
().
isAfter
(
useEnd
))
{
TimeSegment
after
=
copyAvailabilitySegment
(
current
,
useEnd
.
plusSeconds
(
1
),
current
.
getEnd
(),
false
);
if
(
after
.
getEnd
().
isAfter
(
after
.
getStart
()))
{
replacement
.
add
(
after
);
}
}
machine
.
getAvailability
().
addAll
(
replacement
);
machine
.
getAvailability
().
sort
(
Comparator
.
comparing
(
TimeSegment:
:
getStart
));
return
occupied
;
}
private
TimeSegment
copyAvailabilitySegment
(
TimeSegment
source
,
LocalDateTime
start
,
LocalDateTime
end
,
boolean
used
)
{
TimeSegment
copy
=
new
TimeSegment
();
copy
.
setKey
(
UUID
.
randomUUID
().
toString
());
copy
.
setStart
(
start
);
copy
.
setEnd
(
end
);
copy
.
setEarliestTime
(
source
.
getEarliestTime
());
copy
.
setTotalTaskTime
(
source
.
getTotalTaskTime
());
copy
.
setType
(
source
.
getType
());
copy
.
setHoliday
(
source
.
isHoliday
());
copy
.
setUsed
(
used
);
copy
.
setEfficiency
(
source
.
getEfficiency
());
copy
.
setProcessingTime
(
source
.
getProcessingTime
());
return
copy
;
}
private
GAScheduleResult
CreateResult
(
Entry
operation
,
long
machineId
,
int
startTime
,
int
endTime
,
double
processingTime
,
int
setupTime
,
int
preTime
,
int
teardownTime
,
int
bomtime
...
...
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