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
31d2cb46
Commit
31d2cb46
authored
May 12, 2026
by
Tong Li
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bom
parent
b1b2a85e
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
873 additions
and
783 deletions
+873
-783
GlobalParam.java
src/main/java/com/aps/entity/basic/GlobalParam.java
+1
-1
GeneticDecoder.java
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
+149
-408
GeneticDecoderBom.java
...ain/java/com/aps/service/Algorithm/GeneticDecoderBom.java
+323
-107
MachineCalculator.java
...ain/java/com/aps/service/Algorithm/MachineCalculator.java
+54
-40
MaterialRequirementService.java
...com/aps/service/Algorithm/MaterialRequirementService.java
+342
-223
LanuchServiceImpl.java
src/main/java/com/aps/service/impl/LanuchServiceImpl.java
+1
-1
PlanResultService.java
src/main/java/com/aps/service/plan/PlanResultService.java
+1
-1
PlanResultServiceTest.java
src/test/java/com/aps/demo/PlanResultServiceTest.java
+2
-2
No files found.
src/main/java/com/aps/entity/basic/GlobalParam.java
View file @
31d2cb46
...
...
@@ -42,7 +42,7 @@ public class GlobalParam {
/// <summary>
/// 是否全局倒排
/// </summary>
private
boolean
isJit
=
tru
e
;
private
boolean
isJit
=
fals
e
;
private
boolean
_smoothSetup
=
false
;
// 设置时间平滑 工序的前处理是否提前
...
...
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
View file @
31d2cb46
...
...
@@ -61,13 +61,15 @@ public class GeneticDecoder {
private
GlobalParam
_globalParam
;
private
MachineCalculator
machineCalculator
;
private
GeneticDecoderBom
bom
;
private
MaterialRequirementService
materialRequirementService
;
private
DiscreteParameterMatrixService
discreteParameterMatrixService
;
private
String
sceneId
;
private
boolean
rebuildStructureForCurrentDecode
=
fals
e
;
private
boolean
rebuildStructureForCurrentDecode
=
tru
e
;
...
...
@@ -82,6 +84,8 @@ public class GeneticDecoder {
_globalParam
=
globalParam
;
machineCalculator
=
new
MachineCalculator
(
baseTime
,
machines
,
machineScheduler
);
materialRequirementService
=
_materialRequirementService
;
bom
=
new
GeneticDecoderBom
(
this
.
baseTime
,
machineCalculator
,
materialRequirementService
);
sceneId
=
_sceneId
;
// this.orderMaxID = orders.stream().mapToInt(Order::getId).max().orElse(0);
}
...
...
@@ -493,24 +497,52 @@ public class GeneticDecoder {
// 步骤2:按OperationSequencing顺序调度工序
Map
<
Integer
,
Integer
>
orderProcessCounter
=
new
HashMap
<>();
Map
<
Integer
,
Integer
>
orderLastEndTime
=
new
HashMap
<>();
Map
<
Integer
,
Integer
>
orderDueDate
=
new
HashMap
<>();
Map
<
Integer
,
Entry
>
entryIndexById
=
new
HashMap
<>();
Map
<
Integer
,
List
<
Entry
>>
entrysBygroupId
=
new
HashMap
<>();
//工序对应的排产结果
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
=
new
ConcurrentHashMap
<>();
for
(
Order
order
:
chromosome
.
getOrders
())
{
int
end
=
(
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
order
.
getDueDate
());
orderDueDate
.
putIfAbsent
(
order
.
getId
(),
end
);
}
Map
<
Integer
,
Entry
>
entryIndexById
=
new
HashMap
<>();
Map
<
Integer
,
List
<
Entry
>>
entrysBygroupId
=
new
HashMap
<>();
for
(
Entry
op
:
allOperations
)
{
int
groupId
=
op
.
getGroupId
();
orderProcessCounter
.
putIfAbsent
(
groupId
,
0
);
orderLastEndTime
.
putIfAbsent
(
groupId
,
0
);
//工序
entryIndexById
.
put
(
op
.
getId
(),
op
);
//订单下全部工序
entrysBygroupId
.
computeIfAbsent
(
groupId
,
k
->
new
ArrayList
<>()).
add
(
op
);
//scheduleIndexById.put(op.getId(),null);
}
Map
<
Integer
,
Integer
>
orderDueDate
=
new
HashMap
<>();
Map
<
Integer
,
AbstractMap
.
SimpleEntry
<
Boolean
,
Integer
>>
orderSchedulingInfo
=
new
HashMap
<>();
for
(
Order
order
:
chromosome
.
getOrders
())
{
int
end
=
(
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
order
.
getDueDate
());
orderDueDate
.
putIfAbsent
(
order
.
getId
(),
end
);
//存储锚点时间
if
(
isJit
)
{
orderSchedulingInfo
.
put
(
order
.
getId
(),
new
AbstractMap
.
SimpleEntry
<>(
false
,
end
));
}
else
{
orderSchedulingInfo
.
put
(
order
.
getId
(),
new
AbstractMap
.
SimpleEntry
<>(
false
,
0
));
}
}
for
(
Map
.
Entry
<
Integer
,
List
<
Entry
>>
entry
:
entrysBygroupId
.
entrySet
())
{
int
groupId
=
entry
.
getKey
();
Entry
firstOp
=
entry
.
getValue
().
get
(
0
);
if
(
Entry
.
SchedulingMode
.
BACKWARD
.
name
().
equals
(
firstOp
.
getSchedulingMode
()))
{
orderSchedulingInfo
.
put
(
groupId
,
new
AbstractMap
.
SimpleEntry
<>(
true
,
0
));
}
}
// Map<Long, String> machineState = chromosome.getMachines().stream()
// .collect(Collectors.toMap(Machine::getId, m -> ""));
...
...
@@ -528,17 +560,39 @@ public class GeneticDecoder {
boolean
orderIsJit
=
orderDueDate
.
get
(
groupId
)>
0
;
if
(
isJit
&&
orderIsJit
)
AbstractMap
.
SimpleEntry
<
Boolean
,
Integer
>
schedInfo
=
orderSchedulingInfo
.
get
(
groupId
);
orderIsJit
=
schedInfo
!=
null
&&
schedInfo
.
getKey
();
int
orderAnchor
=
schedInfo
!=
null
?
schedInfo
.
getValue
()
:
0
;
// 半成品订单首次处理时,延迟计算锚点:沿依赖链找到根成品工序并正推
if
(
orderIsJit
&&
orderAnchor
==
0
)
{
orderAnchor
=
bom
.
computeSemiFinishedAnchor
(
groupId
,
entrysBygroupId
,
opMachineKeyMap
,
chromosome
,
scheduleIndexById
,
machineTasksCache
);
if
(
orderAnchor
<
0
)
{
orderIsJit
=
false
;
orderSchedulingInfo
.
put
(
groupId
,
new
AbstractMap
.
SimpleEntry
<>(
false
,
-
1
));
}
else
{
orderSchedulingInfo
.
put
(
groupId
,
new
AbstractMap
.
SimpleEntry
<>(
true
,
orderAnchor
));
}
}
if
(
orderIsJit
)
{
orderOps
=
entrysBygroupId
.
get
(
groupId
).
stream
()
.
sorted
(
Comparator
.
comparing
(
Entry:
:
getSequence
).
reversed
())
.
collect
(
Collectors
.
toList
());
orderIsJit
=
true
;
}
else
{
orderOps
=
entrysBygroupId
.
get
(
groupId
).
stream
()
.
sorted
(
Comparator
.
comparing
(
Entry:
:
getSequence
))
.
collect
(
Collectors
.
toList
());
orderIsJit
=
false
;
}
...
...
@@ -570,7 +624,13 @@ public class GeneticDecoder {
long
opStart
=
System
.
nanoTime
();
int
actualEndTime
=
processOperation
(
currentOp
,
machineId
,
processTime
,
machineOption
,
chromosome
,
machineIdMap
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
,(
int
)
orderDueDate
.
get
(
groupId
),
orderIsJit
);
boolean
opIsJit
=
orderIsJit
||(
Entry
.
SchedulingMode
.
BACKWARD
.
name
().
equals
(
currentOp
.
getSchedulingMode
())&&
orderAnchor
>=
0
);
int
dueDateForOp
=
opIsJit
?
orderAnchor
:
(
schedInfo
!=
null
?
schedInfo
.
getValue
()
:
0
);
int
actualEndTime
=
processOperation
(
currentOp
,
machineId
,
processTime
,
machineOption
,
chromosome
,
machineIdMap
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
,
dueDateForOp
,
opIsJit
);
long
opElapsed
=
System
.
nanoTime
()
-
opStart
;
opCount
++;
...
...
@@ -1129,7 +1189,12 @@ public class GeneticDecoder {
{
int
endTime
=
0
;
int
startTime
=
0
;
processingTimeTotal
=(
int
)
Math
.
ceil
(
processingTime
);
if
(
operation
.
getQuantity
()==
0
)
{
processingTimeTotal
=
0
;
}
else
{
processingTimeTotal
=
(
int
)
Math
.
ceil
(
processingTime
);
}
if
(
isJit
)
{
endTime
=
earliestStartTime
;
...
...
@@ -1148,159 +1213,34 @@ public class GeneticDecoder {
return
endTime
;
}
// baseEarliestStartTime:不考虑 BOM 推迟时的理论最早开工时间。
// candidateStartTime:固定点迭代时本轮尝试的开工时间。
// bomtime:按当前候选开工时间试算出来的物料最早可开工时间。
int
baseEarliestStartTime
=
earliestStartTime
;
int
candidateStartTime
=
earliestStartTime
;
if
(
operation
.
getTargetFinishedOperationId
()
!=
null
&&
!
operation
.
getTargetFinishedOperationId
().
isEmpty
())
{
// 1. 计算成品可用时间
GeneticDecoderBom
bom
=
new
GeneticDecoderBom
();
int
finishedAvailableTime
=
bom
.
calculateFinishedAvailableTime
(
operation
,
chromosome
,
baseTime
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
);
if
(
finishedAvailableTime
>
0
)
{
// 2. 计算半成品最晚开工时间(倒排:半成品结束时间 = 成品可用时间,然后往前推加工时间)
// 加上JIT缓冲时间(如果有)
int
semiBufferMinutes
=
_globalParam
.
getSemiJitBufferMinutes
();
int
semiBufferSeconds
=
semiBufferMinutes
*
60
;
// 半成品最晚结束时间 = 成品可用时间 - 缓冲
int
semiLatestEndTime
=
Math
.
max
(
0
,
finishedAvailableTime
-
semiBufferSeconds
);
// 半成品最晚开工时间 = 半成品最晚结束时间 - 加工总时长
int
semiLatestStartTime
=
Math
.
max
(
0
,
semiLatestEndTime
-
processingTimeTotal
);
// 3. 计算半成品物料的BOM齐套时间(正向)
int
semiBomTime
=
getOperationBOMTime
(
operation
,
chromosome
);
// 4. 比较:如果倒排的开工时间早于基准时间或BOM齐套时间,则从基准时间或BOM齐套时间开始正排
int
semiForwardStartTime
=
Math
.
max
(
baseEarliestStartTime
,
semiBomTime
);
if
(
semiLatestStartTime
>=
semiForwardStartTime
)
{
// 倒排可行:使用倒排的最晚开工时间
candidateStartTime
=
semiLatestStartTime
;
}
else
{
// 倒排不可行:使用正排的最早开工时间
candidateStartTime
=
semiForwardStartTime
;
}
// 更新基准最早开工时间
baseEarliestStartTime
=
candidateStartTime
;
}
}
int
setupTime
=
0
;
long
machineId
=
machine
.
getId
();
// 只有存在物料约束(或本次被强制要求重算 BOM)的工序,才需要联立求解“机台何时能排”和“物料何时可用”。
// targetFinishedOperationId != null 的工序通常由前置成品工序驱动,这里不再额外触发一轮 BOM 试算。
boolean
needMaterialCheck
=
false
;
//(operation.getMaterialRequirements()!=null&&operation.getMaterialRequirements().size()>0&&operation.getTargetFinishedOperationId()==null)||calbom;
// 正式落排后还要再做一次带提交的物料校验,把试算阶段推导出的 BOM 状态真正写回 chromosome。
boolean
commitMaterialCheck
=
needMaterialCheck
;
// baseEarliestStartTime:不考虑 BOM 推迟时的理论最早开工时间。
// candidateStartTime:固定点迭代时本轮尝试的开工时间。
// bomtime:按当前候选开工时间试算出来的物料最早可开工时间。
baseEarliestStartTime
=
earliestStartTime
;
candidateStartTime
=
earliestStartTime
;
int
bomtime
=
0
;
// 机台时间和物料时间可能会互相推动,最多迭代 maxSolveIterations 次来找收敛点。
int
maxSolveIterations
=
Math
.
max
(
1
,
_globalParam
.
getMaterialSolveMaxIterations
());
boolean
converged
=
!
needMaterialCheck
;
Entry
scheduledOperation
=
operation
;
Machine
scheduledMachine
=
machine
;
boolean
needMaterialCheck
=(
operation
.
getMaterialRequirements
()!=
null
&&
operation
.
getMaterialRequirements
().
size
()>
0
&&
operation
.
getTargetFinishedOperationId
()==
null
)||
calbom
;
CopyOnWriteArrayList
<
GAScheduleResult
>
machineTasks
=
getMachineTasks
(
machineId
,
chromosome
,
machineTasksCache
);
GAScheduleResult
lastGeneOnMachine
=
getLastMachineTask
(
machineTasks
);
MachineSchedulePreview
machinePreview
=
null
;
CopyOnWriteArrayList
<
ScheduleResultDetail
>
geneDetails
=
new
CopyOnWriteArrayList
<>();
// 固定点求解过程:
// 1. 先按 candidateStartTime 试排机台;
// 2. 再按试排结果试算物料/BOM 的最早可开工时间;
// 3. 如果物料时间继续把开工点往后推,就用新时间再次试排,直到收敛。
int
bomtime
=
0
;
if
(
needMaterialCheck
)
{
for
(
int
iteration
=
0
;
iteration
<
maxSolveIterations
;
iteration
++)
{
// trial BOM 试算会在内部恢复快照,因此每轮都重新从最新 chromosome 中取对象,避免拿到旧引用。
Entry
refreshedOperation
=
entryIndexById
.
get
(
operationId
);
if
(
refreshedOperation
!=
null
)
{
scheduledOperation
=
refreshedOperation
;
}
Machine
refreshedMachine
=
getMachineById
(
chromosome
,
machineId
);
if
(
refreshedMachine
!=
null
)
{
scheduledMachine
=
refreshedMachine
;
}
machineTasks
=
getMachineTasks
(
machineId
,
chromosome
,
machineTasksCache
);
lastGeneOnMachine
=
getLastMachineTask
(
machineTasks
);
if
(
lastGeneOnMachine
!=
null
&&
_globalParam
.
is_smoothChangeOver
())
{
candidateStartTime
=
Math
.
max
(
candidateStartTime
,
lastGeneOnMachine
.
getEndTime
());
}
// 先在机台侧做一次”试排”,geneDetails 中会记录本轮临时占用的机台时间段。
long
iterStart
=
System
.
nanoTime
();
long
previewStart
=
System
.
nanoTime
();
machinePreview
=
buildMachinePreview
(
scheduledOperation
,
scheduledMachine
,
processingTime
,
processingTimeTotal
,
candidateStartTime
,
lastGeneOnMachine
,
machineTasks
,
chromosome
);
long
previewTime
=
System
.
nanoTime
()
-
previewStart
;
long
bomTimeStart
=
System
.
nanoTime
();
try
{
// 物料侧只做试算,不提交最终状态;本轮只关心 BOM 约束会把开工时间推迟到哪里。
bomtime
=
EditOperationBOMTime
(
scheduledOperation
,
chromosome
,
machinePreview
.
getStartTime
(),
machineTasksCache
,
entryIndexById
,
scheduleIndexById
,
false
);
}
finally
{
// buildMachinePreview 会临时锁住机台 availability,这里无论成功或异常都必须释放,
// 否则下一轮迭代会被本轮的试排残留状态污染。
Machine
liveMachineAfterTrial
=
getMachineById
(
chromosome
,
machineId
);
if
(
liveMachineAfterTrial
!=
null
)
{
AddMachineAvailable
(
liveMachineAfterTrial
,
machinePreview
.
getGeneDetails
());
}
else
{
AddMachineAvailable
(
scheduledMachine
,
machinePreview
.
getGeneDetails
());
}
}
// long bomTimeElapsed = System.nanoTime() - bomTimeStart;
// long iterElapsed = System.nanoTime() - iterStart;
// if (iterElapsed > 200_000_000L) { // 200ms
// FileHelper.writeLogFile("[PERF] processWithSingleMachine 固定点迭代慢 opId=" + operationId
// + ", iter=" + iteration + ", preview=" + fmtMs(previewTime)
// + ", BOM=" + fmtMs(bomTimeElapsed) + ", total=" + fmtMs(iterElapsed));
// }
// 下一轮候选开工时间取“基准最早开工”和“物料最早可开工”两者中的较晚值。
int
nextCandidateStartTime
=
Math
.
max
(
baseEarliestStartTime
,
bomtime
);
// 如果物料时间已经不再把机台试排结果往后推,说明机台时间与物料时间达成一致。
if
(
nextCandidateStartTime
<=
machinePreview
.
getStartTime
())
{
converged
=
true
;
candidateStartTime
=
nextCandidateStartTime
;
break
;
}
candidateStartTime
=
nextCandidateStartTime
;
}
// 固定点求解结束后,用收敛得到的候选开工时间作为正式排产的最早开工时间。
earliestStartTime
=
candidateStartTime
;
Entry
refreshedOperation
=
entryIndexById
.
get
(
operationId
);
if
(
refreshedOperation
!=
null
)
{
scheduledOperation
=
refreshedOperation
;
operation
=
refreshedOperation
;
}
Machine
refreshedMachine
=
getMachineById
(
chromosome
,
machineId
);
if
(
refreshedMachine
!=
null
)
{
scheduledMachine
=
refreshedMachine
;
machine
=
refreshedMachine
;
}
machineTasks
=
getMachineTasks
(
machineId
,
chromosome
,
machineTasksCache
);
lastGeneOnMachine
=
getLastMachineTask
(
machineTasks
);
needMaterialCheck
=
false
;
bomtime
=
getOperationBOMTime
(
operation
,
chromosome
,
2
);
earliestStartTime
=
Math
.
max
(
earliestStartTime
,
bomtime
);
}
// 正式落排前,再取一次当前机台最后一道工序,保证换型计算基于最新排程结果。
if
(
machineTasks
!=
null
&&
machineTasks
.
size
()>
0
&&
_globalParam
.
is_smoothChangeOver
())
{
lastGeneOnMachine
=
machineTasks
.
get
(
machineTasks
.
size
()-
1
);
}
CopyOnWriteArrayList
<
ScheduleResultDetail
>
geneDetails
=
new
CopyOnWriteArrayList
<>();
// 下面开始生成正式的 geneDetails。
// 与 buildMachinePreview 的区别是:这里得到的结果会继续向下写入 GAScheduleResult,成为真正排程结果。
//if (_globalParam.is_smoothChangeOver()) {
if
(
false
)
{
if
(
_globalParam
.
is_smoothChangeOver
())
{
//是否考虑换型时间
Map
<
Integer
,
Object
>
reslte
=
calculateSetupTime
(
lastGeneOnMachine
,
operation
,
machine
,
earliestStartTime
,
processingTimeTotal
,
_globalParam
.
is_smoothChangeOverInWeek
(),
chromosome
.
getAllOperations
());
setupTime
=(
int
)
reslte
.
get
(
1
);
//换型时间
...
...
@@ -1317,7 +1257,7 @@ public class GeneticDecoder {
CopyOnWriteArrayList
<
TimeSegment
>
AvailableTimeSegment
=
(
CopyOnWriteArrayList
<
TimeSegment
>)
reslte
.
get
(
6
);
Map
<
Integer
,
Object
>
result
=
machineCalculator
.
CreateScheduleResult
(
machine
,
operation
,
processingTimeTotal
,
earliestStartTime
,
AvailableTimeSegment
,
processingTime
,
operation
.
getQuantity
(),
operation
.
getIsInterrupt
()
!=
1
,
setupTime
,
_globalParam
.
is_smoothChangeOverInWeek
(),
setupStartTime
,
isJit
);
AvailableTimeSegment
,
processingTime
,
operation
.
getQuantity
(),
operation
.
getIsInterrupt
()
!=
1
,
setupTime
,
_globalParam
.
is_smoothChangeOverInWeek
(),
setupStartTime
,
true
,
isJit
);
...
...
@@ -1352,7 +1292,10 @@ public class GeneticDecoder {
.
mapToInt
(
ScheduleResultDetail:
:
getEndTime
)
.
max
()
.
orElse
(
0
);
//扣库存
if
(
needMaterialCheck
)
{
EditOperationBOMTime
(
operation
,
chromosome
,
startTime
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
);
}
//换型时间是否占用设备加工时间
//10:00 开始上班 前面的任务:24:00 结束 开始换型 休息时间 10小时
// 换型时间 12小时
...
...
@@ -1363,29 +1306,7 @@ public class GeneticDecoder {
// 准备工时 加入到加工时间里
// 后处理时间 相同任务的前一工序的结束时间+后处理时间 =当前工序最早开工时间
// 正式提交 BOM 校验:
// 1. 按最终 startTime 重新计算一次物料占用,并把状态真正写回;
// 2. 如果提交后的 BOM 时间仍然晚于 startTime,说明机台时间与物料时间没有收敛,需要直接报错。
if
(
commitMaterialCheck
)
{
long
commitStart
=
System
.
nanoTime
();
int
committedBomTime
=
EditOperationBOMTime
(
operation
,
chromosome
,
startTime
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
,
true
);
long
commitElapsed
=
System
.
nanoTime
()
-
commitStart
;
// if (commitElapsed > 200_000_000L) {
// FileHelper.writeLogFile("[PERF] processWithSingleMachine 正式提交BOM慢 opId=" + operationId
// + ", startTime=" + startTime + ", commitBomTime=" + committedBomTime
// + ", 耗时=" + fmtMs(commitElapsed));
// }
bomtime
=
Math
.
max
(
bomtime
,
committedBomTime
);
if
(
committedBomTime
>
startTime
)
{
// throw new IllegalStateException(String.format(
// "工序固定点求解未收敛,operationId=%d, groupId=%d, startTime=%d, bomTime=%d, maxIterations=%d",
// operation.getId(),
// operation.getGroupId(),
// startTime,
// committedBomTime,
// maxSolveIterations));
}
}
GAScheduleResult
result
=
CreateResult
(
operation
,
machine
.
getId
(),
startTime
,
endTime
,
processingTime
,
setupTime
,
preTime
,
teardownTime
,
bomtime
,
geneDetails
,
existingResult
);
...
...
@@ -1400,7 +1321,6 @@ public class GeneticDecoder {
if
(
machineTasks
!=
null
)
{
machineTasks
.
add
(
result
);
}
updateSemiJitTargets
(
operation
,
startTime
,
chromosome
);
scheduleIndexById
.
put
(
operation
.
getId
(),
result
);
// long pwsElapsed = System.nanoTime() - pwsStart;
// if (pwsElapsed > 500_000_000L) {
...
...
@@ -1537,7 +1457,7 @@ if(geneDetails!=null&&geneDetails.size()>0)
// 有换型占用时,需要把换型段和加工段一起拼成完整的试排结果。
CopyOnWriteArrayList
<
TimeSegment
>
AvailableTimeSegment
=
(
CopyOnWriteArrayList
<
TimeSegment
>)
reslte
.
get
(
6
);
Map
<
Integer
,
Object
>
result
=
machineCalculator
.
CreateScheduleResult
(
machine
,
operation
,
previewProcessingTotal
,
previewStart
,
AvailableTimeSegment
,
processingTime
,
operation
.
getQuantity
(),
operation
.
getIsInterrupt
()
!=
1
,
setupTime
,
_globalParam
.
is_smoothChangeOverInWeek
(),
setupStartTime
,
false
);
AvailableTimeSegment
,
processingTime
,
operation
.
getQuantity
(),
operation
.
getIsInterrupt
()
!=
1
,
setupTime
,
_globalParam
.
is_smoothChangeOverInWeek
(),
setupStartTime
,
true
,
false
);
setupTime
=(
int
)
result
.
get
(
1
);
geneDetails
=(
CopyOnWriteArrayList
<
ScheduleResultDetail
>)
result
.
get
(
2
);
...
...
@@ -1561,7 +1481,7 @@ if(geneDetails!=null&&geneDetails.size()>0)
}
// 按机台缓存已排结果,避免固定点迭代期间反复全表扫描 chromosome.getResult()。
p
rivate
CopyOnWriteArrayList
<
GAScheduleResult
>
getMachineTasks
(
long
machineId
,
Chromosome
chromosome
,
p
ublic
CopyOnWriteArrayList
<
GAScheduleResult
>
getMachineTasks
(
long
machineId
,
Chromosome
chromosome
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
)
{
if
(
machineTasksCache
.
containsKey
(
machineId
))
{
return
machineTasksCache
.
get
(
machineId
);
...
...
@@ -1776,7 +1696,7 @@ if(geneDetails!=null&&geneDetails.size()>0)
* 汇总当前工序的物料约束,返回所有原料/半成品中最晚满足的那个时刻。
* 返回值含义是“这道工序最早允许因物料而开工的秒数”。
*/
private
int
getOperationBOMTime
(
Entry
currentOp
,
Chromosome
chromosome
)
{
private
int
getOperationBOMTime
(
Entry
currentOp
,
Chromosome
chromosome
,
int
bomtype
)
{
List
<
OrderMaterialRequirement
>
opboms
=
currentOp
.
getMaterialRequirements
();
if
(
opboms
==
null
||!
_globalParam
.
isIsCheckMp
())
...
...
@@ -1788,258 +1708,72 @@ if(geneDetails!=null&&geneDetails.size()>0)
int
rawTime
=
0
,
sfTime
=
0
;
if
(
opboms
!=
null
&&
!
opboms
.
isEmpty
())
{
// 计算RawTime
Optional
<
LocalDateTime
>
rawDateOpt
=
opboms
.
stream
()
.
filter
(
t
->
"MP"
.
equals
(
t
.
getMaterialTypeName
()))
.
map
(
OrderMaterialRequirement:
:
getUseTime
)
.
filter
(
Objects:
:
nonNull
)
.
max
(
LocalDateTime:
:
compareTo
);
if
(
rawDateOpt
.
isPresent
())
{
rawTime
=
(
int
)
Duration
.
between
(
baseTime
,
rawDateOpt
.
get
()).
getSeconds
();
if
(
bomtype
==
0
||
bomtype
==
1
)
{
Optional
<
LocalDateTime
>
rawDateOpt
=
opboms
.
stream
()
.
filter
(
t
->
"MP"
.
equals
(
t
.
getMaterialTypeName
()))
.
map
(
OrderMaterialRequirement:
:
getUseTime
)
.
filter
(
Objects:
:
nonNull
)
.
max
(
LocalDateTime:
:
compareTo
);
if
(
rawDateOpt
.
isPresent
())
{
rawTime
=
(
int
)
Duration
.
between
(
baseTime
,
rawDateOpt
.
get
()).
getSeconds
();
}
}
if
(
bomtype
==
0
||
bomtype
==
2
)
{
// 计算SFTime
List
<
OrderMaterialRequirement
>
sfBoms
=
opboms
.
stream
()
.
filter
(
t
->
!
"MP"
.
equals
(
t
.
getMaterialTypeName
())
&&
t
.
getProductOrderID
()
!=
null
&&
!
t
.
getProductOrderID
().
isEmpty
())
.
collect
(
Collectors
.
toList
());
// 计算SFTime
List
<
OrderMaterialRequirement
>
sfBoms
=
opboms
.
stream
()
.
filter
(
t
->
!
"MP"
.
equals
(
t
.
getMaterialTypeName
())
&&
t
.
getProductOrderID
()
!=
null
&&
!
t
.
getProductOrderID
().
isEmpty
())
.
collect
(
Collectors
.
toList
());
if
(!
sfBoms
.
isEmpty
()&&
sfBoms
.
size
()>
0
)
{
for
(
OrderMaterialRequirement
sf
:
sfBoms
)
{
for
(
int
orderid
:
sf
.
getProductOrderID
())
{
int
sfTime1
=
0
;
List
<
GAScheduleResult
>
result
=
chromosome
.
getResult
();
List
<
GAScheduleResult
>
oe
=
result
.
stream
()
.
filter
(
t
->
t
.
getGroupId
()
==
orderid
)
.
collect
(
Collectors
.
toList
());
if
(!
oe
.
isEmpty
())
{
int
CkeckLeadTime
=
0
;
if
(
sf
.
getCheckLeadTime
()!=
null
)
{
CkeckLeadTime
=(
int
)
(
sf
.
getCheckLeadTime
()*
24
*
60
);
if
(!
sfBoms
.
isEmpty
()
&&
sfBoms
.
size
()
>
0
)
{
for
(
OrderMaterialRequirement
sf
:
sfBoms
)
{
for
(
int
orderid
:
sf
.
getProductOrderID
())
{
int
sfTime1
=
0
;
List
<
GAScheduleResult
>
result
=
chromosome
.
getResult
();
List
<
GAScheduleResult
>
oe
=
result
.
stream
()
.
filter
(
t
->
t
.
getGroupId
()
==
orderid
)
.
collect
(
Collectors
.
toList
());
if
(!
oe
.
isEmpty
())
{
int
CkeckLeadTime
=
0
;
if
(
sf
.
getCheckLeadTime
()
!=
null
)
{
CkeckLeadTime
=
(
int
)
(
sf
.
getCheckLeadTime
()
*
24
*
60
);
}
sfTime1
=
oe
.
stream
().
mapToInt
(
GAScheduleResult:
:
getEndTime
).
max
().
orElse
(
0
)
+
CkeckLeadTime
;
sf
.
setUseTime
(
baseTime
.
plusSeconds
(
sfTime1
));
}
sfTime1
=
oe
.
stream
().
mapToInt
(
GAScheduleResult:
:
getEndTime
).
max
().
orElse
(
0
)
+
CkeckLeadTime
;
sf
.
setUseTime
(
baseTime
.
plusSeconds
(
sfTime1
));
sfTime
=
Math
.
max
(
sfTime
,
sfTime1
);
}
sfTime
=
Math
.
max
(
sfTime
,
sfTime1
);
}
}
}
Optional
<
LocalDateTime
>
sfDateOpt
=
opboms
.
stream
()
.
filter
(
t
->
!
"MP"
.
equals
(
t
.
getMaterialTypeName
())&&(
t
.
getProductOrderID
()
==
null
||
t
.
getProductOrderID
().
isEmpty
()))
.
map
(
OrderMaterialRequirement:
:
getUseTime
)
.
filter
(
Objects:
:
nonNull
)
.
max
(
LocalDateTime:
:
compareTo
);
if
(
sfDateOpt
.
isPresent
())
{
sfTime
=
Math
.
max
(
sfTime
,
(
int
)
Duration
.
between
(
baseTime
,
sfDateOpt
.
get
()).
getSeconds
());
}
Optional
<
LocalDateTime
>
sfDateOpt
=
opboms
.
stream
()
.
filter
(
t
->
!
"MP"
.
equals
(
t
.
getMaterialTypeName
())
&&
(
t
.
getProductOrderID
()
==
null
||
t
.
getProductOrderID
().
isEmpty
()))
.
map
(
OrderMaterialRequirement:
:
getUseTime
)
.
filter
(
Objects:
:
nonNull
)
.
max
(
LocalDateTime:
:
compareTo
);
if
(
sfDateOpt
.
isPresent
())
{
sfTime
=
Math
.
max
(
sfTime
,
(
int
)
Duration
.
between
(
baseTime
,
sfDateOpt
.
get
()).
getSeconds
());
}
}
}
return
Math
.
max
(
rawTime
,
sfTime
);
}
// 默认走正式提交路径,调用方不传 commitChanges 时认为要把物料状态真实写回。
private
int
EditOperationBOMTime
(
Entry
currentOp
,
Chromosome
chromosome
,
int
earliestStartTime
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
,
Map
<
Integer
,
Entry
>
entryIndexById
,
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
)
{
return
EditOperationBOMTime
(
currentOp
,
chromosome
,
earliestStartTime
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
,
true
);
}
/**
* 按指定 earliestStartTime 重新计算当前工序的 BOM 可开工时间。
* commitChanges=true:正式提交,真实修改物料/订单/排程状态。
* commitChanges=false:只做试算,方法结束后恢复 chromosome 和相关索引缓存。
*/
private
int
EditOperationBOMTime
(
Entry
currentOp
,
Chromosome
chromosome
,
int
earliestStartTime
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
,
Map
<
Integer
,
Entry
>
entryIndexById
,
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
,
boolean
commitChanges
)
{
long
t0
=
System
.
nanoTime
();
List
<
OrderMaterialRequirement
>
opboms
=
currentOp
.
getMaterialRequirements
();
if
(
opboms
==
null
)
{
return
0
;
}
LocalDateTime
earliestStartTime1
=
baseTime
.
plusSeconds
(
earliestStartTime
);
if
(
commitChanges
)
{
// 正式提交模式:直接把当前开工时间对应的物料占用/供应结果写回业务对象。
materialRequirementService
.
EditOperationBOM
(
currentOp
,
chromosome
,
earliestStartTime1
,
this
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
,
baseTime
,
true
);
int
bomTime
=
getOperationBOMTime
(
currentOp
,
chromosome
);
long
elapsed
=
System
.
nanoTime
()
-
t0
;
// if (elapsed > 200_000_000L) {
// FileHelper.writeLogFile("[PERF] EditOperationBOMTime 正式提交慢 opId=" + currentOp.getId()
// + ", 耗时=" + fmtMs(elapsed));
// }
return
bomTime
;
}
long
snapStart
=
System
.
nanoTime
();
TrialDecodeSnapshot
snapshot
=
createTrialDecodeSnapshot
(
currentOp
,
chromosome
);
long
snapElapsed
=
System
.
nanoTime
()
-
snapStart
;
try
{
materialRequirementService
.
EditOperationBOM
(
currentOp
,
chromosome
,
earliestStartTime1
,
this
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
,
baseTime
,
false
);
return
getOperationBOMTime
(
currentOp
,
chromosome
);
}
finally
{
// long restoreStart = System.nanoTime();
restoreTrialDecodeSnapshot
(
snapshot
);
// long restoreElapsed = System.nanoTime() - restoreStart;
// long total = System.nanoTime() - t0;
// if (total > 200_000_000L) {
// FileHelper.writeLogFile("[PERF] EditOperationBOMTime 试算慢 opId=" + currentOp.getId()
// + ", 快照=" + fmtMs(snapElapsed) + ", 恢复=" + fmtMs(restoreElapsed)
// + ", 总耗时=" + fmtMs(total));
// }
}
}
private
TrialDecodeSnapshot
createTrialDecodeSnapshot
(
Entry
currentOp
,
Chromosome
chromosome
)
{
TrialDecodeSnapshot
snapshot
=
new
TrialDecodeSnapshot
();
long
t0
=
System
.
nanoTime
();
if
(
currentOp
.
getMaterialRequirements
()
!=
null
)
{
for
(
OrderMaterialRequirement
requirement
:
currentOp
.
getMaterialRequirements
())
{
snapshot
.
requirementStates
.
add
(
new
RequirementSnapshot
(
requirement
));
snapshot
.
captureStocks
(
chromosome
,
requirement
.
getMaterialId
());
if
(
requirement
.
getReplaceMaterial
()
!=
null
)
{
for
(
OrderMaterialRequirement
replace
:
requirement
.
getReplaceMaterial
())
{
snapshot
.
captureStocks
(
chromosome
,
replace
.
getMaterialId
());
}
}
}
}
// long total = System.nanoTime() - t0;
// if (total > 100_000_000L) {
// FileHelper.writeLogFile("[PERF] createTrialDecodeSnapshot 慢 requirements=" + snapshot.requirementStates.size()
// + ", stocks=" + snapshot.stockStates.size() + ", transit=" + snapshot.transitStates.size()
// + ", total=" + fmtMs(total));
// }
return
snapshot
;
}
private
void
restoreTrialDecodeSnapshot
(
TrialDecodeSnapshot
snapshot
)
{
for
(
RequirementSnapshot
requirementState
:
snapshot
.
requirementStates
)
{
requirementState
.
restore
();
}
for
(
StockSnapshot
stockState
:
snapshot
.
stockStates
)
{
stockState
.
restore
();
}
for
(
MaterialSupplySnapshot
transitState
:
snapshot
.
transitStates
)
{
transitState
.
restore
();
}
}
private
static
class
TrialDecodeSnapshot
{
private
final
List
<
RequirementSnapshot
>
requirementStates
=
new
ArrayList
<>();
private
final
List
<
StockSnapshot
>
stockStates
=
new
ArrayList
<>();
private
final
List
<
MaterialSupplySnapshot
>
transitStates
=
new
ArrayList
<>();
private
final
Set
<
Stock
>
seenStocks
=
Collections
.
newSetFromMap
(
new
IdentityHashMap
<>());
private
final
Set
<
MaterialSupply
>
seenTransit
=
Collections
.
newSetFromMap
(
new
IdentityHashMap
<>());
private
void
captureStocks
(
Chromosome
chromosome
,
String
materialId
)
{
if
(
materialId
==
null
)
{
return
;
}
Material
material
=
chromosome
.
getMaterials
().
stream
()
.
filter
(
t
->
materialId
.
equals
(
t
.
getId
()))
.
findFirst
()
.
orElse
(
null
);
if
(
material
==
null
)
{
return
;
}
if
(
material
.
getMaterialStocks
()
!=
null
)
{
for
(
Stock
stock
:
material
.
getMaterialStocks
())
{
if
(
seenStocks
.
add
(
stock
))
{
stockStates
.
add
(
new
StockSnapshot
(
stock
));
}
}
}
if
(
material
.
getInTransit
()
!=
null
)
{
for
(
MaterialSupply
supply
:
material
.
getInTransit
())
{
if
(
seenTransit
.
add
(
supply
))
{
transitStates
.
add
(
new
MaterialSupplySnapshot
(
supply
));
}
}
}
}
}
private
static
class
RequirementSnapshot
{
private
final
OrderMaterialRequirement
requirement
;
private
final
double
requiredQuantity
;
private
final
double
ypQty
;
private
final
double
qjQty
;
private
final
double
useStock
;
private
final
double
useTransit
;
private
final
LocalDateTime
arrivalTime
;
private
final
LocalDateTime
useTime
;
private
final
LocalDateTime
purchaseStartTime
;
private
final
LocalDateTime
purchaseEndTime
;
private
final
Integer
checkLeadTime
;
private
final
Integer
purchaseTime
;
private
final
List
<
OrderMaterialRequirement
>
replaceMaterial
;
private
RequirementSnapshot
(
OrderMaterialRequirement
requirement
)
{
this
.
requirement
=
requirement
;
this
.
requiredQuantity
=
requirement
.
getRequiredQuantity
();
this
.
ypQty
=
requirement
.
getYpQty
();
this
.
qjQty
=
requirement
.
getQjQty
();
this
.
useStock
=
requirement
.
getUseStock
();
this
.
useTransit
=
requirement
.
getUseTransit
();
this
.
arrivalTime
=
requirement
.
getArrivalTime
();
this
.
useTime
=
requirement
.
getUseTime
();
this
.
purchaseStartTime
=
requirement
.
getPurchaseStartTime
();
this
.
purchaseEndTime
=
requirement
.
getPurchaseEndTime
();
this
.
checkLeadTime
=
requirement
.
getCheckLeadTime
();
this
.
purchaseTime
=
requirement
.
getPurchaseTime
();
this
.
replaceMaterial
=
ProductionDeepCopyUtil
.
deepCopyList
(
requirement
.
getReplaceMaterial
(),
OrderMaterialRequirement
.
class
);
}
private
void
restore
()
{
requirement
.
setRequiredQuantity
(
requiredQuantity
);
requirement
.
setYpQty
(
ypQty
);
requirement
.
setQjQty
(
qjQty
);
requirement
.
setUseStock
(
useStock
);
requirement
.
setUseTransit
(
useTransit
);
requirement
.
setArrivalTime
(
arrivalTime
);
requirement
.
setUseTime
(
useTime
);
requirement
.
setPurchaseStartTime
(
purchaseStartTime
);
requirement
.
setPurchaseEndTime
(
purchaseEndTime
);
requirement
.
setCheckLeadTime
(
checkLeadTime
);
requirement
.
setPurchaseTime
(
purchaseTime
);
requirement
.
setReplaceMaterial
(
replaceMaterial
==
null
?
new
ArrayList
<>()
:
ProductionDeepCopyUtil
.
deepCopyList
(
replaceMaterial
,
OrderMaterialRequirement
.
class
));
}
}
LocalDateTime
earliestStartTime1
=
baseTime
.
plusSeconds
(
earliestStartTime
);
private
static
class
StockSnapshot
{
private
final
Stock
stock
;
private
final
double
usedInventory
;
materialRequirementService
.
EditOperationBOM
(
currentOp
,
chromosome
,
earliestStartTime1
,
this
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
,
baseTime
,
true
);
private
StockSnapshot
(
Stock
stock
)
{
this
.
stock
=
stock
;
this
.
usedInventory
=
stock
.
getUsedInventory
();
}
private
void
restore
()
{
stock
.
setUsedInventory
(
usedInventory
);
}
return
0
;
}
private
static
class
MaterialSupplySnapshot
{
private
final
MaterialSupply
supply
;
private
final
double
quantity
;
private
MaterialSupplySnapshot
(
MaterialSupply
supply
)
{
this
.
supply
=
supply
;
this
.
quantity
=
supply
.
getQuantity
();
}
private
void
restore
()
{
supply
.
setQuantity
(
quantity
);
}
}
public
void
EditorderOperation
(
Chromosome
chromosome
,
int
groupId
,
double
needed
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
,
Map
<
Integer
,
Entry
>
entryIndexById
,
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
){
List
<
Entry
>
orderOps
=
chromosome
.
getAllOperations
().
stream
()
...
...
@@ -2173,6 +1907,9 @@ if(geneDetails!=null&&geneDetails.size()>0)
.
collect
(
Collectors
.
toList
());
int
GroupId
=
0
;
chromosome
.
getReOrderids
().
add
(
groupid
);
for
(
Entry
entry
:
sourceOps
)
{
if
(!
entry
.
isNewCreate
())
...
...
@@ -2183,6 +1920,10 @@ if(geneDetails!=null&&geneDetails.size()>0)
entry
.
getTargetFinishedOperationId
().
remove
(
orderMaterialRequirement
.
getOperationId
());
continue
;
}
orderMaterialRequirement
.
setProductOrderID
(
null
);
List
<
OrderMaterialRequirement
>
orderMaterialRequirements
=
entry
.
getMaterialRequirements
().
stream
().
filter
(
t
->
!
"MP"
.
equals
(
t
.
getMaterialTypeName
())
&&
t
.
getProductOrderID
()
!=
null
&&
!
t
.
getProductOrderID
().
isEmpty
()
).
collect
(
Collectors
.
toList
());
...
...
src/main/java/com/aps/service/Algorithm/GeneticDecoderBom.java
View file @
31d2cb46
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.GAScheduleResult
;
import
com.aps.entity.Algorithm.OperationDependency
;
import
com.aps.entity.Algorithm.OrderMaterialRequirement
;
import
com.aps.entity.basic.Entry
;
import
com.aps.entity.basic.Machine
;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.entity.Algorithm.*
;
import
com.aps.entity.basic.*
;
import
com.aps.service.plan.MachineSchedulerService
;
import
java.time.Duration
;
import
java.time.LocalDateTime
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.*
;
import
java.util.concurrent.CopyOnWriteArrayList
;
import
java.util.stream.Collectors
;
/**
* 作者:佟礼
* 时间:2026-04-28
*/
public
class
GeneticDecoderBom
{
/**
* 计算成品可用时间(用于半成品排程)
*
* @param semiFinishedOperation 半成品工序
* @param chromosome 染色体
* @param baseTime 基准时间
* @param machineTasksCache 设备任务缓存
* @param entryIndexById 工序索引
* @param scheduleIndexById 排程索引
* @return 成品可用时间(秒)
*/
public
int
calculateFinishedAvailableTime
(
Entry
semiFinishedOperation
,
Chromosome
chromosome
,
LocalDateTime
baseTime
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
,
Map
<
Integer
,
Entry
>
entryIndexById
,
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
)
{
// 如果没有关联的成品工序,返回0
if
(
semiFinishedOperation
.
getTargetFinishedOperationId
()
==
null
||
semiFinishedOperation
.
getTargetFinishedOperationId
().
isEmpty
())
{
return
0
;
public
class
GeneticDecoderBom
{
private
MachineCalculator
machineCalculator
;
private
MaterialRequirementService
materialRequirementService
;
private
LocalDateTime
baseTime
;
GeneticDecoderBom
(
LocalDateTime
_baseTime
,
MachineCalculator
_machineCalculator
,
MaterialRequirementService
_materialRequirementService
)
{
baseTime
=
_baseTime
;
machineCalculator
=
_machineCalculator
;
materialRequirementService
=
_materialRequirementService
;
}
public
int
computeSemiFinishedAnchor
(
int
semiGroupId
,
Map
<
Integer
,
List
<
Entry
>>
entrysBygroupId
,
Map
<
String
,
OpMachine
>
opMachineKeyMap
,
Chromosome
chromosome
,
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
)
{
List
<
Entry
>
semiOps
=
entrysBygroupId
.
get
(
semiGroupId
);
if
(
semiOps
==
null
||
semiOps
.
isEmpty
())
return
0
;
int
currentGroupId
=
semiGroupId
;
List
<
Integer
>
intermediateGroupIds
=
new
ArrayList
<>();
intermediateGroupIds
.
add
(
semiGroupId
);
boolean
isFORWARD
=
false
;
while
(
true
)
{
List
<
Entry
>
ops
=
entrysBygroupId
.
get
(
currentGroupId
);
Entry
lastOp
=
ops
.
stream
()
.
max
(
Comparator
.
comparingInt
(
Entry:
:
getSequence
)).
orElse
(
null
);
if
(
lastOp
==
null
||
lastOp
.
getTargetFinishedOperationId
()
==
null
||
lastOp
.
getTargetFinishedOperationId
().
isEmpty
())
break
;
int
targetOpId
=
lastOp
.
getTargetFinishedOperationId
().
get
(
0
);
int
targetGroupId
=
findGroupForOperation
(
targetOpId
,
entrysBygroupId
);
if
(
targetGroupId
<
0
)
break
;
List
<
Entry
>
targetOps
=
entrysBygroupId
.
get
(
targetGroupId
);
if
(
targetOps
==
null
||
targetOps
.
isEmpty
())
break
;
Entry
firstTargetOp
=
targetOps
.
get
(
0
);
if
(
Entry
.
SchedulingMode
.
FORWARD
.
name
().
equals
(
firstTargetOp
.
getSchedulingMode
()))
{
int
rootStart
=
forwardEstimateToOperation
(
targetOpId
,
targetGroupId
,
0
,
entrysBygroupId
,
opMachineKeyMap
,
chromosome
,
scheduleIndexById
,
machineTasksCache
,
false
);
List
<
Integer
>
chainGroupIds
=
new
ArrayList
<>(
intermediateGroupIds
);
chainGroupIds
.
add
(
targetGroupId
);
rootStart
=
correctByRawMaterialStockForChain
(
chainGroupIds
,
targetGroupId
,
targetOpId
,
rootStart
,
entrysBygroupId
,
chromosome
);
int
anchor
=
rootStart
;
for
(
int
i
=
intermediateGroupIds
.
size
()
-
1
;
i
>=
0
;
i
--)
{
int
start1
=
forwardEstimateToOperation
(
0
,
intermediateGroupIds
.
get
(
i
),
anchor
,
entrysBygroupId
,
opMachineKeyMap
,
chromosome
,
scheduleIndexById
,
machineTasksCache
,
true
);
if
(
start1
<
0
)
{
isFORWARD
=
true
;
break
;
}
if
(
i
!=
0
)
{
anchor
-=
start1
;
if
(
anchor
<
0
)
{
isFORWARD
=
true
;
break
;
}
}
else
{
if
(
anchor
-
start1
<
0
)
{
isFORWARD
=
true
;
break
;
}
}
}
if
(
isFORWARD
)
{
for
(
int
i
=
intermediateGroupIds
.
size
()
-
1
;
i
>=
0
;
i
--)
{
List
<
Entry
>
ops1
=
entrysBygroupId
.
get
(
intermediateGroupIds
.
get
(
i
));
ops1
.
forEach
(
t
->
t
.
setSchedulingMode
(
Entry
.
SchedulingMode
.
FORWARD
.
name
()));
}
return
-
1
;
}
return
Math
.
max
(
0
,
anchor
);
}
intermediateGroupIds
.
add
(
targetGroupId
);
currentGroupId
=
targetGroupId
;
}
return
0
;
}
private
int
findGroupForOperation
(
int
opId
,
Map
<
Integer
,
List
<
Entry
>>
entrysBygroupId
)
{
for
(
Map
.
Entry
<
Integer
,
List
<
Entry
>>
e
:
entrysBygroupId
.
entrySet
())
{
for
(
Entry
op
:
e
.
getValue
())
{
if
(
op
.
getId
()
==
opId
)
return
e
.
getKey
();
}
}
return
-
1
;
}
private
int
forwardEstimateToOperation
(
int
targetOpId
,
int
groupId
,
int
startSecond
,
Map
<
Integer
,
List
<
Entry
>>
entrysBygroupId
,
Map
<
String
,
OpMachine
>
opMachineKeyMap
,
Chromosome
chromosome
,
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
,
boolean
isJit
)
{
List
<
Entry
>
ops
=
entrysBygroupId
.
get
(
groupId
);
if
(
ops
==
null
)
return
0
;
List
<
Entry
>
sorted
=
new
ArrayList
<>();
if
(
isJit
)
{
sorted
=
ops
.
stream
()
.
sorted
(
Comparator
.
comparingInt
(
Entry:
:
getSequence
).
reversed
())
.
collect
(
Collectors
.
toList
());
}
else
{
sorted
=
ops
.
stream
()
.
sorted
(
Comparator
.
comparingInt
(
Entry:
:
getSequence
))
.
collect
(
Collectors
.
toList
());
}
Map
<
Long
,
Machine
>
machineById
=
chromosome
.
getMachines
().
stream
()
.
collect
(
Collectors
.
toMap
(
Machine:
:
getId
,
m
->
m
,
(
a
,
b
)
->
a
));
int
nextAvailableStart
=
startSecond
;
Map
<
Long
,
Integer
>
machineLastEndInOrder
=
new
HashMap
<>();
int
maxFinishedTime
=
0
;
for
(
Entry
op
:
sorted
)
{
String
key
=
groupId
+
"_"
+
op
.
getSequence
();
OpMachine
mo
=
opMachineKeyMap
.
get
(
key
);
if
(
mo
==
null
)
continue
;
Long
mId
=
mo
.
getMachineId
();
Machine
machine
=
machineById
.
get
(
mId
);
// 遍历所有关联的成品工序,计算每个的可用时间,取最大值
for
(
Integer
finishedOperationId
:
semiFinishedOperation
.
getTargetFinishedOperationId
())
{
Entry
finishedOperation
=
entryIndexById
.
get
(
finishedOperationId
);
if
(
finishedOperation
==
null
)
{
int
start
=
nextAvailableStart
;
int
end
=
start
;
// 该工序已排产 → 直接用真实结束时间作为后续工序的基准
GAScheduleResult
prevResult
=
scheduleIndexById
!=
null
?
scheduleIndexById
.
get
(
op
.
getId
())
:
null
;
if
(
prevResult
!=
null
)
{
int
scheduledEnd
=
prevResult
.
getEndTime
();
start
=
Math
.
max
(
start
,
scheduledEnd
);
if
(
op
.
getId
()
==
targetOpId
)
return
prevResult
.
getStartTime
();
machineLastEndInOrder
.
put
(
mId
,
scheduledEnd
);
nextAvailableStart
=
Math
.
max
(
nextAvailableStart
,
scheduledEnd
);
continue
;
}
// 计算该成品工序的可用时间
int
finishedAvailableTime
=
calculateSingleFinishedAvailableTime
(
finishedOperation
,
chromosome
,
baseTime
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
);
if
(!
isJit
)
{
// 同一订单内该设备已有工序的结束时间
Integer
lastInOrder
=
machineLastEndInOrder
.
get
(
mId
);
if
(
lastInOrder
!=
null
)
start
=
Math
.
max
(
start
,
lastInOrder
);
maxFinishedTime
=
Math
.
min
(
maxFinishedTime
,
finishedAvailableTime
);
}
// 该设备上已排产的其他任务(半成品占位)的结束时间
if
(
machineTasksCache
!=
null
)
{
CopyOnWriteArrayList
<
GAScheduleResult
>
tasks
=
machineTasksCache
.
get
(
mId
);
if
(
tasks
!=
null
)
{
for
(
GAScheduleResult
t
:
tasks
)
{
start
=
Math
.
max
(
start
,
t
.
getEndTime
());
}
}
}
}
return
maxFinishedTime
;
}
int
rawDur
=
0
;
if
(
op
.
getConstTime
()==
1
||
machine
.
getCapacityTypeName
().
equals
(
"Infinite"
))
{
if
(
op
.
getQuantity
()==
0
)
{
rawDur
=
0
;
}
else
{
/**
* 计算单个成品工序的可用时间
*
* @param finishedOperation 成品工序
* @param chromosome 染色体
* @param baseTime 基准时间
* @param machineTasksCache 设备任务缓存
* @param entryIndexById 工序索引
* @param scheduleIndexById 排程索引
* @return 成品工序可用时间(秒)
*/
private
int
calculateSingleFinishedAvailableTime
(
Entry
finishedOperation
,
Chromosome
chromosome
,
LocalDateTime
baseTime
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
,
Map
<
Integer
,
Entry
>
entryIndexById
,
Map
<
Integer
,
GAScheduleResult
>
scheduleIndexById
)
{
int
maxTime
=
0
;
// 1. 计算成品前一序时间
int
prevOperationEndTime
=
0
;
if
(!
finishedOperation
.
getPrevEntryIds
().
isEmpty
())
{
for
(
OperationDependency
prevOp
:
finishedOperation
.
getPrevEntryIds
())
{
GAScheduleResult
prevResult
=
scheduleIndexById
.
get
(
prevOp
.
getPrevOperationId
());
if
(
prevResult
!=
null
)
{
prevOperationEndTime
=
Math
.
max
(
prevOperationEndTime
,
prevResult
.
getEndTime
());
rawDur
=
(
int
)
Math
.
ceil
(
mo
.
getProcessingTime
());
}
}
else
{
rawDur
=
(
int
)
Math
.
ceil
(
mo
.
getRuntime
().
doubleValue
()
/
mo
.
getSingleOut
().
doubleValue
()
*
op
.
getQuantity
());
}
}
//成品时间一定晚于prevOperationEndTime
//半成品库存只能用
maxTime
=
Math
.
max
(
maxTime
,
prevOperationEndTime
);
if
(
machine
!=
null
&&!
machine
.
getCapacityTypeName
().
equals
(
"Infinite"
))
{
CopyOnWriteArrayList
<
GAScheduleResult
>
machineTasks
=
getMachineTasks
(
mId
,
chromosome
,
machineTasksCache
);
// 2. 计算成品当前序所用设备最后一个任务的结束时间
Long
machineId
=
finishedOperation
.
getSelectMachineID
();
if
(
machineId
==
null
&&
finishedOperation
.
getMachineOptions
()
!=
null
&&
!
finishedOperation
.
getMachineOptions
().
isEmpty
())
{
// 如果设备还未选择,使用第一个可用设备
machineId
=
finishedOperation
.
getMachineOptions
().
get
(
0
).
getMachineId
();
}
CopyOnWriteArrayList
<
ScheduleResultDetail
>
geneDetails
=
estimateCalendarAwareDuration
(
machine
,
op
,
machineTasks
,
start
,
rawDur
,
mo
.
getProcessingTime
(),
isJit
);
if
(
geneDetails
!=
null
)
{
start
=
geneDetails
.
stream
()
.
mapToInt
(
ScheduleResultDetail:
:
getStartTime
)
.
min
()
.
orElse
(
0
);
end
=
geneDetails
.
stream
()
.
mapToInt
(
ScheduleResultDetail:
:
getEndTime
)
.
max
()
.
orElse
(
0
);
}
else
{
return
-
1
;
}
}
else
{
if
(
isJit
)
{
start
=
start
-
rawDur
;
end
=
start
;
}
else
{
start
=
end
;
end
=
start
+
rawDur
;
}
}
if
(
op
.
getId
()
==
targetOpId
)
return
start
;
if
(
machineId
!=
null
)
{
Long
machineId1
=
machineId
;
Machine
machine
=
chromosome
.
getMachines
().
stream
().
filter
(
t
->
t
.
getId
()==
machineId1
).
findFirst
().
orElse
(
null
);
GAScheduleResult
machineTask
=
machine
.
getLastGene
();
if
(
machineTask
!=
null
)
{
int
lastEndTime
=
machineTask
.
getEndTime
();
maxTime
=
Math
.
max
(
maxTime
,
lastEndTime
);
machineLastEndInOrder
.
put
(
mId
,
end
);
if
(
isJit
)
{
nextAvailableStart
=
Math
.
min
(
nextAvailableStart
,
start
);
}
else
{
nextAvailableStart
=
Math
.
max
(
nextAvailableStart
,
end
);
}
}
// 3. 原材料0库存计算齐套最大时间(只计算原材料,不计算半成品)
int
rawMaterialBomTime
=
calculateRawMaterialBomTimeForFinished
(
finishedOperation
,
chromosome
);
maxTime
=
Math
.
max
(
maxTime
,
rawMaterialBomTime
);
// targetOpId 不在该订单工序内:返回前序工序全部处理后的最早可用开工时间
return
nextAvailableStart
;
}
private
CopyOnWriteArrayList
<
ScheduleResultDetail
>
estimateCalendarAwareDuration
(
Machine
machine
,
Entry
operation
,
CopyOnWriteArrayList
<
GAScheduleResult
>
machineTasks
,
int
startSecond
,
int
rawDurationSecond
,
double
processingTime
,
boolean
isJit
)
{
CopyOnWriteArrayList
<
ScheduleResultDetail
>
geneDetails
=
new
CopyOnWriteArrayList
<>();
return
maxTime
;
geneDetails
=
machineCalculator
.
getNextAvailableTime
(
machine
,
operation
,
startSecond
,
-
1
,
rawDurationSecond
,
machineTasks
,
operation
.
getIsInterrupt
()!=
1
,
true
,
processingTime
,
operation
.
getQuantity
(),
false
,
isJit
);
return
geneDetails
;
}
/**
* 计算成品工序的原材料齐套时间(只计算原材料MP,不计算半成品)
*/
private
int
calculateRawMaterialBomTimeForFinished
(
Entry
finishedOperation
,
Chromosome
chromosome
)
{
List
<
OrderMaterialRequirement
>
materialReqs
=
finishedOperation
.
getMaterialRequirements
();
if
(
materialReqs
==
null
)
{
return
0
;
public
CopyOnWriteArrayList
<
GAScheduleResult
>
getMachineTasks
(
long
machineId
,
Chromosome
chromosome
,
Map
<
Long
,
CopyOnWriteArrayList
<
GAScheduleResult
>>
machineTasksCache
)
{
if
(
machineTasksCache
.
containsKey
(
machineId
))
{
return
machineTasksCache
.
get
(
machineId
);
}
CopyOnWriteArrayList
<
GAScheduleResult
>
machineTasks
=
chromosome
.
getResult
().
stream
()
.
filter
(
t
->
t
.
getMachineId
()
==
machineId
)
.
sorted
(
Comparator
.
comparingInt
(
GAScheduleResult:
:
getStartTime
))
.
collect
(
Collectors
.
toCollection
(
CopyOnWriteArrayList:
:
new
));
machineTasksCache
.
put
(
machineId
,
machineTasks
);
return
machineTasks
;
}
private
int
correctByRawMaterialStockForChain
(
List
<
Integer
>
chainGroupIds
,
int
pfGroupId
,
int
pfOpId
,
int
estimatedStartTime
,
Map
<
Integer
,
List
<
Entry
>>
entrysBygroupId
,
Chromosome
chromosome
)
{
List
<
Material
>
materials
=
chromosome
.
getMaterials
();
if
(
materials
==
null
||
materials
.
isEmpty
())
return
estimatedStartTime
;
List
<
OrderMaterialRequirement
>
remove
=
new
ArrayList
<>();
int
maxTime
=
0
;
Map
<
String
,
OrderMaterialRequirement
>
totalNeededByMaterial
=
new
HashMap
<>()
;
for
(
OrderMaterialRequirement
req
:
materialReqs
)
{
if
(
"MP"
.
equals
(
req
.
getMaterialTypeName
()))
{
// 只计算原材料
// 计算原材料采购提前期
int
purchaseTime
=
req
.
getPurchaseTime
()
!=
null
?
req
.
getPurchaseTime
()
:
0
;
int
checkLeadTime
=
req
.
getCheckLeadTime
()
!=
null
?
req
.
getCheckLeadTime
()
:
0
;
int
totalDays
=
purchaseTime
+
checkLeadTime
;
int
totalSeconds
=
totalDays
*
24
*
3600
;
maxTime
=
Math
.
max
(
maxTime
,
totalSeconds
);
List
<
Entry
>
pfops
=
entrysBygroupId
.
get
(
pfGroupId
);
for
(
Entry
op
:
pfops
)
{
if
(
op
.
getMaterialRequirements
()
==
null
)
continue
;
if
(
pfOpId
!=
op
.
getId
())
{
continue
;
}
for
(
OrderMaterialRequirement
req
:
op
.
getMaterialRequirements
())
{
if
(!
"MP"
.
equals
(
req
.
getMaterialTypeName
()))
{
OrderMaterialRequirement
reqq
=
totalNeededByMaterial
.
get
(
req
.
getMaterialId
());
if
(
reqq
!=
null
)
{
double
allneeded
=
req
.
getSpentQty
()
/
req
.
getMainQty
()
*
op
.
getQuantity
();
allneeded
=
reqq
.
getRequiredQuantity
()
+
allneeded
;
reqq
.
setRequiredQuantity
(
allneeded
);
reqq
.
setQjQty
(
allneeded
);
}
else
{
OrderMaterialRequirement
reqq1
=
ProductionDeepCopyUtil
.
deepCopy
(
req
);
double
allneeded
=
req
.
getSpentQty
()
/
req
.
getMainQty
()
*
op
.
getQuantity
();
reqq1
.
setRequiredQuantity
(
allneeded
);
reqq1
.
setQjQty
(
allneeded
);
totalNeededByMaterial
.
put
(
req
.
getMaterialId
(),
reqq1
);
}
}
}
}
//结合库存计算半成品生产数量,因为可能会修改生产数量所以和原材料分开
materialRequirementService
.
CalBom
(
chromosome
,
0
,
totalNeededByMaterial
,
materials
,
baseTime
.
plusSeconds
(
estimatedStartTime
)
,
false
,
remove
,
entrysBygroupId
,
true
);
totalNeededByMaterial
.
clear
();
for
(
int
groupId
:
chainGroupIds
)
{
List
<
Entry
>
ops
=
entrysBygroupId
.
get
(
groupId
);
if
(
ops
==
null
)
continue
;
for
(
Entry
op
:
ops
)
{
if
(
op
.
getMaterialRequirements
()
==
null
)
continue
;
if
(
pfGroupId
==
op
.
getGroupId
()&&
pfOpId
!=
op
.
getId
())
{
continue
;
}
for
(
OrderMaterialRequirement
req
:
op
.
getMaterialRequirements
())
{
if
(!
"MP"
.
equals
(
req
.
getMaterialTypeName
()))
continue
;
OrderMaterialRequirement
reqq
=
totalNeededByMaterial
.
get
(
req
.
getMaterialId
());
if
(
reqq
!=
null
)
{
double
allneeded
=
req
.
getSpentQty
()
/
req
.
getMainQty
()
*
op
.
getQuantity
();
allneeded
=
reqq
.
getRequiredQuantity
()+
allneeded
;
reqq
.
setRequiredQuantity
(
allneeded
);
reqq
.
setQjQty
(
allneeded
);
}
else
{
OrderMaterialRequirement
reqq1
=
ProductionDeepCopyUtil
.
deepCopy
(
req
);
double
allneeded
=
req
.
getSpentQty
()
/
req
.
getMainQty
()
*
op
.
getQuantity
();
reqq1
.
setRequiredQuantity
(
allneeded
);
reqq1
.
setQjQty
(
allneeded
);
totalNeededByMaterial
.
put
(
req
.
getMaterialId
(),
reqq1
);
}
}
}
}
return
maxTime
;
LocalDateTime
estimatedStartTime1
=
materialRequirementService
.
CalBom
(
chromosome
,
0
,
totalNeededByMaterial
,
materials
,
baseTime
.
plusSeconds
(
estimatedStartTime
)
,
false
,
remove
,
entrysBygroupId
,
false
);
int
rawTime
=
(
int
)
Duration
.
between
(
baseTime
,
estimatedStartTime1
).
getSeconds
();
return
Math
.
max
(
estimatedStartTime
,
rawTime
);
}
}
src/main/java/com/aps/service/Algorithm/MachineCalculator.java
View file @
31d2cb46
...
...
@@ -76,7 +76,7 @@ public class MachineCalculator {
public
Map
<
Integer
,
Object
>
CreateScheduleResult
(
Machine
machine
,
Entry
operation
,
int
processingTime
,
int
proposedStartTime
,
CopyOnWriteArrayList
<
TimeSegment
>
timeSegments
,
double
oneTime
,
double
quantity
,
boolean
isInterrupt
,
int
changeOvertTime
,
boolean
changeOverInWeek
,
int
setupStartTime
,
boolean
isJit
)
{
,
boolean
isInterrupt
,
int
changeOvertTime
,
boolean
changeOverInWeek
,
int
setupStartTime
,
boolean
is
lockMachineTime
,
boolean
is
Jit
)
{
LocalDateTime
startTime
=
baseTime
.
plus
(
proposedStartTime
,
ChronoUnit
.
SECONDS
);
...
...
@@ -167,7 +167,7 @@ public class MachineCalculator {
times
=
CaldScheduleResult
(
machine
,
operation
,
processingTime
,
startTime
,
timeSegments
,
oneTime
,
quantity
,
isJit
timeSegments
,
oneTime
,
quantity
,
is
lockMachineTime
,
is
Jit
);
}
else
{
...
...
@@ -238,7 +238,7 @@ public class MachineCalculator {
.
collect
(
Collectors
.
toCollection
(
CopyOnWriteArrayList:
:
new
));
times
=
CaldScheduleResult
(
machine
,
operation
,
processingTime
,
startTime
,
timeSegments1
,
oneTime
,
quantity
,
isJit
);
timeSegments1
,
oneTime
,
quantity
,
is
lockMachineTime
,
is
Jit
);
}
else
{
double
e
=
(
double
)
processingTime
/
slot
.
getEfficiency
();
...
...
@@ -285,6 +285,18 @@ public class MachineCalculator {
CopyOnWriteArrayList
<
ScheduleResultDetail
>
times
=
new
CopyOnWriteArrayList
<>();
if
(
operation
.
getQuantity
()==
0
)
{
ScheduleResultDetail
time
=
new
ScheduleResultDetail
();
time
.
setKey
(
""
);
time
.
setStartTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
currentTime
));
time
.
setEndTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
currentTime
));
time
.
setOneTime
(
oneTime
);
time
.
setQuantity
(
quantity
);
times
.
add
(
time
);
return
times
;
}
TimeSegment
slot
=
GetCurrentOrNextShift
(
machine
,
currentTime
,
prevtime
,
checkprevtime
,
isJit
);
if
(
slot
==
null
)
return
times
;
LocalDateTime
startCandidate
=
null
;
...
...
@@ -333,10 +345,12 @@ public class MachineCalculator {
times
.
add
(
time
);
CopyOnWriteArrayList
<
TimeSegment
>
usedSegments
=
RemoveMachineAvailable
(
machine
,
time
,
slot
);
if
(
usedSegments
!=
null
&&
usedSegments
.
size
()
>
0
)
{
machine
.
getAvailability
().
addAll
(
usedSegments
);
machine
.
getAvailability
().
sort
(
Comparator
.
comparing
(
TimeSegment:
:
getStart
));
if
(
islockMachineTime
)
{
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
;
}
...
...
@@ -426,10 +440,12 @@ public class MachineCalculator {
CopyOnWriteArrayList
<
ScheduleResultDetail
>
times
=
new
CopyOnWriteArrayList
<>();
CopyOnWriteArrayList
<
TimeSegment
>
timeSegments
=
findAvailableSegments
(
machine
,
currentTime
,
machineTasks
,
remainingTime
,
isInterrupt
,
isJit
);
if
(
timeSegments
==
null
||
timeSegments
.
isEmpty
())
{
return
null
;
}
times
=
CaldScheduleResult
(
machine
,
operation
,
processingTime
,
currentTime
,
timeSegments
,
oneTime
,
quantity
,
isJit
timeSegments
,
oneTime
,
quantity
,
is
lockMachineTime
,
is
Jit
);
// int estimateIndex= (int) Math.ceil(remainingTime / (double) ONE_DAY_MINUTES);
...
...
@@ -472,7 +488,7 @@ public class MachineCalculator {
private
CopyOnWriteArrayList
<
ScheduleResultDetail
>
CaldScheduleResult
(
Machine
machine
,
Entry
operation
,
int
processingTime
,
LocalDateTime
currentTime
,
CopyOnWriteArrayList
<
TimeSegment
>
timeSegments
,
double
oneTime
,
double
quantity
,
boolean
isJit
)
{
,
boolean
islockMachineTime
,
boolean
isJit
)
{
int
remainingTime
=
processingTime
;
CopyOnWriteArrayList
<
ScheduleResultDetail
>
times
=
new
CopyOnWriteArrayList
<>();
...
...
@@ -480,16 +496,12 @@ public class MachineCalculator {
int
estimateIndex
=
(
int
)
Math
.
ceil
(
remainingTime
/
(
double
)
ONE_DAY_MINUTES
);
CopyOnWriteArrayList
<
TimeSegment
>
timeSegments1
=
null
;
if
(
estimateIndex
>
10
)
{
timeSegments1
=
getEnoughSegmentsByEstimateIndex
(
timeSegments
,
currentTime
,
remainingTime
,
isJit
);
if
(
timeSegments1
.
size
()==
2
)
{
timeSegments1
=
getEnoughSegmentsByEstimateIndex
(
timeSegments
,
currentTime
,
remainingTime
,
isJit
);
int
i
=
0
;
}
}
if
(
timeSegments1
==
null
)
{
...
...
@@ -503,10 +515,11 @@ public class MachineCalculator {
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
);
if
(
islockMachineTime
)
{
CopyOnWriteArrayList
<
TimeSegment
>
usedSegments1
=
RemoveMachineAvailable
(
machine
,
time
,
shift
);
if
(
usedSegments1
!=
null
&&
usedSegments1
.
size
()
>
0
)
{
usedSegments
.
addAll
(
usedSegments1
);
}
}
i
++;
}
...
...
@@ -516,13 +529,13 @@ public class MachineCalculator {
machine
.
getAvailability
().
sort
(
Comparator
.
comparing
(
TimeSegment:
:
getStart
));
}
}
else
{
times
=
CaldScheduleResultDetail
(
timeSegments1
,
machine
,
operation
,
currentTime
,
remainingTime
,
oneTime
,
isJit
);
times
=
CaldScheduleResultDetail
(
timeSegments1
,
machine
,
operation
,
currentTime
,
remainingTime
,
oneTime
,
is
lockMachineTime
,
is
Jit
);
}
return
times
;
}
private
CopyOnWriteArrayList
<
ScheduleResultDetail
>
CaldScheduleResultDetail
(
CopyOnWriteArrayList
<
TimeSegment
>
timeSegments
,
Machine
machine
,
Entry
operation
,
LocalDateTime
st
,
int
remainingTime
,
double
oneTime
,
boolean
isJit
)
private
CopyOnWriteArrayList
<
ScheduleResultDetail
>
CaldScheduleResultDetail
(
CopyOnWriteArrayList
<
TimeSegment
>
timeSegments
,
Machine
machine
,
Entry
operation
,
LocalDateTime
st
,
int
remainingTime
,
double
oneTime
,
boolean
is
lockMachineTime
,
boolean
is
Jit
)
{
int
processable1
=(
int
)
calculateTotalAvailableSecond
(
timeSegments
,
st
,
isJit
);
...
...
@@ -538,19 +551,16 @@ public class MachineCalculator {
remainingTime
=(
int
)
outMap
.
get
(
1
);
ScheduleResultDetail
time1
=(
ScheduleResultDetail
)
outMap
.
get
(
2
);
times
.
add
(
time1
);
CopyOnWriteArrayList
<
TimeSegment
>
usedSegments1
=
RemoveMachineAvailable
(
machine
,
time1
,
shiftfrist
);
if
(
usedSegments1
!=
null
&&
usedSegments1
.
size
()
>
0
)
{
usedSegments
.
addAll
(
usedSegments1
);
if
(
islockMachineTime
)
{
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
));
if
(
timeSegments2
==
null
||
timeSegments2
.
size
()==
0
)
{
int
i
=
0
;
}
LocalDateTime
effectiveStart
=
timeSegments2
.
get
(
0
).
getStart
();
LocalDateTime
effectiveend
=
timeSegments2
.
get
(
timeSegments2
.
size
()-
1
).
getEnd
();
...
...
@@ -570,8 +580,10 @@ if(timeSegments2==null||timeSegments2.size()==0)
time
.
setOneTime
(
oneTime
);
time
.
setUsedSegment
(
timeSegments2
);
timeSegments2
.
forEach
(
t
->
t
.
setUsed
(
true
));
remainingTime
-=
processable
;
if
(
islockMachineTime
)
{
timeSegments2
.
forEach
(
t
->
t
.
setUsed
(
true
));
remainingTime
-=
processable
;
}
times
.
add
(
time
);
...
...
@@ -584,14 +596,16 @@ if(timeSegments2==null||timeSegments2.size()==0)
ScheduleResultDetail
timelast
=(
ScheduleResultDetail
)
outMaplast
.
get
(
2
);
times
.
add
(
timelast
);
CopyOnWriteArrayList
<
TimeSegment
>
usedSegments2
=
RemoveMachineAvailable
(
machine
,
timelast
,
shiftlast
);
if
(
usedSegments2
!=
null
&&
usedSegments2
.
size
()
>
0
)
{
usedSegments
.
addAll
(
usedSegments2
);
}
if
(
islockMachineTime
)
{
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
));
if
(
usedSegments
!=
null
&&
usedSegments
.
size
()
>
0
)
{
machine
.
getAvailability
().
addAll
(
usedSegments
);
machine
.
getAvailability
().
sort
(
Comparator
.
comparing
(
TimeSegment:
:
getStart
));
}
}
return
times
;
...
...
@@ -1060,7 +1074,7 @@ if(timeSegments2==null||timeSegments2.size()==0)
if
(!
requireContinuous
||
requiredMinutes
<=
0
)
{
return
baseValidSegments
;
}
//不可中断,中间不能休息
if
(
isJit
)
{
...
...
src/main/java/com/aps/service/Algorithm/MaterialRequirementService.java
View file @
31d2cb46
...
...
@@ -20,6 +20,7 @@ import org.springframework.util.CollectionUtils;
import
java.math.BigDecimal
;
import
java.math.RoundingMode
;
import
java.time.Duration
;
import
java.time.LocalDateTime
;
import
java.util.*
;
import
java.util.concurrent.CopyOnWriteArrayList
;
...
...
@@ -141,10 +142,7 @@ public class MaterialRequirementService {
List
<
Entry
>
Operations
=
_allOperations
.
stream
().
filter
(
t
->
t
.
getOrderId
()
!=
null
)
.
filter
(
t
->
t
.
getOrderId
().
equals
(
orderId
))
.
collect
(
Collectors
.
toList
());
if
(
Operations
==
null
)
{
int
i
=
1
;
}
for
(
Entry
operation
:
Operations
)
{
List
<
Routingsupporting
>
MaterialRequirement_entrys
=
routingsupportings
.
stream
()
.
filter
(
t
->
t
.
getRoutingDetailId
().
equals
(
operation
.
getRoutingDetailId
()))
...
...
@@ -1033,11 +1031,11 @@ if(demand==null)
return
new
BOMBuildResult
(
materialRequirements
,
_childorders
,
_newEntrys
);
}
private
OrderMaterialRequirement
MaterialStock
(
Material
material
,
String
materialId
,
String
orderId
,
String
childorderId
,
Entry
operation
,
double
allneeded
,
double
needed
,
LocalDateTime
earliestStartTime
,
boolean
commitChanges
)
{
private
OrderMaterialRequirement
MaterialStock
(
Material
material
,
String
materialId
,
String
orderId
,
String
childorderId
,
int
operationId
,
double
allneeded
,
double
needed
,
LocalDateTime
earliestStartTime
,
boolean
commitChanges
)
{
OrderMaterialRequirement
orderMaterial
=
new
OrderMaterialRequirement
();
orderMaterial
.
setOrderId
(
orderId
);
orderMaterial
.
setOperationId
(
operation
.
getId
()
);
orderMaterial
.
setOperationId
(
operation
Id
);
orderMaterial
.
setChildOrderId
(
StringUtils
.
isBlank
(
childorderId
)
?
orderId
:
childorderId
);
orderMaterial
.
setRequiredQuantity
(
allneeded
);
orderMaterial
.
setQjQty
(
allneeded
);
...
...
@@ -1082,19 +1080,24 @@ if(demand==null)
private
void
resetRequirementCalc
(
OrderMaterialRequirement
orderMaterial
)
{
orderMaterial
.
setUseStock
(
0
);
orderMaterial
.
setUseTransit
(
0
);
orderMaterial
.
setArrivalTime
(
null
);
orderMaterial
.
setPurchaseStartTime
(
null
);
orderMaterial
.
setPurchaseEndTime
(
null
);
orderMaterial
.
setUseTime
(
null
);
// orderMaterial.setArrivalTime(null);
orderMaterial
.
setPurchaseStartTime
(
baseTime
);
orderMaterial
.
setPurchaseEndTime
(
baseTime
.
plusDays
(
orderMaterial
.
getPurchaseTime
()));
orderMaterial
.
setUseTime
(
baseTime
.
plusDays
(
orderMaterial
.
getPurchaseTime
()+
orderMaterial
.
getCheckLeadTime
()));
if
(
orderMaterial
.
getReplaceMaterial
()
!=
null
&&
!
orderMaterial
.
getReplaceMaterial
().
isEmpty
())
{
for
(
OrderMaterialRequirement
replace
:
orderMaterial
.
getReplaceMaterial
())
{
replace
.
setUseStock
(
0
);
replace
.
setUseTransit
(
0
);
replace
.
setArrivalTime
(
null
);
replace
.
setPurchaseStartTime
(
null
);
replace
.
setPurchaseEndTime
(
null
);
replace
.
setUseTime
(
null
);
}
}
}
}
...
...
@@ -1178,223 +1181,23 @@ if(demand==null)
List
<
Material
>
materials
=
chromosome
.
getMaterials
();
List
<
OrderMaterialRequirement
>
remove
=
new
ArrayList
<>();
Map
<
String
,
OrderMaterialRequirement
>
totalNeededByMaterial
=
new
HashMap
<>();
if
(
MaterialRequirements
!=
null
&&
MaterialRequirements
.
size
()>
0
)
{
for
(
OrderMaterialRequirement
orderMaterial
:
MaterialRequirements
)
{
double
allneeded
=
orderMaterial
.
getSpentQty
()/
orderMaterial
.
getMainQty
()
*
operation
.
getQuantity
();
double
needed
=
allneeded
;
resetRequirementCalc
(
orderMaterial
);
orderMaterial
.
setRequiredQuantity
(
needed
);
orderMaterial
.
setQjQty
(
needed
);
// 查找物料(流式处理替代First)
Material
material
=
materials
.
stream
()
.
filter
(
m
->
m
.
getId
().
equals
(
orderMaterial
.
getMaterialId
()))
.
findFirst
()
.
orElse
(
null
);
if
(
material
==
null
)
{
return
;
}
double
useStock
=
0
;
List
<
Stock
>
stocks
=
material
.
getMaterialStocks
().
stream
()
.
filter
(
t
->
isStockValid
(
t
,
earliestStartTime
)
&&
t
.
getAvailableInventory
()
>
0
)
.
sorted
(
Comparator
.
comparing
(
Stock:
:
getExpiryDate
,
Comparator
.
nullsLast
(
LocalDateTime:
:
compareTo
))
.
thenComparing
(
Stock:
:
getWarehousingDate
,
Comparator
.
nullsLast
(
LocalDateTime:
:
compareTo
)))
.
collect
(
Collectors
.
toList
());
if
(
stocks
!=
null
)
{
for
(
Stock
s:
stocks
)
{
double
useStock1
=
Math
.
min
(
needed
,
s
.
getAvailableInventory
());
needed
-=
useStock1
;
useStock
+=
useStock1
;
if
(
commitChanges
)
{
s
.
setUsedInventory
(
s
.
getUsedInventory
()+
useStock1
);
}
orderMaterial
.
setUseStock
(
useStock
);
if
(
needed
==
0
)
{
break
;
}
}
}
if
(
needed
<=
0
)
{
orderMaterial
.
setYpQty
(
allneeded
-
needed
);
orderMaterial
.
setQjQty
(
needed
);
if
(
commitChanges
)
{
remove
.
add
(
orderMaterial
);
}
continue
;
}
List
<
RoutingSupportingReplace
>
routingsupportingreplaces
=
GetRoutingSupportingReplaces
(
sceneId
);
List
<
RoutingSupportingReplace
>
routingsupportingreplaces2
=
null
;
if
(
routingsupportingreplaces
!=
null
&&
routingsupportingreplaces
.
size
()
>
1
)
{
routingsupportingreplaces2
=
routingsupportingreplaces
.
stream
()
.
filter
(
t
->
t
.
getStrsupid
().
equals
(
orderMaterial
.
getBomId
())
&&
t
.
getMaterialid
().
equals
(
orderMaterial
.
getMaterialId
()))
.
collect
(
Collectors
.
toList
());
if
(
routingsupportingreplaces2
!=
null
&&
routingsupportingreplaces2
.
size
()
>
0
)
{
for
(
RoutingSupportingReplace
rsr
:
routingsupportingreplaces2
)
{
Material
material1
=
materials
.
stream
()
.
filter
(
m
->
m
.
getId
().
equals
(
rsr
.
getTargetmaterialid
()))
.
findFirst
()
.
orElse
(
null
);
if
(
material1
==
null
)
{
break
;
}
OrderMaterialRequirement
orderMaterial1
=
MaterialStock
(
material1
,
rsr
.
getTargetmaterialid
(),
orderMaterial
.
getOrderId
(),
orderMaterial
.
getChildOrderId
(),
operation
,
allneeded
,
needed
,
earliestStartTime
,
commitChanges
);
if
(
orderMaterial1
!=
null
)
{
useStock
=
orderMaterial1
.
getUseStock
();
needed
-=
useStock
;
orderMaterial
.
setUseStock
(
orderMaterial
.
getUseStock
()
+
useStock
);
orderMaterial
.
getReplaceMaterial
().
add
(
orderMaterial1
);
if
(
needed
<=
0
)
{
break
;
}
}
}
}
}
if
(
needed
<=
0
)
{
orderMaterial
.
setYpQty
(
allneeded
-
needed
);
orderMaterial
.
setQjQty
(
needed
);
if
(
commitChanges
)
{
remove
.
add
(
orderMaterial
);
}
continue
;
}
MaterialInTransit
(
material
,
""
,
orderMaterial
,
needed
,
earliestStartTime
,
materials
,
commitChanges
);
needed
-=
orderMaterial
.
getUseTransit
();
if
(
routingsupportingreplaces2
!=
null
&&
routingsupportingreplaces2
.
size
()
>
1
)
{
for
(
RoutingSupportingReplace
rsr:
routingsupportingreplaces2
)
{
OrderMaterialRequirement
orderMaterial1
=
orderMaterial
.
getReplaceMaterial
().
stream
()
.
filter
(
t
->
t
.
getMaterialId
().
equals
(
rsr
.
getTargetmaterialid
()))
.
findFirst
()
.
orElse
(
null
);
Material
material1
=
materials
.
stream
()
.
filter
(
m
->
m
.
getId
().
equals
(
orderMaterial1
.
getMaterialId
()))
.
findFirst
()
.
orElse
(
null
);
if
(
material1
==
null
)
{
break
;
}
MaterialInTransit
(
material1
,
rsr
.
getMaterialid
(),
orderMaterial1
,
needed
,
earliestStartTime
,
materials
,
commitChanges
);
needed
-=
orderMaterial1
.
getUseTransit
();
LocalDateTime
earliestTime
=
orderMaterial
.
getArrivalTime
().
compareTo
(
orderMaterial1
.
getArrivalTime
())>
0
?
orderMaterial
.
getArrivalTime
():
orderMaterial1
.
getArrivalTime
();
orderMaterial
.
setArrivalTime
(
earliestTime
);
orderMaterial
.
setUseTransit
(
orderMaterial
.
getUseTransit
()+
orderMaterial1
.
getUseTransit
());
if
(
needed
<=
0
)
{
break
;
}
}
}
if
(
needed
<=
0
)
{
orderMaterial
.
setYpQty
(
allneeded
-
needed
);
orderMaterial
.
setQjQty
(
needed
);
if
(
commitChanges
)
{
remove
.
add
(
orderMaterial
);
}
continue
;
}
if
(
needed
>
0
)
{
orderMaterial
.
setYpQty
(
allneeded
-
needed
);
orderMaterial
.
setQjQty
(
needed
);
if
(
material
.
getMaterialTypeName
().
equals
(
"MP"
)
)
{
// 处理原材料采购时间
orderMaterial
.
setPurchaseStartTime
(
baseTime
);
// 采购结束时间 = 采购开始时间 + 采购提前期(天)
List
<
MaterialPurchase
>
materialPurchaseList
=
material
.
getMaterialPurchases
();
if
(
materialPurchaseList
!=
null
&&
materialPurchaseList
.
size
()>
0
)
{
int
randomSeq
=
rnd
.
nextInt
(
materialPurchaseList
.
size
());
MaterialPurchase
result
=
materialPurchaseList
.
get
(
randomSeq
);
orderMaterial
.
setPurchaseTime
(
result
.
getPurchaseCycle
());
orderMaterial
.
setCheckLeadTime
(
result
.
getInspectionCycle
());
LocalDateTime
purchaseEndTime
=
baseTime
.
plusDays
(
orderMaterial
.
getPurchaseTime
()
+
orderMaterial
.
getCheckLeadTime
());
orderMaterial
.
setPurchaseEndTime
(
purchaseEndTime
);
}
}
else
{
// 处理半成品/成品的现有订单
double
allneeded
=
orderMaterial
.
getSpentQty
()
/
orderMaterial
.
getMainQty
()
*
operation
.
getQuantity
();
orderMaterial
.
setRequiredQuantity
(
allneeded
);
orderMaterial
.
setQjQty
(
allneeded
);
List
<
Integer
>
orderids
=
orderMaterial
.
getProductOrderID
();
if
(
orderids
!=
null
&&
orderids
.
size
()>
0
)
{
if
(
commitChanges
)
{
for
(
Integer
orderid
:
orderids
)
{
coder
.
ClearorderOperationResult
(
chromosome
,
orderid
);
coder
.
EditorderOperation
(
chromosome
,
orderid
,
needed
,
machineTasksCache
,
entryIndexById
,
scheduleIndexById
);
}
}
}
else
{
List
<
MaterialPurchase
>
materialPurchaseList
=
material
.
getMaterialPurchases
();
if
(
materialPurchaseList
!=
null
&&
materialPurchaseList
.
size
()>
0
)
{
int
randomSeq
=
rnd
.
nextInt
(
materialPurchaseList
.
size
());
MaterialPurchase
result
=
materialPurchaseList
.
get
(
randomSeq
);
orderMaterial
.
setPurchaseTime
(
result
.
getPurchaseCycle
());
orderMaterial
.
setCheckLeadTime
(
result
.
getInspectionCycle
());
LocalDateTime
purchaseEndTime
=
baseTime
.
plusDays
(
orderMaterial
.
getPurchaseTime
()
+
orderMaterial
.
getCheckLeadTime
());
orderMaterial
.
setPurchaseEndTime
(
purchaseEndTime
);
}
}
}
if
(
commitChanges
)
{
orderMaterial
.
getReplaceMaterial
().
removeIf
(
t
->
t
.
getUseStock
()==
0
&&
t
.
getUseTransit
()==
0
);
}
}
// 计算预计可用时间
LocalDateTime
arrivalTime
=
orderMaterial
.
getArrivalTime
();
LocalDateTime
purchaseEndTime
=
orderMaterial
.
getPurchaseEndTime
();
LocalDateTime
useTime
=
null
;
if
(
arrivalTime
==
null
)
{
useTime
=
purchaseEndTime
;
}
else
{
if
(
purchaseEndTime
!=
null
&&
purchaseEndTime
.
isAfter
(
arrivalTime
))
{
useTime
=
purchaseEndTime
;
}
else
{
useTime
=
arrivalTime
;
}
}
orderMaterial
.
setUseTime
(
useTime
);
totalNeededByMaterial
.
put
(
orderMaterial
.
getMaterialId
(),
orderMaterial
);
}
}
CalBom
(
chromosome
,
operation
.
getId
(),
totalNeededByMaterial
,
materials
,
earliestStartTime
,
commitChanges
,
remove
,
null
,
false
);
if
(
commitChanges
&&
remove
!=
null
&&
remove
.
size
()>
0
)
{
if
(
commitChanges
&&
remove
!=
null
&&
remove
.
size
()>
0
)
{
//删除先删排产结果,然后记录orderID,到排产方案里,最后一起删除
for
(
OrderMaterialRequirement
mr:
remove
)
{
List
<
Integer
>
orderids
=
mr
.
getProductOrderID
();
...
...
@@ -1408,6 +1211,322 @@ if(demand==null)
}
}
public
LocalDateTime
CalBom
(
Chromosome
chromosome
,
int
operationId
,
Map
<
String
,
OrderMaterialRequirement
>
MaterialRequirements
,
List
<
Material
>
materials
,
LocalDateTime
earliestStartTime
,
boolean
commitChanges
,
List
<
OrderMaterialRequirement
>
remove
,
Map
<
Integer
,
List
<
Entry
>>
entrysBygroupId
,
boolean
isSf
)
{
String
sceneId
=
chromosome
.
getScenarioID
();
Random
rnd
=
new
Random
();
LocalDateTime
useTime1
=
earliestStartTime
;
if
(
MaterialRequirements
!=
null
&&
MaterialRequirements
.
size
()>
0
)
{
for
(
Map
.
Entry
<
String
,
OrderMaterialRequirement
>
entry
:
MaterialRequirements
.
entrySet
())
{
OrderMaterialRequirement
orderMaterial
=
entry
.
getValue
();
double
allneeded
=
orderMaterial
.
getRequiredQuantity
();
double
needed
=
allneeded
;
resetRequirementCalc
(
orderMaterial
);
// 查找物料(流式处理替代First)
Material
material
=
materials
.
stream
()
.
filter
(
m
->
m
.
getId
().
equals
(
orderMaterial
.
getMaterialId
()))
.
findFirst
()
.
orElse
(
null
);
if
(
material
==
null
)
{
return
useTime1
;
}
double
useStock
=
0
;
List
<
Stock
>
stocks
=
material
.
getMaterialStocks
().
stream
()
.
filter
(
t
->
isStockValid
(
t
,
earliestStartTime
)
&&
t
.
getAvailableInventory
()
>
0
)
.
sorted
(
Comparator
.
comparing
(
Stock:
:
getExpiryDate
,
Comparator
.
nullsLast
(
LocalDateTime:
:
compareTo
))
.
thenComparing
(
Stock:
:
getWarehousingDate
,
Comparator
.
nullsLast
(
LocalDateTime:
:
compareTo
)))
.
collect
(
Collectors
.
toList
());
if
(
stocks
!=
null
)
{
for
(
Stock
s
:
stocks
)
{
double
useStock1
=
Math
.
min
(
needed
,
s
.
getAvailableInventory
());
needed
-=
useStock1
;
useStock
+=
useStock1
;
if
(
commitChanges
)
{
s
.
setUsedInventory
(
s
.
getUsedInventory
()
+
useStock1
);
}
orderMaterial
.
setUseStock
(
useStock
);
if
(
needed
==
0
)
{
break
;
}
}
}
if
(
needed
<=
0
)
{
orderMaterial
.
setYpQty
(
allneeded
-
needed
);
orderMaterial
.
setQjQty
(
needed
);
if
(
commitChanges
)
{
remove
.
add
(
orderMaterial
);
}
if
(
isSf
)
{
if
(!
material
.
getMaterialTypeName
().
equals
(
"MP"
))
{
List
<
Integer
>
orderids
=
orderMaterial
.
getProductOrderID
();
for
(
Integer
orderid
:
orderids
)
{
EditOrderOperation
(
chromosome
,
orderid
,
needed
,
entrysBygroupId
);
}
}
}
continue
;
}
List
<
RoutingSupportingReplace
>
routingsupportingreplaces
=
GetRoutingSupportingReplaces
(
sceneId
);
List
<
RoutingSupportingReplace
>
routingsupportingreplaces2
=
null
;
if
(
routingsupportingreplaces
!=
null
&&
routingsupportingreplaces
.
size
()
>
1
)
{
routingsupportingreplaces2
=
routingsupportingreplaces
.
stream
()
.
filter
(
t
->
t
.
getStrsupid
().
equals
(
orderMaterial
.
getBomId
())
&&
t
.
getMaterialid
().
equals
(
orderMaterial
.
getMaterialId
())
&&
!
t
.
getTargetmaterialid
().
equals
(
orderMaterial
.
getMaterialId
()))
.
collect
(
Collectors
.
toList
());
if
(
routingsupportingreplaces2
!=
null
&&
routingsupportingreplaces2
.
size
()
>
0
)
{
for
(
RoutingSupportingReplace
rsr
:
routingsupportingreplaces2
)
{
Material
material1
=
materials
.
stream
()
.
filter
(
m
->
m
.
getId
().
equals
(
rsr
.
getTargetmaterialid
()))
.
findFirst
()
.
orElse
(
null
);
if
(
material1
==
null
)
{
break
;
}
OrderMaterialRequirement
orderMaterial1
=
MaterialStock
(
material1
,
rsr
.
getTargetmaterialid
(),
orderMaterial
.
getOrderId
(),
orderMaterial
.
getChildOrderId
(),
operationId
,
allneeded
,
needed
,
earliestStartTime
,
commitChanges
);
if
(
orderMaterial1
!=
null
)
{
useStock
=
orderMaterial1
.
getUseStock
();
needed
-=
useStock
;
orderMaterial
.
setUseStock
(
orderMaterial
.
getUseStock
()
+
useStock
);
orderMaterial
.
getReplaceMaterial
().
add
(
orderMaterial1
);
if
(
needed
<=
0
)
{
break
;
}
}
}
}
}
if
(
needed
<=
0
)
{
orderMaterial
.
setYpQty
(
allneeded
-
needed
);
orderMaterial
.
setQjQty
(
needed
);
if
(
commitChanges
)
{
remove
.
add
(
orderMaterial
);
}
if
(
isSf
)
{
if
(!
material
.
getMaterialTypeName
().
equals
(
"MP"
))
{
List
<
Integer
>
orderids
=
orderMaterial
.
getProductOrderID
();
for
(
Integer
orderid
:
orderids
)
{
EditOrderOperation
(
chromosome
,
orderid
,
needed
,
entrysBygroupId
);
}
}
}
continue
;
}
MaterialInTransit
(
material
,
""
,
orderMaterial
,
needed
,
earliestStartTime
,
materials
,
commitChanges
);
needed
-=
orderMaterial
.
getUseTransit
();
if
(
routingsupportingreplaces2
!=
null
&&
routingsupportingreplaces2
.
size
()
>
1
)
{
for
(
RoutingSupportingReplace
rsr
:
routingsupportingreplaces2
)
{
OrderMaterialRequirement
orderMaterial1
=
orderMaterial
.
getReplaceMaterial
().
stream
()
.
filter
(
t
->
t
.
getMaterialId
().
equals
(
rsr
.
getTargetmaterialid
()))
.
findFirst
()
.
orElse
(
null
);
Material
material1
=
materials
.
stream
()
.
filter
(
m
->
m
.
getId
().
equals
(
orderMaterial1
.
getMaterialId
()))
.
findFirst
()
.
orElse
(
null
);
if
(
material1
==
null
)
{
break
;
}
MaterialInTransit
(
material1
,
rsr
.
getMaterialid
(),
orderMaterial1
,
needed
,
earliestStartTime
,
materials
,
commitChanges
);
needed
-=
orderMaterial1
.
getUseTransit
();
if
(
orderMaterial
.
getArrivalTime
()
!=
null
&&
orderMaterial1
.
getArrivalTime
()
!=
null
)
{
LocalDateTime
earliestTime
=
orderMaterial
.
getArrivalTime
().
compareTo
(
orderMaterial1
.
getArrivalTime
())
>
0
?
orderMaterial
.
getArrivalTime
()
:
orderMaterial1
.
getArrivalTime
();
orderMaterial
.
setArrivalTime
(
earliestTime
);
orderMaterial
.
setUseTransit
(
orderMaterial
.
getUseTransit
()
+
orderMaterial1
.
getUseTransit
());
}
else
if
(
orderMaterial
.
getArrivalTime
()
!=
null
)
{
LocalDateTime
earliestTime
=
orderMaterial
.
getArrivalTime
();
orderMaterial
.
setArrivalTime
(
earliestTime
);
orderMaterial
.
setUseTransit
(
orderMaterial
.
getUseTransit
()
+
orderMaterial1
.
getUseTransit
());
}
else
if
(
orderMaterial1
.
getArrivalTime
()
!=
null
)
{
LocalDateTime
earliestTime
=
orderMaterial1
.
getArrivalTime
();
orderMaterial
.
setArrivalTime
(
earliestTime
);
orderMaterial
.
setUseTransit
(
orderMaterial
.
getUseTransit
()
+
orderMaterial1
.
getUseTransit
());
}
if
(
needed
<=
0
)
{
break
;
}
}
}
if
(
needed
<=
0
)
{
orderMaterial
.
setYpQty
(
allneeded
-
needed
);
orderMaterial
.
setQjQty
(
needed
);
if
(
commitChanges
)
{
remove
.
add
(
orderMaterial
);
}
if
(
isSf
)
{
if
(!
material
.
getMaterialTypeName
().
equals
(
"MP"
))
{
List
<
Integer
>
orderids
=
orderMaterial
.
getProductOrderID
();
for
(
Integer
orderid
:
orderids
)
{
EditOrderOperation
(
chromosome
,
orderid
,
needed
,
entrysBygroupId
);
}
}
}
continue
;
}
if
(
needed
>
0
)
{
orderMaterial
.
setYpQty
(
allneeded
-
needed
);
orderMaterial
.
setQjQty
(
needed
);
if
(
material
.
getMaterialTypeName
().
equals
(
"MP"
))
{
// 处理原材料采购时间
orderMaterial
.
setPurchaseStartTime
(
baseTime
);
// 采购结束时间 = 采购开始时间 + 采购提前期(天)
List
<
MaterialPurchase
>
materialPurchaseList
=
material
.
getMaterialPurchases
();
if
(
materialPurchaseList
!=
null
&&
materialPurchaseList
.
size
()
>
0
)
{
int
randomSeq
=
rnd
.
nextInt
(
materialPurchaseList
.
size
());
MaterialPurchase
result
=
materialPurchaseList
.
get
(
randomSeq
);
orderMaterial
.
setPurchaseTime
(
result
.
getPurchaseCycle
());
orderMaterial
.
setCheckLeadTime
(
result
.
getInspectionCycle
());
LocalDateTime
purchaseEndTime
=
baseTime
.
plusDays
(
orderMaterial
.
getPurchaseTime
()
+
orderMaterial
.
getCheckLeadTime
());
orderMaterial
.
setPurchaseEndTime
(
purchaseEndTime
);
}
}
else
{
// 处理半成品/成品的现有订单
List
<
Integer
>
orderids
=
orderMaterial
.
getProductOrderID
();
if
(
orderids
!=
null
&&
orderids
.
size
()
>
0
)
{
if
(
isSf
)
{
for
(
Integer
orderid
:
orderids
)
{
EditOrderOperation
(
chromosome
,
orderid
,
needed
,
entrysBygroupId
);
}
}
}
else
{
List
<
MaterialPurchase
>
materialPurchaseList
=
material
.
getMaterialPurchases
();
if
(
materialPurchaseList
!=
null
&&
materialPurchaseList
.
size
()
>
0
)
{
int
randomSeq
=
rnd
.
nextInt
(
materialPurchaseList
.
size
());
MaterialPurchase
result
=
materialPurchaseList
.
get
(
randomSeq
);
orderMaterial
.
setPurchaseTime
(
result
.
getPurchaseCycle
());
orderMaterial
.
setCheckLeadTime
(
result
.
getInspectionCycle
());
LocalDateTime
purchaseEndTime
=
baseTime
.
plusDays
(
orderMaterial
.
getPurchaseTime
()
+
orderMaterial
.
getCheckLeadTime
());
orderMaterial
.
setPurchaseEndTime
(
purchaseEndTime
);
}
}
}
if
(
commitChanges
)
{
orderMaterial
.
getReplaceMaterial
().
removeIf
(
t
->
t
.
getUseStock
()
==
0
&&
t
.
getUseTransit
()
==
0
);
}
}
// 计算预计可用时间
LocalDateTime
arrivalTime
=
orderMaterial
.
getArrivalTime
();
LocalDateTime
purchaseEndTime
=
orderMaterial
.
getPurchaseEndTime
();
LocalDateTime
useTime
=
null
;
if
(
arrivalTime
==
null
)
{
useTime
=
purchaseEndTime
;
}
else
{
if
(
purchaseEndTime
!=
null
&&
purchaseEndTime
.
isAfter
(
arrivalTime
))
{
useTime
=
purchaseEndTime
;
}
else
{
useTime
=
arrivalTime
;
}
}
useTime1
=
useTime
.
compareTo
(
useTime1
)
>
0
?
useTime1
:
useTime
;
orderMaterial
.
setUseTime
(
useTime
);
if
(
commitChanges
)
{
orderMaterial
.
setUseTime
(
earliestStartTime
);
orderMaterial
.
setPurchaseEndTime
(
earliestStartTime
.
plusDays
(-
orderMaterial
.
getCheckLeadTime
()));
orderMaterial
.
setPurchaseStartTime
(
orderMaterial
.
getPurchaseEndTime
().
plusDays
(-
orderMaterial
.
getPurchaseTime
()));
}
}
}
return
useTime1
;
}
public
void
EditOrderOperation
(
Chromosome
chromosome
,
int
groupId
,
double
needed
,
Map
<
Integer
,
List
<
Entry
>>
entrysBygroupId
)
{
Order
order
=
chromosome
.
getOrders
().
stream
()
.
filter
(
m
->
m
.
getId
()==
groupId
)
.
findFirst
()
.
orElse
(
null
);
if
(
order
!=
null
)
{
if
(
needed
==
order
.
getQuantity
())
{
return
;
}
else
{
order
.
setQuantity
(
needed
);
}
}
List
<
Entry
>
orderOps
=
entrysBygroupId
.
get
(
groupId
);
if
(
orderOps
!=
null
)
{
for
(
Entry
currentOp
:
orderOps
)
{
if
(!
currentOp
.
isNewCreate
())
{
break
;
}
currentOp
.
setQuantity
(
needed
);
if
(
currentOp
.
getMaterialRequirements
()!=
null
)
{
for
(
OrderMaterialRequirement
orderMaterial
:
currentOp
.
getMaterialRequirements
())
{
List
<
Integer
>
orderids
=
orderMaterial
.
getProductOrderID
();
if
(
orderids
!=
null
&&
orderids
.
size
()
>
0
)
{
for
(
Integer
orderid
:
orderids
)
{
double
allneeded
=
orderMaterial
.
getSpentQty
()
/
orderMaterial
.
getMainQty
()
*
currentOp
.
getQuantity
();
EditOrderOperation
(
chromosome
,
orderid
,
allneeded
,
entrysBygroupId
);
}
}
}
}
}
}
}
...
...
src/main/java/com/aps/service/impl/LanuchServiceImpl.java
View file @
31d2cb46
...
...
@@ -45,7 +45,7 @@ import static org.springframework.beans.BeanUtils.copyProperties;
@RequiredArgsConstructor
public
class
LanuchServiceImpl
implements
LanuchService
{
private
static
final
BigDecimal
MAX_PROCESS_DURATION_DAYS
=
BigDecimal
.
valueOf
(
3
0
);
private
static
final
BigDecimal
MAX_PROCESS_DURATION_DAYS
=
BigDecimal
.
valueOf
(
9
0
);
private
static
final
BigDecimal
SECONDS_PER_DAY
=
BigDecimal
.
valueOf
(
24L
*
3600L
);
private
static
final
BigDecimal
MAX_PROCESS_DURATION_SECONDS
=
SECONDS_PER_DAY
.
multiply
(
MAX_PROCESS_DURATION_DAYS
);
...
...
src/main/java/com/aps/service/plan/PlanResultService.java
View file @
31d2cb46
...
...
@@ -1911,7 +1911,7 @@ public class PlanResultService {
.
collect
(
Collectors
.
joining
(
","
));
}
sb
.
append
(
String
.
format
(
"[%d-%d]:[%s-%s] Order %d,OrderID %s, Machine %d, Operation %d,
Batch
%.1f, processingTime %.1f, 前处理 %d, 后处理 %d, 离散参数 %d, bomtime %s,TargetOperationId %s"
,
"[%d-%d]:[%s-%s] Order %d,OrderID %s, Machine %d, Operation %d,
Quantity
%.1f, processingTime %.1f, 前处理 %d, 后处理 %d, 离散参数 %d, bomtime %s,TargetOperationId %s"
,
job
.
getStartTime
(),
job
.
getEndTime
(),
ConvertTime
(
job
.
getStartTime
()),
...
...
src/test/java/com/aps/demo/PlanResultServiceTest.java
View file @
31d2cb46
...
...
@@ -40,9 +40,9 @@ public class PlanResultServiceTest {
// sortService.test1();
// nsgaiiUtils.Test();
// planResultService.execute2("AD62106303684459949A7323D114BF60
");//2000
planResultService
.
execute2
(
"6D7C59CF2576457EBCB5F6CCDF5AF342
"
);
//2000
planResultService
.
execute2
(
"15210B13B88A453F8B84AAC7F16C7541"
);
//2000
//
planResultService.execute2("15210B13B88A453F8B84AAC7F16C7541");//2000
// planResultService.execute2("E29F2B3ADA8149F6B916B5119296A92B");//2000
// planResultService.execute2("E2CD1FC6FF9B4B19A59FEC7F846D4952");//600
...
...
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