IVector ode_solver::extract_invariants() { map<Enode*, pair<double, double>> inv_map; for (auto inv : m_invs) { Enode * p = inv->getCdr()->getCdr()->getCdr()->getCdr()->getCar(); Enode * op = p->getCar(); bool pos = true; // Handle Negation if (op->getId() == ENODE_ID_NOT) { p = p->getCdr()->getCar(); op = p->getCar(); pos = false; } switch (op->getId()) { case ENODE_ID_GEQ: case ENODE_ID_GT: // Handle >= & > pos = !pos; case ENODE_ID_LEQ: case ENODE_ID_LT: { // Handle <= & < Enode * lhs = pos ? p->getCdr()->getCar() : p->getCdr()->getCdr()->getCar(); Enode * rhs = pos ? p->getCdr()->getCdr()->getCar() : p->getCdr()->getCar(); if (lhs->isVar() && rhs->isConstant()) { if (inv_map.find(lhs) != inv_map.end()) { inv_map[lhs].second = rhs->getValue(); } else { inv_map.emplace(lhs, make_pair(lhs->getLowerBound(), rhs->getValue())); } } else if (lhs->isConstant() && rhs->isVar()) { if (inv_map.find(rhs) != inv_map.end()) { inv_map[rhs].first = lhs->getValue(); } else { inv_map.emplace(rhs, make_pair(lhs->getValue(), rhs->getUpperBound())); } } else { cerr << "ode_solver::extract_invariant: error:" << p << endl; } } break; default: cerr << "ode_solver::extract_invariant: error" << p << endl; } } IVector ret (m_t_vars.size()); unsigned i = 0; for (auto const & m_t_var : m_t_vars) { if (inv_map.find(m_t_var) != inv_map.end()) { auto inv = interval(inv_map[m_t_var].first, inv_map[m_t_var].second); DREAL_LOG_INFO << "Invariant extracted from " << m_t_var << " = " << inv; ret[i++] = inv; } else { auto inv = interval(m_t_var->getLowerBound(), m_t_var->getUpperBound()); DREAL_LOG_INFO << "Default Invariant set for " << m_t_var << " = " << inv; ret[i++] = inv; } } return ret; }
bool glpk_wrapper::is_expr_linear(Enode * const t) { if ( t->isPlus() ) { for (Enode * arg_list = t->getCdr(); !arg_list->isEnil(); arg_list = arg_list->getCdr()) { if (!is_expr_linear(arg_list->getCar())) { return false; } } return true; } else if ( t->isTimes() ) { Enode * x = t->get1st(); Enode * y = t->get2nd(); if ( x->isConstant() ) { return is_expr_linear(y); } else if ( y->isConstant() ) { return is_expr_linear(x); } else { return false; } } else { return t->isVar() || t->isConstant(); } }
void SimpSMTSolver::getDLVars( Enode * e, bool negate, Enode ** x, Enode ** y ) { assert( config.sat_preprocess_theory != 0 ); assert( e->isLeq( ) ); Enode * lhs = e->get1st( ); Enode * rhs = e->get2nd( ); (void)rhs; assert( lhs->isMinus( ) ); assert( rhs->isConstant( ) || ( rhs->isUminus( ) && rhs->get1st( )->isConstant( ) ) ); *x = lhs->get1st( ); *y = lhs->get2nd( ); if ( negate ) { Enode *tmp = *x; *x = *y; *y = tmp; } }
lbool CostSolver::inform( Enode * e ) { assert( e ); assert( belongsToT( e ) ); #if DEBUG cout << "ct inform " << e << endl; #endif if ( e->isCostIncur() ) { assert( e->getArity() == 3 ); Enode * args = e->getCdr(); Enode * var = args->getCar(); Enode * cost = args->getCdr()->getCar(); #if DEBUG cout << "ct inform var = " << var << endl; cout << "ct inform cost = " << cost << endl; #endif assert( var->isVar() ); assert( cost->isConstant() ); nodemap_t::iterator it = nodemap_.find( var ); if ( it != nodemap_.end() ) { costfun & fun = *it->second; nodemap_[ e ] = &fun; add_incur( fun, e, cost ); } else { costfun * fun = new costfun( var ); #if DEBUG cout << "ct new cost fun " << var << endl; #endif nodemap_[ var ] = fun; nodemap_[ e ] = fun; costfuns_.push_back( fun ); add_incur( *fun, e, cost ); } } if ( e->isCostBound() ) { assert( e->getArity() == 2 ); Enode * args = e->getCdr(); Enode * var = args->getCar(); nodemap_t::iterator it = nodemap_.find( var ); if ( it != nodemap_.end() ) { costfun & fun = *it->second; nodemap_[ var ] = &fun; nodemap_[ e ] = &fun; add_bound( fun, e ); } else { costfun * fun = new costfun( var ); #if DEBUG cout << "ct new cost fun " << var << endl; #endif nodemap_[ var ] = fun; nodemap_[ e ] = fun; costfuns_.push_back( fun ); add_bound( *fun, e ); } } #if DEBUG print_status( cout ); #endif return l_Undef; }
bool CostSolver::assertLitImpl( Enode * e ) { assert( e ); assert( belongsToT( e ) ); assert( e->hasPolarity() ); assert( e->getPolarity() != l_Undef ); #if DEBUG cout << "ct assert " << (e->getPolarity() == l_True ? "" : "!") << e << endl; #endif assert( !conflict_ ); Enode * atom = e; const bool negated = e->getPolarity() == l_False; if ( atom->isCostIncur() ) { assert( nodemap_[ atom ] ); costfun & fun = *nodemap_[ atom ]; #if DEBUG print_status( cout, fun ); #endif incurnode * node = incurmap_[ atom ]; if ( node->prev ) { node->prev->next = node->next; assert( node->prev->cost <= node->cost ); } if ( node->next ) { node->next->prev = node->prev; assert( node->cost <= node->next->cost ); } else { fun.unassigned.last = node->prev; } if ( fun.unassigned.head == node ) { fun.unassigned.head = node->next; } fun.slack -= node->cost; fun.assigned.push_back( node ); if ( negated ) { undo_ops_.push( undo_op( REMOVE_INCUR_NEG, node ) ); if ( !fun.lowerbound.empty() && get_bound( fun.lowerbound.top() ) > fun.incurred + fun.slack ) { assert( explanation.empty() ); conflict_ = atom; codomain potential = fun.incurred + fun.slack; for ( costfun::nodes_t::iterator it = fun.assigned.begin(); it != fun.assigned.end(); ++it ) { incurnode * node = *it; #if ELIM_REDUNDANT if ( node->atom->getPolarity() != l_False ) { continue; } if ( potential + node->cost < get_bound( fun.lowerbound.top() ) ) { potential += node->cost; continue; } #endif if ( node->atom->getPolarity() == l_False ) { explanation.push_back( node->atom ); } } assert( potential < get_bound( fun.lowerbound.top() ) ); assert( find( explanation.begin(), explanation.end(), conflict_ ) != explanation.end() ); explanation.push_back( fun.lowerbound.top() ); #if DEBUG_CONFLICT cout << " " << explanation << " : " << fun.slack << endl; print_status( cout, fun ); cout << endl; #endif #if DEBUG cout << "conflict found " << conflict_ << endl; print_status( cout, fun ); #endif #if DEBUG_CHECK_STATUS check_status(); #endif return false; } } else { fun.incurred += node->cost; undo_ops_.push( undo_op( REMOVE_INCUR_POS, node ) ); if ( !fun.upperbound.empty() && get_bound( fun.upperbound.top() ) <= fun.incurred ) { conflict_ = atom; codomain incurred = fun.incurred; for ( costfun::nodes_t::iterator it = fun.assigned.begin(); it != fun.assigned.end(); ++it ) { incurnode * node = *it; #if ELIM_REDUNDANT if ( node->atom->getPolarity() != l_True ) { continue; } if ( incurred - node->cost >= get_bound( fun.upperbound.top() ) ) { incurred -= node->cost; continue; } #endif if ( node->atom->getPolarity() == l_True ) { explanation.push_back( node->atom ); } } assert( incurred >= get_bound( fun.upperbound.top() ) ); assert( find( explanation.begin(), explanation.end(), conflict_ ) != explanation.end() ); explanation.push_back( fun.upperbound.top() ); #if DEBUG_CONFLICT cout << explanation << " : " << fun.slack << endl; print_status( cout, fun ); cout << endl; #endif #if DEBUG cout << "conflict found " << conflict_ << endl; print_status( cout, fun ); #endif #if DEBUG_CHECK_STATUS check_status(); #endif return false; } } } else if ( atom->isCostBound() ) { #if DEBUG cout << "ct bound asserted " << atom << endl; #endif assert( nodemap_.find( atom ) != nodemap_.end() ); costfun & fun = *nodemap_[ atom ]; Enode * args = atom->getCdr(); Enode * val = args->getCdr()->getCar(); assert( val->isConstant() ); #if DEBUG cout << atom->get2nd() << endl; #endif const codomain & value = atom->get2nd()->getValue(); if ( negated ) { #if DEBUG cout << "ct bound asserted negatively " << atom << endl; #endif if ( ( !fun.lowerbound.empty() && get_bound( fun.lowerbound.top() ) < value ) || fun.lowerbound.empty() ) { #if DEBUG cout << "ct new lower bound " << atom << endl; #endif fun.lowerbound.push( atom ); undo_ops_.push( undo_op( REMOVE_LBOUND, &fun ) ); if ( fun.incurred + fun.slack < get_bound( fun.lowerbound.top() ) ) { conflict_ = atom; codomain potential = fun.incurred + fun.slack; for ( costfun::nodes_t::iterator it = fun.assigned.begin(); it != fun.assigned.end(); ++it ) { incurnode * node = *it; #if ELIM_REDUNDANT if ( node->atom->getPolarity() != l_False ) { continue; } if ( potential + node->cost < get_bound( fun.lowerbound.top() ) ) { potential += node->cost; continue; } #endif if ( node->atom->getPolarity() == l_False ) { explanation.push_back( node->atom ); } } assert( find( explanation.begin(), explanation.end(), conflict_ ) == explanation.end() ); explanation.push_back( conflict_ ); assert( potential < get_bound( fun.lowerbound.top() ) ); assert( find( explanation.begin(), explanation.end(), conflict_ ) != explanation.end() ); #if DEBUG_CONFLICT cout << explanation << " : " << fun.slack << endl; print_status( cout, fun ); cout << endl; #endif #if DEBUG cout << "conflict found " << conflict_ << endl; print_status( cout, fun ); #endif #if DEBUG_CHECK_STATUS check_status(); #endif return false; } } } else { #if DEBUG cout << "ct bound asserted positively " << atom << endl; #endif if ( ( !fun.upperbound.empty() && get_bound( fun.upperbound.top() ) > value ) || fun.upperbound.empty() ) { #if DEBUG cout << "ct new upper bound " << atom << endl; #endif fun.upperbound.push( atom ); undo_ops_.push( undo_op( REMOVE_UBOUND, &fun ) ); if ( fun.incurred >= get_bound( fun.upperbound.top() ) ) { conflict_ = atom; codomain incurred = fun.incurred; for ( costfun::nodes_t::iterator it = fun.assigned.begin(); it != fun.assigned.end(); ++it ) { incurnode * node = *it; #if ELIM_REDUNDANT if ( node->atom->getPolarity() != l_True ) { continue; } if ( incurred - node->cost >= get_bound( fun.upperbound.top() ) ) { incurred -= node->cost; continue; } #endif if ( node->atom->getPolarity() == l_True ) { explanation.push_back( node->atom ); } } assert( find( explanation.begin(), explanation.end(), conflict_ ) == explanation.end() ); assert( incurred >= get_bound( fun.upperbound.top() ) ); explanation.push_back( conflict_ ); assert( find( explanation.begin(), explanation.end(), conflict_ ) != explanation.end() ); #if DEBUG_CONFLICT cout << " " << explanation << " : " << fun.slack << endl; print_status( cout, fun ); cout << endl; #endif #if DEBUG cout << "conflict found " << conflict_ << endl; print_status( cout, fun ); #endif #if DEBUG_CHECK_STATUS check_status(); #endif return false; } } } if ( !fun.lowerbound.empty() && !fun.upperbound.empty() && get_bound( fun.lowerbound.top() ) >= get_bound( fun.upperbound.top() ) ) { conflict_ = atom; explanation.push_back( fun.lowerbound.top() ); explanation.push_back( fun.upperbound.top() ); #if DEBUG_CONFLICT cout << " " << explanation << " : " << fun.slack << endl; print_status( cout, fun ); cout << endl; #endif #if DEBUG cout << "conflict found " << conflict_ << endl; print_status( cout, fun ); #endif #if DEBUG_CHECK_STATUS check_status(); #endif return false; } } else { #if DEBUG cout << "ct unrecognized " << atom << endl; #endif } #if 1 { // Deduction costfun & fun = *nodemap_[ atom ]; if ( !fun.upperbound.empty() && fun.lowerbound.empty() && fun.unassigned.last && get_bound( fun.upperbound.top() ) <= fun.unassigned.last->cost + fun.incurred && !fun.unassigned.last->atom->isDeduced() ) { #if DEBUG cout << "deducing !" << fun.unassigned.last->atom << endl; #endif fun.unassigned.last->atom->setDeduced( l_False, id ); deductions.push_back( fun.unassigned.last->atom ); } else if ( !fun.lowerbound.empty() && fun.upperbound.empty() && fun.unassigned.last && get_bound( fun.lowerbound.top() ) > fun.incurred + fun.slack - fun.unassigned.last->cost && !fun.unassigned.last->atom->isDeduced() ) { #if DEBUG cout << "deducing " << fun.unassigned.last->atom << endl; #endif fun.unassigned.last->atom->setDeduced( l_True, id ); deductions.push_back( fun.unassigned.last->atom ); } else if ( !fun.upperbound.empty() && !fun.lowerbound.empty() && fun.unassigned.last && get_bound( fun.lowerbound.top() ) +1 == get_bound( fun.upperbound.top() ) ) { if ( fun.unassigned.last->cost == fun.slack && fun.incurred + fun.unassigned.last->cost == get_bound( fun.lowerbound.top() ) && fun.incurred + fun.slack - fun.unassigned.last->cost < get_bound( fun.lowerbound.top() ) ) { #if DEBUG cout << "deducing " << fun.unassigned.last->atom << endl; print_status( cout, fun ); #endif fun.unassigned.last->atom->setDeduced( l_True, 0 ); deductions.push_back( fun.unassigned.last->atom ); } } } #endif #if DEBUG_CHECK_STATUS check_status(); #endif return true; }
void Egraph::gatherInterfaceTerms( Enode * e ) { assert( config.sat_lazy_dtc != 0 ); assert( config.logic == QF_UFIDL || config.logic == QF_UFLRA ); assert( e ); if ( config.verbosity > 2 ) cerr << "# Egraph::Gathering interface terms" << endl; vector< Enode * > unprocessed_enodes; initDup1( ); unprocessed_enodes.push_back( e ); // // Visit the DAG of the term from the leaves to the root // while( !unprocessed_enodes.empty( ) ) { Enode * enode = unprocessed_enodes.back( ); // // Skip if the node has already been processed before // if ( isDup1( enode ) ) { unprocessed_enodes.pop_back( ); continue; } bool unprocessed_children = false; Enode * arg_list; for ( arg_list = enode->getCdr( ) ; arg_list != enil ; arg_list = arg_list->getCdr( ) ) { Enode * arg = arg_list->getCar( ); assert( arg->isTerm( ) ); // // Push only if it is unprocessed // if ( !isDup1( arg ) ) { unprocessed_enodes.push_back( arg ); unprocessed_children = true; } } // // SKip if unprocessed_children // if ( unprocessed_children ) continue; unprocessed_enodes.pop_back( ); // // At this point, every child has been processed // if ( enode->isUFOp( ) ) { // Retrieve arguments for ( Enode * arg_list = enode->getCdr( ) ; !arg_list->isEnil( ) ; arg_list = arg_list->getCdr( ) ) { Enode * arg = arg_list->getCar( ); // This is for sure an interface term if ( ( arg->isArithmeticOp( ) || arg->isConstant( ) ) && interface_terms_cache.insert( arg ).second ) { interface_terms.push_back( arg ); if ( config.verbosity > 2 ) cerr << "# Egraph::Added interface term: " << arg << endl; } // We add this variable to the potential // interface terms or to interface terms if // already seen in LA else if ( arg->isVar( ) || arg->isConstant( ) ) { if ( it_la.find( arg ) == it_la.end( ) ) it_uf.insert( arg ); else if ( interface_terms_cache.insert( arg ).second ) { interface_terms.push_back( arg ); if ( config.verbosity > 2 ) cerr << "# Egraph::Added interface term: " << arg << endl; } } } } if ( enode->isArithmeticOp( ) && !isRootUF( enode ) ) { // Retrieve arguments for ( Enode * arg_list = enode->getCdr( ) ; !arg_list->isEnil( ) ; arg_list = arg_list->getCdr( ) ) { Enode * arg = arg_list->getCar( ); // This is for sure an interface term if ( arg->isUFOp( ) && interface_terms_cache.insert( arg ).second ) { interface_terms.push_back( arg ); if ( config.verbosity > 2 ) cerr << "# Egraph::Added interface term: " << arg << endl; } // We add this variable to the potential // interface terms or to interface terms if // already seen in UF else if ( arg->isVar( ) || arg->isConstant( ) ) { if ( it_uf.find( arg ) == it_uf.end( ) ) it_la.insert( arg ); else if ( interface_terms_cache.insert( arg ).second ) { interface_terms.push_back( arg ); if ( config.verbosity > 2 ) cerr << "# Egraph::Added interface term: " << arg << endl; } } } } assert( !isDup1( enode ) ); storeDup1( enode ); } doneDup1( ); }
ode_solver::ode_solver(SMTConfig& c, Egraph & e, Enode * l_int, vector<Enode*> invs, unordered_map<Enode*, int>& enode_to_rp_id) : m_config(c), m_egraph(e), m_int(l_int), m_invs(invs), m_enode_to_rp_id(enode_to_rp_id), m_stepControl(c.nra_ODE_step), m_time(nullptr) { // Pick the right flow_map (var |-> ODE) using current mode m_mode = l_int->getCdr()->getCar()->getValue(); map<string, Enode *> & flow_map = m_egraph.flow_maps[string("flow_") + to_string(m_mode)]; m_time = l_int->getCdr()->getCdr()->getCdr()->getCar(); string time_str = m_time->getCar()->getName(); // i.e. "time_1" m_step = stoi(time_str.substr(time_str.find_last_of("_") + 1)); // i.e. 1 Enode * var_list = l_int->getCdr()->getCdr()->getCdr()->getCdr(); // Collect _0, _t variables from variable list in integral literal while (!var_list->isEnil()) { string name = var_list->getCar()->getCar()->getName(); size_t second_ = name.find_last_of("_"); size_t first_ = name.find_last_of("_", second_ - 1); string name_prefix, name_postfix; if (first_ == string::npos) { name_prefix = name.substr(0, second_); name_postfix = name.substr(second_); } else { name_prefix = name.substr(0, first_); name_postfix = name.substr(first_); } if (flow_map.find(name_prefix) == flow_map.end()) { cerr << name_prefix << " is not found in flow_map." << endl; assert(flow_map.find(name_prefix) != flow_map.end()); } Enode * rhs = flow_map[name_prefix]; stringstream ss; rhs->print_infix(ss, true, name_postfix); if (rhs->isConstant() && rhs->getValue() == 0.0) { // If RHS of ODE == 0.0, we treat it as a parameter in CAPD m_pars.push_back(var_list->getCar()); m_par_list.push_back(name); } else { // Otherwise, we treat it as an ODE variable. m_0_vars.push_back(var_list->getCar()); m_t_vars.push_back(var_list->getCdr()->getCar()); m_var_list.push_back(name); m_ode_list.push_back(ss.str()); } var_list = var_list->getCdr()->getCdr(); } // join var_list to make diff_var, ode_list to diff_fun_forward string diff_var = ""; if (!m_var_list.empty()) { diff_var = "var:" + join(m_var_list, ", ") + ";"; } string diff_fun_forward = ""; string diff_fun_backward = ""; if (!m_ode_list.empty()) { diff_fun_forward = "fun:" + join(m_ode_list, ", ") + ";"; diff_fun_backward = "fun: -" + join(m_ode_list, ", -") + ";"; } // construct diff_sys_forward (string to CAPD) string diff_par; if (m_par_list.size() > 0) { diff_par = "par:" + join(m_par_list, ", ") + ";"; m_diff_sys_forward = diff_par; m_diff_sys_backward = diff_par; } m_diff_sys_forward += diff_var + diff_fun_forward; m_diff_sys_backward += diff_var + diff_fun_backward; DREAL_LOG_INFO << "diff_par : " << diff_par; DREAL_LOG_INFO << "diff_var : " << diff_var; DREAL_LOG_INFO << "diff_fun_forward : " << diff_fun_forward; DREAL_LOG_INFO << "diff_fun_backward : " << diff_fun_backward; DREAL_LOG_INFO << "diff_sys_forward : " << m_diff_sys_forward; DREAL_LOG_INFO << "diff_sys_backward : " << m_diff_sys_backward; for (auto ode_str : m_ode_list) { string const func_str = diff_par + diff_var + "fun:" + ode_str + ";"; m_funcs.push_back(IFunction(func_str)); }; m_inv = extract_invariants(); }
Var CoreSMTSolver::generateNextEij( ) { if ( egraph.getInterfaceTermsNumber( ) == 0 ) return var_Undef; assert( config.sat_lazy_dtc != 0 ); Var v = var_Undef; lbool pol = l_Undef; while ( v == var_Undef ) { // Already returned all the possible eij if ( next_it_i == egraph.getInterfaceTermsNumber( ) - 1 && next_it_j == egraph.getInterfaceTermsNumber( ) ) return var_Undef; // Get terms // Enode * i = interface_terms[ next_it_i ]; // Enode * j = interface_terms[ next_it_j ]; Enode * i = egraph.getInterfaceTerm( next_it_i ); Enode * j = egraph.getInterfaceTerm( next_it_j ); // Increase counters next_it_j ++; if ( next_it_j == next_it_i ) next_it_j ++; // if ( next_it_j == static_cast< int >( interface_terms.size( ) ) ) if ( next_it_j == egraph.getInterfaceTermsNumber( ) ) { next_it_i ++; next_it_j = next_it_i + 1; } // No need to create eij if both numbers, // it's either trivially true or false if ( i->isConstant( ) && j->isConstant( ) ) continue; if ( config.logic == QF_UFLRA || config.logic == QF_UFIDL ) { // // Since arithmetic solvers do not // understand equalities, produce // the splitted versions of equalities // and add linking clauses // Enode * eij = egraph.mkEq( egraph.cons( i, egraph.cons( j ) ) ); if ( config.verbosity > 2 ) cerr << "# CoreSMTSolver::Adding eij: " << eij << endl; if ( eij->isTrue( ) || eij->isFalse( ) ) continue; // Canonize LAExpression la( eij ); Enode * eij_can = la.toEnode( egraph ); // Continue if already generated equality // if ( !interface_equalities.insert( eij_can ).second ) continue; if ( eij_can->isTrue( ) || eij_can->isFalse( ) ) continue; v = theory_handler->enodeToVar( eij ); // Created one equality that is already assigned // Skip it if ( value( v ) != l_Undef ) { v = var_Undef; continue; } // Get lhs and rhs Enode * lhs = eij_can->get1st( ); Enode * rhs = eij_can->get2nd( ); Enode * leq = egraph.mkLeq( egraph.cons( lhs, egraph.cons( rhs ) ) ); // Canonize lhs LAExpression b( leq ); leq = b.toEnode( egraph ); // Canonize rhs Enode * geq = egraph.mkGeq( egraph.cons( lhs, egraph.cons( rhs ) ) ); LAExpression c( geq ); geq = c.toEnode( egraph ); // Add clause ( !x=y v x<=y ) vector< Enode * > clause; clause.push_back( egraph.mkNot( egraph.cons( eij ) ) ); clause.push_back( leq ); addSMTAxiomClause( clause ); // Add clause ( !x=y v x>=y ) clause.pop_back( ); clause.push_back( geq ); addSMTAxiomClause( clause ); // Add clause ( x=y v !x>=y v !x<=y ) clause.clear( ); clause.push_back( eij ); clause.push_back( egraph.mkNot( egraph.cons( leq ) ) ); clause.push_back( egraph.mkNot( egraph.cons( geq ) ) ); addSMTAxiomClause( clause ); pol = theory_handler->evaluate( eij ); if ( pol == l_Undef ) pol = theory_handler->evaluate( leq ); if ( pol == l_Undef ) pol = theory_handler->evaluate( geq ); } else { Enode * eij = egraph.mkEq( egraph.cons( i, egraph.cons( j ) ) ); // Continue if already generated equality if ( !interface_equalities.insert( eij ).second ) continue; if ( eij->isTrue( ) || eij->isFalse( ) ) continue; // Add new atom and get variable v = theory_handler->enodeToVar( eij ); // Initialize congruence data structure egraph.initializeCong( eij ); } } #ifdef STATISTICS ie_generated ++; #endif assert( v != var_Undef ); assert( polarity.size( ) > v ); // Assign to false first. We merge the least possible // Alternatively we can merge the most, or polarity[ v ] = ( pol == l_True ? false : ( pol == l_False ? true : true ) ); return v; }