Prolog同构图

Prolog同构图,prolog,graph-theory,isomorphism,Prolog,Graph Theory,Isomorphism,试图解决同构图的问题 分配信息: 确定2个无向图是否同构 没有孤立的顶点 顶点数小于30 图的边作为谓词给出,即 e(1, 2). f(1, 2). 我尝试使用以下方法: 每对边(即图1和图2中的每条边) 尝试绑定两条边的顶点 如果无法绑定顶点(即,已存在与其中一个顶点的另一个绑定),则回溯并尝试另一对边 否则,添加绑定并继续处理其余的图(即,删除每个图的一条边并再次应用该过程) 除非两个图都为空(意味着所有顶点都从一个图绑定到另一个图),否则过程将递归,这意味着成功。 否则程序应始

试图解决同构图的问题

分配信息:

  • 确定2个无向图是否同构
  • 没有孤立的顶点
  • 顶点数小于30
  • 图的边作为谓词给出,即

    e(1, 2).
    f(1, 2).
    
我尝试使用以下方法:

  • 每对边(即图1和图2中的每条边)
  • 尝试绑定两条边的顶点
    • 如果无法绑定顶点(即,已存在与其中一个顶点的另一个绑定),则回溯并尝试另一对边
    • 否则,添加绑定并继续处理其余的图(即,删除每个图的一条边并再次应用该过程)
  • 除非两个图都为空(意味着所有顶点都从一个图绑定到另一个图),否则过程将递归,这意味着成功。 否则程序应始终失败(即没有其他可用的绑定组合等)

    我的代码似乎可以工作,但只适用于小图形(猜测,因为它会尝试所有对:))

    因此,如果有人知道如何优化代码(我相信可以插入几个剪切,并且
    try\u bind
    可以以更好的方式编写),或者可以提前告诉我们更好的方法,那就谢谢了

    另外,对于检查非同构,我知道我们可以检查不变量等。现在这并不重要

    代码:


    首先,我祝贺你对这个问题做了很好的介绍,并提出了详尽的解决方案

    在下一段中,我将讨论解决方案的实现细节

    不幸的是,我必须说,我不认为这种解决方案可以扩展到更大的规模。假设图有10条边<代码>iso_acc/4尝试将第一条边指定给第二条边中的任何一条边(10种可能性),第二条边也绑定到任何一条边(每个前一条边有10种可能性:10*10)。如果运气不好的话,那就是10^10的可能性,10!考虑到它们中的大多数会被修剪得更快

    次要意见如下:

    您可以跳过使用
    append(X,[],Y)
    ,因此

    bind([],[],MAP,RES) :- append(MAP,[],RES), !.
    
    可以是:

    bind([],[],MAP,MAP).
    
    try\u bind/3
    中的第二条和第三条规则似乎没有必要,在前一条规则中,您已经验证了没有
    b(X,Y)
    属于
    MAP
    。换句话说,
    成员(b(X,Y),MAP)
    相当于
    成员(b(X,Z,MAP),Z=Y

    附录

    让我们试试下面的方法。让示例图
    e
    为:

            +----3----+
    1 ---2--+    |    +---5
            +----4----+
    
            +----3----+
    2 ---5--+    |    +---1
            +----4----+
    
    f
    be:

            +----3----+
    1 ---2--+    |    +---5
            +----4----+
    
            +----3----+
    2 ---5--+    |    +---1
            +----4----+
    
    基本算法可以是:

    memb( X-A, [X-B|_] ) :- permutation(A,B).
    memb( X, [_|Q] ) :- memb(X, Q).
    
    match( [], _ ).
    match( [H|Q], G2 ) :-
      memb(H,G2),
      match(Q,G2).
    
    graph_equal(G1,G2,MAP) :-
      bagof( X, graph_to_list(G1,X), L1 ),
      length(MAP,40),
      bagof( X, graph_to_list_vars(G2,MAP,X), L2 ), !,
      length( L1, S ),
      length( L2, S ),
      match( L1, L2 ).
    
    从这个起点出发,可以进行优化

    该算法需要一些初始数据转换器,以将每个图形转换为
    节点-[peer1,peer2,…]
    形式的项目列表。此转换的规则是:

    bidir(G,X,Y) :- ( call(G,X,Y); call(G,Y,X) ).
    
    bidir_vars(G,MAP,VX,VY) :- 
       bidir(G,X,Y), nth0(X,MAP,VX), nth0(Y,MAP,VY).
    
    graph_to_list( G, N-XL ) :- 
      setof( X, bidir(G,N,X), XL).
    
    graph_to_list_vars( G, MAP, N-XL ) :- 
      setof( X, bidir_vars(G,MAP,N,X), XL).
    
    附录2

    本例的初始数据为:

    e(1,2).
    e(2,3).
    e(2,4).
    e(3,4).
    e(3,5).
    e(4,5).
    
    f(2,5).
    f(3,5).
    f(4,5).
    f(3,4).
    f(1,4).
    f(1,3).
    
    附录3

    现在使用示例图
    e
    f
    查询完整算法时,结果是:

    [debug]  ?- graph_equal(e,f,MAP).
    MAP = [_G2295, 5, 1, 3, 4, 2, _G2313, _G2316, _G2319|...] ;
    MAP = [_G2295, 5, 1, 4, 3, 2, _G2313, _G2316, _G2319|...] ;
    
    这意味着这些图是同构的,具有可能的节点映射
    e:[5,1,3,4,2]=>f:[1,2,3,4,5]
    e:[5,1,4,3,2]=>f:[1,2,3,4,5]

    附录4

    基本基准。单一解决方案:

    ?- time( graph_equal(e,f,_) ). 
    % 443 inferences, 0.000 CPU in 0.000 seconds (99% CPU, 1718453 Lips)
    
    所有解决方案:

    ?- time( (graph_equal(e,f,_),fail) ).
    % 567 inferences, 0.000 CPU in 0.000 seconds (99% CPU, 2027266 Lips)
    

    用另一种方法解决。代码已附加(算法在代码中)

    prev中的一些谓词。但案例仍然存在(如
    尝试绑定

    代码:

    %作者:丹尼斯·科雷科夫
    %算法说明:
    %G1是图1,G2是图2
    %E1是G1的边,E2是G2的边
    %V1是G1的顶点,V2是G2的顶点
    %0)检查图形是否可以同构(请参阅“初始验证”谓词)
    %1)拾取V1和一些V2并将其从顶点列表中删除
    %2)确保所选顶点均不在相对闭合列表中(否则继续,但将其删除)
    %3)绑定(映射)V1到V2
    %4)展开V1和V2
    %5)确保膨胀度相同
    %6)将展开结果附加到顶点列表的末尾并重复
    %在这里定义图谓词
    %图谓词结束
    %因为我们有无向边
    路1(X,Y):-e(X,Y)。
    路1(X,Y):-e(Y,X)。
    路2(X,Y):-f(X,Y)。
    路2(X,Y):-f(Y,X)。
    %返回图的所有顶点(非重复)
    图1_v(RES):-findall(X,way_g1(X,u),LS),节点(LS,[],RES)。
    图2_v(RES):-findall(X,way_g2(X,u),LS),节点(LS,[],RES)。
    %返回形式为“e(X,Y)”的图的所有边
    图1_e(RES):-findall(边(X,Y),e(X,Y),RES)。
    图2_e(RES):-findall(边(X,Y),f(X,Y),RES)。
    %返回顶点列表(删除列表中的重复顶点)
    %1-顶点列表
    %2-闭合列表(发现的顶点)
    %3-结果列表
    节点([],CL\u LS,RES):-append(CL\u LS,[],RES)。
    节点([X | Rest],CL|LS,RES):-not(成员(X,CL|LS)),节点(Rest,((X,CL|LS),RES)。
    节点([X | Rest],CL|LS,RES):-成员(X,CL|LS),节点(Rest,CL|LS,RES)。
    %必需谓词
    iso:-graph1_v(V1)、graph2_v(V2)、graph1_e(E1)、graph2_e(E2)、初始验证(V1、V2、E1、E2)、iso_acc(V1、V2、[]、[]、[]、[]、[]、uu)。
    %同上,但输出结果(输出结果绑定映射)
    iso_w:-图1_v(V1)、图2_v(V2)、图1_e(E1)、图2_e(E2)、初始验证(V1、V2、E1、E2)、iso_acc(V1、V2、[]、[]、[]、RES_MAP)、写入(RES_MAP)。
    %图至少可以同构的初步验证
    %检查顶点和边的数量以及度
    %1-G1的顶点
    %G2的2-顶点
    %3-G1的边
    %G2的4-边
    初始验证(X_V,Y_V,X_E,Y_E):-
    长度(X_V,X_VL),
    长度(Y_V,Y_VL),
    X_VL=Y_VL,
    长度(X_E,X_EL),
    长度(Y_E,Y_EL),
    X_EL=Y_EL,
    获取度序列g1(X_V,[],X_S),
    获取度序列g2(Y_V,[],Y_S),
    %比较度序列
    比较列表(X、Y)。
    %主算法
    %1-G1的顶点列表
    %2-顶点列表
    
     % ?- iso(ListArchiE,ListArchiF,ListNodiE,ListNodiF,Rel_archi).   
    
    e(a,b).
    e(b,c).
    e(b,d).
    e(a,c).
    e(d,a).
    
    f(50,10).
    f(10,11).
    f(11,50).
    f(10,45).
    f(11,45).
    
    iso(ListaArchiE,ListaArchiF,ListaNodiE,ListaNodiF,Rel_archi) :-
     findall((X,Y), e(X,Y), ListaArchiE),
     findall((X,Y), f(X,Y), ListaArchiF),
     setof(X, Y^(e(X,Y);e(Y,X)), ListaNodiE),
     setof(X, Y^(f(X,Y);f(Y,X)), ListaNodiF),
     !,
     rel_nodi(ListaNodiE,ListaNodiF,Rel_nodi),
     rel_archi(ListaArchiE,ListaArchiF,Rel_nodi,Rel_archi).
    
    rel_nodi([],[],[]).
    rel_nodi([Nodo_e|Resto_e], ListaNodiF, [(Nodo_e,Nodo_f)|R]) :-
     select(Nodo_f, ListaNodiF, Resto_f),
     rel_nodi(Resto_e, Resto_f, R).
    
    rel_archi([],[],_,[]).
    rel_archi([(Ep,Ed)|Resto_e],ListaArchiF,Rel_nodi,  [(e(Ep,Ed),f(Fp,Fd))|R]) :-
     select((Fp,Fd),ListaArchiF,Resto_f),
     member((Ep,Fp),Rel_nodi),
     member((Ed,Fd),Rel_nodi),
     rel_archi(Resto_e,Resto_f,Rel_nodi,R).