#ifndef KNOWLEDGE_TERM_H_
#define KNOWLEDGE_TERM_H_
namespace rule {
namespace internal {
/////////////////////////////////////////////////////////////////////////////////////////
// class knowledge_term
//
/////////////////////////////////////////////////////////////////////////////////////////
class knowledge_term
{
public:
inline knowledge_term(knowledge_rule & krule):
m_knowledge_rule(krule),
m_rule_vertex(0),
m_name(""),
m_is_consequent(false),
m_rule_term(),
m_filter_p(),
m_register_to_inferred_graph(false)
{};
virtual ~knowledge_term(){};
inline rule_vertex
get_rule_vertex()const
{
return m_rule_vertex;
};
inline void
set_rule_vertex(rule_vertex v)
{
m_rule_vertex = v;
};
inline std::string const&
get_name()const
{
return m_name;
};
inline void
set_name(std::string const& name)
{
m_name = name;
if(m_rule_term) m_rule_term->set_name(name);
};
inline void
set_consequent(bool b)
{
m_is_consequent = b;
};
inline bool
is_consequent()const
{
return m_is_consequent;
};
inline knowledge_rule const&
get_knowledge_rule()const
{
return m_knowledge_rule;
};
inline knowledge_rule &
get_knowledge_rule()
{
return m_knowledge_rule;
};
inline void
set_filter(expression_term_ptr_type filter_p)
{
m_filter_p = filter_p;
};
inline expression_term_ptr_type
get_filter()const
{
return m_filter_p;
};
inline bool
has_filter()const{ return m_filter_p ? true : false;};
virtual match_result
compute_match(var_set_t const&)const=0;
virtual bool
is_negation()const=0;
virtual void
extract_vars(var_set_t &)const=0;
virtual rule_term_ptr_type
create_rule_term(rule_term_ptr_type const& left_term, var_set_t const& right_vars)=0;
inline bool
check_for_register_inferred_triple(rule_term_ptr_type consequent_rule_term_p)
{
if(m_register_to_inferred_graph) return true;
if(consequent_rule_term_p->check_for_match(m_rule_term)) m_register_to_inferred_graph = true;
// //*
// if(m_register_to_inferred_graph) {
// std::cout << "knowledge_term " << *m_rule_term << " will be registered to the inferred graph for changes\n";
// }
return m_register_to_inferred_graph;
};
inline bool
register_to_inferred_graph()
{
return m_register_to_inferred_graph;
};
inline void
set_rule_term(rule_term_ptr_type const&rule_term)
{
m_rule_term = rule_term;
if(m_filter_p) {
expression_rule_term_ptr_type expr_t = m_filter_p->create_expression_term(m_rule_term);
m_rule_term->set_filter(expr_t);
};
m_rule_term->set_name(m_name);
};
inline rule_term_ptr_type const&
get_rule_term()const
{
return m_rule_term;
};
inline rule_term_ptr_type &
get_rule_term()
{
return m_rule_term;
};
virtual void
rename_variables(var_map_t & map, int & ivar)=0;
virtual std::string
to_string()const=0;
// called on backward chaining rule only to register the rule's predicate/object and root vertex
virtual void
register_backward_chaining_rule(back_reasoner_mgr & mgr, rule_vertex const root_rule_vertex)const=0;
protected:
inline void rename_var(expression_term_ptr_type & f, var_map_t & map, int & ivar){f->rename_variables(map, ivar);};
inline void rename_var(index_type & , var_map_t & map, int & ivar){};
inline void rename_var(std::string & v, var_map_t & map, int & ivar){v = get_new_name_for(v, map, ivar);};
inline void put_var(var_set_t & vars, expression_term_ptr_type const& f)const{f->extract_vars(vars);};
inline void put_var(var_set_t & vars, index_type const&)const{};
inline void put_var(var_set_t & vars, std::string const& v)const{vars.insert(v);};
friend std::ostream & operator<<(std::ostream &, knowledge_term const&);
knowledge_rule & m_knowledge_rule;
rule_vertex m_rule_vertex;
std::string m_name;
bool m_is_consequent;
rule_term_ptr_type m_rule_term;
expression_term_ptr_type m_filter_p;
bool m_register_to_inferred_graph;
};
inline std::ostream & operator<<(std::ostream & sout, knowledge_term const& kterm)
{
sout << kterm.to_string();
return sout;
};
rule_term_ptr_type create_rt(rule_term_ptr_type const& left_term, var_set_t const& right_vars, index_type const& u, index_type const& v, std::string const& w, bool is_negation);
rule_term_ptr_type create_rt(rule_term_ptr_type const& left_term, var_set_t const& right_vars, index_type const& u, std::string const& v, index_type const& w, bool is_negation);
rule_term_ptr_type create_rt(rule_term_ptr_type const& left_term, var_set_t const& right_vars, index_type const& u, std::string const& v, std::string const& w, bool is_negation);
rule_term_ptr_type create_rt(rule_term_ptr_type const& left_term, var_set_t const& right_vars, std::string const& u, index_type const& v, index_type const& w, bool is_negation);
rule_term_ptr_type create_rt(rule_term_ptr_type const& left_term, var_set_t const& right_vars, std::string const& u, index_type const& v, std::string const& w, bool is_negation);
rule_term_ptr_type create_rt(rule_term_ptr_type const& left_term, var_set_t const& right_vars, std::string const& u, std::string const& v, index_type const& w, bool is_negation);
rule_term_ptr_type create_rt(rule_term_ptr_type const& left_term, var_set_t const& right_vars, std::string const& u, std::string const& v, std::string const& w, bool is_negation);
rule_term_ptr_type create_rt(rule_term_ptr_type const& left_term, var_set_t const& right_vars, index_type const& u, index_type const& v, expression_term_ptr_type const& w, bool is_negation);
rule_term_ptr_type create_rt(rule_term_ptr_type const& left_term, var_set_t const& right_vars, index_type const& u, std::string const& v, expression_term_ptr_type const& w, bool is_negation);
rule_term_ptr_type create_rt(rule_term_ptr_type const& left_term, var_set_t const& right_vars, std::string const& u, index_type const& v, expression_term_ptr_type const& w, bool is_negation);
rule_term_ptr_type create_rt(rule_term_ptr_type const& left_term, var_set_t const& right_vars, std::string const& u, std::string const& v, expression_term_ptr_type const& w, bool is_negation);
template<class V, class W>
inline bool register_rule(back_reasoner_mgr & mgr, V const& v, W const& w, rule_vertex const rv)
{
return false;
};
inline bool register_rule(back_reasoner_mgr & mgr, index_type const& v, index_type const& w, rule_vertex const rv)
{
mgr.register_backward_chaining_rule(v, w, rv);
return true;
};
inline bool register_rule(back_reasoner_mgr & mgr, index_type const& v, std::string const&, rule_vertex const rv)
{
mgr.register_backward_chaining_rule(v, rv);
return true;
};
/////////////////////////////////////////////////////////////////////////////////////////
// class k_term_base
//
/////////////////////////////////////////////////////////////////////////////////////////
template<class U, class V, class W>
class k_term_base: public knowledge_term
{
public:
inline k_term_base(knowledge_rule & krule, U const& u, V const& v, W const& w, bool is_negation=false):
knowledge_term(krule),
m_is_negation(is_negation),
m_u(u),
m_v(v),
m_w(w)
{};
virtual ~k_term_base(){};
inline bool
is_negation()const
{
return m_is_negation;
};
inline void
extract_vars(var_set_t & vars)const
{
put_var(vars, m_u);
put_var(vars, m_v);
put_var(vars, m_w);
};
inline rule_term_ptr_type
create_rule_term(rule_term_ptr_type const& left_term, var_set_t const& right_vars)
{
return create_rt(left_term, right_vars, m_u, m_v, m_w, m_is_negation);
};
void
rename_variables(var_map_t & map, int & ivar)
{
rename_var(m_u, map, ivar);
rename_var(m_v, map, ivar);
rename_var(m_w, map, ivar);
if(m_filter_p) m_filter_p->rename_variables(map, ivar);
};
inline std::string
to_string()const
{
std::ostringstream sout;
if(m_is_negation) sout << "not";
sout << "("
<< rule::internal::to_string(m_u) << " "
<< rule::internal::to_string(m_v) << " "
<< rule::internal::to_string(m_w) << ")";
if(m_filter_p) {
sout << ".[" << *m_filter_p << "]";
}
return sout.str();
};
inline void register_backward_chaining_rule(back_reasoner_mgr & mgr, rule_vertex const root_rule_vertex)const
{
bool registered = register_rule(mgr, m_v, m_w, root_rule_vertex);
if(registered) {
// //*
// std::cout << "knowledge_term::register_backward_chaining_rule w/ rule head "
// << to_string() <<std::endl;
}
};
U const& get_U()const{return m_u;};
V const& get_V()const{return m_v;};
W const& get_W()const{return m_w;};
protected:
bool m_is_negation;
U m_u;
V m_v;
W m_w;
};
/////////////////////////////////////////////////////////////////////////////////////////
// class body_term
//
/////////////////////////////////////////////////////////////////////////////////////////
template<class U, class V, class W>
class body_term: public k_term_base<U, V, W>
{
public:
inline body_term(knowledge_rule & krule, U const& u, V const& v, W const& w, bool is_negation=false):
k_term_base<U, V, W>(krule, u, v, w, is_negation)
{};
~body_term(){};
inline match_result compute_match(var_set_t const& index_map)const
{
// if negated term and variables are not binded, return worse case match result.
if(k_term_base<U, V, W>::is_negation() and (
!has_var_negated_term(index_map, k_term_base<U, V, W>::get_U()) or
!has_var_negated_term(index_map, k_term_base<U, V, W>::get_V()) or
!has_var_negated_term(index_map, k_term_base<U, V, W>::get_W()) )) return match_result();
return match_result(index_map, k_term_base<U, V, W>::get_U(), k_term_base<U, V, W>::get_V(), k_term_base<U, V, W>::get_W());
};
private:
// check if the variable of a negated term are binded (i.er., contained in vars)
inline bool has_var_negated_term(var_set_t const& vars, expression_term_ptr_type const& )const{return false;}; // case not possible
inline bool has_var_negated_term(var_set_t const& vars, index_type const&)const{return true;};
inline bool has_var_negated_term(var_set_t const& vars, std::string const& v)const{return vars.find(v)!=vars.end();};
};
/////////////////////////////////////////////////////////////////////////////////////////
// class consequent_term
//
/////////////////////////////////////////////////////////////////////////////////////////
template<class U, class V, class W>
class consequent_term: public k_term_base<U, V, W>
{
public:
inline consequent_term(knowledge_rule & krule, U const& u, V const& v, W const& w):
k_term_base<U, V, W>(krule, u, v, w, false)
{};
~consequent_term(){};
inline rule_term_ptr_type
create_rule_term(rule_term_ptr_type const& left_term, var_set_t const& right_vars)
{
// validate that all variable are binded in left_term
validate_binded_var(left_term, k_term_base<U, V, W>::get_U());
validate_binded_var(left_term, k_term_base<U, V, W>::get_V());
validate_binded_var(left_term, k_term_base<U, V, W>::get_W());
return create_rt(left_term, right_vars,
k_term_base<U, V, W>::get_U(),
k_term_base<U, V, W>::get_V(),
k_term_base<U, V, W>::get_W(), false);
};
// not called for consequent terms and head terms
inline match_result
compute_match(var_set_t const& index_map)const
{
return match_result();
};
protected:
inline void
validate_binded_var(rule_term_ptr_type const& left_term, expression_term_ptr_type const& f)const
{
if(!f->has_all_vars(left_term)) {
std::string msg = "ERROR-C1: A variable in consequent expression is not binded in rule body.";
std::cout << msg << std::endl;
throw rdf::rdf_exception(rdf::invalid_rule_def, msg);
}
};
inline void
validate_binded_var(rule_term_ptr_type const& left_term, index_type const&)const
{};
inline void
validate_binded_var(rule_term_ptr_type const& left_term, std::string const& v)const
{
if(!left_term->has_index(v)) {
std::string msg = "ERROR-C1: Variable '" + v + "' is not binded in rule body.";
std::cout << msg << std::endl;
throw rdf::rdf_exception(rdf::invalid_rule_def, msg);
}
};
};
/////////////////////////////////////////////////////////////////////////////////////////
// class backward_head_term
//
// Head rule term for backward chaining rule
/////////////////////////////////////////////////////////////////////////////////////////
template<class U, class V, class W>
class backward_head_term: public k_term_base<U, V, W>
{
public:
inline backward_head_term(knowledge_rule & krule, U const& u, V const& v, W const& w):
k_term_base<U, V, W>(krule, u, v, w, false)
{};
~backward_head_term(){};
inline rule_term_ptr_type
create_rule_term(rule_term_ptr_type const& left_term, var_set_t const& right_vars)
{
return create_rt(left_term, right_vars,
k_term_base<U, V, W>::get_U(),
k_term_base<U, V, W>::get_V(),
k_term_base<U, V, W>::get_W(), false);
};
// not called for consequent terms and head terms
inline match_result
compute_match(var_set_t const& index_map)const
{
return match_result();
};
};
/////////////////////////////////////////////////////////////////////////////////////////
// class rule_head_term
//
// class used for query rules to create a root node in rule graph
// class also used by knowledge_base to create the rule graph head node
/////////////////////////////////////////////////////////////////////////////////////////
class rule_head_term: public knowledge_term
{
public:
typedef rule::internal::rule_vertex rule_vertex_type;
inline rule_head_term(knowledge_rule & krule, var_set_t const& vars):
knowledge_term(krule),
m_query_params()
{
var_set_t::const_iterator itor = vars.begin();
var_set_t::const_iterator end = vars.end();
for(;itor!=end; ++itor) if((*itor)[0] == '_') m_query_params.insert(*itor);
};
inline rule_head_term(knowledge_rule & krule):
knowledge_term(krule),
m_query_params()
{};
~rule_head_term(){};
inline bool
is_negation()const
{
return false;
};
inline void
extract_vars(var_set_t & vars)const
{};
// not called for rule head since that have they own tree in the rule_graph
inline match_result compute_match(var_set_t const& index_map)const{return match_result();};
inline rule_term_ptr_type create_rule_term(rule_term_ptr_type const& left_term, var_set_t const& right_vars)
{
rule_term_ptr_type rule_term_p = rule_term_ptr_type(new head_rule_term());
// setup the indexes - used in conjuction with query_rule_wrapper::initialize_head_row
var_set_t::const_iterator itor = m_query_params.begin();
var_set_t::const_iterator end = m_query_params.end();
for(;itor!=end; ++itor) rule_term_p->add_index(index_map_helper::right, 0, *itor);
return rule_term_p;
};
void rename_variables(var_map_t & map, int & ivar){};
inline void register_backward_chaining_rule(back_reasoner_mgr & , rule_vertex const )const
{};
inline std::string to_string()const
{
std::ostringstream sout;
sout << "[";
var_set_t::const_iterator itor = m_query_params.begin();
var_set_t::const_iterator end = m_query_params.end();
while(itor != end) {
sout << *itor;
if(++itor != end) sout << ", ";
}
sout << "]";
return sout.str();
};
private:
var_set_t m_query_params;
};
}; /* internal namespace */
}; /* rule namespace */
#endif /*KNOWLEDGE_TERM_H_*/