diff --git a/Makefile b/Makefile index f900f1c1ca3831dbacad574909e51a60cfa293d6..77908f6d5254351fd38c88d4b74655f7b06e561c 100644 --- a/Makefile +++ b/Makefile @@ -2,12 +2,14 @@ CC = gcc CXX = g++ LDFLAGS = -lm -FLAGS = -g -ggdb -Iexternals/coco -Isrc -FLAGS += -Wall -Wextra -Wstrict-prototypes -Wshadow -Wno-sign-compare -Wconversion +FLAGS = -g -ggdb +FLAGS += -Wall -Wextra SRC = src BIN = bin -OBJS = $(BIN)/coco.o $(BIN)/experiment.o +CPP_FILES := $(wildcard src/ibea/*.cpp) +OBJ_FILES := $(addprefix bin/,$(notdir $(CPP_FILES:.cpp=.o))) +OBJ_FILES += $(BIN)/coco.o $(BIN)/experiment.o ######################################################################## ## Toplevel targets @@ -19,8 +21,8 @@ clean: ######################################################################## ## Programs -experiment: $(OBJS) - ${CC} ${FLAGS} $(OBJS) ${LDFLAGS} -o $(BIN)/$@ +experiment: $(OBJ_FILES) + ${CXX} ${FLAGS} $^ ${LDFLAGS} -o $(BIN)/$@ ######################################################################## ## Additional dependencies @@ -28,4 +30,7 @@ $(BIN)/coco.o: $(SRC)/coco/coco.h $(SRC)/coco/coco.c ${CC} -c $(SRC)/coco/coco.c $(FLAGS) -o $@ $(BIN)/experiment.o: $(SRC)/coco/coco.h $(SRC)/experiment.c - ${CC} -c $(SRC)/experiment.c ${FLAGS} -o $@ + ${CXX} -c $(SRC)/experiment.c ${FLAGS} -o $@ + +$(BIN)/%.o: $(SRC)/ibea/%.cpp + ${CXX} -c $< $(FLAGS) -o $@ diff --git a/src/experiment.c b/src/experiment.c index 5b57de56deb39c73975d9ecb85b5de6bad8b8741..3c7711b71590d41d36f6e1ec96a294d2f31bc40a 100644 --- a/src/experiment.c +++ b/src/experiment.c @@ -10,7 +10,8 @@ #include <time.h> #include "coco/coco.h" -#include "ibea_implementation.h" +/* #include "ibea/population.h" */ +#include "ibea/ibea.h" /** * The maximal budget for evaluations done by an optimization algorithm equals dimension * BUDGET_MULTIPLIER. diff --git a/src/ibea/combination.cpp b/src/ibea/combination.cpp index 03c2e0c868389ec3939e87fffc82329402246e2d..e2dc2bb424a702751ff7be94047d8d3b5c6376c2 100644 --- a/src/ibea/combination.cpp +++ b/src/ibea/combination.cpp @@ -1,10 +1,16 @@ -#include "population.h" -#include "combination.h" #include <utility> #include <cstdlib> + #include "../coco/coco.h" +#include "population.h" +#include "combination.h" + - std::pair <double,double> simple_combination(double parent1,double parent2, const double eta, coco_random_state_t *random_generator){ +std::pair <double,double> simple_combination(double parent1, + double parent2, + const double eta, + coco_random_state_t *random_generator) +{ double child1; double child2; double u = coco_random_uniform(random_generator); @@ -14,8 +20,8 @@ beta = pow(2*u,1/(1+eta)); } else { - beta = pow(1/(2*(1-u)),1/(1+eta)); - } + beta = pow(1/(2*(1-u)),1/(1+eta)); + } child1 = 0.5*((1+beta)*parent1 + (1-beta)*parent2); child2 = 0.5*((1+beta)*parent1 + (1-beta)*parent2); result= std::make_pair(child1,child2); @@ -23,21 +29,26 @@ } /* Recombinaison prédéfini */ -void combine(Population new_pop, Population & pop, coco_random_state_t *random_generator){ - double eta=20; +void combinate(Population pop_in, + Population & pop_out, + double eta, + double p_combination, + coco_random_state_t *random_generator) +{ double u; - double size = new_pop.getSize(); - double dimension = new_pop.getDim(); + double size = pop_in.getCurrentSize(); + double dimension = pop_in.getDim(); std::pair <double,double> childs; u = coco_random_uniform(random_generator); for (int i; i<floor(size/2); i++){ for (int j; j<floor(dimension/2); j++){ - if (u <= 1){ - childs = simple_combination(new_pop.getIndiv(i,j), new_pop.getIndiv(size-i-1,dimension-j-1), eta, random_generator); - pop.setIndiv(i,j,childs.first); - pop.setIndiv(size-i-1,dimension-j-1,childs.second); + if (u <= p_combination){ + childs = simple_combination(pop_in.getIndiv(i,j), pop_in.getIndiv(size-i-1,dimension-j-1), eta, random_generator); + pop_out.setIndiv(i,j,childs.first); + pop_out.setIndiv(size-i-1,dimension-j-1,childs.second); } } } + pop_out.setCurrenSize(size); } diff --git a/src/ibea/combination.h b/src/ibea/combination.h index cc90d8316ca8678d599fa74765c286da2d3edb81..7d6ede9fbdc370376724ed5233212004cb420d33 100644 --- a/src/ibea/combination.h +++ b/src/ibea/combination.h @@ -1,8 +1,14 @@ #ifndef COMBINATION_H #define COMBINATION_H -#include "../coco/coco.h" -#include "population.h" -double simple_combination(double parent, const double eta, coco_random_state_t *random_generator); -void combinate(Population population, Population & pop, coco_random_state_t *random_generator); -#endif +double simple_combination(double parent, + const double eta, + coco_random_state_t *random_generator); + +void combinate(Population population, + Population & pop, + double eta, + double p_combination, + coco_random_state_t *random_generator); + +#endif diff --git a/src/ibea/ibea.cpp b/src/ibea/ibea.cpp index b6c4424e07fb8d6ec6b071f9320045451faab9e7..b75f47d6e336023baf3576393f457b94aff20acc 100644 --- a/src/ibea/ibea.cpp +++ b/src/ibea/ibea.cpp @@ -1,14 +1,11 @@ #include "../coco/coco.h" #include "population.h" -#include "fitness.h" #include "tournament.h" #include "combination.h" #include "mutation.h" #include "ibea.h" - - -void ibea(void* evaluate, +void ibea(evaluate_function_t evaluate, const size_t dimension, const size_t number_of_objectives, const double *lower_bounds, @@ -20,43 +17,39 @@ void ibea(void* evaluate, int n_individus = 20; /* number of individus per generations */ int n_generations = (int) max_budget/n_individus; /* number of generations */ int mu = 10; /* number of tournament */ - int eta = 100; /* polynomiale mutation degree */ + double eta = 20; /* polynomiale mutation degree */ + double p_combination = 1; + double p_mutation = 0.1; + double kappa = 0.05; + /* Initialize */ Population pop = Population(n_individus, dimension, number_of_objectives); Population new_pop = Population(n_individus, dimension, number_of_objectives); - random_init(&pop, random_generator); + pop.random_init(lower_bounds, upper_bounds, random_generator); /* Iterations */ int m = 0; while (m < n_generations){ /* 2 Fitness assignment */ - fitnesses(&pop); + pop.evaluate(evaluate); + pop.compute_fitnesses(kappa); - new_pop_.empty(); + new_pop.empty(); while (new_pop.getCurrentSize() < n_individus){ /* 3 Environemental select */ - fitnesses_update(pop_); + pop.darwin(kappa); /* 4 */ /* 5 Fill mating pool */ - binary_tournament(pop, &new_pop, mu, random_generator); + binary_tournament(pop, new_pop, mu, random_generator); } /* 6 Combination and Mutation */ - pop_.empty(); - combinate(new_pop, &pop, random_generator); - mutate(&pop, lower_bounds, upper_bounds, eta, random_generator); + pop.empty(); + combinate(new_pop, pop, eta, p_combination,random_generator); + mutate(pop, lower_bounds, upper_bounds, eta, p_mutation, random_generator); m++; } } - -void random_init(Population & pop, coco_random_state_t *random_generator){ - for (int i=0; i < pop.getSize(); i++){ - for (int j=0; j < pop.getDim(); j++) { - range = upper_bounds[j] - lower_bounds[j]; - pop.setIndiv(i,j) = lower_bounds[j] + coco_random_uniform(random_generator) * range; - } - } -} diff --git a/src/ibea/ibea.h b/src/ibea/ibea.h index aa7da96c6e61e6e05425c843d047d743bcebb195..0708960ee232838ae91494541590bd2e4560d6f2 100644 --- a/src/ibea/ibea.h +++ b/src/ibea/ibea.h @@ -1,7 +1,9 @@ #ifndef IBEA_H #define IBEA_H -void ibea(void* evaluate, +typedef void (*evaluate_function_t)(const double *x, double *y); + +void ibea(evaluate_function_t evaluate, const size_t dimension, const size_t number_of_objectives, const double *lower_bounds, @@ -9,6 +11,4 @@ void ibea(void* evaluate, const size_t max_budget, coco_random_state_t *random_generator); -void random_init(&Population pop, coco_random_state_t *random_generator); - #endif diff --git a/src/ibea/indicator.cpp b/src/ibea/indicator.cpp index 6708a707e7d555bd38be719ebd1d6a7323491ebd..fb748493b9c8f3eb57dbddfe95b275bbb3a451dd 100644 --- a/src/ibea/indicator.cpp +++ b/src/ibea/indicator.cpp @@ -1,45 +1,34 @@ #include "indicator.h" /** - * Returns the associated espsilon-indicator. In the complete algorithm, we only - * need to take as arguments an only vector, but we still use here A and B as - * sets of vectors. Furthermore, instead of calling in every - * epsilon_indicator the method coco_evaluate, we better save every f(x) and - * enter as parameters of the function the two vectors f(x1) and f(x2) we want - * to compare. - * @param fa: image of the first vector to compare by f - * @param fb: image of the second vector to compare by f - * @returns: the espsilon-indicator - */ -double epsilon_indicator(double [][] a, double [][] b, int dim_obj, int dim_a = 1, int dim_b = 1) { - int i, j, k; - double eps = 0.0, eps_j = 0.0, eps_k=0.0, eps_temp; +* Returns the associated espsilon-indicator. In the complete algorithm, we only +* need to take as arguments an only vector, but we still use here A and B as +* sets of vectors. Furthermore, instead of calling in every +* epsilon_indicator the method coco_evaluate, we better save every f(x) and +* enter as parameters of the function the two vectors f(x1) and f(x2) we want +* to compare. +* @param fa: image of the first vector to compare by f +* @param fb: image of the second vector to compare by f +* @returns: the espsilon-indicator +*/ +double epsilon_indicator(double * a, double * b, int dim_obj) { + int k; + double eps_k=0.0, eps_temp; - /* Here we search for the value of - * I (A, B) = - * min{eps} (∀x2 ∈ B ∃x1 ∈ A : fi(x1) − eps ≤ fi(x2) for i ∈ {1,...,n}). - * eps is between 0 and the dimension of the vectors - * - */ - for (i = 0; i < dim_a; i++) { - for (j = 0; j < dim_b; j++) { - for (k = 0; k < dim_obj; k++) { - eps_temp = b[j][k] - a[i][k]; - if (k == 0) - eps_k = eps_temp; - else if (eps_k < eps_temp) - eps_k = eps_temp; - } - if (j == 0) - eps_j = eps_k; - else if (eps_j > eps_k) - eps_j = eps_k; - } - if (i == 0) - eps = eps_j; - else if (eps < eps_j) - eps = eps_j; - } - return eps; - } -} \ No newline at end of file + /* Here we search for the value of + * I (A, B) = + * min{eps} (∀x2 ∈ B ∃x1 ∈ A : fi(x1) − eps ≤ fi(x2) for i ∈ {1,...,n}). + * eps is between 0 and the dimension of the vectors + * + */ + + for (k = 0; k < dim_obj; k++) { + eps_temp = b[k] - a[k]; + if (k == 0) + eps_k = eps_temp; + else if (eps_k < eps_temp) + eps_k = eps_temp; + } + + return eps_k; +} diff --git a/src/ibea/indicator.h b/src/ibea/indicator.h index f78fa9e486092013d87f20c4aac2478e19f71376..5633c9e40e905d73d020e642dc20a2ad33976c52 100644 --- a/src/ibea/indicator.h +++ b/src/ibea/indicator.h @@ -1,6 +1,6 @@ #ifndef INDICATOR_H #define INDICATOR_H -double epsilon_indicator(); +double epsilon_indicator(double * a, double * b, int dim_obj ); #endif diff --git a/src/ibea/mutation.cpp b/src/ibea/mutation.cpp index 8ba01c6ceb6503882f1616d18a4efb8b9f84b57a..e495753f8033cee38e8c33caaba03345c441d7e1 100644 --- a/src/ibea/mutation.cpp +++ b/src/ibea/mutation.cpp @@ -7,9 +7,9 @@ #include "mutation.h" double polynomiale_mutation(double parent, - const double eta, const double lower_bound, const double upper_bound, + double eta, coco_random_state_t *random_generator) { double child; @@ -29,10 +29,11 @@ double polynomiale_mutation(double parent, return child; } -void mutate(&Population population, +void mutate(Population & population, const double *lower_bounds, const double *upper_bounds, - const double eta, + double eta, + double p_mutation, coco_random_state_t *random_generator) { double u; @@ -42,7 +43,7 @@ void mutate(&Population population, for (int i; i<size; i++){ for (int j; j<dimension; j++){ u = coco_random_uniform(random_generator); - if (u <= 0.01){ + if (u <= p_mutation){ population.setIndiv(i,j,polynomiale_mutation(population.getIndiv(i,j), eta, lower_bounds[j], upper_bounds[j], random_generator)); } } diff --git a/src/ibea/mutation.h b/src/ibea/mutation.h index 24ee24c18bb83b313bf280e72ad8c9e14f0aa208..90764e9d4b43d32f3be3ccb317145ea0f8d4318d 100644 --- a/src/ibea/mutation.h +++ b/src/ibea/mutation.h @@ -2,15 +2,16 @@ #define MUTATION_H double polynomiale_mutation(double parent, - const double eta, const double lower_bound, const double upper_bound, + double eta, coco_random_state_t *random_generator); -void mutate(&Population population, +void mutate(Population & population, const double *lower_bounds, const double *upper_bounds, - const double eta, + double eta, + double p_mutation, coco_random_state_t *random_generator); #endif diff --git a/src/ibea/population.cpp b/src/ibea/population.cpp index 8dc85711f18a19299b9521038e143295b36377d4..d349458211cb5c18192966c08a05543926406a15 100644 --- a/src/ibea/population.cpp +++ b/src/ibea/population.cpp @@ -1,11 +1,12 @@ #include <cstdlib> #include <cmath> +#include "../coco/coco.h" #include "indicator.h" #include "population.h" Population::Population(int size, int dimension, int n_objectives) : - size_(size), current_size_(0), dimension_(dimension), n_objectives_(n_objectives) + size_(size), current_size_(0), dimension_(dimension), n_objectives_(n_objectives) { population_ = (double **) malloc(size_*sizeof(double *)); for (int i=0; i<size_; i++){ @@ -18,9 +19,8 @@ Population::Population(int size, int dimension, int n_objectives) : } indicator_values_ = (double **) malloc(size_*sizeof(double *)); - indicator_values_[0] = NULL; - for (int i=1; i<size_; i++){ - indicator_values_[i] = (double *) malloc((size_-i)*sizeof(double)); + for (int i=0; i<size_; i++){ + indicator_values_[i] = (double *) malloc(size_*sizeof(double)); } fitnesses_ = (double *) malloc(dimension_*sizeof(double)); @@ -37,7 +37,7 @@ Population::~Population(){ for (int i=0; i<size_; i++){ free(values_[i]); } - free(values); + free(values_); /* Free indicator values */ for (int i=1; i<size_; i++){ @@ -57,6 +57,10 @@ int Population::getCurrentSize(){ return current_size_; } +void Population::setCurrenSize(int n){ + current_size_ = n; +} + int Population::getDim(){ return dimension_; } @@ -89,7 +93,21 @@ int Population::getMin(){ return ind_min_; } -void Population::evaluate(void* evaluate_function){ +void Population::random_init(const double *lower_bounds, + const double *upper_bounds, + coco_random_state_t *random_generator) + { + double range; + for (int i=0; i < size_; i++){ + for (int j=0; j < dimension_; j++) { + range = upper_bounds[j] - lower_bounds[j]; + population_[i][j] = lower_bounds[j] + coco_random_uniform(random_generator) * range; + } + } + current_size_ = size_; + } + +void Population::evaluate(evaluate_function_t evaluate_function){ for (int i=0; i<current_size_; i++){ evaluate_function(population_[i], values_[i]); } @@ -98,10 +116,10 @@ void Population::evaluate(void* evaluate_function){ void Population::compute_indicators(){ c_ = 0; for (int i=0; i<current_size_; i++){ - for (int j=i+1; j<current_size_; j++){ - indicator_values_[i][j] = indicator(values_[i], values_[j], n_objectives_); - if (indicator_values_[i][j] > c_){ - c_ = indicator_values_[i][j]; + for (int j=0; j<current_size_; j++){ + indicator_values_[i][j] = epsilon_indicator(values_[i], values_[j], n_objectives_); + if (abs(indicator_values_[i][j]) > c_){ + c_ = abs(indicator_values_[i][j]); } } } @@ -109,11 +127,74 @@ void Population::compute_indicators(){ void Population::compute_fitnesses(double kappa){ int d = c_ * kappa; + int min; + double fitness, min_value; + for (int i=0; i<current_size_; i++){ - fitness = 0 - for (int j=i+1; j<current_size_; j++){ - fitness += -exp(-indicator_values_[i][j]/d); + fitness = 0; + for (int j=0; j<current_size_; j++){ + if (i != j){ + fitness += -exp(-indicator_values_[j][i]/d); + } + } + fitnesses_[i] = fitness; + if (i == 0) { + min_value = fitness; + min = 0; + } + else { + if (min_value >= fitness) { + min_value = fitness; + min = i; + } + } + } + ind_min_ = min; +} + +void Population::darwin(double kappa){ + int d = c_ * kappa; + double * tmp_p; + double tmp; + + /* Update fitnesses */ + for (int i=0; i<current_size_; i++){ + if (i != ind_min_){ + fitnesses_[i] += exp(-indicator_values_[ind_min_][i]/d); + } + } + + /* Remove the individu with the minimum fitness : swapp values with last individu */ + tmp_p = population_[ind_min_]; + population_[ind_min_] = population_[current_size_-1]; + population_[current_size_-1] = tmp_p; + + tmp_p = values_[ind_min_]; + values_[ind_min_] = values_[current_size_-1]; + values_[current_size_-1] = tmp_p; + + tmp_p = indicator_values_[ind_min_]; + indicator_values_[ind_min_] = indicator_values_[current_size_-1]; + indicator_values_[current_size_-1] = tmp_p; + for (int j=0; j<current_size_; j++){ + tmp = indicator_values_[j][ind_min_]; + indicator_values_[j][ind_min_] = indicator_values_[j][current_size_-1]; + indicator_values_[j][current_size_-1] = tmp; + } + + tmp = fitnesses_[ind_min_]; + fitnesses_[ind_min_] = fitnesses_[current_size_-1]; + fitnesses_[current_size_-1] = tmp; + + current_size_ -= 1; + + /* Update c_ = max(abs(indicator_values))*/ + c_ = 0; + for (int i=0; i < current_size_; i++){ + for (int j=i+1; i < current_size_; j++){ + if (abs(indicator_values_[i][j]) > c_){ + c_ = abs(indicator_values_[i][j]); + } } - fitnesses_[i] = fitness } } diff --git a/src/ibea/population.h b/src/ibea/population.h index 514e66faa3c050949faac44c35bc60985ad22fba..e09da7f2aab491a69c542c54276bad9b210e0985 100644 --- a/src/ibea/population.h +++ b/src/ibea/population.h @@ -1,12 +1,15 @@ #ifndef POPULATION_H #define POPULATION_H +typedef void (*evaluate_function_t)(const double *x, double *y); + class Population { public: Population(int size_max, int dimension, int n_objectives); ~Population(); int getSize(); int getCurrentSize(); + void setCurrenSize(int n); int getDim(); void empty(); @@ -18,9 +21,13 @@ public: void setMin(int i); int getMin(); - void evaluate(void* evaluate_function); + void random_init(const double *lower_bounds, + const double *upper_bounds, + coco_random_state_t *random_generator); + void evaluate(evaluate_function_t evaluate_function); void compute_indicators(); - void compute_fitnesses(double kappa) + void compute_fitnesses(double kappa); + void darwin(double kappa); private: int size_; diff --git a/src/ibea/tournament.cpp b/src/ibea/tournament.cpp index 0a3c5d5f26340990fd6b199f3e8af5aa807974d1..3b3e9fcf8c04afab16d4f6aef7b543e267198883 100644 --- a/src/ibea/tournament.cpp +++ b/src/ibea/tournament.cpp @@ -3,28 +3,30 @@ #include "tournament.h" void binary_tournament(Population population_in, - &Population population_out, + Population & population_out, int mu, coco_random_state_t *random_generator) { + int n = population_out.getSize(); int size_in = population_in.getCurrentSize(); int size_out = population_out.getCurrentSize(); - int i,j + int i,j,k = 0; - for (int k = 0; k<mu; k++){ - i = (int) coco_random_uniform(random_generator)*size_in - j = (int) coco_random_uniform(random_generator)*size_in + while (k < mu && (size_out + k < n)){ + i = (int) coco_random_uniform(random_generator)*size_in; + j = (int) coco_random_uniform(random_generator)*size_in; if (population_in.getFit(i) > population_in.getFit(j)) { for (int m = 0; m<population_out.getDim(); m++){ - population_out.setIndiv(size_out + k, m, population_in.getIndiv(i,m)) + population_out.setIndiv(size_out + k, m, population_in.getIndiv(i,m)); } } else { for (int m = 0; m<population_out.getDim(); m++){ - population_out.setIndiv(size_out + k, m, population_in.getIndiv(j,m)) + population_out.setIndiv(size_out + k, m, population_in.getIndiv(j,m)); } } + k++; } - + population_out.setCurrenSize(n+k); } diff --git a/src/ibea/tournament.h b/src/ibea/tournament.h index 76498e105c74f499306318312b5136356fe85716..1903034a45acb01b045613268e680083a02acaba 100644 --- a/src/ibea/tournament.h +++ b/src/ibea/tournament.h @@ -2,7 +2,7 @@ #define TOURNAMENT_H void binary_tournament(Population population_in, - Population population_out, + Population & population_out, int mu, coco_random_state_t *random_generator); diff --git a/src/ibea_implementation.cpp b/src/ibea_implementation.cpp deleted file mode 100644 index 342c225fc5b8846c7c21512089633741607dfe3d..0000000000000000000000000000000000000000 --- a/src/ibea_implementation.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdlib> - -#include "coco/coco.h" -#include "ibea/ibea.h" -#include "ibea_implementation.h" - -void ibea_1(void* evaluate, - const size_t dimension, - const size_t number_of_objectives, - const double *lower_bounds, - const double *upper_bounds, - const size_t max_budget, - coco_random_state_t *random_generator) { - - -} diff --git a/src/ibea_implementation.h b/src/ibea_implementation.h deleted file mode 100644 index 67233f871cc72b3f7f0f062e8d4ca8eea46f6813..0000000000000000000000000000000000000000 --- a/src/ibea_implementation.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef IBEA_IMPLEMENTATION_H -#define IBEA_IMPLEMENTATION_H - - -void ibea_1(void* evaluate, - const size_t dimension, - const size_t number_of_objectives, - const double *lower_bounds, - const double *upper_bounds, - const size_t max_budget, - coco_random_state_t *random_generator); - -#endif