48. Visualización computacional de relaciones y funciones

Una representación visual convierte pares ordenados, matrices y grafos en patrones que podemos explorar. En este tema construiremos visualizaciones con SVG y Canvas para comprender propiedades de relaciones y funciones, detectar errores y comunicar resultados.

48.1 Introducción: ver la estructura de los datos

Una relación discreta es un conjunto de pares ordenados. Por ejemplo, R = {(1, 2), (1, 3), (2, 3)} puede escribirse como texto, tabla, matriz, diagrama de flechas o grafo. Todas las representaciones describen el mismo objeto, pero cada una hace visibles propiedades diferentes.

La visualización computacional es el proceso de transformar datos en elementos gráficos mediante reglas reproducibles. No consiste en decorar una pantalla: una buena visualización conserva la información matemática y ayuda a responder una pregunta.

RelaciónConexiones entre elementos de dos conjuntos o de un mismo conjunto.
FunciónRelación en la que cada entrada tiene exactamente una salida.
MatrizUna celda indica si existe la relación entre una fila y una columna.
GrafoVértices y aristas muestran conexiones, recorridos y componentes.

La visualización resulta especialmente útil cuando el conjunto es finito, cuando queremos comparar alternativas o cuando necesitamos observar una evolución paso a paso. Si el volumen de datos es grande, el dibujo debe resumir y permitir filtrar: mostrar todo no siempre significa explicar mejor.

48.2 De una relación a una representación visual

Consideremos A = {1, 2, 3, 4}, B = {a, b, c} y la relación R = {(1, a), (1, b), (2, b), (3, c), (4, c)}. El par (2, b) se dibuja como una flecha desde 2 hasta b.

El diagrama permite observar inmediatamente que 1 tiene dos imágenes. Por lo tanto, R es una relación, pero no es una función de A en B. En cambio, cada elemento de B recibe al menos una flecha, por lo que sí es sobreyectiva como relación de asignación si se ignora la condición funcional.

Explorador de diagramas de correspondencia

Diagrama de correspondencia entre dos conjuntosLos elementos del conjunto A se conectan con elementos del conjunto B mediante flechas.

En un programa conviene separar los datos de su representación. La relación puede guardarse como arreglo de pares y una función de dibujo puede recibir ese arreglo. Así se puede cambiar el estilo, el tamaño o el formato sin modificar la definición matemática.

const A = [1, 2, 3, 4];
const B = ['a', 'b', 'c'];
const R = [[1, 'a'], [1, 'b'], [2, 'b'], [3, 'c'], [4, 'c']];

function imagenDe(x, relacion) {
  return relacion.filter(([entrada]) => entrada === x)
                 .map(([, salida]) => salida);
}

// La cantidad de salidas de cada entrada permite detectar una función.
const esFuncion = A.every(x => imagenDe(x, R).length === 1);
console.log('Conjunto A:', A);
console.log('Imagen de 1:', imagenDe(1, R));
console.log('¿La relación es función de A en B?:', esFuncion);

48.3 Coordenadas para funciones discretas

Para visualizar una función f: A → B numérica, ubicamos cada entrada x en el eje horizontal y su salida f(x) en el eje vertical. Solo se dibujan los valores que pertenecen al dominio; por eso una función discreta aparece como un conjunto de puntos, no necesariamente como una línea continua.

Unir puntos con segmentos puede sugerir que existen valores intermedios. Esa interpolación es válida solo si el modelo lo justifica. Para una función definida sobre números naturales, los puntos separados comunican mejor que una curva que inventa valores.

Gráfica de una función discreta

El escalado transforma coordenadas matemáticas en píxeles. Si el área de dibujo mide ancho × alto, una transformación típica es:

const margen = 40, xmin = 0, ymin = 0;
const escalaX = 20, escalaY = 15, alto = 300;
const x = 4, y = 6;
const px = margen + (x - xmin) * escalaX;
const py = alto - margen - (y - ymin) * escalaY;
// El eje vertical de Canvas crece hacia abajo; por eso se resta py.
console.log('Coordenada matemática:', { x, y });
console.log('Coordenada de pantalla:', { px, py });

La escala debe ser coherente en ambos ejes cuando se quiere preservar pendientes y distancias. También es importante mostrar el origen, las unidades y una leyenda que indique el dominio utilizado.

48.4 Detectar propiedades de funciones con un diagrama

Las propiedades de una función pueden expresarse visualmente:

  • Funcional: cada elemento del dominio tiene exactamente una flecha saliente.
  • Inyectiva: ningún elemento del codominio recibe flechas desde dos entradas distintas.
  • Sobreyectiva: todo elemento del codominio recibe al menos una flecha.
  • Biyectiva: es funcional, inyectiva y sobreyectiva; cada elemento queda emparejado con uno solo.

