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) :-
% 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_包含(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).
...