1. En el campo de la genética, se busca identificar los genes
asociados a una enfermedad específica. En un estudio reciente se
encontró que un conjunto de 22 genes está fuertemente relacionado con la
aparición de diabetes tipo 2. El equipo de investigación ahora se
pregunta ¿cuántos conjuntos de 22 genes se tendrían que evaluar para
identificar todos los genes relacionados con la diabetes tipo 2? Suponga
que el genoma humano consta de 25.000 genes.
Además, si se
propusiera un algoritmo de búsqueda basado en fuerza bruta que evalúa
cada combinación de 22 genes para determinar su relación con la diabetes
tipo 2 en 1 nanosegundo,
- ¿Cuánto tiempo se necesitaría para
evaluar todas las combinaciones?
- ¿Qué sugerencia haría desde el
punto de vista computacional?
- Contextualice su respuesta para el
problema.
Solución:
Análisis inicial:
Si son 25.000 genes en total y la
verificación de cada gen se hiciese de manera individual, se necesitaría
un igual número de verificaciones que de genes, es decir, 25.000
verificaciones individuales para 25.000 genes.Sin embargo, al agruparlos
en conjuntos de 22 genes, necesitamos calcular las posibles
combinaciones o permutaciones correspondientes.
Esto es, si la
composición de cada grupo de 22 genes resulta relevante para determinar
la relación del conjunto de genes con la aparición de diabetes tipo 2,
pero su orden no tiene relevancia, entonces podemos considerar todas las
posibles combinaciones de grupos de 22 genes: \[
Combinaciones=
\begin{equation}
\frac{25000!}{22!(25000 - 22)!}
\end{equation}
\] Sin embargo, al intentar calcular 25000!, el número es
demasiado grande para el cómputo de este problema en un computador de
nivel domiciliario.
factorial(25000)/(factorial(22)*factorial(25000-22))
## [1] NaN
Obtenemos como resultado NaN que significa Not a
number.
Por otro lado, si el orden de de la cadena de genes es relevante para la determinación de si un conjunto puede estar vinculado a la aparición de diabetes tipo 2, entonces estamos frente a una permutación. Para este caso, la fórmula sería: \[ Permutaciones= \begin{equation} \frac{25000!}{(25000 - 22)!} \end{equation} \]
factorial(25000)/(factorial(25000-22))
## [1] NaN
Tal como ocurre en el caso anterior, factorial de 25 mil es un número demasiado grande para ser calculado computacionalmente con la tecnología actual de un sistema computacional no profesional, por lo que las permutaciones no pueden ser calculadas. Consideremos además que la operación del número total de permutaciones sería un número aún más grande que el de combinaciones.
Estrategia de resolución
Podemos calcular factoriales
demasiado grandes para ser procesador de manera tradicional, utilizando
el paquete gmp.
Combinaciones
# Cargamos el paquete "gmp"
library(gmp)
##
## Attaching package: 'gmp'
## The following objects are masked from 'package:base':
##
## %*%, apply, crossprod, matrix, tcrossprod
# Definimos n y k
n <- as.bigz(25000)
k <- as.bigz(22)
# Cálculo de combinaciones
combinaciones <- chooseZ(n, k)
# Combinaciones
print(combinaciones)
## Big Integer ('bigz') :
## [1] 5010713441141501787577547676827449801905335389570753182333600600985237925000
Permutaciones
# Cálculo del numerador 25.000!
numerador <- as.bigz(25000)
numerador_factorial <- factorialZ(numerador)
# Cálculo del denominador (25.000 - 22)!
denominador <- as.bigz(25000 - 22)
denominador_factorial <- factorialZ(denominador)
# Cálculo de permutaciones -> 25.000! / (25.000 - 22)!
permutaciones <- numerador_factorial / denominador_factorial
# Permutaciones
print(permutaciones)
## Big Rational ('bigq') :
## [1] 5632045554528088973219822914385244299964785963832422226786540210002092493346708052107264000000000
Tiempo de cálculo:
Si cada comprobación toma 1
nanosegundo, podemos multiplicar el total de combinaciones por 1
nanosegundo y obtendremos el tiempo total en nanosegundos. Luego,
pasamos de nanosegundos a segundos dividiendo el total de nanosegundos
en 1.000.000.000 para obtener el tiempo en segundos.
\[
Tiempo\ Total \ [s]=
\begin{equation}
\frac{(Combinaciones\ o \ Permutaciones) \cdot 1\ nanosegundo}{1\ 000\
000\ 000}
\end{equation}
\]
Para calcular el tiempo, tomaré el resultado de combinaciones. De
manera que:
segundos = combinaciones/1000000000
print(segundos)
## Big Rational ('bigq') :
## [1] 200428537645660071503101907073097992076213415582830127293344024039409517/40000
horas = segundos/3600
print(horas)
## Big Rational ('bigq') :
## [1] 200428537645660071503101907073097992076213415582830127293344024039409517/144000000
dias = horas/24
print(dias)
## Big Rational ('bigq') :
## [1] 200428537645660071503101907073097992076213415582830127293344024039409517/3456000000
años = dias/365
print(años)
## Big Rational ('bigq') :
## [1] 200428537645660071503101907073097992076213415582830127293344024039409517/1261440000000
milenios = años/1000
print(milenios)
## Big Rational ('bigq') :
## [1] 200428537645660071503101907073097992076213415582830127293344024039409517/1261440000000000
Incluso exagerando el cálculo, al estimar milenios, el tiempo es extremadamente grande y resulta inmanejable para nuestra realidad humana.
Si calculamos las permutaciones el tiempo resultante es aún mayor:
segundos_p = permutaciones/1000000000
print(segundos_p)
## Big Rational ('bigq') :
## [1] 5632045554528088973219822914385244299964785963832422226786540210002092493346708052107264
horas_p = segundos_p/3600
print(horas_p)
## Big Rational ('bigq') :
## [1] 39111427462000617869582103572119752083088791415502932130462084791681197870463250361856/25
dias_p = horas/24
print(dias_p)
## Big Rational ('bigq') :
## [1] 200428537645660071503101907073097992076213415582830127293344024039409517/3456000000
años_p = dias_p/365
print(años_p)
## Big Rational ('bigq') :
## [1] 200428537645660071503101907073097992076213415582830127293344024039409517/1261440000000
milenios_p = años_p/1000
print(milenios_p)
## Big Rational ('bigq') :
## [1] 200428537645660071503101907073097992076213415582830127293344024039409517/1261440000000000
Sugerencia estratégica desde la óptica
computacional:
i. Disminuir el espacio total de búsqueda definiendo candidatos
de interés
Antes de implementar una solución computacional
que involucre algún tipo de verificación o búsqueda dentro de un
conjunto, es esencial determina exactamente qué es lo que se
busca.
En este sentido, es esencial que previo a cualquier
diseño de implementación computacional se identifique algún tipo de
indicador genético que advierta qué patrones o características existen
al momento de determinar si un gen podría estar relacionado con la
diabetes tipo 2 para así identificar posibles candidatos y priorizar la
verificación de los grupos que contengan a aquellos candidatos. Para
ello se puede analizar en profundidad el estudio y los resultados del
hallazgo inicial que plantea el problema del grupo original de 22 genes.
Por ejemplo,
- ¿Hay elementos en común entre estos genes?
-
¿Existen características diferenciadoras en este grupo respecto de otros
genes?
- ¿Por qué 22 y no otro número?
- ¿Hay alguna
característica especial en la composición de este grupo de
genes?
Responder este tipo de preguntas y más puede ayudarnos a
formar un perfil de candidato(s) en donde prioricemos la búsqueda de
acuerdo a criterios de probabilidad, descartando en el proceso
candidatos débiles y priorizando aquellos grupos que sí tengan mayor
probabilidad. Esta labor puede realizarse de manera manual en términos
generales o bien haciendo uso de los avances en Inteligencia Artificial
para buscar patrones diferenciadores o características en común en el
grupo inicial de 22 genes que da origen a este problema.
Una vez
identificado un grupo más acotado de candidatos, la búsqueda puede ser
más eficiente. Aún así, un algoritmo de fuerza bruta no es la estrategia
más recomendada para buscar coincidencias en un conjunto de elementos
grande de cualquier tipo.
ii. Apoyo de especialistas en
la materia y revisión de precedentes
En este caso y respecto
de las especificidades del problema, sería conveniente consultar avances
en bioinformática para saber qué avances y estrategias se están
utilizando al momento de enfrentar problemas computacionales de tipo
similar.
Del mismo modo, siendo la ciencia una disciplina que se
construye y desarrolla en colectivo, el estudio de precedentes en
investigación e ingeniería ayudará a descubrir si ya se ha realizado
algún ejercicio similar y, en ese caso, consultar la documentación o
pedir asesoramiento o colaboración a los autores puede significar un
impulso y aceleración significativa respecto de la eficiencia en la
elección y el despliegue de la estrategia computacional correcta.
2. En el campo de la ingeniería aeroespacial, se sabe que los
materiales utilizados en las alas de los aviones pueden sufrir de fatiga
y eventualmente fallar. Se ha determinado que la vida útil de los
materiales de las alas es de 20.000 horas de vuelo. Bajo este
contexto:
a) ¿Cuál es la probabilidad de que las alas de un
avión fallen antes de las 5,000 horas de vuelo?
b) ¿Cuál es la
probabilidad de que las alas de un avión fallen antes de las 20,000
horas de vuelo?
c) ¿Cuál es la probabilidad de que las alas de un
avión fallen después de las 30,000 horas de vuelo?
e) Indique y
grafique la distribución asociada.
Solución:
Al trabajar sobre estimaciones de tiempo, estamos considerando
variables continuas. En particular, este problema puede resolverse
mediante distribución exponencial debido a que buscamos calcular la
fiabilidad o durabilidad de un producto o material, en este caso se
trata de las alas de un avión.
Sabemos por el enunciado que la vida
útil de las alas es de 20.000 horas de vuelo, luego:
lambda = 20000
respuesta_a = pexp(5000, rate =1/lambda, lower.tail = T)
print(respuesta_a)
## [1] 0.2211992
respuesta_b = pexp(20000, rate =1/lambda, lower.tail = T)
print(respuesta_b)
## [1] 0.6321206
respuesta_c = pexp(30000, rate =1/lambda, lower.tail = F)
print(respuesta_c)
## [1] 0.2231302
# Gráfico
rango = seq(-10,40000)
distribucion = dexp(rango, rate =1/lambda)
datos=data.frame(rango,distribucion)
library("ggplot2")
grafico = ggplot(data=datos,aes(x=rango,y=distribucion))
grafico = grafico + geom_line(stat="identity",color="pink",linewidth = 0.5)
grafico = grafico + theme_bw() + ggtitle("Distribución de probabilidades: Distribución exponencial")
grafico = grafico + xlab("Horas de vuelo") + ylab("Probabilidad")
plot(grafico)
## Ejercicio 3
3. Se sabe que el tiempo que tarda un
empleado en resolver un problema de soporte técnico en una empresa sigue
una distribución normal de media 15 minutos y desviación estándar de 5
minutos. Con base en esta información:
a) ¿Cuál es la probabilidad
de que un empleado resuelva un problema en exactamente 10 minutos?
Argumente su respuesta.
b) Si seleccionamos aleatoriamente a 50
empleados, ¿cuál es la probabilidad de que el tiempo promedio que tardan
en resolver un problema de soporte técnico sea menor a 12 minutos?
c) Indique y grafíque las distribuciones asociadas.
Solución:
Alternativamente, R nos permite calcular la densidad para un x = 10 minutos mediante la función dnorm:
dnorm(10,15,5)
## [1] 0.04839414
Y, también, podemos calcular la probabilidad de que el trabajador tarde menos de 10 minutos mediante la función pnorm:
pnorm(10,15,5)
## [1] 0.1586553
pnorm(12,15,5)
## [1] 0.2742531
Sin embargo, al tomar una muestra aleatoria de 50 empleados
utilizando distribución binomial, tenemos que:
Sabemos que la probabilidad de que un empleado tarde menos de 12 minutos es de: 0.2742531, calculada mediante pnorm(12,15,5). Luego, utilizamos distribución binomial:
p = pnorm(12,15,5)
respuesta = dbinom(50, size = 50, p)
print(respuesta)
## [1] 8.083113e-29
Por lo tanto, al seleccionar 50 trabajadores aleatoriamente, la probabilidad de que tarden menos de 12 minutos en resolver un problema técnico es de: 8.083113e-29.
#Creación de la distribución
x=seq(0,35,by=0.1)
y=dnorm(seq(0,35,by=0.1),15,5)
z=y
datos=data.frame(x,y,z)
#Gráfico
library("ggplot2")
p = ggplot(data.frame(x = x, y = y)) + aes(x = x, y = y)
p = p+geom_line(color="darkblue") + labs(x = "Dist. normal", y = "Densidad")
p = p + theme_classic() + ggtitle("Distribución normal Ejercicio 3")
p = p + geom_area(data = datos, aes(x=x,y=z), fill="lightblue", alpha=0.4)
#Distribución normal con media de 15 minutos y desviación estándar de 5
plot(p)
library("Rlab")
## Rlab 4.0 attached.
##
## Attaching package: 'Rlab'
## The following objects are masked from 'package:stats':
##
## dexp, dgamma, dweibull, pexp, pgamma, pweibull, qexp, qgamma,
## qweibull, rexp, rgamma, rweibull
## The following object is masked from 'package:datasets':
##
## precip
rango = seq(0,30)
distribucion = dbinom(rango, size = 50,prob = 0.2742531)
datos=data.frame(rango,distribucion)
library("ggplot2")
grafico = ggplot(data=datos,aes(x=rango,y=distribucion))
grafico = grafico + geom_bar(stat="identity",fill="lightblue3")
grafico = grafico + theme_bw() + ggtitle("Distribución de probabilidades pregunta c)")
grafico = grafico + xlab("Rango") + ylab("Probabilidad")
plot(grafico)