tactic clear_tactic(name const & n) { auto fn = [=](environment const &, io_state const &, proof_state const & _s) -> optional<proof_state> { if (!_s.get_goals()) { throw_no_goal_if_enabled(_s); return none_proof_state(); } proof_state s = apply_substitution(_s); goals const & gs = s.get_goals(); goal g = head(gs); goals tail_gs = tail(gs); if (auto p = g.find_hyp(n)) { expr const & h = p->first; unsigned i = p->second; buffer<expr> hyps; g.get_hyps(hyps); hyps.erase(hyps.size() - i - 1); if (depends_on(g.get_type(), h)) { throw_tactic_exception_if_enabled(s, sstream() << "invalid 'clear' tactic, conclusion depends on '" << n << "'"); return none_proof_state(); } if (auto h2 = depends_on(i, hyps.end() - i, h)) { throw_tactic_exception_if_enabled(s, sstream() << "invalid 'clear' tactic, hypothesis '" << *h2 << "' depends on '" << n << "'"); return none_proof_state(); } name_generator ngen = s.get_ngen(); expr new_type = g.get_type(); expr new_meta = mk_app(mk_metavar(ngen.next(), Pi(hyps, new_type)), hyps); goal new_g(new_meta, new_type); substitution new_subst = s.get_subst(); assign(new_subst, g, new_meta); proof_state new_s(s, goals(new_g, tail_gs), new_subst, ngen); return some_proof_state(new_s); } else { throw_tactic_exception_if_enabled(s, sstream() << "invalid 'clear' tactic, goal does not have a hypothesis " << " named '" << n << "'"); return none_proof_state(); } }; return tactic01(fn); }
tactic change_goal_tactic(elaborate_fn const & elab, expr const & e) { return tactic([=](environment const & env, io_state const & ios, proof_state const & s) { proof_state new_s = s; goals const & gs = new_s.get_goals(); if (!gs) { throw_no_goal_if_enabled(s); return proof_state_seq(); } expr t = head(gs).get_type(); bool report_unassigned = true; if (auto new_e = elaborate_with_respect_to(env, ios, elab, new_s, e, none_expr(), report_unassigned)) { goals const & gs = new_s.get_goals(); goal const & g = head(gs); substitution subst = new_s.get_subst(); auto tc = mk_type_checker(env); constraint_seq cs; if (tc->is_def_eq(t, *new_e, justification(), cs)) { if (cs) { unifier_config cfg(ios.get_options()); buffer<constraint> cs_buf; cs.linearize(cs_buf); to_buffer(new_s.get_postponed(), cs_buf); unify_result_seq rseq = unify(env, cs_buf.size(), cs_buf.data(), subst, cfg); return map2<proof_state>(rseq, [=](pair<substitution, constraints> const & p) -> proof_state { substitution const & subst = p.first; constraints const & postponed = p.second; substitution new_subst = subst; expr final_e = new_subst.instantiate_all(*new_e); expr M = g.mk_meta(mk_fresh_name(), final_e); goal new_g(M, final_e); assign(new_subst, g, M); return proof_state(new_s, cons(new_g, tail(gs)), new_subst, postponed); }); } expr M = g.mk_meta(mk_fresh_name(), *new_e); goal new_g(M, *new_e); assign(subst, g, M); return proof_state_seq(proof_state(new_s, cons(new_g, tail(gs)), subst)); } else { throw_tactic_exception_if_enabled(new_s, [=](formatter const & fmt) { format r = format("invalid 'change' tactic, the given type"); r += pp_indent_expr(fmt, *new_e); r += compose(line(), format("does not match the goal type")); r += pp_indent_expr(fmt, t); return r; }); return proof_state_seq(); } } return proof_state_seq(); }); }
tactic revert_tactic(name const & n) { auto fn = [=](environment const &, io_state const &, proof_state const & s) -> optional<proof_state> { goals const & gs = s.get_goals(); if (empty(gs)) { throw_no_goal_if_enabled(s); return none_proof_state(); } goal g = head(gs); goals tail_gs = tail(gs); if (auto p = g.find_hyp(n)) { expr const & h = p->first; unsigned i = p->second; buffer<expr> hyps; g.get_hyps(hyps); hyps.erase(hyps.size() - i - 1); if (optional<expr> other_h = depends_on(i, hyps.end() - i, h)) { throw_tactic_exception_if_enabled(s, sstream() << "invalid 'revert' tactic, hypothesis '" << local_pp_name(*other_h) << "' depends on '" << local_pp_name(h) << "'"); return none_proof_state(); // other hypotheses depend on h } name_generator ngen = s.get_ngen(); expr new_type = Pi(h, g.get_type()); expr new_meta = mk_app(mk_metavar(ngen.next(), Pi(hyps, new_type)), hyps); goal new_g(new_meta, new_type); substitution new_subst = s.get_subst(); assign(new_subst, g, mk_app(new_meta, h)); proof_state new_s(s, goals(new_g, tail_gs), new_subst, ngen); return some_proof_state(new_s); } else { throw_tactic_exception_if_enabled(s, sstream() << "invalid 'revert' tactic, unknown hypothesis '" << n << "'"); return none_proof_state(); } }; return tactic01(fn); }
tactic intros_tactic(list<name> _ns, bool relax_main_opaque) { auto fn = [=](environment const & env, io_state const &, proof_state const & s) { list<name> ns = _ns; goals const & gs = s.get_goals(); if (empty(gs)) { throw_no_goal_if_enabled(s); return optional<proof_state>(); } goal const & g = head(gs); name_generator ngen = s.get_ngen(); auto tc = mk_type_checker(env, ngen.mk_child(), relax_main_opaque); expr t = g.get_type(); expr m = g.get_meta(); bool gen_names = empty(ns); try { while (true) { if (!gen_names && is_nil(ns)) break; if (!is_pi(t)) { if (!is_nil(ns)) { t = tc->ensure_pi(t).first; } else { expr new_t = tc->whnf(t).first; if (!is_pi(new_t)) break; t = new_t; } } name new_name; if (!is_nil(ns)) { new_name = head(ns); ns = tail(ns); } else { new_name = get_unused_name(binding_name(t), m); } expr new_local = mk_local(ngen.next(), new_name, binding_domain(t), binding_info(t)); t = instantiate(binding_body(t), new_local); m = mk_app(m, new_local); } goal new_g(m, t); return some(proof_state(s, goals(new_g, tail(gs)), ngen)); } catch (exception &) { return optional<proof_state>(); } }; return tactic01(fn); }
double HDP_MEDOIDS (vector<Instance*>& data, vector< vector<double> >& means, Lookups* tables, vector<double> lambdas, dist_func df, int FIX_DIM) { // STEP ZERO: validate input and initialization int N = tables->nWords; int D = tables->nDocs; vector< pair<int, int> > doc_lookup = *(tables->doc_lookup); double lambda_global = lambdas[0]; double lambda_local = lambdas[1]; vector< vector<double> > global_means (1, vector<double>(FIX_DIM, 0.0)); vector< vector<int> > k (D, vector<int>(1,0)); // global association vector<int> z (N, 0); // local assignment vector<int> global_asgn (N, 0); // global assignment // STEP ONE: a. set initial *global* medoid as global mean compute_assignment (global_asgn, k, z, tables); compute_means (data, global_asgn, FIX_DIM, global_means); double last_cost = compute_cost (data, global_means, k, z, lambdas, tables, df, FIX_DIM); double new_cost = last_cost; while (true) { // 4. for each point x_ij, for (int j = 0; j < D; j ++) { for (int i = doc_lookup[j].first; i < doc_lookup[j].second; i++) { int num_global_means = global_means.size(); vector<double> d_ij (num_global_means, 0.0); for (int p = 0; p < num_global_means; p ++) { Instance* temp_ins = vec2ins(global_means[p]); double euc_dist = df(data[i], temp_ins, FIX_DIM); d_ij[p] = euc_dist * euc_dist; delete temp_ins; } set<int> temp; for (int p = 0; p < num_global_means; p ++) temp.insert(p); int num_local_means = k[j].size(); for (int q = 0; q < num_local_means; q ++) temp.erase(k[j][q]); set<int>::iterator it; for (it=temp.begin(); it!=temp.end();++it) d_ij[*it] += lambda_local; int min_p = -1; double min_dij = INF; for (int p = 0; p < num_global_means; p ++) if (d_ij[p] < min_dij) { min_p = p; min_dij = d_ij[p]; } if (min_dij > lambda_global + lambda_local) { z[i] = num_local_means; k[j].push_back(num_global_means); vector<double> new_g(FIX_DIM, 0.0); for (int f = 0; f < data[i]->fea.size(); f++) new_g[data[i]->fea[f].first-1] = data[i]->fea[f].second; global_means.push_back(new_g); // cout << "global and local increment" << endl; } else { bool c_exist = false; for (int c = 0; c < num_local_means; c ++) if (k[j][c] == min_p) { z[i] = c; c_exist = true; break; } if (!c_exist) { z[i] = num_local_means; k[j].push_back(min_p); // cout << "local increment" << endl; } } } } /* cout << "half..........." << endl; cout << "#global created: " << global_means.size() << ", #global used: " << get_num_global_means(k); */ new_cost = compute_cost (data, global_means, k, z, lambdas, tables, df, FIX_DIM); // 5. for all local clusters, for (int j = 0; j < D; j ++) { int begin_i = doc_lookup[j].first; int end_i = doc_lookup[j].second; int doc_len = doc_lookup[j].second - doc_lookup[j].first; int num_local_means = k[j].size(); // all local clusters are distinct to each other /* set<int> temp; for (int y = 0; y < num_local_means; y++) temp.insert(k[j][y]); cout << temp.size() << " ==? " << num_local_means << endl; assert (temp.size() == num_local_means); */ // compute means of local clusters vector< vector<double> > local_means (num_local_means, vector<double>(FIX_DIM, 0.0)); vector<int> local_asgn (z.begin()+begin_i, z.begin()+end_i); vector<Instance*> local_data (data.begin()+begin_i,data.begin()+end_i); compute_means (local_data, local_asgn, FIX_DIM, local_means); assert (num_local_means == local_means.size()); // pre-compute instances for global means int num_global_means = global_means.size(); vector<Instance*> temp_global_means (num_global_means, NULL); for (int p = 0; p < num_global_means; p ++) temp_global_means[p] = vec2ins (global_means[p]); // pre-compute instances for local means vector<Instance*> temp_local_means (num_local_means, NULL); for (int c = 0; c < num_local_means; c ++) temp_local_means[c] = vec2ins (local_means[c]); for (int c = 0; c < num_local_means; c++) { // compute distance of local clusters to each global cluster num_global_means = global_means.size(); vector<double> d_jcp (num_global_means, 0.0); double sum_d_ijc = 0.0; for (int i = doc_lookup[j].first; i < doc_lookup[j].second; i ++) { if (z[i] != c) continue; double local_dist = df (data[i], temp_local_means[c], FIX_DIM); sum_d_ijc += local_dist * local_dist; for (int p = 0; p < num_global_means; p ++) { double dist = df (data[i], temp_global_means[p], FIX_DIM); d_jcp[p] += dist * dist; } } int min_p = -1; double min_d_jcp = INF; for (int p = 0; p < num_global_means; p ++) if (d_jcp[p] < min_d_jcp) { min_p = p; min_d_jcp = d_jcp[p]; } assert (min_p >= 0); // cout << min_d_jcp << " " << lambda_global << " " << sum_d_ijc << endl; if (min_d_jcp > lambda_global + sum_d_ijc) { global_means.push_back(local_means[c]); // push mu_jc temp_global_means.push_back(vec2ins (local_means[c])); k[j][c] = num_global_means; // cout << "global increment" << endl; } else { k[j][c] = min_p; } } for (int c = 0; c < num_local_means; c ++) delete temp_local_means[c]; num_global_means = global_means.size(); for (int p = 0; p < num_global_means; p ++) delete temp_global_means[p]; } // 6. for each global clusters, compute_assignment (global_asgn, k, z, tables); /* cout << "compute global means.." << endl; cout << "#global created: " << global_means.size() << ", #global used: " << get_num_global_means(k); */ compute_means (data, global_asgn, FIX_DIM, global_means); // 7. convergence? new_cost = compute_cost (data, global_means, k, z, lambdas, tables, df, FIX_DIM); if ( new_cost < objmin ) objmin = new_cost; objmin_trace << omp_get_wtime()-start_time << " " << objmin << endl; if (new_cost == last_cost) break; if (new_cost < last_cost) { last_cost = new_cost; } else { cerr << "failure" << endl; return INF; assert(false); } } means = global_means; return last_cost; }// entry main function