#!/usr/bin/env node /** * Build Combinatorics discourse JSON and Mermaid. * Counting principles, permutations, combinations, binomial theorem, pigeonhole. * Based on standard discrete math texts. */ const fs = require('fs'); const path = require('path'); const NODES = [ { id: "DefFact", type: "definition", label: "Factorial: n! = n(n-1)...1, 0!=1", short: "Factorial", colorClass: "definition" }, { id: "DefSum", type: "definition", label: "Sum principle: disjoint choices add (OR)", short: "Sum principle", colorClass: "definition" }, { id: "DefProd", type: "definition", label: "Product principle: sequential choices multiply (AND)", short: "Product principle", colorClass: "definition" }, { id: "PermNoRep", type: "theorem", label: "P(n,r) = n!/(n-r)! arrangements of r from n", short: "Permutations no rep", colorClass: "theorem" }, { id: "PermRep", type: "theorem", label: "n^r arrangements of r from n with repetition", short: "Permutations with rep", colorClass: "theorem" }, { id: "CombNoRep", type: "theorem", label: "C(n,r) = n!/(r!(n-r)!) = P(n,r)/r!", short: "Combinations", colorClass: "theorem" }, { id: "CombRep", type: "theorem", label: "C(n+r-1,r) ways to choose r from n with rep", short: "Combinations with rep", colorClass: "theorem" }, { id: "BinomThm", type: "theorem", label: "(a+b)^n = sum C(n,k) a^k b^(n-k)", short: "Binomial theorem", colorClass: "theorem" }, { id: "Pascal", type: "theorem", label: "C(n,k) = C(n-1,k-1) + C(n-1,k)", short: "Pascal identity", colorClass: "theorem" }, { id: "Pigeonhole", type: "theorem", label: "n+1 objects in n boxes implies one box has 2+", short: "Pigeonhole principle", colorClass: "theorem" }, { id: "InclExcl", type: "theorem", label: "|A union B| = |A| + |B| - |A intersect B|", short: "Inclusion-exclusion", colorClass: "theorem" }, { id: "InclExcl3", type: "theorem", label: "Inclusion-exclusion for 3 sets", short: "Incl-excl 3 sets", colorClass: "theorem" }, { id: "Derange", type: "theorem", label: "D(n) = n! sum (-1)^k/k! derangements", short: "Derangements", colorClass: "theorem" }, { id: "Stirling2", type: "theorem", label: "S(n,k) = partitions of n into k nonempty sets", short: "Stirling numbers", colorClass: "theorem" } ]; const DEPS = { PermNoRep: ["DefFact", "DefProd"], PermRep: ["DefProd"], CombNoRep: ["PermNoRep", "DefFact"], CombRep: ["CombNoRep"], BinomThm: ["CombNoRep"], Pascal: ["CombNoRep"], Pigeonhole: ["DefSum"], InclExcl: ["DefSum"], InclExcl3: ["InclExcl"], Derange: ["InclExcl", "PermNoRep"], Stirling2: ["DefSum", "DefProd"] }; const discourse = { schemaVersion: "1.0", discourse: { id: "combinatorics", name: "Combinatorics", subject: "discrete_mathematics", variant: "classical", description: "Counting principles: sum and product rules, permutations (with/without repetition), combinations, binomial theorem, pigeonhole principle, inclusion-exclusion, derangements.", structure: { axioms: 0, definitions: 3, theorems: 11 } }, metadata: { created: "2026-03-15", lastUpdated: "2026-03-15", version: "1.0.0", license: "CC BY 4.0", authors: ["Welz, G."], methodology: "Programming Framework", citation: "Welz, G. (2026). Combinatorics Dependency Graph. Programming Framework.", keywords: ["combinatorics", "permutations", "combinations", "counting", "binomial theorem"] }, sources: [ { id: "dmoi", type: "primary", title: "Discrete Mathematics: An Open Introduction", url: "https://discrete.openmathbooks.org/dmoi4/sec_counting-combperm.html", notes: "Counting principles" }, { id: "mathisfun", type: "digital", title: "Combinations and Permutations", url: "https://www.mathsisfun.com/combinatorics/combinations-permutations.html", notes: "Formulas" } ], nodes: [], edges: [], colorScheme: { axiom: { fill: "#e74c3c", stroke: "#c0392b" }, definition: { fill: "#3498db", stroke: "#2980b9" }, theorem: { fill: "#1abc9c", stroke: "#16a085" } } }; for (const n of NODES) { discourse.nodes.push({ id: n.id, type: n.type, label: n.label, shortLabel: n.id, short: n.short, colorClass: n.colorClass }); for (const dep of DEPS[n.id] || []) { discourse.edges.push({ from: dep, to: n.id }); } } const dataDir = path.join(__dirname, "..", "data"); const outPath = path.join(dataDir, "combinatorics.json"); fs.mkdirSync(dataDir, { recursive: true }); fs.writeFileSync(outPath, JSON.stringify(discourse, null, 2), "utf8"); console.log("Wrote", outPath); function sanitizeMermaidLabel(s) { return String(s) .replace(/→/g, "impl") .replace(/⊢/g, "|-") .replace(/∨/g, "or") .replace(/∧/g, "and") .replace(/↔/g, "iff") .replace(/\n/g, " "); } function toMermaid(filter) { const nodes = filter ? discourse.nodes.filter(filter) : discourse.nodes; const nodeIds = new Set(nodes.map(n => n.id)); const edges = discourse.edges.filter(e => nodeIds.has(e.from) && nodeIds.has(e.to)); const lines = ["graph TD"]; for (const n of nodes) { const desc = n.short || n.label; const raw = (n.shortLabel || n.id) + " " + (desc.length > 30 ? desc.slice(0, 27) + "..." : desc); const lbl = sanitizeMermaidLabel(raw).replace(/"/g, '\\"'); lines.push(` ${n.id}("${lbl}")`); } for (const e of edges) { lines.push(` ${e.from} --> ${e.to}`); } lines.push(" classDef axiom fill:#e74c3c,color:#fff,stroke:#c0392b"); lines.push(" classDef definition fill:#3498db,color:#fff,stroke:#2980b9"); lines.push(" classDef theorem fill:#1abc9c,color:#fff,stroke:#16a085"); const axiomIds = nodes.filter(n => n.type === "axiom").map(n => n.id).join(","); const defIds = nodes.filter(n => n.type === "definition").map(n => n.id).join(","); const thmIds = nodes.filter(n => n.type === "theorem").map(n => n.id).join(","); if (axiomIds) lines.push(` class ${axiomIds} axiom`); if (defIds) lines.push(` class ${defIds} definition`); if (thmIds) lines.push(` class ${thmIds} theorem`); return lines.join("\n"); } function closure(ids) { const needed = new Set(ids); let changed = true; while (changed) { changed = false; for (const e of discourse.edges) { if (needed.has(e.to) && !needed.has(e.from)) { needed.add(e.from); changed = true; } } } return n => needed.has(n.id); } function toMermaidWithCounts(filter) { const nodes = filter ? discourse.nodes.filter(filter) : discourse.nodes; const nodeIds = new Set(nodes.map(n => n.id)); const edges = discourse.edges.filter(e => nodeIds.has(e.from) && nodeIds.has(e.to)); return { mermaid: toMermaid(filter), nodes: nodes.length, edges: edges.length }; } const sections = [ { name: "principles-permutations", ids: ["DefFact", "DefSum", "DefProd", "PermNoRep", "PermRep", "CombNoRep"], title: "Principles and Permutations", desc: "Factorial, sum and product principles, permutations with and without repetition, combinations" }, { name: "combinations-binomial", ids: ["CombRep", "BinomThm", "Pascal"], title: "Combinations and Binomial Theorem", desc: "Combinations with repetition, binomial theorem, Pascal identity" }, { name: "advanced-counting", ids: ["Pigeonhole", "InclExcl", "InclExcl3", "Derange", "Stirling2"], title: "Pigeonhole and Inclusion-Exclusion", desc: "Pigeonhole principle, inclusion-exclusion, derangements, Stirling numbers" } ]; const subgraphData = []; for (const s of sections) { const filter = closure(s.ids); const { mermaid: sub, nodes: n, edges: e } = toMermaidWithCounts(filter); subgraphData.push({ ...s, mermaid: sub, nodes: n, edges: e }); fs.writeFileSync(path.join(dataDir, `combinatorics-${s.name}.mmd`), sub, "utf8"); console.log("Wrote", path.join(dataDir, `combinatorics-${s.name}.mmd`)); } fs.writeFileSync(path.join(dataDir, "combinatorics.mmd"), toMermaid(), "utf8"); const MATH_DB = process.env.MATH_DB || "/home/gdubs/copernicus-web-public/huggingface-space/mathematics-processes-database"; const GEO_DIR = path.join(MATH_DB, "processes", "geometry_topology"); function htmlTemplate(title, subtitle, mermaid, nodes, edges) { const mermaidEscaped = mermaid.replace(//g, ">"); return ` ${title} - Mathematics Process

