Quando a resposta é "quem está ligado a quê, e como"

Grafos: de BFS a Knowledge Graphs e GNNs

Grafo é a estrutura para dados de relacionamento — e o tema atravessa quatro mundos que raramente aparecem juntos: algoritmos de entrevista, ciência de redes, aprendizado de máquina em grafos, e grafos de conhecimento para IA. Esta apostila liga os quatro, do fundamento aplicado ao GraphRAG.

10 módulosBFS/DFS · Dijkstra · A*centralidade & comunidadesnode2vec · GNNKnowledge Graphs · GraphRAGexercícios com gabarito
💡 Onde esta apostila se encaixa

O capítulo 8 da apostila de Algoritmos com Python cobre BFS/DFS/Dijkstra/topológica/Union-Find em nível de entrevista — aqui isso é recap (módulo 2), e o foco é o grafo aplicado. O módulo 7 da apostila de NoSQL apresenta bancos de grafo; aqui a modelagem de grafo já foi tratada na Modelagem de Dados NoSQL (módulo 7). Knowledge Graphs para IA conectam com a apostila de RAG.

MÓDULO 01 · BÁSICO

Vocabulário e representações

Objetivo: fixar o vocabulário (dirigido, ponderado, DAG, bipartido, esparso) e escolher a representação — lista de adjacência, matriz, CSR — pelo custo que ela impõe.

1.1 O vocabulário mínimo

TermoSignificadoExemplo
Nó / vértice, arestaentidade e ligaçãopessoa, "é amiga de"
Dirigido vs não-dirigidoa aresta tem sentido?"segue" (dirigido); "amigo de" (não)
Ponderadoaresta com peso/custodistância, tempo, custo, força da relação
Graunº de arestas de um nó (in/out se dirigido)seguidores = grau de entrada
Caminho, ciclosequência de nós por arestas; caminho que volta ao iníciorota; dependência circular
DAGdirigido acíclicodependências de build, pipeline, árvore de tarefas
Conexo / componentesubconjunto onde todos se alcançamilhas num grafo social
Bipartidodois grupos, arestas só entre gruposusuários × produtos; alunos × turmas
Esparso vs denso|E| ≈ |V| vs |E| ≈ |V|²quase todo grafo real é esparso

1.2 As três representações

# Lista de adjacência — o padrão para grafos esparsos
adj = { "A": [("B", 3), ("C", 1)], "B": [("C", 7)], "C": [] }
# espaço O(V+E); vizinhos de um nó em O(grau); "existe aresta A-B?" em O(grau)

# Matriz de adjacência — boa para grafos densos e operações de álgebra linear
#     A  B  C
# A [ 0  3  1 ]   espaço O(V²); "existe aresta?" em O(1); vizinhos em O(V)

# CSR (Compressed Sparse Row) — o formato de bibliotecas de alto desempenho
# dois arrays (indptr, indices [+ data]); cache-friendly, imutável; usado por SciPy, cuGraph, PyG
OperaçãoLista adj.MatrizCSR
EspaçoO(V+E)O(V²)O(V+E)
Iterar vizinhos de vO(grau(v))O(V)O(grau(v)), sequencial em memória
Existe aresta (u,v)?O(grau(u))O(1)O(grau(u))
Adicionar arestaO(1)O(1)caro (reconstruir)
💡 Regra prática

Grafo dinâmico e esparso (a esmagadora maioria): lista de adjacência (dict de listas, ou um banco de grafo). Grafo pequeno e denso, ou algoritmo que é multiplicação de matrizes (PageRank, caminhos via potências): matriz. Grafo grande, estático, processamento em lote/GPU: CSR.

💼 Mercado de trabalho

Em entrevista, a primeira pergunta implícita de todo problema de grafo é "como você representa?". Dizer "lista de adjacência porque o grafo é esparso, o que dá O(V+E) de espaço e itera vizinhos em O(grau)" antes de codar mostra base. Reconhecer um problema como "isto é um DAG → ordenação topológica" ou "isto é bipartido → matching" economiza metade do tempo.

✏️ Exercício 1 — Modele e represente

Para cada caso, diga: dirigido ou não? ponderado? é um DAG? bipartido? qual representação: (a) malha rodoviária de uma cidade para calcular rotas; (b) dependências entre 5.000 tarefas de um pipeline de CI; (c) quais dos 2 milhões de usuários avaliaram quais dos 500 mil filmes.

