<?xml version="1.0" encoding="utf-8"?> 
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us">
    <generator uri="https://gohugo.io/" version="0.152.2">Hugo</generator><title type="html"><![CDATA[Graphs on Blog]]></title>
    
    
    
            <link href="https://blog.scientific-python.org/tags/graphs/" rel="alternate" type="text/html" title="html" />
            <link href="https://blog.scientific-python.org/tags/graphs/atom.xml" rel="self" type="application/atom" title="atom" />
    <updated>2026-04-04T04:32:36+00:00</updated>
    
    
    
    
        <id>https://blog.scientific-python.org/tags/graphs/</id>
    
        
        <entry>
            <title type="html"><![CDATA[The Python Graph Gallery: hundreds of python charts with reproducible code.]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/python-graph-gallery.com/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/codeswitching-visualization/?utm_source=atom_feed" rel="related" type="text/html" title="Visualizing Code-Switching with Step Charts" />
                <link href="https://blog.scientific-python.org/matplotlib/draw-all-graphs-of-n-nodes/?utm_source=atom_feed" rel="related" type="text/html" title="Draw all graphs of N nodes" />
                <link href="https://blog.scientific-python.org/matplotlib/stellar-chart-alternative-radar-chart/?utm_source=atom_feed" rel="related" type="text/html" title="Stellar Chart, a Type of Chart to Be on Your Radar" />
                <link href="https://blog.scientific-python.org/matplotlib/ipcc-sr15/?utm_source=atom_feed" rel="related" type="text/html" title="Figures in the IPCC Special Report on Global Warming of 1.5°C (SR15)" />
                <link href="https://blog.scientific-python.org/matplotlib/elementary-cellular-automata/?utm_source=atom_feed" rel="related" type="text/html" title="Elementary Cellular Automata" />
            
                <id>https://blog.scientific-python.org/matplotlib/python-graph-gallery.com/</id>
            
            
            <published>2021-07-24T14:06:57+02:00</published>
            <updated>2021-07-24T14:06:57+02:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>The Python Graph Gallery is a website that displays hundreds of chart examples made with python. It goes from very basic to highly customized examples and is based on common viz libraries like matplotlib, seaborn or plotly.</blockquote><p>Data visualization is a key step in a data science pipeline. <a href="https://www.python.org">Python</a> offers great possibilities when it comes to representing some data graphically, but it can be hard and time-consuming to create the appropriate chart.</p>
<p>The <a href="https://www.python-graph-gallery.com">Python Graph Gallery</a> is here to help. It displays many examples, always providing the reproducible code. It allows to build the desired chart in minutes.</p>
<h1 id="about-400-charts-in-40-sections">About 400 charts in 40 sections<a class="headerlink" href="#about-400-charts-in-40-sections" title="Link to this heading">#</a></h1>
<p>The gallery currently provides more than <a href="https://www.python-graph-gallery.com/all-charts/">400 chart examples</a>. Those examples are organized in 40 sections, one for each chart types: <a href="https://www.python-graph-gallery.com/scatter-plot/">scatterplot</a>, <a href="https://www.python-graph-gallery.com/boxplot/">boxplot</a>, <a href="https://www.python-graph-gallery.com/barplot/">barplot</a>, <a href="https://www.python-graph-gallery.com/treemap/">treemap</a> and so on. Those chart types are organized in 7 big families as suggested by <a href="https://www.data-to-viz.com">data-to-viz.com</a>: one for each visualization purpose.</p>
<p>It is important to note that not only the most common chart types are covered. Lesser known charts like <a href="https://www.python-graph-gallery.com/chord-diagram/">chord diagrams</a>, <a href="https://www.python-graph-gallery.com/streamchart/">streamgraphs</a> or <a href="https://www.python-graph-gallery.com/bubble-map/">bubble maps</a> are also available.</p>
<p><img src="/matplotlib/python-graph-gallery.com/sections-overview.png" alt="overview of the python graph gallery sections"></p>
<h1 id="master-the-basics">Master the basics<a class="headerlink" href="#master-the-basics" title="Link to this heading">#</a></h1>
<p>Each section always starts with some very basic examples. It allows to understand how to build a chart type in a few seconds. Hopefully applying the same technique on another dataset will thus be very quick.</p>
<p>For instance, the <a href="https://www.python-graph-gallery.com/scatter-plot/">scatterplot section</a> starts with this <a href="https://matplotlib.org/">matplotlib</a> example. It shows how to create a dataset with <a href="https://pandas.pydata.org/">pandas</a> and plot it with the <code>plot()</code> function. The main graph argument like <code>linestyle</code> and <code>marker</code> are described to make sure the code is understandable.</p>
<p><a href="https://www.python-graph-gallery.com/130-basic-matplotlib-scatterplot"><em>blogpost overview</em>:</a></p>
<p><img src="/matplotlib/python-graph-gallery.com/scatterplot-example.png" alt="a basic scatterplot example"></p>
<h1 id="matplotlib-customization">Matplotlib customization<a class="headerlink" href="#matplotlib-customization" title="Link to this heading">#</a></h1>
<p>The gallery uses several libraries like <a href="https://www.python-graph-gallery.com/seaborn/">seaborn</a> or <a href="https://www.python-graph-gallery.com/plotly/">plotly</a> to produce its charts, but is mainly focus on matplotlib. Matplotlib comes with great flexibility and allows to build any kind of chart without limits.</p>
<p>A <a href="https://www.python-graph-gallery.com/matplotlib/">whole page</a> is dedicated to matplotlib. It describes how to solve recurring issues like customizing <a href="https://www.python-graph-gallery.com/191-custom-axis-on-matplotlib-chart">axes</a> or <a href="https://www.python-graph-gallery.com/190-custom-matplotlib-title">titles</a>, adding <a href="https://www.python-graph-gallery.com/193-annotate-matplotlib-chart">annotations</a> (see below) or even using <a href="https://www.python-graph-gallery.com/custom-fonts-in-matplotlib">custom fonts</a>.</p>
<p><img src="/matplotlib/python-graph-gallery.com/annotations.png" alt="annotation examples"></p>
<p>The gallery is also full of non-straightforward examples. For instance, it has a <a href="https://www.python-graph-gallery.com/streamchart-basic-matplotlib">tutorial</a> explaining how to build a streamchart with matplotlib. It is based on the <code>stackplot()</code> function and adds some smoothing to it:</p>
<p><img src="/matplotlib/python-graph-gallery.com/streamchart.png" alt="stream chart with python and matplotlib"></p>
<p>Last but not least, the gallery also displays some publication ready charts. They usually involve a lot of matplotlib code, but showcase the fine grain control one has over a plot.</p>
<p>Here is an example with a post inspired by <a href="https://www.r-graph-gallery.com/web-violinplot-with-ggstatsplot.html">Tuo Wang</a>&rsquo;s work for the tidyTuesday project. (Code translated from R available <a href="https://www.python-graph-gallery.com/web-ggbetweenstats-with-matplotlib">here</a>)</p>
<p><img src="/matplotlib/python-graph-gallery.com/boxplot.png" alt="python violin and boxplot example"></p>
<h1 id="contributing">Contributing<a class="headerlink" href="#contributing" title="Link to this heading">#</a></h1>
<p>The python graph gallery is an ever growing project. It is open-source, with all its related code hosted on <a href="https://github.com/holtzy/The-Python-Graph-Gallery">github</a>.</p>
<p>Contributions are very welcome to the gallery. Each blogpost is just a jupyter notebook so suggestion should be very easy to do through issues or pull requests!</p>
<h1 id="conclusion">Conclusion<a class="headerlink" href="#conclusion" title="Link to this heading">#</a></h1>
<p>The <a href="https://www.python-graph-gallery.com">python graph gallery</a> is a project developed by <a href="https://www.yan-holtz.com">Yan Holtz</a> in his free time. It can help you improve your technical skills when it comes to visualizing data with python.</p>
<p>The gallery belongs to an ecosystem of educative websites. <a href="https://www.data-to-viz.com">Data to viz</a> describes best practices in data visualization, the <a href="https://www.r-graph-gallery.com">R</a>, <a href="https://www.python-graph-gallery.com">python</a> and <a href="https://www.d3-graph-gallery.com">d3.js</a> graph galleries provide technical help to build charts with the 3 most common tools.</p>
<p>For any question regarding the project, please say hi on twitter at <a href="https://twitter.com/R_Graph_Gallery">@R_Graph_Gallery</a>!</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="graphs" label="graphs" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Visualizing Code-Switching with Step Charts]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/codeswitching-visualization/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/draw-all-graphs-of-n-nodes/?utm_source=atom_feed" rel="related" type="text/html" title="Draw all graphs of N nodes" />
                <link href="https://blog.scientific-python.org/matplotlib/elementary-cellular-automata/?utm_source=atom_feed" rel="related" type="text/html" title="Elementary Cellular Automata" />
                <link href="https://blog.scientific-python.org/matplotlib/animated-fractals/?utm_source=atom_feed" rel="related" type="text/html" title="Animate Your Own Fractals in Python with Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/animated-polar-plot/?utm_source=atom_feed" rel="related" type="text/html" title="Animated polar plot with oceanographic data" />
                <link href="https://blog.scientific-python.org/matplotlib/emoji-mosaic-art/?utm_source=atom_feed" rel="related" type="text/html" title="Emoji Mosaic Art" />
            
                <id>https://blog.scientific-python.org/matplotlib/codeswitching-visualization/</id>
            
            
            <published>2020-09-26T19:41:21-07:00</published>
            <updated>2020-09-26T19:41:21-07:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Learn how to easily create step charts through examining the multilingualism of pop group WayV</blockquote><p><img src="/matplotlib/codeswitching-visualization/Image1.png" alt="Frequency of Code-Switching 200403 WayV Instagram Live, a step chart. The figure shows a plot of ‘cumulative number of times of code-switching’ against the ‘duration of Instagram Live (in seconds)’. There are four members in the livestream: Yangyang (represented with a dark red line), Hendery (represented with a pink line), Ten (represented with a light blue line), Kun (represented with a dark blue line)."></p>
