我有app修改事实db。 我希望能够回滚更改,即如果规则在两者之间的某个点失败,则返回到原始状态。就像数据库事务一样。 prolog是否提供了一些东西? 如果不是,你会怎么解决这个问题?
感谢
============
更改db事实是4-5种不同类型的事实f.e。 :
f1(x,y).
f1(x1,y1).
f2(a,b).
f3(d,f).
....
f5(u,m).
f5(r,g).
我用assert和retract修改了事实db。目前我一次只修改一个事实。但是可以多次调用修改例程。 目前我也可以动态地断言事实,但是仅使用缩回来修改事实,即撤回 - >断言序列。 通过“app”我的意思是我正在写的应用程序,所以我完全控制了我的工作。
答案 0 :(得分:1)
一个棘手的问题......
Prolog不处理传统意义上的交易,主要是因为它不是传统意义上的数据库。实际上,传统(关系型)数据库需要多种语言才能表达程序细节,并且通常不会将记录的顺序视为相关,而在Prolog中,的顺序是控制执行的主要方式...然后交易Prolog上下文中的是什么意思?当执行回溯时,它是'回滚'吗?
从SWI-Prolog中的交易中搜索,我们发现RDF store,ODBC,Berkley DB interface或SQLite pack提供了交易管理。
对于更简单的东西,我认为库(persistency)应该有效。只需在回滚时重新加载状态...库处理的文件是普通的Prolog术语,因此数据存储的演变可以很容易地“调试”
修改的
我偶然发现了docstore包。这可能是更好的选择...
答案 1 :(得分:1)
这实际上取决于你的实际问题(在你的问题中更好地描述它会非常有用)。到目前为止,对您所描述的问题进行建模的最简单方法是使用回溯而不是操纵数据库。
但是,这意味着您必须重新考虑您的方法。您只使用数据库来获取基本事实,而不是将数据库用作临时存储。然后,您在逻辑变量中收集状态。由于你没有提供足够的细节,我会试着通过一个愚蠢的例子来解释我的意思。
假设你有很多想要排序的东西。你不知道Prolog让你排序,而是采取以下非常低效的方法:
所以这是你的事情:
t(foo).
t(bar).
t(baz).
t(foobar).
t(foobarbaz).
t('just another thing').
t(t).
这是一个谓词,用于检查事物是否按递增顺序排序:
is_sorted([]).
is_sorted([X|Xs]) :-
is_sorted_1(Xs, X).
is_sorted_1([], _).
is_sorted_1([X|Xs], Prev) :-
Prev @=< X,
is_sorted_1(Xs, X).
现在变得有趣了。我们把事情作为基本事实。我们在列表中收集它们,并使用此列表作为我们愚蠢排序的起点。
permutation_sort_ts(Sorted_ts) :-
findall(T, t(T), Ts),
permutation_sort(Ts, Sorted_ts).
排列排序符合它所说的。它需要一个列表,对其进行排列,并检查结果是否已排序。
permutation_sort(L, S) :-
permutation(L, S),
is_sorted(S).
以下是从顶层运行谓词时会发生的情况:
?- permutation_sort_ts(R).
R = [bar, baz, foo, foobar, foobarbaz, 'just another thing', t] ;
false.
会发生什么?在谓词permutation_sort/2
中,我们一次生成一个可能的排列,并检查它是否已排序。如果未对排列进行排序,则谓词失败,回溯到最后的选择点。在选择点之后完成的所有绑定都被遗忘了#34;:您不需要清除未排序的排列,因为Prolog只是忘了它!因此,生成一个新的排列并检查它是否已排序。
最重要的是,您不会在任何时候更改数据库。相反,您使用逻辑变量来保持计算状态。如果您不确定究竟发生了什么,请尝试跟踪:
?- trace(permutation_sort/2).
?- permutation_sort_ts(R).
% you should see how permutation are checked in turn
按照您在问题中的建议方式进行操作意味着对于每个排列,您将列表插入数据库,检查它是否已排序,如果不排序,则在继续搜索之前从数据库中撤消。 这不是Prolog的用法!
但如果你想要一个更有用的答案,请提出一个更有针对性的问题。