y operaciones de las cuatro estructuras de datos compuestas fundamentales en Julia, desde una perspectiva matemática y computacional. Operaciones Conceptos Tipado paramétrico Memoria contigua Tablas hash Inmutabilidad JULIA Indexación Broadcasting Teorı́a de conjuntos Estabilidad de tipos Abraham Zamudio Chauca 2 / 55
es una estructura de datos que agrupa múltiples valores bajo un único identificador, permitiendo organizar, almacenar y manipular colecciones de información de manera eficiente. Caracterı́stica Clave en Julia En Julia, todos los tipos compuestos son paramétricos: su comportamiento y rendimiento dependen del tipo especı́fico de sus elementos. Array{T , N }, JULIA Dict{K , V }, Set{T } Abraham Zamudio Chauca 4 / 55
estructuras comparten una interfaz común derivada de AbstractArray, lo que permite un diseño de algoritmos genéricos. JULIA Abraham Zamudio Chauca 5 / 55
colección mutable, de longitud variable, que almacena elementos del mismo tipo en un bloque de memoria contigua. Propiedades Tipo Paramétrico Mutable: sı́ Homogéneo: sı́ Memoria: contigua Orden: column-major Indexación: base 1 JULIA Array{T, N} T : tipo de elementos N: dimensionalidad Abraham Zamudio Chauca 6 / 55
Array se almacenan en posiciones consecutivas de memoria RAM, lo que permite: • Acceso O(1) por ı́ndice • Aprovechamiento de la caché del procesador • Operaciones vectorizadas eficientes 1 2 3 4 5 addr addr+8 addr+16 addr+24 addr+32 Consecuencia Esta disposición es la base del alto rendimiento de Julia en cálculo numérico. JULIA Abraham Zamudio Chauca 7 / 55
especificar el tipo para garantizar type stability: Sintaxis # Vector de enteros de 64 bits v = Int64[1, 2, 3, 4] # Matriz de flotantes de 32 bits M = Float32[1.0 2.0; 3.0 4.0] # Array vacı́o con tipo definido empty_arr = Vector{String}() Precaución Evitar Array{Any, 1}: obliga al compilador a realizar boxing y degrada el rendimiento. JULIA Abraham Zamudio Chauca 10 / 55
20, 30, 40, 50] deleteat!(v, 2) # Elimina ı́ndice 2: [10, 30, 40, 50] pop!(v) # Extrae y retorna el último: 50 # v queda: [10, 30, 40] popfirst!(v) # Extrae el primero: 10 # v queda: [30, 40] # Eliminación por máscara v = [1, 2, 3, 4, 5] deleteat!(v, v .> 3) # v = [1, 2, 3] Precaución Todas estas operaciones son O(n) porque requieren reacomodar la memoria. JULIA Abraham Zamudio Chauca 15 / 55
elemento entre arreglos, o entre un arreglo y un escalar, sin necesidad de bucles explı́citos. Sintaxis con Punto v = [1, 2, 3, 4] w = [10, 20, 30, 40] v .+ 10 v .* 2 v .ˆ 2 # [11, 12, 13, 14] # [2, 4, 6, 8] # [1, 4, 9, 16] v .+ w v .* w # [11, 22, 33, 44] # [10, 40, 90, 160] Regla El punto (.) antes del operador indica broadcasting. JULIA Abraham Zamudio Chauca 16 / 55
de broadcasting en un único bucle, evitando la creación de arreglos temporales. Equivalencia # Expresión fusionada (un solo bucle) y = 2 .* x.ˆ2 .+ 3 .* x .+ 1 # Equivalente manual (más verboso) @. y = 2 * xˆ2 + 3 * x + 1 Rendimiento Esta fusión reduce el uso de memoria y mejora el rendimiento, haciendo que el código legible sea también eficiente. JULIA Abraham Zamudio Chauca 18 / 55
4] B = [5 6; 7 8] A * B A’ A * A’ # Producto matricial # Transpuesta (Adjoint) # A por su transpuesta tr(A) det(A) inv(A) eigvals(A) # Traza # Determinante # Matriz inversa # Valores propios # Resolución de sistemas Ax = b b = [1, 2] x = A \ b # Operador backslash JULIA Abraham Zamudio Chauca 19 / 55
orden por columnas (column-major), igual que Fortran, MATLAB y R. Matriz A Memoria 1 4 7 3 6 9 5 8 11 1 4 7 2 5 8 3 6 9 Implicación Iterar por columnas es más eficiente que por filas. JULIA Abraham Zamudio Chauca 20 / 55
4, 5, 6] # Reshape (no copia datos) M = reshape(v, 2, 3) # Matriz 2x3 T = reshape(v, 3, 2, 1) # Tensor 3D # Vistas (views) - sin copia de memoria v_view = @view v[2:5] # Vista a los elementos 2 a 5 Eficiencia Tanto reshape como @view crean vistas que comparten la memoria con el arreglo original. Modificar la vista modifica el original. Precaución Usar @view en lugar de slicing normal evita copias innecesarias de datos. JULIA Abraham Zamudio Chauca 22 / 55
fijo Stack Mutables Homogéneos Memoria dinámica Heap Cambio de Paradigma Las tuplas sacrifican mutabilidad a cambio de velocidad y seguridad de tipos. JULIA Abraham Zamudio Chauca 23 / 55
ordenada e inmutable de elementos que pueden ser de tipos diferentes. Propiedades Tipo Paramétrico Mutable: no Homogéneo: no Longitud: fija Memoria: stack JULIA Tuple{T1, T2, ...} Cada posición tiene su propio tipo Abraham Zamudio Chauca 24 / 55
3.1415, "texto", [1, 2]) # Tupla de un solo elemento (¡requiere coma!) t1 = (42,) # Tupla vacı́a empty_t = () # Tupla anidada nested = ((1, 2), (3, 4), (5, 6)) Coma Obligatoria La coma en (42,) es esencial para distinguirlo de una expresión entre paréntesis. JULIA Abraham Zamudio Chauca 25 / 55
puede modificarse. Sus elementos no pueden ser reasignados, añadidos o eliminados. Comportamiento t = (1, 2, 3) t[1] # Lectura permitida: 1 t[1] = 10 # ERROR: MethodError # Para "modificar", crear una nueva t_new = (10, t[2], t[3]) # (10, 2, 3) Excepción Si un elemento es mutable (ej. un Array), su contenido interno sı́ puede cambiar. JULIA Abraham Zamudio Chauca 26 / 55
en variables individuales de forma simultánea. Sintaxis t = (1, 2.5, "texto") a, b, c = t # a=1, b=2.5, c="texto" # Ignorar elementos con _ x, _, z = t # x=1, z="texto" # Intercambio de variables (sin temporal) a, b = 10, 20 a, b = b, a # Ahora a=20, b=10 Requisito El número de variables debe coincidir con el de elementos (o usar ). JULIA Abraham Zamudio Chauca 28 / 55
donde cada elemento tiene una etiqueta (clave) asociada, combinando la eficiencia de las tuplas con la legibilidad de los diccionarios. Sintaxis # NamedTuple con etiquetas nt = (x = 1.0, y = 2.5, z = -1.0) # NamedTuple vacı́o empty_nt = NamedTuple() # NamedTuple anidado persona = (nombre = "Ana", edad = 30, ciudad = "Lima") Tipo Paramétrico NamedTuple{(:x, :y, :z), Tuple{Float64, Float64, Float64}} JULIA Abraham Zamudio Chauca 30 / 55
una sola tupla. El retorno múltiple es una ilusión sintáctica basada en desestructuración. Ejemplo function estadisticas(v) return minimum(v), maximum(v), mean(v) end # El retorno es una tupla resultado = estadisticas([1, 2, 3, 4, 5]) # resultado = (1, 5, 3.0) # Desestructuración inmediata min_val, max_val, promedio = estadisticas([1, 2, 3, 4, 5]) Eficiencia Las tuplas retornadas se asignan en el stack, sin overhead de memoria. JULIA Abraham Zamudio Chauca 33 / 55
fijas (x,y,z) Argumentos de funciones Datos heterogéneos pequeños Claves de diccionario Colecciones grandes Datos homogéneos Necesidad de mutación Cálculo matricial Datos de tamaño variable Regla Práctica Si los datos no cambian y son pequeños ⇒ tupla. Si los datos crecen o son numéricos ⇒ array. JULIA Abraham Zamudio Chauca 34 / 55
de pares clave ⇒ valor, implementada mediante tablas hash. Propiedades Tipo Paramétrico Mutable: sı́ Claves únicas: sı́ Orden: no garantizado Acceso: O(1) promedio JULIA Dict{K, V} K : tipo de las claves V : tipo de los valores Abraham Zamudio Chauca 35 / 55
función hash h : K → {0, 1, . . . , m − 1} a cada clave para determinar su posición en memoria. Clave h(k ) Valor ”alpha” 3 1 ”beta” 7 2.0 Complejidad Inserción, consulta y eliminación: O(1) promedio, O(n) peor caso. JULIA Abraham Zamudio Chauca 36 / 55
Inserción de nuevo par d["alpha"] = 1 d["beta"] = 2 # Actualización de valor existente d["alpha"] = 100 # Sobrescribe # Inserción con verificación d["gamma"] = get!(d, "gamma", 3) # Solo si no existe # Merge de diccionarios d1 = Dict("a" => 1, "b" => 2) d2 = Dict("b" => 20, "c" => 30) merge(d1, d2) # Nuevo Dict (no modifica originales) merge!(d1, d2) # Modifica d1 in-place JULIA Abraham Zamudio Chauca 38 / 55
consultar valores, con diferentes comportamientos ante claves inexistentes. Métodos de Consulta d = Dict("a" => 1, "b" => 2, "c" => 3) # Acceso directo (lanza error si no existe) d["a"] # 1 d["z"] # ERROR: KeyError # Acceso seguro con valor por defecto get(d, "a", 0) # 1 get(d, "z", 0) # 0 (no error) # Verificar existencia haskey(d, "a") # true "a" in keys(d) # true JULIA Abraham Zamudio Chauca 39 / 55
"b" => 2, "c" => 3) # Vistas (no copian datos) keys(d) # Iterador de claves values(d) # Iterador de valores pairs(d) # Iterador de pares # Conversión a arreglos collect(keys(d)) # ["a", "b", "c"] collect(values(d)) # [1, 2, 3] # Tamaño length(d) isempty(d) # 3 # false Orden El orden de iteración no está garantizado y puede variar. JULIA Abraham Zamudio Chauca 40 / 55
identificadores internos, inmutables y únicos. Son más eficientes que las cadenas como claves. Comparación # Con Strings (menos eficiente) d1 = Dict("nombre" => "Ana", "edad" => 30) # Con Symbols (más eficiente) d2 = Dict(:nombre => "Ana", :edad => 30) # Acceso d2[:nombre] d2.nombre # "Ana" # También válido (sintaxis de punto) Rendimiento Los sı́mbolos se comparan por identidad (puntero), no por contenido, lo que acelera las operaciones hash. JULIA Abraham Zamudio Chauca 42 / 55
colección mutable, desordenada de elementos únicos, que implementa la teorı́a de conjuntos matemática. Propiedades Tipo Paramétrico Mutable: sı́ Elementos únicos: sı́ Orden: no Pertenencia: O(1) JULIA Set{T} T : tipo de los elementos Abraham Zamudio Chauca 43 / 55
1) # S = Set([1]) push!(S, 2, 3) # S = Set([1, 2, 3]) push!(S, 2) # Ignorado (ya existe) # Eliminar elementos delete!(S, 2) # S = Set([1, 3]) # Extraer elemento arbitrario x = pop!(S) # Extrae y retorna un elemento # Vaciar conjunto empty!(S) # Tamaño length(S) JULIA # Número de elementos Abraham Zamudio Chauca 45 / 55
operaciones de teorı́a de conjuntos, haciendo el código más legible y matemático. Operadores S = Set([1, 2, 3, 4, 5]) # Pertenencia (∈ equivale a in) 3 ∈S # true 99 ∈S # false # No pertenencia 99 ∈S / # true # Forma alternativa in(3, S) # true in(99, S) # false Rendimiento La verificación de pertenencia es O(1) promedio gracias a la tabla hash interna. JULIA Abraham Zamudio Chauca 46 / 55
= Set([3, 4, 5, 6]) # Diferencia (A \ B): elementos en A pero no en B setdiff(A, B) # Set([1, 2]) A \ B # Notación Unicode # Diferencia inversa setdiff(B, A) # Set([5, 6]) B \ A # Set([5, 6]) # Diferencia simétrica: en A o B, pero no en ambos symdiff(A, B) # Set([1, 2, 5, 6]) # Versión in-place A_copy = copy(A) setdiff!(A_copy, B) # Modifica A_copy JULIA Abraham Zamudio Chauca 48 / 55
2, 3, 4, 5]) B = Set([1, 2, 3]) C = Set([1, 2, 6]) # Subconjunto (⊆) B ⊆A # true (B es subconjunto de A) C ⊆A # false # Subconjunto propio (⊊) B ⊊A # true (B ⊆A y B ̸=A) A ⊊A # false # Superconjunto (⊇) A ⊇B # true # Igualdad A == B # false B == Set([1, 2, 3]) # true JULIA Abraham Zamudio Chauca 49 / 55
No Sı́ Sı́ Ordenado Sı́ Sı́ No No Homogéneo Sı́ No No Sı́ No Claves Sı́ Elementos únicos No Acceso O(1) O(1) O(1) O(1) Búsqueda O(n) O(n) O(1) O(1) Selección La elección depende de: mutabilidad requerida, homogeneidad de datos, y operaciones frecuentes. JULIA Abraham Zamudio Chauca 51 / 55
requiere que el compilador pueda inferir todos los tipos en tiempo de compilación. Type-Stable Type-Unstable # Tipos concretos v = Int64[1, 2, 3] d = Dict{String, Int64}() # Tipos abstractos v = Any[1, 2.0, "3"] d = Dict{Any, Any}() # El compilador optimiza @code_warntype sum(v) # El compilador no optimiza @code_warntype sum(v) Rendimiento: lento Rendimiento: nivel C Herramienta Usar @code warntype para detectar inestabilidades de tipos. JULIA Abraham Zamudio Chauca 52 / 55
# Tabla de datos personas = [ (nombre="Ana", edad=30), (nombre="Luis", edad=25), (nombre="Marı́a", edad=28) ] # Datos agrupados datos = Dict( "edades" => [30, 25, 28], "alturas" => [1.65, 1.80, 1.70] ) # Acceso personas[1].nombre # "Ana" # Acceso datos["edades"][2] # 25 Flexibilidad Las estructuras compuestas pueden anidarse para modelar datos complejos. JULIA Abraham Zamudio Chauca 53 / 55
estabilidad 2. Usar broadcasting en lugar de bucles para operaciones vectorizadas 3. Preferir vistas (@view) para evitar copias innecesarias 4. Usar sı́mbolos como claves en diccionarios para mejor rendimiento 5. Aprovechar NamedTuples para datos estructurados pequeños 6. Usar conjuntos para verificación de pertenencia y operaciones matemáticas 7. Consultar documentación con ?nombre función en el REPL Herramientas de Depuración @code warntype, @time, @btime (BenchmarkTools) JULIA Abraham Zamudio Chauca 55 / 55