2016-09-15 4 views
2

Я пытаюсь найти все пути в графе с минимальным расстоянием, используя DLV. Скажем, у меня есть следующий график:Найти кратчайший путь в DLV

graph

Я ожидаю получить предикаты (я надеюсь, что я не пропустить какой-нибудь):

  • путь (а, б, 1), путь (a, d, 1), путь (a, e, 1), путь (a, c, 2)
  • путь (b, a, 1), путь (b, c, 1), путь (d, d, 2), путь (b, e, 2)
  • путь (c, b, 1), путь (c, e, 1), путь (c, a, 2), путь (c, d, 3)
  • Путь (d, a, 1), путь (d, b, 2), путь (d, e, 2), путь (d, c, 3)
  • путь (e, a, 1), путь (e, c, 1) путь (e, d, 2), путь (e, b, 2)

Я предполагаю, что вы можете перемещать арку как влево, так и вправо. Итак, я попытался следующее:

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) 

Идея третьих правил, чтобы добавить 2 существующих пути, если они не собираются обратно (X = Z!) И есть уже не путь, соединяющий то же ребро с более короткое расстояние (не путь (X, Z, V), V < L, #int (V)). Мне пришлось добавить #int (V), потому что в противном случае это правило не было безопасным. Я не знаю, есть ли лучший способ решить эту проблему безопасности с целым значением.

Когда я запускаю этот код (с флагом -N = 5 для установки # maxint = 5), я получаю пути, которых не должно быть, например, путь (d, a, 5). Я не знаю, связана ли проблема с #int (V) или чем-то еще, но я не ожидал появления этих путей, поскольку у меня уже есть путь (d, a, 1). Вероятно, это из-за #int (V), но я не могу понять, как это сделать правильно.

Может ли кто-нибудь помочь мне решить эту проблему? Заранее спасибо.

+0

Я просто решил проблему нахождения пути с использованием списков в _path_ предикат, но все-таки я интересно знать, почему решение я вывешиваю здесь не работает – rutex

+0

Я также сумел придумать решение, основанное на входе @CapelliC. Я отправлю решение с и без списков, если кто-то заинтересован. – rutex

ответ

0

примеры/spaths.dl от DES распространение. См комментируемой ниже код ... -

% 
% 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. 
+0

Спасибо, что опубликовали ваше решение. Я использую DLV, и он не поддерживает «L is L0 + 1», но мне просто нужно было изменить «is» на «=», и он выполнил эту работу. Я не знаком с открытым каталогом, поэтому я не знаю, что должен делать _count_.Сохраняет ли количество ребер в _Max_? Во всяком случае, когда я выполнил этот код, я не получил путь от A -> B -> D, только пути расстояния 1. Также нет доказательств _spaths_. Не могли бы вы предоставить более подробную информацию? Кроме того, можете ли вы добавить к моим конкретным вопросам DLV? – rutex

+0

из книги автора (distribution/docs/manualDES.pdf), 'Обратите внимание, что бесконечное вычисление, которое может возникнуть из-за использования встроенного, равно 0, возникает , ограничивая общую длину пути количеством ребер в график .'. Поэтому я думаю, что да, 'count' делает то, что дает название. Это какая-то константа для этой проблемы, которая не меняет никаких данных. – CapelliC

+0

извините, у меня нет DLV, поэтому не могу помочь ... на случай, если вам интересно, SWI-Prolog имеет табуляцию, что - я думаю - может работать выше DES в основном без изменений. Было бы интересно сравнить ... – CapelliC

1

Решение проблемы с использованием списков для отслеживания пути:

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 без списков (с помощью 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. 

Обратите внимание, что мы должны определить все узлы с предикативного узла() и что предикат arc() предполагает, что край графика двунаправлен.

+0

Решение без списков не выполняет эту работу. Теперь я почти уверен, что мне нужно использовать списки, или невозможно получить все пути. – rutex