Gabarito: (a) Dirigido (mão única existe), ponderado (tempo/distância), não é DAG (há ciclos — quarteirões), não bipartido. Lista de adjacência (esparso: cada cruzamento liga a poucos). (b) Dirigido, geralmente não ponderado, DAG (dependência circular seria erro — detectá-la é um uso), não bipartido. Lista de adjacência + ordenação topológica. (c) Não-dirigido, ponderado pela nota, bipartido (usuários de um lado, filmes do outro), esparso. Lista de adjacência ou matriz esparsa (CSR) — é a base de sistemas de recomendação e de filtragem colaborativa.

MÓDULO 02 · BÁSICO

Travessia: BFS e DFS na prática

Objetivo: recap rápido de BFS e DFS e — o que importa aqui — o mapa de qual problema aplicado cada uma resolve.

2.1 Os dois esqueletos

# BFS — fila; visita por "camadas" (distância crescente em nº de arestas)
from collections import deque
def bfs(adj, s):
    dist = {s: 0}; q = deque([s])
    while q:
        u = q.popleft()
        for v in adj[u]:
            if v not in dist:
                dist[v] = dist[u] + 1
                q.append(v)
    return dist

# DFS — pilha/recursão; vai fundo antes de voltar
def dfs(adj, u, seen):
    seen.add(u)
    for v in adj[u]:
        if v not in seen:
            dfs(adj, v, seen)

Ambas: O(V+E) com lista de adjacência. BFS usa fila; DFS usa pilha (ou a de chamadas — cuidado com o limite de recursão em grafos grandes; use pilha explícita).

2.2 O mapa "problema → algoritmo"

ProblemaFerramenta
Menor nº de saltos entre dois nós; "amigos até 3º grau"BFS (grafo não ponderado)
Todos os nós alcançáveis / componentes conexosBFS ou DFS (qualquer)
Existe ciclo? / detectar dependência circularDFS com cores (branco/cinza/preto) — aresta para nó "cinza" = ciclo
Ordem válida de execução de tarefas com dependênciasOrdenação topológica (DFS pós-ordem, ou Kahn com fila de grau 0)
Menor caminho em grade / labirinto (custo uniforme)BFS
Menor caminho com pesos 0/10-1 BFS (deque)
Flood fill / regiões conectadas em imagemBFS ou DFS
Bicoloração / testar se é bipartidoBFS/DFS alternando cor
⚠️ BFS não serve para grafo ponderado

BFS acha o menor número de arestas, não o menor custo. Se as arestas têm pesos, o menor caminho pode ter mais saltos — aí é Dijkstra (módulo 3). Usar BFS em grafo ponderado é um erro clássico de entrevista.

💼 Mercado de trabalho

Metade dos problemas de grafo em entrevista é "reconheça que é BFS/DFS e adapte". Sinais: "menor número de passos" → BFS; "todos os caminhos / combinações / detectar ciclo" → DFS/backtracking; "ordem respeitando pré-requisitos" → topológica. Saber a coloração de 3 estados da DFS para detecção de ciclo em grafo dirigido é esperado em vaga pleno+.

✏️ Exercício 2 — Escolha e justifique

(a) Um build system precisa dizer se a configuração tem dependência circular e, se não, em que ordem compilar. (b) Numa rede social, "mostre pessoas a até 2 conexões de mim". (c) Verificar se um mapa pode ser colorido com 2 cores sem vizinhos iguais.

Gabarito: (a) DFS com 3 cores para detectar ciclo em grafo dirigido; se não houver, ordenação topológica (Kahn ou DFS pós-ordem invertida) dá a ordem de compilação. (b) BFS a partir de "mim", parando na camada 2 (dist == 2) — grafo não ponderado, "número de saltos". (c) BFS/DFS bicoloração: colore o nó inicial, alterna a cor nos vizinhos; se encontrar uma aresta entre dois nós da mesma cor, não é bipartido/2-colorível.

MÓDULO 03 · INTERMEDIÁRIO

Caminhos mínimos

Objetivo: escolher entre Dijkstra, A*, Bellman-Ford e Floyd-Warshall pelo que o problema tem — pesos negativos, heurística disponível, um par ou todos os pares.

