OpenCog Framework  Branch: master, revision 6f0b7fc776b08468cf1b74aa9db028f387b4f0c0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ForwardChainer.cc
Go to the documentation of this file.
1 /*
2  * ForwardChainer.cc
3  *
4  * Copyright (C) 2014,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 
24 #include <opencog/util/Logger.h>
30 #include "ForwardChainer.h"
31 #include "ForwardChainerCallBack.h"
32 
33 using namespace opencog;
34 
36  _as(as), _rec(_as), _rbs(rbs), _configReader(as, rbs), _fcmem(&as)
37 {
38  init();
39 }
40 
42 {
45  _fcmem.set_cur_rule(nullptr);
46 
47  // Provide a logger
48  _log = NULL;
49  setLogger(new opencog::Logger("forward_chainer.log", Logger::FINE, true));
50 }
51 
52 void ForwardChainer::setLogger(Logger* log)
53 {
54  if (_log)
55  delete _log;
56  _log = log;
57 }
58 
60 {
61  return _log;
62 }
63 
70 {
71 
73  _log->info("[ForwardChainer] No current source, step "
74  "forward chaining aborted.");
75  return;
76  }
77 
78  _log->info("[ForwardChainer] Next source %s",
79  _fcmem.get_cur_source()->toString().c_str());
80 
81  // Choose matching rules whose input matches with the source.
82  vector<Rule*> matched_rules = fcb.choose_rules(_fcmem);
83  _log->info("[ForwardChainer] Found matching rule");
84 
89  if (matched_rules.empty()) {
90  _log->info("[ForwardChainer] No matching rule found. "
91  "Setting all rules as candidates.");
92  matched_rules = _fcmem.get_rules();
93  }
94 
95  // Select a rule amongst the matching rules by tournament selection
96  map<Rule*, float> rule_weight;
97  for (Rule* r : matched_rules) {
98  rule_weight[r] = r->get_weight();
99  }
100 
101  _log->info("[ForwardChainer] Selecting a rule from the set of "
102  "candidate rules.");
103  Rule* r = _rec.tournament_select(rule_weight);
104  _fcmem.set_cur_rule(r);
105  _log->info("[ForwardChainer] Selected rule is %s", (r->get_handle())->toShortString().c_str());
106 
108 
110  _log->info("[ForwardChainer] Applying chosen rule %s",
111  (r->get_handle())->toShortString().c_str());
112  HandleSeq product = fcb.apply_rule(_fcmem);
113 
114  _log->info("PRODUCTS...");
115  for(const auto& p:product)
116  {
117  _log->info("%s ", p->toShortString().c_str() );
118  }
119 
120  _log->info("[ForwardChainer] updating premise list with the "
121  "inference made");
123 
124  _log->info("[ForwardChainer] adding inference to history");
126 }
127 
129  Handle hsource/*=Handle::UNDEFINED*/)
130 {
131  if (hsource == Handle::UNDEFINED) {
132  do_pm();
133  return;
134  }
135  // Variable fulfillment query.
136  UnorderedHandleSet var_nodes = get_outgoing_nodes(hsource,
137  { VARIABLE_NODE });
138  if (not var_nodes.empty())
139  return do_pm(hsource, var_nodes, fcb);
140 
141  HandleSeq init_sources;
142  //Accept set of initial sources wrapped by a SET_LINK
143  if(LinkCast(hsource) and hsource->getType() == SET_LINK)
144  init_sources = _as.get_outgoing(hsource);
145  else
146  init_sources.push_back(hsource);
147  _fcmem.update_potential_sources(init_sources);
148 
149  _fcmem.set_source(fcb.choose_next_source(_fcmem)); //set initial source
150  auto max_iter = _configReader.get_maximum_iterations();
151 
152  while (_iteration < max_iter /*OR other termination criteria*/) {
153  _log->info("Iteration %d", _iteration);
154 
155  do_step(fcb);
156 
158  _log->info("[ForwardChainer] setting next source");
160 
161  _iteration++;
162  }
163 
164  _log->info("[ForwardChainer] finished do_chain.");
165 }
166 
174 void ForwardChainer::do_pm(const Handle& hsource,
175  const UnorderedHandleSet& var_nodes,
177 {
178  DefaultImplicator impl(&_as);
179  impl.implicand = hsource;
180  HandleSeq vars;
181  for (auto h : var_nodes)
182  vars.push_back(h);
183  _fcmem.set_source(hsource);
184  Handle hvar_list = _as.add_link(VARIABLE_LIST, vars);
185  Handle hclause = _as.add_link(AND_LINK, hsource);
186 
187  // Run the pattern matcher, find all patterns that satisfy the
188  // the clause, with the given variables in it.
189  PatternLinkPtr sl(createPatternLink(hvar_list, hclause));
190  sl->satisfy(impl);
191 
192  // Update result
194 
195  // Delete the AND_LINK and LIST_LINK
196  _as.remove_atom(hvar_list);
197  _as.remove_atom(hclause);
198 
200  vector<Rule*> rules = fcb.choose_rules(_fcmem);
201  for (Rule* rule : rules) {
202  BindLinkPtr bl(BindLinkCast(rule->get_handle()));
203  DefaultImplicator impl(&_as);
204  impl.implicand = bl->get_implicand();
205  bl->imply(impl);
206  _fcmem.set_cur_rule(rule);
208  }
209 }
214 {
216  _log->info("Forward chaining on the rule-based system %s "
217  "declared in %s", _rbs->toString().c_str());
218  vector<Rule*> rules = _fcmem.get_rules();
219  for (Rule* rule : rules) {
220  _log->info("Applying rule %s on ", rule->get_name().c_str());
221  BindLinkPtr bl(BindLinkCast(rule->get_handle()));
222  DefaultImplicator impl(&_as);
223  impl.implicand = bl->get_implicand();
224  bl->imply(impl);
225  _fcmem.set_cur_rule(rule);
226 
227  _log->info("OUTPUTS");
228  for (auto h : impl.get_result_list())
229  _log->info("%s", h->toString().c_str());
230 
232  }
233 
234 }
235 
237 {
238  return _fcmem.get_result();
239 }
void add_rules_product(int iteration, HandleSeq product)
Definition: FCMemory.cc:99
virtual Handle choose_next_source(FCMemory &fcmem)=0
ForwardChainer(AtomSpace &as, Handle rbs)
std::vector< Handle > HandleSeq
a list of handles
Definition: Handle.h:246
Handle get_cur_source(void)
Definition: FCMemory.cc:123
#define createPatternLink
Definition: PatternLink.h:188
static BindLinkPtr BindLinkCast(const Handle &h)
Definition: BindLink.h:62
int get_maximum_iterations() const
virtual std::string toString(std::string indent="")=0
Type getType() const
Definition: Atom.h:197
Type tournament_select(map< Type, float > tfitnes_map)
Definition: URECommons.h:91
UREConfigReader _configReader
virtual std::vector< Rule * > choose_rules(FCMemory &fcmem)=0
static const Handle UNDEFINED
Definition: Handle.h:77
void set_rules(const vector< Rule * > &rules)
Definition: FCMemory.cc:51
std::shared_ptr< BindLink > BindLinkPtr
Definition: BindLink.h:61
bool remove_atom(Handle h, bool recursive=false)
Definition: AtomSpace.cc:344
void setLogger(Logger *log)
UnorderedHandleSet get_outgoing_nodes(const Handle &hinput, const std::vector< Type > &types)
Definition: AtomUtils.cc:156
const std::vector< Rule > & get_rules() const
Logger * getLogger(void)
static LinkPtr LinkCast(const Handle &h)
Definition: Link.h:263
void set_search_in_af(bool val)
Definition: FCMemory.cc:79
bool get_attention_allocation() const
void set_cur_rule(Rule *r)
Definition: FCMemory.cc:94
vector< Rule * > & get_rules()
Definition: FCMemory.cc:46
virtual HandleSeq apply_rule(FCMemory &fcmem)=0
std::shared_ptr< PatternLink > PatternLinkPtr
Definition: PatternLink.h:181
void update_potential_sources(HandleSeq input)
Definition: FCMemory.cc:38
void set_source(Handle source)
Definition: FCMemory.cc:63
std::unordered_set< Handle, handle_hash > UnorderedHandleSet
a hash that associates the handle to its unique identificator
Definition: Handle.h:250
Handle add_link(Type t, const HandleSeq &outgoing, bool async=false)
Definition: AtomSpace.cc:175
HandleSeq get_chaining_result(void)
Handle get_handle()
Definition: Rule.cc:93
virtual HandleSeq get_result_list()
Definition: Implicator.cc:72
const HandleSeq & get_outgoing(Handle h) const
Definition: AtomSpace.h:735
void do_step(ForwardChainerCallBack &fcb)
HandleSeq get_result()
Definition: FCMemory.cc:157
void do_chain(ForwardChainerCallBack &fcb, Handle hsource=Handle::UNDEFINED)