1. 程式人生 > >拜占庭將軍問題。口頭演算法OM(n.m);n=3m+1

拜占庭將軍問題。口頭演算法OM(n.m);n=3m+1

一、拜占庭問題的背景這裡就不再介紹直接說演算法

下面的這個截圖是從Lamport發表的論文中擷取的:


對於這個演算法需要說明的是:

(1) 在第一輪 將軍會把訊息傳送給所有的副官,第i個副官收到的記為 Vi。如 1(這裡代表的是Attack)

(2) 在第二輪裡面,Li(即第i個副官)會懷疑將軍發來的訊息Vi是對還是錯,於是他會問其餘的副官。這樣他就會得到剩下的(n-2)個副官的值。 i從1到n-1,所以每個副官都會得到剩餘的n-2個副官手裡的Vi。在這一步驟裡,忠誠的副官j會直接將自己的 Vj傳送給其它人。叛徒則會發假訊息。

在n=7,m=2的時候 如果將軍是忠臣的話,那麼在第二輪忠誠的副官確實已經可以判斷出要做的決定

,因為他們會收到(1 1 1 0 0 )再加上將軍發來的1就是 1 1 1 1 0 0 但是這個演算法是遞迴的所有必須要到第三輪。並且如果將軍是個叛徒的話,那麼第二輪有情形是做不出決定的。

這裡對進入第三輪的解釋是,如L1收到其它L2~L6發來的Vj, 但是他要懷疑準確性,比如L1會想L2發給自己是否是正確的呢?那麼就進入第三輪進行投票。

(3)在第三輪裡面,接著(2)中後面的問題。L1會依次詢問L3,4,5,6 ,問他們上一輪L2給他們發了什麼,然後L1會得到在(2)中 L2->L3, L2->L4,L2->L5, L2->L6的值 這樣再結合自己的L2->L1的值,從這5個裡面用majority函式投出決定得到L2發給自己的訊息值

。依次再進行L3,L4,L5,L6在第二輪中發給自己的訊息的確認。

這樣L1就完成了第二輪的確認。之後L1再從第一步中將軍發給自己的vi和第二輪中確定的5個值中投出自己的決定。

其餘的L2,L3.等等也進行同樣的步驟。

二、好像演算法是挺繞的,如果還是沒清晰的話,直接看下面的過程:


這裡需要注意的是:Lamport提出的容錯的兩個條件

IC1:即所有的忠誠的副官要遵守同一個命令,即達成一致;

IC2:假如將軍是忠誠的,那麼每一個忠誠的副官都應該按照將軍的意思行事。

這裡將軍是叛徒,所以只要滿足IC1條件即可。

Step1 : C給L1~L6 依次發 A R A R A x  (A,R代表攻擊和撤退,這裡因為C是叛徒,所以可以隨便發給L1-L5訊息,這裡只是一個例子,可以用其他的值,只要最後滿足IC1就可以)

截圖是Step2: 


Step3:其實在第三步中 L1會依次確認在step2中, L2~L6發給自己的資訊. 例如確認L2時 會問L3-L6,在Step2中L2發給你們了什麼

最後得到 R, R, R,X (因為L6這時候肯定又說謊) 再結合自己的R , L1確定在Step2中收到L2發來的是R,之後又確認了L3-L6。大家可以自己在草稿紙上畫出。

其實因為L1-L5都是忠誠,他們不會在Step2中撒謊,所以只需投票L6即可 ,(A R A R A )是L6發給L1-L5的資訊,最後投出發的是A , 將A修改到step2中L1-L5收到的

資訊中其餘的資訊可以不用改。

最後得到L1-L5均是 4個A, 2個R。 以L1為例=R A  R  A  A  A 

即L1~L5達成了一致。

三、下面來看簽名時候的情形:(詳細的關於簽名的演算法見下一篇部落格)


在lamport的論文中提到:

簽名就是說每次傳送資訊都要簽署上自己的名字,然後再發給別人。而別人只可以在這條訊息上覆制然後再轉發出去。這樣就變的簡單了,

而且

1)忠誠司令的簽名不可偽造,內容修改可以被檢測出來。

2)任何人都可以識別司令的簽名,叛徒可以偽造叛徒司令的簽名。

四、下面來看相關的證明。

證明1: 為什麼在沒有簽名的情況下,n>3m即可容錯?

在Lamport的論文中,在證明OM(m)在最多隻有m個叛徒,以及超過3m個將軍的時候可以滿足IC(1)和IC(2)條件的時候,先引入了一個引理:

LEMMA1:對於任意m 和k ,如果有超過2k+m 個將軍和最多k 個背叛者,那麼演算法OM(m) 滿足IC2 (回顧下IC2 指的是,如果將軍是忠誠的,所有的副官遵守將軍命令)。

