Reputation: 33
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
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