% |
% This file contains working code for backtrackable updates |
% It works with many different Prologs, and is the conceptual kernel |
% of all my TR prototypes. |
% |
% The code implements strong inserts and strong deletes. That is, the |
% update ins(p) inserts the atom p into the database, but if p is |
% already there, then ins(p) fails. Likewise, the update del(p) deletes |
% atom p from the database, but if p is not there to begin with, then |
% del(p) fails. |
% |
% The code is based on insert and delete tags. The first time that |
% ins(p) is executed, it adds the atom inserted(p) to the database. |
% This atom remains in the database until ins(p) is backtracked. |
% Subsequently, if del(p) is executed, then the atom deleted(p) is added |
% to the database; and if ins(p) is executed, then the atom deleted(p) |
% is removed from the database. This technique prevents the Prolog |
% database from being corrupted when backtracking through updates. |
% |
% The atom db(p) determines whether p is true in the current database |
% state. It returns true iff inserted(p) is in the database and deleted(p) |
% is not. |
% |
:- export ins/1, asrt/1, del/1, db/1, empty/1, updat/1. |
% Atom P is in the database if it has been inserted and not deleted. |
% |
db(P) :- modifiable(P), inserted(P), not(deleted(P)). |
empty(P) :- modifiable(P), not(db(P)).
updat(P) :- modifiable(P).
% Initial inserts are a special case. To insert P for the first time. |
% add the atom inserted(P) to the database. The predicate undo_ins1 |
% removes this atom during backtracking. |
% |
% To undo an initial insert, remove the inserted fact. |
% |
undo_ins1(P). |
undo_ins1(P) :- retract(inserted(P)), !, fail. |
% For all subsequent inserts, remove the atom deleted(P) from the |
% database. The predicate undo_ins2 puts the atom back during |
% backtracking. |
% |
ins(P) :- modifiable(P), |
deleted(P), |
retract(deleted(P)), |
undo_ins2(P). |
|
% To undo a subsequent insert, put the delete tag back. |
% |
undo_ins2(P). |
undo_ins2(P) :- asserta(deleted(P)), !, fail. |
% To delete P, put the atom deleted(P) into the database. The |
% predicate undo_del removes this atom during backtracking. |
% |
del(P) :- modifiable(P), |
inserted(P), |
not(deleted(P)), |
assert(deleted(P)), |
undo_del(P). |
% To undo a deletion, remove the delete tag. |
% |
undo_del(P). |
undo_del(P) :- retract(deleted(P)), !, fail. |
asrt(P) :- assert(modifiable(P)). |
% The following dummy rules let Prolog know that the predicates |
% inserted/1 and deleted/1 are defined. |
% |
inserted(dummy) :- fail. |
deleted(dummy) :- fail. |
modifiable(dummy) :- fail. |
empty(dummy) :- fail. |