3.1 A tabela de decisão

AlgoritmoResolvePesos negativos?Complexidade
BFS1→todos, sem pesoO(V+E)
Dijkstra1→todos, pesos ≥ 0nãoO((V+E) log V) com heap
A*1→1, pesos ≥ 0, com heurística admissívelnão≤ Dijkstra na prática; ótimo se h é admissível
Bellman-Ford1→todos, aceita pesos negativos; detecta ciclo negativosimO(V·E)
Floyd-Warshalltodos→todossim (sem ciclo negativo)O(V³)
Johnsontodos→todos, esparso, com negativossimO(V·E + V² log V)

3.2 Dijkstra — o cavalo de batalha

import heapq
def dijkstra(adj, s):                 # adj[u] = [(v, w), ...], w >= 0
    dist = {s: 0}; pq = [(0, s)]
    while pq:
        d, u = heapq.heappop(pq)
        if d > dist.get(u, float("inf")): continue   # entrada obsoleta
        for v, w in adj[u]:
            nd = d + w
            if nd < dist.get(v, float("inf")):
                dist[v] = nd
                heapq.heappush(pq, (nd, v))
    return dist

3.3 A* — Dijkstra com palpite

A* prioriza pela soma f(n) = g(n) + h(n), onde g é o custo real até n e h é uma estimativa do custo de n até o destino. Se h nunca superestima (admissível) — ex.: distância em linha reta num mapa — A* acha o caminho ótimo explorando muito menos nós que Dijkstra. É o algoritmo de rotas de GPS e de pathfinding em jogos.

3.4 Bellman-Ford e Floyd-Warshall

💼 Mercado de trabalho

Perguntas: "por que Dijkstra não funciona com pesos negativos?" (fecha nós cedo demais), "quando usar A* em vez de Dijkstra?" (par único + heurística admissível), "como detectar arbitragem / ciclo negativo?" (Bellman-Ford na V-ésima iteração). Em system design de mapas/logística/jogos, saber posicionar A* e pré-computação (contraction hierarchies) é diferencial.

✏️ Exercício 3 — Qual algoritmo?

(a) App de entregas: melhor rota de um depósito para 1 endereço, ruas com tempo estimado, você tem as coordenadas. (b) Detectar se um conjunto de taxas de câmbio permite lucro por conversões em ciclo. (c) Num jogo de tabuleiro 20×20, distância mínima entre todos os pares de casas, com custos de terreno. (d) Menor caminho num grafo social não ponderado.

Gabarito: (a) A* — par único, pesos ≥ 0, heurística = distância em linha reta (admissível). (b) Bellman-Ford sobre o grafo de −log(taxa); ciclo negativo = arbitragem. (c) 400 nós, todos os pares, custos não-negativos → Floyd-Warshall (O(V³) ≈ 64 M, ok) ou Dijkstra a partir de cada nó. (d) BFS — sem pesos, "número de saltos".

MÓDULO 04 · INTERMEDIÁRIO

Estrutura: MST, SCC, pontes

Objetivo: os algoritmos que revelam a forma do grafo — árvore geradora mínima, componentes fortemente conexos, e pontos frágeis (pontes e articulações).

4.1 Árvore Geradora Mínima (MST)

Conectar todos os nós com o menor custo total de arestas, sem ciclos. Aplicações: projetar redes (elétrica, fibra, água) com custo mínimo; clustering (remover as arestas mais caras da MST separa grupos); aproximações para o caixeiro viajante.

AlgoritmoIdeiaEstruturaComplexidade
Kruskalordena arestas por peso; adiciona a próxima se não formar cicloUnion-Find (DSU)O(E log E)
Primcresce a árvore a partir de um nó, sempre pela aresta mais barata que sai delaheapO(E log V)

Kruskal brilha em grafo esparso; Prim, em denso (com heap) ou quando você já tem uma matriz.

4.2 Componentes Fortemente Conexos (SCC) grafo dirigido

Um SCC é um subconjunto máximo onde todo nó alcança todo outro (ida e volta). Contrair cada SCC num super-nó transforma qualquer grafo dirigido num DAG — o que permite ordenação topológica e análise de dependências mesmo com ciclos presentes.

4.3 Pontes e pontos de articulação robustez

