Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

retracting on backtracking

7 views
Skip to first unread message

Mike Burrell

unread,
Apr 11, 2009, 1:03:22 PM4/11/09
to
Hello!

I appreciate your patience in advance. I'm not terribly fluent in Prolog :(

As a simplified version of my problem, I have a fact like:

size(group, 10).

Conceptually I would like to break "group" into two subgroups such that
their sizes add up to 10. I figured dynamic predicates might be a nice
way to deal with this. I have:

add_subgroups([G], SZ) :- assert(size(G, SZ)).
add_subgroups([G|GS], SZ) :-
GS \== [],
leq(X, SZ),
assert(size(G, X)),
SZ2 is SZ - X,
add_subgroups(GS, SZ2).

leq is a predicate which binds X to some number between 0 and SZ
inclusive, defined as:

range(Y, Y, [Y]).
range(X, Y, [X|ZS]) :-
X < Y,
X2 is X + 1,
range(X2, Y, ZS).
leq(X, Y) :- range(0, Y, YS), member(X, YS).

The point of all this is that I then do:

add_subgroups([subgroup1, subgroup2], 10).

That will set size(subgroup1, 0) and size(subgroup2, 10). It will then
do some business using those numbers. The problem comes when it
backtracks; I end up with:

size(subgroup1, 0).
size(subgroup1, 1).
size(subgroup2, 10).
size(subgroup2, 9).

which is not what I want. I want to retract the previous asserts
whenever it backtracks. I'm having trouble determining how to structure
things to get it to retract the asserts only when backtracking, though.

If there isn't a simple solution, I suppose I'll abandon the use of
dynamic predicates and just pass around lists of sizes or something. It
would be more code, though.

Thanks for any help!
Mike

Markus Triska

unread,
Apr 11, 2009, 1:20:23 PM4/11/09
to
Mike Burrell <mbu...@SPAM.uwo.ca> writes:

> leq is a predicate which binds X to some number between 0 and SZ
> inclusive, defined as:

In SWI-Prolog, you can use between/3 or CLP(FD) constraints for this:

%?- X + Y #= 10, [X,Y] ins 0..sup, label([X,Y]).
%@ X = 0,
%@ Y = 10 ;
%@ X = 1,
%@ Y = 9 ;
%@ X = 2,
%@ Y = 8 ;
%@ etc.

> I want to retract the previous asserts whenever it backtracks.

Then add a third clause to add_subgroups/2 like:

add_subgroups(_, _) :- retract(size(_,_)), false.

On backtracking, this clause will be selected and do what you say.

> I suppose I'll abandon the use of dynamic predicates and just pass
> around lists of sizes or something.

This seems like a good idea in any case. For one thing, it greatly
simplifies debugging and testing predicates in isolation. Also, it need
not necessarily be more code: You can use DCG notation to invisibly
thread such parameters through and only access them where needed.

--
comp.lang.prolog FAQ: http://www.logic.at/prolog/faq/

fodor...@gmail.com

unread,
Apr 27, 2009, 3:07:52 PM4/27/09
to
Use backtrackable updates instead of assert/retract:

:- dynamic(bkEdb/1).
ins(A):- bkEdb(A), !, fail.
ins(A):- \+ bkEdb(A), assert(bkEdb(A)).
ins(A):- retract(bkEdb(A)), !, fail.
del(A):- \+(bkEdb(A)), !, fail.
del(A):- bkEdb(A), retract(bkEdb(A)).
del(A):- assert(bkEdb(A)), !, fail.


add_subgroups([G], SZ) :- ins(size(G, SZ)).


add_subgroups([G|GS], SZ) :-
GS \== [],
leq(X, SZ),

ins(size(G, X)),

0 new messages