用于识别一阶逻辑项的序言程序

A prolog program for identifying terms of the first order logic

我正在开发一个序言程序来识别一阶逻辑的项,这些项是常量(c1、c2、c3、...)、变量(v1、v2、v3、...)和列表形式为 [fsymbol, t1, t2, ..., tn],其中 fsymbol 是函数符号 (f1a1, f2a1, f3a1, ..., f1a2, f2a2, f3a2, ...), t1, t2, t3 , ..., tn 是一阶逻辑项,n([t1, t2, ..., tn] 中的条目数)是函数 fsymbol 的元数(在 'a' 之后表示),在函数的名称中:例如,f4a6 的元数为 6,f1a3 的元数为 3,等等)。我想定义一个谓词 term/1,如果参数是一阶逻辑的项,它就会成功。只有在将每个变量和每个常量都包含在单例列表中之后,我才能做到这一点,因此 [c1] 是一个术语,但 c1 不是。当我尝试重新定义谓词 term/1 以启用可能是原子(而非列表)的参数时,我收到以下错误消息:

ERROR: Type error: atomic' expected, found [v1]' (a list)

这段代码运行良好,除了不能将 v1、v2、...、c1、c2、...识别为术语;它只接受 [v1]、[v2]、...、[c1]、[c2] 等

onlyDigits([]). %Empty lists has only digits as elements, vacuously.
onlyDigits([A|L]) :- A>=48,A=<57,onlyDigits(L). 
intPos(L) :- length(L,X),X>0,onlyDigits(L),name(N,L),N>0. %Verifies whether the list L converts to a string that represents a positive integer.
letterNumber(Ascii,LN) :- name(LN,[Ascii|L]),intPos(L). %Verifies whether the list LN has precisely a letter (corresponding to the ASCII code Ascii) followed by digits.
variable(V) :- letterNumber(118,V). %v1, v2, v3, etc.
constant(C) :- letterNumber(99,C).  %c1, c2, c3, etc.
function(F) :- function(F,_).       %f1a1, f2a1, f1a2, f2a2, etc.
function(F,A) :- name(F,L),append([102|L1],[97|L2],L),intPos(L1),intPos(L2),name(A,L2).
term([T|L]) :- variable(T), L==[].
term([T|L]) :- constant(T), L==[].
term([T|L]) :- function(T,A),length(L,A),listOfTerms(L,A),!.
listOfTerms([],0).
listOfTerms([T|L],Q) :- Q>0,term(T),Q2 is Q-1,listOfTerms(L,Q2).
listOfTerms(L) :- length(L,Q),listOfTerms(L,Q).

下一个代码运行不正常(我收到了错误消息)。

onlyDigits([]). %Empty lists has only digits as elements, vacuously.
onlyDigits([A|L]) :- A>=48,A=<57,onlyDigits(L).
intPos(L) :- length(L,X),X>0,onlyDigits(L),name(N,L),N>0. %Verifies whether the list L converts to a string that represents a positive integer.
letterNumber(Ascii,LN) :- name(LN,[Ascii|L]),intPos(L). %Verifies whether the list LN has precisely a letter (corresponding to the ASCII code Ascii) followed by digits.
variable(V) :- letterNumber(118,V). %v1, v2, v3, etc.
constant(C) :- letterNumber(99,C).  %c1, c2, c3, etc.
function(F) :- function(F,_).       %f1a1, f2a1, f1a2, f2a2, etc.
function(F,A) :- name(F,L),append([102|L1],[97|L2],L),intPos(L1),intPos(L2),name(A,L2).
term(T) :- variable(T).
term(T) :- constant(T).
term(T) :- T = [T1|L1],function(T1,A),length(L1,A),listOfTerms(L1,A),!.
listOfTerms([],0).
listOfTerms([T|L],Q) :- Q>0,term(T),Q2 is Q-1,listOfTerms(L,Q2).
listOfTerms(L) :- length(L,Q),listOfTerms(L,Q).

这里有什么问题?谓词项是否同时用于原子和列表作为参数?


编辑:我希望我的程序如何工作的一些示例:

?- term(f2a1).
false.

?- term([f2a1, v1]).
true.

?- term(v1).
true.

?- term([f2a2, v1]).
false.

?- term([f2a2, v1, v2]).
true.

?- term([f2a3, v1, v2, [f10a1, c11]]).
true.

?- term([f2a3, v1, v2, [f10a1]]).
false.

?- term([f1a2, [f1a1, v4], [c1]]).
false.

