<commit_before>/*
 * DefaultForwardChainerCB.cc
 *
 * Copyright (C) 2015 <NAME>
 *
 * Author: <NAME> <<EMAIL>>
 *
 * 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.
 */

#include <opencog/atomutils/AtomUtils.h>
#include <opencog/atomutils/FindUtils.h>
#include <opencog/atomutils/Substitutor.h>
#include <opencog/atoms/bind/PatternUtils.h>
#include <opencog/atoms/bind/PatternLink.h>
#include <opencog/atoms/bind/BindLink.h>
#include <opencog/atoms/TypeNode.h>
#include <opencog/query/DefaultImplicator.h>
#include <opencog/query/PatternMatch.cc>
#include <opencog/guile/SchemeSmob.h>
#include <opencog/rule-engine/URECommons.h>

#include "DefaultForwardChainerCB.h"

using namespace opencog;

DefaultForwardChainerCB::DefaultForwardChainerCB(AtomSpace& as,
                                                 source_selection_mode ts_mode
                                                 /*=TV_FITNESS_BASED*/) :
        ForwardChainerCallBack(&as), _as(as), _fcpm(&as), _ts_mode(ts_mode)
{
}

/**
 * Choose rules based on premises of rule matching the source.
 * Uses temporary atomspace to limit the search space. It adds
 * each members of the implicant(members being identified by
 * checking if they are wrapped in Logical links or not) and
 * the source to a temporary atomspace and creates a bindLink
 * for each implicants to match against the source;If they match,
 * the rule in which the implicant was a member is considered as
 *  a valid match and is  added to the return list.
 *
 * @param fcmem forward chainer's working memory
 * @return a vector of chosen rules
 */
vector<Rule*> DefaultForwardChainerCB::choose_rules(FCMemory& fcmem)
{
    new_rules.clear(); //empty vector before starting matching
    Handle source = fcmem.get_cur_source();
    if (source == Handle::UNDEFINED)
        throw InvalidParamException(TRACE_INFO, "Needs a valid source atom");

    vector<Rule*> chosen_rules;
    auto rules = fcmem.get_rules();
    vector<Rule*> visited;
    for (Rule* rule : rules) {
        HandleSeq impl_members = rule->get_implicant_seq();
        bool match = false;
        for (Handle h : impl_members) {
            //exceptions
            if (h->getType() == ABSENT_LINK)
                continue;

            AtomSpace temp_pm_as;
            Handle hcpy = temp_pm_as.add_atom(h);
            Handle implicant_vardecl = temp_pm_as.add_atom(
                    gen_sub_varlist(h, rule->get_vardecl()));
            Handle sourcecpy = temp_pm_as.add_atom(source);

            BindLinkPtr bl = createBindLink(HandleSeq { implicant_vardecl, hcpy,
                                                        hcpy });
            DefaultImplicator imp(&temp_pm_as);
            imp.implicand = bl->get_implicand();
            PMCGroundings gcb(imp);
            bl->imply(gcb);

            FindAtoms fv(VARIABLE_NODE);
            for (const auto& termg_map : gcb._term_groundings) {
                for (const auto& it : termg_map) {
                    if (it.second == sourcecpy) {
                        match = true;
                        fv.search_set(it.first);

                        HandleSeq new_rules = substitute_rule_part(
                                temp_pm_as,
                                temp_pm_as.add_atom(rule->get_handle()),
                                fv.varset, gcb._var_groundings);
                        for (const auto& nr : new_rules)
                            if (find(new_rules.begin(), new_rules.end(),
                                     nr)
                                == new_rules.end())
                                new_rules.push_back(nr);
                    }
                }
            }
        }

        if (match) {
            auto it = find(chosen_rules.begin(), chosen_rules.end(), rule);
            if (it == chosen_rules.end())
                chosen_rules.push_back(rule);
        }
    }

    return chosen_rules;
}
<commit_msg>Make use of VarGroundingPMCB class<commit_after>/*
 * DefaultForwardChainerCB.cc
 *
 * Copyright (C) 2015 <NAME>
 *
 * Author: <NAME> <<EMAIL>>
 *
 * 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.
 */