證明:(1)當m=0的時候,如果將軍是忠誠的,因為在OM(0)的時候忠臣會遵守將軍發來的命令。而此時的將軍是忠臣的所以,即滿足IC2

      (2)當m>0的時候。用數學歸納法,通過證明OM(m-1)有效來證明。因為假設了n>2k+m,在OM(m-1)時剩餘的將軍數是n-1,但是叛徒數仍然是k(因為上1輪中的將軍是忠臣),n>2k+m -> n-1>2k+m-1. 又m-1>=0 -> n-1>2k. 即在OM(m-1)中有忠誠的副官比叛徒多,所以可以投票得出正確結果。在O(m-1)時可證。

接著證明“證明1”中的問題:

證明:通過m的歸納法證明,我們通過假設OM(m-1) 成立來證明OM(m) m>0。

(1)首先考慮傳送命令的將軍是忠誠的。那麼將引理中k 設為m 則OM(m) 滿足IC2 ,IC1 在發令將軍是忠誠的情況下也滿足。 

(2)如果傳送命令的將軍是叛徒。那麼在下一輪中,總共有3m個副官,其中有m-1個副官是叛徒,有3m-(m-1)=2m+1個忠臣,

2m+1>m-1 即 在這裡所有的忠臣是可以達成一致的(這一步是為了說明OM(m-1)是成立的)。下面再推出OM(m-1)的表示式:這裡除去要傳送命令的一個將軍外還有超過3m-1個,有3m-1>3(m-1) 即 n'>3m',所以在OM(m-1)是滿足條件的,得證。 

在這裡也同時證明了為什麼是m+1輪交換。因為OM(m)滿足。m->0 共 m+1;

相關推薦

拜占庭將軍問題口頭演算法OM(n.m);n=3m+1

一、拜占庭問題的背景這裡就不再介紹直接說演算法: 下面的這個截圖是從Lamport發表的論文中擷取的: 對於這個演算法需要說明的是: (1) 在第一輪 將軍會把訊息傳送給所有的副官,第i個副官收到的記為 Vi。如 1(這裡代表的是Attack) (2) 在第二

【分散式共識二】拜占庭將軍問題----口頭協議

拜占庭將軍問題是一個共識問題: 首先由Leslie Lamport與另外兩人在1982年提出,被稱為The Byzantine Generals Problem或者Byzantine Failure。核心描述是軍中可能有叛徒,卻要保證進攻一致,由此引申到計算領域,發展成了一種

給定2個數字,n,m,使得從1n之間的數字組合,他們的和等於m,求所有組合

這個題目也是非常經典的問題,把一個數字分解成多個數字的組合之和,問有多少種可能,並輸出。 微軟比賽題目,對於這類題目,最為簡單的版本就是,給定一個排好序的數字,求,這個陣列中的任意兩個數字之和,等於給定的值。 這個就相對比較,簡單,2個指標,移動他們的位置,和比給定的大,指

hdu1017媽的格式錯誤,注意while(cin>>n>>m,n+m)

#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <sstream> #include <

還需要註冊的是我們還有一個是“交差集”?cross?join,?這種Join沒有辦法用文式圖表示,因為其就是把表A和表B的數據進行一個N*M的組合,即笛卡爾積表達式如下:

笛卡爾 tab 表達 但是 rom 產生 OS 是我 語法 還需要註冊的是我們還有一個是"交差集" cross join, 這種Join沒有辦法用文式圖表示,因為其就是把表A和表B的數據進行一個N*M的組合,即笛卡爾積。表達式如下: SELEC

【死磕演算法1刷Leetcode】——找出兩個有序陣列的中位數【Median of Two Sorted Arrays】O(log(m+n))

Median of Two Sorted Arrays 題目難度:hard 題目要求: There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two s

