如何比较Prolog数据库中的项?

如何比较Prolog数据库中的项?,prolog,Prolog,我有一个Prolog数据库 dateopened(asda,date(1985,12,5)). dateopened(tesco,date(1979,12,17)). dateopened(morrisons,date(1999,12,25)). dateopened(sainsburys,date(1979,12,17)). dateopened(lidl,date(1987,8,27)). 我想了解如何提出以下问题(Prolog查询)来回答以下问题: 是否有两个不同的超市在同一天开业?如果

我有一个Prolog数据库

dateopened(asda,date(1985,12,5)).
dateopened(tesco,date(1979,12,17)).
dateopened(morrisons,date(1999,12,25)).
dateopened(sainsburys,date(1979,12,17)).
dateopened(lidl,date(1987,8,27)).
我想了解如何提出以下问题(Prolog查询)来回答以下问题:

  • 是否有两个不同的超市在同一天开业?如果有,它们的名字是什么? (我不知道如何比较数据库中的项目)
  • 给我一年的时间,在上世纪90年代没有超市开张的时候
  • 我试过:

    ?- dateopened(Supermarket,date(Year,_,_)),Year>1989, Year<2000.
    
    哪一种回答了这个问题,因为我可以说1998年或1997年没有超市开业,但我认为这不是必需的

    有一些线索,可以使用
    member/2
    not/1
    \=
    来回答这些问题


    这是一个初学者查询练习,但我不知道如何开始,尤其是问题1。

    由于这是一个学习练习,我的答案更一般,没有具体的解决方案:

    问题1:Prolog解释器试图用事实基础中的事实和规则来解决它的查询,这些事实和规则形成了已知事物的封闭世界。要根据事实检查某件事是否属实,您只需在查询中声明,以便解算器可以尝试与事实相统一,在需要获取值的位置使用变量,并将其作为不需要实际值的变量的占位符。下面的查询为您提供任何超市,并在变量中包含完整日期

    ?- dateopened(S1,Date1).
    S1 = asda,
    Date1 = date(1985, 12, 5) ;
    ...
    
    如果您的查询需要满足多个条件,您可以将它们与从左到右计算的
    组合。要解决最初的问题,您只需使用不同的变量以相同的方式选择任意两个超市,然后确保它们的日期相等且名称不同,这将减少可能的解决方案的数量,以满足您的需要

    问题2:我认为你的想法几乎与你想要的正好相反,但不是真的,因为1999年的对立面将是所有其他年份。作为解决方案草图:

    • 在九十年代找一年。谓词将有所帮助,但如果只允许您使用上述谓词,则可以使用带有年份和成员(年份,L)的列表
      L
    • 使用你最初尝试的第一部分,将可能的年数减少到超市开张时的年数
    • 使用
      \+
      (假设SWI Prolog,不推荐使用
      not/1
      )反转最后一部分,这样您就可以找到我们之前确定在范围内的其他年份

    @donttrythat-编辑的目的是什么?将来我应该做些什么不同的事情呢?只是对代码进行格式化,这样就可以突出显示Prolog语法,并且代码可读性更好。谢谢你,问题1对我来说非常有用。对于问题2,我尝试了dateopened(超市,日期(年),年份>1989年,年份我以为这是另一个问题,但我找不到,你也能帮我解决这个问题吗?如果谓词oldest/1中输入的超市是最旧的,则必须返回true。我有最老的(X):-日期已开(X,D),日期已开(超市,日期),X\=超市,更早的(D,日期),!。但对于其他一些人和最年长的人来说,这都是真的。第二个被弄糊涂了。首先使用
    member(Year,[…])
    选择九十年代的所有年份,然后选择那些与
    dateopened(…Year…
    不匹配的年份,因为您正在查找那些没有打开的年份。甚至可以让Prolog输出数据库中没有的年份吗?我可以理解它是如何输出数据库中的一年的,但我如何询问它没有的信息?我试过这个90年代=[1990199119921993199419951996199719981999],开张日期(超市,日期(年),年份>1989,向往,这是不可能的。就像我说的:你首先给出一系列可能的年份,然后用那些不匹配的年份来减少:
    ?-member(Year,[1990199119921993199419951996199719981999]),\+dateopened(,date(Year,))。
    ?- dateopened(S1,Date1).
    S1 = asda,
    Date1 = date(1985, 12, 5) ;
    ...