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
f864f507
Commit
f864f507
authored
Apr 16, 2026
by
Tong Li
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
优化
parent
6ba23982
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
85 additions
and
75 deletions
+85
-75
HybridAlgorithm.java
src/main/java/com/aps/service/Algorithm/HybridAlgorithm.java
+1
-1
VariableNeighborhoodSearch.java
...com/aps/service/Algorithm/VariableNeighborhoodSearch.java
+83
-73
PlanResultServiceTest.java
src/test/java/com/aps/demo/PlanResultServiceTest.java
+1
-1
No files found.
src/main/java/com/aps/service/Algorithm/HybridAlgorithm.java
View file @
f864f507
...
...
@@ -304,7 +304,7 @@ int opcount=allOperations.size();
best
.
setScenarioID
(
sceneId
);
// best.setOperatRel(_entryRel);
if
(
best
.
getInitMachines
()==
null
)
if
(
best
.
getInitMachines
()==
null
||
best
.
getInitMachines
().
size
()==
0
)
{
best
.
setInitMachines
(
ProductionDeepCopyUtil
.
deepCopyList
(
machines
,
Machine
.
class
));
}
...
...
src/main/java/com/aps/service/Algorithm/VariableNeighborhoodSearch.java
View file @
f864f507
...
...
@@ -19,36 +19,47 @@ import java.util.stream.Collectors;
public
class
VariableNeighborhoodSearch
{
private
final
Random
rnd
=
new
Random
();
// ==================== 常量定义 ====================
private
static
final
int
MAX_CONSECUTIVE_SAME_STRATEGY
=
3
;
private
static
final
int
MAX_NEIGHBORHOODS
=
4
;
// 优化:从7减少到4个邻域
private
static
final
double
HIGH_PRIORITY_GROUP_PROBABILITY
=
0.7
;
private
static
final
int
MAX_ATTEMPTS
=
50
;
private
static
final
int
NEIGHBOR_SELECTION_TOP_K
=
3
;
private
static
final
int
MOVE_STEPS_MIN
=
1
;
private
static
final
int
MOVE_STEPS_MAX
=
5
;
private
static
final
int
NON_BOTTLENECK_MOVE_STEPS_MAX
=
3
;
private
static
final
int
RANDOM_NEIGHBOR_TYPE_COUNT
=
5
;
private
static
final
double
INITIAL_SUCCESS_RATE
=
0.3
;
private
static
final
double
LOW_SUCCESS_RATE_THRESHOLD
=
0.1
;
private
static
final
int
LOW_SUCCESS_RATE_MIN_TRIALS
=
10
;
private
static
final
double
EXPLORATION_BONUS_FOR_LOW_USE
=
0.3
;
private
static
final
double
EXPLORATION_BONUS_FOR_LOW_SUCCESS
=
0.2
;
private
static
final
double
RANDOM_NOISE_FACTOR
=
0.15
;
private
static
final
double
FORCE_ROTATE_PENALTY
=
0.5
;
private
static
final
double
PERCENTILE_90
=
0.90
;
private
static
final
double
BOTTLENECK_MACHINE_BASE_SCORE
=
10000
;
private
static
final
double
WAIT_TIME_WEIGHT
=
30
;
private
static
final
double
MACHINE_WAIT_TIME_WEIGHT
=
30
;
private
static
final
double
CRITICAL_PATH_WEIGHT_ON_BOTTLENECK
=
25
;
private
static
final
double
CRITICAL_PATH_WEIGHT_OFF_BOTTLENECK
=
20
;
private
static
final
double
DELAY_CONTRIBUTION_WEIGHT_ON_BOTTLENECK
=
15
;
private
static
final
double
DELAY_CONTRIBUTION_WEIGHT_OFF_BOTTLENECK
=
10
;
private
static
final
double
NORMALIZATION_CAP
=
1.5
;
private
static
final
int
TOP_BOTTLENECK_OPS_TO_RETURN
=
10
;
private
static
final
int
TOP_MACHINES_TO_LOG
=
5
;
private
static
final
double
PRIORITY_EPSILON
=
0.001
;
private
static
final
int
MIN_USE_COUNT_FOR_EXPLORATION_BONUS
=
5
;
// ==================== 策略选择与轮换参数 ====================
private
static
final
int
MAX_CONSECUTIVE_SAME_STRATEGY
=
4
;
// 同一策略最多连续使用次数,避免陷入局部最优
private
static
final
int
MAX_NEIGHBORHOODS
=
4
;
// 使用的邻域数量(0-3:插单/交换/并行合并/重排)
// ==================== 邻域搜索参数 ====================
private
static
final
double
HIGH_PRIORITY_GROUP_PROBABILITY
=
0.7
;
// 优先选择高优先级工单的概率
private
static
final
int
MAX_ATTEMPTS
=
30
;
// 每次邻域搜索最大尝试次数,减少无效搜索
private
static
final
int
NEIGHBOR_SELECTION_TOP_K
=
3
;
// 每次选择K个候选工序进行操作
// ==================== 工序移动参数 ====================
private
static
final
int
MOVE_STEPS_MIN
=
1
;
// 工序移动最小步数
private
static
final
int
MOVE_STEPS_MAX
=
5
;
// 工序移动最大步数
private
static
final
int
NON_BOTTLENECK_MOVE_STEPS_MAX
=
3
;
// 非瓶颈设备工序移动最大步数
// ==================== 随机邻域参数 ====================
private
static
final
int
RANDOM_NEIGHBOR_TYPE_COUNT
=
3
;
// 随机邻域尝试次数
// ==================== 策略成功率评分参数 ====================
private
static
final
double
INITIAL_SUCCESS_RATE
=
0.3
;
// 新策略的初始成功率(未使用时的默认值)
private
static
final
double
LOW_SUCCESS_RATE_THRESHOLD
=
0.1
;
// 低成功率阈值,低于此值需要额外探索奖励
private
static
final
int
LOW_SUCCESS_RATE_MIN_TRIALS
=
10
;
// 低成功率判断的最小尝试次数
private
static
final
double
EXPLORATION_BONUS_FOR_LOW_USE
=
0.15
;
// 低使用次数策略的探索奖励分
private
static
final
double
EXPLORATION_BONUS_FOR_LOW_SUCCESS
=
0.1
;
// 低成功率策略的探索奖励分
private
static
final
double
RANDOM_NOISE_FACTOR
=
0.1
;
// 策略排序时的随机扰动因子,避免陷入局部最优
private
static
final
double
FORCE_ROTATE_PENALTY
=
0.5
;
// 强制轮换时的惩罚系数
// ==================== 瓶颈设备评分参数 ====================
private
static
final
double
PERCENTILE_90
=
0.90
;
// 计算瓶颈评分时使用的90分位数,避免极端值影响
private
static
final
double
BOTTLENECK_MACHINE_BASE_SCORE
=
10000
;
// 瓶颈设备工序的基础评分,确保排在前面
private
static
final
double
WAIT_TIME_WEIGHT
=
30
;
// 工序等待时间在瓶颈评分中的权重
private
static
final
double
MACHINE_WAIT_TIME_WEIGHT
=
30
;
// 设备等待时间在瓶颈评分中的权重
private
static
final
double
CRITICAL_PATH_WEIGHT_ON_BOTTLENECK
=
25
;
// 关键路径在瓶颈设备评分中的权重
private
static
final
double
CRITICAL_PATH_WEIGHT_OFF_BOTTLENECK
=
20
;
// 关键路径在非瓶颈设备评分中的权重
private
static
final
double
DELAY_CONTRIBUTION_WEIGHT_ON_BOTTLENECK
=
15
;
// 延迟贡献度在瓶颈设备评分中的权重
private
static
final
double
DELAY_CONTRIBUTION_WEIGHT_OFF_BOTTLENECK
=
10
;
// 延迟贡献度在非瓶颈设备评分中的权重
private
static
final
double
NORMALIZATION_CAP
=
1.5
;
// 归一化截断值,避免极端值过度影响
// ==================== 日志与输出参数 ====================
private
static
final
int
TOP_BOTTLENECK_OPS_TO_RETURN
=
10
;
// 返回的瓶颈工序数量
private
static
final
int
TOP_MACHINES_TO_LOG
=
5
;
// 日志输出的设备数量
private
static
final
int
MIN_USE_COUNT_FOR_EXPLORATION_BONUS
=
5
;
// 低使用次数判断的最小阈值
// 日志级别
private
static
final
int
LOG_LEVEL_DEBUG
=
0
;
...
...
@@ -729,9 +740,9 @@ public class VariableNeighborhoodSearch {
if
(
allResults
!=
null
&&
!
allResults
.
isEmpty
())
{
List
<
BottleneckOperationAnalysis
>
bottleneckAnalyses
=
analyzeBottleneckOperations
(
allResults
,
bottleneckMachineId
);
// 输出瓶颈工序TOP
5
log
(
"变邻域搜索 - ===== 瓶颈工序TOP 5 (按瓶颈评分) ====="
);
for
(
int
i
=
0
;
i
<
Math
.
min
(
5
,
bottleneckAnalyses
.
size
());
i
++)
{
// 输出瓶颈工序TOP
log
(
String
.
format
(
"变邻域搜索 - ===== 瓶颈工序TOP %d (按瓶颈评分) ====="
,
TOP_MACHINES_TO_LOG
)
);
for
(
int
i
=
0
;
i
<
Math
.
min
(
TOP_MACHINES_TO_LOG
,
bottleneckAnalyses
.
size
());
i
++)
{
BottleneckOperationAnalysis
boa
=
bottleneckAnalyses
.
get
(
i
);
GAScheduleResult
op
=
boa
.
operation
;
log
(
String
.
format
(
...
...
@@ -745,7 +756,7 @@ public class VariableNeighborhoodSearch {
// 更新关键工序为识别出的瓶颈工序
if
(
criticalOps
!=
null
&&
!
criticalOps
.
isEmpty
()
&&
!
bottleneckAnalyses
.
isEmpty
())
{
List
<
GAScheduleResult
>
topBottlenecks
=
bottleneckAnalyses
.
stream
()
.
limit
(
Math
.
min
(
10
,
bottleneckAnalyses
.
size
()))
.
limit
(
Math
.
min
(
TOP_BOTTLENECK_OPS_TO_RETURN
,
bottleneckAnalyses
.
size
()))
.
map
(
boa
->
boa
.
operation
)
.
collect
(
Collectors
.
toList
());
analysis
.
put
(
"criticalOps"
,
topBottlenecks
);
...
...
@@ -869,8 +880,8 @@ public class VariableNeighborhoodSearch {
Collections
.
sort
(
machineWaitTimes
);
// 使用90分位数代替最大值,避免极端值影响
double
p90WaitTime
=
Math
.
max
(
1
,
getPercentile
(
waitTimes
,
0.
90
));
// 防止0导致NaN
double
p90MachineWaitTime
=
Math
.
max
(
1
,
getPercentile
(
machineWaitTimes
,
0.
90
));
// 防止0导致NaN
double
p90WaitTime
=
Math
.
max
(
1
,
getPercentile
(
waitTimes
,
PERCENTILE_
90
));
// 防止0导致NaN
double
p90MachineWaitTime
=
Math
.
max
(
1
,
getPercentile
(
machineWaitTimes
,
PERCENTILE_
90
));
// 防止0导致NaN
// 优先找出瓶颈设备上的工序
List
<
BottleneckOperationAnalysis
>
bottleneckMachineOps
=
new
ArrayList
<>();
...
...
@@ -892,42 +903,42 @@ public class VariableNeighborhoodSearch {
if
(
isOnBottleneckMachine
)
{
// 瓶颈设备上的工序:基础分极高,确保排在最前面
score
+=
10000
;
// 提高到10000,
绝对保证排在前面
score
+=
BOTTLENECK_MACHINE_BASE_SCORE
;
//
绝对保证排在前面
// 在瓶颈设备工序内部进行排序(使用截断值)
// 工序等待时间
(权重 30%)
double
normalizedWaitTime
=
Math
.
min
(
boa
.
waitTime
/
p90WaitTime
,
1.5
);
score
+=
normalizedWaitTime
*
30
;
// 工序等待时间
double
normalizedWaitTime
=
Math
.
min
(
boa
.
waitTime
/
p90WaitTime
,
NORMALIZATION_CAP
);
score
+=
normalizedWaitTime
*
WAIT_TIME_WEIGHT
;
// 设备等待时间
(权重 30%)
double
normalizedMachineWaitTime
=
Math
.
min
(
boa
.
machineWaitTime
/
p90MachineWaitTime
,
1.5
);
score
+=
normalizedMachineWaitTime
*
30
;
// 设备等待时间
double
normalizedMachineWaitTime
=
Math
.
min
(
boa
.
machineWaitTime
/
p90MachineWaitTime
,
NORMALIZATION_CAP
);
score
+=
normalizedMachineWaitTime
*
MACHINE_WAIT_TIME_WEIGHT
;
// 关键路径评分
(权重 25%)
// 关键路径评分
if
(
boa
.
onCriticalPath
)
{
score
+=
25
;
score
+=
CRITICAL_PATH_WEIGHT_ON_BOTTLENECK
;
}
// 延迟贡献度评分
(权重 15%)
score
+=
boa
.
delayContribution
*
15
;
// 延迟贡献度评分
score
+=
boa
.
delayContribution
*
DELAY_CONTRIBUTION_WEIGHT_ON_BOTTLENECK
;
}
else
{
// 非瓶颈设备上的工序:基础分低
score
+=
0
;
// 使用截断值,避免极端值影响
double
normalizedMachineWaitTime
=
Math
.
min
(
boa
.
machineWaitTime
/
p90MachineWaitTime
,
1.5
);
score
+=
normalizedMachineWaitTime
*
30
;
double
normalizedMachineWaitTime
=
Math
.
min
(
boa
.
machineWaitTime
/
p90MachineWaitTime
,
NORMALIZATION_CAP
);
score
+=
normalizedMachineWaitTime
*
MACHINE_WAIT_TIME_WEIGHT
;
double
normalizedWaitTime
=
Math
.
min
(
boa
.
waitTime
/
p90WaitTime
,
1.5
);
score
+=
normalizedWaitTime
*
20
;
double
normalizedWaitTime
=
Math
.
min
(
boa
.
waitTime
/
p90WaitTime
,
NORMALIZATION_CAP
);
score
+=
normalizedWaitTime
*
WAIT_TIME_WEIGHT
;
// 关键路径评分
(权重 20%)
// 关键路径评分
if
(
boa
.
onCriticalPath
)
{
score
+=
20
;
score
+=
CRITICAL_PATH_WEIGHT_OFF_BOTTLENECK
;
}
// 延迟贡献度评分
(权重 10%)
score
+=
boa
.
delayContribution
*
10
;
// 延迟贡献度评分
score
+=
boa
.
delayContribution
*
DELAY_CONTRIBUTION_WEIGHT_OFF_BOTTLENECK
;
}
boa
.
bottleneckScore
=
score
;
...
...
@@ -937,12 +948,12 @@ public class VariableNeighborhoodSearch {
log
(
String
.
format
(
"变邻域搜索 - 瓶颈设备ID=%d, 其上工序数=%d"
,
bottleneckMachineId
,
bottleneckMachineOps
.
size
()));
// 输出各设备工序数量统计
(前5个)
// 输出各设备工序数量统计
List
<
Map
.
Entry
<
Long
,
Long
>>
topMachinesByCount
=
machineOpCount
.
entrySet
().
stream
()
.
sorted
((
a
,
b
)
->
Long
.
compare
(
b
.
getValue
(),
a
.
getValue
()))
.
limit
(
5
)
.
limit
(
TOP_MACHINES_TO_LOG
)
.
collect
(
Collectors
.
toList
());
StringBuilder
machineCountStr
=
new
StringBuilder
(
"变邻域搜索 - 设备工序数(前5): "
);
StringBuilder
machineCountStr
=
new
StringBuilder
(
String
.
format
(
"变邻域搜索 - 设备工序数(前%d): "
,
TOP_MACHINES_TO_LOG
)
);
for
(
Map
.
Entry
<
Long
,
Long
>
entry
:
topMachinesByCount
)
{
machineCountStr
.
append
(
String
.
format
(
"[%d:%d] "
,
entry
.
getKey
(),
entry
.
getValue
()));
}
...
...
@@ -983,37 +994,37 @@ public class VariableNeighborhoodSearch {
// 按成功率排序,但加入随机扰动和探索机制
strategies
.
sort
((
a
,
b
)
->
{
double
successRateA
=
strategyTotalCount
[
a
]
>
0
?
(
double
)
strategySuccessCount
[
a
]
/
strategyTotalCount
[
a
]
:
0.3
;
(
double
)
strategySuccessCount
[
a
]
/
strategyTotalCount
[
a
]
:
INITIAL_SUCCESS_RATE
;
double
successRateB
=
strategyTotalCount
[
b
]
>
0
?
(
double
)
strategySuccessCount
[
b
]
/
strategyTotalCount
[
b
]
:
0.3
;
(
double
)
strategySuccessCount
[
b
]
/
strategyTotalCount
[
b
]
:
INITIAL_SUCCESS_RATE
;
// 强制轮换:给最后使用的策略降权
if
(
needForceRotate
&&
a
==
lastUsedStrategy
)
{
successRateA
-=
0.5
;
// 大幅降权
successRateA
-=
FORCE_ROTATE_PENALTY
;
// 大幅降权
}
if
(
needForceRotate
&&
b
==
lastUsedStrategy
)
{
successRateB
-=
0.5
;
successRateB
-=
FORCE_ROTATE_PENALTY
;
}
// 给使用次数少的策略加分,鼓励探索
if
(
strategyTotalCount
[
a
]
<
5
)
{
successRateA
+=
0.3
;
if
(
strategyTotalCount
[
a
]
<
MIN_USE_COUNT_FOR_EXPLORATION_BONUS
)
{
successRateA
+=
EXPLORATION_BONUS_FOR_LOW_USE
;
}
if
(
strategyTotalCount
[
b
]
<
5
)
{
successRateB
+=
0.3
;
if
(
strategyTotalCount
[
b
]
<
MIN_USE_COUNT_FOR_EXPLORATION_BONUS
)
{
successRateB
+=
EXPLORATION_BONUS_FOR_LOW_USE
;
}
// 如果策略被尝试次数很多但成功率很低,给它额外加分鼓励探索
if
(
strategyTotalCount
[
a
]
>
10
&&
successRateA
<
0.1
)
{
successRateA
+=
0.2
;
if
(
strategyTotalCount
[
a
]
>
LOW_SUCCESS_RATE_MIN_TRIALS
&&
successRateA
<
LOW_SUCCESS_RATE_THRESHOLD
)
{
successRateA
+=
EXPLORATION_BONUS_FOR_LOW_SUCCESS
;
}
if
(
strategyTotalCount
[
b
]
>
10
&&
successRateB
<
0.1
)
{
successRateB
+=
0.2
;
if
(
strategyTotalCount
[
b
]
>
LOW_SUCCESS_RATE_MIN_TRIALS
&&
successRateB
<
LOW_SUCCESS_RATE_THRESHOLD
)
{
successRateB
+=
EXPLORATION_BONUS_FOR_LOW_SUCCESS
;
}
// 加入少量随机扰动,避免陷入局部最优
successRateA
+=
rnd
.
nextDouble
()
*
0.15
;
successRateB
+=
rnd
.
nextDouble
()
*
0.15
;
successRateA
+=
rnd
.
nextDouble
()
*
RANDOM_NOISE_FACTOR
;
successRateB
+=
rnd
.
nextDouble
()
*
RANDOM_NOISE_FACTOR
;
return
Double
.
compare
(
successRateB
,
successRateA
);
});
...
...
@@ -2040,7 +2051,6 @@ public class VariableNeighborhoodSearch {
}
else
{
chromosome
.
setResultOld
(
new
CopyOnWriteArrayList
<>());
}
//decoder.decodeChromosomeWithCache(chromosome,true);
});
log
(
String
.
format
(
"变邻域搜索 -复制对象E"
));
...
...
src/test/java/com/aps/demo/PlanResultServiceTest.java
View file @
f864f507
...
...
@@ -40,7 +40,7 @@ public class PlanResultServiceTest {
// sortService.test1();
// nsgaiiUtils.Test();
planResultService
.
execute2
(
"
F6747C64865D4609989D943709939331
"
);
//2000
planResultService
.
execute2
(
"
E29F2B3ADA8149F6B916B5119296A92B
"
);
//2000
// planResultService.execute2("08B1D87FE1B84ECDBAC2E546DDB6FB81");//2000
// planResultService.execute2("0428340BB4F540938F1FB5599F03E8A4");//5000
...
...
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