寻求用于计算Smith和Schwartz集的伪代码

时间:2019-04-04 14:47:08

标签: algorithm pseudocode voting

我已阅读Smith SetSchwartz SetKosaraju's AlgorithmTarjan's Algorithmpath-based strongly component algorithms上的Wikipedia;但是,我对此类算法的经验不足。维基百科还说,您可以使用Kosaraju算法的版本来生成Schwartz集,并且这些算法可以计算Smith集。

Wikpedia也有一些针对Tarjan算法的伪代码,而其他的则没有。它并不特定于此相对敏感的应用程序。我也不确定100%是最容易实现的,它具有实现错误可能性最小的特征。

我想要一些更直接的伪代码来涵盖从这些算法中的一种算法计算Smith和Schwartz集合的情况,并给出一组有等级的选票。当我有一个实际的过程可以走路时,我发现更容易掌握概念。我自己将其转换为实际代码。

请考虑以下数据结构:

Type Ballot {
  Array Votes[] {
    Candidate Candidate; // We do this in C#
    int Rank;
  }
}

对于一个选票集合,每个单独的选票将包含一个数组选票,如下所示:

Ballot b.Votes[] =
  [ Vote(Alex.ID, 1),
    Vote(Chris.ID, 3),
    Vote(Sam.ID, 2) ];

这对应于投票者Alex>Sam>Chris,并且可能还有其他候选人比克里斯受到同样的青睐。

我认为第一步将是汇总个人选票并确定获胜情况。例如:如果100个投票者将Alex排在Sam之上(Alex = 1,Sam> = 2),而50个投票者将Sam排在Alex之上,则Alex击败了Sam。因此,我猜想会有这样的数据结构:

Type GraphNode {
  Candidate Candidate;
  GraphNode Array Defeats[];
  GraphNode Array Ties[];
  GraphNode Array DefeatedBy[];
}

因此,Alex的GraphNode在Defeats[]中将有一个元素指向Sam的GraphNode,反之亦然。

鉴于这些GraphNode,我该如何使用它来识别Smith和Schwartz集?

谢谢。

1 个答案:

答案 0 :(得分:1)

我想python已经足够接近伪代码了。

假设我们有n个候选人,编号从0n - 1

首先,如果候选人beats[i][j]胜过候选人True,而矩阵i胜过j,则可以计算等于False的矩阵for k in range(n): for i in range(n): for j in range(n): beats[i][j] = beats[i][j] or (beats[i][k] and beats[k][j])

现在使用Floyd-Warshall算法计算矩阵的传递闭合:

beats[i][j]

此后,矩阵的含义略有不同:i -> c1 -> c2 -> ... -> j表示存在“拍子路径” i,使得c1拍子c1c2胜过j,依此类推,直到i

Schwartz组件是所有对ji都具有双向运行的跳动路径,并且没有其他候选者可以击败任何一个(请参阅Wikipedia上有关属性的部分提到顶部循环)。

基本上针对每个候选人schwartz_components = [] for i in range(n): schwartz_component = {i} is_schwartz = True for j in range(n): if beats[j][i]: if beats[i][j]: schwartz_component.add(j) else: is_schwartz = False if is_schwartz: schwartz_components.append(schwartz_component) schwartz_set = set.union(*schwartz_components) print(schwartz_set) ,尝试围绕它构建一个组件,如下所示:

cannot_beat[i][j] = not beats[i][j]

对于史密斯集,它会有所不同,您需要从i开始,在其上使用Floyd-Warshall,然后通过添加所有候选项围绕每个cannot_beat构建集通过smith_candidates = [] for i in range(n): smith_candidate = {i} for j in range(n): if cannot_beat[i][j]: smith_candidate.add(j) smith_candidates.append(smith_candidate) # Take the smallest candidate smith_set = min(smith_candidates, key=len) 关系到它的路径。

我想它会变成这样(在Floyd-Warshall步骤之后):

OSError[errno 2]

某处可能存在一个错误,但这大概就是这个想法。