manual de mi pagina
26. arbol diarbol
Manual de Usuario: Diarbol Engine
Diarbol Engine es un ecosistema de visualización y análisis de probabilidad basado en árboles semánticos. No solo dibuja diagramas, sino que permite describir eventos lógicos mediante expresiones JSON, para luego resaltar automáticamente las trayectorias que cumplen ciertas condiciones.
Índice
2. Referencia de funciones: DiarbolAuto
3. Motor de criterios (JSON DSL)
5. Recetario de expresiones frecuentes
1. Arquitectura del nodo
Para que el motor funcione correctamente, cada nodo debe contener más que una etiqueta visual. El árbol necesita metadatos semánticos para poder evaluar eventos.
{
"nodeLabel": "C",
"edgeLabel": "Cara",
"value": 1,
"tipo": "entero",
"dominio": "moneda",
"meta": {
"origen": "auto"
}
}
| Propiedad | Rol |
|---|---|
nodeLabel |
Texto que aparece dentro del nodo. |
edgeLabel |
Texto que aparece sobre la rama. |
value |
Valor semántico utilizado en comparaciones y cálculos. |
tipo |
Tipo del dato: entero, numero, racional o texto. |
dominio |
Contexto del experimento: moneda, dado, urna, ruleta, binario, etc. |
meta |
Información adicional opcional que puede viajar con la rama. |
sum, eq, gt, lt, gte o lte, cada rama debe llegar al árbol con su propiedad value correctamente definida.2. Referencia de funciones: DiarbolAuto
El módulo DiarbolAuto es la fachada principal para construir árboles de manera rápida.
| Función | Descripción |
|---|---|
| dibujarEvento(container, opts) | Renderiza un árbol a partir de una estructura root definida manualmente. |
| dibujarMoneda(container, opts) | Genera automáticamente un árbol de lanzamientos de moneda. |
| dibujarDado(container, opts) | Genera automáticamente un árbol de lanzamientos de dado. |
| dibujarRuleta(container, opts) | Genera árboles basados en sectores o resultados de una ruleta. |
| dibujarExtraccionConReposicion(...) | Modela extracciones donde cada elemento vuelve a la urna. |
| dibujarExtraccionSinReposicion(...) | Modela extracciones donde el espacio muestral cambia en cada nivel. |
| dibujarBinario(container, opts) | Genera árboles con dos ramas por nivel, típicamente éxito/fracaso, usando ramas explícitas como ramaA y ramaB. |
| dibujarExperimentoCompuesto(container, opts) | Genera árboles por etapas, cada una con sus propias ramas y probabilidades. |
| dibujarCasos(container, opts) | Dibuja trayectorias específicas definidas como una colección de casos con su camino. |
value, tipo, dominio y meta hasta el árbol final si se quiere usar DiarbolEventos encima.3. Motor de criterios: JSON DSL
Los eventos se describen mediante expresiones JSON. Estas expresiones se registran con DiarbolEventos.definirEventoDesdeExpresion.
A. Operadores de valor
{ "pos": 1 }
{ "const": 7 }
{ "sum": [ { "pos": 1 }, { "pos": 2 } ] }
B. Operadores de comparación
{ "eq": [ A, B ] }
{ "gt": [ A, B ] }
{ "lt": [ A, B ] }
{ "gte": [ A, B ] }
{ "lte": [ A, B ] }
C. Operadores lógicos
{ "and": [ {regla1}, {regla2} ] }
{ "or": [ {regla1}, {regla2} ] }
{ "not": {regla} }
mod.4. Ejemplos completos de uso
En los siguientes ejemplos se asume que ya están cargados los módulos: diarbol-core.js, diarbol-auto.js y diarbol-eventos.js.
4.1. Ejemplo base HTML
<script src="diarbol-core.js"></script> <script src="diarbol-auto.js"></script> <script src="diarbol-eventos.js"></script> <div id="arbol-ejemplo"></div>
4.2. Tres monedas: “al menos 2 caras”
Supuesto semántico: Cara = 1 y Sello = 0.
const inst = DiarbolAuto.dibujarMoneda('#arbol-ejemplo', {
lanzamientos: 3
});
DiarbolEventos.definirEventoDesdeExpresion(inst, 'alMenos2Caras', {
"gte": [
{
"sum": [
{ "pos": 1 },
{ "pos": 2 },
{ "pos": 3 }
]
},
{ "const": 2 }
]
});
DiarbolEventos.resaltarEvento(inst, 'alMenos2Caras', {
color: '#27ae60'
});
4.3. Dos dados: “la suma es mayor o igual que 8”
const inst = DiarbolAuto.dibujarDado('#arbol-dados', {
lanzamientos: 2
});
DiarbolEventos.definirEventoDesdeExpresion(inst, 'sumaMayorIgual8', {
"gte": [
{
"sum": [
{ "pos": 1 },
{ "pos": 2 }
]
},
{ "const": 8 }
]
});
DiarbolEventos.resaltarEvento(inst, 'sumaMayorIgual8', {
color: '#ef6c00'
});
4.4. Tres monedas: “la primera es cara y el total de caras es 2”
const inst = DiarbolAuto.dibujarMoneda('#arbol-3monedas', {
lanzamientos: 3
});
DiarbolEventos.definirEventoDesdeExpresion(inst, 'eventoA', {
"and": [
{ "eq": [ { "pos": 1 }, { "const": 1 } ] },
{
"eq": [
{
"sum": [
{ "pos": 1 },
{ "pos": 2 },
{ "pos": 3 }
]
},
{ "const": 2 }
]
}
]
});
DiarbolEventos.resaltarEvento(inst, 'eventoA', {
color: '#1565c0'
});
4.5. Extracción con reposición: “ambas son rojas”
const inst = DiarbolAuto.dibujarExtraccionConReposicion('#urna1', {
extracciones: 2,
elementos: [
{ label: 'Roja', nodeLabel: 'R', value: 1, count: 3, tipo: 'entero', dominio: 'urna' },
{ label: 'Azul', nodeLabel: 'A', value: 0, count: 2, tipo: 'entero', dominio: 'urna' }
]
});
DiarbolEventos.definirEventoDesdeExpresion(inst, 'dosRojas', {
"and": [
{ "eq": [ { "pos": 1 }, { "const": 1 } ] },
{ "eq": [ { "pos": 2 }, { "const": 1 } ] }
]
});
DiarbolEventos.resaltarEvento(inst, 'dosRojas', {
color: '#c62828'
});
4.6. Extracción sin reposición: “al menos una roja”
const inst = DiarbolAuto.dibujarExtraccionSinReposicion('#urna2', {
extracciones: 2,
elementos: [
{ label: 'Roja', nodeLabel: 'R', value: 1, count: 2, tipo: 'entero', dominio: 'urna' },
{ label: 'Azul', nodeLabel: 'A', value: 0, count: 1, tipo: 'entero', dominio: 'urna' }
]
});
DiarbolEventos.definirEventoDesdeExpresion(inst, 'alMenosUnaRoja', {
"gte": [
{
"sum": [
{ "pos": 1 },
{ "pos": 2 }
]
},
{ "const": 1 }
]
});
DiarbolEventos.resaltarEvento(inst, 'alMenosUnaRoja', {
color: '#2e7d32'
});
4.7. Binario: “exactamente 3 éxitos en 4 ensayos”
Supuesto semántico: Éxito = 1 y Fracaso = 0.
const inst = DiarbolAuto.dibujarBinario('#binario', {
niveles: 4,
ramaA: {
label: 'Éxito',
nodeLabel: 'E',
value: 1,
tipo: 'entero',
dominio: 'binario'
},
ramaB: {
label: 'Fracaso',
nodeLabel: 'F',
value: 0,
tipo: 'entero',
dominio: 'binario'
}
});
DiarbolEventos.definirEventoDesdeExpresion(inst, 'exactamente3Exitos', {
"eq": [
{
"sum": [
{ "pos": 1 },
{ "pos": 2 },
{ "pos": 3 },
{ "pos": 4 }
]
},
{ "const": 3 }
]
});
DiarbolEventos.resaltarEvento(inst, 'exactamente3Exitos', {
color: '#6a1b9a'
});
4.8. Experimento compuesto: moneda y ruleta
const inst = DiarbolAuto.dibujarExperimentoCompuesto('#compuesto', {
title: 'Moneda + ruleta',
caption: 'Experimento compuesto con 2 etapas',
stageLabels: ['Inicio', 'Moneda', 'Ruleta', 'Resultado final'],
interaction: {
mode: 'capture'
},
mostrarConteos: false,
mostrarProbTotal: true,
crearLineasLeaf: function(path, totalProb) {
var p1 = path[0] ? String(path[0].label).toLowerCase() : '';
var p2 = path[1] ? String(path[1].label) : '';
var lineas = [];
if (p1 && p2) {
lineas.push('(' + p1 + ',' + p2 + ')');
}
if (totalProb && window.DiarbolCore) {
lineas.push('P = ' + window.DiarbolCore.formatearRacional(totalProb));
}
return lineas;
},
etapas: [
{
nombre: 'Moneda',
ramas: [
{ label: 'Cara', nodeLabel: 'C', prob: '1/2', value: 1, tipo: 'entero', dominio: 'moneda' },
{ label: 'Sello', nodeLabel: 'S', prob: '1/2', value: 0, tipo: 'entero', dominio: 'moneda' }
]
},
{
nombre: 'Ruleta',
ramas: [
{ label: '1', nodeLabel: '1', prob: '1/3', value: 1, tipo: 'entero', dominio: 'ruleta' },
{ label: '2', nodeLabel: '2', prob: '1/3', value: 2, tipo: 'entero', dominio: 'ruleta' },
{ label: '3', nodeLabel: '3', prob: '1/3', value: 3, tipo: 'entero', dominio: 'ruleta' }
]
}
]
});
DiarbolEventos.definirEventoDesdeExpresion(inst, 'caraYdos', {
"and": [
{ "eq": [ { "pos": 1 }, { "const": 1 } ] },
{ "eq": [ { "pos": 2 }, { "const": 2 } ] }
]
});
DiarbolEventos.resaltarEvento(inst, 'caraYdos', {
color: '#5e35b1'
});
4.9. Casos manuales
const inst = DiarbolAuto.dibujarCasos('#casos', {
rootLabel: 'I',
casos: [
{
lines: ['Pan A + Carne X'],
camino: [
{ label: 'Pan A', nodeLabel: 'A', value: 'A', tipo: 'texto', dominio: 'pan' },
{ label: 'Carne X', nodeLabel: 'X', value: 'X', tipo: 'texto', dominio: 'carne' }
]
},
{
lines: ['Pan A + Carne Y'],
camino: [
{ label: 'Pan A', nodeLabel: 'A', value: 'A', tipo: 'texto', dominio: 'pan' },
{ label: 'Carne Y', nodeLabel: 'Y', value: 'Y', tipo: 'texto', dominio: 'carne' }
]
},
{
lines: ['Pan B + Carne X'],
camino: [
{ label: 'Pan B', nodeLabel: 'B', value: 'B', tipo: 'texto', dominio: 'pan' },
{ label: 'Carne X', nodeLabel: 'X', value: 'X', tipo: 'texto', dominio: 'carne' }
]
}
]
});
Este caso sirve cuando el árbol no proviene de un experimento estándar, sino de una colección de trayectorias específicas.
4.10. Árbol manual mediante root
const root = {
nodeLabel: 'I',
children: [
{
nodeLabel: 'C',
edgeLabel: 'Cara',
value: 1,
tipo: 'entero',
dominio: 'moneda',
children: [
{ nodeLabel: 'C', edgeLabel: 'Cara', value: 1, tipo: 'entero', dominio: 'moneda' },
{ nodeLabel: 'S', edgeLabel: 'Sello', value: 0, tipo: 'entero', dominio: 'moneda' }
]
},
{
nodeLabel: 'S',
edgeLabel: 'Sello',
value: 0,
tipo: 'entero',
dominio: 'moneda',
children: [
{ nodeLabel: 'C', edgeLabel: 'Cara', value: 1, tipo: 'entero', dominio: 'moneda' },
{ nodeLabel: 'S', edgeLabel: 'Sello', value: 0, tipo: 'entero', dominio: 'moneda' }
]
}
]
};
const inst = DiarbolAuto.dibujarEvento('#manual', { root });
DiarbolEventos.definirEventoDesdeExpresion(inst, 'unaCaraExacta', {
"eq": [
{
"sum": [
{ "pos": 1 },
{ "pos": 2 }
]
},
{ "const": 1 }
]
});
DiarbolEventos.resaltarEvento(inst, 'unaCaraExacta', {
color: '#00897b'
});
5. Recetario de expresiones frecuentes
El evento 1 es 4
{ "eq": [ { "pos": 1 }, { "const": 4 } ] }
El evento 1 es menor que 3
{ "lt": [ { "pos": 1 }, { "const": 3 } ] }
Evento 2 + evento 3 es 7
{
"eq": [
{
"sum": [
{ "pos": 2 },
{ "pos": 3 }
]
},
{ "const": 7 }
]
}
Evento 1 y evento 2 son iguales
{
"eq": [
{ "pos": 1 },
{ "pos": 2 }
]
}
Evento 1 es menor que 3 y evento 2 + evento 3 es par
Esto requiere el operador mod. Sin él, la idea existe, pero no queda expresable de forma natural.
{
"and": [
{ "lt": [ { "pos": 1 }, { "const": 3 } ] },
{
"eq": [
{
"mod": [
{
"sum": [
{ "pos": 2 },
{ "pos": 3 }
]
},
{ "const": 2 }
]
},
{ "const": 0 }
]
}
]
}
Evento 1 y evento 2 son iguales y evento 3 es 5
{
"and": [
{
"eq": [
{ "pos": 1 },
{ "pos": 2 }
]
},
{
"eq": [
{ "pos": 3 },
{ "const": 5 }
]
}
]
}
6. Extensiones recomendadas del DSL
El DSL actual ya es útil, pero para la semántica que quieres manejar, conviene agregar algunos operadores nuevos.
6.1. Operador mod
Permite representar paridad y residuos.
{
"eq": [
{
"mod": [
{ "pos": 1 },
{ "const": 2 }
]
},
{ "const": 0 }
]
}
Interpretación: el evento 1 es par.
6.2. Operador countEq
Cuenta cuántas posiciones son iguales a un valor dado.
{
"gte": [
{
"countEq": {
"items": [
{ "pos": 1 },
{ "pos": 2 },
{ "pos": 3 }
],
"value": { "const": 1 }
}
},
{ "const": 2 }
]
}
Interpretación: al menos dos posiciones valen 1.
6.3. Operador allEq
Permite expresar que varios eventos son iguales.
{
"allEq": [
{ "pos": 1 },
{ "pos": 2 },
{ "pos": 3 }
]
}
6.4. Operador between
Permite describir intervalos.
{
"between": [
{ "pos": 1 },
{ "const": 2 },
{ "const": 5 }
]
}
6.5. Operador in
Útil para dominios de texto o pertenencia a conjuntos de valores.
{
"in": [
{ "pos": 1 },
[ { "const": 2 }, { "const": 4 }, { "const": 6 } ]
]
}
mod, countEq, allEq e in serían extensiones muy naturales.7. Buenas prácticas de diseño
Separar el dibujo de la semántica
El módulo de render debería encargarse de la visualización, mientras que el módulo de eventos debería encargarse de interpretar reglas y evaluar hojas.
Usar value de forma consistente
Si en monedas defines Cara = 1 y Sello = 0, mantén esa convención en todos los árboles equivalentes.
Distinguir dominio y tipo
El campo tipo describe la naturaleza del valor, mientras que dominio describe el contexto del experimento.
Permitir callbacks en la configuración
Si un auto acepta funciones como crearLineasLeaf, el clonado profundo y la mezcla de configuración deben preservarlas sin romperse.
Construir primero una sintaxis clara
Antes de ampliar el motor, conviene dejar estabilizada la sintaxis interna de las expresiones. Eso evita parches después.