共线点的所有子集 - Prolog

时间:2016-12-09 17:29:05

标签: prolog backtracking points

我正在尝试在Prolog中制作一个回溯程序,以确定所有共线点的子集。 问题:在计划中给出n个点(使用其坐标表示)。 写一个谓词来确定所有共线点的子集。

示例:

输入:[[1,1],[2,2],[3,3],[0,0],[4,8],[1,2],[6,7],[8 ,9],[10,11]]

输出:[[[1,1],[2,2],[3,3]],[[1,1],[2,2],[0,0]],[[2, 2],[3,3],[0,0]],[[1,1],[3,3],[0,0]],...]

到目前为止,我通过检查这个公式来检查3点是否共线:  (Xc - Xa)/ (Xb - Xa) = (Yc - Ya)/ (Yb - Ya).

但是,我认为这不会起作用,因为我需要使用回溯来解决问题。我应该在每个函数调用中选择一个候选者,看它是否与其余函数匹配。

你能否建议我检查3点是否共线?

1 个答案:

答案 0 :(得分:1)

我假设您的程序查询类似于:

?- findColinears([[1,1],[2,2],[3,3],[0,0],[4,8],[1,2],[6,7],[8,9],[10,11]], Out).

显然我不会提供代码来解决整个问题,但一般来说,自上而下的方法可能涉及如下谓词:

colinear( P1, P2, P3 ) :- slope( P1, P2, S ), slope( P1, P3, S ).
colinear( P1, P2, P3 ) :- slope( P1, P2, S ), slope( P2, P3, S ).
colinear( P1, P2, P3 ) :- slope( P1, P3, S ), slope( P2, P3, S ).

slope( P1, P2, S ) :-
  P1 = p( X1, Y1 ),
  P2 = p( X2, Y2 ),
  S is ((Y2-Y1)/(X2-X1)).

findColinearTriplet( ListOfPoints, Triplet ) :-
  member( P1, ListOfPoints ),
  member( P2, ListOfPoints ), dif(P1, P2),
  member( P3, ListOfPoints ), dif(P1, P3), dif(P2, P3),
  colinear(P1, P2, P3),
  Triplet = [P1, P2, P3].

然后,您可以使用这些来查找所有可能的Triplet个统一信息 当然,一些三元组是等价的(例如[p(1,1), p(2,2), p(3,3)][p(3,3), p(1,1), p(2,2)])。此外,一些将重复。如果您需要独特的三元组,则必须从收集的所有非唯一三元组中手动构建此类唯一列表。

例如,您的最终findColinears谓词可能类似于:

findColinears( ListOfPairs, Out ) :-
  convertToPoints( ListOfPairs, ListOfPts ),
  findall( Triplet, findColinearTriplet(ListOfPts, Triplet), ListOfTriplets),
  discardDuplicates( ListOfTriplets, Out ).

用于适当定义的convertToPointsdiscardDuplicates谓词。