Towards supporting a (get-difficulty) command.
This tracks an estimate of the difficulty of preprocessed assertions during solving. It will be connected to TheoryEngine (via RelevanceManager) in a followup PR.
theory/decision_manager.h
theory/decision_strategy.cpp
theory/decision_strategy.h
+ theory/difficulty_manager.cpp
+ theory/difficulty_manager.h
theory/ee_manager.cpp
theory/ee_manager.h
theory/ee_manager_central.cpp
default = "false"
help = "turn on unsat assumptions generation"
+[[option]]
+ name = "difficultyMode"
+ category = "regular"
+ long = "difficulty-mode=MODE"
+ type = "DifficultyMode"
+ default = "LEMMA_LITERAL"
+ help = "choose output mode for get-difficulty, see --difficulty-mode=help"
+ help_mode = "difficulty output modes."
+[[option.mode.LEMMA_LITERAL]]
+ name = "lemma-literal"
+ help = "Difficulty of an assertion is how many lemmas use a literal that the assertion depends on to be satisfied."
+[[option.mode.MODEL_CHECK]]
+ name = "model-check"
+ help = "Difficulty of an assertion is how many times it was not satisfied in a candidate model."
+
[[option]]
name = "checkSynthSol"
category = "regular"
--- /dev/null
+/******************************************************************************
+ * Top contributors (to current version):
+ * Andrew Reynolds
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Difficulty manager.
+ */
+
+#include "theory/difficulty_manager.h"
+
+#include "options/smt_options.h"
+#include "smt/env.h"
+#include "theory/theory_model.h"
+#include "util/rational.h"
+
+namespace cvc5 {
+namespace theory {
+
+DifficultyManager::DifficultyManager(context::Context* c, Valuation val)
+ : d_val(val), d_dfmap(c)
+{
+}
+
+void DifficultyManager::getDifficultyMap(std::map<Node, Node>& dmap)
+{
+ NodeManager* nm = NodeManager::currentNM();
+ for (const std::pair<const Node, uint64_t> p : d_dfmap)
+ {
+ dmap[p.first] = nm->mkConst(Rational(p.second));
+ }
+}
+
+void DifficultyManager::notifyLemma(const std::map<TNode, TNode>& rse, Node n)
+{
+ if (options::difficultyMode() != options::DifficultyMode::LEMMA_LITERAL)
+ {
+ return;
+ }
+ Trace("diff-man") << "notifyLemma: " << n << std::endl;
+ Kind nk = n.getKind();
+ // for lemma (or a_1 ... a_n), if a_i is a literal that is not true in the
+ // valuation, then we increment the difficulty of that assertion
+ std::vector<TNode> litsToCheck;
+ if (nk == kind::OR)
+ {
+ litsToCheck.insert(litsToCheck.end(), n.begin(), n.end());
+ }
+ else if (nk == kind::IMPLIES)
+ {
+ litsToCheck.push_back(n[0].negate());
+ litsToCheck.push_back(n[1]);
+ }
+ else
+ {
+ litsToCheck.push_back(n);
+ }
+ std::map<TNode, TNode>::const_iterator it;
+ for (TNode nc : litsToCheck)
+ {
+ bool pol = nc.getKind() != kind::NOT;
+ TNode atom = pol ? nc : nc[0];
+ it = rse.find(atom);
+ if (it != rse.end())
+ {
+ incrementDifficulty(it->second);
+ }
+ }
+}
+
+void DifficultyManager::notifyCandidateModel(const NodeList& input,
+ TheoryModel* m)
+{
+ if (options::difficultyMode() != options::DifficultyMode::MODEL_CHECK)
+ {
+ return;
+ }
+ Trace("diff-man") << "DifficultyManager::notifyCandidateModel, #input="
+ << input.size() << std::endl;
+ for (const Node& a : input)
+ {
+ // should have miniscoped the assertions upstream
+ Assert(a.getKind() != kind::AND);
+ // check if each input is satisfied
+ Node av = m->getValue(a);
+ if (av.isConst() && av.getConst<bool>())
+ {
+ continue;
+ }
+ Trace("diff-man") << " not true: " << a << std::endl;
+ // not satisfied, increment counter
+ incrementDifficulty(a);
+ }
+ Trace("diff-man") << std::endl;
+}
+void DifficultyManager::incrementDifficulty(TNode a, uint64_t amount)
+{
+ Assert(a.getType().isBoolean());
+ d_dfmap[a] = d_dfmap[a] + amount;
+}
+
+} // namespace theory
+} // namespace cvc5
--- /dev/null
+/******************************************************************************
+ * Top contributors (to current version):
+ * Andrew Reynolds
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Relevance manager.
+ */
+
+#include "cvc5_private.h"
+
+#ifndef CVC5__THEORY__DIFFICULTY_MANAGER__H
+#define CVC5__THEORY__DIFFICULTY_MANAGER__H
+
+#include "context/cdhashmap.h"
+#include "context/cdlist.h"
+#include "expr/node.h"
+#include "theory/valuation.h"
+
+namespace cvc5 {
+namespace theory {
+
+class TheoryModel;
+
+/**
+ * Difficulty manager, which tracks an estimate of the difficulty of each
+ * preprocessed assertion during solving.
+ */
+class DifficultyManager
+{
+ typedef context::CDList<Node> NodeList;
+ typedef context::CDHashMap<Node, uint64_t> NodeUIntMap;
+
+ public:
+ DifficultyManager(context::Context* c, Valuation val);
+ /**
+ * Get difficulty map, which populates dmap mapping preprocessed assertions
+ * to a difficulty measure (a constant integer).
+ */
+ void getDifficultyMap(std::map<Node, Node>& dmap);
+ /**
+ * Notify lemma, for difficulty measurements. This increments the difficulty
+ * of assertions that share literals with that lemma if the difficulty mode
+ * is LEMMA_LITERAL. In particular, for each literal lit in the lemma lem, we
+ * increment the difficulty of the assertion res[lit], which corresponds to
+ * the assertion that was the reason why the literal is relevant in the
+ * current context.
+ *
+ * @param rse Mapping from literals to the preprocessed assertion that was
+ * the reason why that literal was relevant in the current context
+ * @param lem The lemma
+ */
+ void notifyLemma(const std::map<TNode, TNode>& rse, Node lem);
+ /**
+ * Notify that `m` is a (candidate) model. This increments the difficulty
+ * of assertions that are not satisfied by that model.
+ *
+ * @param input The list of preprocessed assertions
+ * @param m The candidate model.
+ */
+ void notifyCandidateModel(const NodeList& input, TheoryModel* m);
+
+ private:
+ /** Increment difficulty on assertion a */
+ void incrementDifficulty(TNode a, uint64_t amount = 1);
+ /** The valuation object, used to query current value of theory literals */
+ Valuation d_val;
+ /**
+ * User-context dependent mapping from input assertions to difficulty measure
+ */
+ NodeUIntMap d_dfmap;
+};
+
+} // namespace theory
+} // namespace cvc5
+
+#endif /* CVC5__THEORY__DIFFICULTY_MANAGER__H */