💼 Mercado de trabalho

MST e Union-Find caem muito (Kruskal é praticamente "DSU + ordenação"). SCC aparece em problemas de dependência e em 2-SAT. Pontes/articulações caem como "encontre o ponto único de falha da rede". Saber que contrair SCCs dá um DAG é uma sacada que resolve vários problemas de grafo dirigido com ciclo.

✏️ Exercício 4 — Estrutura revela o quê

(a) Uma operadora quer ligar 200 torres com fibra ao menor custo; você tem o custo de cada trecho possível. (b) Num microsserviço com 60 serviços, quais grupos têm dependência circular entre si? (c) Numa rede de 500 enlaces, quais enlaces, se caírem sozinhos, dividem a rede?

Gabarito: (a) MST — Kruskal (esparso) com Union-Find, ou Prim. O custo da MST é o mínimo para conectar tudo. (b) SCC (Tarjan/Kosaraju) sobre o grafo de dependências dirigido: cada SCC com mais de um serviço é um grupo com dependência circular — candidato a refatoração. (c) Pontes — DFS com disc/low; cada ponte é um enlace cuja queda desconecta, ou seja, um SPOF estrutural.

MÓDULO 05 · INTERMEDIÁRIO → AVANÇADO

Fluxo e emparelhamento

Objetivo: reconhecer os problemas que viram fluxo máximo ou emparelhamento bipartido — muitas vezes disfarçados de "alocação", "capacidade" ou "corte".

5.1 Fluxo máximo / corte mínimo

Dado um grafo com capacidades nas arestas, uma fonte e um sorvedouro, qual o fluxo máximo que passa da fonte ao sorvedouro? O teorema max-flow / min-cut diz que esse valor é igual à capacidade do menor conjunto de arestas cuja remoção separa fonte e sorvedouro — o que torna "fluxo máximo" também a resposta para "corte mínimo" (segmentação, particionamento, confiabilidade).

5.2 Emparelhamento bipartido

Dois grupos (trabalhadores × tarefas, candidatos × vagas, alunos × projetos) e arestas de compatibilidade. O emparelhamento máximo é o maior conjunto de pares sem repetir ninguém. Resolve-se como um caso de fluxo máximo (fonte → grupo A → grupo B → sorvedouro, capacidades 1) ou com Hopcroft-Karp (O(E√V)).

💡 O sinal de "isto é fluxo/matching"

Palavras-gatilho: "capacidade", "máximo de X simultâneos", "alocar cada A a no máximo um B", "menor conjunto de arestas para desconectar", "cada recurso serve k pedidos". Muitos problemas que parecem exigir força bruta são fluxo máximo com uma modelagem esperta (dividir um nó em "entrada/saída" para impor capacidade no nó, por exemplo).

💼 Mercado de trabalho

Fluxo é o tópico "avançado" que separa candidatos em vagas mais competitivas e em competitivo. Não precisa implementar Dinic de cabeça, mas precisa reconhecer que "alocar entregadores a zonas com limite por zona" ou "quantos caminhos disjuntos existem entre A e B" são fluxo/matching, e saber que min-cut = max-flow.

✏️ Exercício 5 — Reduza a fluxo ou matching

(a) 40 médicos, cada um disponível em certos turnos; cada turno precisa de exatamente 3 médicos; cada médico faz no máximo 5 turnos na semana. Existe uma escala válida? (b) Numa rede, quantos enlaces preciso cortar, no mínimo, para isolar o datacenter A do datacenter B? (c) Atribuir 30 tarefas a 30 pessoas minimizando o custo total, dado o custo de cada pessoa em cada tarefa.

Gabarito: (a) Fluxo máximo: fonte → cada médico (capacidade 5) → turnos em que ele pode (cap. 1) → sorvedouro (cada turno com capacidade 3). Escala válida existe se o fluxo máximo = 3 × (nº de turnos). (b) É min-cut entre A e B = max-flow de A para B com capacidade 1 por enlace (ou a capacidade real, se quiser o corte de menor capacidade). (c) Assignment problem — algoritmo húngaro ou min-cost max-flow; emparelhamento perfeito de custo mínimo num grafo bipartido completo com custos.

MÓDULO 06 · AVANÇADO

Ciência de redes

