├── B2OPT_pkg ├── B2OPT.egg-info │ ├── top_level.txt │ ├── dependency_links.txt │ ├── SOURCES.txt │ └── PKG-INFO ├── readme.md ├── requirements.txt ├── install.sh ├── B2OPT │ ├── __init__.py │ ├── imports.py │ ├── __pycache__ │ │ ├── __init__.cpython-38.pyc │ │ ├── imports.cpython-38.pyc │ │ └── problem.cpython-38.pyc │ ├── problem.py │ ├── utils.py │ └── model.py ├── dist │ └── B2OPT-1.0.0.tar.gz └── setup.py ├── exps ├── bbobOffsets_dim10.pkl ├── bbobOffsets_dim100.pkl ├── test.sh ├── train.sh ├── trails │ ├── exp(test1)_f(1)_dim(10).pkl │ ├── exp(test1)_f(2)_dim(10).pkl │ ├── exp(test1)_f(3)_dim(10).pkl │ ├── exp(test1)_f(4)_dim(10).pkl │ ├── exp(test1)_f(5)_dim(10).pkl │ ├── exp(test1)_f(6)_dim(10).pkl │ ├── exp(test1)_f(7)_dim(10).pkl │ ├── exp(test1)_f(8)_dim(10).pkl │ ├── exp(test1)_f(9)_dim(10).pkl │ ├── exp(test1)_f(10)_dim(10).pkl │ ├── exp(test1)_f(11)_dim(10).pkl │ ├── exp(test1)_f(12)_dim(10).pkl │ ├── exp(test1)_f(13)_dim(10).pkl │ ├── exp(test1)_f(14)_dim(10).pkl │ ├── exp(test1)_f(15)_dim(10).pkl │ ├── exp(test1)_f(16)_dim(10).pkl │ ├── exp(test1)_f(17)_dim(10).pkl │ ├── exp(test1)_f(18)_dim(10).pkl │ ├── exp(test1)_f(19)_dim(10).pkl │ ├── exp(test1)_f(20)_dim(10).pkl │ ├── exp(test1)_f(21)_dim(10).pkl │ ├── exp(test1)_f(22)_dim(10).pkl │ ├── exp(test1)_f(23)_dim(10).pkl │ ├── exp(test1)_f(24)_dim(10).pkl │ ├── exp(test1)_f(cecf4)_dim(10).pkl │ ├── exp(test1)_f(cecf5)_dim(10).pkl │ ├── exp(test1)_f(cecf6)_dim(10).pkl │ ├── exp(test1)_f(cecf7)_dim(10).pkl │ ├── exp(test1)_f(cecf8)_dim(10).pkl │ └── exp(test1)_f(cecf9)_dim(10).pkl ├── __pycache__ │ └── decorator.cpython-38.pyc ├── imgs │ └── trainloss │ │ └── test1_ems_30_ws_True_d10.png └── main.py ├── requirements.txt └── README.md /B2OPT_pkg/B2OPT.egg-info/top_level.txt: -------------------------------------------------------------------------------- 1 | B2OPT 2 | -------------------------------------------------------------------------------- /B2OPT_pkg/readme.md: -------------------------------------------------------------------------------- 1 | 这个安装包是B2OPT的核心模块。 2 | 3 | -------------------------------------------------------------------------------- /B2OPT_pkg/B2OPT.egg-info/dependency_links.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /B2OPT_pkg/requirements.txt: -------------------------------------------------------------------------------- 1 | setuptools==68.2.2 2 | torch==1.12.0 3 | -------------------------------------------------------------------------------- /B2OPT_pkg/install.sh: -------------------------------------------------------------------------------- 1 | python setup.py sdist 2 | pip install dist/*.tar.gz -------------------------------------------------------------------------------- /B2OPT_pkg/B2OPT/__init__.py: -------------------------------------------------------------------------------- 1 | name='B2OPT' 2 | __all__=['imports','model','problem','utils'] -------------------------------------------------------------------------------- /exps/bbobOffsets_dim10.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/bbobOffsets_dim10.pkl -------------------------------------------------------------------------------- /exps/bbobOffsets_dim100.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/bbobOffsets_dim100.pkl -------------------------------------------------------------------------------- /exps/test.sh: -------------------------------------------------------------------------------- 1 | python ./main.py -d 10 -expname test1 -ems 30 -ws True -popsize 100 -lr 0.001 -mode test -target sys -------------------------------------------------------------------------------- /B2OPT_pkg/dist/B2OPT-1.0.0.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/B2OPT_pkg/dist/B2OPT-1.0.0.tar.gz -------------------------------------------------------------------------------- /exps/train.sh: -------------------------------------------------------------------------------- 1 | python ./main.py -d 10 -expname test1 -ems 30 -ws True -popsize 100 -maxepoch 500 -lr 0.001 -mode train -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | matplotlib==3.7.5 2 | numpy==1.24.4 3 | setuptools==68.2.2 4 | torch==1.12.1+cu116 5 | tqdm==4.66.2 6 | -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(1)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(1)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(2)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(2)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(3)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(3)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(4)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(4)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(5)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(5)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(6)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(6)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(7)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(7)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(8)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(8)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(9)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(9)_dim(10).pkl -------------------------------------------------------------------------------- /exps/__pycache__/decorator.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/__pycache__/decorator.cpython-38.pyc -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(10)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(10)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(11)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(11)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(12)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(12)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(13)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(13)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(14)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(14)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(15)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(15)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(16)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(16)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(17)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(17)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(18)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(18)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(19)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(19)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(20)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(20)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(21)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(21)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(22)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(22)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(23)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(23)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(24)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(24)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(cecf4)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(cecf4)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(cecf5)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(cecf5)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(cecf6)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(cecf6)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(cecf7)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(cecf7)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(cecf8)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(cecf8)_dim(10).pkl -------------------------------------------------------------------------------- /exps/trails/exp(test1)_f(cecf9)_dim(10).pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/trails/exp(test1)_f(cecf9)_dim(10).pkl -------------------------------------------------------------------------------- /B2OPT_pkg/B2OPT/imports.py: -------------------------------------------------------------------------------- 1 | import torch 2 | DEVICE=torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /exps/imgs/trainloss/test1_ems_30_ws_True_d10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/exps/imgs/trainloss/test1_ems_30_ws_True_d10.png -------------------------------------------------------------------------------- /B2OPT_pkg/B2OPT/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/B2OPT_pkg/B2OPT/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /B2OPT_pkg/B2OPT/__pycache__/imports.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/B2OPT_pkg/B2OPT/__pycache__/imports.cpython-38.pyc -------------------------------------------------------------------------------- /B2OPT_pkg/B2OPT/__pycache__/problem.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninja-wm/B2Opt/HEAD/B2OPT_pkg/B2OPT/__pycache__/problem.cpython-38.pyc -------------------------------------------------------------------------------- /B2OPT_pkg/B2OPT/problem.py: -------------------------------------------------------------------------------- 1 | class Problem: 2 | def __init__(self): 3 | self.useRepaire=False 4 | 5 | 6 | def repaire(self,x): 7 | raise NotImplementedError 8 | 9 | def calfitness(self,x): 10 | raise NotImplementedError -------------------------------------------------------------------------------- /B2OPT_pkg/B2OPT.egg-info/SOURCES.txt: -------------------------------------------------------------------------------- 1 | setup.py 2 | B2OPT/__init__.py 3 | B2OPT/imports.py 4 | B2OPT/model.py 5 | B2OPT/problem.py 6 | B2OPT/utils.py 7 | B2OPT.egg-info/PKG-INFO 8 | B2OPT.egg-info/SOURCES.txt 9 | B2OPT.egg-info/dependency_links.txt 10 | B2OPT.egg-info/top_level.txt -------------------------------------------------------------------------------- /B2OPT_pkg/B2OPT.egg-info/PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 2.1 2 | Name: B2OPT 3 | Version: 1.0.0 4 | Home-page: 5 | Author: EUREKA 6 | Author-email: 2621843957@qq.com 7 | Classifier: Programming Language :: Python :: 3 8 | Classifier: License :: OSI Approved :: MIT License 9 | Classifier: Operating System :: OS Independent 10 | Description-Content-Type: text 11 | 12 | CODE OF B2OPT 13 | -------------------------------------------------------------------------------- /B2OPT_pkg/setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | setuptools.setup( 4 | name="B2OPT", 5 | version="1.0.0", 6 | author="EUREKA", 7 | author_email="2621843957@qq.com", 8 | description="", 9 | long_description="CODE OF B2OPT", 10 | long_description_content_type="text", 11 | url="", 12 | packages=setuptools.find_packages(), 13 | classifiers=[ 14 | "Programming Language :: Python :: 3", 15 | "License :: OSI Approved :: MIT License", 16 | "Operating System :: OS Independent", 17 | ], 18 | ) 19 | -------------------------------------------------------------------------------- /B2OPT_pkg/B2OPT/utils.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import pickle 3 | from B2OPT.imports import DEVICE 4 | 5 | def sampleBatchPop(batchSize,popSize,dim,xlb,xub): 6 | batchpop=torch.rand((batchSize,popSize,dim)).to(DEVICE) 7 | batchpop=batchpop*(xub-xlb)+xlb 8 | return batchpop 9 | 10 | def lossFunc(father,off,fun=None): 11 | return (torch.mean(fun['fun'](off,fun['bias']))-torch.mean( 12 | fun['fun'](father,fun['bias'])))/torch.abs(torch.mean(fun['fun'](father,fun['bias']))) 13 | # return 0.5*torch.mean(fun['fun'](off,fun['bias']))**2 14 | 15 | 16 | 17 | 18 | def reOffSet(fun,zeroOffset=True): 19 | ub=fun['bub'] 20 | lb=fun['blb'] 21 | dim=fun['dim'] 22 | # zeroOffset=True 23 | if not zeroOffset: 24 | bias=torch.rand(dim)*(ub-lb)+lb 25 | else: 26 | bias=torch.zeros(dim) 27 | fun['bias']=bias.to(DEVICE) 28 | return fun 29 | 30 | 31 | def dump(file,path): 32 | with open(path,'wb') as f: 33 | pickle.dump(file,f) 34 | 35 | 36 | 37 | 38 | def load(path): 39 | with open(path,'rb') as f: 40 | file=pickle.load(f) 41 | return file 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # B2Opt-Learning-to-Optimize-Black-box-Optimization-with-Little-Budget 2 | 3 | This repository is the official implementation of the source code of the paper [B2Opt: Learning to Optimize Black-box Optimization with Little Budget](https://arxiv.org/abs/2304.11787). 4 | 5 | # Installation 6 | 7 | This project requires running under the Ubuntu 20.04 system, and you need to install the cuda version of pytorch >= 1.12 first. And the python package [BBOB](https://github.com/ninja-wm/BBOB/tree/main) should be installed. Our python version is 3.8.2. First, please install the dependency packages in requirements. Then, please install B2Opt as follows: 8 | 9 | ```bash 10 | git clone git@github.com:ninja-wm/B2Opt-Learning-to-Optimize-Black-box-Optimization-with-Little-Budget.git 11 | cd B2Opt_pkg 12 | ./install.sh 13 | ``` 14 | 15 | # Quick Start 16 | 17 | Compared with the previous version, we have further packaged B2Opt in this version. This makes training and testing B2Opt easier. 18 | 19 | This tutorial can help you quickly reproduce the results of the synthetic function and BBOB in the paper. 20 | 21 | ```bash 22 | cd exps 23 | ``` 24 | 25 | * step1) Run the following command to view the command line interface parameter description: 26 | 27 | ```bash 28 | python ./main.py --help 29 | ``` 30 | 31 | * step 2) You can train on TF1-TF3 by executing the following command: 32 | 33 | ```bash 34 | python ./main.py -d 10 -expname test1 -ems 30 -ws True -popsize 100 -maxepoch 500 -lr 0.001 -mode train 35 | ``` 36 | 37 | ​ Note: The parameters d, expname, ems, ws and popsize determine the architecture of B2Opt and should therefore be consistent during testing and training. If you want to customize B2Opt and train it on other tasks, please read and modify main.py. 38 | 39 | * step 3) You can directly use the trained B2Opt to solve TF4-TF9 through the following command: 40 | 41 | ```bash 42 | python ./main.py -d 10 -expname test1 -ems 30 -ws True -popsize 100 -lr 0.001 -mode test -target sys 43 | ``` 44 | 45 | ​ Change the target parameter to "bbob" to solve the 24 functions of BBOB. 46 | 47 | # statement 48 | 49 | The code we provide can be run directly, but it is difficult for us to guarantee that it will execute smoothly on different platforms and different operating systems. If you encounter any problems, please submit an issue to help us improve it! Grateful! 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /B2OPT_pkg/B2OPT/model.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch 3 | from B2OPT.imports import * 4 | from B2OPT.problem import * 5 | 6 | class AttnWithFit (nn.Module): 7 | def __init__(self,popSize=100,hiddenDim=100): 8 | super().__init__() 9 | self.popSize=popSize 10 | self.attn=nn.Parameter(torch.randn((1,self.popSize,self.popSize)),requires_grad=True) 11 | self.q =nn.Sequential( 12 | nn.Linear(1, hiddenDim), 13 | ) 14 | self.k =nn.Sequential( 15 | nn.Linear(1, hiddenDim), 16 | ) 17 | self.num_heads = 1 18 | self.F=nn.Parameter(torch.randn((2,)),requires_grad=True) 19 | 20 | 21 | def forward(self,x,fitx): 22 | B, N, C = fitx.shape 23 | q = self.q(fitx).view(B, N, self.num_heads, -1).permute(0, 2, 1, 3) #B,H,N,SEQ 24 | k = self.k(fitx).view(B, N, self.num_heads, -1).permute(0, 2, 1, 3) 25 | fitattn = q @ k.transpose(2, 3) * (x.shape[-1] ** -0.5) #b,h,n,n (a11,a12,aij,...,ann) 26 | fitattn = torch.squeeze(fitattn.softmax(dim=-1) ,dim=1) 27 | y1=self.attn.softmax(dim=-1)@x 28 | y2=fitattn@x 29 | y=y1*self.F.softmax(-1)[0]+y2*self.F.softmax(-1)[1] 30 | return y 31 | 32 | def getStrategy(self,fitx,dim): 33 | B, N, C =fitx.shape 34 | q = self.q(fitx).view(B, N, self.num_heads, -1).permute(0, 2, 1, 3) #B,H,N,SEQ 35 | k = self.k(fitx).view(B, N, self.num_heads, -1).permute(0, 2, 1, 3) 36 | fitattn = q @ k.transpose(2, 3) * (dim** -0.5) 37 | fitattn = torch.squeeze(fitattn.softmax(dim=-1) ,dim=1) 38 | return self.F.softmax(-1)[0]*self.attn.softmax(dim=-1)+self.F.softmax(-1)[1]*fitattn 39 | 40 | 41 | 42 | 43 | class SM(nn.Module): 44 | def __init__(self): 45 | super().__init__() 46 | 47 | 48 | def forward(self,batchpop1,batchpop2,fatherfit,childfit,minimize=True): 49 | ''' 50 | 实现选择操作,默认是最小化函数,若minimize=False,则为最大化目标值问题 51 | ''' 52 | fit1=fatherfit 53 | fit2=childfit 54 | batchMask=fit1-fit2 #b,n,1 55 | if minimize: 56 | batchMask[batchMask>=0]=0 57 | batchMask[batchMask<0]=1 58 | else: 59 | batchMask[batchMask<=0]=0 60 | batchMask[batchMask>0]=1 61 | batchMask=torch.unsqueeze(batchMask,2) 62 | batchMask1=torch.ones_like(batchMask).to(DEVICE)-batchMask 63 | nextPop=batchpop1*batchMask+batchpop2*batchMask1 64 | return nextPop 65 | 66 | 67 | 68 | 69 | 70 | class BaseModel(nn.Module): 71 | def __init__(self): 72 | super().__init__() 73 | 74 | def sortpop(self,x,fitness): 75 | ''' 76 | 说明: 77 | 输入:x(b,n,dim),f(x)(b,n,1) 78 | 输出:排序后的x和f(x) 79 | ''' 80 | fitness,fitindex=torch.sort(fitness,dim=-1) #b,n fit:the order of individuals 81 | y=torch.zeros_like(x) 82 | for index,pop in enumerate(x): 83 | pop=x[index] 84 | y[index]=torch.index_select(pop,0,fitindex[index]) 85 | return y,fitness 86 | 87 | 88 | 89 | 90 | 91 | 92 | class OB(BaseModel): 93 | def __init__(self,dim=64,hidden_dim=100,popSize=10,temid=0): 94 | super().__init__() 95 | self.dim=dim 96 | self.trm=AttnWithFit(popSize=popSize,hiddenDim=hidden_dim) 97 | self.mut=nn.Sequential( 98 | nn.Linear(dim,dim), 99 | nn.ReLU(), 100 | nn.Linear(dim,dim) 101 | ) 102 | self.id=temid 103 | self.vis=False 104 | self.f1=nn.Parameter(torch.randn((1,popSize,1)),requires_grad=True) 105 | self.f2=nn.Parameter(torch.randn((1,popSize,1)),requires_grad=True) 106 | self.f3=nn.Parameter(torch.randn((1,popSize,1)),requires_grad=True) 107 | self.sm=SM() 108 | 109 | 110 | 111 | def forward(self,x,problem,xfit=None): 112 | b,n,d=x.shape 113 | if not xfit is None: 114 | fatherfit=xfit 115 | else: 116 | fatherfit=problem.calfitness(x) 117 | fitx=fatherfit.softmax(dim=-1) 118 | fitx=fitx.view(b,n,1) 119 | crosspop=self.trm(x,fitx) ##A & AF 120 | offpop=self.mut(crosspop) ##NN MUT 121 | off=self.f1*x+self.f2*crosspop+self.f3*offpop 122 | childfit=problem.calfitness(off) 123 | nextpop=self.sm(x,off,fatherfit,childfit) 124 | return nextpop 125 | 126 | 127 | 128 | 129 | 130 | class B2opt(BaseModel): 131 | def __init__(self,dim=64,hidden_dim=100,popSize=10,ems=10,ws=False): 132 | super().__init__() 133 | self.ems=ems 134 | self.ws=ws 135 | if self.ws: 136 | self.ob=OB(dim,hidden_dim,popSize) 137 | else: 138 | self.ob=torch.nn.ModuleList([OB(dim,hidden_dim,popSize,i) for i in range(ems)]) 139 | 140 | 141 | def forward(self,x,problem): 142 | self.trail=None 143 | self.evalnum=[] 144 | 145 | if self.ws is True: 146 | for i in range(self.ems): 147 | fatherfit=problem.calfitness(x) #b,n 148 | x,fatherfit=self.sortpop(x,fatherfit) 149 | trail=torch.min(fatherfit,dim=-1)[0].view(-1,1) 150 | if self.trail is None: 151 | self.trail=trail 152 | self.evalnum.append(x.shape[1]) 153 | else: 154 | self.trail=torch.cat((self.trail,trail),dim=-1) 155 | x=self.ob(x,problem,fatherfit) 156 | self.evalnum.append(self.evalnum[-1]+x.shape[1]) 157 | else: 158 | for ob in (self.ob): 159 | fatherfit=problem.calfitness(x) #b,n 160 | x,fatherfit=self.sortpop(x,fatherfit) 161 | trail=torch.min(fatherfit,dim=-1)[0].view(-1,1) 162 | if self.trail is None: 163 | self.trail=trail 164 | self.evalnum.append(x.shape[1]) 165 | else: 166 | self.trail=torch.cat((self.trail,trail),dim=-1) 167 | x=ob(x,problem,fatherfit) 168 | self.evalnum.append(self.evalnum[-1]+x.shape[1]) 169 | 170 | return x,self.trail,self.evalnum 171 | 172 | 173 | 174 | 175 | # if __name__=='__main__': 176 | # task=myProblem() 177 | # x=torch.randn((10,10,10),device=DEVICE) 178 | # model=B2opt(dim=10,hidden_dim=100,popSize=10,ems=10,ws=False).to(DEVICE) 179 | # x,trail,evalnum=model(x,task) 180 | # print(trail) 181 | # print(evalnum) -------------------------------------------------------------------------------- /exps/main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pickle 3 | import numpy as np 4 | import torch 5 | from B2OPT.problem import Problem 6 | from B2OPT.model import B2opt 7 | from BBOB.cecfunctions import FUNCTIONS as F 8 | from BBOB.bbobfunctions import FUNCTIONS as BBOBF 9 | from BBOB.utils import getFitness,genOffset,setOffset,getOffset 10 | from matplotlib import pyplot as plt 11 | from tqdm import tqdm 12 | import os 13 | import argparse 14 | 15 | os.environ['CUDA_LAUNCH_BLOCKING']='1' 16 | 17 | DEVICE=torch.device("cuda" if torch.cuda.is_available() else "cpu") 18 | class myProblem(Problem): 19 | def __init__(self,fun=None,repaire=True,dim=None): 20 | super().__init__() 21 | self.fun=fun 22 | self.useRepaire=repaire 23 | self.dim=dim 24 | 25 | def repaire(self,x): 26 | xlbmask=torch.zeros_like(x,device=DEVICE) 27 | xlbmask[xself.fun['xub']]=1 34 | normalmask=1-xubmask 35 | xubmask=xubmask*self.fun['xub'] 36 | x=normalmask*x+xubmask 37 | return x 38 | 39 | def calfitness(self,x): 40 | if self.useRepaire: 41 | x1=self.repaire(x) 42 | else: 43 | x1=x 44 | r=getFitness(x1,self.fun) 45 | return r 46 | 47 | def genRandomPop(self,batchShape): 48 | lb=self.fun['xlb'] 49 | ub=self.fun['xub'] 50 | return torch.rand(batchShape,device=DEVICE)*(ub-lb)+lb 51 | 52 | def reoffset(self): 53 | genOffset(self.dim,self.fun) 54 | 55 | 56 | def setOffset(self,offset): 57 | for key in offset.keys(): 58 | self.fun[key]=offset[key] 59 | 60 | def lossFunc(self,father,off): 61 | meanoff=torch.mean(self.calfitness(off)) 62 | meanfather=torch.mean(self.calfitness(father)) 63 | r=(meanoff-meanfather)/torch.abs(meanfather) 64 | 65 | if r is torch.nan: 66 | print('find a nan') 67 | os.system('pause') 68 | return r 69 | 70 | def getfunname(self): 71 | return self.fun['fid'] 72 | 73 | def setfun(self,fun): 74 | self.fun=fun 75 | 76 | 77 | 78 | class bbobProblem(Problem): 79 | def __init__(self,fun=None,repaire=True,dim=None): 80 | super().__init__() 81 | self.fun=fun 82 | self.useRepaire=repaire 83 | self.dim=dim 84 | 85 | def repaire(self,x): 86 | xlbmask=torch.zeros_like(x,device=DEVICE) 87 | xlbmask[xself.fun['xub']]=1 94 | normalmask=1-xubmask 95 | xubmask=xubmask*self.fun['xub'] 96 | x=normalmask*x+xubmask 97 | return x 98 | 99 | def calfitness(self,x): 100 | if self.useRepaire: 101 | x1=self.repaire(x) 102 | else: 103 | x1=x 104 | 105 | b,n,d=x.shape 106 | x1=x1.view((-1,d)) 107 | r=getFitness(x1,self.fun) #b,n,1 108 | r=torch.unsqueeze(r,-1) 109 | r=r.view((b,n)) 110 | 111 | return r 112 | 113 | def genRandomPop(self,batchShape): 114 | lb=self.fun['xlb'] 115 | ub=self.fun['xub'] 116 | return torch.rand(batchShape,device=DEVICE)*(ub-lb)+lb 117 | 118 | def reoffset(self): 119 | genOffset(self.dim,self.fun) 120 | 121 | 122 | def setOffset(self,offset): 123 | for key in offset.keys(): 124 | self.fun[key]=offset[key] 125 | 126 | def lossFunc(self,father,off): 127 | meanoff=torch.mean(self.calfitness(off)) 128 | meanfather=torch.mean(self.calfitness(father)) 129 | r=(meanoff-meanfather)/torch.abs(meanfather) 130 | 131 | if r is torch.nan: 132 | print('find a nan') 133 | os.system('pause') 134 | return r 135 | 136 | def getfunname(self): 137 | return self.fun['fid'] 138 | 139 | def setfun(self,fun): 140 | self.fun=fun 141 | 142 | 143 | 144 | 145 | def train(expname=None,dim=None,hiddendim=None,ems=None,ws=None,popsize=100,problem=None, 146 | maxepoch=None,lr=None,batchsize=None,T=10,funset=None,needsave=True): 147 | 148 | 149 | b2opt=B2opt(dim=dim,hidden_dim=hiddendim,popSize=popsize,ems=ems,ws=ws).to(DEVICE) 150 | opt=torch.optim.Adam(b2opt.parameters(),lr=lr) 151 | batchShape=(batchsize,popsize,dim) 152 | bar=tqdm(range(maxepoch),ncols=120) 153 | losslist=[] 154 | plt.figure(figsize=(12,9)) 155 | minloss=None 156 | for epoch in bar: 157 | if (epoch+1)%100==0: 158 | for param_group in opt.param_groups: 159 | param_group['lr'] *=0.9 160 | if epoch==0 or (epoch+1)%T==0: 161 | for fun in funset: 162 | genOffset(dim,fun) 163 | plt.plot(losslist) 164 | plt.savefig('./imgs/trainloss/%s_ems_%d_ws_%s_d%d.png'%(expname,ems,str(ws),dim)) 165 | 166 | 167 | for fun in funset: 168 | problem.setfun(fun) 169 | pop=problem.genRandomPop(batchShape) 170 | offpop,trail,evalnums=b2opt(pop,problem) 171 | loss=problem.lossFunc(pop,offpop) 172 | opt.zero_grad() 173 | loss.backward() 174 | torch.nn.utils.clip_grad_norm_(b2opt.parameters(), 10, norm_type=2) 175 | opt.step() 176 | 177 | totalloss=None 178 | for fun in funset: 179 | problem.setfun(fun) 180 | pop=problem.genRandomPop(batchShape) 181 | offpop,trail,evalnums=b2opt(pop,problem) 182 | loss=problem.lossFunc(pop,offpop) 183 | if totalloss is None: 184 | totalloss=loss 185 | else: 186 | totalloss+=loss 187 | totalloss/=len(funset) 188 | opt.zero_grad() 189 | loss.backward() 190 | torch.nn.utils.clip_grad_norm_(b2opt.parameters(), 10, norm_type=2) 191 | opt.step() 192 | losslist.append(totalloss.item()) 193 | if (minloss is None or totalloss.item()