Skip to content

Commit 7687543

Browse files
committed
NEW
1 parent 22e9cba commit 7687543

23 files changed

+3926
-2
lines changed

.idea/.name

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/inspectionProfiles/Project_Default.xml

Lines changed: 40 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/workspace.xml

Lines changed: 19 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extend/flutter/pso/assets/img.png

23 KB
Loading

extend/flutter/pso/assets/matply.dll

132 KB
Binary file not shown.

extend/flutter/pso/assets/pso.html

Lines changed: 1089 additions & 0 deletions
Large diffs are not rendered by default.

extend/flutter/pso/assets/pso.md

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
# 粒子群算法
2+
3+
## 基本流程
4+
5+
```mermaid
6+
graph TD
7+
A[初始化粒子群] --> B[评估适应度函数]
8+
B --> C[更新个体最优和全局最优]
9+
C --> D[更新速度和位置]
10+
D --> E{终止条件满足?}
11+
E -->|否| B
12+
E -->|是| F[输出结果]
13+
```
14+
15+
## 代码
16+
```python
17+
import numpy
18+
import matplotlib.pyplot as plt
19+
20+
# 目标函数
21+
def objectiveFunc(x : numpy.ndarray, _max : bool = True) -> numpy.ndarray:
22+
return x * numpy.sin(2 * x) - 5 * x * numpy.cos(2 * x) if _max \
23+
else -1 * (x * numpy.sin(2 * x) - 5 * x * numpy.cos(2 * x))
24+
25+
# 初始化粒子位置和速度
26+
def initialize_particles(n_particles : int, dim : int, lb : float, ub : float) -> [numpy.ndarray]:
27+
pos = numpy.random.uniform(lb, ub, (n_particles, dim))
28+
vel = numpy.random.uniform(-1, 1, (n_particles, dim))
29+
return pos, vel
30+
31+
# 计算适应度值
32+
def calculate_fitness(pos : numpy.ndarray, _max : bool = True) -> numpy.ndarray:
33+
return objectiveFunc(pos, _max)
34+
35+
# 更新个体最优和全局最优
36+
def update_best_positions(
37+
pos : numpy.ndarray,
38+
fitness : numpy.ndarray,
39+
pbest : numpy.ndarray,
40+
pbest_value : numpy.ndarray,
41+
gbest : numpy.ndarray,
42+
gbest_value : numpy.ndarray,
43+
_max: bool
44+
) -> [numpy.ndarray]:
45+
if _max:
46+
better_idx = fitness > pbest_value
47+
pbest[better_idx] = pos[better_idx]
48+
pbest_value[better_idx] = fitness[better_idx]
49+
50+
current_best_idx = numpy.argmax(fitness)
51+
current_best_value = fitness[current_best_idx]
52+
53+
if current_best_value > gbest_value:
54+
gbest = pos[current_best_idx]
55+
gbest_value = current_best_value
56+
else:
57+
better_idx = fitness < pbest_value
58+
pbest[better_idx] = pos[better_idx]
59+
pbest_value[better_idx] = fitness[better_idx]
60+
61+
current_best_idx = numpy.argmin(fitness)
62+
current_best_value = fitness[current_best_idx]
63+
64+
if current_best_value < gbest_value:
65+
gbest = pos[current_best_idx]
66+
gbest_value = current_best_value
67+
68+
return pbest, pbest_value, gbest, gbest_value
69+
70+
# 更新粒子速度和位置
71+
def update_particles(
72+
pos : numpy.ndarray,
73+
vel : numpy.ndarray,
74+
pbest : numpy.ndarray,
75+
gbest : numpy.ndarray,
76+
w : float,
77+
c1 : float,
78+
c2 : float
79+
) -> [numpy.ndarray]:
80+
r1 = numpy.random.rand(*pos.shape)
81+
r2 = numpy.random.rand(*pos.shape)
82+
vel = (w * vel +
83+
c1 * r1 * (pbest - pos) +
84+
c2 * r2 * (gbest - pos))
85+
pos += vel
86+
return pos, vel
87+
88+
# 限制粒子位置在边界范围内
89+
def apply_bounds(pos : numpy.ndarray, lb : float, ub : float) -> numpy.ndarray:
90+
return numpy.clip(pos, lb, ub)
91+
92+
# 粒子群优化主函数
93+
def pso(n_particles : int, n_iterations : int, lb : float, ub : float, _max: bool = True):
94+
dim = 1 # 只有一个维度
95+
96+
# 初始化
97+
pos, vel = initialize_particles(n_particles, dim, lb, ub)
98+
pbest = pos.copy()
99+
pbest_value = calculate_fitness(pbest, _max)
100+
gbest = pbest[numpy.argmax(pbest_value)] if _max else pbest[numpy.argmin(pbest_value)]
101+
gbest_value = numpy.max(pbest_value) if _max else numpy.min(pbest_value)
102+
103+
# 用于存储每次迭代的粒子位置
104+
all_positions = []
105+
106+
# PSO主循环
107+
w = 0.5 # 惯性权重,控制速度
108+
c1 = 1.5 # 个体学习因子,控制个体往自身最佳路径的偏移趋向
109+
c2 = 1.5 # 社会学习因子,控制个体往全局最佳路径的偏移趋向
110+
111+
for _ in range(n_iterations):
112+
all_positions.append(pos.copy()) # 记录每次迭代的粒子位置
113+
fitness = calculate_fitness(pos, _max)
114+
pbest, pbest_value, gbest, gbest_value = update_best_positions(
115+
pos, fitness, pbest, pbest_value, gbest, gbest_value, _max)
116+
pos, vel = update_particles(pos, vel, pbest, gbest, w, c1, c2)
117+
pos = apply_bounds(pos, lb, ub)
118+
119+
return gbest, gbest_value, all_positions
120+
121+
# 参数设置
122+
n_particles = 30 # 粒子数,也就是种群数目
123+
n_iterations = 100 # 迭代次数
124+
lb = -4 # 上下限
125+
ub = 4
126+
127+
# 执行粒子群优化
128+
optimal_x, optimal_f, all_positions = pso(n_particles, n_iterations, lb, ub, _max=True)
129+
print("最优解 x:", optimal_x)
130+
print("最大值:", optimal_f)
131+
132+
# 绘制目标函数和最优解
133+
x = numpy.linspace(-4, 4, 1000)
134+
y = x * numpy.sin(2 * x) - 5 * x * numpy.cos(2 * x)
135+
136+
plt.figure(figsize=(8, 6))
137+
plt.plot(x, y, lw=1)
138+
plt.scatter(optimal_x, optimal_f, c='red', s=100)
139+
plt.show()
140+
141+
```
142+
143+
## 效果
144+
- 红色点即最优解
145+
146+
![img](assets/img.png)
147+
148+
## 采用Dart的matply库进行测试
149+
```dart
150+
import 'matply.dart';
151+
152+
// 参数设置
153+
const n_particles = 30; // 粒子数,也就是种群数目
154+
const n_iterations = 100; // 迭代次数
155+
const lb = -4.0; // 上下限
156+
const ub = 4.0;
157+
158+
// 目标函数
159+
MatrixType objectiveFunc({required MatrixType x}) => x * (x * 2).sin - x * 5 * (x * 2).cos;
160+
161+
// 初始化粒子位置和速度
162+
List<MatrixType> initialize_particles({
163+
required int n_particles,
164+
int dim = 1,
165+
required double lb,
166+
required double ub
167+
}){
168+
final pos = MatrixType.uniform(row: n_particles, column: dim, start: lb, end: ub);
169+
final vel = MatrixType.uniform(row: n_particles, column: dim, start: -1.0, end: 1.0);
170+
return [pos, vel];
171+
}
172+
173+
// 计算适应度值
174+
MatrixType calculate_fitness({required MatrixType pos}) => objectiveFunc(x : pos);
175+
176+
List update_best_positions({
177+
required MatrixType pos,
178+
required MatrixType fitness,
179+
required MatrixType pbest,
180+
required MatrixType pbest_value,
181+
required double gbest,
182+
required double gbest_value
183+
}){
184+
List<List<bool>> better_idx = fitness < pbest_value;
185+
for (int r = 0;r < better_idx.length;r++){
186+
for (int c = 0;c < better_idx[0].length;c ++){
187+
if (better_idx[r][c]){
188+
pbest[r][c] = pos[r][c];
189+
pbest_value[r][c] = fitness[r][c];
190+
}
191+
}
192+
}
193+
int current_best_idx = fitness.argmin(dim: -1) as int;
194+
double current_best_value = fitness.min(dim: -1) as double;
195+
if (current_best_value < gbest_value){
196+
gbest = pos[current_best_idx][0];
197+
gbest_value = current_best_value;
198+
}
199+
return [pbest, pbest_value, gbest, gbest_value];
200+
}
201+
202+
// 更新粒子速度和位置
203+
List<MatrixType> update_particles({
204+
required MatrixType pos,
205+
required MatrixType vel,
206+
required MatrixType pbest,
207+
required double gbest,
208+
required double w,
209+
required double c1,
210+
required double c2
211+
}) {
212+
MatrixType r1 = MatrixType.uniform(row: pos.shape[0], column: pos.shape[1]);
213+
MatrixType r2 = MatrixType.uniform(row: pos.shape[0], column: pos.shape[1]);
214+
vel = (vel * w + r1 * c1 * (pbest - pos) + r2 * c2 * (pos * (-1) + gbest));
215+
pos += vel;
216+
return [pos, vel];
217+
}
218+
219+
// 限制粒子位置在边界范围内
220+
MatrixType apply_bounds({required MatrixType pos, required double lb, required double ub})
221+
=> pos.clip(lb: lb, ub: ub);
222+
223+
// 粒子群优化主函数
224+
List pso({
225+
required int n_particles,
226+
required int n_iterations,
227+
required double lb,
228+
required double ub
229+
}){
230+
var a1 = initialize_particles(n_particles:n_particles, dim : 1, lb : lb, ub : ub);
231+
MatrixType pos = a1[0], vel = a1[1];
232+
MatrixType pbest = MatrixType.deepCopy(pos);
233+
MatrixType pbest_value = calculate_fitness(pos: pbest);
234+
double gbest = pbest[pbest_value.argmin(dim: -1) as int][0];
235+
double gbest_value = pbest_value.min() as double;
236+
List<MatrixType> all_positions = [];
237+
final w = 0.5; // 惯性权重,控制速度
238+
final c1 = 1.5; // 个体学习因子,控制个体往自身最佳路径的偏移趋向
239+
final c2 = 1.5; // 社会学习因子,控制个体往全局最佳路径的偏移趋向
240+
for (int _ = 0;_ < n_iterations;_++){
241+
all_positions.add(MatrixType.deepCopy(pos));
242+
MatrixType fitness = calculate_fitness(pos: pos);
243+
var l = update_best_positions(
244+
pos: pos,
245+
fitness:fitness,
246+
pbest: pbest,
247+
pbest_value: pbest_value,
248+
gbest: gbest,
249+
gbest_value: gbest_value
250+
); // return [pbest, pbest_value, gbest, gbest_value]
251+
pbest = l[0];
252+
pbest_value = l[1];
253+
gbest = l[2];
254+
gbest_value = l[3];
255+
var l1 = update_particles(pos:pos, vel:vel, pbest:pbest, gbest:gbest, w:w, c1:c1, c2:c2);
256+
pos = l1[0];
257+
vel = l1[1];
258+
pos = apply_bounds(pos:pos,lb: lb,ub: ub);
259+
}
260+
return [gbest, gbest_value, all_positions];
261+
}
262+
263+
main(){
264+
var l = pso(n_particles : n_particles, n_iterations : n_iterations, lb: lb, ub: ub);
265+
var optimal_x = l[0], optimal_f = l[1], _ = l[2];
266+
print("最优解 x: $optimal_x");
267+
print("最小值: $optimal_f");
268+
}
269+
270+
// outputs : 最优解 x: 3.129773849645863
271+
// 最小值: -15.718471132486712
272+
```
273+
274+
<!-- ![下载本期汇报软件](pso.zip) -->

extend/flutter/pso/assets/pso.zip

11.2 MB
Binary file not shown.

0 commit comments

Comments
 (0)