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
f7bdf363
Commit
f7bdf363
authored
Nov 30, 2025
by
Tong Li
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
遗传算法
parent
eee3a165
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
1154 additions
and
333 deletions
+1154
-333
ResourceGanttController.java
...ava/com/aps/controller/gantt/ResourceGanttController.java
+4
-4
GAScheduleResult.java
src/main/java/com/aps/entity/Algorithm/GAScheduleResult.java
+10
-3
GroupResult.java
...va/com/aps/entity/Algorithm/IDAndChildID/GroupResult.java
+26
-0
NodeInfo.java
.../java/com/aps/entity/Algorithm/IDAndChildID/NodeInfo.java
+35
-0
Entry.java
src/main/java/com/aps/entity/basic/Entry.java
+7
-1
GlobalParam.java
src/main/java/com/aps/entity/basic/GlobalParam.java
+5
-3
Order.java
src/main/java/com/aps/entity/basic/Order.java
+4
-1
ScheduleChromosome.java
src/main/java/com/aps/entity/basic/ScheduleChromosome.java
+33
-33
GeneticAlgorithm.java
...main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
+25
-19
GeneticDecoder.java
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
+186
-22
GeneticOperations.java
...ain/java/com/aps/service/Algorithm/GeneticOperations.java
+6
-2
IdGroupingWithDualSerial.java
...a/com/aps/service/Algorithm/IdGroupingWithDualSerial.java
+561
-0
Initialization.java
src/main/java/com/aps/service/Algorithm/Initialization.java
+4
-2
MachineCalculator.java
...ain/java/com/aps/service/Algorithm/MachineCalculator.java
+39
-36
OrderSortService.java
...main/java/com/aps/service/Algorithm/OrderSortService.java
+2
-1
AlgorithmScheduler6.java
src/main/java/com/aps/service/plan/AlgorithmScheduler6.java
+1
-1
AlgorithmScheduler7.java
src/main/java/com/aps/service/plan/AlgorithmScheduler7.java
+1
-1
AlgorithmScheduler8.java
src/main/java/com/aps/service/plan/AlgorithmScheduler8.java
+17
-17
MachineSchedulerService.java
...in/java/com/aps/service/plan/MachineSchedulerService.java
+12
-1
PlanResultService.java
src/main/java/com/aps/service/plan/PlanResultService.java
+175
-185
OrderSortServiceTest.java
src/test/java/com/aps/demo/OrderSortServiceTest.java
+1
-1
No files found.
src/main/java/com/aps/controller/gantt/ResourceGanttController.java
View file @
f7bdf363
...
...
@@ -106,9 +106,9 @@ public class ResourceGanttController {
@GetMapping
(
"/getScene"
)
@Operation
(
summary
=
"获取所有场景ID"
,
description
=
"获取所有场景ID"
)
public
List
<
Chromosome
>
getScene
()
{
public
Chromosome
getScene
()
{
// 调用 PlanResultService 获取 ScheduleChromosome 列表
List
<
Chromosome
>
scheduleChromosomes
=
planResultService
.
execute1
();
Chromosome
scheduleChromosomes
=
planResultService
.
execute1
();
// 提取所有场景ID
return
scheduleChromosomes
;
...
...
@@ -116,9 +116,9 @@ public class ResourceGanttController {
@GetMapping
(
"/getScene2"
)
@Operation
(
summary
=
"获取所有场景ID"
,
description
=
"获取所有场景ID"
)
public
List
<
Chromosome
>
getScene2
()
{
public
Chromosome
getScene2
()
{
// 调用 PlanResultService 获取 ScheduleChromosome 列表
List
<
Chromosome
>
scheduleChromosomes
=
planResultService
.
execute2
(
"EAA26D85B5824B40A17554297B4EA32B
"
);
Chromosome
scheduleChromosomes
=
planResultService
.
execute2
(
"B571EF6682DB463AB2977B1055A74112
"
);
// 提取所有场景ID
return
scheduleChromosomes
;
...
...
src/main/java/com/aps/entity/Algorithm/GAScheduleResult.java
View file @
f7bdf363
...
...
@@ -12,11 +12,18 @@ import java.util.List;
@Data
public
class
GAScheduleResult
{
private
int
GroupId
;
private
int
ProductId
;
private
int
OperationId
;
/**
* 工单ID
*/
public
String
ExecId
;
public
String
OrderId
;
private
String
productId
;
private
long
MachineId
;
private
int
StartTime
;
// 相对开始时间(分钟)
private
int
EndTime
;
// 相对结束时间(分钟)
private
int
StartTime
;
// 相对开始时间(秒)
private
int
EndTime
;
// 相对结束时间(秒)
private
int
teardownTime
;
//后处理
private
double
Quantity
;
// 批次大小(订单可拆分)
private
List
<
ScheduleResultDetail
>
GeneDetails
;
// 时间详情
private
double
OneTime
;
// 单件工时
...
...
src/main/java/com/aps/entity/Algorithm/IDAndChildID/GroupResult.java
0 → 100644
View file @
f7bdf363
package
com
.
aps
.
entity
.
Algorithm
.
IDAndChildID
;
import
java.util.List
;
import
java.util.Map
;
/**
* 作者:佟礼
* 时间:2025-11-29
*/
// 存储分组结果:节点信息列表、新父子映射
// 存储分组结果:节点信息列表、原始ID(String)→全局序号映射
// 存储分组结果:节点信息列表、原始ID→全局序号映射
public
class
GroupResult
{
private
List
<
NodeInfo
>
nodeInfoList
;
private
Map
<
String
,
Integer
>
originalToGlobalSerial
;
public
GroupResult
(
List
<
NodeInfo
>
nodeInfoList
,
Map
<
String
,
Integer
>
originalToGlobalSerial
)
{
this
.
nodeInfoList
=
nodeInfoList
;
this
.
originalToGlobalSerial
=
originalToGlobalSerial
;
}
// getter
public
List
<
NodeInfo
>
getNodeInfoList
()
{
return
nodeInfoList
;
}
public
Map
<
String
,
Integer
>
getOriginalToGlobalSerial
()
{
return
originalToGlobalSerial
;
}
}
src/main/java/com/aps/entity/Algorithm/IDAndChildID/NodeInfo.java
0 → 100644
View file @
f7bdf363
package
com
.
aps
.
entity
.
Algorithm
.
IDAndChildID
;
import
lombok.Data
;
import
java.util.List
;
/**
* 作者:佟礼
* 时间:2025-11-29
*/
// 存储节点信息:原ID、新序号、新父ID、新子ID列表
@Data
// 存储节点信息:原ID(String)、全局新序号、分组内序号、新父ID列表、新子ID列表
public
class
NodeInfo
{
private
String
originalId
;
// 原始ID
private
Integer
globalSerial
;
// 全局新序号
private
Integer
groupSerial
;
// 分组内序号
private
List
<
Integer
>
newParentIds
;
// 新父ID列表(基于全局序号)
private
List
<
Integer
>
newChildIds
;
// 新子ID列表(基于全局序号)
public
NodeInfo
(
String
originalId
,
Integer
globalSerial
,
Integer
groupSerial
,
List
<
Integer
>
newParentIds
,
List
<
Integer
>
newChildIds
)
{
this
.
originalId
=
originalId
;
this
.
globalSerial
=
globalSerial
;
this
.
groupSerial
=
groupSerial
;
this
.
newParentIds
=
newParentIds
;
this
.
newChildIds
=
newChildIds
;
}
@Override
public
String
toString
()
{
return
originalId
+
":"
+
globalSerial
;
}
}
src/main/java/com/aps/entity/basic/Entry.java
View file @
f7bdf363
...
...
@@ -29,6 +29,7 @@ public class Entry {
*/
public
String
OrderId
;
private
String
productId
;
/**
* 工单ID
*/
...
...
@@ -36,7 +37,7 @@ public class Entry {
/**
* 离散参数
*/
public
String
DiscreteParameter
;
public
List
<
String
>
DiscreteParameter
;
/**
* 基因编号
*/
...
...
@@ -58,6 +59,11 @@ public class Entry {
*/
public
List
<
Integer
>
PrevEntryIds
;
//前工序
/**
* 前工单ID
*/
public
List
<
Integer
>
NextEntryIds
;
//后工序
/**
* 是否可中断,间缝插针
*/
...
...
src/main/java/com/aps/entity/basic/GlobalParam.java
View file @
f7bdf363
...
...
@@ -11,15 +11,17 @@ public class GlobalParam {
/// <summary>
/// 是否可以打破优先级
/// </summary>
p
ublic
static
boolean
IsBreakPriority
=
false
;
p
rivate
boolean
IsBreakPriority
=
false
;
/// <summary>
/// 是否多台设备
/// </summary>
p
ublic
static
boolean
IsMultipleMachine
=
false
;
p
rivate
boolean
IsMultipleMachine
=
false
;
/// <summary>
/// 是否重叠
/// </summary>
public
static
boolean
IsOverlap
=
false
;
private
boolean
IsOverlap
=
false
;
private
boolean
_smoothSetup
=
false
;
// 默认true,不占用设备时长
}
src/main/java/com/aps/entity/basic/Order.java
View file @
f7bdf363
...
...
@@ -11,11 +11,14 @@ import java.time.OffsetDateTime;
@Data
public
class
Order
{
private
int
id
;
private
String
OrderId
;
private
int
productId
;
private
String
materialId
;
private
double
quantity
=
100
;
// 100个
private
double
sYQuantity
;
private
Offset
DateTime
dueDate
;
private
Local
DateTime
dueDate
;
private
LocalDateTime
orderCompletion
;
private
double
tardiness
;
private
int
priority
;
...
...
src/main/java/com/aps/entity/basic/ScheduleChromosome.java
View file @
f7bdf363
...
...
@@ -96,38 +96,38 @@ public class ScheduleChromosome {
private
List
<
Order
>
calTardiness
()
{
tardiness
=
0
;
for
(
Order
order
:
orders
)
{
final
int
orderId
=
order
.
getId
();
List
<
Gene
>
orderGroups
=
genes
.
stream
()
.
filter
(
g
->
g
.
getOrderId
()
==
orderId
)
.
collect
(
Collectors
.
toList
());
int
orderCompletion
=
orderGroups
.
stream
()
.
mapToInt
(
Gene:
:
getEndTime
)
.
max
()
.
orElse
(
0
);
LocalDateTime
orderCompletionTime
=
baseTime
.
plusMinutes
(
orderCompletion
);
order
.
setOrderCompletion
(
orderCompletionTime
);
order
.
setTardiness
(
0
);
// 修复:统一时间类型
LocalDateTime
dueDateTime
=
order
.
getDueDate
().
toLocalDateTim
e
();
if
(
orderCompletionTime
.
isAfter
(
dueDateTime
))
{
// 方法1:使用分钟计算再转换为小时(推荐)
long
totalMinutes
=
java
.
time
.
temporal
.
ChronoUnit
.
MINUTES
.
between
(
dueDateTime
,
orderCompletionTime
);
double
tardinessHours
=
totalMinutes
/
60.0
;
// 方法2:或者保持原有逻辑但使用统一的时间类型
// long diffHours = java.time.temporal.ChronoUnit.HOURS.between(dueDateTime, orderCompletionTime);
// long remainingMinutes = java.time.temporal.ChronoUnit.MINUTES.between(dueDateTime, orderCompletionTime) % 60;
// double tardinessHours = diffHours + (double) remainingMinutes / 60;
order
.
setTardiness
(
tardinessHours
);
tardiness
+=
tardinessHours
;
}
}
return
orders
;
//
for (Order order : orders) {
//
final int orderId = order.getId();
//
List<Gene> orderGroups = genes.stream()
//
.filter(g -> g.getOrderId() == orderId)
//
.collect(Collectors.toList());
//
//
int orderCompletion = orderGroups.stream()
//
.mapToInt(Gene::getEndTime)
//
.max()
//
.orElse(0);
//
//
LocalDateTime orderCompletionTime = baseTime.plusMinutes(orderCompletion);
//
order.setOrderCompletion(orderCompletionTime);
//
order.setTardiness(0);
//
//
// 修复:统一时间类型
// LocalDateTime dueDateTime = order.getDueDat
e();
//
//
if (orderCompletionTime.isAfter(dueDateTime)) {
//
// 方法1:使用分钟计算再转换为小时(推荐)
//
long totalMinutes = java.time.temporal.ChronoUnit.MINUTES.between(dueDateTime, orderCompletionTime);
//
double tardinessHours = totalMinutes / 60.0;
//
//
// 方法2:或者保持原有逻辑但使用统一的时间类型
//
// long diffHours = java.time.temporal.ChronoUnit.HOURS.between(dueDateTime, orderCompletionTime);
//
// long remainingMinutes = java.time.temporal.ChronoUnit.MINUTES.between(dueDateTime, orderCompletionTime) % 60;
//
// double tardinessHours = diffHours + (double) remainingMinutes / 60;
//
//
order.setTardiness(tardinessHours);
//
tardiness += tardinessHours;
//
}
//
}
return
null
;
}
}
\ No newline at end of file
src/main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
View file @
f7bdf363
...
...
@@ -6,10 +6,7 @@ import com.aps.entity.Algorithm.Chromosome;
import
com.aps.entity.Algorithm.GlobalOperationInfo
;
import
com.aps.entity.Algorithm.Pair
;
import
com.aps.entity.Algorithm.ScheduleParams
;
import
com.aps.entity.basic.Entry
;
import
com.aps.entity.basic.Machine
;
import
com.aps.entity.basic.Material
;
import
com.aps.entity.basic.Order
;
import
com.aps.entity.basic.*
;
import
com.aps.service.plan.MachineSchedulerService
;
import
java.util.*
;
...
...
@@ -25,20 +22,22 @@ public class GeneticAlgorithm {
private
final
MachineSchedulerService
machineScheduler
;
private
final
List
<
Order
>
orders
;
private
final
List
<
Material
>
materials
;
private
static
GlobalParam
_GlobalParam
;
public
GeneticAlgorithm
(
List
<
Machine
>
machines
,
List
<
Order
>
orders
,
public
GeneticAlgorithm
(
GlobalParam
globalParam
,
List
<
Machine
>
machines
,
List
<
Order
>
orders
,
List
<
Material
>
materials
,
MachineSchedulerService
machineScheduler
)
{
this
.
machines
=
machines
;
this
.
orders
=
orders
;
this
.
materials
=
materials
;
this
.
machineScheduler
=
machineScheduler
;
_GlobalParam
=
globalParam
;
}
public
List
<
Chromosome
>
Run
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
)
{
public
Chromosome
Run
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
)
{
System
.
out
.
println
(
"开始"
);
Initialization
initialization
=
new
Initialization
(
allOperations
);
Initialization
initialization
=
new
Initialization
(
_GlobalParam
,
allOperations
);
GeneticOperations
geneticOps
=
new
GeneticOperations
(
allOperations
);
GeneticOperations
geneticOps
=
new
GeneticOperations
(
_GlobalParam
,
allOperations
);
// 预生成全局工序列表(所有初始化方法共享同一顺序)
List
<
GlobalOperationInfo
>
globalOpList
=
initialization
.
generateGlobalOpList
();
...
...
@@ -124,36 +123,43 @@ public class GeneticAlgorithm {
Iteration
++;
}
if
(
Iteration
>
2
0
)
if
(
Iteration
>
1
0
)
{
break
;
}
}
// 步骤3:返回最优解
return
population
.
stream
()
.
sorted
((
c1
,
c2
)
->
Double
.
compare
(
c2
.
getFitness
(),
c1
.
getFitness
()))
.
limit
(
10
)
.
collect
(
Collectors
.
toList
());
return
best
;
}
private
void
Chromosomedecode
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
,
List
<
GlobalOperationInfo
>
globalOpList
,
List
<
Chromosome
>
population
)
{
GeneticDecoder
decoder
=
new
GeneticDecoder
(
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
);
GeneticDecoder
decoder
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
);
FitnessCalculator
fitnessCalc
=
new
FitnessCalculator
();
population
.
parallelStream
().
forEach
(
chromosome
->
{
// population.parallelStream().forEach(chromosome -> {
// chromosome.setResult(new ArrayList<>());
//
// // 假设Machine类有拷贝方法,或使用MapStruct等工具进行映射
// chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(machines)); // 简单拷贝,实际可能需要深拷贝
//
// decoder.decodeChromosomeWithCache(chromosome, globalOpList, allOperations);
// chromosome.setFitness(fitnessCalc.calculateFitness(chromosome));
// });
population
.
forEach
(
chromosome
->
{
chromosome
.
setResult
(
new
ArrayList
<>());
// 假设Machine类有拷贝方法,或使用MapStruct等工具进行映射
chromosome
.
setMachines
(
ProductionDeepCopyUtil
.
deepCopyList
(
machines
));
// 简单拷贝,实际可能需要深拷贝
decoder
.
decodeChromosomeWithCache
(
chromosome
,
globalOpList
,
allOperations
);
chromosome
.
setFitness
(
fitnessCalc
.
calculateFitness
(
chromosome
));
Chromosome
chromosomen
=
decoder
.
decodeChromosomeWithCache
(
chromosome
,
globalOpList
,
allOperations
);
if
(
chromosomen
.
getFitness
()==
0
)
{
chromosomen
.
setFitness
(
fitnessCalc
.
calculateFitness
(
chromosomen
));
}
});
}
}
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
View file @
f7bdf363
...
...
@@ -2,6 +2,7 @@ package com.aps.service.Algorithm;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.entity.Algorithm.*
;
import
com.aps.entity.ProdEquipment
;
import
com.aps.entity.basic.*
;
import
com.aps.service.plan.MachineSchedulerService
;
...
...
@@ -28,7 +29,9 @@ public class GeneticDecoder {
private
final
List
<
Order
>
orders
;
private
int
orderMaxID
;
private
final
List
<
Material
>
materials
;
public
GeneticDecoder
(
LocalDateTime
baseTime
,
List
<
Machine
>
machines
,
List
<
Order
>
orders
,
private
List
<
Entry
>
_allOperations
;
private
GlobalParam
_globalParam
;
public
GeneticDecoder
(
GlobalParam
globalParam
,
LocalDateTime
baseTime
,
List
<
Machine
>
machines
,
List
<
Order
>
orders
,
List
<
Material
>
materials
,
MachineSchedulerService
machineScheduler
)
{
this
.
baseTime
=
baseTime
;
this
.
machines
=
machines
;
...
...
@@ -36,11 +39,12 @@ public class GeneticDecoder {
this
.
orders
.
forEach
(
t
->
t
.
setSYQuantity
(
t
.
getQuantity
()));
this
.
materials
=
materials
;
this
.
machineScheduler
=
machineScheduler
;
this
.
orderMaxID
=
orders
.
stream
().
mapToInt
(
Order:
:
getId
).
max
().
orElse
(
0
);
_globalParam
=
globalParam
;
// this.orderMaxID = orders.stream().mapToInt(Order::getId).max().orElse(0);
}
public
void
decodeChromosomeWithCache
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
,
public
Chromosome
decodeChromosomeWithCache
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
,
List
<
Entry
>
allOperations
)
{
_allOperations
=
allOperations
;
// 1. 创建缓存键
String
cacheKey
=
createCacheKey
(
chromosome
);
...
...
@@ -52,9 +56,9 @@ public class GeneticDecoder {
Chromosome
cachedResult
=
decodingCache
.
get
(
cacheKey
);
// 赋值给染色体
String
ID
=
chromosome
.
getID
();
chromosome
=
ProductionDeepCopyUtil
.
deepCopy
(
cachedResult
);
chromosome
.
setID
(
ID
);
return
;
Chromosome
chromosomen
=
ProductionDeepCopyUtil
.
deepCopy
(
cachedResult
);
chromosomen
.
setID
(
ID
);
return
chromosomen
;
}
}
finally
{
cacheLock
.
unlock
();
// 确保锁释放
...
...
@@ -84,6 +88,7 @@ public class GeneticDecoder {
}
finally
{
cacheLock
.
unlock
();
}
return
chromosome
;
}
/**
* 染色体解码为调度方案
...
...
@@ -163,12 +168,13 @@ public class GeneticDecoder {
int
opSequence
=
currentOp
.
getSequence
();
// 从映射表中获取机器和加工时间
OpMachine
machine
Info
=
opMachineMap
.
stream
()
OpMachine
machine
Option
=
opMachineMap
.
stream
()
.
filter
(
m
->
m
.
getGroupId
()
==
groupId
&&
m
.
getSequence
()==
opSequence
)
.
findFirst
()
.
orElse
(
null
);
Long
machineId
=
machineInfo
.
getMachineId
();
double
processTime
=
machineInfo
.
getProcessingTime
();
Long
machineId
=
machineOption
.
getMachineId
();
double
processTime
=
machineOption
.
getProcessingTime
();
Machine
targetMachine
=
chromosome
.
getMachines
().
stream
()
.
filter
(
m
->
m
.
getId
()
==
machineId
)
.
findFirst
()
...
...
@@ -184,13 +190,13 @@ public class GeneticDecoder {
.
collect
(
Collectors
.
toList
());
for
(
GAScheduleResult
prevOp
:
prevOperations
)
{
prevtime
=
Math
.
max
(
prevtime
,
prevOp
.
getEndTime
());
prevtime
=
Math
.
max
(
prevtime
,
prevOp
.
getEndTime
()
+
prevOp
.
getTeardownTime
()
);
}
}
}
// 上个离散参数
String
lastDiscreteParameter
=
machineState
.
get
(
machineId
);
//
String lastDiscreteParameter = machineState.get(machineId);
int
bomtime
=
0
;
prevtime
=
Math
.
max
(
prevtime
,
bomtime
);
...
...
@@ -200,14 +206,14 @@ public class GeneticDecoder {
.
findFirst
()
.
orElse
(
null
);
int
changeoverTime
=
0
;
//(lastDiscreteParameter.isEmpty() ||
//
int changeoverTime =0; //(lastDiscreteParameter.isEmpty() ||
// lastDiscreteParameter.equals(currentOp.getDiscreteParameter())) ? 0 : 0;
int
actualEndTime
=
processWithSingleMachine
(
currentOp
,
machine
,
processTime
,
prevtime
,
chromosome
);
orderProcessCounter
.
put
(
groupId
,
orderProcessCounter
.
get
(
groupId
)
+
1
);
orderLastEndTime
.
put
(
groupId
,
actualEndTime
);
machineState
.
put
(
machineId
,
currentOp
.
getDiscreteParameter
());
//
machineState.put(machineId, currentOp.getDiscreteParameter());
}
// 步骤4:计算调度指标
...
...
@@ -217,13 +223,74 @@ public class GeneticDecoder {
private
int
processWithSingleMachine
(
Entry
operation
,
Machine
machine
,
double
processingTime
,
int
prev
t
ime
,
Chromosome
chromosome
)
{
int
prev
OperationEndT
ime
,
Chromosome
chromosome
)
{
int
processingTimeTotal
=(
int
)(
processingTime
*
operation
.
getQuantity
());
MachineOption
machineOption
=
operation
.
getMachineOptions
().
stream
()
.
filter
(
t
->
t
.
getMachineId
()==
machine
.
getId
())
.
findFirst
().
orElse
(
null
);
int
teardownTime
=
machineOption
.
getTeardownTime
();
int
preTime
=
machineOption
.
getPreTime
();
int
setupTime
=
calculateSetupTime
(
chromosome
.
getResult
(),
operation
,
machine
,
machineOption
);
System
.
out
.
println
(
" 处理时间: "
+
processingTime
+
", 后处理: "
+
teardownTime
+
", 前处理: "
+
preTime
+
", 换型: "
+
setupTime
);
// 确定任务的最早开始时间(基于前一道工序的完整结束时间,包含后处理)
int
earliestStartTime
=
prevOperationEndTime
;
// 检查设备上是否有前一个任务
GAScheduleResult
lastGeneOnMachine
=
chromosome
.
getResult
().
stream
()
.
filter
(
g
->
g
.
getMachineId
()
==
machine
.
getId
())
.
max
(
Comparator
.
comparingInt
(
GAScheduleResult:
:
getEndTime
))
.
orElse
(
null
);
if
(
lastGeneOnMachine
!=
null
)
{
// 设备上已有任务,当前任务必须在设备可用后开始
// 设备可用时间 = 前一个任务的主处理结束时间(后处理不占用设备)
int
machineAvailableTime
=
lastGeneOnMachine
.
getEndTime
();
if
(
setupTime
>
0
)
{
if
(
_globalParam
.
is_smoothSetup
())
{
machineAvailableTime
+=
setupTime
;
// 平滑模式:换型在非工作时间进行,不额外占用设备时间
System
.
out
.
println
(
" 平滑模式换型:在非工作时间进行,设备可用时间不变"
);
}
else
{
// 标准模式:换型需要额外占用设备时间
machineAvailableTime
+=
setupTime
;
System
.
out
.
println
(
" 标准模式换型:需要额外占用设备 "
+
setupTime
+
" 分钟"
);
}
}
earliestStartTime
=
Math
.
max
(
earliestStartTime
,
machineAvailableTime
);
}
System
.
out
.
println
(
" 最终最早开始时间: "
+
earliestStartTime
+
" (前序工序结束含后处理: "
+
prevOperationEndTime
+
", 设备可用: "
+
(
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
+
"分钟"
);
}
MachineCalculator
machineCalculator
=
new
MachineCalculator
(
baseTime
,
machines
,
machineScheduler
);
List
<
ScheduleResultDetail
>
geneDetails
=
machineCalculator
.
getNextAvailableTime
(
machine
,
prevt
ime
,
-
1
,
List
<
ScheduleResultDetail
>
geneDetails
=
machineCalculator
.
getNextAvailableTime
(
machine
,
earliestStartT
ime
,
-
1
,
processingTimeTotal
,
chromosome
.
getResult
(),
false
,
true
,
true
);
int
startTime
=
geneDetails
.
stream
()
.
mapToInt
(
ScheduleResultDetail:
:
getStartTime
)
.
min
()
...
...
@@ -233,19 +300,110 @@ public class GeneticDecoder {
.
max
()
.
orElse
(
0
);
// 冲突检测和解决
final
int
finalStartTime
=
startTime
;
final
int
finalEndTime
=
endTime
;
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
();
int
conflictSetupTime
=
calculateSetupTimeForConflict
(
chromosome
.
getResult
(),
operation
,
machine
,
machineOption
,
conflictingGene
);
int
conflictEarliestStartTime
=
conflictSetupStartTime
+
conflictSetupTime
;
geneDetails
=
machineCalculator
.
getNextAvailableTime
(
machine
,
conflictEarliestStartTime
,
-
1
,
processingTimeTotal
,
chromosome
.
getResult
(),
false
,
true
,
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
();
result
.
setGroupId
(
operation
.
getGroupId
());
result
.
setOperationId
(
operation
.
getId
());
result
.
setExecId
(
operation
.
getExecId
());
result
.
setOrderId
(
operation
.
getOrderId
());
result
.
setProductId
(
operation
.
getProductId
());
result
.
setMachineId
(
machine
.
getId
());
result
.
setQuantity
(
operation
.
getQuantity
());
result
.
setStartTime
(
startTime
);
result
.
setEndTime
(
endTime
);
result
.
setEndTime
(
teardownTime
);
result
.
setOneTime
(
processingTime
);
result
.
setProcessingTime
(
processingTimeTotal
);
result
.
setGeneDetails
(
geneDetails
);
chromosome
.
getResult
().
add
(
result
);
return
endTime
;
}
private
String
ConvertTime
(
int
minute
)
{
return
baseTime
.
plusSeconds
(
minute
).
format
(
java
.
time
.
format
.
DateTimeFormatter
.
ofPattern
(
"MM-dd HH:mm"
));
}
private
int
calculateSetupTime
(
List
<
GAScheduleResult
>
existingGenes
,
Entry
operation
,
Machine
machine
,
MachineOption
machineOption
)
{
GAScheduleResult
lastGeneOnMachine
=
existingGenes
.
stream
()
.
filter
(
g
->
g
.
getMachineId
()
==
machine
.
getId
())
.
max
(
Comparator
.
comparingInt
(
GAScheduleResult:
:
getEndTime
))
.
orElse
(
null
);
if
(
lastGeneOnMachine
==
null
)
{
System
.
out
.
println
(
"设备 "
+
machine
.
getId
()
+
" 上无历史任务,换型时间为0"
);
return
0
;
}
Entry
prev
=
_allOperations
.
stream
().
filter
(
t
->
t
.
getExecId
().
equals
(
lastGeneOnMachine
.
getExecId
()))
.
findFirst
().
orElse
(
null
);
int
setupTime
=
0
;
if
(
prev
!=
null
)
{
//离散参数
// prev.getDiscreteParameter()
setupTime
=
(
prev
.
getProductId
()
!=
operation
.
getProductId
())
?
machineOption
.
getSetupTime
()
:
0
;
if
(
setupTime
>
0
)
{
System
.
out
.
println
(
"设备 "
+
machine
.
getId
()
+
" 需要换型,因为产品从 "
+
prev
.
getProductId
()
+
" 变更为 "
+
operation
.
getProductId
());
}
}
return
setupTime
;
}
private
int
calculateSetupTimeForConflict
(
List
<
GAScheduleResult
>
existingGenes
,
Entry
operation
,
Machine
machine
,
MachineOption
machineOption
,
GAScheduleResult
conflictingGene
)
{
int
setupTime
=
(
conflictingGene
.
getProductId
()
!=
operation
.
getProductId
())
?
machineOption
.
getSetupTime
()
:
0
;
if
(
existingGenes
.
stream
().
filter
(
g
->
g
.
getMachineId
()
==
machine
.
getId
()).
count
()
<=
1
)
{
setupTime
=
0
;
}
if
(
setupTime
>
0
)
{
System
.
out
.
println
(
"设备 "
+
machine
.
getId
()
+
" 需要换型,因为产品从 "
+
conflictingGene
.
getProductId
()
+
" 变更为 "
+
operation
.
getProductId
());
}
return
setupTime
;
}
private
void
calculateScheduleResult
(
Chromosome
chromosome
)
{
// 1. 最早完工时间(最小化)
...
...
@@ -266,16 +424,22 @@ public class GeneticDecoder {
.
mapToInt
(
GAScheduleResult:
:
getEndTime
)
.
max
()
.
orElse
(
0
);
List
<
String
>
orderIds
=
group
.
getValue
().
stream
()
.
map
(
GAScheduleResult:
:
getOrderId
)
.
distinct
()
.
sorted
()
.
collect
(
Collectors
.
toList
());
Order
order
=
orders
.
stream
()
.
filter
(
t
->
t
.
getId
()
==
groupId
)
.
findFirst
(
)
.
filter
(
t
->
orderIds
.
contains
(
t
.
getOrderId
())
)
.
max
(
Comparator
.
comparing
(
Order:
:
getDueDate
)
)
.
orElse
(
null
);
LocalDateTime
dueDateTime
=
order
.
getDueDate
();
LocalDateTime
completionTime
=
baseTime
.
plusSeconds
(
orderCompletion
);
LocalDateTime
completionTime
=
baseTime
.
plusMinutes
(
orderCompletion
);
// 修复:正确处理OffsetDateTime到LocalDateTime的转换
LocalDateTime
dueDateTime
=
order
.
getDueDate
().
toLocalDateTime
();
if
(
completionTime
.
isAfter
(
dueDateTime
))
{
// 计算延迟小时数(修复时间计算)
...
...
src/main/java/com/aps/service/Algorithm/GeneticOperations.java
View file @
f7bdf363
...
...
@@ -18,9 +18,13 @@ import java.util.stream.Collectors;
*/
public
class
GeneticOperations
{
private
final
Random
rnd
=
new
Random
();
private
static
GlobalParam
_GlobalParam
;
private
static
List
<
Entry
>
allOperations
;
public
GeneticOperations
(
List
<
Entry
>
allOperations
)
{
public
GeneticOperations
(
GlobalParam
globalParam
,
List
<
Entry
>
allOperations
)
{
_GlobalParam
=
globalParam
;
GeneticOperations
.
allOperations
=
allOperations
;
}
...
...
@@ -225,7 +229,7 @@ public class GeneticOperations {
Random
rnd
=
new
Random
();
List
<
OperationSequencingWeight
>
indexWeights
=
CommonCalculator
.
getOsw
(
os
,
allOperations
);
if
(!
GlobalParam
.
IsBreakPriority
)
{
if
(!
_GlobalParam
.
isIsBreakPriority
()
)
{
if
(
weight
==
0
)
{
return
indexWeights
.
get
(
rnd
.
nextInt
(
indexWeights
.
size
()));
}
else
{
...
...
src/main/java/com/aps/service/Algorithm/IdGroupingWithDualSerial.java
0 → 100644
View file @
f7bdf363
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.entity.Algorithm.IDAndChildID.GroupResult
;
import
com.aps.entity.Algorithm.IDAndChildID.NodeInfo
;
import
lombok.Data
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
* 作者:佟礼
* 时间:2025-11-29
*/
public
class
IdGroupingWithDualSerial
{
/**
* 递归获取ID的所有子孙节点(去重)
*/
/**
* 递归获取ID的所有子孙节点(去重)
*/
private
static
Set
<
String
>
getAllDescendants
(
String
id
,
Map
<
String
,
Set
<
String
>>
parentToChildren
,
Set
<
String
>
visited
)
{
Set
<
String
>
descendants
=
new
HashSet
<>();
if
(
visited
.
contains
(
id
)
||
!
parentToChildren
.
containsKey
(
id
))
{
return
descendants
;
}
visited
.
add
(
id
);
Set
<
String
>
directChildren
=
parentToChildren
.
get
(
id
);
for
(
String
child
:
directChildren
)
{
descendants
.
add
(
child
);
descendants
.
addAll
(
getAllDescendants
(
child
,
parentToChildren
,
visited
));
}
return
descendants
;
}
/**
* 分组“无父级且子孙节点有交集”的ID(兼容空ChildID)
*/
private
static
List
<
List
<
String
>>
groupNoParentIds
(
List
<
String
>
idList
,
List
<
String
>
childIdList
)
{
// 构建父→子映射(过滤空ChildID,去重)
Map
<
String
,
Set
<
String
>>
parentToChildren
=
new
HashMap
<>();
for
(
int
i
=
0
;
i
<
idList
.
size
();
i
++)
{
String
parentId
=
idList
.
get
(
i
);
String
childId
=
childIdList
.
get
(
i
);
// 跳过空ChildID
if
(
childId
==
null
||
childId
.
trim
().
isEmpty
())
{
continue
;
}
parentToChildren
.
computeIfAbsent
(
parentId
,
k
->
new
HashSet
<>()).
add
(
childId
);
}
// 构建子→父映射(过滤空ChildID)
Map
<
String
,
Set
<
String
>>
childToParents
=
new
HashMap
<>();
for
(
int
i
=
0
;
i
<
idList
.
size
();
i
++)
{
String
parentId
=
idList
.
get
(
i
);
String
childId
=
childIdList
.
get
(
i
);
if
(
childId
==
null
||
childId
.
trim
().
isEmpty
())
{
continue
;
}
childToParents
.
computeIfAbsent
(
childId
,
k
->
new
HashSet
<>()).
add
(
parentId
);
}
Set
<
String
>
allChildIds
=
new
HashSet
<>();
for
(
String
childId
:
childIdList
)
{
if
(
childId
!=
null
&&
!
childId
.
trim
().
isEmpty
())
{
allChildIds
.
add
(
childId
);
}
}
List
<
String
>
noParentIds
=
parentToChildren
.
keySet
().
stream
()
.
filter
(
id
->
!
allChildIds
.
contains
(
id
))
.
collect
(
Collectors
.
toList
());
// 处理无子女的孤立节点(如23)
Set
<
String
>
allParentIds
=
new
HashSet
<>(
idList
);
for
(
String
id
:
allParentIds
)
{
if
(!
parentToChildren
.
containsKey
(
id
)
&&
!
allChildIds
.
contains
(
id
))
{
noParentIds
.
add
(
id
);
// 孤立节点作为根节点
}
}
List
<
List
<
String
>>
groups
=
new
ArrayList
<>();
Set
<
String
>
processed
=
new
HashSet
<>();
for
(
String
root
:
noParentIds
)
{
if
(
processed
.
contains
(
root
))
continue
;
List
<
String
>
group
=
new
ArrayList
<>();
group
.
add
(
root
);
processed
.
add
(
root
);
Set
<
String
>
rootDescendants
=
getAllDescendants
(
root
,
parentToChildren
,
new
HashSet
<>());
for
(
String
other
:
noParentIds
)
{
if
(
processed
.
contains
(
other
))
continue
;
Set
<
String
>
otherDescendants
=
getAllDescendants
(
other
,
parentToChildren
,
new
HashSet
<>());
Set
<
String
>
intersection
=
new
HashSet
<>(
rootDescendants
);
intersection
.
retainAll
(
otherDescendants
);
if
(!
intersection
.
isEmpty
())
{
group
.
add
(
other
);
processed
.
add
(
other
);
}
}
groups
.
add
(
group
);
}
return
groups
;
}
/**
* 处理单个分组
*/
private
static
GroupResult
processSingleGroup
(
List
<
String
>
groupRoots
,
Map
<
String
,
Set
<
String
>>
parentToChildren
,
Map
<
String
,
Set
<
String
>>
childToParents
,
int
[]
globalCounter
)
{
// 收集分组内所有节点(包含孤立节点)
Set
<
String
>
groupNodes
=
new
HashSet
<>();
Queue
<
String
>
queue
=
new
LinkedList
<>(
groupRoots
);
while
(!
queue
.
isEmpty
())
{
String
node
=
queue
.
poll
();
if
(
groupNodes
.
contains
(
node
))
continue
;
groupNodes
.
add
(
node
);
if
(
parentToChildren
.
containsKey
(
node
))
{
queue
.
addAll
(
parentToChildren
.
get
(
node
));
}
}
// BFS遍历分配序号(包含孤立节点)
List
<
NodeInfo
>
nodeInfoList
=
new
ArrayList
<>();
Map
<
String
,
Integer
>
originalToGlobalSerial
=
new
HashMap
<>();
Queue
<
String
>
bfsQueue
=
new
LinkedList
<>(
groupRoots
);
Set
<
String
>
visited
=
new
HashSet
<>(
groupRoots
);
int
groupCounter
=
1
;
// 处理根节点(包括孤立节点)
for
(
String
root
:
groupRoots
)
{
originalToGlobalSerial
.
put
(
root
,
globalCounter
[
0
]);
nodeInfoList
.
add
(
new
NodeInfo
(
root
,
globalCounter
[
0
]++,
groupCounter
++,
new
ArrayList
<>(),
new
ArrayList
<>()));
}
// 处理子节点
while
(!
bfsQueue
.
isEmpty
())
{
String
parent
=
bfsQueue
.
poll
();
if
(
parentToChildren
.
containsKey
(
parent
))
{
for
(
String
child
:
parentToChildren
.
get
(
parent
))
{
if
(!
groupNodes
.
contains
(
child
)
||
visited
.
contains
(
child
))
continue
;
visited
.
add
(
child
);
originalToGlobalSerial
.
put
(
child
,
globalCounter
[
0
]);
List
<
Integer
>
parentSerials
=
childToParents
.
getOrDefault
(
child
,
new
HashSet
<>()).
stream
()
.
filter
(
p
->
originalToGlobalSerial
.
containsKey
(
p
))
.
map
(
originalToGlobalSerial:
:
get
)
.
distinct
()
.
collect
(
Collectors
.
toList
());
nodeInfoList
.
add
(
new
NodeInfo
(
child
,
globalCounter
[
0
]++,
groupCounter
++,
parentSerials
,
new
ArrayList
<>()));
bfsQueue
.
add
(
child
);
}
}
}
// 填充子ID列表(过滤空值)
for
(
NodeInfo
nodeInfo
:
nodeInfoList
)
{
String
originalId
=
nodeInfo
.
getOriginalId
();
if
(
parentToChildren
.
containsKey
(
originalId
))
{
List
<
Integer
>
childSerials
=
parentToChildren
.
get
(
originalId
).
stream
()
.
filter
(
c
->
originalToGlobalSerial
.
containsKey
(
c
))
.
map
(
originalToGlobalSerial:
:
get
)
.
distinct
()
.
collect
(
Collectors
.
toList
());
nodeInfo
.
setNewChildIds
(
childSerials
);
}
}
return
new
GroupResult
(
nodeInfoList
,
originalToGlobalSerial
);
}
/**
* 主方法:处理包含空ChildID的数据
*/
public
static
List
<
GroupResult
>
groupAndOrderIds
(
List
<
String
>
idList
,
List
<
String
>
childIdList
)
{
List
<
List
<
String
>>
groups
=
groupNoParentIds
(
idList
,
childIdList
);
Map
<
String
,
Set
<
String
>>
parentToChildren
=
new
HashMap
<>();
Map
<
String
,
Set
<
String
>>
childToParents
=
new
HashMap
<>();
for
(
int
i
=
0
;
i
<
idList
.
size
();
i
++)
{
String
parentId
=
idList
.
get
(
i
);
String
childId
=
childIdList
.
get
(
i
);
if
(
childId
==
null
||
childId
.
trim
().
isEmpty
())
{
continue
;
}
parentToChildren
.
computeIfAbsent
(
parentId
,
k
->
new
HashSet
<>()).
add
(
childId
);
childToParents
.
computeIfAbsent
(
childId
,
k
->
new
HashSet
<>()).
add
(
parentId
);
}
int
[]
globalCounter
=
{
1
};
List
<
GroupResult
>
results
=
new
ArrayList
<>();
for
(
List
<
String
>
groupRoots
:
groups
)
{
GroupResult
groupResult
=
processSingleGroup
(
groupRoots
,
parentToChildren
,
childToParents
,
globalCounter
);
results
.
add
(
groupResult
);
}
return
results
;
}
/**
* 简化添加新节点:直接指定新父ID、新子ID
* @param existingResults 已有结果
* @param targetGroupIndex 目标分组索引(如分组2为1)
* @param newId 新节点原始ID
* @param newParentIds 新节点的父ID列表(全局序号)
* @param newChildIds 新节点的子ID列表(全局序号)
* @return 更新后的结果
*/
/**
* 简化添加新节点:直接指定新父ID、新子ID(修复全局序号重复问题)
* @param existingResults 已有结果
* @param targetGroupIndex 目标分组索引(如分组2为1)
* @param newId 新节点原始ID
* @param newParentIds 新节点的父ID列表(全局序号)
* @param newChildIds 新节点的子ID列表(全局序号)
* @return 更新后的结果
*/
public
static
List
<
GroupResult
>
addNode
(
List
<
GroupResult
>
existingResults
,
int
targetGroupIndex
,
String
newId
,
List
<
Integer
>
newParentIds
,
List
<
Integer
>
newChildIds
)
{
// 1. 空值安全检查
if
(
existingResults
==
null
||
existingResults
.
isEmpty
()
||
targetGroupIndex
<
0
||
targetGroupIndex
>=
existingResults
.
size
())
{
throw
new
IllegalArgumentException
(
"无效的现有结果或目标分组索引"
);
}
if
(
newId
==
null
||
newId
.
trim
().
isEmpty
())
{
throw
new
IllegalArgumentException
(
"新节点ID不能为空"
);
}
newParentIds
=
newParentIds
!=
null
?
newParentIds
:
new
ArrayList
<>();
newChildIds
=
newChildIds
!=
null
?
newChildIds
:
new
ArrayList
<>();
// 2. 获取目标分组
GroupResult
targetGroup
=
existingResults
.
get
(
targetGroupIndex
);
List
<
NodeInfo
>
nodeList
=
new
ArrayList
<>(
targetGroup
.
getNodeInfoList
());
Map
<
String
,
Integer
>
serialMap
=
new
HashMap
<>(
targetGroup
.
getOriginalToGlobalSerial
());
// 3. 计算所有分组的最大全局序号(确保全局唯一)
int
maxGlobalSerial
=
existingResults
.
stream
()
.
flatMap
(
g
->
g
.
getNodeInfoList
().
stream
())
.
mapToInt
(
NodeInfo:
:
getGlobalSerial
)
.
max
()
.
orElse
(
0
);
int
newGlobalSerial
=
maxGlobalSerial
+
1
;
// 4. 避免新序号与目标分组内现有序号冲突(双重保障)
while
(
serialMap
.
containsValue
(
newGlobalSerial
))
{
newGlobalSerial
++;
}
// 5. 找到新节点的插入位置(父节点之后)
int
insertIndex
=
0
;
for
(
int
i
=
0
;
i
<
nodeList
.
size
();
i
++)
{
NodeInfo
node
=
nodeList
.
get
(
i
);
if
(
newParentIds
.
contains
(
node
.
getGlobalSerial
()))
{
insertIndex
=
i
+
1
;
// 插入到最后一个父节点之后
}
}
// 6. 创建新节点(分组内序号先设为0,后续重新计算)
NodeInfo
newNode
=
new
NodeInfo
(
newId
,
newGlobalSerial
,
0
,
newParentIds
,
newChildIds
);
nodeList
.
add
(
insertIndex
,
newNode
);
serialMap
.
put
(
newId
,
newGlobalSerial
);
// 7. 更新父节点的子ID列表(添加新节点的全局序号)
for
(
NodeInfo
node
:
nodeList
)
{
if
(
newParentIds
.
contains
(
node
.
getGlobalSerial
()))
{
List
<
Integer
>
childIds
=
new
ArrayList
<>(
node
.
getNewChildIds
());
if
(!
childIds
.
contains
(
newGlobalSerial
))
{
childIds
.
add
(
newGlobalSerial
);
node
.
setNewChildIds
(
childIds
);
}
}
}
// 8. 更新子节点的父ID列表(添加新节点的全局序号)
for
(
NodeInfo
node
:
nodeList
)
{
if
(
newChildIds
.
contains
(
node
.
getGlobalSerial
()))
{
List
<
Integer
>
parentIds
=
new
ArrayList
<>(
node
.
getNewParentIds
());
if
(!
parentIds
.
contains
(
newGlobalSerial
))
{
parentIds
.
add
(
newGlobalSerial
);
node
.
setNewParentIds
(
parentIds
);
}
}
}
// 9. 重新计算分组内序号(按列表顺序)
for
(
int
i
=
0
;
i
<
nodeList
.
size
();
i
++)
{
nodeList
.
get
(
i
).
setGroupSerial
(
i
+
1
);
}
// 10. 替换目标分组并返回结果
List
<
GroupResult
>
newResults
=
new
ArrayList
<>(
existingResults
);
newResults
.
set
(
targetGroupIndex
,
new
GroupResult
(
nodeList
,
serialMap
));
return
newResults
;
}
/**
* 通过全局序号删除节点,并重新计算顺序和父子关系
* @param existingResults 已有分组结果
* @param deleteGlobalSerial 待删除节点的全局序号
* @return 删除后的分组结果
*/
public
static
List
<
GroupResult
>
deleteNodeByGlobalSerial
(
List
<
GroupResult
>
existingResults
,
int
deleteGlobalSerial
)
{
// 1. 定位待删除节点及其所在分组
NodeInfo
deleteNode
=
null
;
int
targetGroupIndex
=
-
1
;
GroupResult
targetGroup
=
null
;
for
(
int
i
=
0
;
i
<
existingResults
.
size
();
i
++)
{
GroupResult
group
=
existingResults
.
get
(
i
);
Optional
<
NodeInfo
>
nodeOpt
=
group
.
getNodeInfoList
().
stream
()
.
filter
(
node
->
deleteGlobalSerial
==
node
.
getGlobalSerial
())
.
findFirst
();
if
(
nodeOpt
.
isPresent
())
{
deleteNode
=
nodeOpt
.
get
();
targetGroupIndex
=
i
;
targetGroup
=
group
;
break
;
}
}
if
(
deleteNode
==
null
)
{
System
.
out
.
println
(
"待删除节点不存在(全局序号:"
+
deleteGlobalSerial
+
")"
);
return
existingResults
;
}
// 2. 获取待删除节点的关键信息
String
deleteOriginalId
=
deleteNode
.
getOriginalId
();
List
<
Integer
>
deleteParentIds
=
deleteNode
.
getNewParentIds
();
List
<
Integer
>
deleteChildIds
=
deleteNode
.
getNewChildIds
();
// 3. 从分组中移除节点,并清理序号映射
List
<
NodeInfo
>
newNodeList
=
targetGroup
.
getNodeInfoList
().
stream
()
.
filter
(
node
->
deleteGlobalSerial
!=
node
.
getGlobalSerial
())
.
collect
(
Collectors
.
toList
());
Map
<
String
,
Integer
>
newSerialMap
=
new
HashMap
<>(
targetGroup
.
getOriginalToGlobalSerial
());
newSerialMap
.
remove
(
deleteOriginalId
);
// 4. 更新父节点的子ID列表(移除待删除节点的全局序号)
for
(
NodeInfo
node
:
newNodeList
)
{
if
(
deleteParentIds
.
contains
(
node
.
getGlobalSerial
()))
{
List
<
Integer
>
newChildIds
=
node
.
getNewChildIds
().
stream
()
.
filter
(
id
->
id
!=
deleteGlobalSerial
)
.
collect
(
Collectors
.
toList
());
node
.
setNewChildIds
(
newChildIds
);
}
}
// 5. 更新子节点的父ID列表(移除待删除节点的全局序号)
for
(
NodeInfo
node
:
newNodeList
)
{
if
(
deleteChildIds
.
contains
(
node
.
getGlobalSerial
()))
{
List
<
Integer
>
newParentIds
=
node
.
getNewParentIds
().
stream
()
.
filter
(
id
->
id
!=
deleteGlobalSerial
)
.
collect
(
Collectors
.
toList
());
node
.
setNewParentIds
(
newParentIds
);
}
}
// 6. 重新计算分组内序号(顺序顺延)
for
(
int
i
=
0
;
i
<
newNodeList
.
size
();
i
++)
{
newNodeList
.
get
(
i
).
setGroupSerial
(
i
+
1
);
}
// 7. (可选)重新计算全局序号(保持连续性,如需可开启)
// resetGlobalSerial(existingResults, targetGroupIndex, newNodeList);
// 8. 替换目标分组并返回结果
List
<
GroupResult
>
newResults
=
new
ArrayList
<>(
existingResults
);
newResults
.
set
(
targetGroupIndex
,
new
GroupResult
(
newNodeList
,
newSerialMap
));
return
newResults
;
}
/**
* 添加新数据(支持仅孤立节点的场景)
* @param existingResults 已有分组结果
* @param newIdList 新数据的ID列表
* @param newChildIdList 新数据的ChildID列表(允许空值)
* @return 包含新分组的结果列表
*/
public
static
List
<
GroupResult
>
addNewDataWithIsolatedGroup
(
List
<
GroupResult
>
existingResults
,
List
<
String
>
newIdList
,
List
<
String
>
newChildIdList
)
{
// 空值安全检查
if
(
newIdList
==
null
||
newIdList
.
isEmpty
())
{
return
existingResults
;
}
if
(
newChildIdList
==
null
)
{
newChildIdList
=
new
ArrayList
<>();
}
// 1. 初始化数据结构
Set
<
String
>
allNewNodes
=
new
HashSet
<>(
newIdList
);
// 所有新节点
Map
<
String
,
String
>
idToChild
=
new
HashMap
<>();
// 临时存储ID与ChildID的映射
// 构建ID→ChildID映射(处理空值)
for
(
int
i
=
0
;
i
<
newIdList
.
size
();
i
++)
{
String
id
=
newIdList
.
get
(
i
);
String
childId
=
i
<
newChildIdList
.
size
()
?
newChildIdList
.
get
(
i
)
:
""
;
if
(
id
!=
null
&&
!
id
.
trim
().
isEmpty
())
{
idToChild
.
put
(
id
,
(
childId
==
null
?
""
:
childId
.
trim
()));
allNewNodes
.
add
(
id
);
// 确保ID被加入
if
(!
childId
.
trim
().
isEmpty
())
{
allNewNodes
.
add
(
childId
.
trim
());
// 子节点也加入
}
}
}
// 2. 分离孤立节点和关联节点
List
<
String
>
isolatedNodes
=
new
ArrayList
<>();
List
<
String
>
relationNodes
=
new
ArrayList
<>();
for
(
String
node
:
allNewNodes
)
{
String
childId
=
idToChild
.
getOrDefault
(
node
,
""
);
// 孤立节点:无ChildID,且不是任何节点的ChildID
boolean
isIsolated
=
childId
.
isEmpty
()
&&
!
idToChild
.
values
().
contains
(
node
);
if
(
isIsolated
)
{
isolatedNodes
.
add
(
node
);
}
else
{
relationNodes
.
add
(
node
);
}
}
// 3. 获取现有结果的最大全局序号
int
maxGlobalSerial
=
existingResults
.
stream
()
.
flatMap
(
g
->
g
.
getNodeInfoList
().
stream
())
.
mapToInt
(
NodeInfo:
:
getGlobalSerial
)
.
max
()
.
orElse
(
0
);
int
[]
globalCounter
=
{
maxGlobalSerial
+
1
};
// 4. 处理关联节点(如果有)
if
(!
relationNodes
.
isEmpty
())
{
GroupResult
relationGroup
=
createRelationGroup
(
idToChild
,
relationNodes
,
globalCounter
);
existingResults
.
add
(
relationGroup
);
}
// 5. 处理孤立节点(即使只有孤立节点也创建分组)
for
(
String
isolatedNode
:
isolatedNodes
)
{
GroupResult
isolatedGroup
=
createIsolatedGroup
(
isolatedNode
,
globalCounter
);
existingResults
.
add
(
isolatedGroup
);
}
return
existingResults
;
}
/**
* 创建关联节点的分组(20→21→22)
*/
private
static
GroupResult
createRelationGroup
(
Map
<
String
,
String
>
idToChild
,
List
<
String
>
relationNodes
,
int
[]
globalCounter
)
{
// 构建父子映射
Map
<
String
,
Set
<
String
>>
parentToChildren
=
new
HashMap
<>();
Map
<
String
,
Set
<
String
>>
childToParents
=
new
HashMap
<>();
for
(
String
parent
:
idToChild
.
keySet
())
{
String
child
=
idToChild
.
get
(
parent
);
if
(!
child
.
isEmpty
())
{
parentToChildren
.
computeIfAbsent
(
parent
,
k
->
new
HashSet
<>()).
add
(
child
);
childToParents
.
computeIfAbsent
(
child
,
k
->
new
HashSet
<>()).
add
(
parent
);
}
}
// 识别根节点(无父级的节点)
List
<
String
>
rootNodes
=
relationNodes
.
stream
()
.
filter
(
node
->
!
childToParents
.
containsKey
(
node
))
.
collect
(
Collectors
.
toList
());
List
<
NodeInfo
>
nodeList
=
new
ArrayList
<>();
Map
<
String
,
Integer
>
serialMap
=
new
HashMap
<>();
Queue
<
String
>
queue
=
new
LinkedList
<>(
rootNodes
);
Set
<
String
>
visited
=
new
HashSet
<>(
rootNodes
);
int
groupCounter
=
1
;
// 处理根节点
for
(
String
root
:
rootNodes
)
{
serialMap
.
put
(
root
,
globalCounter
[
0
]);
nodeList
.
add
(
new
NodeInfo
(
root
,
globalCounter
[
0
]++,
groupCounter
++,
new
ArrayList
<>(),
new
ArrayList
<>()));
}
// BFS处理子节点
while
(!
queue
.
isEmpty
())
{
String
parent
=
queue
.
poll
();
if
(
parentToChildren
.
containsKey
(
parent
))
{
for
(
String
child
:
parentToChildren
.
get
(
parent
))
{
if
(
visited
.
contains
(
child
))
continue
;
visited
.
add
(
child
);
List
<
Integer
>
parentSerials
=
childToParents
.
get
(
child
).
stream
()
.
map
(
p
->
serialMap
.
get
(
p
))
.
collect
(
Collectors
.
toList
());
serialMap
.
put
(
child
,
globalCounter
[
0
]);
nodeList
.
add
(
new
NodeInfo
(
child
,
globalCounter
[
0
]++,
groupCounter
++,
parentSerials
,
new
ArrayList
<>()));
queue
.
add
(
child
);
}
}
}
// 填充子ID列表
for
(
NodeInfo
node
:
nodeList
)
{
String
originalId
=
node
.
getOriginalId
();
if
(
parentToChildren
.
containsKey
(
originalId
))
{
List
<
Integer
>
childSerials
=
parentToChildren
.
get
(
originalId
).
stream
()
.
map
(
c
->
serialMap
.
get
(
c
))
.
collect
(
Collectors
.
toList
());
node
.
setNewChildIds
(
childSerials
);
}
}
return
new
GroupResult
(
nodeList
,
serialMap
);
}
/**
* 创建孤立节点的分组(如24)
*/
private
static
GroupResult
createIsolatedGroup
(
String
isolatedNode
,
int
[]
globalCounter
)
{
NodeInfo
node
=
new
NodeInfo
(
isolatedNode
,
globalCounter
[
0
],
1
,
new
ArrayList
<>(),
new
ArrayList
<>());
List
<
NodeInfo
>
nodeList
=
Collections
.
singletonList
(
node
);
Map
<
String
,
Integer
>
serialMap
=
Collections
.
singletonMap
(
isolatedNode
,
globalCounter
[
0
]++);
return
new
GroupResult
(
nodeList
,
serialMap
);
}
// 测试(新数据)
public
static
void
Test
()
{
// 新表格数据
List
<
String
>
idList
=
Arrays
.
asList
(
"1"
,
"2"
,
"3"
,
"3"
,
"5"
,
"10"
,
"3"
,
"6"
,
"7"
,
"9"
,
"23"
);
List
<
String
>
childIdList
=
Arrays
.
asList
(
"2"
,
"3"
,
"4"
,
"4"
,
"10"
,
"3"
,
"11"
,
"7"
,
"8"
,
"7"
,
""
);
// 分组并生成结果
List
<
GroupResult
>
results
=
groupAndOrderIds
(
idList
,
childIdList
);
// 新增节点信息
// 直接指定新节点信息:原始ID=12,新父ID=[8,9],新子ID=[11]
String
newId
=
"13"
;
List
<
Integer
>
newParentIds
=
Arrays
.
asList
(
8
,
9
);
// 6和9的全局序号
List
<
Integer
>
newChildIds
=
Arrays
.
asList
(
11
);
// 8的全局序号
int
targetGroupIndex
=
1
;
// 分组2的索引
// 添加新节点
results
=
addNode
(
results
,
targetGroupIndex
,
newId
,
newParentIds
,
newChildIds
);
List
<
String
>
newIdList
=
Arrays
.
asList
(
"20"
,
"21"
,
"24"
);
List
<
String
>
newChildIdList
=
Arrays
.
asList
(
"21"
,
"22"
,
""
);
// 添加新数据
results
=
addNewDataWithIsolatedGroup
(
results
,
newIdList
,
newChildIdList
);
results
=
deleteNodeByGlobalSerial
(
results
,
13
);
// 输出结果
for
(
int
i
=
0
;
i
<
results
.
size
();
i
++)
{
GroupResult
groupResult
=
results
.
get
(
i
);
List
<
NodeInfo
>
nodeInfoList
=
groupResult
.
getNodeInfoList
();
System
.
out
.
println
(
"分组"
+
(
i
+
1
)
+
"顺序:"
+
nodeInfoList
);
// 输出每个节点的详细信息
for
(
NodeInfo
nodeInfo
:
nodeInfoList
)
{
System
.
out
.
printf
(
"原始ID:%s → 全局序号:%d,分组内序号:%d,新父ID列表:%s,新子ID列表:%s%n"
,
nodeInfo
.
getOriginalId
(),
nodeInfo
.
getGlobalSerial
(),
nodeInfo
.
getGroupSerial
(),
nodeInfo
.
getNewParentIds
().
isEmpty
()
?
"无"
:
nodeInfo
.
getNewParentIds
(),
nodeInfo
.
getNewChildIds
());
}
System
.
out
.
println
(
"------------------------"
);
}
}
}
src/main/java/com/aps/service/Algorithm/Initialization.java
View file @
f7bdf363
...
...
@@ -17,9 +17,11 @@ import java.util.stream.IntStream;
*/
public
class
Initialization
{
private
static
List
<
Entry
>
allOperations
;
private
static
GlobalParam
_globalParam
;
public
Initialization
(
List
<
Entry
>
allOperations
)
{
public
Initialization
(
GlobalParam
globalParam
,
List
<
Entry
>
allOperations
)
{
Initialization
.
allOperations
=
allOperations
;
_globalParam
=
globalParam
;
}
/**
* 预生成全局工序列表(按“订单0→订单1→…+订单内工序1→2→…”排序,分配GlobalOpId)
...
...
@@ -257,7 +259,7 @@ int populationSize=param.getPopulationSize();
*/
private
List
<
Integer
>
shuffleWithPriority
(
List
<
Integer
>
os
)
{
if
(!
GlobalParam
.
IsBreakPriority
)
{
if
(!
_globalParam
.
isIsBreakPriority
()
)
{
return
new
ArrayList
<>(
os
);
}
...
...
src/main/java/com/aps/service/Algorithm/MachineCalculator.java
View file @
f7bdf363
...
...
@@ -4,6 +4,7 @@ import com.aps.common.util.ProductionDeepCopyUtil;
import
com.aps.entity.Algorithm.GAScheduleResult
;
import
com.aps.entity.Algorithm.ScheduleResultDetail
;
import
com.aps.entity.basic.*
;
import
com.aps.service.plan.AlgorithmScheduler8
;
import
com.aps.service.plan.MachineSchedulerService
;
import
com.baomidou.mybatisplus.core.toolkit.StringUtils
;
...
...
@@ -37,15 +38,15 @@ public class MachineCalculator {
* 获取机器下一个可用时间窗口(考虑班次约束)
*/
public
List
<
ScheduleResultDetail
>
getNextAvailableTime
(
Machine
machine
,
int
proposedStartTime
,
int
prevtime
,
double
processingTime
,
int
prevtime
,
int
processingTime
,
List
<
GAScheduleResult
>
existingTasks
,
boolean
isInterrupt
,
boolean
istask
,
boolean
islockMachineTime
)
{
LocalDateTime
startTime
=
baseTime
.
plus
(
proposedStartTime
,
ChronoUnit
.
MINUTE
S
);
LocalDateTime
startTime
=
baseTime
.
plus
(
proposedStartTime
,
ChronoUnit
.
SECOND
S
);
String
prevtimestr
=
""
;
if
(
prevtime
>
-
1
)
{
prevtimestr
=
baseTime
.
plus
(
prevtime
,
ChronoUnit
.
MINUTE
S
)
prevtimestr
=
baseTime
.
plus
(
prevtime
,
ChronoUnit
.
SECOND
S
)
.
format
(
DateTimeFormatter
.
ofPattern
(
"yyyy-MM-dd HH:mm:ss"
));
}
...
...
@@ -55,54 +56,49 @@ public class MachineCalculator {
}
// 查找最早可用开始时间
private
List
<
ScheduleResultDetail
>
findEarliestStart
(
Machine
machine
,
double
processingTime
,
LocalDateTime
currentTime
,
String
prevtime
,
List
<
GAScheduleResult
>
existingTasks
,
boolean
checkprevtime
,
boolean
islockMachineTime
)
{
// 获取设备上已有任务
private
List
<
ScheduleResultDetail
>
findEarliestStart
(
Machine
machine
,
int
processingTime
,
LocalDateTime
currentTime
,
String
prevtime
,
List
<
GAScheduleResult
>
existingTasks
,
boolean
checkprevtime
,
boolean
islockMachineTime
)
{
List
<
GAScheduleResult
>
machineTasks
=
existingTasks
.
stream
()
.
filter
(
t
->
t
.
getMachineId
()
==
machine
.
getId
())
.
sorted
(
Comparator
.
comparingInt
(
GAScheduleResult:
:
getStartTime
))
.
collect
(
Collectors
.
toList
());
List
<
ScheduleResultDetail
>
times
=
new
ArrayList
<>();
TimeSegment
slot
=
GetCurrentOrNextShift
(
machine
,
currentTime
,
prevtime
,
checkprevtime
);
LocalDateTime
startCandidate
=
slot
.
getStart
().
isAfter
(
(
prevtime
.
isEmpty
()
?
currentTime
:
LocalDateTime
.
parse
(
prevtime
,
DateTimeFormatter
.
ofPattern
(
"yyyy-MM-dd HH:mm:ss"
)))
)
?
slot
.
getStart
()
:
(
prevtime
.
isEmpty
()
?
currentTime
:
LocalDateTime
.
parse
(
prevtime
,
DateTimeFormatter
.
ofPattern
(
"yyyy-MM-dd HH:mm:ss"
)));
TimeSegment
slot
=
GetCurrentOrNextShift
(
machine
,
currentTime
,
prevtime
,
checkprevtime
);
if
(
slot
==
null
)
return
times
;
LocalDateTime
endCandidate
=
startCandidate
.
plus
((
long
)
processingTime
,
ChronoUnit
.
MINUTES
);
LocalDateTime
prevTimeDateTime
=
StringUtils
.
isEmpty
(
prevtime
)
?
null
:
LocalDateTime
.
parse
(
prevtime
);
LocalDateTime
startCandidate
=
slot
.
getStart
().
isAfter
(
prevTimeDateTime
!=
null
?
prevTimeDateTime
:
currentTime
)
?
slot
.
getStart
()
:
(
prevTimeDateTime
!=
null
?
prevTimeDateTime
:
currentTime
);
LocalDateTime
endCandidate
=
startCandidate
.
plusSeconds
(
processingTime
);
// 检查是否在可用时间段内
if
(
endCandidate
.
isAfter
(
slot
.
getEnd
()))
{
// 放不下,继续寻找后续可用时间
return
CaldEarliestStart
(
machine
,
processingTime
,
currentTime
,
prevtime
,
machineTasks
,
checkprevtime
,
islockMachineTime
);
return
CaldEarliestStart
(
machine
,
processingTime
,
currentTime
,
prevtime
,
machineTasks
,
checkprevtime
,
islockMachineTime
);
}
else
{
ScheduleResultDetail
time
=
new
ScheduleResultDetail
();
time
.
setKey
(
slot
.
getKey
());
time
.
setStartTime
((
int
)
ChronoUnit
.
MINUTE
S
.
between
(
baseTime
,
startCandidate
));
time
.
setEndTime
((
int
)
ChronoUnit
.
MINUTE
S
.
between
(
baseTime
,
endCandidate
));
time
.
setStartTime
((
int
)
ChronoUnit
.
SECOND
S
.
between
(
baseTime
,
startCandidate
));
time
.
setEndTime
((
int
)
ChronoUnit
.
SECOND
S
.
between
(
baseTime
,
endCandidate
));
times
.
add
(
time
);
if
(
islockMachineTime
)
{
if
(
islockMachineTime
)
{
RemoveMachineAvailable
(
machine
,
time
);
}
return
times
;
}
}
private
List
<
ScheduleResultDetail
>
CaldEarliestStart
(
Machine
machine
,
double
processingTime
,
LocalDateTime
currentTime
,
Machine
machine
,
int
processingTime
,
LocalDateTime
currentTime
,
String
prevtime
,
List
<
GAScheduleResult
>
machineTasks
,
boolean
checkprevtime
,
boolean
islockMachineTime
)
{
double
remainingTime
=
processingTime
;
int
remainingTime
=
processingTime
;
LocalDateTime
st
=
StringUtils
.
isEmpty
(
prevtime
)
?
currentTime
:
LocalDateTime
.
parse
(
prevtime
);
LocalDateTime
prevEnd
=
LocalDateTime
.
of
(
2000
,
1
,
1
,
0
,
0
,
0
);
List
<
ScheduleResultDetail
>
times
=
new
ArrayList
<>();
...
...
@@ -122,7 +118,7 @@ public class MachineCalculator {
LocalDateTime
finalPrevEnd
=
prevEnd
;
boolean
hasTask
=
machineTasks
.
stream
()
.
anyMatch
(
t
->
{
LocalDateTime
taskStart
=
baseTime
.
plus
Minute
s
(
t
.
getStartTime
());
LocalDateTime
taskStart
=
baseTime
.
plus
Second
s
(
t
.
getStartTime
());
return
taskStart
.
isAfter
(
finalPrevEnd
)
&&
taskStart
.
isBefore
(
shiftStart
);
});
...
...
@@ -158,29 +154,34 @@ public class MachineCalculator {
prevEnd
=
shiftEnd
;
// 计算有效时间
LocalDateTime
effectiveStart
=
st
.
isAfter
(
shiftStart
)
?
st
:
shiftStart
;
long
available
Minutes
=
ChronoUnit
.
MINUTE
S
.
between
(
effectiveStart
,
shiftEnd
);
long
available
Seconds
=
ChronoUnit
.
SECOND
S
.
between
(
effectiveStart
,
shiftEnd
);
// 处理当前班次
double
processable
=
Math
.
min
(
remainingTime
,
(
int
)
availableMinute
s
);
int
processable
=
Math
.
min
(
remainingTime
,
(
int
)
availableSecond
s
);
remainingTime
-=
processable
;
currentTime
=
effectiveStart
.
plus
Minutes
((
long
)
processable
);
currentTime
=
effectiveStart
.
plus
Seconds
(
processable
);
// 添加时间详情
ScheduleResultDetail
time
=
new
ScheduleResultDetail
();
time
.
setKey
(
shift
.
getKey
());
time
.
setStartTime
((
int
)
ChronoUnit
.
MINUTE
S
.
between
(
baseTime
,
effectiveStart
));
time
.
setEndTime
((
int
)
ChronoUnit
.
MINUTE
S
.
between
(
baseTime
,
currentTime
));
time
.
setStartTime
((
int
)
ChronoUnit
.
SECOND
S
.
between
(
baseTime
,
effectiveStart
));
time
.
setEndTime
((
int
)
ChronoUnit
.
SECOND
S
.
between
(
baseTime
,
currentTime
));
times
.
add
(
time
);
if
(
islockMachineTime
)
{
// 还原未使用的时间段
RemoveMachineAvailable
(
machine
,
time
);
}
}
// 还原未使用的时间段
if
(
islockMachineTime
)
{
// 还原未使用的时间段
AddMachineAvailable
(
machine
,
oldTimes
);
}
return
times
;
}
/**
* 获取设备当前或下一个有效班次
*/
...
...
@@ -196,7 +197,7 @@ public class MachineCalculator {
if
(
start
==
null
)
{
// 生成新时间段
List
<
TimeSegment
>
timeSegments
=
machineScheduler
.
generateTimeSegment
(
machine
,
time
);
List
<
TimeSegment
>
timeSegments
=
machineScheduler
.
generateTimeSegment
(
machine
,
time
.
plusDays
(
1
)
);
machine
.
getAvailability
().
addAll
(
timeSegments
);
// 更新设备时间线
...
...
@@ -215,6 +216,8 @@ public class MachineCalculator {
return
start
;
}
private
void
RemoveMachineAvailable
(
Machine
machine
,
ScheduleResultDetail
geneDetails
)
{
List
<
TimeSegment
>
timeSegments
=
new
ArrayList
<>();
...
...
@@ -226,11 +229,11 @@ public class MachineCalculator {
if
(
index
>
-
1
)
{
TimeSegment
targetSegment
=
machine
.
getAvailability
().
get
(
index
);
LocalDateTime
geneEndTime
=
baseTime
.
plus
Minute
s
(
geneDetails
.
getEndTime
());
LocalDateTime
geneEndTime
=
baseTime
.
plus
Second
s
(
geneDetails
.
getEndTime
());
if
(
targetSegment
.
getEnd
().
isAfter
(
geneEndTime
))
{
TimeSegment
usedSegment
=
new
TimeSegment
();
usedSegment
.
setStart
(
baseTime
.
plus
Minute
s
(
geneDetails
.
getStartTime
()));
usedSegment
.
setStart
(
baseTime
.
plus
Second
s
(
geneDetails
.
getStartTime
()));
usedSegment
.
setEnd
(
geneEndTime
);
usedSegment
.
setHoliday
(
false
);
usedSegment
.
setKey
(
UUID
.
randomUUID
().
toString
());
...
...
src/main/java/com/aps/service/Algorithm/OrderSortService.java
View file @
f7bdf363
...
...
@@ -9,6 +9,7 @@ import org.springframework.util.CollectionUtils;
import
javax.annotation.PostConstruct
;
import
java.lang.reflect.Method
;
import
java.time.LocalDate
;
import
java.time.LocalDateTime
;
import
java.time.OffsetDateTime
;
import
java.util.*
;
import
java.util.function.Function
;
...
...
@@ -35,7 +36,7 @@ public class OrderSortService {
registerFieldExtractor
(
"dueDate"
,
Order
->
{
// 直接返回LocalDate,处理null情况
return
Optional
.
ofNullable
(
Order
.
getDueDate
())
.
map
(
Offset
DateTime:
:
toLocalDate
)
.
map
(
Local
DateTime:
:
toLocalDate
)
.
orElse
(
null
);
});
registerFieldExtractor
(
"priority"
,
Order:
:
getPriority
);
...
...
src/main/java/com/aps/service/plan/AlgorithmScheduler6.java
View file @
f7bdf363
...
...
@@ -324,7 +324,7 @@ public class AlgorithmScheduler6 {
LocalDateTime
completionTime
=
chromosome
.
getBaseTime
().
plusMinutes
(
orderCompletion
);
// 修复:正确处理OffsetDateTime到LocalDateTime的转换
LocalDateTime
dueDateTime
=
order
.
getDueDate
()
.
toLocalDateTime
()
;
LocalDateTime
dueDateTime
=
order
.
getDueDate
();
if
(
completionTime
.
isAfter
(
dueDateTime
))
{
// 计算延迟小时数(修复时间计算)
...
...
src/main/java/com/aps/service/plan/AlgorithmScheduler7.java
View file @
f7bdf363
...
...
@@ -473,7 +473,7 @@ public class AlgorithmScheduler7 {
if
(
order
!=
null
)
{
LocalDateTime
completionTime
=
chromosome
.
getBaseTime
().
plusMinutes
(
orderCompletion
);
LocalDateTime
dueDateTime
=
order
.
getDueDate
()
.
toLocalDateTime
()
;
LocalDateTime
dueDateTime
=
order
.
getDueDate
();
if
(
completionTime
.
isAfter
(
dueDateTime
))
{
long
totalMinutes
=
java
.
time
.
temporal
.
ChronoUnit
.
MINUTES
.
between
(
dueDateTime
,
completionTime
);
...
...
src/main/java/com/aps/service/plan/AlgorithmScheduler8.java
View file @
f7bdf363
...
...
@@ -94,7 +94,7 @@ public class AlgorithmScheduler8 {
// 为每个订单分配工序
for
(
Order
order
:
_orders
)
{
Product
product
=
_products
.
stream
()
.
filter
(
p
->
p
.
getId
()
==
order
.
getProductId
())
.
filter
(
p
->
p
.
getId
()
==
order
.
getProductId
())
.
findFirst
()
.
orElseThrow
(()
->
new
NoSuchElementException
(
"Product not found: "
+
order
.
getProductId
()));
...
...
@@ -322,7 +322,7 @@ public class AlgorithmScheduler8 {
// 创建基因
Gene
gene
=
new
Gene
();
gene
.
setOrderId
(
order
.
getId
());
//
gene.setOrderId(order.getId());
gene
.
setProductId
(
order
.
getProductId
());
gene
.
setOperationId
(
operation
.
getId
());
gene
.
setMachineId
(
machine
.
getId
());
...
...
@@ -415,21 +415,21 @@ public class AlgorithmScheduler8 {
.
mapToInt
(
Gene:
:
getEndTime
)
.
max
()
.
orElse
(
0
);
Order
order
=
_orders
.
stream
()
.
filter
(
o
->
o
.
getId
()
==
group
.
getKey
())
.
findFirst
()
.
orElse
(
null
);
if
(
order
!=
null
)
{
LocalDateTime
completionTime
=
chromosome
.
getBaseTime
().
plusMinutes
(
orderCompletion
);
LocalDateTime
dueDateTime
=
order
.
getDueDate
().
toLocalDateTim
e
();
if
(
completionTime
.
isAfter
(
dueDateTime
))
{
long
hours
=
ChronoUnit
.
HOURS
.
between
(
dueDateTime
,
completionTime
);
long
minutes
=
ChronoUnit
.
MINUTES
.
between
(
dueDateTime
,
completionTime
)
%
60
;
tardiness
+=
hours
+
(
double
)
minutes
/
60
;
}
}
//
Order order = _orders.stream()
//
.filter(o -> o.getId() == group.getKey())
//
.findFirst()
//
.orElse(null);
//
//
if (order != null) {
//
LocalDateTime completionTime = chromosome.getBaseTime().plusMinutes(orderCompletion);
// LocalDateTime dueDateTime = order.getDueDat
e();
//
//
if (completionTime.isAfter(dueDateTime)) {
//
long hours = ChronoUnit.HOURS.between(dueDateTime, completionTime);
//
long minutes = ChronoUnit.MINUTES.between(dueDateTime, completionTime) % 60;
//
tardiness += hours + (double) minutes / 60;
//
}
//
}
}
// 3. 总换型时间
...
...
src/main/java/com/aps/service/plan/MachineSchedulerService.java
View file @
f7bdf363
...
...
@@ -206,7 +206,12 @@ public class MachineSchedulerService {
&&
s
.
getDays
()
!=
null
&&
containsDay
(
s
.
getDays
(),
date
.
getDayOfWeek
()))
.
collect
(
Collectors
.
toList
());
if
(
shifts
==
null
||
shifts
.
size
()==
0
)
{
shifts
=
machine
.
getShifts
().
stream
()
.
filter
(
s
->
s
.
getDays
()
!=
null
&&
containsDay
(
s
.
getDays
(),
date
.
getDayOfWeek
()))
.
collect
(
Collectors
.
toList
());
}
for
(
Shift
shift
:
shifts
)
{
LocalDateTime
shiftStart
=
date
.
atTime
(
shift
.
getStartTime
());
LocalDateTime
shiftEnd
=
shift
.
getEndTime
().
isBefore
(
shift
.
getStartTime
())
?
...
...
@@ -247,6 +252,12 @@ public class MachineSchedulerService {
}
private
List
<
TimeSegment
>
mergeSegments
(
List
<
TimeSegment
>
segments
)
{
if
(
segments
==
null
||
segments
.
size
()==
0
)
{
return
null
;
}
List
<
TimeSegment
>
maintenanceSegments
=
segments
.
stream
()
.
filter
(
t
->
t
.
getType
()
==
SegmentType
.
MAINTENANCE
)
.
collect
(
Collectors
.
toList
());
...
...
src/main/java/com/aps/service/plan/PlanResultService.java
View file @
f7bdf363
...
...
@@ -7,6 +7,8 @@ import com.aps.controller.gantt.FileUploadController;
import
com.aps.entity.*
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.GAScheduleResult
;
import
com.aps.entity.Algorithm.IDAndChildID.GroupResult
;
import
com.aps.entity.Algorithm.IDAndChildID.NodeInfo
;
import
com.aps.entity.Algorithm.ScheduleParams
;
import
com.aps.entity.Algorithm.ScheduleResultDetail
;
import
com.aps.entity.basic.ScheduleChromosome
;
...
...
@@ -15,6 +17,7 @@ import com.aps.entity.Schedule.MachineVO;
import
com.aps.entity.basic.*
;
import
com.aps.service.*
;
import
com.aps.service.Algorithm.GeneticAlgorithm
;
import
com.aps.service.Algorithm.IdGroupingWithDualSerial
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
...
...
@@ -41,6 +44,10 @@ public class PlanResultService {
@Autowired
private
MesShiftWorkSchedService
_MesShiftWorkSchedService
;
@Autowired
private
ProdLaunchOrderService
_prodLaunchOrderService
;
@Autowired
private
ProdProcessExecService
_prodProcessExecService
;
...
...
@@ -119,7 +126,7 @@ public class PlanResultService {
}
}
public
List
<
Chromosome
>
execute1
()
{
public
Chromosome
execute1
()
{
try
{
...
...
@@ -189,7 +196,7 @@ public class PlanResultService {
for
(
Operation
o
:
product
.
getOperations
())
{
// 假设Product类有getOperations()方法返回工序列表
Entry
entry
=
new
Entry
();
entry
.
setId
(
id
);
entry
.
setGroupId
(
order
.
getId
());
//
entry.setGroupId(order.getId());
entry
.
setSequence
(
sequence
);
entry
.
setMachineOptions
(
o
.
getMachineOptions
());
// 假设Operation类有获取机器选项的方法
entry
.
setPriority
(
order
.
getPriority
());
...
...
@@ -206,12 +213,13 @@ public class PlanResultService {
id
++;
}
}
GlobalParam
globalParam
=
new
GlobalParam
();
// 5. 执行调度算法
GeneticAlgorithm
scheduler
=
new
GeneticAlgorithm
(
machines
,
orders
,
null
,
machineScheduler
);
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
List
<
Chromosome
>
Chromosomes
=
scheduler
.
Run
(
param
,
allOperations
);
GeneticAlgorithm
scheduler
=
new
GeneticAlgorithm
(
globalParam
,
machines
,
orders
,
null
,
machineScheduler
);
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
Chromosome
Chromosomes
=
scheduler
.
Run
(
param
,
allOperations
);
Chromosomes
.
forEach
(
this
::
WriteScheduleSummary
);
//
Chromosomes.forEach(this::WriteScheduleSummary);
return
Chromosomes
;
...
...
@@ -220,13 +228,14 @@ public class PlanResultService {
}
}
public
List
<
Chromosome
>
execute2
(
String
SceneId
)
{
public
Chromosome
execute2
(
String
SceneId
)
{
try
{
ScheduleParams
param
=
new
ScheduleParams
();
param
.
setBaseTime
(
LocalDateTime
.
of
(
2025
,
11
,
1
,
0
,
0
,
0
));
param
.
setPopulationSize
(
50
);
param
.
setMaxIterations
(
100
);
// 1. 读取数据
// List<Machine> machines = loadData("machines.json", Machine.class);
// List<Product> products = loadData("products.json", Product.class);
...
...
@@ -234,146 +243,40 @@ public class PlanResultService {
List
<
ProdProcessExec
>
ProdProcessExecs
=
_prodProcessExecService
.
lambdaQuery
()
.
eq
(
ProdProcessExec:
:
getSceneId
,
SceneId
)
.
list
();
List
<
ProdEquipment
>
ProdEquipments
=
_prodEquipmentService
.
lambdaQuery
()
.
eq
(
ProdEquipment:
:
getSceneId
,
SceneId
)
.
list
();
List
<
ProdOrderProcess
>
ProdOrderProcesss
=
_prodOrderProcessService
.
lambdaQuery
()
.
eq
(
ProdOrderProcess:
:
getSceneId
,
SceneId
)
List
<
ProdLaunchOrder
>
ProdLaunchOrders
=
_prodLaunchOrderService
.
lambdaQuery
()
.
eq
(
ProdLaunchOrder:
:
getSceneId
,
SceneId
)
.
list
();
Set
<
String
>
targetExecId
=
ProdOrderProcesss
.
stream
()
.
map
(
ProdOrderProcess:
:
getTargetExecId
)
// 提取TARGET_ORDER_ID
.
collect
(
Collectors
.
toSet
());
// 转为Set去重
List
<
ProdProcessExec
>
ops
=
ProdProcessExecs
.
stream
()
.
filter
(
e
->
!
targetExecId
.
contains
(
e
.
getExecId
()))
// 过滤条件
.
collect
(
Collectors
.
toList
());
// 按设备分组
List
<
Long
>
MachineIds
=
ProdEquipments
.
stream
()
.
map
(
ProdEquipment:
:
getEquipId
)
.
distinct
()
.
sorted
()
.
collect
(
Collectors
.
toList
());
List
<
Machine
>
machines
=
new
ArrayList
<>();
for
(
Long
id
:
MachineIds
)
{
Machine
machine
=
new
Machine
();
machine
.
setId
(
id
);
machines
.
add
(
machine
);
}
//节假日
List
<
MesHoliday
>
holidays
=
_MesHolidayService
.
list
();
LambdaQueryWrapper
<
ProdEquipSpecialCal
>
ProdEquipSpecialCalWrapper
=
new
LambdaQueryWrapper
<>();
ProdEquipSpecialCalWrapper
.
eq
(
ProdEquipSpecialCal:
:
getSceneId
,
SceneId
);
List
<
ProdEquipSpecialCal
>
ProdEquipSpecialCals
=
_prodEquipSpecialCalService
.
list
(
ProdEquipSpecialCalWrapper
);
List
<
MesShiftWorkSched
>
MesShiftWorkScheds
=
_MesShiftWorkSchedService
.
list
();
// 将节假日添加到所有设备中
InitCalendarToAllMachines
(
machines
,
ProdEquipSpecialCals
,
MesShiftWorkScheds
);
// 3. 创建调度服务
MachineSchedulerService
machineScheduler
=
new
MachineSchedulerService
(
param
.
getBaseTime
());
// 4. 初始化机器时间线
for
(
Machine
machine
:
machines
)
{
MachineTimeline
timeline
=
machineScheduler
.
getOrCreateTimeline
(
machine
);
machine
.
setAvailability
(
timeline
.
getSegments
());
}
List
<
Machine
>
machines
=
InitCalendarToAllMachines
(
SceneId
,
ProdEquipments
,
machineScheduler
);
// 3. 构建订单-工序数据
List
<
Entry
>
allOperations
=
new
ArrayList
<>();
Random
rnd
=
new
Random
();
// 注意:此处变量声明但未使用,可根据实际需求保留或移除
int
id
=
0
;
int
groupid
=
1
;
List
<
Entry
>
entrys
=
new
ArrayList
<>();
for
(
ProdProcessExec
op
:
ops
)
{
int
sequence
=
1
;
Entry
entry
=
new
Entry
();
id
=
id
+
1
;
entry
.
setId
(
id
);
entry
.
setGroupId
(
groupid
);
entry
.
setSequence
(
sequence
);
entry
.
setExecId
(
op
.
getExecId
());
entry
.
setOrderId
(
op
.
getOrderId
());
entry
.
setQuantity
(
op
.
getPlanQty
());
List
<
ProdEquipment
>
Equipments
=
ProdEquipments
.
stream
()
.
filter
(
t
->
t
.
getExecId
().
equals
(
op
.
getExecId
()))
.
collect
(
Collectors
.
toList
());
if
(
Equipments
!=
null
&&
Equipments
.
size
()>
0
)
{
List
<
MachineOption
>
mos
=
new
ArrayList
<>();
for
(
ProdEquipment
e
:
Equipments
)
{
MachineOption
mo
=
new
MachineOption
();
mo
.
setMachineId
(
e
.
getEquipId
());
mo
.
setProcessingTime
(
e
.
getSpeed
());
// mo.setTeardownTime(op.getPostprocessingTime());
mos
.
add
(
mo
);
}
entry
.
setMachineOptions
(
mos
);
}
// 假设Operation类有获取机器选项的方法
entry
.
setPriority
(
1
);
entrys
.
add
(
entry
);
List
<
ProdOrderProcess
>
nextop
=
ProdOrderProcesss
.
stream
()
.
filter
(
t
->
t
.
getExecId
().
equals
(
op
.
getExecId
()))
.
collect
(
Collectors
.
toList
());
if
(
nextop
!=
null
&&
nextop
.
size
()>
0
)
{
entrys
.
addAll
(
AddNextEntry
(
id
,
sequence
,
id
,
op
.
getExecId
(),
nextop
,
ProdOrderProcesss
,
ProdEquipments
,
ProdProcessExecs
));
}
groupid
++;
List
<
Order
>
orders
=
new
ArrayList
<>();
for
(
ProdLaunchOrder
lo
:
ProdLaunchOrders
)
{
Order
order
=
new
Order
();
order
.
setOrderId
(
lo
.
getOrderId
());
order
.
setMaterialId
(
lo
.
getMaterialId
());
order
.
setDueDate
(
lo
.
getEndDate
());
order
.
setQuantity
(
lo
.
getQuantity
());
orders
.
add
(
order
);
}
List
<
Entry
>
entrys
=
InitEntrys
(
SceneId
,
ProdEquipments
,
ProdLaunchOrders
);
// for (Order order : orders) {
//
// int sequence = 1;
// for (Operation o : product.getOperations()) { // 假设Product类有getOperations()方法返回工序列表
// Entry entry = new Entry();
// entry.setId(id);
// entry.setGroupId(order.getId());
// entry.setSequence(sequence);
// entry.setMachineOptions(o.getMachineOptions()); // 假设Operation类有获取机器选项的方法
// entry.setPriority(order.getPriority());
// entry.setQuantity(order.getQuantity());
// // entry.setMaterialRequirements(o.getMaterialRequirements()); // 假设Operation类有获取物料需求的方法
//
// if (sequence != 1) {
// entry.getPrevEntryIds().add(id - 1); // 假设Entry类有getPrevEntryIds()返回List<Integer>
// }
//
// allOperations.add(entry);
//
// sequence++;
// id++;
// }
// }
GlobalParam
globalParam
=
new
GlobalParam
();
// 5. 执行调度算法
GeneticAlgorithm
scheduler
=
new
GeneticAlgorithm
(
machines
,
null
,
null
,
machineScheduler
);
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
List
<
Chromosome
>
Chromosomes
=
scheduler
.
Run
(
param
,
allOperation
s
);
GeneticAlgorithm
scheduler
=
new
GeneticAlgorithm
(
globalParam
,
machines
,
orders
,
null
,
machineScheduler
);
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
Chromosome
Chromosomes
=
scheduler
.
Run
(
param
,
entry
s
);
Chromosomes
.
forEach
(
this
::
WriteScheduleSummary
);
//
Chromosomes.forEach(this::WriteScheduleSummary);
return
Chromosomes
;
...
...
@@ -382,61 +285,7 @@ public class PlanResultService {
}
}
private
List
<
Entry
>
AddNextEntry
(
int
previd
,
int
prevsequence
,
int
pid
,
String
execId
,
List
<
ProdOrderProcess
>
nextop
,
List
<
ProdOrderProcess
>
ProdOrderProcesss
,
List
<
ProdEquipment
>
ProdEquipments
,
List
<
ProdProcessExec
>
ProdProcessExecs
)
{
List
<
Entry
>
entrys
=
new
ArrayList
<>();
int
id
=
previd
;
int
sequence
=
prevsequence
;
for
(
ProdOrderProcess
o
:
nextop
)
{
List
<
Integer
>
privids
=
new
ArrayList
<>();
privids
.
add
(
pid
);
Entry
entry
=
new
Entry
();
id
=
id
+
1
;
entry
.
setId
(
id
);
sequence
=
sequence
+
1
;
entry
.
setSequence
(
sequence
);
entry
.
setPrevEntryIds
(
privids
);
entry
.
setExecId
(
o
.
getExecId
());
ProdProcessExec
op
=
ProdProcessExecs
.
stream
().
filter
(
t
->
t
.
getExecId
()==
o
.
getExecId
()).
findFirst
().
orElse
(
null
);
entry
.
setOrderId
(
op
.
getOrderId
());
entry
.
setQuantity
(
op
.
getPlanQty
());
List
<
ProdEquipment
>
Equipments
=
ProdEquipments
.
stream
()
.
filter
(
t
->
t
.
getExecId
().
equals
(
op
.
getExecId
()))
.
collect
(
Collectors
.
toList
());
if
(
Equipments
!=
null
&&
Equipments
.
size
()>
0
)
{
List
<
MachineOption
>
mos
=
new
ArrayList
<>();
for
(
ProdEquipment
e
:
Equipments
)
{
MachineOption
mo
=
new
MachineOption
();
mo
.
setMachineId
(
e
.
getEquipId
());
mo
.
setProcessingTime
(
e
.
getSpeed
());
// mo.setTeardownTime(op.getPostprocessingTime());
mos
.
add
(
mo
);
}
entry
.
setMachineOptions
(
mos
);
}
// 假设Operation类有获取机器选项的方法
entry
.
setPriority
(
1
);
entrys
.
add
(
entry
);
}
int
id1
=
previd
;
for
(
ProdOrderProcess
o
:
nextop
)
{
List
<
ProdOrderProcess
>
nextop1
=
ProdOrderProcesss
.
stream
()
.
filter
(
t
->
t
.
getExecId
()
==
o
.
getExecId
())
.
collect
(
Collectors
.
toList
());
if
(
nextop1
!=
null
&&
nextop1
.
size
()>
0
)
{
id1
=
id1
+
1
;
entrys
.
addAll
(
AddNextEntry
(
id
,
sequence
,
id1
,
o
.
getExecId
(),
nextop1
,
ProdOrderProcesss
,
ProdEquipments
,
ProdProcessExecs
));
}
}
return
entrys
;
}
...
...
@@ -544,9 +393,36 @@ public class PlanResultService {
}
}
private
void
InitCalendarToAllMachines
(
List
<
Machine
>
machines
,
List
<
ProdEquipSpecialCal
>
ProdEquipSpecialCals
,
List
<
MesShiftWorkSched
>
MesShiftWorkScheds
)
{
private
List
<
Machine
>
InitCalendarToAllMachines
(
String
SceneId
,
List
<
ProdEquipment
>
ProdEquipments
,
MachineSchedulerService
machineScheduler
)
{
// 按设备分组
List
<
Long
>
MachineIds
=
ProdEquipments
.
stream
()
.
map
(
ProdEquipment:
:
getEquipId
)
.
distinct
()
.
sorted
()
.
collect
(
Collectors
.
toList
());
List
<
Machine
>
machines
=
new
ArrayList
<>();
for
(
Long
id
:
MachineIds
)
{
Machine
machine
=
new
Machine
();
machine
.
setId
(
id
);
machines
.
add
(
machine
);
}
//节假日
List
<
MesHoliday
>
holidays
=
_MesHolidayService
.
list
();
LambdaQueryWrapper
<
ProdEquipSpecialCal
>
ProdEquipSpecialCalWrapper
=
new
LambdaQueryWrapper
<>();
ProdEquipSpecialCalWrapper
.
eq
(
ProdEquipSpecialCal:
:
getSceneId
,
SceneId
);
List
<
ProdEquipSpecialCal
>
ProdEquipSpecialCals
=
_prodEquipSpecialCalService
.
list
(
ProdEquipSpecialCalWrapper
);
List
<
MesShiftWorkSched
>
MesShiftWorkScheds
=
_MesShiftWorkSchedService
.
list
();
if
(
machines
==
null
)
{
return
;
return
null
;
}
for
(
Machine
machine
:
machines
)
{
...
...
@@ -578,6 +454,120 @@ public class PlanResultService {
}
// 4. 初始化机器时间线
for
(
Machine
machine
:
machines
)
{
MachineTimeline
timeline
=
machineScheduler
.
getOrCreateTimeline
(
machine
);
machine
.
setAvailability
(
timeline
.
getSegments
());
}
return
machines
;
}
private
List
<
Entry
>
InitEntrys
(
String
SceneId
,
List
<
ProdEquipment
>
ProdEquipments
,
List
<
ProdLaunchOrder
>
ProdLaunchOrders
)
{
List
<
ProdProcessExec
>
ProdProcessExecs
=
_prodProcessExecService
.
lambdaQuery
()
.
eq
(
ProdProcessExec:
:
getSceneId
,
SceneId
)
.
list
();
List
<
ProdOrderProcess
>
ProdOrderProcesss
=
_prodOrderProcessService
.
lambdaQuery
()
.
eq
(
ProdOrderProcess:
:
getSceneId
,
SceneId
)
.
list
();
List
<
String
>
soutceExecId
=
ProdOrderProcesss
.
stream
()
.
map
(
ProdOrderProcess:
:
getExecId
)
.
distinct
()
// 提取Exec_ID
.
collect
(
Collectors
.
toList
());
List
<
String
>
targetExecId
=
ProdOrderProcesss
.
stream
()
.
map
(
ProdOrderProcess:
:
getTargetExecId
)
.
distinct
()
// 提取TARGET_Exec_ID
.
collect
(
Collectors
.
toList
());
List
<
String
>
ExecIdNoChild
=
ProdProcessExecs
.
stream
()
.
filter
(
e
->
!
soutceExecId
.
contains
(
e
.
getExecId
())&&!
targetExecId
.
contains
(
e
.
getExecId
()))
// 过滤条件
.
map
(
ProdProcessExec:
:
getExecId
)
.
distinct
()
.
collect
(
Collectors
.
toList
());
if
(
ExecIdNoChild
!=
null
&&
ExecIdNoChild
.
size
()>
0
)
{
for
(
String
ExecId
:
ExecIdNoChild
)
{
soutceExecId
.
add
(
ExecId
);
targetExecId
.
add
(
""
);
}
}
List
<
GroupResult
>
results
=
IdGroupingWithDualSerial
.
groupAndOrderIds
(
soutceExecId
,
targetExecId
);
List
<
Entry
>
entrys
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
results
.
size
();
i
++)
{
GroupResult
groupResult
=
results
.
get
(
i
);
List
<
NodeInfo
>
nodeInfoList
=
groupResult
.
getNodeInfoList
();
System
.
out
.
println
(
"分组"
+
(
i
+
1
)
+
"顺序:"
+
nodeInfoList
);
for
(
NodeInfo
nodeInfo
:
nodeInfoList
)
{
System
.
out
.
printf
(
"原始ID:%s → 全局序号:%d,分组内序号:%d,新父ID列表:%s,新子ID列表:%s%n"
,
nodeInfo
.
getOriginalId
(),
nodeInfo
.
getGlobalSerial
(),
nodeInfo
.
getGroupSerial
(),
nodeInfo
.
getNewParentIds
().
isEmpty
()
?
"无"
:
nodeInfo
.
getNewParentIds
(),
nodeInfo
.
getNewChildIds
());
Entry
entry
=
new
Entry
();
entry
.
setId
(
nodeInfo
.
getGlobalSerial
());
entry
.
setGroupId
(
i
+
1
);
entry
.
setSequence
(
nodeInfo
.
getGroupSerial
());
entry
.
setExecId
(
nodeInfo
.
getOriginalId
());
entry
.
setPrevEntryIds
(
nodeInfo
.
getNewParentIds
());
entry
.
setNextEntryIds
(
nodeInfo
.
getNewChildIds
());
ProdProcessExec
op
=
ProdProcessExecs
.
stream
()
.
filter
(
t
->
t
.
getExecId
().
equals
(
entry
.
getExecId
()))
.
findFirst
().
orElse
(
null
);
if
(
op
!=
null
)
{
entry
.
setOrderId
(
op
.
getOrderId
());
entry
.
setQuantity
(
op
.
getPlanQty
());
ProdLaunchOrder
order
=
ProdLaunchOrders
.
stream
()
.
filter
(
t
->
t
.
getOrderId
().
equals
(
op
.
getOrderId
()))
.
findFirst
().
orElse
(
null
);
if
(
order
!=
null
)
{
entry
.
setProductId
(
order
.
getMaterialId
());
}
List
<
ProdEquipment
>
Equipments
=
ProdEquipments
.
stream
()
.
filter
(
t
->
t
.
getExecId
().
equals
(
op
.
getExecId
()))
.
collect
(
Collectors
.
toList
());
if
(
Equipments
!=
null
&&
Equipments
.
size
()
>
0
)
{
List
<
MachineOption
>
mos
=
new
ArrayList
<>();
for
(
ProdEquipment
e
:
Equipments
)
{
MachineOption
mo
=
new
MachineOption
();
mo
.
setMachineId
(
e
.
getEquipId
());
mo
.
setProcessingTime
(
e
.
getSpeed
());
// mo.setContantTime(op.getConstTime());
// mo.setTeardownTime(op.getPostprocessingTime());
mos
.
add
(
mo
);
}
entry
.
setMachineOptions
(
mos
);
}
}
entry
.
setPriority
(
1
);
entrys
.
add
(
entry
);
}
// 输出每个节点的详细信息
System
.
out
.
println
(
"------------------------"
);
}
return
entrys
;
}
/**
...
...
src/test/java/com/aps/demo/OrderSortServiceTest.java
View file @
f7bdf363
...
...
@@ -69,7 +69,7 @@ class OrderSortServiceTest {
order
.
setProductId
(
100
+
i
);
order
.
setQuantity
(
50.0
*
i
);
order
.
setPriority
(
15
-
i
);
// 优先级:5,4,3,2,1(倒序)
order
.
setDueDate
(
OffsetDateTime
.
now
().
plusDays
(
i
));
// 到期日递增
//
order.setDueDate(OffsetDateTime.now().plusDays(i)); // 到期日递增
order
.
setTardiness
(
i
*
0.5
);
order
.
setCanSplit
(
i
%
2
==
0
);
order
.
setCanInterrupt
(
i
%
3
==
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