Skip to content
Back to skills

Algo Graph Representations

ASecurity

Graph representations — adjacency matrix, adjacency list, edge list — with complexity tables, implementation patterns, and biological network use cases.

  • 4 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added May 27, 2026
data-aipythongoreactnode

Security analysis

A100/100

Scanned May 27, 2026

npx -y skills add Pavel-Kravchenko/Bioinformatics --skill algo-graph-representations --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Algo Graph Representations?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Algo Graph Representations
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/pavel-kravchenko-algo-graph-representations/badge)](https://www.skillsdirectory.com/skills/pavel-kravchenko-algo-graph-representations)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: algo-graph-representations
description: Graph representations — adjacency matrix, adjacency list, edge list — with complexity tables, implementation patterns, and biological network use cases.
tool_type: python
primary_tool: NumPy
---

# Graph Representations

## Complexity Comparison

| Operation | Adjacency Matrix | Adjacency List | Edge List |
|-----------|-----------------|----------------|------------|
| Space | O(V²) | O(V + E) | O(E) |
| Add edge | O(1) | O(1) | O(1) |
| Remove edge | O(1) | O(degree) | O(E) |
| Check edge | O(1) | O(degree) w/ list; O(1) w/ set | O(E) |
| Get neighbors | O(V) | O(1) access + O(degree) iterate | O(E) |
| Iterate all edges | O(V²) | O(E) | O(E) |

## Decision Table

| Scenario | Use |
|----------|-----|
| Dense graph (E ≈ V²) | Adjacency Matrix |
| Sparse graph (most bio networks) | Adjacency List |
| Frequent edge existence queries | Adjacency Matrix |
| BFS / DFS traversal | Adjacency List |
| MST (Kruskal's), file I/O | Edge List |
| Small V, matrix operations needed | Adjacency Matrix |

**Most biological networks (PPI, GRN, metabolic) are sparse — adjacency lists are almost always the right choice.**

## Bio Network Vertex/Edge Mapping

| Application | Vertices | Edges |
|------------|----------|-------|
| PPI network | Proteins | Physical interactions |
| Metabolic network | Metabolites | Reactions |
| Gene regulatory | Genes / TFs | Regulatory relationships |
| de Bruijn graph | k-mers | Overlaps |
| Phylogenetic tree | Species / sequences | Evolutionary relationships |

## Implementations

### Adjacency Matrix
```python
import numpy as np

class AdjacencyMatrix:
    def __init__(self, vertices: list):
        self.vertices = vertices
        self.idx = {v: i for i, v in enumerate(vertices)}
        self.n = len(vertices)
        self.matrix = np.zeros((self.n, self.n), dtype=int)

    def add_edge(self, u, v, directed: bool = False):
        i, j = self.idx[u], self.idx[v]
        self.matrix[i][j] = 1
        if not directed:
            self.matrix[j][i] = 1

    def has_edge(self, u, v) -> bool:          # O(1)
        return bool(self.matrix[self.idx[u]][self.idx[v]])

    def neighbors(self, u) -> list:            # O(V)
        i = self.idx[u]
        return [self.vertices[j] for j in range(self.n) if self.matrix[i][j]]

    def degree(self, u) -> int:
        return int(np.sum(self.matrix[self.idx[u]]))
```

### Adjacency List
```python
from collections import defaultdict

class AdjacencyList:
    def __init__(self):
        self.graph: dict = defaultdict(set)  # sets give O(1) edge lookup

    def add_edge(self, u, v, directed: bool = False):
        self.graph[u].add(v)
        if not directed:
            self.graph[v].add(u)

    def has_edge(self, u, v) -> bool:         # O(1) with sets
        return v in self.graph.get(u, set())

    def neighbors(self, u) -> set:            # O(1) access
        return self.graph.get(u, set())

    def degree(self, u) -> int:
        return len(self.graph.get(u, []))

    def edges(self) -> list:                  # undirected: each edge once
        seen = set()
        result = []
        for u in self.graph:
            for v in self.graph[u]:
                key = tuple(sorted([str(u), str(v)]))
                if key not in seen:
                    seen.add(key)
                    result.append((u, v))
        return result
```

### Edge List
```python
class EdgeList:
    def __init__(self):
        self.edges: list[tuple] = []
        self._vertices: set = set()

    def add_edge(self, u, v, weight: float = 1.0):
        self.edges.append((u, v, weight))
        self._vertices.update([u, v])

    def sorted_by_weight(self) -> list:       # for Kruskal's MST
        return sorted(self.edges, key=lambda e: e[2])
```

### Loading from file
```python
from pathlib import Path
from collections import defaultdict

def load_edge_list(filepath: str) -> dict[str, list[tuple]]:
    """Parse 'node_a  node_b  weight' file into adjacency list."""
    graph: dict = defaultdict(list)
    with open(filepath) as f:
        for line in f:
            line = line.strip()
            if not line:
                continue
            u, v, w = line.split()
            graph[u].append((v, float(w)))
            graph[v].append((u, float(w)))  # undirected
    return dict(graph)
```

## Memory Analysis (Human PPI: 20,000 proteins, 300,000 interactions)

```python
V, E = 20_000, 300_000
matrix_mb = V * V * 8 / 1e6              # ~3,200 MB
list_mb   = (2 * E * 8 + V * 56) / 1e6  # ~5.9 MB
# Ratio: ~542x — adjacency list wins for sparse graphs
```

## Pitfalls

- **Adjacency matrix for large sparse graphs**: 20k proteins → 3.2 GB matrix for a network that fits in 6 MB as an adjacency list.
- **List vs set for adjacency list**: using a `list` makes `has_edge` O(degree); use `set` for O(1) lookup if duplicate edges are not needed.
- **Undirected graphs and `edges()`**: naively iterating gives each edge twice. Track seen pairs with a set or only iterate `u < v`.
- **Vertex not in graph**: `graph[v]` on a `defaultdict` silently creates an empty entry. Use `graph.get(v, set())` to avoid spurious vertices.
- **Edge list for BFS/DFS**: finding neighbors requires scanning all edges — O(E) per node. Use an adjacency list instead.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…