Term* Term::replace_argument(int fun_id, int arg_num, Term* replacement) { switch(this->get_term_type()) { case CONSTANT_TERM: case VARIABLE_TERM: return this; case FUNCTION_TERM: { FunctionTerm* ft = (FunctionTerm*)this; const vector<Term*>& args = ft->get_args(); bool changed = false; vector<Term*> new_args; for(unsigned int i=0; i < args.size(); i++) { Term* cur = args[i]; Term* new_cur = cur->replace_argument(fun_id, arg_num, replacement); if(cur != new_cur) { changed = true; } new_args.push_back(new_cur); } if(ft->get_id() == fun_id ) { changed = true; new_args[arg_num] = replacement; } if(!changed) return this; return FunctionTerm::make(ft->get_id(), new_args, ft->is_invertible()); } case ARITHMETIC_TERM: { ArithmeticTerm* at = (ArithmeticTerm*) this; const map<Term*, long int>& elems = at->get_elems(); map<Term*, long int>::const_iterator it = elems.begin(); bool changed = false; map<Term*, long int> new_elems; for(; it!=elems.end(); it++) { Term* t = it->first; long int c = it->second; Term* new_t = t->replace_argument(fun_id, arg_num, replacement); new_elems[new_t] = c; if(t!= new_t) changed = true; } if(!changed) return this; return ArithmeticTerm::make(new_elems, at->get_constant()); } default: assert(false); } }
void VariableEliminator::get_function_terms_in_clause(Clause& cl, map<int, set<FunctionTerm*> >& functions_in_clause) { set<EqLeaf*>::iterator it = cl.pos_eq.begin(); for(; it!= cl.pos_eq.end(); it++) { set<Term*> terms; EqLeaf* eq = *it; eq->get_lhs()->get_nested_terms(terms); eq->get_rhs()->get_nested_terms(terms); set<Term*>::iterator it2 = terms.begin(); for(; it2 != terms.end(); it2++) { Term* t = *it2; if(t->get_term_type() != FUNCTION_TERM) continue; FunctionTerm* ft = (FunctionTerm*) t; functions_in_clause[ft->get_id()].insert(ft); } } it = cl.neg_eq.begin(); for(; it!= cl.neg_eq.end(); it++) { set<Term*> terms; EqLeaf* eq = *it; if(eq->get_lhs() == NULL) { cout << eq->get_type() << endl; cout << "EQ: " << eq->to_string() << endl; } eq->get_lhs()->get_nested_terms(terms); eq->get_rhs()->get_nested_terms(terms); set<Term*>::iterator it2 = terms.begin(); for(; it2 != terms.end(); it2++) { Term* t = *it2; if(t->get_term_type() != FUNCTION_TERM) continue; FunctionTerm* ft = (FunctionTerm*) t; functions_in_clause[ft->get_id()].insert(ft); } } if(DEBUG) { cout << " --- FUNCTIONS IN CLAUSE ---- " << endl; map<int, set<FunctionTerm*> >::iterator it = functions_in_clause.begin(); for(; it != functions_in_clause.end(); it++) { cout << "Function: " << CNode::get_varmap().get_name(it->first) << endl; set<FunctionTerm*>::iterator it2 = it->second.begin(); for(; it2!= it->second.end(); it2++) { cout << "\t " << (*it2)->to_string() << endl; } } } }
void Term::get_all_fun_ids(set<int> & ids) { switch(this->get_term_type()) { case CONSTANT_TERM: case VARIABLE_TERM: return; case FUNCTION_TERM: { FunctionTerm* ft = (FunctionTerm*)this; ids.insert(ft->get_id()); for(unsigned int i=0; i < ft->get_args().size(); i++) { ft->get_args()[i]->get_all_fun_ids(ids); } return; } case ARITHMETIC_TERM: { ArithmeticTerm* at = (ArithmeticTerm*) this; const map<Term*, long int>& elems = at->get_elems(); map<Term*, long int>::const_iterator it = elems.begin(); for(; it!=elems.end(); it++) { it->first->get_all_fun_ids(ids); } return; } default: assert(false); } }
Term* UniversalInstantiator::instantiate_term(Term* t, map<int, Term*> &sub_map) { if(t->get_term_type() == CONSTANT_TERM) return t; if(t->get_term_type() == VARIABLE_TERM){ VariableTerm *vt = (VariableTerm*)t; if(sub_map.count(vt->get_var_id()) == 0) return vt; return sub_map[vt->get_var_id()]; } if(t->get_term_type() == ARITHMETIC_TERM) { ArithmeticTerm* at = (ArithmeticTerm*)t; bool changed = false; map<Term*, long int> new_elems; map<Term*, long int>::const_iterator it = at->get_elems().begin(); for(; it!= at->get_elems().end(); it++) { Term* new_t = instantiate_term(it->first, sub_map); if(new_t != t) changed = true; new_elems[new_t] = it->second; } if(!changed) return at; return ArithmeticTerm::make(new_elems, at->get_constant()); } FunctionTerm *ft = (FunctionTerm*)t; vector<Term*> new_args; for(unsigned int i=0; i < ft->get_args().size(); i++) { Term* cur = instantiate_term(ft->get_args()[i], sub_map); new_args.push_back(cur); } return FunctionTerm::make(ft->get_id(), new_args, ft->is_invertible()); }
Term* Term::substitute(Term* (*sub_func)(Term* t, void* data), void* my_data) { Term* new_t = (*sub_func)(this, my_data); if(new_t != this) { return new_t; } Term* res = NULL; switch (get_term_type()) { case CONSTANT_TERM: case VARIABLE_TERM: { res= this; break; } case FUNCTION_TERM: { FunctionTerm* ft = (FunctionTerm*) this; const vector<Term*>& args = ft->get_args(); vector<Term*> new_args; bool changed = false; for (unsigned int i = 0; i < args.size(); i++) { Term* new_arg = args[i]->substitute(sub_func, my_data); if (new_arg != args[i]) changed = true; new_args.push_back(new_arg); } if (!changed) { res = this; break; } res= FunctionTerm::make(ft->get_id(), new_args, ft->is_invertible()); break; } case ARITHMETIC_TERM: { ArithmeticTerm* at = (ArithmeticTerm*) this; bool changed = false; map<Term*, long int> new_elems; map<Term*, long int>::const_iterator it = at->get_elems().begin(); for (; it != at->get_elems().end(); it++) { Term* new_t = it->first->substitute(sub_func, my_data); if (new_t != it->first) changed = true; new_elems[new_t]+= it->second; } if (!changed) { res = at; break; } res = ArithmeticTerm::make(new_elems, at->get_constant()); break; } default: assert(false); } return res; }
Term* Term::evalute_term(map<Term*, SatValue>& assignments) { switch(this->get_term_type()) { case CONSTANT_TERM: return this; case VARIABLE_TERM: { if(assignments.count(this) > 0){ return ConstantTerm::make(assignments[this].value.to_int()); } return this; } case FUNCTION_TERM: { if(assignments.count(this) > 0){ return ConstantTerm::make(assignments[this].value.to_int()); } vector<Term*> new_args; FunctionTerm* ft = (FunctionTerm*) this; for(unsigned int i = 0; i < ft->get_args().size(); i++) { Term* arg = ft->get_args()[i]; arg = arg->evalute_term(assignments); new_args.push_back(arg); } Term* new_t = FunctionTerm::make(ft->get_id(), new_args, ft->is_invertible()); if(assignments.count(new_t) > 0) return ConstantTerm::make(assignments[new_t].value.to_int()); return new_t; } case ARITHMETIC_TERM: { ArithmeticTerm* at = (ArithmeticTerm*) this; Term* res = ConstantTerm::make(at->get_constant()); const map<Term*, long int>& elems = at->get_elems(); map<Term*, long int>::const_iterator it = elems.begin(); for(; it!=elems.end(); it++) { Term* t = it->first; Term* val = t->evalute_term(assignments); res = res->add(val->multiply(it->second)); } if(assignments.count(res) > 0) return ConstantTerm::make(assignments[res].value.to_int()); return res; } default: assert(false); } }
/* * Cdr's down terms to build the index set. * This can only be called if the term is not in index guard. */ bool UniversalInstantiator::build_index_set_term(Term* t, set<int> &qvars, int fun_id, int arg_num) { if(t->get_term_type() == FUNCTION_TERM) { FunctionTerm* ft = (FunctionTerm*)t; bool contains_uvar = false; for(unsigned int i=0; i < ft->get_args().size(); i++) { bool res = build_index_set_term(ft->get_args()[i], qvars, ft->get_id(), i); if(res) contains_uvar = true; } if(contains_uvar) return true; } if(t->get_term_type() == ARITHMETIC_TERM) { bool contains_uvar = false; ArithmeticTerm* at = (ArithmeticTerm*) t; map<Term*, long int>::const_iterator it = at->get_elems().begin(); for(; it!=at->get_elems().end(); it++){ bool res = build_index_set_term(it->first, qvars, -1, -1); if(res) contains_uvar = true; } if(contains_uvar) return true; } pair<int, int> key(fun_id, arg_num); if(reverse_fun_arg_universal.count(key) ==0) return false; if(t->get_term_type() == VARIABLE_TERM){ VariableTerm* vt = (VariableTerm*) t; if(qvars.count(vt->get_var_id()) != 0){ return true; } } Term* se = t; set<qvar>* val = reverse_fun_arg_universal[key]; if(val->size() == 0) { return false; } bool added = false; set<qvar>::iterator it = val->begin(); for(; it!= val->end(); it++){ set<Term*>* s = index_set[*it]; if(s == NULL){ s= new set<Term*>(); index_set[*it] =s; } unsigned int old_size = s->size(); s->insert(se); if(s->size() > old_size) added = true; } return false; }
Term* Term::rename_variables(map<int, int>& replacements) { switch (get_term_type()) { case CONSTANT_TERM: return this; case VARIABLE_TERM: { VariableTerm* vt = (VariableTerm*) this; int var_id = vt->get_var_id(); if (replacements.count(var_id)==0) return this; Term* res= VariableTerm::make(replacements[var_id]); return res; } case FUNCTION_TERM: { FunctionTerm* ft = (FunctionTerm*) this; const vector<Term*>& args = ft->get_args(); vector<Term*> new_args; bool changed = false; for (unsigned int i = 0; i < args.size(); i++) { Term* new_arg = args[i]->rename_variables(replacements); if (new_arg != args[i]) changed = true; new_args.push_back(new_arg); } if (!changed) return this; Term* res= FunctionTerm::make(ft->get_id(), new_args, ft->is_invertible()); return res; } case ARITHMETIC_TERM: { ArithmeticTerm* at = (ArithmeticTerm*) this; bool changed = false; map<Term*, long int> new_elems; map<Term*, long int>::const_iterator it = at->get_elems().begin(); for (; it != at->get_elems().end(); it++) { Term* new_t = it->first->rename_variables(replacements); if (new_t != it->first) changed = true; new_elems[new_t] += it->second; } if (!changed) return at; Term* res= ArithmeticTerm::make(new_elems, at->get_constant()); return res; } default: assert(false); } }
void Term::get_all_first_arguments(set<int>& fn_ids, map<int, set<Term*> >& fn_id_to_first_arg) { switch(this->get_term_type()) { case CONSTANT_TERM: case VARIABLE_TERM: return; case FUNCTION_TERM: { FunctionTerm* ft = (FunctionTerm*)this; const vector<Term*>& args = ft->get_args(); int my_id = ft->get_id(); if(fn_ids.count(my_id) > 0) { Term* arg = args[0]; fn_id_to_first_arg[my_id].insert(arg); } for(unsigned int i=0; i < args.size(); i++) { Term* cur = args[i]; cur->get_all_first_arguments(fn_ids, fn_id_to_first_arg); } return; } case ARITHMETIC_TERM: { ArithmeticTerm* at = (ArithmeticTerm*) this; const map<Term*, long int>& elems = at->get_elems(); map<Term*, long int>::const_iterator it = elems.begin(); for(; it!=elems.end(); it++) { Term* t = it->first; t->get_all_first_arguments(fn_ids, fn_id_to_first_arg); } return; } default: assert(false); } }
void Term::get_all_arguments(int fun_id, int arg_num, set<Term*> & args) { switch(this->get_term_type()) { case CONSTANT_TERM: case VARIABLE_TERM: return; case FUNCTION_TERM: { FunctionTerm* ft = (FunctionTerm*)this; if(ft->get_id() == fun_id){ assert((int) ft->get_args().size() > arg_num); args.insert(ft->get_args()[arg_num]); } for(unsigned int i=0; i < ft->get_args().size(); i++) { ft->get_args()[i]->get_all_arguments(fun_id, arg_num, args); } return; } case ARITHMETIC_TERM: { ArithmeticTerm* at = (ArithmeticTerm*) this; const map<Term*, long int>& elems = at->get_elems(); map<Term*, long int>::const_iterator it = elems.begin(); for(; it!=elems.end(); it++) { it->first->get_all_arguments(fun_id, arg_num, args); } return; } default: assert(false); } }
/* * Substitutes variables if there are any * active subtituitons & byuilds the fun_arg_universal * and reverse_fun_arg universal maps. This is * recursive since we need to cdr down * nested function terms. */ Term* UniversalInstantiator::process_term(Term* t, map<int,int> & var_subs, int fun_id, int arg_num, QuantifiedLeaf* ql) { if(t->get_term_type() == CONSTANT_TERM) return t; if(t->get_term_type() == VARIABLE_TERM){ VariableTerm* vt = (VariableTerm*)t; int var_id = vt->get_var_id(); if(var_subs.count(var_id)>0){ Term* new_vt = VariableTerm::make(var_subs[var_id]); return new_vt; } else if(fun_id != -1 && ql!= NULL && ql->get_quantified_vars().count(var_id) >0) { assert(arg_num != -1); qvar qv; //qv.orig_id = ql->get_orig_id(); qv.id = (long int) ql; qv.var_id = var_id; map<int, int> *fun_map = NULL; if(fun_arg_universal.count(qv)>0) { fun_map = fun_arg_universal[qv]; } else { fun_map = new map<int, int>(); fun_arg_universal[qv] = fun_map; } if(fun_map->count(fun_id) == 0){ (*fun_map)[fun_id] = arg_num; pair<int, int> key(fun_id, arg_num); set<qvar>* val = reverse_fun_arg_universal[key]; if(val == NULL){ val = new set<qvar>(); reverse_fun_arg_universal[key] = val; } val->insert(qv); } else { if((*fun_map)[fun_id] != arg_num) return NULL; } } return t; } if(t->get_term_type() == FUNCTION_TERM) { FunctionTerm* ft = (FunctionTerm*)t; vector<Term*> new_args; for(unsigned int i=0; i < ft->get_args().size(); i++) { Term* cur_arg = process_term(ft->get_args()[i], var_subs, ft->get_id(), i, ql); if(cur_arg == NULL){ return NULL; } new_args.push_back(cur_arg); } Term* new_ft = FunctionTerm::make(ft->get_id(), new_args, ft->is_invertible()); return new_ft; } else { assert(t->get_term_type() == ARITHMETIC_TERM); ArithmeticTerm* at = (ArithmeticTerm*) t; bool changed = false; map<Term*, long int> new_elems; map<Term*, long int>::const_iterator it = at->get_elems().begin(); for(; it!= at->get_elems().end(); it++){ Term* new_t = process_term(it->first, var_subs, -1, -1, ql); if(new_t == NULL) return NULL; new_elems[new_t] = it->second; } if(!changed) return at; Term* new_at = ArithmeticTerm::make(new_elems, at->get_constant()); return new_at; } }