예제 #1
0
class Engine(object):
    def __init__(self, load_system=False):
        self.operations = None
        self.modulewrapper = ModuleWrapper(self)
        if load_system:
            self.modulewrapper.init_system_module()
        
        from prolog.builtin.statistics import Clocks
        self.clocks = Clocks()
        self.clocks.startup()
        self.streamwrapper = StreamWrapper()

    def _freeze_(self):
        return True

    # _____________________________________________________
    # database functionality

    def add_rule(self, ruleterm, end=True):
        module = self.modulewrapper.current_module
        rule = self.make_rule(ruleterm, module)

        signature = rule.signature
        if self.get_builtin(signature):
            error.throw_permission_error(
                "modify", "static_procedure", rule.head.get_prolog_signature())

        function = module.lookup(signature)
        function.add_rule(rule, end)
        return rule

    def make_rule(self, ruleterm, module):
        if helper.is_term(ruleterm):
            assert isinstance(ruleterm, Callable)
            if ruleterm.signature().eq(predsig):
                return Rule(ruleterm.argument_at(0), ruleterm.argument_at(1), module)
            else:
                return Rule(ruleterm, None, module)
        elif isinstance(ruleterm, Atom):
            return Rule(ruleterm, None, module)
        else:
            error.throw_type_error("callable", ruleterm)

    @jit.elidable_promote('all')
    def get_builtin(self, signature):
        from prolog import builtin # for the side-effects
        return signature.get_extra("builtin")


    # _____________________________________________________
    # parsing-related functionality

    def _build_and_run(self, tree, source_string, file_name):
        assert self is not None # for the annotator (!)
        from prolog.interpreter.parsing import TermBuilder
        builder = TermBuilder()
        term = builder.build_query(tree)
        if isinstance(term, Callable) and term.signature().eq(callsig):
            self.run_query_in_current(term.argument_at(0))
        else:
            term = self._term_expand(term)
            rule = self.add_rule(term)
            rule.file_name = file_name
            rule._init_source_info(tree, source_string)

    def _term_expand(self, term):
        if self.modulewrapper.system is not None:
            v = BindingVar()
            call = Callable.build("term_expand", [term, v])
            try:
                self.run_query_in_current(call)
            except error.UnificationFailed:
                v = BindingVar()
                call = Callable.build("term_expand", [term, v])
                self.run_query(call, self.modulewrapper.system)
            term = v.dereference(None)
        return term

    def runstring(self, s, file_name=None):
        from prolog.interpreter.parsing import parse_file
        parse_file(s, None, Engine._build_and_run, self, file_name=file_name)

    def parse(self, s, file_name=None):
        from prolog.interpreter.parsing import parse_file, TermBuilder
        builder = TermBuilder()
        trees = parse_file(s, None, file_name=file_name)
        terms = builder.build_many(trees)
        return terms, builder.varname_to_var

    def getoperations(self):
        from prolog.interpreter.parsing import default_operations
        if self.operations is None:
            return default_operations
        return self.operations

    # _____________________________________________________
    # Prolog execution

    def run_query(self, query, module, continuation=None):
        assert isinstance(module, Module)
        rule = module._toplevel_rule
        fcont = DoneFailureContinuation(self)
        if continuation is None:
            continuation = CutScopeNotifier(self, DoneSuccessContinuation(self), fcont)
        continuation = BodyContinuation(self, rule, continuation, query)
        return driver(continuation, fcont, Heap())

    def run_query_in_current(self, query, continuation=None):
        module = self.modulewrapper.current_module
        return self.run_query(query, module, continuation)

    def call(self, query, rule, scont, fcont, heap):
        if isinstance(query, Var):
            query = query.dereference(heap)
        if not isinstance(query, Callable):
            if isinstance(query, Var):
                raise error.throw_instantiation_error()
            raise error.throw_type_error('callable', query)
        signature = query.signature()        
        builtin = self.get_builtin(signature)
        if builtin is not None:
            return BuiltinContinuation(self, rule, scont, builtin, query), fcont, heap

        # do a real call
        module = rule.module
        function = self._get_function(signature, module, query)
        query = function.add_meta_prefixes(query, module.nameatom)
        startrulechain = jit.hint(function.rulechain, promote=True)
        rulechain = startrulechain.find_applicable_rule(query)
        if rulechain is None:
            raise error.UnificationFailed
        scont, fcont, heap = _make_rule_conts(self, scont, fcont, heap, query, rulechain)
        return scont, fcont, heap

    def call_in_module(self, query, module, scont, fcont, heap):
        return self.call(query, module._toplevel_rule, scont, fcont, heap)

    def _get_function(self, signature, module, query): 
        function = module.lookup(signature)
        if function.rulechain is None and self.modulewrapper.system is not None:
            function = self.modulewrapper.system.lookup(signature)
        if function.rulechain is None:
            return error.throw_existence_error(
                    "procedure", query.get_prolog_signature())
        return function

    # _____________________________________________________
    # module handling

    def switch_module(self, modulename):
        m = self.modulewrapper
        try:
            m.current_module = m.modules[modulename]
        except KeyError:
            module = Module(modulename)
            m.modules[modulename] = module
            m.current_module = module

    # _____________________________________________________
    # error handling

    @jit.unroll_safe
    def throw(self, exc, scont, fcont, heap, rule_likely_source=None):
        from prolog.interpreter import memo
        exc_term = exc.term
        # copy to make sure that variables in the exception that are
        # backtracked by the revert_upto below have the right value.
        exc_term = exc.term.copy(heap, memo.CopyMemo())
        orig_scont = scont
        while not scont.is_done():
            if not isinstance(scont, CatchingDelimiter):
                scont = scont.nextcont
                continue
            discard_heap = scont.heap
            heap = heap.revert_upto(discard_heap)
            try:
                scont.catcher.unify(exc_term, heap)
            except error.UnificationFailed:
                scont = scont.nextcont
            else:
                return self.call(
                    scont.recover, scont.rule, scont.nextcont, scont.fcont, heap)
        raise error.UncaughtError(exc_term, exc.sig_context, rule_likely_source, orig_scont)



    def __freeze__(self):
        return True
