This adds a new print format for instantiations --print-instantiations=num, which prints the total number of instantations of quantified formulas. This count is user-context-dependent, which is in sync with the existing print-instantiation format (list).
It also simplifies and improves printing of Instantiation Tries.
default = "false"
help = "track instantiation lemmas (for proofs, unsat cores, qe and synthesis minimization)"
+### Output options
+
+[[option]]
+ name = "printInstMode"
+ category = "regular"
+ long = "print-inst=MODE"
+ type = "PrintInstMode"
+ default = "LIST"
+ help = "print format for printing instantiations"
+ help_mode = "Print format for printing instantiations."
+[[option.mode.LIST]]
+ name = "list"
+ help = "Print the list of instantiations per quantified formula, when non-empty."
+[[option.mode.NUM]]
+ name = "num"
+ help = "Print the total number of instantiations per quantified formula, when non-zero."
+
+[[option]]
+ name = "printInstFull"
+ category = "regular"
+ long = "print-inst-full"
+ type = "bool"
+ default = "true"
+ help = "print instantiations for formulas that do not have given identifiers"
### SyGuS instantiation options
c->setMuted(true);
PARSER_STATE->preemptCommand(c);
}
+ | tok=( ATTRIBUTE_QUANTIFIER_ID_TOK ) symbolicExpr[sexpr]
+ {
+ api::Sort boolType = SOLVER->getBooleanSort();
+ api::Term avar = SOLVER->mkVar(boolType, sexpr.toString());
+ attr = std::string(":qid");
+ retExpr = MK_TERM(api::INST_ATTRIBUTE, avar);
+ Command* c = new SetUserAttributeCommand("qid", avar.getExpr());
+ c->setMuted(true);
+ PARSER_STATE->preemptCommand(c);
+ }
| ATTRIBUTE_NAMED_TOK symbolicExpr[sexpr]
{
attr = std::string(":named");
ATTRIBUTE_NO_PATTERN_TOK : ':no-pattern';
ATTRIBUTE_NAMED_TOK : ':named';
ATTRIBUTE_INST_LEVEL : ':quant-inst-max-level';
+ATTRIBUTE_QUANTIFIER_ID_TOK : ':qid';
// operators (NOTE: theory symbols go here)
EXISTS_TOK : 'exists';
void InstMatchTrie::print(std::ostream& out,
Node q,
std::vector<TNode>& terms,
- bool& firstTime,
bool useActive,
std::vector<Node>& active) const
{
}
if (print)
{
- if (firstTime)
- {
- out << "(instantiation " << q << std::endl;
- firstTime = false;
- }
out << " ( ";
for (unsigned i = 0, size = terms.size(); i < size; i++)
{
for (const std::pair<const Node, InstMatchTrie>& d : d_data)
{
terms.push_back(d.first);
- d.second.print(out, q, terms, firstTime, useActive, active);
+ d.second.print(out, q, terms, useActive, active);
terms.pop_back();
}
}
void CDInstMatchTrie::print(std::ostream& out,
Node q,
std::vector<TNode>& terms,
- bool& firstTime,
bool useActive,
std::vector<Node>& active) const
{
}
if (print)
{
- if (firstTime)
- {
- out << "(instantiation " << q << std::endl;
- firstTime = false;
- }
out << " ( ";
for (unsigned i = 0; i < terms.size(); i++)
{
for (const std::pair<const Node, CDInstMatchTrie*>& d : d_data)
{
terms.push_back(d.first);
- d.second->print(out, q, terms, firstTime, useActive, active);
+ d.second->print(out, q, terms, useActive, active);
terms.pop_back();
}
}
/** print this class */
void print(std::ostream& out,
Node q,
- bool& firstTime,
bool useActive,
std::vector<Node>& active) const
{
std::vector<TNode> terms;
- print(out, q, terms, firstTime, useActive, active);
+ print(out, q, terms, useActive, active);
}
/** the data */
std::map<Node, InstMatchTrie> d_data;
void print(std::ostream& out,
Node q,
std::vector<TNode>& terms,
- bool& firstTime,
bool useActive,
std::vector<Node>& active) const;
/** helper for get instantiations
/** print this class */
void print(std::ostream& out,
Node q,
- bool& firstTime,
bool useActive,
std::vector<Node>& active) const
{
std::vector<TNode> terms;
- print(out, q, terms, firstTime, useActive, active);
+ print(out, q, terms, useActive, active);
}
private:
void print(std::ostream& out,
Node q,
std::vector<TNode>& terms,
- bool& firstTime,
bool useActive,
std::vector<Node>& active) const;
/** helper for get instantiations
: d_qe(qe),
d_term_db(nullptr),
d_term_util(nullptr),
- d_total_inst_count_debug(0),
+ d_total_inst_debug(u),
d_c_inst_match_trie_dom(u)
{
}
return false;
}
- d_total_inst_debug[q]++;
+ d_total_inst_debug[q] = d_total_inst_debug[q] + 1;
d_temp_inst_debug[q]++;
- d_total_inst_count_debug++;
if (Trace.isOn("inst"))
{
Trace("inst") << "*** Instantiate " << q << " with " << std::endl;
}
bool Instantiate::printInstantiations(std::ostream& out)
+{
+ if (options::printInstMode() == options::PrintInstMode::NUM)
+ {
+ return printInstantiationsNum(out);
+ }
+ Assert(options::printInstMode() == options::PrintInstMode::LIST);
+ return printInstantiationsList(out);
+}
+
+bool Instantiate::printInstantiationsList(std::ostream& out)
{
bool useUnsatCore = false;
std::vector<Node> active_lemmas;
useUnsatCore = true;
}
bool printed = false;
+ bool isFull = options::printInstFull();
if (options::incrementalSolving())
{
for (std::pair<const Node, inst::CDInstMatchTrie*>& t : d_c_inst_match_trie)
{
- bool firstTime = true;
- t.second->print(out, t.first, firstTime, useUnsatCore, active_lemmas);
- if (!firstTime)
+ std::stringstream qout;
+ if (!printQuant(t.first, qout, isFull))
+ {
+ continue;
+ }
+ std::stringstream sout;
+ t.second->print(sout, t.first, useUnsatCore, active_lemmas);
+ if (!sout.str().empty())
{
+ out << "(instantiations " << qout.str() << std::endl;
+ out << sout.str();
out << ")" << std::endl;
+ printed = true;
}
- printed = printed || !firstTime;
}
}
else
{
for (std::pair<const Node, inst::InstMatchTrie>& t : d_inst_match_trie)
{
- bool firstTime = true;
- t.second.print(out, t.first, firstTime, useUnsatCore, active_lemmas);
- if (!firstTime)
+ std::stringstream qout;
+ if (!printQuant(t.first, qout, isFull))
+ {
+ continue;
+ }
+ std::stringstream sout;
+ t.second.print(sout, t.first, useUnsatCore, active_lemmas);
+ if (!sout.str().empty())
{
+ out << "(instantiations " << qout.str() << std::endl;
+ out << sout.str();
out << ")" << std::endl;
+ printed = true;
}
- printed = printed || !firstTime;
}
}
+ out << std::endl;
return printed;
}
+bool Instantiate::printInstantiationsNum(std::ostream& out)
+{
+ if (d_total_inst_debug.empty())
+ {
+ return false;
+ }
+ bool isFull = options::printInstFull();
+ for (NodeUIntMap::iterator it = d_total_inst_debug.begin();
+ it != d_total_inst_debug.end();
+ ++it)
+ {
+ std::stringstream ss;
+ if (printQuant((*it).first, ss, isFull))
+ {
+ out << "(num-instantiations " << ss.str() << " " << (*it).second << ")"
+ << std::endl;
+ }
+ }
+ return true;
+}
+
+bool Instantiate::printQuant(Node q, std::ostream& out, bool isFull)
+{
+ if (isFull)
+ {
+ out << q;
+ return true;
+ }
+ quantifiers::QuantAttributes* qa = d_qe->getQuantAttributes();
+ Node name = qa->getQuantName(q);
+ if (name.isNull())
+ {
+ return false;
+ }
+ out << name;
+ return true;
+}
+
void Instantiate::getInstantiatedQuantifiedFormulas(std::vector<Node>& qs)
{
if (options::incrementalSolving())
// debug information
if (Trace.isOn("inst-per-quant-round"))
{
- for (std::pair<const Node, int>& i : d_temp_inst_debug)
+ for (std::pair<const Node, uint32_t>& i : d_temp_inst_debug)
{
Trace("inst-per-quant-round") << " * " << i.second << " for " << i.first
<< std::endl;
{
if (Trace.isOn("inst-per-quant"))
{
- for (std::pair<const Node, int>& i : d_total_inst_debug)
+ for (NodeUIntMap::iterator it = d_total_inst_debug.begin();
+ it != d_total_inst_debug.end();
+ ++it)
{
- Trace("inst-per-quant") << " * " << i.second << " for " << i.first
- << std::endl;
+ Trace("inst-per-quant")
+ << " * " << (*it).second << " for " << (*it).first << std::endl;
}
}
}
*/
class Instantiate : public QuantifiersUtil
{
+ typedef context::CDHashMap<Node, uint32_t, NodeHashFunction> NodeUIntMap;
+
public:
Instantiate(QuantifiersEngine* qe, context::UserContext* u);
~Instantiate();
/** print instantiations
*
* Print all instantiations for all quantified formulas on out,
- * returns true if at least one instantiation was printed.
+ * returns true if at least one instantiation was printed. The type of output
+ * (list, num, etc.) is determined by printInstMode.
*/
bool printInstantiations(std::ostream& out);
/** get instantiated quantified formulas
* if possible.
*/
static Node ensureType(Node n, TypeNode tn);
+ /** print instantiations in list format */
+ bool printInstantiationsList(std::ostream& out);
+ /** print instantiations in num format */
+ bool printInstantiationsNum(std::ostream& out);
+ /**
+ * Print quantified formula q on output out. If isFull is false, then we print
+ * the identifier of the quantified formula if it has one, or print
+ * nothing and return false otherwise.
+ */
+ bool printQuant(Node q, std::ostream& out, bool isFull);
/** pointer to the quantifiers engine */
QuantifiersEngine* d_qe;
/** instantiation rewriter classes */
std::vector<InstantiationRewriter*> d_instRewrite;
- /** statistics for debugging total instantiation */
- int d_total_inst_count_debug;
/** statistics for debugging total instantiations per quantifier */
- std::map<Node, int> d_total_inst_debug;
+ NodeUIntMap d_total_inst_debug;
/** statistics for debugging total instantiations per quantifier per round */
- std::map<Node, int> d_temp_inst_debug;
+ std::map<Node, uint32_t> d_temp_inst_debug;
/** list of all instantiations produced for each quantifier
*
SygusAttribute ca;
n.setAttribute( ca, true );
}
- else if (attr == "quant-name")
+ else if (attr == "qid")
{
+ // using z3 syntax "qid"
Trace("quant-attr-debug") << "Set quant-name " << n << std::endl;
QuantNameAttribute qna;
n.setAttribute(qna, true);
}
}
+Node QuantAttributes::getQuantName(Node q) const
+{
+ std::map<Node, QAttributes>::const_iterator it = d_qattr.find(q);
+ if (it != d_qattr.end())
+ {
+ return it->second.d_name;
+ }
+ return Node::null();
+}
+
int QuantAttributes::getQuantIdNum( Node q ) {
std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
if( it!=d_qattr.end() ){
/** the instantiation pattern list for this quantified formula (its 3rd child)
*/
Node d_ipl;
- /** the name of this quantified formula */
+ /** The name of this quantified formula, used for :qid */
Node d_name;
- /** the quantifier id associated with this formula */
+ /** The (internal) quantifier id associated with this formula */
Node d_qid_num;
/** is this quantified formula a function definition? */
bool isFunDef() const { return !d_fundef_f.isNull(); }
bool isQuantElim( Node q );
/** is quant elim partial */
bool isQuantElimPartial( Node q );
- /** get quant id num */
+ /** get quant name, which is used for :qid */
+ Node getQuantName(Node q) const;
+ /** get (internal) quant id num */
int getQuantIdNum( Node q );
- /** get quant id num */
+ /** get (internal)quant id num */
Node getQuantIdNumNode( Node q );
/** set instantiation level attr */
{
out.handleUserAttribute( "fun-def", this );
out.handleUserAttribute( "sygus", this );
- out.handleUserAttribute("quant-name", this);
+ out.handleUserAttribute("qid", this);
out.handleUserAttribute("sygus-synth-grammar", this);
out.handleUserAttribute( "sygus-synth-fun-var-list", this );
out.handleUserAttribute( "quant-inst-max-level", this );
void QuantifiersEngine::printInstantiations( std::ostream& out ) {
bool printed = false;
// print the skolemizations
- if (d_skolemize->printSkolemization(out))
+ if (options::printInstMode() == options::PrintInstMode::LIST)
{
- printed = true;
+ if (d_skolemize->printSkolemization(out))
+ {
+ printed = true;
+ }
}
// print the instantiations
if (d_instantiate->printInstantiations(out))
regress1/quantifiers/qcft-smtlib3dbc51.smt2
regress1/quantifiers/qe-partial.smt2
regress1/quantifiers/qe.smt2
+ regress1/quantifiers/qid.smt2
regress1/quantifiers/quant-wf-int-ind.smt2
regress1/quantifiers/quaternion_ds1_symm_0428.fof.smt2
regress1/quantifiers/recfact.cvc
; EXPECT: (skolem (forall ((x Int)) (or (P x) (Q x)) )
; EXPECT: ( skv_TERM )
; EXPECT: )
-; EXPECT: (instantiation (forall ((x Int)) (P x) )
+; EXPECT: (instantiations (forall ((x Int)) (P x) )
; EXPECT: ( skv_TERM )
; EXPECT: )
; EXPECT: unsat
; EXPECT: (skolem (forall ((x Int)) (or (P x) (R x)) )
; EXPECT: ( skv_TERM )
; EXPECT: )
-; EXPECT: (instantiation (forall ((x Int)) (P x) )
+; EXPECT: (instantiations (forall ((x Int)) (P x) )
; EXPECT: ( skv_TERM )
; EXPECT: )
(set-logic UFLIA)
; REQUIRES: proof
; COMMAND-LINE: --dump-instantiations --proof
; EXPECT: unsat
-; EXPECT: (instantiation (forall ((x Int)) (or (P x) (Q x)) )
+; EXPECT: (instantiations (forall ((x Int)) (or (P x) (Q x)) )
; EXPECT: ( 2 )
; EXPECT: )
-; EXPECT: (instantiation (forall ((x Int)) (or (not (S x)) (not (Q x))) )
+; EXPECT: (instantiations (forall ((x Int)) (or (not (S x)) (not (Q x))) )
; EXPECT: ( 2 )
; EXPECT: )
(set-logic UFLIA)
; EXPECT: (skolem (forall ((x Int)) (or (P x) (Q x)) )
; EXPECT: ( skv_TERM )
; EXPECT: )
-; EXPECT: (instantiation (forall ((x Int)) (P x) )
+; EXPECT: (instantiations (forall ((x Int)) (P x) )
; EXPECT: ( skv_TERM )
; EXPECT: )
(set-logic UFLIA)
--- /dev/null
+; COMMAND-LINE: --dump-instantiations --print-inst=num --no-print-inst-full
+; EXPECT: unsat
+; EXPECT: (num-instantiations myQuantP 1)
+; EXPECT: (num-instantiations myQuantQ 7)
+
+(set-logic UFLIA)
+(declare-fun P (Int) Bool)
+(declare-fun Q (Int) Bool)
+(assert (forall ((x Int)) (! (P x) :qid |myQuantP|)))
+(assert (forall ((x Int)) (! (=> (Q x) (Q (+ x 1))) :qid |myQuantQ|)))
+(assert (Q 0))
+(assert (or (not (P 5)) (not (Q 7))))
+(check-sat)