Skip to content

Commit 459ae2a

Browse files
committed
review all files, write more comments
1 parent ba83162 commit 459ae2a

39 files changed

+581
-538
lines changed

fluid_coarse/bba.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1-
# https://github.com/Sanbongawa/binary_swarm_intelligence
1+
# reference: https://github.com/Sanbongawa/binary_swarm_intelligence
22

33
import math
44

55
import torch
66
import tqdm
77

88

9+
@torch.no_grad()
910
def bba(func, x0=None, n=200, maxiter=2000, topk=100, is_min=True, fmin=0, fmax=2, loud_A=0.25, r0=0.4, alpha=0.999, gamma=10., progress=False):
1011
"""
12+
Binary Bat Algorithm
1113
input:{ func: Evaluate_Function, type is nn.Module
1214
x0: initial guess of the solution
13-
n: Number of population, default=20
14-
maxiter: Number of max iteration, default=300
15+
n: Number of population
16+
maxiter: Number of max iteration
1517
topk: the number of states to output (see output best_s_list)
1618
is_min: minimizing (True) or maximizing (False) func
1719
fmin: a hyperparamter, frequency minimum to step
1820
fmax: a hyperparamter, frequency maximum to step
19-
loud_A: a hyperparamter, value of Loudness, default=0.25
21+
loud_A: a hyperparamter, value of Loudness
2022
r0: a hyperparamter, pulse rate, Probability to relocate near the best position
2123
alpha: a hyperparamter, decay rate of loud_A
2224
gamma: a hyperparamter, decay rate of gamma
@@ -29,28 +31,28 @@ def bba(func, x0=None, n=200, maxiter=2000, topk=100, is_min=True, fmin=0, fmax=
2931
}
3032
"""
3133

32-
device = next(func.parameters()).device
34+
device = next(func.parameters()).device # get device(CPU/GPU) from `func`
3335
dim = x0.shape[1]
3436

37+
# initialize
3538
v = torch.zeros(n, dim, device=device)
36-
3739
x = torch.rand(n - 1, dim)
38-
x = (x > 0.9).type_as(x0)
40+
x = (x > 0.9).type_as(x0) # convert to binary
3941
x = torch.cat([x, x0], dim=0)
4042

41-
torch.set_grad_enabled(False)
4243
fit = func(x) if is_min else -func(x)
4344
min_fit = fit.min()
4445
best_v = min_fit
4546
best_s = x[fit.argmin()].reshape((1, -1))
46-
best_list = []
47+
best_v_list = []
4748

4849
if progress:
4950
m = tqdm.tqdm(range(maxiter))
5051
else:
5152
m = range(maxiter)
5253
for t in m:
5354

55+
# update parameters
5456
r = r0 * (1 - torch.exp(torch.tensor(-gamma * t, device=device)))
5557
loud_A *= alpha
5658

