bkim::Blog

DNA imortal

Uma pessoa contém um conjunto único de genes que nenhuma outra pessoa possui, descontando gêmeos idênticos. Quantos desses genes são preservados nos seus filhos? Seria possível ser imortal (de uma certa maneira) ao deixar metade de você em muitas pessoas? Eu fiz uma simulação usando a linguagem Clojure para descobrir, enquanto aguardava minha parceira na porta do provador da C&A. Usei o aplicativo Clojure REPL, que aparentemente não está mais disponível na Play Store; você deve conseguir fazer a mesma coisa no repl.it ou clojurescript.io.

Cada filho carrega uma metade aleatória dos seus genes. Simulei isso com uma função dna que seleciona aleatoriamente 50 números entre 0 e 99, inclusive.

(defn dna [] (take 50 (shuffle (range 100))))

Ao ter dois filhos, é possível (mas improvável) que ambos acabem com os mesmos genes vindos de você, de modo que apenas 50% da sua composição são perpetuados. Também é possível (e improvável) que cada um receba metades completamente distintas, e 100% de você estará presente nos dois! Na média, a gente espera que 75% dos seus genes sejam passados adiante pelos dois filhos. Podemos simular isso como segue:

(count (-> #{} (into (dna)) (into (dna))))
#_=> 78

Esse programa insere (into) os elementos de dois DNAs aleatórios em um conjunto vazio (#{}), e então conta os elementos (count). A estrutura de dados do conjunto remove as duplicatas, e como esperado, obtemos um número perto de 75. Com 3 filhos, devemos esperar uma média de 87,5%:

(count (-> #{} (into (dna)) (into (dna)) (into (dna))))
#_=> 90

Deve existir uma maneira mais simples para se fazer isso, mas já tem muito tempo que não programo Clojure… Para estender para k filhos, eu usei reduce para eliminar as repetições acima, abstraindo o procedimento para uma função sim, de simulação.

(defn sim [k] (count (reduce #(into % %2) #{} (repeatedly k dna))))
(sim 2)
#_=> 73
(sim 3)
#_=> 85

Agora podemos ter uma visão mais completa sobre essa rota para a imortalidade! Vamos fazer repetidas simulações e verificar a curva formada. Felizmente a função frequencies já existe para calcular um histograma das ocorrências de cada número. O programa a seguir realiza 1000 simulações e conta a fração dos genes que são passados adiante com 2 filhos:

(sort (frequencies (repeatedly 1000 #(sim 2))))
#_=> ([67 1] [68 4] [69 8] [70 24] [71 42] [72 81] [73 121] [74 138] [75 171] [76 156] [77 185] [78 72] [79 50] [80 18] [81 5] [82 4])

Cada par representa um resultado da simulação e quantas vezes ele aparece em 1000 amostras. Por exemplo, [74 138] mostra que 138/1000 das simulações terminam com resultado 74 -- ou, existe 13,8 % de probabilidade de 74% dos genes serem perpetuados. Como esperado, temos um máximo em 75 e a maior parte (978/1000) das simulações fica entre 70 e 80.

Meus avós paternos tiveram 4 filhos (que chegaram à idade adulta) e os maternos tiveram 12 (que chegaram à idade adulta). Quanto deles está preservado nos genes da geração seguinte?

(sort (frequencies (repeatedly 1000 #(sim 4))))
#_=> ([85 1] [87 4] [88 12] [89 9] [90 34] [91 86] [92 130] [93 178] [94 204] [95 144] [96 118] [97 58] [98 16] [99 5] [100 1])
(sort (frequencies (repeatedly 1000 #(sim 12))))
#_=> ([99 32] [100 968])

O que isso mostra é que com alta probabilidade (>95%) mais de 90% dos seus genes são perpetuados entre 4 filhos. Com 12 filhos, é quase certo que mais de 99% dos seus genes sejam perpetuados!

Não leve essas simulações muito a sério, pois elas têm muitas aproximações para serem respeitadas. Além do mais, com certeza existe uma fórmula simples para calcular isso com uma distribuição de Bernoulli… mas eu sou computeiro, não estatístico.

Published in .