Prolog Determine if graph is connected - prolog

I need to determine if an undirected graph is connected.
for example, I have such a graph (and yes, it is connected. since from any node of the graph you can get to any other node of the graph)
------b------
| | |
| | |
a | |
d------c
so far I have only such logic of the program: defining paths
edge(g1,a,b).
edge(g1,b,d).
edge(g1,b,c).
edge(g1,c,d).
path(A,Z,G,P):-
path1(A,[Z],G,P).
path1(A,[A|Path],Graph,[A|Path]).
path1(A,[Y|Visited],Graph,Path):-
adjacent(Graph,X,Y),
not(member(X,Visited)),
path1(A,[X,Y|Visited],Graph,Path).
adjacent(G,A,B):-
edge(G,A,B).
adjacent(G,A,B):-
edge(G,B,A).
and it works as follows, for example:
?-path(a,c,g1,X).
X = [a, b, c]
X = [a, b, d, c]
but I don't understand a little how to finish this program anyway. I want to define a new predicate that only the graph receives as input, like this:
connected(X):-
. . .
Can you tell me how it can be completed in this way? That is, I have to check that each node has the path of that other node..I probably have to submit nodes somewhere else in a good way..I'm confused, I hope you can help me
upd:
I tried to do something, but I didn't get exactly what I expected
connected(_,[]).
connected(G,[X|XT]):- connected1(G,X,XT),connected(G,XT).
connected1(_,_,[]).
connected1(G,X,[Y|YT]):-path(X,Y,G,_),connected1(G,X,YT).
When my goal looks like this connected(g1,[a,b,c,d]). , i got 32 "true" in console. But I want to get only one true value.at the same time, there are fewer of my paths (if I'm not mistaken, there are 22 of them in that graph, not 32.)
but when my graph is really disconnected I get the value false.
can you tell me what I made a mistake in the part that I added,please?
I solved the problem by adding Cuts:
connected(_,[]):-!.
connected(G,[X|XT]):-connected1(G,X,XT),!,connected(G,XT).
connected1(_,_,[]):-!.
connected1(G,X,[Y|YT]):-path(X,Y,G,_),connected1(G,X,YT).
but just not sure about Cut here:
connected(G,[X|XT]):-connected1(G,X,XT),!,connected(G,XT).
I also tried to put it in this line:
connected1(G,X,[Y|YT]):-path(X,Y,G,_),!,connected1(G,X,YT).
but I didn't see any differences. Can you tell me where it would be more correct to put this "!"?

Related

How to add this type of node description by Mermaid?

This is a flowchart pattern that I really like to use and I currently use drawio to draw it:
Notice that there are two kinds of descriptions in the flow chart
description1:How does A get to B
description2:Some properties of B
I know Mermaid can implement the description1 by:
graph TB
A --->|"description1:<br>How does A get to B"| B
But description2 is also very important to me, is there any way to achieve it?
The current workaround:
I use the heading of subgraph instead of description2:
graph TB
A --->|"description1:<br>How does A get to B"| B
subgraph description2:<br>Some properties of B
B
end
But I have to say it's a very ugly temporary solution. So I ask here..
While some types of Mermaid diagrams explicitly support notes (e.g. sequence diagrams), flowcharts do not.
I believe the closest you're going to get is to connect B to itself with an invisible link (~~~):
graph TB
A --->|"description1:<br>How does A get to B"| B
B ~~~|"description2:<br>Some properties of B"| B

How to extend prolog driver and determine number of columns and rows by reading an eps file

Good day! I would like to ask for help in understanding Prolog code as well as learning how to extend its functionality. Based on my limited yet newbie knowledge of programming, the function of the first given code (is quite like a main file), everything originates from it and thus it is the first file that is run before calling any other function.
main.pl
printSequences([]).
printSequences([Sequence|Sequences]):-
writeln(Sequence),
printSequences(Sequences).
loadHelpers:-
['helpers'],
['part01'],
['part02'],
['part03'],
['part04'].
part01:-
readExtremePegSolitaireFile('test04.eps',_,Game),
printGame(Game),
columnsAndRows(Game).
part02:-
readExtremePegSolitaireFile('part01test01.eps',_,Game),
printGame(Game),
openSpaces(Game).
part03:-
readExtremePegSolitaireFile('test04.single.eps',_,Game),
printGame(Game),
setof(Moves,fewestMoves(Game,Moves),AllMoves),
writeln(moves),
printSequences(AllMoves).
part04:-
readExtremePegSolitaireFile('test04.eps',_,Game),
printGame(Game),
noIslands(Game).
I don't think I have any problems understanding the first given code above, but my problem is mostly with this second given code and how to go about manipulating other files. I can't seem to understand the prefix part (is this the definition of a list of lists?) Also am I correct that most of the other functions are declared in this helper file to make the code more organized?
helpers.pl
:- module( helpers,
[ readExtremePegSolitaireFile/3
, printGame/1
]
).
prefix([H],[]).
prefix([H|T],[H|PreT]):-
prefix(T,PreT).
readExtremePegSolitaireFile(File,Moves,Game):-
open(File,read,Input),
read(Input,Moves),
readGame(Input,Temp),
prefix(Temp,Game),
close(Input).
readGame(Input,[]):-
at_end_of_stream(Input),
!.
readGame(Input,[Row|Rows]):-
\+ at_end_of_stream(Input),
read(Input,Row),
readGame(Input,Rows).
printGame(Game):-
writeln(game),
printRows(Game).
printRows([]).
printRows([Row|Rows]):-
writeln(Row),
printRows(Rows).
Last is a peg solitaire board that is given with the first line being the list of moves performed and the following lines are the board declarations (1,2,3,4 - players, x - peg, and '-' as empty spaces)
test04.eps
[r,d,u,r,l,l,l,d,l,u,r,r].
[2,-,x,x,x,x,x].
[x,x,-,x,-,x,x].
[x,3,x,-,x,-,x].
[x,-,4,x,x,x,x].
[x,x,-,x,x,-,x].
[x,x,x,1,-,x,x].
[x,x,x,x,x,x,x].
I would like to know how one would be able to calculate the number of columns and rows via a query columnsAndRows(Game). My first plan of action was to use something like this: (Which would be able to calculate the length of the rows by counting each element in the list however, it seems to have calculated all the elements in the list. 2 things that I noticed was:
It didn't stop at the end of the row
Apparently it didn't print the entire board, it was missing the last line of the board!
columnsAndRows(Game) :-
flatten(Game, FlatList),
length(FlatList,FlatListSize),
writeln(FlatListSize).
?- [a04tests].
?- loadHelpers.
?- part01.
game
[2,-,x,x,x,x,x]
[x,x,-,x,-,x,x]
[x,3,x,-,x,-,x]
[x,-,4,x,x,x,x]
[x,x,-,x,x,-,x]
[x,x,x,1,-,x,x]
42
true
I'm honestly really lost and I'd appreciate any guidance as to where to begin, or even a process flow for this program. Many thanks!

(Prolog) How to find if a connection exists between 2 predicates

This is what I have so far. I need to show that if two stations are connected via a third station, they are connected to each other
station(hamburg).
station(bremen).
station(hannover).
station(berlin).
station(leipzig).
station(osnabruck).
station(stuttgart).
station(fulda).
station(munich).
adjacent(hamburg, bremen).
adjacent(hamburg, berlin).
adjacent(berlin, hannover).
adjacent(berlin, leipzig).
adjacent(leipzig, fulda).
adjacent(fulda, hannover).
adjacent(hannover, osnabruck).
adjacent(osnabruck, bremen).
adjacent(stuttgart, munich).
/* insert your clauses here */
adjacent_(X,Y) :-adjacent(Y,X) .
adjacent_(X,Y) :-adjacent(X,Y) .
connected(X,Y) :-adjacent(X,Y) .
connected(X,Z) :-connected(X,Y), adjacent_(Y,Z) .
Your first connected clause will fail for a clause like:
?- connected(bremen, hamburg).
Presumably you meant to write
connected(X,Y) :- adjacent_(X,Y) .
instead.
Other than the above bug, your code seems fine. The only thing I'd add is that you're not guarding against "cycles". E.g. if you were trying to find if berlin is connected to fulda, in theory you might never get there because of the following cycle:
berlin -> hannover -> osnabruck -> bremen -> hamburg -> berlin (and so on ad infinitum).
Therefore you could also include an accumulator in your code, containing all the nodes visited so far, such that you don't allow your clause to succeed if the current node already appears in your node "path".
PS. If you're only interested to find out whether X and Z are connected, and not in how many possible ways, you could also explicitly specify a cut (i.e. !) at the end of each connected clause.

Force Graphviz to complain for duplicate nodes

I just noticed that duplicate node names (even if labeled uniquely) get processed without complaint by Graphviz. For example, consider the following simple graph as rendered (with circo) in the image below:
graph {
a [label="a1"]
a [label="a2"]
b
c
d
e
a -- b;
b -- c;
a -- c;
d -- c;
e -- c;
e -- a;
}
I want the above graph to have two nodes: a1 and a2. So I know I should instantiate them with unique names (different than what I did above). But in a large graph, I may not notice that I mistakenly instantiated two different nodes with identical names. So if I do something like this, I'd like to force Graphviz to complain about it or bring it to my attention somehow, maybe with a warning or an error message.
How do I accomplish that?
All the graphviz programs silently merge nodes with duplicate names and I cannot find any way to have them produce a warning when they do that. Since we only have to find the cases where nodes are declared by themselves, however, rather than nodes that are implicitly declared when an edge is declared (in which case duplication is normal and expected), we just have to find all the node names and identify the duplicates.
If no more than one node is ever declared on a line, this could be done with the following script:
#!/bin/sh
sed -n 's/^[\t ][\t ]*\([_a-zA-Z][_a-zA-Z0-9]*\) *\(\[.*\)*;*$/\1/ p' | \
sort | uniq -c | awk '$$1>1'
If we call this script findDupNodes, we can run it as follows:
$ findDupNodes <duplicates.gv
2 a
The script finds node names that are either declared by themselves or with a list of attributes that starts with [, sorts them, counts how many times each is declared (with uniq -c) and filters out the ones that are declared only once.
Multiple nodes can be declared on a single line (e.g. a; b; c; d;) but this script does not handle that case, or (probably) some other cases -- most of which would probably require a full-blown xdot language parser.
Nevertheless, this script should find many of the duplicate node names that might find their way into hand-written graphviz scripts.

Why cant i get the answer to the zebra puzzle in prolog?

this is my code currently, I am trying to solve the zebra puzzle.
exists(A,(A,_,_,_,_)).
exists(A,(_,A,_,_,_)).
exists(A,(_,_,A,_,_)).
exists(A,(_,_,_,A,_)).
exists(A,(_,_,_,_,A)).
rightOf(A,B,(B,A,_,_,_)).
rightOf(A,B,(_,B,A,_,_)).
rightOf(A,B,(_,_,B,A,_)).
rightOf(A,B,(_,_,_,B,A)).
middleHouse(A,(_,_,A,_,_)).
firstHouse(A,(A,_,_,_,_)).
nextTo(A,B,(B,A,_,_,_)).
nextTo(A,B,(_,B,A,_,_)).
nextTo(A,B,(_,_,B,A,_)).
nextTo(A,B,(_,_,_,B,A)).
nextTo(A,B,(A,B,_,_,_)).
nextTo(A,B,(_,A,B,_,_)).
nextTo(A,B,(_,_,A,B,_)).
nextTo(A,B,(_,_,_,A,B)).
:- Houses = (house(N1,P1,S1,D1,C1),house(N2,P2,S2,D2,C2),house(N3,P3,S3,D3,C3),house(N4,P4,S4,D4,C4),house(N5,P5,S5,D5,C5)),
exists(house(english,_,_,_,red),Houses),
exists(house(spainish,dog,_,_,_),Houses),
exists(house(_,_,_,coffee,green),Houses),
exists(house(ukrainian,_,_,tea,_),Houses),
rightOf(house(_,_,_,_,green),house(_,_,_,_,ivory),Houses),
exists(house(_,dog,oldgold,_,_),Houses),
exists(house(_,_,kools,_,yellow),Houses),
middleHouse(house(_,_,_,milk,_),Houses),
firstHouse(house(norwegian,_,_,_,_),Houses),
nextTo(house(_,_,chesterfields,_,_),house(_,fox,_,_,_),Houses),
nextTo(house(_,_,kools,_,_),house(_,horse,_,_,_),Houses),
exists(house(_,_,luckystike,orangejuice,_),Houses),
exists(house(japanise,_,parliments,_,_),Houses),
nextTo(house(norwegian,_,_,_,_),house(_,_,_,_,blue),Houses),
exists(house(WaterDrinker,_,_,water,_),Houses),
exists(house(ZebraOwner,zebra,_,_,_),Houses).
I have typed this up and saved it as zebra.pl, this I open it and enter [zebra] into SWI-prolog, it returns a warning message about the singleton use of N1,P1,C1 etc.. and returns true, then i ask it to print water drinker using print(WaterDrinker) and it returns _G317 and true,
why is it doing this and not returning the answer which could be norwegian, it does the same if i ask it return any variable like C3 or ZebraOwner
The main problem is that you cannot write a goal like :- Houses = ... in the middle of your program. Rather, you should write something like
solution(WaterDrinker, ZebraOwner) :-
Houses = ...
and then after the program has been loaded type
solution(W, Z).
at the -? prompt to compute the solution.
You also don't specify that all the values should be distinct. If you do that you will use the variables a second time and the warning will go away.
If you really need a variable only once you can prepend it with an underscore to make the warning go away. Or you can just use an underscore, like you already did many times.

Resources