livebooks/guides/network_analysis.livemd

# Network Analysis

```elixir
Mix.install([
  {:yog_ex, path: "/home/mafinar/repos/elixir/yog_ex"},
  {:kino_vizjs, "~> 0.5.0"}
])
```

## Introduction

Network analysis allows us to understand the underlying structure of a graph. Who are the most influential actors? Are there distinct communities? Where are the bottlenecks that could cause the network to fail?

`Yog` provides professional-grade tools for these questions, used in everything from social network analysis to logistics.

## 🌟 Centrality: Who is Important?

Centrality measures tell us which nodes are the most "important," but "importance" can mean different things:

*   **Degree Centrality**: Who has the most connections? (Popularity)
*   **Betweenness Centrality**: Who acts as a bridge between groups? (Brokerage)
*   **PageRank**: Who is connected to other important nodes? (Influence)

```elixir
# Create a "Bowtie" graph: two triangles connected by a bridge
g = Yog.undirected()
  |> Yog.add_edges!([
    {:a, :b, 1}, {:b, :c, 1}, {:c, :a, 1}, # Triangle 1
    {:c, :d, 1},                          # The Bridge
    {:d, :e, 1}, {:e, :f, 1}, {:f, :d, 1}  # Triangle 2
  ])

# 1. PageRank (Influence)
IO.inspect(Yog.Centrality.pagerank(g), label: "PageRank Scores")

# 2. Betweenness (Brokerage)
# Node :c and :d should have high scores as they bridge the two groups
IO.inspect(Yog.Centrality.betweenness(g), label: "Betweenness Scores")
```

## 🏘️ Community Detection

Community detection finds groups of nodes that are more densely connected to each other than to the rest of the network.

```elixir
# Generate a random graph with built-in communities
# Using Stochastic Block Model (SBM)
g = Yog.Generator.Random.sbm([10, 10, 10], [[0.8, 0.1, 0.1], [0.1, 0.8, 0.1], [0.1, 0.1, 0.8]])

# Detect communities using the Louvain method
communities = Yog.Community.Louvain.detect(g)

IO.puts "Found #{length(communities.communities)} communities."

# Visualize it! (We'll color nodes by community)
colors = ["#6366f1", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6"]
node_styles = 
  communities.communities
  |> Enum.with_index()
  |> Enum.flat_map(fn {nodes, idx} -> 
    color = Enum.at(colors, rem(idx, length(colors)))
    Enum.map(nodes, fn node -> {node, [color: color, style: "filled", fillcolor: color]} end)
  end)
  |> Map.new()

dot = Yog.Render.DOT.to_dot(g, node_attributes: node_styles)
Kino.VizJS.render(dot)
```

## 🏗️ Connectivity & Robustness

A network is only as strong as its weakest link. `Yog` can find **Articulation Points** (nodes whose removal increases the number of connected components) and **Bridges** (edges whose removal does the same).

```elixir
g = Yog.undirected()
  |> Yog.add_edges!([
    {1, 2, 1}, {2, 3, 1}, {3, 1, 1}, # Component 1
    {3, 4, 1},                      # Bridge!
    {4, 5, 1}, {5, 6, 1}, {6, 4, 1}  # Component 2
  ])

# Find Articulation Points
# Nodes 3 and 4 are articulation points
IO.inspect(Yog.Connectivity.Articulation.find(g), label: "Articulation Points")

# Find Bridges
# Edge {3, 4} is a bridge
IO.inspect(Yog.Connectivity.Bridge.find(g), label: "Bridges")
```

## Summary

`Yog`'s network analysis toolkit includes:
1.  **9+ Centrality Measures** for identifying key actors.
2.  **State-of-the-art Community Detection** (Louvain, Leiden, Infomap).
3.  **Connectivity Analysis** to identify vulnerabilities and bottlenecks.

Next, explore **Network Flow** to see how much "traffic" your network can handle!