給定一個m*n的格子或棋盤,問從左上角走到右下角的走法總數(每次只能向右或向下移動一個方格邊長的距離

比如一個2*3的矩陣, 1 2 3 4 5 6 從1出發走到6,則可能的走法為:1 2 3 6, 1 2 5 6, 1 4 5 6共有三種。 這道題可以看成是深度優先遍歷一顆樹。解法為: public class MatrixTraversal { public s

給出一個m*n的矩陣,求左上角到右下角的距離的最小值

問題描述 這是一個商湯科技筆試題的變形,大致是給出一個m*n的矩陣,矩陣裡的數代表其他相鄰格到此格的距離,且只能向右和向下走,求左上角到右下角的距離的最小值。 例: 0 1 9 3 5 2 6 8 7 這個例子的最短距離是0-1-5-2-7,結果是15。 這個真

劍指offer第32題JS演算法:輸入一個整數n,求從1nn個整數的十進位制表示中1出現的次數例如輸入12,從1到12這些整數中包含1的數字有1,10,11和12,1一共出現了5次

題目:輸入一個整數n,求從1到n這n個整數的十進位制表示中1出現的次數。例如輸入12,從1到12這些整數中包含1的數字有1,10,11和12,1一共出現了5次 這是我某一次去朋友公司面試試水時出的面試題,結果給我五分鐘我寫了個for迴圈的方法,被狠狠鄙視/哭笑不得 結果回來後好奇就跟同事

ACMNO.14一球從M米高度自由下落,每次落地後返回原高度的一半,再落下 它在第N次落地時反彈多高?共經過多少米? 保留兩位小數 輸入 M N 輸出 它在第N次落地時反彈多高?共經過多少米

題目描述 一球從M米高度自由下落,每次落地後返回原高度的一半,再落下。 它在第N次落地時反彈多高?共經過多少米? 保留兩位小數 輸入 M N 輸出 它在第N次落地時反彈多高?共經過多少米? 保留兩位小數,空格隔開,放在一行 樣例輸入 1000 5

“穩定婚姻演算法”雨夜談-M/N資源匹配問題

一個很不錯的演算法,穩定婚姻演算法。 先給出一個概念,來自百度百科: 穩定婚姻問題:https://baike.baidu.com/item/穩定婚姻問題/12760040 再給出一篇部落格連結: 什麼是演算法:如何尋找穩定的婚姻搭配:http://www.matrix67.com/blog

排列組合數C(m,n)的O(n)演算法

剛開始,想用它的定義來做 C(m,n) = m!/(m-n!*n!) 但是發現如果用int的話,階乘的運算到13就爆int了,所以算這個不要寫一個階乘函式然後讓他們運算,而是應該先化簡後再來計算。 化簡之後我發現其實算C(m,n)只要計算mi

矩陣找數--一個m*n的矩陣,從左到右從上到下都是遞增的,給一個數x,判斷x是否在矩陣中要求效率儘可能的高

思路一:迴圈找 效率差 思路二: 因為從左到右從上到下都是遞增的。 所以用數字和右上角的數字比較 如果要找的數字是7,則數字先與9比。比9小說明在9的左側。 再與8比,比8小,說明在8的左側。 與2比,比2大,在2的下側。 比4大,在4的下側

約瑟夫問題,從o(n*m)到o(n)乃至o(m)的演算法複雜度進階

問題描述: n個人(編號1~n),從1開始報數,報到m的退出,剩下的人繼續從1開始報數。按順序輸出列者編號。 1.演算法複雜度為o(n*m) 使用連結串列進行模擬整個遊戲過程 2.演算法複雜度為o(n) 將n個人按照從0~n進行編號,出列的第一個人編號是m%n-1,將

一個m*n的矩陣,從左到右從上到下都是遞增的,給一個數x,判斷x是否在矩陣中(高效率)

這樣的矩陣可以使用一個二維陣列儲存,知道了矩陣的特點,選取一個元素時可以將矩陣分割槽 可以看到隨意選一個元素的話會分成四個區域,陰影部分是可能的區域,深色的是確定比要查詢的大或者小,淺色陰影是有可能,所以下一步的動作很難確定,因此,隨意取一個點進行比較然後

輸入兩個整數mn,及另一個整數k,計算m/n,結果精確到小數點後k位

#include<stdio.h> int main() { int m,n,k,i; printf("Please input integer m , n and k\n"); scanf("%d%d%d",&m,&n,&k); pri

對於一個m*n的整數矩陣,其中每一行和每一列的元素都按升序排列,設計一個高效的演算法判斷一個數值是否存在,並給出位置

package com.huanchuang.arvin.vo; public class Finder {     private String findElement(int[][] matrix, int target) {         int row = 0,

從倆個有序陣列中找出第K小的數要求時間複雜度O(logmin(m,n))

思路 該題目要求時間複雜度為O(log(min{m,n})) 所以不能直接遍歷任意一個數組這樣時間複雜度就不符合了。也不能對任意一陣列進行二分查詢,因為要求是倆個數組元素合併後的第K小的數,所以直接遍歷用二分遍歷任意一個數組也是行不通的。 故我們可以以

程式設計求解,輸入兩個整數nm,從數列1,2,3,……n中隨意取幾個數,使其和等於m要求將所有的可能組合列出來(揹包問題求解) .

程式設計求解,輸入兩個整數n和m,從數列1,2,3,……n中隨意取幾個數,使其和等於m。要求將所有的可能組合列出來。實際上就是一個揹包問題。 求解思路: 1.首先判斷,如果n>m,則n中大於m的數不可能參與組合,此時置n = m; 2.將最大數n加入且n == m,則

Python程式碼筆記(1)輾轉相除法/歐幾里得演算法求最大公約數gcd(m,n

歐幾里得演算法求最大公約數:輾轉相除法 具體做法:用較小數除較大數,再用出現的餘數(第一餘數)去除除數,再用出現的餘數(第二餘數)去除除數,如此反覆,直到最後餘數是0為止。如果是求兩個數的最大公約數,