Tony H
Tony H

Reputation: 33

How can I check if a Prolog rules was already fired?

I need to check if a rule was already "fired" before to fire it again. I mean before asserting a new fact I need to know if the same fact was already asserted in the previous loop iteration.

I tried to use a list but I think they aren't so "friendly" for my problem. What else can I use to do this?

Upvotes: 1

Views: 298

Answers (1)

Alexander Serebrenik
Alexander Serebrenik

Reputation: 3577

I'm rephrasing my comment above as an answer to elaborate a bit more on it.

You might consider the failure-driven loop that would fail after generating a solution and force Prolog to backtrack and explore other possibilities:

failure_driven_loop(Info):- generate(Info,Term), fail. 
failure_driven_loop(Info). 

(example is from Paul Brna's book). In this example Term records a solution and generate/2 generates solutions for the given Info. The second clause is needed to make the loop succeed when all solutions have been exhausted.

Once a solution has been generated, the first clause fails and the execution backtracks, i.e., Prolog will try to find a different proof for generate(Info,Term), which will commonly involve different clauses either for generate/2 itself or for one of the predicates directly or indirectly invoked by generate/2. If you would like to ensure that once generate/2 has used one of its clauses it should not try and reuse the same clause, you should add cuts, i.e., instead of

generate(Info,Term) :- solve_somehow(Info,Term).
generate(Info,Term) :- solve_in_some_other_way(Info,Term).

you should write

generate(Info,Term) :- solve_somehow(Info,Term), !.
generate(Info,Term) :- solve_in_some_other_way(Info,Term), !.

Solutions found by generate/2 can be recorded with assert. As @CapelliC has pointed out, assertions are not undone if your program backtracks, so the failure driven loop preserves your solutions:

:- dynamic solution/1.

failure_driven_loop(Info):- generate(Info,Term), assert(solution(Term)), fail. 
failure_driven_loop(Info). 

Upvotes: 1

Related Questions