Graphs.jl icon indicating copy to clipboard operation
Graphs.jl copied to clipboard

human-readable output for simple graphs

Open etiennedeg opened this issue 2 years ago • 4 comments

Fix #139

Should I omit vertices with degree 0 ?

julia> Graph()
{0, 0} undirected simple Int64 graph

julia> Graph(5)
{5, 0} undirected simple Int64 graph
1 => []
2 => []
3 => []
4 => []
5 => []

julia> Graph(100)
{100, 0} undirected simple Int64 graph
  1 => []
  2 => []
  3 => []
  4 => []
  5 => []
  6 => []
  ⋮
 95 => []
 96 => []
 97 => []
 98 => []
 99 => []
100 => []

julia> Graph{Int16}(5)
{5, 0} undirected simple Int16 graph
1 => []
2 => []
3 => []
4 => []
5 => []

julia> path_graph(5)
{5, 4} undirected simple Int64 graph
1 => [2]
2 => [1, 3]
3 => [2, 4]
4 => [3, 5]
5 => [4]

julia> path_graph(100)
{100, 99} undirected simple Int64 graph
  1 => [2]
  2 => [1, 3]
  3 => [2, 4]
  4 => [3, 5]
  5 => [4, 6]
  6 => [5, 7]
  ⋮
 95 => [94, 96]
 96 => [95, 97]
 97 => [96, 98]
 98 => [97, 99]
 99 => [98, 100]
100 => [99]

julia> path_graph(100) # REPL with minimum height
{100, 99} undirected simple Int64 graph …

julia> path_graph(100) # slowly increasing height
{100, 99} undirected simple Int64 graph 
  ⋮

julia> path_graph(100)
{100, 99} undirected simple Int64 graph
  1 => [2]
  ⋮

julia> path_graph(100)
{100, 99} undirected simple Int64 graph
  1 => [2]
  ⋮
100 => [99]

julia> erdos_renyi(1000, 0.5)
{1000, 249729} undirected simple Int64 graph
   1 => [2, 3, 5, 6, 7, 9, 10, 16, 17, 19  …  977, 980, 981, 983, 987, 992, 993, 994, 995, 999]
   2 => [1, 3, 6, 7, 13, 14, 16, 17, 18, 19  …  984, 985, 987, 988, 991, 994, 996, 997, 998, 1000]
   3 => [1, 2, 6, 7, 9, 11, 13, 16, 17, 18  …  978, 979, 980, 981, 987, 992, 994, 998, 999, 1000]
   4 => [6, 9, 11, 16, 17, 20, 21, 22, 24, 25  …  984, 985, 987, 988, 992, 994, 995, 997, 999, 1000]
   5 => [1, 6, 7, 10, 15, 17, 18, 19, 21, 25  …  984, 986, 988, 991, 994, 995, 996, 998, 999, 1000]
   6 => [1, 2, 3, 4, 5, 7, 8, 9, 11, 15  …  977, 980, 983, 984, 989, 993, 995, 996, 998, 1000]
   ⋮
 995 => [1, 4, 5, 6, 7, 10, 11, 12, 13, 14  …  983, 985, 986, 987, 988, 989, 992, 994, 998, 1000]
 996 => [2, 5, 6, 8, 9, 10, 13, 14, 15, 16  …  979, 980, 982, 985, 987, 990, 991, 993, 999, 1000]
 997 => [2, 4, 7, 8, 9, 11, 13, 15, 18, 22  …  985, 988, 989, 990, 991, 992, 993, 994, 998, 1000]
 998 => [2, 3, 5, 6, 7, 8, 9, 11, 13, 16  …  984, 985, 988, 990, 991, 994, 995, 997, 999, 1000]
 999 => [1, 3, 4, 5, 8, 9, 11, 12, 14, 15  …  975, 977, 978, 982, 983, 984, 986, 989, 996, 998]
1000 => [2, 3, 4, 5, 6, 7, 11, 13, 17, 18  …  986, 989, 991, 992, 993, 994, 995, 996, 997, 998]

etiennedeg avatar Jun 22 '22 15:06 etiennedeg

Codecov Report

Merging #148 (110545f) into master (48cb6ec) will increase coverage by 0.49%. The diff coverage is 78.04%.

@@            Coverage Diff             @@
##           master     #148      +/-   ##
==========================================
+ Coverage   97.54%   98.04%   +0.49%     
==========================================
  Files         109      109              
  Lines        6314     5779     -535     
