1

I am interested in plotting a random graph in Python.

More precisely, I consider all the points (x, y) with integer coordinates, such that |x| < 30, |y| < 30 (n = 30 is just an example here).

Then, for each couple of points, I decide with probability p (we can say p = 0.5) whether these two points are connected or not.

Then, I want to plot all the segments I got. For instance, we could get something like that:

Random graph

The problem I encounter is that plotting all these segments takes quite some time. And of course, it increases with both n and p.

So my question is: how can I plot quickly all these segments using pyplot ?

Thank you for your help.

EDIT: here is an example of a code that works, but that is slow.

import numpy as np
import matplotlib.pyplot as plt

for i in range(101):
    for j in range(101):
        if i < 100:
            if np.random.uniform() < 1/2:
                plt.plot([i - 50, i - 50 + 1], [j - 50, j - 50], "r")
        if j < 100:
            if np.random.uniform() < 1/2:
                plt.plot([i - 50, i - 50], [j - 50, j - 50 + 1], "r")
                
plt.show()
JackEight
  • 113
  • 4

2 Answers2

2

You have not provided a source code, but I guess that you are generating your segments, and then plot them separately using plt.plot(point_A, point_B)

You should consider one of the following solutions:

1. Plot your graph as a 2D image

Instead of considering your graph as a list of segments, we consider it as a 2d matrix of connections, and simply plot that matrix once.

E.g.


segments = ... # you generate this list of pairs (POINT_A, POINT_B) that define your segments using your algorithm

matrix = np.zeros((30, 30))
for ((xA, yA), (xB, yB)) in segments:
   # we re-order coordinates in order to always have A inferior to B
   if yA > yB:
      yA, yB = yB, yA
   if xA > xB:
      xA, xB = xB, xA

   # we mark all points belonging to the segment [A, B] as True in the matrix
   matrix[yA:yB+1, xA:xB+1] = 1
plt.imshow(matrix)

I have not tested the code and provide it just to illustrate the idea.

2. Use lineCollections from matplotlib

Best described here: https://stackoverflow.com/a/21357666/5728381

Ultramoi
  • 166
  • 1
  • 9
  • Thank you for your answer ! I am not too sure of how the plt.plot(matrix) works. When I try it with a simple example (segments only contains two points), it gives me quite a weird result ... But I will try and understand it. As for the lineCollections part, I had found it on Google indeed, but if it is possible, I would prefer not using it. – JackEight May 29 '22 at 18:37
  • 1
    You're welcome :) Sorry it was a typo, `plt.plot(matrix)` won't work on a 2d image, I meant `plt.imshow(matrix)` https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.imshow.html – Ultramoi May 29 '22 at 18:40
1

It looks to me like your "segments" are actually single pixels.

plt.plot([i - 50, i - 50 + 1], [j - 50, j - 50], "r")

is a horribly inefficient way to set the color of a pixel.

Suggest: Create a matrix in memory, and calculate the locations that need to be colored. Then iterate through the matrix, and for each location that is set, color the corresponding pixel. If you have a decent graphics library then if you postpone the screen update until all the pixel are colored, then you will get a huge perfomance boost. ( Using the windows API you can use a "memory device context" and when finished swap the entire context from memory to the screen )

ravenspoint
  • 19,093
  • 6
  • 57
  • 103