README.md

# Hypergraph

Elixir library for working with hypergraphs.

A hypergraph is a generalization of a regular graph where edges can connect more than two vertices at once.
In a regular graph, each edge connects exactly two vertices. But in a hypergraph, an edge (called a "hyperedge") can connect any number of vertices - it could connect 3, 4, 5, or even all vertices in the hypergraph simultaneously.

Mathematically, a hypergraph `H` is defined as an ordered pair `(V, E)` where `V` is a set of vertices and `E` is a set of hyperedges, with each hyperedge being a non-empty subset of `V`.

Hypergraphs are particularly useful for modeling complex relationships that involve multiple entities at once — such as social groups, chemical reactions, collaborative networks, and more.

## Installation

Add `hypergraph` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:hypergraph, "~> 1.0.0"}
  ]
end
```

## Modules

* [`Hypergraph`](https://hexdocs.pm/hypergraph/Hypergraph.html) — Create, update, and query hypergraphs
* [`Hypergraph.CorrelationLength`](https://hexdocs.pm/hypergraph/Hypergraph.CorrelationLength.html) — Measure how far structural information propagates using Mutual Information decay
* [`Hypergraph.NetworkGraph`](https://hexdocs.pm/hypergraph/Hypergraph.NetworkGraph.html) — Render a hypergraph as a VegaLite network graph

## Usage

### Building a hypergraph

```elixir
hg =
  Hypergraph.new()
  |> Hypergraph.add_hyperedge([:alice, :bob, :charlie])  # 3-way connection
  |> Hypergraph.add_hyperedge([:bob, :diana])            # 2-way connection
  |> Hypergraph.add_hyperedge([:diana, :eve, :frank])    # another group
```

### Querying

```elixir
Hypergraph.vertices(hg)                        #=> MapSet of all vertices
Hypergraph.hyperedges(hg)                      #=> list of all hyperedges
Hypergraph.degree(hg, :bob)                    #=> number of hyperedges containing :bob
Hypergraph.neighbors(hg, :alice)               #=> vertices sharing a hyperedge with :alice
Hypergraph.incident_hyperedges(hg, :bob)       #=> hyperedges that contain :bob
Hypergraph.connected?(hg, :alice, :charlie)    #=> true if they share a hyperedge
Hypergraph.vertex_count(hg)                    #=> total number of vertices
Hypergraph.hyperedge_count(hg)                 #=> total number of hyperedges
```

### Statistics

```elixir
Hypergraph.stats(hg)
# %{
#   vertex_count: 5,
#   hyperedge_count: 3,
#   max_hyperedge_size: 3,
#   min_hyperedge_size: 2,
#   avg_hyperedge_size: 2.67,
#   max_degree: 2,
#   min_degree: 1,
#   avg_degree: 1.4
# }
```

### Modifying a hypergraph

```elixir
hg = Hypergraph.remove_vertex(hg, :eve)           # remove vertex and its hyperedges
hg = Hypergraph.remove_hyperedge(hg, [:bob, :diana])
```

### Converting to a regular graph

```elixir
# Returns pairwise edges for every pair of vertices sharing a hyperedge
Hypergraph.to_graph(hg)
#=> [{:alice, :bob}, {:alice, :charlie}, {:bob, :charlie}, ...]
```

### Correlation Length

Measures how far structural information propagates through the hypergraph by fitting an exponential decay curve to Mutual Information values between distant regions.

```elixir
{:ok, length} = Hypergraph.CorrelationLength.compute(hg)
# length is a float representing the characteristic decay distance

# With custom parameters:
{:ok, length} = Hypergraph.CorrelationLength.compute(hg,
  _max_distance = 15,
  _region_size = 3,
  _samples = 200
)
```

Possible error returns: `:insufficient_data`, `:insufficient_points`, `:insufficient_positive_data`, `:no_decay`, `:singular_matrix`.

### Visualization

Renders the hypergraph as an interactive VegaLite network graph. Vertices are arranged in a circular layout; node size and color reflect vertex degree.

```elixir
# In a Livebook or any environment with kino_vega_lite:
Hypergraph.NetworkGraph.visualize(hg)
```

See `examples.livemd` for runnable Livebook examples including social network and chemical reaction hypergraphs.

## License

Apache 2.0 — see [LICENSE](LICENSE).