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)
184 std::tuple<std::optional<Individual<T>>, VectorXf>
cross(
194 std::tuple<std::optional<Individual<T>>, VectorXf>
mutate(
232 vector<std::shared_ptr<Individual<T>>> aux_individuals;
233 for (
unsigned i = 0; i < indices.size(); ++i)
245 std::optional<Individual<T>> opt = std::nullopt;
249 auto idx = parents.at(i % parents.size());
256 vector<Individual<T>> ind_parents;
269 [](
const auto& n) { return n.get_prob_change()<=0.0; }))
282 const Individual<T>& dad = pop[parents.at((i+1) % parents.size())];
285 auto variation_result =
cross(mom, dad);
286 ind_parents = {mom, dad};
287 tie(opt, context) = variation_result;
292 auto variation_result =
mutate(mom, choice);
295 tie(opt, context) = variation_result;
333 auto data_aux =
data.get_training_data();
359 vector<float> deltas;
384 else if (obj.compare(
"complexity") == 0) {
388 else if (obj.compare(
"linear_complexity") == 0) {
392 else if (obj.compare(
"size") == 0) {
396 else if (obj.compare(
"depth") == 0) {
412 float weighted_delta =
delta * weight;
415 deltas.push_back(weighted_delta);
422 bool allPositive =
true;
423 bool allNegative =
true;
424 for (
float d : deltas) {
432 if (allPositive && !allNegative)
436 if (
parameters.bandit.compare(
"linear_thompson") == 0)
449 if ( allPositive && !allNegative)
r = 1.0;
450 if (!allPositive && allNegative)
r = -1.0;
466 for (
auto& node : changed_nodes) {
467 if (node.get_arg_count() == 0) {
468 auto datatype = node.get_ret_type();
473 auto ret_type = node.get_ret_type();
474 auto args_type = node.args_type();
475 auto name = node.name;
477 this->
op_bandits[ret_type][args_type].update(name,
r, context);
490 pop.
individuals.at(indices.at(i)) = std::make_shared<Individual<T>>(ind);
519 string terminal_name = bandit.choose(context);
522 auto it = std::find_if(
525 [&](
auto& node) { return node.get_feature() == terminal_name; });
528 auto index = std::distance(
search_space.terminal_map.at(R).begin(), it);
558 string node_name = bandit.choose(context);
564 for (
const auto& [node_type, node_value]: entries)
567 if (node_value.name == node_name) {
578 VectorXf& context,
int max_args=0)
581 vector<size_t> matches;
582 vector<float> weights;
584 for (
const auto& [args_type, name_map]: args_map) {
585 for (
const auto& [name, node]: name_map) {
586 auto node_arg_types = node.get_arg_types();
588 auto within_size_limit = !(max_args) || (node.get_arg_count() <= max_args);
590 if (
in(node_arg_types, arg)
592 &&
search_space.node_map_weights.at(ret).at(args_type).at(name) > 0.0f ) {
594 matches.push_back(node.args_type());
599 if (matches.size()==0)
603 auto args_type = *
r.select_randomly(matches.begin(),
606 string node_name = bandit.choose(context);
610 for (
const auto& [node_type, node_value]: entries)
612 if (node_value.name == node_name) {
627 auto& [args_type, bandit] = *
r.select_randomly(
op_bandits[ret].begin(),
630 string node_name = bandit.choose(context);
633 for (
const auto& [node_type, node_value]: entries)
635 if (node_value.name == node_name) {
676 using Iter = tree<Node>::pre_order_iterator;
678 template<Brush::ProgramType T>
682 vector<float> weights(program.
Tree.size());
685 std::transform(program.
Tree.begin(), program.
Tree.end(), weights.begin(),
686 [&](
const auto& n){ return n.get_prob_change();});
692 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)
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_get_node_like(Node node, VectorXf &context)
Bandit< string > variation_bandit
std::tuple< std::optional< Individual< T > >, VectorXf > mutate(const Individual< T > &parent, string choice="")
Performs mutation operation on an individual.
std::tuple< std::optional< Individual< T > >, VectorXf > cross(const Individual< T > &mom, const Individual< T > &dad)
Performs croearch_spaceover operation on two individuals.
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
map< DataType, Bandit< string > > terminal_bandits
std::optional< Node > bandit_sample_terminal(DataType R, VectorXf &context)
Constants_simplifier constants_simplifier
VectorXf get_context(const Program< T > &program, Iter spot)
void vary_and_update(Population< T > &pop, int island, const vector< size_t > &parents, const Dataset &data, Evaluation< T > &evaluator)
Varies a population and updates the selection strategy based on rewards.
map< DataType, map< size_t, Bandit< string > > > op_bandits
Variation(Parameters ¶ms, SearchSpace &ss, Dataset &d)
Constructor that initializes the Variation object with parameters and search space.
std::optional< Node > bandit_sample_op(DataType ret, VectorXf &context)
std::optional< Node > bandit_sample_op_with_arg(DataType ret, DataType arg, VectorXf &context, int max_args=0)
#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
tree< Node >::pre_order_iterator Iter
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...