-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
how to get all solutions not just the pareto optimal solutions? #187
Comments
Depends what you mean with "all". If you mean all the solutions in the Pareto frontier here is example code that you can probably tweak for your purposes: julia> using BlackBoxOptim
julia> fitness_schaffer1(x) = (sum(abs2, x), sum(abs2, x .- 2.0))
fitness_schaffer1 (generic function with 1 method)
julia> res = bboptimize(fitness_schaffer1; Method=:borg_moea,
FitnessScheme=ParetoFitnessScheme{2}(is_minimizing=true),
SearchRange=(-10.0, 10.0), NumDimensions=3, ϵ=0.05,
MaxSteps=50000, TraceInterval=1.0, TraceMode=:silent);
julia> allpf_solutions = map(params, pareto_frontier(res));
julia> length(allpf_solutions)
120
julia> allpf_fitnesses = map(fitness, pareto_frontier(res));
julia> length(allpf_fitnesses)
120
julia> typeof(allpf_solutions)
Vector{Vector{Float64}} (alias for Array{Array{Float64, 1}, 1})
julia> typeof(allpf_fitnesses)
Vector{Tuple{Float64, Float64}} (alias for Array{Tuple{Float64, Float64}, 1}) Note that the number of solutions on the frontier depends on the specific problem and the specific optimization run. It can never be higher than MaxFuncEvals but will typically be much smaller since not all evaluated solutions are good enough to be on the frontier. If you really want to access all solutions that have been evaluated you can just save them in your fitness function. But this is quite rare and not clear what the benefits are (unless you are doing some kind of research on the optimization methods or similar). |
To clarify the example above we found 120 solutions that are on the Pareto frontier, i.e. none of them Pareto dominates any of the others. Let's look at three of them to make sure: julia> allpf_fitnesses[17]
(1.9856426463662804, 4.223005212769594)
julia> allpf_fitnesses[18]
(1.9465173029354108, 4.280634320756287)
julia> allpf_fitnesses[49]
(7.069529667506938, 0.6484321993051512) We can see that 17 dominates 18 on fitness value 2, since 4.22 < 4.28, and 17 dominates 49 on fitness value 1, since 1.99<7.07. We can see that 18 dominates 17 on fitness value 1 and 18 dominates 49 on fitness value 1. We can see that 49 dominates 17 and 18 on fitness value 2. So none of them can be deleted from the Pareto frontier (based on comparing these 3 but of course this should hold for the whole frontier). I hope this clarifies. |
Thanks for your reply! |
|
Well, your fitness function will be called for each evaluation so you can just save them yourself. Basic idea: const AllSolutions = Vector{Float64}[]
function my_saving_fitness(x)
push!(AllSolutions, x)
return my_fitness(x)
end |
This is a single-objective example but should be same for multi-objective: julia> using BlackBoxOptim
julia> function rosenbrock2d(x)
return (1.0 - x[1])^2 + 100.0 * (x[2] - x[1]^2)^2
end
rosenbrock2d (generic function with 1 method)
julia> const AllSolutions = Vector{Float64}[]
Vector{Float64}[]
julia> function my_saving_fitness(x)
push!(AllSolutions, x)
return rosenbrock2d(x)
end
my_saving_fitness (generic function with 1 method)
julia> res = bboptimize(my_saving_fitness; SearchRange = (-5.0, 5.0), NumDimensions = 2, TraceMode=:silent, MaxFuncEvals=1000);
julia> length(AllSolutions)
1002 The exact number of evaluations is not exactly that of the MaxFuncEvals value since different optimization algorithms might need some number of evals before starting the main loop etc. But it should be fairly limited how many "extra" evals are used. |
Thank you for your help! I have tried it, this is very useful to me. But In the AllSolutions, there are just all sets of parameters' values, How can I also get all corresponding fitness values? |
Before you return the fitness to BBO just save it in a similar manner. const AllSolutions = Vector{Float64}[]
const AllFitnesses = Float64[]
function my_saving_fitness(x)
push!(AllSolutions, x)
f = my_fitness(x)
push!(AllFitnesses, f)
return f
end |
I really appreciate it! Thanks a lot! |
I have tried the method you told me about. I can get all fitness values and they are different and correct. But when I look at all solutions' values, most of them are the same. So they are not the corresponding solutions to each fitness. And the Best candidates are not in them. I am confused. Could you please tell me why? -1.48973 | 2.080654 | 0.131677 | 0.07129 | 1.85131 | 449.1027 | 4.377311 | 0.750455 | 3.589066 | 4.519954 |
Ah, for some optimization methods they might update the candidate array as they go along. So if you want to be sure to save the candidate at a certain point in time you can deepcopy them. Of course, they might still evaluate the same (or close to the same) candidate when getting close to the optimum when it is hard to make any real progress. using BlackBoxOptim
function rosenbrock(x)
return( sum( 100*( x[2:end] .- x[1:end-1].^2 ).^2 .+ ( x[1:end-1] .- 1 ).^2 ) )
end
AllSolutions = Vector{Float64}[]
function my_saving_fitness(x)
global AllSolutions
push!(AllSolutions, deepcopy(x))
return rosenbrock(x)
end
res = bboptimize(my_saving_fitness; SearchRange = (-5.0, 5.0), NumDimensions = 2, TraceMode=:silent,
MaxFuncEvals=1000);
length(AllSolutions) # I get 1002 here
length(unique(AllSolutions)) # I get about 940 here |
Okay! Thanks for your reply and help! |
I applied this method to solve muti_objective problem.
res = bboptimize(Pro; Method=:borg_moea,
FitnessScheme=ParetoFitnessScheme{2}(is_minimizing=true),
SearchRange=[(-2.5,2.5),(1.0,5.0),(0.1,0.7),(0.001,0.3),
(1.5,5.0),(300.0,500.0),(0.9,5.0),(0.0,1.0),(0.1,4.0),(0.3,5.0),
(0.1,1.5),(100.0,300.0),(0.9,5.0),(0.1,4.0),(0.3,5.0),
(50.0,100.0),(0.9,5.0),(0.1,4.0),(0.3,5.0)],
PopulationSize =100,NumDimensions=19,ϵ=0.01,MaxFuncEvals=1000,TraceInterval=1.0,TraceMode=:compact)
After running it, I can see the running process. in each eval, there is a fitness result. I thought I can get 1000 soutions when I set
MaxFuncEvals=1000. But I use "pf = pareto_frontier(res)",then I just get one pareto optimal solution.
...
...
pop.size=100 arch.size=1 n.restarts=0
1071.49 secs, 990 evals, 735 steps, fitness=(0.52232, 0.34539) agg=0.86771
pop.size=100 arch.size=1 n.restarts=0
1073.56 secs, 992 evals, 736 steps, fitness=(0.52225, 0.34514) agg=0.86738
pop.size=100 arch.size=1 n.restarts=0
1074.64 secs, 993 evals, 737 steps, fitness=(0.52225, 0.34514) agg=0.86738
pop.size=100 arch.size=1 n.restarts=0
1075.69 secs, 994 evals, 738 steps, fitness=(0.52225, 0.34514) agg=0.86738
pop.size=100 arch.size=1 n.restarts=0
1077.79 secs, 996 evals, 739 steps, fitness=(0.52225, 0.34514) agg=0.86738
pop.size=100 arch.size=1 n.restarts=0
1078.84 secs, 997 evals, 740 steps, fitness=(0.52225, 0.34514) agg=0.86738
pop.size=100 arch.size=1 n.restarts=0
1079.88 secs, 998 evals, 741 steps, fitness=(0.52225, 0.34514) agg=0.86738
pop.size=100 arch.size=1 n.restarts=0
1082.04 secs, 1000 evals, 742 steps, fitness=(0.52225, 0.34512) agg=0.86737
pop.size=100 arch.size=1 n.restarts=0
I want to get all the solutions in the process. But I don't know how to do it. Could you please help me?
The text was updated successfully, but these errors were encountered: