Rocha Preprint · versão 2

Preprint pessoal · não revisado por pares

Ezequias Rocha: de listas de algoritmos a inferência de vínculos sociais

Retrato de Ezequias Rocha
Ezequias Rocha1,2 github.com/ezequiasOR

1Laboratório de Sistemas de Informação (LSI), Universidade Federal de Campina Grande
2Bacharel em Ciência da Computação pela UFCG; mestrando

no GitHub desde out/2018 · 50 repositórios públicos · 138 seguidores

Resumo

Este documento descreve o trabalho técnico de um analista de sistemas e pesquisador do LSI/UFCG a partir do que está publicado nos seus repositórios. O resultado central é a replicação, em PyTorch, de um modelo não supervisionado que infere amizades a partir de trajetórias de check-in, com embeddings de 128 dimensões por aspecto e projeções no estilo TransH [1], [2]. Em paralelo, relatamos uma correção de digitação em teclados ABNT num projeto de ditado por voz [3], uma API FastAPI com lint e cobertura acoplados aos testes [5], três aplicações full stack em web e mobile e duas trilhas de ensino de algoritmos que vão de busca binária ao algoritmo de Mo. Medimos cerca de 1.110 commits autorais em 22 repositórios próprios entre 2019 e 2026.

Palavras-chave: inferência de vínculos sociais; embeddings de grafos de conhecimento; TransH; PyTorch; FastAPI; programação competitiva; Neovim.


1Introdução

Ezequias Rocha é analista de sistemas e pesquisador no Laboratório de Sistemas de Informação da UFCG, em Campina Grande, Paraíba. Formou-se bacharel em Ciência da Computação na mesma universidade e hoje faz mestrado. Também integra a organização EssentIA no GitHub, dedicada a agentes de IA, cujos repositórios são privados e por isso ficam fora deste texto.

A versão anterior deste documento era uma página com um nome e uma piada.Hospedada em ezequias.vercel.app. Esta é a v2, e a mudança de escopo é proposital. A versão 2 faz o contrário: tudo o que segue foi verificado clonando os repositórios públicos e lendo o código. Não há percentuais de domínio, datas de emprego ou empresas que não estejam nos próprios commits.

As contribuições descritas são quatro:

  1. uma replicação completa de um modelo de inferência de vínculos sociais não supervisionado, com ~2.400 linhas de Python em oito módulos (§2.1);
  2. uma correção em software livre que torna o ditado por voz utilizável com layout ABNT no Linux (§2.2);
  3. projetos de backend e full stack com testes automatizados desde 2020 (§2.3 a §2.5);
  4. material didático de algoritmos, com listas semanais e vídeos de resolução (§4).

A Tabela 1 resume as ferramentas que aparecem nesses trabalhos, agrupadas por área. A ordem dentro de cada linha não indica preferência.

Tabela 1.Ferramentas presentes no código público, por área.
ÁreaFerramentas
IA e dadosPython, PyTorch, scikit-learn, Pandas, NumPy, Jupyter, embeddings de grafos (TransH, TransR, TransD), Whisper e faster-whisper
BackendFastAPI, Pydantic, Node.js, Express, rotas de API do Next.js, Knex, Mongoose, Socket.io
Front e mobileTypeScript, React, React Native, Expo, Next.js, Leaflet, Vue
BancosPostgreSQL, SQLite, MongoDB, MySQL e SQL relacional
Qualidade e infrapytest, Jest, Supertest, Ruff, Prettier, Poetry, Docker, Docker Compose, CUDA, Vercel, Git
AmbienteLinux (Pop!_OS), Neovim em Lua, tmux, Wayland e X11

2Trabalhos

2.1Inferência não supervisionada de vínculos sociais

Problema.Dado apenas o histórico de check-ins de usuários do Foursquare em Nova York, decidir quais pares de pessoas são amigas, sem nenhum rótulo de amizade no treino. O repositório [2] replica o modelo ANES, proposto por Byun, Choi e Kim na Information Sciences em 2023 [1]. A ideia é que dois amigos deixam rastros parecidos em vários aspectos ao mesmo tempo: os mesmos lugares, em horários parecidos, em categorias de lugar parecidas, em regiões próximas.

