all possible routes between the Entry and the Exit - prolog

i need help to solve the maze path. Thanks in advance
link(a,b).
link(b,c).
link(c,d).
link(f,c).
link(b,e).
link(d,e).
link(e,f).
Write a predicate that defines a route between any two adjacent points (X and Y for example) based on the fact that there is a link between them and a recursive predicate that covers the more general case of a route between any two non-adjacent points (X and Z for example) by establishing for a fact that there is a link between X and a third point in the maze (say Y) and a route between Y and Z.
Two special rooms – one connected to “a” and called “Entry” and another one connected to “f” and called “Exit”. Add a set of facts to reflect the two new rooms. Using the predicates from task 1, write a predicate that finds all possible routes between the Entry and the Exit and creates a list of the visited rooms. Write another predicate that displays the list in the interactive console at the end of every iteration, or in other words every time the Exit is reached. Write a test plan that shows your anticipated results and the actual results. Evaluate this solution and identify any potential problems and the situations that may cause their occurrence.
The problem with this solution is looping.If I want to link(a,f) prolog says no.Is anything wrong with my predicate.
| ?- link(a,b).
link(b,c).
link(c,d).
link(f,c).
link(b,e).
link(d,e).
link(e,f).
route(X,Y):- link(X,Y).
route(X,Y):- link(X,Z), route(Z,Y).
yes
yes
yes
yes
yes
yes
yes
! ----------------------------------------
! Error 20 : Predicate Not Defined
! Goal : route(_31102,_31104) :- link(_31102,_31104)
Aborted
| ?- link(a,f).
no
| ?- route(X,Y).
X = a ,
Y = b ;
X = b ,
Y = c ;
X = c ,
Y = d ;
X = f ,
Y = c ;
X = b ,
Y = e ;
X = d ,
Y = e ;
X = e ,
Y = f ;
X = a ,
Y = c ;
X = a ,
Y = e ;
X = a ,
Y = d
;
X = a ,
Y = d
| ?- link(X,Z).
X = a ,
Z = b
| ?-
| ?- link(X,Z).
X = a ,
Z = b ;
X = b ,
Z = c ;
X = c ,
Z = d ;
X = f ,
Z = c ;
X = b ,
Z = e ;
X = d ,
Z = e ;
X = e ,
Z = f

connected_to( A,B) :-
closure0(link, A,B).
See this question for a definition of closure0/3.
Or, to use your new name:
route(A0,A) :-
link(A0,A1),
closure0(link, A1,A).

Related

Prolog - Connectivity Graph Beginner

I am a beginner in Prolog and I have a task to do.
I need to check if the graph is connected.
For now I have that...
graph(
[arc(a,b)],
[arc(a,f)],
[arc(b,c)],
[arc(c,d)],
[arc(c,e)],
[arc(e,d)],
[arc(f,c)],
[arc(f,e)],
[arc(f,g)],
[arc(g,c)],
[arc(c,a)]).
edge(X,Y):-arc(X,Y);arc(Y,X).
path(X,Y):-edge(X,Y).
path(X,Y):-edge(X,Z),path(Z,Y).
triangle(X,Y,Z):-arc(X,Y),arc(Y,Z),arc(Z,X).
cycle(X):-arc(X,Y),path(Y,X).
connectivity([]):-forall(member(edge(X,Y)),path(X,Y)).
Check:
connectivity(graph).
upper I have arc(x,y) and I need check if every pair is connected.
Could u help me ?
Since you changed the question after I was almost done I will post what would solve the question before the change and you can figure out how to change it to meet your update.
arc(a,b).
arc(a,f).
arc(b,c).
arc(c,d).
arc(c,e).
arc(e,d).
arc(f,c).
arc(f,e).
arc(f,g).
arc(g,c).
arc(c,a).
edge(X,Y) :-
arc(X,Y), !.
edge(X,Y) :-
arc(Y,X).
path_prime(Visited,X,Y) :-
\+ member(X,Visited),
edge(X,Y), !.
path_prime(Visited,X,Y) :-
\+ member(X,Visited),
edge(X,Z),
path_prime([X|Visited],Z,Y).
path(X,X) :-
ground(X), !.
path(X,Y) :-
path_prime([],X,Y).
nodes(Nodes) :-
setof(A,B^arc(A,B),Starts),
setof(B,A^arc(A,B),Ends),
union(Starts,Ends,Nodes).
connected(X,Y) :-
nodes(Nodes),
member(X,Nodes),
member(Y,Nodes),
path(X,Y).
The first thing that has to be done is to get a list of the unique nodes which will be a set.
This can be done using
nodes(Nodes) :-
setof(A,B^arc(A,B),Starts),
setof(B,A^arc(A,B),Ends),
union(Starts,Ends,Nodes).
Notice that both the start and the end node of an arc are done separately. In particular notice that the node d is only in the destination of an arc.
Since you included edge(X,Y):-arc(X,Y);arc(Y,X). in your question, this indicated that the arcs should not be directional and so it is possible to get cycles. To avoid the cycles the list of visited nodes is added to the argument list and checked before proceeding.
As no test cases or examples of a correct solution were given, some times a node connected to itself is valid and so the clause
path(X,X) :-
ground(X), !.
was added.
This is by no means an optimal or best way to do this, just to give you something that works.
Partial run
?- connected(X,Y).
X = Y, Y = a ;
X = a,
Y = b ;
X = a,
Y = c ;
X = a,
Y = d ;
X = a,
Y = e ;
X = a,
Y = f ;
X = a,
Y = g ;
X = b,
Y = a ;
X = Y, Y = b ;
X = b,
Y = c ;
...
As I often comment, you should do problems with pen an paper first before writing code. If you don't know exactly what the code will be before you start typing the first line of code then why are you typing in code?
Questions from comments:
And setof ,union ,whats mean? Im rly beigneer and I don't understand that language and predicates.
setof/3 collects all of the values from arc/2. Since only one of the two values is needed, ^ tells setup/3 not to bind the variable in the Goal, or in beginner terms to just ignore the values from the variable.
union/3 just combines the to sets into one set; remember that a set will only have unique values.

