3

I am curious about pathfinding algorithms, so I took a look at Dijkstra's. I'm using this video as a guide (and it's what I'm basing my graph on). Here is the graph I am working from:

Image

I now want to be able to find all connections of a given vertex. I think that I should use findall for this, which I tried to use in the all_connections goal below. However, with main, my output is [b,b,b,b]. Why is that happening? That makes no sense. If you understand what I am doing wrong please let me know.

connection(s, c, 3).
connection(c, l, 2).
connection(l, i, 4).
connection(l, j, 4).
connection(i, j, 6).
connection(i, k, 4).
connection(j, k, 4).
connection(k, e, 5).
connection(e, g, 2).
connection(g, h, 2).
connection(h, f, 3).
connection(f, d, 5).
connection(d, a, 4).
connection(b, d, 4).
connection(b, a, 3).
connection(b, s, 2).
connection(b, h, 1).
connection(a, s, 7).

are_connected(A, B, Score) :-
    connection(A, B, Score);
    connection(B, A, Score).

all_connections(A, Z) :-
    findall(A, are_connected(A, _, _), Z).

main :-
    all_connections(b, X),
    write(X).
Caspian Ahlberg
  • 934
  • 10
  • 19
  • 3
    Note: I just solved my problem. Here was how I used `findall`: the first argument was the result from the goal that would be solved for each time, the second was the functor call, and the third was the result: `findall(Connected, are_connected(Node, Connected, _), Connections).` – Caspian Ahlberg Jan 15 '21 at 16:36
  • It's been some time I haven't seen fanfold paper (the last time in the office for building security, with the NEC pinwriter that goes with it) – David Tonhofer Jan 15 '21 at 17:03

2 Answers2

4

Congratulations on solving your problem. If you post the solution as an answer, we can upvote it.

This is a comment on something else: Since you are a relative beginner, now is the best possible time to learn good coding conventions. Specifically, this:

are_connected(A, B, Score) :-
    connection(A, B, Score);
    connection(B, A, Score).

is very bad. Prolog's disjunction is a very powerful, and often confusing, tool. When you use it, the use should really stick out. Otherwise it's easy to mistake your code for this:

are_connected(A, B, Score) :-
    connection(A, B, Score),
    connection(B, A, Score).

The way you have written this, the semicolon is very easy to miss at the end of a line. Rule of thumb: You should never use ; at the end of a line.

Alternatives:

are_connected(A, B, Score) :-
    connection(A, B, Score).
are_connected(A, B, Score) :-
    connection(B, A, Score).

(This transformation only works since the entire body of your definition is a disjunction.)

are_connected(A, B, Score) :-
    (   connection(A, B, Score)
    ;   connection(B, A, Score) ).

Or:

are_connected(A, B, Score) :-
    (
        connection(A, B, Score)
    ;
        connection(B, A, Score)
    ).

You get the idea. Each of these variants make it clear that what you are doing is very different from using conjunction.

Isabelle Newbie
  • 9,258
  • 1
  • 20
  • 32
  • 2
    As seen in [Coding Guidelines for Prolog](https://arxiv.org/abs/0911.2899) on page 10 of the PDF. – David Tonhofer Jan 15 '21 at 17:34
  • I still have the fervent wish that "Coding Guidelines for Prolog" were in a HTML page somewhere with commenting possibility instead of mummified inside a PDF on arxiv. – David Tonhofer Jan 15 '21 at 22:30
  • @DavidTonhofer There's https://www.arxiv-vanity.com/ for rendering arXiv papers as HTML, though it chokes on this one. And offers no commenting anyway. – Isabelle Newbie Jan 15 '21 at 23:04
2

Here is how I solved my problem:

are_connected(A, B, S) :-
    connection(A, B, S)
    ;
    connection(B, A, S).

Many thanks to Isabelle for giving me advice on proper conventions.

Caspian Ahlberg
  • 934
  • 10
  • 19