2

I am trying to find all the paths in a graph with minimum distance using DLV. Say I have the following graph:

graph

I am expecting to obtain the predicates (I hope I don't skip any):

  • path(a, b, 1), path(a, d, 1), path(a, e, 1), path(a, c, 2)
  • path(b, a, 1), path(b, c, 1), path(d, d, 2), path(b, e, 2)
  • path(c, b, 1), path(c, e, 1), path(c, a, 2), path(c, d, 3)
  • path(d, a, 1), path(d, b, 2), path(d, e, 2), path(d, c, 3)
  • path(e, a, 1), path(e, c, 1), path(e, d, 2), path(e, b, 2)

I assume that you can travel an arch both left or right. So, I tried the following:

path(X, Y, 1) :- arc(X, Y).
path(Y, X, 1) :- arc(X, Y).
path(X, Z, L) :- path(X, Y, M), path(Y, Z, N), 
                 X!=Z, 
                 L = M + N,
                 not path(X, Z, V), V < L, #int(V) 

The idea of the third rule was to add 2 existing paths if they are not going back (X!=Z) and there is not already a path connecting the same edges with a shorter distance (not path(X, Z, V), V < L, #int(V)). I had to add #int(V) because otherwise the rule was not safe. I don't know if there is a better way of resolving this safety issue with an integer value.

When I run this code (with the flag -N=5 to set #maxint=5) I get paths that should not be there, for example, path(d,a,5). I don't know if the problem is with the #int(V) or something else but I wouldn't expect these paths to appear since I already have a path(d,a,1). Probably it is because of #int(V) but I can't figure out how to do this right.

Can anyone help me solve this? Thanks in advance.

false
  • 10,264
  • 13
  • 101
  • 209
rutex
  • 137
  • 3
  • 12
  • I have just solved the problem of finding the path using lists within the _path_ predicate but still I am interested in knowing why the solution I am posting here does not work – rutex Sep 15 '16 at 09:28
  • I have also managed to come up with a solution based on the input by @CapelliC. I will post the solution with and without lists in case anyone is interested – rutex Sep 16 '16 at 06:18

2 Answers2

1

Solution to the problem using lists to keep track of the path:

path(X, Y, [X, Y], 1) :- arc(X, Y).
path(Y, X, [Y, X], 1) :- arc(X, Y).
path(X, Z, P, D) :- path(X, Y, P1, D1),
                    path(Y, Z, P2, 1),
                    #insLast(P1, Z, P), 
                    D = D1 + 1,
                    not #member(Z, P1).
shortest_path(X, Y, D) :-   node(X), node(Y), 
                            #min{L: path(X, Y, P, L)} = D.                  

Solution without the need of lists (with the help of CapelliC)

path(X, Y, 1)   :-  arc(X,Y).
path(Y, X, 1)   :-  arc(X,Y).
path(X, Y, D)   :-  path(X,Z,D0), arc(Z,Y),
                    #count{A: node(A)} = Max,
                    D0<Max, X != Y,
                    D = D0+1.

shorter_paths(X, Y, D) :- node(X), node(Y), 
                          #min{L: path(X, Y, L)} = D.

Note that we need to define all nodes with a predicate node() and that the predicate arc() assumes that the edge of the graph is bidirectional.

Community
  • 1
  • 1
rutex
  • 137
  • 3
  • 12
  • The solution without lists does not do the job. Now I am almost certain that I need to use lists or it is impossible to get all the paths. – rutex Sep 20 '16 at 09:18
0

examples/spaths.dl from DES distribution. See the commented code below... -

%
% Shortest Paths in a Graph
%
% Datalog Formulation
%
% Program: Shortest paths in a graph
% Author : Fernando Sáenz-Pérez
% Date   : September, 2009

edge(a,b).
edge(a,c).
edge(b,a).
edge(b,d).

path(X,Y,1) :- 
  edge(X,Y).
path(X,Y,L) :-
  path(X,Z,L0),
  edge(Z,Y),
  count(edge(A,B),Max),
  L0<Max,
  L is L0+1.

spaths(X,Y,L) :-
   min(path(X,Y,Z),Z,L).


% Note that the following is not stratifiable in DES

%sp(X,Y,1) :- 
%  edge(X,Y).
%sp(X,Y,L) :-
%  sp(X,Z,L0),
%  not(shorter(X,Z,L0)), 
%  edge(Z,Y),
%  L is L0+1.

%shorter(X,Y,L) :-
%  sp(X,Y,L0),
%  L0<L.
CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • Thanks for posting your solution. I am using DLV and it doesn't support "L is L0 + 1" but I had just to change "is" to "=" and it did the job. I am not familiar with plain datalog so I don't really know what _count_ is supposed to do. Does it store the number of edges in _Max_ ? Anyway, when I executed this code I didn't get the path from A -> B -> D, only paths of distance 1. Also, there is no evidence of _spaths_. Can you please provide more details? Also, can you add up to my particular DLV questions? – rutex Sep 15 '16 at 13:43
  • from the author book (distribution/docs/manualDES.pdf), `Note that the infinite computation that may raise from using the built-in is/2 is avoided by limiting the total length of a path to the number of edges in the graph.`. So I think that yes, `count` does what it's name suggests. It's kind of a constant for this problem, that doesn't change any data – CapelliC Sep 15 '16 at 14:00
  • sorry, I don't have DLV available, so cannot help ... in case you're interested, SWI-Prolog has tabling, that - I think - could run the above DES mostly unchanged. Would be interesting to compare... – CapelliC Sep 15 '16 at 14:02
  • Thanks again for your replies. I have been abled to adapt the code to my needs without much effort. I will post a solution in DLV based on your input :-) – rutex Sep 16 '16 at 06:16