From 11755d2a84dc6774bc1d9c4391b854ac76b87d95 Mon Sep 17 00:00:00 2001 From: soldamatlab Date: Wed, 14 Feb 2024 21:19:16 +0100 Subject: [PATCH] Add de_evaluation --- scripts/benchmark.jl | 33 ++++++++++++ scripts/runscripts.jl | 1 + src/DESilico.jl | 3 +- src/de_evaluation.jl | 115 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 scripts/benchmark.jl create mode 100644 src/de_evaluation.jl diff --git a/scripts/benchmark.jl b/scripts/benchmark.jl new file mode 100644 index 0000000..0fa7cd7 --- /dev/null +++ b/scripts/benchmark.jl @@ -0,0 +1,33 @@ +using BenchmarkTools + +include("de_sandbox.jl") + +""" +A simple benchmark showcasing the speed-up achieved via parallelization of `de_evaluation`. +""" +function parallel_benchmark(runs::Int=160000, n_iterations::Int=5) + ss = SequenceSpace{Nothing}(initial_population) + seq = @elapsed de_evaluation( + ss, + runs; + screening, + selection_strategy, + mutagenesis, + n_iterations, + parallel=false, + ) + + ss = SequenceSpace{Nothing}(initial_population) + par = @elapsed de_evaluation( + ss, + runs; + screening, + selection_strategy, + mutagenesis, + n_iterations, + parallel=true, + ) + + println("SEQUENTIAL de_evaluation: $seq") + println("PARALLEL de_evaluation : $par") +end diff --git a/scripts/runscripts.jl b/scripts/runscripts.jl index 9445396..a681ac9 100644 --- a/scripts/runscripts.jl +++ b/scripts/runscripts.jl @@ -4,3 +4,4 @@ include("custom_modules_example.jl") #include("de_example.jl") #include("de_sandbox.jl") #include("profiling.jl") +#include("benchmark.jl") diff --git a/src/DESilico.jl b/src/DESilico.jl index 112d616..f2136e5 100644 --- a/src/DESilico.jl +++ b/src/DESilico.jl @@ -1,10 +1,11 @@ module DESilico export Variant, SequenceSpace -export de! +export de!, de_evaluation include("types/include.jl") include("de.jl") +include("de_evaluation.jl") include("selection_strategy/include.jl") include("mutagenesis/include.jl") include("screening/include.jl") diff --git a/src/de_evaluation.jl b/src/de_evaluation.jl new file mode 100644 index 0000000..b2eaec9 --- /dev/null +++ b/src/de_evaluation.jl @@ -0,0 +1,115 @@ +""" + de_evaluation(sequence_space::SequenceSpace, runs::Int; kwargs...) + +Perform directed evolution through `de!()` with defined options `runs` times. +Returns the top fitness obtained in each run as a `Vector{Float64}`. + +# Arguments +- `sequence_space::SequenceSpace`: Initial `SeqeunceSpace` which will be used in each run of `de!()`. +- `runs::Int`: Number of times `de!()` will be called. + +# Keywords +- `screening::Screening`: Assigns fitness value to a sequence. +- `selection_strategy::SelectionStrategy`: Defines the algorithm used to select new parents from a pool of screened variants. +- `mutagenesis:Mutagenesis`: Defines the algorithm used to create new mutants from current population. +- `n_iterations::Integer`: Specifies the number of iteration of `de!()`. +- `parallel::Bool=false`: If true, the calls of `de!()` will be run in parallel. +""" +function de_evaluation( + sequence_space::SequenceSpace, + runs::Int; + screening::Screening, + selection_strategy::SelectionStrategy, + mutagenesis::Mutagenesis, + n_iterations::Int, + parallel::Bool=false, +) + @assert runs > 0 + results = Vector{Float64}(undef, runs) + get_sequence_space = r -> SequenceSpace{Nothing}(sequence_space.population, sequence_space.top_variant) + if parallel + _run_de_parallel!(results, get_sequence_space, runs; screening, selection_strategy, mutagenesis, n_iterations) + else + _run_de_sequential!(results, get_sequence_space, runs; screening, selection_strategy, mutagenesis, n_iterations) + end + return results +end + +""" + de_evaluation(sequence_space::SequenceSpace, runs::Int; kwargs...) + +Perform directed evolution through `de!()` with defined options `runs` times. +Returns the top fitness obtained in each run as a `Vector{Float64}`. + +# Arguments +- `starting_variants::AbstractVector{Variant}`: Each of the `starting_variants` will be used as the sole initial parent in one run of `de!()`. + +# Keywords +- `screening::Screening`: Assigns fitness value to a sequence. +- `selection_strategy::SelectionStrategy`: Defines the algorithm used to select new parents from a pool of screened variants. +- `mutagenesis:Mutagenesis`: Defines the algorithm used to create new mutants from current population. +- `n_iterations::Integer`: Specifies the number of iteration of `de!()`. +- `parallel::Bool=false`: If true, the calls of `de!()` will be run in parallel. +""" +function de_evaluation( + starting_variants::AbstractVector{Variant}; + screening::Screening, + selection_strategy::SelectionStrategy, + mutagenesis::Mutagenesis, + n_iterations::Int, + parallel::Bool=false, +) + @assert length(starting_variants) > 0 + results = Vector{Float64}(undef, length(starting_variants)) + get_sequence_space = r -> SequenceSpace([starting_variants[r]]) + if parallel + _run_de_parallel!(results, get_sequence_space, length(starting_variants); screening, selection_strategy, mutagenesis, n_iterations) + else + _run_de_sequential!(results, get_sequence_space, length(starting_variants); screening, selection_strategy, mutagenesis, n_iterations) + end + return results +end + +function _run_de_sequential!( + results::Vector{Float64}, + get_sequence_space::Function, + runs::Int; + screening::Screening, + selection_strategy::SelectionStrategy, + mutagenesis::Mutagenesis, + n_iterations::Int, +) + for r = 1:runs + ss = get_sequence_space(r) + de!( + ss; + screening, + selection_strategy, + mutagenesis, + n_iterations, + ) + results[r] = ss.top_variant.fitness + end +end + +function _run_de_parallel!( + results::Vector{Float64}, + get_sequence_space::Function, + runs::Int; + screening::Screening, + selection_strategy::SelectionStrategy, + mutagenesis::Mutagenesis, + n_iterations::Int, +) + Threads.@threads :static for r = 1:runs + ss = get_sequence_space(r) + de!( + ss; + screening, + selection_strategy, + mutagenesis, + n_iterations, + ) + results[r] = ss.top_variant.fitness + end +end