==========================================
- Hits         6159     5666     -493     
+ Misses        155      113      -42     

codecov[bot] avatar Jun 22 '22 15:06 codecov[bot]

I am not sure if I like this. For small graph it makes sense, but for larger graphs like your last example, I feel like it adds too much noise, without providing much information to the user.

I wonder if a small adjacency matrix with some unicode characters would be more useful?

Another point, if we are going for printing the whole graph, maybe we can use do-syntax instead of =>? https://en.wikipedia.org/wiki/DOT_%28graph_description_language%29

simonschoelly avatar Jun 22 '22 15:06 simonschoelly

Something like 2 -- {1 3} (or with commas) and 2 -> {1 3} for directed graphs? Do you have an idea for an adjacency matrix representation? A dotted representation like for sparse arrays?

etiennedeg avatar Jun 22 '22 17:06 etiennedeg

I tried a circle plot, not sure if this is better, even for small graphs (it looks better by copy-pasting it in the REPL). For bigger graphs, maybe we can use some scaling on the density of edges passing through a point but it gets time consuming, and I'm not sure it will be much more informative. IMO, I prefer printing the outneighbors lists.

julia> plot(stdout, erdos_renyi(5, 0.5))
{5, 6} undirected simple Int64 graph
⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠴1⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⡠⠒⠁⠀⠀⢱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⣀⠔⠉⠀⠀⠀⠀⠀⠀⢇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⢀⡤⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀5⠦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢱⠀⠀⠀⠀⠀⢀⠴2⠀
⠀⠘⡄⠈⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⢇⠀⢀⡠⠚⠁⢠⠃⠀
⠀⠀⢸⠀⠀⠀⠉⠒⣄⠀⠀⠀⠀⠀⠀⣸⡖⠉⠀⠀⠀⡇⠀⠀
⠀⠀⠀⢇⠀⠀⠀⠀⠀⠙⠤⣀⣀⠴⠉⠀⢱⠀⠀⠀⡸⠀⠀⠀
⠀⠀⠀⠸⡀⠀⠀⠀⠀⢀⡤⠚⠓⢤⡀⠀⠀⢇⠀⢀⠇⠀⠀⠀
⠀⠀⠀⠀⢱⠀⠀⡠⠖⠁⠀⠀⠀⠀⠈⠲⢄⠘⡄⡎⠀⠀⠀⠀
⠀⠀⠀⠀⠈4⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙3⠁⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

julia> plot(stdout, erdos_renyi(7, 0.5))
{7, 14} undirected simple Int64 graph
⠀⠀⠀⠀⠀⠀⠀⠀⢀⡠⢶1⢷⠦⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⢀⡠⠔⠚⠁⡔⠁⠀⠀⠑⡄⠈⠓⠤⢄⡀⠀⠀⠀⠀
⠀⠀⠀7⡿⡒⠒⢲⠚⠒⠒⠒⠒⠒⠚⢳⡒⠒⠒⠛2⠀⠀⠀
⠀⠀⠀⠀⠑⢌⡕⠓⠤⡀⠀⠀⠀⠀⠀⠀⠘⢄⠀⠀⡇⡇⠀⠀
⠀⠀⠀⠀⢠⠊⠢⡀⠀⠈⠑⠒⠤⡀⠀⠀⠀⠀⠣⣼⠀⢸⡀⠀
⠀⠀⠀⡔⠁⠀⠀⠑⢆⠀⠀⠀⠀⠈⠑⠒⠤⡀⠀⡞⢢⠀⢇⠀
⠀⣠⠊⠀⠀⠀⠀⠀⠈⠲⡀⠀⠀⠀⠀⠀⠀⠈⢱⠓⠤⡑⣼⡀
6⣷⢖⡒⠒⠒⠒⠒⠒⠒⠛⢖⠒⠒⠒⠒⠒⠒⡞⠒⠒⠚⣻3
⠀⠀⠓⡌⠑⠢⢤⡀⠀⠀⠀⠈⠱⡀⠀⠀⠀⢰⠁⠀⢠⠚⠀⠀
⠀⠀⠀⠘⢢⡀⠀⠈⠑⠒⢤⣀⠀⠈⢆⠀⠀⡜⢀⡔⠁⠀⠀⠀
⠀⠀⠀⠀⠀⠘⢄⠀⠀⠀⠀⠀⠉⠒⠢⣱⣤⡣⠃⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀5⠉⠉⠉⠉⠉⠉⠉⠉4⠀⠀⠀⠀⠀⠀⠀