@@ -61,10 +63,10 @@ def bba(func, x0=None, n=200, maxiter=2000, topk=100, is_min=True, fmin=0, fmax=
6163
x_new = x.clone()
6264

6365
# flip
64-
accept = torch.rand(n, dim, device=device) < vstf + 1 / 160
66+
accept = torch.rand(n, dim, device=device) < vstf + 1 / dim
6567
x_new[accept] = 1. - x_new[accept]
6668

67-
# local opt
69+
# accept local optimum
6870
accept = torch.rand(n, dim, device=device) > r
6971
x_new[accept] = best_s.expand(n, dim)[accept]
7072

@@ -77,14 +79,15 @@ def bba(func, x0=None, n=200, maxiter=2000, topk=100, is_min=True, fmin=0, fmax=
7779
x[accept, :] = x_new[accept, :]
7880
fit[accept] = fit_new[accept]
7981

82+
# update best solution
8083
min_fit, argmin_f = fit.min(0)
81-
8284
if min_fit < best_v:
8385
best_s = x[argmin_f].reshape((1, -1)).clone()
8486
best_v = min_fit.clone()
8587

86-
best_list.append(best_v if is_min else - best_v)
88+
best_v_list.append(best_v if is_min else - best_v)
8789

88-
best_s_list = torch.unique(torch.cat((fit, x), dim=1), dim=0)[0:topk, :]
90+
# postprcess, get ready to output
91+
best_s_list = torch.unique(torch.cat((fit, x), dim=1), dim=0)[0:topk, :] # delete repeated solutions
8992

90-
return (best_v if is_min else - best_v), best_s, best_s_list, best_list
93+
return (best_v if is_min else - best_v), best_s, best_s_list, best_v_list

fluid_coarse/func_inputs_gen.m

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
function inputs = func_inputs_gen(n,seed_gen,base,nx,ny,p,inputs_ori,n_coeff)
2-
% generate inputs by three ways based on args
2+
% generate new inputs (samples) by three ways based on args
33
% 1) if `base` is empty, meaning the inital step, then 161 arrays will be
44
% generated
55
% 2) if `base` is not empty, `p` is empty, employ SOLO-G, return base
6-
% 3) if `base` is not empty, `p` is not empty, employ SOLO-R, add
7-
% disturbance
6+
% 3) if `base` is not empty, `p` is not empty, employ SOLO-R, add disturbance
7+
8+
% Inputs:
9+
% iter: number of total samples that needs to output
10+
% base: base design, i.e., the optimized solution from DNN in SOLO
11+
% p: empty or [a1,a2,a3,...,an] where `ai` (i<n) denotes the probability to mutate a ixi matrix, and `an` denotes convolution possbility
12+
% inputs_ori: existing samples, used to remove repeated ones of new samples
13+
% n_coeff: a coefficient to generate more samples than needed. Since repeated samples will be deleted later, more samples are needed at the generation stage
814
rng(seed_gen);
915
base_empty=isempty(base);
1016
alpha=4;
1117

1218
if ~exist('n_coeff','var')
13-
n_coeff=100; % used when p exist
19+
n_coeff=100; % set a default value, used when p exist
1420
end
1521

1622

fluid_coarse/main_greedy.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@
1212
n=10; % number of additional samples per iteration
1313
n_0=161; % number of samples in the initial batch
1414
results(:,1)=(n:n:n*iter)';
15-
seed_train=3; % DNN training random seed
16-
seed_opt=123; % BBA optimization random seed
15+
seed_train=3; % random seed for DNN training
16+
seed_opt=123; % random seed for BBA optimization
1717
nx=a/delta; % number of design variables in x direction
1818
ny=b/delta; % number of design variables in y direction
1919
%% loops
2020

2121
for i=1:iter
2222
% get input/output file names
23-
testfile=['./',folder,'/',num2str(n),'ntrain_test_step',num2str(i),'.mat'];
2423
optfile=['./',folder,'/',num2str(n),'ntrain_opt_step',num2str(i),'.mat'];
2524
trainfile=['./',folder,'/',num2str(n),'ntrain_train_step',num2str(i),'.mat'];
2625

@@ -31,7 +30,8 @@
3130
% eliminate invalid data
3231
inputs(outputs==Inf,:,:)=[];
3332
outputs(outputs==Inf)=[];
34-
if i>1
33+
34+
if i>1 % if not initial batch, combine data
3535
mydata=load(['./',folder,'/',num2str(n),'ntrain_train_step',num2str(i-1),'.mat']);
3636
inputs=[mydata.inputs;inputs];
3737
outputs=[mydata.outputs;outputs];

fluid_coarse/main_regular.m

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@
1717
nx=a/delta; % number of design variables in x direction
1818
ny=b/delta; % number of design variables in y direction
1919
%% loops
20-
p=[0.1,0.1,0.2,0.2,0.2];
20+
p=[0.1,0.1,0.2,0.2,0.2]; % [a1,a2,a3,...,an] where `ai` (i<n) denotes the probability to mutate a ixi matrix, and `an` denotes crossover possbility
2121
for i=1:iter
2222
% get input/output file names
23-
testfile=['./',folder,'/',num2str(n),'ntrain_test_step',num2str(i),'.mat'];
2423
optfile=['./',folder,'/',num2str(n),'ntrain_opt_step',num2str(i),'.mat'];
2524
trainfile=['./',folder,'/',num2str(n),'ntrain_train_step',num2str(i),'.mat'];
2625

