Prolog 层次无向图表示

Prolog 层次无向图表示,prolog,graph-theory,Prolog,Graph Theory,我需要这样表示图形: Graph = graph([Object1,Object2,Object3,Object4], [arc(Object1,Object2,connected), arc(Object2,Object4,connected), arc(Object3,Object4,connected), arc(Object1,Object3,connected),

我需要这样表示图形:

Graph = graph([Object1,Object2,Object3,Object4],
              [arc(Object1,Object2,connected),
               arc(Object2,Object4,connected),
               arc(Object3,Object4,connected),
               arc(Object1,Object3,connected),
               arc(Object2,Object3,parallel),
               arc(Object1,Object4,parallel),
               arc(Object2,Object3,similar_size),
               arc(Object1,Object4,similar_size)])
我对代码没有限制,但是我坚持使用这种表示法,因为它适合我已经编写的所有其他结构

我的意思是无向图,其中顶点是一些对象和表示它们之间无向关系的边。在这个特殊的例子中,为了给你们更多的背景知识,我试图表示一个矩形,所以对象是它的四条边(线段)。这些线段的表示方式与使用顶点等相同。重点是构建图的层次结构,它将表示同一级别上对象之间的约束

问题在于边的表示。表示弧(a,b)最明显的方法是将(a,b)和(b,a)都放在程序中。然而,这使我的程序充斥着指数级的冗余数据。例如,如果我有顶点a,b,c,d。我可以构建段(a,b),(a,c),(a,d),(b,c),(b,d),(c,d)。但我也得到(b,a),(c,a),等等。在这一点上,这不是一个问题。但后来我建立了一个矩形。它可以由段(a,b),(b,c),(c,d),(a,d)组成。我想得到答案-有一个矩形。你们可以计算出我得到的这个矩形的多少个组合。它也需要太多的时间来计算,显然我不想在矩形级别完成

我考虑过对元素进行排序。我可以对线段中的顶点进行排序。但是,如果我想在矩形中对线段进行排序,那么约束将不再有效。图形变得有方向。例如,考虑到前两个关系,假设我们有弧(a,b)和(a,c)。如果未对弧进行排序,程序将按我希望的方式回答:弧(b,a,已连接),弧(a,c,已连接),匹配:Object1=b,Object2=a,Object4=c。如果我对元素进行排序,它将不再有效,因为我无法尝试arc(b,a,已连接)和arc(a,b,已连接)。只有第二个。我会坚持分类,但我不知道如何解决最后一个问题

希望我把这一切都说得很清楚。我更愿意尽可能接近我已有的表现和想法。但全新的也非常受欢迎。我不希望得到任何确切的答案,而是指出我的方向正确,或者建议一些具体的阅读内容,因为我对Prolog非常陌生,也许这个问题并不像我想的那么罕见


从昨天开始我就一直在试图解决这个问题,但我想不出任何简单的答案。我研究了一些离散数学和常见的无向图表示,如邻接列表。如果有什么不清楚的地方,请告诉我-我会尽量提供更多的细节。

有趣的问题,虽然有点宽泛,因为它没有说明您实际想要对圆弧、矩形等做什么;仅在某些用途下,表示可能是有效的(时间/空间/优雅)。无论如何,这里有一些想法:

排序
最明显的问题就是你提到的那个问题;如果排序对存在,可以通过引入一个成功的子句来解决此问题:

arc(X,Y):-
    arc_data(X,Y)
  ; arc_data(Y,X).
请注意,您应该而不是执行以下操作:

arc(a,b).
arc(b,c).
arc(X,Y):-
   arc(Y,X)
因为如果弧不存在,这将导致无限循环。 但是,您只能检查第一个参数是否大于第二个参数:

arc(a,b).
arc(b,c).
arc(X,Y):-
   compare(>,X,Y),
   arc(Y,X)
这种方法无法解决由于圆弧以两种方式表示而可能出现的多个解决方案。 简单的解决方法是使用
一次/1
只检查一个解决方案,其中只有一个解决方案:

3 ?- arc(X,Y).
X = a,
Y = b ;
X = b,
Y = a.

4 ?- once(arc(X,Y)).
X = a,
Y = b.
当然,当可能存在多个解决方案时,您不能这样做

另一种方法是实施进一步的抽象:此时,当您有两个点(
a
b
)时,您可以在检查这些点是否连接后创建弧(
arc(a,b)
arc(b,a)
)。相反,您应该通过谓词创建圆弧(也可以检查点是否连接)。好处是您不再直接参与圆弧的表示,因此可以强制排序(是的,基本上是面向对象的):

(假设为数据库
arc(a,b)
):

当然,对于其他对象,您需要遵循类似的原则;我假设您正在这样做,以找到一个矩形:

rectangle(A,B,C,D):-
    arc(A,B),
    arc(B,C),
    arc(C,D),
    arc(D,A).
除了由于弧(已解析)而产生的重复,这将识别ABCD、DABC等不同的矩形:

28 ?- rectangle(A,B,C,D).
A = a,
B = b,
C = c,
D = d ;
A = b,
B = c,
C = d,
D = a ;
A = c,
B = d,
C = a,
D = b ;
A = d,
B = a,
C = b,
D = c.
我们将再次这样做:

rectangle(rectangle(A,B,C,D)):-
    cv_arc(A,B,AB),
    cv_arc(B,C,BC),
    compare(<,AB,BC),
    cv_arc(C,D,CD),
    compare(<,BC,CD),
    cv_arc(D,A,DA),
    compare(<,CD,DA).

请注意,如果圆弧顺序错误,我们不会对矩形重新排序;我们只是失败了。通过这种方式,我们避免了重复的解决方案(如果我们对它们进行排序并将其作为一个有效的矩形接受,我们将拥有相同的矩形四次),但是查找矩形所花费的时间增加了。我们通过在第一个无序的弧处停止搜索而不是创建整个矩形来减少开销。此外,如果对弧进行排序(因为将对第一个匹配进行排序),也会减少开销。另一方面,如果我们考虑以这种方式搜索所有矩形的复杂性,那么开销就不那么重要了。而且,它只适用于只需要第一个矩形的情况;如果我们想得到更多的解决方案或确保没有其他解决方案,prolog将搜索整个树,无论它是否报告解决方案。

有趣的问题,尽管有点宽泛,因为它没有说明您实际想要对圆弧、矩形等做什么;仅在某些用途下,表示可能是有效的(时间/空间/优雅)。无论如何,这里有一些想法:

排序
最明显的问题就是你提到的那个问题;如果排序对存在,可以通过引入一个成功的子句来解决此问题:

arc(X,Y):-
    arc_data(X,Y)
  ; arc_data(Y,X).
请注意,您应该而不是执行以下操作:

arc(a,b).
arc(b,c).
arc(X,Y):-
   arc(Y,X)
因为如果弧不存在,这将导致无限循环。 但是,您只能检查第一个参数是否大于第二个参数:

arc(a,b).
arc(b,c).
arc(X,Y):-
   compare(>,X,Y),
   arc(Y,X)
本美联社