Reputation: 75
I am quite new with Prolog and I am trying to use it to order a list with defined constraints.
The problem starts with the following definitions:
Item
is length 3 list: [Name, Type, Weight]
.Content
is a list of Items [item_0,.....item_n]
.ContentList
is a list of Content
For example:
With the items:
item_1 = [chicken, meat, 1.0]
item_2 = [eggplant, vegetable, 0.5]
item_3 = [tomatoes, vegetable, 1.0]
item_4 = [bread, other, 0.2]
We build two Contents:
contentA = [item_2, item_3]
contentB = [item_1, item_4]
contentC = [item_3, item_4]
So now, let's say we have some content defintions:
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).
The goal would be:
Given a list of Content
returns a ContentList
that matches the best a defined order:
For example (but thus my question i'm not sure if it is the right way of doing it.)
-> `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).
Ideally, I would like something like that:
solve([contentB, contentC, contentA])
to would return [contentA, contentB, contentC]
because: order(contentA, contentB), order(contentA, contentC), order(contentB, contentC)
So I have basically two questions:
order
and constraints are correctly defined, what would be the way to write a solver?I understand my question is a bit wide, so I will take any suggestions, references, ideas ;)
Thanks in advance if you read this!
Upvotes: 1
Views: 508
Reputation: 12972
What you need is a sorting function but not sorting with standard comparing functions-predicates like =<
or >=
but with using your order predicate. So you need to implement a sorting algorithm in Prolog, for example insertion sort:
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).
You could also implement mergesort which is more efficient. Since I have no data I can't see if the above is really working or if it has some bugs so I'm waiting for comments...
I think it works I tested it by querying:
insertionSort([[[chicken, meat, 1.0],[beaf, meat, 1.0]],[[eggplant, vegetable, 0.5],[tomatoes, vegetable, 1.0]]],Result).
where I gave a list [content1,cntent2] where content1 had type meat and content 2 had type vegetable so according to order predicate the output should be [content2,content1] so the output I think is right:
?- 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.
Upvotes: 1