Objetivo: medir a estrutura de redes reais — quem é importante (centralidade), quais os grupos (comunidades), quais ligações vão surgir (previsão de link) — com NetworkX e Neo4j GDS.

6.1 Centralidade: "importância" tem várias definições

MedidaCapturaExemplo de uso
Grauquantas conexões diretasinfluência local; nós populares
Intermediação (betweenness)quantos caminhos mínimos passam pelo nó"pontes" entre grupos; pontos de controle de fluxo; vulnerabilidade
Proximidade (closeness)quão perto (em média) o nó está de todos os outrosmelhor posição para espalhar informação rápido
Autovetor / PageRankimportância recursiva: você é importante se nós importantes te apontamranking de páginas, de papers, de contas; detecção de influência real vs inflada
Katz / HITSvariações (hubs e authorities no HITS)ranking em grafos de citação/link

Betweenness exata é O(V·E) (Brandes) — cara em grafos grandes; usa-se amostragem. PageRank é iterativo (multiplicação matriz-vetor até convergir), escala bem.

6.2 Detecção de comunidades

6.3 Previsão de link

Dado o grafo atual, quais arestas vão aparecer (ou estão faltando)? Base de "pessoas que você talvez conheça", recomendação, completar bases incompletas.

6.4 As ferramentas

import networkx as nx
G = nx.karate_club_graph()
pr   = nx.pagerank(G)
btw  = nx.betweenness_centrality(G)
comm = nx.community.louvain_communities(G, seed=42)
💼 Mercado de trabalho

Ciência de redes aparece em times de fraude, risco, growth, produto (recomendação) e pesquisa. O que se espera: saber que "centralidade" não é uma coisa só (grau ≠ betweenness ≠ PageRank) e qual usar para qual pergunta; conhecer Louvain/Leiden para comunidades; e citar o problema do vazamento temporal em previsão de link. Mão na massa com NetworkX + um dataset real vale muito no portfólio.

✏️ Exercício 6 — A medida certa

(a) Numa rede de colaboração entre pesquisadores, quem, se sair, mais fragmenta a colaboração entre subáreas? (b) Numa rede de transações, quais contas formam grupos densos que quase não transacionam para fora (possível lavagem)? (c) Numa rede de seguidores, quem tem influência "real" e não apenas muitos seguidores comprados?

Gabarito: (a) Betweenness alta — esses nós estão nos caminhos entre subáreas; removê-los desconecta grupos. (b) Detecção de comunidades (Louvain/Leiden) + checar a razão de arestas internas/externas de cada comunidade; grupos com modularidade alta e pouquíssimas arestas externas são suspeitos. (c) PageRank (ou autovetor): seguidores comprados são contas de baixo PageRank, então apontar-lhe não eleva o seu; influência real vem de ser apontado por contas que também são apontadas.

MÓDULO 07 · AVANÇADO

Embeddings de grafo

Objetivo: transformar nós (ou o grafo todo) em vetores densos que preservam a estrutura — para alimentar classificadores, busca por similaridade e clustering sem uma GNN.

7.1 A ideia

Um node embedding mapeia cada nó para um vetor de baixa dimensão (64–256) tal que nós estruturalmente próximos no grafo fiquem próximos no espaço vetorial. Com isso, tarefas de grafo viram tarefas tabulares: classificar nós, prever links (distância entre embeddings), agrupar, buscar "nós parecidos".

7.2 Os métodos baseados em passeio aleatório

MétodoIdeia
DeepWalkgera passeios aleatórios (sequências de nós) e trata cada passeio como uma "frase" → aplica word2vec (skip-gram). Nós que aparecem em contextos parecidos ganham vetores parecidos.
node2vecDeepWalk com passeio enviesável: os parâmetros p e q interpolam entre explorar a vizinhança (BFS-like → captura papel/homofilia) e ir longe (DFS-like → captura comunidade).
LINEotimiza diretamente proximidade de 1ª ordem (vizinhos diretos) e 2ª ordem (vizinhanças parecidas); escala para grafos grandes.
from node2vec import Node2Vec
emb = Node2Vec(G, dimensions=128, walk_length=30, num_walks=200, p=1, q=1).fit()
vec = emb.wv["42"]                 # vetor do nó 42
emb.wv.most_similar("42")             # nós estruturalmente parecidos

