bool InstantiationEngine::hasNonArithmeticVariable( Node f ){ for( int i=0; i<(int)f[0].getNumChildren(); i++ ){ TypeNode tn = f[0][i].getType(); if( !tn.isInteger() && !tn.isReal() ){ return true; } } return false; }
bool InstStrategyCbqi::hasNonCbqiVariable( Node q ){ for( unsigned i=0; i<q[0].getNumChildren(); i++ ){ TypeNode tn = q[0][i].getType(); if( !tn.isInteger() && !tn.isReal() && !tn.isBoolean() ){ if( options::cbqiSplx() ){ return true; }else{ //datatypes supported in new implementation if( !tn.isDatatype() ){ return true; } } } } return false; }
Node TermDb::getFreeVariableForInstConstant( Node n ){ TypeNode tn = n.getType(); if( d_free_vars.find( tn )==d_free_vars.end() ){ //if integer or real, make zero if( tn.isInteger() || tn.isReal() ){ Rational z(0); d_free_vars[tn] = NodeManager::currentNM()->mkConst( z ); }else{ if( d_type_map[ tn ].empty() ){ d_free_vars[tn] = NodeManager::currentNM()->mkSkolem( "freevar_$$", tn, "is a free variable created by termdb" ); Trace("mkVar") << "FreeVar:: Make variable " << d_free_vars[tn] << " : " << tn << std::endl; }else{ d_free_vars[tn] = d_type_map[ tn ][ 0 ]; } } } return d_free_vars[tn]; }
void ModelEngine::registerQuantifier( Node f ){ if( Trace.isOn("fmf-warn") ){ bool canHandle = true; for( unsigned i=0; i<f[0].getNumChildren(); i++ ){ TypeNode tn = f[0][i].getType(); if( !tn.isSort() ){ if( !tn.getCardinality().isFinite() ){ if( tn.isInteger() ){ if( !options::fmfBoundInt() ){ canHandle = false; } }else{ canHandle = false; } } } } if( !canHandle ){ Trace("fmf-warn") << "Warning : Model Engine : may not be able to answer SAT because of formula : " << f << std::endl; } } }
bool RepSetIterator::initialize(){ for( size_t i=0; i<d_types.size(); i++ ){ d_index.push_back( 0 ); //store default index order d_index_order.push_back( i ); d_var_order[i] = i; //store default domain d_domain.push_back( RepDomain() ); TypeNode tn = d_types[i]; if( tn.isSort() ){ if( !d_rep_set->hasType( tn ) ){ Node var = NodeManager::currentNM()->mkSkolem( "repSet", tn, "is a variable created by the RepSetIterator" ); Trace("mkVar") << "RepSetIterator:: Make variable " << var << " : " << tn << std::endl; d_rep_set->add( tn, var ); } }else if( tn.isInteger() ){ bool inc = false; //check if it is bound if( d_owner.getKind()==FORALL && d_qe && d_qe->getBoundedIntegers() ){ if( d_qe->getBoundedIntegers()->isBoundVar( d_owner, d_owner[0][i] ) ){ Trace("bound-int-rsi") << "Rep set iterator: variable #" << i << " is bounded integer." << std::endl; d_enum_type.push_back( ENUM_RANGE ); }else{ inc = true; } }else{ inc = true; } if( inc ){ //check if it is otherwise bound if( d_bounds[0].find(i)!=d_bounds[0].end() && d_bounds[1].find(i)!=d_bounds[1].end() ){ Trace("bound-int-rsi") << "Rep set iterator: variable #" << i << " is bounded." << std::endl; d_enum_type.push_back( ENUM_RANGE ); }else{ Trace("fmf-incomplete") << "Incomplete because of integer quantification of " << d_owner[0][i] << "." << std::endl; d_incomplete = true; } } //enumerate if the sort is reasonably small, the upper bound of 1000 is chosen arbitrarily for now }else if( tn.getCardinality().isFinite() && !tn.getCardinality().isLargeFinite() && tn.getCardinality().getFiniteCardinality().toUnsignedInt()<=1000 ){ d_rep_set->complete( tn ); }else{ Trace("fmf-incomplete") << "Incomplete because of quantification of type " << tn << std::endl; d_incomplete = true; } if( d_enum_type.size()<=i ){ d_enum_type.push_back( ENUM_DOMAIN_ELEMENTS ); if( d_rep_set->hasType( tn ) ){ for( size_t j=0; j<d_rep_set->d_type_reps[tn].size(); j++ ){ d_domain[i].push_back( j ); } }else{ return false; } } } //must set a variable index order based on bounded integers if (d_owner.getKind()==FORALL && d_qe && d_qe->getBoundedIntegers()) { Trace("bound-int-rsi") << "Calculating variable order..." << std::endl; std::vector< int > varOrder; for( unsigned i=0; i<d_qe->getBoundedIntegers()->getNumBoundVars(d_owner); i++ ){ varOrder.push_back(d_qe->getBoundedIntegers()->getBoundVarNum(d_owner,i)); } for( unsigned i=0; i<d_owner[0].getNumChildren(); i++) { if( !d_qe->getBoundedIntegers()->isBoundVar(d_owner, d_owner[0][i])) { varOrder.push_back(i); } } Trace("bound-int-rsi") << "Variable order : "; for( unsigned i=0; i<varOrder.size(); i++) { Trace("bound-int-rsi") << varOrder[i] << " "; } Trace("bound-int-rsi") << std::endl; std::vector< int > indexOrder; indexOrder.resize(varOrder.size()); for( unsigned i=0; i<varOrder.size(); i++){ indexOrder[varOrder[i]] = i; } Trace("bound-int-rsi") << "Will use index order : "; for( unsigned i=0; i<indexOrder.size(); i++) { Trace("bound-int-rsi") << indexOrder[i] << " "; } Trace("bound-int-rsi") << std::endl; setIndexOrder(indexOrder); } //now reset the indices for (unsigned i=0; i<d_index.size(); i++) { if (!resetIndex(i, true)){ break; } } return true; }
//this isolates the atom into solved form // veq_c * pv <> val + vts_coeff_delta * delta + vts_coeff_inf * inf // ensures val is Int if pv is Int, and val does not contain vts symbols int ArithInstantiator::solve_arith( CegInstantiator * ci, Node pv, Node atom, Node& veq_c, Node& val, Node& vts_coeff_inf, Node& vts_coeff_delta ) { int ires = 0; Trace("cbqi-inst-debug") << "isolate for " << pv << " in " << atom << std::endl; std::map< Node, Node > msum; if( QuantArith::getMonomialSumLit( atom, msum ) ){ Trace("cbqi-inst-debug") << "got monomial sum: " << std::endl; if( Trace.isOn("cbqi-inst-debug") ){ QuantArith::debugPrintMonomialSum( msum, "cbqi-inst-debug" ); } TypeNode pvtn = pv.getType(); //remove vts symbols from polynomial Node vts_coeff[2]; for( unsigned t=0; t<2; t++ ){ if( !d_vts_sym[t].isNull() ){ std::map< Node, Node >::iterator itminf = msum.find( d_vts_sym[t] ); if( itminf!=msum.end() ){ vts_coeff[t] = itminf->second; if( vts_coeff[t].isNull() ){ vts_coeff[t] = NodeManager::currentNM()->mkConst( Rational( 1 ) ); } //negate if coefficient on variable is positive std::map< Node, Node >::iterator itv = msum.find( pv ); if( itv!=msum.end() ){ //multiply by the coefficient we will isolate for if( itv->second.isNull() ){ vts_coeff[t] = QuantArith::negate(vts_coeff[t]); }else{ if( !pvtn.isInteger() ){ vts_coeff[t] = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkConst( Rational(-1) / itv->second.getConst<Rational>() ), vts_coeff[t] ); vts_coeff[t] = Rewriter::rewrite( vts_coeff[t] ); }else if( itv->second.getConst<Rational>().sgn()==1 ){ vts_coeff[t] = QuantArith::negate(vts_coeff[t]); } } } Trace("cbqi-inst-debug") << "vts[" << t << "] coefficient is " << vts_coeff[t] << std::endl; msum.erase( d_vts_sym[t] ); } } } ires = QuantArith::isolate( pv, msum, veq_c, val, atom.getKind() ); if( ires!=0 ){ Node realPart; if( Trace.isOn("cbqi-inst-debug") ){ Trace("cbqi-inst-debug") << "Isolate : "; if( !veq_c.isNull() ){ Trace("cbqi-inst-debug") << veq_c << " * "; } Trace("cbqi-inst-debug") << pv << " " << atom.getKind() << " " << val << std::endl; } if( options::cbqiAll() ){ // when not pure LIA/LRA, we must check whether the lhs contains pv if( TermDb::containsTerm( val, pv ) ){ Trace("cbqi-inst-debug") << "fail : contains bad term" << std::endl; return 0; } } if( pvtn.isInteger() && ( ( !veq_c.isNull() && !veq_c.getType().isInteger() ) || !val.getType().isInteger() ) ){ //redo, split integer/non-integer parts bool useCoeff = false; Integer coeff = ci->getQuantifiersEngine()->getTermDatabase()->d_one.getConst<Rational>().getNumerator(); for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){ if( it->first.isNull() || it->first.getType().isInteger() ){ if( !it->second.isNull() ){ coeff = coeff.lcm( it->second.getConst<Rational>().getDenominator() ); useCoeff = true; } } } //multiply everything by this coefficient Node rcoeff = NodeManager::currentNM()->mkConst( Rational( coeff ) ); std::vector< Node > real_part; for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){ if( useCoeff ){ if( it->second.isNull() ){ msum[it->first] = rcoeff; }else{ msum[it->first] = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MULT, it->second, rcoeff ) ); } } if( !it->first.isNull() && !it->first.getType().isInteger() ){ real_part.push_back( msum[it->first].isNull() ? it->first : NodeManager::currentNM()->mkNode( MULT, msum[it->first], it->first ) ); } } //remove delta TODO: check this vts_coeff[1] = Node::null(); //multiply inf if( !vts_coeff[0].isNull() ){ vts_coeff[0] = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MULT, rcoeff, vts_coeff[0] ) ); } realPart = real_part.empty() ? ci->getQuantifiersEngine()->getTermDatabase()->d_zero : ( real_part.size()==1 ? real_part[0] : NodeManager::currentNM()->mkNode( PLUS, real_part ) ); Assert( ci->getOutput()->isEligibleForInstantiation( realPart ) ); //re-isolate Trace("cbqi-inst-debug") << "Re-isolate..." << std::endl; ires = QuantArith::isolate( pv, msum, veq_c, val, atom.getKind() ); Trace("cbqi-inst-debug") << "Isolate for mixed Int/Real : " << veq_c << " * " << pv << " " << atom.getKind() << " " << val << std::endl; Trace("cbqi-inst-debug") << " real part : " << realPart << std::endl; if( ires!=0 ){ int ires_use = ( msum[pv].isNull() || msum[pv].getConst<Rational>().sgn()==1 ) ? 1 : -1; val = Rewriter::rewrite( NodeManager::currentNM()->mkNode( ires_use==-1 ? PLUS : MINUS, NodeManager::currentNM()->mkNode( ires_use==-1 ? MINUS : PLUS, val, realPart ), NodeManager::currentNM()->mkNode( TO_INTEGER, realPart ) ) ); //TODO: round up for upper bounds? Trace("cbqi-inst-debug") << "result : " << val << std::endl; Assert( val.getType().isInteger() ); } } } vts_coeff_inf = vts_coeff[0]; vts_coeff_delta = vts_coeff[1]; Trace("cbqi-inst-debug") << "Return " << veq_c << " * " << pv << " " << atom.getKind() << " " << val << ", vts = (" << vts_coeff_inf << ", " << vts_coeff_delta << ")" << std::endl; }else{ Trace("cbqi-inst-debug") << "fail : could not get monomial sum" << std::endl; } return ires; }