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
6c291a36
Commit
6c291a36
authored
Jun 10, 2026
by
Tong Li
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
CP
parent
fef1ef87
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
566 additions
and
12 deletions
+566
-12
Order.java
src/main/java/com/aps/entity/basic/Order.java
+11
-0
CpSatInitializer.java
...main/java/com/aps/service/Algorithm/CpSatInitializer.java
+6
-2
CpSatOrderMergeService.java
...ava/com/aps/service/Algorithm/CpSatOrderMergeService.java
+342
-0
HybridAlgorithm.java
src/main/java/com/aps/service/Algorithm/HybridAlgorithm.java
+3
-1
RoutingDataService.java
...in/java/com/aps/service/Algorithm/RoutingDataService.java
+21
-4
PlanResultService.java
src/main/java/com/aps/service/plan/PlanResultService.java
+181
-3
PlanResultServiceTest.java
src/test/java/com/aps/demo/PlanResultServiceTest.java
+2
-2
No files found.
src/main/java/com/aps/entity/basic/Order.java
View file @
6c291a36
...
...
@@ -193,4 +193,15 @@ public class Order {
* 多级排序路径(用于精确字典序排序,避免浮点精度问题)
*/
private
List
<
Integer
>
sortKey
;
/**
* 合并来源订单ID列表(合并订单时记录原始订单ID,用于结果追溯)
*/
private
List
<
String
>
mergedChildOrderIds
;
/**
* 是否为合并订单
*/
private
boolean
merged
=
false
;
}
\ No newline at end of file
src/main/java/com/aps/service/Algorithm/CpSatInitializer.java
View file @
6c291a36
...
...
@@ -74,8 +74,12 @@ public class CpSatInitializer {
}
else
if
(
opCount
<=
LARGE_SCALE_THRESHOLD
)
{
return
largeScaleDecomposed
(
globalOpList
,
targetCount
,
timeBudgetSec
);
}
else
{
FileHelper
.
writeLogFile
(
"[CP-SAT] 工序数超过阈值,跳过CP-SAT,回退启发式"
);
return
Collections
.
emptyList
();
return
largeScaleDecomposed
(
globalOpList
,
targetCount
,
timeBudgetSec
);
// FileHelper.writeLogFile("[CP-SAT] 工序数超过阈值,跳过CP-SAT,回退启发式");
// return Collections.emptyList();
}
}
catch
(
Exception
e
)
{
FileHelper
.
writeLogFile
(
"[CP-SAT] 求解异常,回退启发式: "
+
e
.
getMessage
());
...
...
src/main/java/com/aps/service/Algorithm/CpSatOrderMergeService.java
0 → 100644
View file @
6c291a36
This diff is collapsed.
Click to expand it.
src/main/java/com/aps/service/Algorithm/HybridAlgorithm.java
View file @
6c291a36
...
...
@@ -98,8 +98,10 @@ public class HybridAlgorithm {
// .filter(t->existIds.add(t.getId()))//HashSet.add() 方法:添加成功返回 true,重复返回 false;
// .collect(Collectors.toList());
// }
LocalDateTime
starttime
=
LocalDateTime
.
now
();
FileHelper
.
writeLogFile
(
"排产-----------开始-----------"
+
allOperations
.
get
(
0
).
getSceneId
());
FileHelper
.
writeLogFile
(
"排产-----------开始-----
"
+
(
_GlobalParam
.
isJit
()?
"倒排"
:
"正排"
)+
"
------"
+
allOperations
.
get
(
0
).
getSceneId
());
// 在整个流程开始时创建一个全局 shared decoder,所有阶段共享解码缓存
GeneticDecoder
sharedDecoder
=
new
GeneticDecoder
(
_GlobalParam
,
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
,
materialRequirementService
,
sceneId
);
...
...
src/main/java/com/aps/service/Algorithm/RoutingDataService.java
View file @
6c291a36
...
...
@@ -63,6 +63,11 @@ public class RoutingDataService {
private
EquipinfoService
_equipinfoService
;
public
Map
<
Integer
,
Object
>
InitEntrys
(
String
SceneId
,
List
<
ProdEquipment
>
ProdEquipments
,
List
<
Order
>
ProdLaunchOrders
)
{
return
InitEntrys
(
SceneId
,
ProdEquipments
,
ProdLaunchOrders
,
null
);
}
public
Map
<
Integer
,
Object
>
InitEntrys
(
String
SceneId
,
List
<
ProdEquipment
>
ProdEquipments
,
List
<
Order
>
ProdLaunchOrders
,
Map
<
String
,
Order
>
mergeMap
)
{
Map
<
Integer
,
Object
>
list
=
new
HashMap
<>();
List
<
ProdProcessExec
>
ProdProcessExecs
=
_prodProcessExecService
.
lambdaQuery
()
...
...
@@ -111,6 +116,11 @@ public class RoutingDataService {
}
public
Map
<
Integer
,
Object
>
CreateEntry
(
String
SceneId
,
List
<
ProdEquipment
>
ProdEquipments
,
List
<
Order
>
ProdLaunchOrders
,
List
<
RoutingDiscreteParam
>
routingDiscreteParams
,
List
<
ProdOrderProcess
>
ProdOrderProcesss
,
List
<
ProdProcessExec
>
ProdProcessExecs
,
List
<
GroupResult
>
existingResults
,
int
FinishOpertionID
)
{
return
CreateEntry
(
SceneId
,
ProdEquipments
,
ProdLaunchOrders
,
routingDiscreteParams
,
ProdOrderProcesss
,
ProdProcessExecs
,
existingResults
,
FinishOpertionID
,
null
);
}
public
Map
<
Integer
,
Object
>
CreateEntry
(
String
SceneId
,
List
<
ProdEquipment
>
ProdEquipments
,
List
<
Order
>
ProdLaunchOrders
,
List
<
RoutingDiscreteParam
>
routingDiscreteParams
,
List
<
ProdOrderProcess
>
ProdOrderProcesss
,
List
<
ProdProcessExec
>
ProdProcessExecs
,
List
<
GroupResult
>
existingResults
,
int
FinishOpertionID
,
Map
<
String
,
Order
>
mergeMap
)
{
Map
<
Integer
,
Object
>
list
=
new
HashMap
<>();
List
<
String
>
soutceExecId
=
ProdOrderProcesss
.
stream
()
...
...
@@ -240,9 +250,9 @@ public class RoutingDataService {
entry
.
setDepartmentId
(
op
.
getDepartmentId
());
}
entry
.
setIsInterrupt
(
op
.
getCanInterrupt
());
Order
order
=
ProdLaunchOrders
.
stream
()
.
filter
(
t
->
t
.
getOrderId
().
equals
(
op
.
getOrderId
()))
.
findFirst
().
orElse
(
null
);
Order
order
=
findOrderByOrderId
(
ProdLaunchOrders
,
mergeMap
,
op
.
getOrderId
());
if
(
order
!=
null
)
{
entry
.
setOrderCode
(
order
.
getOrderCode
());
entry
.
setProductId
(
order
.
getMaterialId
());
...
...
@@ -315,7 +325,14 @@ if(entry.getMachineOptions()!=null)
return
list
;
}
private
Order
findOrderByOrderId
(
List
<
Order
>
orderList
,
Map
<
String
,
Order
>
mergeMap
,
String
orderId
)
{
if
(
mergeMap
!=
null
&&
mergeMap
.
containsKey
(
orderId
))
{
return
mergeMap
.
get
(
orderId
);
}
return
orderList
.
stream
()
.
filter
(
t
->
t
.
getOrderId
().
equals
(
orderId
))
.
findFirst
().
orElse
(
null
);
}
public
List
<
Machine
>
InitCalendarToAllMachines
(
String
SceneId
,
List
<
ProdEquipment
>
ProdEquipments
,
MachineSchedulerService
machineScheduler
,
boolean
IsUseCalendar
)
{
// 按设备分组
...
...
src/main/java/com/aps/service/plan/PlanResultService.java
View file @
6c291a36
...
...
@@ -188,7 +188,7 @@ public class PlanResultService {
try
{
ScheduleParams
param
=
InitScheduleParams
();
//
param.setBaseTime(LocalDateTime.of(2026, 5, 20, 0, 0, 0));
//
param.setBaseTime(LocalDateTime.of(2026, 5, 20, 0, 0, 0));
this
.
baseTime
=
param
.
getBaseTime
();
// 策略读取入口:优先使用前端传入的 userId;没传时用 sceneId 查场景创建人。
Long
effectiveUserId
=
scheduleStrategyService
.
resolveScheduleUserId
(
SceneId
,
userId
);
...
...
@@ -275,9 +275,9 @@ public class PlanResultService {
// 5. 执行调度算法
HybridAlgorithm
scheduler
=
new
HybridAlgorithm
(
globalParam
,
machines
,
orders
,
materialmap
,
materialIds
,
machineScheduler
,
entryRel
,
materialRequirementService
,
_sceneService
,
SceneId
);
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
param
.
initAdaptiveParams
(
entrys
.
size
());
double
[]
customWeights
=
new
double
[]
{
0.4
,
0.1
,
0.1
,
0.1
,
0.3
};
// 延迟时间权重提升到0.5
//
double[] customWeights = new double[] { 0.4, 0.1, 0.1, 0.1, 0.3 }; // 延迟时间权重提升到0.5
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
scheduler
.
Init
();
//
scheduler.Init();
Chromosome
chromosome
=
scheduler
.
Run
(
param
,
entrys
);
KpiCalculator
kpiCalculator
=
new
KpiCalculator
(
chromosome
);
...
...
@@ -2402,6 +2402,184 @@ if(job.getGeneDetails()!=null)
return
orders
;
}
/**
* 排产前合并兼容订单:相同物料+相同工艺路线+相同系列+时间窗口重叠且交付日期相近的订单合并为一个
* @param orders 原始订单列表
* @param materials 物料列表(用于 maxProduction 上限校验)
* @return entry: key=合并后的订单列表, value=originalOrderId→mergedOrder 映射表
*/
public
AbstractMap
.
SimpleEntry
<
List
<
Order
>,
Map
<
String
,
Order
>>
mergeOrders
(
List
<
Order
>
orders
,
List
<
Material
>
materials
)
{
return
mergeOrders
(
orders
,
materials
,
DEFAULT_MERGE_DUE_DATE_RANGE_DAYS
);
}
/**
* 使用 OR-Tools CP-SAT 求解最优合并方案(替代贪心算法)
* 将兼容订单建模为 Bin Packing,最小化合并组数
*
* @param orders 原始订单列表
* @param materials 物料列表
* @param dueDateRangeDays 交付日期相差上限(天)
* @return entry: key=合并后的订单列表, value=originalOrderId→mergedOrder 映射表
*/
public
AbstractMap
.
SimpleEntry
<
List
<
Order
>,
Map
<
String
,
Order
>>
mergeOrdersWithCpSat
(
List
<
Order
>
orders
,
List
<
Material
>
materials
,
int
dueDateRangeDays
)
{
CpSatOrderMergeService
solver
=
new
CpSatOrderMergeService
();
return
solver
.
mergeOrders
(
orders
,
materials
,
dueDateRangeDays
);
}
/**
* @param dueDateRangeDays 允许合并的交付日期最大相差天数
*/
public
AbstractMap
.
SimpleEntry
<
List
<
Order
>,
Map
<
String
,
Order
>>
mergeOrders
(
List
<
Order
>
orders
,
List
<
Material
>
materials
,
int
dueDateRangeDays
)
{
if
(
orders
==
null
||
orders
.
size
()
<=
1
)
{
return
new
AbstractMap
.
SimpleEntry
<>(
orders
,
new
HashMap
<>());
}
Map
<
String
,
Material
>
materialMap
=
buildMaterialMap
(
materials
);
Map
<
String
,
Order
>
mergeMap
=
new
HashMap
<>();
List
<
Order
>
mergedOrders
=
new
ArrayList
<>();
List
<
Order
>
remaining
=
new
ArrayList
<>(
orders
);
while
(!
remaining
.
isEmpty
())
{
Order
base
=
remaining
.
remove
(
0
);
List
<
Order
>
mergeGroup
=
new
ArrayList
<>();
mergeGroup
.
add
(
base
);
double
groupQty
=
base
.
getQuantity
();
Material
material
=
materialMap
.
get
(
base
.
getMaterialId
());
BigDecimal
maxProduction
=
(
material
!=
null
&&
material
.
getMaxProduction
()
!=
null
&&
material
.
getMaxProduction
().
compareTo
(
BigDecimal
.
ZERO
)
>
0
)
?
material
.
getMaxProduction
()
:
null
;
Iterator
<
Order
>
it
=
remaining
.
iterator
();
while
(
it
.
hasNext
())
{
Order
candidate
=
it
.
next
();
if
(!
canMerge
(
base
,
candidate
,
dueDateRangeDays
))
{
continue
;
}
double
newQty
=
groupQty
+
candidate
.
getQuantity
();
if
(
maxProduction
!=
null
&&
BigDecimal
.
valueOf
(
newQty
).
compareTo
(
maxProduction
)
>
0
)
{
continue
;
}
mergeGroup
.
add
(
candidate
);
groupQty
=
newQty
;
it
.
remove
();
}
if
(
mergeGroup
.
size
()
==
1
)
{
mergedOrders
.
add
(
base
);
}
else
{
Order
merged
=
createMergedOrder
(
mergeGroup
);
mergedOrders
.
add
(
merged
);
for
(
Order
child
:
mergeGroup
)
{
mergeMap
.
put
(
child
.
getOrderId
(),
merged
);
}
}
}
FileHelper
.
writeLogFile
(
String
.
format
(
"订单合并完成:原始%d个 → 合并后%d个,合并组%d组"
,
orders
.
size
(),
mergedOrders
.
size
(),
(
int
)
mergeMap
.
values
().
stream
().
distinct
().
count
()));
return
new
AbstractMap
.
SimpleEntry
<>(
mergedOrders
,
mergeMap
);
}
private
static
final
int
DEFAULT_MERGE_DUE_DATE_RANGE_DAYS
=
7
;
private
Map
<
String
,
Material
>
buildMaterialMap
(
List
<
Material
>
materials
)
{
if
(
materials
==
null
||
materials
.
isEmpty
())
{
return
Collections
.
emptyMap
();
}
return
materials
.
stream
()
.
filter
(
m
->
m
.
getId
()
!=
null
)
.
collect
(
Collectors
.
toMap
(
Material:
:
getId
,
m
->
m
,
(
existing
,
replacement
)
->
existing
));
}
private
boolean
canMerge
(
Order
a
,
Order
b
,
int
dueDateRangeDays
)
{
if
(
a
==
null
||
b
==
null
)
{
return
false
;
}
if
(
a
.
getRoutingId
()
==
null
||
b
.
getRoutingId
()
==
null
)
{
return
false
;
}
if
(!
a
.
getRoutingId
().
equals
(
b
.
getRoutingId
()))
{
return
false
;
}
if
(
a
.
getMaterialCode
()
==
null
||
b
.
getMaterialCode
()
==
null
)
{
return
false
;
}
if
(!
a
.
getMaterialCode
().
equals
(
b
.
getMaterialCode
()))
{
return
false
;
}
if
(
a
.
getSerie
()
==
null
||
b
.
getSerie
()
==
null
)
{
return
false
;
}
if
(!
a
.
getSerie
().
equals
(
b
.
getSerie
()))
{
return
false
;
}
if
(
a
.
isMerged
()
||
b
.
isMerged
())
{
return
false
;
}
if
(
a
.
getStartDate
()
==
null
||
a
.
getDueDate
()
==
null
||
b
.
getStartDate
()
==
null
||
b
.
getDueDate
()
==
null
)
{
return
false
;
}
boolean
overlap
=
!
a
.
getDueDate
().
isBefore
(
b
.
getStartDate
())
&&
!
b
.
getDueDate
().
isBefore
(
a
.
getStartDate
());
if
(!
overlap
)
{
return
false
;
}
long
daysDiff
=
Math
.
abs
(
ChronoUnit
.
DAYS
.
between
(
a
.
getDueDate
().
toLocalDate
(),
b
.
getDueDate
().
toLocalDate
()));
return
daysDiff
<=
dueDateRangeDays
;
}
private
Order
createMergedOrder
(
List
<
Order
>
group
)
{
Order
merged
=
new
Order
();
Order
first
=
group
.
get
(
0
);
merged
.
setOrderId
(
first
.
getOrderId
());
merged
.
setOrderCode
(
first
.
getOrderCode
()
+
"-MG"
);
merged
.
setMaterialCode
(
first
.
getMaterialCode
());
merged
.
setMaterialName
(
first
.
getMaterialName
());
merged
.
setMaterialId
(
first
.
getMaterialId
());
merged
.
setSerie
(
first
.
getSerie
());
merged
.
setRoutingId
(
first
.
getRoutingId
());
merged
.
setRoutingCode
(
first
.
getRoutingCode
());
merged
.
setProductId
(
first
.
getProductId
());
merged
.
setMerged
(
true
);
double
totalQty
=
group
.
stream
().
mapToDouble
(
Order:
:
getQuantity
).
sum
();
merged
.
setQuantity
(
totalQty
);
merged
.
setSYQuantity
(
totalQty
);
LocalDateTime
maxStartDate
=
group
.
stream
()
.
map
(
Order:
:
getStartDate
)
.
filter
(
Objects:
:
nonNull
)
.
max
(
LocalDateTime:
:
compareTo
)
.
orElse
(
null
);
merged
.
setStartDate
(
maxStartDate
);
LocalDateTime
minDueDate
=
group
.
stream
()
.
map
(
Order:
:
getDueDate
)
.
filter
(
Objects:
:
nonNull
)
.
min
(
LocalDateTime:
:
compareTo
)
.
orElse
(
null
);
merged
.
setDueDate
(
minDueDate
);
int
minPriority
=
group
.
stream
()
.
mapToInt
(
Order:
:
getPriority
)
.
min
()
.
orElse
(
first
.
getPriority
());
merged
.
setPriority
(
minPriority
);
merged
.
setActualPriority
(
minPriority
);
List
<
String
>
childIds
=
group
.
stream
()
.
map
(
Order:
:
getOrderId
)
.
collect
(
Collectors
.
toList
());
merged
.
setMergedChildOrderIds
(
childIds
);
return
merged
;
}
public
List
<
Material
>
InitMaterial
()
{
List
<
Material
>
materials
=
new
ArrayList
<>();
FileHelper
.
writeLogFile
(
"初始化物料-----------开始-------"
);
...
...
src/test/java/com/aps/demo/PlanResultServiceTest.java
View file @
6c291a36
...
...
@@ -42,8 +42,8 @@ public class PlanResultServiceTest {
// nsgaiiUtils.Test();
// planResultService.execute2("64E64F6B68094AF38CEDC418630C3CC2");//2000
planResultService
.
execute2
(
"E1448B3C9C8743DEAB39708F2CFE348A"
);
//2000
// planResultService.execute2("E1448B3C9C8743DEAB39708F2CFE348A");//倒排bomces
planResultService
.
execute2
(
"29C78D0363244300BBB149E7D7873AF1"
);
// planResultService.execute2("15210B13B88A453F8B84AAC7F16C7541");//2000
// planResultService.execute2("E29F2B3ADA8149F6B916B5119296A92B");//2000
...
...
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