static int do_search(struct saucy *s) { int min; unprepare_permutation(s); /* Backtrack to the ancestor with zeta */ if (s->lev > s->anc) s->lev = s->anc + 1; /* Perform additional backtracking */ min = backtrack(s); /* Keep going while there are tree nodes to expand */ while (s->lev) { /* Descend to a new leaf node */ if (descend(s, &s->right, s->start[s->lev], min) && descend_left(s)) { /* Prepare permutation */ prepare_permutation(s); /* If we found an automorphism, return it */ if (s->is_automorphism(s)) { ++s->stats->gens; s->stats->support += s->ndiffs; update_theta(s); return s->consumer(s->n, s->gamma, s->ndiffs, s->unsupp, s->arg); } else { unprepare_permutation(s); } } /* If we get here, something went wrong; backtrack */ ++s->stats->bads; min = backtrack_bad(s); } /* Normalize group size */ while (s->stats->grpsize_base >= 10.0) { s->stats->grpsize_base /= 10; ++s->stats->grpsize_exp; } return 0; }
void SPF::learn() { double old_likelihood, delta_likelihood, likelihood = -1e10; int likelihood_decreasing_count = 0; time_t start_time, end_time; int iteration = 0; char iter_as_str[4]; bool converged = false; bool on_final_pass = false; while (!converged) { time(&start_time); iteration++; printf("iteration %d\n", iteration); reset_helper_params(); // update rate for user preferences b_theta.each_col() += sum(beta, 1); set<int> items; int user = -1, item, rating; for (int i = 0; i < settings->sample_size; i++) { if (on_final_pass && settings->final_pass_test) { user++; while (data->test_users.count(user)==0) { user++; } } else if (settings->svi) { user = gsl_rng_uniform_int(rand_gen, data->user_count()); } else { user = i; } bool user_converged = false; int user_iters = 0; while (!user_converged) { user_iters++; a_beta_user.zeros(); a_delta_user.zeros(); // look at all the user's items for (int j = 0; j < data->item_count(user); j++) { item = data->get_item(user, j); items.insert(item); rating = 1; //TODO: rating = data->get_train_rating(i); update_shape(user, item, rating); } // update per-user parameters double user_change = 0; if (!settings->factor_only && !settings->fix_influence) user_change += update_tau(user); if (!settings->social_only) user_change += update_theta(user); if (!settings->social_only && !settings->factor_only && !settings->fix_influence) { user_change /= 2; // if the updates are less than 1% change, the local params have converged if (user_change < 0.01) user_converged = true; } else { // if we're only looking at social or factor (not combined) // then the user parameters will always have converged with // a single pass (since there's nothing to balance against) user_converged = true; } } if (settings->verbose) printf("%d\tuser %d took %d iters to converge\n", iteration, user, user_iters); a_beta += a_beta_user; a_delta += a_delta_user; } if (!settings->social_only) { // update rate for item attributes b_beta.each_col() += sum(theta, 1); // update per-item parameters set<int>::iterator it; for (it = items.begin(); it != items.end(); it++) { item = *it; if (iter_count[item] == 0) iter_count[item] = 0; iter_count[item]++; update_beta(item); if (settings->item_bias) update_delta(item); } } else if (settings->item_bias) { set<int>::iterator it; for (it = items.begin(); it != items.end(); it++) { item = *it; if (iter_count[item] == 0) iter_count[item] = 0; iter_count[item]++; if (settings->item_bias) update_delta(item); } } // check for convergence if (on_final_pass) { printf("Final pass complete\n"); converged = true; old_likelihood = likelihood; likelihood = get_ave_log_likelihood(); delta_likelihood = abs((old_likelihood - likelihood) / old_likelihood); log_convergence(iteration, likelihood, delta_likelihood); } else if (iteration >= settings->max_iter) { printf("Reached maximum number of iterations.\n"); converged = true; old_likelihood = likelihood; likelihood = get_ave_log_likelihood(); delta_likelihood = abs((old_likelihood - likelihood) / old_likelihood); log_convergence(iteration, likelihood, delta_likelihood); } else if (iteration % settings->conv_freq == 0) { old_likelihood = likelihood; likelihood = get_ave_log_likelihood(); if (likelihood < old_likelihood) likelihood_decreasing_count += 1; else likelihood_decreasing_count = 0; delta_likelihood = abs((old_likelihood - likelihood) / old_likelihood); log_convergence(iteration, likelihood, delta_likelihood); if (settings->verbose) { printf("delta: %f\n", delta_likelihood); printf("old: %f\n", old_likelihood); printf("new: %f\n", likelihood); } if (iteration >= settings->min_iter && delta_likelihood < settings->likelihood_delta) { printf("Model converged.\n"); converged = true; } else if (iteration >= settings->min_iter && likelihood_decreasing_count >= 2) { printf("Likelihood decreasing.\n"); converged = true; } } // save intermediate results if (!converged && settings->save_freq > 0 && iteration % settings->save_freq == 0) { printf(" saving\n"); sprintf(iter_as_str, "%04d", iteration); save_parameters(iter_as_str); } // intermediate evaluation if (!converged && settings->eval_freq > 0 && iteration % settings->eval_freq == 0) { sprintf(iter_as_str, "%04d", iteration); evaluate(iter_as_str); } time(&end_time); log_time(iteration, difftime(end_time, start_time)); if (converged && !on_final_pass && (settings->final_pass || settings->final_pass_test)) { printf("final pass on all users.\n"); on_final_pass = true; converged = false; // we need to modify some settings for the final pass // things should look exactly like batch for all users if (settings->final_pass) { settings->set_stochastic_inference(false); settings->set_sample_size(data->user_count()); scale = 1; } else { settings->set_sample_size(data->test_users.size()); scale = data->user_count() / settings->sample_size; } } } save_parameters("final"); }
int * saucy_search(void) { int i; /* Do initialization steps if necessary */ if (!init) { init = 1; /* Initialize stats */ stats->grpsize_base = 1.0; stats->grpsize_exp = stats->nodes = stats->bads = stats->gens = 0; /* Preprocessing after initial coloring */ refine(); } /* Keep going while there are tree nodes to expand */ while (lev) { if (desc) { desc = 0; descend(); } /* Find a target cell */ ++stats->nodes; target_cell(); if (target != n+1) { descend_left(); continue; } /* We don't have a target, so we're discrete */ if (!have_zeta) { have_zeta = 1; for (i = 0; i < n; ++i) zeta[lab[i]] = i; if (canon != NULL) memcpy(canon, lab, n * sizeof(int)); } else { /* Prepare permutation and check */ for (i = 0; i < n; ++i) gamma[i] = lab[zeta[i]]; is_automorphism(); /* Do some stuff if we actually got an automorphism */ if (flag) { ++stats->gens; update_theta(); } /* Keep track of leaf nodes that are not automorphisms */ else { ++stats->bads; } } /* Since we're discrete, we need to backtrack */ backtrack(stats); desc = 1; if (flag) return gamma; } /* Normalize group size */ while (stats->grpsize_base >= 10.0) { stats->grpsize_base /= 10; ++stats->grpsize_exp; } /* All done */ return NULL; }