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
ee581dc1
Commit
ee581dc1
authored
Nov 26, 2025
by
Tong Li
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
遗传算法
parent
4d69e6bd
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
2412 additions
and
1829078 deletions
+2412
-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
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 @
ee581dc1
...
...
@@ -91,6 +91,7 @@
<artifactId>
spring-boot-starter-test
</artifactId>
<scope>
test
</scope>
</dependency>
</dependencies>
<build>
...
...
schedule_log.txt
View file @
ee581dc1
This diff is collapsed.
Click to expand it.
src/main/java/com/aps/controller/gantt/ResourceGanttController.java
View file @
ee581dc1
package
com
.
aps
.
controller
.
gantt
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.basic.ScheduleChromosome
;
import
com.aps.entity.Gantt.ProductGanttVO
;
import
com.aps.entity.Gantt.ResourceGanttVO
;
...
...
@@ -103,6 +104,16 @@ public class ResourceGanttController {
.
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 列表
* @param scheduleChromosome 调度结果
...
...
src/main/java/com/aps/entity/Algorithm/Chromosome.java
View file @
ee581dc1
package
com
.
aps
.
entity
.
Algorithm
;
import
com.aps.entity.Algorithm.ScheduleResult
;
import
com.aps.entity.basic.Machine
;
import
lombok.Data
;
import
java.util.List
;
import
java.util.UUID
;
import
java.util.stream.Collectors
;
/**
* 作者:佟礼
...
...
@@ -12,16 +13,41 @@ import java.util.List;
*/
@Data
public
class
Chromosome
{
private
String
ID
=
UUID
.
randomUUID
().
toString
();
/// <summary>
/// 机器选择部分(可选机器集中的顺序号)
/// </summary>
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>
/// 工序排序部分(工件/订单ID)
/// </summary>
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>
...
...
@@ -35,7 +61,7 @@ public class Chromosome {
/// <summary>
/// 解码后的调度结果
/// </summary>
private
List
<
ScheduleResult
>
Result
;
private
List
<
GA
ScheduleResult
>
Result
;
/// <summary>
/// 最早完工时间
...
...
src/main/java/com/aps/entity/Algorithm/ScheduleResult.java
→
src/main/java/com/aps/entity/Algorithm/
GA
ScheduleResult.java
View file @
ee581dc1
...
...
@@ -9,7 +9,7 @@ import java.util.List;
* 时间:2025-11-21
*/
@Data
public
class
ScheduleResult
{
public
class
GA
ScheduleResult
{
private
int
GroupId
;
private
int
ProductId
;
private
int
OperationId
;
...
...
@@ -21,4 +21,9 @@ public class ScheduleResult {
private
int
OneTime
;
// 单件工时
private
int
ProcessingTime
;
// 绝对处理时间(分钟)
private
int
ChangeoverTime
;
public
int
getFlowTime
()
{
return
EndTime
-
StartTime
;
};
}
src/main/java/com/aps/entity/Algorithm/OpMachine.java
0 → 100644
View file @
ee581dc1
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 @
ee581dc1
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 @
ee581dc1
...
...
@@ -3,6 +3,7 @@ package com.aps.entity.Algorithm;
import
com.aps.entity.basic.Entry
;
import
lombok.Data
;
import
java.time.LocalDateTime
;
import
java.util.Date
;
/**
...
...
@@ -11,12 +12,9 @@ import java.util.Date;
*/
@Data
public
class
ScheduleParams
{
private
Date
BaseTime
=
new
Date
();
// 当前基准时间
private
LocalDateTime
BaseTime
;
// 当前基准时间
/// <summary>
/// 设备总数
/// </summary>
private
int
MachineCount
;
// 设备总数
/// <summary>
/// 交叉概率
...
...
src/main/java/com/aps/entity/basic/MachineOption.java
View file @
ee581dc1
...
...
@@ -8,7 +8,7 @@ import lombok.Data;
@Data
public
class
MachineOption
{
private
int
machineId
;
private
int
processingTime
;
// 加工时间
private
int
processingTime
;
// 加工时间
(秒)
private
int
setupTime
;
// 换型时间(如果与前一个产品不同)
private
int
teardownTime
;
// 收尾时间(后处理时间)
private
int
contantTime
;
// 常数时间
...
...
src/main/java/com/aps/entity/basic/Order.java
View file @
ee581dc1
...
...
@@ -13,6 +13,8 @@ public class Order {
private
int
id
;
private
int
productId
;
private
int
quantity
=
100
;
// 100个
private
int
sYQuantity
;
private
OffsetDateTime
dueDate
;
private
LocalDateTime
orderCompletion
;
private
double
tardiness
;
...
...
src/main/java/com/aps/service/Algorithm/FitnessCalculator.java
0 → 100644
View file @
ee581dc1
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 @
ee581dc1
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
*/
public
class
GeneticAlgorithm
{
public
void
Run
()
{
System
.
out
.
println
(
""
);
private
final
Random
rnd
=
new
Random
();
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 @
ee581dc1
This diff is collapsed.
Click to expand it.
src/main/java/com/aps/service/Algorithm/GeneticOperations.java
0 → 100644
View file @
ee581dc1
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 @
ee581dc1
...
...
@@ -43,33 +43,42 @@ public class Initialization {
*/
public
List
<
Chromosome
>
generateInitialPopulation
(
ScheduleParams
param
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
List
<
Chromosome
>
population
=
new
ArrayList
<>();
// 按比例生成不同类型个体(GS:40%, LS:40%, RS:20%)
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
populationSize
=
param
.
getPopulationSize
();
// 并行循环:对应 Parallel.For(0, PopulationSize, i => { ... })
IntStream
.
range
(
0
,
populationSize
)
.
parallel
()
// 开启并行
.
forEach
(
i
->
{
Chromosome
chromo
=
new
Chromosome
();
// 初始化染色体
// 全局选择(GS):按GlobalOpId顺序生成MachineSelection
for
(
int
i
=
0
;
i
<
gsCount
;
i
++)
{
population
.
add
(
generateGSChromosome
(
globalOpList
,
param
.
getMachineCount
()));
}
if
(
i
<
gsCount
)
{
generateGSChromosome
(
chromo
,
globalOpList
);
// 对应 C# GenerateGSChromosome
}
else
if
(
i
<
lsCount
)
{
// 局部选择(LS):按GlobalOpId顺序生成MachineSelection(仅负载计算范围不同)
for
(
int
i
=
0
;
i
<
lsCount
;
i
++)
{
population
.
add
(
generateLSChromosome
(
globalOpList
,
param
.
getMachineCount
()));
}
generateLSChromosome
(
chromo
,
globalOpList
);
}
else
{
// 随机选择(RS):按GlobalOpId顺序生成MachineSelection(仅机器选择随机)
for
(
int
i
=
0
;
i
<
rsCount
;
i
++)
{
population
.
add
(
generateRSChromosome
(
globalOpList
,
param
.
getMachineCount
()));
generateRSChromosome
(
chromo
,
globalOpList
);
}
population
.
add
(
chromo
);
// 赋值到数组,线程安全(数组索引唯一)
});
return
population
;
}
/**
* 全局选择(GS)生成染色体(按GlobalOpId顺序生成MachineSelection)
*/
private
Chromosome
generateGSChromosome
(
List
<
GlobalOperationInfo
>
globalOpList
,
int
machineCount
)
{
Chromosome
chromosome
=
new
Chromosome
();
private
Chromosome
generateGSChromosome
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
Map
<
Integer
,
Integer
>
machineLoad
=
new
HashMap
<>();
// int[] machineLoad = new int[machineCount + 1]; // 设备负载(1-based,设备ID从1开始)
List
<
Integer
>
ms
=
new
ArrayList
<>();
// MachineSelection(顺序=GlobalOpId顺序)
...
...
@@ -106,7 +115,7 @@ public class Initialization {
.
findFirst
();
// 计算该机器在“可选机器列表”中的顺序号(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
);
// 更新设备负载
...
...
@@ -132,8 +141,9 @@ public class Initialization {
/**
* 局部选择(LS)生成染色体(按GlobalOpId顺序,每个订单重新初始化负载)
*/
private
Chromosome
generateLSChromosome
(
List
<
GlobalOperationInfo
>
globalOpList
,
int
machineCount
)
{
Chromosome
chromosome
=
new
Chromosome
();
private
Chromosome
generateLSChromosome
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
List
<
Integer
>
ms
=
new
ArrayList
<>();
List
<
Integer
>
os
=
new
ArrayList
<>();
Random
rnd
=
new
Random
();
...
...
@@ -199,8 +209,9 @@ public class Initialization {
/**
* 随机选择(RS)生成染色体(按GlobalOpId顺序,随机选择机器)
*/
private
Chromosome
generateRSChromosome
(
List
<
GlobalOperationInfo
>
globalOpList
,
int
machineCount
)
{
Chromosome
chromosome
=
new
Chromosome
();
private
Chromosome
generateRSChromosome
(
Chromosome
chromosome
,
List
<
GlobalOperationInfo
>
globalOpList
)
{
List
<
Integer
>
ms
=
new
ArrayList
<>();
List
<
Integer
>
os
=
new
ArrayList
<>();
Random
rnd
=
new
Random
();
...
...
src/main/java/com/aps/service/Algorithm/MachineCalculator.java
0 → 100644
View file @
ee581dc1
This diff is collapsed.
Click to expand it.
src/main/java/com/aps/service/plan/PlanResultService.java
View file @
ee581dc1
package
com
.
aps
.
service
.
plan
;
import
com.aps.common.util.FileHelper
;
import
com.aps.common.util.JsonFileReader
;
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.Schedule.GenVO
;
import
com.aps.entity.Schedule.MachineVO
;
...
...
@@ -13,9 +18,7 @@ import org.springframework.stereotype.Service;
import
java.io.IOException
;
import
java.math.BigDecimal
;
import
java.time.LocalDateTime
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.*
;
import
java.util.stream.Collectors
;
@Service
...
...
@@ -92,10 +95,9 @@ public class PlanResultService {
}
}
public
List
<
ScheduleChromosome
>
execute1
()
{
public
List
<
Chromosome
>
execute1
()
{
try
{
Entry
entry
=
new
Entry
();
// 1. 读取数据
List
<
Machine
>
machines
=
loadData
(
"machines.json"
,
Machine
.
class
);
...
...
@@ -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
(
...
...
@@ -134,34 +141,118 @@ public class PlanResultService {
// 3. 创建调度服务
MachineSchedulerService
machineScheduler
=
new
MachineSchedulerService
(
holidays
,
LocalDateTime
.
of
(
2025
,
10
,
1
,
0
,
0
,
0
));
holidays
,
param
.
getBaseTime
(
));
// 4. 初始化机器时间线
for
(
Machine
machine
:
machines
)
{
MachineTimeline
timeline
=
machineScheduler
.
getOrCreateTimeline
(
machine
);
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. 执行调度算法
GeneticAlgorithm
scheduler
=
new
GeneticAlgorithm
();
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
List
<
ScheduleChromosome
>
scheduleChromosomes
=
null
;
scheduler
.
Run
();
GeneticAlgorithm
scheduler
=
new
GeneticAlgorithm
(
machines
,
orders
,
null
,
machineScheduler
);
//new GeneticAlgorithm(products, machines, orders, machineScheduler);
List
<
Chromosome
>
Chromosomes
=
scheduler
.
Run
(
param
,
allOperations
);
// 对调度结果按照 fitness 由高到低排序
scheduleChromosomes
.
sort
((
c1
,
c2
)
->
Double
.
compare
(
c2
.
getFitness
(),
c1
.
getFitness
()));
Chromosomes
.
forEach
(
this
::
WriteScheduleSummary
);
// 为每个 ScheduleChromosome 分配场景ID(基于排序后的位置)
for
(
int
i
=
0
;
i
<
scheduleChromosomes
.
size
();
i
++)
{
scheduleChromosomes
.
get
(
i
).
setSceneId
(
i
+
1
);
// 场景ID从1开始
}
return
scheduleChromosomes
;
return
Chromosomes
;
}
catch
(
Exception
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加载
...
...
src/main/resources/application.yml
View file @
ee581dc1
...
...
@@ -23,23 +23,23 @@ spring:
# 默认数据源
strict
:
false
# 关闭严格模式
datasource
:
# MySQL数据源
mysql
:
driver-class-name
:
com.mysql.cj.jdbc.Driver
url
:
jdbc:mysql://192.168.0.181:3310/mes?useSSL=false&serverTimezone=UTC
username
:
root
# 替换为你的MySQL用户名
password
:
root_mes@123456~
# 替换为你的MySQL密码
#
# MySQL数据源
#
mysql:
#
driver-class-name: com.mysql.cj.jdbc.Driver
#
url: jdbc:mysql://192.168.0.181:3310/mes?useSSL=false&serverTimezone=UTC
#
username: root # 替换为你的MySQL用户名
#
password: root_mes@123456~ # 替换为你的MySQL密码
# Oracle数据源
oracle
:
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用户名
password
:
root_mes123456
# 替换为你的Oracle密码
sqlserver
:
driver-class-name
:
com.microsoft.sqlserver.jdbc.SQLServerDriver
url
:
jdbc:sqlserver://192.168.0.181:1434;databaseName=mes;encrypt=false
username
:
sa
password
:
root_mes123456
#
sqlserver:
#
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
#
url: jdbc:sqlserver://192.168.0.181:1434;databaseName=mes;encrypt=false
#
username: sa
#
password: root_mes123456
# 文件上传配置
...
...
src/main/resources/machines.json
View file @
ee581dc1
...
...
@@ -5,6 +5,8 @@
"startTime"
:
"08:00:00"
,
"endTime"
:
"18:00:00"
,
"days"
:
[
1
,
2
,
3
,
4
,
5
],
"startDate"
:
"2025-10-10T00:00:00"
,
"endDate"
:
"2025-11-10T00:00:00"
,
"shiftDate"
:
"0001-01-01T00:00:00"
,
"temporaryShift"
:
false
,
"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