7.3 Graph embeddings (o grafo inteiro) e KG embeddings

⚠️ Transdutivo vs indutivo

DeepWalk/node2vec são transdutivos: aprendem um vetor por nó do grafo visto no treino. Um nó novo (usuário que acabou de entrar) não tem embedding sem re-treinar. Para grafos que crescem, prefira métodos indutivos — GraphSAGE (módulo 8) gera o embedding de um nó novo a partir das features dele e da vizinhança, sem re-treino.

💼 Mercado de trabalho

Node embeddings são o "meio-termo" pragmático: mais poder que heurísticas, menos complexidade que GNN. Espera-se saber o que node2vec faz (passeios + word2vec), o papel dos parâmetros p/q (homofilia vs estrutura), a limitação transdutiva, e que KG embeddings (TransE e cia.) servem para completar bases de conhecimento.

✏️ Exercício 7 — Embedding serve aqui?

(a) Classificar 100 mil contas como fraude/não-fraude num grafo de transações que muda toda hora, com contas novas o tempo todo. (b) Recomendar "conexões" numa rede profissional razoavelmente estável. (c) Prever relações faltantes num grafo de conhecimento de produtos (marca, categoria, compatível-com).

Gabarito: (a) node2vec é ruim aqui — transdutivo, e o grafo muda com contas novas constantemente. Melhor: GraphSAGE (indutivo, usa features da conta) ou features de grafo calculadas online + modelo tabular. (b) node2vec funciona bem — grafo estável, tarefa de similaridade/link prediction; gerar embeddings, recomendar por vizinhança no espaço vetorial, re-treinar periodicamente. (c) KG embeddings (TransE/ComplEx/RotatE): treinar sobre as triplas existentes e pontuar triplas candidatas; as de score alto são as relações faltantes prováveis.

MÓDULO 08 · AVANÇADO

Graph Neural Networks

Objetivo: entender message passing — a mecânica comum a GCN, GraphSAGE e GAT — as tarefas que uma GNN resolve, e as armadilhas (over-smoothing, escala).

8.1 Message passing: a ideia central

Uma GNN calcula o vetor (embedding) de cada nó agregando os vetores dos vizinhos, camada após camada. Após k camadas, o vetor de um nó resume informação da sua vizinhança de k saltos. Cada camada faz, para todo nó v:

h_v^(k) = UPDATE( h_v^(k-1) ,  AGGREGATE( { h_u^(k-1) : u vizinho de v } ) )
ArquiteturaComo agrega
GCNmédia ponderada normalizada dos vizinhos (pelo grau) + transformação linear + não-linearidade
GraphSAGEamostra um subconjunto de vizinhos e agrega (média, pooling, LSTM) — indutivo e escalável; funciona para nós novos
GATaprende pesos de atenção por vizinho — nem todo vizinho importa igual
GINagregação por soma + MLP; teoricamente tão expressiva quanto o teste de isomorfismo de Weisfeiler-Lehman

8.2 As três tarefas

8.3 Armadilhas

import torch_geometric.nn as gnn
class Net(torch.nn.Module):
    def __init__(self, in_dim, hid, out):
        self.c1 = gnn.SAGEConv(in_dim, hid)
        self.c2 = gnn.SAGEConv(hid, out)
    def forward(self, x, edge_index):
        x = self.c1(x, edge_index).relu()
        return self.c2(x, edge_index)

Frameworks: PyTorch Geometric (PyG) e DGL são os dois padrões.

💼 Mercado de trabalho

GNN é procurada em fraude, recomendação, bioinformática/farma, e cada vez mais em KG + LLM. O que se cobra: explicar message passing em uma frase, saber a diferença GCN (transdutivo, agregação fixa) vs GraphSAGE (indutivo, amostra) vs GAT (atenção), citar over-smoothing e o limite de 2–4 camadas, e — sinal de maturidade — insistir numa baseline (MLP + features de grafo) antes de partir para GNN.

✏️ Exercício 8 — GNN ou não, e qual?

(a) Detecção de fraude num grafo de transações com 200 M de nós que ganha nós novos toda hora, com features ricas por conta. (b) Classificar 3.000 moléculas por toxicidade (cada molécula é um grafo pequeno). (c) Recomendar itens num grafo usuário-item estável, sem features além da estrutura.

