Beispiel #1
0
CNode* VariableEliminator::eliminate_var_rec(CNode* node,
		VariableTerm* evar, CNode* active_constraint)
{


	CNode* and_c = Connective::make(AND, node, active_constraint);

	/*CNode* canonical = and_c->make_canonical();
	Solver s(canonical, UNSAT_SIMPLIFY);
	CNode* res_c = s.get_result();
	if(res_c->get_type() == FALSE_NODE) return False::make(); */

	if(DEBUG) {
		cout << "CUR CONSTRAINT: " << node->to_string() << endl;
		cout << "Active constraint: " << active_constraint->to_string() << endl;
	}

	if(!and_c->contains_term(evar)){
		if(DEBUG) {
			cout << "Does not contain var to eliminate " << endl;
			cout << "Result: " << and_c->to_string() << endl;
		}
		return and_c;
	}


	/*
	 * If we can find an equality like t=T', then substitute
	 * every occurence of t in the subtree with T'.
	 */


	Term* sub = and_c->contains_term_equality(evar);
	if(sub != NULL) {
		if(DEBUG){
			cout << "Simple substitution found! " << evar->to_string()
			<< "-> " << sub->to_string() << " in constraint: " <<
			and_c->to_string() << endl;
		}
		map<Term*, Term*> sub_map;
		sub_map[evar] = sub;
		CNode* res = and_c->substitute(sub_map);
		if(DEBUG) {
			cout << "Result: " << res->to_string() << endl;
		}
		return res;

	}


	if(and_c->is_conjunct())
	{
		simplify = true;
		CNode* res = eliminate_var_conjunct(and_c, evar);
		CNode* simp_res = res;
		if(DEBUG) {
			cout << "Base case (conjunct)  " << endl;
			//cout << "Result: " << res->to_string() << endl;
		}
		return simp_res;
	}

	if(node->is_conjunct())
	{
		CNode* res = eliminate_var_rec(and_c, evar, True::make());
		if(DEBUG) {
			cout << "Pseudo base-case: " << endl;
			cout << "Result: " << res->to_string() << endl;
		}
		return res;
	}

	assert(node->is_connective());
	Connective* parent = (Connective*) node;

	bool changed = false;
	set<CNode*> new_children;
	set<CNode*>::const_iterator it = parent->get_operands().begin();

	if(parent->get_type() == OR)
	{
		bool and_active_constraint = false;
		it = parent->get_operands().begin();
		for(; it!= parent->get_operands().end() ;it++)
		{
			CNode* child = *it;
			if(!child->contains_term(evar)) {
				and_active_constraint = true;
				new_children.insert(child);
				continue;
			}
			CNode* new_child = eliminate_var_rec(child, evar,
					active_constraint);
			if(new_child->get_type() == TRUE_NODE) {
				return True::make();
			}
			if(new_child != child) {
				changed = true;
			}
			new_children.insert(new_child);

		}
		if(!changed){
			if(DEBUG)
			{
				cout << "OR not changed: " << endl;
				cout << "Result: " << node->to_string() << endl;
			}
			return node;
		}
		CNode* res = Connective::make_or(new_children);
		if(and_active_constraint) {
			CNode* new_active = eliminate_var_rec(active_constraint, evar, True::make());
			res = Connective::make(AND, res, new_active);
		}

		if(DEBUG) {
			cout << "Or case: " << endl;
			cout << "Result: " << res->to_string() << endl;
		}

		return res;
	}

	if(parent->get_type() == AND) {



		/*
		 * Find a disjunct (one must exist because this is not a conjunct)
		 */
		Connective* c = (Connective*) parent;
		const set<CNode*>& ops = c->get_operands();
		CNode* or_child = NULL;
		set<CNode*>::const_iterator it = ops.begin();
		for(; it!= ops.end(); it++) {
			CNode* cur = *it;
			if(cur->get_type() == OR && cur->contains_term(evar)) {
				or_child = cur;
				break;
			}
		}

		if(or_child == NULL) {
			set<CNode*> to_and;
			set<CNode*> new_ops;
			const set<CNode*>& ops = c->get_operands();
			it = ops.begin();
			for(; it!= ops.end(); it++) {
				CNode* op = *it;
				if(op->contains_term(evar)) {
					new_ops.insert(op);
				}
				else {
					to_and.insert(op);
				}
			}
			CNode* conjunct = Connective::make_and(new_ops);
			CNode* rec_res = eliminate_var_rec(conjunct, evar, active_constraint);
			to_and.insert(rec_res);

			CNode* res = Connective::make_and(to_and);
			return res;
		}


		/*
		 * Find active constraints containing the var to be eliminated.
		 */
		set<CNode*> containing_evar;
		set<CNode*> no_evar;
		it = ops.begin();
		for(; it!= ops.end(); it++){
			CNode* cur = *it;
			if(cur == or_child) continue;
			if(cur->contains_term(evar)) {
				containing_evar.insert(cur);
			}
			else no_evar.insert(cur);
		}

		//cout << "Current node: " << c->to_string() << endl;
		//cout << "Or child: " << or_child->to_string() << endl;

		CNode* sibling_constraints = Connective::make_and(containing_evar);
		CNode* new_active = Connective::make(AND, active_constraint,
				sibling_constraints);
		CNode* inactive_constraint = Connective::make_and(no_evar);

		assert(or_child != c);
		CNode* rec_res = eliminate_var_rec(or_child, evar, new_active);
		CNode* res = Connective::make(AND, rec_res, inactive_constraint);
		CNode* final_res = res;

		if(DEBUG) {
			cout << "AND case: " << endl;
			cout << "Result: " << final_res->to_string() << endl;
		}


		return final_res;
	}
	assert(false);
}