Representação.Cada check-in vira uma tripla aspecto-orientada, como num grafo de conhecimento. Usuário, POI, tempo, categoria e geografia recebem tabelas de embedding separadas, todas com 128 dimensões.O código traz cinco variantes de modelo: ANES, ANES_GEO, ANES_GEO_YELP, ANES_GEO_Others e LBGC_v4. Em vez de comparar embeddings direto, o modelo projeta usuário e entidade num hiperplano específico de cada aspecto, à maneira do TransH, e mede a translação ali. A Figura 1 mostra o caminho completo; passe o cursor, toque ou navegue com Tab pelas partes.

check-in (u, p, t, c, g) Foursquare · NYC usuário 𝐮 ∈ ℝ¹²⁸ POI 𝐩 ∈ ℝ¹²⁸ tempo 168 slots categoria 𝐜 ∈ ℝ¹²⁸ geografia 𝐠 ∈ ℝ¹²⁸ projeção por aspecto hiperplano do aspecto r 𝐰ᵣ 𝐡 𝐡⊥ perdas margem + ortogonal + norma score de vínculo s(uᵢ, uⱼ) amigos ou não?

arraste para os lados para ver a figura inteira

visão geral Um check-in se decompõe em cinco aspectos, cada um com sua tabela de embedding de 128 dimensões. Os vetores são projetados no hiperplano do aspecto e as distâncias ali alimentam o score de vínculo entre dois usuários. Selecione uma parte para ver o detalhe.
Figura 1(a).Arquitetura do ANES como implementada em model.py (776 linhas) [2]. Os retângulos listrados representam vetores de ℝ¹²⁸ em escala reduzida. A geometria do hiperplano segue a Equação (1).

Projeção.Seja 𝐰ᵣ o vetor normal unitário do hiperplano associado ao aspecto r. A projeção de um embedding 𝐡 remove dele a componente na direção de 𝐰ᵣ:

𝐡⊥=𝐡− (𝐰r⊤𝐡) 𝐰r , ‖𝐰r‖2=1 (1)

e a plausibilidade de uma tripla (h, r, t) é a distância L1 entre as projeções depois da translação 𝐝ᵣ,O treino da replicação usa norma L1, taxa de aprendizado 10⁻⁴ e 1000 iterações.

fr(h,t)= ‖𝐡⊥+𝐝r−𝐭⊥‖1 (2)

O arquivo loss.py combina três termos: uma margin loss que separa triplas observadas de triplas negativas, uma orthogonal loss que mantém o vetor de relação coerente com o hiperplano e uma norm loss que limita a norma dos embeddings. Na formulação clássica do TransH, o termo ortogonal tem a forma

ℒorth= ∑r [ (𝐰r⊤𝐝r)2 ‖𝐝r‖22 −ε2 ]+ (3)

que só penaliza quando o cosseno entre 𝐰ᵣ e 𝐝ᵣ passa de ε. O módulo projection.py também traz as variantes TransR e TransD, que trocam o hiperplano por uma matriz de projeção por relação e por vetores de projeção dinâmicos, respectivamente.

Tempo.O aspecto temporal não usa o timestamp cru. A hora local de cada check-in, corrigida pelo offset de fuso em minutos que vem no próprio dado, é mapeada para um de 168 slots semanais, um por combinação de dia da semana e hora. Assim, “terça às 19h” vira o mesmo token em qualquer semana do conjunto. A Figura 1(b) mostra a grade.

slot = 24·d + h  ·  passe o cursor ou toque numa célula
Figura 1(b).Discretização do tempo em 7 × 24 = 168 slots. A ordem dos dias aqui é ilustrativa; o que importa é que cada slot tem seu próprio embedding de 128 dimensões.

Amostragem negativa.Treinar com margem exige pares negativos, e sortear negativos de forma uniforme ignora a distribuição real de popularidade dos lugares. A replicação constrói a função de distribuição acumulada e sorteia com busca binária sobre ela, o que custa O(log n) por amostra em vez de O(n).Em Python isso costuma ser bisect sobre a lista acumulada; o ganho aparece porque o sorteio roda a cada lote, milhares de vezes por época. O Algoritmo 1 descreve o esquema.

