Check if two lists are different in prolog - prolog

diverso([X|L1],L2) :- nonp(X,L2), diverso(L1,L2).
nonp(X,[]).
nonp(X,[A|B]) :- X\=A, nonp(X,B).
this is my code, it doesn't work and I don't know why.
Error is
Diverso/2 unknown predicate
My query is:
?-diverso([3,4],[1,2]).

Adding the recursive base case for the diverso predicate solves the problem!

Related

forall/2 predicate query doesn’t return results

I have the following facts.
loves(ami, paul).
loves(lucy, paul).
female(ami).
artist(ami).
female(lucy).
artist(lucy).
canadian(paul).
lovesCanadianArtists(Person) :- forall(canadian(X), loves(Person, X)).
When I execute the query in SWI-Prolog:
?- lovesCanadianArtists(X).
The answer is true, and I don't get results.
Someone told me that the issue is the predicate isLovedByArtists(Person) is not inversible or invertible. So, I should add a condition on Person variable because it is not bound by the forall\2 predicate. Like:
lovesCanadianArtists(Person) :- female(Person), forall(canadian(X), loves(Person, X)).
So, my questions are:
Is this predicate invertibility documented anywhere ? I can't find it.
For me, the explanation given is wrong, and but I am not sure whether I should get results with my first rule. What's the underlying issue here ?
What's the underlying issue here ?
"forall/2 does not change any variable bindings. [...] If your intent is to create variable bindings, the forall/2 control structure is inadequate." - https://www.swi-prolog.org/pldoc/man?section=forall2
Perhaps one of foreach, findall, bagof or setof will do what you want, although it's not clear from the plural 'artists' and singular 'Person' exactly what that is; e.g. for a list of all People who love at least one Canadian artist, which may have duplicates if you add more Canadian artists:
lovesCanadianArtists(People) :-
findall(Person, (canadian(X), loves(Person, X)), People).

Could not derive which predicate may be called

I'm studying for an exam and got stuck on one of the prep questions:
Question:
The following Prolog-program is a meta-program. Explain why this
program is a meta-program and give the output to the three questions
to the program:
?- prove(moving_method(bird,M),N).
?- prove(moving_method(ross,M),N).
?- prove(moving_method(kim,M),N).
I'm trying to run the code(on swish.swi-prolog.org) but it only gives me this error message:
Sandbox restriction!
Could not derive which predicate may be called from
call(C)
prove(A,B)
prove(moving_method(bird,A),B)
The code we are given:
:- dynamic moving_method/2, is_a/2.
is_a(bird,animal).
is_a(ross,albatross).
is_a(kim,kiwi).
is_a(albatross,bird).
moving_method(bird,fly).
moving_method(kiwi,walk).
prove(Fact,l):-
Fact,!.
prove(Fact,X):-
Fact=..[Rel,A1,A2],
is_a(A1,SA),
NewFact=..[Rel,SA,A2],
prove(NewFact,X1),
X is X1 + 1.
The error message might be fairly straight forward but how do I fix it? And why is this a meta-program?
Thank you!
why is this a meta-program?
See: SWI-Prolog Meta-Call Predicates
Meta-call predicates are used to call terms constructed at run time.
In this case passing in the predicate to call, Fact, then running it as a goal.

Prolog Cut operator

I defined my knowledge base as:
edge(mammal,isa,animal).
edge(human,isa,mammal).
edge(simba,isa,human).
edge(animal,swim,bybirth).
edge(human,swim,mustlearn).
path(X,Y) :- edge(X,isa,Y).
path(X,Y) :- edge(X,isa,Z), path(Z,Y).
swim(X,Y) :- edge(X,swim,Y).
swim(X,Y) :- path(X,Z), swim(Z,Y).
Now, to use the above knowledge base, I use the following:
?- swim(simba,bybirth).
?- swim(simba,mustlearn).
And for both the queries, Prolog returns true. I want Prolog to check for the property swim locally first, then look at the direct parent, and so on in a hierarchical fashion. And it should stop searching as soon as we know that Simba "mustlearn" to swim, and shouldn't look any further. Thus, it should return false for the first query and true for the second.
I know it has to be done by limiting backtracking. I tried using the cut and not operators, but couldn't succeed. Is there a way to achieve this?
I tried it and ran into a problem too. I thought this might work:
swim(X,Y) :- once((edge(X,swim,Y); path(X,Z), swim(Z,Y))).
It doesn't work, because if Y is already instantiated on the way in, the first step will fail to unify and it will try the second route going through the human intermediate. So even though the query only produces one result, it can be fooled into producing swim(simba, bybirth). The solution is to force Prolog to commit to a binding on another variable and then check that binding after the commitment:
swim(X,Y) :-
once((edge(X,swim,Method); path(X,Z), swim(Z,Method))),
Method = Y.
This tells Prolog, there is only one way to get to this method, so find that method, and then it must be Y. If you find the wrong method, it won't go on a search, it will just fail. Try it!