<h1 id="introduction">Introduction<a class="headerlink" href="#introduction" title="Link to this heading">#</a></h1>
<p>Code-switching is the practice of alternating between two or more languages in the context of a single conversation, either consciously or unconsciously. As someone who grew up bilingual and is currently learning other languages, I find code-switching a fascinating facet of communication from not only a purely linguistic perspective, but also a social one. In particular, I&rsquo;ve personally found that code-switching often helps build a sense of community and familiarity in a group and that the unique ways in which speakers code-switch with each other greatly contribute to shaping group dynamics.</p>
<p>This is something that&rsquo;s evident in seven-member pop boy group WayV. Aside from their discography, artistry, and group chemistry, WayV is well-known among fans and many non-fans alike for their multilingualism and code-switching, which many fans have affectionately coined as &ldquo;WayV language.&rdquo; Every member in the group is fluent in both Mandarin and Korean, and at least one member in the group is fluent in one or more of the following: English, Cantonese, Thai, Wenzhounese, and German. It&rsquo;s an impressive trait that&rsquo;s become a trademark of WayV as they&rsquo;ve quickly drawn a global audience since their debut in January 2019. Their multilingualism is reflected in their music as well. On top of their regular album releases in Mandarin, WayV has also released singles in Korean and English, with their latest single &ldquo;Bad Alive (English Ver.)&rdquo; being a mix of English, Korean, and Mandarin.</p>
<p>As an independent translator who translates WayV content into English, I&rsquo;ve become keenly aware of the true extent and rate of WayV&rsquo;s code-switching when communicating with each other. In a lot of their content, WayV frequently switches between three or more languages every couple of seconds, a phenomenon that can make translating quite challenging at times, but also extremely rewarding and fun. I wanted to be able to present this aspect of WayV in a way that would both highlight their linguistic skills and present this dimension of their group dynamic in a more concrete, quantitative, and visually intuitive manner, beyond just stating that &ldquo;they code-switch a lot.&rdquo; This prompted me to make step charts - perfect for displaying data that changes at irregular intervals but remains constant between the changes - in hopes of enriching the viewer&rsquo;s experience and helping make a potentially abstract concept more understandable and readily consumable. With a step chart, it becomes more apparent to the viewer the extent of how a group communicates, and cross-sections of the graph allow a rudimentary look into how multilinguals influence each other in code-switching.</p>
<h1 id="tutorial">Tutorial<a class="headerlink" href="#tutorial" title="Link to this heading">#</a></h1>
<p>This tutorial on creating step charts uses one of WayV&rsquo;s livestreams as an example. There were four members in this livestream and a total of eight languages/dialects spoken. I will go through the basic steps of creating a step chart that depicts the frequency of code-switching for just one member. A full code chunk that shows how to layer two or more step chart lines in one graph to depict code-switching for multiple members can be found near the end.</p>
<h2 id="dataset">Dataset<a class="headerlink" href="#dataset" title="Link to this heading">#</a></h2>
<p>First, we import the required libraries and load the data into a Pandas dataframe.</p>
<pre><code>import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
</code></pre>
<p>This dataset includes the timestamp of every switch (in seconds) and the language of switch for one speaker.</p>
<pre><code>df_h = pd.read_csv(&quot;WayVHendery.csv&quot;)
HENDERY = df_h.reset_index()
HENDERY.head()
</code></pre>
<table>
  <thead>
      <tr>
          <th>index</th>
          <th>time</th>
          <th>lang</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>0</td>
          <td>2</td>
          <td>ENG</td>
      </tr>
      <tr>
          <td>1</td>
          <td>3</td>
          <td>KOR</td>
      </tr>
      <tr>
          <td>2</td>
          <td>10</td>
          <td>ENG</td>
      </tr>
      <tr>
          <td>3</td>
          <td>13</td>
          <td>MAND</td>
      </tr>
      <tr>
          <td>4</td>
          <td>15</td>
          <td>ENG</td>
      </tr>
  </tbody>