예제 #2
0
class Engine(object):
    def __init__(self,
                 load_system=False,
                 similarity=None,
                 max_depth=3,
                 lambda_cut=0.1):
        self.similarity = similarity or Similarity(lambda_cut)
        self.operations = None
        self.modulewrapper = ModuleWrapper(self)
        self.max_depth = max_depth
        if load_system:
            self.modulewrapper.init_system_module()

        from prolog.builtin.statistics import Clocks
        self.clocks = Clocks()
        self.clocks.startup()
        self.streamwrapper = StreamWrapper()

    def _freeze_(self):
        return True

    # _____________________________________________________
    # database functionality

    def add_rule(self, ruleterm, end=True):
        module = self.modulewrapper.current_module
        rule = self.make_rule(ruleterm, module)

        signature = rule.signature
        if self.get_builtin(signature):
            error.throw_permission_error("modify", "static_procedure",
                                         rule.head.get_prolog_signature())

        function = module.lookup(signature)
        function.add_rule(rule, end)
        return rule

    def make_rule(self, ruleterm, module):
        if helper.is_term(ruleterm):
            assert isinstance(ruleterm, Callable)
            if ruleterm.signature().eq(predsig):
                return Rule(ruleterm.argument_at(0), ruleterm.argument_at(1),
                            module)
            else:
                return Rule(ruleterm, None, module)
        elif isinstance(ruleterm, Atom):
            return Rule(ruleterm, None, module)
        else:
            error.throw_type_error("callable", ruleterm)

    @jit.elidable_promote('all')
    def get_builtin(self, signature):
        from prolog import builtin  # for the side-effects
        return signature.get_extra("builtin")

    # _____________________________________________________
    # parsing-related functionality

    def _build_and_run(self, tree, source_string, file_name, similarity=None):
        assert self is not None  # for the annotator (!)
        from prolog.interpreter.parsing import TermBuilder
        builder = TermBuilder()
        term = builder.build_query(tree)
        if isinstance(term, Callable) and term.signature().eq(callsig):
            self.run_query_in_current(term.argument_at(0))
        else:
            term = self._term_expand(term)
            rule = self.add_rule(term)
            if similarity is not None:
                rule.scores = similarity.get_initial_rule_scores(term)
            rule.file_name = file_name
            rule._init_source_info(tree, source_string)

    def _term_expand(self, term):
        if self.modulewrapper.system is not None:
            v = BindingVar()
            call = Callable.build("term_expand", [term, v])
            try:
                self.run_query_in_current(call)
            except error.UnificationFailed:
                v = BindingVar()
                call = Callable.build("term_expand", [term, v])
                self.run_query(call, self.modulewrapper.system)
            term = v.dereference(None)
        return term

    def runstring(self, s, file_name=None, similarity=None):
        from prolog.interpreter.parsing import parse_file
        parse_file(s,
                   None,
                   Engine._build_and_run,
                   self,
                   file_name=file_name,
                   similarity=similarity)

    def parse(self, s, file_name=None):
        from prolog.interpreter.parsing import parse_file, TermBuilder
        builder = TermBuilder()
        trees = parse_file(s, None, file_name=file_name)
        terms = builder.build_many(trees)
        return terms, builder.varname_to_var

    def getoperations(self):
        from prolog.interpreter.parsing import default_operations
        if self.operations is None:
            return default_operations
        return self.operations

    # _____________________________________________________
    # Prolog execution

    def run_query(self, query, module, continuation=None):
        assert isinstance(module, Module)
        rule = module._toplevel_rule
        fcont = DoneFailureContinuation(self)
        if continuation is None:
            continuation = CutScopeNotifier(self,
                                            DoneSuccessContinuation(self),
                                            fcont)
        continuation = BodyContinuation(self, rule, continuation, query)
        return driver(continuation, fcont, Heap())

    def run_query_in_current(self, query, continuation=None):
        module = self.modulewrapper.current_module
        return self.run_query(query, module, continuation)

    def call(self, query, rule, scont, fcont, heap):
        if isinstance(query, Var):
            query = query.dereference(heap)
        if not isinstance(query, Callable):
            if isinstance(query, Var):
                raise error.throw_instantiation_error()
            raise error.throw_type_error('callable', query)
        signature = query.signature()
        builtin = self.get_builtin(signature)
        if builtin is not None:
            return BuiltinContinuation(self, rule, scont, builtin,
                                       query), fcont, heap

        # do a real call
        module = rule.module
        function = self._get_function(signature, module, query)
        query = function.add_meta_prefixes(query, module.nameatom)
        startrulechain = jit.hint(function.rulechain, promote=True)
        rulechain = startrulechain.find_applicable_rule(
            query, heap, self.similarity)
        if rulechain is None:
            raise error.UnificationFailed
        if heap.depth > self.max_depth:
            raise error.UnificationFailed

        scont, fcont, heap = _make_rule_conts(self, scont, fcont, heap, query,
                                              rulechain)
        return scont, fcont, heap

    def call_in_module(self, query, module, scont, fcont, heap):
        return self.call(query, module._toplevel_rule, scont, fcont, heap)

    def _get_function(self, signature, module, query):
        function = module.lookup(signature)
        if function.rulechain is None and self.modulewrapper.system is not None:
            function = self.modulewrapper.system.lookup(signature)
        if function.rulechain is None:
            raise error.UnificationFailed
            # TODO Is this okay?
            # return error.throw_existence_error(
            #         "procedure", query.get_prolog_signature())
        return function

    # _____________________________________________________
    # module handling

    def switch_module(self, modulename):
        m = self.modulewrapper
        try:
            m.current_module = m.modules[modulename]
        except KeyError:
            module = Module(modulename)
            m.modules[modulename] = module
            m.current_module = module

    # _____________________________________________________
    # error handling

    @jit.unroll_safe
    def throw(self, exc, scont, fcont, heap, rule_likely_source=None):
        from prolog.interpreter import memo
        exc_term = exc.term
        # copy to make sure that variables in the exception that are
        # backtracked by the revert_upto below have the right value.
        exc_term = exc.term.copy(heap, memo.CopyMemo())
        orig_scont = scont
        while not scont.is_done():
            if not isinstance(scont, CatchingDelimiter):
                scont = scont.nextcont
                continue
            discard_heap = scont.heap
            heap = heap.revert_upto(discard_heap)
            try:
                scont.catcher.unify(exc_term, heap)
            except error.UnificationFailed:
                scont = scont.nextcont
            else:
                return self.call(scont.recover, scont.rule, scont.nextcont,
                                 scont.fcont, heap)
        raise error.UncaughtError(exc_term, exc.sig_context,
                                  rule_likely_source, orig_scont)

    def __freeze__(self):
        return True