Un algoritmo puede verificar esas propiedades antes de dibujar. Así la visualización no depende de una inspección subjetiva:

function analizarFuncion(dominio, codominio, pares) {
  const salidas = new Map();
  for (const [x, y] of pares) {
    if (!dominio.includes(x) || !codominio.includes(y)) return { valida: false };
    if (salidas.has(x)) return { valida: false, motivo: 'entrada repetida' };
    salidas.set(x, y);
  }
  const valores = [...salidas.values()];
  return {
    valida: dominio.every(x => salidas.has(x)),
    inyectiva: new Set(valores).size === valores.length,
    sobreyectiva: codominio.every(y => valores.includes(y))
  };
}

const analisis = analizarFuncion(
  [1, 2, 3],
  ['a', 'b'],
  [[1, 'a'], [2, 'b'], [3, 'a']]
);
console.log('Análisis de la función:', analisis);
Idea clave: primero se verifica el modelo y luego se decide cómo representarlo. Un gráfico atractivo que omite elementos del dominio puede ocultar que la función está mal definida.

48.5 Matrices de relación como mapas de calor

Una relación sobre un conjunto finito puede representarse mediante una matriz booleana. Para A = {1, 2, 3, 4}, la celda (i, j) vale 1 si i R j y 0 en caso contrario. Un mapa de calor reemplaza 1 por un color intenso y 0 por un color tenue.

Este formato es útil para observar simetría, densidad y patrones. Una matriz simétrica respecto de la diagonal representa una relación simétrica; una diagonal completa indica reflexividad; la cantidad de unos por fila muestra cuántas imágenes tiene cada elemento.

Mapa de calor de una relación

Para no confundir un valor ausente con un dato desconocido, la interfaz debe distinguir al menos tres estados cuando corresponda: verdadero, falso y sin información. La paleta también debe funcionar para personas con daltonismo; las etiquetas y los valores numéricos siguen siendo necesarios.

48.6 Relaciones como grafos y redes

Cuando los elementos pertenecen al mismo conjunto, una relación binaria se dibuja como un grafo dirigido. Cada elemento es un vértice y cada par (u, v) es una arista orientada de u a v. Los lazos representan pares como (u, u).

En una red de dependencias, por ejemplo, una flecha A → B puede significar “A necesita a B”. La visualización permite detectar ciclos, vértices aislados y caminos. Es importante no confundir la dirección de la arista con una relación simétrica: que A se conecte con B no implica que B se conecte con A.

Explorador de una red dirigida

Para grafos pequeños es suficiente usar SVG: cada vértice puede ser un círculo y cada arista una línea con marcador de flecha. Para miles de elementos se suelen usar técnicas de agrupamiento, filtros, lienzo (Canvas) o WebGL, porque dibujar cada etiqueta puede volver lenta la interfaz.

const aristas = [['A', 'B'], ['A', 'C'], ['B', 'D'], ['C', 'D'], ['D', 'E'], ['E', 'F']];

function vecinos(origen, relaciones) {
  return relaciones.filter(([u]) => u === origen).map(([, v]) => v);
}

// El mismo arreglo alimenta una vista SVG, una tabla de adyacencia
// o una búsqueda en anchura. Datos y presentación permanecen separados.
console.log('Vecinos de A:', vecinos('A', aristas));
console.log('Vecinos de C:', vecinos('C', aristas));

48.7 Animación: mostrar una relación que cambia

Una animación agrega una dimensión temporal. Puede mostrar cómo se construye una clausura transitiva, cómo se propaga una búsqueda o cómo cambia una función al variar un parámetro. Cada paso debe corresponder a un estado matemático bien definido; mover objetos sin explicar qué representa el movimiento solo añade ruido.

Una estrategia sencilla es mantener un índice paso y dibujar únicamente los pares cuyo índice sea menor o igual. Para reproducibilidad, se puede pausar, avanzar y volver al estado inicial. Esto facilita que el estudiante compruebe qué arista se incorporó y por qué.

let paso = 0;
const estados = [
  [['A', 'B']],
  [['A', 'B'], ['B', 'C']],
  [['A', 'B'], ['B', 'C'], ['A', 'C']] // aparece por transitividad
];

function avanzar() {
  paso = Math.min(paso + 1, estados.length - 1);
  console.log(`Paso ${paso}:`, estados[paso]);
}

avanzar();
avanzar();

En visualizaciones educativas, la animación debe poder detenerse y no debe ser la única forma de acceder a la información. Una tabla equivalente, texto alternativo o una descripción del estado hacen que el contenido siga siendo comprensible.

