15
15
#include < set>
16
16
#include < functional>
17
17
18
- class chc_db ;
19
- class horn_clause
18
+ class chc_dbt ;
19
+
20
+ /*
21
+ * A horn clause.
22
+ * This class is simply a wrapper around a forall_exprt with a few utilities:
23
+ * 1. Getting the body of a clause
24
+ * 2. Getting the head of a clause
25
+ * 3. Checking if a clause is a fact or a query
26
+ * 4. Getting used relations (the predicates) or function applications
27
+ * (their instantiations) in a clause.
28
+ */
29
+ class horn_clauset
20
30
{
21
31
forall_exprt m_chc;
22
32
23
33
public:
24
- horn_clause (forall_exprt f) : m_chc(f) {}
34
+ horn_clauset (forall_exprt f) : m_chc(f) {}
25
35
26
- horn_clause (std::vector<symbol_exprt> & vars, exprt clause) : m_chc(vars, clause) {
36
+ horn_clauset (std::vector<symbol_exprt> & vars, exprt clause) : m_chc(vars, clause) {
27
37
28
38
}
29
39
@@ -76,74 +86,75 @@ class horn_clause
76
86
return false ;
77
87
}
78
88
79
- bool operator ==(const horn_clause &other) const
89
+ bool operator ==(const horn_clauset &other) const
80
90
{
81
91
return m_chc == other.m_chc ;
82
92
}
83
93
84
- bool operator !=(const horn_clause &other) const
94
+ bool operator !=(const horn_clauset &other) const
85
95
{
86
96
return !(*this ==other);
87
97
}
88
98
89
- bool operator <(const horn_clause &other) const
99
+ bool operator <(const horn_clauset &other) const
90
100
{
91
101
return m_chc < other.m_chc ;
92
102
}
93
103
94
104
template <typename OutputIterator>
95
- void used_relations (chc_db &db, OutputIterator out) const ;
105
+ void used_relations (chc_dbt &db, OutputIterator out) const ;
96
106
template <typename OutputIterator>
97
- void used_func_app (chc_db &db, OutputIterator out) const ;
107
+ void used_func_app (chc_dbt &db, OutputIterator out) const ;
98
108
};
99
109
100
110
/*
101
111
* A database of CHCs.
102
112
* Uninterpreted relations need to be registered.
103
113
*/
104
- class chc_db
114
+ class chc_dbt
105
115
{
106
- friend class horn_clause ;
116
+ friend class horn_clauset ;
107
117
public:
108
118
struct is_state_pred : public std ::__unary_function<exprt, bool > {
109
- const chc_db &m_db;
110
- is_state_pred (const chc_db &db) : m_db(db) {}
119
+ const chc_dbt &m_db;
120
+ is_state_pred (const chc_dbt &db) : m_db(db) {}
111
121
112
122
bool operator ()(symbol_exprt state) { return m_db.has_state_pred (state); }
113
123
};
114
124
125
+ typedef std::unordered_set<std::size_t > chc_sett;
126
+
115
127
private:
116
- using chcst = std::vector<horn_clause >;
128
+ using chcst = std::vector<horn_clauset >;
117
129
chcst m_clauses;
118
130
119
- std::set <symbol_exprt> m_state_preds;
131
+ std::unordered_set <symbol_exprt, irep_hash > m_state_preds;
120
132
121
- typedef std::set<const horn_clause *> chc_sett;
122
- typedef std::map<exprt, std::set<const horn_clause *>> chc_indext;
133
+ typedef std::map<exprt, chc_sett> chc_indext;
123
134
chc_indext m_body_idx;
124
135
chc_indext m_head_idx;
125
136
126
137
// representing the empty set
127
138
static chc_sett m_empty_set;
128
139
129
140
public:
130
- chc_db () {}
141
+ chc_dbt () {}
131
142
132
143
void add_state_pred (const symbol_exprt & state) { m_state_preds.insert (state); }
133
- const std::set <symbol_exprt> &get_state_preds () { return m_state_preds; }
144
+ const std::unordered_set <symbol_exprt, irep_hash > &get_state_preds () { return m_state_preds; }
134
145
bool has_state_pred (const symbol_exprt & state) const { return m_state_preds.count (state) > 0 ; }
135
146
136
147
void build_indices ();
137
148
void reset_indices ();
138
149
139
- const std::set< const horn_clause *> & use (const exprt & state) const {
150
+ const chc_sett & use (const exprt & state) const {
140
151
auto it = m_body_idx.find (state);
141
152
if (it == m_body_idx.end ())
142
153
return m_empty_set;
143
154
return it->second ;
144
155
}
145
156
146
- const std::set< const horn_clause *> & def (const exprt & state) const {
157
+ const chc_sett & def (const exprt & state) const {
147
158
auto it = m_head_idx.find (state);
148
159
if (it == m_head_idx.end ())
149
160
return m_empty_set;
@@ -157,24 +168,30 @@ class chc_db
157
168
for (auto & c : m_clauses) {
158
169
if (c.get_chc ()==f) return ;
159
170
}
160
- m_clauses.push_back (horn_clause (f));
171
+ m_clauses.push_back (horn_clauset (f));
161
172
reset_indices ();
162
173
}
163
174
175
+ [[nodiscard]] const horn_clauset & get_clause (std::size_t idx) const
176
+ {
177
+ INVARIANT (idx < m_clauses.size (), " Index in range" );
178
+ return m_clauses[idx];
179
+ }
180
+
164
181
chcst::iterator begin () { return m_clauses.begin (); }
165
182
chcst::iterator end () { return m_clauses.end (); }
166
183
chcst::const_iterator begin () const { return m_clauses.begin (); }
167
184
chcst::const_iterator end () const { return m_clauses.end (); }
168
185
};
169
186
170
187
template <typename OutputIterator>
171
- void horn_clause ::used_relations (chc_db &db, OutputIterator out) const
188
+ void horn_clauset ::used_relations (chc_dbt &db, OutputIterator out) const
172
189
{
173
190
const exprt *body = this ->body ();
174
191
if (body == nullptr ) return ;
175
192
std::set<symbol_exprt> symbols = find_symbols (*body);
176
193
177
- chc_db ::is_state_pred filter (db);
194
+ chc_dbt ::is_state_pred filter (db);
178
195
for (auto & symb : symbols) {
179
196
if (filter (symb)) {
180
197
*out = symb;
@@ -183,12 +200,12 @@ void horn_clause::used_relations(chc_db &db, OutputIterator out) const
183
200
}
184
201
185
202
template <typename OutputIterator>
186
- void horn_clause ::used_func_app (chc_db &db, OutputIterator out) const
203
+ void horn_clauset ::used_func_app (chc_dbt &db, OutputIterator out) const
187
204
{
188
205
const exprt *body = this ->body ();
189
206
if (body == nullptr ) return ;
190
207
191
- std::set <function_application_exprt> funcs;
208
+ std::unordered_set <function_application_exprt, irep_hash > funcs;
192
209
body->visit_pre ([&funcs](const exprt &expr) {
193
210
if (can_cast_expr<function_application_exprt>(expr))
194
211
{
@@ -197,7 +214,7 @@ void horn_clause::used_func_app(chc_db &db, OutputIterator out) const
197
214
}
198
215
});
199
216
200
- chc_db ::is_state_pred filter (db);
217
+ chc_dbt ::is_state_pred filter (db);
201
218
for (auto & f : funcs) {
202
219
if (filter (to_symbol_expr (f.function ()))) {
203
220
*out = f;
@@ -210,19 +227,19 @@ void horn_clause::used_func_app(chc_db &db, OutputIterator out) const
210
227
* Uninterpreted relations are vertices, dependency is based on clauses:
211
228
* relations in the body have an edge to the relation in the head.
212
229
*/
213
- class chc_graph
230
+ class chc_grapht
214
231
{
215
- chc_db & m_db;
216
- typedef std::map<exprt, std::set <exprt>> grapht;
232
+ chc_dbt & m_db;
233
+ typedef std::map<exprt, std::unordered_set <exprt, irep_hash >> grapht;
217
234
grapht m_incoming;
218
235
grapht m_outgoing;
219
236
const symbol_exprt *m_entry;
220
237
221
238
// representing the empty set
222
- static std::set <exprt> m_expr_empty_set;
239
+ static std::unordered_set <exprt, irep_hash > m_expr_empty_set;
223
240
224
241
public:
225
- chc_graph (chc_db & db) : m_db(db), m_entry(nullptr ) {}
242
+ chc_grapht (chc_dbt & db) : m_db(db), m_entry(nullptr ) {}
226
243
227
244
void build_graph ();
228
245
@@ -231,14 +248,14 @@ class chc_graph
231
248
INVARIANT (has_entry (), " Entry must exist." );
232
249
return m_entry; }
233
250
234
- const std::set <exprt> &outgoing (const symbol_exprt &state) const {
251
+ const std::unordered_set <exprt, irep_hash > &outgoing (const symbol_exprt &state) const {
235
252
auto it = m_outgoing.find (state);
236
253
if (it == m_outgoing.end ())
237
254
return m_expr_empty_set;
238
255
return it->second ;
239
256
}
240
257
241
- const std::set <exprt> &incoming (const symbol_exprt &state) const {
258
+ const std::unordered_set <exprt, irep_hash > &incoming (const symbol_exprt &state) const {
242
259
auto it = m_incoming.find (state);
243
260
if (it == m_incoming.end ())
244
261
return m_expr_empty_set;
0 commit comments