Brush C++ API
A flexible interpretable machine learning framework
Loading...
Searching...
No Matches
archive.cpp
Go to the documentation of this file.
1#include "archive.h"
2
3namespace Brush {
4namespace Pop {
5
6template<ProgramType T>
7Archive<T>::Archive(): selector(true) {};
8
9template<ProgramType T>
10void Archive<T>::set_objectives(vector<string> objectives)
11{
12 this->sort_complexity = in(objectives, std::string("complexity"));
13}
14
15// sorting etc --- all done using fitness class (easier to compare regardless of obj func)
16template<ProgramType T>
18 const Individual<T>& rhs)
19{
20 // TODO: use getters for all info in fitness (instead of directly accessing them?).
21 // other option would be having the getters and setters to use iin pybind11, but
22 // in cpp we do it directly (we know how to manipulate this thing, but users may not,
23 // so these setters could do some validation to justify its existence).
24
25 return lhs.fitness.complexity < rhs.fitness.complexity;
26}
27
28template<ProgramType T>
30 const Individual<T>& rhs)
31{
32 // sort based on index (we can have more than 2 obj in brush implementation)
33 // obs: because of the weights, every objective is a maximization problem
34 // when comparing weighted values (which should be the right way of doing it)
35 // the bigger the better. the weights allow us to use different min/max metrics
36 // without having to deal with this particular details
37
38 float lhs_obj1 = lhs.fitness.wvalues.at(0);
39 float rhs_obj1 = rhs.fitness.wvalues.at(0);
40
41 return lhs_obj1 > rhs_obj1;
42}
43
44template<ProgramType T>
46 const Individual<T>& rhs)
47{
48 // fitness' operator== is overloaded to compare wvalues.
49 // we also check complexity equality to avoid the case where the user
50 // did not specified complexity as one of the objectives
51 return (lhs.fitness == rhs.fitness &&
52 lhs.fitness.complexity == rhs.fitness.complexity);
53}
54
55template<ProgramType T>
57 const Individual<T>& rhs)
58{
59 return (lhs.fitness == rhs.fitness);
60
61}
62
63template<ProgramType T>
65{
66 // TODO: copy the population to a new vector (instead of changing inplace).
67 // also, fix this in update function
68
69 individuals.resize(0);
70
71 // dealing with islands --> fast nds for each island
72 for (int island =0; island< pop.num_islands; ++island) {
73 vector<size_t> indices = pop.get_island_indexes(island);
74
75 selector.fast_nds(pop, indices);
76 }
77
78 // OBS: fast_nds will change all individual fitness inplace.
79 // It will update the values for dcounter, rank, and dominated individuals.
80
81 // TODO: fix this way of getting pareto front (the pareto front of different islands combined will not necessarily be the final pareto front). Also fix this in update
82
83 /* vector<size_t> front = this->sorted_front(); */
84 for (int island =0; island< pop.num_islands; ++island) {
86
87 for (unsigned i = 0; i<indices.size(); ++i)
88 {
89 const auto& t = *pop.individuals.at(indices.at(i));
90
91 if (t.fitness.rank ==1){
92 // we can store a reference for the original ind, since
93 // variation operators does not change inplace. Ideally, the
94 // original individual is modified inplace just by fit(), which
95 // is a side effect that is OK to have here
96 individuals.push_back(t);
97 }
98 }
99 }
100 if (this->sort_complexity)
101 std::sort(individuals.begin(),individuals.end(), &sortComplexity);
102 else
103 std::sort(individuals.begin(),individuals.end(), &sortObj1);
104
105}
106
107template<ProgramType T>
109{
110 individuals.resize(0); // clear archive
111
112 // refill archive with new pareto fronts (one pareto front for each island!)
113 for (int island =0; island< pop.num_islands; ++island) {
114 vector<size_t> indices = pop.get_island_indexes(island);
115
116 // TODO: can i just call fast nds with all indexes in indices?
117 vector<vector<int>> front = selector.fast_nds(pop, indices);
118 for (const auto& i : front[0])
119 {
120 individuals.push_back( *pop.individuals.at(i) );
121 }
122 }
123
124 if (this->sort_complexity)
125 std::sort(individuals.begin(), individuals.end(), &sortComplexity);
126 else
127 std::sort(individuals.begin(), individuals.end(), &sortObj1);
128
129 /* auto it = std::unique(individuals.begin(),individuals.end(), &sameFitComplexity); */
130 auto it = std::unique(individuals.begin(),individuals.end(),
131 &sameObjectives);
132
133 individuals.resize(std::distance(individuals.begin(),it));
134}
135
136} // Pop
137} // Brush
void bind_engine(py::module &m, string name)
vector< size_t > get_island_indexes(int island)
Definition population.h:38
vector< std::shared_ptr< Individual< T > > > individuals
Definition population.h:18
bool in(const V &v, const T &i)
check if element is in vector.
Definition utils.h:192
< nsga2 selection operator for getting the front
Definition data.cpp:12
void set_objectives(vector< string > objectives)
Sets the objectives for the archive.
Definition archive.cpp:10
void update(Population< T > &pop, const Parameters &params)
Updates the archive with individuals from a population.
Definition archive.cpp:108
void init(Population< T > &pop)
Initializes the archive with individuals from a population.
Definition archive.cpp:64
static bool sameFitComplexity(const Individual< T > &lhs, const Individual< T > &rhs)
Checks if two individuals have the same fitness complexity.
Definition archive.cpp:45
static bool sortObj1(const Individual< T > &lhs, const Individual< T > &rhs)
Sorts the population by the first objective.
Definition archive.cpp:29
static bool sortComplexity(const Individual< T > &lhs, const Individual< T > &rhs)
Sorts the population in increasing complexity.
Definition archive.cpp:17
static bool sameObjectives(const Individual< T > &lhs, const Individual< T > &rhs)
Checks if two individuals have the same objectives.
Definition archive.cpp:56
Archive()
Default constructor for the Archive struct.
Definition archive.cpp:7