首页 文章

分布式领导者选举算法的可视化模拟器

提问于
浏览
1

这会有点长,所以请耐心等待 .

我编写了一个Visual Studio C#控制台程序来模拟单向环网中的distributed leader election algorithms .

让我先简要描述领导者选举问题:假设你有一个环网络,其中包含分配给每个节点的唯一(或非唯一,但让我们考虑唯一的情况)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 .

enter image description here

不要担心所有的混乱,注意'活跃'和'选中'列 . 它们代表每个节点中两个变量的状态 . 如果为真,则表示活跃,并且分别知道当选的领导者 .

现在,我想将其转换为可视化程序 . 也就是说,我想在每个TimeTick()上显示一个节点环,如果Active == TRUE,则显示一种颜色,如果Active == FALSE,则将它们交叉 . 此外,我想在每个节点旁边显示节点中各种变量的状态 . 例如,上面的执行,如果以我想要的方式直观显示,将如下所示 . 每个环都是每个时间步显示的环 .

Click to enlarge

我该怎么做?在我深入研究它之前,我想从你们这些人那里得到一些意见,因此这个帖子 .

我的第一个问题,直到运行时我才知道环大小,那么如何在运行时显示我的'节点'?我想我必须使用图片控件或类似的东西 . 我知道我无法显示大量节点,所以我可以自由地限制环的大小 . 基本上,我想以相等的距离将我在圆方向上的节点数量分开 .

如示例图像所示,我还希望看到彼此相邻显示的各种变量的状态 . 那么我是否应该创建一个包含我想要显示的所有内容的新类,然后以某种方式将其附加到图片控件?

任何引导我朝着良好方向前进的技巧都会很方便!

2 回答

  • 0

    你有很多选择 . 使用命名空间 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.TranslateTransform(dx, dy);轻松调整坐标系 .

    你可以在这里找到一个教程:GDI+ & Graphics GDI+ Tutorial for Beginners(还有很多其他的here) .


    如何在圆上均匀分布形状?那你需要一些数学 . 以角度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);
        }
    }
    
  • 3

    嘿我在这里的第一个答案,所以如果我可以改进任何事情让我知道 .

    您可以使用表单应用程序对其进行非常简单的直观表示 .

    我不确定它是否正确使用了计时器,但您确实可以使用计时器来检查脚本中的变量是否已更改,如果是,您只需将标签文本更改为“已激活”即可或取消激活取决于具体情况 .

    对于交叉/圆形的东西,我会使用Picturebox,只需在值改变时从代码中更改图像 .

    RSS_Button.Image = Properties.Resources.RSS;
    

    是我以前用图片框制作自定义按钮(我的图片框名为rss_button) .

    我希望它有所帮助!

相关问题