int coco_archive_add_solution(coco_archive_t *archive, const double f1, const double f2, const char *text) { coco_archive_avl_item_t* insert_item = coco_archive_node_item_create(f1, f2, text); double *insert_objectives, *node_objectives; avl_node_t *node, *next_node; int update = 0; int dominance; insert_objectives = coco_archive_node_item_get_vector(insert_item); /* Find the first point that is not worse than the new point (NULL if such point does not exist) */ node = avl_item_search_right(archive->tree, insert_item, NULL); if (node == NULL) { /* The new point is an extremal point */ update = 1; next_node = archive->tree->head; } else { node_objectives = coco_archive_node_item_get_vector((coco_archive_avl_item_t*) node->item); dominance = mo_get_dominance(insert_objectives, node_objectives, archive->number_of_objectives); coco_free_memory(node_objectives); if (dominance > -1) { update = 1; next_node = node->next; if (dominance == 1) { /* The new point dominates the next point, remove the next point */ avl_node_delete(archive->tree, node); } } else { /* The new point is dominated, nothing more to do */ update = 0; } } if (!update) { coco_archive_node_item_free(insert_item, NULL); } else { /* Perform tree update */ while (next_node != NULL) { /* Check the dominance relation between the new node and the next node. There are only two possibilities: * dominance = 0: the new node and the next node are nondominated * dominance = 1: the new node dominates the next node */ node = next_node; node_objectives = coco_archive_node_item_get_vector((coco_archive_avl_item_t*) node->item); dominance = mo_get_dominance(insert_objectives, node_objectives, archive->number_of_objectives); coco_free_memory(node_objectives); if (dominance == 1) { /* The new point dominates the next point, remove the next point */ next_node = node->next; avl_node_delete(archive->tree, node); } else { break; } } avl_item_insert(archive->tree, insert_item); archive->is_up_to_date = 0; } coco_free_memory(insert_objectives); return update; }
/** * @brief Updates the archive and buffer trees with the given node. * * Checks for domination and updates the archive tree and the values of the indicators if the given node is * not weakly dominated by existing nodes in the archive tree. This is where the main computation of * indicator values takes place. * * @return 1 if the update was performed and 0 otherwise. */ static int logger_biobj_tree_update(logger_biobj_data_t *logger, const coco_problem_t *problem, logger_biobj_avl_item_t *node_item) { avl_node_t *node, *next_node, *new_node; int trigger_update = 0; int dominance; size_t i; int previous_unavailable = 0; /* Find the first point that is not worse than the new point (NULL if such point does not exist) */ node = avl_item_search_right(logger->archive_tree, node_item, NULL); if (node == NULL) { /* The new point is an extremal point */ trigger_update = 1; next_node = logger->archive_tree->head; } else { dominance = mo_get_dominance(node_item->y, ((logger_biobj_avl_item_t*) node->item)->y, logger->number_of_objectives); if (dominance > -1) { trigger_update = 1; next_node = node->next; if (dominance == 1) { /* The new point dominates the next point, remove the next point */ if (logger->compute_indicators) { for (i = 0; i < OBSERVER_BIOBJ_NUMBER_OF_INDICATORS; i++) { logger->indicators[i]->current_value -= ((logger_biobj_avl_item_t*) node->item)->indicator_contribution[i]; } } avl_item_delete(logger->buffer_tree, node->item); avl_node_delete(logger->archive_tree, node); } } else { /* The new point is dominated, nothing more to do */ trigger_update = 0; } } if (!trigger_update) { logger_biobj_node_free(node_item, NULL); } else { /* Perform tree update */ while (next_node != NULL) { /* Check the dominance relation between the new node and the next node. There are only two possibilities: * dominance = 0: the new node and the next node are nondominated * dominance = 1: the new node dominates the next node */ node = next_node; dominance = mo_get_dominance(node_item->y, ((logger_biobj_avl_item_t*) node->item)->y, logger->number_of_objectives); if (dominance == 1) { /* The new point dominates the next point, remove the next point */ if (logger->compute_indicators) { for (i = 0; i < OBSERVER_BIOBJ_NUMBER_OF_INDICATORS; i++) { logger->indicators[i]->current_value -= ((logger_biobj_avl_item_t*) node->item)->indicator_contribution[i]; } } next_node = node->next; avl_item_delete(logger->buffer_tree, node->item); avl_node_delete(logger->archive_tree, node); } else { break; } } new_node = avl_item_insert(logger->archive_tree, node_item); avl_item_insert(logger->buffer_tree, node_item); if (logger->compute_indicators) { logger_biobj_check_if_within_ROI(problem, new_node); if (node_item->within_ROI) { /* Compute indicator value for new node and update the indicator value of the affected nodes */ logger_biobj_avl_item_t *next_item, *previous_item; if (new_node->next != NULL) { next_item = (logger_biobj_avl_item_t*) new_node->next->item; if (next_item->within_ROI) { for (i = 0; i < OBSERVER_BIOBJ_NUMBER_OF_INDICATORS; i++) { logger->indicators[i]->current_value -= next_item->indicator_contribution[i]; if (strcmp(logger->indicators[i]->name, "hyp") == 0) { next_item->indicator_contribution[i] = (node_item->y[0] - next_item->y[0]) / (problem->nadir_value[0] - problem->best_value[0]) * (problem->nadir_value[1] - next_item->y[1]) / (problem->nadir_value[1] - problem->best_value[1]); } else { coco_error( "logger_biobj_tree_update(): Indicator computation not implemented yet for indicator %s", logger->indicators[i]->name); } logger->indicators[i]->current_value += next_item->indicator_contribution[i]; } } } previous_unavailable = 0; if (new_node->prev != NULL) { previous_item = (logger_biobj_avl_item_t*) new_node->prev->item; if (previous_item->within_ROI) { for (i = 0; i < OBSERVER_BIOBJ_NUMBER_OF_INDICATORS; i++) { if (strcmp(logger->indicators[i]->name, "hyp") == 0) { node_item->indicator_contribution[i] = (previous_item->y[0] - node_item->y[0]) / (problem->nadir_value[0] - problem->best_value[0]) * (problem->nadir_value[1] - node_item->y[1]) / (problem->nadir_value[1] - problem->best_value[1]); } else { coco_error( "logger_biobj_tree_update(): Indicator computation not implemented yet for indicator %s", logger->indicators[i]->name); } } } else { previous_unavailable = 1; } } else { previous_unavailable = 1; } if (previous_unavailable) { /* Previous item does not exist or is out of ROI, use reference point instead */ for (i = 0; i < OBSERVER_BIOBJ_NUMBER_OF_INDICATORS; i++) { if (strcmp(logger->indicators[i]->name, "hyp") == 0) { node_item->indicator_contribution[i] = (problem->nadir_value[0] - node_item->y[0]) / (problem->nadir_value[0] - problem->best_value[0]) * (problem->nadir_value[1] - node_item->y[1]) / (problem->nadir_value[1] - problem->best_value[1]); } else { coco_error( "logger_biobj_tree_update(): Indicator computation not implemented yet for indicator %s", logger->indicators[i]->name); } } } for (i = 0; i < OBSERVER_BIOBJ_NUMBER_OF_INDICATORS; i++) { logger->indicators[i]->current_value += node_item->indicator_contribution[i]; } } } } return trigger_update; }
int coco_archive_add_solution(coco_archive_t *archive, const double y1, const double y2, const char *text) { coco_archive_avl_item_t* insert_item; avl_node_t *node, *next_node; int update = 0; int dominance; double *y = coco_allocate_vector(2); y[0] = y1; y[1] = y2; insert_item = coco_archive_node_item_create(y, archive->ideal, archive->nadir, archive->number_of_objectives, text); coco_free_memory(y); /* Find the first point that is not worse than the new point (NULL if such point does not exist) */ node = avl_item_search_right(archive->tree, insert_item, NULL); if (node == NULL) { /* The new point is an extreme point */ update = 1; next_node = archive->tree->head; } else { dominance = mo_get_dominance(insert_item->normalized_y, ((coco_archive_avl_item_t*) node->item)->normalized_y, archive->number_of_objectives); if (dominance > -1) { update = 1; next_node = node->next; if (dominance == 1) { /* The new point dominates the next point, remove the next point */ assert((node != archive->extreme1) && (node != archive->extreme2)); avl_node_delete(archive->tree, node); } } else { /* The new point is dominated or equal to an existing one, ignore */ update = 0; } } if (!update) { coco_archive_node_item_free(insert_item, NULL); } else { /* Perform tree update */ while (next_node != NULL) { /* Check the dominance relation between the new node and the next node. There are only two possibilities: * dominance = 0: the new node and the next node are nondominated * dominance = 1: the new node dominates the next node */ node = next_node; dominance = mo_get_dominance(insert_item->normalized_y, ((coco_archive_avl_item_t*) node->item)->normalized_y, archive->number_of_objectives); if (dominance == 1) { next_node = node->next; /* The new point dominates the next point, remove the next point */ assert((node != archive->extreme1) && (node != archive->extreme2)); avl_node_delete(archive->tree, node); } else { break; } } if(avl_item_insert(archive->tree, insert_item) == NULL) { coco_warning("Solution %s did not update the archive", text); update = 0; } archive->is_up_to_date = 0; } return update; }