Facsímil 02 · Completo

Inteligencia clásica

Búsqueda, heurísticas, restricciones, planificación, juegos y conocimiento simbólico: la IA antes del deep learning, explicada desde problemas concretos.

Contenido disponible
12 de 12 capítulos listos
Contenido completo, pendiente de revisión editorial final.
Estado editorial
Completo
Lectura web generada desde los capítulos Markdown originales.

Sobre esta edición

Esta página se genera desde capítulos Markdown propios del facsímil. Las fórmulas se renderizan con KaTeX, los mapas con Mermaid y las notas al pie se mantienen junto al texto para leer el facsímil como una pieza autónoma, no como una exportación del taller.

Capítulo 01

Facsímil 2 · Inteligencia clásica

Capítulo 01: Búsqueda: resolver problemas como espacio de estados

Entrando en el tema

A mediados de los años cincuenta, Allen Newell, J. C. Shaw y Herbert Simon mostraron que un programa podía demostrar teoremas explorando sistemáticamente el espacio de posibles deducciones. Poco después formalizaron el General Problem Solver como intento de solucionador general mediante búsqueda en espacios de estados.1 No usaba redes neuronales. No usaba aprendizaje. Usaba búsqueda.

Siete décadas después, la búsqueda sigue siendo el corazón de sistemas que usas a diario. Un sistema de navegación puede encontrar rutas explorando un espacio donde cada estado es una ubicación y cada acción es una carretera. Un videojuego puede mover personajes con A*, un algoritmo de búsqueda de 1968. Y cuando diseñamos un agente LLM que decide qué herramienta llamar a continuación, podemos modelar esa decisión —de forma implícita y heurística— como un problema de búsqueda.

Este capítulo empieza por el principio: ¿qué es exactamente un problema de búsqueda? ¿Cómo se modela? ¿Y por qué algo tan simple es, al mismo tiempo, tan poderoso y tan peligrosamente costoso?

El vocabulario de la búsqueda

Todo problema de búsqueda empieza con cuatro ideas operativas: estado, acción, meta y coste.2 Luego, cuando lo escribimos con notación formal, esas ideas se descomponen un poco más para que no quede nada en el aire.

Estado

Una descripción suficiente de la situación actual. «Estoy en Madrid». «El robot está en la coordenada (3,7) mirando al norte». «El puzzle tiene las piezas en esta configuración».

El estado debe contener todo lo necesario para decidir qué hacer a continuación. Si falta información, el algoritmo tomará decisiones incorrectas. Piensa en el estado como una fotografía del problema en un instante: debe capturar todo lo relevante y nada de lo irrelevante.3

Un error clásico es incluir información redundante en el estado —«la temperatura ambiente», «el color del coche»— que no afecta a las decisiones pero multiplica el número de estados posibles. Cada bit innecesario en el estado duplica el espacio de búsqueda.

Acción

Una operación que transforma un estado en otro. «Viajar de Madrid a Barcelona» (coste: 620 km). «Avanzar una casilla hacia el norte» (coste: 1 paso). «Mover la pieza A a la posición B» (coste: 1 movimiento).

No todas las acciones están disponibles en todos los estados. Desde Madrid puedes viajar a Barcelona, pero no a Buenos Aires (no hay carretera). Esta restricción —llamada precondición— es lo que diferencia un problema bien modelado de uno imposible. Las acciones definen la topología del espacio de búsqueda: qué estados están conectados y a qué precio.4

Meta

La condición que queremos alcanzar. Puede ser un estado concreto («estar en Berlín») o una propiedad («tener todas las cajas en la zona de carga, da igual en qué orden»). La meta puede ser única o múltiple; puede ser un estado exacto o una condición abstracta.

Lo crucial es que la meta sea verificable. Dado un estado, debes poder responder «sí» o «no» a la pregunta «¿es este el objetivo?» sin ambigüedad. Si no puedes verificarlo, no puedes saber cuándo has terminado.5

Coste

El precio de cada acción o del camino completo. Distancia, tiempo, dinero, consumo de combustible, tokens de API: cualquier magnitud que queramos minimizar. El coste es lo que convierte «encuentra un camino cualquiera» en «encuentra el mejor camino».

Sin coste, cualquier camino sirve. Con coste, la búsqueda se convierte en optimización: no solo encontrar una solución, sino encontrar la mejor. Esta distinción —satisfacer vs optimizar— es una de las más importantes de la IA.6

La explosión combinatoria: por qué la búsqueda es difícil

El espacio de estados crece de forma aterradora. Imagina un problema donde cada estado tiene, de media, 10 acciones posibles (factor de ramificación b=10b = 10). A profundidad 1, tienes 10 estados. A profundidad 2, 100. A profundidad 5, 100 000. A profundidad 10, diez mil millones.7

La forma compacta de verlo es esta:

N(d)=i=0dbi=bd+11b1N(d) = \sum_{i=0}^{d} b^i = \frac{b^{d+1} - 1}{b - 1}
SímboloSignificadoEjemplo
N(d)N(d)Número total de nodos que aparecen hasta profundidad dd, contando la raíz.Si exploramos hasta profundidad 5, N(5)N(5).
bbFactor de ramificación medio: cuántas acciones nuevas aparecen desde cada estado.b=10b = 10.
ddProfundidad máxima explorada: cuántas acciones tiene el camino más largo considerado.d=5d = 5.
iiNivel concreto del árbol de búsqueda.i=0i = 0 es el estado inicial; i=5i = 5, los estados a cinco acciones.

Con números:

N(5)=1+10+100+1000+10000+100000=111111N(5) = 1 + 10 + 100 + 1\,000 + 10\,000 + 100\,000 = 111\,111

Cinco decisiones encadenadas ya generan más de cien mil nodos. Con profundidad 10:

N(10)=101119=11111111111N(10) = \frac{10^{11} - 1}{9} = 11\,111\,111\,111

Más de once mil millones. Por eso no basta con decir «probemos todas las opciones». La búsqueda clásica consiste, en buena medida, en decidir qué opciones no merece la pena mirar.

Esto es la explosión combinatoria: el número de estados crece exponencialmente con la profundidad. No es un problema de hardware: aunque tuvieras un ordenador mil millones de veces más rápido, solo podrías explorar unos pocos niveles adicionales. La explosión combinatoria es el obstáculo central de la búsqueda.

Por eso los algoritmos de búsqueda no intentan explorar todo el espacio. Usan la frontera para decidir qué explorar a continuación, ignorando la mayor parte del espacio. La diferencia entre un algoritmo que encuentra la solución en segundos y uno que no la encuentra nunca está en cómo gestiona esa frontera.

Árbol de búsqueda vs grafo de estados

Aquí hay una distinción sutil pero crítica. El grafo de estados es el mapa real: todas las configuraciones posibles y cómo se conectan. Es la realidad física del problema. El árbol de búsqueda es lo que el algoritmo construye mientras explora: un registro de los caminos que ha probado.8

Imagina un laberinto. El grafo de estados es el laberinto completo —cada casilla es un estado, cada pasillo es una acción—. El árbol de búsqueda es el recorrido que haces al explorar: empiezas en la entrada, pruebas un pasillo, vuelves atrás si no lleva a ningún sitio, pruebas otro. El árbol crece a medida que avanzas, pero nunca ves el grafo completo. Si lo vieras, ya habrías resuelto el problema.

¿Por qué importa esta diferencia? Porque el grafo puede tener ciclos: puedes ir de A a B y de B a A, dando vueltas. El árbol, si no tienes cuidado, puede crecer infinitamente reflejando esos ciclos una y otra vez. Los buenos algoritmos de búsqueda mantienen un conjunto de estados visitados y evitan reexplorarlos. Sin esta precaución, BFS y UCS pueden quedar atrapados en bucles infinitos.9

Cómo funciona un algoritmo de búsqueda

Todos los algoritmos de búsqueda clásicos comparten la misma estructura.10 Mantienen una frontera: el conjunto de estados que han sido descubiertos pero aún no explorados. El bucle es:

  1. Extraer un estado de la frontera.
  2. Comprobar si es la meta. Si lo es, reconstruir el camino y terminar.
  3. Expandir: generar todos los estados alcanzables desde este estado mediante las acciones disponibles.
  4. Añadir los nuevos estados a la frontera, siempre que no hayan sido visitados antes.
  5. Repetir desde el paso 1.

Eso es todo. Cuatro pasos y un bucle. La diferencia entre BFS, DFS, coste uniforme, greedy y A* está exclusivamente en el paso 1: qué estado extraemos de la frontera. La estructura de datos que usemos —cola, pila, cola de prioridad— determina completamente el comportamiento del algoritmo.

Anatomía de un problema de búsqueda Diagrama del bucle de búsqueda: modelo del problema, frontera, nodo extraído, prueba de meta, expansión, visitados y coste acumulado. Anatomía de un problema de búsqueda un mismo bucle; cambia la política con la que eliges el siguiente nodo de la frontera MODELO DEL PROBLEMA s0 S estados A(s) acciones f(s,a) G metas c(s,a) MOTOR DE BÚSQUEDA Frontera nodos descubiertos, todavía no expandidos s3 g=315 h=300 s7 g=420 h=180 s2 g=510 h=90 1. EXTRAER n = s3 la estructura decide: FIFO, LIFO, g o g+h 2. PROBAR META n ∈ G? 3. EXPANDIR A(s3) → {s8, s9, s10} aplicar f(s,a), calcular coste y filtrar ciclos VISITADOS {s0, s1, s2} evita repetir estados y bucles COSTE g(n)=Σ c(si,ai) permite elegir mejor camino, no solo alguno SOLUCIÓN no nuevos nodos IA para gente curiosa / Facsímil 02 / Capítulo 01 / 686f6c61

Definición formal del problema

Conviene fijar la notación con precisión. Un problema de búsqueda se define formalmente como una tupla:11

Problema=(S,A,f,s0,G,c)\text{Problema} = (S, A, f, s_0, G, c)
SímboloSignificadoEjemplo
SSEspacio de estados: conjunto de todas las configuraciones posibles.En un mapa, todos los cruces y ciudades que podrían visitarse.
A(s)A(s)Acciones aplicables desde el estado ss.Desde Zaragoza, tomar la carretera hacia Barcelona o hacia Madrid.
f(s,a)f(s, a)Función de transición: el estado que aparece al aplicar una acción.f(Zaragoza,ir a Barcelona)=Barcelonaf(\text{Zaragoza}, \text{ir a Barcelona}) = \text{Barcelona}.
s0s_0Estado inicial.Madrid.
GGConjunto de estados meta.{Barcelona}\{\text{Barcelona}\}.
c(s,a)c(s, a)Coste de aplicar la acción aa en el estado ss.Kilómetros, minutos, euros o tokens consumidos.

La fórmula dice algo bastante sencillo: para resolver el problema necesitamos saber dónde podemos estar, qué podemos hacer, qué ocurre al hacerlo, dónde empezamos, qué cuenta como llegar y cuánto cuesta cada paso. Si falta una de esas piezas, la búsqueda queda coja.

Una solución es una secuencia de acciones:

π=(a1,a2,,an)\pi = (a_1, a_2, \ldots, a_n)

La letra π\pi se lee «pi» y aquí representa un plan: una lista ordenada de acciones. No es todavía «la mejor» solución; solo es una candidata. Para comprobar si realmente sirve, aplicamos cada acción una detrás de otra:

si=f(si1,ai),i=1,2,,ns_i = f(s_{i-1}, a_i), \quad i = 1, 2, \ldots, n
SímboloSignificadoEjemplo
π\piPlan o secuencia de acciones.(MadridZaragoza,ZaragozaBarcelona)(\text{Madrid} \to \text{Zaragoza}, \text{Zaragoza} \to \text{Barcelona}).
aia_iAcción número ii del plan.a1=a_1 = ir de Madrid a Zaragoza.
sis_iEstado alcanzado después de ejecutar ii acciones.s1=s_1 = Zaragoza; s2=s_2 = Barcelona.
ffFunción de transición que calcula el siguiente estado.Aplicar «ir a Zaragoza» desde Madrid produce Zaragoza.
nnNúmero total de acciones del plan.n=2n = 2.

El plan es una solución si el último estado pertenece al conjunto de metas:

snGs_n \in G

En nuestro ejemplo, s2=Barcelonas_2 = \text{Barcelona} y G={Barcelona}G = \{\text{Barcelona}\}. Por tanto, el plan llega a la meta.

Ahora falta saber cuánto cuesta. El coste total de un plan es la suma de los costes de cada acción:

C(π)=i=1nc(si1,ai)C(\pi) = \sum_{i=1}^{n} c(s_{i-1}, a_i)
SímboloSignificadoEjemplo
C(π)C(\pi)Coste total del plan π\pi.Kilómetros totales recorridos.
c(si1,ai)c(s_{i-1}, a_i)Coste de ejecutar la acción aia_i desde el estado anterior.c(Madrid,ir a Zaragoza)=315c(\text{Madrid}, \text{ir a Zaragoza}) = 315 km.
iiÍndice de la acción dentro del plan.i=1i = 1 para el primer tramo; i=2i = 2 para el segundo.
nnNúmero de acciones del plan.n=2n = 2.

Con números:

C(π)=315+300=615C(\pi) = 315 + 300 = 615

Si existe otro plan Madrid → Valencia → Barcelona con coste 720720, ambos llegan a la meta, pero el primero es mejor. Una solución es óptima si minimiza C(π)C(\pi) entre todas las soluciones posibles.

Esta formalización permite razonar sobre propiedades como la completitud (¿el algoritmo siempre encuentra solución si existe?), la optimalidad (¿encuentra la mejor?) y la complejidad (¿cuánto tarda y cuánta memoria consume en función del tamaño del problema?).12

Búsqueda no informada vs informada

Los algoritmos de búsqueda se dividen en dos familias, y la línea que las separa es la información disponible:

No informados (ciegos). No tienen ninguna pista sobre qué acciones son mejores. Solo conocen el coste de las acciones ya realizadas y la definición de la meta. Son como explorar un laberinto a oscuras, tanteando las paredes. BFS, DFS y coste uniforme pertenecen a esta familia. Su gran ventaja es que no necesitan conocimiento específico del dominio: funcionan para cualquier problema bien definido. Su gran desventaja es la ineficiencia: exploran a ciegas, sin priorizar.13

Informados (heurísticos). Disponen de una función heurística h(n)h(n) que estima lo lejos que está un estado de la meta. Es una estimación diseñada para ser barata de calcular y suficientemente informativa para ordenar la búsqueda; no sustituye al coste real ni a la prueba de optimalidad. Greedy y A* usan heurísticas para priorizar estados prometedores. Su gran ventaja es la eficiencia: pueden encontrar soluciones explorando órdenes de magnitud menos estados. Su gran desventaja es que necesitan una buena heurística, y diseñar una heurística admisible —que nunca sobreestime el coste real— no siempre es fácil.14

El resto de este bloque de búsqueda se estructura alrededor de esta división: el capítulo 2 explora los algoritmos ciegos; el capítulo 3, los informados; y el capítulo 4 tiende el puente hacia los agentes modernos.

En el día a día

La búsqueda en espacios de estados no es una reliquia académica. Aparece en sistemas reales constantemente:

  • Navegación GPS: encontrar una ruta útil entre dos puntos. Cada cruce puede modelarse como un estado. Cada calle es una acción con un coste, normalmente distancia, tiempo o una combinación de ambas. A* y sus variantes ayudan porque una heurística geométrica permite mirar antes las rutas prometedoras, aunque los sistemas reales añaden tráfico, restricciones de giro, cierres, peajes y optimizaciones de ingeniería.15
  • Planificación logística: una empresa con 50 paquetes y 5 furgonetas. El espacio de estados es astronómico —combinatorio, con un factor de ramificación enorme— y sin embargo los algoritmos de búsqueda heurística encuentran soluciones casi óptimas en segundos. La diferencia entre una ruta óptima y una subóptima son miles de euros al mes en combustible.
  • Agentes LLM: cuando un agente decide si llamar a search_database o a check_calendar, podemos leer esa decisión como una evaluación de acciones en un espacio de estados implícito. El LLM puede actuar como heurística: «dado el contexto actual, ¿qué herramienta parece más prometedora?». El sistema alrededor debe añadir costes, permisos, observación y criterio de parada.

Antes del algoritmo: auditar el modelo

Un error muy común es discutir si usar BFS, A* o una heurística sofisticada antes de haber comprobado que el problema está bien definido. En ingeniería, el primer paso no es elegir algoritmo: es validar el contrato de búsqueda.

PreguntaQué compruebaFallo típico
¿s0s_0 pertenece a SS?Que el estado inicial existe en el modelo.Arrancar desde un identificador que no está en el grafo.
¿GSG \subseteq S?Que todas las metas son estados válidos.Definir como meta una etiqueta textual que ninguna transición alcanza.
¿Toda acción tiene origen, destino y coste?Que f(s,a)f(s,a) y c(s,a)c(s,a) están definidos.Acción sin coste o transición a estado inexistente.
¿Los costes son no negativos?Que UCS y A* puedan razonar correctamente.Costes negativos que rompen garantías de optimalidad.
¿Hay ciclos?Que el algoritmo necesitará visitados.Madrid → Zaragoza → Madrid repitiéndose para siempre.
¿Cuál es bb y hasta qué profundidad buscarías?Estimación de explosión combinatoria.Descubrir tarde que bdb^d no cabe en memoria.

Esta auditoría parece humilde, pero es exactamente el tipo de trabajo que evita sistemas frágiles. Si el contrato está mal, el algoritmo puede estar perfectamente implementado y aun así devolver basura.

Un plan candidato también se puede comprobar antes de hablar de optimalidad:

vaˊlido(π)s0a1s1a2ansnsnG\text{válido}(\pi) \Leftrightarrow s_0 \xrightarrow{a_1} s_1 \xrightarrow{a_2} \cdots \xrightarrow{a_n} s_n \land s_n \in G

Y su coste se compara con otros planes:

C(π)=i=1nc(si1,ai)C(\pi) = \sum_{i=1}^{n} c(s_{i-1}, a_i)

Una práctica útil es mantener en tus sistemas una salida trazable: qué estados se recorrieron, qué acción llevó a cada estado, qué coste se acumuló y por qué el plan termina o no en meta. Eso conecta este capítulo con planificación, agentes y evaluación: no basta con “llegó”; hay que poder explicar cómo.

Por qué debería importarte

La búsqueda es el paradigma más antiguo de la IA y, paradójicamente, uno de los más vigentes. No ha sido sustituido por el deep learning: ha sido aumentado por él. Los LLMs no reemplazan la búsqueda; la hacen más inteligente, proporcionando heurísticas donde antes había que diseñarlas a mano.

Entender la búsqueda te da un marco mental para razonar sobre problemas secuenciales: aquellos donde la solución no es una respuesta única, sino una secuencia de decisiones. Y te prepara para los capítulos siguientes: sin entender el vocabulario de estados, acciones y fronteras, no puedes entender CSP, planificación ni juegos. Todo el facsímil 2 se construye sobre este capítulo.

Dónde solía tropezar yo

ErrorPor qué es un errorAntídoto
Confundir el grafo de estados con el árbol de búsquedaEl grafo es el mapa completo; el árbol es lo que el algoritmo explora. Tratar el árbol como si fuera el grafo lleva a reexplorar estados innecesariamente y a no detectar ciclos.Mantén un conjunto visited y nunca reexpandas un estado ya visitado. Es la optimización más rentable en búsqueda.
No definir bien el estadoSi el estado no contiene toda la información necesaria para decidir la siguiente acción, el algoritmo tomará decisiones basadas en información incompleta.Pregúntate: «con esta información, ¿puedo generar todas las acciones posibles y evaluar si he llegado a la meta?». Si la respuesta es no, tu estado está incompleto.
Subestimar la explosión combinatoriaUn espacio con b=10 y d=10 tiene 10^10 estados. Explorarlos todos es inviable en cualquier hardware. La búsqueda ciega solo funciona para espacios pequeños.Calcula b y d antes de elegir algoritmo. Si b^d es mayor que unos pocos millones, necesitas una heurística o una poda.
Olvidar el costeSin coste, cualquier camino sirve. Con costes variables, el camino más corto en pasos no es necesariamente el más barato. BFS encuentra el primero; UCS encuentra el mejor.Define el coste de cada acción. Si los costes no son uniformes, usa UCS o A*, no BFS.

Manos a la obra

La práctica real de este capítulo está en kit descargable. El kit valida un problema de rutas como tupla de búsqueda, calcula factor de ramificación, detecta ciclos, estima explosión combinatoria y evalúa planes candidatos.

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/audit_search_problem.py --write
cat output/search_model_decision.md

Qué deberías ver. El informe distingue tres cosas: si el modelo del problema es válido, qué planes candidatos llegan a meta y qué coste tiene cada uno. También marca por qué un plan puede ser inválido: acción inexistente, transición imposible o final fuera de GG.

ArchivoPapel
data/search_problem.jsonEstados, acciones, estado inicial, metas y planes candidatos.
contracts/search_policy.jsonUmbrales de explosión combinatoria y reglas de validación.
ops/audit_search_problem.pyAuditor ejecutable sin dependencias externas.
output/search_model_report.jsonResultado estructurado para revisar o automatizar.
output/search_model_decision.mdInforme legible para entregar.

Cómo lo adaptas a tu caso. Cambia las ciudades por estados de un flujo real: pasos de onboarding, estados de un pedido, pantallas de una app, acciones de un agente o rutas de logística. Después añade dos planes: uno que llegue a meta y otro que falle. La entrega interesante no es que el plan “funcione”: es que puedas explicar por qué funciona.

Puedes complementar el kit con recursos visuales:

  • Pathfinding visualizer: dibuja obstáculos, elige BFS, DFS o A* y observa cómo cada algoritmo explora el espacio de estados de forma radicalmente distinta. La diferencia visual entre BFS (explora en ondas concéntricas) y DFS (se lanza por un camino hasta el fondo) es imposible de transmitir solo con texto.
  • Ejercicio mental: modela el problema de «ir de tu casa al trabajo» como un espacio de estados. Define el estado, las acciones, la meta y el coste. ¿Cuál es el factor de ramificación aproximado? ¿Qué profundidad tiene una solución típica? ¿Qué algoritmo usarías?

Qué entregaría un alumno. El Markdown generado, una versión propia de search_problem.json, un plan válido, un plan inválido explicado y una estimación honesta de si el espacio de búsqueda es pequeño, manejable o explosivo.

Cómo encaja todo

Este mapa se lee de izquierda a derecha: primero defines el problema, después eliges cómo gestionar la frontera, y solo entonces aparecen las garantías de completitud, optimalidad y coste. Los capítulos siguientes cambian la política de frontera, añaden heurísticas o convierten estados en asignaciones, planes y decisiones con otros actores.

La conexión con sistemas modernos no es decorativa: un agente con herramientas también necesita estado, acciones, coste, meta y trazabilidad. Cambia la forma de representar el problema, pero no desaparece el patrón.

graph TD
    subgraph "Capítulo 1: Fundamentos de búsqueda"
        direction TB
        PROBLEMA["Problema = (S, A, f, s₀, G, c)"]
        S_ESPACIO["S: espacio de estados<br/>finito o infinito, discreto o continuo"]
        A_ACCIONES["A(s): acciones aplicables en s<br/>f: S × A → S (función de transición)"]
        S0_INICIAL["s₀ ∈ S: estado inicial"]
        G_META["G ⊆ S: conjunto de estados meta"]
        C_COSTE["c: S × A → ℝ⁺: función de coste"]
        SOLUCION["Solución: secuencia (a₁,…,aₙ) tal que<br/>s₀ →^a₁ s₁ →^a₂ … →^aₙ sₙ ∈ G"]
        OPTIMA["Solución óptima: minimiza Σ c(sᵢ, aᵢ₊₁)"]
    end
    subgraph "Propiedades formales"
        COMPLETITUD[Completitud: ¿encuentra solución si existe?]
        OPTIMALIDAD[Optimalidad: ¿encuentra la de menor coste?]
        COMPLEJIDAD["Complejidad: O(b^d) tiempo, O(b·d) espacio"]
        ADMISIBILIDAD["Admisibilidad: h(s) ≤ h*(s) ∀s"]
    end
    subgraph "Frontera: el núcleo algorítmico"
        FRONTERA[Frontera: estados descubiertos, no expandidos]
        COLA["Cola FIFO → BFS: O(b^d)"]
        PILA["Pila LIFO → DFS: O(b·d)"]
        PRIORIDAD["Cola prioridad por g → UCS"]
        HEURISTICA["Cola prioridad por g+h → A*"]
    end
    subgraph "Conexiones en el facsímil 2"
        CSP["CSP: variables + restricciones<br/>la búsqueda con backtracking"]
        PLANIFICACION["Planificación: PDDL<br/>acciones con precondiciones y efectos"]
        JUEGOS["Juegos: minimax, MCTS<br/>búsqueda con otros actores"]
    end
    subgraph "Conexiones modernas"
        AGENTES_LLM["Agentes LLM: búsqueda implícita<br/>el modelo como heurística aprendida"]
        RAG["RAG: retrieval = búsqueda<br/>en espacio de documentos"]
    end

    PROBLEMA --> S_ESPACIO
    PROBLEMA --> A_ACCIONES
    PROBLEMA --> S0_INICIAL
    PROBLEMA --> G_META
    PROBLEMA --> C_COSTE
    S_ESPACIO --> SOLUCION
    A_ACCIONES --> SOLUCION
    S0_INICIAL --> SOLUCION
    G_META --> SOLUCION
    SOLUCION --> OPTIMA
    C_COSTE --> OPTIMA
    SOLUCION -->|"se encuentra mediante"| FRONTERA
    FRONTERA -->|"implementada como"| COLA
    FRONTERA -->|"implementada como"| PILA
    FRONTERA -->|"implementada como"| PRIORIDAD
    FRONTERA -->|"implementada como"| HEURISTICA
    COLA -->|"garantiza"| COMPLETITUD
    PRIORIDAD -->|"garantiza"| OPTIMALIDAD
    HEURISTICA -->|"con h admisible"| OPTIMALIDAD
    HEURISTICA -->|"requiere"| ADMISIBILIDAD
    COLA -->|"complejidad"| COMPLEJIDAD
    PILA -->|"complejidad"| COMPLEJIDAD
    COMPLETITUD -->|"hereda"| CSP
    OPTIMALIDAD -->|"extiende a"| PLANIFICACION
    FRONTERA -->|"fundamento de"| JUEGOS
    HEURISTICA -->|"inspira"| AGENTES_LLM
    COLA -->|"análogo a"| RAG

    style PROBLEMA fill:#F5F5F5,stroke:#000000,stroke-width:2
    style FRONTERA fill:#F5F5F5,stroke:#000000,stroke-width:2
    style HEURISTICA fill:#F5F5F5,stroke:#000000,stroke-width:2
    style CSP stroke-dasharray: 5 5
    style PLANIFICACION stroke-dasharray: 5 5
    style JUEGOS stroke-dasharray: 5 5
    style AGENTES_LLM stroke-dasharray: 5 5
    style RAG stroke-dasharray: 5 5

Vocabulario aprendido

TérminoDefinición
EstadoDescripción suficiente de la situación actual del problema en un momento dado.
Espacio de estadosConjunto de todas las configuraciones posibles que puede alcanzar el problema.
Árbol de búsquedaEstructura que el algoritmo construye al explorar, donde cada nodo es un estado y cada rama una acción.
FronteraConjunto de estados descubiertos pero aún no explorados. Su estructura determina el algoritmo.
Factor de ramificaciónNúmero medio de acciones disponibles en cada estado. Determina la explosión combinatoria.
HeurísticaFunción que estima la distancia de un estado a la meta, guiando la búsqueda informada.
Contrato de búsquedaDefinición verificable de estados, acciones, transición, estado inicial, metas y costes.
Plan candidatoSecuencia de acciones que debe poder ejecutarse desde s0s_0 y terminar en GG para ser solución.
Estado visitadoEstado ya revisado para evitar ciclos y reexpansiones innecesarias.

Antes de pasar página

  • ¿Puedo definir los cuatro ingredientes de un problema de búsqueda y poner un ejemplo concreto de cada uno? (Si no, vuelve a «El vocabulario de la búsqueda».)
  • ¿Entiendo por qué la explosión combinatoria hace que la búsqueda ciega sea inviable para espacios grandes? (Si no, vuelve a «La explosión combinatoria».)
  • ¿Sé diferenciar el grafo de estados del árbol de búsqueda y explicar por qué importa la diferencia? (Si no, vuelve a «Árbol de búsqueda vs grafo de estados».)
  • ¿Puedo explicar el bucle genérico de un algoritmo de búsqueda? (Si no, vuelve a «Cómo funciona un algoritmo de búsqueda».)
  • ¿Entiendo la diferencia entre búsqueda no informada e informada? (Si no, vuelve a «Búsqueda no informada vs informada».)
  • ¿Puedo auditar si un problema está bien definido antes de elegir algoritmo? (Si no, vuelve a «Antes del algoritmo: auditar el modelo».)
  • ¿He ejecutado kit descargable y puedo explicar un plan válido y uno inválido? (Si no, vuelve a «Manos a la obra».)

En resumen

Idea fuerzaDetalle
Todo problema de búsqueda se define con estados, acciones, meta y coste.Si no puedes definir estos cuatro elementos, no tienes un problema de búsqueda. Si tu estado contiene información irrelevante, tu espacio de búsqueda explota innecesariamente.
La explosión combinatoria es el obstáculo central.El espacio crece exponencialmente con la profundidad. Más hardware ayuda poco si el modelo explora ramas inútiles. La defensa es modelar mejor, podar, usar heurísticas y medir costes.
La frontera es el corazón del algoritmo.Qué estado extraes de la frontera determina si estás haciendo BFS, DFS, UCS o A*. Todo lo demás es el mismo bucle.
El contrato del problema va antes del algoritmo.Si estados, acciones, transición, meta o coste están mal definidos, ningún algoritmo arregla el modelo.
La búsqueda no ha muerto: ha evolucionado.Los LLMs no reemplazan la búsqueda; pueden aportar heurísticas aprendidas dentro de sistemas con estado, acciones, validación y trazas. El patrón viene de la IA clásica.

Para saber más

Hart, P. E., Nilsson, N. J. y Raphael, B. (1968). A formal basis for the heuristic determination of minimum cost paths. IEEE Transactions on Systems Science and Cybernetics, 4(2), 100-107. https://doi.org/10.1109/TSSC.1968.300136

Luger, G. F. (2008). Artificial intelligence: structures and strategies for complex problem solving (6.ª ed.). Pearson.

Newell, A., Shaw, J. C. y Simon, H. A. (1959). Report on a general problem-solving program. En Proceedings of the International Conference on Information Processing (pp. 256-264). UNESCO.

Nilsson, N. J. (1998). Artificial intelligence: a new synthesis. Morgan Kaufmann.

Pearl, J. (1984). Heuristics: intelligent search strategies for computer problem solving. Addison-Wesley.

Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press.

Rich, E., Knight, K. y Nair, S. B. (2009). Artificial intelligence (3.ª ed.). McGraw-Hill.

Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. https://aima.cs.berkeley.edu/

Notas

  1. Newell, A., Shaw, J. C. y Simon, H. A. (1959). Report on a general problem-solving program. En Proceedings of the International Conference on Information Processing (pp. 256-264). UNESCO.

  2. Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. Los capítulos 3 y 4 abordan la resolución de problemas mediante búsqueda, estableciendo el marco conceptual de estados, acciones, metas y costes que sigue siendo la base de la IA moderna.

  3. Nilsson, N. J. (1998). Artificial intelligence: a new synthesis. Morgan Kaufmann. El capítulo 7 presenta los fundamentos de la búsqueda en espacios de estados, incluyendo la distinción entre búsqueda ciega y búsqueda heurística.

  4. Rich, E., Knight, K. y Nair, S. B. (2009). Artificial intelligence (3.ª ed.). McGraw-Hill. El capítulo 2 describe cómo modelar problemas como espacios de estados, enfatizando la importancia de definir correctamente las precondiciones de cada acción.

  5. Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press. La sección 3.3 analiza cómo definir metas verificables y su papel en la terminación correcta de los algoritmos de búsqueda.

  6. Luger, G. F. (2008). Artificial intelligence: structures and strategies for complex problem solving (6.ª ed.). Pearson. El capítulo 3 desarrolla la distinción entre búsqueda de cualquier solución y búsqueda de la solución óptima, y cómo el coste transforma el problema.

  7. Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. La sección 3.3 introduce el concepto de complejidad de la búsqueda y analiza cómo el factor de ramificación y la profundidad determinan la viabilidad de los algoritmos.

  8. Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. La sección 3.3 detalla la diferencia entre el grafo de estados y el árbol de búsqueda.

  9. Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press. El capítulo 3 aborda la detección de ciclos como una optimización crítica para la viabilidad práctica de los algoritmos de búsqueda.

  10. Nilsson, N. J. (1998). Artificial intelligence: a new synthesis. Morgan Kaufmann. El capítulo 7 presenta un marco unificado donde la única diferencia entre algoritmos es la política de extracción de la frontera.

  11. Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. La sección 3.1 introduce la definición formal del problema de búsqueda, incluyendo la notación de espacios de estados, función de transición, y función de coste.

  12. Pearl, J. (1984). Heuristics: intelligent search strategies for computer problem solving. Addison-Wesley. El capítulo 2 formaliza las propiedades de los algoritmos de búsqueda en términos de completitud, admisibilidad y optimalidad.

  13. Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. La sección 3.4 clasifica los algoritmos de búsqueda no informada y analiza sus propiedades de completitud, optimalidad y complejidad.

  14. Pearl, J. (1984). Heuristics: intelligent search strategies for computer problem solving. Addison-Wesley. Pearl estableció las bases teóricas de la búsqueda heurística, incluyendo las propiedades de admisibilidad y consistencia que garantizan la optimalidad de A*, y el concepto de poder heurístico que permite comparar la eficiencia de distintas heurísticas.

  15. Hart, P. E., Nilsson, N. J. y Raphael, B. (1968). A formal basis for the heuristic determination of minimum cost paths. IEEE Transactions on Systems Science and Cybernetics, 4(2), 100-107. https://doi.org/10.1109/TSSC.1968.300136.

Capítulo 02

Facsímil 2 · Inteligencia clásica

Capítulo 02: BFS, DFS y coste uniforme: los algoritmos ciegos

Entrando en el tema

En el capítulo anterior definiste el problema: estados, acciones, meta y coste. Construiste el vocabulario. Ahora necesitas algoritmos que resuelvan ese problema sin pistas del dominio y sin función heurística. A ciegas.

Tres algoritmos compiten por el título de «mejor búsqueda ciega». Los tres usan exactamente el mismo bucle —extraer, comprobar, expandir, añadir—. La única diferencia entre ellos es la estructura de datos de la frontera.1 Una cola produce BFS. Una pila produce DFS. Una cola de prioridad produce UCS. El resto es el mismo código.

Este capítulo desmenuza los tres. Con pseudocódigo. Con análisis de complejidad. Con ejemplos trazados paso a paso. Porque si no entiendes por qué BFS consume memoria exponencial y DFS puede perderse para siempre, no entenderás por qué A* —el algoritmo del próximo capítulo— fue una revolución.

El bucle genérico

Antes de entrar en cada algoritmo, fijemos el pseudocódigo común.2 Los tres algoritmos ejecutan exactamente esto:

función BÚSQUEDA(problema):
    frontera ← [s₀]                    // estructura depende del algoritmo
    visitados ← {s₀}
    
    mientras frontera no esté vacía:
        s ← EXTRAER(frontera)          // ← aquí está toda la diferencia
        si ES-META(s):
            return RECONSTRUIR-CAMINO(s)
        para cada acción a en A(s):
            s' ← f(s, a)
            si s' ∉ visitados:
                visitados ← visitados ∪ {s'}
                AÑADIR(frontera, s')
    
    return FRACASO

La línea s ← EXTRAER(frontera) es la única que cambia entre algoritmos.3 En BFS, EXTRAER es dequeue (el primero que entró). En DFS, es pop (el último que entró). En UCS, es extract-min (el de menor coste). Tres implementaciones. Tres comportamientos radicalmente distintos.

La forma matemática de decirlo es: en cada iteración elegimos un nodo de la frontera según una política π\pi:

nt=extraerπ(Ft)n_t = \operatorname{extraer}_{\pi}(F_t)
SímboloSignificadoEjemplo
FtF_tFrontera en el instante tt: nodos descubiertos pero no expandidos.[B,C,D][B, C, D].
ntn_tNodo elegido para expandir en la iteración tt.En BFS sería BB; en DFS podría ser DD.
π\piPolítica de extracción de la frontera.FIFO, LIFO o menor coste g(n)g(n).
extraerπ\operatorname{extraer}_{\pi}Operación que aplica esa política.dequeue, pop o extract-min.

Y el resto del bucle actualiza frontera y visitados:

Ft+1=(Ft{nt})(Succ(nt)Vt)F_{t+1} = \left(F_t \setminus \{n_t\}\right) \cup \left(\operatorname{Succ}(n_t) \setminus V_t\right)
SímboloSignificadoEjemplo
Succ(nt)\operatorname{Succ}(n_t)Sucesores generados al expandir ntn_t.Si nt=Bn_t=B, quizá {D,E}\{D,E\}.
VtV_tEstados ya visitados antes de la iteración tt.{A,B}\{A,B\}.
\setminusDiferencia de conjuntos: quitar elementos ya presentes.No reañadir estados visitados.

Así que los tres algoritmos se reducen a tres políticas:

πBFS=FIFO,πDFS=LIFO,πUCS(n)=argminnFg(n)\pi_{\text{BFS}} = \text{FIFO}, \qquad \pi_{\text{DFS}} = \text{LIFO}, \qquad \pi_{\text{UCS}}(n) = \arg\min_{n \in F} g(n)

BFS: explorar por niveles

Algoritmo

BFS usa una cola (FIFO: first in, first out). Cuando expandimos un estado a profundidad dd, sus sucesores se añaden al final de la cola, detrás de todos los estados de profundidad dd que aún no se han expandido. El resultado es una exploración por niveles concéntricos.4

Frontera: [A]           → dequeue A, enqueue(B, C)
Frontera: [B, C]        → dequeue B, enqueue(D, E)
Frontera: [C, D, E]     → dequeue C, enqueue(F)
Frontera: [D, E, F]     → ...

Propiedades formales

Para un espacio de búsqueda con factor de ramificación bb y profundidad de la solución más superficial dd:5

PropiedadValorExplicación
CompletitudSí (si bb es finito)Si existe solución, BFS la encuentra porque explora sistemáticamente todos los nodos por niveles.
OptimalidadSí (si coste = 1)BFS encuentra el camino con menos pasos porque el primer nodo meta que descubre está a la profundidad mínima.
TiempoO(bd)O(b^d)En el peor caso, explora todos los nodos hasta profundidad dd. Con b=10,d=10b=10, d=10: 101010^{10} expansiones.
EspacioO(bd)O(b^d)Almacena todos los nodos del nivel actual en la frontera. Este es su talón de Aquiles.

El conteo de nodos de BFS sale de la suma de niveles del árbol:

NBFS(d)=i=0dbi=bd+11b1N_{\text{BFS}}(d) = \sum_{i=0}^{d} b^i = \frac{b^{d+1}-1}{b-1}
SímboloSignificadoEjemplo
NBFS(d)N_{\text{BFS}}(d)Nodos generados hasta profundidad dd.Si d=6d=6, todos los niveles de 0 a 6.
bbFactor de ramificación medio.b=10b=10.
ddProfundidad de la solución más superficial.d=6d=6.
iiNivel del árbol de búsqueda.i=0i=0 es el estado inicial.

Con b=10b=10 y d=6d=6:

NBFS(6)=1+10+102+103+104+105+106=1111111N_{\text{BFS}}(6) = 1 + 10 + 10^2 + 10^3 + 10^4 + 10^5 + 10^6 = 1\,111\,111

La memoria se aproxima por el tamaño del nivel más profundo que queda en la frontera:

MBFS(d)bdM_{\text{BFS}}(d) \approx b^d

Con b=10b=10 y d=12d=12, BFS puede necesitar almacenar alrededor de 101210^{12} nodos. A 1 KB por nodo, eso ronda 101510^{15} bytes: aproximadamente 1 PB, no “un ordenador grande”. Imposible para la mayoría de problemas reales.6

DFS: lanzarse en profundidad

Algoritmo

DFS usa una pila (LIFO: last in, first out). Cuando expandimos un estado, sus sucesores se colocan en el tope de la pila, y el algoritmo explora inmediatamente el que queda arriba. El resultado es una inmersión profunda por la primera rama disponible.7

Convención: el tope de la pila está a la izquierda.

Frontera: [A]           → pop A, push(C), push(B)
Frontera: [B, C]        → pop B (tope de la pila), push(E), push(D)
Frontera: [D, E, C]     → pop D
Frontera: [E, C]        → ...

DFS es inherentemente recursivo. De hecho, la implementación más natural de DFS es recursiva, sin frontera explícita:

función DFS-RECURSIVO(s, visitados):
    si ES-META(s): return s
    visitados ← visitados ∪ {s}
    para cada acción a en A(s):
        s' ← f(s, a)
        si s' ∉ visitados:
            resultado ← DFS-RECURSIVO(s', visitados)
            si resultado ≠ FRACASO: return resultado
    return FRACASO

La pila de llamadas de la recursión es la frontera. Cada llamada anidada es un paso más en profundidad.8

Propiedades formales

PropiedadValorExplicación
CompletitudNo (sin límite)En espacios infinitos, DFS puede perderse por una rama infinita sin retroceder nunca. Con límite de profundidad, es completo.
OptimalidadNoEncuentra el primer camino, no el más corto. Puede devolver uno de 50 pasos cuando existe uno de 3.
TiempoO(bm)O(b^m)mm es la profundidad máxima. Peor que BFS si mdm \gg d.
EspacioO(bm)O(b \cdot m)Solo almacena el camino actual y sus hermanos no explorados. Esta es su gran ventaja.

La diferencia entre tiempo y memoria se ve mejor separando las dos fórmulas:

TDFS(m)=O(bm)T_{\text{DFS}}(m) = O(b^m) MDFS(m)=O(bm)M_{\text{DFS}}(m) = O(b \cdot m)
SímboloSignificadoEjemplo
TDFS(m)T_{\text{DFS}}(m)Trabajo máximo si DFS baja hasta profundidad mm.Puede ser enorme si la rama mala es muy profunda.
MDFS(m)M_{\text{DFS}}(m)Memoria necesaria para camino actual y alternativas pendientes.Con b=10,m=20b=10, m=20, unos 200200 nodos.
mmProfundidad máxima explorada.m=20m=20.

La ventaja de memoria de DFS es dramática. Con b=10,m=20b=10, m=20, DFS mantiene del orden de:

bm=1020=200b \cdot m = 10 \cdot 20 = 200

nodos de memoria. BFS para una frontera comparable podría necesitar 102010^{20} nodos. DFS es el único algoritmo viable para espacios profundos sin heurística, pero esa frugalidad se paga con ausencia de optimalidad y riesgo de perderse.9

IDS: lo mejor de dos mundos

El Iterative Deepening Search (IDS) combina la optimalidad de BFS con la memoria de DFS.10 La idea es simple: ejecuta DFS con límite de profundidad L=0,1,2,L = 0, 1, 2, \ldots hasta encontrar la solución:

función IDS(problema):
    para L = 0, 1, 2, ... hasta ∞:
        resultado ← DFS-LIMITADO(s₀, L)
        si resultado ≠ FRACASO: return resultado

Parece ineficiente —cada iteración reexplora los niveles anteriores—, pero el coste de la reexploración es sorprendentemente bajo: los niveles profundos dominan el coste total. El número aproximado de nodos expandidos por IDS hasta profundidad dd es:

NIDS(d)==0d(d+1)bN_{\text{IDS}}(d) = \sum_{\ell=0}^{d} (d-\ell+1)b^\ell
SímboloSignificadoEjemplo
\ellNivel del árbol que se reexplora en varias iteraciones.El nivel 0 se toca d+1d+1 veces.
d+1d-\ell+1Número de veces que IDS vuelve a visitar el nivel \ell.Si d=3d=3, el nivel 1 se visita 3 veces.
bb^\ellNodos aproximados del nivel \ell.Con b=10b=10, el nivel 3 tiene 10001\,000 nodos.

Comparado con BFS:

NIDSNBFSbb1\frac{N_{\text{IDS}}}{N_{\text{BFS}}} \approx \frac{b}{b-1}

Para b=10b=10:

1091.11\frac{10}{9} \approx 1.11

IDS explora aproximadamente un 11 % más de nodos que BFS, pero con un consumo de memoria O(bd)O(b \cdot d) en lugar de O(bd)O(b^d).11 Es el algoritmo preferido cuando el espacio de búsqueda es grande, la profundidad de la solución es desconocida y no hay heurística disponible.

UCS: cuando cada paso cuesta distinto

BFS asume que todos los pasos cuestan lo mismo. Pero en el mundo real, un paso puede costar 5 y otro 500. BFS encuentra el camino con menos pasos, no el más barato.

UCS generaliza BFS reemplazando la cola por una cola de prioridad ordenada por g(n)g(n), el coste acumulado desde el estado inicial hasta nn.12 En cada paso, UCS expande el nodo con menor g(n)g(n):

g(n)=i=1kc(si1,ai)g(n) = \sum_{i=1}^{k} c(s_{i-1}, a_i)
SímboloSignificadoEjemplo
g(n)g(n)Coste acumulado desde el estado inicial hasta el nodo nn.Llegar a DD cuesta 7.
c(si1,ai)c(s_{i-1}, a_i)Coste de aplicar la acción aia_i desde el estado anterior.Una carretera de 5 km o una acción con coste 5.
kkNúmero de acciones del camino hasta nn.Tres movimientos: k=3k=3.
s0s1sks_0 \to s_1 \to \ldots \to s_kSecuencia de estados recorrida hasta llegar a nn.ACDA \to C \to D.

La política de extracción queda así:

nt=argminnFtg(n)n_t = \arg\min_{n \in F_t} g(n)

Si dos caminos llegan al mismo estado, UCS conserva el de menor coste:

gnuevo(s)=g(nt)+c(nt,a)g_{\text{nuevo}}(s') = g(n_t) + c(n_t, a) g(s)min(g(s),gnuevo(s))g(s') \leftarrow \min\left(g(s'), g_{\text{nuevo}}(s')\right)
SímboloSignificadoEjemplo
ntn_tNodo extraído de la frontera en la iteración tt.CC, porque g(C)=2g(C)=2.
FtF_tFrontera ordenada por coste acumulado.[(C,2),(B,5)][(C,2), (B,5)].
gnuevo(s)g_{\text{nuevo}}(s')Coste candidato para llegar a un sucesor.Si g(C)=2g(C)=2 y c(C,D)=5c(C,D)=5, entonces gnuevo(D)=7g_{\text{nuevo}}(D)=7.
min\minOperación que se queda con el camino más barato conocido.Si ya había D=9D=9, se reemplaza por D=7D=7.

Ejemplo concreto:

Frontera: [(A, g=0)]            → extraer A, añadir B(g=5), C(g=2)
Frontera: [(C, g=2), (B, g=5)]  → extraer C (menor coste), añadir D(g=7)
Frontera: [(B, g=5), (D, g=7)]  → extraer B, añadir E(g=11)

Observa que B se descubrió antes que C, pero C se expandió primero porque su coste acumulado era menor. UCS no discrimina por antigüedad: solo le importa el coste.

Propiedades formales

PropiedadValorCondición
CompletitudTodos los costes c(s,a)ϵ>0c(s,a) \geq \epsilon > 0
OptimalidadEl primer nodo meta extraído es óptimo
TiempoO(b1+C/ϵ)O(b^{1 + \lfloor C^*/\epsilon \rfloor})CC^* = coste solución óptima, ϵ\epsilon = coste mínimo
EspacioO(b1+C/ϵ)O(b^{1 + \lfloor C^*/\epsilon \rfloor})Similar al tiempo en el peor caso

BFS es un caso especial de UCS donde c(s,a)=1c(s,a) = 1 para toda acción. En ese caso, g(n)=profundidad(n)g(n) = \text{profundidad}(n) y UCS se comporta exactamente como BFS.13

Comparar búsquedas como ingeniero

Una comparación útil no se queda en “este algoritmo encuentra camino”. Debe registrar la traza de expansión y métricas mínimas. Si no las registras, no puedes explicar por qué BFS encontró una solución rápida pero cara, por qué DFS tuvo suerte o por qué UCS tardó más pero devolvió menor coste.

MétricaQué midePor qué importa
Estados expandidosCuántas veces sacaste un nodo de la frontera.Aproxima trabajo computacional.
Estados generadosCuántos sucesores se produjeron.Mide cuánto crece el árbol aunque no todo se expanda.
Frontera máximaMáximo tamaño de la frontera.Aproxima presión de memoria.
Profundidad de soluciónNúmero de acciones del camino devuelto.BFS optimiza esto si los costes son uniformes.
Coste de soluciónSuma de costes g(n)g(n).UCS optimiza esto si los costes son positivos.
TrazaOrden exacto de expansión.Permite revisar empates, ciclos y decisiones de frontera.

También hay un detalle profesional que suele pasarse por alto: el desempate. Si dos nodos tienen el mismo coste, la implementación debe decidir cuál sale primero. Dos implementaciones correctas de UCS pueden expandir nodos en orden distinto si no fijan una regla estable de desempate. Para comparar runs, fija el orden de sucesores y el criterio de desempate.

Tres algoritmos, mismo bucle, distinta frontera El algoritmo base no cambia: cambia la política que decide qué nodo sale de la frontera. BUCLE COMÚN EXTRAER(F) COMPROBAR META EXPANDIR AÑADIR SUCESORES nt = extraerπ(Ft) BFS DFS UCS Cola FIFO: sale el primero que entró. Pila LIFO: sale el último que entró. Prioridad: sale el menor g(n). Frontera B C D E n = front(F) nivel 0, luego nivel 1, luego nivel 2... T = O(b^d) · M ≈ b^d Completo y óptimo si coste = 1 Frontera B C D n = top(F) se hunde en una rama antes de volver T = O(b^m) · M ≈ b·m Poca memoria, sin garantía de óptimo Frontera C g=2 B g=5 D g=7 n = argmin g(n) T, M = O(b^(1+floor(C*/ε))) Óptimo con costes positivos b = ramificación · d = profundidad solución · m = profundidad máxima · C* = coste óptimo · ε = coste mínimo IA para gente curiosa / Facsímil 02 / Capítulo 02 / 686f6c61

Tabla comparativa

AlgoritmoFronteraCompletoÓptimoTiempoEspacio
BFSCola (FIFO)Sí (costes = 1)O(bd)O(b^d)O(bd)O(b^d)
DFSPila (LIFO)No (sin lím.)NoO(bm)O(b^m)O(bm)O(b \cdot m)
UCSCola prioridad (gg)O(b1+C/ϵ)O(b^{1+\lfloor C^*/\epsilon \rfloor})O(b1+C/ϵ)O(b^{1+\lfloor C^*/\epsilon \rfloor})
IDSPila (LIFO, repetido)Sí (costes = 1)O(bd)O(b^d)O(bd)O(b \cdot d)

Donde bb = factor de ramificación, dd = profundidad de la solución más superficial, mm = profundidad máxima, CC^* = coste de la solución óptima, ϵ\epsilon = coste mínimo de cualquier acción.

En el día a día

  • BFS es la base del web crawling (explorar internet por niveles de enlaces), de los algoritmos de «seis grados de separación» en redes sociales, y de cualquier problema donde necesites garantizar el camino más corto en un grafo no ponderado.
  • DFS aparece en analizadores sintácticos (recorrer el árbol de sintaxis en profundidad), en la resolución de laberintos con poca memoria, y como base del backtracking que veremos en el capítulo 7 sobre CSP. También es el algoritmo natural para generar permutaciones y combinaciones.
  • UCS está en el corazón de los sistemas de navegación. Google Maps no usa BFS (las carreteras no miden todas lo mismo): usa UCS (o A*, que es UCS con heurística) para encontrar rutas óptimas en grafos con pesos.
  • IDS es el algoritmo preferido en motores de ajedrez y otros juegos con espacio de búsqueda profundo y factor de ramificación alto, donde BFS se queda sin memoria y DFS sin garantías.

Por qué debería importarte

BFS, DFS y UCS no son algoritmos para memorizar: son patrones de diseño algorítmico. El patrón es «frontera + bucle». La elección de la estructura de datos para la frontera es la decisión de diseño que determina todas las propiedades del algoritmo resultante.

Este principio —una decisión de implementación aparentemente menor que determina propiedades asintóticas— es recurrente en informática. Y en IA, es la base sobre la que se construye A*: UCS con una heurística añadida a la prioridad. Si no entiendes por qué BFS explora por niveles y DFS se lanza en profundidad, no entenderás por qué A* es mejor que ambos.14

Dónde solía tropezar yo

ErrorPor qué es un errorAntídoto
Usar DFS sin límite en espacios infinitosDFS se pierde por una rama infinita sin retroceder. El algoritmo nunca termina.Usa IDS o establece un límite de profundidad basado en el conocimiento del dominio.
Asumir que BFS es siempre mejor que DFSBFS garantiza optimalidad pero su consumo de memoria es exponencial. Para b=10,d=15b=10, d=15, BFS necesita petabytes de RAM.Evalúa bb y dd antes de elegir. Si bdb^d supera la memoria disponible, usa IDS o DFS con límite.
Usar BFS con costes no uniformesBFS optimiza el número de pasos, no el coste. Si las acciones tienen costes distintos, BFS no encuentra el camino óptimo.Usa UCS. BFS es UCS con c(s,a)=1c(s,a)=1; fuera de ese caso, UCS es la herramienta correcta.
No detectar estados repetidosSin un conjunto visitados, los tres algoritmos pueden quedar atrapados en ciclos infinitos.Mantén visitados y comprueba antes de añadir a la frontera. Es la optimización más rentable en búsqueda.

Manos a la obra

La práctica real está en kit descargable. Ejecuta BFS, DFS, UCS e IDS sobre el mismo grafo ponderado y genera un informe con camino, coste, profundidad, nodos expandidos, nodos generados, frontera máxima y traza.

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/compare_frontiers.py --write
cat output/frontier_decision.md

Qué deberías ver. BFS encuentra el camino con menos acciones, pero no necesariamente el más barato. UCS encuentra el menor coste porque ordena por g(n)g(n). DFS puede encontrar una solución válida, pero depende mucho del orden de sucesores. IDS reexplora, pero mantiene memoria baja.

ArchivoPapel
data/weighted_graph.jsonGrafo ponderado, estado inicial, meta y orden estable de sucesores.
contracts/frontier_policy.jsonLímites y reglas de comparación.
ops/compare_frontiers.pyImplementación ejecutable sin dependencias externas.
output/frontier_report.jsonMétricas estructuradas por algoritmo.
output/frontier_decision.mdInforme legible para revisión o entrega.

Cómo lo adaptas a tu caso. Cambia el grafo por un flujo real: navegación en una app, pasos de una herramienta, estados de un pedido o rutas de soporte. Mantén costes distintos para que BFS y UCS puedan diferir.

Qué entregaría un alumno. El Markdown generado, un grafo modificado, una explicación de por qué BFS no minimiza coste cuando los pesos cambian y una decisión técnica sobre qué política usaría según memoria, coste y garantías.

Cómo encaja todo

El capítulo anterior definió el contrato del problema. Este capítulo enseña que, una vez tienes estados y acciones, la decisión crítica es la política de frontera. Cambiar una cola por una pila o por una cola de prioridad cambia garantías, memoria y coste encontrado.

Esto prepara el salto al capítulo 3: A* no aparece de la nada. Es UCS con una estimación del coste restante. Primero entiendes g(n)g(n); después podrás entender g(n)+h(n)g(n)+h(n).

graph TD
    subgraph "Capítulo 2: Algoritmos ciegos"
        GEN["Bucle genérico:<br/>extraer → comprobar → expandir → añadir"]
        FRONTERA["Frontera: núcleo del algoritmo"]
        COLA["Cola FIFO"]
        PILA["Pila LIFO"]
        CPRIOR["Cola prioridad por g(n)"]
    end
    subgraph "Propiedades formales"
        COMPLETITUD["Completitud: ¿siempre encuentra solución?"]
        OPTIMALIDAD["Optimalidad: ¿encuentra la mejor?"]
        COMPLEJIDAD["Complejidad: O(b^d) vs O(b·m)"]
    end
    subgraph "Algoritmos resultantes"
        BFS["BFS: completo, óptimo, O(b^d) espacio"]
        DFS["DFS: no completo, no óptimo, O(b·m) espacio"]
        UCS["UCS: completo, óptimo, generaliza BFS"]
        IDS["IDS: completo, óptimo, O(b·d) espacio"]
    end
    subgraph "Conexiones"
        CAP1["Espacio de estados (cap. 1)"]
        ASTAR["A* (cap. 3)"]
        BACKTRACK["Backtracking CSP (cap. 7)"]
    end

    GEN --> FRONTERA
    FRONTERA -->|"implementada con"| COLA
    FRONTERA -->|"implementada con"| PILA
    FRONTERA -->|"implementada con"| CPRIOR
    COLA -->|"produce"| BFS
    PILA -->|"produce"| DFS
    PILA -->|"con límites crecientes produce"| IDS
    CPRIOR -->|"produce"| UCS
    BFS -->|"garantiza"| COMPLETITUD
    BFS -->|"garantiza"| OPTIMALIDAD
    BFS -->|"tiene"| COMPLEJIDAD
    DFS -->|"tiene"| COMPLEJIDAD
    UCS -->|"garantiza"| OPTIMALIDAD
    CAP1 -.->|"define los"| GEN
    UCS -.->|"base de"| ASTAR
    DFS -.->|"base de"| BACKTRACK
    IDS -.->|"inspira"| ASTAR

    style CAP1 stroke-dasharray: 5 5
    style ASTAR stroke-dasharray: 5 5
    style BACKTRACK stroke-dasharray: 5 5
    style FRONTERA fill:#F5F5F5,stroke:#000000,stroke-width:2
    style UCS fill:#F5F5F5,stroke:#000000,stroke-width:2

Vocabulario aprendido

TérminoDefinición
BFSAlgoritmo de búsqueda por niveles con cola FIFO. Completo y óptimo para costes uniformes. O(bd)O(b^d) en tiempo y espacio.
DFSAlgoritmo de búsqueda en profundidad con pila LIFO. O(bm)O(b \cdot m) en espacio pero no es completo ni óptimo sin límite.
UCSAlgoritmo con cola de prioridad por g(n)g(n). Generaliza BFS para costes no uniformes. Óptimo con costes positivos.
IDSDFS repetido con límites crecientes. Combina optimalidad de BFS con bajo consumo de memoria de DFS.
Factor de ramificación (bb)Número medio de sucesores por estado. Determina la complejidad exponencial de la búsqueda.
Traza de expansiónOrden en el que el algoritmo extrae estados de la frontera. Permite auditar la búsqueda.
Frontera máximaTamaño máximo que alcanza la frontera durante la ejecución. Aproxima presión de memoria.
Coste acumuladog(n)g(n): suma de costes desde el estado inicial hasta el nodo actual.

Antes de pasar página

  • ¿Puedo escribir el pseudocódigo del bucle genérico de búsqueda? (Si no, vuelve a «El bucle genérico».)
  • ¿Sé qué estructura de datos usa la frontera en BFS, DFS y UCS? (Cola, pila, cola de prioridad.)
  • ¿Puedo explicar las propiedades formales (completitud, optimalidad, complejidad) de cada algoritmo? (Si no, vuelve a las tablas de propiedades.)
  • ¿Entiendo por qué IDS es preferible a BFS en espacios profundos? (Si no, vuelve a «IDS: lo mejor de dos mundos».)
  • ¿He ejecutado kit descargable y puedo explicar camino, coste, expansiones y frontera máxima? (Si no, vuelve a «Manos a la obra».)

En resumen

Idea fuerzaDetalle
La frontera lo decide todo.Una cola produce BFS. Una pila produce DFS. Una cola de prioridad por g(n)g(n) produce UCS. El resto del bucle es idéntico.
BFS es óptimo en pasos pero devorador de memoria. DFS es frugal en memoria pero ni completo ni óptimo.IDS combina lo mejor de ambos: optimalidad de BFS con memoria de DFS, a costa de reexplorar (~11 % más de nodos).
UCS es BFS generalizado: optimiza coste, no pasos.Con costes uniformes, UCS = BFS. Con costes variables, solo UCS (o A*) garantiza optimalidad.
Una búsqueda seria deja traza.Sin orden de expansión, frontera máxima y coste acumulado no puedes comparar algoritmos de forma profesional.

Para saber más

Hart, P. E., Nilsson, N. J. y Raphael, B. (1968). A formal basis for the heuristic determination of minimum cost paths. IEEE Transactions on Systems Science and Cybernetics, 4(2), 100-107. https://doi.org/10.1109/TSSC.1968.300136

Luger, G. F. (2008). Artificial intelligence: structures and strategies for complex problem solving (6.ª ed.). Pearson.

Nilsson, N. J. (1998). Artificial intelligence: a new synthesis. Morgan Kaufmann.

Pearl, J. (1984). Heuristics: intelligent search strategies for computer problem solving. Addison-Wesley.

Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press.

Rich, E., Knight, K. y Nair, S. B. (2009). Artificial intelligence (3.ª ed.). McGraw-Hill.

Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. https://aima.cs.berkeley.edu/

Notas

  1. Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. La sección 3.4 demuestra que todos los algoritmos de búsqueda no informada comparten la misma estructura algorítmica y que su comportamiento queda completamente determinado por la política de extracción de la frontera.

  2. Nilsson, N. J. (1998). Artificial intelligence: a new synthesis. Morgan Kaufmann. El capítulo 7 presenta el algoritmo genérico de búsqueda en grafos que unifica BFS, DFS y UCS.

  3. Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press. El capítulo 3 presenta este marco unificado y demuestra que encapsula toda la familia de algoritmos de búsqueda no informada.

  4. Rich, E., Knight, K. y Nair, S. B. (2009). Artificial intelligence (3.ª ed.). McGraw-Hill. El capítulo 3 analiza BFS en detalle, incluyendo su implementación con cola y el análisis de complejidad.

  5. Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson.

  6. Luger, G. F. (2008). Artificial intelligence: structures and strategies for complex problem solving (6.ª ed.). Pearson. La sección 3.2 cuantifica el problema de memoria de BFS y motiva la necesidad de DFS e IDS.

  7. Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press.

  8. Nilsson, N. J. (1998). Artificial intelligence: a new synthesis. Morgan Kaufmann. El capítulo 7 explica la equivalencia entre DFS con pila explícita y DFS recursivo, y analiza las implicaciones para el consumo de memoria.

  9. Rich, E., Knight, K. y Nair, S. B. (2009). Artificial intelligence (3.ª ed.). McGraw-Hill.

  10. Luger, G. F. (2008). Artificial intelligence: structures and strategies for complex problem solving (6.ª ed.). Pearson.

  11. Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson.

  12. Hart, P. E., Nilsson, N. J. y Raphael, B. (1968). A formal basis for the heuristic determination of minimum cost paths. IEEE Transactions on Systems Science and Cybernetics, 4(2), 100-107. https://doi.org/10.1109/TSSC.1968.300136

  13. Pearl, J. (1984). Heuristics: intelligent search strategies for computer problem solving. Addison-Wesley. El capítulo 2 demuestra formalmente que UCS es una generalización de BFS y que A* es a su vez una generalización de UCS.

  14. Pearl, J. (1984). Heuristics: intelligent search strategies for computer problem solving. Addison-Wesley. El capítulo 3 demuestra cómo A* emerge naturalmente de UCS al incorporar una heurística en la función de evaluación.

Capítulo 03

Facsímil 2 · Inteligencia clásica

Capítulo 03: Greedy, A* y heurísticas: buscar con estimaciones

Entrando en el tema

Hasta ahora has explorado a ciegas. BFS, DFS, UCS: algoritmos que no saben nada del problema salvo qué acciones existen y cuánto cuestan. Funcionan, pero son terriblemente ineficientes: exploran miles de estados que no llevan a ninguna parte.

Ahora imagina que tienes una estimación matemática barata. Una función h(n)h(n) que, para cualquier estado nn, estima cuánto falta para llegar a la meta. No es exacta —si lo fuera, ya habrías resuelto el problema—, pero es útil. Con esa estimación, puedes priorizar los estados que parecen más prometedores e ignorar los que se alejan. Puedes encontrar la solución explorando cientos de estados en vez de millones.

Esa función se llama heurística. Y los algoritmos que la usan —Greedy y A*— son piezas centrales de la búsqueda informada.1 Sin heurísticas, muchos problemas de rutas, planificación y videojuegos tendrían que mirar demasiadas opciones antes de responder.

Greedy best-first: seguir solo la estimación

El algoritmo greedy best-first search es el más simple de los informados. Evalúa cada estado exclusivamente con la heurística h(n)h(n) —la estimación de lo que falta hasta la meta— e ignora completamente el coste acumulado g(n)g(n).2

Es como ir de Madrid a Berlín mirando exclusivamente la distancia en línea recta: «Barcelona está más cerca de Berlín que Lisboa, voy a Barcelona. París está más cerca que Roma, voy a París». Nunca mira hacia atrás. Nunca considera si el camino acumulado es bueno o si la ruta aparente esconde un desvío enorme.

Formalmente, Greedy usa esta función de evaluación:

fGreedy(n)=h(n)f_{\text{Greedy}}(n) = h(n)

Y en cada iteración extrae de la frontera el nodo que parece más cercano a la meta:

nt=argminnFth(n)n_t = \arg\min_{n \in F_t} h(n)
SímboloSignificadoEjemplo
fGreedy(n)f_{\text{Greedy}}(n)Prioridad que Greedy asigna al nodo nn.Si h(B)=3h(B)=3, la prioridad de BB es 3.
h(n)h(n)Estimación de coste desde nn hasta la meta.Distancia Manhattan hasta la salida.
FtF_tFrontera en la iteración tt.{B,C,D}\{B,C,D\}.
argmin\arg\minOperación que devuelve el elemento con menor valor.Si h(C)=2h(C)=2, Greedy elige CC.

Mira el detalle peligroso: no aparece g(n)g(n). Si llegar hasta CC ya te ha costado 40 pasos y llegar hasta BB solo 2, Greedy no lo ve. Solo pregunta: «¿cuál parece más cerca de la meta desde aquí?».

Ventaja: velocidad. Si h(n)h(n) es razonablemente buena, Greedy encuentra una solución explorando muy pocos estados. En navegación con distancia euclídea, suele ir directo al destino.

Riesgo: no es ni completo ni óptimo. Puede quedarse atascado en un mínimo local, eligiendo repetidamente estados que parecen buenos según hh pero que no llevan a ninguna parte. Y el camino que encuentra rara vez es el mejor: la heurística puede empujarte hacia una montaña —porque en línea recta parece más corta— cuando el camino óptimo da un rodeo por el valle.3

En agentes LLM modernos, Greedy equivale a elegir la tool que parece obvia sin verificar restricciones: «¿cuál es la respuesta? Voy a buscar en la base de datos». Pero quizás antes necesitabas comprobar permisos. La heurística te empujó en una dirección que parecía correcta pero no lo era.

La tabla de propiedades queda así:

PropiedadValorPor qué
CompletitudNo en generalPuede entrar en ciclos o perseguir una rama infinita que parece prometedora.
OptimalidadNoIgnora el coste acumulado g(n)g(n).
TiempoO(bm)O(b^m) en el peor casoSi la heurística engaña, puede explorar una rama profunda entera.
EspacioO(bm)O(b^m) en el peor casoMantiene frontera y visitados como otros algoritmos de búsqueda en grafos.

A*: coste real + estimación

A* corrige el defecto fundamental de Greedy combinando dos piezas de información en una sola función de evaluación:4

f(n)=g(n)+h(n)f(n) = g(n) + h(n)
SímboloSignificadoCálculo
f(n)f(n)Coste total estimado del camino óptimo que pasa por nng(n)+h(n)g(n) + h(n)
g(n)g(n)Coste real acumulado desde el inicio hasta nnc(si1,ai)\sum c(s_{i-1}, a_i)
h(n)h(n)Heurística: coste estimado desde nn hasta la metaEspecífica del problema
h(n)h^*(n)Coste real óptimo desde nn hasta la metaDesconocido (es lo que buscamos)

g(n)g(n) es lo que ya has pagado. h(n)h(n) es lo que estimas que te queda. f(n)f(n) es el total estimado. A* expande siempre el nodo con menor f(n)f(n).5

La política de extracción de A* es:

nt=argminnFt(g(n)+h(n))n_t = \arg\min_{n \in F_t} \left(g(n) + h(n)\right)
Nodog(n)g(n): coste ya pagadoh(n)h(n): estimación restantef(n)=g(n)+h(n)f(n)=g(n)+h(n)Quién lo elegiría
BB8210Greedy, porque h(B)h(B) es menor.
CC347A*, porque f(C)f(C) es menor.

Este ejemplo pequeño captura toda la diferencia. Greedy ve 2<42 < 4 y elige BB. A* ve 10>710 > 7 y elige CC, porque entiende que lo que ya has pagado también cuenta.

Esto resuelve el problema de Greedy. Si la heurística te empuja hacia un camino que parece corto pero es caro, g(n)g(n) —el coste real acumulado— penaliza esa decisión. A* no solo mira lo prometedor: también penaliza los caminos que ya han costado demasiado.6

Propiedades formales de A*

Admisibilidad. Una heurística h(n)h(n) es admisible si nunca sobreestima el coste real hasta la meta. Formalmente:

0h(n)h(n)0 \leq h(n) \leq h^*(n)
SímboloSignificadoEjemplo
h(n)h(n)Estimación que calculas rápido.Distancia en línea recta: 12 km.
h(n)h^*(n)Coste real óptimo desde nn hasta la meta.Mejor carretera real: 15 km.
0h(n)0 \leq h(n)La heurística no puede ser negativa.No tiene sentido decir “faltan -3 km”.
h(n)h(n)h(n) \leq h^*(n)La heurística no promete más de lo que existe.12 km no sobreestima 15 km.

La distancia en línea recta es admisible porque ningún camino por carreteras puede ser más corto que la línea recta. Una heurística que estime tiempos ignorando semáforos, cuestas o peajes puede dejar de ser admisible si promete rutas demasiado optimistas.7

Teorema de optimalidad. En búsqueda en árbol, si h(n)h(n) es admisible, A* encuentra un camino de coste mínimo. En búsqueda en grafo, la garantía requiere además gestionar correctamente reaperturas de estados o trabajar con una heurística consistente. La demostración se basa en que A* no termina hasta haber descartado los nodos que podrían tener f(n)<Cf(n) < C^* (el coste óptimo) y, cuando encuentra la meta, su ff es igual a gg porque h(meta)=0h(\text{meta}) = 0.

Consistencia (monotonicidad). Una propiedad más fuerte que la admisibilidad:

h(n)c(n,a,n)+h(n)h(n) \leq c(n,a,n') + h(n')
SímboloSignificadoEjemplo
c(n,a,n)c(n,a,n')Coste de ir de nn a nn' aplicando aa.Moverte una casilla cuesta 1.
h(n)h(n)Estimación antes de moverte.Faltan 8 pasos estimados.
h(n)h(n')Estimación después de moverte.Faltan 7 pasos estimados.

La lectura es sencilla: la estimación desde nn no puede ser mayor que «lo que cuesta dar un paso» más «lo que estimas desde el siguiente estado». Si hh es consistente, entonces f(n)f(n) nunca baja a lo largo de un camino:

f(n)=g(n)+c(n,a,n)+h(n)g(n)+h(n)=f(n)f(n') = g(n) + c(n,a,n') + h(n') \geq g(n) + h(n) = f(n)

Por eso A* con heurística consistente puede tratar los estados como cerrados la primera vez que los expande: no necesitará reabrirlos más tarde con un coste mejor.8

Heurísticas: el arte de saber qué ignorar

Una heurística es una función h:SR0+h: S \to \mathbb{R}^+_0 que, dado un estado, devuelve una estimación. Diseñar una buena heurística exige escoger información que aporte señal, sea barata de calcular y no rompa las garantías que quieres conservar.9

En una rejilla, dos heurísticas clásicas son:

hManhattan(n)=xnxmeta+ynymetah_{\text{Manhattan}}(n) = |x_n - x_{\text{meta}}| + |y_n - y_{\text{meta}}| hEuclidea(n)=(xnxmeta)2+(ynymeta)2h_{\text{Euclidea}}(n) = \sqrt{(x_n - x_{\text{meta}})^2 + (y_n - y_{\text{meta}})^2}
SímboloSignificadoEjemplo
xn,ynx_n, y_nCoordenadas del estado actual.n=(2,3)n=(2,3).
xmeta,ymetax_{\text{meta}}, y_{\text{meta}}Coordenadas de la meta.meta=(7,6)\text{meta}=(7,6).
$x_n-x_{\text{meta}}$
$y_n-y_{\text{meta}}$

Con esos números:

hManhattan(n)=5+3=8h_{\text{Manhattan}}(n) = 5 + 3 = 8 hEuclidea(n)=52+32=345.83h_{\text{Euclidea}}(n) = \sqrt{5^2 + 3^2} = \sqrt{34} \approx 5.83

Si solo puedes moverte en horizontal y vertical, Manhattan suele ser más informativa. Si puedes moverte en cualquier dirección, la euclídea encaja mejor.

TipoEjemploAdmisibleInformativa
BuenaDistancia euclídea en navegaciónAlta
AceptableDistancia Manhattan en rejillaMedia
Mala«Dificultad del examen = páginas del temario»NoBaja
Engañosa«Número de paquetes que faltan»NoEngaña

La diferencia entre una heurística buena y una mala puede ser la diferencia entre explorar 100 estados y 100 000. Una heurística perfecta —h(n)=h(n)h(n) = h^*(n)— haría que A* fuera directamente a la solución sin explorar nada más, pero calcular h(n)h^*(n) es tan difícil como resolver el problema original. El arte está en aproximar h(n)h^*(n) sin calcularla exactamente.

Una técnica clásica es relajar el problema: eliminar alguna restricción para crear una versión más fácil. La solución del problema relajado es una heurística admisible para el problema original.10 Por ejemplo, la distancia en línea recta es la solución al problema de navegación relajado donde ignoras los obstáculos y las carreteras.

También comparamos heurísticas por dominancia:

h1h2n,  h1(n)h2(n)h_1 \succeq h_2 \quad \Longleftrightarrow \quad \forall n,\; h_1(n) \geq h_2(n)

siempre que ambas sigan siendo admisibles. Si h1h_1 domina a h2h_2, A* con h1h_1 no expande más nodos que A* con h2h_2. Dicho en castellano: cuanto más cerca esté h(n)h(n) de h(n)h^*(n) sin pasarse, menos trabajo hace A*.

Auditar una heurística antes de usarla

Una heurística no se acepta porque “suena razonable”. Se audita. Para problemas pequeños, puedes calcular h(n)h^*(n), el coste óptimo real desde cada estado hasta la meta, y comparar.

PruebaFórmulaQué detecta
No negatividadh(n)0h(n)\geq0Estimaciones sin sentido.
Meta a ceroh(meta)=0h(\text{meta})=0Heurísticas que penalizan llegar.
Admisibilidadh(n)h(n)h(n)\leq h^*(n)Sobreestimaciones que rompen optimalidad de A*.
Consistenciah(n)c(n,a,n)+h(n)h(n)\leq c(n,a,n')+h(n')Necesidad de reabrir nodos en grafos.
Dominanciah1(n)h2(n)h_1(n)\geq h_2(n) para todo nnQué heurística informará más a A* sin perder garantías.

En producción no siempre puedes conocer h(n)h^*(n); si pudieras, ya tendrías resuelto el problema. Pero en entornos pequeños, tests, mapas de juguete o fixtures, esta auditoría es oro: te permite validar que tu heurística no está metiendo una promesa falsa en el algoritmo.

También conviene medir el coste de calcular h(n)h(n). Una heurística brillante pero carísima puede perder contra una heurística sencilla si cada evaluación tarda demasiado. A* no solo paga expansiones; también paga evaluaciones de heurística.

UCS, Greedy y A*: la misma frontera con distinta prioridad La decisión cambia según mires solo el coste real, solo la estimación o la suma de ambos. FRONTERA EN ESTE INSTANTE B: g=8, h=2 C: g=3, h=4 D: g=5, h=7 UCS Greedy A* Solo mira lo que ya costó. Solo mira lo que parece faltar. Suma coste real + estimación. f(n) = g(n) f(n) = h(n) f(n) = g(n) + h(n) elige C porque g(C)=3 es menor elige B porque h(B)=2 es menor elige C porque f(C)=3+4=7 Óptimo sin heurística Rápido, pero no óptimo Óptimo si h es admisible Condición clave de A* 0 ≤ h(n) ≤ h*(n) · h(meta) = 0 · consistencia: h(n) ≤ c(n,a,n') + h(n') IA para gente curiosa / Facsímil 02 / Capítulo 03 / 686f6c61

En el día a día

  • GPS y navegación: A* con h(n)h(n) = distancia euclídea es una simplificación útil para entender la idea. Los sistemas reales añaden datos de tráfico, restricciones de giro, jerarquías de carretera y cachés, pero el mecanismo permanece: una heurística buena reduce mucho el espacio que hay que mirar.
  • Videojuegos: pathfinding de NPCs con A* y distancia Manhattan. Sin A*, los personajes se quedarían atascados contra las paredes.
  • Agentes LLM: una decisión de tool puede modelarse como un paso de búsqueda. El LLM puede proponer qué herramienta parece más prometedora, pero el sistema debería añadir coste acumulado, riesgo, permisos y observación. Si penalizas caminos que ya han consumido demasiados tokens o llamadas caras, estás metiendo una idea parecida a g(n)g(n) en el diseño.

Por qué debería importarte

A* es uno de los algoritmos centrales de la IA clásica: combina coste real y estimación futura de una forma sorprendentemente clara. La ecuación f(n)=g(n)+h(n)f(n) = g(n) + h(n) resume décadas de investigación. Pero la lección más profunda no es memorizar el algoritmo: es aprender a diseñar heurísticas que ahorran búsqueda sin romper las garantías que necesitas.

Y este concepto trasciende la IA: en optimización, en diseño de algoritmos, en toma de decisiones, la habilidad de encontrar atajos informados que no comprometan la calidad de la solución es universal. A* formaliza esa tensión entre coste observado y estimación restante.

Dónde solía tropezar yo

ErrorPor qué es un errorAntídoto
Heurística no admisible con A*Si h(n)h(n) sobreestima el coste real, A* puede pasar de largo la solución óptima.Verifica 0h(n)h(n)0 \leq h(n) \leq h^*(n). La distancia euclídea y Manhattan son admisibles. Las heurísticas basadas en «coste medio» no lo son.
Confundir Greedy con A*Greedy ignora g(n)g(n): no garantiza optimalidad. A* usa g(n)+h(n)g(n) + h(n): sí la garantiza con hh admisible.Usa A* si necesitas optimalidad. Greedy solo si necesitas una solución rápida y la calidad no es crítica.
Heurística demasiado cara de calcularEvaluar h(n)h(n) cuesta tiempo. Si calcular hh tarda más que expandir unos cientos de nodos extra con una heurística más simple, estás perdiendo eficiencia neta.Mide el tiempo de h(n)h(n). Si es más lento que expandir ~100 nodos, simplifica la heurística.

Manos a la obra

La práctica real está en kit descargable. Ejecuta UCS, Greedy, A*, A* con heurística nula y Weighted A* sobre el mismo grafo. Además audita heurísticas contra el coste óptimo real h(n)h^*(n).

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/audit_heuristics.py --write
cat output/heuristic_decision.md

Qué deberías ver. La heurística nula convierte A* en UCS. Una heurística admisible y consistente conserva optimalidad y suele reducir expansiones. Greedy puede encontrar una solución rápida pero no tiene garantías. Weighted A* puede expandir menos, pero si w>1w>1 ya no promete óptimo.

ArchivoPapel
data/heuristic_graph.jsonGrafo ponderado y valores heurísticos candidatos.
contracts/heuristic_policy.jsonPeso de Weighted A*, reglas de auditoría y límites de comparación.
ops/audit_heuristics.pyAuditor e implementaciones ejecutables sin dependencias externas.
output/heuristic_report.jsonResultados estructurados: admisibilidad, consistencia, dominancia y búsquedas.
output/heuristic_decision.mdInforme legible para entregar.

Cómo lo adaptas a tu caso. Cambia el grafo, añade una heurística nueva y mira si sigue siendo admisible. Después modifica el peso de Weighted A*. Si el coste baja o sube, explica por qué.

Qué entregaría un alumno. El Markdown generado, una heurística propia, una prueba de si es admisible/consistente y una comparación entre UCS, Greedy, A* y Weighted A*.

Cómo encaja todo

Este capítulo añade una pieza nueva a la frontera del capítulo 02: ya no ordenas solo por antigüedad o por coste real acumulado. Ahora introduces una estimación del futuro. Esa estimación puede ahorrar muchísimo trabajo, pero solo mantiene garantías si se comporta matemáticamente bien.

La idea seguirá viva en planificación, juegos y agentes: muchas decisiones inteligentes son una mezcla de coste pagado, coste esperado, riesgo y una función de evaluación.

graph TD
    subgraph "Capítulo 3: Búsqueda informada"
        FN["f(n) = g(n) + h(n)"]
        GREEDY["Greedy: solo h(n)"]
        ASTAR["A*: g(n) + h(n)"]
        ADM["Admisibilidad: 0 &lt;= h(n) &lt;= h*(n)"]
        CONS["Consistencia: h(n) &lt;= c + h(n')"]
    end
    subgraph "Capítulos previos"
        UCS["UCS: f(n) = g(n) (cap. 2)"]
    end
    subgraph "Conexiones"
        PLAN["Planificación heurística (cap. 10)"]
        AGENTES["Agentes LLM (cap. 4, fasc. 5)"]
        JUEGOS["Juegos: evaluación heurística (cap. 11)"]
    end

    UCS -->|"añadir h(n)"| FN
    FN -->|"sin g(n)"| GREEDY
    FN -->|"con g(n) + h(n)"| ASTAR
    ASTAR -->|"requiere"| ADM
    CONS -->|"implica"| ADM
    ASTAR -->|"fundamento de"| PLAN
    GREEDY -->|"patron en"| AGENTES
    FN -->|"inspira evaluación en"| JUEGOS

    style UCS stroke-dasharray: 5 5
    style PLAN stroke-dasharray: 5 5
    style AGENTES stroke-dasharray: 5 5
    style JUEGOS stroke-dasharray: 5 5
    style FN fill:#F5F5F5,stroke:#000000,stroke-width:2

Vocabulario aprendido

TérminoDefinición
A*f(n)=g(n)+h(n)f(n)=g(n)+h(n). Óptimo si hh es admisible.
Heurística admisibleNunca sobreestima: 0h(n)h(n)0 \leq h(n) \leq h^*(n).
Greedy best-firstSolo h(n)h(n). Rápido, no óptimo.
Consistenciah(n)c(n,a,n)+h(n)h(n) \leq c(n,a,n') + h(n'). Más fuerte que admisibilidad.
RelajaciónSimplificar el problema para obtener una heurística admisible.
Dominancia heurísticaUna heurística admisible domina a otra si estima siempre igual o más sin sobreestimar. Suele reducir expansiones.
Weighted A*Variante f(n)=g(n)+wh(n)f(n)=g(n)+w h(n). Con w>1w>1 puede ser más rápida, pero pierde optimalidad garantizada.

Antes de pasar página

  • ¿Puedo escribir f(n)=g(n)+h(n)f(n) = g(n) + h(n) y explicar cada término?
  • ¿Entiendo qué significa que hh sea admisible?
  • ¿Sé diferenciar Greedy de A*?
  • ¿Puedo auditar una heurística con admisibilidad, consistencia y dominancia?
  • ¿He ejecutado kit descargable y puedo explicar por qué Weighted A* puede perder optimalidad?

En resumen

Idea fuerzaDetalle
A* = UCS + heurística.g(n)g(n) garantiza optimalidad; h(n)h(n) añade eficiencia.
Admisibilidad abre la puerta a la optimalidad.h(n)h(n)h(n) \leq h^*(n) es la condición suficiente que A* necesita en búsqueda en árbol; en grafos, la consistencia evita reexpansiones.
La heurística lo es todo.De millones de estados a cientos. El arte está en el equilibrio entre precisión y coste.
Las heurísticas también se testean.No basta con una estimación plausible: admisibilidad, consistencia, dominancia y coste de cálculo son parte del contrato.

Para saber más

Hart, P. E., Nilsson, N. J. y Raphael, B. (1968). A formal basis for the heuristic determination of minimum cost paths. IEEE Transactions on Systems Science and Cybernetics, 4(2), 100-107. https://doi.org/10.1109/TSSC.1968.300136

Luger, G. F. (2008). Artificial intelligence: structures and strategies for complex problem solving (6.ª ed.). Pearson.

Nilsson, N. J. (1998). Artificial intelligence: a new synthesis. Morgan Kaufmann.

Pearl, J. (1984). Heuristics: intelligent search strategies for computer problem solving. Addison-Wesley.

Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press.

Rich, E., Knight, K. y Nair, S. B. (2009). Artificial intelligence (3.ª ed.). McGraw-Hill.

Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. https://aima.cs.berkeley.edu/

Notas

  1. Pearl, J. (1984). Heuristics: intelligent search strategies for computer problem solving. Addison-Wesley. Pearl estableció las bases teóricas de la búsqueda heurística, formalizando conceptos como admisibilidad, consistencia y poder heurístico que permiten comparar rigurosamente distintas heurísticas.

  2. Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. La sección 3.5 presenta greedy best-first como el primer algoritmo informado, destacando que su velocidad tiene como contrapartida la ausencia de garantías de optimalidad.

  3. Nilsson, N. J. (1998). Artificial intelligence: a new synthesis. Morgan Kaufmann. La sección 8.2 analiza las limitaciones de Greedy y demuestra con ejemplos concretos por qué ignorar el coste del camino puede llevar a soluciones arbitrariamente malas.

  4. Hart, P. E., Nilsson, N. J. y Raphael, B. (1968). A formal basis for the heuristic determination of minimum cost paths. IEEE Transactions on Systems Science and Cybernetics, 4(2), 100-107. https://doi.org/10.1109/TSSC.1968.300136. Este artículo presentó A* y demostró formalmente que, con heurística admisible, el algoritmo es óptimo y expande el mínimo número de nodos entre todos los algoritmos óptimos que usan la misma heurística.

  5. Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press.

  6. Luger, G. F. (2008). Artificial intelligence: structures and strategies for complex problem solving (6.ª ed.). Pearson.

  7. Pearl, J. (1984). Heuristics: intelligent search strategies for computer problem solving. Addison-Wesley. El capítulo 3 demuestra el teorema de optimalidad de A*: si hh es admisible, A* es óptimo en búsqueda en árbol.

  8. Rich, E., Knight, K. y Nair, S. B. (2009). Artificial intelligence (3.ª ed.). McGraw-Hill.

  9. Pearl, J. (1984). Heuristics: intelligent search strategies for computer problem solving. Addison-Wesley. Pearl introdujo el concepto de poder heurístico: una heurística h1h_1 domina a h2h_2 si h1(n)h2(n)h_1(n) \geq h_2(n) para todo nn, y una heurística más informada produce una búsqueda más eficiente.

  10. Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. La sección 3.6 explica cómo derivar heurísticas admisibles a partir de versiones relajadas del problema, siendo la distancia en línea recta el ejemplo canónico (ignorar obstáculos es la relajación).

Capítulo 04

Facsímil 2 · Inteligencia clásica

Capítulo 04: Búsqueda en agentes modernos y recapitulación

Entrando en el tema

Has aprendido a formular un problema como estados, acciones, meta y coste. Has visto qué ocurre cuando exploras a ciegas con BFS, DFS y UCS. Después has añadido estimaciones heurísticas con Greedy y A*. Ahora toca cerrar el bloque con una pregunta muy práctica: ¿por qué importa todo esto si hoy hablamos de LLMs, agentes y tools?

Porque muchas decisiones de un agente moderno pueden modelarse como decisiones en un espacio de posibilidades. Puede que no dibuje un árbol de búsqueda en pantalla. Puede que no tenga una cola de prioridad explícita llamada frontier. Pero cuando decide si debe leer un archivo, consultar una base de datos, llamar a una API, pedir aclaración o responder, está eligiendo una acción desde un estado, con costes, restricciones y una meta.1

Este capítulo tiene dos trabajos. Primero, traducir la búsqueda clásica al lenguaje de los agentes actuales. Segundo, recapitular activamente los cuatro primeros capítulos del facsímil 2, igual que hicimos al cerrar el facsímil 1: concepto, recuerdo, ejemplo y punto exacto al que volver si algo no está asentado.

El agente como motor de búsqueda

Un agente LLM con herramientas puede leerse como un sistema de búsqueda que descubre el espacio mientras actúa.2 La formulación mínima sería:

st=(mt,ot,rt,q)s_t = (m_t, o_t, r_t, q)
SímboloSignificadoEjemplo
sts_tEstado del agente en el instante tt.Lo que sabe después de dos llamadas a herramientas.
mtm_tMemoria o historial disponible.Mensajes previos, notas, resumen de contexto.
oto_tObservaciones recibidas del entorno.Resultado de una búsqueda, salida de un test, respuesta de una API.
rtr_tRestricciones activas.Permisos, presupuesto de tokens, formato esperado.
qqObjetivo o pregunta que se intenta resolver.“Encuentra por qué falla este test”.

Las acciones son las tools que puede ejecutar:

atA(st)a_t \in A(s_t)
SímboloSignificadoEjemplo
ata_tAcción elegida en el paso tt.Leer un archivo, ejecutar un test, buscar documentación.
A(st)A(s_t)Acciones disponibles desde el estado actual.Si no hay red, “buscar online” no está disponible.

Después de actuar, el agente recibe una observación y actualiza su estado:

st+1=T(st,at,ot+1)s_{t+1} = T(s_t, a_t, o_{t+1})

Esta es la lectura de búsqueda que nos interesa. El árbol no está escrito antes de empezar: aparece a medida que el agente actúa, observa y actualiza su estado.3

El mecanismo paso a paso

En búsqueda clásica, la frontera contiene nodos. En un agente, la frontera contiene siguientes acciones plausibles: “consultar docs”, “leer logs”, “ejecutar test”, “preguntar al usuario”, “responder ya”. Una política de extracción decide cuál probar primero.

Ejemplo de fórmula. Podemos escribir una versión operativa inspirada en la función de evaluación de A*. No es una ley universal de agentes ni un algoritmo estándar: es una plantilla de diseño para obligarnos a separar coste, avance esperado y riesgo antes de elegir una acción.

F(ast)=G(ast)+H(ast)+R(ast)F(a \mid s_t) = G(a \mid s_t) + H(a \mid s_t) + R(a \mid s_t)
SímboloSignificadoEjemplo
F(ast)F(a \mid s_t)Prioridad total de una acción aa desde el estado actual.Menor valor: acción más recomendable.
G(ast)G(a \mid s_t)Coste operativo esperado.Tokens, latencia, dinero, complejidad.
H(ast)H(a \mid s_t)Estimación de distancia restante a la meta.“Leer el error exacto probablemente acerca mucho”.
R(ast)R(a \mid s_t)Penalización por riesgo o incertidumbre.Acción destructiva, datos sensibles, baja confianza.

Y la política de decisión sería:

at=argminaA(st)F(ast)a_t = \arg\min_{a \in A(s_t)} F(a \mid s_t)

Esto no significa que todos los agentes implementen literalmente esta ecuación. Significa que la ecuación te da un lenguaje para diseñarlos y auditar una política concreta. Los pesos, unidades y umbrales deben calibrarse con trazas reales: latencia, coste, errores, acciones bloqueadas y consecuencias. Un agente puramente Greedy minimiza solo HH: elige lo que parece prometedor. Un agente más cuidadoso incluye GG: evita gastar tokens y tiempo sin necesidad. Un agente robusto añade RR: no ejecuta acciones arriesgadas solo porque parezcan útiles.4

Diseñar una política de agente que se pueda auditar

En ingeniería no basta con decir “el agente decide”. Una decisión de agente debería poder explicarse después: qué sabía, qué acciones podía ejecutar, cuáles estaban bloqueadas, qué coste esperaba pagar, qué riesgo aceptaba y por qué eligió una opción concreta. Si no puedes reconstruir esa historia, tienes una caja negra operativa.

Por eso conviene separar dos capas:

E(ast){0,1}E(a \mid s_t) \in \{0,1\} at=argminaA(st),  E(ast)=1F(ast)a_t = \arg\min_{a \in A(s_t),\; E(a \mid s_t)=1} F(a \mid s_t)
CapaPreguntaEjemplo
Elegibilidad E(ast)E(a \mid s_t)¿Se puede ejecutar esta acción ahora?No editar producción sin evidencia; no consultar datos personales sin permiso.
Ranking F(ast)F(a \mid s_t)Entre las acciones permitidas, ¿cuál conviene primero?Leer consola cuesta poco y reduce incertidumbre: buena primera acción.
Parada¿Cuándo dejo de buscar?Responder si hay evidencia suficiente; pedir aprobación si la acción siguiente es destructiva.
Trazabilidad¿Qué debería quedar registrado?Estado inicial, acciones candidatas, puntuación, bloqueos, observaciones y decisión.

Esta separación evita dos errores frecuentes. El primero es usar una puntuación blanda para permitir acciones que deberían estar prohibidas. Si una acción requiere aprobación, no debería “ganar” por tener buen score: debería quedar bloqueada hasta tener autorización. El segundo es esconder las razones de la política dentro de un prompt. Puedes usar un LLM como parte del sistema, pero el contrato operativo —presupuestos, permisos, formato, evidencias mínimas y criterios de parada— debe existir fuera del texto improvisado.

En agentes con herramientas, esta trazabilidad también sirve para depurar. Si el agente gastó diez llamadas antes de leer el error principal, el problema no era “el modelo”: era la política. Si editó código antes de mirar una prueba mínima, el problema no era “la IA”: era que no había una precondición de evidencia.

Un agente moderno también busca La frontera no contiene solo nodos: contiene próximas acciones posibles. Estado st memoria + observaciones restricciones + objetivo Frontera de acciones leer test preguntar Tool ejecutada acción at devuelve observación F(a | st) = G(a | st) + H(a | st) + R(a | st) coste operativo + distancia estimada + riesgo at = argmin F(a | st) Agente Greedy Agente tipo A* Agente robusto minimiza solo H equilibra G + H equilibra G + H + R IA para gente curiosa / Facsímil 02 / Capítulo 04 / 686f6c61

En el día a día

Imagina un agente de código que recibe: “la página falla al cargar”. Puede hacer muchas cosas. Leer el error de consola. Abrir el navegador. Buscar en el repositorio. Ejecutar tests. Mirar el último commit. Preguntar al usuario. Todas son acciones válidas, pero no todas son igual de buenas.

Una política Greedy elegiría lo que parece más directo: “abrir el navegador”. Puede funcionar. Pero si no mira los logs, quizá pierda diez minutos en la pantalla equivocada. Una política tipo A* ponderaría el coste y la información esperada: “leer el error de consola cuesta poco y reduce mucho la incertidumbre; hagamos eso primero”.

En producción, esta diferencia se traduce en dinero y fiabilidad. Un agente que llama a diez herramientas para resolver una pregunta sencilla no solo es más lento: también introduce más puntos de fallo. Un agente que responde demasiado pronto parece rápido, pero puede inventar. El buen diseño está en equilibrar información, coste y riesgo.5

Por qué debería importarte

La búsqueda clásica te da un vocabulario para diseñar agentes modernos sin confundir una salida fluida con una decisión controlada. Si defines mal el estado, el agente se pierde. Si defines mal las acciones, no puede llegar a la solución. Si ignoras el coste, se vuelve caro. Si ignoras el riesgo, se vuelve peligroso. Si la heurística es mala, parece inteligente mientras da vueltas.

Esto es especialmente importante porque los LLMs son convincentes. Pueden explicar una decisión con mucha seguridad aunque la decisión sea mala. La estructura de búsqueda te obliga a preguntar: ¿qué estado tenía?, ¿qué acciones consideró?, ¿qué coste pagó?, ¿qué evidencia observó?, ¿por qué eligió esa acción y no otra?

Dónde solía tropezar yo

ErrorPor qué es un errorAntídoto
Llamar “agente” a cualquier prompt con herramientasTener tools no basta. Un agente necesita estado, acciones, criterio de decisión y actualización tras observar resultados.Dibuja sts_t, A(st)A(s_t), ata_t y st+1s_{t+1}. Si no puedes, todavía no hay diseño de agente.
Hacer tool selection puramente GreedyLa herramienta obvia puede ser cara, arriesgada o prematura.Añade coste GG y riesgo RR al criterio de decisión.
No modelar el coste en tokens y latenciaUn agente puede ser correcto y aun así inviable si tarda demasiado o cuesta demasiado.Define presupuesto antes de ejecutar: tokens máximos, llamadas máximas y tiempo máximo.
Confundir observación con verdadUna tool puede devolver datos incompletos, antiguos o mal interpretados.Guarda la fuente de cada observación y verifica las decisiones importantes.
Recapitular sin comprobarLeer “ya lo entiendo” no equivale a poder reconstruirlo.Usa las preguntas de revisión activa; si fallas una, vuelve al capítulo concreto.

Manos a la obra

La práctica real está en kit descargable. El kit simula un agente de ingeniería que recibe una incidencia: la página de checkout falla. Tiene varias acciones candidatas, pero no todas son elegibles. Algunas son baratas y aportan evidencia; otras son caras; otras requieren aprobación porque tocan datos o podrían modificar código sin pruebas.

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/rank_agent_actions.py --write
cat output/agent_action_decision.md

Como gate:

python3 ops/rank_agent_actions.py --write --fail-on-invalid

Qué deberías ver. El sistema separa acciones bloqueadas de acciones elegibles. Después ordena las elegibles con F=G+H+RF=G+H+R. La mejor primera acción no es “editar rápido”, sino recoger evidencia barata: leer la consola del navegador. Eso enseña una regla práctica: un agente útil no solo elige lo que parece acercarle a la solución; también respeta precondiciones.

ArchivoPapel
data/agent_case.jsonIncidencia, estado inicial y acciones candidatas.
contracts/action_policy.jsonPesos de coste, incertidumbre y riesgo; presupuestos y bloqueos duros.
ops/rank_agent_actions.pyMotor de ranking y auditoría sin dependencias externas.
output/agent_action_report.jsonResultado estructurado para revisión automática.
output/agent_action_decision.mdDecisión legible: acción recomendada, ranking y bloqueos.

Cómo lo adaptas a tu caso. Cambia las acciones candidatas por herramientas reales de tu proyecto: leer logs, ejecutar tests, consultar documentación interna, pedir aprobación, abrir un ticket o llamar a una API. Después ajusta pesos y bloqueos. Si una acción peligrosa gana el ranking, el contrato está mal: no deberías arreglarlo con un prompt, sino con una regla de elegibilidad.

Qué entregaría un alumno. El Markdown generado, una acción nueva añadida al caso, una justificación de sus valores GG, HH y RR, y una decisión escrita sobre qué acción ejecutaría primero y cuál quedaría bloqueada.

Recapitulación activa del bloque de búsqueda

Este cierre funciona como el capítulo 12 del facsímil 1: no es un resumen para leer rápido, sino una revisión activa. Si una sección no te sale, vuelve al capítulo indicado.

1. Búsqueda como espacio de estados

El concepto. Un problema de búsqueda se define con estado inicial, acciones, función de transición, prueba de meta y coste. Si una de esas piezas está borrosa, el algoritmo no tiene dónde agarrarse.6

Para recordar. El estado no es “todo lo que existe”: es solo la información necesaria para decidir la siguiente acción. Meter información irrelevante infla el espacio de búsqueda.

Ejemplo fresco. En un laberinto, el estado puede ser la coordenada (x,y)(x,y). No necesitas guardar el color de la pared ni la hora del día. En un agente de código, el estado puede incluir error, archivos leídos y tests ejecutados; no necesita recordar cada token de una conversación si ya tiene un resumen fiable.

Vuelve al capítulo 1 si: no puedes definir estado, acción, meta y coste para un problema cotidiano.

2. BFS, DFS, UCS e IDS

El concepto. La frontera determina el algoritmo. Cola FIFO produce BFS. Pila LIFO produce DFS. Cola de prioridad por g(n)g(n) produce UCS. DFS con límites crecientes produce IDS.7

Para recordar. BFS es completo y óptimo con costes uniformes, pero consume memoria O(bd)O(b^d). DFS consume mucha menos memoria, O(bm)O(b \cdot m), pero no garantiza optimalidad. UCS generaliza BFS cuando las acciones cuestan distinto.

Ejemplo fresco. Si todas las calles pesan igual, BFS encuentra el camino con menos cruces. Si unas calles son autopistas y otras caminos lentos, necesitas UCS. Si el espacio es enorme y solo quieres no quedarte sin memoria, IDS es el puente.

Vuelve al capítulo 2 si: no puedes explicar por qué cambiar cola por pila cambia completamente el comportamiento.

3. Greedy, A* y heurísticas

El concepto. Greedy usa f(n)=h(n)f(n)=h(n). A* usa f(n)=g(n)+h(n)f(n)=g(n)+h(n). La heurística h(n)h(n) es una estimación de lo que falta, y su calidad decide cuántos estados se exploran.8

Para recordar. Greedy es rápido porque ignora el coste acumulado. A* es más disciplinado porque suma lo que ya pagaste y lo que estimas que falta. Con hh admisible, A* conserva garantías de optimalidad.9

Ejemplo fresco. En una rejilla, Manhattan puede decirte cuántos pasos mínimos faltan si solo te mueves en horizontal y vertical. Esa estimación no resuelve el problema, pero evita explorar media ciudad.

Vuelve al capítulo 3 si: no puedes explicar admisibilidad, consistencia y dominancia de heurísticas.

4. Agentes modernos

El concepto. Un agente moderno selecciona acciones en un estado parcialmente observado, ejecuta herramientas, recibe observaciones y actualiza su estado. La búsqueda puede ser implícita, pero sigue estando ahí.

Para recordar. “LLM + tools” no es automáticamente un buen agente. Hace falta una política: cuándo usar herramientas, cuáles priorizar, cuándo parar, cuándo pedir aclaración y cuándo responder.

Ejemplo fresco. Ante un fallo de build, un agente prudente no edita a ciegas. Primero lee el error, identifica el archivo probable, ejecuta el test mínimo, modifica, y vuelve a verificar. Eso es búsqueda guiada por evidencia.

Vuelve a este capítulo si: no puedes mapear un agente a sts_t, A(st)A(s_t), ata_t, observación y st+1s_{t+1}.

Cómo encaja todo

Este mapa cierra el primer bloque del facsímil. Los capítulos 1, 2 y 3 nos dieron el lenguaje clásico: estado, frontera, coste real y heurística. Aquí usamos ese lenguaje para leer un agente moderno sin caer en la fantasía de que todo ocurre dentro del modelo.

La decisión nueva es separar propuesta, elegibilidad, puntuación, ejecución y observación. Esa separación volverá en restricciones, planificación, agentes de software y operación.

graph TD
    subgraph "Capítulos 1-3: búsqueda explícita"
        C01["Cap. 1: estado, acción, meta y coste"]
        C02["Cap. 2: frontera FIFO, LIFO y g(n)"]
        C03["Cap. 3: h(n), admisibilidad y A*"]
    end
    subgraph "Capítulo 4: agente como búsqueda implícita"
        STATE["Estado s_t: memoria, observaciones, restricciones y objetivo"]
        CANDIDATES["A(s_t): acciones candidatas"]
        ELIGIBILITY["E(a|s_t): permisos, presupuesto y precondiciones"]
        SCORE["F(a|s_t)=G+H+R"]
        TOOL["Tool ejecutada"]
        OBS["Observación nueva"]
        STOP["Criterio de parada o siguiente iteración"]
    end
    subgraph "Lo que viene después"
        CSP["Cap. 5-8: restricciones y guardrails"]
        PLAN["Cap. 9-10: planificación"]
        GAMES["Cap. 11: otros actores eligen"]
        SYMBOLIC["Cap. 12: conocimiento simbólico"]
        AGENTS["Fasc. 5: agentes de software"]
    end

    C01 --> STATE
    C02 --> CANDIDATES
    C03 --> SCORE
    STATE --> CANDIDATES
    CANDIDATES --> ELIGIBILITY
    ELIGIBILITY --> SCORE
    SCORE --> TOOL
    TOOL --> OBS
    OBS --> STATE
    OBS --> STOP
    ELIGIBILITY --> CSP
    STOP --> PLAN
    SCORE --> GAMES
    OBS --> SYMBOLIC
    TOOL --> AGENTS

    style STATE fill:#F5F5F5,stroke:#000000,stroke-width:2
    style ELIGIBILITY fill:#F5F5F5,stroke:#000000,stroke-width:2
    style SCORE fill:#F5F5F5,stroke:#000000,stroke-width:2
    style CSP stroke-dasharray: 5 5
    style PLAN stroke-dasharray: 5 5
    style GAMES stroke-dasharray: 5 5
    style SYMBOLIC stroke-dasharray: 5 5
    style AGENTS stroke-dasharray: 5 5
Facsímil 2: bloque de búsqueda De formular problemas a diseñar agentes que deciden con coste, heurística y riesgo. Cap. 1 Cap. 2 Cap. 3 Cap. 4 espacio de estados búsqueda ciega heurísticas agentes modernos S, A, T, meta, c FIFO · LIFO · g(n) h(n) · g(n)+h(n) G + H + R Idea madre Diseñar inteligencia práctica es diseñar una buena representación, una frontera útil y una política de decisión verificable. IA para gente curiosa / Facsímil 02 / Capítulo 04 / 686f6c61

Vocabulario aprendido

TérminoDefinición
Agente de búsquedaSistema que elige acciones para avanzar desde un estado hacia una meta.
Estado de agenteRepresentación compacta de lo que el agente sabe y de las restricciones activas.
Tool selectionElección de la siguiente herramienta o acción que conviene ejecutar.
Coste operacionalTokens, latencia, dinero, riesgo y complejidad acumulados al actuar.
Heurística aprendidaEstimación producida por un modelo o regla para priorizar acciones.
Política de decisiónRegla que transforma estado y acciones disponibles en una acción concreta.
Criterio de paradaCondición que decide si el agente responde, pide aprobación, sigue buscando o escala.
Trazabilidad de decisiónRegistro de estado, acciones candidatas, bloqueos, puntuaciones y observaciones.

Antes de pasar página

  • ¿Puedo explicar cómo un agente con tools se modela como búsqueda?
  • ¿Puedo escribir qué representa st=(mt,ot,rt,q)s_t = (m_t, o_t, r_t, q)?
  • ¿Sé diferenciar una política Greedy de una política que incluye coste y riesgo?
  • ¿Puedo separar acciones bloqueadas de acciones elegibles antes de rankear?
  • ¿Puedo recapitular BFS, DFS, UCS, Greedy y A* sin mirar?
  • ¿Entiendo por qué el siguiente bloque, CSP, sigue siendo búsqueda pero con restricciones?

En resumen

Idea fuerzaDetalle
Los agentes modernos no eliminan la búsqueda: la esconden.Cada decisión de tool es una elección entre acciones candidatas.
El estado decide lo que el agente puede razonar.Si el estado omite información relevante, la política tomará malas decisiones.
G+H+RG + H + R es una brújula útil.Coste, heurística y riesgo permiten diseñar agentes menos impulsivos que un Greedy puro.
La elegibilidad va antes que el ranking.Una acción prohibida o sin permisos no debería ganar por tener buen score.
El bloque de búsqueda ya está cerrado.Estados, frontera, coste, heurística y política quedan listos para CSP, planificación y juegos.

Para saber más

Hart, P. E., Nilsson, N. J. y Raphael, B. (1968). A formal basis for the heuristic determination of minimum cost paths. IEEE Transactions on Systems Science and Cybernetics, 4(2), 100-107. https://doi.org/10.1109/TSSC.1968.300136

Luger, G. F. (2008). Artificial intelligence: structures and strategies for complex problem solving (6.ª ed.). Pearson.

Nilsson, N. J. (1998). Artificial intelligence: a new synthesis. Morgan Kaufmann.

Pearl, J. (1984). Heuristics: intelligent search strategies for computer problem solving. Addison-Wesley.

Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press.

Rich, E., Knight, K. y Nair, S. B. (2009). Artificial intelligence (3.ª ed.). McGraw-Hill.

Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. https://aima.cs.berkeley.edu/

Notas

  1. Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. El capítulo 2 define los agentes racionales como sistemas que seleccionan acciones para maximizar una medida de rendimiento, una idea que conecta directamente con la búsqueda como selección de acciones.

  2. Nilsson, N. J. (1998). Artificial intelligence: a new synthesis. Morgan Kaufmann. Nilsson conecta búsqueda, planificación y agentes como variantes de un mismo problema de decisión secuencial.

  3. Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press. Su marco de búsqueda como transición entre estados permite modelar tanto algoritmos clásicos como agentes que intercalan percepción, acción y actualización de creencias.

  4. Hart, P. E., Nilsson, N. J. y Raphael, B. (1968). A formal basis for the heuristic determination of minimum cost paths. IEEE Transactions on Systems Science and Cybernetics, 4(2), 100-107. https://doi.org/10.1109/TSSC.1968.300136. A* formalizó la combinación de coste acumulado y estimación restante; esa idea sigue siendo una plantilla útil para razonar sobre agentes con herramientas.

  5. Luger, G. F. (2008). Artificial intelligence: structures and strategies for complex problem solving (6.ª ed.). Pearson. El capítulo 3 insiste en que la eficiencia de una búsqueda depende tanto de la representación del problema como de la estrategia de control.

  6. Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson.

  7. Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press.

  8. Pearl, J. (1984). Heuristics: intelligent search strategies for computer problem solving. Addison-Wesley.

  9. Hart, P. E., Nilsson, N. J. y Raphael, B. (1968). A formal basis for the heuristic determination of minimum cost paths. IEEE Transactions on Systems Science and Cybernetics, 4(2), 100-107. https://doi.org/10.1109/TSSC.1968.300136.

Capítulo 05

Facsímil 2 · Inteligencia clásica

Capítulo 05: SAT y CSP: la IA como restricciones

Entrando en el tema

Imagina que tienes que organizar una semana de reuniones. Hay salas, franjas horarias, personas que no pueden coincidir, permisos, duraciones distintas y una regla sencilla: la agenda final no puede tener solapes. Un modelo generativo puede proponer una agenda bonita. Pero bonita no significa válida.

Aquí aparece una idea muy antigua y muy viva de la inteligencia artificial: no todo consiste en generar una respuesta; a veces consiste en encontrar una asignación que cumpla reglas exactas.1 Si una sala no puede estar en dos reuniones a la vez, esa regla no es una sugerencia. Es una restricción.

SAT y CSP son dos formas clásicas de expresar ese tipo de problema. SAT trabaja con variables booleanas: verdadero o falso. CSP trabaja con variables que pueden tomar valores de dominios más ricos: horas, salas, personas, rutas, configuraciones. En ambos casos, la pregunta central es la misma: ¿existe una solución que cumpla todas las reglas?

No estamos buscando texto plausible

El malentendido habitual es pensar que SAT y CSP son algoritmos viejos para problemas académicos. En realidad, son una forma de disciplina. Te obligan a separar tres cosas que conviene no mezclar:

CapaQué haceEjemplo
InterpretarEntender una petición ambigua.“Busca una agenda para el equipo esta semana”.
ProponerConstruir candidatos posibles.Tres horarios alternativos.
VerificarAceptar solo lo que cumple reglas.Sin solapes, sala disponible, permisos correctos.

Un LLM puede ayudar en las dos primeras capas. Puede leer lenguaje natural, resumir preferencias y proponer candidatos. Pero la tercera capa debería ser verificable: un solver, un validador, un esquema JSON, una política de permisos, una regla de negocio o una combinación de todo eso.

La lección del capítulo es esta: cuando hay reglas duras, la aceptación no debe depender de si la respuesta suena convincente.

Antes de entrar en la notación, quédate con dos imágenes sencillas:

Problema cotidianoCómo lo ve SAT o CSPPregunta que responde
Activar o no activar opciones de una campaña.SAT lo ve como interruptores: email sí/no, banner sí/no, aprobación legal sí/no.¿Hay alguna combinación de interruptores compatible con todas las reglas?
Colocar reuniones en una agenda.CSP lo ve como huecos que hay que rellenar: reunión 1 a las 9:00 o 10:00, reunión 2 a las 9:00 o 10:00.¿Qué valor pongo en cada hueco para que no haya conflictos?
Aceptar una acción de un agente.Un validador lo ve como una puerta: pasa si cumple permisos, formato, coste y estado.¿Esta acción se puede ejecutar o debe rechazarse?

La matemática que viene ahora formaliza esa idea. SAT habla de interruptores. CSP habla de huecos con valores posibles. Los validadores hablan de puertas que se abren o se cierran.

SAT: verdadero, falso y contradicción

SAT, abreviatura de satisfacibilidad booleana, pregunta si existe una asignación de valores verdadero/falso que hace verdadera una fórmula lógica. Cook demostró en 1971 que SAT es NP-completo, convirtiéndolo en una piedra angular de la teoría de la complejidad.2 Hoy SAT sigue siendo práctico porque los solvers modernos explotan estructura, propagación y aprendizaje de cláusulas.3

Piensa en una campaña muy simple. El equipo quiere publicar una oferta, pero hay reglas:

VariableSignificado cotidianoValor posible
AAEnviar la oferta por email.Sí o no.
BBMostrar la oferta como banner en la app.Sí o no.
CCTener el texto aprobado por legal.Sí o no.

Las reglas son igual de simples:

  1. La oferta debe salir por al menos un canal: email o banner.
  2. Si sale por email, el texto debe estar aprobado.
  3. Si sale por banner, el texto debe estar aprobado.

SAT convierte esas frases en lógica booleana. No está escribiendo la campaña. Solo comprueba si existe una combinación que respete las reglas.

La forma canónica se llama CNF: una conjunción de cláusulas. Cada cláusula es una disyunción de literales.

φ=j=1mCj,Cj=Lj,{xi,¬xi}\varphi = \bigwedge_{j=1}^{m} C_j, \qquad C_j = \bigvee_{\ell \in L_j} \ell, \qquad \ell \in \{x_i, \neg x_i\}
SímboloSignificadoEjemplo
φ\varphiFórmula booleana completa que queremos satisfacer.(AB)(¬AC)(A \lor B) \land (\neg A \lor C).
CjC_jCláusula número jj. Debe ser verdadera.C1=(AB)C_1 = (A \lor B).
mmNúmero total de cláusulas.m=3m = 3.
LjL_jConjunto de literales dentro de la cláusula jj.L1={A,B}L_1 = \{A, B\}.
\ellLiteral: variable afirmada o negada.AA o ¬A\neg A.
xix_iVariable booleana.A=verdaderoA=\text{verdadero}: se envía email.

Una asignación es una función que da valor a cada variable:

α:X{0,1}\alpha : X \rightarrow \{0,1\}
SímboloSignificadoEjemplo
α\alphaAsignación concreta de valores.α(A)=1,α(B)=0,α(C)=1\alpha(A)=1, \alpha(B)=0, \alpha(C)=1.
XXConjunto de variables booleanas.X={A,B,C}X=\{A,B,C\}.
{0,1}\{0,1\}Dominio booleano: falso o verdadero.0=falso,1=verdadero0=\text{falso}, 1=\text{verdadero}.

La fórmula es satisfacible si existe al menos una asignación que hace verdaderas todas las cláusulas:

α  j{1,,m}:Cj(α)=1\exists \alpha \; \forall j \in \{1,\dots,m\}: C_j(\alpha)=1
SímboloSignificadoEjemplo
α\exists \alphaExiste una asignación.Probar A=1,B=0,C=1A=1,B=0,C=1.
j\forall jPara toda cláusula.C1,C2,C3C_1, C_2, C_3 deben cumplirse.
Cj(α)C_j(\alpha)Valor de la cláusula jj bajo la asignación α\alpha.C2(α)=1C_2(\alpha)=1.
11Verdadero.La cláusula queda satisfecha.

Veámoslo con la campaña anterior. Tomemos:

φ=(AB)(¬AC)(¬BC)\varphi = (A \lor B) \land (\neg A \lor C) \land (\neg B \lor C)

La primera cláusula dice “usa email o banner”. La segunda dice “si usas email, legal debe estar aprobado”. La tercera dice “si usas banner, legal debe estar aprobado”.

Probamos la asignación α(A)=1\alpha(A)=1, α(B)=0\alpha(B)=0, α(C)=1\alpha(C)=1:

CláusulaSustituciónResultado
ABA \lor B101 \lor 011
¬AC\neg A \lor C010 \lor 111
¬BC\neg B \lor C111 \lor 111

Leído en castellano: enviamos email, no mostramos banner y legal sí ha aprobado el texto. Todas las cláusulas valen 11. Por tanto, la fórmula es SAT y α\alpha es un modelo. Si ninguna asignación de las 23=82^3=8 posibles funcionara, la fórmula sería UNSAT.

Cómo se pasa de frase a cláusula

La parte que más se suele subestimar no es ejecutar un solver, sino codificar bien el problema. Un solver SAT no entiende “legal debe aprobar si hay campaña”. Entiende literales y cláusulas. El trabajo de ingeniería está en traducir sin perder significado.

Frase de negocioLógicaCNF
“Debe haber email o banner.”ABA \lor BABA \lor B
“Si hay email, legal aprueba.”ACA \rightarrow C¬AC\neg A \lor C
“Si hay banner, legal aprueba.”BCB \rightarrow C¬BC\neg B \lor C
“No pueden estar email y banner a la vez.”¬(AB)\neg(A \land B)¬A¬B\neg A \lor \neg B

La equivalencia más útil es esta:

pq¬pqp \rightarrow q \equiv \neg p \lor q
SímboloLecturaPor qué importa
pqp \rightarrow qSi pp, entonces qq.Muchas reglas de negocio tienen esta forma.
¬pq\neg p \lor qO no ocurre pp, o sí ocurre qq.Es la forma que un solver SAT puede consumir en CNF.

Otra familia de reglas aparece continuamente: exactamente uno. Por ejemplo, “elige exactamente un plan”. Se suele partir en dos piezas:

al menos uno: x1x2xn\text{al menos uno: } x_1 \lor x_2 \lor \dots \lor x_n a lo sumo uno: i<j(¬xi¬xj)\text{a lo sumo uno: } \bigwedge_{i<j}(\neg x_i \lor \neg x_j)

Esto enseña una lección práctica: a veces una frase sencilla genera muchas cláusulas. Si tienes 100 opciones y codificas “a lo sumo una” por pares, salen 10099/2=4950100 \cdot 99 / 2 = 4950 cláusulas. No es malo por sí mismo, pero conviene saber qué estás creando.

CSP: variables, dominios y restricciones

Un CSP, problema de satisfacción de restricciones, generaliza la idea. Ya no trabajamos solo con verdadero/falso. Una variable puede ser una sala, una hora, una persona, una ruta, un plan o una configuración. Los primeros trabajos sobre redes de restricciones formalizaron esta forma de representar problemas combinatorios como relaciones entre variables.4 Mackworth popularizó la consistencia de redes de relaciones como herramienta para reducir búsqueda antes de probar soluciones completas.5

CSP es parecido, pero ya no todo cabe en interruptores. Piensa en una agenda: una reunión no es “verdadera” o “falsa”; hay que ponerla a una hora. Una sala no es “verdadera” o “falsa”; hay que elegir cuál. Por eso CSP habla de variables con dominios.

VariablePregunta cotidianaDominio posible
R1R_1¿A qué hora va la reunión de producto?9:00 o 10:00.
R2R_2¿A qué hora va la reunión con cliente?9:00 o 10:00.
R3R_3¿A qué hora va la revisión técnica?9:00 o 10:00.

Formalmente, un CSP se puede escribir así:

P=(X,D,C)\mathcal{P} = (X, D, C)
SímboloSignificadoEjemplo
P\mathcal{P}Problema completo de satisfacción de restricciones.Agenda semanal del equipo.
XXConjunto de variables que hay que asignar.X={R1,R2,R3}X=\{R_1,R_2,R_3\}, tres reuniones.
DDDominios permitidos para esas variables.Cada reunión puede ir a las 9:00 o 10:00.
CCConjunto de restricciones que deben cumplirse.Sin solapes para la misma persona.

Cada variable XiX_i tiene su dominio:

X={X1,,Xn},XiDiX = \{X_1,\dots,X_n\}, \qquad X_i \in D_i
SímboloSignificadoEjemplo
XiX_iVariable individual.R1R_1: reunión de producto.
nnNúmero de variables.n=3n=3.
DiD_iDominio de valores posibles para XiX_i.D1={9,10}D_1=\{9,10\}.
XiDiX_i \in D_iLa variable debe tomar un valor permitido.R1=9R_1=9.

Una restricción es una relación sobre una o varias variables:

Ck=(Sk,Rk)C_k = (S_k, R_k)
SímboloSignificadoEjemplo
CkC_kRestricción número kk.“Ana no puede estar en dos reuniones a la vez”.
SkS_kAlcance de la restricción: variables afectadas.Sk=(R1,R2)S_k=(R_1,R_2).
RkR_kRelación permitida entre los valores de esas variables.R1R2R_1 \neq R_2.

Una asignación aa es solución si asigna un valor permitido a cada variable y todas las restricciones se cumplen:

XiX:  a(Xi)DiyCkC:  Ck(a)=verdadero\forall X_i \in X:\; a(X_i) \in D_i \qquad \text{y} \qquad \forall C_k \in C:\; C_k(a)=\text{verdadero}
SímboloSignificadoEjemplo
aaAsignación de valores a variables.a(R1)=9,a(R2)=10,a(R3)=9a(R_1)=9, a(R_2)=10, a(R_3)=9.
a(Xi)a(X_i)Valor elegido para la variable XiX_i.a(R2)=10a(R_2)=10.
Ck(a)C_k(a)Evaluación de la restricción bajo la asignación aa.R1R2R_1 \neq R_2 es verdadero.
verdadero\text{verdadero}La restricción queda satisfecha.No hay conflicto.

Ejemplo mínimo:

VariableDominioSignificado
R1R_1{9,10}\{9,10\}Reunión de producto.
R2R_2{9,10}\{9,10\}Reunión con cliente.
R3R_3{9,10}\{9,10\}Revisión técnica.

Restricciones:

  1. R1R2R_1 \neq R_2, porque Ana participa en ambas.
  2. R2=10R_2 = 10, porque el cliente solo puede a las 10:00.
  3. R3R2R_3 \neq R_2, porque comparten sala.

Sin restricciones hay 23=82^3=8 asignaciones. Con restricciones, una solución válida es:

a(R1)=9,a(R2)=10,a(R3)=9a(R_1)=9,\qquad a(R_2)=10,\qquad a(R_3)=9

Comprueba:

RestricciónSustituciónResultado
R1R2R_1 \neq R_29109 \neq 10Verdadero
R2=10R_2 = 1010=1010 = 10Verdadero
R3R2R_3 \neq R_29109 \neq 10Verdadero

Esta asignación no es “plausible”. Es válida. Esa diferencia es el corazón del capítulo.

Modelar CSP como ingeniería, no como decoración matemática

Un CSP bien modelado empieza con decisiones de representación. Si eliges mal las variables, el problema explota. Si eliges dominios demasiado grandes, el solver prueba demasiado. Si escondes restricciones globales como muchas restricciones pequeñas sin necesidad, pierdes estructura.

Decisión de modeladoPregunta de ingenieríaConsecuencia
Variables¿Qué estoy asignando realmente?Reunión-franja, persona-turno, tarea-máquina.
Dominio¿Qué valores son posibles antes de buscar?Cuanto más limpio el dominio, menos combinatoria.
Restricciones duras¿Qué no puede violarse nunca?Filtran candidatos inválidos.
Restricciones blandas¿Qué preferimos si se puede?Definen coste entre soluciones válidas.
Granularidad¿Una variable enorme o varias pequeñas?Afecta a propagación, explicación y depuración.

En un sistema real conviene registrar también por qué falla una asignación. “No hay solución” puede ser correcto, pero no siempre es suficiente para operar. Si un horario no existe porque Ana, la sala 2 y el cliente tienen ventanas incompatibles, esa explicación permite corregir datos, relajar preferencias o pedir una decisión humana.

SAT y CSP: de una idea bonita a una solución válida El modelo puede proponer. Las reglas comprobables deciden si algo pasa o se rechaza. Petición humana “Haz una campaña” “Organiza mi agenda” lenguaje ambiguo Candidato texto, plan u horario puede sonar perfecto todavía no es válido Filtro duro sin solapes con permisos con aprobación SAT: interruptores sí/no Caso: publicar una oferta sin saltarse legal. A: email B: banner no C: legal Regla 1: A o B hay al menos un canal Regla 2: si A, entonces C email requiere legal Regla 3: si B, entonces C banner requiere legal Resultado: SAT, combinación válida CSP: rellenar huecos Caso: colocar tres reuniones en dos horas. Variable Dominio Valor R1 producto 9 o 10 9 R2 cliente 9 o 10 10 R3 técnica 9 o 10 9 Reglas: R1 != R2, R2 = 10, R3 != R2 No basta con que parezca una agenda: debe pasar cada regla. Resultado: agenda consistente La regla práctica Si incumple una restricción dura, se rechaza aunque esté muy bien escrito. IA para gente curiosa / Facsímil 02 / Capítulo 05 / 686f6c61

De validez a optimización

Hasta ahora solo hemos preguntado si existe una solución válida. Muchas veces queremos algo más: la mejor solución válida según un coste. Eso nos lleva a la optimización con restricciones, que se puede escribir así:

a=argminaAJ(a)sujeto aCkC:  Ck(a)=verdaderoa^* = \arg\min_{a \in \mathcal{A}} J(a) \quad \text{sujeto a} \quad \forall C_k \in C:\; C_k(a)=\text{verdadero}
SímboloSignificadoEjemplo
aa^*Mejor asignación válida encontrada.Agenda con menos cambios respecto a la semana anterior.
A\mathcal{A}Conjunto de asignaciones candidatas.Todas las agendas posibles.
J(a)J(a)Función de coste o penalización.Número de cambios de sala + preferencias incumplidas.
CkC_kRestricción dura.Nadie puede estar en dos reuniones a la vez.
Ck(a)=verdaderoC_k(a)=\text{verdadero}La asignación cumple la regla kk.El calendario no tiene solapes.

La parte importante es el orden mental: primero validez, después preferencia. Si mezclas reglas duras y preferencias blandas, puedes convertir un problema resoluble en uno imposible.

Ejemplo:

AgendaRestricciones durasCoste J(a)J(a)Decisión
a1a_1Cumple todas5Válida, pero mejorable
a2a_2Incumple un solape1Rechazada aunque sea barata
a3a_3Cumple todas2Mejor válida

La agenda a2a_2 no gana porque su coste sea menor. Si viola una restricción dura, queda fuera. Entre las válidas, elegimos la de menor coste: a3a_3.

En el día a día

SAT y CSP aparecen cada vez que un sistema debe decir “esto se puede” o “esto no se puede” de forma verificable.

En configuración de producto, un cliente puede activar módulos, planes, complementos y permisos. Algunas combinaciones son incompatibles: si plan_basic=true, quizá soporte_dedicado=false. Eso se parece mucho a SAT.

En planificación de turnos, cada persona tiene disponibilidad, descansos mínimos, habilidades, límites legales y preferencias. Eso se parece mucho a CSP: variables con dominios y restricciones entre ellas. Dechter lo trata precisamente como procesamiento de restricciones: reducir dominios, propagar consecuencias y buscar solo donde todavía puede existir solución.6

En sistemas con LLMs, la conexión es todavía más práctica. El modelo puede redactar un plan, pero el sistema debería validar permisos, formato, estados permitidos y acciones peligrosas antes de ejecutar. Ahí SAT y CSP se convierten en arquitectura: no son solo algoritmos, son una forma de separar creatividad y garantía.

Por qué debería importarte

Porque los LLMs son buenos generando candidatos, pero no son garantías. Si pides “haz un horario sin conflictos”, puede devolver algo que parece correcto y contiene un solape escondido. Si pides “crea una configuración compatible”, puede inventar una combinación que viola una regla comercial.

SAT y CSP te enseñan a diseñar sistemas donde la respuesta final no se acepta por estilo, sino por verificación. Esta idea conecta directamente con guardrails, validadores, permisos, planificación, agentes y evaluación. Poole, Mackworth y Goebel presentan esta separación entre representación, inferencia y búsqueda como una de las bases de la IA computacional.7

Dónde solía tropezar yo

ErrorPor qué es un errorAntídoto
Tratar una preferencia como restricción dura“Ana prefiere mañana” no es lo mismo que “Ana solo puede mañana”. Si lo endureces todo, el problema puede volverse imposible.Marca cada regla como dura o blanda antes de modelar. Lo duro filtra; lo blando puntúa.
Pensar que SAT y CSP generan explicacionesUn solver puede decir SAT, UNSAT o devolver una asignación. La explicación pedagógica es otra capa.Usa el solver para validez y una capa aparte para explicar por qué una solución cumple o falla.
Validar después de actuarSi ejecutas una acción y luego descubres que violaba una restricción, ya has convertido un problema lógico en un incidente operativo.Valida antes de hacer commit: antes de enviar, reservar, desplegar o cobrar.
Modelar variables enormesUna variable gigante tiene un dominio inmenso y restricciones difíciles de expresar.Divide el problema en decisiones pequeñas: persona-día, reunión-franja, permiso-acción.

Manos a la obra

La práctica real está en kit descargable. El kit contiene dos problemas: una campaña codificada como SAT y una agenda codificada como CSP con restricciones duras y preferencias blandas. No usa librerías externas; enumera combinaciones para que se vea el mecanismo completo.

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/validate_constraints.py --write
cat output/constraint_decision.md

Como gate:

python3 ops/validate_constraints.py --write --fail-on-invalid

Qué deberías ver. La parte SAT devuelve modelos que satisfacen todas las cláusulas. La parte CSP enumera horarios válidos, rechaza candidatos inválidos con motivo concreto y elige la mejor agenda válida según preferencias blandas.

ArchivoPapel
data/constraint_case.jsonFórmula SAT, CSP de agenda y candidatos a validar.
contracts/constraint_policy.jsonNúmero esperado de modelos, reglas mínimas y coste máximo aceptable.
ops/validate_constraints.pyEnumerador, validador y explicador sin dependencias externas.
output/constraint_report.jsonResultado estructurado para tests o revisión automática.
output/constraint_decision.mdInforme legible para entregar.

Cómo lo adaptas a tu caso. Cambia las variables SAT por flags reales de configuración y cambia el CSP por turnos, salas, rutas o permisos. Después añade un candidato inválido y comprueba que el validador explica qué regla falla.

Qué entregaría un alumno. El Markdown generado, una cláusula SAT nueva, una restricción CSP nueva, un candidato inválido con explicación y una decisión sobre qué reglas deberían ser duras y cuáles blandas.

Cómo encaja todo

Este mapa marca el cambio de fase del facsímil: dejamos de pensar solo en caminos y empezamos a pensar en reglas que una solución debe satisfacer. La búsqueda sigue estando debajo, pero ahora el criterio principal no es “qué nodo miro primero”, sino “qué combinaciones quedan permitidas”.

La decisión aprendida aquí es convertir frases del mundo en restricciones verificables. Esa idea se reutiliza en CSP, guardrails, planificación y sistemas con permisos.

graph TD
    subgraph "Capítulo 5: SAT y CSP"
        RESTR["Reglas duras"]
        SAT["SAT<br/>sí / no"]
        CSP["CSP<br/>huecos con valores"]
        VAL["Validador<br/>acepta o rechaza"]
        OPT["Mejor solución<br/>válida"]
    end
    subgraph "Capítulos anteriores"
        BUSQ["Estados<br/>(cap. 1)"]
        FRON["Frontera<br/>(cap. 2)"]
        HEUR["Heurísticas<br/>(cap. 3)"]
        AGENTES["Agentes<br/>(cap. 4)"]
    end
    subgraph "Capítulos siguientes"
        VARS["Modelar CSP<br/>(cap. 6)"]
        PROP["Propagar<br/>(cap. 7)"]
        GUARD["Guardrails<br/>(cap. 8)"]
        PLAN["Planning SAT<br/>(cap. 10)"]
    end

    BUSQ -->|"formular"| RESTR
    FRON -->|"explorar"| CSP
    HEUR -->|"priorizar"| OPT
    AGENTES -->|"validar"| VAL
    RESTR -->|"booleanas"| SAT
    RESTR -->|"dominios"| CSP
    SAT -->|"modelo / UNSAT"| VAL
    CSP -->|"asignación"| VAL
    CSP -->|"coste"| OPT
    CSP -->|"prepara"| VARS
    VARS -->|"permite"| PROP
    VAL -->|"base de"| GUARD
    SAT -->|"horizonte"| PLAN

    style BUSQ stroke-dasharray: 5 5
    style FRON stroke-dasharray: 5 5
    style HEUR stroke-dasharray: 5 5
    style AGENTES stroke-dasharray: 5 5
    style VARS stroke-dasharray: 5 5
    style PROP stroke-dasharray: 5 5
    style GUARD stroke-dasharray: 5 5
    style PLAN stroke-dasharray: 5 5
    style RESTR fill:#F5F5F5,stroke:#000000,stroke-width:2

Vocabulario aprendido

TérminoDefinición
SATProblema de decidir si una fórmula booleana tiene alguna asignación que la haga verdadera.
UNSATResultado que indica que ninguna asignación cumple todas las cláusulas.
Modelo SATAsignación concreta que satisface la fórmula.
CSPProblema definido por variables, dominios y restricciones.
DominioConjunto de valores permitidos para una variable.
Restricción duraRegla que no se puede violar. Si se viola, la solución se rechaza.
Restricción blandaPreferencia que puede incumplirse pagando un coste o penalización.
Validador deterministaComponente que decide validez aplicando reglas comprobables.

Antes de pasar página

  • ¿Puedo explicar la diferencia entre SAT y CSP sin usar jerga?
  • ¿Sé escribir una fórmula CNF pequeña y probar una asignación?
  • ¿Puedo formular un CSP como P=(X,D,C)\mathcal{P}=(X,D,C)?
  • ¿Distingo una restricción dura de una preferencia blanda?
  • ¿He ejecutado kit descargable y puedo explicar por qué un candidato válido no tiene por qué ser el mejor?
  • ¿Entiendo por qué un LLM puede proponer, pero no debería ser quien garantice la validez final?

En resumen

Idea fuerzaDetalle
SAT pregunta por verdad booleana.Busca una asignación de verdadero/falso que satisfaga todas las cláusulas.
CSP amplía la idea a dominios ricos.Variables, valores permitidos y restricciones describen horarios, permisos, recursos y configuraciones.
Validez y preferencia no son lo mismo.Primero se descartan soluciones inválidas; después se optimiza entre las válidas.
La IA moderna necesita restricciones clásicas.Un LLM puede generar candidatos, pero la aceptación debe pasar por reglas verificables.

Para saber más

Biere, A., Heule, M., van Maaren, H. y Walsh, T. (Eds.). (2009). Handbook of satisfiability. IOS Press.

Cook, S. A. (1971). The complexity of theorem-proving procedures. En Proceedings of the Third Annual ACM Symposium on Theory of Computing (pp. 151-158). ACM. https://doi.org/10.1145/800157.805047

Dechter, R. (2003). Constraint processing. Morgan Kaufmann.

Mackworth, A. K. (1977). Consistency in networks of relations. Artificial Intelligence, 8(1), 99-118. https://doi.org/10.1016/0004-3702(77)90007-8

Montanari, U. (1974). Networks of constraints: Fundamental properties and applications to picture processing. Information Sciences, 7, 95-132. https://doi.org/10.1016/0020-0255(74)90008-5

Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press.

Rossi, F., van Beek, P. y Walsh, T. (Eds.). (2006). Handbook of constraint programming. Elsevier.

Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson.

Notas

  1. Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. Los capítulos sobre búsqueda y satisfacción de restricciones presentan los problemas como asignaciones sometidas a condiciones verificables.

  2. Cook, S. A. (1971). The complexity of theorem-proving procedures. En Proceedings of the Third Annual ACM Symposium on Theory of Computing (pp. 151-158). ACM. https://doi.org/10.1145/800157.805047

  3. Biere, A., Heule, M., van Maaren, H. y Walsh, T. (Eds.). (2009). Handbook of satisfiability. IOS Press.

  4. Montanari, U. (1974). Networks of constraints: Fundamental properties and applications to picture processing. Information Sciences, 7, 95-132. https://doi.org/10.1016/0020-0255(74)90008-5

  5. Mackworth, A. K. (1977). Consistency in networks of relations. Artificial Intelligence, 8(1), 99-118. https://doi.org/10.1016/0004-3702(77)90007-8

  6. Dechter, R. (2003). Constraint processing. Morgan Kaufmann.

  7. Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press.

Capítulo 06

Facsímil 2 · Inteligencia clásica

Capítulo 06: CSP: variables, dominios y restricciones

Entrando en el tema

En el capítulo anterior vimos la idea general: un CSP busca una asignación válida. Ahora toca la parte que parece pequeña y lo cambia todo: cómo eliges las variables, qué valores permites en cada dominio y qué reglas escribes como restricciones.

Parece una decisión de nomenclatura, pero no lo es. Si modelas mal, el solver se ahoga. Si modelas bien, el problema se vuelve transparente. Es la diferencia entre decir “organiza todos los turnos de la semana” y decir “para cada persona y cada día, elige mañana, tarde, noche o libre”.

Un CSP bien modelado no empieza con un algoritmo. Empieza con una pregunta humilde: ¿cuáles son exactamente los huecos que tengo que rellenar?

El problema no es el solver, es el modelado

Piensa en una hoja de cálculo. Cada celda vacía es una decisión pendiente. Algunas celdas solo aceptan ciertos valores. Algunas combinaciones entre celdas están prohibidas. Si rellenas todo sin romper ninguna regla, tienes una solución.

Pieza del CSPImagen cotidianaEjemplo
VariableHueco que hay que rellenar.Hora de la reunión de producto.
DominioValores permitidos para ese hueco.9:00, 10:00 o 11:00.
RestricciónRegla que descarta combinaciones.Ana no puede estar en dos reuniones a la vez.
Asignación parcialHoja a medio rellenar.Producto a las 9:00; cliente todavía sin hora.
SoluciónHoja completa sin reglas rotas.Todas las reuniones colocadas sin solapes.

Esta forma de pensar viene de la programación con restricciones: representar un problema como variables, dominios y relaciones permitidas, y después buscar o propagar hasta encontrar consistencia.1 La parte difícil rara vez es escribir for value in domain. La parte difícil es decidir qué cuenta como variable.

Variables: qué huecos vamos a rellenar

Una variable CSP representa una decisión pendiente. No tiene por qué ser “una cosa del mundo”; puede ser una combinación que nos conviene para modelar. En horarios, una variable puede ser reunión, persona-día, aula-hora, paquete-versión o tarea-máquina.

Formalmente:

X={X1,X2,,Xn}X = \{X_1, X_2, \dots, X_n\}
SímboloSignificadoEjemplo
XXConjunto de todas las variables del problema.Tres cursos que hay que colocar en horario.
XiX_iVariable individual número ii.X1=Curso IAX_1=\text{Curso IA}.
nnNúmero total de variables.n=3n=3.

Ejemplo concreto:

VariableQué decisión representaComentario
X1X_1Dónde y cuándo colocar “Curso IA”.Lo imparte Ana.
X2X_2Dónde y cuándo colocar “Curso Python”.También lo imparte Ana.
X3X_3Dónde y cuándo colocar “Curso Datos”.Necesita sala B.

Aquí hemos elegido una variable por curso. Podríamos haber elegido una variable por franja horaria y sala, pero entonces el valor sería “qué curso pongo aquí”. Las dos opciones pueden ser correctas. La buena es la que permite expresar reglas con menos esfuerzo y menos confusión.

Dominios: qué valores puede tomar cada variable

El dominio de una variable es el conjunto de valores que puede tomar. Si la variable es un curso, su dominio puede ser el conjunto de pares (hora, sala).

Di={vi1,vi2,,viki}XiDiD_i = \{v_{i1}, v_{i2}, \dots, v_{ik_i}\} \qquad X_i \in D_i
SímboloSignificadoEjemplo
DiD_iDominio de la variable XiX_i.Posibles combinaciones de hora y sala.
vijv_{ij}Valor jj permitido para XiX_i.(9,A)(9,\text{A}).
kik_iTamaño del dominio de XiX_i.Si hay 2 horas y 2 salas, ki=4k_i=4.
XiDiX_i \in D_iLa variable debe recibir un valor de su dominio.“Curso IA” puede ir a (9,A)(9,\text{A}).

Para nuestro ejemplo:

D1=D2=D3={(9,A),(9,B),(10,A),(10,B)}D_1 = D_2 = D_3 = \{(9,A), (9,B), (10,A), (10,B)\}

Cada curso puede colocarse a las 9:00 o a las 10:00, en sala A o B. Sin restricciones, el número de asignaciones posibles es:

A=i=1nDi|\mathcal{A}| = \prod_{i=1}^{n} |D_i|
SímboloSignificadoEjemplo
A\mathcal{A}Conjunto de asignaciones completas candidatas.Todos los horarios posibles antes de filtrar.
$\mathcal{A}$
$D_i$
\prodProducto de los tamaños de dominio.Multiplicar 4444\cdot4\cdot4.

Con tres cursos y cuatro opciones por curso:

A=43=64|\mathcal{A}| = 4^3 = 64

Sesenta y cuatro horarios candidatos no parecen muchos. Pero si tienes 30 eventos y cada uno tiene 20 opciones, el espacio sería 203020^{30}. Ahí ya no estás rellenando una hoja: estás mirando un océano.

Auditar dominios antes de resolver

Un buen modelo CSP no espera al solver para eliminar lo obvio. Si una restricción unaria dice que Python solo puede ir a las 10:00, no tiene sentido conservar valores de Python a las 9:00 en el dominio inicial. Eso no es “hacer trampa”: es escribir mejor el problema.

Podemos comparar dos tamaños:

Abruta=iDi|\mathcal{A}_{bruta}| = \prod_i |D_i| Apodada=iDi|\mathcal{A}_{podada}| = \prod_i |D'_i|
SímboloSignificadoEjemplo
DiD_iDominio original.Python: (9,A),(9,B),(10,A),(10,B)(9,A),(9,B),(10,A),(10,B).
DiD'_iDominio podado por reglas unarias.Python: (10,A),(10,B)(10,A),(10,B).
$\mathcal{A}_{bruta}$
$\mathcal{A}_{podada}$

La diferencia entre 64 y 16 en un ejemplo pequeño no impresiona demasiado. La diferencia entre 203020^{30} y algo dos órdenes de magnitud menor sí puede decidir si tu sistema responde hoy o nunca.

Restricciones: qué combinaciones quedan prohibidas

Una restricción dice qué combinaciones de valores son aceptables. Puede afectar a una variable, a dos o a muchas. Montanari formalizó estas redes de restricciones como relaciones entre variables, una idea que después se volvió central en CSP.2

Formalmente:

Ck=(Sk,Rk)C_k = (S_k, R_k)
SímboloSignificadoEjemplo
CkC_kRestricción número kk.“Ana no puede impartir dos cursos a la misma hora”.
SkS_kAlcance: variables afectadas por la restricción.Sk=(X1,X2)S_k=(X_1, X_2).
RkR_kRelación permitida entre valores.Hora de X1X_1 distinta de hora de X2X_2.

En nuestro horario:

TipoReglaCómo se lee
Unariahora(X2)=10hora(X_2)=10Python solo puede ir a las 10:00.
Unariasala(X3)=Bsala(X_3)=BDatos necesita sala B.
Binariahora(X1)hora(X2)hora(X_1)\neq hora(X_2)Ana imparte IA y Python; no puede duplicarse.
Globalall_different((hora, sala))Dos cursos no pueden ocupar la misma sala a la misma hora.

Una asignación aa es válida cuando todas las restricciones son verdaderas:

valida(a)=CkCCk(a)\operatorname{valida}(a) = \bigwedge_{C_k \in C} C_k(a)
SímboloSignificadoEjemplo
aaAsignación completa de valores.IA (9,A)(9,A), Python (10,A)(10,A), Datos (9,B)(9,B).
valida(a)\operatorname{valida}(a)Indica si la asignación cumple todas las reglas.Verdadero si no hay solapes ni salas incorrectas.
\bigwedge“Y” lógico: todo debe cumplirse.Si una regla falla, toda la asignación falla.
Ck(a)C_k(a)Resultado de evaluar la restricción kk sobre aa.hora(X1)hora(X2)hora(X_1)\neq hora(X_2).

Probemos esta asignación:

a(X1)=(9,A),a(X2)=(10,A),a(X3)=(9,B)a(X_1)=(9,A),\qquad a(X_2)=(10,A),\qquad a(X_3)=(9,B)
RestricciónSustituciónResultado
hora(X2)=10hora(X_2)=1010=1010=10Verdadero
sala(X3)=Bsala(X_3)=BB=BB=BVerdadero
hora(X1)hora(X2)hora(X_1)\neq hora(X_2)9109\neq10Verdadero
No compartir sala y hora(9,A),(10,A),(9,B)(9,A),(10,A),(9,B) son distintosVerdadero

La asignación es válida. No porque “parezca buena”, sino porque supera cada regla.

Anatomía de un CSP: una mesa de modelado Convertimos una petición cotidiana en huecos, opciones, reglas y una solución verificable. Petición original “Coloca tres cursos en dos horas y dos salas, sin solapes y respetando condiciones especiales.” Huecos las variables que vamos a rellenar X1 · Curso IA X2 · Curso Python X3 · Curso Datos Opciones el dominio de cada variable 9 · A 9 · B 10 · A 10 · B Reglas restricciones que filtran Python solo a las 10 Datos necesita sala B Ana no puede duplicarse Nadie comparte sala-hora Una candidata se coloca en la mesa y se verifica IA 9 · A Python 10 · A Datos 9 · B Veredicto válida La solución no se cree: pasa por todas las reglas IA para gente curiosa / Facsímil 02 / Capítulo 06 / 686f6c61

Restricciones unarias, binarias y globales

Conviene poner nombre a los tipos de restricción porque cada uno cambia cómo se resuelve el problema.

TipoAfecta aEjemplo entendiblePapel práctico
UnariaUna variable.Python solo puede ir a las 10:00.Reduce un dominio individual.
BinariaDos variables.IA y Python no pueden tener la misma hora.Conecta dos decisiones.
GlobalMuchas variables.Ningún curso comparte sala y hora.Expresa reglas de conjunto sin escribir miles de pares.
BlandaUna o muchas variables, con penalización.Preferimos sala A, pero sala B vale.Optimiza sin convertir preferencias en imposibles.

Mackworth mostró que muchas restricciones binarias pueden verse como arcos entre variables y que limpiar inconsistencias locales reduce muchísimo la búsqueda posterior.3 Esta idea nos llevará al capítulo 7: propagación y backtracking.

La aridad de una restricción es cuántas variables toca. Una unaria tiene aridad 1; una binaria, aridad 2; una global puede tener aridad nn. Esto importa porque afecta a cómo depuras el problema. Una restricción unaria suele explicar fallos muy localmente: “Python no puede ir a las 9”. Una global puede explicar fallos de conjunto: “dos cursos comparten sala-hora”. En sistemas reales conviene que cada restricción tenga identificador, descripción humana y datos suficientes para explicar por qué rechazó una asignación.

En el día a día

En producto, los dominios aparecen como opciones de configuración. Un plan puede aceptar o no ciertos módulos, regiones, monedas, permisos o límites. Cada elección abre y cierra posibilidades.

En operaciones, los dominios aparecen como calendarios, turnos, recursos y máquinas disponibles. Si el dominio incluye valores que nunca deberían usarse, el solver perderá tiempo y quizás proponga soluciones absurdas.

En agentes con LLMs, las variables pueden ser más abstractas: qué herramienta usar, qué permisos pedir, qué paso ejecutar después, qué formato devolver. Nilsson ya presentaba búsqueda, planificación y agentes como problemas de decisión secuencial; los CSP añaden una capa útil cuando esas decisiones deben respetar restricciones explícitas.4

Por qué debería importarte

Porque modelar un CSP es diseñar el contrato entre el mundo y el solver. Si haces variables demasiado grandes, el dominio explota. Si haces variables demasiado pequeñas, las restricciones se vuelven difíciles de leer. Si confundes reglas duras con preferencias, el sistema rechaza soluciones útiles o acepta soluciones peligrosas.

Russell y Norvig insisten en que la representación importa tanto como el algoritmo: un buen espacio de estados o una buena formulación de restricciones puede hacer que una búsqueda difícil se vuelva manejable.5 En IA aplicada, esa frase se traduce así: antes de pedirle inteligencia al solver, dale un problema bien escrito.

Dónde solía tropezar yo

ErrorPor qué es un errorAntídoto
Elegir variables demasiado grandesUna variable “horario completo de la semana” tiene un dominio gigantesco y opaco.Divide en decisiones pequeñas: curso, reunión, persona-día, tarea-máquina.
Meter valores imposibles en el dominioSi Ana nunca trabaja de noche, no pongas “noche” en su dominio para filtrarlo después.Limpia dominios antes de escribir restricciones complejas.
Escribir restricciones repetidas a manoCien reglas binarias pueden ocultar una regla global sencilla.Busca patrones: “todos distintos”, “exactamente dos”, “al menos uno”, “capacidad máxima”.
Confundir ausencia de solución con fallo del solverA veces el problema está realmente sobre-restringido.Prueba con menos restricciones y añade reglas una a una para localizar la contradicción.

Manos a la obra

La práctica real está en kit descargable. El kit toma el horario de este capítulo, lo guarda como modelo JSON y produce una auditoría: tamaño bruto del espacio, dominios podados por restricciones unarias, soluciones válidas, coste de preferencias y explicación de candidatos rechazados.

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/audit_csp_model.py --write
cat output/csp_model_decision.md

Como gate:

python3 ops/audit_csp_model.py --write --fail-on-invalid

Qué deberías ver. El espacio bruto tiene 43=644^3=64 candidatos. Tras aplicar restricciones unarias al dominio, baja a 16. Después las restricciones binarias y globales dejan cuatro soluciones válidas. Esta es la lectura importante: modelar bien reduce búsqueda antes de buscar.

ArchivoPapel
data/course_schedule_model.jsonVariables, dominios, restricciones, preferencias y candidatos.
contracts/csp_model_policy.jsonCondiciones esperadas para validar la auditoría.
ops/audit_csp_model.pyAuditor de dominios, restricciones y soluciones sin dependencias externas.
output/csp_model_report.jsonResultado estructurado del modelo.
output/csp_model_decision.mdInforme legible para entregar.

Cómo lo adaptas a tu caso. Añade un curso, una sala o una restricción global nueva. Mira cómo cambia Abruta|\mathcal{A}_{bruta}|, Apodada|\mathcal{A}_{podada}| y el número de soluciones. Si al añadir una regla te quedas sin soluciones, el informe te dirá qué restricciones están rechazando candidatos.

Qué entregaría un alumno. El Markdown generado, una variable nueva, una restricción nueva con identificador y explicación, y una comparación de tamaño antes y después de podar dominios.

Cómo encaja todo

Este mapa se lee como una cadena de modelado. El capítulo 5 nos dio la idea general de restricción; este capítulo baja al contrato operativo de un CSP: qué variables existen, qué valores pueden tomar y qué reglas eliminan combinaciones.

La decisión importante no es elegir solver todavía. Es escribir un modelo que se pueda auditar, podar y explicar antes de buscar soluciones.

graph LR
    subgraph "Cap. 5: validez"
        SATCSP["SAT/CSP<br/>reglas verificables"]
        HARD["Restricciones duras<br/>vs blandas"]
    end
    subgraph "Cap. 6: modelado CSP"
        PED["Problema real"]
        VAR["Variables<br/>huecos"]
        DOM["Dominios<br/>opciones"]
        PRUNE["Dominio podado<br/>por unarias"]
        CON["Restricciones<br/>unarias, binarias y globales"]
        ASIG["Asignación<br/>candidata"]
    end
    subgraph "Cap. 7 y 8: ejecución y control"
        PROP["Propagación<br/>cap. 7"]
        BACK["Backtracking<br/>cap. 7"]
        GUARD["Guardrails<br/>cap. 8"]
    end
    subgraph "Conexiones posteriores"
        PLAN["Planificación<br/>cap. 9-10"]
        AGENTS["Agentes<br/>fasc. 5"]
    end

    SATCSP --> PED
    HARD --> CON
    PED -->|"elige huecos"| VAR
    VAR -->|"reciben"| DOM
    DOM -->|"limpia"| PRUNE
    PRUNE -->|"genera menos"| ASIG
    CON -->|"filtra y explica"| ASIG
    DOM -->|"genera"| ASIG
    CON -->|"permite"| PROP
    PROP --> BACK
    ASIG -->|"contrato para"| GUARD
    ASIG -->|"planes válidos"| PLAN
    GUARD -->|"acciones válidas"| AGENTS

    style SATCSP stroke-dasharray: 5 5
    style HARD stroke-dasharray: 5 5
    style PROP stroke-dasharray: 5 5
    style GUARD stroke-dasharray: 5 5
    style PLAN stroke-dasharray: 5 5
    style AGENTS stroke-dasharray: 5 5
    style CON fill:#F5F5F5,stroke:#000000,stroke-width:2
    style PRUNE fill:#F5F5F5,stroke:#000000,stroke-width:2

Vocabulario aprendido

TérminoDefinición
Variable CSPDecisión pendiente que hay que rellenar con un valor.
DominioConjunto de valores permitidos para una variable.
Restricción unariaRegla que afecta a una sola variable.
Restricción binariaRegla que relaciona dos variables.
Restricción globalRegla que afecta a muchas variables a la vez.
Asignación parcialEstado donde algunas variables ya tienen valor y otras no.
Asignación completaEstado donde todas las variables tienen valor.
SoluciónAsignación completa que cumple todas las restricciones duras.
AridadNúmero de variables que toca una restricción.
Dominio podadoDominio reducido antes de buscar, normalmente por restricciones unarias.

Antes de pasar página

  • ¿Puedo explicar qué es una variable CSP usando el ejemplo de una agenda?
  • ¿Sé calcular el número de candidatos con A=iDi|\mathcal{A}|=\prod_i |D_i|?
  • ¿Distingo una restricción unaria de una binaria y una global?
  • ¿Entiendo por qué elegir variables demasiado grandes puede hacer explotar el problema?
  • ¿He ejecutado kit descargable y puedo explicar la diferencia entre espacio bruto y dominio podado?

En resumen

Idea fuerzaDetalle
Modelar es elegir huecos.Las variables son las decisiones que el solver debe rellenar.
El dominio controla el tamaño del problema.Tres variables con cuatro opciones generan 43=644^3=64 candidatos; con muchas variables, el crecimiento explota.
Podar dominios también es ingeniería.Las restricciones unarias pueden eliminar valores antes de que empiece la búsqueda.
Las restricciones convierten candidatos en soluciones.Una asignación solo vale si pasa todas las reglas duras.
La calidad del CSP depende del modelado.Un solver bueno no compensa variables mal elegidas ni dominios llenos de valores imposibles.

Para saber más

Dechter, R. (2003). Constraint processing. Morgan Kaufmann.

Mackworth, A. K. (1977). Consistency in networks of relations. Artificial Intelligence, 8(1), 99-118. https://doi.org/10.1016/0004-3702(77)90007-8

Montanari, U. (1974). Networks of constraints: Fundamental properties and applications to picture processing. Information Sciences, 7, 95-132. https://doi.org/10.1016/0020-0255(74)90008-5

Nilsson, N. J. (1998). Artificial intelligence: A new synthesis. Morgan Kaufmann.

Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press.

Rossi, F., van Beek, P. y Walsh, T. (Eds.). (2006). Handbook of constraint programming. Elsevier.

Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson.

Notas

  1. Rossi, F., van Beek, P. y Walsh, T. (Eds.). (2006). Handbook of constraint programming. Elsevier. El manual organiza el campo precisamente alrededor de modelado, propagación, búsqueda y optimización.

  2. Montanari, U. (1974). Networks of constraints: Fundamental properties and applications to picture processing. Information Sciences, 7, 95-132. https://doi.org/10.1016/0020-0255(74)90008-5

  3. Mackworth, A. K. (1977). Consistency in networks of relations. Artificial Intelligence, 8(1), 99-118. https://doi.org/10.1016/0004-3702(77)90007-8

  4. Nilsson, N. J. (1998). Artificial intelligence: a new synthesis. Morgan Kaufmann.

  5. Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson.

Capítulo 07

Facsímil 2 · Inteligencia clásica

Capítulo 07: Propagación, backtracking y heurísticas en CSP

Entrando en el tema

En el capítulo anterior construimos un CSP pequeño: tres cursos, dos horas, dos salas y varias reglas. Sin restricciones había 43=644^3=64 horarios candidatos. Con reglas, solo quedaban cuatro soluciones válidas.

La pregunta ahora es: ¿tenemos que probar los 64 horarios para descubrirlo? No. Esa es la belleza de los CSP. Antes de buscar, podemos podar. Podemos mirar las reglas y eliminar valores imposibles. Después, cuando toque probar, podemos hacerlo con cabeza: elegir primero la variable más estrecha, detectar contradicciones temprano y volver atrás sin dramatismo.

Este capítulo explica tres ideas que convierten un CSP ingenuo en un método práctico: propagación, backtracking y heurísticas.

No queremos probarlo todo

Imagina que estás rellenando un sudoku. No pruebas números al azar hasta completar la cuadrícula. Primero miras filas, columnas y bloques. Si en una casilla solo puede ir un 7, lo escribes. Si al poner un 7 otra casilla pierde esa opción, actualizas. Solo cuando ya no puedes deducir más, pruebas.

Eso es exactamente lo que hacen los CSP bien resueltos: deducir antes de explorar. Dechter lo resume como procesamiento de restricciones: reducir dominios, detectar inconsistencias y combinar inferencia local con búsqueda.1

EstrategiaQué haceImagen cotidiana
PropagaciónElimina valores imposibles antes de probar.“Python solo puede ir a las 10:00; borra las 9:00”.
BacktrackingPrueba una opción y vuelve atrás si contradice algo.“Si esta sala causa conflicto, deshaz y prueba otra”.
HeurísticasDecide qué variable y qué valor probar primero.“Empieza por quien tiene menos disponibilidad”.

La clave es no confundir inteligencia con fuerza bruta. A veces el algoritmo parece listo porque en realidad evita mirar tonterías.

Propagación: borrar antes de buscar

Propagar significa usar restricciones para reducir dominios. Si una regla dice que Python solo puede ir a las 10:00, no tiene sentido conservar valores a las 9:00 en el dominio de Python.

Podemos escribirlo así:

Di={vDiCk(Xi=v)=verdadero}D_i' = \{v \in D_i \mid C_k(X_i=v)=\text{verdadero}\}
SímboloSignificadoEjemplo
DiD_iDominio original de la variable XiX_i.Python: {(9,A),(9,B),(10,A),(10,B)}\{(9,A),(9,B),(10,A),(10,B)\}.
DiD_i'Dominio reducido después de aplicar una restricción.Python: {(10,A),(10,B)}\{(10,A),(10,B)\}.
vvValor candidato dentro del dominio.(9,A)(9,A).
Ck(Xi=v)C_k(X_i=v)Restricción evaluada al asignar vv a XiX_i.“La hora de Python es 10”.

Con nuestro ejemplo:

VariableDominio inicialRegla aplicadaDominio tras propagar
IA(9,A),(9,B),(10,A),(10,B)(9,A),(9,B),(10,A),(10,B)Ninguna unaria(9,A),(9,B),(10,A),(10,B)(9,A),(9,B),(10,A),(10,B)
Python(9,A),(9,B),(10,A),(10,B)(9,A),(9,B),(10,A),(10,B)Python a las 10(10,A),(10,B)(10,A),(10,B)
Datos(9,A),(9,B),(10,A),(10,B)(9,A),(9,B),(10,A),(10,B)Datos en sala B(9,B),(10,B)(9,B),(10,B)

Solo con dos reglas unarias hemos pasado de 4×4×4=644 \times 4 \times 4 = 64 combinaciones a 4×2×2=164 \times 2 \times 2 = 16. Todavía no hemos buscado. Solo hemos borrado valores imposibles.

Consistencia de arco: cada valor necesita apoyo

La propagación más interesante aparece cuando una restricción conecta dos variables. Mackworth formuló la consistencia de arco como una manera de limpiar dominios mirando si cada valor tiene “apoyo” en la variable vecina.2

Un arco (Xi,Xj)(X_i, X_j) es consistente si:

xDi,  yDj:  Cij(x,y)=verdadero\forall x \in D_i,\; \exists y \in D_j:\; C_{ij}(x,y)=\text{verdadero}
SímboloSignificadoEjemplo
Xi,XjX_i, X_jVariables conectadas por una restricción.IA y Python.
xDix \in D_iValor candidato para XiX_i.IA a las 10:00 en sala A.
yDjy \in D_jValor candidato para XjX_j.Python a las 10:00 en sala B.
Cij(x,y)C_{ij}(x,y)Restricción entre ambas variables.IA y Python no pueden tener la misma hora.
y\exists yExiste al menos un valor compatible al otro lado.IA a las 9:00 sí tiene apoyo.

Como Python ya solo puede ir a las 10:00, cualquier valor de IA a las 10:00 deja de tener apoyo. Si IA va a las 10:00, Ana tendría IA y Python a la vez. Por tanto, se elimina.

Valor de IA¿Hay algún valor de Python compatible?Acción
(9,A)(9,A)Sí: Python puede ir a (10,A)(10,A) o (10,B)(10,B).Se conserva.
(9,B)(9,B)Sí: Python puede ir a (10,A)(10,A) o (10,B)(10,B).Se conserva.
(10,A)(10,A)No: Python siempre va a las 10:00.Se elimina.
(10,B)(10,B)No: Python siempre va a las 10:00.Se elimina.

Después de esta limpieza:

DIA={(9,A),(9,B)}D_{\text{IA}}'=\{(9,A),(9,B)\}

No hemos probado horarios completos. Solo hemos dicho: “si esta opción nunca puede convivir con ninguna opción vecina, fuera”.

Backtracking: probar, fallar, volver

La propagación no siempre resuelve todo. Cuando quedan varias opciones posibles, necesitamos buscar. El método clásico es backtracking: asignar una variable, comprobar consistencia y, si algo falla, deshacer.

Russell y Norvig presentan el backtracking como la búsqueda básica para CSP: una asignación parcial se extiende mientras siga siendo consistente; cuando no puede extenderse, se retrocede.3

La condición de consistencia parcial se puede escribir así:

consistente(ap)=CkCpCk(ap)\operatorname{consistente}(a_p)= \bigwedge_{C_k \in C_p} C_k(a_p)
SímboloSignificadoEjemplo
apa_pAsignación parcial.Python (10,A)(10,A), IA todavía vacía.
CpC_pRestricciones que ya pueden evaluarse con lo asignado.“Python a las 10” sí; “IA distinta de Python” aún no si IA está vacía.
Ck(ap)C_k(a_p)Resultado de evaluar la restricción kk.Verdadero o falso.
\bigwedgeTodas las restricciones evaluables deben cumplirse.Si una falla, se vuelve atrás.

El esquema mental es:

elige variable
prueba valor
si sigue siendo consistente:
    propaga consecuencias
    continúa
si aparece contradicción:
    deshaz y prueba otro valor

No es una caja negra. Es una búsqueda ordenada, con freno y marcha atrás.

Heurísticas: fallar pronto y dejar opciones

Si hay muchas variables, el orden importa. Una buena heurística no “adivina” la solución. Lo que hace es ordenar la búsqueda para descubrir contradicciones pronto y conservar alternativas útiles.4

La primera heurística es MRV (minimum remaining values): elige la variable con menos valores legales restantes.

X=argminXiapDi(ap)X^* = \arg\min_{X_i \notin a_p} |D_i^{(a_p)}|
SímboloSignificadoEjemplo
XX^*Variable elegida para asignar ahora.Python, si solo tiene dos opciones.
XiapX_i \notin a_pVariable todavía no asignada.IA o Datos si Python ya está fijada.
Di(ap)D_i^{(a_p)}Dominio restante después de la asignación parcial.Valores que siguen siendo legales.
argmin\arg\minElige quien minimiza el tamaño del dominio.“Empieza por quien tiene menos margen”.

La segunda es la heurística de grado: si dos variables empatan, elige la que participa en más restricciones pendientes.

X=argmaxXiapgrado(Xi)X^* = \arg\max_{X_i \notin a_p} \operatorname{grado}(X_i)

Y la tercera es LCV (least constraining value): prueba primero el valor que menos opciones elimina a las demás.

v=argminvDiXjXieliminados(XjXi=v)v^* = \arg\min_{v \in D_i} \sum_{X_j \neq X_i} \operatorname{eliminados}(X_j \mid X_i=v)
SímboloSignificadoEjemplo
vv^*Valor que conviene probar primero.IA a las 9:00 en sala A.
eliminados\operatorname{eliminados}Número de valores que se pierden en otra variable.Si elegir sala A bloquea muchas opciones, es peor.
\sumSuma de pérdidas sobre variables vecinas.Total de opciones que dejamos fuera.

Luger resume estas heurísticas como conocimiento de control: no cambian las soluciones válidas, cambian el camino por el que llegas a ellas.5

Qué se mide en una búsqueda CSP seria

Si quieres saber si una estrategia de CSP mejora algo, no basta con decir “encuentra solución”. Hay que medir el trabajo que ha evitado. Dos estrategias pueden devolver las mismas cuatro soluciones y, aun así, una visitar diez nodos y otra sesenta.

MétricaQué midePor qué importa
Nodos visitadosAsignaciones parciales exploradas.Aproxima el trabajo real del backtracking.
Valores podadosOpciones eliminadas de dominios futuros.Enseña si la propagación está haciendo algo útil.
Dominios vacíosContradicciones detectadas pronto.Indica dónde se corta una rama.
Profundidad máximaCuánto llega a comprometerse la búsqueda.Ayuda a entender si falla pronto o tarde.
Orden de variablesQué decide MRV o grado en cada paso.Permite depurar heurísticas de selección.
Soluciones encontradasAsignaciones completas válidas.Resultado final, pero no única métrica.

Esta traza es especialmente útil cuando un CSP real no encuentra solución. Sin traza solo tienes un “no”. Con traza puedes ver si el problema está sobre-restringido, si una variable se queda sin dominio demasiado pronto o si una restricción global está eliminando casi todo.

Resolver un CSP es cerrar puertas cuanto antes La solución no aparece por mirar más ramas, sino por borrar las que ya no pueden funcionar. 1. Espacio ingenuo todo parece posible 4³ = 64 candidatos 2. Propagación reglas unarias y arcos 10,A 10,B 9,A 9,B 64 → 16 candidatos 3. Orden inteligente MRV · grado · LCV elige Python primero deja opciones vivas 4. Backtracking: caminar por el árbol podado Python 10,A rama útil 10,B rama útil IA 9,A IA 10,A Datos 10,A Datos 9,B Poda no cambia la respuesta: cambia cuánto trabajo haces para llegar IA para gente curiosa / Facsímil 02 / Capítulo 07 / 686f6c61

En el día a día

En planificación de turnos, propagación es borrar turnos imposibles antes de construir el calendario: quien no trabaja sábados pierde todos los valores de sábado; quien necesita descanso tras una noche pierde la mañana siguiente.

En configuración de producto, backtracking aparece cuando eliges módulos compatibles. Si activar “facturación avanzada” exige “plan empresa”, y el cliente tiene “plan básico”, esa rama se corta antes de seguir configurando complementos.

En agentes con herramientas, la analogía práctica es clara: no pruebes acciones imposibles. Antes de pedirle al modelo que elija una herramienta, filtra por permisos, estado, coste y disponibilidad. Poole, Mackworth y Goebel conectan esta idea con la separación entre representación e inferencia: si el conocimiento del dominio está bien representado, el razonamiento puede descartar opciones temprano.6

Por qué debería importarte

Porque la diferencia entre resolver y no resolver suele estar en la poda. Dos formulaciones con las mismas soluciones pueden comportarse de forma muy distinta si una detecta contradicciones pronto y la otra las descubre al final.

En sistemas modernos, esto se traduce a coste real: menos llamadas a herramientas, menos tokens, menos latencia, menos acciones rechazadas tarde. La programación con restricciones no es una reliquia; es una forma de diseñar sistemas que no gastan energía explorando lo que ya sabemos que no puede funcionar.7

Dónde solía tropezar yo

ErrorPor qué es un errorAntídoto
Propagar una sola vez y olvidarmeAl borrar valores de un dominio, otras restricciones pueden empezar a borrar nuevos valores.Repite hasta que no cambie nada o hasta encontrar un dominio vacío.
Confundir forward checking con consistencia de arcoForward checking mira consecuencias inmediatas de una asignación; consistencia de arco limpia apoyos entre pares de variables.Recuerda: forward checking ocurre tras elegir; AC mira compatibilidad entre dominios.
Elegir variables en orden arbitrarioPuedes dejar el cuello de botella para el final y descubrir tarde que todo era imposible.Usa MRV y, si hay empate, grado.
Probar primero valores muy restrictivosUn valor que bloquea muchas opciones puede encerrar la búsqueda sin necesidad.Usa LCV cuando conservar alternativas importe.

Manos a la obra

La práctica real está en kit descargable. El kit resuelve el mismo horario del capítulo 6, pero ahora genera una traza completa de backtracking con MRV y forward checking.

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/trace_backtracking.py --write
cat output/backtracking_decision.md

Como gate:

python3 ops/trace_backtracking.py --write --fail-on-invalid

Qué deberías ver. El informe compara candidatos brutos, dominios tras propagación unaria, nodos visitados por backtracking y soluciones encontradas. Además se genera output/backtracking_trace.jsonl, que puedes abrir línea a línea para ver qué variable eligió MRV, qué valores probó y qué dominios se redujeron.

ArchivoPapel
data/backtracking_problem.jsonVariables, dominios y restricciones del horario.
contracts/backtracking_policy.jsonExpectativas mínimas del ejercicio: soluciones, nodos y poda.
ops/trace_backtracking.pyBacktracking con MRV y forward checking sin dependencias externas.
output/backtracking_report.jsonMétricas estructuradas.
output/backtracking_trace.jsonlTraza evento a evento.
output/backtracking_decision.mdInforme legible para entregar.

Cómo lo adaptas a tu caso. Añade una variable nueva y observa cómo suben los candidatos brutos. Después añade una restricción unaria y mira cuánto baja el espacio podado. Si el número de soluciones cae a cero, lee la traza para localizar dónde se vacía un dominio.

Qué entregaría un alumno. El Markdown generado, una captura de tres eventos de la traza, una explicación de por qué MRV eligió una variable concreta y una comparación entre candidatos brutos y nodos visitados.

Cómo encaja todo

Este mapa muestra el paso de modelar a resolver. Venimos de variables, dominios y restricciones; ahora añadimos mecanismos que reducen búsqueda: propagación antes de probar, MRV para elegir dónde duele más y backtracking para volver atrás con criterio.

La idea se reutiliza después en guardrails, planificación y agentes: antes de gastar pasos caros, intenta eliminar opciones imposibles con información barata.

graph LR
    subgraph "Antes de buscar"
        DOM["Dominios<br/>grandes"]
        PROP["Propagación<br/>borra"]
        AC["Arcos<br/>con apoyo"]
    end
    subgraph "Durante la búsqueda"
        MRV["MRV<br/>menos margen"]
        BT["Backtracking<br/>prueba"]
        FC["Forward<br/>checking"]
        CUT["Rama<br/>podada"]
    end
    subgraph "Resultado"
        SOL["Soluciones<br/>válidas"]
        COST["Menos<br/>trabajo"]
    end
    subgraph "Conecta con"
        C6["Modelo CSP<br/>cap. 6"]
        C8["Guardrails<br/>cap. 8"]
        C11["Juegos<br/>cap. 11"]
    end

    C6 -->|"da"| DOM
    DOM -->|"reduce"| PROP
    PROP -->|"usa"| AC
    PROP -->|"deja"| MRV
    MRV -->|"elige"| BT
    BT -->|"tras elegir"| FC
    FC -->|"detecta"| CUT
    BT -->|"si cumple"| SOL
    CUT -->|"ahorra"| COST
    SOL -->|"valida"| C8
    MRV -->|"idea para"| C11

    style C6 stroke-dasharray: 5 5
    style C8 stroke-dasharray: 5 5
    style C11 stroke-dasharray: 5 5
    style PROP fill:#F5F5F5,stroke:#000000,stroke-width:2

Vocabulario aprendido

TérminoDefinición
PropagaciónReducción de dominios usando restricciones.
BacktrackingProbar, comprobar, avanzar y volver atrás si aparece contradicción.
Forward checkingEliminar valores futuros incompatibles con una asignación recién tomada.
Consistencia de arcoCada valor de una variable debe tener algún valor compatible en la variable vecina.
MRVElegir primero la variable con menos valores legales restantes.
GradoElegir la variable que participa en más restricciones pendientes.
LCVProbar primero el valor que menos opciones elimina a las demás variables.
Nodo de búsquedaAsignación parcial visitada por el backtracking.
Traza de propagaciónRegistro de decisiones, podas, dominios vacíos y soluciones.

Antes de pasar página

  • ¿Puedo explicar por qué propagar no es lo mismo que buscar?
  • ¿Sé escribir la condición de consistencia de arco?
  • ¿Entiendo qué hace backtracking cuando encuentra una contradicción?
  • ¿Sé cuándo usar MRV, grado y LCV?
  • ¿He ejecutado kit descargable y puedo leer tres eventos de la traza?

En resumen

Idea fuerzaDetalle
Propagar es borrar imposibles.Antes de buscar, las restricciones reducen dominios.
La consistencia de arco exige apoyo.Un valor sin valor compatible en la variable vecina se elimina.
Backtracking evita comprometerse con errores.Si una rama contradice reglas, se deshace y se prueba otra.
Las heurísticas ordenan la búsqueda.MRV, grado y LCV no cambian las soluciones, pero reducen trabajo inútil.
La traza convierte el solver en algo depurable.Sin traza solo sabes si hay solución; con traza ves por qué se poda cada rama.

Para saber más

Dechter, R. (2003). Constraint processing. Morgan Kaufmann.

Luger, G. F. (2008). Artificial intelligence: structures and strategies for complex problem solving (6.ª ed.). Pearson.

Mackworth, A. K. (1977). Consistency in networks of relations. Artificial Intelligence, 8(1), 99-118. https://doi.org/10.1016/0004-3702(77)90007-8

Pearl, J. (1984). Heuristics: intelligent search strategies for computer problem solving. Addison-Wesley.

Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press.

Rossi, F., van Beek, P. y Walsh, T. (Eds.). (2006). Handbook of constraint programming. Elsevier.

Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. https://aima.cs.berkeley.edu/

Notas

  1. Dechter, R. (2003). Constraint processing. Morgan Kaufmann. La obra presenta la propagación y la búsqueda como dos piezas complementarias: una reduce el espacio y la otra explora lo que queda.

  2. Mackworth, A. K. (1977). Consistency in networks of relations. Artificial Intelligence, 8(1), 99-118. https://doi.org/10.1016/0004-3702(77)90007-8

  3. Russell, S. y Norvig, P. (2021). Artificial intelligence: a modern approach (4.ª ed.). Pearson. En el tratamiento de CSP, el backtracking aparece como búsqueda en profundidad sobre asignaciones parciales, reforzada con propagación y heurísticas.

  4. Pearl, J. (1984). Heuristics: intelligent search strategies for computer problem solving. Addison-Wesley. Aunque el libro se centra en búsqueda heurística general, su idea central aplica aquí: una buena estimación reduce exploración inútil.

  5. Luger, G. F. (2008). Artificial intelligence: structures and strategies for complex problem solving (6.ª ed.). Pearson.

  6. Poole, D., Mackworth, A. y Goebel, R. (1998). Computational intelligence: a logical approach. Oxford University Press.

  7. Rossi, F., van Beek, P. y Walsh, T. (Eds.). (2006). Handbook of constraint programming. Elsevier.

Capítulo 08

Facsímil 2 · Inteligencia clásica

Capítulo 08: Restricciones como guardrails

Entrando en el tema

Imagina un agente de soporte. El usuario escribe: “Devuélveme el dinero del pedido A101; estoy muy enfadado”. El LLM entiende la intención, redacta una respuesta amable y propone llamar a una herramienta: refund_order(order_id="A101", amount_eur=850).

Ahora viene la pregunta importante: ¿puede hacerlo?

La respuesta no debería estar escondida en un prompt. No basta con escribir “no hagas reembolsos grandes sin permiso” y esperar que el modelo obedezca siempre. Si una acción cambia dinero, permisos, datos personales, contratos, infraestructura o comunicaciones externas, necesitamos controles ejecutables. En el lenguaje de este facsímil: necesitamos restricciones duras.

El prompt orienta, el guardrail decide

Un prompt es útil para tono, intención y ejemplos. Pero no es un sistema de permisos. Tampoco es un validador de tipos, ni una política de negocio, ni una auditoría. OWASP sitúa prompt injection, exposición de información sensible y uso inseguro de salidas entre los riesgos principales de aplicaciones con LLMs.1

Fecha de corte: 10 de junio de 2026. Para esta parte he tomado como fuentes de referencia la documentación de OpenAI sobre salidas estructuradas, la lista OWASP Top 10 para aplicaciones con LLM de 2025 y el AI RMF 1.0 de NIST. Los principios de permisos, schema, política y trazabilidad son estables; las APIs concretas, nombres comerciales y categorías de riesgo pueden cambiar.

CapaSirve paraNo debería ser la única barrera
PromptExplicar intención, tono y criterio general.“No hagas reembolsos grandes”.
SchemaComprobar forma, tipos y valores.amount_eur debe ser número positivo.
PermisosDecidir quién puede ejecutar una acción.Soporte solo puede reembolsar hasta 100 EUR.
PolíticaAplicar reglas del negocio y del estado.No reembolsar pedidos en disputa.
RiesgoEscalar acciones costosas o irreversibles.Reembolso grande requiere aprobación humana.
AuditoríaRegistrar qué pasó y por qué.Trazabilidad para revisar incidentes.

La idea central es sencilla: el LLM puede proponer; el sistema acepta o rechaza.

La llamada a herramienta como candidato

Una llamada a herramienta es una asignación candidata. Igual que en un CSP, tiene variables, dominios y restricciones.

Pieza CSPEn una tool de agenteEjemplo
VariableArgumento pendiente.amount_eur.
DominioValores permitidos.Entre 0 y 1000.
RestricciónRegla que filtra.Soporte no aprueba más de 100 EUR.
SoluciónTool call aceptada.Reembolso pequeño, pedido pagado, usuario autorizado.

OpenAI llama Structured Outputs a la capacidad de hacer que la salida del modelo se ajuste a un esquema especificado; aun así, el propio enfoque distingue entre generar estructura y validar lo que una aplicación permite hacer.2 JSON Schema, por su parte, formaliza vocabularios para validar estructura y valores de documentos JSON.3

Pero un schema no basta. Que una llamada tenga forma correcta no significa que esté autorizada.

La fórmula del guardrail

Podemos modelar un guardrail como una conjunción de controles:

permitida(a,s,u)=S(a)P(a,u)B(a,s)R(a)I(a,s)\operatorname{permitida}(a,s,u)= S(a)\land P(a,u)\land B(a,s)\land R(a)\land I(a,s)
SímboloSignificadoEjemplo
aaAcción candidata propuesta por el agente.Reembolsar pedido A101 por 850 EUR.
ssEstado actual del sistema.Pedido pagado, en disputa o ya reembolsado.
uuUsuario o identidad que solicita la acción.Agente de soporte con rol support.
S(a)S(a)Validación de schema.Campos presentes y tipos correctos.
P(a,u)P(a,u)Política de permisos.Soporte solo puede reembolsar hasta 100 EUR.
B(a,s)B(a,s)Regla de negocio dependiente del estado.No reembolsar pedido en disputa.
R(a)R(a)Control de riesgo.Riesgo menor o igual que el umbral.
I(a,s)I(a,s)Invariante que debe conservarse.El pedido no queda reembolsado dos veces.

Si cualquiera de esas piezas es falsa, la acción no se ejecuta.

Tres decisiones, no dos

En sistemas reales no todo debería acabar en “sí” o “no”. Muchas acciones deberían tener tres salidas:

DecisiónCuándo ocurreQué hace el sistema
ALLOWTodos los controles pasan y el riesgo es bajo.Ejecuta la herramienta y registra la acción.
DENYFalta schema, estado válido, invariante o permiso imprescindible.Bloquea y explica qué control falló.
HITLLa acción puede ser legítima, pero supera umbral de riesgo o importe.Pide aprobación humana con contexto y trazas.

Esto evita dos extremos malos. El primero es permitir demasiado porque el modelo “parece seguro”. El segundo es bloquear todo lo que se salga de un caso pequeño, haciendo el sistema inútil. La ingeniería buena suele estar en el medio: automatizar lo seguro, denegar lo inválido y escalar lo delicado.

También conviene separar el punto que decide del punto que ejecuta. En seguridad se habla a menudo de policy decision point y policy enforcement point: una pieza evalúa la política; otra impide que la herramienta se ejecute si la decisión no lo permite. Para un agente, esto significa que el LLM no llama directamente a la API sensible. Propone una llamada; el guardrail decide; el ejecutor obedece solo si la decisión es permitida.

La regla por defecto debería ser fail closed: si falta un campo, no se sabe el rol, el estado no está cargado o el cálculo de riesgo falla, la acción no se ejecuta automáticamente. Un sistema puede ser amable en el mensaje de rechazo, pero no debe ser generoso con permisos incompletos.

Ejemplo 1:

ControlEvaluaciónResultado
S(a)S(a)order_id es texto y amount_eur=80 es número positivo.Verdadero
P(a,u)P(a,u)Rol support; importe 80 EUR.Verdadero
B(a,s)B(a,s)Pedido pagado y no reembolsado.Verdadero
R(a)R(a)Riesgo bajo.Verdadero
I(a,s)I(a,s)No duplica reembolso.Verdadero

La acción se permite.

Ejemplo 2:

ControlEvaluaciónResultado
S(a)S(a)La llamada tiene forma correcta.Verdadero
P(a,u)P(a,u)Rol support; importe 850 EUR.Falso
B(a,s)B(a,s)Pedido pagado.Verdadero
R(a)R(a)Riesgo alto.Falso
I(a,s)I(a,s)No duplica reembolso.Verdadero

La acción se rechaza aunque el LLM la haya propuesto con mucha seguridad.

Riesgo, umbrales y aprobación humana

Ejemplo de fórmula. Para decidir cuándo escalar a una persona, podemos usar una puntuación simple de riesgo. Esta fórmula no pretende sustituir una matriz de riesgo formal ni una política legal; sirve para que el equipo haga explícitos los factores que está mezclando antes de ejecutar una acción.

riesgo(a)=impacto(a)probabilidad(a)irreversibilidad(a)\operatorname{riesgo}(a)=impacto(a)\cdot probabilidad(a)\cdot irreversibilidad(a)
SímboloSignificadoEjemplo
impacto(a)impacto(a)Daño si la acción sale mal.5 para un reembolso grande.
probabilidad(a)probabilidad(a)Probabilidad estimada de error o abuso.2 si hay señales dudosas.
irreversibilidad(a)irreversibilidad(a)Dificultad de deshacer la acción.2 si requiere proceso externo.
riesgo(a)\operatorname{riesgo}(a)Puntuación total de riesgo.522=205\cdot2\cdot2=20.

Definimos:

R(a)=riesgo(a)τR(a)=\operatorname{riesgo}(a)\leq \tau
SímboloSignificadoEjemplo
R(a)R(a)Control que dice si el riesgo es aceptable.Verdadero si no supera el umbral.
τ\tauUmbral de ejecución automática.τ=8\tau=8.

Si el riesgo es 2020 y el umbral es 88, la acción no se ejecuta automáticamente. Puede pasar a revisión humana. En un sistema real, los valores de impacto, probabilidad e irreversibilidad deben venir de incidentes, políticas internas, auditorías y límites de negocio, no de una sensación improvisada. NIST propone gestionar riesgos de IA de forma medible, trazable y adaptada al contexto; esa filosofía encaja con convertir acciones peligrosas en decisiones explícitas, no en obediencia ciega al modelo.4

Permisos: el modelo no es identidad

Los permisos deben vivir fuera del LLM. La idea de control de acceso basado en roles aparece formalizada en trabajos clásicos de Ferraiolo y Kuhn, donde los permisos se asocian a roles y no a frases libres.5

Un modelo puede decir “el usuario parece administrador”. Eso no convierte al usuario en administrador. El sistema debe comprobarlo.

PreguntaDebe contestarlaEjemplo
¿Quién pide la acción?Identidad/autenticación.Usuario u2.
¿Qué rol tiene?Sistema de permisos.support, no admin.
¿Qué intenta hacer?Tool call estructurada.Reembolsar 850 EUR.
¿Puede hacerlo?Política ejecutable.No sin aprobación.

Saltzer y Schroeder ya defendían principios como mínimo privilegio y mediación completa: cada acceso relevante debe comprobarse, no asumirse.6 Los agentes no eliminan esos principios. Los hacen más importantes.

Guardrails: la esclusa entre proponer y ejecutar El modelo redacta una intención; la aplicación decide con controles verificables. Propuesta del LLM refund_order amount_eur = 850 candidata Esclusa de validación cada compuerta puede bloquear la acción 1 2 3 4 5 Schema campos, tipos y rango Permisos rol, identidad y alcance Política estado del pedido Riesgo umbral o revisión humana Invariante no romper reglas globales permitida = S ∧ P ∧ B ∧ R ∧ I Ejecutar tool con efecto real solo si todo pasa acción registrada Bloquear rechazar o escalar explicar el control pedir aprobación Auditoría: dejar rastro de la decisión quién qué pidió qué falló decisión resultado El prompt orienta. La esclusa decide. El log permite auditar. IA para gente curiosa / Facsímil 02 / Capítulo 08 / 686f6c61

En el día a día

En una aplicación de soporte, el guardrail no es una pantalla bonita de “confirmar”. Es una cadena de controles antes de llamar a la herramienta. Primero se valida que los argumentos tienen forma. Después se comprueba el rol. Luego se revisa el estado del pedido. Después se calcula el riesgo. Finalmente se registra todo.

En un sistema RAG, el guardrail puede exigir que toda respuesta legal cite documentos recuperados. En un agente de despliegue, puede impedir deploy si no hay build verde. En una herramienta financiera, puede escalar toda operación por encima de cierto importe.

La idea no cambia: donde haya reglas duras, no las delegues a una frase del prompt.

Por qué debería importarte

Porque el fallo caro no suele ser que el modelo redacte mal. El fallo caro es que una salida plausible atraviese el sistema y ejecute algo que no debía. En aplicaciones con herramientas, una respuesta deja de ser solo texto: puede cambiar el mundo.

Los guardrails son la traducción operativa de lo que venimos aprendiendo desde SAT y CSP. Separan propuesta de aceptación. Hacen visible qué regla falló. Permiten auditar. Y, sobre todo, reducen la superficie donde el modelo puede improvisar.

En programación con restricciones, esta separación entre variables, dominios, restricciones y soluciones es la forma natural de modelar decisiones que no admiten “casi correcto”.7

Dónde solía tropezar yo

ErrorPor qué es un errorAntídoto
Poner una regla dura solo en el promptUn prompt puede ser ignorado, contradicho o rodeado por instrucciones no confiables.Codifica la regla como schema, permiso, política o validador.
Confundir JSON válido con acción válidaUna llamada puede tener campos correctos y aun así no estar autorizada.Separa schema, permisos, estado y riesgo.
Validar después de ejecutarSi la herramienta ya cambió dinero o datos, el daño puede estar hecho.Valida antes de ejecutar y registra después.
No explicar el rechazoUn “no” opaco parece fallo del sistema.Devuelve qué control falló y qué alternativa segura existe.

Manos a la obra

La práctica real está en kit descargable. El kit simula llamadas a una tool de reembolso y las pasa por schema, permisos, política de negocio, riesgo e invariantes. Produce tres decisiones: ALLOW, DENY y HITL.

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/evaluate_guardrails.py --write
cat output/guardrail_decision.md

Como gate:

python3 ops/evaluate_guardrails.py --write --fail-on-invalid

Qué deberías ver. Una llamada pequeña y válida se permite. Una llamada de importe alto no se ejecuta automáticamente: pasa a aprobación humana. Una llamada sobre pedido en disputa se deniega. Una llamada con importe inválido falla en schema. Una llamada duplicada falla por invariante.

ArchivoPapel
data/refund_calls.jsonTool calls candidatas, usuario, estado y riesgo.
contracts/guardrail_policy.jsonLímites de rol, umbrales HITL, estados válidos e invariantes.
ops/evaluate_guardrails.pyEvaluador sin dependencias externas.
output/guardrail_report.jsonResultado estructurado.
output/guardrail_audit_log.jsonlLog de auditoría línea a línea.
output/guardrail_decision.mdInforme legible para entregar.

Cómo lo adaptas a tu caso. Cambia refund_order por una herramienta real: deploy_service, send_email, delete_user, create_invoice o query_database. Mantén la idea: schema primero, permisos después, reglas de estado, riesgo, invariantes y auditoría.

Qué entregaría un alumno. El Markdown generado, una tool nueva, una política de límites por rol, un caso HITL y una explicación de por qué fail closed protege mejor que permitir por defecto.

Cómo encaja todo

Este mapa traduce SAT y CSP a una arquitectura de producto. Una llamada a herramienta es una candidata, no una orden. Antes de ejecutarla, el sistema debe validar forma, permisos, estado, riesgo e invariantes.

La decisión aprendida es separar el texto que propone de los controles que autorizan. Esa separación se reutiliza en planificación, agentes, operación y seguridad.

graph TD
    subgraph "Este capítulo"
        CALL["Tool call<br/>candidata"]
        GUARD["Guardrail<br/>ejecutable"]
        CHECKS["S ∧ P ∧ B ∧ R ∧ I"]
        DEC["Decisión<br/>auditable"]
    end
    subgraph "Mismo facsímil"
        SEARCH["Búsqueda<br/>caps. 1-4"]
        CSP["CSP<br/>cap. 6"]
        PROP["Poda<br/>cap. 7"]
        PLAN["Planificación<br/>cap. 9"]
        GAMES["Juegos<br/>cap. 11"]
        KNOW["Conocimiento<br/>cap. 12"]
    end
    subgraph "Otros facsímiles"
        TOOLS["APIs y herramientas<br/>fasc. 4"]
        AGENTS["Agentes<br/>fasc. 5"]
        OPS["Operación<br/>fasc. 6"]
        SEC["Seguridad<br/>fasc. 9"]
        UX["Producto y UX<br/>fasc. 11"]
    end

    SEARCH -->|"proponer"| CALL
    CSP -->|"modelar"| GUARD
    PROP -->|"podar"| GUARD
    CALL -->|"validar"| CHECKS
    GUARD -->|"componer"| CHECKS
    CHECKS -->|"decidir"| DEC
    DEC -->|"ejecutar"| TOOLS
    DEC -->|"controlar"| AGENTS
    DEC -->|"observar"| OPS
    DEC -->|"gobernar"| SEC
    DEC -->|"explicar"| UX
    GUARD -->|"reutilizar"| PLAN
    GUARD -->|"limitar"| GAMES
    GUARD -->|"formalizar"| KNOW

    style CALL fill:#F5F5F5,stroke:#000000,stroke-width:2
    style GUARD fill:#F5F5F5,stroke:#000000,stroke-width:2
    style CHECKS fill:#F5F5F5,stroke:#000000,stroke-width:2
    style DEC fill:#F5F5F5,stroke:#000000,stroke-width:2
    style SEARCH stroke-dasharray: 5 5
    style CSP stroke-dasharray: 5 5
    style PROP stroke-dasharray: 5 5
    style PLAN stroke-dasharray: 5 5
    style GAMES stroke-dasharray: 5 5
    style KNOW stroke-dasharray: 5 5
    style TOOLS stroke-dasharray: 5 5
    style AGENTS stroke-dasharray: 5 5
    style OPS stroke-dasharray: 5 5
    style SEC stroke-dasharray: 5 5
    style UX stroke-dasharray: 5 5

Vocabulario aprendido

TérminoDefinición
GuardrailControl ejecutable que limita, valida o bloquea una acción de IA.
SchemaContrato que define campos, tipos y valores aceptados.
Política de permisosRegla que decide quién puede ejecutar qué acción.
InvarianteCondición que debe seguir siendo cierta antes y después de actuar.
HITLAprobación humana cuando el riesgo supera un umbral.
AuditoríaRegistro revisable de petición, decisión, acción y resultado.
Fail closedAnte duda o error, bloquear o escalar en vez de ejecutar automáticamente.
Policy decision pointComponente que evalúa la política antes de que el ejecutor llame a la herramienta.

Antes de pasar página

  • ¿Puedo explicar por qué un prompt no es un guardrail suficiente?
  • ¿Distingo schema correcto de acción autorizada?
  • ¿Sé escribir permitida(a,s,u)=SPBRI\operatorname{permitida}(a,s,u)=S\land P\land B\land R\land I?
  • ¿Entiendo cuándo una acción debe escalar a una persona?
  • ¿He ejecutado kit descargable y puedo explicar una decisión ALLOW, una DENY y una HITL?

En resumen

Idea fuerzaDetalle
El LLM propone, la aplicación decide.La aceptación debe depender de controles ejecutables.
El schema no basta.Forma correcta no implica permiso, estado válido ni riesgo aceptable.
Los guardrails son restricciones duras.Schema, permisos, políticas, riesgo e invariantes son filtros antes de ejecutar.
Algunas acciones no se deniegan: se escalan.HITL permite tratar riesgo alto sin convertir el sistema en todo o nada.
La auditoría convierte decisiones en trazas.Si algo falla, necesitamos saber quién pidió qué, qué se validó y qué ocurrió.

Para saber más

Ferraiolo, D. F. y Kuhn, D. R. (1992). Role-Based Access Controls. En Proceedings of the 15th National Computer Security Conference (pp. 554-563). https://www.nist.gov/publications/role-based-access-controls

JSON Schema. (2020). JSON Schema Validation: A Vocabulary for Structural Validation of JSON. https://json-schema.org/draft/2020-12/json-schema-validation

OpenAI. (2026). Structured model outputs. https://platform.openai.com/docs/guides/structured-outputs

OWASP Foundation. (2025). OWASP Top 10 for LLM and Generative AI Applications 2025. https://genai.owasp.org/

Rossi, F., van Beek, P. y Walsh, T. (Eds.). (2006). Handbook of constraint programming. Elsevier.

Saltzer, J. H. y Schroeder, M. D. (1975). The protection of information in computer systems. Proceedings of the IEEE, 63(9), 1278-1308. https://doi.org/10.1109/PROC.1975.9939

Tabassi, E. (2023). Artificial Intelligence Risk Management Framework (AI RMF 1.0). National Institute of Standards and Technology. https://doi.org/10.6028/NIST.AI.100-1

Notas

  1. OWASP Foundation. (2025). OWASP Top 10 for LLM and Generative AI Applications 2025. https://genai.owasp.org/. La lista enfatiza que la seguridad de aplicaciones con LLM requiere controles fuera del texto del prompt, especialmente ante instrucciones no confiables, datos sensibles y acciones de herramientas.

  2. OpenAI. (2026). Structured model outputs. https://platform.openai.com/docs/guides/structured-outputs. La documentación diferencia la generación estructurada de JSON de la adhesión a un esquema y recomienda usar esquemas estrictos cuando se necesita forma controlada.

  3. JSON Schema. (2020). JSON Schema Validation: A Vocabulary for Structural Validation of JSON. https://json-schema.org/draft/2020-12/json-schema-validation

  4. Tabassi, E. (2023). Artificial Intelligence Risk Management Framework (AI RMF 1.0). National Institute of Standards and Technology. https://doi.org/10.6028/NIST.AI.100-1

  5. Ferraiolo, D. F. y Kuhn, D. R. (1992). Role-Based Access Controls. En Proceedings of the 15th National Computer Security Conference (pp. 554-563). https://www.nist.gov/publications/role-based-access-controls

  6. Saltzer, J. H. y Schroeder, M. D. (1975). The protection of information in computer systems. Proceedings of the IEEE, 63(9), 1278-1308. https://doi.org/10.1109/PROC.1975.9939

  7. Rossi, F., van Beek, P. y Walsh, T. (Eds.). (2006). Handbook of constraint programming. Elsevier.

Capítulo 09

Facsímil 2 · Inteligencia clásica

Capítulo 09: Planificación automática: PDDL y modelado de dominios

Entrando en el tema

Imagina una tarea aparentemente simple: “envía la factura al cliente”. Parece una instrucción de una sola línea. Pero si intentamos automatizarla de verdad, enseguida aparecen preguntas incómodas.

¿Existe el cliente? ¿La factura está completa? ¿El importe está calculado? ¿El correo está confirmado? ¿Hay permiso para enviarla? ¿Qué pasa si ya se envió ayer?

Un humano puede resolver esas preguntas con contexto y prudencia. Una automatización necesita otra cosa: un modelo explícito de estado, acciones, precondiciones y efectos. Eso es planificación automática.

Un plan no es una lista de tareas

Una lista dice qué pasos suenan razonables. Un plan dice qué pasos son ejecutables, en qué orden y bajo qué condiciones. La diferencia parece pequeña hasta que una acción tiene efectos reales.

En planificación clásica, el mundo se representa como un estado; las acciones solo se pueden aplicar si sus precondiciones se cumplen, y al aplicarlas cambian el estado. Ghallab, Nau y Traverso presentan esta idea como el modelo básico de la planificación automática: encontrar una forma de pasar de una situación inicial a una situación objetivo mediante acciones descritas formalmente.1

En agentes modernos pasa lo mismo, aunque el vocabulario sea distinto. El estado puede ser memoria, ficheros, base de datos, tickets, logs o respuestas de herramientas. Las acciones pueden ser tool calls. Las precondiciones son permisos, datos disponibles y reglas del negocio. Los efectos son cambios observables.

Russell y Norvig tratan la planificación como una extensión natural de la búsqueda: ya no buscamos solo un camino entre nodos, sino una secuencia de acciones que respete un modelo explícito del mundo.2

La planificación como sistema formal

Podemos escribir una tarea de planificación como:

Π=(S,A,γ,s0,G)\Pi=(S,A,\gamma,s_0,G)
SímboloSignificadoEjemplo
Π\PiProblema de planificación completo.Enviar una factura validada.
SSConjunto de estados posibles.Todas las combinaciones de hechos sobre cliente, factura y envío.
AAConjunto de acciones disponibles.validar_factura, enviar_email, registrar_log.
γ\gammaFunción de transición: aplica una acción y devuelve el nuevo estado.Si envío el email, aparece email_enviado.
s0s_0Estado inicial.Cliente identificado, factura preparada.
GGObjetivo: hechos que deben ser ciertos al final.Factura enviada y log creado.

Una acción aa tiene tres piezas:

a=(pre(a),add(a),del(a))a=(pre(a),add(a),del(a))
SímboloSignificadoEjemplo
pre(a)pre(a)Precondiciones: hechos requeridos antes de actuar.factura_validada y email_confirmado.
add(a)add(a)Hechos que pasan a ser verdaderos.email_enviado.
del(a)del(a)Hechos que dejan de ser verdaderos.factura_preparada.

Esta forma de pensar viene de STRIPS, uno de los lenguajes clásicos para describir acciones mediante precondiciones y efectos de añadir o borrar hechos.3

Una acción es aplicable si todas sus precondiciones están en el estado actual:

aplicable(a,s)pre(a)s\operatorname{aplicable}(a,s)\Leftrightarrow pre(a)\subseteq s
SímboloSignificadoEjemplo
aaAcción que queremos ejecutar.enviar_factura.
ssEstado actual.Conjunto de hechos verdaderos ahora.
pre(a)pre(a)Hechos requeridos por la acción.{factura_validada, email_confirmado}.
pre(a)spre(a)\subseteq sTodas las precondiciones están presentes en el estado.La factura está validada y el email confirmado.

Si la acción es aplicable, el nuevo estado se calcula así:

γ(s,a)=(sdel(a))add(a)\gamma(s,a)=(s\setminus del(a))\cup add(a)
SímboloSignificadoEjemplo
γ(s,a)\gamma(s,a)Estado resultante tras ejecutar la acción.Estado después de enviar la factura.
sdel(a)s\setminus del(a)Estado sin los hechos que la acción elimina.Quitamos factura_preparada.
add(a)add(a)Hechos nuevos que la acción añade.Añadimos email_enviado.
\cupUnión de hechos.Juntamos lo que queda con lo nuevo.

Por último, un plan es una secuencia de acciones:

π=a1,a2,,ak\pi=\langle a_1,a_2,\ldots,a_k\rangle
SímboloSignificadoEjemplo
π\piPlan completo.Validar, enviar, registrar.
aia_iAcción en la posición ii.a2=a_2= enviar_factura.
kkLongitud del plan.Tres acciones.

El plan es válido si, al aplicar sus acciones una a una desde s0s_0, llegamos a un estado final sks_k donde el objetivo se cumple:

GskG\subseteq s_k
SímboloSignificadoEjemplo
GGObjetivo que queremos lograr.{email_enviado, log_creado}.
sks_kEstado después de ejecutar las kk acciones.Estado final tras validar, enviar y registrar.
GskG\subseteq s_kTodos los hechos objetivo son verdaderos al final.El email se envió y quedó registrado.

Un ejemplo pequeño: enviar una factura

Tomemos este estado inicial:

s0={cliente_identificado, factura_preparada, importe_calculado, email_confirmado}s_0=\{cliente\_identificado,\ factura\_preparada,\ importe\_calculado,\ email\_confirmado\}

Y este objetivo:

G={factura_validada, email_enviado, log_creado}G=\{factura\_validada,\ email\_enviado,\ log\_creado\}
AcciónPrecondicionesAñadeElimina
validar_facturacliente_identificado, importe_calculado, factura_preparadafactura_validadafactura_preparada
enviar_facturafactura_validada, email_confirmadoemail_enviadoNada
registrar_envioemail_enviadolog_creadoNada

El plan válido es:

π=validar_factura, enviar_factura, registrar_envio\pi=\langle validar\_factura,\ enviar\_factura,\ registrar\_envio\rangle

No porque suene bien, sino porque cada paso se puede comprobar.

Si intentamos enviar_factura primero, falla: factura_validada todavía no pertenece a s0s_0. Si intentamos registrar_envio primero, falla: email_enviado todavía no es cierto.

PDDL: separar dominio y problema

PDDL, Planning Domain Definition Language, se creó para estandarizar cómo describir problemas de planificación en competiciones y sistemas de planning.4

La idea más importante no es memorizar la sintaxis. La idea importante es separar dos cosas:

PiezaQué contieneQué no debería contener
DominioReglas reutilizables: tipos, predicados y acciones.Datos concretos del caso de hoy.
ProblemaObjetos, estado inicial y objetivo concreto.Lógica general de las acciones.

El dominio describe cómo funciona el mundo:

(define (domain facturas)
  (:requirements :strips)
  (:predicates
    (cliente-identificado)
    (factura-preparada)
    (importe-calculado)
    (factura-validada)
    (email-confirmado)
    (email-enviado)
    (log-creado))

  (:action validar-factura
    :precondition (and
      (cliente-identificado)
      (importe-calculado)
      (factura-preparada))
    :effect (and
      (factura-validada)
      (not (factura-preparada))))

  (:action enviar-factura
    :precondition (and
      (factura-validada)
      (email-confirmado))
    :effect (email-enviado))

  (:action registrar-envio
    :precondition (email-enviado)
    :effect (log-creado)))

El problema describe el caso concreto:

(define (problem envio-factura-123)
  (:domain facturas)
  (:init
    (cliente-identificado)
    (factura-preparada)
    (importe-calculado)
    (email-confirmado))
  (:goal (and
    (factura-validada)
    (email-enviado)
    (log-creado))))

Separar dominio y problema es parecido a separar código y configuración. No reescribes la acción enviar-factura cada vez que cambia el número de factura. Cambias la instancia.

PDDL también nos enseña una disciplina útil aunque nunca lo usemos en producción: cada acción debe declarar qué espera del mundo y qué promete cambiar. Ese contrato permite detectar tres clases de errores que un texto libre disimula muy bien.

ErrorCómo lo detecta el modelo de planificaciónEjemplo
Paso imposibleFalta una precondición.Intentar enviar sin factura_validada.
Paso inútilEl efecto no acerca al objetivo.Consultar tres veces el mismo pedido.
Paso peligrosoEl efecto rompe una regla o requiere aprobación.Enviar una factura de alto importe sin revisión.

Por eso PDDL encaja tan bien con tools y agentes: convierte una acción de “parece razonable” en una acción de “puedo comprobar si es legal”.

Planificar, ejecutar, observar, corregir Un plan útil no termina al elegir pasos: comprueba cada acción y aprende del estado observado. Dominio reutilizable Predicados Acciones pre(a), add(a), del(a) validar, enviar, registrar Problema concreto s0 cliente, factura, email G email enviado + log Instancia pedido, cliente y permisos de hoy Planificador aplicable(a,s) ⇔ pre(a) ⊆ s γ(s,a)=(s - del(a)) ∪ add(a) si falla una precondición, se descarta Contrato de acción 1. comprobar precondiciones 2. aplicar efectos esperados 3. observar el estado real Ejecución vigilada 1 2 3 validar observar factura válida enviar observar email enviado registrar observar log creado Monitor compara estado esperado con observación real si contradice: replanificación Plan válido: no solo pasos, también evidencia s0 validar enviar registrar G cumplido Un agente fiable planifica con modelo, actúa con guardrails y corrige con observaciones. IA para gente curiosa / Facsímil 02 / Capítulo 09 / 686f6c61

En el día a día

PDDL puede parecer antiguo, pero su disciplina es muy moderna. Cuando diseñas una tool para un agente, estás definiendo algo muy parecido a una acción de planificación.

Pregunta de diseñoEn PDDLEn una tool moderna
¿Qué recibe?Parámetros.JSON schema o tipos.
¿Cuándo puede ejecutarse?Precondiciones.Permisos, estado y validadores.
¿Qué cambia?Efectos.Base de datos, fichero, ticket, email o log.
¿Cómo sé que funcionó?Nuevo estado.Observación verificable, test o evento registrado.

El capítulo anterior hablaba de guardrails. Este capítulo dice dónde viven muchos de esos guardrails: antes y después de cada acción. Antes, para comprobar precondiciones. Después, para comprobar efectos.

Cuando el mundo no coincide con el plan

La planificación clásica suele empezar con un modelo limpio: sabemos qué hechos son ciertos, qué acciones existen y qué efectos tienen. El mundo real rara vez es tan educado. Una API puede fallar, una credencial puede caducar, otra persona puede cambiar el ticket o una herramienta puede devolver un resultado parcial.

Por eso, en sistemas modernos, planificar no debería significar “generar diez pasos y ejecutarlos sin mirar”. El patrón más sano es planificar, ejecutar un paso, observar, actualizar estado y decidir otra vez. Si la observación coincide con el efecto esperado, seguimos. Si no coincide, replanificamos.

MomentoPreguntaEjemplo
Antes de actuar¿Se cumplen las precondiciones?¿La factura está validada y el email confirmado?
Al actuar¿La tool devuelve un resultado estructurado?send_email devuelve message_id.
Después de actuar¿El efecto esperado aparece en el estado?Existe email_enviado.
Si falla¿Qué acción sigue siendo legal ahora?Reintentar, pedir dato, escalar o parar.

En un agente con LLM, esta tabla vale oro. El modelo puede proponer el siguiente paso, pero el sistema debe mirar el estado real antes de aceptarlo. Esa es la diferencia entre un plan textual y una automatización operable.

Por qué debería importarte

Porque muchos agentes fallan no por falta de lenguaje, sino por falta de modelo de mundo. Redactan pasos razonables, pero no saben qué pasos son aplicables, qué dependencias faltan, qué efecto real produjo cada herramienta o cuándo deben parar.

La planificación automática te da una forma de depurar esas automatizaciones: mira el estado inicial, las acciones disponibles, las precondiciones, los efectos y el objetivo. Si alguna pieza no está escrita, el sistema puede estar improvisando.

Además, la planificación crece rápido. Si en cada estado hay bb acciones aplicables y buscamos planes de longitud dd, el árbol bruto puede crecer como:

O(bd)O(b^d)
SímboloSignificadoEjemplo
bbFactor de ramificación: acciones candidatas por estado.4 acciones disponibles.
ddProfundidad o longitud máxima del plan.5 pasos.
O(bd)O(b^d)Crecimiento aproximado de combinaciones a explorar.45=10244^5=1024 secuencias posibles.

Bylander mostró que la planificación proposicional STRIPS tiene una complejidad computacional dura incluso con representaciones relativamente simples.5 Por eso el siguiente capítulo hablará de heurísticas, planificación con SAT y técnicas para no explorar planes absurdos. Graphplan fue una de las grandes ideas para usar grafos de planificación y restricciones mutuas de forma eficiente.6 FF, más tarde, hizo popular el uso de búsqueda hacia delante con heurísticas derivadas de planes relajados.7

Dónde solía tropezar yo

ErrorPor qué es un errorAntídoto
Confundir plan con lista bonitaUna lista puede ignorar precondiciones y efectos.Pregunta qué debe ser cierto antes y después de cada paso.
Meter el caso concreto dentro del dominioHace que cada instancia obligue a reescribir reglas.Separa dominio reutilizable y problema de hoy.
No modelar efectos negativosEl sistema recuerda hechos que ya no son ciertos.Escribe también qué se elimina: del(a) o not (...).
Asumir que ejecutar es verificarUna tool puede ejecutarse y aun así no lograr el objetivo.Comprueba el estado resultante y registra evidencia.
Olvidar el coste de búsquedaLos planes posibles crecen muy rápido.Usa límites, heurísticas, SAT o descomposición.

Manos a la obra

La práctica real está en kit descargable. El kit implementa un planificador STRIPS mínimo con búsqueda en anchura, pero lo hace como artefacto reutilizable: dominio, problema, contrato, planes candidatos, trazas y salida de decisión.

No basta con que el plan «suene bien». El script valida si cada acción es aplicable en el estado donde aparece, aplica efectos positivos y negativos, y comprueba que el estado final contiene el objetivo. También incluye planes candidatos inválidos para que puedas ver exactamente dónde fallan.

ArchivoQué contiene
data/planning_problem.jsonEstado inicial, objetivo, acciones STRIPS y planes candidatos.
contracts/planning_policy.jsonLongitud máxima, hechos obligatorios y checks mínimos.
ops/solve_strips_plan.pyPlanificador BFS, validador de planes y generador de informe.
output/strips_plan_report.jsonPlan encontrado, estados intermedios, candidatos válidos e inválidos.
output/strips_plan_decision.mdLectura técnica del plan y de los fallos.

Ejecuta:

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/solve_strips_plan.py --write
cat output/strips_plan_decision.md

Como gate:

python3 ops/solve_strips_plan.py --write --fail-on-invalid

Qué entregaría un alumno. El Markdown generado, una acción nueva añadida al JSON, un plan candidato inválido con su explicación y una decisión: qué precondición falta para que el proceso sea seguro en un caso real.

Cómo encaja todo

Este mapa une búsqueda, restricciones y acción. Un dominio PDDL no es una lista bonita: define acciones con precondiciones y efectos. Un problema fija estado inicial y objetivo. El plan aparece cuando esas piezas encajan paso a paso.

La decisión nueva es tratar cada acción como contrato verificable. Esa idea prepara el capítulo 10, donde el plan se guía con heurísticas, SAT y observación real.

graph TD
    subgraph "Modelo formal"
        DOM["Dominio<br/>PDDL"]
        PROB["Problema<br/>s0 y G"]
        ACT["Acción<br/>pre add del"]
        APP["Aplicable<br/>pre(a) ⊆ s"]
        TRANS["Transición<br/>γ(s,a)"]
    end
    subgraph "Ciclo operativo"
        PLAN["Plan<br/>π"]
        EXEC["Ejecutar<br/>un paso"]
        OBS["Observar<br/>estado real"]
        REPLAN["Replanificar<br/>si falla"]
    end
    subgraph "Mismo facsímil"
        SEARCH["Búsqueda<br/>caps. 1-4"]
        SATCSP["SAT y CSP<br/>caps. 5-7"]
        GUARD["Guardrails<br/>cap. 8"]
        HEUR["Heurísticas y SAT<br/>cap. 10"]
        GAME["Juegos<br/>cap. 11"]
    end
    subgraph "Otros facsímiles"
        TOOLS["Tools y APIs<br/>fasc. 4"]
        AGENTS["Agentes<br/>fasc. 5"]
        OPS["Operación<br/>fasc. 6"]
        SEC["Seguridad<br/>fasc. 9"]
    end

    DOM -->|"define"| ACT
    PROB -->|"fija"| PLAN
    ACT -->|"exige"| APP
    APP -->|"permite"| TRANS
    TRANS -->|"actualiza"| PLAN
    PLAN -->|"elige"| EXEC
    EXEC -->|"produce"| OBS
    OBS -->|"confirma"| PLAN
    OBS -->|"contradice"| REPLAN
    REPLAN -->|"vuelve a buscar"| PLAN
    SEARCH -->|"explorar"| PLAN
    SATCSP -->|"restringir"| APP
    GUARD -->|"validar"| EXEC
    PLAN -->|"preparar"| HEUR
    PLAN -->|"secuenciar"| TOOLS
    PLAN -->|"controlar"| AGENTS
    PLAN -->|"observar"| OPS
    PLAN -->|"limitar riesgo"| SEC
    GAME -->|"añadir actores"| PLAN

    style DOM fill:#F5F5F5,stroke:#000000,stroke-width:2
    style PROB fill:#F5F5F5,stroke:#000000,stroke-width:2
    style ACT fill:#F5F5F5,stroke:#000000,stroke-width:2
    style APP fill:#F5F5F5,stroke:#000000,stroke-width:2
    style TRANS fill:#F5F5F5,stroke:#000000,stroke-width:2
    style PLAN fill:#F5F5F5,stroke:#000000,stroke-width:2
    style EXEC fill:#F5F5F5,stroke:#000000,stroke-width:2
    style OBS fill:#F5F5F5,stroke:#000000,stroke-width:2
    style REPLAN fill:#F5F5F5,stroke:#000000,stroke-width:2
    style SEARCH stroke-dasharray: 5 5
    style SATCSP stroke-dasharray: 5 5
    style GUARD stroke-dasharray: 5 5
    style HEUR stroke-dasharray: 5 5
    style GAME stroke-dasharray: 5 5
    style TOOLS stroke-dasharray: 5 5
    style AGENTS stroke-dasharray: 5 5
    style OPS stroke-dasharray: 5 5
    style SEC stroke-dasharray: 5 5

Vocabulario aprendido

TérminoDefinición
Planificación automáticaBúsqueda de una secuencia de acciones que transforma un estado inicial en un objetivo.
PredicadoHecho verificable que puede ser verdadero o falso.
PrecondiciónHecho que debe cumplirse antes de ejecutar una acción.
EfectoCambio que una acción produce en el estado.
Dominio PDDLDescripción reutilizable de tipos, predicados y acciones.
Problema PDDLInstancia concreta con objetos, estado inicial y objetivo.
ObservaciónEvidencia real que confirma o corrige el estado esperado tras actuar.
ReplanificaciónConstrucción de un nuevo plan cuando la observación contradice el plan anterior.

Antes de pasar página

  • ¿Puedo explicar por qué un plan no es solo una lista de pasos?
  • ¿Sé distinguir estado inicial, acciones y objetivo?
  • ¿Entiendo cuándo una acción es aplicable: pre(a)spre(a)\subseteq s?
  • ¿Sé calcular el nuevo estado con (sdel(a))add(a)(s\setminus del(a))\cup add(a)?
  • ¿Distingo dominio PDDL de problema PDDL?
  • ¿Entiendo por qué ejecutar un paso debe producir una observación verificable?
  • ¿He ejecutado kit descargable y entendido por qué el orden del plan importa?

En resumen

Idea fuerzaDetalle
Planificar es transformar estado.Partimos de s0s_0, aplicamos acciones legales y buscamos llegar a GG.
Una acción tiene contrato.Precondiciones antes; efectos después. Sin eso, una tool opera a ciegas.
PDDL separa reglas e instancia.Dominio es la lógica reutilizable; problema es el caso concreto.
Los planes se verifican y se corrigen.Ejecutar, observar y replanificar evita seguir una ruta que el mundo ya contradijo.

Para saber más

Blum, A. L. y Furst, M. L. (1997). Fast planning through planning graph analysis. Artificial Intelligence, 90(1-2), 281-300. https://doi.org/10.1016/S0004-3702(96)00047-1

Bylander, T. (1994). The computational complexity of propositional STRIPS planning. Artificial Intelligence, 69(1-2), 165-204. https://doi.org/10.1016/0004-3702(94)90081-7

Fikes, R. E. y Nilsson, N. J. (1971). STRIPS: A new approach to the application of theorem proving to problem solving. Artificial Intelligence, 2(3-4), 189-208. https://doi.org/10.1016/0004-3702(71)90010-5

Ghallab, M., Nau, D. y Traverso, P. (2004). Automated Planning: Theory and Practice. Morgan Kaufmann.

Hoffmann, J. y Nebel, B. (2001). The FF planning system: fast plan generation through heuristic search. Journal of Artificial Intelligence Research, 14, 253-302. https://doi.org/10.1613/jair.855

McDermott, D., Ghallab, M., Howe, A., Knoblock, C., Ram, A., Veloso, M., Weld, D. y Wilkins, D. (1998). PDDL: The Planning Domain Definition Language, Version 1.2. Yale Center for Computational Vision and Control. https://www.isi.edu/results/publications/19837/pddl-the-planning-domain-definition-language-version-1-2

Russell, S. y Norvig, P. (2021). Artificial Intelligence: A Modern Approach (4.ª ed.). Pearson.

Notas

  1. Ghallab, M., Nau, D. y Traverso, P. (2004). Automated Planning: Theory and Practice. Morgan Kaufmann.

  2. Russell, S. y Norvig, P. (2021). Artificial Intelligence: A Modern Approach (4.ª ed.). Pearson.

  3. Fikes, R. E. y Nilsson, N. J. (1971). STRIPS: A new approach to the application of theorem proving to problem solving. Artificial Intelligence, 2(3-4), 189-208. https://doi.org/10.1016/0004-3702(71)90010-5

  4. McDermott, D., Ghallab, M., Howe, A., Knoblock, C., Ram, A., Veloso, M., Weld, D. y Wilkins, D. (1998). PDDL: The Planning Domain Definition Language, Version 1.2. Yale Center for Computational Vision and Control. https://www.isi.edu/results/publications/19837/pddl-the-planning-domain-definition-language-version-1-2

  5. Bylander, T. (1994). The computational complexity of propositional STRIPS planning. Artificial Intelligence, 69(1-2), 165-204. https://doi.org/10.1016/0004-3702(94)90081-7

  6. Blum, A. L. y Furst, M. L. (1997). Fast planning through planning graph analysis. Artificial Intelligence, 90(1-2), 281-300. https://doi.org/10.1016/S0004-3702(96)00047-1

  7. Hoffmann, J. y Nebel, B. (2001). The FF planning system: fast plan generation through heuristic search. Journal of Artificial Intelligence Research, 14, 253-302. https://doi.org/10.1613/jair.855

Capítulo 10

Facsímil 2 · Inteligencia clásica

Capítulo 10: Planificación heurística, con SAT y agentes LLM

Entrando en el tema

En el capítulo anterior construimos un plan pequeño: validar una factura, enviarla y registrar el envío. Tres acciones. Mundo amable. Todo cabía en la cabeza.

Ahora subamos un poco la temperatura. Imagina un agente que prepara una release de software: ejecutar tests, revisar migraciones, comprobar permisos, generar changelog, pedir aprobación si hay riesgo, desplegar en staging, observar logs, desplegar en producción y dejar trazas. Además, cualquier paso puede fallar.

Ahí una lista de tareas ya no basta. Necesitamos decidir qué probar primero, cómo evitar combinaciones absurdas, cuándo preguntar a un solver y cuándo dejar que un LLM proponga el siguiente paso sin convertirlo en autoridad absoluta.

Tres maneras de no perderse

La planificación clásica enseña una idea sencilla: un plan es una secuencia de acciones aplicables que llega al objetivo. El problema es que las secuencias posibles crecen muy deprisa. Bylander mostró que incluso versiones proposicionales de STRIPS tienen complejidad computacional dura.1

En la práctica, se suelen combinar tres estrategias:

EstrategiaQué haceCuándo ayuda
HeurísticaOrdena la búsqueda por promesa.Cuando hay muchas acciones posibles.
SATPregunta si existe un plan de longitud kk.Cuando queremos una prueba lógica de factibilidad.
Agente LLMPropone pasos y explica decisiones.Cuando el entorno es abierto o lingüístico.

La clave es no confundir sus papeles. Una heurística orienta, pero puede equivocarse. SAT verifica una codificación, pero necesita un horizonte y un modelo. Un LLM propone y adapta lenguaje, pero sus pasos deben validarse.

Antes de elegir motor, conviene tener una definición mínima. Un plan π\pi no es una intención ni una explicación bonita. Es una secuencia de acciones que transforma estados sin saltarse precondiciones:

π=a0,a1,,an1,st+1=γ(st,at),Gsn\pi=\langle a_0,a_1,\ldots,a_{n-1}\rangle,\quad s_{t+1}=\gamma(s_t,a_t),\quad G\subseteq s_n
SímboloSignificadoEjemplo
π\piPlan completo.Validar, enviar, registrar.
ata_tAcción elegida en el paso tt.enviar_factura.
γ(st,at)\gamma(s_t,a_t)Función de transición: aplica una acción a un estado.Si la factura está validada, pasa a enviada.
GsnG\subseteq s_nEl estado final contiene todos los objetivos.Hay email enviado y log creado.

Si además hay costes, no basta con llegar. También importa cómo llegamos:

C(π)=t=0n1c(at)C(\pi)=\sum_{t=0}^{n-1}c(a_t)

Un plan de tres pasos puede ser peor que uno de cinco si el tercero manda un email irreversible sin revisión humana. Por eso en sistemas reales solemos mezclar longitud, coste, riesgo, permisos y confianza en la observación.

La misma tarea se ve distinta según la lente:

LentePregunta que haceRespuesta útil
Heurística¿Qué estado parece más cerca del objetivo?“Prueba primero el camino que ya tiene tests y changelog”.
SAT¿Existe algún plan de kk pasos que cumpla todas las reglas?“Con k=2k=2 no; con k=3k=3 sí”.
Agente LLM¿Qué paso tiene sentido proponer con este contexto textual?“Pide aprobación antes de desplegar porque hay una migración”.

Planificación como búsqueda heurística

Podemos leer un planner como un buscador en estados. Desde un estado ss, aplicamos acciones válidas y avanzamos. Para no probar todo a ciegas, usamos una función de evaluación:

f(s)=g(s)+h(s)f(s)=g(s)+h(s)
SímboloSignificadoEjemplo
ssEstado candidato durante la búsqueda.Tests pasados, changelog pendiente.
g(s)g(s)Coste acumulado desde el inicio.Dos acciones ejecutadas.
h(s)h(s)Estimación del coste restante hasta el objetivo.Faltan deploy y verificación.
f(s)f(s)Prioridad total del estado.2+2=42+2=4.

Esta idea conecta con A*, que ya vimos en búsqueda, pero en planificación la heurística suele estimar cuántas acciones faltan o qué hechos objetivo siguen sin cumplirse. Bonet y Geffner formularon la planificación como búsqueda heurística y mostraron cómo estimaciones relativamente simples podían guiar planners hacia soluciones útiles.2

Ejemplo de fórmula. Una heurística pedagógica muy simple sería contar cuántos objetivos faltan:

h(s)=Gsh(s)=|G\setminus s|
SímboloSignificadoEjemplo
GGConjunto de hechos objetivo.{tests_ok, deploy_hecho, logs_ok}.
ssHechos verdaderos ahora.{tests_ok}.
GsG\setminus sObjetivos que todavía faltan.{deploy_hecho, logs_ok}.
$G\setminus s$

Esta heurística es pobre, pero pedagógica: si un estado ya logró más objetivos, lo miramos antes. No cuenta mutex, recursos, precondiciones ocultas ni coste de acciones; por eso puede ordenar mal. Los planners reales usan heurísticas más informativas, como planes relajados o grafos de planificación. Graphplan introdujo una forma influyente de razonar con grafos de niveles y exclusiones mutuas.3 FF popularizó heurísticas basadas en planes relajados: ignorar ciertos efectos negativos para estimar una ruta optimista hacia el objetivo.4

Planificación con SAT

Otra forma de plantear el problema es fijar un horizonte kk: “¿existe un plan de kk pasos o menos?”. En vez de recorrer estados, construimos una fórmula booleana. Si la fórmula es SAT, el modelo nos dice qué acciones ocurren en cada tiempo. Si es UNSAT, no existe plan bajo esa codificación y ese horizonte.

Kautz y Selman hicieron célebre esta idea al formular planificación como satisfacibilidad.5

Podemos resumirlo así:

Φk=I0T0T1Tk1Gk\Phi_k = I_0 \land T_0 \land T_1 \land \cdots \land T_{k-1} \land G_k
SímboloSignificadoEjemplo
Φk\Phi_kFórmula SAT del problema con horizonte kk.“¿Hay plan de 3 pasos?”.
I0I_0Estado inicial codificado en tiempo 0.tests_pendientes@0.
TtT_tRestricciones de transición entre tt y t+1t+1.Si deploy@1, entonces build_ok@1.
GkG_kObjetivo exigido en el tiempo final.produccion_actualizada@3.

Las restricciones típicas son:

RestricciónForma mentalQué impide
Precondiciónatpre(a)ta_t\Rightarrow pre(a)_tEjecutar acciones sin requisitos.
Efecto positivoatadd(a)t+1a_t\Rightarrow add(a)_{t+1}Acciones que no cambian nada.
Efecto negativoat¬del(a)t+1a_t\Rightarrow \neg del(a)_{t+1}Hechos que sobreviven aunque fueron eliminados.
PersistenciaSi nadie cambia pp, pp persiste.Mundos que olvidan hechos arbitrariamente.
MutexAcciones incompatibles no ocurren juntas.Dos acciones compiten por el mismo recurso.

SAT no “entiende” el mundo. Solo decide si la fórmula tiene una asignación que cumple todo. La potencia está en que esa asignación es verificable.

Agentes LLM: propuesta no es permiso

Los agentes LLM reabren la planificación desde otro ángulo. No siempre tenemos un dominio PDDL completo. A veces el mundo es texto, páginas web, APIs, tickets, ficheros y decisiones humanas. Ahí el LLM es útil para proponer pasos, interpretar observaciones y decidir qué información falta.

ReAct mostró una forma influyente de intercalar razonamiento y actuación: el modelo razona, actúa sobre un entorno, observa y continúa.6 Toolformer exploró cómo un modelo puede aprender a invocar herramientas externas mediante APIs.7

Pero aquí conviene ser muy estrictos: un agente LLM no sustituye el modelo de planificación. Lo complementa.

PiezaEn planning clásicoEn agente LLM
EstadoHechos explícitos.Contexto, memoria, ficheros, logs.
AcciónOperador formal.Tool call propuesta.
PrecondiciónFórmula verificable.Validador antes de ejecutar.
EfectoAdd/delete list.Observación estructurada tras tool.
ReplanificaciónNueva búsqueda.Nuevo paso tras observar realidad.

El patrón sano es:

st+1=observe(exec(at,st))s_{t+1}=\operatorname{observe}(\operatorname{exec}(a_t,s_t))
SímboloSignificadoEjemplo
sts_tEstado antes del paso.Build verde, deploy pendiente.
ata_tAcción elegida para el paso tt.Ejecutar deploy en staging.
exec\operatorname{exec}Ejecución real de la herramienta.Llamada a CI/CD.
observe\operatorname{observe}Lectura verificable del resultado.Logs, código de salida, métricas.
st+1s_{t+1}Estado actualizado tras observar.Staging desplegado o fallo registrado.

Si st+1s_{t+1} contradice lo esperado, no seguimos “porque el plan lo decía”. Replanificamos.

Tres motores para planificar sin ir a ciegas Heurística ordena, SAT verifica horizontes y el agente propone pasos bajo validación. Búsqueda heurística f(s)=g(s)+h(s) prioriza estados prometedores usa planes relajados reduce exploración inútil SAT por horizonte Φk = I0 ∧ T0...Tk-1 ∧ Gk k=2 → UNSAT k=3 → SAT devuelve acciones por tiempo Agente LLM propone el siguiente paso lee observaciones explica fallos y alternativas no ejecuta sin validación Validador de pasos precondiciones · permisos · coste · riesgo · objetivo la propuesta se acepta solo si el estado la permite Ejecutar y observar si la observación contradice el plan, se vuelve al motor adecuado El LLM propone; la heurística prioriza; SAT verifica; el sistema observa. IA para gente curiosa / Facsímil 02 / Capítulo 10 / 686f6c61

En el día a día

En un equipo que construye agentes, este capítulo se traduce en decisiones muy prácticas. No basta con preguntar al modelo “qué harías ahora”. Hay que decidir qué propuestas pasan a ejecución y cuáles se descartan.

SituaciónLectura de planificaciónControl útil
Muchas tools posiblesAlto factor de ramificación.Heurística por coste, riesgo o progreso.
Duda sobre si existe plan cortoHorizonte kk.Codificación SAT o búsqueda acotada.
Tool críticaAcción con precondiciones duras.Guardrails antes de ejecutar.
Resultado inesperadoEstado observado distinto.Replanificación, no insistencia ciega.

En producción, una buena arquitectura suele separar cuatro capas: el LLM propone, el planificador o política ordena, los validadores autorizan y el monitor observa. Si esas capas se mezclan en un prompt enorme, el sistema puede parecer inteligente en la demo y volverse frágil con usuarios reales.

Por qué debería importarte

Porque los costes de un mal plan no son solo tokens. Un agente que reintenta sin nueva evidencia consume tiempo, dinero y confianza. Un agente que ejecuta pasos en el orden equivocado puede romper datos. Y un agente que no observa efectos reales vive en una ficción: cree que hizo algo porque lo escribió.

La planificación avanzada no consiste en meter más matemática por gusto. Consiste en elegir qué parte del sistema debe decidir qué. Las heurísticas reducen búsqueda, SAT da verificaciones fuertes para horizontes concretos, y los LLMs aportan flexibilidad lingüística. Juntos funcionan mejor cuando cada uno tiene límites claros.

Dónde solía tropezar yo

ErrorPor qué es un errorAntídoto
Creer que la heurística es una garantíaUna heurística ordena la búsqueda, no demuestra que un paso sea válido.Validar precondiciones y efectos después de elegir.
Usar SAT sin mirar la codificaciónSAT solo verifica lo que hemos escrito en la fórmula.Revisar transiciones, persistencia y mutex.
Pedir al LLM un plan largo y ejecutarlo enteroEl mundo puede cambiar tras el primer paso.Ejecutar un paso, observar y replanificar.
No contar el coste de las accionesEl plan más corto puede ser caro o peligroso.Añadir coste, riesgo y aprobación humana.
Reintentar sin nueva informaciónUn bucle no es planificación; es ausencia de criterio de parada.Registrar observación nueva o escalar.

Manos a la obra

La práctica real está en kit descargable. Compara tres cosas que conviene no mezclar: una heurística que ordena búsqueda, una comprobación por horizonte que dice SAT/UNSAT para una longitud concreta y una observación que puede romper el plan tras ejecutar el primer paso.

El caso base parece sencillo: validar, enviar y registrar. Pero el kit añade coste, riesgo irreversible y una observación de mundo real: después de validar, el correo deja de estar confirmado. Con esa observación, el sistema no debe insistir. Debe replanificar o escalar.

ArchivoQué contiene
data/planning_horizon_case.jsonEstado inicial, objetivo, acciones, costes y observación de fallo.
contracts/planning_horizon_policy.jsonHorizonte máximo y reglas mínimas de validación.
ops/compare_planning_strategies.pyBúsqueda heurística, enumeración de horizontes y replanificación.
output/planning_horizon_report.jsonResultados por horizonte, plan heurístico y replan tras observación.
output/planning_horizon_decision.mdInforme técnico del experimento.

Ejecuta:

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/compare_planning_strategies.py --write
cat output/planning_horizon_decision.md

Como gate:

python3 ops/compare_planning_strategies.py --write --fail-on-invalid

Qué entregaría un alumno. El Markdown generado, una acción alternativa con coste alto, una observación que rompa el plan y una decisión escrita: usar heurística, horizonte, aprobación humana o replanificación.

Cómo encaja todo

Este mapa compara tres formas de no perderse al planificar: una heurística ordena búsqueda, SAT verifica si existe plan para un horizonte concreto y el LLM propone pasos en entornos abiertos. Ninguna pieza debería ocupar el lugar de las otras.

La decisión aprendida es diseñar un bucle donde proponer, validar, ejecutar, observar y replanificar sean fases separadas. Esa arquitectura se reutiliza directamente en agentes y operación.

graph TD
    subgraph "Este capítulo"
        H["Heurística<br/>h(s)"]
        SAT["SAT<br/>horizonte k"]
        LLM["Agente LLM<br/>propone"]
        VAL["Validador<br/>pre y riesgo"]
        OBS["Observación<br/>estado real"]
        REPLAN["Replanificar"]
    end
    subgraph "Mismo facsímil"
        SEARCH["Búsqueda<br/>caps. 1-4"]
        CSP["SAT y CSP<br/>caps. 5-7"]
        GUARD["Guardrails<br/>cap. 8"]
        PDDL["PDDL<br/>cap. 9"]
        GAME["Juegos<br/>cap. 11"]
    end
    subgraph "Otros facsímiles"
        TOOLS["Tools y APIs<br/>fasc. 4"]
        AGENTS["Agentes<br/>fasc. 5"]
        OPS["Operación<br/>fasc. 6"]
        SEC["Seguridad<br/>fasc. 9"]
        UX["Producto y UX<br/>fasc. 11"]
    end

    SEARCH -->|"hereda"| H
    CSP -->|"codifica"| SAT
    PDDL -->|"define acciones"| VAL
    GUARD -->|"autoriza"| VAL
    H -->|"prioriza"| VAL
    SAT -->|"verifica"| VAL
    LLM -->|"propone"| VAL
    VAL -->|"ejecuta"| TOOLS
    TOOLS -->|"devuelve"| OBS
    OBS -->|"confirma"| AGENTS
    OBS -->|"contradice"| REPLAN
    REPLAN -->|"pide nuevo paso"| LLM
    REPLAN -->|"nueva búsqueda"| H
    REPLAN -->|"nuevo horizonte"| SAT
    OBS -->|"telemetría"| OPS
    VAL -->|"controles"| SEC
    GAME -->|"otros actores"| REPLAN
    UX -->|"explica estado"| OBS

    style H fill:#F5F5F5,stroke:#000000,stroke-width:2
    style SAT fill:#F5F5F5,stroke:#000000,stroke-width:2
    style LLM fill:#F5F5F5,stroke:#000000,stroke-width:2
    style VAL fill:#F5F5F5,stroke:#000000,stroke-width:2
    style OBS fill:#F5F5F5,stroke:#000000,stroke-width:2
    style REPLAN fill:#F5F5F5,stroke:#000000,stroke-width:2
    style SEARCH stroke-dasharray: 5 5
    style CSP stroke-dasharray: 5 5
    style GUARD stroke-dasharray: 5 5
    style PDDL stroke-dasharray: 5 5
    style GAME stroke-dasharray: 5 5
    style TOOLS stroke-dasharray: 5 5
    style AGENTS stroke-dasharray: 5 5
    style OPS stroke-dasharray: 5 5
    style SEC stroke-dasharray: 5 5
    style UX stroke-dasharray: 5 5

Vocabulario aprendido

TérminoDefinición
Heurística de planificaciónEstimación del coste restante hasta el objetivo.
HorizonteNúmero máximo de pasos permitido en el plan.
Función de transiciónRegla que calcula el siguiente estado tras aplicar una acción válida.
Planificación con SATTraducción de planning a una fórmula booleana.
MutexRelación de incompatibilidad entre acciones o hechos simultáneos.
Plan relajadoEstimación optimista que ignora algunos efectos negativos.
Bucle agenteCiclo de proponer, validar, ejecutar, observar y replanificar.

Antes de pasar página

  • ¿Puedo explicar para qué sirve una heurística en planificación?
  • ¿Distingo una heurística de una garantía lógica?
  • ¿Entiendo qué significa preguntar si Φk\Phi_k es SAT?
  • ¿Sé nombrar al menos tres restricciones de una codificación SAT de planning?
  • ¿Puedo explicar por qué un agente LLM debe observar antes de seguir?
  • ¿He ejecutado kit descargable y entendido por qué k=2k=2 es UNSAT?

En resumen

Idea fuerzaDetalle
La heurística ordena la búsqueda.Ayuda a mirar primero los estados prometedores, pero no garantiza validez.
SAT verifica horizontes.Si Φk\Phi_k es SAT, tenemos una asignación coherente de acciones y hechos.
El LLM propone, no autoriza.Sus pasos deben pasar por precondiciones, permisos, coste y observación.
La observación manda.Si el mundo contradice el plan, el sistema debe replanificar.

Para saber más

Blum, A. L. y Furst, M. L. (1997). Fast planning through planning graph analysis. Artificial Intelligence, 90(1-2), 281-300. https://doi.org/10.1016/S0004-3702(96)00047-1

Bonet, B. y Geffner, H. (2001). Planning as heuristic search. Artificial Intelligence, 129(1-2), 5-33. https://doi.org/10.1016/S0004-3702(01)00108-4

Bylander, T. (1994). The computational complexity of propositional STRIPS planning. Artificial Intelligence, 69(1-2), 165-204. https://doi.org/10.1016/0004-3702(94)90081-7

Ghallab, M., Nau, D. y Traverso, P. (2004). Automated Planning: Theory and Practice. Morgan Kaufmann.

Hoffmann, J. y Nebel, B. (2001). The FF planning system: fast plan generation through heuristic search. Journal of Artificial Intelligence Research, 14, 253-302. https://doi.org/10.1613/jair.855

Kautz, H. A. y Selman, B. (1992). Planning as satisfiability. En Proceedings of the 10th European Conference on Artificial Intelligence (pp. 359-363). John Wiley and Sons.

Schick, T., Dwivedi-Yu, J., Dessì, R., Raileanu, R., Lomeli, M., Zettlemoyer, L., Cancedda, N. y Scialom, T. (2023). Toolformer: Language Models Can Teach Themselves to Use Tools. https://doi.org/10.48550/arXiv.2302.04761

Yao, S., Zhao, J., Yu, D., Du, N., Shafran, I., Narasimhan, K. y Cao, Y. (2023). ReAct: Synergizing Reasoning and Acting in Language Models. International Conference on Learning Representations. https://arxiv.org/abs/2210.03629

Notas

  1. Bylander, T. (1994). The computational complexity of propositional STRIPS planning. Artificial Intelligence, 69(1-2), 165-204. https://doi.org/10.1016/0004-3702(94)90081-7

  2. Bonet, B. y Geffner, H. (2001). Planning as heuristic search. Artificial Intelligence, 129(1-2), 5-33. https://doi.org/10.1016/S0004-3702(01)00108-4

  3. Blum, A. L. y Furst, M. L. (1997). Fast planning through planning graph analysis. Artificial Intelligence, 90(1-2), 281-300. https://doi.org/10.1016/S0004-3702(96)00047-1

  4. Hoffmann, J. y Nebel, B. (2001). The FF planning system: fast plan generation through heuristic search. Journal of Artificial Intelligence Research, 14, 253-302. https://doi.org/10.1613/jair.855

  5. Kautz, H. A. y Selman, B. (1992). Planning as satisfiability. En Proceedings of the 10th European Conference on Artificial Intelligence (pp. 359-363). John Wiley and Sons.

  6. Yao, S., Zhao, J., Yu, D., Du, N., Shafran, I., Narasimhan, K. y Cao, Y. (2023). ReAct: Synergizing Reasoning and Acting in Language Models. International Conference on Learning Representations. https://arxiv.org/abs/2210.03629

  7. Schick, T., Dwivedi-Yu, J., Dessì, R., Raileanu, R., Lomeli, M., Zettlemoyer, L., Cancedda, N. y Scialom, T. (2023). Toolformer: Language Models Can Teach Themselves to Use Tools. https://doi.org/10.48550/arXiv.2302.04761

Capítulo 11

Facsímil 2 · Inteligencia clásica

Capítulo 11: Juegos: decidir con otros actores

Entrando en el tema

Hasta ahora hemos buscado caminos, satisfecho restricciones y construido planes. En todos esos casos el mundo podía ser difícil, pero no necesariamente estaba intentando ganarnos.

Un juego cambia la pregunta. Ya no basta con “¿qué acción me acerca al objetivo?”. Ahora hay que preguntar: “¿qué acción sigue siendo buena cuando otra persona, sistema, regla o instrucción externa reacciona?”.

Esto aparece en sitios muy cotidianos. Un sistema de validación mueve un umbral y los casos límite cambian de forma. Un moderador bloquea una formulación y aparecen rodeos lingüísticos. Un agente con herramientas lee una página web y esa página contiene otra orden que compite con la del usuario. Un competidor responde a tu precio. La distribución no está quieta: aprende de ti.

La teoría de juegos moderna nace con la idea de modelar decisiones interdependientes, popularizada por von Neumann y Morgenstern.1 En IA, los juegos fueron uno de los laboratorios clásicos para estudiar búsqueda con otros actores que responden. Shannon ya formulaba en 1950 cómo programar una computadora para jugar al ajedrez mediante búsqueda, evaluación y elección de jugadas.2

Cuando otro actor también elige

Podemos modelar un juego de forma mínima como:

J=(S,A,T,u,τ)\mathcal{J}=(S,A,T,u,\tau)
SímboloSignificadoEjemplo
SSEstados posibles del juego.Posiciones de un tablero o estados de un flujo.
A(s)A(s)Acciones legales en el estado ss.Mover pieza, aprobar, bloquear, escalar.
T(s,a)T(s,a)Transición tras aplicar una acción.Nuevo tablero o nuevo estado del sistema.
u(s)u(s)Utilidad de un resultado.Ganar +1+1, perder 1-1, coste alto 5-5.
τ(s)\tau(s)Jugador que decide en ese estado.MAX, MIN, usuario, sistema.

La diferencia con la planificación del capítulo anterior es sutil pero enorme: la transición ya no depende solo de mis acciones. También depende de respuestas.

ProblemaPregunta centralRiesgo si lo olvidas
Búsqueda¿Cómo llego al objetivo?Explorar demasiado.
Planificación¿Qué secuencia es ejecutable?Saltarte precondiciones.
Juego¿Qué pasa si alguien responde con un objetivo distinto?Diseñar solo para el caso feliz.

En un juego de suma cero, lo que MAX gana lo pierde MIN. Muchos productos reales no son suma cero pura, pero el modelo sigue siendo útil como gimnasia mental: obliga a imaginar al actor que persigue un objetivo propio.

Antes de seguir con fórmulas, bajémoslo a escenas reconocibles:

EscenaQué eliges túQué elige la otra parteQué enseña
Trabajo de claseEscribir una respuesta rápida.La rúbrica exige justificar pasos.No optimices solo velocidad.
Agente con correoResumir un email.El email contiene otra orden.Datos e instrucciones no son lo mismo.
SoporteCerrar un ticket.El usuario vuelve si no resolviste la causa.El resultado real llega después.
Planificación de turnosDar el turno preferido a alguien.Otra regla exige cubrir una franja crítica.Hay objetivos que compiten.
Producto con preciosBajar el precio.Clientes y competidores reajustan conducta.Una acción cambia el entorno.

La palabra “juego” no significa pelea. Significa interdependencia: mi decisión modifica tus opciones, y tu respuesta modifica el valor de mi decisión.

Minimax: elegir contra una respuesta buena

Minimax es la versión más limpia de esta idea. MAX quiere maximizar la utilidad. MIN quiere minimizarla. La función de valor se define recursivamente:

V(s)={u(s)si s es terminal maxaA(s)V(T(s,a))si τ(s)=MAX minaA(s)V(T(s,a))si τ(s)=MINV(s)= \begin{cases} u(s) & \text{si }s\text{ es terminal}\ \max_{a\in A(s)}V(T(s,a)) & \text{si }\tau(s)=MAX\ \min_{a\in A(s)}V(T(s,a)) & \text{si }\tau(s)=MIN \end{cases}
PiezaLectura sencillaEjemplo
Hoja terminalResultado ya evaluado.Victoria, derrota, caso resuelto.
Turno de MINLa otra parte elige tu peor continuación.Una instrucción externa compite con la orden principal.
Turno de MAXTú eliges la mejor garantía.Control que sigue bien ante respuestas distintas.
Valor de raízDecisión recomendada.Acción robusta, no acción optimista.

La enseñanza importante no es que todos los otros actores sean perfectos. Es que una decisión no se evalúa sola. Se evalúa por el árbol de respuestas que permite.

Si una acción parece brillante solo cuando nadie reacciona, no era una buena acción: era un deseo.

Ejemplo cercano: un agente puede hacer tres cosas con una herramienta delicada.

Acción de MAXSi todo va fácilSi aparece una instrucción conflictivaValor minimaxLectura humana
seguir_automatico+9+98-88-8Brilla en el caso cómodo, pero se cae cuando hay tensión.
pedir_revision+7+7+3+3+3+3Más lento, pero razonable.
limitar_tool+5+5+4+4+4+4No es espectacular, pero aguanta mejor.

Minimax elegiría limitar_tool: no porque sea la opción más vistosa, sino porque su resultado garantizado es mejor. Esta es la idea que quiero que te lleves: a veces la decisión madura no maximiza el mejor caso, sino que cuida el caso difícil.

Poda alfa-beta: no mirar lo que ya no decide

Minimax exacto puede crecer como una bestia:

O(bd)O(b^d)
SímboloSignificadoEjemplo
bbFactor de ramificación: acciones por estado.30 jugadas posibles.
ddProfundidad explorada.6 turnos.
bdb^dNodos aproximados a explorar.30630^6, demasiado grande.

La poda alfa-beta llega con una idea preciosa: no cambia la respuesta de minimax, cambia cuánto trabajo hace para encontrarla. Knuth y Moore analizaron formalmente esta técnica y su dependencia del orden de exploración.3

Mantenemos dos límites:

α=mejor valor garantizado para MAX,β=mejor valor garantizado para MIN\alpha=\text{mejor valor garantizado para MAX},\quad \beta=\text{mejor valor garantizado para MIN}

Una rama se poda cuando:

αβ\alpha\geq\beta
ConceptoQué significaIntuición
α\alphaMAX ya tiene una alternativa al menos así de buena.“No acepto menos que esto”.
β\betaMIN ya puede forzar una alternativa al menos así de mala para MAX.“La otra parte no me dejará mejorar por aquí”.
αβ\alpha\geq\betaLa rama no puede cambiar la decisión.Cortamos sin perder exactitud.
Orden de accionesQué rama miramos primero.Buen orden produce más poda.

En agentes modernos, esta idea se parece a no gastar herramientas caras, llamadas a modelos o exploraciones que ya no pueden cambiar la decisión. Para podar necesitas límites parciales: coste, riesgo, probabilidad, permisos o valor esperado.

Siguiendo el ejemplo anterior, imagina que ya evaluamos limitar_tool y sabemos que garantiza 44. Ese 44 se convierte en α\alpha: MAX ya tiene una alternativa aceptable.

Ahora exploramos seguir_automatico. La primera respuesta posible nos da 8-8. Como estamos en turno de MIN, la otra parte puede quedarse con ese 8-8. Da igual que todavía exista una rama cómoda con +9+9: MIN no tiene por qué escogerla. Esa rama ya no puede superar el 44 garantizado de limitar_tool, así que podemos cortarla.

MomentoQué sabemosQué hacemos
Ya vimos limitar_toolMAX puede garantizar 44.α=4\alpha=4.
Entramos en seguir_automaticoMIN encuentra una continuación con 8-8.β=8\beta=-8.
Comparamosα=4β=8\alpha=4\geq\beta=-8.Podamos lo que queda de esa rama.
ResultadoLa decisión no cambia.Ahorramos exploración.

En clase suele costar porque parece contraintuitivo: “¿cómo voy a ignorar una rama que podría tener +9+9?”. La respuesta es que esa rama depende de que MIN quiera ayudarte. Minimax no asume eso.

Funciones de evaluación

No siempre podemos llegar al final del árbol. En ajedrez, en Go, en un flujo de revisión o en un agente con herramientas, la profundidad útil se acaba antes que el mundo. Ejemplo de fórmula. Entonces podemos usar una función de evaluación. La forma lineal siguiente es una plantilla habitual para explicar la idea, pero en un sistema real las señales, pesos y escala se aprenden, se ajustan o se validan contra partidas, simulaciones o decisiones históricas:

Eval(s)=iwiϕi(s)\operatorname{Eval}(s)=\sum_i w_i\phi_i(s)
SímboloSignificadoEjemplo
ϕi(s)\phi_i(s)Señal observable del estado.Riesgo, coste, evidencia, satisfacción.
wiw_iPeso de esa señal.Seguridad pesa más que velocidad.
Eval(s)\operatorname{Eval}(s)Puntuación aproximada del estado.Estado prometedor o peligroso.

La función de evaluación es conocimiento del dominio convertido en número. Ahí está su poder y su peligro: si eliges señales pobres, el algoritmo optimiza una caricatura del problema. Si eliges señales medibles y las validas contra casos reales, la evaluación se vuelve una pieza de ingeniería, no una opinión.

DominioSeñales útilesError típico
AjedrezMaterial, movilidad, seguridad del rey.Capturar material y dejar mate.
SoporteResolución, satisfacción, coste, riesgo.Cerrar tickets rápido sin resolver.
RAGRelevancia, evidencia, cita, actualidad.Respuesta fluida sin soporte.
SeguridadImpacto, probabilidad, detectabilidad.Optimizar falsos positivos y dejar casos importantes fuera.

Si premias mal, el sistema buscará bien lo equivocado. Esa frase conviene tenerla muy subrayada.

Una forma de empatizar con esto es pensar en una rúbrica. Si en un examen solo puntúas que el resultado final sea correcto, alguien puede acertar por casualidad y parecer competente. Si también puntúas pasos, unidades, justificación y límites, la evaluación se parece más a lo que realmente querías medir.

SistemaSeñal que parece buenaLo que faltaba medir
Agente de soporteTicket cerrado rápido.Reapertura, satisfacción y evidencia.
Respuesta RAGTexto convincente.Citas, actualidad y trazabilidad.
ModeraciónPocas revisiones manuales.Casos dudosos que el sistema dejó pasar.
Agente con toolsTarea completada.Coste, permisos y reversibilidad.

La función de evaluación siempre educa al sistema. Si educas con una señal pobre, no te sorprendas de recibir un comportamiento pobre con buena presentación.

Monte Carlo: decidir simulando

Monte Carlo acepta una concesión: quizá no puedo calcular el árbol completo, pero puedo simular muchas trayectorias y estimar el valor medio de una acción.

V^(a)=1ni=1nRi\hat V(a)=\frac{1}{n}\sum_{i=1}^{n}R_i
SímboloSignificadoEjemplo
aaAcción que estamos estimando.Limitar una herramienta.
RiR_iRetorno observado en la simulación ii.Resultado de un caso simulado.
nnNúmero de simulaciones.100, 1 000, 10 000.
V^(a)\hat V(a)Valor medio estimado.Calidad esperada de la acción.

La incertidumbre baja despacio:

errorσn\operatorname{error}\approx \frac{\sigma}{\sqrt n}

Cuadruplicar simulaciones no divide el error entre cuatro; lo divide aproximadamente entre dos. Esta humildad estadística es importante. Monte Carlo no convierte un simulador malo en verdad: solo estima bien lo que el simulador representa.

Ejemplo: antes de permitir que un agente ejecute una herramienta, simulas conversaciones con tres políticas.

PolíticaSimulaciones observadasMediaLectura
limitar_tool4, 5, 4, 3, 4, 54,17Bastante estable.
seguir_automatico9, -8, -8, 2, -8, 9-0,67Puede ir muy bien o muy mal.
pedir_revision3, 7, 3, 6, 3, 74,83Buena media, con coste operativo.

Monte Carlo te ayuda a ver distribución, no solo una historia. Si solo miras el primer 99, seguir_automatico parece brillante. Si miras varias trayectorias, aparece la fragilidad.

MCTS: explorar y explotar

Monte Carlo Tree Search añade una pregunta: si tengo presupuesto limitado, ¿dónde simulo?

La respuesta clásica es equilibrar explotación y exploración. Kocsis y Szepesvári propusieron UCT, que aplica ideas de bandidos multi-brazo al árbol de búsqueda.4 Browne y colaboradores ofrecen una revisión amplia de MCTS y sus variantes.5

Una forma habitual de seleccionar acción es:

UCT(s,a)=Q(s,a)+clnN(s)N(s,a)UCT(s,a)=Q(s,a)+c\sqrt{\frac{\ln N(s)}{N(s,a)}}
SímboloSignificadoIntuición
Q(s,a)Q(s,a)Valor medio observado de la acción.Explotar lo que va bien.
N(s)N(s)Visitas al estado.Cuánto sabemos del nodo padre.
N(s,a)N(s,a)Veces que probamos esa acción.Cuánto sabemos de esa rama.
ccPeso de exploración.Más alto: más curiosidad.

El primer término explota: elige acciones con buena media. El segundo explora: empuja ramas poco visitadas para no casarnos demasiado pronto con la primera señal buena.

En una clase, esto se parece a preparar un examen. Si siempre estudias el tema que ya te sale bien, explotas. Si dedicas algo de tiempo al tema que apenas has mirado, exploras. MCTS formaliza ese equilibrio: profundiza donde hay señal, pero reserva presupuesto para descubrir sorpresas.

SituaciónExplotarExplorar
Agente con toolsProbar más la política que ya funciona.Revisar una tool poco usada pero crítica.
ProductoOptimizar el flujo con mejor conversión.Probar una variante nueva con pocos datos.
EvaluaciónAñadir casos parecidos a los conocidos.Buscar casos límite que no aparecen en la muestra.
EstudioRepasar lo que dominas.Entrenar el punto que todavía te incomoda.

Por eso cc importa tanto en UCT. Si cc es pequeño, el sistema se queda cerca de lo que ya parece bueno. Si cc es grande, se permite investigar más. No hay valor universal: depende del coste de equivocarte y de cuánto te duela no descubrir una opción mejor.

Simular con LLMs no es lo mismo

Un LLM puede generar escenarios, usuarios sintéticos, instrucciones alternativas o diálogos de prueba. Eso es útil. Pero no debemos confundir plausibilidad textual con muestra estadística de un proceso real.

Uso de LLMSí aportaNo demuestra
Pruebas de tensiónIdeas de casos límite y variaciones de instrucción.Frecuencia real de esos casos.
ProductoObjeciones y casos límite.Conversión esperada.
SoporteTickets sintéticos para ampliar criterios.Distribución real de incidencias.
EvalsCasos iniciales para cubrir huecos.Calidad final sin datos reales.

La regla práctica: usa el LLM para descubrir hipótesis; usa datos, experimentos, revisión humana o simuladores formales para justificar decisiones.

Decisión con instrucciones en tensión

La conexión con agentes modernos es directa. Un sistema que llama herramientas tiene superficie de interacción. Documentos recuperados, páginas web, tickets, correos o entradas de usuario pueden contener instrucciones que compiten con la tarea principal.

Fecha de corte: 10 de junio de 2026. En esta sección uso OWASP 2025 como marco de riesgos vigente para aplicaciones con LLM, pero lo importante para este capítulo no es memorizar una lista concreta: es aprender a modelar instrucciones externas, permisos, presupuesto y acciones excesivas como respuestas posibles dentro del árbol de decisión.

OWASP incluye riesgos específicos de aplicaciones con LLM, como instrucciones no confiables, exposición de datos, uso inseguro de salidas y acciones excesivas de agentes.6 Visto desde juegos, eso significa que una instrucción externa no es ruido: es otra fuerza dentro del sistema.

ControlPregunta de tensión
Permisos mínimos¿Qué pasa si el modelo intenta una herramienta que no debería?
Separar datos e instrucciones¿Un documento recuperado puede dar órdenes al agente?
Límites de presupuesto¿Pueden forzar llamadas infinitas o caras?
Trazas¿Verás una desviación antes de que tenga efecto real?
Pruebas de tensión continuas¿Tu eval incluye casos nuevos o solo los de lanzamiento?

Puente hacia aprendizaje por refuerzo

Juegos, MCTS y aprendizaje por refuerzo comparten una pregunta: qué acción conviene ahora para mejorar el valor futuro.

Sutton y Barto formulan el retorno como acumulación de recompensas, normalmente descontadas.7

Gt=k=0γkrt+k+1G_t=\sum_{k=0}^{\infty}\gamma^k r_{t+k+1}
SímboloSignificadoEjemplo
GtG_tRetorno desde el tiempo tt.Valor futuro de una política.
rt+k+1r_{t+k+1}Recompensa futura.Éxito, coste, seguridad, satisfacción.
γ\gammaFactor de descuento.Cuánto importa el futuro lejano.
PolíticaRegla para elegir acciones.Modelo + reglas + routing + permisos.

Esto prepara el terreno para capítulos posteriores: no evaluaremos solo respuestas aisladas, sino comportamiento a lo largo de una trayectoria.

Decidir cuando alguien responde Minimax garantiza, alfa-beta poda, MCTS simula y producto pregunta por incentivos. Árbol con respuestas MAX elige MIN MIN MIN 5 4 -8 9 3 7 MIN propaga mínimos; MAX elige la mejor garantía. MCTS con presupuesto Seleccionar Expandir Simular Actualizar Q(s,a)+c√(ln N / Nₐ) Más valor medio, pero también curiosidad por ramas poco visitadas. Lectura de producto Incentivo qué gana el otro Capacidad qué puede probar Superficie inputs y tools Respuesta cómo se adapta Si otra orden o incentivo puede cambiar el resultado, modela el juego. La pregunta no es solo “qué hago”, sino “qué respuesta habilito”. IA para gente curiosa / Facsímil 02 / Capítulo 11 / 686f6c61

En el día a día

La mentalidad de juegos cambia cómo diseñamos sistemas con IA.

SituaciónLectura de juegoControl útil
Usuario bordea una política.MIN representa la respuesta que presiona tu regla.Evals de tensión y trazas.
Agente lee contenido externo.El documento puede traer otra instrucción.Separar instrucciones de datos.
Tool cara o irreversible.Una entrada externa puede forzar coste o efecto no deseado.Presupuesto, permisos y aprobación humana.
Métrica fácil de manipular.El sistema optimiza el marcador, no el objetivo.Métricas compuestas y revisión.

Cuando una decisión importante depende de cómo responde otra parte, diseña como si estuvieras jugando una partida. No por paranoia: por respeto a la realidad.

Por qué debería importarte

Porque muchos fallos de IA no ocurren en el primer uso feliz. Ocurren cuando alguien descubre cómo responde el sistema y empieza a optimizar contra esa respuesta.

Si tu agente siempre confía en el documento recuperado, el documento se vuelve un canal de instrucciones. Si tu moderador solo detecta palabras obvias, los rodeos cambian de forma. Si tu eval premia rapidez, el agente aprende atajos. Si tu política no limita presupuesto, una conversación puede acabar en una acción costosa.

Los juegos enseñan a preguntar por el segundo movimiento.

Dónde solía tropezar yo

ErrorPor qué es un errorAntídoto
Evaluar solo la acción propiaLa calidad depende de la respuesta que habilita.Dibujar al menos un turno del otro actor.
Pensar que minimax describe a toda personaNo todo usuario es racional ni persigue un objetivo opuesto.Usarlo como caso de tensión, no como psicología humana.
Creer que alfa-beta cambia la decisiónLa poda exacta conserva el resultado de minimax.Separar semántica de eficiencia.
Usar Monte Carlo con simulador débilSimular mucho no corrige un modelo malo del mundo.Validar el simulador con datos reales.
Tratar al LLM como simulador estadísticoGenera plausibilidad, no muestras independientes.Usarlo para hipótesis; contrastar con evidencia.
Diseñar solo para el usuario idealLos sistemas reales tienen incentivos, fricción y órdenes en conflicto.Preguntar qué cambia si el sistema falla.

Manos a la obra

La práctica real está en kit descargable. El kit compara minimax, alfa-beta, medias Monte Carlo y UCT sobre el mismo árbol de decisión. El escenario no habla de un oponente caricaturesco: habla de otro actor, otro sistema o un entorno que puede responder de forma desfavorable.

El aprendizaje útil es que la decisión cambia según el criterio. Minimax protege el peor caso. Monte Carlo estima comportamiento medio. UCT decide dónde gastar más simulación. Alfa-beta no cambia la respuesta exacta de minimax; solo evita mirar ramas que ya no pueden mejorar la decisión.

ArchivoQué contiene
data/game_tree.jsonÁrbol de decisiones, utilidades terminales, rollouts y visitas UCT.
contracts/game_policy.jsonConstante UCT y checks mínimos de poda/consistencia.
ops/audit_game_search.pyMinimax, alfa-beta, media Monte Carlo y UCT.
output/game_search_report.jsonScores, hojas visitadas, podas, medias y UCT.
output/game_search_decision.mdLectura técnica para defender la decisión.

Ejecuta:

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/audit_game_search.py --write
cat output/game_search_decision.md

Como gate:

python3 ops/audit_game_search.py --write --fail-on-invalid

Qué entregaría un alumno. El Markdown generado, un nodo nuevo con utilidades terminales, una comparación entre minimax y Monte Carlo y una decisión escrita: optimizar peor caso, media, revisión humana o más simulación.

Cómo encaja todo

Este mapa añade una capa que no estaba en la planificación simple: otras personas, sistemas, reglas o instrucciones también pueden responder. Por eso aparecen minimax, poda alfa-beta, evaluación, Monte Carlo y MCTS.

La decisión aprendida es no evaluar solo el primer movimiento. Hay que mirar qué respuestas habilita una acción, qué peor caso toleras y cuándo merece la pena simular más.

graph TD
    subgraph "Este capítulo"
        GAME["Juego<br/>actores e incentivos"]
        MINI["Minimax<br/>peor respuesta"]
        AB["Alfa-beta<br/>poda exacta"]
        EVAL["Evaluación<br/>score parcial"]
        MC["Monte Carlo<br/>simulación"]
        MCTS["MCTS<br/>UCT"]
        PROD["Producto<br/>con incentivos"]
    end
    subgraph "Mismo facsímil"
        SEARCH["Búsqueda<br/>caps. 1-4"]
        GUARD["Guardrails<br/>cap. 8"]
        PLAN["Planificación<br/>caps. 9-10"]
        SYMBOL["Símbolos<br/>cap. 12"]
    end
    subgraph "Otros facsímiles"
        EVALS["Evals<br/>fasc. 4"]
        AGENTS["Agentes<br/>fasc. 5"]
        RL["Aprendizaje por refuerzo<br/>fasc. 7"]
        SEC["Seguridad<br/>fasc. 9"]
        OPS["Operación<br/>fasc. 6"]
    end

    SEARCH -->|"árbol"| GAME
    GAME -->|"respuesta"| MINI
    MINI -->|"misma decisión"| AB
    MINI -->|"corte por profundidad"| EVAL
    GAME -->|"incertidumbre"| MC
    MC -->|"asigna presupuesto"| MCTS
    MCTS -->|"retorno futuro"| RL
    PLAN -->|"acciones"| PROD
    GUARD -->|"límites"| PROD
    PROD -->|"casos límite"| SEC
    PROD -->|"casos"| EVALS
    PROD -->|"tools"| AGENTS
    EVAL -->|"métricas"| EVALS
    SYMBOL -->|"reglas"| GUARD
    OPS -->|"trazas"| PROD

    style GAME fill:#F5F5F5,stroke:#000000,stroke-width:2
    style MINI fill:#F5F5F5,stroke:#000000,stroke-width:2
    style AB fill:#F5F5F5,stroke:#000000,stroke-width:2
    style EVAL fill:#F5F5F5,stroke:#000000,stroke-width:2
    style MC fill:#F5F5F5,stroke:#000000,stroke-width:2
    style MCTS fill:#F5F5F5,stroke:#000000,stroke-width:2
    style PROD fill:#F5F5F5,stroke:#000000,stroke-width:2
    style SEARCH stroke-dasharray: 5 5
    style GUARD stroke-dasharray: 5 5
    style PLAN stroke-dasharray: 5 5
    style SYMBOL stroke-dasharray: 5 5
    style EVALS stroke-dasharray: 5 5
    style AGENTS stroke-dasharray: 5 5
    style RL stroke-dasharray: 5 5
    style SEC stroke-dasharray: 5 5
    style OPS stroke-dasharray: 5 5

Vocabulario aprendido

TérminoDefinición
Juego con otros actoresDecisión donde otras partes responden con objetivos propios.
UtilidadValor numérico de un resultado para un jugador.
EstrategiaRegla para elegir acciones según estado e información.
MinimaxElección con mejor valor garantizado ante respuesta óptima de MIN.
Poda alfa-betaDescarte de ramas que no pueden cambiar la decisión de minimax.
Función de evaluaciónHeurística que puntúa estados no terminales.
Monte CarloEstimación por simulaciones repetidas.
MCTSBúsqueda en árbol que reparte simulaciones de forma adaptativa.
UCTFórmula que mezcla valor observado y exploración de ramas poco visitadas.
RetornoRecompensa acumulada futura de una trayectoria.

Antes de pasar página

  • ¿Puedo explicar por qué un juego no es una búsqueda normal?
  • ¿Entiendo la recursión de minimax para MAX y MIN?
  • ¿Sé qué representan α\alpha y β\beta?
  • ¿Distingo función de evaluación de utilidad terminal?
  • ¿Puedo explicar qué estima Monte Carlo y qué no demuestra?
  • ¿Entiendo por qué MCTS necesita explorar y explotar?
  • ¿Puedo traducir un problema de producto a actores, incentivos y respuestas?

En resumen

Idea fuerzaDetalle
Juegos añaden respuesta.La acción importa por las opciones que habilita al otro actor.
Minimax busca garantía.Elige la mejor jugada bajo peor respuesta racional.
Alfa-beta ahorra trabajo.Poda ramas sin cambiar la decisión exacta de minimax.
Evaluar es diseñar criterio.Si puntúas mal, el sistema buscará bien lo incorrecto.
Monte Carlo estima.Simular ayuda con presupuesto finito, pero depende del simulador.
Producto también tiene incentivos.Si otra orden o interés cambia el resultado, hay un juego que modelar.

Para saber más

Browne, C. B., Powley, E., Whitehouse, D., Lucas, S. M., Cowling, P. I., Rohlfshagen, P., Tavener, S., Perez, D., Samothrakis, S. y Colton, S. (2012). A survey of Monte Carlo Tree Search methods. IEEE Transactions on Computational Intelligence and AI in Games, 4(1), 1-43. https://doi.org/10.1109/TCIAIG.2012.2186810

Knuth, D. E. y Moore, R. W. (1975). An analysis of alpha-beta pruning. Artificial Intelligence, 6(4), 293-326. https://doi.org/10.1016/0004-3702(75)90019-3

Kocsis, L. y Szepesvári, C. (2006). Bandit based Monte-Carlo planning. En Machine Learning: ECML 2006 (LNCS 4212, pp. 282-293). Springer. https://doi.org/10.1007/11871842_29

OWASP Foundation. (2025). OWASP Top 10 for LLM and Generative AI Applications 2025. https://genai.owasp.org/

Russell, S. y Norvig, P. (2021). Artificial Intelligence: A Modern Approach (4.ª ed.). Pearson.

Shannon, C. E. (1950). Programming a computer for playing chess. The London, Edinburgh, and Dublin Philosophical Magazine and Journal of Science, 41(314), 256-275. https://doi.org/10.1080/14786445008521796

Sutton, R. S. y Barto, A. G. (2018). Reinforcement Learning: An Introduction (2.ª ed.). MIT Press. https://incompleteideas.net/book/the-book-2nd.html

von Neumann, J. y Morgenstern, O. (1944). Theory of Games and Economic Behavior. Princeton University Press.

Notas

  1. von Neumann, J. y Morgenstern, O. (1944). Theory of Games and Economic Behavior. Princeton University Press.

  2. Shannon, C. E. (1950). Programming a computer for playing chess. The London, Edinburgh, and Dublin Philosophical Magazine and Journal of Science, 41(314), 256-275. https://doi.org/10.1080/14786445008521796

  3. Knuth, D. E. y Moore, R. W. (1975). An analysis of alpha-beta pruning. Artificial Intelligence, 6(4), 293-326. https://doi.org/10.1016/0004-3702(75)90019-3

  4. Kocsis, L. y Szepesvári, C. (2006). Bandit based Monte-Carlo planning. En Machine Learning: ECML 2006 (LNCS 4212, pp. 282-293). Springer. https://doi.org/10.1007/11871842_29

  5. Browne, C. B., Powley, E., Whitehouse, D., Lucas, S. M., Cowling, P. I., Rohlfshagen, P., Tavener, S., Perez, D., Samothrakis, S. y Colton, S. (2012). A survey of Monte Carlo Tree Search methods. IEEE Transactions on Computational Intelligence and AI in Games, 4(1), 1-43. https://doi.org/10.1109/TCIAIG.2012.2186810

  6. OWASP Foundation. (2025). OWASP Top 10 for LLM and Generative AI Applications 2025. https://genai.owasp.org/

  7. Sutton, R. S. y Barto, A. G. (2018). Reinforcement Learning: An Introduction (2.ª ed.). MIT Press. https://incompleteideas.net/book/the-book-2nd.html

Capítulo 12

Facsímil 2 · Inteligencia clásica

Capítulo 12: Conocimiento simbólico y recapitulación

Entrando en el tema

Este facsímil empezó con una pregunta humilde: ¿cómo resuelve problemas la IA cuando el mundo se puede modelar como estados, acciones, restricciones y decisiones?

Hemos recorrido búsqueda, heurísticas, SAT, CSP, planificación, guardrails y juegos con otros actores. Todas esas piezas tienen algo en común: no viven solo de texto plausible. Necesitan estructura.

El conocimiento simbólico es la parte de la IA que intenta decir cosas explícitas sobre el mundo: qué entidades existen, cómo se relacionan, qué reglas valen, qué se puede inferir y qué pregunta exacta queremos hacer. No sustituye a los modelos neuronales. Los complementa.

Un LLM puede redactar una respuesta magnífica. Un vector store puede encontrar el fragmento parecido. Un grafo de conocimiento puede decir: “esta factura pertenece a este cliente, este cliente tiene este contrato, este contrato exige esta condición y por eso esta acción está permitida”.

Ese “por eso” es la pieza clave.

Cuando parecerse no basta

En un buscador semántico, convertimos textos y preguntas en vectores. Luego medimos similitud. Una fórmula habitual es la similitud coseno:

sim(q,d)=cos(q,d)=qdqd\operatorname{sim}(q,d)=\cos(q,d)=\frac{q\cdot d}{\|q\|\,\|d\|}
SímboloSignificadoLectura sencilla
qqEmbedding de la pregunta.La consulta convertida en vector.
ddEmbedding del documento.Un fragmento convertido en vector.
qdq\cdot dProducto escalar.Cuánto apuntan en dirección parecida.
q\|q\|, d\|d\|Norma de cada vector.Tamaño del vector.
cos(q,d)\cos(q,d)Similitud normalizada.Cercanía semántica entre pregunta y documento.

Esto es potentísimo para recuperar contexto. Pero tiene un límite: la similitud no es una prueba.

PreguntaUn vector store puede hacerUn grafo puede hacer
“Busca documentos parecidos a esta duda”Recuperar fragmentos relacionados.No es su punto fuerte.
“¿Qué servicios dependen de esta base de datos?”Encontrar textos que lo mencionan.Seguir relaciones dependeDe.
“¿Puede este usuario aprobar esta factura?”Encontrar políticas similares.Evaluar permisos, roles y umbrales.
“¿Por qué se tomó esta decisión?”Mostrar fragmentos usados.Devolver una cadena de hechos y reglas.

La diferencia no es estética. Es operativa. Cuando estás explorando, el parecido ayuda. Cuando estás tomando decisiones, la relación exacta importa.

RDF: hechos pequeños con identidad

RDF representa conocimiento como tripletas: sujeto, predicado y objeto.1

t=(s,p,o),G={t1,t2,,tn}t=(s,p,o),\qquad \mathcal{G}=\{t_1,t_2,\ldots,t_n\}
SímboloSignificadoEjemplo
ssSujeto.factura:f9
ppPredicado o relación.perteneceA
ooObjeto.cliente:c42
ttUna tripleta.Un hecho elemental.
G\mathcal{G}Grafo RDF.Conjunto de tripletas.

Ejemplos cotidianos:

SujetoPredicadoObjeto
factura:f9perteneceAcliente:c42
factura:f9importe1280
cliente:c42tienePlanplan:empresa
servicio:apidependeDeservicio:db
servicio:dbalmacenatabla:facturas
persona:anatieneRolrol:finanzas

La parte importante no es solo el formato. Es la identidad. cliente:c42 no es una palabra suelta. Es una referencia estable. Si otra tabla, documento, API o agente habla de cliente:c42, estamos hablando de la misma cosa.

Ese detalle evita un montón de niebla. “Ana”, “A. García”, “ana@empresa.com” y persona:ana-garcia pueden ser cuatro formas de referirse a una entidad. El conocimiento simbólico obliga a decidir cuándo son lo mismo y cuándo no.

RDFS y OWL: decir qué significa el grafo

RDF dice hechos. RDFS y OWL ayudan a decir qué significan esos hechos. Si RDF es “Ana trabaja en Finanzas”, RDFS y OWL son el vocabulario que permite entender qué es una persona, qué es un departamento, qué significa trabajaEn y qué consecuencias se derivan de esa relación.

No son grafos aparte. Son capas de significado encima del mismo grafo.

CapaQué aportaPregunta que responde
RDFHechos como tripletas.¿Qué relaciones concretas existen?
RDFSClases, subclases, dominio y rango.¿Qué tipo de cosas conectan esas relaciones?
OWLAxiomas más expresivos para ontologías.¿Qué reglas lógicas adicionales valen en el dominio?

RDFS es útil cuando quieres que el grafo tenga una gramática compartida. Permite declarar que Factura es una clase, que Factura es subclase de DocumentoFiscal, que perteneceA conecta documentos fiscales con clientes y que ciertos tipos se heredan.2 OWL añade más expresividad: clases disjuntas, equivalencias, propiedades inversas, restricciones de cardinalidad y axiomas para razonar con más precisión.3

Una forma rápida de verlo:

NecesidadRDFS suele bastarOWL empieza a tener sentido
Heredar tipos.Factura subclase de DocumentoFiscal.También, pero con más axiomas alrededor.
Decir qué conecta una relación.perteneceA tiene dominio y rango.Puedes añadir inversas o restricciones.
Evitar categorías incompatibles.Limitado.Cliente disjunto de Servicio.
Decir que dos clases son equivalentes.Limitado.CompradorEmpresa equivalente a cierta combinación de condiciones.
Expresar “exactamente uno”.No es su fuerte.Cardinalidad sobre una propiedad.

Una inferencia sencilla:

type(x,C)CDtype(x,D)\operatorname{type}(x,C)\land C\sqsubseteq D\Rightarrow \operatorname{type}(x,D)
SímboloSignificadoEjemplo
type(x,C)\operatorname{type}(x,C)xx pertenece a la clase CC.factura:f9 es Factura.
CDC\sqsubseteq DCC es subclase de DD.Factura subclase de DocumentoFiscal.
\RightarrowPodemos derivar.factura:f9 es DocumentoFiscal.

Esto parece pequeño, pero cambia cómo trabajamos. Si una regla aplica a todo DocumentoFiscal, también aplica a facturas, abonos o recibos que hereden de esa clase.

RDFS también permite inferir tipos desde dominio y rango:

(s,p,o)domain(p,C)type(s,C)(s,p,o)\land \operatorname{domain}(p,C)\Rightarrow \operatorname{type}(s,C) (s,p,o)range(p,D)type(o,D)(s,p,o)\land \operatorname{range}(p,D)\Rightarrow \operatorname{type}(o,D)
PiezaLectura sencillaEjemplo
domain(p,C)\operatorname{domain}(p,C)Quien usa la relación pp como sujeto pertenece a CC.Si algo perteneceA, ese algo es DocumentoFiscal.
range(p,D)\operatorname{range}(p,D)Quien aparece como objeto de pp pertenece a DD.Si algo recibe perteneceA, ese algo es Cliente.
(s,p,o)(s,p,o)Hecho observado.factura:f9 perteneceA cliente:c42.
Tipo inferidoConclusión derivada.factura:f9 es DocumentoFiscal; cliente:c42 es Cliente.
DeclaraciónLectura humanaUtilidad
Factura subClassOf DocumentoFiscalToda factura es un documento fiscal.Reutilizar reglas.
perteneceA domain DocumentoFiscalSi algo pertenece a un cliente, esperamos que sea documento fiscal.Detectar modelado raro.
perteneceA range ClienteEl objeto de esa relación debe ser cliente.Validar datos.
Cliente disjointWith ServicioUna entidad no debería ser ambas cosas.Evitar mezclas de dominio.

OWL conviene cuando la frase que quieres modelar ya no cabe bien en “subclase, dominio y rango”.

Axioma OWLLectura humanaEjemplo comprensible
disjointWithDos clases no deberían solaparse.Un Cliente no es un Servicio.
equivalentClassDos descripciones nombran la misma clase.ClientePremium equivale a cliente con plan empresa y contrato activo.
inverseOfUna relación es la inversa de otra.Si factura perteneceA cliente, cliente tieneFactura factura.
cardinalityUna relación debe aparecer cierto número de veces.Una factura debería tener un único cliente responsable.
sameAsDos identificadores nombran la misma entidad.persona:ana y usuario:u17 son la misma persona.

La parte delicada: más expresividad también trae más responsabilidad. OWL razona con una lógica formal y, en muchos usos, con una mentalidad de mundo abierto: que no sepas un dato no significa que sea falso. Para producto, permisos o formularios, muchas veces conviene traducir las reglas críticas a validadores ejecutables además de modelarlas en la ontología.

RDFS y OWL: significado sobre el grafo RDF declara hechos; RDFS hereda tipos; OWL añade axiomas para razonar con más cuidado. 1 · Datos RDF factura f9 cliente c42 servicio api servicio db perteneceA dependeDe 2 · RDFS Factura clase DocumentoFiscal superclase Cliente rango BaseDatos clase subClassOf Dominio y rango permiten inferir tipos desde relaciones observadas. 3 · OWL disjointWith clases incompatibles inverseOf relación inversa cardinality cantidad esperada sameAs misma entidad Más semántica no es decoración: es más contrato que mantener. IA para gente curiosa / Facsímil 02 / Capítulo 12 / 686f6c61

La tentación es convertir la ontología en una catedral perfecta. Suele ser mala idea. Una ontología útil empieza pequeña: nombres claros, relaciones estables, restricciones que de verdad ayuden y ejemplos que el equipo entienda.

SPARQL: preguntar por relaciones exactas

SPARQL es el lenguaje estándar para consultar grafos RDF.4 En vez de pedir “texto parecido”, buscamos patrones de tripletas.

La forma mental más útil no es “SQL para grafos”, aunque el nombre se parezca. Es mejor leerlo así: dibujo un pequeño patrón con huecos, y el motor busca en el grafo todas las formas de rellenar esos huecos.

Un patrón mínimo:

q={(?x,:dependeDe,:servicioDB)}q=\{(?x,\texttt{:dependeDe},\texttt{:servicioDB})\}

La variable  ?x\ ?x se rellena con las entidades que encajan.

Formalmente, una consulta de patrones devuelve asignaciones de variables:

Sol(P,G)={μtP, μ(t)G}\operatorname{Sol}(P,\mathcal{G})=\{\mu\mid \forall t\in P,\ \mu(t)\in \mathcal{G}\}
SímboloSignificadoLectura sencilla
PPPatrón de tripletas.Lo que preguntamos.
G\mathcal{G}Grafo RDF.Los hechos disponibles.
μ\muAsignación de variables.Qué valor toma cada ?variable.
Sol(P,G)\operatorname{Sol}(P,\mathcal{G})Soluciones.Filas de la tabla resultado.
SELECT ?factura WHERE {
  ?factura :perteneceA :clienteC42 .
  ?factura rdf:type :DocumentoFiscal .
}

Lectura humana: “dame las facturas que pertenecen al cliente C42 y además son documentos fiscales”.

La consulta se lee de dentro hacia fuera:

ParteQué haceLectura humana
?facturaVariable.“Algo que todavía no sé”.
:perteneceA :clienteC42Relación obligatoria.Ese algo pertenece al cliente C42.
rdf:type :DocumentoFiscalTipo obligatorio.Ese algo es documento fiscal.
SELECT ?facturaProyección.Devuelve solo la variable ?factura.

Un ejemplo algo más realista:

PREFIX : <https://empresa.ejemplo/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT ?factura ?importe WHERE {
  ?factura rdf:type :DocumentoFiscal ;
           :perteneceA :clienteC42 ;
           :importe ?importe .

  FILTER(?importe > 1000)
}
ORDER BY DESC(?importe)

Lectura humana: “dame documentos fiscales del cliente C42 cuyo importe supere 1000, ordenados de mayor a menor”.

Hay tres detalles prácticos aquí:

DetalleQué significaPor qué importa
PREFIXAbrevia URIs largas.Hace legible la consulta.
;Reutiliza el mismo sujeto.Evita repetir ?factura tres veces.
FILTERRestringe soluciones.No basta con encajar: debe cumplir una condición.

OPTIONAL sirve cuando un dato ayuda, pero no debería eliminar la fila si falta:

SELECT ?factura ?importe ?fechaPago WHERE {
  ?factura rdf:type :DocumentoFiscal ;
           :perteneceA :clienteC42 ;
           :importe ?importe .

  OPTIONAL {
    ?factura :fechaPago ?fechaPago .
  }
}

Lectura humana: “dame las facturas y su importe; si existe fecha de pago, añádela, pero no descartes facturas sin fecha”.

Esto es muy importante en producto. Si usas una relación obligatoria cuando el dato es opcional, desaparecen resultados válidos. Si usas OPTIONAL para algo que de verdad debería existir, puedes ocultar un problema de calidad de datos.

SPARQL también tiene distintas formas de preguntar:

FormaDevuelveCuándo usarla
SELECTTabla de variables.Listar facturas, servicios, permisos.
ASKtrue o false.Comprobar si existe una relación.
CONSTRUCTNuevas tripletas RDF.Crear una vista o grafo derivado.
DESCRIBEDescripción de un recurso.Explorar una entidad concreta.

Ejemplo con ASK:

ASK WHERE {
  :usuarioU17 :tienePermiso :permisoExportar .
  :permisoExportar :autorizaFuncion :exportarDatos .
}

Lectura humana: “¿tiene este usuario un permiso que autoriza exportar datos?”.

Ejemplo con CONSTRUCT:

CONSTRUCT {
  ?servicio :afectadoPor :servicioDB .
}
WHERE {
  ?servicio :dependeDe+ :servicioDB .
}

Lectura humana: “construye nuevas tripletas diciendo qué servicios quedan afectados por servicioDB, siguiendo una o más dependencias”.

El + de :dependeDe+ es un camino de propiedad. Permite seguir relaciones encadenadas:

ExpresiónLectura
:dependeDeUna dependencia directa.
:dependeDe+Una o más dependencias encadenadas.
:dependeDe*Cero o más dependencias encadenadas.
^:dependeDeLa relación en sentido inverso.

En operaciones, esto es oro. Si api depende de db, y web depende de api, preguntar por :dependeDe+ :db permite encontrar tanto api como web.

SPARQL: patrón, grafo y resultado La consulta dibuja huecos; el grafo los rellena con entidades que cumplen todas las relaciones. Patrón WHERE ?factura hueco :perteneceA cliente c42 FILTER(?importe > 1000) Grafo RDF factura f9 cliente c42 factura f8 cliente c42 perteneceA perteneceA importe 1280 tipo fiscal importe 650 tipo fiscal Tabla SELECT ?factura ?importe factura:f9 1280 factura:f8 encaja en cliente y tipo, pero cae por el filtro de importe. La consulta no inventa: solo enlaza variables con hechos existentes. Si el grafo está incompleto, SPARQL será exacto sobre un mundo incompleto. Para decidir, primero modela bien; después consulta con precisión. IA para gente curiosa / Facsímil 02 / Capítulo 12 / 686f6c61

Otro ejemplo:

SELECT ?servicio WHERE {
  ?servicio :dependeDe+ :servicioDB .
}

Lectura humana: “dime qué servicios dependen directa o indirectamente de esta base de datos”.

En sistemas con LLM, SPARQL suele entrar después de resolver entidades. El modelo puede entender que “la base de datos de facturación” se refiere a :servicioDB. Pero la consulta que decide qué servicios dependen de ella debería ser formal, trazable y repetible.

PasoQué hace el LLMQué hace SPARQL
Entender la preguntaDetecta intención y entidades candidatas.No interpreta lenguaje natural.
Resolver entidadPropone :servicioDB.Usa la URI exacta.
Consultar relacionesPuede explicar la consulta.Devuelve coincidencias del grafo.
ResponderRedacta con contexto.Aporta hechos y trazabilidad.

SPARQL no arregla un grafo pobre. Si falta una relación, no aparecerá. Si dos entidades están duplicadas, puede devolver resultados partidos. Si una propiedad se usa con significados distintos, la consulta será técnicamente correcta y semánticamente frágil.

Por eso SPARQL y ontología van juntas: una buena consulta depende de un buen vocabulario.

La diferencia con una búsqueda textual es clara:

Búsqueda textualConsulta simbólica
“Devuélveme textos donde parezca hablarse de dependencias.”“Devuélveme entidades con relación dependeDe hacia servicioDB.”
Puede recuperar fragmentos útiles aunque usen otras palabras.Devuelve coincidencias exactas del modelo.
Tolera ambigüedad.Exige datos bien modelados.
Ideal para explorar.Ideal para decidir, auditar y explicar.

Ontologías y sistemas expertos

Thomas Gruber definió una ontología como una especificación explícita de una conceptualización.5 Dicho sin solemnidad: una ontología es el acuerdo sobre cómo vamos a nombrar y relacionar las cosas importantes.

Ese acuerdo es más profundo que un glosario. Un glosario define palabras. Una ontología define qué tipos de cosas existen, qué relaciones son válidas, qué restricciones importan y qué se puede inferir. Noy y McGuinness popularizaron una guía práctica para crear ontologías empezando por alcance, reutilización, clases, propiedades, restricciones e instancias.6

Una forma compacta de escribirlo:

O=(C,P,R,A)\mathcal{O}=(\mathcal{C},\mathcal{P},\mathcal{R},\mathcal{A})
SímboloSignificadoEjemplo
C\mathcal{C}Clases del dominio.Cliente, Factura, Servicio.
P\mathcal{P}Propiedades o relaciones.perteneceA, dependeDe, autoriza.
R\mathcal{R}Restricciones.“Una factura tiene un cliente responsable”.
A\mathcal{A}Axiomas.Subclases, equivalencias, incompatibilidades.

Y la base de conocimiento queda como:

KB=OI\mathcal{KB}=\mathcal{O}\cup \mathcal{I}
PiezaQué esEjemplo
O\mathcal{O}Ontología: el modelo del dominio.Qué es una factura y cómo se relaciona con clientes.
I\mathcal{I}Instancias: datos concretos.factura:f9, cliente:c42, servicio:api.
KB\mathcal{KB}Base de conocimiento.Modelo + datos + inferencias posibles.

La distinción importa porque una ontología sin instancias es un mapa vacío, y muchas instancias sin ontología son una habitación llena de etiquetas sueltas.

No confundirQué haceQué le falta
GlosarioDefine términos.Relaciones formales e inferencia.
TaxonomíaOrdena categorías.Propiedades, restricciones y reglas.
Esquema de base de datosDefine tablas y columnas.Semántica compartida entre sistemas.
JSON SchemaValida forma de datos.Significado del dominio y herencia.
OntologíaModela conceptos, relaciones y restricciones.Datos concretos si no se instancia.

Una ontología nace bien cuando empieza por preguntas de competencia: preguntas concretas que el sistema debería poder responder. No son preguntas decorativas; son el test de alcance.

Pregunta de competenciaQué obliga a modelar
¿Quién puede aprobar esta factura y por qué?Persona, rol, factura, importe, política, autorización.
¿Qué servicios se ven afectados si cae esta base de datos?Servicio, dependencia, equipo responsable, criticidad.
¿Qué documentos fiscales tiene este cliente?Cliente, documento fiscal, relación de pertenencia.
¿Qué funciones incluye este plan de producto?Plan, función, contrato, disponibilidad.
¿Qué regla explica que esta acción se escale a una persona?Umbral, riesgo, aprobación, traza.

Si no puedes escribir cinco preguntas así, todavía no necesitas una ontología completa. Necesitas entender mejor el dominio.

El proceso práctico suele parecerse a esto:

  1. Fijar alcance: qué preguntas debe responder y cuáles no.
  2. Reutilizar vocabularios existentes cuando encajen.
  3. Nombrar clases: cosas del dominio, no pantallas ni tablas.
  4. Nombrar propiedades: verbos o relaciones estables.
  5. Añadir restricciones: lo mínimo que evita ambigüedad peligrosa.
  6. Crear instancias de ejemplo: casos reales, no juguetes perfectos.
  7. Probar consultas: SPARQL, reglas o validadores.
  8. Revisar con personas del dominio: contabilidad, legal, soporte, producto, operaciones.
  9. Versionar cambios: una ontología viva necesita dueño y criterio de evolución.
DominioEntidadesRelacionesRegla útil
UniversidadAlumno, asignatura, matrícula.cursa, aprueba, requiere.No matricular si falta prerrequisito.
FinanzasFactura, cliente, contrato, rol.perteneceA, autoriza, superaUmbral.Escalar si importe supera límite.
ProductoPlan, función, usuario, permiso.incluye, puedeUsar, requiere.Mostrar solo funciones disponibles.
OperaciónServicio, base de datos, equipo.dependeDe, mantiene, expone.Avisar a equipos afectados.

Ejemplo: en un producto SaaS, una ontología mínima podría decir:

ClaseInstanciasPropiedades
Clientecliente:c42tieneContrato, tienePlan.
Planplan:empresaincluyeFuncion.
Funcionfuncion:exportarDatosrequierePermiso.
Usuariousuario:u17perteneceACliente, tieneRol.
Permisopermiso:exportarautorizaFuncion.

Con eso puedes contestar algo muy concreto: “¿puede este usuario exportar datos?”. El LLM puede explicar la respuesta en lenguaje humano, pero la decisión debería apoyarse en relaciones verificables:

puedeUsar(u,f)perteneceACliente(u,c)tienePlan(c,p)incluyeFuncion(p,f)tienePermiso(u,π)autorizaFuncion(π,f)\operatorname{puedeUsar}(u,f)\Leftarrow \operatorname{perteneceACliente}(u,c)\land \operatorname{tienePlan}(c,p)\land \operatorname{incluyeFuncion}(p,f)\land \operatorname{tienePermiso}(u,\pi)\land \operatorname{autorizaFuncion}(\pi,f)
Parte de la reglaLectura humana
perteneceAClienteEl usuario pertenece a ese cliente.
tienePlanEl cliente tiene un plan contratado.
incluyeFuncionEl plan incluye la función pedida.
tienePermisoEl usuario tiene un permiso concreto.
autorizaFuncionEse permiso autoriza esa función.
Cómo nace una ontología útil No empieza por dibujar cajas: empieza por preguntas que el sistema debe poder contestar. 1 · Preguntas de competencia ¿quién puede aprobar? ¿qué depende de qué? ¿por qué se escala? 2 · Modelo semántico Clases Cliente, Factura Propiedades perteneceA Restricciones un cliente responsable Axiomas subclases, inversas La ontología define el idioma compartido antes de llenar el grafo de datos. 3 · Prueba de realidad SPARQL Reglas Validación humana Si no responde preguntas reales, no es ontología: es decoración técnica. IA para gente curiosa / Facsímil 02 / Capítulo 12 / 686f6c61

La ontología también necesita gobierno. Alguien debe poder responder: quién puede añadir una clase, cuándo una relación queda obsoleta, cómo se migran instancias, qué cambios rompen consultas y cómo se documenta una decisión de modelado. Sin eso, el grafo envejece rápido.

Decisión de gobiernoPregunta práctica
Dueño del vocabulario¿Quién aprueba cambios de clases y propiedades?
Versionado¿Qué consultas o agentes dependen de esta versión?
Calidad de datos¿Qué instancias están incompletas o duplicadas?
Deprecación¿Qué relación antigua sigue existiendo solo por compatibilidad?
Trazabilidad¿Qué fuente justifica este hecho o regla?

Un sistema experto combina cinco piezas:

PiezaQué contienePregunta que responde
Base de conocimientoHechos del dominio.¿Qué sabemos?
OntologíaVocabulario y estructura.¿Qué significa lo que sabemos?
ReglasCondiciones explícitas.¿Qué se deriva?
Motor de inferenciaMecanismo que aplica reglas.¿Qué conclusiones siguen?
ExplicaciónTrazas de hechos y reglas.¿Por qué?

Esto suena antiguo hasta que lo conectas con agentes modernos. Un LLM puede interpretar una solicitud. Un RAG puede traer contexto. Pero una ontología y una regla simbólica pueden decidir si una tool está permitida, si falta una aprobación o si una respuesta debe incluir una fuente.

No es nostalgia. Es ingeniería.

Grafo de conocimiento, vector store y GraphRAG

Un vector store recupera por parecido. Un grafo de conocimiento consulta por relación. GraphRAG intenta usar estructura de grafo para mejorar recuperación, agregación y explicación en sistemas RAG.7 La idea es atractiva, pero conviene no confundir extracción automática con conocimiento fiable.

NecesidadVector storeGrafo de conocimientoHíbrido
Encontrar texto relevante.Muy fuerte.Menos directo.Recupera documentos y entidades.
Responder “quién depende de quién”.Débil si no hay frases explícitas.Muy fuerte.Consulta grafo y cita documentos.
Explicar una decisión.Muestra fragmentos.Muestra hechos y reglas.Une evidencia textual y trazabilidad.
Actualizar permisos.Reindexar texto no basta.Cambiar regla o relación.Validar acciones con reglas.

La combinación madura suele verse así:

  1. El LLM entiende la pregunta y propone una intención.
  2. El vector store recupera fragmentos útiles.
  3. El grafo resuelve entidades y relaciones.
  4. Las reglas validan permisos, límites y coherencia.
  5. La respuesta cita evidencia y explica el camino.

Cuando alguien dice “hagamos GraphRAG”, la pregunta buena es: ¿qué relaciones sabemos de verdad, quién las mantiene y cómo sabremos que siguen siendo correctas?

Del texto parecido al conocimiento trazable El cierre del facsímil: buscar, restringir, planificar, decidir con otros actores y explicar con símbolos. Recuperar por parecido Pregunta q Documento d cos(q,d)= q·d / ||q|| ||d|| Ideal para explorar contexto; insuficiente para probar una relación. Consultar por relación factura f9 cliente c42 plan empresa perteneceA tienePlan hechos + reglas = explicación Recapitulación del facsímil 02 Búsqueda espacios Restricciones SAT y CSP Guardrails reglas duras Planes acciones Juegos respuestas Agentes modernos fiables LLM para lenguaje, retrieval para contexto, símbolos para reglas y trazabilidad. La IA clásica no desaparece: se convierte en el esqueleto del sistema. IA para gente curiosa / Facsímil 02 / Capítulo 12 / 686f6c61

En el día a día

El conocimiento simbólico aparece cuando necesitas que el sistema recuerde hechos con nombre propio.

SituaciónSin símbolosCon símbolos
Soporte internoBuscar tickets parecidos.Saber qué cliente, contrato y SLA aplican.
Agente con toolsEl modelo decide desde texto.Las tools consultan permisos y estado.
ComplianceResumen libre de políticas.Reglas ejecutables y trazas revisables.
OperacionesDocumentos de arquitectura.Grafo de dependencias vivo.
ProductoPreguntas frecuentes.Planes, funciones y permisos consultables.

La señal práctica es sencilla: si la frase contiene “siempre”, “solo si”, “depende de”, “pertenece a”, “autoriza”, “requiere” o “explica por qué”, probablemente hay conocimiento simbólico esperando salir.

Por qué debería importarte

Porque muchos sistemas de IA fallan no por falta de modelo, sino por falta de estructura alrededor del modelo.

Si todo vive como texto, cada decisión vuelve a interpretarse desde cero. Si una regla está en un prompt, no es una regla operativa. Si una entidad no tiene identidad estable, dos sistemas pueden hablar de lo mismo sin saberlo. Si una relación no está modelada, el sistema solo podrá adivinarla por parecido.

El conocimiento simbólico no hace que un sistema sea perfecto. Hace algo igual de importante: permite preguntar, validar y explicar.

Recapitulación activa del facsímil

Este cierre funciona como el capítulo 12 del facsímil 1: no es un resumen para leer rápido, sino una revisión activa. Cada sección recupera un concepto nuclear, lo reformula desde otro ángulo, lo conecta con el resto y te confronta con una pregunta. Si algo no te sale, el número de capítulo te dice exactamente dónde volver.

No es un examen. Es un espejo. Si te reconoces en estas páginas, tienes el vocabulario clásico que permite mirar los agentes modernos como sistemas de decisión, no como cajas negras.


1. Búsqueda: resolver problemas como espacio de estados

El concepto. Un problema de búsqueda se define por estado inicial, acciones, transición, objetivo y coste. Resolverlo es recorrer un espacio hasta encontrar una ruta aceptable.

Para recordar. Si no sabes nombrar estados y acciones, todavía no tienes un problema de IA: tienes una idea sin contrato operativo.

Ejemplo fresco. Un agente que reserva una cita médica tiene estados: especialidad elegida, fecha filtrada, seguro validado, cita confirmada. Cada click cambia el estado.

Vuelve al capítulo 1 si: no puedes escribir P=(S,A,T,s0,G,c)P=(S,A,T,s_0,G,c) y explicar cada pieza.


2. BFS, DFS y coste uniforme

El concepto. Los algoritmos ciegos comparten el mismo bucle: extraer de una frontera, expandir vecinos y decidir qué entra después. Cambia la estructura de la frontera.

Para recordar. BFS prioriza poca profundidad, DFS poca memoria, UCS menor coste acumulado.

Ejemplo fresco. Si todas las acciones cuestan igual, BFS puede encontrar la solución más corta. Si llamar a una API cuesta más que leer caché, necesitas coste uniforme.

Vuelve al capítulo 2 si: confundes profundidad, anchura y coste acumulado.


3. Greedy, A* y heurísticas

El concepto. Una heurística estima cuánto falta. Greedy mira solo h(n)h(n). A* combina lo recorrido y lo estimado:

f(n)=g(n)+h(n)f(n)=g(n)+h(n)

Para recordar. Una buena estimación no reemplaza el coste real. A* funciona tan bien porque equilibra ambos.

Ejemplo fresco. En un asistente que depura código, g(n)g(n) puede ser coste ya gastado y h(n)h(n) la cercanía estimada al fallo. Si solo sigues la pista más prometedora, puedes ignorar una solución barata.

Vuelve al capítulo 3 si: no puedes explicar por qué Greedy puede ser rápido y equivocarse.


4. Búsqueda en agentes modernos

El concepto. Un agente moderno también busca: propone pasos, ejecuta tools, observa resultados y replanifica.

Para recordar. El LLM no es todo el sistema. Es una pieza dentro de un bucle con estado, herramientas, validaciones y memoria.

Ejemplo fresco. Un agente de datos prueba una consulta SQL, recibe error de columna inexistente, revisa el esquema y genera otra consulta. Eso es búsqueda con observación.

Vuelve al capítulo 4 si: ves un agente como una respuesta larga en vez de como un proceso iterativo.


5. SAT y CSP

El concepto. SAT pregunta si existe una asignación booleana que hace verdadera una fórmula. CSP generaliza a variables, dominios y restricciones.

Para recordar. A veces la IA no “predice”: satisface condiciones.

Ejemplo fresco. Crear horarios de un curso no es escribir texto bonito. Es asignar aulas, docentes y franjas sin romper restricciones.

Vuelve al capítulo 5 si: no puedes distinguir validez, satisfacibilidad y optimización.


6. Variables, dominios y restricciones

El concepto. Un CSP se modela como:

P=(X,D,C)\mathcal{P}=(X,D,C)

Para recordar. Modelar bien decide más que elegir solver. Variables malas producen problemas raros.

Ejemplo fresco. Si una variable representa “turno completo” quizá el dominio explota. Si separas día, hora y persona, aparecen restricciones más claras.

Vuelve al capítulo 6 si: te cuesta convertir un problema cotidiano en variables, dominios y restricciones.


7. Propagación, backtracking y heurísticas en CSP

El concepto. Propagar reduce dominios antes de buscar. Backtracking prueba asignaciones parciales y vuelve atrás cuando una restricción falla. Heurísticas como MRV eligen primero lo más limitado.

Para recordar. El gran ahorro no está en probar más rápido, sino en probar menos.

Ejemplo fresco. Si Ana solo puede lunes o martes, decidir su turno antes puede revelar pronto si el horario es viable.

Vuelve al capítulo 7 si: no puedes explicar por qué “fallar pronto” es una virtud.


8. Restricciones como guardrails

El concepto. Un guardrail convierte una regla de negocio o seguridad en validación ejecutable.

Para recordar. Un prompt orienta. Un control decide.

Ejemplo fresco. “No borres datos sin aprobación” no debería vivir solo como frase. Debe ser permiso, schema, umbral y traza.

Vuelve al capítulo 8 si: todavía pones reglas duras únicamente en texto libre.


9. Planificación automática

El concepto. Planificar es encontrar una secuencia de acciones que transforma un estado inicial en un estado objetivo respetando precondiciones y efectos.

Para recordar. Una lista de tareas no es un plan si no dice qué debe ser cierto antes y después de cada acción.

Ejemplo fresco. Para enviar una factura: validar cliente, calcular importe, generar PDF, aprobar, enviar y registrar. Si falta aprobación, el plan no es ejecutable.

Vuelve al capítulo 9 si: no puedes distinguir acción, precondición, efecto y objetivo.


10. Planificación heurística, SAT y agentes LLM

El concepto. La planificación avanzada usa heurísticas para ordenar búsqueda, codificación SAT para probar horizontes y bucles agente para observar y replanificar.

Para recordar. Proponer una acción no equivale a tener permiso para ejecutarla.

Ejemplo fresco. Un agente puede proponer actualizar una base de datos. El sistema debe comprobar estado, permisos, coste, reversibilidad y trazas antes de actuar.

Vuelve al capítulo 10 si: no puedes explicar qué significa horizonte kk en planificación con SAT.


11. Juegos: decidir con otros actores

El concepto. Los juegos añaden interdependencia: otras personas, sistemas, reglas o instrucciones también pueden elegir.

Para recordar. La calidad de una acción depende de las respuestas que habilita.

Ejemplo fresco. Si un documento recuperado contiene otra orden, tu agente debe distinguir datos de instrucciones antes de llamar una tool.

Vuelve al capítulo 11 si: evalúas decisiones solo por el primer movimiento.


12. Conocimiento simbólico

El concepto. Entidades, relaciones, reglas y consultas explícitas permiten representar conocimiento trazable.

Para recordar. Los embeddings recuperan parecido. Los símbolos expresan relación.

Ejemplo fresco. “Cliente C42 puede usar la función X porque su plan la incluye y su contrato está activo” es una explicación simbólica.

Vuelve a este capítulo si: no puedes distinguir un vector store de un grafo de conocimiento.


Dónde solía tropezar yo

ErrorPor qué es un errorAntídoto
Pensar que simbólico significa viejoMuchas arquitecturas modernas necesitan reglas, permisos, grafos y consultas.Preguntar qué parte del sistema debe ser trazable.
Confundir similitud con verdadUn texto cercano puede no probar una relación.Separar recuperación, verificación e inferencia.
Sobremodelar una ontologíaUna ontología enorme se vuelve inmantenible.Empezar con pocas clases y relaciones críticas.
Creer que GraphRAG aparece soloExtraer entidades no garantiza conocimiento correcto.Definir dueños, validación y actualización del grafo.
Meter reglas duras en promptsEl prompt no es una base de conocimiento ejecutable.Convertir reglas en políticas, schemas o consultas.
Recapitular como quien pasa listaRecordar nombres no asegura comprensión.Volver a explicar cada pieza con un ejemplo nuevo.

Manos a la obra

La práctica breve está en kit descargable. Construye un micrografo con tripletas, ejecuta consultas sencillas e infiere tipos por subclases. No es una implementación completa de RDF, RDFS, OWL ni SPARQL; es una maqueta para ver el mecanismo funcionando sin esconderlo detrás de una base de datos.

La diferencia importante es esta: un vector store puede recuperar texto parecido; un grafo puede decir qué relación sostiene una decisión. Si el sistema necesita explicar por qué una factura pertenece a un cliente o por qué una entidad hereda una clase, los hechos explícitos importan.

ArchivoQué contiene
data/triples.jsonTripletas base de factura, cliente, plan y servicios.
contracts/graph_policy.jsonConsultas esperadas e inferencias obligatorias.
ops/query_symbolic_graph.pyMotor mínimo de consulta e inferencia por subclase.
output/symbolic_graph_report.jsonTripletas base, inferidas y respuestas.
output/symbolic_graph_decision.mdLectura técnica del micrografo.

Ejecuta:

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/query_symbolic_graph.py --write
cat output/symbolic_graph_decision.md

Como gate:

python3 ops/query_symbolic_graph.py --write --fail-on-invalid

Qué entregaría un alumno. El Markdown generado, tres tripletas nuevas, una consulta nueva con su respuesta y una explicación de cuándo usaría grafo, vector store o ambos.

Cómo encaja todo

Este mapa es el cierre del facsímil. La búsqueda, las restricciones, la planificación y los juegos nos han dado mecanismos para decidir. El conocimiento simbólico añade identidad, relaciones y explicación: qué entidad es cuál, qué regla aplica y qué consulta demuestra una decisión.

La decisión aprendida es cuándo no basta con parecido semántico. Si necesitas trazabilidad, permisos, dependencias o una explicación reproducible, los hechos y relaciones explícitas se vuelven parte de la arquitectura.

graph TD
    subgraph "Este capítulo"
        RDF["RDF<br/>tripletas"]
        OWL["RDFS y OWL<br/>significado"]
        SPARQL["SPARQL<br/>consultas"]
        ONTO["Ontología<br/>acuerdo común"]
        KG["Grafo<br/>relaciones"]
        EXPERT["Sistema experto<br/>reglas"]
        RECAP["Recapitulación<br/>facsímil 02"]
    end
    subgraph "Mismo facsímil"
        SEARCH["Búsqueda<br/>caps. 1-4"]
        CSP["SAT y CSP<br/>caps. 5-7"]
        GUARD["Guardrails<br/>cap. 8"]
        PLAN["Planificación<br/>caps. 9-10"]
        GAME["Juegos<br/>cap. 11"]
    end
    subgraph "Otros facsímiles"
        EMB["Embeddings<br/>fasc. 1"]
        RAG["RAG<br/>fasc. 4"]
        AGENTS["Agentes<br/>fasc. 5"]
        EVALS["Evals<br/>fasc. 4"]
        OPS["Operación<br/>fasc. 6"]
    end

    RDF -->|"hechos"| KG
    OWL -->|"clases y axiomas"| KG
    ONTO -->|"vocabulario"| OWL
    SPARQL -->|"pregunta"| KG
    KG -->|"hechos trazables"| EXPERT
    EXPERT -->|"reglas"| GUARD
    RECAP --> SEARCH
    RECAP --> CSP
    RECAP --> PLAN
    RECAP --> GAME
    SEARCH -->|"espacios"| PLAN
    CSP -->|"restricciones"| GUARD
    PLAN -->|"acciones"| AGENTS
    GAME -->|"respuestas"| EVALS
    EMB -->|"parecido"| RAG
    RAG -->|"contexto"| KG
    KG -->|"trazas"| OPS
    AGENTS -->|"tools"| GUARD

    style RDF fill:#F5F5F5,stroke:#000000,stroke-width:2
    style OWL fill:#F5F5F5,stroke:#000000,stroke-width:2
    style SPARQL fill:#F5F5F5,stroke:#000000,stroke-width:2
    style ONTO fill:#F5F5F5,stroke:#000000,stroke-width:2
    style KG fill:#F5F5F5,stroke:#000000,stroke-width:2
    style EXPERT fill:#F5F5F5,stroke:#000000,stroke-width:2
    style RECAP fill:#F5F5F5,stroke:#000000,stroke-width:2
    style SEARCH stroke-dasharray: 5 5
    style CSP stroke-dasharray: 5 5
    style GUARD stroke-dasharray: 5 5
    style PLAN stroke-dasharray: 5 5
    style GAME stroke-dasharray: 5 5
    style EMB stroke-dasharray: 5 5
    style RAG stroke-dasharray: 5 5
    style AGENTS stroke-dasharray: 5 5
    style EVALS stroke-dasharray: 5 5
    style OPS stroke-dasharray: 5 5

Vocabulario aprendido

TérminoDefinición
EntidadObjeto identificable del dominio.
Tripleta RDFHecho con forma sujeto-predicado-objeto.
Grafo de conocimientoConjunto de entidades y relaciones explícitas.
OntologíaAcuerdo formal sobre clases, relaciones y restricciones.
ClaseCategoría de entidades dentro de una ontología.
InstanciaEntidad concreta que pertenece a una clase.
PropiedadRelación o atributo que conecta entidades o asigna valores.
Pregunta de competenciaPregunta que la ontología debería poder responder.
RDFSVocabulario para clases, subclases, dominio y rango.
OWLLenguaje de ontologías con axiomas más expresivos.
SPARQLLenguaje para consultar patrones de tripletas.
Consulta SPARQLPregunta formal que enlaza variables con hechos del grafo.
FILTERCondición que restringe las soluciones de una consulta.
OPTIONALBloque que añade datos si existen sin eliminar la solución principal.
Camino de propiedadExpresión para recorrer relaciones encadenadas.
Linked DataDatos publicados con identificadores estables y enlaces.
Sistema expertoOntología, hechos, reglas, inferencia y explicación.
Vector storeAlmacén de embeddings para recuperar por similitud.

Antes de pasar página

  • ¿Puedo explicar la diferencia entre parecido semántico y relación explícita?
  • ¿Sé leer una tripleta RDF como sujeto, predicado y objeto?
  • ¿Entiendo qué añade una ontología frente a una lista de hechos?
  • ¿Puedo distinguir clase, instancia, propiedad, restricción y axioma?
  • ¿Sé escribir preguntas de competencia para acotar una ontología?
  • ¿Puedo explicar para qué sirve SPARQL?
  • ¿Sé leer SELECT, WHERE, FILTER, OPTIONAL, ASK y CONSTRUCT?
  • ¿Entiendo por qué :dependeDe+ encuentra dependencias encadenadas?
  • ¿Sé cuándo usar vector store, grafo o una combinación?
  • ¿Puedo resumir los doce capítulos del facsímil con un ejemplo de cada uno?
  • ¿Tengo claro qué aporta la IA clásica a los agentes modernos?

En resumen

Idea fuerzaDetalle
Los vectores recuperan parecido.Muy útiles para contexto, menos para probar relaciones.
Los símbolos dan identidad.Entidades y relaciones permiten consultar y explicar.
RDF modela hechos mínimos.Una tripleta basta para declarar una relación.
Una ontología es contrato semántico.Define clases, propiedades, restricciones, axiomas y alcance.
RDFS y OWL añaden significado.Clases, subclases, dominio, rango y axiomas.
SPARQL pregunta al grafo.Enlaza variables con patrones exactos, filtros, opcionales y caminos de propiedad.
GraphRAG necesita cuidado.Un grafo útil requiere validación, mantenimiento y dueños.
La IA clásica sigue viva.Búsqueda, restricciones, planificación, juegos y símbolos son infraestructura para sistemas modernos.

Para saber más

Berners-Lee, T. (2006). Linked Data. https://www.w3.org/DesignIssues/LinkedData.html

Gruber, T. R. (1993). A translation approach to portable ontology specifications. Knowledge Acquisition, 5(2), 199-220. https://doi.org/10.1006/knac.1993.1008

Microsoft. (2024). GraphRAG. https://microsoft.github.io/graphrag/

Noy, N. F. y McGuinness, D. L. (2001). Ontology Development 101: A Guide to Creating Your First Ontology. Stanford Knowledge Systems Laboratory Technical Report KSL-01-05. https://protege.stanford.edu/publications/ontology_development/ontology101.pdf

Russell, S. y Norvig, P. (2021). Artificial Intelligence: A Modern Approach (4.ª ed.). Pearson.

W3C. (2014). RDF 1.1 Concepts and Abstract Syntax. https://www.w3.org/TR/rdf11-concepts/

W3C. (2014). RDF Schema 1.1. https://www.w3.org/TR/rdf-schema/

W3C. (2012). OWL 2 Web Ontology Language Document Overview. https://www.w3.org/TR/owl2-overview/

W3C. (2013). SPARQL 1.1 Query Language. https://www.w3.org/TR/sparql11-query/

Laboratorio

Este laboratorio sirve para convertir el facsímil 2 en práctica. Hemos hablado de búsqueda, fronteras, heurísticas, restricciones, planificación, juegos con otros actores y conocimiento simbólico. Ahora vamos a usarlos como se usan de verdad: para ordenar un problema, reducir posibilidades, validar una decisión y dejar una explicación que otra persona pueda revisar.

En este laboratorio vas a trabajar cuatro gestos importantes:

  • Del capítulo 1 al 4: modelar una situación como estados, acciones, costes y prioridades.
  • Del capítulo 5 al 8: convertir reglas del mundo en restricciones verificables.
  • Del capítulo 9 al 11: pensar en planes y decisiones donde no todo depende de una sola elección.
  • Del capítulo 12: usar hechos explícitos para justificar una acción y no depender solo de texto parecido.

La intención no es que memorices nombres de algoritmos. La intención es que puedas mirar un problema cotidiano y preguntarte: ¿qué estoy buscando?, ¿qué está prohibido?, ¿qué coste tiene cada paso?, ¿qué puedo comprobar antes de actuar?, ¿cómo explico la decisión?

El kit real está en:

kit/

Ejecuta:

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/solve_csp_schedule.py --write
python3 ops/evaluate_symbolic_plan.py --write
python3 ops/check_student_submission.py --submission-dir solutions/reference --write --fail-on-missing

Qué produce:

ArchivoQué demuestra
output/csp_solution.jsonAsignación válida y eventos de búsqueda.
output/csp_decision.mdPor qué la agenda cumple restricciones.
output/csp_trace.jsonlVariable elegida, valor probado y poda.
output/symbolic_plan_report.jsonChecks, acción y plan final sobre el grafo.
output/symbolic_plan_decision.mdDecisión explicada con precondiciones.
output/symbolic_plan_trace.jsonlEntidades, consulta de grafo, validación y registro.

La práctica completa no consiste en “encontrar una solución”, sino en poder explicar qué restricciones se respetaron y qué hechos sostienen la acción final.

Reto 1: organizar un pequeño taller sin romper restricciones

Contexto

Imagina que tienes que organizar tres sesiones de apoyo para un grupo de estudiantes: una sesión de repaso, una práctica con ordenador y una tutoría de proyectos. Parece una agenda sencilla, pero enseguida aparecen reglas: la práctica necesita laboratorio, la tutoría solo puede ser el martes y no puedes poner dos sesiones a la misma hora porque el docente es la misma persona.

Esto es un CSP pequeño. No estamos pidiendo a un modelo que "proponga un horario bonito". Estamos definiendo variables, dominios y restricciones para saber qué horarios son válidos.

Objetivo

Construir un solucionador mínimo de horarios con backtracking y una heurística sencilla de elección de variable. Debe devolver una asignación válida y permitir explicar por qué cumple las reglas.

Esto sale del capítulo 6, cuando modelamos un CSP como variables, dominios y restricciones, y del capítulo 7, cuando vimos que resolver un CSP consiste en podar antes de probarlo todo.

Material base

Tenemos tres sesiones:

VariableSignificado
repasoSesión inicial de repaso de búsqueda y heurísticas.
practicaSesión con ordenador para trabajar CSP.
tutoriaTutoría de proyectos.

Cada sesión debe recibir un valor de la forma (hora, sala).

Hora disponibleSalas
lun_09Aula, Lab
lun_11Aula, Lab
mar_09Aula, Lab
mar_11Aula, Lab

Restricciones:

  1. No puede haber dos sesiones en la misma hora.
  2. practica debe hacerse en Lab.
  3. repaso debe ocurrir antes que practica.
  4. tutoria solo puede ocurrir el martes.

Formalmente:

P=(X,D,C)\mathcal{P}=(X,D,C)
SímboloSignificadoEn este reto
XXVariables del problema.repaso, practica, tutoria.
DDDominios de valores posibles.Pares (hora, sala).
CCRestricciones que debe cumplir la asignación.No solapar, usar laboratorio, respetar orden y disponibilidad.

Una asignación completa AA es válida si satisface todas las restricciones:

ciC,ci(A)=verdadero\forall c_i \in C,\quad c_i(A)=\text{verdadero}

Enunciado

  1. Escribe los dominios de cada variable.
  2. Implementa una función is_consistent que rechace asignaciones parciales inválidas.
  3. Usa backtracking para buscar una solución.
  4. Elige primero la variable con menos valores disponibles.
  5. Explica por qué la solución encontrada cumple todas las reglas.

Resolución paso a paso

Primero reducimos dominios antes de buscar:

  • practica solo puede usar Lab.
  • tutoria solo puede usar horarios del martes.
  • repaso puede usar cualquier hueco.

Después buscamos por asignaciones parciales. Si una asignación ya incumple una regla, no seguimos por esa rama. Esto conecta directamente con el capítulo 7: no buscamos por fuerza bruta; podamos.

sessions = ["repaso", "practica", "tutoria"]
slots = ["lun_09", "lun_11", "mar_09", "mar_11"]
rooms = ["Aula", "Lab"]
slot_order = {slot: i for i, slot in enumerate(slots)}

base_domain = [(slot, room) for slot in slots for room in rooms]
domains = {
    "repaso": base_domain,
    "practica": [(slot, "Lab") for slot in slots],
    "tutoria": [(slot, room) for slot in ["mar_09", "mar_11"] for room in rooms],
}


def is_consistent(assignment):
    used_slots = [value[0] for value in assignment.values()]
    if len(used_slots) != len(set(used_slots)):
        return False

    if assignment.get("practica", (None, None))[1] not in (None, "Lab"):
        return False

    if "repaso" in assignment and "practica" in assignment:
        if slot_order[assignment["repaso"][0]] >= slot_order[assignment["practica"][0]]:
            return False

    if "tutoria" in assignment and not assignment["tutoria"][0].startswith("mar"):
        return False

    return True


def select_unassigned(assignment):
    candidates = [session for session in sessions if session not in assignment]
    return min(candidates, key=lambda session: len(domains[session]))


def backtrack(assignment):
    if len(assignment) == len(sessions):
        return assignment

    session = select_unassigned(assignment)
    for value in domains[session]:
        candidate = {**assignment, session: value}
        if is_consistent(candidate):
            result = backtrack(candidate)
            if result:
                return result
    return None


solution = backtrack({})

for session in sessions:
    slot, room = solution[session]
    print(f"{session}: {slot} en {room}")

Salida esperada

repaso: lun_09 en Aula
practica: lun_11 en Lab
tutoria: mar_09 en Aula

Solución

La solución cumple las cuatro restricciones:

RestricciónComprobación
No coinciden horaslun_09, lun_11 y mar_09 son distintas.
La práctica usa laboratoriopractica queda en Lab.
El repaso ocurre antes de la prácticalun_09 va antes que lun_11.
La tutoría ocurre el martestutoria queda en mar_09.

La heurística de elegir primero la variable con menos valores disponibles ayuda porque tutoria y practica están más restringidas que repaso. Si las colocamos pronto, detectamos contradicciones antes.

Por qué funciona

Este reto junta varias piezas del facsímil:

  • Capítulo 1: una agenda se convierte en espacio de estados si cada asignación parcial es un estado.
  • Capítulo 2: el backtracking se parece a DFS, pero con poda.
  • Capítulo 6: variables, dominios y restricciones definen el problema.
  • Capítulo 7: elegir primero lo más restringido reduce ramas inútiles.
  • Capítulo 8: una restricción funciona como guardrail porque bloquea salidas inválidas.

Lo importante es la disciplina: antes de pedir una solución, escribimos qué significa que una solución sea válida.

Cómo explicarlo a otra persona

"No hemos pedido al sistema que invente un horario. Le hemos dado huecos posibles y reglas. El programa prueba opciones, pero en cuanto una opción incumple una regla, deja de seguir por ahí. Por eso encuentra un horario válido sin revisar combinaciones que ya sabemos que no pueden funcionar."

Variaciones para seguir practicando

  • Añade una cuarta sesión llamada demo_final que debe ocurrir después de tutoria.
  • Añade una sala nueva Seminario y prohíbe usarla para practica.
  • Cambia la regla para que repaso y practica no puedan estar el mismo día. ¿Sigue habiendo solución?

Reto 2: decidir una acción de soporte con plan, reglas y grafo

Contexto

Ahora imagina un asistente interno de soporte. Llega un ticket: una persona necesita acceso temporal a un panel de facturas. Un LLM podría redactar una respuesta muy convincente, pero el sistema no debería conceder nada solo porque el texto suena razonable.

Queremos una arquitectura mínima con tres capas:

  1. Un plan de pasos.
  2. Guardrails que validan si la acción se puede ejecutar.
  3. Un grafo de conocimiento que contiene hechos consultables sobre personas, roles, recursos y aprobaciones.

Este reto conecta planificación, restricciones y conocimiento simbólico. Es exactamente el tipo de mezcla que aparece en sistemas de IA modernos: el modelo puede ayudar a interpretar el ticket, pero la decisión debe apoyarse en reglas verificables.

Objetivo

Construir una maqueta que reciba un ticket, consulte hechos del grafo, valide restricciones y devuelva un plan trazable. No buscamos un agente completo. Buscamos la columna vertebral: qué se puede comprobar antes de actuar.

Esto sale del capítulo 9, cuando hablamos de planificación como secuencia de acciones con precondiciones y efectos; del capítulo 8, cuando vimos restricciones como guardrails; y del capítulo 12, cuando usamos tripletas y consultas para justificar decisiones.

Material base

Hechos del dominio:

SujetoPredicadoObjeto
ticket:t1paraPersonapersona:ana
ticket:t1solicitaAccesoArecurso:facturas
ticket:t1tieneAprobacionpersona:luis
persona:anaperteneceAequipo:finanzas
persona:anatieneRolrol:finanzas
persona:luisresponsableDeequipo:finanzas
recurso:facturasrequiereRolrol:finanzas
recurso:facturaspermiteAccesotemporal

La acción final conceder_acceso_temporal(persona, recurso) solo puede ejecutarse si:

  1. La persona tiene el rol requerido por el recurso.
  2. La aprobación viene de alguien responsable del equipo de la persona.
  3. El recurso permite acceso temporal.

Podemos verlo como una precondición:

pre(a)=rolOK(u,r)aprobacionOK(t,u)modoOK(r)\operatorname{pre}(a)= \operatorname{rolOK}(u,r)\land \operatorname{aprobacionOK}(t,u)\land \operatorname{modoOK}(r)
SímboloSignificadoEn este reto
aaAcción candidata.conceder_acceso_temporal.
uuPersona afectada.persona:ana.
rrRecurso solicitado.recurso:facturas.
ttTicket.ticket:t1.
pre(a)\operatorname{pre}(a)Condiciones que deben cumplirse antes de ejecutar.Rol, aprobación y modo temporal.

La consulta SPARQL equivalente tendría esta pinta:

SELECT ?persona ?recurso ?aprobador
WHERE {
  :ticketT1 :paraPersona ?persona ;
            :solicitaAccesoA ?recurso ;
            :tieneAprobacion ?aprobador .

  ?persona :tieneRol ?rol ;
           :perteneceA ?equipo .

  ?recurso :requiereRol ?rol ;
           :permiteAcceso "temporal" .

  ?aprobador :responsableDe ?equipo .
}

Enunciado

  1. Representa los hechos como tripletas.
  2. Escribe una función de consulta sencilla.
  3. Comprueba las tres precondiciones.
  4. Devuelve una decisión: conceder acceso temporal o pedir revisión humana.
  5. Devuelve un plan trazable con los pasos que se han seguido.

Resolución paso a paso

Primero guardamos los hechos como tripletas. Después hacemos consultas pequeñas: objetos de un sujeto y predicado, y comprobación de si una tripleta existe.

triples = {
    ("ticket:t1", "paraPersona", "persona:ana"),
    ("ticket:t1", "solicitaAccesoA", "recurso:facturas"),
    ("ticket:t1", "tieneAprobacion", "persona:luis"),
    ("persona:ana", "perteneceA", "equipo:finanzas"),
    ("persona:ana", "tieneRol", "rol:finanzas"),
    ("persona:luis", "responsableDe", "equipo:finanzas"),
    ("recurso:facturas", "requiereRol", "rol:finanzas"),
    ("recurso:facturas", "permiteAcceso", "temporal"),
}


def objects(subject, predicate):
    return sorted(o for s, p, o in triples if s == subject and p == predicate)


def has(subject, predicate, obj):
    return (subject, predicate, obj) in triples


def evaluate_ticket(ticket):
    user = objects(ticket, "paraPersona")[0]
    resource = objects(ticket, "solicitaAccesoA")[0]
    approver = objects(ticket, "tieneAprobacion")[0]
    required_role = objects(resource, "requiereRol")[0]
    user_team = objects(user, "perteneceA")[0]

    checks = {
        "rol requerido": has(user, "tieneRol", required_role),
        "aprobación del equipo": has(approver, "responsableDe", user_team),
        "acceso temporal permitido": has(resource, "permiteAcceso", "temporal"),
    }

    if all(checks.values()):
        action = "conceder_acceso_temporal"
    else:
        action = "pedir_revision_humana"

    plan = [
        f"resolver_entidades({ticket})",
        f"consultar_grafo({user}, {resource})",
        f"validar_rol({required_role})",
        f"validar_aprobacion({approver})",
        f"{action}({user}, {resource})",
        f"registrar_traza({ticket})",
    ]
    return action, checks, plan


action, checks, plan = evaluate_ticket("ticket:t1")

print("Decisión:", action)
print("Comprobaciones:")
for name, ok in checks.items():
    print(f"- {name}: {'sí' if ok else 'no'}")

print("Plan:")
for step in plan:
    print("-", step)

Salida esperada

Decisión: conceder_acceso_temporal
Comprobaciones:
- rol requerido: sí
- aprobación del equipo: sí
- acceso temporal permitido: sí
Plan:
- resolver_entidades(ticket:t1)
- consultar_grafo(persona:ana, recurso:facturas)
- validar_rol(rol:finanzas)
- validar_aprobacion(persona:luis)
- conceder_acceso_temporal(persona:ana, recurso:facturas)
- registrar_traza(ticket:t1)

Solución

La decisión es conceder_acceso_temporal porque las tres comprobaciones dan .

ComprobaciónHecho que la sostiene
Ana tiene el rol requeridopersona:ana tieneRol rol:finanzas y recurso:facturas requiereRol rol:finanzas.
La aprobación viene del equipo correctopersona:luis responsableDe equipo:finanzas y persona:ana perteneceA equipo:finanzas.
El recurso permite acceso temporalrecurso:facturas permiteAcceso temporal.

El plan resultante no es una cadena de texto decorativa. Es la traza de razonamiento operativo:

  1. Resolver entidades.
  2. Consultar grafo.
  3. Validar rol.
  4. Validar aprobación.
  5. Ejecutar o pedir revisión.
  6. Registrar lo ocurrido.

Si mañana el resultado fuera pedir_revision_humana, podríamos mirar exactamente qué comprobación falló.

Por qué funciona

Este reto junta casi todo el facsímil:

  • Capítulo 1: el problema se puede modelar como estados y acciones.
  • Capítulo 3: una heurística podría priorizar tickets urgentes, pero no debe saltarse las reglas.
  • Capítulo 8: el guardrail decide si una acción candidata es ejecutable.
  • Capítulo 9: el plan tiene pasos con precondiciones.
  • Capítulo 10: SAT o CSP podrían validar planes más grandes.
  • Capítulo 12: el grafo da hechos explícitos y trazables.

La idea potente es separar papeles. El LLM puede leer el ticket y sugerir entidades. El grafo responde relaciones. Las restricciones validan la acción. El plan deja traza. Cada pieza hace su trabajo.

Cómo explicarlo a otra persona

"Antes de dar acceso, el sistema no se fía de una frase bonita. Mira hechos: quién lo pide, a qué recurso, qué rol tiene, quién aprobó y qué permite ese recurso. Si todo encaja, ejecuta un plan corto y deja registro. Si algo no encaja, no improvisa: pide revisión."

Variaciones para seguir practicando

  • Quita la tripleta persona:ana tieneRol rol:finanzas. ¿Qué decisión devuelve ahora?
  • Cambia permiteAcceso temporal por permiteAcceso permanente. ¿Debe conceder acceso temporal?
  • Añade otro ticket para una persona de otro equipo y comprueba si la aprobación sigue siendo válida.
  • Escribe una consulta SPARQL que devuelva todos los recursos que Ana puede solicitar con acceso temporal.

Cierre del laboratorio

Si has trabajado estos dos retos, ya has usado la IA clásica como una caja de herramientas moderna. No como museo. Como ingeniería.

El primer reto te obligó a convertir una agenda en un CSP. El segundo te obligó a separar plan, reglas y hechos. Esa separación es la lección más importante del facsímil: cuando un sistema de IA va a hacer algo en el mundo, no basta con que la respuesta parezca buena. Hay que saber qué buscaba, qué restricciones respetó, qué hechos consultó y por qué eligió ese paso.

Ese criterio nos va a acompañar en los siguientes facsímiles. Cambiarán los modelos, las APIs, las arquitecturas y los agentes. La pregunta de fondo seguirá siendo la misma: ¿qué parte debe generar, qué parte debe verificar y qué parte debe explicar?

Notas

  1. W3C. (2014). RDF 1.1 Concepts and Abstract Syntax. https://www.w3.org/TR/rdf11-concepts/

  2. W3C. (2014). RDF Schema 1.1. https://www.w3.org/TR/rdf-schema/

  3. W3C. (2012). OWL 2 Web Ontology Language Document Overview. https://www.w3.org/TR/owl2-overview/

  4. W3C. (2013). SPARQL 1.1 Query Language. https://www.w3.org/TR/sparql11-query/

  5. Gruber, T. R. (1993). A translation approach to portable ontology specifications. Knowledge Acquisition, 5(2), 199-220. https://doi.org/10.1006/knac.1993.1008

  6. Noy, N. F. y McGuinness, D. L. (2001). Ontology Development 101: A Guide to Creating Your First Ontology. Stanford Knowledge Systems Laboratory Technical Report KSL-01-05. https://protege.stanford.edu/publications/ontology_development/ontology101.pdf

  7. Microsoft. (2024). GraphRAG. https://microsoft.github.io/graphrag/