예제 #3
0
class Engine(object):
    def __init__(self,
                 load_system=False,
                 similarity=None,
                 max_depth=20,
                 lambda_cut=0.1,
                 embeddings=None,
                 rule2index=None,
                 maxk=3):
        self.similarity = similarity or Similarity(lambda_cut)
        self.operations = None
        self.modulewrapper = ModuleWrapper(self)
        self.max_depth = max_depth
        if load_system:
            self.modulewrapper.init_system_module()

        from prolog.builtin.statistics import Clocks
        self.clocks = Clocks()
        self.clocks.startup()
        self.streamwrapper = StreamWrapper()
        self.embeddings = embeddings
        self.rule2index = rule2index
        self.maxk = maxk
        self.index2rule = {}

    def _freeze_(self):
        return True

    # _____________________________________________________
    # database functionality

    def add_rule(self, ruleterm, end=True):
        module = self.modulewrapper.current_module
        rule = self.make_rule(ruleterm, module)
        signature = rule.signature

        if self.get_builtin(signature):
            error.throw_permission_error("modify", "static_procedure",
                                         rule.head.get_prolog_signature())

        function = module.lookup(signature)  #adding to module.functions
        function.add_rule(rule, end)  #adding to rulechain
        return rule

    def make_rule(self, ruleterm, module):
        if helper.is_term(ruleterm):
            assert isinstance(ruleterm, Callable)
            if ruleterm.signature().eq(predsig):
                return Rule(ruleterm.argument_at(0), ruleterm.argument_at(1),
                            module)
            else:
                return Rule(ruleterm, None, module)
        elif isinstance(ruleterm, Atom):
            return Rule(ruleterm, None, module)
        else:
            error.throw_type_error("callable", ruleterm)

    @jit.elidable_promote('all')
    def get_builtin(self, signature):
        from prolog import builtin  # for the side-effects
        return signature.get_extra("builtin")

    # _____________________________________________________
    # parsing-related functionality

    def _build_and_run(self, tree, source_string, file_name, similarity=None):
        assert self is not None  # for the annotator (!)
        from prolog.interpreter.parsing import TermBuilder
        builder = TermBuilder()
        term = builder.build_query(tree)
        if isinstance(term, Callable) and term.signature().eq(callsig):
            self.run_query_in_current(term.argument_at(0))
        else:
            term = self._term_expand(term)
            rule = self.add_rule(term)
            if similarity is not None:
                rule.scores = similarity.get_initial_rule_scores(term)
            else:
                rule.scores = [1.0]

            rule.file_name = file_name
            rule._init_source_info(tree, source_string)

            rule_index = self.rule2index[rule.source]
            self.index2rule[rule_index] = rule

    def _term_expand(self, term):
        if self.modulewrapper.system is not None:
            v = BindingVar()
            call = Callable.build("term_expand", [term, v])
            try:
                self.run_query_in_current(call)
            except error.UnificationFailed:
                v = BindingVar()
                call = Callable.build("term_expand", [term, v])
                self.run_query(call, self.modulewrapper.system)
            term = v.dereference(None)
        return term

    def runstring(self, s, file_name=None, similarity=None):
        from prolog.interpreter.parsing import parse_file
        parse_file(s,
                   None,
                   Engine._build_and_run,
                   self,
                   file_name=file_name,
                   similarity=similarity)

    def parse(self, s, file_name=None):
        from prolog.interpreter.parsing import parse_file, TermBuilder
        builder = TermBuilder()
        trees = parse_file(s, None, file_name=file_name)
        terms = builder.build_many(trees)
        return terms, builder.varname_to_var

    def getoperations(self):
        from prolog.interpreter.parsing import default_operations
        if self.operations is None:
            return default_operations
        return self.operations

    # _____________________________________________________
    # Prolog execution

    def run_query(self, query, module, continuation=None, embedding=None):
        assert isinstance(module, Module)
        rule = module._toplevel_rule
        fcont = DoneFailureContinuation(self)
        if continuation is None:
            continuation = CutScopeNotifier(self,
                                            DoneSuccessContinuation(self),
                                            fcont)
        continuation = BodyContinuation(self, rule, continuation, query)
        return driver(continuation, fcont, Heap(), self)

    def run_query_in_current(self, query, continuation=None):
        module = self.modulewrapper.current_module
        return self.run_query(query, module, continuation)

    #EDIT: _rule_to_simchain takes in a rulechain and returns a list containing
    #names of all names with attributed similarity scores including itself
    def _rule_to_simchain(self, rulechain):
        simchain = []
        sig = rulechain.signature
        if (sig.name in self.similarity.simdict):
            simchain = self.similarity.simdict[sig.name]
        return simchain

    def _print_rulechain(self, rulechain):
        chain = []
        x = rulechain
        while x is not None:
            chain.append(x)
            x = x.next
        print "Rulechain is", chain
        return

    def get_query_string(self, query):
        queryargs = []
        for v in query.arguments():
            if isinstance(v, Atom):
                queryargs.append(v.name())
            elif isinstance(v, BindingVar):
                if (v.binding is not None):
                    queryargs.append(v.binding.name())
                else:
                    queryargs.append(v.name())
            elif isinstance(v, Number):
                queryargs.append(str(v.num))

        querystring = query._signature.name + '(' + ','.join(queryargs) + ').'
        return querystring

    # TODO: write this
    def get_query_embedding(self, query_string):
        call('python3 ../../../get_query_embedding.py', shell=True)
        with open('embedding.pkl', 'rb') as f:
            query_embedding = pickle.load(f)
        return query_embedding

    # TODO: write this
    def get_similar_rule(self, query_embedding, k=0):

        arr = self.embeddings
        vec = query_embedding
        den = np.sqrt(
            np.einsum('ij,ij->i', arr, arr) * np.einsum('j,j', vec, vec))
        out = arr.dot(vec) / den
        out = (out + 1.0) / 2.0

        rule_index = np.argpartition(out, -k)[-k:][0]

        rule_score = out[rule_index]

        return rule_index, rule_score

    def call(self, query, rule, scont, fcont, heap, k=0):
        if isinstance(query, Var):
            query = query.dereference(heap)
        if not isinstance(query, Callable):
            if isinstance(query, Var):
                raise error.throw_instantiation_error()
            raise error.throw_type_error('callable', query)

        signature = query.signature()
        builtin = self.get_builtin(signature)
        if builtin is not None:
            return BuiltinContinuation(self, rule, scont, builtin,
                                       query), fcont, heap

        # get embedding of querystring using charRNN
        query_string = self.get_query_string(query)
        query_embedding = self.get_query_embedding(querystring)

        # find kth most similar rule
        # TODO: figure out how to track k
        rule_index, rule_score = self.get_similar_rule(query_embedding, k)
        rule = self.index2rule[rule_index]

        if (k >= self.maxk):
            raise error.UnificationFailed
        else:
            k = k + 1

        if heap.depth > self.max_depth:
            raise error.UnificationFailed

        scont, fcont, heap = _make_rule_conts(self, scont, fcont, heap, query,
                                              rule, k, rule_score)
        return scont, fcont, heap

    def call_in_module(self, query, module, scont, fcont, heap):
        return self.call(query, module._toplevel_rule, scont, fcont, heap)

    def _get_function(self, signature, module, query):
        function = module.lookup(signature)
        if function.rulechain is None and self.modulewrapper.system is not None:
            function = self.modulewrapper.system.lookup(signature)
        if function.rulechain is None:
            raise error.UnificationFailed
            # TODO Is this okay?
            # return error.throw_existence_error(
            #         "procedure", query.get_prolog_signature())
        return function

    # _____________________________________________________
    # module handling

    def switch_module(self, modulename):
        m = self.modulewrapper
        try:
            m.current_module = m.modules[modulename]
        except KeyError:
            module = Module(modulename)
            m.modules[modulename] = module
            m.current_module = module

    # _____________________________________________________
    # error handling

    @jit.unroll_safe
    def throw(self, exc, scont, fcont, heap, rule_likely_source=None):
        from prolog.interpreter import memo
        exc_term = exc.term
        # copy to make sure that variables in the exception that are
        # backtracked by the revert_upto below have the right value.
        exc_term = exc.term.copy(heap, memo.CopyMemo())
        orig_scont = scont
        while not scont.is_done():
            if not isinstance(scont, CatchingDelimiter):
                scont = scont.nextcont
                continue
            discard_heap = scont.heap
            heap = heap.revert_upto(discard_heap)
            try:
                scont.catcher.unify(exc_term, heap)
            except error.UnificationFailed:
                scont = scont.nextcont
            else:
                return self.call(scont.recover, scont.rule, scont.nextcont,
                                 scont.fcont, heap)
        raise error.UncaughtError(exc_term, exc.sig_context,
                                  rule_likely_source, orig_scont)

    def __freeze__(self):
        return True