Gabarito: (a) GraphSAGE — indutivo (lida com nós novos sem re-treino), amostra vizinhança (escala para 200 M), usa as features das contas; tarefa de classificação de nó. Comparar com baseline MLP+features de grafo. (b) GNN de nível de grafo (GIN ou GCN + readout/pooling) — cada molécula é um grafo, a saída é uma propriedade do grafo inteiro; PyG tem datasets e loaders para isso. (c) Sem features, grafo estável: node2vec + similaridade, ou uma GNN que usa embeddings estruturais como entrada; link prediction. A GNN pode não valer a complexidade aqui.

MÓDULO 09 · MUITO AVANÇADO

Knowledge Graphs e GraphRAG

Objetivo: construir e usar um grafo de conhecimento — property graph vs RDF, ontologia, resolução de entidades, extração a partir de texto — e por que ele melhora RAG.

9.1 Property graph vs RDF/SPARQL

Property Graph (Neo4j, Memgraph)RDF / Triple Store (GraphDB, Blazegraph, Neptune)
Unidadenós e arestas com propriedades (chave-valor)triplas <sujeito, predicado, objeto>
ConsultaCypher / GQLSPARQL
Esquemaflexível; rótulos e propriedadesontologias formais (RDFS/OWL), inferência, IRIs globais
Forte emdesenvolvimento de aplicação, travessia, analytics (GDS)interoperabilidade, dados ligados (Linked Data), raciocínio lógico, padrões W3C

Para um KG interno de produto, property graph costuma ser mais produtivo. RDF ganha quando você precisa integrar com vocabulários públicos (schema.org, Wikidata), fazer inferência formal, ou publicar dados ligados.

9.2 Ontologia e resolução de entidades — onde a qualidade se decide

9.3 Construir um KG a partir de texto

  1. Extração de entidades (NER) e de relações — hoje frequentemente com um LLM guiado por um schema-alvo ("extraia triplas (Pessoa, CARGO_EM, Organização)").
  2. Normalização e resolução de entidades contra o KG existente.
  3. Carga das triplas/nós com proveniência; deduplicação de arestas.
  4. Validação: consistência com a ontologia, detecção de contradições, amostragem humana.
  5. Atualização incremental: novos documentos adicionam/reforçam arestas; versionar e permitir expiração de fatos.

9.4 GraphRAG tema em alta

RAG clássico recupera trechos por similaridade vetorial. Ele falha em perguntas que exigem conectar informação espalhada ("quais fornecedores da empresa A também fornecem para concorrentes dela?") e em perguntas globais ("quais os temas principais deste corpus?"). GraphRAG usa um KG construído do corpus:

Conecta com a apostila de IA Generativa & RAG (retrieval, avaliação) e com a Modelagem de Dados NoSQL (módulo 7, modelagem de grafo e KG).

💼 Mercado de trabalho

KG + GraphRAG é uma das habilidades de IA mais procuradas e menos concorridas em 2026. O que diferencia: saber que a ontologia e a resolução de entidades determinam a qualidade (não o banco escolhido); saber quando GraphRAG vence RAG vetorial (multi-hop, perguntas globais) e quando não vale o custo; e ter construído um KG pequeno de ponta a ponta.

✏️ Exercício 9 — Projete o KG

Você tem 50 mil relatórios de incidentes de TI em texto livre. Objetivo: responder perguntas como "quais serviços foram afetados por incidentes causados pela mudança X?" e "qual componente aparece na maioria dos incidentes de rede?". Descreva ontologia, extração, resolução de entidades e a estratégia de recuperação.

Gabarito (esboço): Ontologia: nós Incidente, Servico, Componente, Mudanca, Causa; arestas AFETOU (Incidente→Servico), ENVOLVEU (Incidente→Componente), CAUSADO_POR (Incidente→Mudanca/Causa), DEPENDE_DE (Servico→Componente). Extração: LLM guiado pelo schema extrai triplas de cada relatório, com proveniência (id do relatório, data, trecho). Resolução de entidades: normalizar nomes de serviço/componente contra o CMDB/catálogo de serviços existente (id canônico); heurística + revisão dos casos de baixa confiança. Recuperação: para "serviços afetados pela mudança X" — achar o nó Mudanca X, seguir <-CAUSADO_POR- Incidente -AFETOU-> Servico (travessia multi-hop, resposta exata com fontes). Para "componente mais frequente em incidentes de rede" — filtrar incidentes por categoria "rede", contar ENVOLVEU por componente (analítico, não vetorial). RAG vetorial puro erraria a primeira (informação espalhada em vários relatórios) e a segunda (é agregação, não recuperação de trecho).