48.8 Buen diseño: precisión antes que apariencia

DecisiónBuena prácticaRiesgo frecuente
EscalaIndicar unidades, límites y origen.Exagerar una diferencia cambiando el eje.
ColorUsar una paleta consistente y con contraste.Usar color como única codificación.
EtiquetasNombrar conjuntos, ejes y relaciones.Obligar a adivinar qué significa cada nodo.
VolumenFiltrar, agrupar y permitir explorar.Superponer miles de elementos ilegibles.
InteracciónMostrar estado, selección y acción disponible.Animar sin explicar qué cambió.

Una visualización puede ser formalmente correcta y aun así inducir a errores. Por ejemplo, una línea que une puntos de una función discreta puede sugerir continuidad; una flecha sin punta puede ocultar la dirección; y un grafo sin leyenda puede hacer pasar una arista por una simple conexión no orientada.

48.9 Arquitectura de una visualización en JavaScript

Un diseño mantenible separa cuatro responsabilidades:

  1. Modelo: conjuntos, pares, valores de la función o matriz.
  2. Análisis: dominio, imagen, grados, propiedades y errores.
  3. Vista: creación de SVG, Canvas, tabla y leyenda.
  4. Interacción: eventos de botones, filtros, selección y teclado.
const modelo = {
  dominio: [1, 2, 3],
  codominio: ['a', 'b'],
  pares: [[1, 'a'], [2, 'b'], [3, 'a']]
};

function analizar(modelo) {
  const imagen = new Set(modelo.pares.map(([, y]) => y));
  return { imagen: [...imagen], sobreyectiva: imagen.size === modelo.codominio.length };
}

function renderizar(modelo, resultado) {
  // La vista consume datos ya validados y dibuja sin cambiar el modelo.
  console.log(`Imagen: ${resultado.imagen.join(', ')}`);
  console.log(`¿Es sobreyectiva?: ${resultado.sobreyectiva}`);
}

const resultado = analizar(modelo);
renderizar(modelo, resultado);

Esta separación permite probar el análisis sin abrir un navegador y cambiar SVG por Canvas sin reescribir las reglas matemáticas. También facilita guardar un estado, compartir una configuración o exportar una tabla.

48.10 Actividades de práctica

  1. Representa la relación “divide a” sobre {1, 2, 3, 4, 6, 12} como matriz y como grafo dirigido. ¿Es reflexiva, antisimétrica o transitiva?
  2. Construye una función f: {0, 1, 2, 3} → {0, 1, 4, 9} definida por f(x) = x². Visualízala como diagrama y como puntos. ¿Es inyectiva y sobreyectiva?
  3. Modifica el mapa de calor para que las celdas de la diagonal tengan un color diferente. Explica qué propiedad estás haciendo visible.
  4. Añade a la red una arista F → A. ¿Qué ciclo aparece? Implementa una búsqueda en profundidad que lo detecte y resáltalo en el SVG.
  5. Diseña una versión accesible de una de las demostraciones: agrega una tabla textual sincronizada, foco visible y una descripción del estado seleccionado.

Qué debes recordar de este tema

Puntos clave
  • Una relación puede representarse como pares, tabla, matriz, diagrama de correspondencia o grafo.
  • La representación debe elegirse según la pregunta: las matrices muestran densidad y simetría; los grafos muestran caminos y conexiones.
  • Una función discreta se dibuja como puntos; unirlos requiere una justificación del modelo.
  • Las propiedades funcional, inyectiva, sobreyectiva y biyectiva pueden comprobarse algorítmicamente y comunicarse visualmente.
  • SVG es apropiado para gráficos vectoriales interactivos y accesibles; Canvas es conveniente para muchos puntos y dibujo frecuente.
  • Datos, análisis, vista e interacción deben mantenerse separados.
  • Escala, color, etiquetas, contraste y alternativas textuales forman parte de la exactitud de la visualización.

Conclusión

Visualizar relaciones y funciones es traducir una estructura matemática a una representación que podamos recorrer con la vista y con la interacción. El objetivo no es reemplazar la definición formal, sino hacer explícitas sus consecuencias: qué elementos se relacionan, cuántas imágenes tiene una entrada, si existe un camino, dónde aparece un ciclo o qué patrón tiene una matriz.

Cuando el modelo está separado de la vista, JavaScript permite cambiar entre diagramas, gráficas, matrices y redes sin perder rigor. La mejor visualización es la que permite formular una pregunta, encontrar la evidencia y volver a los datos originales para comprobarla.

Una relación bien visualizada no solo se ve: se puede explorar, verificar y explicar.