예제 #1
0
파일: walksat.c 프로젝트: SRI-CSL/pce
/* 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);
}
예제 #2
0
파일: kmeans.c 프로젝트: megion/premir_cpp
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);
  }