/* MaxWalkSAT */ void mw_sat(samp_table_t *table, int32_t num_trials, double rvar_probability, int32_t max_flips, uint32_t timeout) { rule_inst_table_t *rule_inst_table = &table->rule_inst_table; atom_table_t *atom_table = &table->atom_table; int32_t i, j; time_t fintime; if (timeout != 0) { fintime = time(NULL) + timeout; } double best_cost = DBL_MAX; for (i = 0; i < num_trials; i++) { init_random_assignment(table); //scan_rule_instances(table); for (j = 0; j < rule_inst_table->num_rule_insts; j++) { if (rule_inst_table->rule_insts[j]->weight == DBL_MAX) rule_inst_table->assignment[j] = v_up_true; else rule_inst_table->assignment[j] = v_true; } init_live_clauses(table); scan_live_clauses(table); if (get_verbosity_level() >= 3) { printf("\n[mw_sat] Trial %d: \n", i); print_live_clauses(table); } for (j = 0; j < max_flips; j++) { if (timeout != 0 && time(NULL) >= fintime) { printf("Timeout after %"PRIu32" samples\n", i); break; } if (rule_inst_table->unsat_clauses.length == 0 && rule_inst_table->unsat_soft_rules.nelems == 0) { return; } int32_t c = genrand_uint(rule_inst_table->unsat_clauses.length + rule_inst_table->unsat_soft_rules.nelems); if (c < rule_inst_table->unsat_clauses.length) { /* picked a hard clause */ samp_clause_t *clause = choose_random_clause(&rule_inst_table->unsat_clauses); int32_t litidx = choose_clause_var(table, clause, rvar_probability); if (litidx == clause->num_lits) { if (get_verbosity_level() >= 3) { printf("[flip_rule_to_unsat] Rule %d: ", clause->rule_index); print_rule_instance(rule_inst_table->rule_insts[clause->rule_index], table); printf("\n"); } /* picked the rule auxiliary variable, i.e., rinst T -> F */ hmap_get(&rule_inst_table->unsat_soft_rules, clause->rule_index); rule_inst_table->assignment[clause->rule_index] = v_false; rule_inst_t *rinst = rule_inst_table->rule_insts[clause->rule_index]; rule_inst_table->unsat_weight += rinst->weight; /* Is this really going to do the right thing?? */ rule_inst_table->sat_weight -= rinst->weight; /* move unsat_clauses to live_clause_list and rescan */ clause_list_concat(&rule_inst_table->unsat_clauses, &rule_inst_table->live_clauses); scan_live_clauses(table); } else { flip_unfixed_variable(table, var_of(clause->disjunct[litidx])); } } else { /* picked a soft rule auxiliary variable, i.e., rinst F -> T */ int32_t rule_index = hmap_remove_random(&rule_inst_table->unsat_soft_rules); rule_inst_table->assignment[rule_index] = v_true; rule_inst_t *rinst = rule_inst_table->rule_insts[rule_index]; rule_inst_table->unsat_weight -= rinst->weight; rule_inst_table->sat_weight += rinst->weight; if (get_verbosity_level() >= 3) { printf("[flip_rule_to_sat] Rule %d: ", rule_index); print_rule_instance(rinst, table); printf("\n"); } /* move watch[~r] to live_clause_list and rescan */ clause_list_concat(&rule_inst_table->rule_watched[rule_index], &rule_inst_table->live_clauses); scan_live_clauses(table); } if (get_verbosity_level() >= 1) { printf("[mw_sat] Flip %d: # unsat hard = %d, # unsat soft = %d, " "weight of unsat soft = %f; weight of sat soft = %f\n", j, rule_inst_table->unsat_clauses.length, rule_inst_table->unsat_soft_rules.nelems, rule_inst_table->unsat_weight, rule_inst_table->sat_weight ); } if (get_verbosity_level() >= 3) { print_live_clauses(table); } if (best_cost > rule_inst_table->unsat_weight) { best_cost = rule_inst_table->unsat_weight; copy_assignment_array(atom_table); } } } restore_assignment_array(atom_table); }
void kmeans( int dim, // dimension of data double *X, // pointer to data int n, // number of elements int k, // number of clusters double *cluster_centroid, // initial cluster centroids int *cluster_assignment_final // output ) { double *dist = (double *)malloc(sizeof(double) * n * k); int *cluster_assignment_cur = (int *)malloc(sizeof(int) * n); int *cluster_assignment_prev = (int *)malloc(sizeof(int) * n); double *point_move_score = (double *)malloc(sizeof(double) * n * k); if (!dist || !cluster_assignment_cur || !cluster_assignment_prev || !point_move_score) fail("Error allocating dist arrays"); // initial setup calc_all_distances(dim, n, k, X, cluster_centroid, dist); choose_all_clusters_from_distances(dim, n, k, dist, cluster_assignment_cur); copy_assignment_array(n, cluster_assignment_cur, cluster_assignment_prev); // BATCH UPDATE double prev_totD = BIG_double; int batch_iteration = 0; while (batch_iteration < MAX_ITERATIONS) { // printf("batch iteration %d \n", batch_iteration); // cluster_diag(dim, n, k, X, cluster_assignment_cur, cluster_centroid); // update cluster centroids calc_cluster_centroids(dim, n, k, X, cluster_assignment_cur, cluster_centroid); // deal with empty clusters // XXXXXXXXXXXXXX // see if we've failed to improve double totD = calc_total_distance(dim, n, k, X, cluster_centroid, cluster_assignment_cur); if (totD > prev_totD) // failed to improve - currently solution worse than previous { // restore old assignments copy_assignment_array(n, cluster_assignment_prev, cluster_assignment_cur); // recalc centroids calc_cluster_centroids(dim, n, k, X, cluster_assignment_cur, cluster_centroid); printf(" negative progress made on this step - iteration completed (%.2f) \n", totD - prev_totD); // done with this phase break; } // save previous step copy_assignment_array(n, cluster_assignment_cur, cluster_assignment_prev); // move all points to nearest cluster calc_all_distances(dim, n, k, X, cluster_centroid, dist); choose_all_clusters_from_distances(dim, n, k, dist, cluster_assignment_cur); int change_count = assignment_change_count(n, cluster_assignment_cur, cluster_assignment_prev); printf("%3d %u %9d %16.2f %17.2f\n", batch_iteration, 1, change_count, totD, totD - prev_totD); fflush(stdout); // done with this phase if nothing has changed if (change_count == 0) { printf(" no change made on this step - iteration completed \n"); break; } prev_totD = totD; batch_iteration++; } cluster_diag(dim, n, k, X, cluster_assignment_cur, cluster_centroid); // ONLINE UPDATE /* The online update prtion of this code has never worked properly, but batch update has been adequate for our projects so far. int online_iteration = 0; int last_point_moved = 0; int cluster_changed[MAX_CLUSTERS]; for (int ii = 0; ii < k; ii++) cluster_changed[ii] = 1; int cluster_member_count[MAX_CLUSTERS]; get_cluster_member_count(n, k, cluster_assignment_cur, cluster_member_count); while (online_iteration < MAX_ITERATIONS) { // printf("online iteration %d \n", online_iteration); // for each cluster for (int ii = 0; ii < k; ii++) if (cluster_changed[ii]) update_delta_score_table(dim, n, k, X, cluster_assignment_cur, cluster_centroid, cluster_member_count, point_move_score, ii); // pick a point to move // look at points in sequence starting at one after previously moved point int make_move = 0; int point_to_move = -1; int target_cluster = -1; for (int ii = 0; ii < n; ii++) { int point_to_consider = (last_point_moved + 1 + ii) % n; // find the best target for it int best_target_cluster = -1; int best_match_count = 0; double best_delta = BIG_double; // for each possible target for (int jj = 0; jj < k; jj++) { double cur_delta = point_move_score[point_to_consider*k + jj]; // is this the best move so far? if (cur_delta < best_delta) // yes - record it { best_target_cluster = jj; best_delta = cur_delta; best_match_count = 1; } else if (cur_delta == best_delta) // no, but it's tied with the best one best_match_count++; } // is the best cluster for this point its current cluster? if (best_target_cluster == cluster_assignment_cur[point_to_consider]) // yes - don't move this point continue; // do we have a unique best move? if (best_match_count > 1) // no - don't move this point (ignore ties) continue; else // yes - we've found a good point to move { point_to_move = point_to_consider; target_cluster = best_target_cluster; make_move = 1; break; } } if (make_move) { // where should we move it to? printf(" %10d: moved %d to %d \n", point_to_move, cluster_assignment_cur[point_to_move], target_cluster); // mark which clusters have been modified for (int ii = 0; ii < k; ii++) cluster_changed[ii] = 0; cluster_changed[cluster_assignment_cur[point_to_move]] = 1; cluster_changed[target_cluster] = 1; // perform move perform_move(dim, n, k, X, cluster_assignment_cur, cluster_centroid, cluster_member_count, point_to_move, target_cluster); // count an iteration every time we've cycled through all the points if (point_to_move < last_point_moved) online_iteration++; last_point_moved = point_to_move; } } */ // printf("iterations: %3d %3d \n", batch_iteration, online_iteration); // write to output array copy_assignment_array(n, cluster_assignment_cur, cluster_assignment_final); free(dist); free(cluster_assignment_cur); free(cluster_assignment_prev); free(point_move_score); }