</table>
<h2 id="plotting">Plotting<a class="headerlink" href="#plotting" title="Link to this heading">#</a></h2>
<p>With the dataset loaded, we can now set up our graph in terms of determining the size of the figure, dpi, font size, and axes limits. We can also play around with the aesthetics, such as modifying the colors of our plot. These few simple steps easily transform the default all-white graph into a more visually appealing one.</p>
<h3 id="without-customization">Without Customization<a class="headerlink" href="#without-customization" title="Link to this heading">#</a></h3>
<pre><code>fig, ax = plt.subplots(figsize = (20,12))
</code></pre>
<p><img src="/matplotlib/codeswitching-visualization/fig1.png" alt="An all-white graph with the x and y axis defined on the range [0, 1]."></p>
<h3 id="with-customization">With Customization<a class="headerlink" href="#with-customization" title="Link to this heading">#</a></h3>
<pre><code>sns.set(rc={'axes.facecolor':'aliceblue', 'figure.facecolor':'c'})
fig, ax = plt.subplots(figsize = (20,12), dpi = 300)

plt.xlabel(&quot;Duration of Instagram Live (seconds)&quot;, fontsize = 18)
plt.ylabel(&quot;Cumulative Number of Times of Code-Switching&quot;, fontsize = 18)

plt.xlim(0, 570)
plt.ylim(0, 85)
</code></pre>
<p><img src="/matplotlib/codeswitching-visualization/fig2.png" alt="A styled, blank graph with the ‘cumulative number of times of code-switching’ values on the y-axis and the ‘duration of Instagram Live (in seconds)’ values on the x-axis"></p>
<!--     ax.step(HENDERY.time, HENDERY.index, label = "HENDERY") -->
<p>Following this, we can make our step chart line easily with matplotlib.pyplot.step, in which we plot the x and y values and determine the text of the legend, color of the step chart line, and width of the step chart line.</p>
<pre><code>ax.step(HENDERY.time, HENDERY.index, label = &quot;HENDERY&quot;, color = &quot;palevioletred&quot;, linewidth = 4)
</code></pre>
<p><img src="/matplotlib/codeswitching-visualization/fig3.png" alt="A graph with the ‘cumulative number of times of code-switching’ values on the y-axis and the ‘duration of Instagram Live (in seconds)’ values on the x-axis showing a step chart line (in pink) for Hendery."></p>
<h2 id="labeling">Labeling<a class="headerlink" href="#labeling" title="Link to this heading">#</a></h2>
<p>Of course, we want to know not only how many switches there were and when they occurred, but also to what language the member switched. For this, we can write a for loop that labels each switch with its respective language as recorded in our dataset.</p>
<pre><code>for x,y,z in zip(HENDERY[&quot;time&quot;], HENDERY[&quot;index&quot;], HENDERY[&quot;lang&quot;]):
    label = z
    ax.annotate(label, #text
                 (x,y), #label coordinate
                 textcoords = &quot;offset points&quot;, #how to position text
                 xytext = (15,-5), #distance from text to coordinate (x,y)
                 ha = &quot;center&quot;, #alignment
                 fontsize = 8.5) #font size of text
