Menu

[r3]: / libtop_engine / knowledge_rule.h  Maximize  Restore  History

Download this file

397 lines (309 with data), 13.5 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
#ifndef KNOWLEDGE_RULE_H_
#define KNOWLEDGE_RULE_H_
namespace rule {
namespace internal {
class extract_variables_action;
class optimize_indexes_action;
}; /* internal namespace */
using internal::knowledge_term;
typedef std::tr1::shared_ptr<knowledge_term> kterm_ptr_type;
/////////////////////////////////////////////////////////////////////////////////////////
// enum rule_type
//
// Identify the type of rule. head_rule_rt is a special type to indicate that the rule
// is associated with the head_term and is not really a rule but serve as a place holder.
/////////////////////////////////////////////////////////////////////////////////////////
enum rule_type {
query_rule, forward_chaining_rule, backward_chaining_rule, head_rule_rt
};
/////////////////////////////////////////////////////////////////////////////////////////
// class knowledge_rule
//
/////////////////////////////////////////////////////////////////////////////////////////
class knowledge_rule
{
public:
typedef internal::expression_term_ptr_type xprsn_ptr_t;
typedef std::list<kterm_ptr_type> term_list;
typedef std::list<xprsn_ptr_t> xprsn_list;
typedef internal::rule_term_ptr_type rule_term_ptr_t;
typedef std::vector<rule_term_ptr_t> explain_rule_term_vec_t;
typedef explain_rule_term_vec_t::const_iterator rule_term_ptr_const_iterator;
typedef term_list::const_iterator kterm_ptr_const_iterator;
typedef term_list::iterator kterm_ptr_iterator;
typedef internal::var_set_t::const_iterator string_const_iterator;
typedef xprsn_list::const_iterator xprsn_ptr_const_iterator;
typedef internal::rule_vertex rule_vertex_type;
typedef std::vector<internal::rule_vertex> body_term_vertices_t;
typedef body_term_vertices_t::const_iterator rule_vertex_const_iterator;
// mappings needed for query - map old var name (user supplied name) to beta relation index
typedef std::tr1::unordered_map<std::string, unsigned int> select_vars_map_t;
knowledge_rule(rule_type const type, std::string const& name, knowledge_base & kbase, unsigned int s, bool has_explain_info, bool opt_flag):
m_type(type),
m_name(name),
m_text(),
m_salience(s),
m_has_explain_info(has_explain_info),
m_opt_flag(opt_flag),
m_kbase(kbase),
m_head_term(),
m_body_terms(),
m_filters(),
m_consequent_terms(),
m_select_vars(),
m_select_vars_map(),
m_explain_terms(),
m_rule_dep_vertex(),
m_body_term_vertices()
{};
virtual ~knowledge_rule() {};
inline rule_type get_rule_type()const {return m_type;};
inline std::string const& get_rule_name()const{return m_name;};
inline void set_rule_text(std::string const& text){m_text = text;};
inline std::string const& get_rule_text()const{return m_text;};
inline void set_rule_salience(unsigned int s){m_salience = s;};
inline unsigned int get_rule_salience()const{return m_salience;};
inline void keep_explain_info(bool b){m_has_explain_info = b;};
inline bool has_explain_info()const{return m_has_explain_info;};
inline void set_optimization_flag(bool b){m_opt_flag = b;};
inline bool get_optimization_flag()const{return m_opt_flag;};
// for backward chaining rule only
template<class O>
inline kterm_ptr_type
set_head_term(std::string const& s, index_type const p, O const& o)
{
if(m_type != backward_chaining_rule) {
const char * msg = "ERROR-R11: knowledge_rule::set_head_term: Available only to backward_chaining_rule";
std::cout << msg << std::endl;
throw rdf::rdf_exception(rdf::invalid_rule_def, msg);
}
m_head_term = kterm_ptr_type(new internal::backward_head_term<std::string, index_type, O>(*this, s, p, o));
add_consequent_term(s, p, o);
return m_head_term;
};
// for query, forward, and backward chaining rules
template<class U, class V, class W>
inline kterm_ptr_type
add_rule_term(U const& u, V const& v, W const& w)
{
kterm_ptr_type term_p = kterm_ptr_type(new internal::body_term<U, V, W>(*this, u, v, w));
m_body_terms.push_back(term_p);
return term_p;
};
// for query, forward, and backward chaining rules
template<class U, class V, class W>
inline kterm_ptr_type
add_negated_rule_term(U const& u, V const& v, W const& w)
{
kterm_ptr_type term_p = kterm_ptr_type(new internal::body_term<U, V, W>(*this, u, v, w, true));
m_body_terms.push_back(term_p);
return term_p;
};
// for query, forward, and backward chaining rules
template<class Oper, class X, class Y>
xprsn_ptr_t
create_expression(Oper const& oper, X const& x, Y const& y)
{
return xprsn_ptr_t(new internal::binary_expression_term<Oper, X, Y>(oper, x, y));
};
template<class Oper, class X>
xprsn_ptr_t
create_expression(Oper const& oper, X const& x)
{
return xprsn_ptr_t(new internal::unary_expression_term<Oper, X>(oper, x));
};
void
set_filter(kterm_ptr_type rule_term_p, xprsn_ptr_t filter_p)
{
if(m_opt_flag) m_filters.push_back(filter_p);
else rule_term_p->set_filter(filter_p);
};
// used by forward chaining rules only (consequent term for backward chaining rules are created from head term)
template<class U, class V, class W>
inline kterm_ptr_type
add_consequent_term(U const& u, V const& v, W const& w)
{
kterm_ptr_type term_p = kterm_ptr_type(new internal::consequent_term<U, V, W>(*this, u, v, w));
term_p->set_consequent(true);
m_consequent_terms.push_back(term_p);
return term_p;
};
// used for query rule only
inline void
add_select_variable(std::string const& v)
{
m_select_vars.insert(v);
};
inline unsigned int
get_select_vars_count()const
{
return m_select_vars_map.size();
};
// used to get the index of a select variable
inline unsigned int
get_select_var_mapping(std::string var)const
{
select_vars_map_t::const_iterator itor = m_select_vars_map.find(var);
if(itor == m_select_vars_map.end()) {
std::string msg("ERROR-R14: knowledge_rule::get_select_var_mapping: Variable '"+var+"' does not exist in the select clause of the query.");
std::cout << msg << std::endl;
throw rdf::rdf_exception(rdf::invalid_rule_def, msg);
}
return itor->second;
};
inline bool
contains_select_var(std::string var)const
{
select_vars_map_t::const_iterator itor = m_select_vars_map.find(var);
if(itor == m_select_vars_map.end()) return false;
return true;
};
inline void
add_select_var_mapping(std::string var, unsigned int index)
{
m_select_vars_map.insert(select_vars_map_t::value_type(var, index));
};
void
set_dependency_graph_vertex(rule_vertex_type const v)
{
m_rule_dep_vertex = v;
};
rule_vertex_type
get_dependency_graph_vertex()const
{
return m_rule_dep_vertex;
};
// usefull for discovering and printing
inline kterm_ptr_const_iterator get_body_terms_begin()const{return m_body_terms.begin();};
inline kterm_ptr_const_iterator get_body_terms_end() const{return m_body_terms.end();};
inline kterm_ptr_iterator get_body_terms_begin(){return m_body_terms.begin();};
inline kterm_ptr_iterator get_body_terms_end() {return m_body_terms.end();};
inline kterm_ptr_const_iterator get_consequent_terms_begin()const{return m_consequent_terms.begin();};
inline kterm_ptr_const_iterator get_consequent_terms_end() const{return m_consequent_terms.end();};
inline kterm_ptr_iterator get_consequent_terms_begin(){return m_consequent_terms.begin();};
inline kterm_ptr_iterator get_consequent_terms_end() {return m_consequent_terms.end();};
inline rule_term_ptr_const_iterator get_explain_terms_begin()const{return m_explain_terms.begin();};
inline rule_term_ptr_const_iterator get_explain_terms_end ()const{return m_explain_terms.end();};
inline kterm_ptr_type const& get_head_term()const{return m_head_term;};
inline kterm_ptr_type & get_head_term(){return m_head_term;};
inline string_const_iterator get_select_vars_begin()const{return m_select_vars.begin();};
inline string_const_iterator get_select_vars_end() const{return m_select_vars.end();};
inline xprsn_ptr_const_iterator get_unallocated_filters_begin()const{return m_filters.begin();};
inline xprsn_ptr_const_iterator get_unallocated_filters_end() const{return m_filters.end();};
inline void add_body_term_vertex(rule_vertex_type v){m_body_term_vertices.push_back(v);};
inline rule_vertex_const_iterator get_body_term_vertices_begin()const{return m_body_term_vertices.begin();};
inline rule_vertex_const_iterator get_body_term_vertices_end() const{return m_body_term_vertices.end();};
inline rule_vertex_type get_tail_body_term_vertex()const{return m_body_term_vertices.back();};
// used in index_triple_cback::perform_merge_row and index_triple_cback::perform_remove_row
// argument v should not be the graph head vertex.
inline rule_vertex_type
get_parent_of(rule_vertex_type v)const
{
rule_vertex_const_iterator itor = get_body_term_vertices_begin();
rule_vertex_const_iterator end = get_body_term_vertices_end();
rule_vertex_const_iterator parent_itor = itor;
// the first one is the graph head vertex which should not be the argument v
for(; itor!=end; ++itor) {
if(*itor == v) {
if(itor == parent_itor) {
// something went wrong
throw rdf::rdf_exception(rdf::unexpected_logic_error, "ERROR: knowledge_rule::get_parent_of: Called with graph head vertex!");
}
return *parent_itor;
}
parent_itor = itor;
}
throw rdf::rdf_exception(rdf::invalid_rule_def, "ERROR: knowledge_rule::get_parent_of: Vertex not found!");
};
protected:
void setup_for_query (rule_term_ptr_t & left_term, internal::var_set_t & right_vars);
void setup_for_head (rule_term_ptr_t & left_term, internal::var_set_t & right_vars);
void setup_for_forward (rule_term_ptr_t & left_term, internal::var_set_t & right_vars);
void setup_for_backward(rule_term_ptr_t & left_term, internal::var_set_t & right_vars);
void
build_consequent_and_explaination_terms(rule_term_ptr_t & left_term, internal::var_set_t & right_vars);
// called by knowledge base
void
compile_rule();
inline unsigned int
nbr_rule_vertices()
{
switch(m_type) {
case head_rule_rt: return 1;
case query_rule: return m_body_terms.size()+1;
case forward_chaining_rule: return m_body_terms.size();
case backward_chaining_rule: return m_body_terms.size()+1;
}
const char * msg = "ERROR-R12: knowledge_rule::nbr_rule_vertices: Missing rule type in switch statement";
std::cout << msg << std::endl;
throw rdf::rdf_exception(rdf::invalid_rule_def, msg);
};
void
create_rule_vertices(bool verbose);
void
check_for_register_inferred_triple(rule_term_ptr_t rule_term_p);
private:
friend class knowledge_base;
friend class internal::optimize_indexes_action;
friend std::ostream & operator<<(std::ostream &, knowledge_rule const&);
void optimize_rule_term_ordering();
void rename_variables();
rule_type m_type;
std::string m_name;
std::string m_text;
unsigned int m_salience;
bool m_has_explain_info;
bool m_opt_flag;
knowledge_base & m_kbase;
kterm_ptr_type m_head_term;
term_list m_body_terms;
xprsn_list m_filters;
term_list m_consequent_terms;
internal::var_set_t m_select_vars;
select_vars_map_t m_select_vars_map; // mapping of user supplied name to index of result set (query case)
explain_rule_term_vec_t m_explain_terms;
rule_vertex_type m_rule_dep_vertex;
body_term_vertices_t m_body_term_vertices;
};
inline std::ostream & operator<<(std::ostream & sout, knowledge_rule const& krule)
{
sout << krule.m_name<< "[salience " << krule.m_salience << "]: ";
if(krule.m_type == backward_chaining_rule) {
sout << (*krule.m_head_term) << " <- ";
}
if(krule.m_type == query_rule) {
sout << " SELECT ";
knowledge_rule::string_const_iterator itor = krule.get_select_vars_begin();
knowledge_rule::string_const_iterator end = krule.get_select_vars_end();
if(itor == end) sout << "*";
for(; itor!=end; ++itor) sout << (*itor) << " ";
sout << " FROM ";
}
knowledge_rule::kterm_ptr_const_iterator itor = krule.get_body_terms_begin();
knowledge_rule::kterm_ptr_const_iterator end = krule.get_body_terms_end();
while(itor != end) {
sout << **itor;
++itor;
if(itor != end) sout << ".";
}
knowledge_rule::xprsn_ptr_const_iterator fitor = krule.get_unallocated_filters_begin();
knowledge_rule::xprsn_ptr_const_iterator fend = krule.get_unallocated_filters_end();
while(fitor != fend) {
sout << "[" << **fitor << "]";
++fitor;
if(fitor != fend) sout << ".";
}
if(krule.m_type == forward_chaining_rule) {
sout << " -> ";
itor = krule.get_consequent_terms_begin();
end = krule.get_consequent_terms_end();
while(itor != end) {
sout << (**itor);
++itor;
if(itor != end) sout << ".";
}
}
return sout;
};
}; /* rule namespace */
#endif /*KNOWLEDGE_RULE_H_*/
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.