예제 #4
0
class Engine(object):
    def __init__(self, load_system=False, similarity=None, max_depth=20, lambda_cut=0.1, embeddings = None, rule2index = None, maxk = 5):
        self.similarity = similarity or Similarity(lambda_cut)
        self.operations = None
        self.modulewrapper = ModuleWrapper(self)
        self.max_depth = max_depth
        if load_system:
            self.modulewrapper.init_system_module()
        
        from prolog.builtin.statistics import Clocks
        self.clocks = Clocks()
        self.clocks.startup()
        self.streamwrapper = StreamWrapper()
        self.embeddings = embeddings
        self.rule2index = rule2index
        self.maxk = maxk
        self.index2rule = {}


    def _freeze_(self):
        return True

    # _____________________________________________________
    # database functionality

    def add_rule(self, ruleterm, end=True):
        module = self.modulewrapper.current_module
        rule = self.make_rule(ruleterm, module)
        signature = rule.signature
        
        if self.get_builtin(signature):
            error.throw_permission_error(
                "modify", "static_procedure", rule.head.get_prolog_signature())

        function = module.lookup(signature) #adding to module.functions
        function.add_rule(rule, end) #adding to rulechain
        return rule

    def make_rule(self, ruleterm, module):
        if helper.is_term(ruleterm):
            assert isinstance(ruleterm, Callable)
            if ruleterm.signature().eq(predsig):
                return Rule(ruleterm.argument_at(0), ruleterm.argument_at(1), module)
            else:
                return Rule(ruleterm, None, module)
        elif isinstance(ruleterm, Atom):
            return Rule(ruleterm, None, module)
        else:
            error.throw_type_error("callable", ruleterm)

    @jit.elidable_promote('all')
    def get_builtin(self, signature):
        from prolog import builtin # for the side-effects
        return signature.get_extra("builtin")


    # _____________________________________________________
    # parsing-related functionality

    def _build_and_run(self, tree, source_string, file_name, similarity=None):
        assert self is not None # for the annotator (!)
        from prolog.interpreter.parsing import TermBuilder
        builder = TermBuilder()
        term = builder.build_query(tree)
        if isinstance(term, Callable) and term.signature().eq(callsig):
            self.run_query_in_current(term.argument_at(0))
        else:
            term = self._term_expand(term)
            rule = self.add_rule(term)
            if similarity is not None:
                rule.scores = similarity.get_initial_rule_scores(term)
            else:
                rule.scores = [1.0]

            rule.file_name = file_name
            rule._init_source_info(tree, source_string)
            
            if len(rule.source.split(':-')) < 2:
                source = rule.source
                startArgs = source.find('(') + 1
                pred = source[:startArgs-1]
                endArgs = source.find(')') 
                nargs = len(source[startArgs:endArgs].split(','))
                key = pred + '/' + str(nargs)
                if key in self.rule2index:
                    rule_index = self.rule2index[key]
                    self.index2rule[rule_index] = key
            else:
                if rule.source in self.rule2index:
                    rule_index = self.rule2index[rule.source]
                    self.index2rule[rule_index] = rule

    def _term_expand(self, term):
        if self.modulewrapper.system is not None:
            v = BindingVar()
            call = Callable.build("term_expand", [term, v])
            try:
                self.run_query_in_current(call)
            except error.UnificationFailed:
                v = BindingVar()
                call = Callable.build("term_expand", [term, v])
                self.run_query(call, self.modulewrapper.system)
            term = v.dereference(None)
        return term

    def runstring(self, s, file_name=None, similarity=None):
        from prolog.interpreter.parsing import parse_file
        parse_file(s, None, Engine._build_and_run, self, file_name=file_name, similarity=similarity)

    def parse(self, s, file_name=None):
        from prolog.interpreter.parsing import parse_file, TermBuilder
        builder = TermBuilder()
        trees = parse_file(s, None, file_name=file_name)
        terms = builder.build_many(trees)
        return terms, builder.varname_to_var

    def getoperations(self):
        from prolog.interpreter.parsing import default_operations
        if self.operations is None:
            return default_operations
        return self.operations

    # _____________________________________________________
    # Prolog execution


    def run_query(self, query, module, continuation=None, embedding = None):
        assert isinstance(module, Module)
        rule = module._toplevel_rule
        fcont = DoneFailureContinuation(self)
        if continuation is None:
            continuation = CutScopeNotifier(self, DoneSuccessContinuation(self), fcont)
        continuation = BodyContinuation(self, rule, continuation, query)
        continuation.first = True
        return driver(continuation, fcont, Heap(), self)

    def run_query_in_current(self, query, continuation=None):
        module = self.modulewrapper.current_module
        return self.run_query(query, module, continuation)

    
    #EDIT: _rule_to_simchain takes in a rulechain and returns a list containing
    #names of all names with attributed similarity scores including itself
    def _rule_to_simchain(self, rulechain):
        simchain = []
        sig = rulechain.signature
        if (sig.name in self.similarity.simdict):
            simchain = self.similarity.simdict[sig.name]
        return simchain  

    def _print_rulechain(self, rulechain):
        chain = []
        x = rulechain
        while x is not None:
            chain.append(x)
            x = x.next
        print "Rulechain is", chain
        return

    def get_query_string(self, query):
        queryargs = []
        for v in query.arguments():
            if isinstance(v, Atom):
                queryargs.append(v.name())
            elif isinstance(v, BindingVar):
                if (v.binding is not None):
                    try:
                        queryargs.append(v.binding.name())
                    except:
                        queryargs.append(str(v.binding.num))
                else:
                    queryargs.append(v.name())
            elif isinstance(v, Number):
                queryargs.append(str(v.num))

        querystring = query._signature.name + '(' + ','.join(queryargs) + ').'
        return querystring

    # pass in heap
    def get_next_rule(self, rule_dist, heap):  
        # TODO: consider setting a threshold below which rules are not tried

        if (rule_dist is None):
            return None, 0.0, rule_dist

        if isinstance(rule_dist, tuple):
            facts, rule_dist= rule_dist
            if (facts == []):
                return self.get_next_rule(rule_dist, heap)
            else:
                return facts[0], 1.0, (facts[1:], rule_dist)
            
        if (np.amax(rule_dist) == -np.inf):
            return None, 0.0, rule_dist

        rule_index = (-rule_dist).argsort()[0]
        score = rule_dist[rule_index]
        
        # set value of ruleindex in rule_dist to -inf so it isn't selected
        # again for the same query
        rule_dist[rule_index] = -np.inf
        rule = self.index2rule[rule_index]
        #print 'rule output', rule
        #print '\n'

        return rule, score, rule_dist

    def get_top_ten(self, rule_dist):
        if (rule_dist is not None):
            rule_indices = (-rule_dist).argsort()[:10]
            for i in rule_indices: 
                if isFact(self.index2rule[i]):
                    print(self.index2rule[i])
                else:
                    print(self.index2rule[i].source)

   
    def regularcall(self, query, rule, scont, fcont, heap):
        # do a real call
        signature = query.signature()
        module = rule.module
        function = self._get_function(signature, module, query)
        query = function.add_meta_prefixes(query, module.nameatom)
        startrulechain = jit.hint(function.rulechain, promote=True)
        rulechain, simchain = startrulechain.find_applicable_rule(query, heap, self.similarity)
        if rulechain is None:
            raise error.UnificationFailed
        if heap.depth > self.max_depth:
            raise error.UnificationFailed

        scont, fcont, heap = regular_make_rule_conts(self, scont, fcont, heap, query, rulechain)
        return scont, fcont, heap



        
    def call(self, query, rule, scont, fcont, heap, k = 0, parent_rule = None, sister_rule = None, first = False):
        if isinstance(query, Var):
            query = query.dereference(heap)
        if not isinstance(query, Callable):
            if isinstance(query, Var):
                raise error.throw_instantiation_error()
            raise error.throw_type_error('callable', query)

        signature = query.signature()        
        builtin = self.get_builtin(signature)

        rule1 = None
        try: 
            rule1 = scont.rule
        except:
            pass
        log_sister = (rule1 == rule) and scont.from_and 
        
        if builtin is not None:
            if (signature.name != ','):
                if (log_sister):
                    scont.sister_rule = sister_rule
            scont = BuiltinContinuation(self, rule, scont, builtin, query, parent_rule, sister_rule)
            return scont, fcont, heap

        if first:
            return self.regularcall(query, rule, scont, fcont, heap)


        query_string = self.get_query_string(query)
        rule = (parent_rule, sister_rule)
        var_start = query_string.index('(')
        var_end = query_string.index(')')
        var = query_string[var_start+1:var_end]
        var = map(str.strip, var)
        if (len(var) < 4):
            var += [None] * (4-len(var))
        rule_dist, term_dist = run_model(query_string, rule, var)
        
        print('TOP TEN RULES')
        self.get_top_ten(rule_dist)
        print('\n')
        rule, score, rule_dist = self.get_next_rule(rule_dist, heap)

        if (rule is None):
            k = self.maxk

        if (k < self.maxk):
            k = k+1

        if heap.depth > self.max_depth:
            raise error.UnificationFailed

        scont, fcont, heap = _make_rule_conts(self, scont, fcont, heap,\
                              query, rule, k, rule_dist, score, \
                              parent_rule, sister_rule, log_sister)
        return scont, fcont, heap


    def call_in_module(self, query, module, scont, fcont, heap):
        return self.call(query, module._toplevel_rule, scont, fcont, heap)

    def _get_function(self, signature, module, query): 
        function = module.lookup(signature)
        if function.rulechain is None and self.modulewrapper.system is not None:
            function = self.modulewrapper.system.lookup(signature)
        if function.rulechain is None:
            raise error.UnificationFailed
            # TODO Is this okay?
            # return error.throw_existence_error(
            #         "procedure", query.get_prolog_signature())
        return function

    # _____________________________________________________
    # module handling

    def switch_module(self, modulename):
        m = self.modulewrapper
        try:
            m.current_module = m.modules[modulename]
        except KeyError:
            module = Module(modulename)
            m.modules[modulename] = module
            m.current_module = module

    # _____________________________________________________
    # error handling

    @jit.unroll_safe
    def throw(self, exc, scont, fcont, heap, rule_likely_source=None):
        from prolog.interpreter import memo
        exc_term = exc.term
        # copy to make sure that variables in the exception that are
        # backtracked by the revert_upto below have the right value.
        exc_term = exc.term.copy(heap, memo.CopyMemo())
        orig_scont = scont
        while not scont.is_done():
            if not isinstance(scont, CatchingDelimiter):
                scont = scont.nextcont
                continue
            discard_heap = scont.heap
            heap = heap.revert_upto(discard_heap)
            try:
                scont.catcher.unify(exc_term, heap)
            except error.UnificationFailed:
                scont = scont.nextcont
            else:
                return self.call(
                    scont.recover, scont.rule, scont.nextcont, scont.fcont, heap)
        raise error.UncaughtError(exc_term, exc.sig_context, rule_likely_source, orig_scont)

    def __freeze__(self):
        return True