Este notebook está organizado en los fundamentos (teoría de conjuntos, axiomas de los números reales e inducción matemática, siguiendo la Parte 2, Parte 3 y Parte 4 de Apostol) Cada paso tiene una breve explicación en texto antes del código.
Un conjunto es una colección de objetos, llamados elementos. En R podemos representar conjuntos con vectores, teniendo cuidado de no repetir elementos.
Paso 1: Creamos un conjunto en R
A <- c(1, 2, 3, 4, 5)
A
## [1] 1 2 3 4 5
Paso 2: Verificamos si un elemento pertenece al conjunto (relación de pertenencia)
3 %in% A
## [1] TRUE
8 %in% A
## [1] FALSE
Un conjunto puede describirse por extensión (listando sus elementos) o por comprensión (una regla que cumplen sus elementos), por ejemplo \(B = \{x : x \text{ es par}, 1 \le x \le 20\}\).
Paso 1: Definimos el conjunto por extensión
B_extension <- c(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
B_extension
## [1] 2 4 6 8 10 12 14 16 18 20
Paso 2: Definimos el mismo conjunto por comprensión usando una condición lógica
x <- 1:20
B_comprension <- x[x %% 2 == 0]
B_comprension
## [1] 2 4 6 8 10 12 14 16 18 20
Paso 3: Comprobamos que ambas formas generan el mismo conjunto
identical(B_extension, B_comprension)
## [1] FALSE
Un conjunto \(C\) es subconjunto de \(D\) si todo elemento de \(C\) también pertenece a \(D\), lo que se denota \(C \subseteq D\).
Paso 1: Definimos dos conjuntos
C <- c(2, 4, 6)
D <- c(1, 2, 3, 4, 5, 6, 7)
Paso 2: Verificamos si C es subconjunto de D
es_subconjunto <- all(C %in% D)
es_subconjunto
## [1] TRUE
Paso 3: Verificamos la igualdad de conjuntos (doble contención)
E <- c(6, 4, 2) # mismos elementos que C, distinto orden
son_iguales <- setequal(C, E)
son_iguales
## [1] TRUE
Paso 1: Definimos dos conjuntos de trabajo
conjunto_F <- c(1, 2, 3, 4, 5)
conjunto_G <- c(4, 5, 6, 7, 8)
Paso 2: Calculamos la union (reunión) F ∪ G
union_FG <- union(conjunto_F, conjunto_G)
union_FG
## [1] 1 2 3 4 5 6 7 8
Paso 3: Calculamos la intersección F ∩ G
interseccion_FG <- intersect(conjunto_F, conjunto_G)
interseccion_FG
## [1] 4 5
Paso 4: Calculamos el complemento de F respecto a un conjunto universal U
U <- 1:10
complemento_F <- setdiff(U, conjunto_F)
complemento_F
## [1] 6 7 8 9 10
Paso 5: Calculamos la diferencia de conjuntos F - G
diferencia_FG <- setdiff(conjunto_F, conjunto_G)
diferencia_FG
## [1] 1 2 3
Las leyes de De Morgan afirman que \((F \cup G)^c = F^c \cap G^c\) y \((F \cap G)^c = F^c \cup G^c\).
Paso 1: Calculamos el lado izquierdo de la primera ley
lado_izq1 <- setdiff(U, union(conjunto_F, conjunto_G))
lado_izq1
## [1] 9 10
Paso 2: Calculamos el lado derecho de la primera ley
lado_der1 <- intersect(setdiff(U, conjunto_F), setdiff(U, conjunto_G))
lado_der1
## [1] 9 10
Paso 3: Comparamos ambos resultados
setequal(lado_izq1, lado_der1)
## [1] TRUE
El sistema de los números reales se construye a partir de un conjunto de axiomas: axiomas de cuerpo, axiomas de orden y el axioma del extremo superior. En esta sección ilustramos cada axioma con ejemplos numericos en R.
Los axiomas de cuerpo garantizan que la suma y el producto de números reales cumplen propiedades como conmutatividad, asociatividad, existencia de elemento neutro e inverso, y distributividad.
Paso 1: Verificamos la propiedad conmutativa de la suma y el producto
a <- 3.5
b <- 7.2
c(a + b == b + a, a * b == b * a)
## [1] TRUE TRUE
Paso 2: Verificamos la propiedad asociativa
c <- 2.1
c((a + b) + c == a + (b + c), (a * b) * c == a * (b * c))
## [1] FALSE TRUE
Paso 3: Verificamos la existencia del elemento neutro (0 para la suma, 1 para el producto)
c(a + 0 == a, a * 1 == a)
## [1] TRUE TRUE
Paso 4: Verificamos la existencia del inverso aditivo y multiplicativo
c(a + (-a) == 0, a * (1/a) == 1)
## [1] TRUE TRUE
Paso 5: Verificamos la propiedad distributiva
a * (b + c) == a*b + a*c
## [1] FALSE
Si \(a + c = b + c\) entonces \(a = b\).
Paso 1: Definimos valores y verificamos la hipotesis
a <- 5
b <- 5
c <- 3.7
(a + c) == (b + c)
## [1] TRUE
Paso 2: Confirmamos la conclusión
a == b
## [1] TRUE
El orden de los números reales cumple tricotomia (dado a y b, se tiene a<b, a=b o a>b), transitividad, y compatibilidad con la suma y el producto por positivos.
Paso 1: Verificamos la ley de tricotomia
comparar <- function(x, y) {
if (x < y) "x < y" else if (x > y) "x > y" else "x = y"
}
comparar(4, 7)
## [1] "x < y"
Paso 2: Verificamos la transitividad (si a<b y b<c, entonces a<c)
a <- 2; b <- 5; c <- 9
(a < b) & (b < c) & (a < c)
## [1] TRUE
Paso 3: Verificamos que el orden se preserva al sumar la misma cantidad
k <- 10
(a < b) == (a + k < b + k)
## [1] TRUE
Paso 4: Verificamos que el orden se preserva al multiplicar por un positivo, y se invierte al multiplicar por un negativo
m_pos <- 3
m_neg <- -3
c((a < b) == (a*m_pos < b*m_pos), (a < b) == (a*m_neg > b*m_neg))
## [1] TRUE TRUE
Resolver \(2x - 3 < 7\).
Paso 1: Definimos la desigualdad como función
desigualdad <- function(x) 2*x - 3 < 7
Paso 2: Probamos varios valores para verificar la solución x < 5
valores_prueba <- c(3, 4, 4.9, 5, 5.1, 6)
data.frame(x = valores_prueba, cumple = desigualdad(valores_prueba))
## x cumple
## 1 3.0 TRUE
## 2 4.0 TRUE
## 3 4.9 TRUE
## 4 5.0 FALSE
## 5 5.1 FALSE
## 6 6.0 FALSE
Paso 1: Verificamos si un número es entero en R
valores <- c(4, 4.5, -3, 0, 7/2)
son_enteros <- valores == floor(valores)
data.frame(valor = valores, es_entero = son_enteros)
## valor es_entero
## 1 4.0 TRUE
## 2 4.5 FALSE
## 3 -3.0 TRUE
## 4 0.0 TRUE
## 5 3.5 FALSE
Paso 2: Representamos un número racional como fracción p/q usando la libreria pracma
racional <- 0.75
fraccion <- pracma::rats(racional)
## 3/4
fraccion
## [1] 0.75
Paso 1: Ubicamos varios números reales en la recta numérica
puntos <- c(-3, -1.5, 0, 2, 4.7)
puntos
## [1] -3.0 -1.5 0.0 2.0 4.7
Paso 2: Graficamos estos puntos sobre una recta numérica
plot(puntos, rep(0, length(puntos)), pch = 19, col = "blue",
yaxt = "n", ylab = "", xlab = "Recta real",
main = "Interpretación geométrica de los números reales")
abline(h = 0)
text(puntos, 0.05, labels = puntos)
Paso 1: Definimos un conjunto acotado superiormente
conjunto_H <- c(1, 2, 3, 3.5, 3.9)
Paso 2: Verificamos que un valor es cota superior (mayor o igual a todos los elementos)
cota_candidata <- 4
es_cota_superior <- all(conjunto_H <= cota_candidata)
es_cota_superior
## [1] TRUE
Paso 3: Calculamos el extremo superior (supremo), que en este caso coincide con el máximo
supremo <- max(conjunto_H)
supremo
## [1] 3.9
Este axioma garantiza que todo conjunto no vacío de números reales acotado superiormente tiene un extremo superior (supremo), aunque dicho supremo no siempre sea alcanzado por el conjunto.
Paso 1: Ilustramos un conjunto cuyo supremo no pertenece al conjunto: valores de 1 - 1/n
n <- 1:20
conjunto_I <- 1 - 1/n
conjunto_I
## [1] 0.0000000 0.5000000 0.6666667 0.7500000 0.8000000 0.8333333 0.8571429
## [8] 0.8750000 0.8888889 0.9000000 0.9090909 0.9166667 0.9230769 0.9285714
## [15] 0.9333333 0.9375000 0.9411765 0.9444444 0.9473684 0.9500000
Paso 2: El supremo teórico de este conjunto es 1, aunque ningun elemento lo alcanza
max(conjunto_I) < 1
## [1] TRUE
supremo_teorico <- 1
supremo_teorico
## [1] 1
Paso 3: Graficamos como los elementos se acercan al supremo sin alcanzarlo
plot(n, conjunto_I, type = "b", col = "darkred",
main = "Elementos acercandose al supremo (1 - 1/n)",
xlab = "n", ylab = "1 - 1/n")
abline(h = 1, lty = 2, col = "blue")
La propiedad arquimediana establece que para todo número real \(x\), existe un número natural \(n\) tal que \(n > x\).
Paso 1: Definimos un número real grande
x_real <- 1000000.5
Paso 2: Buscamos un número natural que lo supere
n_natural <- ceiling(x_real) + 1
n_natural > x_real
## [1] TRUE
Paso 1: Verificamos que el supremo de la union de dos conjuntos es el máximo de los supremos individuales
conjunto_J <- c(1, 2, 3)
conjunto_K <- c(2, 4, 5)
sup_J <- max(conjunto_J)
sup_K <- max(conjunto_K)
sup_union <- max(union(conjunto_J, conjunto_K))
c(sup_J, sup_K, sup_union, max(sup_J, sup_K) == sup_union)
## [1] 3 5 5 1
Sea el conjunto \(L = \{x : 2 < x \le 6\}\).
Paso 1: Generamos una muestra densa de puntos del conjunto
L <- seq(2.0001, 6, by = 0.0001)
Paso 2: Calculamos el supremo (que si pertenece al conjunto) y el infimo (que no pertenece)
supremo_L <- max(L)
infimo_L <- min(L)
c(supremo_L = supremo_L, infimo_L = infimo_L)
## supremo_L infimo_L
## 6.0000 2.0001
Paso 1: Calculamos la raíz cuadrada de un número no negativo
numero <- 7
raiz <- sqrt(numero)
raiz
## [1] 2.645751
Paso 2: Verificamos que el resultado satisface la definición (raíz^2 = número)
isTRUE(all.equal(raiz^2, numero))
## [1] TRUE
Paso 3: Aproximamos la raíz cuadrada mediante el método de Newton, paso a paso
aproximar_raiz <- function(a, iteraciones = 6) {
x <- a / 2
historial <- numeric(iteraciones)
for (i in 1:iteraciones) {
x <- (x + a/x) / 2
historial[i] <- x
}
historial
}
aproximar_raiz(7)
## [1] 2.750000 2.647727 2.645752 2.645751 2.645751 2.645751
Paso 1: Calculamos una raíz de orden superior, por ejemplo la raíz cubica
raiz_cubica <- 27^(1/3)
raiz_cubica
## [1] 3
Paso 2: Calculamos una potencia racional general, por ejemplo 8^(2/3)
potencia_racional <- 8^(2/3)
potencia_racional
## [1] 4
Paso 3: Verificamos la propiedad (a(p/q))q = a^p
a_val <- 8; p_val <- 2; q_val <- 3
lado_izq <- (a_val^(p_val/q_val))^q_val
lado_der <- a_val^p_val
isTRUE(all.equal(lado_izq, lado_der))
## [1] TRUE
Paso 1: Obtenemos la representación decimal de un número racional
fraccion_ejemplo <- 1/3
print(fraccion_ejemplo, digits = 15)
## [1] 0.333333333333333
Paso 2: Identificamos el periodo de un decimal periódico generando varios digitos
options(digits = 15)
1/7
## [1] 0.142857142857143
options(digits = 7) # restauramos el valor por defecto
Paso 3: Aproximamos un número irracional (no periódico) como Pi con muchos decimales
print(pi, digits = 15)
## [1] 3.14159265358979
Queremos comprobar la formula \(1 + 2 + \dots + n = \frac{n(n+1)}{2}\).
Paso 1: Definimos la suma directa y la formula cerrada
suma_directa <- function(n) sum(1:n)
formula_cerrada <- function(n) n*(n+1)/2
Paso 2: Comparamos ambas para varios valores de n
n_vals <- 1:10
data.frame(n = n_vals,
suma_directa = sapply(n_vals, suma_directa),
formula = formula_cerrada(n_vals))
## n suma_directa formula
## 1 1 1 1
## 2 2 3 3
## 3 3 6 6
## 4 4 10 10
## 5 5 15 15
## 6 6 21 21
## 7 7 28 28
## 8 8 36 36
## 9 9 45 45
## 10 10 55 55
El principio de inducción establece que si una proposición \(P(n)\) es verdadera para \(n=1\) (caso base), y si \(P(k)\) verdadera implica \(P(k+1)\) verdadera (paso inductivo), entonces \(P(n)\) es verdadera para todo \(n \ge 1\).
Paso 1: Verificamos el caso base de la formula de la suma
n <- 1
suma_directa(n) == formula_cerrada(n)
## [1] TRUE
Paso 2: Verificamos el paso inductivo para un valor arbitrario k
k <- 15
paso_inductivo <- (formula_cerrada(k) + (k+1)) == formula_cerrada(k+1)
paso_inductivo
## [1] TRUE
Todo subconjunto no vacío de números naturales tiene un elemento mínimo.
Paso 1: Definimos un subconjunto de números naturales
subconjunto_naturales <- c(15, 3, 42, 7, 99, 3)
Paso 2: Encontramos el elemento mínimo
elemento_minimo <- min(subconjunto_naturales)
elemento_minimo
## [1] 3
Paso 1: Verificamos el caso base
n <- 1
2^n > n
## [1] TRUE
Paso 2: Verificamos numéricamente el paso inductivo para varios valores
k_vals <- 1:20
cumple <- 2^k_vals > k_vals
data.frame(k = k_vals, cumple_desigualdad = cumple)
## k cumple_desigualdad
## 1 1 TRUE
## 2 2 TRUE
## 3 3 TRUE
## 4 4 TRUE
## 5 5 TRUE
## 6 6 TRUE
## 7 7 TRUE
## 8 8 TRUE
## 9 9 TRUE
## 10 10 TRUE
## 11 11 TRUE
## 12 12 TRUE
## 13 13 TRUE
## 14 14 TRUE
## 15 15 TRUE
## 16 16 TRUE
## 17 17 TRUE
## 18 18 TRUE
## 19 19 TRUE
## 20 20 TRUE
Paso 1: Generamos un conjunto aleatorio de números naturales
set.seed(123)
conjunto_aleatorio <- sample(1:1000, 10)
conjunto_aleatorio
## [1] 415 463 179 526 195 938 818 118 299 229
Paso 2: Confirmamos que siempre existe un mínimo, sin importar el orden en que se presenten los elementos
min(conjunto_aleatorio)
## [1] 118
Paso 1: Calculamos una suma finita usando el símbolo sumatorio (sum en R)
\[\sum_{i=1}^{5} i^2\]
suma1 <- sum((1:5)^2)
suma1
## [1] 55
Paso 2: Calculamos una suma con indice que no comienza en 1
\[\sum_{i=3}^{8} (2i - 1)\]
suma2 <- sum(2*(3:8) - 1)
suma2
## [1] 60
Paso 3: Verificamos la propiedad de linealidad del sumatorio
\[\sum_{i=1}^{n} (a_i + b_i) = \sum_{i=1}^{n} a_i + \sum_{i=1}^{n} b_i\]
a_vec <- 1:5
b_vec <- 6:10
sum(a_vec + b_vec) == sum(a_vec) + sum(b_vec)
## [1] TRUE
Formula: \(\sum_{i=1}^{n} i^2 = \frac{n(n+1)(2n+1)}{6}\)
Paso 1: Calculamos la suma directa para n = 10
n <- 10
suma_directa_cuadrados <- sum((1:n)^2)
suma_directa_cuadrados
## [1] 385
Paso 2: Comparamos con la formula cerrada
formula_cuadrados <- n*(n+1)*(2*n+1)/6
formula_cuadrados
## [1] 385
La desigualdad triangular establece que \(|a + b| \le |a| + |b|\) para todo par de números reales.
Paso 1: Calculamos el valor absoluto de varios números
valores <- c(-5, 3, -2.7, 0)
abs(valores)
## [1] 5.0 3.0 2.7 0.0
Paso 2: Verificamos la desigualdad triangular con un ejemplo
a <- -4
b <- 6
c(abs(a + b), abs(a) + abs(b), abs(a + b) <= abs(a) + abs(b))
## [1] 2 10 1
Paso 3: Verificamos la desigualdad triangular para muchos pares aleatorios de números
set.seed(42)
a_rand <- runif(1000, -50, 50)
b_rand <- runif(1000, -50, 50)
todos_cumplen <- all(abs(a_rand + b_rand) <= abs(a_rand) + abs(b_rand))
todos_cumplen
## [1] TRUE
Resolver \(|x - 3| = 5\).
Paso 1: Planteamos las dos posibles soluciones
solucion1 <- 3 + 5
solucion2 <- 3 - 5
c(solucion1, solucion2)
## [1] 8 -2
Paso 2: Verificamos ambas soluciones
c(abs(solucion1 - 3) == 5, abs(solucion2 - 3) == 5)
## [1] TRUE TRUE
Paso 1: Definimos ambas funciones
factorial_vals <- function(n) factorial(n)
potencia_vals <- function(n) 2^n
Paso 2: Comparamos para varios valores de n a partir de 4
n_vals <- 4:12
data.frame(n = n_vals,
factorial = factorial_vals(n_vals),
potencia_2n = potencia_vals(n_vals),
cumple = factorial_vals(n_vals) > potencia_vals(n_vals))
## n factorial potencia_2n cumple
## 1 4 24 16 TRUE
## 2 5 120 32 TRUE
## 3 6 720 64 TRUE
## 4 7 5040 128 TRUE
## 5 8 40320 256 TRUE
## 6 9 362880 512 TRUE
## 7 10 3628800 1024 TRUE
## 8 11 39916800 2048 TRUE
## 9 12 479001600 4096 TRUE