21#include "non_dominated_sort.h"
24void insert_node(list *node,
long x) {
27 printf(
"\n Error!! asked to enter after a NULL pointer, hence exiting \n");
30 temp = (list *)malloc(
sizeof(list));
32 temp->child = node->child;
34 if (node->child != NULL)
35 node->child->parent = temp;
41list *del_node(list *node) {
44 printf(
"\n Error!! asked to delete a NULL pointer, hence exiting \n");
48 temp->child = node->child;
49 if (temp->child != NULL)
50 temp->child->parent = temp;
60long check_dominance(individual *a, individual *b,
long nobj) {
66 if (a->constr_violation < 0 && b->constr_violation < 0) {
67 if (a->constr_violation > b->constr_violation)
69 else if (a->constr_violation < b->constr_violation)
74 if (a->constr_violation < 0 && b->constr_violation >= 0)
76 else if (a->constr_violation >= 0 && b->constr_violation < 0)
79 for (i = 0; i < nobj; i++) {
80 if (a->obj[i] < b->obj[i])
82 else if (a->obj[i] > b->obj[i])
85 if (flag1 == 1 && flag2 == 0)
87 else if (flag1 == 0 && flag2 == 1)
96void assign_crowding_distance_list(population *pop, list *lst,
long front_size,
long start_i, int64_t *sorted_index) {
104 if (front_size == 1) {
105 pop->ind[lst->index].crowd_dist = INF;
107 }
else if (front_size == 2) {
108 pop->ind[lst->index].crowd_dist = INF;
109 pop->ind[lst->child->index].crowd_dist = INF;
112 obj_array = (
long **)malloc(nobj *
sizeof(
long));
113 dist = (
long *)malloc(front_size *
sizeof(
long));
114 for (i = 0; i < nobj; i++)
115 obj_array[i] = (
long *)malloc(front_size *
sizeof(
long));
117 for (j = 0; j < front_size; j++) {
118 dist[j] = temp->index;
121 assign_crowding_distance(pop, dist, obj_array, front_size, nobj);
122 q_sort_dist(pop, dist, 0, front_size - 1);
123 for (j = 0; j < front_size; j++)
124 sorted_index[start_i + j] = dist[j];
126 for (i = 0; i < nobj; i++)
133void assign_crowding_distance_indices(population *pop,
long c1,
long c2,
long nobj) {
138 front_size = c2 - c1 + 1;
139 if (front_size == 1) {
140 pop->ind[c1].crowd_dist = INF;
142 }
else if (front_size == 2) {
143 pop->ind[c1].crowd_dist = INF;
144 pop->ind[c2].crowd_dist = INF;
147 obj_array = (
long **)malloc(nobj *
sizeof(
long));
148 dist = (
long *)malloc(front_size *
sizeof(
long));
149 for (i = 0; i < nobj; i++)
150 obj_array[i] = (
long *)malloc(front_size *
sizeof(
long));
151 for (j = 0; j < front_size; j++)
153 assign_crowding_distance(pop, dist, obj_array, front_size, nobj);
155 for (i = 0; i < nobj; i++)
163void quicksort_front_obj(population *pop,
long objcount,
long obj_array[],
long obj_array_size) {
164 q_sort_front_obj(pop, objcount, obj_array, 0, obj_array_size - 1);
170void q_sort_front_obj(population *pop,
long objcount,
long obj_array[],
long left,
long right) {
176 index = (left + right) / 2;
177 temp = obj_array[right];
178 obj_array[right] = obj_array[index];
179 obj_array[index] = temp;
180 pivot = pop->ind[obj_array[right]].obj[objcount];
182 for (j = left; j < right; j++) {
183 if (pop->ind[obj_array[j]].obj[objcount] <= pivot) {
186 obj_array[j] = obj_array[i];
191 temp = obj_array[index];
192 obj_array[index] = obj_array[right];
193 obj_array[right] = temp;
194 q_sort_front_obj(pop, objcount, obj_array, left, index - 1);
195 q_sort_front_obj(pop, objcount, obj_array, index + 1, right);
201void quicksort_dist(population *pop,
long *dist,
long front_size) {
202 q_sort_dist(pop, dist, 0, front_size - 1);
207void q_sort_dist(population *pop,
long *dist,
long left,
long right) {
213 index = (left + right) / 2;
215 dist[right] = dist[index];
217 pivot = pop->ind[dist[right]].crowd_dist;
219 for (j = left; j < right; j++) {
220 if (pop->ind[dist[j]].crowd_dist > pivot) {
229 dist[index] = dist[right];
231 q_sort_dist(pop, dist, left, index - 1);
232 q_sort_dist(pop, dist, index + 1, right);
238void assign_crowding_distance(population *pop,
long *dist,
long **obj_array,
long front_size,
long nobj) {
240 for (i = 0; i < nobj; i++) {
241 for (j = 0; j < front_size; j++)
242 obj_array[i][j] = dist[j];
243 quicksort_front_obj(pop, i, obj_array[i], front_size);
245 for (j = 0; j < front_size; j++)
246 pop->ind[dist[j]].crowd_dist = 0.0;
247 for (i = 0; i < nobj; i++)
248 pop->ind[obj_array[i][0]].crowd_dist = INF;
249 for (i = 0; i < nobj; i++) {
250 for (j = 1; j < front_size - 1; j++) {
251 if (pop->ind[obj_array[i][j]].crowd_dist != INF) {
252 if (pop->ind[obj_array[i][front_size - 1]].obj[i] == pop->ind[obj_array[i][0]].obj[i])
253 pop->ind[obj_array[i][j]].crowd_dist += 0.0;
255 pop->ind[obj_array[i][j]].crowd_dist += (pop->ind[obj_array[i][j + 1]].obj[i] - pop->ind[obj_array[i][j - 1]].obj[i]) / (pop->ind[obj_array[i][front_size - 1]].obj[i] - pop->ind[obj_array[i][0]].obj[i]);
259 for (j = 0; j < front_size; j++) {
260 if (pop->ind[dist[j]].crowd_dist != INF)
261 pop->ind[dist[j]].crowd_dist = (pop->ind[dist[j]].crowd_dist) / nobj;
276 long flag, popsize, i, end, front_size, rank = 1, j;
277 int64_t *sorted_index = NULL;
281 orig = (list *)malloc(
sizeof(list));
282 cur = (list *)malloc(
sizeof(list));
291 popsize = new_pop->popsize;
292 sorted_index = (int64_t *)malloc(
sizeof(*sorted_index) * popsize);
293 for (i = 0; i < popsize; i++) {
295 insert_node(temp1, i);
296 temp1 = temp1->child;
300 if (orig->child->child == NULL) {
301 new_pop->ind[orig->child->index].rank = rank;
302 new_pop->ind[orig->child->index].crowd_dist = INF;
303 sorted_index[i++] = orig->child->index;
308 insert_node(cur, temp1->index);
311 temp1 = del_node(temp1);
312 temp1 = temp1->child;
317 flag = check_dominance(&(new_pop->ind[temp1->index]),
318 &(new_pop->ind[temp2->index]), new_pop->nobj);
320 insert_node(orig, temp2->index);
321 temp2 = del_node(temp2);
323 temp2 = temp2->child;
326 temp2 = temp2->child;
329 }
while (end != 1 && temp2 != NULL);
330 if (flag == 0 || flag == 1) {
331 insert_node(cur, temp1->index);
333 temp1 = del_node(temp1);
335 temp1 = temp1->child;
336 }
while (temp1 != NULL);
339 new_pop->ind[temp2->index].rank = rank;
340 sorted_index[i++] = temp2->index;
341 temp2 = temp2->child;
342 }
while (temp2 != NULL);
343 assign_crowding_distance_list(new_pop, cur->child, front_size, j, sorted_index);
347 temp2 = del_node(temp2);
348 temp2 = temp2->child;
349 }
while (cur->child != NULL);
351 }
while (orig->child != NULL);
370void fill_population(population *pop,
long rows,
long columns,
double **columnValue,
long *maximize,
double *const_violation) {
373 fprintf(stderr,
"Null pointer passed to fill_population.\n");
376 pop->ind = (individual *)malloc(rows *
sizeof(individual));
378 pop->nbin = pop->ncons = pop->nreal = 0;
381 for (i = 0; i < rows; i++) {
382 pop->ind[i].xreal = NULL;
383 pop->ind[i].xbin = NULL;
384 pop->ind[i].gene = NULL;
385 pop->ind[i].obj = (
double *)malloc(
sizeof(
double) * pop->nobj);
387 pop->ind[i].constr_violation = const_violation[i];
389 pop->ind[i].constr_violation = 0;
390 pop->ind[i].constr = NULL;
391 pop->ind[i].rank = 0;
392 pop->ind[i].crowd_dist = 0;
393 for (j = 0; j < columns; j++) {
395 pop->ind[i].obj[j] = -1.0 * columnValue[j][i];
397 pop->ind[i].obj[j] = columnValue[j][i];
413 for (i = 0; i < pop->popsize; i++) {
414 if (pop->ind[i].xreal)
415 free(pop->ind[i].xreal);
417 free(pop->ind[i].obj);
418 if (pop->ind[i].xbin)
419 free(pop->ind[i].xbin);
420 if (pop->ind[i].constr)
421 free(pop->ind[i].constr);
422 for (j = 0; j < pop->nbin; j++)
423 if (pop->ind[i].gene && pop->ind[i].gene[j])
424 free(pop->ind[i].gene[j]);
425 if (pop->ind[i].gene)
426 free(pop->ind[i].gene);
int64_t * non_dominated_sort(population *new_pop)
Performs non-dominated sorting on a population and assigns ranks and crowding distances.
void fill_population(population *pop, long rows, long columns, double **columnValue, long *maximize, double *const_violation)
Initializes and fills the population structure with individuals and their objective values.
void free_pop_mem(population *pop)
Frees all dynamically allocated memory associated with a population.