</code></pre>
<p><img src="/matplotlib/codeswitching-visualization/fig4.png" alt="Language labels for each step on the graph. Languages include English, Korean, Mandarin, and German. The graph has the ‘cumulative number of times of code-switching’ values on the y-axis and the ‘duration of Instagram Live (in seconds)’ values on the x-axis showing a step chart line (in pink) for Hendery."></p>
<h2 id="final-touches">Final Touches<a class="headerlink" href="#final-touches" title="Link to this heading">#</a></h2>
<p>Now add a title, save the graph, and there you have it!</p>
<pre><code>plt.title(&quot;WayV Livestream Code-Switching&quot;, fontsize = 35)

fig.savefig(&quot;wayv_codeswitching.png&quot;, bbox_inches = &quot;tight&quot;, facecolor = fig.get_facecolor())
</code></pre>
<p>Below is the complete code for layering step chart lines for multiple speakers in one graph. You can see how easy it is to take the code for visualizing the code-switching of one speaker and adapt it to visualizing that of multiple speakers. In addition, you can see that I&rsquo;ve intentionally left the title blank so I can incorporate external graphic adjustments after I created the chart in Matplotlib, such as the addition of my social media handle and the use of a specific font I wanted, which you can see in the final graph. With visualizations being all about communicating information, I believe using Matplotlib in conjunction with simple elements of graphic design can be another way to make whatever you&rsquo;re presenting that little bit more effective and personal, especially when you&rsquo;re doing so on social media platforms.</p>
<h2 id="complete-code-for-step-chart-of-multiple-speakers">Complete Code for Step Chart of Multiple Speakers<a class="headerlink" href="#complete-code-for-step-chart-of-multiple-speakers" title="Link to this heading">#</a></h2>
<!-- ![](fig5.png) -->
<pre><code># Initialize graph color and size
sns.set(rc={'axes.facecolor':'aliceblue', 'figure.facecolor':'c'})

fig, ax = plt.subplots(figsize = (20,12), dpi = 120)

# Set up axes and labels
plt.xlabel(&quot;Duration of Instagram Live (seconds)&quot;, fontsize = 18)
plt.ylabel(&quot;Cumulative Number of Times of Code-Switching&quot;, fontsize = 18)

plt.xlim(0, 570)
plt.ylim(0, 85)

# Layer step charts for each speaker
ax.step(YANGYANG.time, YANGYANG.index, label = &quot;YANGYANG&quot;, color = &quot;firebrick&quot;, linewidth = 4)
ax.step(HENDERY.time, HENDERY.index, label = &quot;HENDERY&quot;, color = &quot;palevioletred&quot;, linewidth = 4)
ax.step(TEN.time, TEN.index, label = &quot;TEN&quot;, color = &quot;mediumpurple&quot;, linewidth = 4)
ax.step(KUN.time, KUN.index, label = &quot;KUN&quot;, color = &quot;mediumblue&quot;, linewidth = 4)