Algoritmo 1. Sorteio de negativo pela CDF (esquema)
  1. entrada: pesos w₁ … wₙ dos candidatos
  2. C[i] ← w₁ + … + wᵢ  // uma vez, O(n)
  3. x ← Uniforme(0, C[n])
  4. retorne o menor i com C[i] ≥ x  // busca binária, O(log n)

Protocolo.O pré-processamento gera recortes NYC_20, NYC_40, NYC_60, NYC_80 e NYC_100, cada um com pares verdadeiros e falsos separados em treino, validação e teste. O espaço aprendido é inspecionado com t-SNE. O código está dividido conforme a Tabela 2.

Tabela 2.Módulos de replication-ANES, ~2.400 linhas de Python no total [2].
MóduloResponsabilidade
preprocessing.pycheck-ins, slots de tempo, recortes NYC_20 a NYC_100
ANES.pylaço de treino
model.pyembeddings por aspecto e as cinco variantes (776 linhas)
data.pycarregamento e lotes
loss.pymargem, ortogonal, norma
projection.pyTransH, TransR, TransD
graphutils.pyutilidades de grafo
utils.pyfunções auxiliares

2.2turbo-whisper: o apóstrofo que virava til

O turbo-whisper é um ditado por voz para desktop no estilo do SuperWhisper: atalho global, waveform na tela, transcrição com o Whisper da OpenAI em 99 idiomas e interface em PyQt6. Em setembro de 2026, Ezequias fez um fork do projeto original [4] e enviou três commits [3].

O primeiro corrige um bug que só aparece para quem usa teclado brasileiro. O texto transcrito era digitado na janela ativa via evdev, que injeta scancodes crus pensando num teclado US-QWERTY. O scancode que no layout americano produz ' cai, no ABNT, na tecla do til. Resultado: todo apóstrofo ditado aparecia como ~.O evdev fala com o kernel em nível de tecla física, abaixo do layout. Quem traduz tecla em caractere é o servidor gráfico, por isso o mesmo código físico vira outro símbolo quando o layout muda. A correção inverte a ordem de preferência: primeiro ferramentas que digitam caracteres respeitando o layout ativo, e só depois o evdev.

1def _type_linux(self, text: str) -> bool:
2    # Prefer xdotool (X11) / wtype (Wayland): both honor the active keyboard
3    # layout and handle Unicode. The evdev fallback sends raw US-QWERTY
4    # scancodes, so non-US layouts mistype punctuation (e.g. ABNT turns ' into ~).
5    is_wayland = bool(os.environ.get("WAYLAND_DISPLAY")) or (
6        os.environ.get("XDG_SESSION_TYPE", "").lower() == "wayland"
7    )
8    if is_wayland and shutil.which("wtype"):
9        subprocess.run(["wtype", "--", text], check=True, timeout=30)
10    if shutil.which("xdotool"):
11        delay_ms = max(1, int(self._typing_delay * 1000))
12        subprocess.run(["xdotool", "type", "--clearmodifiers",
13                        "--delay", str(delay_ms), "--", text], check=True, timeout=30)
14    if self._evdev_available and self._uinput:
15        return self._type_evdev(text)
16    # ... depois PyAutoGUI e, por último, área de transferência
Listagem 1.Ordem de fallback em typer.py após o commit fix: prefer xdotool/wtype over evdev for auto-typing. Trecho resumido: no original, cada tentativa fica num try que retorna True no sucesso e imprime o erro antes de cair para a próxima.

Dois detalhes da listagem merecem nota. A detecção de Wayland olha duas variáveis, porque nem toda sessão exporta XDG_SESSION_TYPE de forma confiável. E o xdotool roda com --clearmodifiers,--clearmodifiers solta temporariamente teclas como Ctrl e Shift que ainda estejam pressionadas pelo atalho de gravação, evitando que o texto vire uma sequência de comandos. com o atraso entre teclas vindo da configuração typing_delay_ms já existente no projeto.

O segundo commit, feat: language selection, headless recording, clearer offline error, acrescenta 143 linhas em api.py, config.py e main.py: escolha de idioma, gravação sem interface e uma mensagem de erro que diz claramente quando o servidor de transcrição está fora do ar. O terceiro documenta a instalação auto-hospedada no Pop!_OS: um servidor faster-whisper em Docker com CUDA (--gpus all, modelo Systran/faster-whisper-small), porta exposta só em 127.0.0.1, cache do HuggingFace montado como volume para não baixar o modelo a cada subida, e áudio via PipeWire e PortAudio.

