Algorithm 在n个人中查找最多(n/2)-1个说谎者的最快算法

Algorithm 在n个人中查找最多(n/2)-1个说谎者的最快算法,algorithm,find,compare,Algorithm,Find,Compare,以下是我的设想: 这个问题是用说谎者和说真话的人来描述的,但它在识别复杂系统的哪些组成部分是好的(功能正常)和哪些是错误的方面有实际的应用。假设我们有一个由n人组成的社区,我们知道一个整数tn/2的唯一最大群体。我将把它留给那些容易破坏家庭作业的问题来优化。你说说谎者可能会说真话,也可能会撒谎。在我看来,这使问题变得很困难。我在规范中提供了一个解决方案撒谎者总是撒谎的典型案例 让G成为感兴趣的群体。选择群体中的任意成员,X说。观察询问X的过程“是Y说谎者吗?”如果X和Y都是说真话的人或者都是说谎

以下是我的设想:

这个问题是用说谎者和说真话的人来描述的,但它在识别复杂系统的哪些组成部分是好的(功能正常)和哪些是错误的方面有实际的应用。假设我们有一个由n人组成的社区,我们知道一个整数t 我认为说真话的人总是诚实和正确的,说谎者可能会说出错误的答案或正确的答案

我们将通过连续挑选成对的人(X,Y)来识别社区中的说谎者,比如说,并询问X:Y是说谎者吗?。回答是“是”或“否”


最佳算法是什么(最少步数)要找到所有的说谎者?

如果你查询所有对,那么说真话的人将显示为大小>n/2的唯一最大群体。我将把它留给那些容易破坏家庭作业的问题来优化。

你说说谎者可能会说真话,也可能会撒谎。在我看来,这使问题变得很困难。我在规范中提供了一个解决方案撒谎者总是撒谎的典型案例


G
成为感兴趣的群体。选择群体中的任意成员,
X
说。观察询问
X
的过程“是
Y
说谎者吗?”如果
X
Y
都是说真话的人或者都是说谎者,则回答为“是”“否则。因此,通过询问
X
“Y是否是说谎者?”对于
G
中的每个
Y
(不包括
X
),您可以找出哪些成员
Y
X
在同一个“团队”中。事实上,说谎者必须多于说谎者,这允许您确定哪个“团队”
X
打开,之后很容易识别说谎者。

关于这个主题的一篇好论文是莱斯利·兰波特的《拜占庭将军问题》,可在


这不是一个直接的解决方案,但对感兴趣的人来说是一个很好的背景阅读。

具有最佳预期运行时间O(n)和优秀常数的随机算法:

  • 随手挑选
  • 询问其他人他是否撒谎,直到其中一个选项(是或否)的权重大于n/2(即,直到超过n/2的人给出相同的答案)。
    多数人决定(这是关键观察!)
  • 如果他不是一个说谎者,那么重复其余的人,只问他每个人是否都是一个说谎者(因为我们确定他说的是实话)
  • 如果他是个骗子,把他带出小组,回到1
  • 关键的观察结果是,如果我们询问每个人关于一个人的情况,大多数人的意见必须是正确的(因为大多数人都是讲真话的人)一个轻微的技术性问题是,如果我们先选择一个不说谎的人,然后问其他人,假设所有说谎的人都说谎,那么我们将达到50-50,那么我们如何决定哪一方说的是实话?这不是问题,因为如果我们首先选择一个不说谎的人,我们只能达到50-50,所以我们所讨论的人确实是一个说真话的人


    我们必须随机选择的预期人数是O(1)(这是这个问题中最重要的部分,因为这可能是家庭作业,我将跳过证明,但提示一个简单的证明:几何分布),这意味着我们将在O(1)*O(n)时间内找到我们的真相讲述者和可靠的来源,然后是另一个O(n)总的来说,O(n)。

    我的解决方案的伪代码,基本上与Davin的解决方案相同。一个显著的区别是,您只需要最大可能剩余说谎者+1的共识

    set unknown = all
    set known_true = {}
    set known_lie = {}
    
    while known_true.is_empty()
      voted_lie = {}
      voted_true = {}
      truth_votes = 0
      lie_votes = 0
      to_check = unknown.get(0)
      while truth_votes < t - known_lie.size() + 1 && lie_votes < t - known_lie.size() + 1:
        checker = unknown.get_next()
        if checker.is_liar(to_check):
          lie_votes++
          voted_lie.add(checker)
        else
          truth_votes++
          voted_true.add(checker)
    
      if truth_votes > t + 1:
        unknown.remove(to_check)
        known_true.add(to_check)
        known_lie.add_all(voted_lie)
        unknown.remove_all(voted_lie)
      else:
        unknown.remove(to_check)
        known_lie.add(to_check)
        known_lie.add_all(voted_true)
        unknown.remove_all(voted_true)
    
    
    while not unknown.is_empty() && known_liar.size() < t:
      to_check = unknown.get(0)
      if known_true.get(0).is_liar(to_check):
        unknown.remove(to_check)
        known_lie.add(to_check)
      else
        unknown.remove(to_check)
        known_true.add(to_check)
    
    set unknown=all
    设置已知_true={}
    集合已知_lie={}
    虽然已知,但为真。是否为空()
    投票表决_lie={}
    投票结果为_true={}
    真理票数=0
    lie_票数=0
    to_check=未知。获取(0)
    当真理投票t+1:
    未知。删除(要检查)
    已知\u为真。添加(到\u检查)
    已知谎言。添加所有谎言(投票谎言)
    未知。删除所有(投票表决)
    其他:
    未知。删除(要检查)
    已知谎言。添加(到检查)
    已知谎言。添加所有(投票为真)
    未知。删除所有(投票为真)
    虽然不是未知的。是否为空()&&known\u liar.size()
    问题出在哪里?如何识别说谎者?当然,如果说谎者可能说谎,也可能不说谎,那么没有最低的步骤数?你可能不走运,他们可能会在说谎之前任意说出很多次真相。此外,似乎暗示每个人都确切知道说谎者是谁;这是正确的吗?这看起来像是家工作。事实上,这似乎是Cormen等人在《算法导论》第87-88页中练习4-6(VLSI芯片测试)的一个变体。看这个:我只想问,“你是大象吗?”非常有趣的论文。感谢链接!很好的解决方案。你已经证明,说谎者不一定总是撒谎的规定并不会让问题变得更难。如果有n/2-1个说谎者,选择一个说谎者可能是一项困难的任务:假设我们在试图确定单个说谎者时总是选择说谎者。然后整个过程在O(n^2)中,而最优解在O(n)中。@Philip,预期运行时间!你熟悉预期的概率概念吗?