43template<ProgramType T>
78 map<string, float> variation_probs;
79 for (
const auto& mutation :
parameters.get_mutation_probs())
81 if (mutation.second > 0.0)
82 variation_probs[mutation.first] = mutation.second;
95 for (
const auto& entry : this->
search_space.terminal_weights) {
101 map<string, float> terminal_probs;
102 for (
int i = 0; i < entry.second.size(); i++)
104 if (entry.second[i] > 0.0)
106 auto node_name =
search_space.terminal_map.at(entry.first).at(i).get_feature();
107 terminal_probs[node_name] = entry.second[i];
110 if (terminal_probs.size()>0)
119 for (
auto& [ret_type, arg_w_map]:
search_space.node_map)
124 for (
const auto& [args_type, node_map] : arg_w_map)
130 map<string, float> node_probs;
132 for (
const auto& [node_type, node]: node_map)
134 auto weight =
search_space.node_map_weights.at(ret_type).at(args_type).at(node_type);
139 auto [it, inserted] = node_probs.try_emplace(node.name, weight);
148 if (node_probs.size() > 0)
156 for (
const auto& entry : this->
search_space.terminal_weights) {
157 map<string, float> terminal_probs;
158 for (
int i = 0; i < entry.second.size(); i++)
159 if (entry.second[i] > 0.0)
163 tree<Node> dummy_tree;
164 dummy_tree.insert(dummy_tree.begin(), node);
165 auto it = dummy_tree.begin();
179 std::optional<Individual<T>>
cross(
189 std::optional<Individual<T>>
mutate(
227 vector<std::shared_ptr<Individual<T>>> aux_individuals;
228 for (
unsigned i = 0; i < indices.size(); ++i)
237 std::optional<Individual<T>> opt = std::nullopt;
241 auto idx = parents.at(i % parents.size());
246 vector<Individual<T>> ind_parents = {mom};
257 [](
const auto& n) { return n.get_prob_change()<=0.0; }))
276 if (choice.compare(
"cx") == 0)
280 const Individual<T>& dad = pop[parents.at((i+1) % parents.size())];
282 opt =
cross(mom, dad);
283 ind_parents.push_back(dad);
287 opt =
mutate(mom, choice);
323 if (
parameters.constants_simplification && do_simplification)
332 vector<size_t> idx(inputDim);
333 std::iota(idx.begin(), idx.end(), 0);
336 if (do_simplification)
354 vector<float> deltas;
369 else if (obj.compare(
"complexity") == 0) {
372 else if (obj.compare(
"linear_complexity") == 0) {
375 else if (obj.compare(
"size") == 0) {
378 else if (obj.compare(
"depth") == 0) {
391 float weighted_delta =
delta * weight;
392 deltas.push_back(weighted_delta);
395 bool allPositive =
true;
396 bool allNegative =
true;
397 for (
float d : deltas) {
405 if (allPositive && !allNegative)
417 for (
auto& node : changed_nodes) {
418 if (node.get_arg_count() == 0) {
419 auto datatype = node.get_ret_type();
424 auto ret_type = node.get_ret_type();
425 auto args_type = node.args_type();
426 auto name = node.name;
428 this->
op_bandits[ret_type][args_type].update(name,
r);
439 pop.
individuals.at(indices.at(i)) = std::make_shared<Individual<T>>(ind);
466 string terminal_name = bandit.choose();
468 auto it = std::find_if(
471 [&](
auto& node) { return node.get_feature() == terminal_name; });
474 auto index = std::distance(
search_space.terminal_map.at(R).begin(), it);
501 string node_name = bandit.choose();
505 for (
const auto& [node_type, node_value]: entries)
507 if (node_value.name == node_name) {
519 vector<size_t> matches;
520 vector<float> weights;
522 for (
const auto& [args_type, name_map]: args_map) {
523 for (
const auto& [name, node]: name_map) {
524 auto node_arg_types = node.get_arg_types();
526 auto within_size_limit = !(max_args) || (node.get_arg_count() <= max_args);
528 if (
in(node_arg_types, arg)
530 &&
search_space.node_map_weights.at(ret).at(args_type).at(name) > 0.0f ) {
532 matches.push_back(node.args_type());
537 if (matches.size()==0)
541 auto args_type = *
r.select_randomly(matches.begin(),
544 string node_name = bandit.choose();
548 for (
const auto& [node_type, node_value]: entries)
550 if (node_value.name == node_name) {
565 auto& [args_type, bandit] = *
r.select_randomly(
op_bandits[ret].begin(),
568 string node_name = bandit.choose();
571 for (
const auto& [node_type, node_value]: entries)
573 if (node_value.name == node_name) {
615 using Iter = tree<Node>::pre_order_iterator;
617 template<Brush::ProgramType T>
621 vector<float> weights(program.
Tree.size());
624 std::transform(program.
Tree.begin(), program.
Tree.end(), weights.begin(),
625 [&](
const auto& n){ return n.get_prob_change();});
631 template<Brush::ProgramType T>
holds variable type data.
Class for evaluating the fitness of individuals in a population.
void assign_fit(Individual< T > &ind, const Dataset &data, const Parameters ¶ms, bool val=false)
Assign fitness to an individual.
static std::map< std::string, float > weightsMap
set parent ids using id values
vector< Node > get_sampled_nodes() const
Fitness fitness
aggregate fitness score
string get_variation() const
vector< string > get_objectives() const
void set_parents(const vector< Individual< T > > &parents)
void init(SearchSpace &ss, const Parameters ¶ms)
Program< T > program
executable data structure
vector< size_t > get_island_indexes(int island)
vector< std::shared_ptr< Individual< T > > > individuals
static auto find_spots(Program< T > &program, Variation< T > &variator, const Parameters ¶ms)
tree< Node >::pre_order_iterator Iter
static auto mutate(Program< T > &program, Iter spot, Variation< T > &variator, const Parameters ¶ms)
Class representing the variation operators in Brush.
std::optional< Node > bandit_sample_op(DataType ret)
map< DataType, map< size_t, Bandit > > op_bandits
void vary_and_update(Population< T > &pop, int island, const vector< size_t > &parents, const Dataset &data, Evaluation< T > &evaluator, bool do_simplification)
Varies a population and updates the selection strategy based on rewards.
void vary(Population< T > &pop, int island, const vector< size_t > &parents)
Handles variation of a population.
void init()
Initializes the Variation object with parameters and search space.
Variation()=default
Default constructor.
Inexact_simplifier inexact_simplifier
std::optional< Node > bandit_sample_op_with_arg(DataType ret, DataType arg, int max_args=0)
Constants_simplifier constants_simplifier
Variation(Parameters ¶ms, SearchSpace &ss, Dataset &d)
Constructor that initializes the Variation object with parameters and search space.
std::optional< Individual< T > > cross(const Individual< T > &mom, const Individual< T > &dad)
Performs croearch_spaceover operation on two individuals.
std::optional< Node > bandit_sample_terminal(DataType R)
void log_simplification_table(std::ofstream &log)
std::optional< Node > bandit_get_node_like(Node node)
map< DataType, Bandit > terminal_bandits
std::optional< Individual< T > > mutate(const Individual< T > &parent, string choice="")
Performs mutation operation on an individual.
#define HANDLE_ERROR_THROW(err)
bool in(const V &v, const T &i)
check if element is in vector.
< nsga2 selection operator for getting the front
auto Is(NodeType nt) -> bool
unsigned int get_prev_depth() const
float get_prev_loss() const
unsigned int get_prev_size() const
unsigned int get_prev_complexity() const
void set_linear_complexity(unsigned int new_lc)
void set_complexity(unsigned int new_c)
void set_loss_v(float f_v)
void set_depth(unsigned int new_d)
unsigned int get_prev_linear_complexity() const
unsigned int get_complexity() const
void set_size(unsigned int new_s)
unsigned int get_depth() const
unsigned int get_linear_complexity() const
unsigned int get_size() const
The Bandit struct represents a multi-armed bandit.
class holding the data for a node in a tree.
NodeType node_type
the node type
DataType ret_type
return data type
std::size_t args_type() const
An individual program, a.k.a. model.
Program< PType > & fit(const Dataset &d)
int size(bool include_weight=true) const
count the tree size of the program, including the weights in weighted nodes.
Holds a search space, consisting of operations and terminals and functions, and methods to sample tha...