MÓDULO 10 · CARREIRA

Visualização, mercado de trabalho e entrevistas

Objetivo: visualizar grafos sem virar "prato de espaguete", e converter o conteúdo em aprovação — o que cada trilha cobra, projetos e perguntas.

10.1 Visualização de grafos

10.2 Onde grafos aparecem nas vagas

TrilhaO que cobram
Backend / SWE (entrevista)BFS/DFS, topológica, Dijkstra, Union-Find/MST, detecção de ciclo; reconhecer o problema como grafo
Engenharia de DadosDAGs de pipeline, linhagem de dados, modelagem de grafo, GDS/consultas de travessia
Fraude / Risco / Antifinanceirociência de redes (centralidade, comunidades), grafos de entidade, GNN para detecção
ML / DSnode2vec, GNN (PyG/DGL), previsão de link, vazamento temporal, baselines
IA / LLMKnowledge Graphs, extração com LLM, GraphRAG, resolução de entidades

10.3 Roadmap (5 semanas)

10.4 Banco de perguntas (com a resposta que aprova)

Backend — "Como você representaria um grafo e por quê?"

Lista de adjacência para grafo esparso (a maioria): O(V+E) de espaço, itera vizinhos em O(grau). Matriz para grafo denso ou álgebra linear (PageRank via potências). CSR para grafo grande e estático em processamento em lote/GPU. A escolha decorre de densidade, se é dinâmico, e das operações dominantes.

Backend — "Por que Dijkstra não funciona com pesos negativos, e o que usar?"

Dijkstra fecha um nó ao retirá-lo do heap, assumindo que nenhum caminho futuro o melhora — uma aresta negativa viola isso. Com pesos negativos (sem ciclo negativo), use Bellman-Ford (O(V·E)), que também detecta ciclo negativo na V-ésima iteração; para todos-os-pares com negativos e grafo esparso, Johnson.

DS/ML — "node2vec vs GraphSAGE, quando cada um?"

node2vec: passeios aleatórios enviesáveis (p/q entre homofilia e estrutura) + word2vec; transdutivo — só nós vistos no treino, sem features. Bom para grafo estável sem features. GraphSAGE: agrega features de vizinhos amostrados; indutivo — gera embedding de nós novos sem re-treino, escala por amostragem. Bom para grafos que crescem e com features de nó. Em ambos os casos, comparar com baseline (MLP + features de grafo).

IA — "O que GraphRAG resolve que o RAG vetorial não resolve?"

Perguntas multi-hop (conectar fatos espalhados em vários documentos — "fornecedores de A que também atendem concorrentes") e perguntas globais ("temas principais do corpus"), que a recuperação por similaridade de trechos não cobre. GraphRAG constrói um KG do corpus e recupera por travessia (subrede entre as entidades da pergunta) e/ou por resumos de comunidade. Custo: extração do KG com LLM é cara — justifica-se onde o RAG vetorial comprovadamente falha; não é substituto universal.

Fraude — "Que medida de grafo para achar contas que intermediam grupos?"

Betweenness centrality — conta quantos caminhos mínimos passam por cada nó; alta betweenness = nó "ponte" entre grupos, típico de laranjas/intermediários. Complementar com detecção de comunidades (Leiden) para ver os grupos e com a razão de arestas internas/externas para achar clusters fechados.

10.5 Fontes

🏁 Síntese final

Grafo é uma estrutura, não um nicho: o mesmo objeto responde "qual a rota mais curta" (Dijkstra/A*), "quem é o gargalo" (betweenness, pontes), "quais os grupos" (Louvain/Leiden), "esta ligação vai existir" (embeddings, GNN) e "como conectar fatos espalhados num corpus" (Knowledge Graph, GraphRAG). O trabalho é reconhecer qual pergunta você tem e trazer a ferramenta certa — do BFS de dez linhas ao GraphRAG.