2.3fast_zero: qualidade amarrada ao comando de teste

Uma API REST de usuários em FastAPI [5], pequena de propósito, onde o interesse está na engenharia ao redor. Os schemas em Pydantic v2 separam papéis: UserSchema para entrada, UserPublic para resposta, UserDB para o registro e UserList para coleções. O e-mail é validado por EmailStr, as rotas respondem com HTTPStatus explícito e o caso de usuário inexistente devolve 404.

O projeto usa Python 3.14 e Poetry. O Ruff roda com as regras I, F, E, W, PL (as checagens do pylint) e PT (estilo pytest), em modo preview. O taskipy encadeia tudo: pre_test = lint impede que um teste rode sobre código fora do padrão e post_test = coverage html gera o relatório de cobertura do pytest-cov ao final.O TestClient do FastAPI fica numa fixture do pytest, então cada teste recebe um cliente pronto sem subir servidor.

2.4clone-tabnews

Um clone do TabNews em Next.js 13 com PostgreSQL [6], publicado na Vercel [7]. O banco de desenvolvimento sobe via Docker Compose a partir de infra/compose.yaml, a aplicação fala com ele pelo driver pg e o endpoint /api/v1/status tem teste de integração em Jest, que bate no banco de verdade em vez de num mock. Prettier, .editorconfig e .nvmrc fixam formatação e versão do Node para qualquer máquina.

2.5Três aplicações em três plataformas

Em 2020, três projetos repetiram a mesma forma (API, web e app mobile) com problemas diferentes. O Ecoleta [8] é um marketplace de pontos de coleta de resíduos por geolocalização; o DevRadar [9] encontra desenvolvedores próximos e avisa em tempo real; o be-the-hero [10] é o que tem a API coberta por testes. A Tabela 3 compara as decisões técnicas.

Tabela 3.Decisões técnicas nos três projetos full stack de 2020. A última linha conta commits do autor em cada repositório.
Ecoleta [8]DevRadar [9]be-the-hero [10]
APIExpress + Knex, migrations e seedsExpress + MongooseExpress + Knex
BancoSQLiteMongoDB, consultas geoespaciaisSQLite
Destaquevalidação Celebrate/Joi; upload com Multer; mapas Leaflet; drag-and-dropSocket.io avisa devs próximos; API do GitHub via axiosvalidação Celebrate; testes com Jest + Supertest, cross-env
WebReact + TypeScript, react-routerReactReact
MobileExpo, react-native-maps, expo-location, mail-composerExpo, mapas, WebView, socket.io-clientReact Native / Expo
Commits124123122

No DevRadar, a busca por proximidade fica no banco, com consultas geoespaciais do MongoDB via Mongoose, e o Socket.io avisa em tempo real os devs próximos. No Ecoleta, a mesma imagem atravessa duas camadas: react-dropzone no navegador e Multer na API, que valida o corpo da requisição com Celebrate antes de gravar pelo Knex.

3Métodos e ambiente

O trabalho acontece em Linux, no Pop!_OS, com Neovim configurado em Lua [15] e tmux [16]. A configuração do editor usa LSP para diagnóstico e navegação, Telescope para busca, Treesitter para sintaxe, Harpoon para alternar entre poucos arquivos marcados,Harpoon troca a busca por arquivo por atalhos fixos para os três ou quatro arquivos da tarefa atual. Undotree mostra o histórico de desfazer como árvore, não como linha. Fugitive para Git, Undotree, Trouble para listas de diagnóstico, Zen Mode, um plugin de refatoração e o cloak, que esconde valores de arquivos .env enquanto a tela está sendo compartilhada.

É o mesmo ambiente das notas de auto-hospedagem do §2.2: Pop!_OS, Docker com CUDA e teclado ABNT, onde o bug do apóstrofo aparece no uso diário.

4Ensino de algoritmos

Desde 2020, Ezequias monta trilhas semanais de Aprendizado de Algoritmos com listas no vJudge e grava vídeos resolvendo as questões para os alunos [11], [12].