?- term([f1a2, [f1a1, v4], c1]).
false.

我认为您可以根据以下代码使用 SWI-Prolog 解决您的问题:

isdigit(Char) :-
    Char @>= '0',
    Char @=< '9'.

alldigits(ListOfChars) :-
    maplist(isdigit, ListOfChars).

constant(Atom) :-
    atom_chars(Atom, [c|Rest]),
    alldigits(Rest).

variable(Atom) :-
    atom_chars(Atom, [v|Rest]),
    alldigits(Rest).

function(Atom) :-
    atom_chars(Atom, [f|Rest]),
    once(append(Prefix, [a|Suffix], Rest)),
    alldigits(Prefix),
    alldigits(Suffix).

term(Atom) :-
    once( (   constant(Atom)
          ;   variable(Atom)
          ;   function(Atom) ) ).

list_of_terms(List) :-
    maplist(term, List).

一些例子:

?- include(constant, [c12, v345, c6, f7a2, v89, f103a5], R).
R = [c12, c6].

?- include(variable, [c12, v345, c6, f7a2, v89, f103a5], R).
R = [v345, v89].

?- include(function, [c12, v345, c6, f7a2, v89, f103a5], R).
R = [f7a2, f103a5].

?- list_of_terms([c12, v345, c6, f7a2, v89, f103a5]).
true.

UPDATED考虑问题的变化:

isdigit(Char) :-
    Char @>= '0',
    Char @=< '9'.

alldigits(ListOfChars) :-
    maplist(isdigit, ListOfChars).

constant(Atom) :-
    atom(Atom),
    atom_chars(Atom, [c|Rest]),
    alldigits(Rest).

variable(Atom) :-
    atom(Atom),
    atom_chars(Atom, [v|Rest]),
    alldigits(Rest).

function([Atom|Args]) :-
    atom(Atom),
    atom_chars(Atom, [f|Rest]),
    once(append(Prefix, [a|Suffix], Rest)),
    alldigits(Prefix),
    alldigits(Suffix),
    number_chars(Arity, Suffix),
    length(Args, Arity),
    list_of_terms(Args).

term(Term) :-
    once( (   constant(Term)
          ;   variable(Term)
          ;   function(Term) ) ).

list_of_terms(List) :-
    maplist(term, List).

示例:

?- term(c123).
true.

?- term(v4).
true.

?- term([f56a2, c1, v3]).
true.

?- term([f56a7, c1, v3]).
false.

?- term([f46a3, v1, c2, [f1a4, v3, v3, v4, c6]]).
true.

?- term([f46a3, v1, c2, [f1a4, v3, v3, v4]]).
false.

我刚刚修复了程序,谓词 is_list/1:

onlyDigits([]).
onlyDigits([A|L]) :- A>=48,A=<57,onlyDigits(L).
posInt(L) :- length(L,X),X>0,onlyDigits(L),name(N,L),N>0.
letterNumber(Ascii,LetraNum) :- name(LetraNum,[Ascii|L]),posInt(L).
variable(V) :- letterNumber(118,V).%v1, v2, v3, etc.
constant(C) :- letterNumber(99,C). %c1, c2, c3, etc.
function(F) :- function(F,_),!.    %f1a1, f2a1, f1a2, f2a2, etc.
function(F,A) :- name(F,L),append([102|L1],[97|L2],L),posInt(L1),posInt(L2),name(A,L2),!.
term([T|L]) :- function(T,A),length(L,A),listOfTerms(L,A),!.
term(X) :- not(is_list(X)),variable(X),!;not(is_list(X)),constant(X),!.
listOfTerms([],0).
listOfTerms([T|L],Q) :- Q>0,term(T),Q2 is Q-1,listOfTerms(L,Q2).
listOfTerms(L) :- length(L,Q),listOfTerms(L,Q).

示例:

?- term([f1a3, v1, [f1a1, v2], c3]). 是的。

?- 术语([f2a2,f1a1])。 假的。

?- 术语([f2a2,[f1a1]])。 假的。

?- 术语([f2a2,[f1a1,v54]])。 假的。

?- term([f2a2, [f1a1, v54], c0]). 假的。

?- term([f2a2, [f1a1, v54], c462]). 是的。

?- 术语 (v1)。 是的。

?- 术语 (c2)。 是的。

?- listOfTerms([v1, c2, [f1a4, v3, v3, v4, c6]])。 是的。

?- term([f46a3, v1, c2, [f1a4, v3, v3, v4, c6]])。 是的。