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
e45bc27d
Commit
e45bc27d
authored
Nov 26, 2025
by
DESKTOP-VKRD9QF\Administration
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master'
parents
acfb5bcd
a15bc091
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
2561 additions
and
1829078 deletions
+2561
-1829078
pom.xml
pom.xml
+1
-0
schedule_log.txt
schedule_log.txt
+1055
-1829018
ResourceGanttController.java
...ava/com/aps/controller/gantt/ResourceGanttController.java
+11
-0
Chromosome.java
src/main/java/com/aps/entity/Algorithm/Chromosome.java
+28
-2
GAScheduleResult.java
src/main/java/com/aps/entity/Algorithm/GAScheduleResult.java
+6
-1
OpMachine.java
src/main/java/com/aps/entity/Algorithm/OpMachine.java
+29
-0
Pair.java
src/main/java/com/aps/entity/Algorithm/Pair.java
+23
-0
ScheduleParams.java
src/main/java/com/aps/entity/Algorithm/ScheduleParams.java
+3
-5
MachineOption.java
src/main/java/com/aps/entity/basic/MachineOption.java
+1
-1
Order.java
src/main/java/com/aps/entity/basic/Order.java
+2
-0
AdaptiveGaParams.java
...main/java/com/aps/service/Algorithm/AdaptiveGaParams.java
+149
-0
FitnessCalculator.java
...ain/java/com/aps/service/Algorithm/FitnessCalculator.java
+31
-0
GeneticAlgorithm.java
...main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
+149
-2
GeneticDecoder.java
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
+376
-0
GeneticOperations.java
...ain/java/com/aps/service/Algorithm/GeneticOperations.java
+243
-0
Initialization.java
src/main/java/com/aps/service/Algorithm/Initialization.java
+32
-21
MachineCalculator.java
...ain/java/com/aps/service/Algorithm/MachineCalculator.java
+301
-0
PlanResultService.java
src/main/java/com/aps/service/plan/PlanResultService.java
+107
-16
application.yml
src/main/resources/application.yml
+12
-12
machines.json
src/main/resources/machines.json
+2
-0
No files found.
pom.xml
View file @
e45bc27d
...
@@ -91,6 +91,7 @@
...
@@ -91,6 +91,7 @@
<artifactId>
spring-boot-starter-test
</artifactId>
<artifactId>
spring-boot-starter-test
</artifactId>
<scope>
test
</scope>
<scope>
test
</scope>
</dependency>
</dependency>
</dependencies>
</dependencies>
<build>
<build>
...
...
schedule_log.txt
View file @
e45bc27d
This diff is collapsed.
Click to expand it.
src/main/java/com/aps/controller/gantt/ResourceGanttController.java
View file @
e45bc27d
package
com
.
aps
.
controller
.
gantt
;
package
com
.
aps
.
controller
.
gantt
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.basic.ScheduleChromosome
;
import
com.aps.entity.basic.ScheduleChromosome
;
import
com.aps.entity.Gantt.ProductGanttVO
;
import
com.aps.entity.Gantt.ProductGanttVO
;
import
com.aps.entity.Gantt.ResourceGanttVO
;
import
com.aps.entity.Gantt.ResourceGanttVO
;
...
@@ -103,6 +104,16 @@ public class ResourceGanttController {
...
@@ -103,6 +104,16 @@ public class ResourceGanttController {
.
collect
(
Collectors
.
toList
());
.
collect
(
Collectors
.
toList
());
}
}
@GetMapping
(
"/getScene"
)
@Operation
(
summary
=
"获取所有场景ID"
,
description
=
"获取所有场景ID"
)
public
List
<
Chromosome
>
getScene
()
{
// 调用 PlanResultService 获取 ScheduleChromosome 列表
List
<
Chromosome
>
scheduleChromosomes
=
planResultService
.
execute1
();
// 提取所有场景ID
return
scheduleChromosomes
;
}
/**
/**
* 将 ScheduleChromosome 转换为 ResourceGanttVO 列表
* 将 ScheduleChromosome 转换为 ResourceGanttVO 列表
* @param scheduleChromosome 调度结果
* @param scheduleChromosome 调度结果
...
...
src/main/java/com/aps/entity/Algorithm/Chromosome.java
View file @
e45bc27d
package
com
.
aps
.
entity
.
Algorithm
;
package
com
.
aps
.
entity
.
Algorithm
;
import
com.aps.entity.Algorithm.ScheduleResult
;
import
com.aps.entity.basic.Machine
;
import
com.aps.entity.basic.Machine
;
import
lombok.Data
;
import
lombok.Data
;
import
java.util.List
;
import
java.util.List
;
import
java.util.UUID
;
import
java.util.stream.Collectors
;
/**
/**
* 作者:佟礼
* 作者:佟礼
...
@@ -12,16 +13,41 @@ import java.util.List;
...
@@ -12,16 +13,41 @@ import java.util.List;
*/
*/
@Data
@Data
public
class
Chromosome
{
public
class
Chromosome
{
private
String
ID
=
UUID
.
randomUUID
().
toString
();
/// <summary>
/// <summary>
/// 机器选择部分(可选机器集中的顺序号)
/// 机器选择部分(可选机器集中的顺序号)
/// </summary>
/// </summary>
private
List
<
Integer
>
MachineSelection
;
private
List
<
Integer
>
MachineSelection
;
/// <summary>
/// 工序排序部分(工件/订单ID)
/// </summary>
private
String
MachineStr
;
public
String
getMachineStr
()
{
return
MachineSelection
.
stream
()
.
map
(
String:
:
valueOf
)
// 将每个 Integer 转换为 String
.
collect
(
Collectors
.
joining
(
","
));
};
/// <summary>
/// <summary>
/// 工序排序部分(工件/订单ID)
/// 工序排序部分(工件/订单ID)
/// </summary>
/// </summary>
private
List
<
Integer
>
OperationSequencing
;
private
List
<
Integer
>
OperationSequencing
;
/// <summary>
/// 工序排序部分(工件/订单ID)
/// </summary>
private
String
OperationStr
;
public
String
getOperationStr
()
{
return
OperationSequencing
.
stream
()
.
map
(
String:
:
valueOf
)
// 将每个 Integer 转换为 String
.
collect
(
Collectors
.
joining
(
"|"
));
};
/// <summary>
/// <summary>
/// 适应度值
/// 适应度值
/// </summary>
/// </summary>
...
@@ -35,7 +61,7 @@ public class Chromosome {
...
@@ -35,7 +61,7 @@ public class Chromosome {
/// <summary>
/// <summary>
/// 解码后的调度结果
/// 解码后的调度结果
/// </summary>
/// </summary>
private
List
<
ScheduleResult
>
Result
;
private
List
<
GA
ScheduleResult
>
Result
;
/// <summary>
/// <summary>
/// 最早完工时间
/// 最早完工时间
...
...
src/main/java/com/aps/entity/Algorithm/ScheduleResult.java
→
src/main/java/com/aps/entity/Algorithm/
GA
ScheduleResult.java
View file @
e45bc27d
...
@@ -9,7 +9,7 @@ import java.util.List;
...
@@ -9,7 +9,7 @@ import java.util.List;
* 时间:2025-11-21
* 时间:2025-11-21
*/
*/
@Data
@Data
public
class
ScheduleResult
{
public
class
GA
ScheduleResult
{
private
int
GroupId
;
private
int
GroupId
;
private
int
ProductId
;
private
int
ProductId
;
private
int
OperationId
;
private
int
OperationId
;
...
@@ -21,4 +21,9 @@ public class ScheduleResult {
...
@@ -21,4 +21,9 @@ public class ScheduleResult {
private
int
OneTime
;
// 单件工时
private
int
OneTime
;
// 单件工时
private
int
ProcessingTime
;
// 绝对处理时间(分钟)
private
int
ProcessingTime
;
// 绝对处理时间(分钟)
private
int
ChangeoverTime
;
private
int
ChangeoverTime
;
public
int
getFlowTime
()
{
return
EndTime
-
StartTime
;
};
}
}
src/main/java/com/aps/entity/Algorithm/OpMachine.java
0 → 100644
View file @
e45bc27d
package
com
.
aps
.
entity
.
Algorithm
;
import
lombok.Data
;
/**
* 作者:佟礼
* 时间:2025-11-25
*/
@Data
public
class
OpMachine
{
/**
* 所属组ID
*/
private
int
GroupId
;
/**
* 订单内工序顺序号
*/
private
int
Sequence
;
/**
* 设备ID
*/
private
int
machineId
;
/**
* 单件工时
*/
private
int
processingTime
;
// 加工时间
}
src/main/java/com/aps/entity/Algorithm/Pair.java
0 → 100644
View file @
e45bc27d
package
com
.
aps
.
entity
.
Algorithm
;
/**
* 作者:佟礼
* 时间:2025-11-24
*/
public
class
Pair
<
A
,
B
>
{
private
final
A
first
;
private
final
B
second
;
public
Pair
(
A
first
,
B
second
)
{
this
.
first
=
first
;
this
.
second
=
second
;
}
public
A
getFirst
()
{
return
first
;
}
public
B
getSecond
()
{
return
second
;
}
}
src/main/java/com/aps/entity/Algorithm/ScheduleParams.java
View file @
e45bc27d
...
@@ -3,6 +3,7 @@ package com.aps.entity.Algorithm;
...
@@ -3,6 +3,7 @@ package com.aps.entity.Algorithm;
import
com.aps.entity.basic.Entry
;
import
com.aps.entity.basic.Entry
;
import
lombok.Data
;
import
lombok.Data
;
import
java.time.LocalDateTime
;
import
java.util.Date
;
import
java.util.Date
;
/**
/**
...
@@ -11,12 +12,9 @@ import java.util.Date;
...
@@ -11,12 +12,9 @@ import java.util.Date;
*/
*/
@Data
@Data
public
class
ScheduleParams
{
public
class
ScheduleParams
{
private
Date
BaseTime
=
new
Date
();
// 当前基准时间
private
LocalDateTime
BaseTime
;
// 当前基准时间
/// <summary>
/// 设备总数
/// </summary>
private
int
MachineCount
;
// 设备总数
/// <summary>
/// <summary>
/// 交叉概率
/// 交叉概率
...
...
src/main/java/com/aps/entity/basic/MachineOption.java
View file @
e45bc27d
...
@@ -8,7 +8,7 @@ import lombok.Data;
...
@@ -8,7 +8,7 @@ import lombok.Data;
@Data
@Data
public
class
MachineOption
{
public
class
MachineOption
{
private
int
machineId
;
private
int
machineId
;
private
int
processingTime
;
// 加工时间
private
int
processingTime
;
// 加工时间
(秒)
private
int
setupTime
;
// 换型时间(如果与前一个产品不同)
private
int
setupTime
;
// 换型时间(如果与前一个产品不同)
private
int
teardownTime
;
// 收尾时间(后处理时间)
private
int
teardownTime
;
// 收尾时间(后处理时间)
private
int
contantTime
;
// 常数时间
private
int
contantTime
;
// 常数时间
...
...
src/main/java/com/aps/entity/basic/Order.java
View file @
e45bc27d
...
@@ -13,6 +13,8 @@ public class Order {
...
@@ -13,6 +13,8 @@ public class Order {
private
int
id
;
private
int
id
;
private
int
productId
;
private
int
productId
;
private
int
quantity
=
100
;
// 100个
private
int
quantity
=
100
;
// 100个
private
int
sYQuantity
;
private
OffsetDateTime
dueDate
;
private
OffsetDateTime
dueDate
;
private
LocalDateTime
orderCompletion
;
private
LocalDateTime
orderCompletion
;
private
double
tardiness
;
private
double
tardiness
;
...
...
src/main/java/com/aps/service/Algorithm/AdaptiveGaParams.java
0 → 100644
View file @
e45bc27d
package
com
.
aps
.
service
.
Algorithm
;
import
lombok.Data
;
import
java.text.DecimalFormat
;
/**
* 作者:佟礼
* 时间:2025-11-26
*/
@Data
public
class
AdaptiveGaParams
{
// 基础参数(自适应调整的基准值)
private
static
final
int
MIN_POPULATION_SIZE
=
50
;
private
static
final
int
MAX_POPULATION_SIZE
=
500
;
private
static
final
int
MIN_MAX_ITERATIONS
=
50
;
private
static
final
int
MAX_MAX_ITERATIONS
=
200
;
private
static
final
float
MIN_CROSSOVER_PROB
=
0.6f
;
private
static
final
float
MAX_CROSSOVER_PROB
=
0.9f
;
private
static
final
float
MIN_MUTATION_PROB
=
0.05f
;
private
static
final
float
MAX_MUTATION_PROB
=
0.2f
;
private
static
final
int
MIN_TOURNAMENT_SIZE
=
3
;
private
static
final
int
MAX_TOURNAMENT_SIZE
=
7
;
private
static
final
int
MIN_LOW_PRIORITY_THRESHOLD
=
3
;
private
static
final
int
MAX_LOW_PRIORITY_THRESHOLD
=
6
;
private
static
final
int
DELIVERY_DEADLINE_BASE
=
1000
;
// 交付期基准值
// 自适应调整后的参数(公开可访问)
private
int
populationSize
;
private
int
maxIterations
;
private
float
crossoverProb
;
private
float
mutationProb
;
private
int
tournamentSize
;
private
int
lowPriorityThreshold
;
private
int
deliveryDeadline
;
// 自适应调整系数(可根据实际场景微调)
private
float
populationSizeCoeff
=
0.1f
;
// 种群大小对工序数的敏感系数
private
float
maxIterationsCoeff
=
0.05f
;
// 迭代次数对工序数的敏感系数
private
float
crossoverProbCoeff
=
0.0001f
;
// 交叉概率对工序数的敏感系数
private
float
mutationProbCoeff
=
0.00005f
;
// 变异概率对工序数的敏感系数
private
float
tournamentSizeCoeff
=
200
f
;
// 锦标赛规模对工序数的敏感系数(分母越大越不敏感)
private
float
lowPriorityThresholdCoeff
=
300
f
;
// 低优先级阈值对工序数的敏感系数(分母越大越不敏感)
private
float
deliveryDeadlineCoeff
=
0.5f
;
// 交付期对工序数的敏感系数
/**
* 根据总工序数初始化自适应参数(一次性调整)
*
* @param totalOps 总工序数
*/
public
void
initAdaptiveParams
(
int
totalOps
)
{
// 1. 种群大小:50 ~ 500,随工序数线性增加
double
populationSizeTemp
=
MIN_POPULATION_SIZE
+
totalOps
*
populationSizeCoeff
;
populationSize
=
(
int
)
clamp
(
populationSizeTemp
,
MIN_POPULATION_SIZE
,
MAX_POPULATION_SIZE
);
// 确保偶数(方便交叉)
if
(
populationSize
%
2
!=
0
)
{
populationSize
+=
1
;
}
// 2. 最大迭代次数:50 ~ 200,随工序数线性减少
double
maxIterationsTemp
=
MAX_MAX_ITERATIONS
-
totalOps
*
maxIterationsCoeff
;
maxIterations
=
(
int
)
clamp
(
maxIterationsTemp
,
MIN_MAX_ITERATIONS
,
MAX_MAX_ITERATIONS
);
// 3. 交叉概率:0.6 ~ 0.9,随工序数轻微减少
double
crossoverProbTemp
=
MAX_CROSSOVER_PROB
-
totalOps
*
crossoverProbCoeff
;
crossoverProb
=
(
float
)
clamp
(
crossoverProbTemp
,
MIN_CROSSOVER_PROB
,
MAX_CROSSOVER_PROB
);
// 4. 变异概率:0.05 ~ 0.2,随工序数轻微增加
double
mutationProbTemp
=
MIN_MUTATION_PROB
+
totalOps
*
mutationProbCoeff
;
mutationProb
=
(
float
)
clamp
(
mutationProbTemp
,
MIN_MUTATION_PROB
,
MAX_MUTATION_PROB
);
// 5. 锦标赛规模:3 ~ 7,随工序数阶梯式增加
double
tournamentSizeTemp
=
MIN_TOURNAMENT_SIZE
+
totalOps
/
tournamentSizeCoeff
;
tournamentSize
=
(
int
)
clamp
(
tournamentSizeTemp
,
MIN_TOURNAMENT_SIZE
,
MAX_TOURNAMENT_SIZE
);
// 6. 低优先级阈值:3 ~ 6,随工序数阶梯式减少
double
lowPriorityThresholdTemp
=
MAX_LOW_PRIORITY_THRESHOLD
-
totalOps
/
lowPriorityThresholdCoeff
;
lowPriorityThreshold
=
(
int
)
clamp
(
lowPriorityThresholdTemp
,
MIN_LOW_PRIORITY_THRESHOLD
,
MAX_LOW_PRIORITY_THRESHOLD
);
// 7. 交付期:基准1000 + 工序数*0.5(随工序数增加)
deliveryDeadline
=
(
int
)
(
DELIVERY_DEADLINE_BASE
+
totalOps
*
deliveryDeadlineCoeff
);
// 输出自适应参数日志
DecimalFormat
df
=
new
DecimalFormat
(
"#.###"
);
System
.
out
.
println
(
"=== 自适应参数初始化完成(总工序数:"
+
totalOps
+
")==="
);
System
.
out
.
println
(
"种群大小:"
+
populationSize
);
System
.
out
.
println
(
"最大迭代次数:"
+
maxIterations
);
System
.
out
.
println
(
"交叉概率:"
+
df
.
format
(
crossoverProb
));
System
.
out
.
println
(
"变异概率:"
+
df
.
format
(
mutationProb
));
System
.
out
.
println
(
"锦标赛规模:"
+
tournamentSize
);
System
.
out
.
println
(
"低优先级阈值:"
+
lowPriorityThreshold
);
System
.
out
.
println
(
"交付期:"
+
deliveryDeadline
);
System
.
out
.
println
(
"============================================\n"
);
}
/**
* 迭代中动态微调参数(根据种群收敛情况)
*
* @param currentIter 当前迭代次数
* @param fitnessStd 当前种群适应度标准差(越小收敛越好)
*/
public
void
fineTuneParams
(
int
currentIter
,
float
fitnessStd
)
{
// 每10代微调一次,避免频繁调整
if
(
currentIter
%
10
!=
0
)
{
return
;
}
// 适应度标准差阈值(可调整):小于0.05视为收敛过慢,大于0.2视为收敛过快
final
float
LOW_STD_THRESHOLD
=
0.05f
;
final
float
HIGH_STD_THRESHOLD
=
0.2f
;
final
float
ADJUST_STEP
=
0.05f
;
// 调整步长
DecimalFormat
df
=
new
DecimalFormat
(
"#.###"
);
// 1. 收敛过慢(适应度方差小):增加变异概率,降低交叉概率
if
(
fitnessStd
<
LOW_STD_THRESHOLD
)
{
mutationProb
=
(
float
)
clamp
(
mutationProb
+
ADJUST_STEP
*
0.5f
,
MIN_MUTATION_PROB
,
MAX_MUTATION_PROB
);
crossoverProb
=
(
float
)
clamp
(
crossoverProb
-
ADJUST_STEP
*
0.3f
,
MIN_CROSSOVER_PROB
,
MAX_CROSSOVER_PROB
);
System
.
out
.
println
(
"迭代"
+
currentIter
+
":收敛过慢,微调参数→变异概率:"
+
df
.
format
(
mutationProb
)
+
",交叉概率:"
+
df
.
format
(
crossoverProb
));
}
// 2. 收敛过快(适应度方差大):降低变异概率,增加交叉概率
else
if
(
fitnessStd
>
HIGH_STD_THRESHOLD
)
{
mutationProb
=
(
float
)
clamp
(
mutationProb
-
ADJUST_STEP
*
0.5f
,
MIN_MUTATION_PROB
,
MAX_MUTATION_PROB
);
crossoverProb
=
(
float
)
clamp
(
crossoverProb
+
ADJUST_STEP
*
0.3f
,
MIN_CROSSOVER_PROB
,
MAX_CROSSOVER_PROB
);
System
.
out
.
println
(
"迭代"
+
currentIter
+
":收敛过快,微调参数→变异概率:"
+
df
.
format
(
mutationProb
)
+
",交叉概率:"
+
df
.
format
(
crossoverProb
));
}
// 3. 后期迭代(超过80%迭代次数):降低变异概率,稳定最优解
if
(
currentIter
>
maxIterations
*
0.8f
)
{
mutationProb
=
(
float
)
clamp
(
mutationProb
*
0.8f
,
MIN_MUTATION_PROB
,
MAX_MUTATION_PROB
);
System
.
out
.
println
(
"迭代"
+
currentIter
+
":后期迭代,微调参数→变异概率:"
+
df
.
format
(
mutationProb
));
}
}
/**
*
*
* @param value 需要限制的值
* @param min 最小值
* @param max 最大值
* @return 限制后的值
*/
private
double
clamp
(
double
value
,
double
min
,
double
max
)
{
return
Math
.
max
(
min
,
Math
.
min
(
max
,
value
));
}
}
src/main/java/com/aps/service/Algorithm/FitnessCalculator.java
0 → 100644
View file @
e45bc27d
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.entity.Algorithm.Chromosome
;
/**
* 作者:佟礼
* 时间:2025-11-24
*/
public
class
FitnessCalculator
{
/**
* 多目标适应度计算(加权求和)
*/
public
double
calculateFitness
(
Chromosome
chromosome
)
{
// 权重可根据实际需求调整
double
w1
=
0.3
;
// 最早完工时间(越小越好,归一化后取反)
double
w2
=
0.2
;
// 总流程时间(越小越好)
double
w3
=
0.15
;
// 总换型时间(越小越好)
double
w4
=
0.2
;
// 机器负载均衡(标准差越小越好)
double
w5
=
0.15
;
// 交付期延迟(越小越好)
// 归一化(假设最大可能值,实际应根据问题规模调整)
double
normMakespan
=
1
/
(
1
+(
double
)
chromosome
.
getMakespan
());
double
normFlowTime
=
1
/
(
1
+
(
double
)
chromosome
.
getTotalFlowTime
()
);
double
normChangeover
=
1
/
(
1
+
(
double
)
chromosome
.
getTotalChangeoverTime
());
double
normLoadStd
=
chromosome
.
getMachineLoadStd
();
double
normDelay
=
1
/
(
1
+
(
double
)
chromosome
.
getDelayTime
()
);
// 适应度值(越大越好)
return
w1
*
normMakespan
+
w2
*
normFlowTime
+
w3
*
normChangeover
+
w4
*
normLoadStd
+
w5
*
normDelay
;
}
}
src/main/java/com/aps/service/Algorithm/GeneticAlgorithm.java
View file @
e45bc27d
package
com
.
aps
.
service
.
Algorithm
;
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.common.util.DeepCopyUtil
;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.GlobalOperationInfo
;
import
com.aps.entity.Algorithm.Pair
;
import
com.aps.entity.Algorithm.ScheduleParams
;
import
com.aps.entity.basic.Entry
;
import
com.aps.entity.basic.Machine
;
import
com.aps.entity.basic.Material
;
import
com.aps.entity.basic.Order
;
import
com.aps.service.plan.MachineSchedulerService
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
/**
* 作者:佟礼
* 作者:佟礼
* 时间:2025-11-21
* 时间:2025-11-21
*/
*/
public
class
GeneticAlgorithm
{
public
class
GeneticAlgorithm
{
public
void
Run
()
{
private
final
Random
rnd
=
new
Random
();
System
.
out
.
println
(
""
);
private
final
List
<
Machine
>
machines
;
private
final
MachineSchedulerService
machineScheduler
;
private
final
List
<
Order
>
orders
;
private
final
List
<
Material
>
materials
;
public
GeneticAlgorithm
(
List
<
Machine
>
machines
,
List
<
Order
>
orders
,
List
<
Material
>
materials
,
MachineSchedulerService
machineScheduler
)
{
this
.
machines
=
machines
;
this
.
orders
=
orders
;
this
.
materials
=
materials
;
this
.
machineScheduler
=
machineScheduler
;
}
public
List
<
Chromosome
>
Run
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
)
{
System
.
out
.
println
(
"开始"
);
Initialization
initialization
=
new
Initialization
(
allOperations
);
GeneticOperations
geneticOps
=
new
GeneticOperations
(
allOperations
);
// 预生成全局工序列表(所有初始化方法共享同一顺序)
List
<
GlobalOperationInfo
>
globalOpList
=
initialization
.
generateGlobalOpList
();
// 步骤1:初始化种群
List
<
Chromosome
>
population
=
initialization
.
generateInitialPopulation
(
param
,
globalOpList
);
Chromosomedecode
(
param
,
allOperations
,
globalOpList
,
population
);
int
ordercount
=
globalOpList
.
stream
()
.
mapToInt
(
GlobalOperationInfo:
:
getGroupId
)
.
max
()
.
orElse
(
0
);
Chromosome
best
=
new
Chromosome
();
double
bestFitness
=
0
;
int
Iteration
=
0
;
// 步骤2:迭代进化
for
(
int
iter
=
0
;
iter
<
param
.
getMaxIterations
();
iter
++)
{
// 解码并计算适应度
// 检查终止条件(此处简化为迭代次数)
if
(
iter
==
param
.
getMaxIterations
()
-
1
)
{
break
;
}
// 选择操作
List
<
Chromosome
>
selected
=
geneticOps
.
tournamentSelection
(
population
);
// 交叉操作
List
<
Chromosome
>
nextPopulation
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
selected
.
size
();
i
+=
2
)
{
if
(
i
+
1
>=
selected
.
size
())
{
nextPopulation
.
add
(
selected
.
get
(
i
));
break
;
}
Chromosome
parent1
=
selected
.
get
(
i
);
Chromosome
parent2
=
selected
.
get
(
i
+
1
);
if
(
rnd
.
nextDouble
()
<
param
.
getCrossoverProb
())
{
// 假设PoxCrossover返回包含两个子染色体的数组
Pair
<
Chromosome
,
Chromosome
>
children
=
geneticOps
.
poxCrossover
(
parent1
,
parent2
,
ordercount
);
nextPopulation
.
add
(
children
.
getFirst
());
nextPopulation
.
add
(
children
.
getSecond
());
}
else
{
nextPopulation
.
add
(
parent1
);
nextPopulation
.
add
(
parent2
);
}
}
// 变异操作
for
(
Chromosome
chromosome
:
nextPopulation
)
{
if
(
rnd
.
nextDouble
()
<
param
.
getMutationProb
())
{
geneticOps
.
mutate
(
chromosome
,
globalOpList
);
}
}
// 精英保留
List
<
Chromosome
>
population1
=
population
.
stream
()
.
sorted
((
c1
,
c2
)
->
Double
.
compare
(
c2
.
getFitness
(),
c1
.
getFitness
()))
.
collect
(
Collectors
.
toList
());
// 降序排序
List
<
Chromosome
>
elites
=
population1
.
subList
(
0
,
param
.
getElitismCount
());
List
<
Chromosome
>
newPopulation
=
new
ArrayList
<>();
newPopulation
.
addAll
(
elites
);
newPopulation
.
addAll
(
nextPopulation
);
// 更新种群
population
=
newPopulation
.
stream
()
.
limit
(
param
.
getPopulationSize
()
)
.
collect
(
Collectors
.
toList
());
Chromosomedecode
(
param
,
allOperations
,
globalOpList
,
population
);
best
=
population
.
stream
()
.
max
(
Comparator
.
comparingDouble
(
Chromosome:
:
getFitness
))
.
orElse
(
null
);
if
(
bestFitness
<
best
.
getFitness
())
{
bestFitness
=
best
.
getFitness
();
}
else
{
Iteration
++;
}
if
(
Iteration
>
20
)
{
break
;
}
}
// 步骤3:返回最优解
return
population
.
stream
()
.
sorted
((
c1
,
c2
)
->
Double
.
compare
(
c2
.
getFitness
(),
c1
.
getFitness
()))
.
limit
(
10
)
.
collect
(
Collectors
.
toList
());
}
private
void
Chromosomedecode
(
ScheduleParams
param
,
List
<
Entry
>
allOperations
,
List
<
GlobalOperationInfo
>
globalOpList
,
List
<
Chromosome
>
population
)
{
GeneticDecoder
decoder
=
new
GeneticDecoder
(
param
.
getBaseTime
(),
machines
,
orders
,
materials
,
machineScheduler
);
FitnessCalculator
fitnessCalc
=
new
FitnessCalculator
();
population
.
parallelStream
().
forEach
(
chromosome
->
{
chromosome
.
setResult
(
new
ArrayList
<>());
// 假设Machine类有拷贝方法,或使用MapStruct等工具进行映射
chromosome
.
setMachines
(
ProductionDeepCopyUtil
.
deepCopyList
(
machines
));
// 简单拷贝,实际可能需要深拷贝
decoder
.
decodeChromosomeWithCache
(
chromosome
,
globalOpList
,
allOperations
);
chromosome
.
setFitness
(
fitnessCalc
.
calculateFitness
(
chromosome
));
});
}
}
}
}
src/main/java/com/aps/service/Algorithm/GeneticDecoder.java
0 → 100644
View file @
e45bc27d
This diff is collapsed.
Click to expand it.
src/main/java/com/aps/service/Algorithm/GeneticOperations.java
0 → 100644
View file @
e45bc27d
package
com
.
aps
.
service
.
Algorithm
;
import
com.aps.common.util.ProductionDeepCopyUtil
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.GlobalOperationInfo
;
import
com.aps.entity.Algorithm.OperationSequencingWeight
;
import
com.aps.entity.Algorithm.Pair
;
import
com.aps.entity.basic.Entry
;
import
com.aps.entity.basic.GlobalParam
;
import
com.aps.entity.basic.MachineOption
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
* 作者:佟礼
* 时间:2025-11-24
*/
public
class
GeneticOperations
{
private
final
Random
rnd
=
new
Random
();
private
static
List
<
Entry
>
allOperations
;
public
GeneticOperations
(
List
<
Entry
>
allOperations
)
{
GeneticOperations
.
allOperations
=
allOperations
;
}
/**
* 锦标赛选择
*/
public
List
<
Chromosome
>
tournamentSelection
(
List
<
Chromosome
>
population
,
int
tournamentSize
)
{
List
<
Chromosome
>
selected
=
new
ArrayList
<>();
while
(
selected
.
size
()
<
population
.
size
())
{
// 随机选择k个个体
// List<Chromosome> candidates = population.stream()
// .sorted((a, b) -> rnd.nextInt())
// .limit(tournamentSize)
// .collect(Collectors.toList());
// 步骤1: 创建一个临时列表用于存放候选者
List
<
Chromosome
>
candidates
=
new
ArrayList
<>(
population
);
// 步骤2: 随机打乱候选者列表
Collections
.
shuffle
(
candidates
,
rnd
);
// 步骤3: 截取前 tournamentSize 个元素作为本次锦标赛的参与者
if
(
tournamentSize
<
candidates
.
size
())
{
candidates
=
candidates
.
subList
(
0
,
tournamentSize
);
}
// 步骤4: 从参与者中选择适应度最高的个体
Chromosome
best
=
candidates
.
stream
()
.
max
(
Comparator
.
comparingDouble
(
Chromosome:
:
getFitness
))
.
orElseThrow
(()
->
new
IllegalStateException
(
"候选列表为空,无法选择最佳个体。"
));
// 复制个体(假设Chromosome有复制方法或通过构造函数复制)
selected
.
add
(
ProductionDeepCopyUtil
.
deepCopy
(
best
));
}
return
selected
;
}
// 重载,使用默认锦标赛大小3
public
List
<
Chromosome
>
tournamentSelection
(
List
<
Chromosome
>
population
)
{
return
tournamentSelection
(
population
,
3
);
}
/**
* 改进POX交叉(工序排序部分)
*/
public
Pair
<
Chromosome
,
Chromosome
>
poxCrossover
(
Chromosome
parent1
,
Chromosome
parent2
,
int
orderCount
)
{
// 步骤1:随机划分工件集
List
<
Integer
>
jobset1
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
orderCount
;
i
++)
{
jobset1
.
add
(
i
);
}
Collections
.
shuffle
(
jobset1
,
rnd
);
jobset1
=
jobset1
.
subList
(
0
,
orderCount
/
2
);
Set
<
Integer
>
jobset1Set
=
new
HashSet
<>(
jobset1
);
List
<
Integer
>
jobset2
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
orderCount
;
i
++)
{
if
(!
jobset1Set
.
contains
(
i
))
{
jobset2
.
add
(
i
);
}
}
// 步骤2:生成子代1
List
<
Integer
>
child1Os
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
parent1
.
getOperationSequencing
().
size
();
i
++)
{
int
op1
=
parent1
.
getOperationSequencing
().
get
(
i
);
int
op2
=
parent2
.
getOperationSequencing
().
get
(
i
);
if
(
jobset1Set
.
contains
(
op1
)
||
jobset1Set
.
contains
(
op2
))
{
child1Os
.
add
(
op1
);
}
else
{
child1Os
.
add
(
op2
);
}
}
// 步骤3:生成子代2
List
<
Integer
>
child2Os
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
parent2
.
getOperationSequencing
().
size
();
i
++)
{
int
op1
=
parent1
.
getOperationSequencing
().
get
(
i
);
int
op2
=
parent2
.
getOperationSequencing
().
get
(
i
);
if
(
jobset1Set
.
contains
(
op2
)
||
jobset1Set
.
contains
(
op1
))
{
child2Os
.
add
(
op2
);
}
else
{
child2Os
.
add
(
op1
);
}
}
// 机器选择部分交叉
List
<
Integer
>
child1Ms
=
new
ArrayList
<>();
List
<
Integer
>
child2Ms
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
parent1
.
getMachineSelection
().
size
();
i
++)
{
int
m1
=
parent1
.
getMachineSelection
().
get
(
i
);
int
m2
=
parent2
.
getMachineSelection
().
get
(
i
);
if
(
rnd
.
nextDouble
()
<
0.5
)
{
child1Ms
.
add
(
m1
);
child2Ms
.
add
(
m2
);
}
else
{
child1Ms
.
add
(
m2
);
child2Ms
.
add
(
m1
);
}
}
Chromosome
child1
=
new
Chromosome
();
child1
.
setMachineSelection
(
child1Ms
);
child1
.
setOperationSequencing
(
child1Os
);
Chromosome
child2
=
new
Chromosome
();
child2
.
setMachineSelection
(
child2Ms
);
child2
.
setOperationSequencing
(
child2Os
);
return
new
Pair
<>(
child1
,
child2
);
}
/**
* 变异操作
*/
public
void
mutate
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
,
double
baseMutationProb
)
{
// 1. 机器选择部分变异
mutateMachineSelection
(
chromosome
,
globalOpList
,
baseMutationProb
);
// 2. 工序排序部分变异
mutateOperationSequencing
(
chromosome
);
}
// 重载,使用默认变异概率
public
void
mutate
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
mutate
(
chromosome
,
globalOpList
,
0.1
);
}
private
void
mutateMachineSelection
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
,
double
baseMutationProb
)
{
// 计算变异位置数量
int
r
=
Math
.
max
(
1
,
(
int
)
(
chromosome
.
getMachineSelection
().
size
()
*
baseMutationProb
));
int
i
=
0
;
while
(
i
<
r
)
{
int
pos
=
rnd
.
nextInt
(
chromosome
.
getMachineSelection
().
size
());
// 获取对应工序
GlobalOperationInfo
opInfo
=
globalOpList
.
get
(
pos
);
Entry
operation
=
opInfo
.
getOp
();
int
machineSeq
=
chromosome
.
getMachineSelection
().
get
(
pos
);
if
(
operation
.
getMachineOptions
().
size
()
==
1
)
{
continue
;
}
else
{
// 选择当前所选设备外最短加工时间的机器
List
<
MachineOption
>
optionalMachines
=
operation
.
getMachineOptions
();
// 找到当前选中的机器
MachineOption
currentMachine
=
optionalMachines
.
get
(
machineSeq
-
1
);
// 筛选其他机器并找到加工时间最短的
MachineOption
minLoadMachine
=
optionalMachines
.
stream
()
.
filter
(
m
->
m
.
getMachineId
()
!=
currentMachine
.
getMachineId
())
.
min
(
Comparator
.
comparingInt
(
m
->
m
.
getProcessingTime
()))
.
orElse
(
currentMachine
);
// 如果没有其他机器,保持当前
machineSeq
=
optionalMachines
.
indexOf
(
minLoadMachine
)
+
1
;
chromosome
.
getMachineSelection
().
set
(
pos
,
machineSeq
);
i
++;
}
}
}
/**
* 低优先级优先的工序排序变异
*/
private
void
mutateOperationSequencing
(
Chromosome
chromosome
)
{
Random
rnd
=
new
Random
();
// 选择变异方式(交换或反转)
if
(
rnd
.
nextDouble
()
<
0.5
)
{
// 交换:优先选择高优先级工序的索引
OperationSequencingWeight
os1
=
selectHighPriorityIndex
(
chromosome
.
getOperationSequencing
(),
0
);
int
idx1
=
os1
.
getIndex
();
OperationSequencingWeight
os2
=
selectHighPriorityIndex
(
chromosome
.
getOperationSequencing
(),
os1
.
getWeight
());
int
idx2
=
os2
.
getIndex
();
// 交换位置
List
<
Integer
>
os
=
chromosome
.
getOperationSequencing
();
Collections
.
swap
(
os
,
idx1
,
idx2
);
}
else
{
// 反转:仅对高优先级工序集中的子序列反转
OperationSequencingWeight
osStart
=
selectHighPriorityIndex
(
chromosome
.
getOperationSequencing
(),
0
);
int
start
=
osStart
.
getIndex
();
OperationSequencingWeight
osEnd
=
selectHighPriorityIndex
(
chromosome
.
getOperationSequencing
(),
osStart
.
getWeight
());
int
end
=
osEnd
.
getIndex
();
if
(
start
>
end
)
{
int
temp
=
start
;
start
=
end
;
end
=
temp
;
}
// 执行反转
List
<
Integer
>
os
=
chromosome
.
getOperationSequencing
();
for
(
int
i
=
0
;
i
<
(
end
-
start
+
1
)
/
2
;
i
++)
{
int
pos1
=
start
+
i
;
int
pos2
=
end
-
i
;
Collections
.
swap
(
os
,
pos1
,
pos2
);
}
}
}
/**
* 优先选择高优先级工序的索引(用于变异)
*/
private
OperationSequencingWeight
selectHighPriorityIndex
(
List
<
Integer
>
os
,
int
weight
)
{
Random
rnd
=
new
Random
();
List
<
OperationSequencingWeight
>
indexWeights
=
CommonCalculator
.
getOsw
(
os
,
allOperations
);
if
(!
GlobalParam
.
IsBreakPriority
)
{
if
(
weight
==
0
)
{
return
indexWeights
.
get
(
rnd
.
nextInt
(
indexWeights
.
size
()));
}
else
{
List
<
OperationSequencingWeight
>
filtered
=
indexWeights
.
stream
()
.
filter
(
t
->
t
.
getWeight
()
==
weight
)
.
collect
(
Collectors
.
toList
());
return
filtered
.
get
(
rnd
.
nextInt
(
filtered
.
size
()));
}
}
return
indexWeights
.
get
(
CommonCalculator
.
getOsIndex
(
indexWeights
));
}
}
src/main/java/com/aps/service/Algorithm/Initialization.java
View file @
e45bc27d
...
@@ -43,33 +43,42 @@ public class Initialization {
...
@@ -43,33 +43,42 @@ public class Initialization {
*/
*/
public
List
<
Chromosome
>
generateInitialPopulation
(
ScheduleParams
param
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
public
List
<
Chromosome
>
generateInitialPopulation
(
ScheduleParams
param
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
List
<
Chromosome
>
population
=
new
ArrayList
<>();
List
<
Chromosome
>
population
=
new
ArrayList
<>();
// 按比例生成不同类型个体(GS:40%, LS:40%, RS:20%)
int
gsCount
=
(
int
)
(
param
.
getPopulationSize
()
*
param
.
getGsRatio
());
int
gsCount
=
(
int
)
(
param
.
getPopulationSize
()
*
param
.
getGsRatio
());
int
lsCount
=
(
int
)
(
param
.
getPopulationSize
()
*
param
.
getLsRatio
());
int
lsCount
=
gsCount
+
(
int
)
(
param
.
getPopulationSize
()
*
param
.
getLsRatio
());
int
rsCount
=
param
.
getPopulationSize
()
-
gsCount
-
lsCount
;
int
rsCount
=
param
.
getPopulationSize
()
-
gsCount
-
lsCount
;
int
populationSize
=
param
.
getPopulationSize
();
// 并行循环:对应 Parallel.For(0, PopulationSize, i => { ... })
IntStream
.
range
(
0
,
populationSize
)
.
parallel
()
// 开启并行
.
forEach
(
i
->
{
Chromosome
chromo
=
new
Chromosome
();
// 初始化染色体
// 全局选择(GS):按GlobalOpId顺序生成MachineSelection
// 全局选择(GS):按GlobalOpId顺序生成MachineSelection
for
(
int
i
=
0
;
i
<
gsCount
;
i
++)
{
if
(
i
<
gsCount
)
{
population
.
add
(
generateGSChromosome
(
globalOpList
,
param
.
getMachineCount
()));
generateGSChromosome
(
chromo
,
globalOpList
);
// 对应 C# GenerateGSChromosome
}
}
else
if
(
i
<
lsCount
)
{
// 局部选择(LS):按GlobalOpId顺序生成MachineSelection(仅负载计算范围不同)
// 局部选择(LS):按GlobalOpId顺序生成MachineSelection(仅负载计算范围不同)
for
(
int
i
=
0
;
i
<
lsCount
;
i
++)
{
generateLSChromosome
(
chromo
,
globalOpList
);
population
.
add
(
generateLSChromosome
(
globalOpList
,
param
.
getMachineCount
()));
}
else
{
}
// 随机选择(RS):按GlobalOpId顺序生成MachineSelection(仅机器选择随机)
// 随机选择(RS):按GlobalOpId顺序生成MachineSelection(仅机器选择随机)
for
(
int
i
=
0
;
i
<
rsCount
;
i
++)
{
generateRSChromosome
(
chromo
,
globalOpList
);
population
.
add
(
generateRSChromosome
(
globalOpList
,
param
.
getMachineCount
()));
}
}
population
.
add
(
chromo
);
// 赋值到数组,线程安全(数组索引唯一)
});
return
population
;
return
population
;
}
}
/**
/**
* 全局选择(GS)生成染色体(按GlobalOpId顺序生成MachineSelection)
* 全局选择(GS)生成染色体(按GlobalOpId顺序生成MachineSelection)
*/
*/
private
Chromosome
generateGSChromosome
(
List
<
GlobalOperationInfo
>
globalOpList
,
int
machineCount
)
{
private
Chromosome
generateGSChromosome
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
Chromosome
chromosome
=
new
Chromosome
();
Map
<
Integer
,
Integer
>
machineLoad
=
new
HashMap
<>();
Map
<
Integer
,
Integer
>
machineLoad
=
new
HashMap
<>();
// int[] machineLoad = new int[machineCount + 1]; // 设备负载(1-based,设备ID从1开始)
// int[] machineLoad = new int[machineCount + 1]; // 设备负载(1-based,设备ID从1开始)
List
<
Integer
>
ms
=
new
ArrayList
<>();
// MachineSelection(顺序=GlobalOpId顺序)
List
<
Integer
>
ms
=
new
ArrayList
<>();
// MachineSelection(顺序=GlobalOpId顺序)
...
@@ -106,7 +115,7 @@ public class Initialization {
...
@@ -106,7 +115,7 @@ public class Initialization {
.
findFirst
();
.
findFirst
();
// 计算该机器在“可选机器列表”中的顺序号(1-based)
// 计算该机器在“可选机器列表”中的顺序号(1-based)
int
machineSeq
=
index
.
orElse
(
0
)
;
//findIndex(optionalMachines, minLoadMachine.getMachineId()) + 1;
int
machineSeq
=
index
.
orElse
(
0
)
+
1
;
//findIndex(optionalMachines, minLoadMachine.getMachineId()) + 1;
ms
.
add
(
machineSeq
);
ms
.
add
(
machineSeq
);
// 更新设备负载
// 更新设备负载
...
@@ -132,8 +141,9 @@ public class Initialization {
...
@@ -132,8 +141,9 @@ public class Initialization {
/**
/**
* 局部选择(LS)生成染色体(按GlobalOpId顺序,每个订单重新初始化负载)
* 局部选择(LS)生成染色体(按GlobalOpId顺序,每个订单重新初始化负载)
*/
*/
private
Chromosome
generateLSChromosome
(
List
<
GlobalOperationInfo
>
globalOpList
,
int
machineCount
)
{
private
Chromosome
generateLSChromosome
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
Chromosome
chromosome
=
new
Chromosome
();
List
<
Integer
>
ms
=
new
ArrayList
<>();
List
<
Integer
>
ms
=
new
ArrayList
<>();
List
<
Integer
>
os
=
new
ArrayList
<>();
List
<
Integer
>
os
=
new
ArrayList
<>();
Random
rnd
=
new
Random
();
Random
rnd
=
new
Random
();
...
@@ -199,8 +209,9 @@ public class Initialization {
...
@@ -199,8 +209,9 @@ public class Initialization {
/**
/**
* 随机选择(RS)生成染色体(按GlobalOpId顺序,随机选择机器)
* 随机选择(RS)生成染色体(按GlobalOpId顺序,随机选择机器)
*/
*/
private
Chromosome
generateRSChromosome
(
List
<
GlobalOperationInfo
>
globalOpList
,
int
machineCount
)
{
private
Chromosome
generateRSChromosome
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
Chromosome
chromosome
=
new
Chromosome
();
List
<
Integer
>
ms
=
new
ArrayList
<>();
List
<
Integer
>
ms
=
new
ArrayList
<>();
List
<
Integer
>
os
=
new
ArrayList
<>();
List
<
Integer
>
os
=
new
ArrayList
<>();
Random
rnd
=
new
Random
();
Random
rnd
=
new
Random
();
...
...
src/main/java/com/aps/service/Algorithm/MachineCalculator.java
0 → 100644
View file @
e45bc27d
This diff is collapsed.
Click to expand it.
src/main/java/com/aps/service/plan/PlanResultService.java
View file @
e45bc27d
package
com
.
aps
.
service
.
plan
;
package
com
.
aps
.
service
.
plan
;
import
com.aps.common.util.FileHelper
;
import
com.aps.common.util.JsonFileReader
;
import
com.aps.common.util.JsonFileReader
;
import
com.aps.controller.gantt.FileUploadController
;
import
com.aps.controller.gantt.FileUploadController
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.GAScheduleResult
;
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
;
...
@@ -13,9 +18,7 @@ import org.springframework.stereotype.Service;
...
@@ -13,9 +18,7 @@ import org.springframework.stereotype.Service;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.math.BigDecimal
;
import
java.math.BigDecimal
;
import
java.time.LocalDateTime
;
import
java.time.LocalDateTime
;
import
java.util.ArrayList
;
import
java.util.*
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.stream.Collectors
;
import
java.util.stream.Collectors
;
@Service
@Service
...
@@ -92,10 +95,9 @@ public class PlanResultService {
...
@@ -92,10 +95,9 @@ public class PlanResultService {
}
}
}
}
public
List
<
ScheduleChromosome
>
execute1
()
{
public
List
<
Chromosome
>
execute1
()
{
try
{
try
{
Entry
entry
=
new
Entry
();
// 1. 读取数据
// 1. 读取数据
List
<
Machine
>
machines
=
loadData
(
"machines.json"
,
Machine
.
class
);
List
<
Machine
>
machines
=
loadData
(
"machines.json"
,
Machine
.
class
);
...
@@ -122,6 +124,11 @@ public class PlanResultService {
...
@@ -122,6 +124,11 @@ public class PlanResultService {
}
}
}
}
}
}
ScheduleParams
param
=
new
ScheduleParams
();
param
.
setBaseTime
(
LocalDateTime
.
of
(
2025
,
10
,
1
,
0
,
0
,
0
));
param
.
setPopulationSize
(
50
);
param
.
setMaxIterations
(
100
);
// 创建节假日
// 创建节假日
List
<
Holiday
>
holidays
=
Arrays
.
asList
(
List
<
Holiday
>
holidays
=
Arrays
.
asList
(
...
@@ -134,34 +141,118 @@ public class PlanResultService {
...
@@ -134,34 +141,118 @@ public class PlanResultService {
// 3. 创建调度服务
// 3. 创建调度服务
MachineSchedulerService
machineScheduler
=
new
MachineSchedulerService
(
MachineSchedulerService
machineScheduler
=
new
MachineSchedulerService
(
holidays
,
LocalDateTime
.
of
(
2025
,
10
,
1
,
0
,
0
,
0
));
holidays
,
param
.
getBaseTime
(
));
// 4. 初始化机器时间线
// 4. 初始化机器时间线
for
(
Machine
machine
:
machines
)
{
for
(
Machine
machine
:
machines
)
{
MachineTimeline
timeline
=
machineScheduler
.
getOrCreateTimeline
(
machine
);
MachineTimeline
timeline
=
machineScheduler
.
getOrCreateTimeline
(
machine
);
machine
.
setAvailability
(
timeline
.
getSegments
());
machine
.
setAvailability
(
timeline
.
getSegments
());
}
}
// 3. 构建订单-工序数据
List
<
Entry
>
allOperations
=
new
ArrayList
<>();
Random
rnd
=
new
Random
();
// 注意:此处变量声明但未使用,可根据实际需求保留或移除
int
id
=
1
;
for
(
Order
order
:
orders
)
{
// 假设products是一个List<Product>,根据Product的Id查找对应的产品
Product
product
=
products
.
stream
()
.
filter
(
p
->
p
.
getId
()
==
order
.
getProductId
())
.
findFirst
()
.
orElseThrow
(()
->
new
IllegalArgumentException
(
"未找到对应产品: "
+
order
.
getProductId
()));
int
sequence
=
1
;
for
(
Operation
o
:
product
.
getOperations
())
{
// 假设Product类有getOperations()方法返回工序列表
Entry
entry
=
new
Entry
();
entry
.
setId
(
id
);
entry
.
setGroupId
(
order
.
getId
());
entry
.
setSequence
(
sequence
);
entry
.
setMachineOptions
(
o
.
getMachineOptions
());
// 假设Operation类有获取机器选项的方法
entry
.
setPriority
(
order
.
getPriority
());
entry
.
setQuantity
(
order
.
getQuantity
());
// entry.setMaterialRequirements(o.getMaterialRequirements()); // 假设Operation类有获取物料需求的方法
if
(
sequence
!=
1
)
{
entry
.
getPrevEntryIds
().
add
(
id
-
1
);
// 假设Entry类有getPrevEntryIds()返回List<Integer>
}
allOperations
.
add
(
entry
);
sequence
++;
id
++;
}
}
// 5. 执行调度算法
// 5. 执行调度算法
GeneticAlgorithm
scheduler
=
new
GeneticAlgorithm
();
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
GeneticAlgorithm
scheduler
=
new
GeneticAlgorithm
(
machines
,
orders
,
null
,
machineScheduler
);
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
List
<
ScheduleChromosome
>
scheduleChromosomes
=
null
;
List
<
Chromosome
>
Chromosomes
=
scheduler
.
Run
(
param
,
allOperations
);
scheduler
.
Run
();
// 对调度结果按照 fitness 由高到低排序
Chromosomes
.
forEach
(
this
::
WriteScheduleSummary
);
scheduleChromosomes
.
sort
((
c1
,
c2
)
->
Double
.
compare
(
c2
.
getFitness
(),
c1
.
getFitness
()));
// 为每个 ScheduleChromosome 分配场景ID(基于排序后的位置)
return
Chromosomes
;
for
(
int
i
=
0
;
i
<
scheduleChromosomes
.
size
();
i
++)
{
scheduleChromosomes
.
get
(
i
).
setSceneId
(
i
+
1
);
// 场景ID从1开始
}
return
scheduleChromosomes
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"调度执行失败"
,
e
);
throw
new
RuntimeException
(
"调度执行失败"
,
e
);
}
}
}
}
public
void
WriteScheduleSummary
(
Chromosome
schedule
)
{
// 写入日志
FileHelper
.
writeLogFile
(
String
.
format
(
"\n=== Schedule Summary === %f"
,
schedule
.
getFitness
()));
FileHelper
.
writeLogFile
(
String
.
format
(
"Operation: %s"
,
schedule
.
getOperationStr
()));
FileHelper
.
writeLogFile
(
String
.
format
(
"Makespan: %f minutes"
,
schedule
.
getMakespan
()));
FileHelper
.
writeLogFile
(
String
.
format
(
"Total Tardiness: %f hours"
,
schedule
.
getDelayTime
()));
FileHelper
.
writeLogFile
(
String
.
format
(
"Setup Time: %f minutes"
,
schedule
.
getTotalChangeoverTime
()));
FileHelper
.
writeLogFile
(
String
.
format
(
"Flow Time: %f minutes"
,
schedule
.
getTotalFlowTime
()));
FileHelper
.
writeLogFile
(
String
.
format
(
"Machine Load Balance: %.2f%%"
,
schedule
.
getMachineLoadStd
()
*
100
));
FileHelper
.
writeLogFile
(
"-------------------------"
);
// 按订单分组写入
Map
<
Integer
,
List
<
GAScheduleResult
>>
orderGroups
=
schedule
.
getResult
().
stream
()
.
collect
(
Collectors
.
groupingBy
(
GAScheduleResult:
:
getGroupId
));
for
(
Map
.
Entry
<
Integer
,
List
<
GAScheduleResult
>>
group
:
orderGroups
.
entrySet
())
{
List
<
GAScheduleResult
>
sortedJobs
=
group
.
getValue
().
stream
()
.
sorted
(
Comparator
.
comparingInt
(
GAScheduleResult:
:
getOperationId
))
.
collect
(
Collectors
.
toList
());
for
(
GAScheduleResult
job
:
sortedJobs
)
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
String
.
format
(
"[%d-%d]:[%s-%s] Order %d, Machine %d, Operation %d, Batch %d, processingTime %d"
,
job
.
getStartTime
(),
job
.
getEndTime
(),
ConvertTime
(
job
.
getStartTime
()),
ConvertTime
(
job
.
getEndTime
()),
job
.
getGroupId
(),
job
.
getMachineId
(),
job
.
getOperationId
(),
job
.
getQuantity
(),
job
.
getProcessingTime
()
));
// 追加基因详情
for
(
ScheduleResultDetail
d
:
job
.
getGeneDetails
())
{
sb
.
append
(
String
.
format
(
"\n\t\t\t\t\t\t\t\t\t\t [%d-%d]:[%s-%s] %d"
,
d
.
getStartTime
(),
d
.
getEndTime
(),
ConvertTime
(
d
.
getStartTime
()),
ConvertTime
(
d
.
getEndTime
()),
d
.
getEndTime
()
-
d
.
getStartTime
()
));
}
FileHelper
.
writeLogFile
(
sb
.
toString
());
}
FileHelper
.
writeLogFile
(
""
);
}
}
private
String
ConvertTime
(
int
minute
)
{
return
baseTime
.
plusMinutes
(
minute
).
format
(
java
.
time
.
format
.
DateTimeFormatter
.
ofPattern
(
"MM-dd HH:mm"
));
}
/**
/**
* 加载数据,优先从上传文件夹加载,如果不存在则从resources加载
* 加载数据,优先从上传文件夹加载,如果不存在则从resources加载
...
...
src/main/resources/application.yml
View file @
e45bc27d
...
@@ -23,23 +23,23 @@ spring:
...
@@ -23,23 +23,23 @@ spring:
# 默认数据源
# 默认数据源
strict
:
false
# 关闭严格模式
strict
:
false
# 关闭严格模式
datasource
:
datasource
:
# MySQL数据源
#
# MySQL数据源
mysql
:
#
mysql:
driver-class-name
:
com.mysql.cj.jdbc.Driver
#
driver-class-name: com.mysql.cj.jdbc.Driver
url
:
jdbc:mysql://192.168.0.181:3310/mes?useSSL=false&serverTimezone=UTC
#
url: jdbc:mysql://192.168.0.181:3310/mes?useSSL=false&serverTimezone=UTC
username
:
root
# 替换为你的MySQL用户名
#
username: root # 替换为你的MySQL用户名
password
:
root_mes@123456~
# 替换为你的MySQL密码
#
password: root_mes@123456~ # 替换为你的MySQL密码
# Oracle数据源
# Oracle数据源
oracle
:
oracle
:
driver-class-name
:
oracle.jdbc.OracleDriver
driver-class-name
:
oracle.jdbc.OracleDriver
url
:
jdbc:oracle:thin:@//
192.168.0.181:152
2/ORCLPDB1
# ORCL为你的Oracle实例名
url
:
jdbc:oracle:thin:@//
39.100.78.207:700
2/ORCLPDB1
# ORCL为你的Oracle实例名
username
:
mes
# 替换为你的Oracle用户名
username
:
mes
# 替换为你的Oracle用户名
password
:
root_mes123456
# 替换为你的Oracle密码
password
:
root_mes123456
# 替换为你的Oracle密码
sqlserver
:
#
sqlserver:
driver-class-name
:
com.microsoft.sqlserver.jdbc.SQLServerDriver
#
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
url
:
jdbc:sqlserver://192.168.0.181:1434;databaseName=mes;encrypt=false
#
url: jdbc:sqlserver://192.168.0.181:1434;databaseName=mes;encrypt=false
username
:
sa
#
username: sa
password
:
root_mes123456
#
password: root_mes123456
# 文件上传配置
# 文件上传配置
...
...
src/main/resources/machines.json
View file @
e45bc27d
...
@@ -5,6 +5,8 @@
...
@@ -5,6 +5,8 @@
"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"
:
"2025-10-10T00:00:00"
,
"endDate"
:
"2025-11-10T00:00:00"
,
"shiftDate"
:
"0001-01-01T00:00:00"
,
"shiftDate"
:
"0001-01-01T00:00:00"
,
"temporaryShift"
:
false
,
"temporaryShift"
:
false
,
"priority"
:
0
,
"priority"
:
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