fluid_coarse/plot_b_d_e.m

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
%% set parameters and preprocessing
99
g=round(p0./g,6); % there are equivalent solutions with very slight different outputs, use round to eliminate numerical error
1010
r=p0./r;
11+
font='Times';
1112
%% generate some beautiful colors
1213
colors=func_linspecer(8);
1314
%% energy (objective)
@@ -18,16 +19,16 @@
1819
plot(func_best_min(r),'-','Color',colors(7,:),'LineWidth',3);hold on;
1920

2021
xl=xlabel('$n_{train}$','Interpreter','latex');
21-
yl=ylabel('$\tilde{P}$','Interpreter','latex','Rotation',0);
22+
yl=ylabel('$\widetilde{P}$','Interpreter','latex','Rotation',0);
2223
[y,x]=min(g);
2324
scatter(x,y,300,colors(6,:),'x','LineWidth',2); hold on;
2425
[y,x]=min(r);
2526
scatter(x,y,300,colors(7,:),'x','LineWidth',2); hold on;
2627

27-
lgd=legend('Gradient-based','SOLO-G','SOLO-R','Interpreter','latex');
28+
lgd=legend('Gradient-based','SOLO-G','SOLO-R');
2829
lgd.Position=([0.6529 0.7008 0.3305 0.2692]);
2930