${title}

Mathematics Geometry & Topology / Discrete Source: Standard discrete math texts

Description

${subtitle}

Source: Discrete Mathematics: An Open Introduction; standard combinatorics texts

Dependency Flowchart

Note: Arrows mean "depends on" (tail to head).

${mermaidEscaped}

Color Scheme

Red
Axioms
Blue
Definitions
Teal
Theorems

Statistics

  • Nodes: ${nodes}
  • Edges: ${edges}

Keywords

  • combinatorics
  • permutations
  • combinations
  • binomial theorem
  • counting
`; } if (fs.existsSync(path.join(MATH_DB, "processes"))) { for (const d of subgraphData) { const html = htmlTemplate( `Combinatorics — ${d.title}`, d.desc + ". Shows how counting formulas depend on principles and prior results.", d.mermaid, d.nodes, d.edges ); const fileName = "geometry_topology-combinatorics-" + d.name; fs.writeFileSync(path.join(GEO_DIR, fileName + ".html"), html, "utf8"); console.log("Wrote", path.join(GEO_DIR, fileName + ".html")); } const indexHtml = ` Combinatorics - Mathematics Process

Combinatorics

Counting principles: sum and product rules, permutations, combinations, binomial theorem, pigeonhole principle, inclusion-exclusion, derangements. Split into three views.

Chart 1 — Principles and Permutations Chart 2 — Combinations and Binomial Theorem Chart 3 — Pigeonhole and Inclusion-Exclusion
`; fs.writeFileSync(path.join(GEO_DIR, "geometry_topology-combinatorics.html"), indexHtml, "utf8"); console.log("Wrote", path.join(GEO_DIR, "geometry_topology-combinatorics.html")); } else { console.log("MATH_DB not found - skipping HTML generation."); } console.log("Done. Nodes:", discourse.nodes.length, "Edges:", discourse.edges.length);