OpenCog Framework  Branch: master, revision 6f0b7fc776b08468cf1b74aa9db028f387b4f0c0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
DefaultForwardChainerCB.cc
Go to the documentation of this file.
1 /*
2  * DefaultForwardChainerCB.cc
3  *
4  * Copyright (C) 2015 Misgana Bayetta
5  *
6  * Author: Misgana Bayetta <misgana.bayetta@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Affero General Public License v3 as
10  * published by the Free Software Foundation and including the exceptions
11  * at http://opencog.org/wiki/Licenses
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Affero General Public License
19  * along with this program; if not, write to:
20  * Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
30 #include <opencog/atoms/TypeNode.h>
35 
36 #include "VarGroundingPMCB.h"
38 
39 using namespace opencog;
40 
42  source_selection_mode ts_mode
43  /*=TV_FITNESS_BASED*/) :
44  ForwardChainerCallBack(&as), _as(as), _fcpm(&as), _ts_mode(ts_mode)
45 {
46 }
47 
60 {
61  Handle source = fcmem.get_cur_source();
62  if (source == Handle::UNDEFINED)
63  throw InvalidParamException(TRACE_INFO, "Needs a valid source atom");
64 
65  rule_derivations.clear(); //clear previous mapping
66 
67  vector<Rule*> chosen_rules;
68  auto rules = fcmem.get_rules();
69 
70  for (Rule* rule : rules) {
71  HandleSeq derived_rules = {};
72 
73  HandleSeq hs = rule->get_implicand_seq();
74  for(Handle target: hs)
75  {
76  HandleSeq hs = unify(source,target,rule);
77  derived_rules.insert(derived_rules.end(),hs.begin(),hs.end());
78  }
79  //Chosen rule.
80  if (not derived_rules.empty())
81  {
82  chosen_rules.push_back(rule);
83  rule_derivations[rule->get_handle()] = derived_rules;
84  }
85  }
86 
87  return chosen_rules;
88 }
89 
103  //exceptions
104  if(not is_valid_implicant(target)) return {};
105 
106  HandleSeq derived_rules={};
107 
108  AtomSpace temp_pm_as;
109  Handle hcpy = temp_pm_as.add_atom(target);
110  Handle implicant_vardecl = temp_pm_as.add_atom(
111  gen_sub_varlist(target, rule->get_vardecl()));
112  Handle sourcecpy = temp_pm_as.add_atom(source);
113 
114  BindLinkPtr bl =
115  createBindLink(HandleSeq { implicant_vardecl, hcpy, hcpy });
116  VarGroundingPMCB gcb(&temp_pm_as);
117  gcb.implicand = bl->get_implicand();
118 
119  bl->imply(gcb);
120 
121  auto del_by_value =
122  [] (std::vector<std::map<Handle,Handle>>& vec_map,const Handle& h) {
123  for (auto& map: vec_map)
124  for(auto& it:map) { if (it.second == h) map.erase(it.first);}
125  };
126 
127  //We don't want implicant_var list to be matched as
128  //in the case of free vars in modus-ponens rules.
129  del_by_value(gcb.term_groundings, implicant_vardecl);
130  del_by_value(gcb.var_groundings, implicant_vardecl);
131 
132  FindAtoms fv(VARIABLE_NODE);
133  for (const auto& termg_map : gcb.term_groundings) {
134  for (const auto& it : termg_map) {
135  if (it.second == sourcecpy) {
136  fv.search_set(it.first);
137 
138  Handle rhandle = rule->get_handle();
139  HandleSeq new_candidate_rules = substitute_rule_part(
140  temp_pm_as, temp_pm_as.add_atom(rhandle), fv.varset,
141  gcb.var_groundings);
142 
143  for (Handle nr : new_candidate_rules) {
144  if (find(derived_rules.begin(), derived_rules.end(), nr) == derived_rules.end()) {
145  //Adding back to _as avoids UUID clashes.
146  Handle h = _as.add_atom(nr);
147  //Avoid adding original rule to derived rule list
148  if (h != rhandle)
149  derived_rules.push_back(h);
150  }
151  }
152  }
153  }
154  }
155 
156  return derived_rules;
157 }
167 {
168  HandleSeq derived_rules={};
169  HandleSeq impl_members = rule->get_implicant_seq();
170 
171  UnorderedHandleSet output_expanded;
172  for (Handle h : impl_members) {
174  hs.erase(h); //Already tried to unify this.
175  output_expanded.insert(hs.begin(), hs.end());
176  }
177 
178  for (Handle h : output_expanded) {
179  HandleSeq result = unify(source, h, rule);
180  derived_rules.insert(derived_rules.end(), result.begin(), result.end());
181  }
182 
183  return derived_rules;
184 }
185 
187 {
188  HandleSeq inputs;
189  URECommons urec(_as);
190  Handle hsource = fcmem.get_cur_source();
191 
192  // Get everything associated with the source handle.
193  UnorderedHandleSet neighbors = get_distant_neighbors(hsource, 2);
194 
195  // Add all root links of atoms in @param neighbors.
196  for (auto hn : neighbors) {
197  if (hn->getType() != VARIABLE_NODE) {
198  HandleSeq roots;
199  urec.get_root_links(hn, roots);
200  for (auto r : roots) {
201  if (find(inputs.begin(), inputs.end(), r) == inputs.end() and r->getType()
202  != BIND_LINK)
203  inputs.push_back(r);
204  }
205  }
206  }
207 
208  return inputs;
209 }
210 
212 {
213  HandleSeq tlist = fcmem.get_potential_sources();
214  map<Handle, float> tournament_elem;
215  URECommons urec(_as);
216  Handle hchosen = Handle::UNDEFINED;
217 
218  for (Handle t : tlist) {
219  switch (_ts_mode) {
220  case TV_FITNESS_BASED: {
221  float fitness = urec.tv_fitness(t);
222  tournament_elem[t] = fitness;
223  }
224  break;
225  case STI_BASED:
226  tournament_elem[t] = t->getSTI();
227  break;
228  default:
229  throw RuntimeException(TRACE_INFO,
230  "Unknown source selection mode.");
231  break;
232  }
233  }
234 
238  for (size_t i = 0; i < tournament_elem.size(); i++) {
239  Handle hselected = urec.tournament_select(tournament_elem);
240  if (fcmem.isin_selected_sources(hselected)) {
241  continue;
242  } else {
243  hchosen = hselected;
244  break;
245  }
246  }
247 
248  // Incase of when all sources are selected
249  if (hchosen == Handle::UNDEFINED)
250  return urec.tournament_select(tournament_elem);
251 
252  return hchosen;
253 }
254 
256 {
257  _fcpm.set_fcmem(&fcmem);
258 
259  auto rule_handle = fcmem.get_cur_rule()->get_handle();
260  BindLinkPtr bl(BindLinkCast(rule_handle));
261  if (NULL == bl) {
262  bl = createBindLink(*LinkCast(rule_handle));
263  }
264  _fcpm.implicand = bl->get_implicand();
265  bl->imply(_fcpm);
266  // bl->satisfy(*_fcpm);
267 
268  HandleSeq product = _fcpm.get_products();
269 
271  for (auto iter = product.begin(); iter != product.end();) {
272  if (fcmem.isin_potential_sources(*iter))
273  iter = product.erase(iter);
274  else
275  ++iter;
276  }
277 
278  return product;
279 }
280 
282  const Handle& parent_varlist)
283 {
284  FindAtoms fv(VARIABLE_NODE);
285  fv.search_set(parent);
286 
287  HandleSeq oset;
288  if (LinkCast(parent_varlist))
289  oset = LinkCast(parent_varlist)->getOutgoingSet();
290  else
291  oset.push_back(parent_varlist);
292 
293  HandleSeq final_oset;
294 
295  // for each var in varlist, check if it is used in parent
296  for (const Handle& h : oset) {
297  Type t = h->getType();
298 
299  if (VARIABLE_NODE == t && fv.varset.count(h) == 1)
300  final_oset.push_back(h);
301  else if (TYPED_VARIABLE_LINK == t
302  and fv.varset.count(LinkCast(h)->getOutgoingSet()[0]) == 1)
303  final_oset.push_back(h);
304  }
305 
306  return Handle(createVariableList(final_oset));
307 }
308 
321  AtomSpace& as, Handle hrule,const std::set<Handle>& vars,
322  const std::vector<std::map<Handle, Handle>>& var_groundings)
323 {
324  std::vector<std::map<Handle, Handle>> filtered_vgmap_list;
325 
326  //Filter out variables not listed in vars from var-groundings
327  for (const auto& varg_map : var_groundings) {
328  std::map<Handle, Handle> filtered;
329 
330  for (const auto& iv : varg_map){
331  if (find(vars.begin(), vars.end(), iv.first) != vars.end()){
332  filtered[iv.first] = iv.second;
333  }
334  }
335 
336  filtered_vgmap_list.push_back(filtered);
337  }
338 
339  HandleSeq derived_rules;
340  BindLinkPtr blptr = BindLinkCast(hrule);
341  Substitutor st(&as);
342 
343  for (auto& vgmap : filtered_vgmap_list) {
344  Handle himplicand = st.substitute(blptr->get_implicand(), vgmap);
345  //Create the BindLink/Rule by substituting vars with groundings
346  if (contains_atomtype(himplicand, VARIABLE_NODE)) {
347  Handle himplicant = st.substitute(blptr->get_body(), vgmap);
348 
349  //Assuming himplicant's set of variables are superset for himplicand's,
350  //generate varlist from himplicant.
351  Handle hvarlist = gen_sub_varlist(
352  himplicant, LinkCast(hrule)->getOutgoingSet()[0]);
353  Handle hderived_rule = Handle(LinkCast(createBindLink(HandleSeq {
354  hvarlist, himplicant, himplicand })));
355  derived_rules.push_back(hderived_rule);
356  }
357  else{
358  //TODO Execute if executable and push to FC results
359  }
360  }
361 
362  return derived_rules;
363 }
364 
373 {
374  if (h->getType() == ABSENT_LINK)
375  return false;
376 
377  FindAtoms fv(VARIABLE_NODE);
378  fv.search_set(h);
379 
380  if (fv.varset.empty())
381  return false;
382 
383  return true;
384 }
static bool contains_atomtype(const Handle &clause, Type atom_type)
Definition: FindUtils.h:329
HandleSeq get_potential_sources(void)
Definition: FCMemory.cc:74
std::set< Handle > varset
Definition: FindUtils.h:88
HandleSeq get_implicant_seq()
Definition: Rule.cc:128
void set_fcmem(FCMemory *fcmem)
std::vector< Handle > HandleSeq
a list of handles
Definition: Handle.h:246
DefaultForwardChainerCB(AtomSpace &as, source_selection_mode ts_mode=TV_FITNESS_BASED)
Handle get_vardecl()
Definition: Rule.cc:103
Handle get_cur_source(void)
Definition: FCMemory.cc:123
virtual HandleSeq choose_premises(FCMemory &fcmem)
static BindLinkPtr BindLinkCast(const Handle &h)
Definition: BindLink.h:62
HandleSeq unify(Handle source, Handle target, Rule *rule)
Type getType() const
Definition: Atom.h:197
Type tournament_select(map< Type, float > tfitnes_map)
Definition: URECommons.h:91
UnorderedHandleSet get_distant_neighbors(const Handle &h, int dist)
Definition: AtomUtils.cc:216
HandleSeq subatom_unify(Handle source, Rule *rule)
static const Handle UNDEFINED
Definition: Handle.h:77
bool isin_potential_sources(Handle h)
Definition: FCMemory.cc:133
#define createVariableList
Definition: VariableList.h:101
bool isin_selected_sources(Handle h)
Definition: FCMemory.cc:128
std::shared_ptr< BindLink > BindLinkPtr
Definition: BindLink.h:61
Handle substitute(const Handle &expr, const std::map< Handle, Handle > &vars)
Definition: Substitutor.h:83
static LinkPtr LinkCast(const Handle &h)
Definition: Link.h:263
virtual Handle choose_next_source(FCMemory &fcmem)
Handle gen_sub_varlist(const Handle &parent, const Handle &parent_varlist)
HandleSeq substitute_rule_part(AtomSpace &as, Handle hrule, const std::set< Handle > &vars, const std::vector< std::map< Handle, Handle >> &var_groundings)
vector< Rule * > & get_rules()
Definition: FCMemory.cc:46
UnorderedHandleSet get_all_unique_atoms(Handle h)
Definition: AtomUtils.cc:113
void get_root_links(Handle h, HandleSeq &parents)
Definition: URECommons.cc:134
Rule * get_cur_rule()
Definition: FCMemory.cc:89
virtual vector< Rule * > choose_rules(FCMemory &fcmem)
unsigned short Type
type of Atoms, represented as short integer (16 bits)
Definition: types.h:40
std::unordered_set< Handle, handle_hash > UnorderedHandleSet
a hash that associates the handle to its unique identificator
Definition: Handle.h:250
float tv_fitness(Handle h)
Definition: URECommons.cc:151
std::map< Handle, std::vector< Handle > > rule_derivations
#define createBindLink
Definition: BindLink.h:68
virtual HandleSeq apply_rule(FCMemory &fcmem)
void search_set(const Handle &h)
Definition: FindUtils.h:128
Handle get_handle()
Definition: Rule.cc:93
Handle add_atom(AtomPtr atom, bool async=false)
Definition: AtomSpace.cc:100