/*++ Copyright (c) 2006 Microsoft Corporation Module Name: dl_base.cpp Abstract: Author: Krystof Hoder (t-khoder) 2010-09-14. Revision History: --*/ #include"ast_pp.h" #include"union_find.h" #include"vector.h" #include"dl_context.h" #include"dl_base.h" #include"bool_rewriter.h" #include namespace datalog { context & get_context_from_rel_manager(const relation_manager & rm) { return rm.get_context(); } ast_manager & get_ast_manager_from_rel_manager(const relation_manager & rm) { return rm.get_context().get_manager(); } #if DL_LEAK_HUNTING void leak_guard_check(const symbol & s) { } #endif void relation_signature::output(ast_manager & m, std::ostream & out) const { unsigned sz=size(); out<<"("; for(unsigned i=0; i reset_fn = get_manager().mk_filter_interpreted_fn(static_cast(*this), bottom_ref); if(!reset_fn) { NOT_IMPLEMENTED_YET(); } (*reset_fn)(*this); } void table_signature::from_join(const table_signature & s1, const table_signature & s2, unsigned col_cnt, const unsigned * cols1, const unsigned * cols2, table_signature & result) { result.reset(); unsigned s1sz=s1.size(); unsigned s2sz=s2.size(); unsigned s1first_func=s1sz-s1.functional_columns(); unsigned s2first_func=s2sz-s2.functional_columns(); for(unsigned i=0; i=col_cnt); result.set_functional_columns(func_cnt-col_cnt); } } void table_signature::from_project_with_reduce(const table_signature & src, unsigned col_cnt, const unsigned * removed_cols, table_signature & result) { signature_base::from_project(src, col_cnt, removed_cols, result); unsigned remaining_fun = src.functional_columns(); unsigned first_src_fun = src.first_functional(); for(int i=col_cnt-1; i>=0; i--) { if(removed_cols[i] remaining_in_equivalence_class; remaining_in_equivalence_class.resize(join_sig_sz, 0); bool merging_rows_can_happen = false; union_find_default_ctx uf_ctx; union_find<> uf(uf_ctx); //the numbers in uf correspond to column indexes after the join for(unsigned i=0; icols1[i]) ? cols1[i] : (first_func_ofs+cols1[i]-s1_first_func); unsigned idx2 = (s2_first_func>cols2[i]) ? (second_ofs+cols2[i]) : (second_func_ofs+cols2[i]-s2_first_func); uf.merge(idx1, idx2); } for(unsigned i=0; i=first_func_ofs) { //removing functional columns won't make us merge rows continue; } unsigned eq_class_idx = uf.find(rc); if(remaining_in_equivalence_class[eq_class_idx]>1) { remaining_in_equivalence_class[eq_class_idx]--; } else { merging_rows_can_happen = true; break; } } if(merging_rows_can_happen) { //this one marks all columns as non-functional from_project(aux, removed_col_cnt, removed_cols, result); SASSERT(result.functional_columns()==0); } else { //this one preserves columns to be functional from_project_with_reduce(aux, removed_col_cnt, removed_cols, result); } } // ----------------------------------- // // table_base // // ----------------------------------- //here we give generic implementation of table operations using iterators bool table_base::empty() const { return begin()==end(); } void table_base::remove_facts(unsigned fact_cnt, const table_fact * facts) { for(unsigned i=0; i to_remove; table_base::iterator it = begin(); table_base::iterator iend = end(); table_fact row; for(; it!=iend; ++it) { it->get_fact(row); to_remove.append(row); } remove_facts(to_remove.size(), to_remove.c_ptr()); } bool table_base::contains_fact(const table_fact & f) const { iterator it = begin(); iterator iend = end(); table_fact row; for(; it!=iend; ++it) { it->get_fact(row); if(vectors_equal(row, f)) { return true; } } return false; } bool table_base::fetch_fact(table_fact & f) const { if(get_signature().functional_columns()==0) { return contains_fact(f); } else { unsigned sig_sz = get_signature().size(); unsigned non_func_cnt = sig_sz-get_signature().functional_columns(); table_base::iterator it = begin(); table_base::iterator iend = end(); table_fact row; for(; it!=iend; ++it) { it->get_fact(row); bool differs = false; for(unsigned i=0; iget_fact(row); res->add_new_fact(row); } return res; } table_base * table_base::complement(func_decl* p, const table_element * func_columns) const { const table_signature & sig = get_signature(); SASSERT(sig.functional_columns()==0 || func_columns!=0); table_base * res = get_plugin().mk_empty(sig); table_fact fact; fact.resize(sig.first_functional()); fact.append(sig.functional_columns(), func_columns); if(sig.first_functional()==0) { if(empty()) { res->add_fact(fact); } return res; } if(sig.first_functional()!=1) { //now we support only tables with one non-functional column NOT_IMPLEMENTED_YET(); } uint64 upper_bound = get_signature()[0]; bool empty_table = empty(); if (upper_bound > (1 << 18)) { std::ostringstream buffer; buffer << "creating large table of size " << upper_bound; if (p) buffer << " for relation " << p->get_name(); warning_msg(buffer.str().c_str()); } for(table_element i=0; iadd_fact(fact); } } return res; #if 0 svector var_arg_indexes(arity); var_arg_indexes.fill(0); svector var_arg_domain_sizes = s; unsigned var_cnt=var_arg_indexes.size(); table_fact fact; fact.resize(arity); fact.fill(0); unsigned depth=arity; while(true) { if(depth==arity) { SASSERT(!res->contains_fact(fact)); if(empty_table || !contains_fact(fact)) { res->add_fact(fact); } depth--; } else if(fact[depth]==s[depth]-1) { val_indexes[depth]=0; if(depth==0) { break; } depth--; } else { SASSERT(val_indexes[depth]