在Prolog中实现顶点覆盖

时间:2018-04-18 04:09:10

标签: math graph prolog graph-theory np

我正在尝试在prolog中实现vertex covering。我在考虑做以下事情:

以下列格式[(VertexSouce/VertexDest), ...]使用图表,并在图表中传递多个总顶点。所以谓词看起来像vertexCover(NodeCount, Graph, MaxNodesInResult, Result)Result应小于MaxNodesInResult`

我得到了以下示例输出:

?- vertexCover(6,[(1/2),(1/3),(2/3),(2/4),(3/5),(4/5),(4/6)],3,L).
L = [1,3,4] ;
L = [2,3,4] ;
false.
?- vertexCover(6,[(1/2),(1/3),(2/3),(2/4),(3/5),(4/5),(4/6)],2,L).
false.

任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:3)

这应该是对Dartuso正确解决方案的评论,但它不适合。所以这里作为另一种选择。使用Dartuso的代码,您会得到重复的答案:

?- vertexCover(6,[(1/2),(1/3),(2/3),(2/4),(3/5),(4/5),(4/6)],3,L).
L = [1, 3, 4] ;
L = [1, 3, 4] ;
L = [2, 3, 4] ;
L = [2, 3, 4] ;
L = [2, 3, 4] ;
L = [2, 3, 4] ;
false.

获得重复的答案并没有错。但有时我们希望出于性能原因而避免使用它们,或者只是为了获得更好的输出。

在这种情况下,复制来自以下事实:单个边缘可以通过多种方式出现在封面中:

?- isIn([1, 3], (1/3)).
true ;
true ;
false.

这是因为Dartuso给出的isIn/2条款并不相互排斥。第一个和第二个子句都匹配此查询,这就是您获得两次成功的原因。

有几种方法可以“修复”这个问题。最干净的是添加条件以排除先前条款已涵盖的案例:

isIn([A|_],(X/_)) :-
    A = X.
isIn([A|_],(X/Y)) :-
    dif(A, X),
    A = Y.
isIn([A|T],(X/Y)) :-
    dif(A, X),
    dif(A, Y),
    isIn(T,(X/Y)).

这里dif/2谓词表达了不平等。因此,第二个子句在第一个子句中的等式已经涵盖的情况下不再能够成功,这消除了重复的成功和重复的答案:

?- isIn([1, 3], (1/3)).
true ;
false.

?- vertexCover(6,[(1/2),(1/3),(2/3),(2/4),(3/5),(4/5),(4/6)],3,L).
L = [1, 3, 4] ;
L = [2, 3, 4] ;
false.

一个不太好的解决方案使用“if-then-else”构造Condition -> TrueBranch ; FalseBranch,这不是没有问题的(但非常实用!):

isIn([A|T],(X/Y)) :-
    (   A = X
    ->  true
    ;   A = Y
    ->  true
    ;   isIn(T, (X/Y)) ).

或者,正如我在实践中写的那样:

isIn([A|T],(X/Y)) :-
    (   ( A = X ; A = Y )
    ->  true
    ;   isIn(T, (X/Y)) ).

使用后一种解决方案,上面的查询只会成功一次,甚至不会留下选择点:

?- isIn([1, 3], (1/3)).
true.

有了这个,整个谓词也不再有重复的答案:

?- vertexCover(6,[(1/2),(1/3),(2/3),(2/4),(3/5),(4/5),(4/6)],3,L).
L = [1, 3, 4] ;
L = [2, 3, 4] ;
false.

在这种特殊情况下,if-then-else只会删除不需要的重复解决方案,但一般情况下它可以消除您想要的解决方案。小心使用。

(其他人可能会告诉你使用剪切运算符!/0,因为它比某些解决方案更短。不要让步。更短的代码不会自动更好的代码,并且削减使你的代码特别复杂和困难理解和修改。)

答案 1 :(得分:2)

这是一个有效的解决方案,感谢Isabelle的修复!正如她提到的另一个解决方案,我发现在第二行封面/ 2上添加了一个剪切,但她的解决方案更清晰。

var visited = sessionStorage.getItem('visit');
if (visited == null || document.location.href == sessionStorage.getItem('lastPage')) {
    setTimeout(function() { 
    alert('Hello World')
        }, 10000
  )
    sessionStorage.setItem('visit', 1);
  };