Necro,但我有同样的问题,我尝试了 nb_setval 和 b_setval 的组合。它似乎适用于更简单的情况,但我还没有在更难的情况下进行测试。主要区别在于您不能直接查询 b_assert'ed 事实,而必须使用 b_query。
:- dynamic b_asserted/2.
:- nb_setval(b_assert_nbc, 0), nb_setval(b_assert_bc, 0).
b_assert(What):-
b_assert_maintain_consistency,
b_getval(b_assert_nbc, NBC),
AssertId is NBC+1,
assert(b_asserted(AssertId, What)),
nb_setval(b_assert_nbc, AssertId),
b_setval(b_assert_bc, AssertId).
b_query(What):-
b_assert_maintain_consistency,
b_asserted(_, What).
% The overhead
b_assert_maintain_consistency:-
nb_getval(b_assert_nbc, NBC),
b_getval(b_assert_bc, BC), % BC < NBC if backtracking happened
b_assert_restore_consistency(BC, NBC).
b_assert_restore_consistency(C, C):- !.
b_assert_restore_consistency(BC, NBC):-
BC1 is BC+1,
(between(BC1, NBC, DeleteMe), retract(b_asserted(DeleteMe, _)), fail; true),
nb_setval(b_assert_nbc, BC).
如果这可行,奖金将是找出 b_retract。也许我们 b_assert(b_retracted(What)) 并在 b_query 中重放断言和撤回?