Datalog code not working in Racket - prolog

I am trying to port this Prolog code to Datalog in Racket, using example at bottom of this page.
#lang datalog
edge(a, b). edge(b, c). edge(c, d). edge(d, a).
path(X, Y) :- edge(X, Y).
path(X, Y) :- edge(X, Z), path(Z, Y).
path(X, Y)?
pathall(X,X,[]).
pathall(X,Y,[X,Z|L]):- arc(X,Z),pathall(Z,Y,L).
pathall(a, d)?
But it is giving this error at [X,Z|L] on last line of code:
read: expected a `]' to close `['
How do I represent a list in Datalog? Thanks for your help.

Datalog is a syntactic subset of Prolog.
In particular, compound terms such as lists are not supported in Datalog.

Related

Uncle or Aunt without sibling fact

I'm wondering how would I be able to call a nephew or niece in a family tree without using a sibling fact for prolog. I can't figure out a way to do it by calling the uncle directly.
For example:
parent(elli, lisa).
parent(kelly, lisa).
parent(ben, claire).
parent(lisa, claire).
grandparent(X, Y) :- parent(X, Z), parent(Z, Y).
Since ellie or kelly is ben's niece, I have the rule that when called by grandparent(X, claire). will give elli and kelly as the grandchild of claire. How would I make a rule to be able to call niece(ben, X). so it'll list all of ben's niece. I can't figure out a way to do it with only the parent fact, the only way of doing it would be to include a sibling fact but is there a way to do it without making a sibling fact?
I'm very new to prolog, literally like a week ago so please excuse me if I don't understand it that well.
brother(X, Y) :- male(X), parent(X, Z), parent(Y, Z), X \= Y.
uncle(X, Y) :- brother(X, Z), parent(Y, Z).

In prolog, why doesn't adding "edge(X, Y) :- edge(Y, X)." alone work for converting a directed graph definition to an undirected graph

I'm just learning Prolog, and I'm reviewing lecture notes and all the notes say is that:
given the following definition for directed graphs:
path(X, Y) :- edge(X, Y).
path(X, Y) :- edge(X, Z), path(Z, Y).
If we wanted to make this an undirected graph, defining
edge(X, Y) :- edge(Y, X). alone doesn't work, and I can't figure out why.
X to Y has an edge if Y to X has an edge. Seems to make sense to me.
The notes don't really clarify why not, but it does define that the proper solution would be:
edge1(X, Y) :- edge(X, Y).
edge1(X, Y) :- edge(Y, X).
to what we already had.
Can anyone explain this to me, please and thanks? <3
There are several potential sources of non-termination in your program.
First, with the rule edge(X, Y) :- edge(Y, X). your program will never terminate. Regardless of where you add this rule to your program.
What is often quite irritating is that your program will still produce many answers which somewhat suggests that it works. However, it will never stop.
The best way to understand this, is to consider a slightly modified program, called a failure-slice. This modified program will share many properties with your program. Not all of them, but some. We will add goals false into your program. If the resulting program loops, the original program will loop as well.
path(X, Y) :- edge(X, Y), false.
path(X, Y) :- false, edge(X, Z), path(Z, Y).
edge(a, b) :- false.
edge(X, Y) :- edge(Y, X).
Second, there is another source of non-termination in your improved program. Here is the related failure-slice:
path(X, Y) :- false, edge1(X, Y).
path(X, Y) :- edge1(X, Z), path(Z, Y), false.
edge1(X, Y) :- edge(X, Y).
edge1(X, Y) :- edge(Y, X).
edge(a, b).
edge1/2 now always contains cycles, so this fragment will loop for path(a, Y). and more generally also path(X, Y), false.
To solve this problem, you will have to rewrite path/2.
You can rewrite this in a generic manner by using closure0/3 and path/4!
So path/2 can be defined as:
path(X, Y) :-
closure(edge, X, Y).
Because rules don't work the same as facts, and you are spiraling off into an infinite loop if you use the same predicate.
Let's take the example ?-edge(5,2). We will end up calling --
edge(5,2) :- edge(2,5).
Ok, what happens when we call edge(2,5)?
edge(2,5) :- edge(5,2).
... Uh oh. Logic circle.
When using edge1, you are simply creating a wrapper for your predicate to escape the recursive definition.

run function with all possibilities resulted from other function

I have two predicates:
foo(Y,X)
bar(Y,Z)
After running foo, How can I run bar with all possibilities of Y ?
example:
foo(Y, key) % all possibilities of Y => chat
% faq
% about
% search
How can I run bar with these all possibilities ?
bar(chat, Z)
bar(faq, Z)
bar(about, Z)
bar(serach, Z)
And then store all the results of Z in a list Zs?
foo/2 and bar/2 are already in join, and after each run of foo/2 bar/2 will be tried.
Maybe you are looking for forall(foo(Y,X), bar(Y,Z)), that run all possibilities of foo/2, and then bar/2. I.e. is required that bar/2 doesn't fail.
To understand the behaviour of forall/2, as well as other all solutions builtins, like setof/3, can be useful test with very simple builtins, with well known behaviour:
?- forall(member(X,[f,o,o]),(member(Y,[b,a,r]),writeln(X-Y))).
f-b
o-b
o-b
true.
You can see that the complete solution search of forall applies to its first argument, not the second.
HTH
allZs(X, Zs) :-
setof(Y, foo(Y, X), Ys),
maplist(bar, Ys, Zs).
related SWI-Prolog man pages: Finding all Solutions to a Goal and library apply
Note: usually in Prolog the convention is to put intput arguments before output ones - in your first predicate that'd mean foo(X, Y) instead of foo(Y, X). Plus here it'd outline the transitivity: foo(X, Y), bar(Y, Z)..
I think you want something like this:
barOnList([], []).
barOnList([Y|Ys], [Z|Zs]) :- bar(Y, Z), barOnList(Ys, Zs).

How to negate in Prolog

I'm new to PROLOG and am at the very beginning of the exercises on this page. Given the rules parent(X, Y) and male(X), I'm trying to define a rule mother(X, Y) as
mother(X, Y) :-
not(male(X)),
parent(X, Y).
However, in GNU Prolog I get the following error:
| ?- mother(lina, julia).
uncaught exception: error(existence_error(procedure,not/1),mother/2)
| ?-
\+/1 is the ISO Prolog predicate to "negate". Note that "negate" means here not provable at that point.
You can refer to this excellent answer by #false for more on the subject
The solution is actually in the exercise file on that page:
female(X) :- \+ male(X).
As #Mog said, negation is the unary \+ operator.

Getting all the solutions to a predicate in Prolog

I'm writing a text adventure game in Prolog, and I am printing out room exits. I have code that does:
exits_from(Room) :-
connected(Room, X),
write(X), write(' ').
where connected/2 is:
connected(X, Y) :- path(X, Y).
connected(X, Y) :- path(Y, X).
and path is:
path(room, hallway).
path(hallway, foyer).
and so on.
When I am printing the exits for a room though, it gets the first, then wants a ';' to say that I want another solution. Is there anyway to force a predicate to compute the result entirely, so that the player wouldn't have to keep asking for more exits?
one way is to do something like
print_all_solutions :-
solution(Sol),
write(Sol),
fail. % this causes backtracking
print_all_solutions. % succed
another is to use special predicate forall, like follows:
forall(solution(Sol), write(Sol))

Resources