#ifndef RULE_TERM_BASE_H_
#define RULE_TERM_BASE_H_
#include "rdf_rule_core.h"
#include "rdf_rule_cback.h"
#include "backward_reasoner.h"
#include "rule_internal.h"
namespace rule {
class rule_session;
namespace internal {
class expression_rule_term_base;
typedef std::tr1::shared_ptr<expression_rule_term_base> expression_rule_term_ptr_type;
/////////////////////////////////////////////////////////////////////////////////////////
// class index_map_helper
//
/////////////////////////////////////////////////////////////////////////////////////////
class index_map_helper
{
typedef std::vector<unsigned int> index_map_t;
typedef std::vector<std::string> index_label_map_t;
public:
typedef std::pair<unsigned int, std::string const> index_label_pair;
typedef index_map_t::const_iterator index_iterator;
typedef index_label_map_t::const_iterator label_iterator;
enum left_right_tag{left=0x0100, right=0x0200, hi_mask=0xFF00, lo_mask=0x00FF};
inline index_map_helper():
m_label_map(),
m_index_map(),
m_lookup_index(beta_relation::NO_LOOKUP_INDEX)
{};
virtual ~index_map_helper(){};
inline unsigned int
get_index_map_size()const
{
return m_index_map.size();
};
/*
* Used in create_rt of knowledge_base.cpp to create rule_term - may worth to move this into hash_map(string, index_label_pair)
* Used in consequent_term::create_rule_term to ensure all variable are binded (knowledge_base.h)
*/
inline bool has_index(std::string const& label)const
{
unsigned int sz = m_label_map.size();
for(unsigned int idx = 0; idx<sz; ++idx) if(label == m_label_map[idx]) return true;
return false;
};
inline index_label_pair
get_index(std::string const& label)const
{
unsigned int sz = m_label_map.size();
for(unsigned int idx = 0; idx<sz; ++idx) if(label == m_label_map[idx]) return index_label_pair(idx, label);
std::cout << "index_map_helper::get_index: invalid label: " << label << std::endl;
throw rdf::rdf_exception(rdf::invalid_index, "rule_term_base::get_index: invalid label");
};
inline void
add_index(left_right_tag lr, unsigned int index, std::string const& label)
{
if(index & hi_mask) {
std::cout<<"index_map_helper::add_index: called w/ index too big: "<< index <<std::endl;
throw rdf::rdf_exception(rdf::invalid_index, "rule_term_base::add_index: invalid index");
}
m_index_map.push_back(lr | index);
m_label_map.push_back(label);
};
inline void
add_left_index(index_label_pair const& index_label)
{
add_index(left, index_label.first, index_label.second);
};
inline void
add_left_index(unsigned int index, std::string const& label)
{
add_index(left, index, label);
};
inline void
add_right_index(unsigned int index, std::string const& label)
{
add_index(right, index, label);
};
void
print_index();
inline index_iterator
get_index_iterator_begin()const
{
return m_index_map.begin();
};
inline index_iterator
get_index_iterator_end()const
{
return m_index_map.end();
};
inline label_iterator
label_iterator_begin()const
{
return m_label_map.begin();
};
inline label_iterator
label_iterator_end()const
{
return m_label_map.end();
};
inline std::string const&
get_label(unsigned int idx)const
{
return m_label_map[idx];
};
std::string
label_to_string()const;
inline void
set_lookup_index(unsigned int index_)
{
m_lookup_index = index_;
};
inline unsigned int
get_lookup_index()
{
return m_lookup_index;
};
private:
index_label_map_t m_label_map;
index_map_t m_index_map;
unsigned int m_lookup_index;
};
typedef std::tr1::shared_ptr<index_map_helper> index_map_helper_ptr_type;
// used to determine if need to register to infer graph (by knowledge_rule)
enum functor_name {fu_name, fv_name, fw_name};
/////////////////////////////////////////////////////////////////////////////////////////
// class rule_term_base
//
/////////////////////////////////////////////////////////////////////////////////////////
// declared in rdf_rule_cback.h due to forward declaration
// class rule_term_base;
// typedef std::tr1::shared_ptr<rule_term_base> rule_term_ptr_type;
class rule_term_base
{
public:
inline rule_term_base():
m_index_map_helper_p(new index_map_helper()),
m_filter_p(),
m_name()
{};
rule_term_base(rule_term_base const& rhs):
m_index_map_helper_p(rhs.m_index_map_helper_p),
m_filter_p(rhs.m_filter_p),
m_name(rhs.m_name)
{};
virtual ~rule_term_base(){};
/* Used by rule_propagation on tree_edge of rule_graph during DFS */
virtual unsigned int compute_rows(rule_session * rule_session_p, beta_relation::const_iterator& left_relation, beta_relation& relation)const=0;
/* Used by rule_propagation on tree_edge of rule_graph during DFS */
virtual unsigned int retract_rows(rule_session * rule_session_p, beta_relation::const_iterator& left_relation, beta_relation& relation)const=0;
/* Exposed for use by explain_why on consequent terms only */
virtual bool is_match_row (rule_session * rule_session_p, relation_row_map const& relation_row, rdf::index_type const* triple)const=0;
/* Used by rule_engine for explain_why on consequent terms only */
virtual bool can_triple_match(rdf::index_type const* triple)const=0;
/* Used by knowledge_rule to check if the consequent terms (argument) can infer triple that would match */
virtual bool check_for_match(rule_term_ptr_type const&)const=0;
/* Used by call back functor only */
virtual unsigned int merge_rows (rule_session * rule_session_p, beta_relation const& left_relation, rdf::index_type const*triple, beta_relation& relation)const=0;
/* Used by call back functor only */
virtual unsigned int remove_rows(rule_session * rule_session_p, beta_relation const& left_relation, rdf::index_type const*triple, beta_relation& relation)const=0;
/* Used on consequent terms only */
virtual unsigned int compute_inferred_triples(rule_session * rule_session_p, relation_row_map const& relation_row)const=0;
/* Used on rule terms (from rule_properties) to either explain log a rule_event (rule_engine) or explain a triple (explain_why) */
virtual rdf::index_type * get_inferred_triples(rule_session *, rdf::index_type *t3, relation_row_map const& relation_row)const=0;
/* Used on consequent terms only */
virtual unsigned int retract_inferred_triples(rule_session * rule_session_p, relation_row_map const& relation_row)const=0;
/* Used by rule_engine to register call back during rule configuration.
* This register the rule_term to the inferred or asserted graph for when triple are
* inserted that matches this rule_term.
*/
virtual void register_cback(rdf::rdf_cback_mgr& manager, rdf::index_triple_cback_ptr_type const& cback)const=0;
/* Used by knowledge_base to register backward_chaining rules to this rule_term.
* Events will be sent to rule_session to activate backward_chaining rules when.
*/
virtual void register_backward_chaining_rules(back_reasoner_mgr & mgr)=0;
/* Used by rule_cback and explain_why to dertermine if rule term is a negation */
virtual bool is_assertion_term()const=0;
inline std::size_t
initialize_row(relation_row_ptr_type &row_p, relation_row_map const& relation_row, rdf::index_type const*triple)const
{
index_map_helper::index_iterator itor = m_index_map_helper_p->get_index_iterator_begin();
index_map_helper::index_iterator end = m_index_map_helper_p->get_index_iterator_end();
relation_row_map::size_type key = 0;
std::size_t hash_code = 0;
rdf::index_type value;
while(itor!=end) {
internal::relation_row_map::size_type index = *itor;
if(index & index_map_helper::left) value = relation_row[index & index_map_helper::lo_mask];
else {
if(!triple) {
// invalid pointer - must be an expression_rule_term with an invalid m_index_map
char const* msg = "rule_term_base::initialize_row: ERROR: Null triple - must be an expression_rule_term with invalid index_map - make sure not to have right index";
std::cout << msg << "\n";
throw rdf::rdf_exception(rdf::invalid_index, msg);
};
value = triple[index & index_map_helper::lo_mask];
}
(*row_p)[key] = value;
++itor;
++key;
hash_code += std::size_t(value);
};
return hash_code;
};
// defined in rule_session.h due to dependency and to ensure inlining
unsigned int
add_row(rule_session * rule_session_p, relation_row_map const& relation_row, rdf::index_type const* triple, beta_relation &relation)const;
// defined in rule_session.h due to dependency and to ensure inlining
unsigned int
remove_row(rule_session * rule_session_p, relation_row_map const& relation_row, rdf::index_type const* triple, beta_relation &relation)const;
inline void set_filter(expression_rule_term_ptr_type filter_p){m_filter_p = filter_p;};
inline expression_rule_term_ptr_type const& get_filter()const{return m_filter_p;};
inline expression_rule_term_ptr_type & get_filter() {return m_filter_p;};
// return true if row is filtered-out, false to keep the row
// called by rule_term_base::add_row and remove_row
// defined in rule_expression.h due to the forward declaration of expression_rule_term_base
inline bool
apply_filter(rule_session * rule_session_p, relation_row_map const& relation_row)const;
// used in conjuction w/ operator<<
virtual std::string to_string()const=0;
// to help debugging and verbose mode - name of knowledge_term
inline void
set_name(std::string name)
{
m_name = name;
};
inline std::string
get_name()const
{
return m_name;
};
// =========================================================================================
// MEMBER FUNCTIONS TO MANAGE THE INDEXES OF THE BETA RELATION
// Used by knowledge base and rule terms methods
// Functionality localized into a helper class so that the indexes can be compacted
// =========================================================================================
inline index_map_helper_ptr_type
get_index_map_helper_ptr()const
{
return m_index_map_helper_p;
};
inline void
set_index_map_helper_ptr(index_map_helper_ptr_type index_map_helper_p)
{
m_index_map_helper_p = index_map_helper_p;
};
inline unsigned int
get_index_map_size()const
{
return m_index_map_helper_p->get_index_map_size();
};
/*
* Used in create_rt of knowledge_base.cpp to create rule_term - may worth to move this into hash_map(string, index_label_pair)
* Used in consequent_term::create_rule_term to ensure all variable are binded (knowledge_base.h)
*/
inline bool has_index(std::string const& label)const
{
return m_index_map_helper_p->has_index(label);
};
inline index_map_helper::index_label_pair
get_index(std::string const& label)const
{
return m_index_map_helper_p->get_index(label);
};
inline void
add_index(index_map_helper::left_right_tag lr, unsigned int index, std::string const& label)
{
m_index_map_helper_p->add_index(lr, index, label);
};
inline void
add_left_index(index_map_helper::index_label_pair const& index_label)
{
m_index_map_helper_p->add_left_index(index_label);
};
inline void
add_right_index(std::string const& label)
{
m_index_map_helper_p->add_right_index(get_triple_index(label), label);
};
inline void
add_right_index(unsigned int index)
{
m_index_map_helper_p->add_right_index(index, get_triple_label(index));
};
void print_index();
inline index_map_helper::label_iterator
label_iterator_begin()const
{
return m_index_map_helper_p->label_iterator_begin();
};
inline index_map_helper::label_iterator
label_iterator_end()const
{
return m_index_map_helper_p->label_iterator_end();
};
inline std::string const&
get_label(unsigned int idx)const
{
return m_index_map_helper_p->get_label(idx);
};
inline std::string
label_to_string()const
{
return m_index_map_helper_p->label_to_string();
};
// determine the best index to setup by looking at u, v, w terms
virtual unsigned int
get_preferred_lookup_index()=0;
inline void
set_lookup_index(unsigned int index)
{
m_index_map_helper_p->set_lookup_index(index);
};
inline unsigned int
get_lookup_index()
{
return m_index_map_helper_p->get_lookup_index();
};
// =========================================================================================
// =========================================================================================
// MEMBER FUNCTIONS TO DETERMINE IF TWO TERMS ARE EQUIVALENT
// Used by bool is_same_as(rule_term_ptr_type const& rt_p)const above
// =========================================================================================
virtual bool check_for_match(functor_name const f, rdf::index_type const index)const=0;
virtual bool check_for_match(functor_name const f, std::string const&)const=0;
virtual bool check_for_match(functor_name const f, F_expression const&)const=0;
virtual bool is_same_as(functor_name const f, internal::F_cst const&)const=0;
virtual bool is_same_as(functor_name const f, internal::F_join const&)const=0;
virtual bool is_same_as(functor_name const f, internal::F_var const&)const=0;
virtual bool is_same_as(functor_name const f, internal::F_expression const&)const=0;
bool is_filter_same_as(expression_rule_term_ptr_type const& rhs)const;
virtual bool is_same_as(rule_term_ptr_type const& rhs)const=0;
// =========================================================================================
protected:
friend std::ostream & operator<<(std::ostream &, rule_term_base const&);
virtual unsigned int get_triple_index(std::string const& label)const=0;
virtual std::string get_triple_label(unsigned int index)const{return "";};
private:
index_map_helper_ptr_type m_index_map_helper_p;
expression_rule_term_ptr_type m_filter_p;
std::string m_name;
};
inline std::ostream & operator<<(std::ostream & sout, rule_term_base const& x)
{
sout << x.to_string();
return sout;
};
/////////////////////////////////////////////////////////////////////////////////////////
// class head_rule_term
//
/////////////////////////////////////////////////////////////////////////////////////////
class head_rule_term: public rule_term_base {
public:
inline head_rule_term() : rule_term_base() {};
inline head_rule_term(head_rule_term const& rhs) : rule_term_base(rhs) {};
inline virtual ~head_rule_term(){};
inline unsigned int compute_rows(rule_session * rule_session_p, beta_relation::const_iterator& left_relation, beta_relation& relation)const{return 0;};
inline unsigned int retract_rows(rule_session * rule_session_p, beta_relation::const_iterator& left_relation, beta_relation& relation)const{return 0;};
inline bool is_match_row (rule_session * rule_session_p, relation_row_map const& relation_row, rdf::index_type const* triple)const{return false;};
inline bool can_triple_match(rdf::index_type const* triple)const{return false;};
inline unsigned int merge_rows(rule_session * rule_session_p, beta_relation const& left_relation, rdf::index_type const*triple, beta_relation& relation)const{return 0;};
inline unsigned int remove_rows(rule_session * rule_session_p, beta_relation const& left_relation, rdf::index_type const*triple, beta_relation& relation)const{return 0;};
inline unsigned int compute_inferred_triples(rule_session * rule_session_p, relation_row_map const& relation_row)const{return 0;};
inline rdf::index_type * get_inferred_triples(rule_session *, rdf::index_type *t3, relation_row_map const& relation_row)const{t3[0]=0; t3[1]=0; t3[2]=0; return t3;};
inline unsigned int retract_inferred_triples(rule_session * rule_session_p, relation_row_map const& relation_row)const{return 0;};
inline void register_cback(rdf::rdf_cback_mgr& manager, rdf::index_triple_cback_ptr_type const& cback)const{};
inline void register_backward_chaining_rules(back_reasoner_mgr & mgr){};
inline bool is_assertion_term()const{return true;};
/* Used by knowledge_rule to merge identical rule_term with existing ones in the rule_graph */
inline bool is_same_as(rule_term_ptr_type const& rt_p)const{return false;};
inline std::string to_string()const{return "(head_term)";};
inline bool check_for_match(functor_name const f, rdf::index_type const index)const{return false;};
inline bool check_for_match(functor_name const f, std::string const&)const{return false;};
inline bool check_for_match(functor_name const f, struct F_expression const&)const{return false;};
inline bool check_for_match(rule_term_ptr_type const&)const{return false;};
inline bool is_same_as(functor_name const f, F_cst const& x)const{return false;};
inline bool is_same_as(functor_name const f, F_join const& x)const{return false;};
inline bool is_same_as(functor_name const f, F_var const& x)const{return false;};
inline bool is_same_as(functor_name const f, F_expression const& x)const{return false;};
inline unsigned int
get_preferred_lookup_index()
{
return beta_relation::NO_LOOKUP_INDEX;
};
protected:
inline unsigned int get_triple_index(std::string const& label)const
{
std::cout << "head_rule_term::get_triple_index: Head rule term cannot have indexes; invalid label: " << label << std::endl;
throw rdf::rdf_exception(rdf::invalid_index, "head_rule_term::get_triple_index: Head rule term cannot have indexes; invalid label");
};
};
}; /* internal namespace */
}; /* rule namespace */
#endif /*RULE_TERM_BASE_H_*/