#include <opencog/atomutils/AtomUtils.h>
#include <opencog/atomutils/FindUtils.h>
#include <opencog/atomutils/Substitutor.h>
#include <opencog/atoms/bind/PatternUtils.h>
#include <opencog/atoms/bind/PatternLink.h>
#include <opencog/atoms/bind/BindLink.h>
#include <opencog/atoms/TypeNode.h>
#include <opencog/query/DefaultImplicator.h>
#include <opencog/query/PatternMatch.cc>
#include <opencog/guile/SchemeSmob.h>
#include <opencog/rule-engine/URECommons.h>

#include "VarGroundingPMCB.h"
#include "DefaultForwardChainerCB.h"

using namespace opencog;

DefaultForwardChainerCB::DefaultForwardChainerCB(AtomSpace& as,
                                                 source_selection_mode ts_mode
                                                 /*=TV_FITNESS_BASED*/) :
        ForwardChainerCallBack(&as), _as(as), _fcpm(&as), _ts_mode(ts_mode)
{
}

/**
 * Choose rules based on premises of rule matching the source.
 * Uses temporary atomspace to limit the search space. It adds
 * each members of the implicant(members being identified by
 * checking if they are wrapped in Logical links or not) and
 * the source to a temporary atomspace and creates a bindLink
 * for each implicants to match against the source;If they match,
 * the rule in which the implicant was a member is considered as
 *  a valid match and is  added to the return list.
 *
 * @param fcmem forward chainer's working memory
 * @return a vector of chosen rules
 */
vector<Rule*> DefaultForwardChainerCB::choose_rules(FCMemory& fcmem)
{
    new_rules.clear(); //empty vector before starting matching
    Handle source = fcmem.get_cur_source();
    if (source == Handle::UNDEFINED)
        throw InvalidParamException(TRACE_INFO, "Needs a valid source atom");

    vector<Rule*> chosen_rules;
    auto rules = fcmem.get_rules();
    vector<Rule*> visited;
    for (Rule* rule : rules) {
        HandleSeq impl_members = rule->get_implicant_seq();
        bool match = false;
        for (Handle h : impl_members) {
            //exceptions
            if (h->getType() == ABSENT_LINK)
                continue;

            AtomSpace temp_pm_as;
            Handle hcpy = temp_pm_as.add_atom(h);
            Handle implicant_vardecl = temp_pm_as.add_atom(
                    gen_sub_varlist(h, rule->get_vardecl()));
            Handle sourcecpy = temp_pm_as.add_atom(source);

            BindLinkPtr bl = createBindLink(HandleSeq { implicant_vardecl,
                                                         hcpy,hcpy });
            VarGroundingPMCB gcb(&temp_pm_as);
            gcb.implicand = bl->get_implicand();
            bl->imply(gcb);

            FindAtoms fv(VARIABLE_NODE);
            for (const auto& termg_map : gcb.term_groundings) {
                for (const auto& it : termg_map) {
                    if (it.second == sourcecpy) {
                        match = true;
                        fv.search_set(it.first);

                        HandleSeq new_rules = substitute_rule_part(
                                temp_pm_as,
                                temp_pm_as.add_atom(rule->get_handle()),
                                fv.varset, gcb.var_groundings);
                        for (const auto& nr : new_rules)
                            if (find(new_rules.begin(), new_rules.end(),
                                     nr) == new_rules.end())
                                new_rules.push_back(nr);
                    }
                }
            }
        }

        if (match) {
            auto it = find(chosen_rules.begin(), chosen_rules.end(), rule);
            if (it == chosen_rules.end())
                chosen_rules.push_back(rule);
        }
    }

    return chosen_rules;
}

{'fraction_non_alphanumeric': 0.09038503371764194, 'fraction_numerical': 0.003480530780944094, 'mean_word_length': 2.1597938144329896, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7588430', 'n_tokens_mistral': 2672, 'n_tokens_neox': 2571, 'n_words': 741}