从随机生成的图中计算邻接矩阵

时间:2012-12-06 21:42:02

标签: c# graph connection binary-data adjacency-matrix

我开发了一个小程序,它在图形之间随机生成几个连接(计数值也可以随机,但是对于测试目标,我已经定义了 const值 ,可以随时重新定义随机值。

代码是C#:http://ideone.com/FDCtT0

(结果:成功时间:0.04s内存:36968 kB返回值:0)

如果您不知道,邻接矩阵是什么,请转到此处:http://en.wikipedia.org/wiki/Adjacency_matrix

enter image description here

我认为,我的代码版本没有经过优化。 如果我将处理大型矩阵,其大小为: 10k x 10k

  1. 您有什么建议,如何更好地进行并行计算 这个任务?我应该使用一些像信号量这样的储物柜模型 等,用于大矩阵的多线程计算。

  2. 您对重新设计架构有何建议? 程序。我应该如何为大型矩阵做好准备?

  3. 如您所见,在 ideone 上面,我已经在RAM中显示了时间执行参数和分配的内存。执行程序的渐近值是多少?是 O(n ^ 2)

  4. 所以我想听听你的建议如何增加渐近标记,使用信号量进行并行计算(或者更好的线程锁模型)。

    谢谢!

    PS: SO不允许在没有格式化代码的情况下发布主题,所以我最后发帖(完整程序):

    /*
        Oleg Orlov, 2012(c), generating randomly adjacency matrix and graph connections
    */
    
    using System;
    using System.Collections.Generic;
    
    class Graph
    {
        internal int id;
        private int value;
        internal Graph[] links;
    
        public Graph(int inc_id, int inc_value)
        {
            this.id = inc_id;
            this.value = inc_value;
            links = new Graph[Program.random_generator.Next(0, 4)];
        }
    }
    
    class Program
    {
        private const int graphs_count = 10;
        private static List<Graph> list;
        public static Random random_generator;
    
        private static void Init()
        {
            random_generator = new Random();
            list = new List<Graph>(graphs_count);
    
            for (int i = 0; i < list.Capacity; i++)
            {
                list.Add(new Graph(i, random_generator.Next(100, 255) * i + random_generator.Next(0, 32)));
            }
        }
    
        private static void InitGraphs()
        {
            for (int i = 0; i < list.Count; i++)
            {
                Graph graph = list[i] as Graph;
                graph.links = new Graph[random_generator.Next(1, 4)];
    
                for (int j = 0; j < graph.links.Length; j++)
                {
                    graph.links[j] = list[random_generator.Next(0, 10)];
                }
    
                list[i] = graph;
            }
        }
    
        private static bool[,] ParseAdjectiveMatrix()
        {
            bool[,] matrix = new bool[list.Count, list.Count];
    
            foreach (Graph graph in list)
            {
                int[] links = new int[graph.links.Length];
    
                for (int i = 0; i < links.Length; i++)
                {
                    links[i] = graph.links[i].id;
                    matrix[graph.id, links[i]] = matrix[links[i], graph.id] = true;
                }
            }
    
            return matrix;
        }
    
        private static void PrintMatrix(ref bool[,] matrix)
        {
            for (int i = 0; i < list.Count; i++)
            {
                Console.Write("{0} | [ ", i);
    
                for (int j = 0; j < list.Count; j++)
                {
                    Console.Write(" {0},", Convert.ToInt32(matrix[i, j]));
                }
    
                Console.Write(" ]\r\n");
            }
    
            Console.Write("{0}", new string(' ', 7));
    
            for (int i = 0; i < list.Count; i++)
            {
                Console.Write("---");
            }
    
            Console.Write("\r\n{0}", new string(' ', 7));
    
            for (int i = 0; i < list.Count; i++)
            {
                Console.Write("{0}  ", i);
            }
    
            Console.Write("\r\n");
        }
    
        private static void PrintGraphs()
        {
            foreach (Graph graph in list)
            {
                Console.Write("\r\nGraph id: {0}. It references to the graphs: ", graph.id);
    
                for (int i = 0; i < graph.links.Length; i++)
                {
                    Console.Write(" {0}", graph.links[i].id);
                }
            }
        }
    
        [STAThread]
        static void Main()
        {
            try
            {
                Init();
                InitGraphs();
                bool[,] matrix = ParseAdjectiveMatrix();
                PrintMatrix(ref matrix);
                PrintGraphs();
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc.Message);
            }
    
            Console.Write("\r\n\r\nPress enter to exit this program...");
            Console.ReadLine();
        }
    }
    

1 个答案:

答案 0 :(得分:2)

如果你不介意的话,我会从最后开始。 :)

3)当然,它是O(n^2)。以及内存使用情况。

2)从sizeof(bool) == 1 byte, not bit开始,您可以通过使用位掩码而不是原始bool值来优化内存使用量,这将使(8 bits per bool)^2 = 64次更少。

1)我不太了解C#,但正如我刚用Google搜索的那样,我发现C#原语类型是原子的,这意味着你可以安全地在多线程中使用它们。然后,您将创建一个超级简单的多线程任务:只需按线程拆分图形,然后按“运行”按钮,该按钮将运行每个线程及其部分图形。它们是独立的,所以不会有任何问题,你不需要任何信号量,锁等等。

问题是你将无法拥有大小为10 ^ 9 x 10 ^ 9的邻接矩阵。你只是不能将它存储在内存中。但是,还有另一种方式 为每个顶点创建一个邻接列表,它将包含与其连接的所有顶点的列表。从图表构建这些列表后,为每个顶点排序这些列表。然后,您可以使用二进制搜索在a时间内回复'bO( log(size of adjacency list for vertex a) )'相关联,这对于常见用途来说非常快。

现在,如果你想快速实现Dijkstra算法,你将不需要adj。矩阵,只是那些列表。

同样,这一切都取决于未来的任务和约束。你不能存储那个大小的矩阵,就是这样。 Dijkstra或BFS你不需要它,这是事实。 :)图表方面没有概念上的区别:无论存储在哪种数据结构中,图形都是相同的。

如果你真的想要矩阵,那就是解决方案:
我们知道,矩阵中的连接数(1)远小于其最大值n ^ 2。通过执行这些列表,我们只需存储1的位置(它也称为稀疏矩阵),它不会占用任何不需要的内存。