prologclauseprolog-findall

Efficient findall() processing?


I have the following structure of "facts".

if( conds, score, idx).

Then I expect to have thousands of them. The 'conds' is a conditions that will be evaluated as the facts are processed. For every fact that is true I store the score and the index in a list for further processing. The general idea is to findall/3 facts and then go over them ...

findall([Cond, Q, Ix], clause(if(Cond, Q, Ix), true), Conds)
check(Conds, True_QIxLst) ...

My worry is that findall/3 would gobble all thousand of facts for every run i.e. use too much memory.

How would I do what findall does, but process the conditions one-by-one. I will still process all the conditions, but I would like to use less memory.


As per "mat" suggestion this seem to work out :

is_true(Q,Ix) :-
   if(Cond, Q, Ix),
   check(Cond).

run(QI) :-
   findall([Q,Ix], is_true(Q,Ix), QI).

Solution

  • The key to writing efficient Prolog code is to delegate as much work as possible to the engine.

    Everything you do explicitly (i.e., within Prolog) will typically be slower than if the same thing is accomplished by the core engine implicitly. If that isn't the case, it means that there is an opportunity for improvement in the core engine.

    In your particular case, if findall/3 would use too much memory, consider whether findall/3 is even necessary for your use case.

    How about getting out of the way, and delegating it all to Prolog's built-in backtracking?

    true_q_ix(Q, Ix) :-
        if(Cond, Q, Ix),
        cond_is_true(Cond).
    

    No findall/3, no nothing: Just plain backtracking, yielding all Q and Ix for which Cond evaluates to true in your interpretation.

    Don't do anything! Nothing!

    If necessary, you can still wrap this in findall/3, paying its various costs.