Trilha iniciante.Ad hoc, dois ponteiros, soma acumulada, busca binária, estruturas de dados (fila, heap, pilha, set e mapa), teoria dos números com MDC, MMC e crivo, aritmética modular e exponenciação binária.

Trilha avançada.Três técnicas para consultas em intervalos, que respondem a perguntas diferentes, como resume a Tabela 4. A Segment Tree responde consulta e atualização pontual em O(log n). A Lazy Propagation adia atualizações de intervalo inteiro nos nós internos e só as empurra para baixo quando um filho é visitado. O algoritmo de Mo resolve consultas offline: ordena as consultas por bloco de tamanho √n e move dois ponteiros, adicionando e removendo um elemento por vez.Mo serve quando a resposta não é decomponível (contar elementos distintos num intervalo, por exemplo), situação em que a Segment Tree não combina bem os filhos.

Tabela 4.Custos das técnicas da trilha avançada, com n elementos e q consultas.
TécnicaAtualizaçãoConsultaModo
Segment TreeO(log n) pontualO(log n)online
+ Lazy PropagationO(log n) em intervaloO(log n)online
Decomposição √nO(1) ou O(√n)O(√n)online
Algoritmo de Monão se aplicaO((n + q)√n) no totaloffline

ATAL.Na disciplina de Análise e Técnicas de Algoritmos da UFCG, as soluções de Codeforces ficaram organizadas por paradigma [13]: força bruta, backtracking, guloso, divisão e conquista, programação dinâmica e grafos com BFS e DFS. Organizar por paradigma, e não por número de questão, faz do repositório um índice de técnicas.

Inteligência Artificial.Entre 2022 e 2023, os quizzes da disciplina de IA da UFCG ficaram em notebooks Jupyter [14], o que explica boa parte do volume de Jupyter na Figura 3.

5Resultados quantitativos

As medidas abaixo vêm de 22 repositórios próprios clonados e analisados, sem contar forks. A Figura 2 mostra os commits do autor por ano, desenhados na mesma escala; o total é de aproximadamente 1.110.Os 3 commits de 2026 são os do turbo-whisper (§2.2). A contagem só enxerga repositórios públicos próprios; os da EssentIA são privados e ficam de fora.

Figura 2.Commits autorais por ano nos 22 repositórios próprios. Eixo vertical linear de 0 a 260; as barras são proporcionais ao valor. As notas sob o eixo marcam o trabalho dominante de cada ano segundo a §6.

A Figura 3 mede volume de código por linguagem, em bytes. É uma medida de quanto texto foi escrito em cada linguagem, não de proficiência.Notebooks Jupyter são JSON com saídas embutidas, então os bytes superestimam o código ali. CSS e HTML vêm sobretudo dos projetos web de 2019 e 2020. O peso de JavaScript reflete os anos de estudo web e os projetos de 2020; Python é menor em bytes mas concentra o trabalho de pesquisa.

Figura 3.Volume de código por linguagem nos repositórios próprios, em KB. Barra hachurada: Jupyter, cujo formato infla a contagem. Escala linear, 828 KB na barra cheia.

6Histórico

Como num histórico de versões, cada ano registra o que entrou.

2018
Conta no GitHub, em outubro.
2019
Começa os repositórios de estudo de longo prazo: Web-Estudos [17] e Python-Estudos [18].
2020
Java na UFCG; Semanas Omnistack (DevRadar, be-the-hero) e NLW (Ecoleta); extensão que acelera áudios do WhatsApp Web; começa a ensinar algoritmos.
2021
ATAL: soluções organizadas por paradigma.
2022–23
IA na UFCG em notebooks; ambiente migra para Neovim em Lua; clone-tabnews começa em 2023.
2024
Replicação do ANES em PyTorch (pesquisa); configuração de tmux.
2025
fast_zero em FastAPI; nova turma de algoritmos.
2026
Contribuição open source no turbo-whisper, com a correção do ABNT.

Estudos de longo prazo.O Web-Estudos tem 844 commits entre 2019 e 2025, 479 deles do autor. Vai de JavaScript do zero (map, filter, reduce, estilo imperativo contra declarativo) a AJAX com XHR, fetch, axios e jQuery, depois Express, Gulp, Webpack, Vue e React, e termina em SQL relacional com joins e agregação e em MongoDB com $lookup. O Python-Estudos, com 105 commits do autor, cobre acesso a banco com consultas parametrizadas, incluindo um exercício chamado “selecionar sem SQL injection”, CRUD e paginação com LIMIT/OFFSET.