30-
set(gca,'FontSize',fontsize,'Fontname', 'Times New Roman', 'Position',[0.1,0.13,0.7750,0.7950])
31+
set(gca,'FontSize',fontsize,'Fontname', font, 'Position',[0.1,0.13,0.7750,0.7950])
3132
xl.Position=[2.7169e+03 0.9605 -1];
3233
yl.Position=[-222.5806 0.9971 -1];
3334
ylim([0.955,1])
@@ -69,7 +70,7 @@
6970
[val, idx]=min(g);
7071
inputs=gdata.inputs;
7172
input=inputs(idx,:,:);
72-
h=heatmap(squeeze(1-input)','CellLabelColor','none','FontName','Times New Roman','FontSize',20);
73+
h=heatmap(squeeze(1-input)','CellLabelColor','none','FontName',font,'FontSize',20);
7374
colormap(gray)
7475
colorbar off
7576
h.Position=[0.1,0.2,0.8,0.8];
@@ -82,7 +83,7 @@
8283
[val, idx]=min(r);
8384
inputs=rdata.inputs;
8485
input=inputs(idx,:,:);
85-
h=heatmap(squeeze(1-input)','CellLabelColor','none','FontName','Times New Roman','FontSize',20);
86+
h=heatmap(squeeze(1-input)','CellLabelColor','none','FontName',font,'FontSize',20);
8687
colormap(gray)
8788
colorbar off
8889
h.Position=[0.1,0.2,0.8,0.8];

fluid_coarse/plot_c.m

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
%% comsol server required, you can jump to `plot` if data is downloaded
2-
model = mphload('fluid_optimized.mph');
3-
data=mpheval(model,{'dtopo1.theta'},'selection',2,'edim','domain','dataset','dset2');
42
a=2;
53
b=0.8;
6-
delta=0.1;
4+
delta=0.05;
75
nx=a/delta;
86
ny=b/delta;
7+
8+
% extract nodal values
9+
model = mphload('fluid_optimized.mph');
10+
data=mpheval(model,{'dtopo1.theta'},'selection',2,'edim','domain','dataset','dset2');
911
indices=round(data.p./delta+1);
1012
input_node=zeros(nx+1,ny+1);
1113
for i=1:size(indices,2)
@@ -33,11 +35,13 @@
3335
outputs = func_outputs_nowrite(inputs_unique,nx,ny);
3436
[val, idx]=max(outputs);
3537
save('data_gb.mat','idx','outputs','inputs_unique');
36-
% 1.557373167442459
38+
% val=1.557373167442459
3739
%% plot
40+
font='Times';
41+
load('data_gb.mat');
3842
figure('Position',[0,0,500,200])
3943
input=inputs_unique(idx,:,:);
40-
h=heatmap(squeeze(1-input)','CellLabelColor','none','FontName','Times New Roman','FontSize',20);
44+
h=heatmap(squeeze(1-input)','CellLabelColor','none','FontName',font,'FontSize',20);
4145
colormap(gray)
4246
colorbar off
4347
h.Position=[0.1,0.2,0.8,0.8];

fluid_coarse/readme.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,13 @@ from [Google Drive](https://drive.google.com/drive/folders/1f6Xrd9e-RAUsh9vqIqUX
5353
## How to run
5454

5555
1. Connect MATLAB with COMSOL server
56-
2. Run __fluid.m__ by COMSOL to generate __fluid.mph__
56+
2. Run __fluid.m__ by COMSOL to generate __fluid.mph__, or download it
57+
from [Google Drive](https://drive.google.com/drive/folders/1f6Xrd9e-RAUsh9vqIqUXbEw8F1_2Qg_5?usp=sharing)
5758
3. Set up MATLAB such that it can call python scripts ([instructions](https://www.mathworks.com/help/matlab/call-python-libraries.html))
5859
4. Run __main_greedy.m__ and __main_regular.m__
5960
5. [optional] Run __plot_b_d_e.m__ and __plot_s\[4-6\].m__
60-
6. Run __fluid_optimized.m__ by _COMSOL_ to generate __fluid_optimized.mph__
61+
6. Run __fluid_optimized.m__ by _COMSOL_ to generate __fluid_optimized.mph__, or download it
62+
from [Google Drive](https://drive.google.com/drive/folders/1f6Xrd9e-RAUsh9vqIqUXbEw8F1_2Qg_5?usp=sharing)
6163
7. [optional] Run __plot_c.m__
6264

6365
As long as a __*.m__ file says `Comsol server required` in the comment at the top, you need to connect the MATLAB with a COMSOL server to run the

fluid_fine/bba.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1-
# https://github.com/Sanbongawa/binary_swarm_intelligence
1+
# reference: https://github.com/Sanbongawa/binary_swarm_intelligence
22

33
import math
44

55
import torch
66
import tqdm
77

88

9+
@torch.no_grad()
910
def bba(func, x0=None, n=200, maxiter=2000, topk=100, is_min=True, fmin=0, fmax=2, loud_A=0.25, r0=0.4, alpha=0.999, gamma=10., progress=False):
1011
"""
12+
Binary Bat Algorithm
1113
input:{ func: Evaluate_Function, type is nn.Module
1214
x0: initial guess of the solution
13-
n: Number of population, default=20
14-
maxiter: Number of max iteration, default=300
15+
n: Number of population
16+
maxiter: Number of max iteration
1517
topk: the number of states to output (see output best_s_list)
1618
is_min: minimizing (True) or maximizing (False) func
1719
fmin: a hyperparamter, frequency minimum to step
1820
fmax: a hyperparamter, frequency maximum to step
19-
loud_A: a hyperparamter, value of Loudness, default=0.25
21+
loud_A: a hyperparamter, value of Loudness
2022
r0: a hyperparamter, pulse rate, Probability to relocate near the best position
2123
alpha: a hyperparamter, decay rate of loud_A
2224
gamma: a hyperparamter, decay rate of gamma
@@ -29,28 +31,28 @@ def bba(func, x0=None, n=200, maxiter=2000, topk=100, is_min=True, fmin=0, fmax=
2931
}
3032
"""
3133

32-
device = next(func.parameters()).device
34+
device = next(func.parameters()).device # get device(CPU/GPU) from `func`
3335
dim = x0.shape[1]
3436

37+
# initialize
3538
v = torch.zeros(n, dim, device=device)
36-
3739
x = torch.rand(n - 1, dim)
38-
x = (x > 0.9).type_as(x0)
40+
x = (x > 0.9).type_as(x0) # convert to binary
3941
x = torch.cat([x, x0], dim=0)
4042

41-
torch.set_grad_enabled(False)
4243
fit = func(x) if is_min else -func(x)
4344
min_fit = fit.min()
4445
best_v = min_fit
4546
best_s = x[fit.argmin()].reshape((1, -1))
46-
best_list = []
47+
best_v_list = []
4748

4849
if progress:
4950
m = tqdm.tqdm(range(maxiter))
5051
else:
5152
m = range(maxiter)
5253
for t in m:
5354

55+
# update parameters
5456
r = r0 * (1 - torch.exp(torch.tensor(-gamma * t, device=device)))
5557
loud_A *= alpha
5658

@@ -62,9 +64,11 @@ def bba(func, x0=None, n=200, maxiter=2000, topk=100, is_min=True, fmin=0, fmax=
6264

6365
# flip
6466
accept = torch.rand(n, dim, device=device) < vstf + 1 / 160
67+
# TODO: I made a mistake here, `160` above should be `dim` to match the paper (although I do not think it matters).
68+
# I kept this mistake to help repeat my result, but you can change it for new problems
6569
x_new[accept] = 1. - x_new[accept]
6670

67-
# local opt
71+
# accept local optimum
6872
accept = torch.rand(n, dim, device=device) > r
6973
x_new[accept] = best_s.expand(n, dim)[accept]
7074

@@ -77,14 +81,15 @@ def bba(func, x0=None, n=200, maxiter=2000, topk=100, is_min=True, fmin=0, fmax=
7781
x[accept, :] = x_new[accept, :]
7882
fit[accept] = fit_new[accept]
7983

84+
# update best solution
8085
min_fit, argmin_f = fit.min(0)
81-
8286
if min_fit < best_v:
8387
best_s = x[argmin_f].reshape((1, -1)).clone()
8488
best_v = min_fit.clone()
8589

86-
best_list.append(best_v if is_min else - best_v)
90+
best_v_list.append(best_v if is_min else - best_v)
8791

88-
best_s_list = torch.unique(torch.cat((fit, x), dim=1), dim=0)[0:topk, :]
92+
# postprcess, get ready to output
93+
best_s_list = torch.unique(torch.cat((fit, x), dim=1), dim=0)[0:topk, :] # delete repeated solutions
8994

90-
return (best_v if is_min else - best_v), best_s, best_s_list, best_list
95+
return (best_v if is_min else - best_v), best_s, best_s_list, best_v_list

fluid_fine/main_greedy.m

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,19 @@
77
delta=0.05; % grid size of design variables
88

99
base=[]; % initial guess of solution
10-
iter=200; % total number of iterations of the algorithm
10+
iter=200; % number of total iterations of the algorithm
1111
results=zeros(iter,3); % initialize result table
1212
n=10; % number of additional samples per iteration
1313
n_0=641; % number of samples in the initial batch
1414
results(:,1)=(n:n:n*iter)';
15-
seed_train=3; % DNN training random seed
16-
seed_opt=123; % BBA optimization random seed
15+
seed_train=3; % random seed for DNN training
16+
seed_opt=123; % random seed for BBA optimization
1717
nx=a/delta; % number of design variables in x direction
1818
ny=b/delta; % number of design variables in y direction
1919

2020
%% loops
2121
for i=1:iter
2222
% get input/output file names
23-
testfile=['./',folder,'/',num2str(n),'ntrain_test_step',num2str(i),'.mat'];
2423
optfile=['./',folder,'/',num2str(n),'ntrain_opt_step',num2str(i),'.mat'];
2524
trainfile=['./',folder,'/',num2str(n),'ntrain_train_step',num2str(i),'.mat'];
2625

@@ -31,8 +30,8 @@
3130
% eliminate invalid data
3231
inputs(outputs==Inf,:,:)=[];
3332
outputs(outputs==Inf)=[];
34-
%
35-
if i>1
33+
34+
if i>1 % if not initial batch, combine data
3635
mydata=load(['./',folder,'/',num2str(n),'ntrain_train_step',num2str(i-1),'.mat']);
3736
inputs=[mydata.inputs;inputs];
3837
outputs=[mydata.outputs;outputs];

0 commit comments

Comments
 (0)