/* * Update the cost after swapping current medoid m with non-medoid n * Distance to closest medoid, closest medoid index are updated. */ static double pam_swap_cost(pam_partition p, size_t m, size_t n) { double cost = 0.0; size_t i, cl; gsl_vector_view col; /* Update for each column */ for (i = 0; i < p->M->size2; i++) { cl = gsl_vector_ulong_get(p->cl_index, i); /* If closest to medoid being removed, find new closest medoid */ if (cl == m) { col = gsl_matrix_column(p->M, i); gsl_vector_masked_min_index(&(col.vector), p->in_set, &cl, gsl_vector_ptr(p->cl_dist, i)); gsl_vector_ulong_set(p->cl_index, i, cl); } else { /* Check if the new medoid is closer than the old */ assert(gsl_vector_get(p->cl_dist, i) == gsl_matrix_get(p->M, gsl_vector_ulong_get(p->cl_index, i), i)); if (gsl_matrix_get(p->M, n, i) < gsl_vector_get(p->cl_dist, i)) { gsl_vector_set(p->cl_dist, i, gsl_matrix_get(p->M, n, i)); gsl_vector_ulong_set(p->cl_index, i, n); } } cost += gsl_vector_get(p->cl_dist, i); } return cost; }
/* Set the closest medoid, distance to closest medoid for column i */ static void pam_find_closest_medoid_index(pam_partition p, size_t i) { size_t index; double min; gsl_vector_view col; min = FLT_MAX; col = gsl_matrix_column(p->M, i); gsl_vector_masked_min_index(&(col.vector), p->in_set, &index, &min); assert(min < FLT_MAX); gsl_vector_ulong_set(p->cl_index, i, index); gsl_vector_set(p->cl_dist, i, min); }
static void dvine_select_order(dml_vine_t *vine, const gsl_matrix *data, dml_vine_weight_t weight, dml_measure_t ***measure_matrix, const gsl_rng *rng) { int n = (int) vine->dim; double **weight_matrix; size_t selected_node; gsl_vector_ulong *tour; gsl_vector_short *in_tour; double selected_cost, current_cost; size_t current_pos = 0, selected_pos = 0; // Initialized to avoid GCC warnings. double dik, dkj, dij; size_t i, j; int cut_index; // Compute the weights. The weights are minimized. weight_matrix = g_malloc_n(n, sizeof(double *)); for (size_t i = 0; i < n; i++) { weight_matrix[i] = g_malloc_n(n, sizeof(double)); for (size_t j = 0; j < i; j++) { switch (weight) { case DML_VINE_WEIGHT_TAU: weight_matrix[i][j] = 1 - fabs(dml_measure_tau_coef(measure_matrix[i][j])); break; case DML_VINE_WEIGHT_CVM: weight_matrix[i][j] = measure_matrix[i][j]->x->size - dml_measure_cvm_stat(measure_matrix[i][j]); break; default: weight_matrix[i][j] = 0; break; } weight_matrix[j][i] = weight_matrix[i][j]; } } // Compute an approximate solution for the TSP instance using the // Cheapest insertion heuristic. The dummy node has index n. tour = gsl_vector_ulong_alloc(n + 1); in_tour = gsl_vector_short_alloc(n + 1); gsl_vector_short_set_all(in_tour, FALSE); for (size_t node_count = 0; node_count < n + 1; node_count++) { // Select the node to be inserted. if (node_count == 0) { // Initial node (randomly selected). selected_node = floor((n + 1) * gsl_rng_uniform(rng)); gsl_vector_ulong_set(tour, node_count, selected_node); gsl_vector_short_set(in_tour, selected_node, TRUE); } else { selected_cost = GSL_DBL_MAX; // Rest of the nodes. Choose the nodes with the minimal insertion cost. for (size_t k = 0; k < n + 1; k++) { if (!gsl_vector_short_get(in_tour, k)) { if (node_count == 1) { i = gsl_vector_ulong_get(tour, 0); current_cost = (i == n || k == n) ? 0: weight_matrix[i][k]; current_pos = 0; } else { current_cost = GSL_DBL_MAX; for (size_t pos = 0; pos < node_count - 1; pos++) { i = gsl_vector_ulong_get(tour, pos); j = gsl_vector_ulong_get(tour, pos + 1); dik = (i == n || k == n) ? 0: weight_matrix[i][k]; dkj = (k == n || j == n) ? 0: weight_matrix[k][j]; dij = (i == n || j == n) ? 0: weight_matrix[i][j]; if (dik + dkj + dij < current_cost) { current_cost = dik + dkj + dij; current_pos = pos; } } } // Check the last position. i = gsl_vector_ulong_get(tour, node_count - 1); j = gsl_vector_ulong_get(tour, 0); dik = (i == n || k == n) ? 0: weight_matrix[i][k]; dkj = (k == n || j == n) ? 0: weight_matrix[k][j]; dij = (i == n || j == n) ? 0: weight_matrix[i][j]; if (dik + dkj + dij < current_cost) { current_cost = dik + dkj + dij; current_pos = node_count - 1; } if (current_cost < selected_cost) { selected_node = k; selected_cost = current_cost; selected_pos = current_pos; } } } // Add the selected node to the tour. for (size_t pos = selected_pos; pos < node_count; pos++) { i = gsl_vector_ulong_get(tour, pos + 1); if (pos == selected_pos) { gsl_vector_ulong_set(tour, pos + 1, selected_node); } else { gsl_vector_ulong_set(tour, pos + 1, j); } j = i; } gsl_vector_short_set(in_tour, selected_node, TRUE); } } // Cut the tour at the dummy node. cut_index = -1; for (int i = 0; i < n + 1; i++) { if (cut_index >= 0) { vine->order[i - cut_index - 1] = gsl_vector_ulong_get(tour, i); } else if (gsl_vector_ulong_get(tour, i) == n) { cut_index = i; } } for (int i = 0; i < cut_index; i++) { vine->order[n - cut_index + i] = gsl_vector_ulong_get(tour, i); } gsl_vector_ulong_free(tour); gsl_vector_short_free(in_tour); for (size_t i = 0; i < n; i++) { g_free(weight_matrix[i]); } g_free(weight_matrix); }