opencog/ure

Backward chainer takes super long in this case

alexander-gabriel opened this issue · 3 comments

The Backward Chainer takes over 4 seconds in this scenarios with only 10 waypoints. This time increases only marginally with 100 or 200 waypoints.

To run this, you need to create a 9-fold fuzzy and in the pln/opencog/pln/rules/propositional/fuzzy-conjunction-introduction.scm file and adjust the path to the file in the script.

#!/usr/bin/env python
import time

from opencog.type_constructors import *
from opencog.bindlink import execute_atom, evaluate_atom
from opencog.ure import BackwardChainer, ForwardChainer
from opencog.utilities import initialize_opencog
from opencog.atomspace import AtomSpace, types, TruthValue, create_child_atomspace
from opencog.logger import create_logger, Logger,log
from opencog.scheme_wrapper import scheme_eval

TRUE = TruthValue(1.0, 1.0)

def identical_formula(A, B):
    # rospy.loginfo("identical_formula({},{})".format(A,B))
    link = IdenticalLink(A,B)
    # out = A.get_out()
    if A == B:
        link.tv = TruthValue(1, 1)
    else:
        link.tv = TruthValue(0, 1)
    return link


def build_deduction_rulebase():
    rbs = ConceptNode("deduction-rule-base")
    execute_code = \
    '''
    (use-modules (opencog))
    (use-modules (opencog logger) (opencog ure) (opencog exec))
    (load-from-path "/home/rasberry/git/pln/opencog/pln/rules/propositional/fuzzy-conjunction-introduction.scm")
    (define rbs (Concept "deduction-rule-base"))
    (ure-set-complexity-penalty rbs 0.1)
    '''
    scheme_eval(atomspace, execute_code)

    MemberLink(DefinedSchemaNode("fuzzy-conjunction-introduction-9ary-rule"), rbs)

    return rbs


def print_results(query,results):
    print("Query:\n{:}\n\nResults:\n{:}\n\nDetails:\n--------".format(query, results))
    if query.type_name == "GetLink":
        for setlink in results.get_out():
            for result in setlink.get_out():
                print("Result Truth: {:}".format(result.tv))
                print("Result:\n{:}".format(result))
                print("------------------------\n")
    elif query.type_name == "AndLink":
        for result in results.get_out():
            print("Result Truth: {:}".format(result.tv))
            print("Result:\n{:}".format(result))
            for condition in result.get_out():
                print("------------------------")
                print("Condition:{:}".format(condition))
                print("Condition Truth: {:}".format(condition.tv))
                if condition.type_name == "NotLink":
                    subcondition = condition.get_out()[0]
                    print("    Subcondition: {:}".format(subcondition))
                    print("    Subcondition Truth: {:}".format(subcondition.tv))
            print("-----------------------------------------------------")
    else:
        for result in results.get_out():
            print("Result Truth: {:}".format(result.tv))
            print("Result:\n{:}".format(result))
            print("------------------------\n")


if __name__ == '__main__':
    atomspace = AtomSpace()

    initialize_opencog(atomspace)
    rbs = build_deduction_rulebase()



    for index in range(1,10,1):
        odd = "wp_{:d}".format(index)
        even = "wp_{:d}".format(index+1)
        o = ConceptNode(odd).truth_value(1.0, 1.0)
        e = ConceptNode(even).truth_value(1.0, 1.0)
        # print("creating link {}<->{}".format(o,e))
        EvaluationLink(PredicateNode("leads_to"), ListLink(o, e)).truth_value(1.0, 1.0)
        EvaluationLink(PredicateNode("leads_to"), ListLink(e, o)).truth_value(1.0, 1.0)

    wp5 = ConceptNode("wp_5")
    wp6 = ConceptNode("wp_6")

    true = ConceptNode("true").truth_value(1.0, 1.0)
    false = ConceptNode("false").truth_value(1.0, 1.0)
    seen_picking = ConceptNode("seen_picking").truth_value(1.0, 1.0)
    called_robot = ConceptNode("called_robot").truth_value(1.0, 1.0)
    approaching = ConceptNode("approaching").truth_value(1.0, 1.0)
    movement = ConceptNode("movement").truth_value(1.0, 1.0)

    human = ConceptNode("human").truth_value(1.0, 1.0)
    alice = ConceptNode("alice").truth_value(1.0, 1.0)
    InheritanceLink(alice, human).truth_value(1.0, 1.0)
    StateLink(alice, wp5).truth_value(1.0, 1.0)
    StateLink(ListLink(alice, seen_picking), false).truth_value(1.0, 1.0)
    StateLink(ListLink(alice, called_robot), false).truth_value(1.0, 1.0)
    StateLink(ListLink(alice, movement), approaching)

    robot = ConceptNode("bob").truth_value(1.0, 1.0)
    StateLink(robot, wp6).truth_value(1.0, 1.0)

    variables = VariableList(
        TypedVariableLink(VariableNode("person"), TypeNode("ConceptNode")),
        TypedVariableLink(VariableNode("person_location"), TypeNode("ConceptNode")),
        TypedVariableLink(VariableNode("origin"), TypeNode("ConceptNode")),
        TypedVariableLink(VariableNode("destination"), TypeNode("ConceptNode")),
        TypedVariableLink(VariableNode("nobody"), TypeNode("ConceptNode"))
        )

    query =     AndLink(
                    InheritanceLink(VariableNode("person"), human),
                    StateLink(VariableNode("person"), VariableNode("person_location")),
                    StateLink(ListLink(VariableNode("person"), movement), approaching),
                    StateLink(robot, VariableNode("origin")),
                    StateLink(ListLink(VariableNode("person"), seen_picking), false),
                    StateLink(ListLink(VariableNode("person"), called_robot), false),
                    EvaluationLink(
                        PredicateNode("leads_to"),
                        ListLink(VariableNode("person_location"), VariableNode("origin"))
                    ),
                    EvaluationLink(
                        PredicateNode("leads_to"),
                        ListLink(VariableNode("origin"), VariableNode("destination"))
                    ),
                    AbsentLink(
                            StateLink(VariableNode("nobody"), VariableNode("destination"))
                    )
                )

    start_time = time.time()
    # query = GetLink(variables, query)
    chainer = BackwardChainer(_as=atomspace,
                      rbs=rbs, trace_as=None, control_as=None, focus_set=None,
                      target=query, vardecl=variables)
    chainer.do_chain()
    print("The BackwardChainer took {:.2f}\n--------------".format(time.time()-start_time))
    results = chainer.get_results()
    print_results(query, results)

To make this more clear: there is only one rule involved which has to be applied only once. And there are only 21 concepts and about 30 links

@alexander-gabriel, I think the problem is with unification that tries all permutations since And is unordered.

Sidenote: you no longer need to generate multiple rules for multiple arities since Glob is now supported by the URE. I (or someone else) need(s) to update these rules...

If you could attach the log file (with debug or fine level) that would be helpful.

I'm closing, would rather have a simpler more narrowed issue for this problem.