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
f30098ce
Commit
f30098ce
authored
Mar 17, 2026
by
Tong Li
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
目标kpi可配置
parent
e9d075e2
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
492 additions
and
149 deletions
+492
-149
GlobalParam.java
src/main/java/com/aps/entity/basic/GlobalParam.java
+123
-0
ObjectiveConfig.java
src/main/java/com/aps/entity/basic/ObjectiveConfig.java
+46
-0
GeneticAlgorithm.java
...main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
+3
-7
GeneticDecoder.java
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
+83
-65
NSGAIIUtils.java
src/main/java/com/aps/service/Algorithm/NSGAIIUtils.java
+213
-73
PlanResultService.java
src/main/java/com/aps/service/plan/PlanResultService.java
+5
-3
NSGAIIUtilsTest.java
src/test/java/com/aps/demo/NSGAIIUtilsTest.java
+18
-0
PlanResultServiceTest.java
src/test/java/com/aps/demo/PlanResultServiceTest.java
+1
-1
No files found.
src/main/java/com/aps/entity/basic/GlobalParam.java
View file @
f30098ce
...
@@ -2,6 +2,11 @@ package com.aps.entity.basic;
...
@@ -2,6 +2,11 @@ package com.aps.entity.basic;
import
lombok.Data
;
import
lombok.Data
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
/**
/**
* 作者:佟礼
* 作者:佟礼
* 时间:2025-11-21
* 时间:2025-11-21
...
@@ -43,4 +48,122 @@ public class GlobalParam {
...
@@ -43,4 +48,122 @@ public class GlobalParam {
private
boolean
_smoothChangeOver
=
true
;
// 默认true,设置时间 是否考虑换型时间
private
boolean
_smoothChangeOver
=
true
;
// 默认true,设置时间 是否考虑换型时间
private
boolean
_smoothChangeOverInWeek
=
true
;
// 默认true,后台任务设置 休息时间是否换型
private
boolean
_smoothChangeOverInWeek
=
true
;
// 默认true,后台任务设置 休息时间是否换型
/**
* NSGA-II模式:true=纯帕累托(无视权重),false=加权帕累托
*/
private
boolean
pureNSGAIIMode
=
true
;
/// <summary>
/// 目标值配置列表:包含目标值的名称、是否启用、层级和权重
/// </summary>
private
List
<
ObjectiveConfig
>
objectiveConfigs
=
new
ArrayList
<>();
/// <summary>
/// 目标值名称常量
/// </summary>
public
static
final
String
OBJECTIVE_MAKESPAN
=
"makespan"
;
// 最早完工时间
public
static
final
String
OBJECTIVE_FLOW_TIME
=
"flowTime"
;
// 总流程时间
public
static
final
String
OBJECTIVE_SETUP_TIME
=
"setupTime"
;
// 总换型时间
public
static
final
String
OBJECTIVE_MACHINE_LOAD
=
"machineLoad"
;
// 机器负载均衡
public
static
final
String
OBJECTIVE_TARDINESS
=
"tardiness"
;
// 延迟时间
/// <summary>
/// 构造函数,初始化默认值
/// </summary>
public
GlobalParam
()
{
// 初始化默认目标值配置
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_MAKESPAN
,
true
,
1
,
0.6
));
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_FLOW_TIME
,
false
,
2
,
0.1
));
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_SETUP_TIME
,
true
,
2
,
0.1
));
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_MACHINE_LOAD
,
false
,
3
,
0.1
));
objectiveConfigs
.
add
(
new
ObjectiveConfig
(
OBJECTIVE_TARDINESS
,
true
,
1
,
0.3
));
}
/// <summary>
/// 获取目标值启用状态
/// </summary>
public
Map
<
String
,
Boolean
>
getObjectiveEnabled
()
{
Map
<
String
,
Boolean
>
enabledMap
=
new
HashMap
<>();
for
(
ObjectiveConfig
config
:
objectiveConfigs
)
{
enabledMap
.
put
(
config
.
getName
(),
config
.
isEnabled
());
}
return
enabledMap
;
}
/// <summary>
/// 获取目标值层级
/// </summary>
public
Map
<
String
,
Integer
>
getObjectiveLevels
()
{
Map
<
String
,
Integer
>
levelsMap
=
new
HashMap
<>();
for
(
ObjectiveConfig
config
:
objectiveConfigs
)
{
levelsMap
.
put
(
config
.
getName
(),
config
.
getLevel
());
}
return
levelsMap
;
}
/// <summary>
/// 获取目标值顺序
/// </summary>
public
List
<
String
>
getObjectiveOrder
()
{
List
<
String
>
orderList
=
new
ArrayList
<>();
for
(
ObjectiveConfig
config
:
objectiveConfigs
)
{
orderList
.
add
(
config
.
getName
());
}
return
orderList
;
}
/// <summary>
/// 获取目标值权重
/// </summary>
public
Map
<
String
,
Double
>
getObjectiveWeights
()
{
Map
<
String
,
Double
>
weightsMap
=
new
HashMap
<>();
for
(
ObjectiveConfig
config
:
objectiveConfigs
)
{
if
(
config
.
isEnabled
())
{
weightsMap
.
put
(
config
.
getName
(),
config
.
getWeight
());
}
}
return
weightsMap
;
}
/// <summary>
/// 根据名称获取目标值配置
/// </summary>
public
ObjectiveConfig
getObjectiveConfig
(
String
name
)
{
for
(
ObjectiveConfig
config
:
objectiveConfigs
)
{
if
(
config
.
getName
().
equals
(
name
))
{
return
config
;
}
}
return
null
;
}
/// <summary>
/// 添加目标值配置
/// </summary>
public
void
addObjectiveConfig
(
ObjectiveConfig
config
)
{
objectiveConfigs
.
add
(
config
);
}
/// <summary>
/// 更新目标值配置
/// </summary>
public
void
updateObjectiveConfig
(
String
name
,
ObjectiveConfig
config
)
{
for
(
int
i
=
0
;
i
<
objectiveConfigs
.
size
();
i
++)
{
if
(
objectiveConfigs
.
get
(
i
).
getName
().
equals
(
name
))
{
objectiveConfigs
.
set
(
i
,
config
);
return
;
}
}
}
/// <summary>
/// 移除目标值配置
/// </summary>
public
void
removeObjectiveConfig
(
String
name
)
{
objectiveConfigs
.
removeIf
(
config
->
config
.
getName
().
equals
(
name
));
}
}
}
src/main/java/com/aps/entity/basic/ObjectiveConfig.java
0 → 100644
View file @
f30098ce
package
com
.
aps
.
entity
.
basic
;
import
lombok.Data
;
/**
* 目标值配置实体类
* 作者:佟礼
* 时间:2026-03-17
*/
@Data
public
class
ObjectiveConfig
{
/**
* 目标值名称
*/
private
String
name
;
/**
* 是否启用
*/
private
boolean
enabled
;
/**
* 层级,层级越低优先级越高,1为最高
*/
private
int
level
;
/**
* 权重
*/
private
double
weight
;
/**
* 构造函数
*/
public
ObjectiveConfig
()
{
}
/**
* 构造函数
*/
public
ObjectiveConfig
(
String
name
,
boolean
enabled
,
int
level
,
double
weight
)
{
this
.
name
=
name
;
this
.
enabled
=
enabled
;
this
.
level
=
level
;
this
.
weight
=
weight
;
}
}
\ No newline at end of file
src/main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
View file @
f30098ce
...
@@ -65,14 +65,10 @@ public class GeneticAlgorithm {
...
@@ -65,14 +65,10 @@ public class GeneticAlgorithm {
materialIds
=
_materialIds
;
materialIds
=
_materialIds
;
}
}
public
void
Init
(
double
[]
customWeights
,
boolean
pureNSGAIIMode
)
{
public
void
Init
()
{
// 自定义权重配置
// 自定义权重配置
if
(
customWeights
!=
null
&&
customWeights
.
length
==
5
)
{
_nsgaIIUtils
.
init
(
_GlobalParam
);
_objectiveWeights
.
setWeights
(
customWeights
);
_objectiveWeights
.
setPureNSGAIIMode
(
pureNSGAIIMode
);
}
_nsgaIIUtils
.
init
(
_objectiveWeights
);
}
}
public
Chromosome
Run
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
)
{
public
Chromosome
Run
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
)
{
...
...
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
View file @
f30098ce
...
@@ -1759,73 +1759,91 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
...
@@ -1759,73 +1759,91 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
private
void
calculateScheduleResult
(
Chromosome
chromosome
)
{
private
void
calculateScheduleResult
(
Chromosome
chromosome
)
{
// 1. 最早完工时间(最小化)
double
[]
Objectives
=
new
double
[
_globalParam
.
getObjectiveWeights
().
size
()];
double
makespan
=
chromosome
.
getResult
().
stream
()
.
mapToInt
(
GAScheduleResult:
:
getEndTime
)
int
i
=
0
;
.
max
()
for
(
ObjectiveConfig
config
:
_globalParam
.
getObjectiveConfigs
())
{
.
orElse
(
0
);
if
(
config
.
isEnabled
())
{
// 2. 交付期满足情况(最小化延迟)
if
(
config
.
getName
()==
GlobalParam
.
OBJECTIVE_MAKESPAN
)
double
tardiness
=
0
;
{
// 1. 最早完工时间(最小化)
Map
<
Integer
,
List
<
GAScheduleResult
>>
orderGroups
=
chromosome
.
getResult
().
stream
()
double
makespan
=
chromosome
.
getResult
().
stream
()
.
collect
(
Collectors
.
groupingBy
(
GAScheduleResult:
:
getGroupId
));
.
mapToInt
(
GAScheduleResult:
:
getEndTime
)
.
max
()
for
(
Map
.
Entry
<
Integer
,
List
<
GAScheduleResult
>>
group
:
orderGroups
.
entrySet
())
{
.
orElse
(
0
);
int
groupId
=
group
.
getKey
();
Objectives
[
i
]=
makespan
;
int
orderCompletion
=
group
.
getValue
().
stream
()
chromosome
.
setMakespan
(
makespan
);
.
mapToInt
(
GAScheduleResult:
:
getEndTime
)
}
.
max
()
if
(
config
.
getName
()==
GlobalParam
.
OBJECTIVE_TARDINESS
)
.
orElse
(
0
);
{
List
<
String
>
orderIds
=
group
.
getValue
().
stream
()
// 2. 交付期满足情况(最小化延迟)
.
map
(
GAScheduleResult:
:
getOrderId
)
double
tardiness
=
0
;
.
distinct
()
.
sorted
()
Map
<
Integer
,
List
<
GAScheduleResult
>>
orderGroups
=
chromosome
.
getResult
().
stream
()
.
collect
(
Collectors
.
toList
());
.
collect
(
Collectors
.
groupingBy
(
GAScheduleResult:
:
getGroupId
));
Order
order
=
chromosome
.
getOrders
().
stream
()
.
filter
(
t
->
orderIds
.
contains
(
t
.
getOrderId
()))
for
(
Map
.
Entry
<
Integer
,
List
<
GAScheduleResult
>>
group
:
orderGroups
.
entrySet
())
{
.
max
(
Comparator
.
comparing
(
Order:
:
getDueDate
))
int
groupId
=
group
.
getKey
();
.
orElse
(
null
);
int
orderCompletion
=
group
.
getValue
().
stream
()
if
(
order
.
isNewCreate
())
.
mapToInt
(
GAScheduleResult:
:
getEndTime
)
{
continue
;}
.
max
()
LocalDateTime
dueDateTime
=
order
.
getDueDate
();
.
orElse
(
0
);
List
<
String
>
orderIds
=
group
.
getValue
().
stream
()
.
map
(
GAScheduleResult:
:
getOrderId
)
.
distinct
()
LocalDateTime
completionTime
=
baseTime
.
plusSeconds
(
orderCompletion
);
.
sorted
()
.
collect
(
Collectors
.
toList
());
Order
order
=
chromosome
.
getOrders
().
stream
()
if
(
completionTime
.
isAfter
(
dueDateTime
))
{
.
filter
(
t
->
orderIds
.
contains
(
t
.
getOrderId
()))
// 计算延迟小时数(修复时间计算)
.
max
(
Comparator
.
comparing
(
Order:
:
getDueDate
))
long
hours
=
ChronoUnit
.
HOURS
.
between
(
dueDateTime
,
completionTime
);
.
orElse
(
null
);
long
minutes
=
ChronoUnit
.
MINUTES
.
between
(
dueDateTime
,
completionTime
)
%
60
;
if
(
order
.
isNewCreate
())
tardiness
+=
hours
*
60
+
(
double
)
minutes
;
{
continue
;}
}
LocalDateTime
dueDateTime
=
order
.
getDueDate
();
LocalDateTime
completionTime
=
baseTime
.
plusSeconds
(
orderCompletion
);
if
(
completionTime
.
isAfter
(
dueDateTime
))
{
// 计算延迟小时数(修复时间计算)
long
hours
=
ChronoUnit
.
HOURS
.
between
(
dueDateTime
,
completionTime
);
long
minutes
=
ChronoUnit
.
MINUTES
.
between
(
dueDateTime
,
completionTime
)
%
60
;
tardiness
+=
hours
*
60
+
(
double
)
minutes
;
}
}
Objectives
[
i
]=
tardiness
;
chromosome
.
setDelayTime
(
tardiness
);
}
if
(
config
.
getName
()==
GlobalParam
.
OBJECTIVE_SETUP_TIME
)
{
// 3. 最小总换型时间
double
totalSetupTime
=
calculateTotalSetupTime
(
chromosome
);
chromosome
.
setTotalChangeoverTime
(
totalSetupTime
);
Objectives
[
i
]=
totalSetupTime
;
}
if
(
config
.
getName
()==
GlobalParam
.
OBJECTIVE_FLOW_TIME
)
{
// 4. 最小化总流程时间 所有工序加工时间的总和
double
totalFlowTime
=
calculateTotalFlowTime
(
chromosome
);
chromosome
.
setTotalFlowTime
(
totalFlowTime
);
Objectives
[
i
]=
totalFlowTime
;
}
if
(
config
.
getName
()==
GlobalParam
.
OBJECTIVE_MACHINE_LOAD
)
{
// 5. 机器负载均衡
double
machineLoadBalance
=
calculateMachineLoadBalance
(
chromosome
);
chromosome
.
setMachineLoadStd
(
machineLoadBalance
);
Objectives
[
i
]=
machineLoadBalance
;
}
i
++;
}
}
}
// 3. 最小总换型时间
double
totalSetupTime
=
calculateTotalSetupTime
(
chromosome
);
// 4. 最小化总流程时间 所有工序加工时间的总和
double
totalFlowTime
=
calculateTotalFlowTime
(
chromosome
);
// 5. 机器负载均衡
double
machineLoadBalance
=
calculateMachineLoadBalance
(
chromosome
);
// 存储各目标值
chromosome
.
setMakespan
(
makespan
);
chromosome
.
setTotalFlowTime
(
totalFlowTime
);
chromosome
.
setTotalChangeoverTime
(
totalSetupTime
);
chromosome
.
setMachineLoadStd
(
machineLoadBalance
);
chromosome
.
setDelayTime
(
tardiness
);
double
[]
Objectives
=
new
double
[
5
];
Objectives
[
0
]
=
makespan
;
Objectives
[
1
]
=
totalFlowTime
;
Objectives
[
2
]
=
totalSetupTime
;
Objectives
[
3
]
=
machineLoadBalance
;
Objectives
[
4
]
=
tardiness
;
chromosome
.
setObjectives
(
Objectives
);
chromosome
.
setObjectives
(
Objectives
);
}
}
...
...
src/main/java/com/aps/service/Algorithm/NSGAIIUtils.java
View file @
f30098ce
...
@@ -3,14 +3,12 @@ package com.aps.service.Algorithm;
...
@@ -3,14 +3,12 @@ package com.aps.service.Algorithm;
import
com.aps.common.util.FileHelper
;
import
com.aps.common.util.FileHelper
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.ObjectiveWeights
;
import
com.aps.entity.Algorithm.ObjectiveWeights
;
import
com.aps.entity.basic.GlobalParam
;
import
java.util.*
;
import
java.util.*
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.stream.Collectors
;
import
java.util.stream.Collectors
;
import
java.util.*
;
import
java.util.concurrent.*
;
import
java.util.concurrent.*
;
import
java.util.stream.Collectors
;
import
java.util.stream.IntStream
;
import
java.util.stream.IntStream
;
/**
/**
...
@@ -19,31 +17,56 @@ import java.util.stream.IntStream;
...
@@ -19,31 +17,56 @@ import java.util.stream.IntStream;
public
class
NSGAIIUtils
{
public
class
NSGAIIUtils
{
private
ObjectiveWeights
objectiveWeights
;
private
ObjectiveWeights
objectiveWeights
;
private
int
taskCount
;
// 并行任务数(默认=CPU核心数)
private
int
taskCount
;
// 并行任务数(默认=CPU核心数)
private
GlobalParam
globalParam
;
// 全局参数配置
// true 越小越好
// true 越小越好
private
boolean
[]
isMinimize
=
{
true
,
true
,
true
,
true
,
true
};
private
boolean
[]
isMinimize
=
{
true
,
true
,
true
,
true
,
true
};
public
void
init
(
ObjectiveWeights
weights
,
int
taskCount
,
boolean
[]
isMinimize
)
{
this
.
objectiveWeights
=
(
weights
!=
null
)
?
weights
:
new
ObjectiveWeights
();
this
.
taskCount
=
(
taskCount
>
0
)
?
taskCount
:
Runtime
.
getRuntime
().
availableProcessors
()-
1
;
this
.
isMinimize
=
isMinimize
;
}
/**
/**
* 初始化(设置权重和并行任务数)
* 初始化(设置权重和并行任务数)
*/
*/
public
void
init
(
ObjectiveWeights
weights
,
int
taskCount
)
{
public
void
init
(
GlobalParam
globalParam
,
int
taskCount
)
{
this
.
objectiveWeights
=
(
weights
!=
null
)
?
weights
:
new
ObjectiveWeights
();
this
.
globalParam
=
globalParam
;
this
.
objectiveWeights
=
(
globalParam
.
getObjectiveWeights
()
!=
null
)
?
buildObjectiveWeightsFromGlobalParam
()
:
new
ObjectiveWeights
();
this
.
taskCount
=
(
taskCount
>
0
)
?
taskCount
:
Runtime
.
getRuntime
().
availableProcessors
()-
1
;
this
.
taskCount
=
(
taskCount
>
0
)
?
taskCount
:
Runtime
.
getRuntime
().
availableProcessors
()-
1
;
}
}
/**
/**
* 重载初始化方法(默认任务数)
* 重载初始化方法(默认任务数)
*/
*/
public
void
init
(
ObjectiveWeights
weights
)
{
public
void
init
(
GlobalParam
globalParam
)
{
init
(
weights
,
0
);
init
(
globalParam
,
0
);
}
}
/**
* 从 globalParam 构建 ObjectiveWeights
*/
private
ObjectiveWeights
buildObjectiveWeightsFromGlobalParam
()
{
ObjectiveWeights
weights
=
new
ObjectiveWeights
();
// 设置 pureNSGAIIMode
if
(
globalParam
!=
null
)
{
weights
.
setPureNSGAIIMode
(
globalParam
.
isPureNSGAIIMode
());
// 按照固定顺序构建权重数组
Map
<
String
,
Double
>
objectiveWeights
=
globalParam
.
getObjectiveWeights
();
double
[]
weightsArray
=
new
double
[
objectiveWeights
.
size
()];
int
i
=
0
;
for
(
Double
weight
:
objectiveWeights
.
values
())
{
weightsArray
[
i
]=
weight
;
i
++;
}
weights
.
setWeights
(
weightsArray
);
}
return
weights
;
}
/**
/**
* 并行快速非支配排序(大规模种群提速50%+)
* 并行快速非支配排序(大规模种群提速50%+)
...
@@ -65,57 +88,75 @@ public class NSGAIIUtils {
...
@@ -65,57 +88,75 @@ public class NSGAIIUtils {
// 步骤2:拆分种群为多个块,并行计算支配关系
// 步骤2:拆分种群为多个块,并行计算支配关系
List
<
List
<
Chromosome
>>
chunks
=
splitPopulation
(
population
,
chunkCount
);
List
<
List
<
Chromosome
>>
chunks
=
splitPopulation
(
population
,
chunkCount
);
Map
<
Chromosome
,
List
<
Chromosome
>>
dominanceMatrix
=
new
HashMap
<>();
// Map<Chromosome, List<Chromosome>> dominanceMatrix = new HashMap<>();
Map
<
Chromosome
,
Integer
>
dominatedCount
=
new
HashMap
<>();
// Map<Chromosome, Integer> dominatedCount = new HashMap<>();
ConcurrentHashMap
<
Chromosome
,
ConcurrentLinkedQueue
<
Chromosome
>>
dominanceMatrix
=
new
ConcurrentHashMap
<>();
ConcurrentHashMap
<
Chromosome
,
AtomicInteger
>
dominatedCount
=
new
ConcurrentHashMap
<>();
for
(
Chromosome
chromo
:
population
)
{
for
(
Chromosome
chromo
:
population
)
{
dominanceMatrix
.
put
(
chromo
,
new
ArrayList
<>());
// dominanceMatrix.put(chromo, new ArrayList<>());
dominatedCount
.
put
(
chromo
,
0
);
// dominatedCount.put(chromo, 0);
dominanceMatrix
.
putIfAbsent
(
chromo
,
new
ConcurrentLinkedQueue
<>());
dominatedCount
.
putIfAbsent
(
chromo
,
new
AtomicInteger
(
0
));
}
}
ExecutorService
executor
=
Executors
.
newFixedThreadPool
(
chunkCount
);
// ExecutorService executor = Executors.newFixedThreadPool(chunkCount);
try
{
// try {
List
<
Future
<?>>
futures
=
new
ArrayList
<>();
// 存储任务Future,确保全量等待
// List<Future<?>> futures = new ArrayList<>(); // 存储任务Future,确保全量等待
for
(
List
<
Chromosome
>
chunk
:
chunks
)
{
// for (List<Chromosome> chunk : chunks) {
futures
.
add
(
executor
.
submit
(()
->
{
// futures.add(executor.submit(() -> {
for
(
Chromosome
p
:
chunk
)
{
// for (Chromosome p : chunk) {
for
(
Chromosome
q
:
population
)
{
// for (Chromosome q : population) {
if
(
p
==
q
)
continue
;
// if (p == q) continue;
if
(
dominates
(
p
,
q
))
{
// if (dominates(p, q)) {
synchronized
(
dominanceMatrix
.
get
(
p
))
{
// 细粒度锁
// synchronized (dominanceMatrix.get(p)) { // 细粒度锁
dominanceMatrix
.
get
(
p
).
add
(
q
);
// dominanceMatrix.get(p).add(q);
}
// }
}
else
if
(
dominates
(
q
,
p
))
{
// } else if (dominates(q, p)) {
synchronized
(
dominatedCount
)
{
// synchronized (dominatedCount) {
dominatedCount
.
put
(
p
,
dominatedCount
.
get
(
p
)
+
1
);
// dominatedCount.put(p, dominatedCount.get(p) + 1);
}
// }
}
// }
}
// }
// }
// }));
// }
//
// // 核心修复2:等待所有任务完成,避免提前终止导致的计算不完整
// for (Future<?> future : futures) {
// try {
// future.get(); // 等待单个任务完成,抛出异常则终止
// } catch (ExecutionException e) {
// throw new RuntimeException("并行计算支配关系失败", e.getCause());
// }
// }
//
// executor.shutdown();
//
// }catch (InterruptedException e) {
// Thread.currentThread().interrupt();
// throw new RuntimeException("并行计算支配关系中断", e);
// } finally {
// if (!executor.isShutdown()) {
// executor.shutdownNow(); // 确保线程池关闭
// }
// }
// 并行计算支配关系
chunks
.
parallelStream
().
forEach
(
chunk
->
{
for
(
Chromosome
p
:
chunk
)
{
for
(
Chromosome
q
:
population
)
{
if
(
p
==
q
)
continue
;
if
(
dominates
(
p
,
q
))
{
dominanceMatrix
.
get
(
p
).
add
(
q
);
}
else
if
(
dominates
(
q
,
p
))
{
dominatedCount
.
get
(
p
).
incrementAndGet
();
}
}
}));
}
// 核心修复2:等待所有任务完成,避免提前终止导致的计算不完整
for
(
Future
<?>
future
:
futures
)
{
try
{
future
.
get
();
// 等待单个任务完成,抛出异常则终止
}
catch
(
ExecutionException
e
)
{
throw
new
RuntimeException
(
"并行计算支配关系失败"
,
e
.
getCause
());
}
}
}
}
});
executor
.
shutdown
();
}
catch
(
InterruptedException
e
)
{
Thread
.
currentThread
().
interrupt
();
throw
new
RuntimeException
(
"并行计算支配关系中断"
,
e
);
}
finally
{
if
(!
executor
.
isShutdown
())
{
executor
.
shutdownNow
();
// 确保线程池关闭
}
}
// 生成前沿
// 生成前沿
// 染色体 -> 数组下标的映射表
// 染色体 -> 数组下标的映射表
...
@@ -124,6 +165,7 @@ public class NSGAIIUtils {
...
@@ -124,6 +165,7 @@ public class NSGAIIUtils {
// 新增:支配矩阵数组化 - 每个p的下标,对应一个存储q下标的List
// 新增:支配矩阵数组化 - 每个p的下标,对应一个存储q下标的List
List
<
List
<
Integer
>>
dominanceMatrixArr
=
new
ArrayList
<>(
popSize
);
List
<
List
<
Integer
>>
dominanceMatrixArr
=
new
ArrayList
<>(
popSize
);
// ======== 修复空指针的核心行:循环popSize次,给每个索引塞一个空的ArrayList ========
// ======== 修复空指针的核心行:循环popSize次,给每个索引塞一个空的ArrayList ========
//初始化每个位置的空列表
for
(
int
idx
=
0
;
idx
<
popSize
;
idx
++)
{
for
(
int
idx
=
0
;
idx
<
popSize
;
idx
++)
{
dominanceMatrixArr
.
add
(
new
ArrayList
<>());
// 必须加这行,初始化每个位置的空列表
dominanceMatrixArr
.
add
(
new
ArrayList
<>());
// 必须加这行,初始化每个位置的空列表
Chromosome
c
=
population
.
get
(
idx
);
Chromosome
c
=
population
.
get
(
idx
);
...
@@ -133,16 +175,28 @@ public class NSGAIIUtils {
...
@@ -133,16 +175,28 @@ public class NSGAIIUtils {
for
(
int
idx
=
0
;
idx
<
popSize
;
idx
++)
{
for
(
int
idx
=
0
;
idx
<
popSize
;
idx
++)
{
Chromosome
c
=
population
.
get
(
idx
);
Chromosome
c
=
population
.
get
(
idx
);
dominatedCounts
[
idx
]
=
dominatedCount
.
get
(
c
);
// dominatedCounts[idx] = dominatedCount.get(c);
// 把HashMap的支配列表,转成q的下标列表,存入数组
// // 把HashMap的支配列表,转成q的下标列表,存入数组
List
<
Chromosome
>
qList
=
dominanceMatrix
.
get
(
c
);
// List<Chromosome> qList = dominanceMatrix.get(c);
List
<
Integer
>
qIdxList
=
dominanceMatrixArr
.
get
(
idx
);
// 此时get(idx)绝对非空!
// List<Integer> qIdxList = dominanceMatrixArr.get(idx); // 此时get(idx)绝对非空!
for
(
Chromosome
q
:
qList
)
{
// for (Chromosome q : qList) {
// Integer qIdx = chromosomeIndexMap.get(q);
// if(qIdx != null){ // 额外兜底:防止q是null导致的空指针
// qIdxList.add(qIdx);
// }
// }
dominatedCounts
[
idx
]
=
dominatedCount
.
get
(
c
).
get
();
// 把ConcurrentHashMap的支配队列,转成q的下标列表,存入数组
ConcurrentLinkedQueue
<
Chromosome
>
qQueue
=
dominanceMatrix
.
get
(
c
);
List
<
Integer
>
qIdxList
=
dominanceMatrixArr
.
get
(
idx
);
for
(
Chromosome
q
:
qQueue
)
{
Integer
qIdx
=
chromosomeIndexMap
.
get
(
q
);
Integer
qIdx
=
chromosomeIndexMap
.
get
(
q
);
if
(
qIdx
!=
null
){
// 额外兜底:防止q是null导致的空指针
if
(
qIdx
!=
null
){
// 额外兜底:防止q是null导致的空指针
qIdxList
.
add
(
qIdx
);
qIdxList
.
add
(
qIdx
);
}
}
}
}
}
}
// ========== 初始化前沿列表,必须先添加F1(第一个前沿) ==========
// ========== 初始化前沿列表,必须先添加F1(第一个前沿) ==========
...
@@ -150,7 +204,9 @@ public class NSGAIIUtils {
...
@@ -150,7 +204,9 @@ public class NSGAIIUtils {
// 遍历种群,找到所有被支配数=0的个体 → 这就是F1,绝对不被任何个体支配的最优解
// 遍历种群,找到所有被支配数=0的个体 → 这就是F1,绝对不被任何个体支配的最优解
for
(
Chromosome
chromosome
:
population
)
{
for
(
Chromosome
chromosome
:
population
)
{
if
(
chromosome
==
null
)
continue
;
if
(
chromosome
==
null
)
continue
;
int
count
=
dominatedCount
.
getOrDefault
(
chromosome
,
0
);
// int count = dominatedCount.getOrDefault(chromosome, 0);
int
count
=
dominatedCount
.
getOrDefault
(
chromosome
,
new
AtomicInteger
(
0
)).
get
();
if
(
count
==
0
)
{
if
(
count
==
0
)
{
firstFront
.
add
(
chromosome
);
firstFront
.
add
(
chromosome
);
}
}
...
@@ -375,22 +431,22 @@ public class NSGAIIUtils {
...
@@ -375,22 +431,22 @@ public class NSGAIIUtils {
*/
*/
private
void
preprocessObjectives
(
List
<
Chromosome
>
population
)
{
private
void
preprocessObjectives
(
List
<
Chromosome
>
population
)
{
int
kpi
s
ize
=
population
.
get
(
0
).
getObjectives
().
length
;
int
kpi
S
ize
=
population
.
get
(
0
).
getObjectives
().
length
;
// 计算每个目标的最大/最小值
// 计算每个目标的最大/最小值
double
[]
minValues
=
new
double
[
kpi
s
ize
];
double
[]
minValues
=
new
double
[
kpi
S
ize
];
double
[]
maxValues
=
new
double
[
kpi
s
ize
];
double
[]
maxValues
=
new
double
[
kpi
S
ize
];
// for (int i = 0; i < kpisize; i++) {
// for (int i = 0; i < kpisize; i++) {
// final int idx = i;
// final int idx = i;
// minValues[i] = population.stream().mapToDouble(c -> c.getObjectives()[idx]).min().orElse(0);
// minValues[i] = population.stream().mapToDouble(c -> c.getObjectives()[idx]).min().orElse(0);
// maxValues[i] = population.stream().mapToDouble(c -> c.getObjectives()[idx]).max().orElse(0);
// maxValues[i] = population.stream().mapToDouble(c -> c.getObjectives()[idx]).max().orElse(0);
// }
// }
for
(
int
i
=
0
;
i
<
kpi
s
ize
;
i
++)
{
for
(
int
i
=
0
;
i
<
kpi
S
ize
;
i
++)
{
minValues
[
i
]
=
Double
.
MAX_VALUE
;
minValues
[
i
]
=
Double
.
MAX_VALUE
;
maxValues
[
i
]
=
Double
.
MIN_VALUE
;
maxValues
[
i
]
=
Double
.
MIN_VALUE
;
}
}
for
(
Chromosome
chromo
:
population
)
{
for
(
Chromosome
chromo
:
population
)
{
double
[]
obj
=
chromo
.
getObjectives
();
double
[]
obj
=
chromo
.
getObjectives
();
for
(
int
i
=
0
;
i
<
kpi
s
ize
;
i
++)
{
for
(
int
i
=
0
;
i
<
kpi
S
ize
;
i
++)
{
minValues
[
i
]
=
Math
.
min
(
minValues
[
i
],
obj
[
i
]);
minValues
[
i
]
=
Math
.
min
(
minValues
[
i
],
obj
[
i
]);
maxValues
[
i
]
=
Math
.
max
(
maxValues
[
i
],
obj
[
i
]);
maxValues
[
i
]
=
Math
.
max
(
maxValues
[
i
],
obj
[
i
]);
}
}
...
@@ -400,6 +456,7 @@ public class NSGAIIUtils {
...
@@ -400,6 +456,7 @@ public class NSGAIIUtils {
population
.
parallelStream
().
forEach
(
chromo
->
{
population
.
parallelStream
().
forEach
(
chromo
->
{
double
[]
normalized
=
objectiveWeights
.
normalizeObjectives
(
chromo
.
getObjectives
(),
minValues
,
maxValues
,
this
.
isMinimize
);
double
[]
normalized
=
objectiveWeights
.
normalizeObjectives
(
chromo
.
getObjectives
(),
minValues
,
maxValues
,
this
.
isMinimize
);
chromo
.
setMaxObjectives
(
maxValues
);
chromo
.
setMaxObjectives
(
maxValues
);
chromo
.
setMinObjectives
(
minValues
);
chromo
.
setMinObjectives
(
minValues
);
chromo
.
setWeightedObjectives
(
normalized
);
chromo
.
setWeightedObjectives
(
normalized
);
...
@@ -434,6 +491,11 @@ public class NSGAIIUtils {
...
@@ -434,6 +491,11 @@ public class NSGAIIUtils {
// 纯NSGA-II模式:标准帕累托支配
// 纯NSGA-II模式:标准帕累托支配
double
[]
pObjectives
=
p
.
getWeightedObjectives
();
double
[]
pObjectives
=
p
.
getWeightedObjectives
();
double
[]
qObjectives
=
q
.
getWeightedObjectives
();
double
[]
qObjectives
=
q
.
getWeightedObjectives
();
// 如果启用了目标层级,则使用层级排序
// if (globalParam != null && globalParam.getObjectiveLevels() != null) {
// return dominatesWithLevels(p, q, pObjectives, qObjectives);
// }
if
(
objectiveWeights
.
isPureNSGAIIMode
())
{
if
(
objectiveWeights
.
isPureNSGAIIMode
())
{
boolean
hasBetter
=
false
;
// 是否至少有一个目标更优
boolean
hasBetter
=
false
;
// 是否至少有一个目标更优
boolean
hasWorse
=
false
;
// 是否有任何一个目标更差
boolean
hasWorse
=
false
;
// 是否有任何一个目标更差
...
@@ -478,6 +540,74 @@ public class NSGAIIUtils {
...
@@ -478,6 +540,74 @@ public class NSGAIIUtils {
return
hasBetterScore
&&
hasAtLeastOneNotWorse
;
return
hasBetterScore
&&
hasAtLeastOneNotWorse
;
}
}
}
}
/**
* 基于目标层级的支配关系判断
*/
private
boolean
dominatesWithLevels
(
Chromosome
p
,
Chromosome
q
,
double
[]
pObjectives
,
double
[]
qObjectives
)
{
// 获取启用的目标及其层级
Map
<
String
,
Integer
>
objectiveLevels
=
globalParam
.
getObjectiveLevels
();
List
<
String
>
objectiveOrder
=
globalParam
.
getObjectiveOrder
();
List
<
String
>
enabledObjectives
=
new
ArrayList
<>();
Map
<
String
,
Integer
>
levelMap
=
new
HashMap
<>();
// 构建启用的目标列表和层级映射
int
objIndex
=
0
;
for
(
String
objectiveName
:
objectiveOrder
)
{
if
(
globalParam
.
getObjectiveEnabled
().
getOrDefault
(
objectiveName
,
true
))
{
enabledObjectives
.
add
(
objectiveName
);
levelMap
.
put
(
objectiveName
,
objectiveLevels
.
getOrDefault
(
objectiveName
,
1
));
objIndex
++;
}
}
// 按层级从低到高排序,层级越低优先级越高
List
<
Integer
>
sortedLevels
=
new
ArrayList
<>(
new
HashSet
<>(
levelMap
.
values
()));
sortedLevels
.
sort
(
Comparator
.
naturalOrder
());
// 遍历每个层级
for
(
int
level
:
sortedLevels
)
{
// 获取当前层级的所有目标名称
List
<
String
>
levelObjectives
=
new
ArrayList
<>();
for
(
Map
.
Entry
<
String
,
Integer
>
entry
:
levelMap
.
entrySet
())
{
if
(
entry
.
getValue
()
==
level
)
{
levelObjectives
.
add
(
entry
.
getKey
());
}
}
// 比较当前层级的目标值
boolean
hasBetter
=
false
;
boolean
hasWorse
=
false
;
for
(
String
objectiveName
:
levelObjectives
)
{
int
objIdx
=
enabledObjectives
.
indexOf
(
objectiveName
);
if
(
objIdx
<
0
||
objIdx
>=
pObjectives
.
length
||
objIdx
>=
qObjectives
.
length
)
{
continue
;
}
double
thisObj
=
pObjectives
[
objIdx
];
double
otherObj
=
qObjectives
[
objIdx
];
// 目标越大越好:当前解 > 另一个解 → 更优
if
(
thisObj
>
otherObj
)
{
hasBetter
=
true
;
}
// 当前解 < 另一个解 → 更差
else
if
(
thisObj
<
otherObj
)
{
hasWorse
=
true
;
}
}
// 如果当前层级有差异,则根据差异判断支配关系
if
(
hasBetter
&&
!
hasWorse
)
{
return
true
;
}
else
if
(
hasWorse
)
{
return
false
;
}
// 如果当前层级无差异,则继续比较下一层级
}
// 所有层级都无差异,不支配
return
false
;
}
/**
/**
* 并行计算拥挤距离
* 并行计算拥挤距离
...
@@ -547,6 +677,16 @@ public class NSGAIIUtils {
...
@@ -547,6 +677,16 @@ public class NSGAIIUtils {
}
}
return
Math
.
sqrt
(
sum
);
// 开平方得到欧氏距离
return
Math
.
sqrt
(
sum
);
// 开平方得到欧氏距离
}
}
// 考虑使用标准化欧氏距离
private
double
calculateNormalizedEuclideanDistance
(
double
[]
objectives
,
double
[]
idealPoint
,
double
[]
maxValues
,
double
[]
minValues
)
{
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
objectives
.
length
;
i
++)
{
double
range
=
maxValues
[
i
]
-
minValues
[
i
];
double
normalizedDiff
=
range
>
0
?
(
objectives
[
i
]
-
idealPoint
[
i
])
/
range
:
0
;
sum
+=
normalizedDiff
*
normalizedDiff
;
}
return
Math
.
sqrt
(
sum
);
}
/**
/**
* 选择下一代种群(兼容并行计算)
* 选择下一代种群(兼容并行计算)
...
@@ -576,11 +716,11 @@ public class NSGAIIUtils {
...
@@ -576,11 +716,11 @@ public class NSGAIIUtils {
public
void
Test
()
{
public
void
Test
()
{
ObjectiveWeights
weights
=
new
ObjectiveWeights
();
GlobalParam
globalParam1
=
new
GlobalParam
();
double
[]
weightvs
=
new
double
[]
{
0.5
,
0.5
};
weights
.
setWeights
(
weightvs
);
weights
.
setPureNSGAIIMode
(
false
);
globalParam1
.
setPureNSGAIIMode
(
false
);
init
(
weights
);
init
(
globalParam1
);
List
<
Chromosome
>
chromosomeList
=
new
ArrayList
<>();
List
<
Chromosome
>
chromosomeList
=
new
ArrayList
<>();
Chromosome
chromosome1
=
new
Chromosome
();
Chromosome
chromosome1
=
new
Chromosome
();
chromosome1
.
setID
(
"A"
);
chromosome1
.
setID
(
"A"
);
...
...
src/main/java/com/aps/service/plan/PlanResultService.java
View file @
f30098ce
...
@@ -208,13 +208,14 @@ public class PlanResultService {
...
@@ -208,13 +208,14 @@ public class PlanResultService {
.
map
(
Material:
:
getId
)
.
map
(
Material:
:
getId
)
.
distinct
()
.
distinct
()
.
collect
(
Collectors
.
toList
());
.
collect
(
Collectors
.
toList
());
globalParam
.
setPureNSGAIIMode
(
false
);
// 5. 执行调度算法
// 5. 执行调度算法
GeneticAlgorithm
scheduler
=
new
GeneticAlgorithm
(
globalParam
,
machines
,
orders
,
Materials1
,
materialIds
,
machineScheduler
,
entryRel
,
materialRequirementService
,
_sceneService
,
SceneId
);
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
GeneticAlgorithm
scheduler
=
new
GeneticAlgorithm
(
globalParam
,
machines
,
orders
,
Materials1
,
materialIds
,
machineScheduler
,
entryRel
,
materialRequirementService
,
_sceneService
,
SceneId
);
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
param
.
initAdaptiveParams
(
entrys
.
size
());
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
(
customWeights
,
false
);
scheduler
.
Init
();
// scheduler.Init(customWeights,false);
Chromosome
chromosome
=
scheduler
.
Run
(
param
,
entrys
);
Chromosome
chromosome
=
scheduler
.
Run
(
param
,
entrys
);
KpiCalculator
kpiCalculator
=
new
KpiCalculator
(
chromosome
);
KpiCalculator
kpiCalculator
=
new
KpiCalculator
(
chromosome
);
...
@@ -770,7 +771,8 @@ public class PlanResultService {
...
@@ -770,7 +771,8 @@ public class PlanResultService {
param
.
initAdaptiveParams
(
entrys
.
size
());
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
(
customWeights
,
false
);
// scheduler.Init(customWeights,false);
scheduler
.
Init
();
Chromosome
chromosomes
=
scheduler
.
Run
(
param
,
entrys
);
Chromosome
chromosomes
=
scheduler
.
Run
(
param
,
entrys
);
KpiCalculator
kpiCalculator
=
new
KpiCalculator
(
chromosomes
);
KpiCalculator
kpiCalculator
=
new
KpiCalculator
(
chromosomes
);
kpiCalculator
.
calculatekpi
();
kpiCalculator
.
calculatekpi
();
...
...
src/test/java/com/aps/demo/NSGAIIUtilsTest.java
0 → 100644
View file @
f30098ce
package
com
.
aps
.
demo
;
import
com.aps.service.Algorithm.NSGAIIUtils
;
import
org.junit.jupiter.api.Test
;
import
org.springframework.boot.test.context.SpringBootTest
;
/**
* 作者:佟礼
* 时间:2026-03-17
*/
@SpringBootTest
public
class
NSGAIIUtilsTest
{
private
NSGAIIUtils
_nsgaIIUtils
=
new
NSGAIIUtils
();
@Test
public
void
test
()
{
_nsgaIIUtils
.
Test
();
}
}
src/test/java/com/aps/demo/PlanResultServiceTest.java
View file @
f30098ce
...
@@ -39,7 +39,7 @@ public class PlanResultServiceTest {
...
@@ -39,7 +39,7 @@ public class PlanResultServiceTest {
// TestSortService sortService=new TestSortService();
// TestSortService sortService=new TestSortService();
// sortService.test1();
// sortService.test1();
// nsgaiiUtils.Test();
// nsgaiiUtils.Test();
planResultService
.
execute2
(
"
5475E00B844847ACB6DC20227967BA2F
"
);
planResultService
.
execute2
(
"
EFDD34E4B5BC434BAEAE6A84DFCD4E7B
"
);
// planResultService.execute2("00E0C5D3E4AD4F36B56C39395906618D");
// planResultService.execute2("00E0C5D3E4AD4F36B56C39395906618D");
// planResultService.execute2("92BB773E1E2447C99D8176C991D5C9D2");
// planResultService.execute2("92BB773E1E2447C99D8176C991D5C9D2");
...
...
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