retracting and asserting values in prolog

I have been modelling some directive graphs in prolog. It consists of nodes and edges and how they are connected. Every node has a certain value of surfers (page rank).
e.g.
e(a,c).
e(b,a).
e(b,h).
:-dynamic s/2.
s(a,1).
s(b,1).
s(c,1).
I have written an interpreter. This interpreter calculates new values for each node.
The problem is how to assign these new values to the database.
I have been doing it with retractall(s(,)) and asserting new values to every single node with e.g. assertz(s(a,sum0),
assertz(s(b,sum1), ....
This has been working, but is it possible to assert new values without asserting each particular node in the graph a value, so that the interpreter is completely independent from the graph?
I have been trying to generate a list with all nodes in a graph and indicating the nodes of a graph in this list.
sum_nodes_0(X,Y):-
list_nodes(_,L),
amount_nodes(N),
nth1(I,L,X),I=<N,sum_node(X,Y).
reset(X,S):-
list_nodes(_,L),
s(X,S),
sum_node(X,Y),
retractall(s(_,_)),
forall(member(X,L),assertz(s(X,Y))).
sum_nodes_0 displays me the new values like.
X = a,
Y = 1.0 ;
X = b,
Y = 1 ;
X = c,
Y = 2 ;
X = d,
Y = 0.5 ;
X = e,
Y = 1.5 ;
X = f,
Y = 0.5 ;
X = g,
Y = 1 ;
X = h,
Y = 0.5.
These values I want to be assigned by reset(X,S). But reset just resets one value not all. e.g.
X=h; Y=0
I have tried foreach, forall and member predicates. But it didn't work as intended.
I hope that someone has an idea.

Predicate arithmetic combination (only + or -) to find a result from a list of numbers

I'm trying to achieve an old exercice from my school and i can't figure it out how to solve it. Here is the result expected :
bC([1,12,34,23,11],23,Res).
Res = 1+11-12+23
So bC/3 is supposed to find every combination of addition or substract operation (the third argument) from a list of number (the first argument) to match a result (the second argument).
I can't find a way to start resolving this... If someone could give me a clue about this problem, i would really appreciate it.
UPDATE: Some elements of the list can be left out.
As a hint: you can aim to construct all expressions by exhautively searching over the expression space. Since X - (Y - Z) is just X - Y + Z, this is good news, since we can restrict us to left recursive expressions, like:
makepm([], ExpI, ExpI).
makepm([H|T], ExpI, ExpO) :-
makepm(T, +(ExpI, H), ExpO).
makepm([H|T], ExpI, ExpO) :-
makepm(T, -(ExpI, H), ExpO).
If as first element we take 1, and we inject the rest of the list in the makepm/3, we get:
?- makepm([12,34,23,11], 1, F).
F = 1+12+34+23+11 ;
F = 1+12+34+23-11 ;
F = 1+12+34-23+11 ;
F = 1+12+34-23-11 ;
F = 1+12-34+23+11 ;
F = 1+12-34+23-11 ;
F = 1+12-34-23+11 ;
F = 1+12-34-23-11 ;
F = 1-12+34+23+11 ;
F = 1-12+34+23-11 ;
F = 1-12+34-23+11 ;
F = 1-12+34-23-11 ;
F = 1-12-34+23+11 ;
F = 1-12-34+23-11 ;
F = 1-12-34-23+11 ;
F = 1-12-34-23-11.
What still needs to be done: the question is not perfectly clear about the fact if numbers can be left out, if that is the case, then you should write a predicate that first selects a subset of numbers. Then we can exhaustively enumerate all expressions which we create with makepm/3, and then we need to verify, for example with the is/2 [swi-doc] predicate that the expression sums up to the requested value. If that is the case the predicate can succeed.

Prolog - adding two arguments, even if one is not a number

in Prolog, how should I proceed when I want to add two arguments, even if one is not a number. So for instance, if I enter add2args(1,2,R). the result should be R = 3. If I enter add2args(1,x,R). the result should be R=1+x.
So far I have this:
add_2args(X,Y,R):- number(X),number(Y), R is (X+Y).
Which allows me to add two numbers, but I don't know how I can get it to print out anything other than true and false if X and Y are not numbers which is normal since number(X) checks if X is a number or not. What other rule do I have to add to get the desired result?
Prolog will view an expression symbolically (as a Prolog term) unless explicitly evaluated with something like is/2. So the simplest way to do this in your case would be the following:
add_2args(X, Y, R) :-
( number(X), number(Y) % Both X and Y are numbers, then...
-> R is X + Y % Evaluate the expression
; R = X + Y % Else, just unify R with the expression
).
The R = X + Y will not evaluate the expression but only unify the term X + Y with R. This is also a nice "Prolog beginner's guide" illustration for the difference between =/2 and is/2. If you wrote, for example, R = 2 + 3, then did a write(R) you would see 2 + 3, not 5. You could subsequently do, Result is R which would then evaluate the expression R and yield Result = 5.
| ?- R = 2 + 3, Result is R.
R = 2+3
Result = 5
yes
| ?-

How to make a condition to end the query in prolog?

i'm new in prolog, so i have done a program which have a method to query something, but when i use it, it keeps yielding results even when it should end.
amigos(juanarjona,omarpacheco).
amigos(juanarjona,jasonancona).
amigos(juanarjona,jorgebolio).
amigos(juanarjona,gerardoadrian).
amigos(Amigo,Amigoslista):-!,amigos(Amigoslista,Amigo).
for example, when i execute
amigos(X,juanarjona).
it should give me just this answers:
X = omarpacheco ; X = jasonancona ; X = jorgebolio ; X = gerardoadrian
;
but what it really do is to repeat those answers without end like this
X = omarpacheco ; X = jasonancona ; X = jorgebolio ; X = gerardoadrian
; X = omarpacheco ; X = jasonancona ; X = jorgebolio ; X =
gerardoadrian . . . . . . . . . . . . (repeating)...........
so, that's why i'm recurring to you guys, i need to know how to establish a condition which do not let repeating the answers.
Sorry for my bad english by the way.
I Forgot to say that it must be with just one predicate in this case "amigos"
It's easy: Use two predicates instead of one!
The first predicate comprises facts only:
amigos(juanarjona, omarpacheco).
amigos(juanarjona, jasonancona).
amigos(juanarjona, jorgebolio).
amigos(juanarjona, gerardoadrian).
The second one—built on top of the first one—provides the symmetric closure1:
sym_amigos(X, Y) :- amigos(X, Y).
sym_amigos(X, Y) :- amigos(Y, X).
Sample query using SICStus Prolog 4.3.2:
| ?- sym_amigos(P, Q).
P = juanarjona, Q = omarpacheco ? ;
P = juanarjona, Q = jasonancona ? ;
P = juanarjona, Q = jorgebolio ? ;
P = juanarjona, Q = gerardoadrian ? ;
P = omarpacheco, Q = juanarjona ? ;
P = jasonancona, Q = juanarjona ? ;
P = jorgebolio, Q = juanarjona ? ;
P = gerardoadrian, Q = juanarjona ? ;
no
As your fact base gets larger and larger, looking at all the concrete answers gets tiresome... So, to check if sym_amigos/2 terminates universally, we can run a query like this one:
| ?- sym_amigos(P, Q), % looking for amigos ...
false. % ... we discard every candidate solution.
no % "no" means "terminates universally"
Above query can never yield any solution—after all, it is a conjunction with the goal false/0:
It can, however, tell us if the above goal terminates universally.
If Prolog returns no—it does2—we know that sym_amigos/2 terminates universally.
Footnote 1:
meta-predicate symm/2 covers the common idiom "symmetric closure".
Footnote 2: SWI-Prolog does not reply no but false instead.

Resources