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
1c20209d
Commit
1c20209d
authored
Dec 05, 2025
by
Tong Li
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
遗传算法
parent
edfba6c2
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
699 additions
and
80 deletions
+699
-80
DependencyType.java
src/main/java/com/aps/entity/Algorithm/DependencyType.java
+22
-0
OperationDependency.java
...in/java/com/aps/entity/Algorithm/OperationDependency.java
+15
-0
ScheduleResultDetail.java
...n/java/com/aps/entity/Algorithm/ScheduleResultDetail.java
+36
-2
Entry.java
src/main/java/com/aps/entity/basic/Entry.java
+5
-4
GeneticDecoder.java
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
+261
-13
MachineCalculator.java
...ain/java/com/aps/service/Algorithm/MachineCalculator.java
+212
-4
ScheduleOperationService.java
...a/com/aps/service/Algorithm/ScheduleOperationService.java
+91
-15
PlanResultService.java
src/main/java/com/aps/service/plan/PlanResultService.java
+47
-16
machines.json
src/main/resources/machines.json
+10
-26
No files found.
src/main/java/com/aps/entity/Algorithm/DependencyType.java
0 → 100644
View file @
1c20209d
package
com
.
aps
.
entity
.
Algorithm
;
/**
* 作者:佟礼
* 时间:2025-12-04
*/
public
enum
DependencyType
{
FinishToStart
(
0
),
// 完成-开始(FS):串行 下料→加工→组装
StartToStart
(
1
),
// 开始-开始(SS): 加工 A 和加工 B 可同时进行 重叠 重叠生产:涂装开始后 30 分钟,烘烤可开始
FinishToFinish
(
2
),
// 完成-完成(FF):前置工序完成后,后继工序才能完成 所有并行加工工序需同时完成
StartToFinish
(
3
);
// 开始-完成(SF):前置工序开始后,后继工序才能完成
private
final
int
value
;
DependencyType
(
int
value
)
{
this
.
value
=
value
;
}
public
int
getValue
()
{
return
value
;
}
}
src/main/java/com/aps/entity/Algorithm/OperationDependency.java
0 → 100644
View file @
1c20209d
package
com
.
aps
.
entity
.
Algorithm
;
import
lombok.Data
;
/**
* 作者:佟礼
* 时间:2025-12-04
*/
@Data
public
class
OperationDependency
{
private
int
Id
;
private
int
prevOperationId
;
// 前置工序ID
private
int
nextOperationId
;
// 后继工序ID
private
DependencyType
dependencyType
=
DependencyType
.
FinishToStart
;
// 依赖类型
}
src/main/java/com/aps/entity/Algorithm/ScheduleResultDetail.java
View file @
1c20209d
...
@@ -9,6 +9,40 @@ import lombok.Data;
...
@@ -9,6 +9,40 @@ import lombok.Data;
@Data
@Data
public
class
ScheduleResultDetail
{
public
class
ScheduleResultDetail
{
private
String
Key
;
private
String
Key
;
private
int
StartTime
;
// 相对开始时间(分钟)
private
int
StartTime
;
// 相对开始时间(秒)
private
int
EndTime
;
// 相对结束时间(分钟)
private
int
EndTime
;
// 相对结束时间(秒)
private
double
OneTime
;
// 单件工时
private
double
Quantity
;
// 时间段
// Key 的 getter/setter
public
String
getKey
()
{
return
Key
;
}
public
void
setKey
(
String
key
)
{
this
.
Key
=
key
;
}
// StartTime 的 getter/setter
public
int
getStartTime
()
{
return
StartTime
;
}
public
void
setStartTime
(
int
startTime
)
{
this
.
StartTime
=
startTime
;
}
// EndTime 的 getter/setter
public
int
getEndTime
()
{
return
EndTime
;
}
public
void
setEndTime
(
int
endTime
)
{
this
.
EndTime
=
endTime
;
}
// 对应C#的计算属性 processingTime(通过方法实现)
public
int
getProcessingTime
()
{
return
EndTime
-
StartTime
;
// 绝对处理时间(分钟)
}
}
}
src/main/java/com/aps/entity/basic/Entry.java
View file @
1c20209d
package
com
.
aps
.
entity
.
basic
;
package
com
.
aps
.
entity
.
basic
;
import
com.aps.entity.Algorithm.OperationDependency
;
import
lombok.Data
;
import
lombok.Data
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
...
@@ -12,7 +13,7 @@ import java.util.List;
...
@@ -12,7 +13,7 @@ import java.util.List;
@Data
@Data
public
class
Entry
{
public
class
Entry
{
public
Entry
()
{
public
Entry
()
{
PrevEntryIds
=
new
ArrayList
<
Integer
>();
PrevEntryIds
=
new
ArrayList
<
OperationDependency
>();
}
}
/**
/**
...
@@ -74,12 +75,12 @@ public class Entry {
...
@@ -74,12 +75,12 @@ public class Entry {
/**
/**
* 前工单ID
* 前工单ID
*/
*/
public
List
<
Integer
>
PrevEntryIds
;
//前工序
public
List
<
OperationDependency
>
PrevEntryIds
;
//前工序
/**
/**
*
前
工单ID
*
后
工单ID
*/
*/
public
List
<
Integer
>
NextEntryIds
;
//后工序
public
List
<
OperationDependency
>
NextEntryIds
;
//后工序
/**
/**
* 数据状态 1 拆分 2 新建
* 数据状态 1 拆分 2 新建
...
...
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
View file @
1c20209d
...
@@ -5,6 +5,7 @@ import com.aps.entity.Algorithm.*;
...
@@ -5,6 +5,7 @@ import com.aps.entity.Algorithm.*;
import
com.aps.entity.ProdEquipment
;
import
com.aps.entity.ProdEquipment
;
import
com.aps.entity.basic.*
;
import
com.aps.entity.basic.*
;
import
com.aps.service.plan.MachineSchedulerService
;
import
com.aps.service.plan.MachineSchedulerService
;
import
org.springframework.http.server.DelegatingServerHttpResponse
;
import
java.math.BigDecimal
;
import
java.math.BigDecimal
;
import
java.time.LocalDateTime
;
import
java.time.LocalDateTime
;
...
@@ -31,6 +32,7 @@ public class GeneticDecoder {
...
@@ -31,6 +32,7 @@ public class GeneticDecoder {
private
final
List
<
Material
>
materials
;
private
final
List
<
Material
>
materials
;
private
List
<
Entry
>
_allOperations
;
private
List
<
Entry
>
_allOperations
;
private
GlobalParam
_globalParam
;
private
GlobalParam
_globalParam
;
private
MachineCalculator
machineCalculator
;
public
GeneticDecoder
(
GlobalParam
globalParam
,
LocalDateTime
baseTime
,
List
<
Machine
>
machines
,
List
<
Order
>
orders
,
public
GeneticDecoder
(
GlobalParam
globalParam
,
LocalDateTime
baseTime
,
List
<
Machine
>
machines
,
List
<
Order
>
orders
,
List
<
Material
>
materials
,
MachineSchedulerService
machineScheduler
)
{
List
<
Material
>
materials
,
MachineSchedulerService
machineScheduler
)
{
this
.
baseTime
=
baseTime
;
this
.
baseTime
=
baseTime
;
...
@@ -40,6 +42,7 @@ public class GeneticDecoder {
...
@@ -40,6 +42,7 @@ public class GeneticDecoder {
this
.
materials
=
materials
;
this
.
materials
=
materials
;
this
.
machineScheduler
=
machineScheduler
;
this
.
machineScheduler
=
machineScheduler
;
_globalParam
=
globalParam
;
_globalParam
=
globalParam
;
machineCalculator
=
new
MachineCalculator
(
baseTime
,
machines
,
machineScheduler
);
// this.orderMaxID = orders.stream().mapToInt(Order::getId).max().orElse(0);
// this.orderMaxID = orders.stream().mapToInt(Order::getId).max().orElse(0);
}
}
public
Chromosome
decodeChromosomeWithCache
(
Chromosome
chromosome
)
{
public
Chromosome
decodeChromosomeWithCache
(
Chromosome
chromosome
)
{
...
@@ -195,15 +198,7 @@ public class GeneticDecoder {
...
@@ -195,15 +198,7 @@ public class GeneticDecoder {
if
(!
currentOp
.
getPrevEntryIds
().
isEmpty
())
{
if
(!
currentOp
.
getPrevEntryIds
().
isEmpty
())
{
// 处理多个前工序
// 处理多个前工序
for
(
int
opid
:
currentOp
.
getPrevEntryIds
())
{
prevtime
=
CalPrevtime
(
prevtime
,
currentOp
,
chromosome
,
processTime
,
targetMachine
);
List
<
GAScheduleResult
>
prevOperations
=
chromosome
.
getResult
().
stream
()
.
filter
(
t
->
t
.
getGroupId
()
==
groupId
&&
t
.
getOperationId
()
==
opid
)
.
collect
(
Collectors
.
toList
());
for
(
GAScheduleResult
prevOp
:
prevOperations
)
{
prevtime
=
Math
.
max
(
prevtime
,
prevOp
.
getEndTime
()+
prevOp
.
getTeardownTime
());
}
}
}
}
// 上个离散参数
// 上个离散参数
...
@@ -303,9 +298,10 @@ public class GeneticDecoder {
...
@@ -303,9 +298,10 @@ public class GeneticDecoder {
}
}
MachineCalculator
machineCalculator
=
new
MachineCalculator
(
baseTime
,
machines
,
machineScheduler
);
List
<
ScheduleResultDetail
>
geneDetails
=
machineCalculator
.
getNextAvailableTime
(
machine
,
earliestStartTime
,
-
1
,
List
<
ScheduleResultDetail
>
geneDetails
=
machineCalculator
.
getNextAvailableTime
(
machine
,
earliestStartTime
,
-
1
,
processingTimeTotal
,
chromosome
.
getResult
(),
false
,
true
,
true
);
processingTimeTotal
,
chromosome
.
getResult
(),
false
,
true
,
processingTime
,
operation
.
getQuantity
(),
true
);
...
@@ -337,7 +333,7 @@ public class GeneticDecoder {
...
@@ -337,7 +333,7 @@ public class GeneticDecoder {
machineCalculator
.
AddMachineAvailable
(
machine
,
geneDetails
);
machineCalculator
.
AddMachineAvailable
(
machine
,
geneDetails
);
geneDetails
=
machineCalculator
.
getNextAvailableTime
(
machine
,
conflictEarliestStartTime
,
-
1
,
geneDetails
=
machineCalculator
.
getNextAvailableTime
(
machine
,
conflictEarliestStartTime
,
-
1
,
processingTimeTotal
,
chromosome
.
getResult
(),
false
,
true
,
true
);
processingTimeTotal
,
chromosome
.
getResult
(),
false
,
true
,
processingTime
,
operation
.
getQuantity
(),
true
);
if
(!
geneDetails
.
isEmpty
())
{
if
(!
geneDetails
.
isEmpty
())
{
startTime
=
geneDetails
.
stream
()
startTime
=
geneDetails
.
stream
()
...
@@ -361,9 +357,11 @@ public class GeneticDecoder {
...
@@ -361,9 +357,11 @@ public class GeneticDecoder {
result
.
setProductId
(
operation
.
getProductId
());
result
.
setProductId
(
operation
.
getProductId
());
result
.
setMachineId
(
machine
.
getId
());
result
.
setMachineId
(
machine
.
getId
());
operation
.
setSelectMachineID
(
machine
.
getId
());
operation
.
setSelectMachineID
(
machine
.
getId
());
result
.
setQuantity
(
operation
.
getQuantity
());
result
.
setStartTime
(
startTime
);
result
.
setStartTime
(
startTime
);
result
.
setEndTime
(
endTime
);
result
.
setEndTime
(
endTime
);
result
.
setOneTime
(
processingTime
);
result
.
setQuantity
(
operation
.
getQuantity
());
result
.
setTeardownTime
(
teardownTime
);
result
.
setTeardownTime
(
teardownTime
);
if
(
existingResult
!=
null
)
{
if
(
existingResult
!=
null
)
{
result
.
setDesignatedStartTime
(
existingResult
.
getDesignatedStartTime
());
result
.
setDesignatedStartTime
(
existingResult
.
getDesignatedStartTime
());
...
@@ -376,6 +374,256 @@ public class GeneticDecoder {
...
@@ -376,6 +374,256 @@ public class GeneticDecoder {
chromosome
.
getResult
().
add
(
result
);
chromosome
.
getResult
().
add
(
result
);
return
endTime
;
return
endTime
;
}
}
/**
* 计算前序结束时间
* @param prevtime
* @param currentOp
* @param chromosome
* @return
*/
private
int
CalPrevtime
(
int
prevtime
,
Entry
currentOp
,
Chromosome
chromosome
,
double
processTime
,
Machine
machine
)
{
List
<
OperationDependency
>
FsOperations
=
currentOp
.
getPrevEntryIds
().
stream
()
.
filter
(
t
->
t
.
getDependencyType
()
==
DependencyType
.
FinishToStart
)
.
collect
(
Collectors
.
toList
());
//串行
if
(
FsOperations
!=
null
&&
FsOperations
.
size
()
>
0
)
{
for
(
OperationDependency
opid
:
FsOperations
)
{
List
<
GAScheduleResult
>
prevOperations
=
chromosome
.
getResult
().
stream
()
.
filter
(
t
->
t
.
getGroupId
()
==
currentOp
.
GroupId
&&
t
.
getOperationId
()
==
opid
.
getPrevOperationId
())
.
collect
(
Collectors
.
toList
());
//多台
for
(
GAScheduleResult
prevOp
:
prevOperations
)
{
prevtime
=
Math
.
max
(
prevtime
,
prevOp
.
getEndTime
()
+
prevOp
.
getTeardownTime
());
}
}
}
List
<
OperationDependency
>
SSOperations
=
currentOp
.
getPrevEntryIds
().
stream
()
.
filter
(
t
->
t
.
getDependencyType
()
==
DependencyType
.
StartToStart
)
.
collect
(
Collectors
.
toList
());
//重叠
if
(
FsOperations
!=
null
&&
FsOperations
.
size
()
>
0
)
{
List
<
GAScheduleResult
>
newScheduleResult
=
new
ArrayList
<>();
List
<
ScheduleResultDetail
>
newScheduleResultDetails
=
new
ArrayList
<>();
for
(
OperationDependency
opid
:
SSOperations
)
{
List
<
GAScheduleResult
>
prevOperations
=
chromosome
.
getResult
().
stream
()
.
filter
(
t
->
t
.
getGroupId
()
==
currentOp
.
GroupId
&&
t
.
getOperationId
()
==
opid
.
getPrevOperationId
())
.
collect
(
Collectors
.
toList
());
//多台
for
(
GAScheduleResult
prevOp
:
prevOperations
)
{
newScheduleResult
.
add
(
prevOp
);
newScheduleResultDetails
.
addAll
(
prevOp
.
getGeneDetails
());
}
}
int
prevperationEndTime
=
newScheduleResult
.
stream
()
.
mapToInt
(
GAScheduleResult:
:
getEndTime
)
.
max
()
.
orElse
(
0
);
prevtime
=
calculateNextOperationStartTime
(
newScheduleResult
,
newScheduleResultDetails
,
0
,
processTime
);
// 下一工序结束时间需晚于上一工序结束时间一个产品加工时间
double
nextopplanend
=
prevperationEndTime
+
processTime
;
List
<
ScheduleResultDetail
>
geneDetails1
=
machineCalculator
.
checkMachineStartTime
(
machine
,
(
int
)
(
processTime
*
currentOp
.
getQuantity
()),
baseTime
.
plusSeconds
((
int
)
nextopplanend
),
baseTime
.
plusSeconds
(
prevtime
),
chromosome
.
getResult
());
if
(
geneDetails1
!=
null
&&
!
geneDetails1
.
isEmpty
())
{
prevtime
=
Math
.
max
(
prevtime
,
geneDetails1
.
stream
()
.
mapToInt
(
ScheduleResultDetail:
:
getStartTime
)
.
min
()
.
orElse
(
prevtime
)
);
}
}
return
prevtime
;
}
/**
* 计算在上一工序生产后什么时间可以开工
* @param details 工序详情列表
* @param startindex 起始索引
* @param time2 时间参数2
* @return 可开工时间
*/
private
int
calculateNextOperationStartTime
(
List
<
GAScheduleResult
>
results
,
List
<
ScheduleResultDetail
>
details
,
int
startindex
,
double
time2
)
{
double
qty
=
results
.
stream
().
mapToDouble
(
GAScheduleResult:
:
getQuantity
)
// 替换为实际字段名
.
sum
();
double
time1
=
0.0
;
for
(
GAScheduleResult
r
:
results
)
{
time1
+=
1.0
/
r
.
getOneTime
();
}
int
leadCount
=(
int
)
calculateLeadProductionItems
(
qty
,
time1
,
time2
);
if
(
leadCount
==
qty
)
{
return
details
.
stream
()
.
mapToInt
(
ScheduleResultDetail:
:
getEndTime
)
.
max
()
.
orElse
(
0
);
}
if
(
startindex
>
leadCount
)
{
leadCount
=
startindex
;
}
if
(
results
.
size
()>
1
)
{
//多前置工序
calculateWithMoreMachine
(
details
,
leadCount
);
}
// 单设备时使用原逻辑
return
(
int
)
calculateWithSingleMachine
(
details
,
leadCount
,
time1
);
}
/**
* 多设备并行时计算满足提前量的最早时间
*/
private
int
calculateWithParallelMachines
(
List
<
ScheduleResultDetail
>
details
,
int
leadCount
,
int
time1
)
{
// 收集所有设备的时间点(开始和结束)并去重排序
Set
<
Integer
>
timePoints
=
new
TreeSet
<>();
for
(
ScheduleResultDetail
detail
:
details
)
{
timePoints
.
add
(
detail
.
getStartTime
());
timePoints
.
add
(
detail
.
getEndTime
());
}
List
<
Integer
>
sortedTimes
=
new
ArrayList
<>(
timePoints
);
int
accumulatedQty
=
0
;
int
prevTime
=
0
;
for
(
int
currTime
:
sortedTimes
)
{
if
(
prevTime
>=
currTime
)
{
prevTime
=
currTime
;
continue
;
}
// 计算当前时间区间[prevTime, currTime)内的有效产能
int
duration
=
currTime
-
prevTime
;
int
machinesWorking
=
0
;
for
(
ScheduleResultDetail
detail
:
details
)
{
// 设备在当前区间内是否处于工作状态
if
(
detail
.
getStartTime
()
<=
prevTime
&&
detail
.
getEndTime
()
>=
currTime
)
{
machinesWorking
++;
}
}
// 区间内的产量(每台设备单位时间产能为1/time1,多设备累加)
int
qtyInInterval
=
(
duration
/
time1
)
*
machinesWorking
;
accumulatedQty
+=
qtyInInterval
;
// 检查是否满足提前量
if
(
accumulatedQty
>=
leadCount
)
{
// 反推精确满足提前量的时间点
int
excess
=
accumulatedQty
-
leadCount
;
int
timeNeeded
=
leadCount
*
time1
-
(
accumulatedQty
-
qtyInInterval
)
*
time1
;
return
prevTime
+
timeNeeded
;
}
prevTime
=
currTime
;
}
// 若所有时间点仍未满足,返回最后结束时间
return
details
.
stream
().
mapToInt
(
ScheduleResultDetail:
:
getEndTime
).
max
().
orElse
(
0
);
}
/**
* 前置多工序多台,合并时间片段并计算满足前置产量的时间点
* @param details 排产详情列表(包含开始时间、结束时间、单件工时)
* @param leadCount 需要提前生产的数量
* @return 满足前置产量的时间点
*/
private
int
calculateWithMoreMachine
(
List
<
ScheduleResultDetail
>
details
,
int
leadCount
)
{
if
(
details
==
null
||
details
.
isEmpty
()
||
leadCount
<=
0
)
{
return
0
;
// 边界条件处理
}
// 1. 收集所有时间点(开始和结束)并去重排序
Set
<
Integer
>
timePoints
=
new
TreeSet
<>();
for
(
ScheduleResultDetail
detail
:
details
)
{
timePoints
.
add
(
detail
.
getStartTime
());
timePoints
.
add
(
detail
.
getEndTime
());
}
List
<
Integer
>
sortedTimes
=
new
ArrayList
<>(
timePoints
);
if
(
sortedTimes
.
size
()
<
2
)
{
return
details
.
get
(
0
).
getEndTime
();
// 无有效时间片段
}
// 2. 按时间片段计算累计产量
double
accumulatedQty
=
0.0
;
for
(
int
i
=
0
;
i
<
sortedTimes
.
size
()
-
1
;
i
++)
{
int
startTime
=
sortedTimes
.
get
(
i
);
int
endTime
=
sortedTimes
.
get
(
i
+
1
);
int
duration
=
endTime
-
startTime
;
if
(
duration
<=
0
)
{
continue
;
// 跳过无效时间段
}
// 计算当前时间段内所有运行的设备总效率(件/单位时间)
//1秒生产的数量
double
totalEfficiency
=
details
.
stream
()
.
filter
(
detail
->
detail
.
getStartTime
()
<=
startTime
&&
detail
.
getEndTime
()
>=
endTime
)
.
mapToDouble
(
detail
->
1.0
/
detail
.
getOneTime
())
// 单件工时的倒数即效率
.
sum
();
// 当前时间段可生产的数量
double
segmentQty
=
totalEfficiency
*
duration
;
// 检查是否在当前时间段内满足前置产量
if
(
accumulatedQty
+
segmentQty
>=
leadCount
)
{
// 计算精确时间点(向上取整避免小数精度问题)
double
remainingQty
=
leadCount
-
accumulatedQty
;
int
requiredTime
=
(
int
)
Math
.
ceil
(
remainingQty
/
totalEfficiency
);
//数量除以每秒的数量, 每秒生产多少个,生产X用几秒
return
startTime
+
requiredTime
;
}
accumulatedQty
+=
segmentQty
;
}
// 3. 所有片段累计仍未满足(返回最后结束时间)
return
details
.
stream
()
.
mapToInt
(
ScheduleResultDetail:
:
getEndTime
)
.
max
()
.
orElse
(
0
);
}
/**
* 单设备时使用原逻辑(保持兼容)
*/
private
double
calculateWithSingleMachine
(
List
<
ScheduleResultDetail
>
details
,
int
leadCount
,
double
time1
)
{
//上一工序的排产详情 - 需要提前生产出来的数量花费的时间
double
alltime
=
leadCount
*
time1
;
for
(
ScheduleResultDetail
detail
:
details
)
{
double
time3
=
alltime
-
detail
.
getProcessingTime
();
if
(
time3
<
0
)
{
return
detail
.
getEndTime
()
+
time3
;
}
else
if
(
time3
==
0
)
{
return
detail
.
getEndTime
();
}
else
{
alltime
=
time3
;
}
}
return
details
.
get
(
details
.
size
()
-
1
).
getEndTime
();
}
/**
* 计算工序1需要提前生产的件数
* @param qty 总订单量
* @param time1 工序1单件工时
* @param time2 工序2单件工时
* @return 工序1需要提前生产的件数
*/
private
double
calculateLeadProductionItems
(
double
qty
,
double
time1
,
double
time2
)
{
if
(
time1
<
time2
)
{
return
1
;
}
if
(
qty
<=
0
||
time1
<=
0
||
time2
<=
0
)
{
throw
new
IllegalArgumentException
(
"参数必须为正整数"
);
}
double
totalTime1
=
qty
*
time1
;
double
totalTime2
=
qty
*
time2
;
double
timeDifference
=
totalTime2
-
totalTime1
;
return
(
timeDifference
/
time1
)
>
qty
?
qty
:
(
timeDifference
/
time1
);
}
private
String
ConvertTime
(
int
minute
)
{
private
String
ConvertTime
(
int
minute
)
{
return
baseTime
.
plusSeconds
(
minute
).
format
(
java
.
time
.
format
.
DateTimeFormatter
.
ofPattern
(
"MM-dd HH:mm"
));
return
baseTime
.
plusSeconds
(
minute
).
format
(
java
.
time
.
format
.
DateTimeFormatter
.
ofPattern
(
"MM-dd HH:mm"
));
}
}
...
...
src/main/java/com/aps/service/Algorithm/MachineCalculator.java
View file @
1c20209d
...
@@ -9,6 +9,7 @@ import com.aps.service.plan.MachineSchedulerService;
...
@@ -9,6 +9,7 @@ import com.aps.service.plan.MachineSchedulerService;
import
com.baomidou.mybatisplus.core.toolkit.StringUtils
;
import
com.baomidou.mybatisplus.core.toolkit.StringUtils
;
import
java.math.BigDecimal
;
import
java.math.BigDecimal
;
import
java.time.Duration
;
import
java.time.LocalDateTime
;
import
java.time.LocalDateTime
;
import
java.time.format.DateTimeFormatter
;
import
java.time.format.DateTimeFormatter
;
import
java.time.temporal.ChronoUnit
;
import
java.time.temporal.ChronoUnit
;
...
@@ -41,6 +42,7 @@ public class MachineCalculator {
...
@@ -41,6 +42,7 @@ public class MachineCalculator {
int
prevtime
,
int
processingTime
,
int
prevtime
,
int
processingTime
,
List
<
GAScheduleResult
>
existingTasks
,
List
<
GAScheduleResult
>
existingTasks
,
boolean
isInterrupt
,
boolean
istask
,
boolean
isInterrupt
,
boolean
istask
,
double
oneTime
,
double
quantity
,
boolean
islockMachineTime
)
{
boolean
islockMachineTime
)
{
LocalDateTime
startTime
=
baseTime
.
plus
(
proposedStartTime
,
ChronoUnit
.
SECONDS
);
LocalDateTime
startTime
=
baseTime
.
plus
(
proposedStartTime
,
ChronoUnit
.
SECONDS
);
...
@@ -52,7 +54,7 @@ public class MachineCalculator {
...
@@ -52,7 +54,7 @@ public class MachineCalculator {
// 查找合适的班次窗口
// 查找合适的班次窗口
return
findEarliestStart
(
machine
,
processingTime
,
startTime
,
prevtimestr
,
return
findEarliestStart
(
machine
,
processingTime
,
startTime
,
prevtimestr
,
existingTasks
,
istask
,
islockMachineTime
);
existingTasks
,
oneTime
,
quantity
,
istask
,
islockMachineTime
);
}
}
...
@@ -60,7 +62,7 @@ public class MachineCalculator {
...
@@ -60,7 +62,7 @@ public class MachineCalculator {
private
List
<
ScheduleResultDetail
>
findEarliestStart
(
private
List
<
ScheduleResultDetail
>
findEarliestStart
(
Machine
machine
,
int
processingTime
,
LocalDateTime
currentTime
,
Machine
machine
,
int
processingTime
,
LocalDateTime
currentTime
,
String
prevtime
,
List
<
GAScheduleResult
>
existingTasks
,
boolean
checkprevtime
,
boolean
islockMachineTime
String
prevtime
,
List
<
GAScheduleResult
>
existingTasks
,
double
oneTime
,
double
quantity
,
boolean
checkprevtime
,
boolean
islockMachineTime
)
{
)
{
List
<
GAScheduleResult
>
machineTasks
=
existingTasks
.
stream
()
List
<
GAScheduleResult
>
machineTasks
=
existingTasks
.
stream
()
.
filter
(
t
->
t
.
getMachineId
()
==
machine
.
getId
())
.
filter
(
t
->
t
.
getMachineId
()
==
machine
.
getId
())
...
@@ -79,12 +81,14 @@ public class MachineCalculator {
...
@@ -79,12 +81,14 @@ public class MachineCalculator {
LocalDateTime
endCandidate
=
startCandidate
.
plusSeconds
(
processingTime
);
LocalDateTime
endCandidate
=
startCandidate
.
plusSeconds
(
processingTime
);
if
(
endCandidate
.
isAfter
(
slot
.
getEnd
()))
{
if
(
endCandidate
.
isAfter
(
slot
.
getEnd
()))
{
return
CaldEarliestStart
(
machine
,
processingTime
,
currentTime
,
prevtime
,
machineTasks
,
checkprevtime
,
islockMachineTime
);
return
CaldEarliestStart
(
machine
,
processingTime
,
currentTime
,
prevtime
,
machineTasks
,
oneTime
,
quantity
,
checkprevtime
,
islockMachineTime
);
}
else
{
}
else
{
ScheduleResultDetail
time
=
new
ScheduleResultDetail
();
ScheduleResultDetail
time
=
new
ScheduleResultDetail
();
time
.
setKey
(
slot
.
getKey
());
time
.
setKey
(
slot
.
getKey
());
time
.
setStartTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
startCandidate
));
time
.
setStartTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
startCandidate
));
time
.
setEndTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
endCandidate
));
time
.
setEndTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
endCandidate
));
time
.
setOneTime
(
oneTime
);
time
.
setQuantity
(
quantity
);
times
.
add
(
time
);
times
.
add
(
time
);
if
(
islockMachineTime
)
{
if
(
islockMachineTime
)
{
RemoveMachineAvailable
(
machine
,
time
);
RemoveMachineAvailable
(
machine
,
time
);
...
@@ -96,7 +100,7 @@ public class MachineCalculator {
...
@@ -96,7 +100,7 @@ public class MachineCalculator {
private
List
<
ScheduleResultDetail
>
CaldEarliestStart
(
private
List
<
ScheduleResultDetail
>
CaldEarliestStart
(
Machine
machine
,
int
processingTime
,
LocalDateTime
currentTime
,
Machine
machine
,
int
processingTime
,
LocalDateTime
currentTime
,
String
prevtime
,
List
<
GAScheduleResult
>
machineTasks
,
boolean
checkprevtime
,
boolean
islockMachineTime
String
prevtime
,
List
<
GAScheduleResult
>
machineTasks
,
double
oneTime
,
double
quantity
,
boolean
checkprevtime
,
boolean
islockMachineTime
)
{
)
{
int
remainingTime
=
processingTime
;
int
remainingTime
=
processingTime
;
LocalDateTime
st
=
StringUtils
.
isEmpty
(
prevtime
)
?
currentTime
:
LocalDateTime
.
parse
(
prevtime
);
LocalDateTime
st
=
StringUtils
.
isEmpty
(
prevtime
)
?
currentTime
:
LocalDateTime
.
parse
(
prevtime
);
...
@@ -166,6 +170,8 @@ public class MachineCalculator {
...
@@ -166,6 +170,8 @@ public class MachineCalculator {
time
.
setKey
(
shift
.
getKey
());
time
.
setKey
(
shift
.
getKey
());
time
.
setStartTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
effectiveStart
));
time
.
setStartTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
effectiveStart
));
time
.
setEndTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
currentTime
));
time
.
setEndTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
currentTime
));
time
.
setQuantity
((
int
)(
processable
/
oneTime
));
time
.
setOneTime
(
oneTime
);
times
.
add
(
time
);
times
.
add
(
time
);
if
(
islockMachineTime
)
{
if
(
islockMachineTime
)
{
// 还原未使用的时间段
// 还原未使用的时间段
...
@@ -216,7 +222,209 @@ public class MachineCalculator {
...
@@ -216,7 +222,209 @@ public class MachineCalculator {
return
start
;
return
start
;
}
}
/**
* 检查设备的可用开工时间
* @param machine 目标设备
* @param processingTime 加工时长(分钟)
* @param currentTime 当前时间
* @param startTime 开始时间
* @param existingTasks 已有任务列表
* @return 可用时间段列表,无可用时间返回null
*/
public
List
<
ScheduleResultDetail
>
checkMachineStartTime
(
Machine
machine
,
int
processingTime
,
LocalDateTime
currentTime
,
LocalDateTime
startTime
,
List
<
GAScheduleResult
>
existingTasks
)
{
// 获取设备上已有任务并按开始时间排序
List
<
GAScheduleResult
>
machineTasks
=
existingTasks
.
stream
()
.
filter
(
t
->
t
.
getMachineId
()
==
machine
.
getId
())
.
sorted
(
Comparator
.
comparing
(
GAScheduleResult:
:
getStartTime
))
.
collect
(
Collectors
.
toList
());
List
<
ScheduleResultDetail
>
times
=
new
ArrayList
<>();
// 获取当前/上一个班次
TimeSegment
slot
=
getCurrentOrPrevShift
(
machine
,
currentTime
);
if
(
slot
==
null
)
{
return
null
;
}
// 计算候选开始/结束时间(当前时间往前推加工时长)
LocalDateTime
startCandidate
=
currentTime
.
minusSeconds
(
processingTime
);
LocalDateTime
endCandidate
=
currentTime
;
// 检查是否在可用时间段内
if
(
startCandidate
.
isBefore
(
slot
.
getStart
()))
{
// 放不下,寻找后续可用时间
return
checkMachineShift
(
machine
,
processingTime
,
currentTime
,
startTime
,
machineTasks
);
}
else
{
// 生成可用时间段
ScheduleResultDetail
time
=
new
ScheduleResultDetail
();
time
.
setKey
(
slot
.
getKey
());
// 计算相对基准时间的分钟数(对应原代码TotalMinutes
time
.
setStartTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
startCandidate
));
time
.
setEndTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
endCandidate
));
times
.
add
(
time
);
return
times
;
}
}
/**
* 获取设备当前或上一个有效班次
* @param machine 目标设备
* @param time 目标时间
* @return 有效班次,无则递归生成后返回
*/
private
TimeSegment
getCurrentOrPrevShift
(
Machine
machine
,
LocalDateTime
time
)
{
TimeSegment
start
=
null
;
// 找到最后一个可用班次:未使用、非维护类型、开始时间早于目标时间
// 倒序遍历找最后一个符合条件的班次
List
<
TimeSegment
>
availability
=
machine
.
getAvailability
();
for
(
int
i
=
availability
.
size
()
-
1
;
i
>=
0
;
i
--)
{
TimeSegment
slot
=
availability
.
get
(
i
);
if
(!
slot
.
isUsed
()
&&
slot
.
getType
()
!=
SegmentType
.
MAINTENANCE
&&
slot
.
getStart
().
isBefore
(
time
))
{
start
=
slot
;
break
;
}
}
// 若未找到班次,且目标时间晚于所有班次的结束时间 → 生成新班次并递归
if
(
start
==
null
)
{
// 获取所有班次的最大结束时间
Optional
<
LocalDateTime
>
maxEndTime
=
availability
.
stream
()
.
map
(
TimeSegment:
:
getEnd
)
.
max
(
LocalDateTime:
:
compareTo
);
// 检查是否目标时间晚于最大结束时间(处理空列表情况)
boolean
isTimeAfterMaxEnd
=
maxEndTime
.
map
(
end
->
time
.
isAfter
(
end
)).
orElse
(
true
);
if
(
isTimeAfterMaxEnd
)
{
// 生成新的时间段并添加到设备可用班次中
LocalDateTime
generateStartTime
=
maxEndTime
.
orElse
(
LocalDateTime
.
now
());
List
<
TimeSegment
>
timeSegments
=
machineScheduler
.
generateTimeSegment
(
machine
,
generateStartTime
);
machine
.
getAvailability
().
addAll
(
timeSegments
);
// 更新机器列表中的对应机器
Machine
m
=
machines
.
stream
()
.
filter
(
t
->
t
.
getId
()
==
machine
.
getId
())
.
findFirst
()
.
orElse
(
null
);
if
(
m
!=
null
)
{
MachineTimeline
machineTimeline
=
machineScheduler
.
getOrCreateTimeline
(
m
);
// 原代码注释:m.Availability = machineTimeline.Segments;
// 如需启用请补充:m.setAvailability(machineTimeline.getSegments());
}
// 递归调用,重新获取有效班次
return
getCurrentOrPrevShift
(
machine
,
time
);
}
}
return
start
;
}
/**
* 检查设备班次,计算满足加工时长的可用时间段
* @param machine 目标设备
* @param processingTime 总加工时长(分钟)
* @param currentTime 当前时间
* @param startTime 开始时间阈值
* @param machineTasks 设备已有任务列表
* @return 分段的可用时间段列表,无可用时间返回null
*/
private
List
<
ScheduleResultDetail
>
checkMachineShift
(
Machine
machine
,
int
processingTime
,
LocalDateTime
currentTime
,
LocalDateTime
startTime
,
List
<
GAScheduleResult
>
machineTasks
)
{
int
remainingTime
=
processingTime
;
// 初始化上一班次结束时间(对应原2000-01-01的初始值)
LocalDateTime
prevEnd
=
LocalDateTime
.
of
(
2000
,
1
,
1
,
0
,
0
);
List
<
ScheduleResultDetail
>
times
=
new
ArrayList
<>();
while
(
remainingTime
>
0
)
{
// 开始时间阈值超过当前时间,无可用时间
if
(
startTime
.
isAfter
(
currentTime
))
{
return
null
;
}
// 获取当前/上一个有效班次
TimeSegment
shift
=
getCurrentOrPrevShift
(
machine
,
currentTime
);
if
(
shift
==
null
)
{
return
null
;
}
LocalDateTime
shiftStart
=
shift
.
getStart
();
LocalDateTime
shiftEnd
=
shift
.
getEnd
();
// 非初始状态(上一班次已存在),检查班次连续性
if
(
prevEnd
.
getYear
()!=
2000
)
{
// 检查上一班次和当前班次之间是否有任务
if
(
prevEnd
.
isAfter
(
shiftEnd
))
{
// 查找任务:任务开始时间在当前班次开始 ~ 上一班次结束之间
LocalDateTime
finalPrevEnd
=
prevEnd
;
Optional
<
GAScheduleResult
>
task
=
machineTasks
.
stream
()
.
filter
(
t
->
baseTime
.
plusSeconds
(
t
.
getStartTime
()).
isAfter
(
shiftStart
)
&&
baseTime
.
plusSeconds
(
t
.
getStartTime
()).
isBefore
(
finalPrevEnd
))
.
findFirst
();
if
(
task
.
isPresent
())
{
// 班次间有任务,重置状态重新查找
currentTime
=
shiftStart
;
remainingTime
=
processingTime
;
prevEnd
=
LocalDateTime
.
of
(
2000
,
1
,
1
,
0
,
0
);
times
.
clear
();
continue
;
}
}
// 检查维护窗口
if
(
machine
.
getMaintenanceWindows
()
!=
null
&&
!
machine
.
getMaintenanceWindows
().
isEmpty
())
{
LocalDateTime
finalPrevEnd
=
prevEnd
;
Optional
<
MaintenanceWindow
>
maintenanceTask
=
machine
.
getMaintenanceWindows
().
stream
()
.
filter
(
t
->
t
.
getStartTime
().
isAfter
(
shiftStart
)
&&
t
.
getStartTime
().
isBefore
(
finalPrevEnd
))
.
findFirst
();
if
(
maintenanceTask
.
isPresent
())
{
// 班次间有维护任务,重置状态重新查找
currentTime
=
shiftStart
;
remainingTime
=
processingTime
;
prevEnd
=
LocalDateTime
.
of
(
2000
,
1
,
1
,
0
,
0
);
times
.
clear
();
continue
;
}
}
}
// 调整班次有效结束时间(不超过当前时间)
LocalDateTime
effectiveEnd
=
shiftEnd
.
isAfter
(
currentTime
)
?
currentTime
:
shiftEnd
;
// 计算班次可用时长
Duration
availableDuration
=
Duration
.
between
(
shiftStart
,
effectiveEnd
);
long
availableMinutes
=
availableDuration
.
getSeconds
();
// 当前班次可处理的时长(不超过剩余需要的时长)
int
processableMinutes
=
(
int
)
Math
.
min
(
remainingTime
,
availableMinutes
);
// 计算当前班次的有效开始时间
LocalDateTime
effectiveStart
=
effectiveEnd
.
minusSeconds
(
processableMinutes
);
prevEnd
=
effectiveStart
;
// 更新上一班次结束时间
remainingTime
-=
processableMinutes
;
// 剩余时长递减
currentTime
=
effectiveStart
;
// 更新当前时间,继续循环
// 生成当前班次的时间片段
ScheduleResultDetail
time
=
new
ScheduleResultDetail
();
time
.
setKey
(
shift
.
getKey
());
time
.
setStartTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
effectiveStart
));
time
.
setEndTime
((
int
)
ChronoUnit
.
SECONDS
.
between
(
baseTime
,
effectiveEnd
));
times
.
add
(
time
);
}
return
times
;
}
private
void
RemoveMachineAvailable
(
Machine
machine
,
ScheduleResultDetail
geneDetails
)
{
private
void
RemoveMachineAvailable
(
Machine
machine
,
ScheduleResultDetail
geneDetails
)
{
List
<
TimeSegment
>
timeSegments
=
new
ArrayList
<>();
List
<
TimeSegment
>
timeSegments
=
new
ArrayList
<>();
...
...
src/main/java/com/aps/service/Algorithm/ScheduleOperationService.java
View file @
1c20209d
package
com
.
aps
.
service
.
Algorithm
;
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.*
;
import
com.aps.entity.Algorithm.GAScheduleResult
;
import
com.aps.entity.Algorithm.GlobalOperationInfo
;
import
com.aps.entity.Algorithm.IDAndChildID.GroupResult
;
import
com.aps.entity.Algorithm.IDAndChildID.GroupResult
;
import
com.aps.entity.Algorithm.IDAndChildID.NodeInfo
;
import
com.aps.entity.Algorithm.IDAndChildID.NodeInfo
;
import
com.aps.entity.Algorithm.ScheduleResultDetail
;
import
com.aps.entity.basic.Entry
;
import
com.aps.entity.basic.Entry
;
import
com.aps.entity.basic.GlobalParam
;
import
com.aps.entity.basic.GlobalParam
;
import
com.aps.entity.basic.MachineOption
;
import
com.aps.entity.basic.MachineOption
;
...
@@ -173,9 +170,28 @@ public class ScheduleOperationService {
...
@@ -173,9 +170,28 @@ public class ScheduleOperationService {
{
{
//存在则修改顺和前后序
//存在则修改顺和前后序
entry
.
setSequence
(
nodeInfo
.
getGroupSerial
());
entry
.
setSequence
(
nodeInfo
.
getGroupSerial
());
entry
.
setPrevEntryIds
(
nodeInfo
.
getNewParentIds
());
// entry.setPrevEntryIds(nodeInfo.getNewParentIds());
entry
.
setNextEntryIds
(
nodeInfo
.
getNewChildIds
());
// entry.setNextEntryIds(nodeInfo.getNewChildIds());
if
(
nodeInfo
.
getNewParentIds
()!=
null
)
{
List
<
OperationDependency
>
OperationDependency
=
new
ArrayList
<>();
for
(
int
id
:
nodeInfo
.
getNewParentIds
())
{
OperationDependency
od
=
new
OperationDependency
();
od
.
setPrevOperationId
(
id
);
OperationDependency
.
add
(
od
);
}
entry
.
setPrevEntryIds
(
OperationDependency
);
}
if
(
nodeInfo
.
getNewChildIds
()!=
null
)
{
List
<
OperationDependency
>
OperationDependency
=
new
ArrayList
<>();
for
(
int
id
:
nodeInfo
.
getNewChildIds
())
{
OperationDependency
od
=
new
OperationDependency
();
od
.
setNextOperationId
(
id
);
OperationDependency
.
add
(
od
);
}
entry
.
setNextEntryIds
(
OperationDependency
);
}
GlobalOperationInfo
info
=
chromosome
.
getGlobalOpList
().
stream
()
GlobalOperationInfo
info
=
chromosome
.
getGlobalOpList
().
stream
()
.
filter
(
t
->
t
.
getOp
().
getId
()==
entry
.
getId
())
.
filter
(
t
->
t
.
getOp
().
getId
()==
entry
.
getId
())
.
findFirst
()
.
findFirst
()
...
@@ -196,8 +212,28 @@ public class ScheduleOperationService {
...
@@ -196,8 +212,28 @@ public class ScheduleOperationService {
newOp
.
setId
(
nodeInfo
.
getGlobalSerial
());
newOp
.
setId
(
nodeInfo
.
getGlobalSerial
());
newOp
.
setSequence
(
nodeInfo
.
getGroupSerial
());
newOp
.
setSequence
(
nodeInfo
.
getGroupSerial
());
newOp
.
setExecId
(
nodeInfo
.
getOriginalId
());
newOp
.
setExecId
(
nodeInfo
.
getOriginalId
());
newOp
.
setPrevEntryIds
(
nodeInfo
.
getNewParentIds
());
// newOp.setPrevEntryIds(nodeInfo.getNewParentIds());
newOp
.
setNextEntryIds
(
nodeInfo
.
getNewChildIds
());
// newOp.setNextEntryIds(nodeInfo.getNewChildIds());
if
(
nodeInfo
.
getNewParentIds
()!=
null
)
{
List
<
OperationDependency
>
OperationDependency
=
new
ArrayList
<>();
for
(
int
id
:
nodeInfo
.
getNewParentIds
())
{
OperationDependency
od
=
new
OperationDependency
();
od
.
setPrevOperationId
(
id
);
OperationDependency
.
add
(
od
);
}
entry
.
setPrevEntryIds
(
OperationDependency
);
}
if
(
nodeInfo
.
getNewChildIds
()!=
null
)
{
List
<
OperationDependency
>
OperationDependency
=
new
ArrayList
<>();
for
(
int
id
:
nodeInfo
.
getNewChildIds
())
{
OperationDependency
od
=
new
OperationDependency
();
od
.
setNextOperationId
(
id
);
OperationDependency
.
add
(
od
);
}
entry
.
setNextEntryIds
(
OperationDependency
);
}
newOp
.
setQuantity
(
newids
.
get
(
nodeInfo
.
getOriginalId
()));
newOp
.
setQuantity
(
newids
.
get
(
nodeInfo
.
getOriginalId
()));
newOp
.
setMainId
(
MainId
);
newOp
.
setMainId
(
MainId
);
newOp
.
setState
(
2
);
newOp
.
setState
(
2
);
...
@@ -281,10 +317,10 @@ public class ScheduleOperationService {
...
@@ -281,10 +317,10 @@ public class ScheduleOperationService {
for
(
Entry
entry
:
newEntrys
)
{
for
(
Entry
entry
:
newEntrys
)
{
if
(
entry
.
getNextEntryIds
().
size
()>
0
)
if
(
entry
.
getNextEntryIds
().
size
()>
0
)
{
{
for
(
Integer
i
d
:
entry
.
getNextEntryIds
())
{
for
(
OperationDependency
o
d
:
entry
.
getNextEntryIds
())
{
Entry
nextentry
=
newEntrys
.
stream
()
Entry
nextentry
=
newEntrys
.
stream
()
.
filter
(
t
->
t
.
getGroupId
()==
entry
.
getGroupId
()&&
t
.
getId
()==
id
)
.
filter
(
t
->
t
.
getGroupId
()==
entry
.
getGroupId
()&&
t
.
getId
()==
od
.
getNextOperationId
()
)
.
findFirst
()
.
findFirst
()
.
orElse
(
null
);
.
orElse
(
null
);
if
(
nextentry
!=
null
)
{
if
(
nextentry
!=
null
)
{
...
@@ -325,8 +361,28 @@ public class ScheduleOperationService {
...
@@ -325,8 +361,28 @@ public class ScheduleOperationService {
entry
.
setGroupId
(
i
+
1
);
entry
.
setGroupId
(
i
+
1
);
entry
.
setSequence
(
nodeInfo
.
getGroupSerial
());
entry
.
setSequence
(
nodeInfo
.
getGroupSerial
());
entry
.
setExecId
(
nodeInfo
.
getOriginalId
());
entry
.
setExecId
(
nodeInfo
.
getOriginalId
());
entry
.
setPrevEntryIds
(
nodeInfo
.
getNewParentIds
());
// entry.setPrevEntryIds(nodeInfo.getNewParentIds());
entry
.
setNextEntryIds
(
nodeInfo
.
getNewChildIds
());
// entry.setNextEntryIds(nodeInfo.getNewChildIds());
if
(
nodeInfo
.
getNewParentIds
()!=
null
)
{
List
<
OperationDependency
>
OperationDependency
=
new
ArrayList
<>();
for
(
int
id
:
nodeInfo
.
getNewParentIds
())
{
OperationDependency
od
=
new
OperationDependency
();
od
.
setPrevOperationId
(
id
);
OperationDependency
.
add
(
od
);
}
entry
.
setPrevEntryIds
(
OperationDependency
);
}
if
(
nodeInfo
.
getNewChildIds
()!=
null
)
{
List
<
OperationDependency
>
OperationDependency
=
new
ArrayList
<>();
for
(
int
id
:
nodeInfo
.
getNewChildIds
())
{
OperationDependency
od
=
new
OperationDependency
();
od
.
setNextOperationId
(
id
);
OperationDependency
.
add
(
od
);
}
entry
.
setNextEntryIds
(
OperationDependency
);
}
entry
.
setMainId
(
""
);
entry
.
setMainId
(
""
);
entry
.
setState
(
2
);
entry
.
setState
(
2
);
//工序基本信息
//工序基本信息
...
@@ -487,8 +543,28 @@ public class ScheduleOperationService {
...
@@ -487,8 +543,28 @@ public class ScheduleOperationService {
if
(
node
!=
null
)
if
(
node
!=
null
)
{
{
entry
.
setSequence
(
node
.
getGroupSerial
());
entry
.
setSequence
(
node
.
getGroupSerial
());
entry
.
setPrevEntryIds
(
node
.
getNewParentIds
());
// entry.setPrevEntryIds(node.getNewParentIds());
entry
.
setNextEntryIds
(
node
.
getNewChildIds
());
// entry.setNextEntryIds(node.getNewChildIds());
if
(
node
.
getNewParentIds
()!=
null
)
{
List
<
OperationDependency
>
OperationDependency
=
new
ArrayList
<>();
for
(
int
id
:
node
.
getNewParentIds
())
{
OperationDependency
od
=
new
OperationDependency
();
od
.
setPrevOperationId
(
id
);
OperationDependency
.
add
(
od
);
}
entry
.
setPrevEntryIds
(
OperationDependency
);
}
if
(
node
.
getNewChildIds
()!=
null
)
{
List
<
OperationDependency
>
OperationDependency
=
new
ArrayList
<>();
for
(
int
id
:
node
.
getNewChildIds
())
{
OperationDependency
od
=
new
OperationDependency
();
od
.
setNextOperationId
(
id
);
OperationDependency
.
add
(
od
);
}
entry
.
setNextEntryIds
(
OperationDependency
);
}
GlobalOperationInfo
info
=
chromosome
.
getGlobalOpList
().
stream
()
GlobalOperationInfo
info
=
chromosome
.
getGlobalOpList
().
stream
()
.
filter
(
t
->
t
.
getOp
().
getId
()==
entry
.
getId
())
.
filter
(
t
->
t
.
getOp
().
getId
()==
entry
.
getId
())
.
findFirst
()
.
findFirst
()
...
...
src/main/java/com/aps/service/plan/PlanResultService.java
View file @
1c20209d
...
@@ -5,12 +5,9 @@ import com.aps.common.util.JsonFileReader;
...
@@ -5,12 +5,9 @@ import com.aps.common.util.JsonFileReader;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.controller.gantt.FileUploadController
;
import
com.aps.controller.gantt.FileUploadController
;
import
com.aps.entity.*
;
import
com.aps.entity.*
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.*
;
import
com.aps.entity.Algorithm.GAScheduleResult
;
import
com.aps.entity.Algorithm.IDAndChildID.GroupResult
;
import
com.aps.entity.Algorithm.IDAndChildID.GroupResult
;
import
com.aps.entity.Algorithm.IDAndChildID.NodeInfo
;
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
;
import
com.aps.entity.basic.ScheduleChromosome
;
import
com.aps.entity.Schedule.GenVO
;
import
com.aps.entity.Schedule.GenVO
;
import
com.aps.entity.Schedule.MachineVO
;
import
com.aps.entity.Schedule.MachineVO
;
...
@@ -135,10 +132,25 @@ public class PlanResultService {
...
@@ -135,10 +132,25 @@ public class PlanResultService {
}
}
}
}
public
Chromosome
execute1
()
{
public
Chromosome
execute1
()
{
try
{
try
{
//List<ScheduleResultDetail> details=new ArrayList<>();
// ScheduleResultDetail detail1=new ScheduleResultDetail();
//
// detail1.setOneTime(100);//单件工时
//
//
// ScheduleResultDetail detail2=new ScheduleResultDetail();
//
// detail2.setOneTime(200);//单件工时
// details.add(detail1);
// details.add(detail2);
// mergeSegmentsWithDifferentOneTime(details, 50);
// 1. 读取数据
// 1. 读取数据
List
<
Machine
>
machines
=
loadData
(
"machines.json"
,
Machine
.
class
);
List
<
Machine
>
machines
=
loadData
(
"machines.json"
,
Machine
.
class
);
List
<
Product
>
products
=
loadData
(
"products.json"
,
Product
.
class
);
List
<
Product
>
products
=
loadData
(
"products.json"
,
Product
.
class
);
...
@@ -166,23 +178,20 @@ public class PlanResultService {
...
@@ -166,23 +178,20 @@ public class PlanResultService {
}
}
ScheduleParams
param
=
new
ScheduleParams
();
ScheduleParams
param
=
new
ScheduleParams
();
param
.
setBaseTime
(
LocalDateTime
.
of
(
2025
,
11
,
1
,
0
,
0
,
0
));
param
.
setBaseTime
(
LocalDateTime
.
of
(
2025
,
11
,
1
,
0
,
0
,
0
));
param
.
setPopulationSize
(
50
);
param
.
setPopulationSize
(
1
);
param
.
setMaxIterations
(
100
);
param
.
setMaxIterations
(
2
);
// List<MesHoliday> holidays= _MesHolidayService.list();
// List<MesHoliday> holidays= _MesHolidayService.list();
// 创建节假日
// 创建节假日
List
<
Holiday
>
holidays
=
Arrays
.
asList
(
new
Holiday
(
LocalDateTime
.
of
(
2025
,
10
,
1
,
0
,
0
),
LocalDateTime
.
of
(
2025
,
10
,
7
,
23
,
59
))
);
// 将节假日添加到所有设备中
// 将节假日添加到所有设备中
addHolidaysToAllMachines
(
machines
,
holiday
s
);
// addHolidaysToAllMachines(machine
s);
// 3. 创建调度服务
// 3. 创建调度服务
MachineSchedulerService
machineScheduler
=
new
MachineSchedulerService
(
MachineSchedulerService
machineScheduler
=
new
MachineSchedulerService
(
holidays
,
param
.
getBaseTime
());
param
.
getBaseTime
());
// 4. 初始化机器时间线
// 4. 初始化机器时间线
for
(
Machine
machine
:
machines
)
{
for
(
Machine
machine
:
machines
)
{
...
@@ -214,7 +223,10 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
...
@@ -214,7 +223,10 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
// entry.setMaterialRequirements(o.getMaterialRequirements()); // 假设Operation类有获取物料需求的方法
// entry.setMaterialRequirements(o.getMaterialRequirements()); // 假设Operation类有获取物料需求的方法
if
(
sequence
!=
1
)
{
if
(
sequence
!=
1
)
{
entry
.
getPrevEntryIds
().
add
(
id
-
1
);
// 假设Entry类有getPrevEntryIds()返回List<Integer>
OperationDependency
od
=
new
OperationDependency
();
od
.
setPrevOperationId
(
id
-
1
);
entry
.
getPrevEntryIds
().
add
(
od
);
// 假设Entry类有getPrevEntryIds()返回List<Integer>
}
}
allOperations
.
add
(
entry
);
allOperations
.
add
(
entry
);
...
@@ -794,8 +806,27 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
...
@@ -794,8 +806,27 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
entry
.
setGroupId
(
i
+
1
);
entry
.
setGroupId
(
i
+
1
);
entry
.
setSequence
(
nodeInfo
.
getGroupSerial
());
entry
.
setSequence
(
nodeInfo
.
getGroupSerial
());
entry
.
setExecId
(
nodeInfo
.
getOriginalId
());
entry
.
setExecId
(
nodeInfo
.
getOriginalId
());
entry
.
setPrevEntryIds
(
nodeInfo
.
getNewParentIds
());
entry
.
setNextEntryIds
(
nodeInfo
.
getNewChildIds
());
if
(
nodeInfo
.
getNewParentIds
()!=
null
)
{
List
<
OperationDependency
>
OperationDependency
=
new
ArrayList
<>();
for
(
int
id
:
nodeInfo
.
getNewParentIds
())
{
OperationDependency
od
=
new
OperationDependency
();
od
.
setPrevOperationId
(
id
);
OperationDependency
.
add
(
od
);
}
entry
.
setPrevEntryIds
(
OperationDependency
);
}
if
(
nodeInfo
.
getNewChildIds
()!=
null
)
{
List
<
OperationDependency
>
OperationDependency
=
new
ArrayList
<>();
for
(
int
id
:
nodeInfo
.
getNewChildIds
())
{
OperationDependency
od
=
new
OperationDependency
();
od
.
setNextOperationId
(
id
);
OperationDependency
.
add
(
od
);
}
entry
.
setNextEntryIds
(
OperationDependency
);
}
ProdProcessExec
op
=
ProdProcessExecs
.
stream
()
ProdProcessExec
op
=
ProdProcessExecs
.
stream
()
.
filter
(
t
->
t
.
getExecId
().
equals
(
entry
.
getExecId
()))
.
filter
(
t
->
t
.
getExecId
().
equals
(
entry
.
getExecId
()))
.
findFirst
().
orElse
(
null
);
.
findFirst
().
orElse
(
null
);
...
...
src/main/resources/machines.json
View file @
1c20209d
...
@@ -5,36 +5,12 @@
...
@@ -5,36 +5,12 @@
"startTime"
:
"08:00:00"
,
"startTime"
:
"08:00:00"
,
"endTime"
:
"18:00:00"
,
"endTime"
:
"18:00:00"
,
"days"
:
[
1
,
2
,
3
,
4
,
5
],
"days"
:
[
1
,
2
,
3
,
4
,
5
],
"startDate"
:
"20
25-10-10
T00:00:00"
,
"startDate"
:
"20
00-01-01
T00:00:00"
,
"endDate"
:
"20
25-11-10
T00:00:00"
,
"endDate"
:
"20
00-01-01
T00:00:00"
,
"shiftDate"
:
"0001-01-01T00:00:00"
,
"shiftDate"
:
"0001-01-01T00:00:00"
,
"temporaryShift"
:
false
,
"temporaryShift"
:
false
,
"priority"
:
0
,
"priority"
:
0
,
"status"
:
0
"status"
:
0
},{
"startTime"
:
"18:00:00"
,
"endTime"
:
"20:00:00"
,
"days"
:
[
1
,
2
,
3
,
4
,
5
],
"shiftDate"
:
"0001-01-01T00:00:00"
,
"temporaryShift"
:
true
,
"priority"
:
0
,
"status"
:
1
},{
"startTime"
:
"08:00:00"
,
"endTime"
:
"18:00:00"
,
"days"
:
[
0
],
"shiftDate"
:
"0001-01-01T00:00:00"
,
"temporaryShift"
:
true
,
"priority"
:
0
,
"status"
:
1
},{
"startTime"
:
"08:00:00"
,
"endTime"
:
"18:00:00"
,
"days"
:
null
,
"shiftDate"
:
"2025-10-01T00:00:00"
,
"temporaryShift"
:
true
,
"priority"
:
0
,
"status"
:
1
}],
}],
"maintenanceWindows"
:
[{
"maintenanceWindows"
:
[{
"startTime"
:
"2025-10-08T10:00:00"
,
"startTime"
:
"2025-10-08T10:00:00"
,
...
@@ -49,6 +25,8 @@
...
@@ -49,6 +25,8 @@
"endTime"
:
"18:00:00"
,
"endTime"
:
"18:00:00"
,
"days"
:
[
1
,
2
,
3
,
4
,
5
],
"days"
:
[
1
,
2
,
3
,
4
,
5
],
"shiftDate"
:
"0001-01-01T00:00:00"
,
"shiftDate"
:
"0001-01-01T00:00:00"
,
"startDate"
:
"2000-01-01T00:00:00"
,
"endDate"
:
"2000-01-01T00:00:00"
,
"temporaryShift"
:
false
,
"temporaryShift"
:
false
,
"priority"
:
0
,
"priority"
:
0
,
"status"
:
0
"status"
:
0
...
@@ -62,6 +40,8 @@
...
@@ -62,6 +40,8 @@
"endTime"
:
"18:00:00"
,
"endTime"
:
"18:00:00"
,
"days"
:
[
1
,
2
,
3
,
4
,
5
],
"days"
:
[
1
,
2
,
3
,
4
,
5
],
"shiftDate"
:
"0001-01-01T00:00:00"
,
"shiftDate"
:
"0001-01-01T00:00:00"
,
"startDate"
:
"2000-01-01T00:00:00"
,
"endDate"
:
"2000-01-01T00:00:00"
,
"temporaryShift"
:
false
,
"temporaryShift"
:
false
,
"priority"
:
0
,
"priority"
:
0
,
"status"
:
0
"status"
:
0
...
@@ -75,6 +55,8 @@
...
@@ -75,6 +55,8 @@
"endTime"
:
"18:00:00"
,
"endTime"
:
"18:00:00"
,
"days"
:
[
1
,
2
,
3
,
4
,
5
],
"days"
:
[
1
,
2
,
3
,
4
,
5
],
"shiftDate"
:
"0001-01-01T00:00:00"
,
"shiftDate"
:
"0001-01-01T00:00:00"
,
"startDate"
:
"2000-01-01T00:00:00"
,
"endDate"
:
"2000-01-01T00:00:00"
,
"temporaryShift"
:
false
,
"temporaryShift"
:
false
,
"priority"
:
0
,
"priority"
:
0
,
"status"
:
0
"status"
:
0
...
@@ -88,6 +70,8 @@
...
@@ -88,6 +70,8 @@
"endTime"
:
"18:00:00"
,
"endTime"
:
"18:00:00"
,
"days"
:
[
1
,
2
,
3
,
4
,
5
],
"days"
:
[
1
,
2
,
3
,
4
,
5
],
"shiftDate"
:
"0001-01-01T00:00:00"
,
"shiftDate"
:
"0001-01-01T00:00:00"
,
"startDate"
:
"2000-01-01T00:00:00"
,
"endDate"
:
"2000-01-01T00:00:00"
,
"temporaryShift"
:
false
,
"temporaryShift"
:
false
,
"priority"
:
0
,
"priority"
:
0
,
"status"
:
0
"status"
:
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