我目前的任务是在数据库系统中实现CCL算法(用C ++编写)。该算法将为超过阈值的给定多维数组的所有值分配标签,并且相邻的标记值将具有相同的标签。
编写基本的CCL算法并不困难,但在我的域中,输入数组是在数据库的多个实例中随机分区的。当我的CCL操作符被调用时,每个实例对它负责的数据块执行操作并返回其本地CCL结果。然后合并这些本地结果以产生最终结果。
我不知道在运行时哪个实例负责数组的任何给定部分,并且实例在最后的合并步骤之前无法相互通信。
- = - = - = -
目前,我通过以下方式开展此工作:
每个实例都会创建一个大小等于的布尔值数组 数组中的项目数,并将所有值设置为FALSE。
每个实例都会遍历它负责的值和 检查这些值是否超过阈值;如果他们是,他们 将其本地数组中相应的布尔值更改为TRUE。
实例都将其数组发送给协调器 使用OR组合结果以创建最终的布尔向量。
协调器遍历数组中的每个值,跳过 已标记的值。如果该值未标记并且 与该值对应的布尔值为true,它为其赋值 新标签并递归地分配其所有邻居(和 邻居的邻居等)相同的标签。
返回标签矢量。
上述算法有效,但唯一利用多个实例的是阈值计算。因为这个实现只是收集所有内容并在协调器上进行扫描,所以它首先打败了使用多个实例的重点。
- = - = - = -
本质上,这种算法是自动制成分而治之的算法,但这些划分是完全不可控制的随机。
我们希望通过在每个实例上执行CCL扫描,然后在协调器上组合这些本地CCL结果来利用这种划分;也就是说,如果两个实例产生彼此相邻的标签组,我们希望将这两个标签组合在一起,而不再扫描每个值。这个斜体点是给我们带来最多麻烦的,而且我们很遗憾如何继续前进。如果有人对算法或数据结构提出了很好的建议,那将非常感激。
答案 0 :(得分:0)
邻接连接组件(与图形连接组件相对)需要检查所有相邻(相邻像素)对的集合。
即,
{ ((x1, y1), (x2, y2)) }
为此
(abs(x2 - x1) + abs(y2 - y1)) <= 1
和(x1 != x2 && y1 != y2)
max(abs(x2 - x1), abs(y2 - y1)) <= 1
和(x1 != x2 && y1 != y2)
理解的下一步需要知道Equivalence relation。值得注意的是,它必须满足:
这三个要求有一个有趣的结果:
需要注意的是,下面将讨论的“Disjoint-Set”的算法接口正是等价关系列表。因此,可以不同地处理这个等价关系列表,并且仍然得到相同的结果。
要表示和描述计算和处理连接组件的算法,应该研究Disjoint-Set。
我们应该学习Disjoint-Set的实际实现,并了解它是如何从连接组件算法中实际使用(调用)的。
之后,应该提高理解的抽象级别 - Disjoint-Set的抽象概念(算法接口)。在学习了这个抽象之后,您将能够以不寻常的方式重新实现Disjoint-Set 。
Union
函数。Find
功能仅在Union
功能中使用。Union( (x1, y1), (x2, y2) )
消息调用流提供接收器来抽象出Disjoint-Set的操作。Union
的冗余调用,因为在排队呼叫之前不会检查两个节点是否已经是相同的标签。这个问题将在下一部分讨论。现在我们将介绍一种安排这些Union
消息进行处理的方法。
假设节点分布在不同的机器上。
{ ((x1, y1), (x2, y2)) }
对进行分区:
要在不同的机器上处理Union-Find,只需一个
*从相同机器对的相邻像素对生成Union
消息
*然后,过滤Union
消息以删除多余消息。
*从不同机器对的相邻像素对生成Union
消息。
*在同一台机器消息的结果上执行不同的机器消息。
这个答案是以过于抽象的方式写的,因为更具体的答案需要更多关于问题的细节,特别是关于“完全和不可控制的随机分区”的部分。