Completam o arquivo: ibdmd, com datasets de BI cruzando lojas, gerentes e vendas; os primeiros projetos em Java na UFCG, como o coisa (Controle Institucional da Situação Acadêmica), uma agenda de contatos e um controle de alunos; o audio-speed-controller; e os exercícios bin2dec, casa-criativa e doe, este último da MaratonaDev.

7Conclusão

O fio que liga as seções é o mesmo nos dois extremos do histórico: ler a fundo antes de construir. Nas listas de algoritmos, isso significa saber por que Mo precisa ser offline. Na pesquisa, significa reimplementar um paper inteiro, com suas três perdas e sua amostragem pela CDF, em vez de chamar uma biblioteca. Em software livre, significa descer até o scancode para entender por que um apóstrofo vira til.

Disponibilidade de código.Todos os repositórios citados são públicos em github.com/ezequiasOR. Os repositórios da EssentIA são privados e não foram usados aqui.

Agradecimentos

Aos alunos das trilhas de Aprendizado de Algoritmos, para quem as listas e os vídeos foram feitos. Ao LSI/UFCG. E aos mantenedores do turbo-whisper, por deixarem o código aberto o bastante para alguém com teclado ABNT consertar.

Referências

  1. [1]J. Byun, S. Choi, S. Kim. Aspect-oriented unsupervised social link inference on user trajectory data. Information Sciences, vol. 626, 2023. doi:10.1016/j.ins.2023.01.022
  2. [2]E. Rocha. replication-ANES: replicação em PyTorch de [1], 2024. github.com/ezequiasOR/replication-ANES
  3. [3]E. Rocha. turbo-whisper (fork): correção ABNT, seleção de idioma, notas de auto-hospedagem, 2026. github.com/ezequiasOR/turbo-whisper
  4. [4]knowall-ai. turbo-whisper, projeto original. github.com/knowall-ai/turbo-whisper
  5. [5]E. Rocha. fast_zero: API em FastAPI com Ruff, pytest e taskipy, 2025. github.com/ezequiasOR/fast_zero
  6. [6]E. Rocha. clone-tabnews: Next.js e PostgreSQL em Docker, 2023–24. github.com/ezequiasOR/clone-tabnews
  7. [7]clone-tabnews, demonstração publicada na Vercel. clone-tabnews-brown.vercel.app
  8. [8]E. Rocha. Ecoleta: API, web e mobile em TypeScript, 2020. github.com/ezequiasOR/Ecoleta
  9. [9]E. Rocha. DevRadar: geolocalização e WebSocket, 2020. github.com/ezequiasOR/DevRadar
  10. [10]E. Rocha. be-the-hero: API testada com Jest e Supertest, 2020. github.com/ezequiasOR/be-the-hero
  11. [11]E. Rocha. aa-iniciante: trilha iniciante de Aprendizado de Algoritmos. github.com/ezequiasOR/aa-iniciante
  12. [12]E. Rocha. aa: trilha avançada, Segment Tree, Lazy Propagation, Mo. github.com/ezequiasOR/aa
  13. [13]E. Rocha. atal-ufcg: soluções por paradigma. github.com/ezequiasOR/atal-ufcg
  14. [14]E. Rocha. ia-ufcg: quizzes de Inteligência Artificial em Jupyter, 2022–23. github.com/ezequiasOR/ia-ufcg
  15. [15]E. Rocha. nvim: configuração do Neovim em Lua. github.com/ezequiasOR/nvim
  16. [16]E. Rocha. tmux: configuração do tmux. github.com/ezequiasOR/tmux
  17. [17]E. Rocha. Web-Estudos, 2019–2025. github.com/ezequiasOR/Web-Estudos
  18. [18]E. Rocha. Python-Estudos. github.com/ezequiasOR/Python-Estudos

Correspondência

Correspondência sobre este trabalho pode ser enviada por qualquer um dos canais abaixo.

Composto em Newsreader e IBM Plex Mono. Equações em MathML. voltar ao título ↑