代码之家  ›  专栏  ›  技术社区  ›  Afonso Ramos

必须在Prolog中使用约束

  •  2
  • Afonso Ramos  · 技术社区  · 7 年前

    我目前正试图解决这个难题 houses 仅使用clpfd prolog库提供的约束,这意味着我不能使用回溯!

    我的输入是这样的坐标列表 [[0,0],[0,3],[2,0],[3,0],[2,1],[3,1],[2,2],[3,3]] 解决办法是:

    [
       [[0,0],[0,3]],
       [[2,0],[3,1]],
       [[2,1],[3,0]],
       [[2,2],[3,3]]
    ]
    

    我目前的进展是:

    connect(Houses):-
        %There are only 2 distances and they're different
        length(Distances, 2),
        all_distinct(Distances),
    
        %One connection per 2 houses (pairs) means half the number of houses as connections
        length(Houses, NHouses),
        NConnections #= NHouses // 2,
        length(Connections, NConnections),
    
        restrictDistances(Connections, Distances), %restrict every connection to have one of the two distances
    
    
        %All the houses must be connected
        append(Connections, ConnectedHouses),
        ensureAllConnected(Houses, ConnectedHouses), %table
    
        removeSymmetries(Connections), %avoid symmetries
    
        %flatten list and labeling
        append(ConnectedHouses, HousesCoordinates),
        labeling([], HousesCoordinates),
        write(Connections).
    
    /*
        All distances of all connections are one of the two distances
        Distance is kept squared to keep it an integer i.e. dist(connection) = dist([[x1, y1], [x2, y2]]) = (x2-x1)^2 + (y2-y1)^2
    */
    restrictDistances([], _).
    restrictDistances([[[X1, Y1], [X2, Y2]]|Connections], Distances):-
        DiffX #= X2 - X1,
        DiffY #= Y2 - Y1,
        Dis #= DiffX * DiffX + DiffY * DiffY,
        % element(Idx, Distances, Dis), %element
        member(Dis, Distances), %element
        restrictDistances(Connections, Distances).
    
    /*
        Ensures all houses are connected
    */
    ensureAllConnected([], _).
    ensureAllConnected([H|Houses], ConnectedHouses):-
        member(H, ConnectedHouses),
        % element(_, ConnectedHouses, H),
        ensureAllConnected(Houses, ConnectedHouses).
    
    /*
        Remove symmetries and connection permutations in final result
    */
    removeSymmetries([_]).
    removeSymmetries([[[X1, _], [X2, _]], [[X3, Y3], [X4, Y4]]|Connections]):-
        X1 #=< X2,
        X1 #=< X3,
        X3 #=< X4,
        removeSymmetries([[[X3, Y3], [X4, Y4]]|Connections]).
    

    最糟糕的是 然而,谓词 member 无法使用,因为它使用回溯。。。是的,谓词 element 存在,但无法替换为它,因为如果替换第一个,输出将不同,如果替换第二个,则会出现实例化错误。

    1 回复  |  直到 7 年前
        1
  •  4
  •   Mats Carlsson    7 年前

    对于这个谜题,考虑哪些子任务可以用全局约束编码是很有用的。以下是一些提示:

    • 你需要找到一个匹配的-可以用 assignment(Xs,Xs) .
    • 你可以用 table/2 编码 (房子,房子,距离) 关系
    • nvalue/2 约束 不同距离的数目。

    这些是SICStus Prolog中的全局约束。