prolog expanding predicate to iterate for multiple results, combining / resolving result sets

I have a predicate "lookupOptions" which returns one by one some lists (Menus).
I'm trying to get it to satisfy the case of multiple inputs. I can return a single set of options as follows, by reading the head of the "list_places" list.
find_options(Restaurant,Town,Menu) :- lookupOptions(Restaurant,H,Menu), list_places(Town,[H|T])
But, I'm not able to get it to iterate.
I have tried a lot of things, these were my best efforts so far.
a) standard enough iteration, but it wont resolve ...
doStuff(X,[],_).
doStuff(Restaurant,[H|T],_):- lookupOptions(Resturant,H,_), doStuff(Restaurant,T,_).
find_options(Restaurant,Town,Menu) :- doStuff(Restaurant,[H|T],Menu), list_places(Town,[H|T]).
b) expanding the goal predicate ...
find_options(_,Town,[H|T],_)
find_options(Restaurant,Town,Menu) :- find_options(Restaurant,Town,[],Menu).
find_options(Restaurant,Town,X,Menu) :- list_places(Town,X).
find_options(Restaurant,Town,[H|T],Menu) :- lookupOptions(Restaurant,[H],Menu), find_options(Restaurant,Town,T,Menu).
Would either of these work ? if the pattern was written correctly. Or if there was an appropriate cut put in place?
Any help most appreciated ...
It's no clear on what you want iterate. Prolog uses backtracking to examine all alternatives, then you should start backtracking if you are after some alternative, or use the all solutions family.
Now I think you want simply declare there could be more find_options(Restaurant,Town,Menu). Then try replacing the head match [H|T] with this:
find_options(Restaurant,Town,Menu) :-
lookupOptions(Restaurant,H,Menu),
list_places(Town, Places),
member(H, Places).
BTW T is a singleton in your original rule. This could be a hint for the need of generalize it.

Understanding a prolog predicate

I'm having some troubles in understanding the following prolog predicate ,
I can understand that it concatenate some chars , also produces the possible lists (first & second goal ) , but I can't understand how it do this ? how it executes ?
domains
i=integer
l=i*
slist=string*
clist=char*
predicates
nondeterm conc(clist,clist,clist).
clauses
conc([],L,L).
conc([H|L1],L2,[H|L3]):-
conc(L1,L2,L3).
The first goal
goal
conc(['a','b'],['c','d'],L).
result
L=['a','b','c','d']
the second goal
goal
conc(L1,L2,['a','b','c']).
result
L1=[], L2=['a','b','c']
L1=['a'], L2=['b','c']
L1=['a','b'], L2=['c']
L1=['a','b','c'], L2=[]
4 Solutions
I'm neither an expert in prolog, nor in logic, but I'll try to explain what I think how it works.
After the call to:
<- conc(['a','b'],['c','d'],L).
Prolog will look for a predicate that matches the signature. In this case that would be:
conc([H|L1],L2,[H|L3])
It tries to resolve the variables with the given data.
|1: H:=['a'], L1:=['b'], L2:=['c','d']
Now it steps into the recursion with these data calling:
<- conc(['b'], ['c','d'], L3).
|2: H:=['b'], L1:=[], L2:=['c','d']
<- conc([], ['c','d'], L3).
The last line causes prolog to use the predicate with the signature:
conc([],L,L).
resolving:
|3: L:=['c','d']
Now Prolog is able to construct the concatinated List handing over L up the recursion stack.
|2: [H|L3]:=['b','c','d']
|1: [H|L3]:=['a','b','c','d']
I hope that is a hint in the right direction. Maybe you should read this article for clarification

Resources