julia> plot(stdout, erdos_renyi(10, 0.5))
{10, 19} undirected simple Int64 graph
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⢦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⣠⠒⠶⠶⣒⡒⢲⢻⠒⠳⡖⠒⠒⠒⢢⠀⠀⠀⠀⠀
⠀⠀⢀⡰⠁⠀⠀⠀⠀⢈⡟⢺⠢⠤⣘⣄⠀⠀⢸⠀⠀⠀⠀⠀
⠀⢠⠎⠀⠀⠀⠀⠀⠀⡸⠀⢸⠀⠀⠀⠈⠫⡑⢺⠤⣀⣀⠀⠀
⠀⠹⡶⡢⢤⣀⠀⠀⢠⠃⠀⢸⠀⠀⠀⠀⠀⠑⣼⡤⢔⢶⣷⠀
⠀⠀⠘⢬⠓⢄⡉⠑⡞⠤⢄⣸⣀⡠⠤⠒⠊⢉⣸⢺⡥⢣⢻⠀
⠀⠀⠀⠀⢣⡀⣉⣲⣥⠒⠊⢹⠉⠑⠒⣤⢖⣉⢸⠚⠓⡇⢸⠀
⠀⣀⣤⣔⣚⣙⣄⣇⣀⣙⣤⣸⣀⣴⣉⣀⣀⣰⣻⣓⣺⣼⣾⠀
⠀⠘⢆⠀⠀⠀⡜⢆⡀⢀⡤⢺⠓⢤⡀⢀⠞⠀⢸⢀⠇⡰⠃⠀
⠀⠀⠈⠲⡀⢰⠁⡠⠷⡁⠀⢸⠀⠀⡸⠺⢄⠀⢸⣎⠖⠁⠀⠀
⠀⠀⠀⠀⠙⠾⣋⣀⠀⠉⢆⢸⢀⠎⠁⠀⠀⠙⠺⠋⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠉⠒⠚⠿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

julia> plot(stdout, erdos_renyi(20, 0.5))
{20, 95} undirected simple Int64 graph
⠀⠀⠀⠀⠀⠀⢀⣠⣤⣶⢶⣷⣯⣶⣦⣤⡀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⣠⣶⣿⣿⡿⣿⣟⠶⣿⣿⣿⣿⢾⢶⣦⠀⠀⠀⠀⠀
⠀⠀⢠⣴⣿⣿⣿⣷⣷⣿⢷⡽⣿⣿⣿⢿⣷⣿⣯⣦⣤⡀⠀⠀
⠀⢠⣾⣿⣿⣿⡮⢿⣿⡭⢟⣿⡻⣛⣽⣿⣿⣬⣿⣟⣻⣺⣆⠀
⢠⣿⣿⣾⣿⣿⡿⡽⣿⣠⠛⣼⢟⣷⣿⣽⢎⢽⣅⡬⠶⣻⣿⠀
⣼⣿⣿⣽⢳⣷⣟⣝⣿⣿⣾⣿⣱⣷⢿⢿⠯⣿⢌⣢⡮⢫⠻⡄
⠘⣿⣻⣿⣻⡾⣿⣻⣷⣿⢿⣏⣟⡿⣷⢼⣄⣯⢾⢿⣗⣇⣾⠁
⠀⣿⣿⣿⣿⣽⣶⣷⡟⡹⣭⣽⡿⡏⢏⣻⢿⡲⠫⢷⡾⣿⣏⠀
⠀⠘⢿⣿⣿⢿⣏⣟⣯⡕⢣⢯⣻⣽⣺⣸⣿⣯⠗⣾⣿⣽⠃⠀
⠀⠀⠘⠻⣽⢧⣿⣿⡷⣱⡮⡤⡞⣷⣿⣿⣧⣿⣼⣾⡿⠃⠀⠀
⠀⠀⠀⠀⠙⠾⣿⣿⣿⣿⣯⣭⣯⢯⣿⣿⣿⣿⠷⠋⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠈⠛⠛⠛⠿⠿⠿⠛⠛⠁⠀⠀⠀⠀⠀⠀⠀

etiennedeg avatar Jun 23 '22 15:06 etiennedeg