optional<expr> mk_class_instance(environment const & env, io_state const & ios, local_context const & ctx, name const & prefix, expr const & type, bool relax_opaque, bool use_local_instances, unifier_config const & cfg) { auto C = std::make_shared<class_instance_context>(env, ios, prefix, relax_opaque, use_local_instances); if (!is_ext_class(C->tc(), type)) return none_expr(); expr meta = ctx.mk_meta(C->m_ngen, some_expr(type), type.get_tag()); unsigned depth = 0; constraint c = mk_class_instance_cnstr(C, ctx, meta, depth); unifier_config new_cfg(cfg); new_cfg.m_discard = true; new_cfg.m_use_exceptions = true; new_cfg.m_pattern = true; new_cfg.m_kind = C->m_conservative ? unifier_kind::VeryConservative : unifier_kind::Liberal; try { auto seq = unify(env, 1, &c, C->m_ngen.mk_child(), substitution(), new_cfg); while (true) { auto p = seq.pull(); lean_assert(p); substitution s = p->first.first; expr r = s.instantiate_all(meta); if (!has_expr_metavar_relaxed(r)) return some_expr(r); seq = p->second; } } catch (exception &) { return none_expr(); } }
bool match_pattern(type_checker & tc, expr const & pattern, declaration const & d, unsigned max_steps, bool cheap) { name_generator ngen = tc.mk_ngen(); buffer<level> ls; unsigned num_ls = d.get_num_univ_params(); for (unsigned i = 0; i < num_ls; i++) ls.push_back(mk_meta_univ(ngen.next())); expr dt = instantiate_type_univ_params(d, to_list(ls.begin(), ls.end())); unsigned num_e = get_expect_num_args(tc, pattern); unsigned num_d = get_expect_num_args(tc, dt); if (num_e > num_d) return false; for (unsigned i = 0; i < num_d - num_e; i++) { dt = tc.whnf(dt).first; expr local = mk_local(ngen.next(), binding_domain(dt)); dt = instantiate(binding_body(dt), local); } try { unifier_config cfg; cfg.m_max_steps = max_steps; cfg.m_kind = cheap ? unifier_kind::Cheap : unifier_kind::Liberal; cfg.m_ignore_context_check = true; auto r = unify(tc.env(), pattern, dt, tc.mk_ngen(), substitution(), cfg); return static_cast<bool>(r.pull()); } catch (exception&) { return false; } }
string subst (const string& model, const string& a0, const string& a1) { vector<string> args(10); args[0] = a0; args[1] = a1; return substitution (model, args); }
int main() { Test test; substitution(test); std::cout << test.integer << std::endl; return 0; }
string subst (const string& model, const string& a0, const string& a1, const string& a2, const string& a3) { vector<string> args(10); args[0] = a0; args[1] = a1; args[2] = a2; args[3] = a3; return substitution (model, args); }
string subst (const string& model, const string& a0, const string& a1, const string& a2, const string& a3, const string& a4, const string& a5, const string& a6) { vector<string> args(10); args[0] = a0; args[1] = a1; args[2] = a2; args[3] = a3; args[4] = a4; args[5] = a5; args[6] = a6; return substitution (model, args); }
QVariant QSystemLocalePrivate::toString(const QDate &date, QLocale::FormatType type) { SYSTEMTIME st; memset(&st, 0, sizeof(SYSTEMTIME)); st.wYear = date.year(); st.wMonth = date.month(); st.wDay = date.day(); DWORD flags = (type == QLocale::LongFormat ? DATE_LONGDATE : DATE_SHORTDATE); wchar_t buf[255]; if (GetDateFormat(lcid, flags, &st, NULL, buf, 255)) { QString format = QString::fromWCharArray(buf); if (substitution() == SAlways) substituteDigits(format); return format; } return QString(); }
void potential_mut(int codon[], double *s_total) { int k, l, same, nonsense, substcodon[3][3][3]; substitution(codon, substcodon); for(k = 0; k < 3; k++) { same = 0; nonsense = 0; for(l = 0; l < 3; l++) { if(aa[calc_codon(substcodon[k][l])] == stopcodon) { nonsense++; } else { if(aa[calc_codon(substcodon[k][l])] == aa[calc_codon(codon)]) same++; } } *s_total += (double)same / (double)(3 - nonsense); } }
QVariant QSystemLocalePrivate::toString(const QTime &time, QLocale::FormatType) { SYSTEMTIME st; memset(&st, 0, sizeof(SYSTEMTIME)); st.wHour = time.hour(); st.wMinute = time.minute(); st.wSecond = time.second(); st.wMilliseconds = 0; DWORD flags = 0; wchar_t buf[255]; if (GetTimeFormat(lcid, flags, &st, NULL, buf, 255)) { QString format = QString::fromWCharArray(buf); if (substitution() == SAlways) substituteDigits(format); return format; } return QString(); }
/** * Text substitution. Creates a string by replacing all the $n * occurences in the model string, with the corresponding arguments. * Example : * subst("float $0 = $1;", "var", T(10.2)) */ string subst (const string& model, const vector<string>& args) { return substitution(model, args); }
/** Run alignment algorithm. \param first_last Last aligned position in first sequence (output) \param second_last Last aligned position in second sequence (output) */ void align(int& first_last, int& second_last) const { adjust_matrix_size(); limit_range(); make_frame(); ASSERT_TRUE(!local() || max_errors() == -1); int& r_row = first_last; int& r_col = second_last; r_row = r_col = -1; for (int row = 0; row <= max_row(); row++) { int start_col = min_col(row); int stop_col = max_col(row); int min_score_col = start_col; for (int col = start_col; col <= stop_col; col++) { ASSERT_TRUE(col >= 0 && col < side()); ASSERT_TRUE(in(row, col)); int match = at(row - 1, col - 1) + substitution(row, col); int gap1 = at(row, col - 1) + gap_penalty(); int gap2 = at(row - 1, col) + gap_penalty(); int score = std::min(match, std::min(gap1, gap2)); if (local()) { score = std::min(score, 0); } at(row, col) = score; if (score < at(row, min_score_col)) { min_score_col = col; } track(row, col) = (score == match) ? MATCH : (score == gap1) ? COL_INC : ROW_INC; } if (max_errors() != -1 && at(row, min_score_col) > max_errors()) { break; } r_row = row; r_col = min_score_col; } if (max_errors() == -1) { // col -> max_col in this row ASSERT_TRUE(in(max_row(), max_col(max_row()))); ASSERT_EQ(r_row, max_row()); r_col = max_col(max_row()); // if stopped earlier because of gap range int last_row = contents().first_size() - 1; int last_col = contents().second_size() - 1; if (r_row == last_row) { while (r_col < last_col) { r_col += 1; track(r_row, r_col) = COL_INC; } } else if (r_col == last_col) { while (r_row < last_row) { r_row += 1; track(r_row, r_col) = ROW_INC; } } else { throw Exception("row and column are not last"); } } }
format goal::pp(formatter const & fmt) const { return pp(fmt, substitution()); }
/** \brief Given a term <tt>a : a_type</tt>, and a metavariable \c m, creates a constraint that considers coercions from a_type to the type assigned to \c m. */ constraint mk_coercion_cnstr(type_checker & from_tc, type_checker & to_tc, coercion_info_manager & infom, expr const & m, expr const & a, expr const & a_type, justification const & j, unsigned delay_factor, bool lift_coe) { auto choice_fn = [=, &from_tc, &to_tc, &infom](expr const & meta, expr const & d_type, substitution const & s) { expr new_a_type; justification new_a_type_jst; if (is_meta(a_type)) { auto p = substitution(s).instantiate_metavars(a_type); new_a_type = p.first; new_a_type_jst = p.second; } else { new_a_type = a_type; } if (is_meta(new_a_type)) { if (delay_factor < to_delay_factor(cnstr_group::DelayedChoice)) { // postpone... return lazy_list<constraints>(constraints(mk_coercion_cnstr(from_tc, to_tc, infom, m, a, a_type, justification(), delay_factor+1, lift_coe))); } else { // giveup... return lazy_list<constraints>(constraints(mk_eq_cnstr(meta, a, justification()))); } } constraint_seq cs; new_a_type = from_tc.whnf(new_a_type, cs); if ((lift_coe && is_pi_meta(d_type)) || (!lift_coe && is_meta(d_type))) { // case-split buffer<expr> locals; expr it_from = new_a_type; expr it_to = d_type; while (is_pi(it_from) && is_pi(it_to)) { expr dom_from = binding_domain(it_from); expr dom_to = binding_domain(it_to); if (!from_tc.is_def_eq(dom_from, dom_to, justification(), cs)) return lazy_list<constraints>(); expr local = mk_local(mk_fresh_name(), binding_name(it_from), dom_from, binder_info()); locals.push_back(local); it_from = instantiate(binding_body(it_from), local); it_to = instantiate(binding_body(it_to), local); } buffer<expr> alts; get_coercions_from(from_tc.env(), it_from, alts); expr fn_a; if (!locals.empty()) fn_a = mk_local(mk_fresh_name(), "f", new_a_type, binder_info()); buffer<constraints> choices; buffer<expr> coes; // first alternative: no coercion constraint_seq cs1 = cs + mk_eq_cnstr(meta, a, justification()); choices.push_back(cs1.to_list()); unsigned i = alts.size(); while (i > 0) { --i; expr coe = alts[i]; if (!locals.empty()) coe = Fun(fn_a, Fun(locals, mk_app(coe, mk_app(fn_a, locals)))); expr new_a = copy_tag(a, mk_app(coe, a)); coes.push_back(coe); constraint_seq csi = cs + mk_eq_cnstr(meta, new_a, new_a_type_jst); choices.push_back(csi.to_list()); } return choose(std::make_shared<coercion_elaborator>(infom, meta, to_list(choices.begin(), choices.end()), to_list(coes.begin(), coes.end()))); } else { list<expr> coes = get_coercions_from_to(from_tc, to_tc, new_a_type, d_type, cs, lift_coe); if (is_nil(coes)) { expr new_a = a; infom.erase_coercion_info(a); cs += mk_eq_cnstr(meta, new_a, new_a_type_jst); return lazy_list<constraints>(cs.to_list()); } else if (is_nil(tail(coes))) { expr new_a = copy_tag(a, mk_app(head(coes), a)); infom.save_coercion_info(a, new_a); cs += mk_eq_cnstr(meta, new_a, new_a_type_jst); return lazy_list<constraints>(cs.to_list()); } else { list<constraints> choices = map2<constraints>(coes, [&](expr const & coe) { expr new_a = copy_tag(a, mk_app(coe, a)); constraint c = mk_eq_cnstr(meta, new_a, new_a_type_jst); return (cs + c).to_list(); }); return choose(std::make_shared<coercion_elaborator>(infom, meta, choices, coes, false)); } } }; return mk_choice_cnstr(m, choice_fn, delay_factor, true, j); }
constraint mk_class_instance_root_cnstr(std::shared_ptr<class_instance_context> const & C, local_context const & _ctx, expr const & m, bool is_strict, unifier_config const & cfg, delay_factor const & factor) { environment const & env = C->env(); justification j = mk_failed_to_synthesize_jst(env, m); auto choice_fn = [=](expr const & meta, expr const & meta_type, substitution const & s, name_generator const & ngen) { environment const & env = C->env(); auto cls_name_it = is_ext_class(C->tc(), meta_type); if (!cls_name_it) { // do nothing, since type is not a class. return lazy_list<constraints>(constraints()); } local_context ctx = _ctx.instantiate(substitution(s)); pair<expr, justification> mj = update_meta(meta, s); expr new_meta = mj.first; justification new_j = mj.second; unsigned depth = 0; constraint c = mk_class_instance_cnstr(C, ctx, new_meta, depth); unifier_config new_cfg(cfg); new_cfg.m_discard = false; new_cfg.m_use_exceptions = false; new_cfg.m_pattern = true; new_cfg.m_kind = C->m_conservative ? unifier_kind::VeryConservative : unifier_kind::Liberal; auto to_cnstrs_fn = [=](substitution const & subst, constraints const & cnstrs) -> constraints { substitution new_s = subst; // some constraints may have been postponed (example: universe level constraints) constraints postponed = map(cnstrs, [&](constraint const & c) { // we erase internal justifications return update_justification(c, mk_composite1(j, new_j)); }); metavar_closure cls(new_meta); cls.add(meta_type); bool relax = C->m_relax; constraints cs = cls.mk_constraints(new_s, new_j, relax); return append(cs, postponed); }; auto no_solution_fn = [=]() { if (is_strict) return lazy_list<constraints>(); else return lazy_list<constraints>(constraints()); }; unify_result_seq seq1 = unify(env, 1, &c, ngen, substitution(), new_cfg); unify_result_seq seq2 = filter(seq1, [=](pair<substitution, constraints> const & p) { substitution new_s = p.first; expr result = new_s.instantiate(new_meta); // We only keep complete solutions (modulo universe metavariables) return !has_expr_metavar_relaxed(result); }); if (get_class_unique_class_instances(C->m_ios.get_options())) { optional<expr> solution; substitution subst; constraints cnstrs; for_each(seq2, [&](pair<substitution, constraints> const & p) { subst = p.first; cnstrs = p.second; expr next_solution = subst.instantiate(new_meta); if (solution) { throw_class_exception(m, [=](formatter const & fmt) { format r = format("ambiguous class-instance resolution, " "there is more than one solution"); r += pp_indent_expr(fmt, *solution); r += compose(line(), format("and")); r += pp_indent_expr(fmt, next_solution); return r; }); } else { solution = next_solution; } }); if (!solution) { return no_solution_fn(); } else { // some constraints may have been postponed (example: universe level constraints) return lazy_list<constraints>(to_cnstrs_fn(subst, cnstrs)); } } else { if (try_multiple_instances(env, *cls_name_it)) { lazy_list<constraints> seq3 = map2<constraints>(seq2, [=](pair<substitution, constraints> const & p) { return to_cnstrs_fn(p.first, p.second); }); if (is_strict) { return seq3; } else { // make sure it does not fail by appending empty set of constraints return append(seq3, lazy_list<constraints>(constraints())); } } else { auto p = seq2.pull(); if (!p) return no_solution_fn(); else return lazy_list<constraints>(to_cnstrs_fn(p->first.first, p->first.second)); } } }; bool owner = false; bool relax = C->m_relax; return mk_choice_cnstr(m, choice_fn, factor, owner, j, relax); }
QVariant QSystemLocalePrivate::toCurrencyString(const QSystemLocale::CurrencyToStringArgument &arg) { QString value; switch (arg.value.type()) { case QVariant::Int: value = QLocalePrivate::longLongToString(QLatin1Char('0'), QLatin1Char(','), QLatin1Char('+'), QLatin1Char('-'), arg.value.toInt(), -1, 10, -1, QLocale::OmitGroupSeparator); break; case QVariant::UInt: value = QLocalePrivate::unsLongLongToString(QLatin1Char('0'), QLatin1Char(','), QLatin1Char('+'), arg.value.toUInt(), -1, 10, -1, QLocale::OmitGroupSeparator); break; case QVariant::Double: value = QLocalePrivate::doubleToString(QLatin1Char('0'), QLatin1Char('+'), QLatin1Char('-'), QLatin1Char(' '), QLatin1Char(','), QLatin1Char('.'), arg.value.toDouble(), -1, QLocalePrivate::DFDecimal, -1, QLocale::OmitGroupSeparator); break; case QVariant::LongLong: value = QLocalePrivate::longLongToString(QLatin1Char('0'), QLatin1Char(','), QLatin1Char('+'), QLatin1Char('-'), arg.value.toLongLong(), -1, 10, -1, QLocale::OmitGroupSeparator); break; case QVariant::ULongLong: value = QLocalePrivate::unsLongLongToString(QLatin1Char('0'), QLatin1Char(','), QLatin1Char('+'), arg.value.toULongLong(), -1, 10, -1, QLocale::OmitGroupSeparator); break; default: return QVariant(); } QVarLengthArray<wchar_t, 64> out(64); QString decimalSep; QString thousandSep; CURRENCYFMT format; CURRENCYFMT *pformat = NULL; if (!arg.symbol.isEmpty()) { format.NumDigits = getLocaleInfo_int(lcid, LOCALE_ICURRDIGITS); format.LeadingZero = getLocaleInfo_int(lcid, LOCALE_ILZERO); decimalSep = getLocaleInfo(lcid, LOCALE_SMONDECIMALSEP); format.lpDecimalSep = (wchar_t *)decimalSep.utf16(); thousandSep = getLocaleInfo(lcid, LOCALE_SMONTHOUSANDSEP); format.lpThousandSep = (wchar_t *)thousandSep.utf16(); format.NegativeOrder = getLocaleInfo_int(lcid, LOCALE_INEGCURR); format.PositiveOrder = getLocaleInfo_int(lcid, LOCALE_ICURRENCY); format.lpCurrencySymbol = (wchar_t *)arg.symbol.utf16(); // grouping is complicated and ugly: // int(0) == "123456789.00" == string("0") // int(3) == "123,456,789.00" == string("3;0") // int(30) == "123456,789.00" == string("3;0;0") // int(32) == "12,34,56,789.00" == string("3;2;0") // int(320)== "1234,56,789.00" == string("3;2") QString groupingStr = getLocaleInfo(lcid, LOCALE_SMONGROUPING); format.Grouping = groupingStr.remove(QLatin1Char(';')).toInt(); if (format.Grouping % 10 == 0) // magic format.Grouping /= 10; else format.Grouping *= 10; pformat = &format; } int ret = ::GetCurrencyFormat(lcid, 0, reinterpret_cast<const wchar_t *>(value.utf16()), pformat, out.data(), out.size()); if (ret == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { ret = ::GetCurrencyFormat(lcid, 0, reinterpret_cast<const wchar_t *>(value.utf16()), pformat, out.data(), 0); out.resize(ret); ::GetCurrencyFormat(lcid, 0, reinterpret_cast<const wchar_t *>(value.utf16()), pformat, out.data(), out.size()); } value = QString::fromWCharArray(out.data()); if (substitution() == SAlways) substituteDigits( value); return value; }
/** * @brief parse * @param[in] fp : file stream * @param[out] conf : configuration * @param[in] line : reading line * @retval ==0 : success * @retval < 0 : failure */ inline int file_stream::_parse_(FILE *fp, configuration *conf, int *line) { char ws[512]; int ret; LogDebugf("Begin - int FileStream::_parse_(%p, %p, %p)\n", fp, conf, line); LogIndent(); // ---> file read loop while( !::feof(fp) ){ // zero clear workspace ::memset(ws, 0, sizeof(ws)); // file read if( !::fgets(ws + ::strlen(ws), sizeof(ws) - ::strlen(ws), fp) ) break; // count line number (*line)++; LogDebugf("line \'%d\'\n", *line); conf->show(0); // erase comment erase_comment(ws); if( (ret = find_separater(ws)) < 0){ if( unnamed(ws, conf, line) < 0){ LogUnindent(); LogDebugf("Fail - int FileStream::_parse_(%p, %p, %p)", fp, conf, line); return -1; } } else { LogDebugf("get separater \'%c\'\n", ws[ret]); switch( ws[ret] ){ // substruct case TokenSubst: { ws[ret] = '\0'; if( substitution(fp, ws, ws + ret + 1, conf, line) < 0){ LogUnindent(); LogDebugf("Fail - int FileStream::_parse_(%p, %p, %p)", fp, conf, line); return -1; } } break; // nesting case TokenBeginScope: LogDebug("invalid nesting"); break; case TokenEndScope: if( unnamed(ws, conf, line) < 0){ LogDebugf("configure read error at line %d\n", *line); LogUnindent(); LogDebugf(" Fail: int FileStream::_parse_(%p, %p, %p)", fp, conf, line); return -1; } return 0; // unnamed value case TokenComment: case TokenEndValue: case TokenEndLine: if( unnamed(ws, conf, line) < 0){ LogDebugf("configure read error at line %d\n", *line); LogUnindent(); LogDebugf(" Fail: int FileStream::_parse_(%p, %p, %p)", fp, conf, line); return -1; } break; } // <--- switch } } // <--- file read loop LogUnindent(); LogDebugf(" End: int FileStream::_parse_(%p, %p, %p)\n", fp, conf, line); return 0; }
edit_distance(char * X,char * Y, int x1,int x2, int y1, int y2)//,int a,int b, int c, int d) { //this function calculates the edit distance between 2 strings int i,j,k; //int maxDist,minI,minJ; int del,ins,sub; //int dist; //initialization int M ; M= x2-x1+1; int N ; N= y2-y1+1; char *A = malloc(sizeof(char)*(M+1)); char *B = malloc(sizeof(char)*(N+1)); strncpy(A, &(X[x1]), M); strncpy(B, &(Y[y1]), N); //printf("point3\n"); int distance[M][N]; //create a MxN matrix where D(i,j) stores the edit distance between A1....AM to B1.....BN /*int trace[M][N]; // create a matrix to store the pointers for backtracing */ char alignA[M+N]; // aligned sequence for A char alignB[M+N]; // aligned sequence for B //printf("point4\n"); for(i=0;i<M;i++) distance[i][0] = -i; for(j=0;j<N;j++) distance[0][j] = -j; //printf("point5\n"); /*for(i=0;i<M;i++) trace[i][0] = 0; for(j=0;j<N;j++) trace[0][j] = 0;*/ /*printf("point6\n"); maxDist=0; minI=0; minJ=0; */ //fill in the matrix for(i=1;i<M;i++){ //each i = i...M for (j= 1;j<N;j++){//each j = 1....N /******/ //distance[0][0] = //dist = 0; //trace[i][j] = STOP; /********/ printf("point6.1: j= %d, i = %d\n",j,i); del = distance[i-1][j] - 1; //deletion penalty is 1 //printf("point6.3\n"); ins = distance[i][j-1] - 1; // insertion penalty is 1 //printf("point6.5: j= %d, i = %d\n",j,i); sub = distance[i-1][j-1] - substitution(A[i-1],B[j-1]); // substitution penalty is 1 printf("comparing %c, and %c\n",A[i-1],B[j-1]); printf("del is: %d, ins is: %d, sub is %d\n",del,ins,sub); //printf("point6.8: j= %d, i = %d\n",j,i); distance[i][j] = max (del, ins, sub); // D(i-1,j)-1: deletion ; D(i,j-1)-1 : insertion ; M(i-1,j-1)-S(A[i],B[j]): substitution //printf("point6.9: j= %d, i = %d\n",j,i); printf("what is distance? ---------- %d\n",distance[i][j]); // store the trace matrix based on the different operations we perform /*if (distance[i][j] == del) trace[i][j] = LEFT; // LEFT for insertion; DOWN for deletion; DIAG for substitution if (distance[i][j] == ins) trace[i][j] = UP; //DOWN if (distance[i][j] == sub) trace[i][j] = DIAG; //DIAG */ } } /****print the trace graph****/ /*for(i=0;i<M;i++){ for(j=0;j<N;j++){ printf("%.2i.",abs(trace[i][j])); } printf("\n"); } */ printf("\n"); for(i=0;i<M;i++){ for(j=0;j<N;j++){ printf("%.2i.",(distance[i][j])); } printf("\n"); } //printf("point8\n"); //printf("minI = %d,minJ=%d\n",minI,minJ); //printf("maxDist is: %d\n",maxDist); //now we create aligned sequence alignA and alignB (in reverse order) i = M-1; //start from the top right ie. backtrace j = N-1; k = 0; // this is the index for the aligned sequence printf("start!\n"); //backtrace(i,j,k); while (k<M+N){ if( i>0 && j>0 && (distance[i][j] == distance [i-1][j-1]) ){ // this suggest a match between the two sequence alignB[k] = B[j-1]; alignA[k] = A[i-1]; i=i-1; j=j-1; k++; } if(i>0 && j>0 && (distance[i][j] == distance[i-1][j-1] -1) ){ //this suggest a mismatch alignB[k]= B[j-1]; alignA[k]= A[i-1]; i=i-1; j=j-1; k++; } if(j>0 && (distance[i][j] == distance[i][j-1] -1) ) { // this suggest a insertion alignA[k] = '-'; alignB[k] = B[j-1]; j=j-1 ; k++; } if(i>0 && (distance[i][j] == distance[i-1][j] -1)){ // this suggest a deletion alignA[k] = A[i-1]; alignB[k] = '-'; i=i-1 ; k++; } if(i==0 && j ==0) break; } /* print in reverse order */ printf("printing!\n"); for(i=k-1;i>=0;i--) printf("%c",alignB[i]); //printf("%s",alignB); printf("\n"); //printf("%s",alignA); for(i=k-1;i>=0;i--) printf("%c",alignA[i]); printf("\n"); }
/// computes a junction tree from an elimination tree void DefaultJunctionTreeStrategy::__computeJunctionTree() { // if no triangulation is assigned to the strategy, do nothing if (!__triangulation) return; // get the elimination tree const CliqueGraph &elim_tree = __triangulation->eliminationTree(); // copy the elimination tree into the junction tree __junction_tree = elim_tree; // mark all the edges of the junction tree to false EdgeProperty<bool> mark = __junction_tree.edgesProperty(false); // create a vector indicating by which clique a given clique has been // substituted during the transformation from the elimination tree to the // junction tree. Assume that clique J of the elmination tree has been // substituted by clique K of the elimination tree, and that clique J // (resp. K) was the jth (resp. kth) one created during the triangulation // process. Then, in the vector below, substitution[j] = k. const std::vector<NodeId> &elim_order = __triangulation->eliminationOrder(); std::vector<unsigned int> substitution(elim_order.size()); for (unsigned int i = 0; i < substitution.size(); ++i) substitution[i] = i; // for all cliques C_i, from the last one created to the first one, check if // there exists a parent C_j (a neighbour created before C_i) such that // |C_j| = |C_i| + 1 and such that the edge is not marked. In this case, this // means that C_j contains C_i. Hence, we should remove C_i, and link all of // its neighbours to C_j. These links will be marked to true as no such // neighbour can be included in C_j (and conversely). // NodeSetIterator iter; for (unsigned int i = elim_order.size() - 1; i < elim_order.size(); --i) { NodeId C_i = i; unsigned int card_C_i = __junction_tree.clique(C_i).size(); // search for C_j such that |C_j| = [C_i| + 1 NodeId C_j = C_i; for (const auto C_jj : __junction_tree.neighbours(C_i)) if ((i > C_jj) && !mark[Edge(C_i, C_jj)] && (__junction_tree.clique(C_jj).size() == card_C_i + 1)) { // ok, here we found a parent such that |C_jj| = [C_i| + 1 C_j = C_jj; __junction_tree.eraseEdge(Edge(C_i, C_j)); break; } // if we found a C_j, link the neighbours of C_i to C_j if (C_j != C_i) { for (const auto nei : __junction_tree.neighbours(C_i)) { __junction_tree.addEdge(C_j, nei); mark.insert(Edge(C_j, nei), true); } substitution[i] = C_j; __junction_tree.eraseNode(C_i); } } // compute the transitive closure of vector substitution for (unsigned int i = 0; i < substitution.size(); ++i) substitution[i] = substitution[substitution[i]]; // using the transitive closure of vector substitution, compute for each node // the clique of the junction tree that was created by its elimination during // the triangulation for (unsigned int i = 0; i < elim_order.size(); ++i) { __node_2_junction_clique.insert(elim_order[i], substitution[i]); } __has_junction_tree = true; }
/** \brief Create a "choice" constraint that postpones the resolution of a calc proof step. By delaying it, we can perform quick fixes such as: - adding symmetry - adding ! - adding subst */ constraint mk_calc_proof_cnstr(environment const & env, options const & opts, old_local_context const & _ctx, expr const & m, expr const & _e, constraint_seq const & cs, unifier_config const & cfg, info_manager * im, update_type_info_fn const & fn) { justification j = mk_failed_to_synthesize_jst(env, m); auto choice_fn = [=](expr const & meta, expr const & _meta_type, substitution const & _s) { old_local_context ctx = _ctx; expr e = _e; substitution s = _s; expr meta_type = _meta_type; type_checker_ptr tc = mk_type_checker(env); constraint_seq new_cs = cs; expr e_type = tc->infer(e, new_cs); e_type = s.instantiate(e_type); tag g = e.get_tag(); bool calc_assistant = get_elaborator_calc_assistant(opts); if (calc_assistant) { // add '!' is needed while (is_norm_pi(*tc, e_type, new_cs)) { binder_info bi = binding_info(e_type); if (!bi.is_implicit() && !bi.is_inst_implicit()) { if (!has_free_var(binding_body(e_type), 0)) { // if the rest of the type does not reference argument, // then we also stop consuming arguments break; } } expr imp_arg = ctx.mk_meta(some_expr(binding_domain(e_type)), g); e = mk_app(e, imp_arg, g); e_type = instantiate(binding_body(e_type), imp_arg); } if (im) fn(e); } e_type = head_beta_reduce(e_type); expr const & meta_type_fn = get_app_fn(meta_type); expr const & e_type_fn = get_app_fn(e_type); if (is_constant(meta_type_fn) && (!is_constant(e_type_fn) || const_name(e_type_fn) != const_name(meta_type_fn))) { // try to make sure meta_type and e_type have the same head symbol if (!try_normalize_to_head(env, const_name(meta_type_fn), e_type, new_cs) && is_constant(e_type_fn)) { try_normalize_to_head(env, const_name(e_type_fn), meta_type, new_cs); } } auto try_alternative = [&](expr const & e, expr const & e_type, constraint_seq fcs, bool conservative) { justification new_j = mk_type_mismatch_jst(e, e_type, meta_type); if (!tc->is_def_eq(e_type, meta_type, new_j, fcs)) throw unifier_exception(new_j, s); buffer<constraint> cs_buffer; fcs.linearize(cs_buffer); metavar_closure cls(meta); cls.add(meta_type); cls.mk_constraints(s, j, cs_buffer); unifier_config new_cfg(cfg); new_cfg.m_discard = false; new_cfg.m_kind = conservative ? unifier_kind::Conservative : unifier_kind::Liberal; unify_result_seq seq = unify(env, cs_buffer.size(), cs_buffer.data(), substitution(), new_cfg); auto p = seq.pull(); lean_assert(p); substitution new_s = p->first.first; constraints postponed = map(p->first.second, [&](constraint const & c) { // we erase internal justifications return update_justification(c, j); }); expr new_e = new_s.instantiate(e); if (conservative && has_expr_metavar_relaxed(new_s.instantiate_all(e))) throw_elaborator_exception("solution contains metavariables", e); if (im) im->instantiate(new_s); constraints r = cls.mk_constraints(new_s, j); buffer<expr> locals; expr mvar = get_app_args(meta, locals); expr val = Fun(locals, new_e); r = cons(mk_eq_cnstr(mvar, val, j), r); return append(r, postponed); }; if (!get_elaborator_calc_assistant(opts)) { bool conservative = false; return try_alternative(e, e_type, new_cs, conservative); } else { // TODO(Leo): after we have the simplifier and rewriter tactic, we should revise // this code. It is "abusing" the higher-order unifier. { // Try the following possible intrepretations using a "conservative" unification procedure. // That is, we only unfold definitions marked as reducible. // Assume pr is the proof provided. // 1. pr bool conservative = true; try { return try_alternative(e, e_type, new_cs, conservative); } catch (exception & ex) {} // 2. eq.symm pr constraint_seq symm_cs = new_cs; auto symm = apply_symmetry(env, ctx, tc, e, e_type, symm_cs, g); if (symm) { try { return try_alternative(symm->first, symm->second, symm_cs, conservative); } catch (exception &) {} } // 3. subst pr (eq.refl lhs) constraint_seq subst_cs = new_cs; if (auto subst = apply_subst(env, ctx, tc, e, e_type, meta_type, subst_cs, g)) { try { return try_alternative(subst->first, subst->second, subst_cs, conservative); } catch (exception&) {} } // 4. subst (eq.symm pr) (eq.refl lhs) if (symm) { constraint_seq subst_cs = symm_cs; if (auto subst = apply_subst(env, ctx, tc, symm->first, symm->second, meta_type, subst_cs, g)) { try { return try_alternative(subst->first, subst->second, subst_cs, conservative); } catch (exception&) {} } } } { // Try the following possible insterpretations using the default unification procedure. // 1. pr bool conservative = false; std::unique_ptr<throwable> saved_ex; try { return try_alternative(e, e_type, new_cs, conservative); } catch (exception & ex) { saved_ex.reset(ex.clone()); } // 2. eq.symm pr constraint_seq symm_cs = new_cs; auto symm = apply_symmetry(env, ctx, tc, e, e_type, symm_cs, g); if (symm) { try { return try_alternative(symm->first, symm->second, symm_cs, conservative); } catch (exception &) {} } // We use the exception for the first alternative as the error message saved_ex->rethrow(); lean_unreachable(); } } }; bool owner = false; return mk_choice_cnstr(m, choice_fn, to_delay_factor(cnstr_group::Epilogue), owner, j); }