Regex 正则表达式匹配Prolog

Regex 正则表达式匹配Prolog,regex,prolog,dcg,failure-slice,Regex,Prolog,Dcg,Failure Slice,我正在尝试进行正则表达式匹配。我已经把所有的功能都写出来了,但它们并没有按应有的方式工作。据我所知,当我试图比较一个列表时,它有一个问题。 例如,“re_包含(a,a)。”和“re_包含(并集(a,b),a)”一样给出了true(显然) 但一旦我把它列出来,它就失败了。“re_contains(seq(a,b),[a,b])”返回false。Append应该检查所有可能的组合以找到匹配项,但是这些函数都不能正常工作。这让我觉得我可能错过了一个基本案例。但是我认为“re_包含(X,L):-X==L

我正在尝试进行正则表达式匹配。我已经把所有的功能都写出来了,但它们并没有按应有的方式工作。据我所知,当我试图比较一个列表时,它有一个问题。
例如,“re_包含(a,a)。”和“re_包含(并集(a,b),a)”一样给出了true(显然)

但一旦我把它列出来,它就失败了。“re_contains(seq(a,b),[a,b])”返回false。Append应该检查所有可能的组合以找到匹配项,但是这些函数都不能正常工作。这让我觉得我可能错过了一个基本案例。但是我认为“re_包含(X,L):-X==L”应该处理它。我一定是在看什么重要的东西

这是我的密码:

re_contains(empty, []).

re_contains(X, L) :-
    X == L.

re_contains(seq(X, Y), L) :-
    append(L1, L2, L),
    re_contains(X, L1),
    re_contains(Y, L2). 

re_contains(union(X, _), L) :-
    re_contains(X, L).

re_contains(union(_, Y), L) :- 
    re_contains(Y, L).  

re_contains(kleene(X), L) :- 
    append([Car|L1], L2, L),
    re_contains(X, [Car|L1]),
    re_contains(kleene(X), L2).

re_contains(kleene(_),[]).

append/3
将拆分
L
,并且
L1
L2
都将是列表

我会尝试将
re_contains(X,L):-X==L.
替换为
re_contains(X,[X])。

更改后,
re\u包含(a,a)。
将失败


您以不同的方式表示序列,而matcher并没有同时提供这两种方式。实际上,唯一的“有效”案例是而不是序列。

有几个问题。以下是最明显的例子:

打字。 谓词
re_包含/2
需要一个列表作为第二个参数。
re_包含(a,a)。
的成功与其说是意图,不如说是巧合

单调性。另一个问题是
re_包含([a],[a])
成功,但
re_包含([X],[a])
失败。或者,从另一个角度来看:
re包含([X],[a])
失败,但
X=a,re包含([X],[a])
成功。通过添加目标
X=a
我们专门化了查询,因此最初失败的查询应该再次失败

身份测试(
==/2
)应该由相等(
=/2
取代,并确保我们有一些列表。因此:

re_contains(X, L) :- % X == L. X = L, append(X,_,_). 现在,假设我们这里有一个长度
N
的列表。目标
附加(L1、L2、L)
可能有多少个答案?实际上
N+1
。这与实际值无关。现在考虑:

?- length(L,1000000), time(re_contains(seq([a],[]),[b|L])). % 2,000,005 inferences, 0.886 CPU in 0.890 seconds (100% CPU, 2258604 Lips) false. 不再调查整个列表:

?- length(L,1000000), time(phrase(re(seq([a],[])),[b|L])). % 6 inferences, 0.000 CPU in 0.000 seconds (88% CPU, 127313 Lips) false. ?长度(L,1000000),时间(词组(re(seq([a],]),[b | L]))。 %6个推论,0.000秒0.000 CPU(88%CPU,127313个嘴唇) 错。 顺便说一句,这是一个完整的定义

终止/不终止。与效率相关的是终止的属性。理想情况下,如果解决方案集可以有限表示,则查询将终止。也就是说,通过有限数量的答案。好的,这就是我们努力追求的理想。Prolog的简单但非常高效的执行算法有时会循环,而只有有限数量的答案是可能的。理解不终止协议的原因有时非常棘手。通常的调试策略(如跟踪或使用调试器单步执行)不起作用,因为它们显示了太多的细节。幸运的是,有一种更好的技术:

我不再看你的整个程序,我将再次只看它的一小部分。此片段是一个片段(有关更多详细信息,请参阅链接)。它要小得多,但讲述了很多关于原始程序的内容——前提是它是一个纯粹、单调的程序:

如果故障片未终止,则原始程序不会终止。 因此,如果我们发现这样一个失败片段,我们可以立即对整个程序做出结论。甚至没有读过剩下的

下面是一个非常有趣的失败片段:

... re_contains(X, L) :- false, X = L re_contains(seq(X, Y), L) :- append(L1, L2, L), false, re_contains(X, L1), re_contains(Y, L2). re_contains(union(X, _), L) :- false, re_contains(X, L). ... ... re_包含(X,L):-false, X=L re_包含(序列(X,Y),L):- 附加(L1,L2,L),false, re_包含(X,L1), re_包含(Y,L2)。 re_包含(并集(X,u),L):-false, re_包含(X,L)。 ...
现在考虑一下目标
re_包含(seq([],[]),L)。
理想情况下,应该只有一个答案
L=[]
,目标应该终止。但是,它会循环,因为
append(L1,L2,L)
不会终止。这与上面的DCG解决方案不同,DCG解决方案终止于
短语(re(seq([]),L)

re_contains
可用于序列。C.f.
re_包含([a],[a])
。当然可以,但OP不使用列表来表示正则表达式。我建议消除这种不匹配。存在
re_contains(X,L):-X==L的事实表明列表是有意的。@chac这实际上也起到了作用。我想我的问题是,我只是假设Prolog知道它应该是一个列表。我犯了愚蠢的错误。非常感谢你们!非常感谢。我完全不熟悉Prolog语法。我想我是想做更多的C#if语句之类的事情。
?- length(L,1000000), time(phrase(re(seq([a],[])),[b|L])).
% 6 inferences, 0.000 CPU in 0.000 seconds (88% CPU, 127313 Lips)
false.
...
re_contains(X, L) :- false,
    X = L
re_contains(seq(X, Y), L) :-
    append(L1, L2, L), false,
    re_contains(X, L1),
    re_contains(Y, L2).
re_contains(union(X, _), L) :- false,
    re_contains(X, L).
...