OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-ure / opencog / ure / forwardchainer / ForwardChainer.h

264 lines · c ref:
/*
 * ForwardChainer.h
 *
 * Copyright (C) 2014,2015 OpenCog Foundation
 *
 * Author: Misgana Bayetta <misgana.bayetta@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef _OPENCOG_FORWARDCHAINER_H_
#define _OPENCOG_FORWARDCHAINER_H_

#include <mutex>
// #include <shared_mutex>

#include "../UREConfig.h"
#include "SourceSet.h"
#include "SourceRuleSet.h"
#include "FCStat.h"

class ForwardChainerUTest;

namespace opencog
{

enum class source_selection_mode
{
	TV_FITNESS, STI, UNIFORM
};

class Rule;

// Pair of Rule and its probability estimate that it fullfils the
// objective
typedef std::pair<RulePtr, double> RuleProbabilityPair;

class ForwardChainer
{
public:
	/**
	 * Ctor.
	 *
	 * @param kb_as     Knowledge-base atomspace
	 * @param rb_as     Rule-base atomspace
	 * @param rbs       Handle pointing to rule-based system.
	 * @param source    Source to start with, if it is a pattern, or a Set,
	 *                  multiple sources are considered
	 * @param vardecl   Variable declaration of Source if pattern
	 * @param focus_set Set of atoms under focus
	 */
	ForwardChainer(AtomSpace& kb_as,
	               AtomSpace& rb_as,
	               const Handle& rbs,
	               const Handle& source,
	               const Handle& vardecl=Handle::UNDEFINED,
	               AtomSpace* trace_as=nullptr,
	               const HandleSeq& focus_set=HandleSeq());

	/**
	 * Like above, but use as rule-base atomspace, the atomspace of rbs
	 * if any, otherwise use kb_as if rbs has no atomspace.
	 */
	ForwardChainer(AtomSpace& kb_as,
	               const Handle& rbs,
	               const Handle& source,
	               const Handle& vardecl=Handle::UNDEFINED,
	               AtomSpace* trace_as=nullptr,
	               const HandleSeq& focus_set=HandleSeq());
	~ForwardChainer();

	/**
	 * URE configuration accessors
	 */
	UREConfig& get_config();
	const UREConfig& get_config() const;

	/**
	 * Perform forward chaining inference till the termination
	 * criteria have been met.
	 */
	void do_chain();

	/**
	 * run steps (single or multi threaded) until termination criteria
	 * are met.
	 */
	void do_steps_singlethread();
	void do_steps_multithread();

	/**
	 * Source rule producer implementation of do_steps.
	 */
	void do_steps_srpi();

	/**
	 * Perform a single forward chaining inference step on the given
	 * iteration.
	 */
	void do_step(int iteration);

	/**
	 * Source rule producer implementation of do_step.
	 */
	void do_step_srpi(int iteration);

	/**
	 * @return true if the termination criteria have been met.
	 */
	bool termination();

	/**
	 * Log the cause of termination
	 */
	void termination_log();

	/**
	 * @return all results in their order of inference.
	 */
	Handle get_results() const;
	HandleSet get_results_set() const;

private:
	friend class ::ForwardChainerUTest;

	void init(const Handle& source,
	          const Handle& vardecl,
	          const HandleSeq& focus_set);

	void apply_all_rules();

	void validate(const Handle& source);

	/**
	 * Expand all meta rules into mesa rules.
	 *
	 * @param msgprfx is a prefix to prepend before each log message.
	 */
	void expand_meta_rules(const std::string& msgprfx);

	/**
	 * choose next source to expand
	 *
	 * @return  A Source to expand
	 *
	 * Warning: it is not const because the source is gonna be modified
	 * by keeping track of the rules applied to it.
	 */
	SourcePtr select_source(const std::string& msgprfx);

	/**
	 * Build a source rule pair for application trial. If and only if
	 * no such pair is available, then return an invalid pair.
	 */
	SourceRule mk_source_rule(const std::string& msgprfx);

	/**
	 * Populate the source rule set with pairs
	 */
	void populate_source_rule_set(const std::string& msgprfx);

	/**
	 * Select source rule pair
	 */
	std::pair<SourceRule, TruthValuePtr>
	select_source_rule(const std::string& msgprfx);

	/**
	 * Given a source rule pair, calculate its truth value of success.
	 */
	TruthValuePtr calculate_source_rule_tv(const SourceRule& sr);

	/**
	 * Get rules that unify with the source and that are not exhausted,
	 * which include rules currently being run.
	 */
	RuleSet get_valid_rules(const Source& source);

	/**
	 * Choose an applicable rules from the rule base by selecting
	 * rules whose premise structurally matches with the source.
	 *
	 * If no rule can be chosen return invalid rule.
	 *
	 * @return  A rule that in which @param source could ground.
	 *
	 * TODO: move to ControlPolicy
	 */
	RuleProbabilityPair select_rule(const Handle& source,
	                                const std::string& msgprfx="");
	RuleProbabilityPair select_rule(Source& source,
	                                const std::string& msgprfx="");
	RuleProbabilityPair select_rule(const RuleSet&,
	                                const std::string& msgprfx="");

	/**
	 * Apply rule.
	 */
	HandleSet apply_rule(const Rule& rule);
	HandleSet apply_rule(const SourceRule& sr);

	RuleSet _rules; /* loaded rules */

	// Knowledge base atomspace
	AtomSpace& _kb_as;

	// Rule base atomspace (can be the same as _kb_as)
	AtomSpace& _rb_as;

	// The focus set is copied into this atomspace; during chaining,
	// the pattern matcher is applied only to this atomspace.  This
	// is the primary mechanism by which chaining is restricted to
	// the focus set.  This is effective, but not very efficient;
	// perhaps there is some better mechanism?
	AtomSpacePtr _focus_set_as;

	UREConfig _config;

	// Current iteration
	std::atomic<int> _iteration;

	bool _search_focus_set;

	// TODO: subdivide in smaller and shared mutexes
	mutable std::mutex _whole_mutex;
	mutable std::mutex _part_mutex;

	// TODO: use shared mutexes
	mutable std::mutex _rules_mutex;

	// Keep track of the number of threads to make sure
	std::atomic<int> _thread_count;

	// Population of sources to expand forward
	SourceSet _sources;

	FCStat _fcstat;

	// Enable alternative implementation using (source, rule) producer,
	// srpi stands for Source Rule Producer Implementation. This flag
	// is here, likely temporarily, to compare old and new way.
	const bool _srpi;

	// Set of weighted pairs (source, rule).
	SourceRuleSet _source_rule_set;
};

} // ~namespace opencog

#endif /* _OPENCOG_FORWARDCHAINER_H_ */