# Add legend
ax.legend(fontsize = 17)

# Label each data point with the language switch
for i in (KUN, TEN, HENDERY, YANGYANG): #for each dataset
    for x,y,z in zip(i[&quot;time&quot;], i[&quot;index&quot;], i[&quot;lang&quot;]): #looping within the dataset
        label = z
        ax.annotate(label, #text
                     (x,y), #label coordinate
                     textcoords = &quot;offset points&quot;, #how to position text
                     xytext = (15,-5), #distance from text to coordinate (x,y)
                     ha = &quot;center&quot;, #alignment
                     fontsize = 8.5) #font size of text

# Add title (blank to leave room for external graphics)
plt.title(&quot;\n\n&quot;, fontsize = 35)

# Save figure
fig.savefig(&quot;wayv_codeswitching.png&quot;, bbox_inches = &quot;tight&quot;, facecolor = fig.get_facecolor())
</code></pre>
<p><img src="/matplotlib/codeswitching-visualization/Image1.png" alt="Frequency of Code-Switching 200403 WayV Instagram Live, a step chart. The figure shows a plot of ‘cumulative number of times of code-switching’ against the ‘duration of Instagram Live (in seconds)’. There are four members in the livestream: Yangyang (represented with a dark red line), Hendery (represented with a pink line), Ten (represented with a light blue line), Kun (represented with a dark blue line)."></p>
<p>Languages/dialects: Korean (KOR), English (ENG), Mandarin (MAND), German (GER), Cantonese (CANT), Hokkien (HOKK), Teochew (TEO), Thai (THAI)</p>
<p>186 total switches! That&rsquo;s approximately one code-switch in the group every 2.95 seconds.</p>
<p>And voilà! There you have it: a brief guide on how to make step charts. While I utilized step charts here to visualize code-switching, you can use them to visualize whatever data you would like. Please feel free to contact me <a href="https://twitter.com/WayVSubs2019">here</a> if you have any questions or comments. I hope you enjoyed this tutorial, and thank you so much for reading!</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="graphs" label="graphs" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Draw all graphs of N nodes]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/draw-all-graphs-of-n-nodes/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-cyberpunk-style/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib Cyberpunk Style" />
                <link href="https://blog.scientific-python.org/matplotlib/mpl-for-making-diagrams/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib for Making Diagrams" />
                <link href="https://blog.scientific-python.org/matplotlib/create-ridgeplots-in-matplotlib/?utm_source=atom_feed" rel="related" type="text/html" title="Create Ridgeplots in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/create-a-tesla-cybertruck-that-drives/?utm_source=atom_feed" rel="related" type="text/html" title="Create a Tesla Cybertruck That Drives" />
                <link href="https://blog.scientific-python.org/matplotlib/an-inquiry-into-matplotlib-figures/?utm_source=atom_feed" rel="related" type="text/html" title="An Inquiry Into Matplotlib&#39;s Figures" />
            
                <id>https://blog.scientific-python.org/matplotlib/draw-all-graphs-of-n-nodes/</id>
            
            
            <published>2020-05-07T09:05:32+01:00</published>
            <updated>2020-05-07T09:05:32+01:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>A fun project about drawing all possible differently-looking (not isomorphic) graphs of N nodes.</blockquote><p>The other day I was homeschooling my kids, and they asked me: &ldquo;Daddy, can you draw us all possible non-isomorphic graphs of 3 nodes&rdquo;? Or maybe I asked them that? Either way, we happily drew all possible graphs of 3 nodes, but already for 4 nodes it got hard, and for 5 nodes - <a href="https://www.graphclasses.org/smallgraphs.html#nodes5">plain impossible</a>!</p>
