簡體   English   中英

分布式領導者選舉算法的可視化模擬器

[英]Visual Simulator for Distributed Leader Election Algorithm

這會有點長,所以請耐心等待。

我編寫了一個Visual Studio C#Console程序來模擬單向環網中的分布式領導者選舉算法

讓我先簡要描述領導者選舉問題:假設你有一個環網絡,其中包含分配給每個節點的唯一(或非唯一,但讓我們考慮唯一的情況)ID的節點。 它們中的每一個都具有相同的程序(算法)。 消息可以在一個預定方向(CW或CCW)上僅在鄰居之間傳遞。 一旦算法完成,必須選擇一個節點作為“領導者”,並且所有其他節點應該知道領導者已被選舉並且領導者的ID。

其中最簡單的是LCR算法(我已經使用過),如下所示。 在步驟1,每個節點在消息中將它們自己的ID發送給它們(例如)CW鄰居。 這意味着每個人都會收到一個。 收到消息后:

  • 如果它大於您的ID,請將其傳遞並將自己標記為非活動狀態
  • 如果它小於您的ID,請將其丟棄
  • 如果您在郵件中收到自己的ID,請選擇自己為領導者

這樣,在n步之后(n =網絡的大小),只有具有最大ID的節點保持活動狀態並被選為領導者。 然后它在環上發送一條消息,通知每個人它是領導者,當它收到該消息時,我們完成執行。

我編寫了一個如下控制台程序。 我有我的主程序,我的算法在一個單獨的DLL中。 DLL具有TimeTick()函數,其中包含算法的所有步驟。 從我的主程序中,我以用戶指定的時間間隔(例如10ms)重復調用TimeTick()函數。 因此,在我的程序中執行一次TimeTick()類似於在算法中傳遞“step”的一條消息。 我可以訪問DLL中的所有重要變量,因此從我的主程序中我可以知道每個節點的狀態,它是否處於活動狀態,是否知道領導者正在被選舉等等。

以下是執行以下環的示例屏幕截圖:順時針順序為1-3-2。

在此輸入圖像描述

不要擔心所有的混亂,注意'主動'和'選中'欄目。 它們代表每個節點中兩個變量的狀態。 如果為真,則表示活躍,並且分別知道當選的領導者。

現在,我想將其轉換為可視化程序。 也就是說,我想在每個TimeTick()上顯示一個節點環,如果Active == TRUE,則顯示一種顏色,如果Active == FALSE,則將它們交叉。 此外,我想在每個節點旁邊顯示節點中各種變量的狀態。 例如,上面的執行,如果以我想要的方式直觀顯示,將如下所示。 每個環都是每個時間步顯示的環。

點擊放大

我該怎么做? 在我深入研究它之前,我想從你們這些人那里得到一些意見,因此這個帖子。

我的第一個問題,直到運行時才知道環大小,那么我如何在運行時顯示我的'節點'? 我想我必須使用圖片控件或類似的東西。 我知道我無法顯示大量節點,所以我可以自由地限制環的大小。 基本上,我想以相等的距離將我在圓方向上的節點數量分開。

如示例圖像所示,我還希望看到彼此相鄰顯示的各種變量的狀態。 那么我是否應該創建一個包含我想要顯示的所有內容的新類,然后以某種方式將其附加到圖片控件?

任何引導我朝着良好方向前進的提示都會很方便!

你有很多選擇。 使用命名空間System.Drawing (GDI +)在自定義WinForms控件上繪制圖形的相對簡單的一個。 對於這個簡單的圖形,您不需要更多的性能,也需要更復雜的游戲引擎。 GDI +非常快。 繪制自己的圖形使您可以靈活地在可變配置中生成任何顏色的任何類型的形狀,也可以繪制文本。

只需通過從System.Windows.Forms.Control派生類來創建自定義控件。 編譯后,此控件將自動顯示在窗體設計器的工具箱中,您可以將其拖放到窗體表面上。

public class ElectionDisplayControl : Control
{
    public ElectionDisplayControl()
    {
        this.DoubleBuffered = true;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        g.SetHighQuality();

        // TODO: put your drawing logic here!
    }

    protected override void OnResize(EventArgs e)
    {
        Invalidate();
        base.OnResize(e);
    }
}

重要的是要了解您不應該通過直接調用OnPaint方法來繪制。 而是在每個TimeTick上調用控件的Invalidate方法。 Windows決定何時必須重繪控件並在必要時調用OnPaint (例如,當您的控件隱藏在另一個窗體后面時,現在變得可見。)

// At each tick:
electionDisplayControl1.Invalidate(); 

DoubleBuffered消除了閃爍。 在調整大小時重繪控件是很好的。 您可以將控件錨定到表單的邊緣,以允許用戶通過調整表單大小來調整其大小。 確定相對於控件大小的形狀大小是個好主意。 這會創建自動縮放效果。 您可以使用g.ScaleTransform(sx, sy);輕松調整坐標系g.ScaleTransform(sx, sy); g.TranslateTransform(dx, dy);

你可以在這里找到一個教程: GDI +圖形GDI +教程初學者 (和其他許多人在這里 )。


如何在圓上均勻分布形狀? 那你需要一些數學。 以角度phi計算圓上的點(假設圓的中心位於{x = 0,y = 0}):

x = radius * cos(phi)
y = -radius * sin(phi)

y的減號是因為y軸指向GDI +中的向下。 靜態System.Math類需要以弧度表示的角度,即整圓= 2 * pi。


我忘記了: SetHighQuality是我的擴展方法之一。 這里有一些其他有用的:

public static class GraphicsExtensions
    public static void SetHighQuality(this Graphics g)
    {
        g.CompositingMode = CompositingMode.SourceOver;
        g.CompositingQuality = CompositingQuality.HighQuality;
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.SmoothingMode = SmoothingMode.HighQuality;
        g.PixelOffsetMode = PixelOffsetMode.HighQuality;
    }

    public static void DrawCircle(this Graphics g, Pen pen, float centerX, float centerY, float radius)
    {
        g.DrawEllipse(pen, centerX - radius, centerY - radius, radius + radius, radius + radius);
    }

    public static void FillCircle(this Graphics g, Brush brush, float centerX, float centerY, float radius)
    {
        g.FillEllipse(brush, centerX - radius, centerY - radius, radius + radius, radius + radius);
    }
}

嘿我在這里的第一個答案,所以如果我可以改進任何事情讓我知道。

您可以使用表單應用程序對其進行非常簡單的直觀表示。

我不確定它是否正確使用了計時器,但您確實可以使用計時器來檢查腳本中的變量是否已更改,如果是,您只需將標簽文本更改為“已激活”即可或取消激活取決於具體情況。

對於交叉/圓形的東西,我會使用Picturebox,只需在值改變時從代碼中更改圖像。

            RSS_Button.Image = Properties.Resources.RSS;

是我以前用圖片框制作自定義按鈕(我的圖片框名為rss_button)。

我希望它有所幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM