1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Kshitij Bansal, Gereon Kremer, Andres Noetzli |
4 |
|
* |
5 |
|
* This file is part of the cvc5 project. |
6 |
|
* |
7 |
|
* Copyright (c) 2009-2021 by the authors listed in the file AUTHORS |
8 |
|
* in the top-level source directory and their institutional affiliations. |
9 |
|
* All rights reserved. See the file COPYING in the top-level source |
10 |
|
* directory for licensing information. |
11 |
|
* **************************************************************************** |
12 |
|
* |
13 |
|
* Justification heuristic for decision making |
14 |
|
* |
15 |
|
* A ATGP-inspired justification-based decision heuristic. See |
16 |
|
* [insert reference] for more details. This code is, or not, based |
17 |
|
* on the CVC3 implementation of the same heuristic. |
18 |
|
* |
19 |
|
* It needs access to the simplified but non-clausal formula. |
20 |
|
*/ |
21 |
|
|
22 |
|
#include "cvc5_private.h" |
23 |
|
|
24 |
|
#ifndef CVC5__DECISION__JUSTIFICATION_HEURISTIC |
25 |
|
#define CVC5__DECISION__JUSTIFICATION_HEURISTIC |
26 |
|
|
27 |
|
#include <unordered_set> |
28 |
|
#include <utility> |
29 |
|
|
30 |
|
#include "context/cdhashmap.h" |
31 |
|
#include "context/cdhashset.h" |
32 |
|
#include "context/cdlist.h" |
33 |
|
#include "context/cdo.h" |
34 |
|
#include "decision/decision_strategy.h" |
35 |
|
#include "expr/node.h" |
36 |
|
#include "options/decision_weight.h" |
37 |
|
#include "prop/sat_solver_types.h" |
38 |
|
#include "util/statistics_stats.h" |
39 |
|
|
40 |
|
namespace cvc5 { |
41 |
|
namespace decision { |
42 |
|
|
43 |
|
class JustificationHeuristic : public ITEDecisionStrategy { |
44 |
|
// TRUE FALSE MEH |
45 |
|
enum SearchResult {FOUND_SPLITTER, NO_SPLITTER, DONT_KNOW}; |
46 |
|
|
47 |
|
typedef std::vector<std::pair<Node, Node> > SkolemList; |
48 |
|
typedef context::CDHashMap<Node, SkolemList> SkolemCache; |
49 |
|
typedef std::vector<Node> ChildList; |
50 |
|
typedef context::CDHashMap<Node, std::pair<ChildList, ChildList>> ChildCache; |
51 |
|
typedef context::CDHashMap<Node, Node> SkolemMap; |
52 |
|
typedef context::CDHashMap<Node, std::pair<DecisionWeight, DecisionWeight>> |
53 |
|
WeightCache; |
54 |
|
|
55 |
|
// being 'justified' is monotonic with respect to decisions |
56 |
|
typedef context::CDHashSet<Node> JustifiedSet; |
57 |
|
JustifiedSet d_justified; |
58 |
|
typedef context::CDHashMap<Node, DecisionWeight> ExploredThreshold; |
59 |
|
ExploredThreshold d_exploredThreshold; |
60 |
|
context::CDO<unsigned> d_prvsIndex; |
61 |
|
context::CDO<unsigned> d_threshPrvsIndex; |
62 |
|
|
63 |
|
IntStat d_helpfulness; |
64 |
|
IntStat d_giveup; |
65 |
|
TimerStat d_timestat; |
66 |
|
|
67 |
|
/** |
68 |
|
* A copy of the assertions that need to be justified |
69 |
|
* directly. Doesn't have ones introduced during during term removal. |
70 |
|
*/ |
71 |
|
context::CDList<Node> d_assertions; |
72 |
|
|
73 |
|
/** map from skolems introduced in term removal to the corresponding assertion |
74 |
|
*/ |
75 |
|
SkolemMap d_skolemAssertions; |
76 |
|
|
77 |
|
/** Cache for skolems present in a atomic formula */ |
78 |
|
SkolemCache d_skolemCache; |
79 |
|
|
80 |
|
/** |
81 |
|
* This is used to prevent infinite loop when trying to find a |
82 |
|
* splitter. Can happen when exploring assertion corresponding to a |
83 |
|
* term-ITE. |
84 |
|
*/ |
85 |
|
std::unordered_set<Node> d_visited; |
86 |
|
|
87 |
|
/** |
88 |
|
* Set to track visited nodes in a dfs search done in computeSkolems |
89 |
|
* function |
90 |
|
*/ |
91 |
|
std::unordered_set<Node> d_visitedComputeSkolems; |
92 |
|
|
93 |
|
/** current decision for the recursive call */ |
94 |
|
prop::SatLiteral d_curDecision; |
95 |
|
/** current threshold for the recursive call */ |
96 |
|
DecisionWeight d_curThreshold; |
97 |
|
|
98 |
|
/** child cache */ |
99 |
|
ChildCache d_childCache; |
100 |
|
|
101 |
|
/** computed polarized weight cache */ |
102 |
|
WeightCache d_weightCache; |
103 |
|
|
104 |
|
|
105 |
|
class myCompareClass { |
106 |
|
JustificationHeuristic* d_jh; |
107 |
|
bool d_b; |
108 |
|
public: |
109 |
|
myCompareClass(JustificationHeuristic* jh, bool b):d_jh(jh),d_b(b) {}; |
110 |
|
bool operator() (TNode n1, TNode n2) { |
111 |
|
return d_jh->getWeightPolarized(n1, d_b) < d_jh->getWeightPolarized(n2, d_b); |
112 |
|
} |
113 |
|
}; |
114 |
|
|
115 |
|
public: |
116 |
|
JustificationHeuristic(DecisionEngineOld* de, |
117 |
|
context::UserContext* uc, |
118 |
|
context::Context* c); |
119 |
|
|
120 |
|
~JustificationHeuristic(); |
121 |
|
|
122 |
|
prop::SatLiteral getNext(bool& stopSearch) override; |
123 |
|
|
124 |
|
/** |
125 |
|
* Notify this class that assertion is an (input) assertion, not corresponding |
126 |
|
* to a skolem definition. |
127 |
|
*/ |
128 |
|
void addAssertion(TNode assertion) override; |
129 |
|
/** |
130 |
|
* Notify this class that lem is the skolem definition for skolem, which is |
131 |
|
* a part of the current assertions. |
132 |
|
*/ |
133 |
|
void addSkolemDefinition(TNode lem, TNode skolem) override; |
134 |
|
|
135 |
|
private: |
136 |
|
/* getNext with an option to specify threshold */ |
137 |
|
prop::SatLiteral getNextThresh(bool& stopSearch, DecisionWeight threshold); |
138 |
|
|
139 |
|
prop::SatLiteral findSplitter(TNode node, prop::SatValue desiredVal); |
140 |
|
|
141 |
|
/** |
142 |
|
* Do all the hard work. |
143 |
|
*/ |
144 |
|
SearchResult findSplitterRec(TNode node, prop::SatValue value); |
145 |
|
|
146 |
|
/* Helper functions */ |
147 |
|
void setJustified(TNode); |
148 |
|
bool checkJustified(TNode); |
149 |
|
DecisionWeight getExploredThreshold(TNode); |
150 |
|
void setExploredThreshold(TNode); |
151 |
|
void setPrvsIndex(int); |
152 |
|
int getPrvsIndex(); |
153 |
|
DecisionWeight getWeightPolarized(TNode n, bool polarity); |
154 |
|
DecisionWeight getWeightPolarized(TNode n, prop::SatValue); |
155 |
|
static DecisionWeight getWeight(TNode); |
156 |
|
bool compareByWeightFalse(TNode, TNode); |
157 |
|
bool compareByWeightTrue(TNode, TNode); |
158 |
|
TNode getChildByWeight(TNode n, int i, bool polarity); |
159 |
|
|
160 |
|
/* If literal exists corresponding to the node return |
161 |
|
that. Otherwise an UNKNOWN */ |
162 |
|
prop::SatValue tryGetSatValue(Node n); |
163 |
|
|
164 |
|
/* Get list of all term-ITEs for the atomic formula v */ |
165 |
|
JustificationHeuristic::SkolemList getSkolems(TNode n); |
166 |
|
|
167 |
|
/** |
168 |
|
* For big and/or nodes, a cache to save starting index into children |
169 |
|
* for efficiently. |
170 |
|
*/ |
171 |
|
typedef context::CDHashMap<Node, int> StartIndexCache; |
172 |
|
StartIndexCache d_startIndexCache; |
173 |
|
int getStartIndex(TNode node); |
174 |
|
void saveStartIndex(TNode node, int val); |
175 |
|
|
176 |
|
/* Compute all term-removal skolems in a node recursively */ |
177 |
|
void computeSkolems(TNode n, SkolemList& l); |
178 |
|
|
179 |
|
SearchResult handleAndOrEasy(TNode node, prop::SatValue desiredVal); |
180 |
|
SearchResult handleAndOrHard(TNode node, prop::SatValue desiredVal); |
181 |
|
SearchResult handleBinaryEasy(TNode node1, |
182 |
|
prop::SatValue desiredVal1, |
183 |
|
TNode node2, |
184 |
|
prop::SatValue desiredVal2); |
185 |
|
SearchResult handleBinaryHard(TNode node1, |
186 |
|
prop::SatValue desiredVal1, |
187 |
|
TNode node2, |
188 |
|
prop::SatValue desiredVal2); |
189 |
|
SearchResult handleITE(TNode node, prop::SatValue desiredVal); |
190 |
|
SearchResult handleEmbeddedSkolems(TNode node); |
191 |
|
};/* class JustificationHeuristic */ |
192 |
|
|
193 |
|
}/* namespace decision */ |
194 |
|
} // namespace cvc5 |
195 |
|
|
196 |
|
#endif /* CVC5__DECISION__JUSTIFICATION_HEURISTIC */ |