Prolog,如何订购带有约束的列表

时间:2016-10-17 10:33:10

标签: prolog constraint-programming

我对Prolog很新,我正在尝试使用它来订购具有已定义约束的列表。

问题始于以下定义:

  • Item是长度为3的列表:[Name, Type, Weight]
  • Content是项目[item_0,.....item_n]
  • 的列表
  • ContentListContent
  • 的列表

例如:

使用以下项目:

item_1 = [chicken, meat, 1.0]
item_2 = [eggplant, vegetable, 0.5]
item_3 = [tomatoes, vegetable, 1.0]
item_4 = [bread, other, 0.2]

我们构建了两个内容:

contentA = [item_2, item_3]
contentB = [item_1, item_4]
contentC = [item_3, item_4]

现在,让我们说我们有一些内容定义:

hasItemType([_, XType, _], XType).

hasListItemType([H|T], Type) :-
    hasItemType(H, Type);
    hasListItemType(T, Type).

hasListOnlyItemType([H|T], Type) :-
    hasItemType(H, Type),
    hasListItemType(T, Type)

isVegetarian(Content) :- hasListOnlyItemType(Content, vegetable).
hasVegetables(Content) :- hasListItemType(Content, vegetable).
hasMeat(Content) :- hasListItemType(Content, meat).

目标是:

根据Content列表,返回ContentList,其中匹配定义的最佳订单:

例如(但因此我的问题是我不确定这是否是正确的做法。)

 -> `order(A, B)` A is before B in the output list.


order(ContentA, ContentB) :-
    isVegetarian(ContentA),
    hasVegetables(ContentB).

order(ContentA, ContentB) :-
    hasVegetables(ContentA),
    hasMeat(ContentB).

理想情况下,我想要这样的事情:

solve([contentB, contentC, contentA])将返回[contentA, contentB, contentC]

,因为:     订单(contentA,contentB),订单(contentA,contentC),订单(contentB,contentC)

所以我基本上有两个问题:

  1. 将问题正式化是否合理。
  2. 正确定义order和约束后,编写解算器的方法是什么?
  3. 我理解我的问题有点宽,所以我会接受任何建议,参考,想法;)

    如果你读到这篇文章,请提前致谢!

1 个答案:

答案 0 :(得分:1)

您需要的是排序功能,但不能使用标准比较函数 - 谓词(如=<>=进行排序,而是使用您的订单谓词。因此,您需要在Prolog中实现排序算法,例如插入排序:

insertionSort([], []).

insertionSort([HEAD|TAIL], RESULT) :-
   insertionSort(TAIL, LIST), insertInPlace(HEAD, LIST, RESULT).

insertInPlace(ELEMENT, [], [ELEMENT]).

insertInPlace(ELEMENT, [HEAD|TAIL], [ELEMENT|LIST]) :-
   order(ELEMENT,HEAD), insertInPlace(HEAD, TAIL, LIST).

insertInPlace(ELEMENT, [HEAD|TAIL], [HEAD|LIST]) :-
   \+order(ELEMENT ,HEAD), insertInPlace(ELEMENT, TAIL, LIST).

您还可以实现更高效的mergesort。由于我没有数据,我无法看到上述内容是否真的有效,或者是否有一些错误,所以我在等待评论......

我认为它有效我通过查询来测试它:

insertionSort([[[chicken, meat, 1.0],[beaf, meat, 1.0]],[[eggplant, vegetable, 0.5],[tomatoes, vegetable, 1.0]]],Result).

我给了一个列表[content1,cntent2]其中content1有类型的肉,而内容2有类型的蔬菜所以根据顺序谓词输出应该是[content2,content1]所以输出我认为是正确的:

?- insertionSort([[[chicken, meat, 1.0],[beaf, meat, 1.0]],[[eggplant, vegetable, 0.5],[tomatoes, vegetable, 1.0]]],Result).
Result = [[[eggplant, vegetable, 0.5], [tomatoes, vegetable, 1.0]], [[chicken, meat, 1.0], [beaf, meat, 1.0]]] ;
false.