查找prolog规则集中的大多数引用

查找prolog规则集中的大多数引用,prolog,Prolog,我似乎无法理解Prolog实际上是如何工作的。我非常习惯于其他编程语言,如Java和Python,但Prolog似乎非常不同,因为它基于一组逻辑语句 如果有人能向我解释我将如何处理一种情况,在这种情况下,我会得到一套规则,例如 likes(john,mary). likes(mary,adam). likes(adam,mary). likes(jack,destiny). likes(destiny,adam). likes(brianna,adam). 我想知道如何判断谁是最受欢迎的人(在

我似乎无法理解Prolog实际上是如何工作的。我非常习惯于其他编程语言,如Java和Python,但Prolog似乎非常不同,因为它基于一组逻辑语句

如果有人能向我解释我将如何处理一种情况,在这种情况下,我会得到一套规则,例如

likes(john,mary).
likes(mary,adam).
likes(adam,mary).
likes(jack,destiny).
likes(destiny,adam).
likes(brianna,adam).

我想知道如何判断谁是最受欢迎的人(在本例中为adam=3),我将如何做到这一点?

如果您认为Prolog是一种特殊的数据库检索语言,它可以在同一行中变形为函数式编程,可能会更容易些

在这里,我们有一个关系
likes/2
,我们想在它上面运行统计数据

可以使用
library(aggregate)
或类似的谓词,但我们不能这样做

建议将三个业务连锁:

  • 创建一个更好的结构来运行统计数据
  • 在更好的结构上运行统计数据
  • 找到最好的
  • 创建更好的结构来运行统计数据

    收集

    • 在谓词
      likes/2
      中作为第二个参数出现的人的向量(以形式或序言列表的形式),以及
    • 人的集合(也以Prolog列表的形式),以便我们可以迭代某些内容
    关键是集合谓词和

    • findall/3
      用于收集出现在
      likes/2的第二个参数位置上的所有
      Person
    • setof/3
      用于收集出现在
      likes/2
      的第一个或第二个参数位置上的所有
      Person
      集合。 为了实现这一点,
      setof/3
      需要通过 用
      X^
      对其进行“存在量化”
    person\u事件(PersonVec):-
    findall(Person,likes,Person),PersonVec)。
    人员设置(人员设置):-
    集合(Person,X^(likes(Person,X);likes(X,Person)),PersonSet)。
    
    对于
    人员集/2
    ,更易于理解:

    person(person):-喜欢(person)。
    person(person):-喜欢(X,person)。
    person_set(PersonSet):-setof(person,person(person),PersonSet)。
    
    在“Prolog Toplevel”上尝试这一点表明我们走上了正确的道路:

    ?-人员事件(personse)。
    PersonSet=[玛丽,亚当,玛丽,命运,亚当,亚当]。
    ?人员设置(人员设置)。
    PersonSet=[亚当、布丽安娜、命运、杰克、约翰、玛丽]。
    
    我们可以很容易地计算一个人在人的向量中出现的频率, 通过使用
    findall/3
    创建
    x
    的任意列表(例如), 每次出现一个
    x
    ,然后确定该列表的长度:

    计数(个人、个人、计数):-
    findall(x,成员(Person,PersonVec),Xs),长度(Xs,Count)。
    
    在“Prolog Toplevel”上尝试这一点表明我们走上了正确的道路:

    ?-个人事件(PersonVec),计数(mary,PersonVec,count)。
    PersonVec=[玛丽,亚当,玛丽,命运,亚当,亚当],
    计数=2。
    
    我们现在有了“更好的结构”,可以用来统计数据,即 “人的载体”和“人的集合”

    在更好的结构上运行统计数据

    这里的结果,称为
    Stats
    ,应该是一个列表(总是列表) 配对
    -(PersonInPerson向量的发生次数,Person)
    , 哪个可以更容易地写成“中缀”:
    countperson
    ,例如
    2-mary

    这是一个递归定义(或归纳定义),我们据此“计数” 对于
    persent
    中的每个person元素,直到
    persent
    为空集为止 (或者更确切地说,是一张空名单),我们已经完成并取得了成功。结果 在第三个参数中构造:

    %stats(PersonVec、PersonSet、stats)
    统计数据(u,[],[])。
    统计数据(PersonVec、[Person | morests]、[Count Person | morests]:-
    计数(个人,个人,计数),%
    统计数据(个人、更多人、更多统计数据)。%递归
    
    在“Prolog Toplevel”上尝试这一点表明我们走上了正确的道路:

    ?-个人事件(PersonVec),统计(PersonVec,[mary],stats)。
    PersonVec=[玛丽,亚当,玛丽,命运,亚当,亚当],
    统计数据=[2-mary];%也许有更多的解决方案?
    错.%不。
    
    新功能我们可以构建整个统计列表:

    stats(stats):-
    个人事件(PersonVec),
    人员设置(人员设置),
    统计数据(PersonVec、PersonSet、stats)。
    
    在“Prolog Toplevel”上尝试这一点表明我们走上了正确的道路:

    ?-stats(统计)。
    统计数据=[3-adam,0-brianna,1-destiny,0-jack,0-john,2-mary];
    错。
    
    找到最好的

    给定
    Stats
    ,我们可以通过最大化配对列表来找到
    BestPerson

    这可以通过选择“最大”对直接完成 根据“术语的标准顺序”:首先是数字计数 因此,具有较大数值计数的术语比具有 更小的数字计数,这是我们想要的。谓词 我们想要的是:

    best(Stats,BestPerson,BestCount) :-
       max_member(BestCount-BestPerson,Statss).
    
    或者,我们可以编程出
    max_member/2
    (并保持 它对第一个参数进行数值比较,并得到几个参数 如果有几个人有相同的“喜好”,则回答 例如:

    %使用一个伪“(-1)-nobody”在Stats上启动最大化
    最佳(统计、最佳人数、最佳计数):-
    最佳2(统计数据,(-1)-无人,最佳计数最佳个人)。
    %最佳2(统计数据、最佳人数、最佳个人成绩)。
    best2([],BestCountSoFar BestPersonSoFar,BestCountSoFar BestPersonSoFar)。
    best2([Count-| MoreStats],BestCountSoFar BestPersonSoFar,结果):-
    计数<最佳计数迄今为止,
    最佳2(更多统计数据、最佳人数、最佳个人、结果)。%保持最佳状态
    best2([Count-| MoreStats],BestCountSoFar BestPersonSoFar,结果):-
    计数==迄今为止的最佳计数,
    最佳2(贝斯莫尔斯塔斯)
    
    likes(john,mary).
    likes(mary,adam).
    likes(adam,mary).
    likes(jack,destiny).
    likes(destiny,adam).
    likes(brianna,adam).
    
    ?- setof(Person, likes(Person,Someone), ListOfPersons).
    Someone = adam,
    ListOfPersons = [brianna, destiny, mary] ;
    Someone = destiny,
    ListOfPersons = [jack] ;
    Someone = mary,
    ListOfPersons = [adam, john].
    
    ?- findall(Someone-ListOfPersons, setof(Person, likes(Person,Someone), ListOfPersons), Pairs).
    Pairs = [adam-[brianna, destiny, mary], destiny-[jack], mary-[adam, john]].
    
    ?- findall(Someone-ListOfPersons, setof(Person, likes(Person,Someone), ListOfPersons), Pairs), 
       maplist([Someone-ListOfPersons, Someone-NumberOfPersons]>>length(ListOfPersons,NumberOfPersons), Pairs, NewPairs).
    Pairs = [adam-[brianna, destiny, mary], destiny-[jack], mary-[adam, john]],
    NewPairs = [adam-3, destiny-1, mary-2].
    
    ?- findall(Someone-ListOfPersons, setof(Person, likes(Person,Someone), ListOfPersons), Pairs), 
       maplist([Someone-ListOfPersons, Someone-NumberOfPersons]>>length(ListOfPersons,NumberOfPersons), Pairs, NewPairs), 
       sort(2,>=,NewPairs, SortedPairs).
    Pairs = [adam-[brianna, destiny, mary], destiny-[jack], mary-[adam, john]],
    NewPairs = [adam-3, destiny-1, mary-2],
    SortedPairs = [adam-3, mary-2, destiny-1].
    
    most_liked(Person) :-
       findall(Someone-ListOfPersons, 
               setof(Person, likes(Person,Someone), ListOfPersons), 
               Pairs), 
       maplist([Someone-ListOfPersons, Someone-NumberOfPersons]>>length(ListOfPersons, NumberOfPersons), 
               Pairs, 
               NewPairs), 
       sort(2, >=, NewPairs, [Person-_|_]).
    
    ?- most_liked(Person).
    Person = adam.