コード例 #1
0
ファイル: model_builder.cpp プロジェクト: Fininvest/CVC4
void QModelBuilderInstGen::constructModelUf( FirstOrderModel* fm, Node op ){
  FirstOrderModelIG* fmig = fm->asFirstOrderModelIG();
  bool setDefaultVal = true;
  Node defaultTerm = d_qe->getTermDatabase()->getModelBasisOpTerm( op );
  //set the values in the model
  for( size_t i=0; i<fmig->d_uf_terms[op].size(); i++ ){
    Node n = fmig->d_uf_terms[op][i];
    if( isTermActive( n ) ){
      Node v = fmig->getRepresentative( n );
      fmig->d_uf_model_gen[op].setValue( fm, n, v );
    }
    //also possible set as default
    if( d_term_selected.find( n )!=d_term_selected.end() || n==defaultTerm ){
      Node v = fmig->getRepresentative( n );
      fmig->d_uf_model_gen[op].setValue( fm, n, v, false );
      if( n==defaultTerm ){
        setDefaultVal = false;
      }
    }
  }
  //set the overall default value if not set already  (is this necessary??)
  if( setDefaultVal ){
    Node defaultVal = d_uf_prefs[op].getBestDefaultValue( defaultTerm, fm );
    fmig->d_uf_model_gen[op].setValue( fm, defaultTerm, defaultVal, false );
  }
  fmig->d_uf_model_gen[op].makeModel( fm, fmig->d_uf_model_tree[op] );
  d_uf_model_constructed[op] = true;
}
コード例 #2
0
ファイル: model_builder.cpp プロジェクト: pysmt/CVC4
void QModelBuilderIG::analyzeModel( FirstOrderModel* fm ) {
    FirstOrderModelIG* fmig = fm->asFirstOrderModelIG();
    d_uf_model_constructed.clear();
    //determine if any functions are constant
    for( std::map< Node, uf::UfModelTree >::iterator it = fmig->d_uf_model_tree.begin(); it != fmig->d_uf_model_tree.end(); ++it ) {
        Node op = it->first;
        TermArgBasisTrie tabt;
        for( size_t i=0; i<fmig->d_uf_terms[op].size(); i++ ) {
            Node n = fmig->d_uf_terms[op][i];
            //for calculating if op is constant
            if( !n.getAttribute(NoMatchAttribute()) ) {
                Node v = fmig->getRepresentative( n );
                if( i==0 ) {
                    d_uf_prefs[op].d_const_val = v;
                } else if( v!=d_uf_prefs[op].d_const_val ) {
                    d_uf_prefs[op].d_const_val = Node::null();
                    break;
                }
            }
            //for calculating terms that we don't need to consider
            if( !n.getAttribute(NoMatchAttribute()) || n.getAttribute(ModelBasisArgAttribute())!=0 ) {
                if( !n.getAttribute(BasisNoMatchAttribute()) ) {
                    //need to consider if it is not congruent modulo model basis
                    if( !tabt.addTerm( fmig, n ) ) {
                        BasisNoMatchAttribute bnma;
                        n.setAttribute(bnma,true);
                    }
                }
            }
        }
        if( !d_uf_prefs[op].d_const_val.isNull() ) {
            fmig->d_uf_model_gen[op].setDefaultValue( d_uf_prefs[op].d_const_val );
            fmig->d_uf_model_gen[op].makeModel( fmig, it->second );
            Debug("fmf-model-cons") << "Function " << op << " is the constant function ";
            fmig->printRepresentativeDebug( "fmf-model-cons", d_uf_prefs[op].d_const_val );
            Debug("fmf-model-cons") << std::endl;
            d_uf_model_constructed[op] = true;
        } else {
            d_uf_model_constructed[op] = false;
        }
    }
}
コード例 #3
0
ファイル: model_builder.cpp プロジェクト: pysmt/CVC4
void QModelBuilderDefault::constructModelUf( FirstOrderModel* fm, Node op ) {
    FirstOrderModelIG* fmig = fm->asFirstOrderModelIG();
    if( optReconsiderFuncConstants() ) {
        //reconsider constant functions that weren't necessary
        if( d_uf_model_constructed[op] ) {
            if( d_uf_prefs[op].d_reconsiderModel ) {
                //if we are allowed to reconsider default value, then see if the default value can be improved
                Node v = d_uf_prefs[op].d_const_val;
                if( d_uf_prefs[op].d_value_pro_con[0][v].empty() ) {
                    Debug("fmf-model-cons-debug") << "Consider changing the default value for " << op << std::endl;
                    fmig->d_uf_model_tree[op].clear();
                    fmig->d_uf_model_gen[op].clear();
                    d_uf_model_constructed[op] = false;
                }
            }
        }
    }
    if( !d_uf_model_constructed[op] ) {
        //construct the model for the uninterpretted function/predicate
        bool setDefaultVal = true;
        Node defaultTerm = d_qe->getTermDatabase()->getModelBasisOpTerm( op );
        Trace("fmf-model-cons") << "Construct model for " << op << "..." << std::endl;
        //set the values in the model
        for( size_t i=0; i<fmig->d_uf_terms[op].size(); i++ ) {
            Node n = fmig->d_uf_terms[op][i];
            if( isTermActive( n ) ) {
                Node v = fmig->getRepresentative( n );
                Trace("fmf-model-cons") << "Set term " << n << " : " << fmig->d_rep_set.getIndexFor( v ) << " " << v << std::endl;
                //if this assertion did not help the model, just consider it ground
                //set n = v in the model tree
                //set it as ground value
                fmig->d_uf_model_gen[op].setValue( fm, n, v );
                if( fmig->d_uf_model_gen[op].optUsePartialDefaults() ) {
                    //also set as default value if necessary
                    if( n.hasAttribute(ModelBasisArgAttribute()) && n.getAttribute(ModelBasisArgAttribute())!=0 ) {
                        Trace("fmf-model-cons") << "  Set as default." << std::endl;
                        fmig->d_uf_model_gen[op].setValue( fm, n, v, false );
                        if( n==defaultTerm ) {
                            //incidentally already set, we will not need to find a default value
                            setDefaultVal = false;
                        }
                    }
                } else {
                    if( n==defaultTerm ) {
                        fmig->d_uf_model_gen[op].setValue( fm, n, v, false );
                        //incidentally already set, we will not need to find a default value
                        setDefaultVal = false;
                    }
                }
            }
        }
        //set the overall default value if not set already  (is this necessary??)
        if( setDefaultVal ) {
            Trace("fmf-model-cons") << "  Choose default value..." << std::endl;
            //chose defaultVal based on heuristic, currently the best ratio of "pro" responses
            Node defaultVal = d_uf_prefs[op].getBestDefaultValue( defaultTerm, fm );
            if( defaultVal.isNull() ) {
                if (!fmig->d_rep_set.hasType(defaultTerm.getType())) {
                    Node mbt = d_qe->getTermDatabase()->getModelBasisTerm(defaultTerm.getType());
                    fmig->d_rep_set.d_type_reps[defaultTerm.getType()].push_back(mbt);
                }
                defaultVal = fmig->d_rep_set.d_type_reps[defaultTerm.getType()][0];
            }
            Assert( !defaultVal.isNull() );
            Trace("fmf-model-cons") << "Set default term : " << fmig->d_rep_set.getIndexFor( defaultVal ) << std::endl;
            fmig->d_uf_model_gen[op].setValue( fm, defaultTerm, defaultVal, false );
        }
        Debug("fmf-model-cons") << "  Making model...";
        fmig->d_uf_model_gen[op].makeModel( fm, fmig->d_uf_model_tree[op] );
        d_uf_model_constructed[op] = true;
        Debug("fmf-model-cons") << "  Finished constructing model for " << op << "." << std::endl;
    }
}
コード例 #4
0
ファイル: model_builder.cpp プロジェクト: pysmt/CVC4
void QModelBuilderDefault::analyzeQuantifier( FirstOrderModel* fm, Node f ) {
    FirstOrderModelIG* fmig = fm->asFirstOrderModelIG();
    Debug("fmf-model-prefs") << "Analyze quantifier " << f << std::endl;
    //the pro/con preferences for this quantifier
    std::vector< Node > pro_con[2];
    //the terms in the selection literal we choose
    std::vector< Node > selectionLitTerms;
    Trace("inst-gen-debug-quant") << "Inst-gen analyze " << f << std::endl;
    //for each asserted quantifier f,
    // - determine selection literals
    // - check which function/predicates have good and bad definitions for satisfying f
    if( d_phase_reqs.find( f )==d_phase_reqs.end() ) {
        d_phase_reqs[f].initialize( d_qe->getTermDatabase()->getInstConstantBody( f ), true );
    }
    int selectLitScore = -1;
    for( std::map< Node, bool >::iterator it = d_phase_reqs[f].d_phase_reqs.begin(); it != d_phase_reqs[f].d_phase_reqs.end(); ++it ) {
        //the literal n is phase-required for quantifier f
        Node n = it->first;
        Node gn = d_qe->getTermDatabase()->getModelBasis( f, n );
        Debug("fmf-model-req") << "   Req: " << n << " -> " << it->second << std::endl;
        bool value;
        //if the corresponding ground abstraction literal has a SAT value
        if( d_qe->getValuation().hasSatValue( gn, value ) ) {
            //collect the non-ground uf terms that this literal contains
            //  and compute if all of the symbols in this literal have
            //  constant definitions.
            bool isConst = true;
            std::vector< Node > uf_terms;
            if( TermDb::hasInstConstAttr(n) ) {
                isConst = false;
                if( gn.getKind()==APPLY_UF ) {
                    uf_terms.push_back( gn );
                    isConst = hasConstantDefinition( gn );
                } else if( gn.getKind()==EQUAL ) {
                    isConst = true;
                    for( int j=0; j<2; j++ ) {
                        if( TermDb::hasInstConstAttr(n[j]) ) {
                            if( n[j].getKind()==APPLY_UF &&
                                    fmig->d_uf_model_tree.find( gn[j].getOperator() )!=fmig->d_uf_model_tree.end() ) {
                                uf_terms.push_back( gn[j] );
                                isConst = isConst && hasConstantDefinition( gn[j] );
                            } else {
                                isConst = false;
                            }
                        }
                    }
                }
            }
            //check if the value in the SAT solver matches the preference according to the quantifier
            int pref = 0;
            if( value!=it->second ) {
                //we have a possible selection literal
                bool selectLit = d_quant_selection_lit[f].isNull();
                bool selectLitConstraints = true;
                //it is a constantly defined selection literal : the quantifier is sat
                if( isConst ) {
                    selectLit = selectLit || d_quant_sat.find( f )==d_quant_sat.end();
                    d_quant_sat[f] = true;
                    //check if choosing this literal would add any additional constraints to default definitions
                    selectLitConstraints = false;
                    for( int j=0; j<(int)uf_terms.size(); j++ ) {
                        Node op = uf_terms[j].getOperator();
                        if( d_uf_prefs[op].d_reconsiderModel ) {
                            selectLitConstraints = true;
                        }
                    }
                    if( !selectLitConstraints ) {
                        selectLit = true;
                    }
                }
                //also check if it is naturally a better literal
                if( !selectLit ) {
                    int score = getSelectionScore( uf_terms );
                    //Trace("inst-gen-debug") << "Check " << score << " < " << selectLitScore << std::endl;
                    selectLit = score<selectLitScore;
                }
                //see if we wish to choose this as a selection literal
                d_quant_selection_lit_candidates[f].push_back( value ? n : n.notNode() );
                if( selectLit ) {
                    selectLitScore = getSelectionScore( uf_terms );
                    Trace("inst-gen-debug") << "Choose selection literal " << gn << std::endl;
                    Trace("inst-gen-debug") << "  flags: " << isConst << " " << selectLitConstraints << " " << selectLitScore << std::endl;
                    d_quant_selection_lit[f] = value ? n : n.notNode();
                    selectionLitTerms.clear();
                    selectionLitTerms.insert( selectionLitTerms.begin(), uf_terms.begin(), uf_terms.end() );
                    if( !selectLitConstraints ) {
                        break;
                    }
                }
                pref = 1;
            } else {
                pref = -1;
            }
            //if we are not yet SAT, so we will add to preferences
            if( d_quant_sat.find( f )==d_quant_sat.end() ) {
                Debug("fmf-model-prefs") << "  It is " << ( pref==1 ? "pro" : "con" );
                Debug("fmf-model-prefs") << " the definition of " << n << std::endl;
                for( int j=0; j<(int)uf_terms.size(); j++ ) {
                    pro_con[ pref==1 ? 0 : 1 ].push_back( uf_terms[j] );
                }
            }
        }
    }
    //process information about selection literal for f
    if( !d_quant_selection_lit[f].isNull() ) {
        d_quant_selection_lit_terms[f].insert( d_quant_selection_lit_terms[f].begin(), selectionLitTerms.begin(), selectionLitTerms.end() );
        for( int i=0; i<(int)selectionLitTerms.size(); i++ ) {
            d_term_selection_lit[ selectionLitTerms[i] ] = d_quant_selection_lit[f];
            d_op_selection_terms[ selectionLitTerms[i].getOperator() ].push_back( selectionLitTerms[i] );
        }
    } else {
        Trace("inst-gen-warn") << "WARNING: " << f << " has no selection literals" << std::endl;
    }
    //process information about requirements and preferences of quantifier f
    if( d_quant_sat.find( f )!=d_quant_sat.end() ) {
        Debug("fmf-model-prefs") << "  * Constant SAT due to definition of ops: ";
        for( int i=0; i<(int)selectionLitTerms.size(); i++ ) {
            Debug("fmf-model-prefs") << selectionLitTerms[i] << " ";
            d_uf_prefs[ selectionLitTerms[i].getOperator() ].d_reconsiderModel = false;
        }
        Debug("fmf-model-prefs") << std::endl;
    } else {
        //note quantifier's value preferences to models
        for( int k=0; k<2; k++ ) {
            for( int j=0; j<(int)pro_con[k].size(); j++ ) {
                Node op = pro_con[k][j].getOperator();
                Node r = fmig->getRepresentative( pro_con[k][j] );
                d_uf_prefs[op].setValuePreference( f, pro_con[k][j], r, k==0 );
            }
        }
    }
}
コード例 #5
0
ファイル: model_builder.cpp プロジェクト: pysmt/CVC4
//do exhaustive instantiation
bool QModelBuilderIG::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) {
    if( optUseModel() ) {
        RepSetIterator riter( d_qe, &(d_qe->getModel()->d_rep_set) );
        if( riter.setQuantifier( f ) ) {
            FirstOrderModelIG * fmig = (FirstOrderModelIG*)d_qe->getModel();
            Debug("inst-fmf-ei") << "Reset evaluate..." << std::endl;
            fmig->resetEvaluate();
            Debug("inst-fmf-ei") << "Begin instantiation..." << std::endl;
            while( !riter.isFinished() && ( d_addedLemmas==0 || !options::fmfOneInstPerRound() ) ) {
                d_triedLemmas++;
                for( int i=0; i<(int)riter.d_index.size(); i++ ) {
                    Trace("try") << i << " : " << riter.d_index[i] << " : " << riter.getTerm( i ) << std::endl;
                }
                int eval = 0;
                int depIndex;
                //see if instantiation is already true in current model
                Debug("fmf-model-eval") << "Evaluating ";
                riter.debugPrintSmall("fmf-model-eval");
                Debug("fmf-model-eval") << "Done calculating terms." << std::endl;
                //if evaluate(...)==1, then the instantiation is already true in the model
                //  depIndex is the index of the least significant variable that this evaluation relies upon
                depIndex = riter.getNumTerms()-1;
                Debug("fmf-model-eval") << "We will evaluate " << d_qe->getTermDatabase()->getInstConstantBody( f ) << std::endl;
                eval = fmig->evaluate( d_qe->getTermDatabase()->getInstConstantBody( f ), depIndex, &riter );
                if( eval==1 ) {
                    Debug("fmf-model-eval") << "  Returned success with depIndex = " << depIndex << std::endl;
                } else {
                    Debug("fmf-model-eval") << "  Returned " << (eval==-1 ? "failure" : "unknown") << ", depIndex = " << depIndex << std::endl;
                }
                if( eval==1 ) {
                    //instantiation is already true -> skip
                    riter.increment2( depIndex );
                } else {
                    //instantiation was not shown to be true, construct the match
                    InstMatch m( f );
                    for( int i=0; i<riter.getNumTerms(); i++ ) {
                        m.set( d_qe, riter.d_index_order[i], riter.getTerm( i ) );
                    }
                    Debug("fmf-model-eval") << "* Add instantiation " << m << std::endl;
                    //add as instantiation
                    if( d_qe->addInstantiation( f, m, true ) ) {
                        d_addedLemmas++;
                        if( d_qe->inConflict() ) {
                            break;
                        }
                        //if the instantiation is show to be false, and we wish to skip multiple instantiations at once
                        if( eval==-1 ) {
                            riter.increment2( depIndex );
                        } else {
                            riter.increment();
                        }
                    } else {
                        Debug("fmf-model-eval") << "* Failed Add instantiation " << m << std::endl;
                        riter.increment();
                    }
                }
            }
            //print debugging information
            if( fmig ) {
                d_statistics.d_eval_formulas += fmig->d_eval_formulas;
                d_statistics.d_eval_uf_terms += fmig->d_eval_uf_terms;
                d_statistics.d_eval_lits += fmig->d_eval_lits;
                d_statistics.d_eval_lits_unknown += fmig->d_eval_lits_unknown;
            }
            Trace("inst-fmf-ei") << "For " << f << ", finished: " << std::endl;
            Trace("inst-fmf-ei") << "   Inst Tried: " << d_triedLemmas << std::endl;
            Trace("inst-fmf-ei") << "   Inst Added: " << d_addedLemmas << std::endl;
            if( d_addedLemmas>1000 ) {
                Trace("model-engine-warn") << "WARNING: many instantiations produced for " << f << ": " << std::endl;
                Trace("model-engine-warn") << "   Inst Tried: " << d_triedLemmas << std::endl;
                Trace("model-engine-warn") << "   Inst Added: " << d_addedLemmas << std::endl;
                Trace("model-engine-warn") << std::endl;
            }
        }
        //if the iterator is incomplete, we will return unknown instead of sat if no instantiations are added this round
        d_incomplete_check = riter.d_incomplete;
        return true;
    } else {
        return false;
    }
}
コード例 #6
0
ファイル: model_builder.cpp プロジェクト: pysmt/CVC4
void QModelBuilderIG::processBuildModel( TheoryModel* m, bool fullModel ) {
    FirstOrderModel* f = (FirstOrderModel*)m;
    FirstOrderModelIG* fm = f->asFirstOrderModelIG();
    Trace("model-engine-debug") << "Process build model, fullModel = " << fullModel << " " << optUseModel() << std::endl;
    if( fullModel ) {
        Assert( d_curr_model==fm );
        //update models
        for( std::map< Node, uf::UfModelTree >::iterator it = fm->d_uf_model_tree.begin(); it != fm->d_uf_model_tree.end(); ++it ) {
            it->second.update( fm );
            Trace("model-func") << "QModelBuilder: Make function value from tree " << it->first << std::endl;
            //construct function values
            fm->d_uf_models[ it->first ] = it->second.getFunctionValue( "$x" );
        }
        TheoryEngineModelBuilder::processBuildModel( m, fullModel );
        //mark that the model has been set
        fm->markModelSet();
        //debug the model
        debugModel( fm );
    } else {
        d_curr_model = fm;
        d_didInstGen = false;
        //reset the internal information
        reset( fm );
        //only construct first order model if optUseModel() is true
        if( optUseModel() ) {
            Trace("model-engine-debug") << "Initializing " << fm->getNumAssertedQuantifiers() << " quantifiers..." << std::endl;
            //check if any quantifiers are un-initialized
            for( unsigned i=0; i<fm->getNumAssertedQuantifiers(); i++ ) {
                Node f = fm->getAssertedQuantifier( i );
                if( isQuantifierActive( f ) ) {
                    int lems = initializeQuantifier( f, f );
                    d_statistics.d_init_inst_gen_lemmas += lems;
                    d_addedLemmas += lems;
                    if( d_qe->inConflict() ) {
                        break;
                    }
                }
            }
            if( d_addedLemmas>0 ) {
                Trace("model-engine") << "Initialize, Added Lemmas = " << d_addedLemmas << std::endl;
            } else {
                Assert( !d_qe->inConflict() );
                //initialize model
                fm->initialize();
                //analyze the functions
                Trace("model-engine-debug") << "Analyzing model..." << std::endl;
                analyzeModel( fm );
                //analyze the quantifiers
                Trace("model-engine-debug") << "Analyzing quantifiers..." << std::endl;
                d_quant_sat.clear();
                d_uf_prefs.clear();
                for( unsigned i=0; i<fm->getNumAssertedQuantifiers(); i++ ) {
                    Node f = fm->getAssertedQuantifier( i );
                    if( isQuantifierActive( f ) ) {
                        analyzeQuantifier( fm, f );
                    }
                }

                //if applicable, find exceptions to model via inst-gen
                if( options::fmfInstGen() ) {
                    d_didInstGen = true;
                    d_instGenMatches = 0;
                    d_numQuantSat = 0;
                    d_numQuantInstGen = 0;
                    d_numQuantNoInstGen = 0;
                    d_numQuantNoSelForm = 0;
                    //now, see if we know that any exceptions via InstGen exist
                    Trace("model-engine-debug") << "Perform InstGen techniques for quantifiers..." << std::endl;
                    for( unsigned i=0; i<fm->getNumAssertedQuantifiers(); i++ ) {
                        Node f = fm->getAssertedQuantifier( i );
                        if( isQuantifierActive( f ) ) {
                            int lems = doInstGen( fm, f );
                            d_statistics.d_inst_gen_lemmas += lems;
                            d_addedLemmas += lems;
                            //temporary
                            if( lems>0 ) {
                                d_numQuantInstGen++;
                            } else if( d_quant_sat.find( f )!=d_quant_sat.end() ) {
                                d_numQuantSat++;
                            } else if( hasInstGen( f ) ) {
                                d_numQuantNoInstGen++;
                            } else {
                                d_numQuantNoSelForm++;
                            }
                            if( d_qe->inConflict() || ( options::fmfInstGenOneQuantPerRound() && lems>0 ) ) {
                                break;
                            }
                        } else if( d_quant_sat.find( f )!=d_quant_sat.end() ) {
                            d_numQuantSat++;
                        }
                    }
                    Trace("model-engine-debug") << "Quantifiers sat/ig/n-ig/null " << d_numQuantSat << " / " << d_numQuantInstGen << " / ";
                    Trace("model-engine-debug") << d_numQuantNoInstGen << " / " << d_numQuantNoSelForm << std::endl;
                    Trace("model-engine-debug") << "Inst-gen # matches examined = " << d_instGenMatches << std::endl;
                    if( Trace.isOn("model-engine") ) {
                        if( d_addedLemmas>0 ) {
                            Trace("model-engine") << "InstGen, added lemmas = " << d_addedLemmas << std::endl;
                        } else {
                            Trace("model-engine") << "No InstGen lemmas..." << std::endl;
                        }
                    }
                }
                //construct the model if necessary
                if( d_addedLemmas==0 ) {
                    //if no immediate exceptions, build the model
                    //  this model will be an approximation that will need to be tested via exhaustive instantiation
                    Trace("model-engine-debug") << "Building model..." << std::endl;
                    //build model for UF
                    for( std::map< Node, uf::UfModelTree >::iterator it = fm->d_uf_model_tree.begin(); it != fm->d_uf_model_tree.end(); ++it ) {
                        Trace("model-engine-debug-uf") << "Building model for " << it->first << "..." << std::endl;
                        constructModelUf( fm, it->first );
                    }
                    /*
                    //build model for arrays
                    for( std::map< Node, arrays::ArrayModel >::iterator it = fm->d_array_model.begin(); it != fm->d_array_model.end(); ++it ){
                      //consult the model basis select term
                      // i.e. the default value for array A is the value of select( A, e ), where e is the model basis term
                      TypeNode tn = it->first.getType();
                      Node selModelBasis = NodeManager::currentNM()->mkNode( SELECT, it->first, fm->getTermDatabase()->getModelBasisTerm( tn[0] ) );
                      it->second.setDefaultValue( fm->getRepresentative( selModelBasis ) );
                    }
                    */
                    Trace("model-engine-debug") << "Done building models." << std::endl;
                }
            }
        }
    }
}