<p>So I thought: let me try to write a brute-force program to do it! I spent a few hours sketching some smart dynamic programming solution to generate these graphs, and went nowhere, as apparently the <a href="http://www.cs.columbia.edu/~cs4205/files/CM9.pdf">problem is quite hard</a>. I gave up, and decided to go with a naive approach:</p>
<ol>
<li>Generate all graphs of N nodes, even if some of them look the same (are isomorphic). For \(N\) nodes, there are \(\frac{N(N-1)}{2}\) potential edges to connect these nodes, so it&rsquo;s like generating a bunch of binary numbers. Simple!</li>
<li>Write a program to tell if two graphs are isomorphic, then remove all duplicates, unworthy of being presented in the final picture.</li>
</ol>
<p>This strategy seemed more reasonable, but writing a &ldquo;graph-comparator&rdquo; still felt like a cumbersome task, and more importantly, this part would itself be slow, as I&rsquo;d still have to go through a whole tree of options for every graph comparison. So after some more head-scratching, I decided to simplify it even further, and use the fact that these days the memory is cheap:</p>
<ol>
<li>Generate all possible graphs (some of them totally isomorphic, meaning that they would look as a repetition if plotted on a figure)</li>
<li>For each graph, generate its &ldquo;description&rdquo; (like an <a href="https://en.wikipedia.org/wiki/Adjacency_matrix">adjacency matrix</a>, of an edge list), and check if a graph with this description is already on the list. If yes, skip it, we got its portrait already!</li>
<li>If however the graph is unique, include it in the picture, and also generate all possible &ldquo;descriptions&rdquo; of it, up to node permutation, and add them to the hash table. To make sure no other graph of this particular shape would ever be included in our pretty picture again.</li>
</ol>
<p>For the first task, I went with the edge list, which made the task identical to <a href="https://www.geeksforgeeks.org/generate-all-the-binary-strings-of-n-bits/">generating all binary numbers</a> of length \(\frac{N(N-1)}{2}\) with a recursive function, except instead of writing zeroes you skip edges, and instead of writing ones, you include them. Below is the function that does the trick, and has an additional bonus of listing all edges in a neat orderly way. For every edge \(i \rightarrow j\) we can be sure that \(i\) is lower than \(j\), and also that edges are sorted as words in a dictionary. Which is good, as it restricts the set of possible descriptions a bit, which will simplify our life later.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_graphs</span><span class="p">(</span><span class="n">n</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">i</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">j</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Make a graph recursively, by either including, or skipping each edge.
</span></span></span><span class="line"><span class="cl"><span class="s2">    Edges are given in lexicographical order by construction.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">out</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">i</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>  <span class="c1"># First call</span>
</span></span><span class="line"><span class="cl">        <span class="n">out</span> <span class="o">=</span> <span class="p">[[(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)]</span> <span class="o">+</span> <span class="n">r</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">make_graphs</span><span class="p">(</span><span class="n">n</span><span class="o">=</span><span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">j</span><span class="o">=</span><span class="mi">1</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">    <span class="k">elif</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">out</span> <span class="o">+=</span> <span class="p">[[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span> <span class="o">+</span> <span class="n">r</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">make_graphs</span><span class="p">(</span><span class="n">n</span><span class="o">=</span><span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="o">=</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="o">=</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">        <span class="n">out</span> <span class="o">+=</span> <span class="p">[</span><span class="n">r</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">make_graphs</span><span class="p">(</span><span class="n">n</span><span class="o">=</span><span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="o">=</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="o">=</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">    <span class="k">elif</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">out</span> <span class="o">=</span> <span class="n">make_graphs</span><span class="p">(</span><span class="n">n</span><span class="o">=</span><span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="o">=</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="o">=</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">out</span> <span class="o">=</span> <span class="p">[[]]</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">out</span></span></span></code></pre>
</div>
<p>If you run this function for a small number of nodes (say, \(N=3\)), you can see how it generates all possible graph topologies, but that some of the descriptions would actually lead to identical pictures, if drawn (graphs 2 and 3 in the list below).</p>

<div class="highlight">
  <pre>[(0, 1), (0, 2), (1, 2)]
[(0, 1), (0, 2)]
[(0, 1), (1, 2)]
[(0, 1)]</pre>
</div>

<p>Also, while building a graph from edges means that we&rsquo;ll never get lonely unconnected points, we can get graphs that are smaller than \(n\) nodes (the last graph in the list above), or graphs that have unconnected parts. It is impossible for \(n=3\), but starting with \(n=4\) we would get things like <code>[(0,1), (2,3)]</code>, which is technically a graph, but you cannot exactly wear it as a piece of jewelry, as it would fall apart. So at this point I decided to only visualize fully connected graphs of exactly \(n\) vertices.</p>
<p>To continue with the plan, we now need to make a function that for every graph would generate a family of its &ldquo;alternative representations&rdquo; (given the constraints of our generator), to make sure duplicates would not slip under the radar. First we need a permutation function, to permute the nodes (you could also use a built-in function in <code>numpy</code>, but coding this one from scratch is always fun, isn&rsquo;t it?). Here&rsquo;s the permutation generator:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">perm</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;All permutations of n elements.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">s</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">perm</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="n">s</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="p">[[]]</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">[[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">p</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">s</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">perm</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">([</span><span class="n">k</span> <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">s</span> <span class="k">if</span> <span class="n">k</span> <span class="o">!=</span> <span class="n">i</span><span class="p">]))]</span></span></span></code></pre>
</div>
<p>Now, for any given graph description, we can permute its nodes, sort the \(i,j\) within each edge, sort the edges themselves, remove duplicate alt-descriptions, and remember the list of potential impostors:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">permute</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Create a set of all possible isomorphic codes for a graph,
</span></span></span><span class="line"><span class="cl"><span class="s2">    as nice hashable tuples. All edges are i&lt;j, and sorted lexicographically.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">ps</span> <span class="o">=</span> <span class="n">perm</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">out</span> <span class="o">=</span> <span class="nb">set</span><span class="p">([])</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">ps</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">out</span><span class="o">.</span><span class="n">add</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="nb">tuple</span><span class="p">(</span><span class="nb">sorted</span><span class="p">([(</span><span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="k">if</span> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="k">else</span> <span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">g</span><span class="p">]))</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">list</span><span class="p">(</span><span class="n">out</span><span class="p">)</span></span></span></code></pre>
</div>
<p>Say, for an input description of <code>[(0, 1), (0, 2)]</code>, the function above returns three &ldquo;synonyms&rdquo;:</p>

<div class="highlight">
  <pre>((0, 1), (1, 2))
((0, 1), (0, 2))
((0, 2), (1, 2))</pre>
</div>

<p>I suspect there should be a neater way to code that, to avoid using the <code>list → set → list</code> pipeline to get rid of duplicates, but hey, it works!</p>
<p>At this point, the only thing that&rsquo;s missing is the function to check whether the graph comes in one piece, which happens to be a famous and neat algorithm called the &ldquo;<a href="https://en.wikipedia.org/wiki/Disjoint-set_data_structure">Union-Find</a>&rdquo;. I won&rsquo;t describe it here in detail, but in short, it goes though all edges and connects nodes to each other in a special way; then counts how many separate connected components (like, chunks of the graph) remain in the end. If all nodes are in one chunk, we like it. If not, I don&rsquo;t want to see it in my pictures!</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">connected</span><span class="p">(</span><span class="n">g</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Check if the graph is fully connected, with Union-Find.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">nodes</span> <span class="o">=</span> <span class="nb">set</span><span class="p">([</span><span class="n">i</span> <span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">g</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">e</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="n">roots</span> <span class="o">=</span> <span class="p">{</span><span class="n">node</span><span class="p">:</span> <span class="n">node</span> <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">nodes</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">_root</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">depth</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">node</span> <span class="o">==</span> <span class="n">roots</span><span class="p">[</span><span class="n">node</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">depth</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">_root</span><span class="p">(</span><span class="n">roots</span><span class="p">[</span><span class="n">node</span><span class="p">],</span> <span class="n">depth</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">g</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">ri</span><span class="p">,</span> <span class="n">di</span> <span class="o">=</span> <span class="n">_root</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">rj</span><span class="p">,</span> <span class="n">dj</span> <span class="o">=</span> <span class="n">_root</span><span class="p">(</span><span class="n">j</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">ri</span> <span class="o">==</span> <span class="n">rj</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">di</span> <span class="o">&lt;=</span> <span class="n">dj</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">roots</span><span class="p">[</span><span class="n">ri</span><span class="p">]</span> <span class="o">=</span> <span class="n">rj</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">roots</span><span class="p">[</span><span class="n">rj</span><span class="p">]</span> <span class="o">=</span> <span class="n">ri</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="nb">set</span><span class="p">([</span><span class="n">_root</span><span class="p">(</span><span class="n">node</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">nodes</span><span class="p">]))</span> <span class="o">==</span> <span class="mi">1</span></span></span></code></pre>
</div>
<p>Now we can finally generate the &ldquo;overkill&rdquo; list of graphs, filter it, and plot the pics:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">filter</span><span class="p">(</span><span class="n">gs</span><span class="p">,</span> <span class="n">target_nv</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Filter all improper graphs: those with not enough nodes,
</span></span></span><span class="line"><span class="cl"><span class="s2">    those not fully connected, and those isomorphic to previously considered.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">mem</span> <span class="o">=</span> <span class="nb">set</span><span class="p">({})</span>
</span></span><span class="line"><span class="cl">    <span class="n">gs2</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">g</span> <span class="ow">in</span> <span class="n">gs</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">nv</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="nb">set</span><span class="p">([</span><span class="n">i</span> <span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">g</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">e</span><span class="p">]))</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">nv</span> <span class="o">!=</span> <span class="n">target_nv</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="ow">not</span> <span class="n">connected</span><span class="p">(</span><span class="n">g</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">g</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">mem</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">gs2</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">mem</span> <span class="o">|=</span> <span class="nb">set</span><span class="p">(</span><span class="n">permute</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">target_nv</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">gs2</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Main body</span>
</span></span><span class="line"><span class="cl"><span class="n">NV</span> <span class="o">=</span> <span class="mi">6</span>
</span></span><span class="line"><span class="cl"><span class="n">gs</span> <span class="o">=</span> <span class="n">make_graphs</span><span class="p">(</span><span class="n">NV</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">gs</span> <span class="o">=</span> <span class="nb">filter</span><span class="p">(</span><span class="n">gs</span><span class="p">,</span> <span class="n">NV</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plot_graphs</span><span class="p">(</span><span class="n">gs</span><span class="p">,</span> <span class="n">figsize</span><span class="o">=</span><span class="mi">14</span><span class="p">,</span> <span class="n">dotsize</span><span class="o">=</span><span class="mi">20</span><span class="p">)</span></span></span></code></pre>
</div>
<p>For plotting the graphs I wrote a small wrapper for the MatPlotLib-based NetworkX visualizer, splitting the figure into lots of tiny little facets using Matplotlib <code>subplot</code> command. &ldquo;Kamada-Kawai&rdquo; layout below is a <a href="https://en.wikipedia.org/wiki/Force-directed_graph_drawing">popular and fast version of a spring-based layout</a>, that makes the graphs look really nice.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">plot_graphs</span><span class="p">(</span><span class="n">graphs</span><span class="p">,</span> <span class="n">figsize</span><span class="o">=</span><span class="mi">14</span><span class="p">,</span> <span class="n">dotsize</span><span class="o">=</span><span class="mi">20</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Utility to plot a lot of graphs from an array of graphs.
</span></span></span><span class="line"><span class="cl"><span class="s2">    Each graphs is a list of edges; each edge is a tuple.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">n</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">graphs</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="n">figsize</span><span class="p">,</span> <span class="n">figsize</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span><span class="o">.</span><span class="n">patch</span><span class="o">.</span><span class="n">set_facecolor</span><span class="p">(</span><span class="s2">&#34;white&#34;</span><span class="p">)</span>  <span class="c1"># To make copying possible (white background)</span>
</span></span><span class="line"><span class="cl">    <span class="n">k</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">plt</span><span class="o">.</span><span class="n">subplot</span><span class="p">(</span><span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">g</span> <span class="o">=</span> <span class="n">nx</span><span class="o">.</span><span class="n">Graph</span><span class="p">()</span>  <span class="c1"># Generate a Networkx object</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">graphs</span><span class="p">[</span><span class="n">i</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">            <span class="n">g</span><span class="o">.</span><span class="n">add_edge</span><span class="p">(</span><span class="n">e</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">e</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">        <span class="n">nx</span><span class="o">.</span><span class="n">draw_kamada_kawai</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">node_size</span><span class="o">=</span><span class="n">dotsize</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;.&#34;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&#34;&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p>Here are the results. To build the anticipation, let&rsquo;s start with something trivial: all graphs of 3 nodes:</p>
<p><img src="/matplotlib/draw-all-graphs-of-n-nodes/3nodes.png" alt="Two non isomorphic graphs with 3 nodes, the first graph connects all 3 nodes and creates a triangle. The second graph is a path graph with 3 nodes connected as a single path."></p>
<p>All graphs of 4 nodes:</p>
<p><img src="/matplotlib/draw-all-graphs-of-n-nodes/4nodes.png" alt="All six possible non isomorphic graphs with 4 nodes. The first graph is a complete graph with all 4 nodes connected to each other. The second one is a complete graph with one edge removed. The third graph is a triangle graph with one node attached with one of the nodes in the graph. The fourth graph is a star graph, with one central node connected to the other 3 nodes. The fifth one is a graph where the edges form a square. The sixth one is a path graph which connects all 4 nodes as a single path."></p>
<p>All graphs of 5 nodes:</p>
<p><img src="/matplotlib/draw-all-graphs-of-n-nodes/5nodes.png" alt="All 21 possibilities of non isomorphic graphs with 5 nodes. The different graphs show multiple possible structures from a complete graph of 5 nodes to a path graph of 5 nodes. Other structures present in this collection of graphs show a pentagon shaped graph, a star graph and others."></p>
<p>Generating figures above is of course all instantaneous on a decent computer, but for 6 nodes (below) it takes a few seconds:</p>
<p><img src="/matplotlib/draw-all-graphs-of-n-nodes/6nodes.png" alt="All 112 possibilities of non isomorphic graphs with 6 nodes. The different graphs show multiple possible structures from a complete graph of 6 nodes to a path graph of 6 nodes. Other structures present in this collection of graphs show a hexagon shaped graph, a star graph, two complete graphs with 4 nodes stacked on top of each other with the two complete 4 graphs sharing an edge and 107 other structures!"></p>
<p>For 7 nodes (below) it takes about 5-10 minutes. It&rsquo;s easy to see why: the brute-force approach generates all \(2^{\frac{n(n-1)}{2}}\) possible graphs, which means that the number of operations grows exponentially! Every increase of \(n\) by one, gives us \(n-1\) new edges to consider, which means that the time to run the program increases by \(~2^{n-1}\). For \(n=7\) it brought me from seconds to minutes, for \(n=8\) it would have shifted me from minutes to hours, and for \(n=9\), from hours, to months of computation. Isn&rsquo;t it fun? We are all specialists in exponential growth these days, so here you are :)</p>
<p><img src="/matplotlib/draw-all-graphs-of-n-nodes/7nodes.png" alt="ALL 853 possibilities of non isomorphic graphs with 7 nodes. The different graphs show multiple possible structures from a complete graph of 7 nodes to a path graph of 7 nodes. Other structures present in this collection show many star and kite-shaped graphs."></p>
<p>The code is available as a <a href="https://github.com/khakhalin/Sketches/blob/master/classic/generate_all_graphs.ipynb">Jupyter Notebook on my GitHub</a>. I hope you enjoyed the pictures, and the read! Which of those charms above would bring most luck? Which ones seem best for divination? Let me know what you think! :)</p>
<p>Contact me via <a href="https://twitter.com/ampanmdagaba">Twitter</a> or <a href="https://github.com/khakhalin">Github</a>.</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="graphs" label="graphs" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
</feed>
