{"spec_id":"bifurcation-basic","library":"muix","language":"javascript","code":"// anyplot.ai\n// bifurcation-basic: Bifurcation Diagram for Dynamical Systems\n// Library: muix 7.29.1 | JavaScript 22.22.3\n// Quality: 91/100 | Created: 2026-06-17\n//# anyplot-orientation: landscape\n// anyplot.ai\n// bifurcation-basic: Bifurcation Diagram for Dynamical Systems\n// Library: MUI X Charts | React | Node 22\n// License: @mui/x-charts — MIT (community). Pro/Premium are out of scope.\n// Quality: pending | Created: 2026-06-17\n\nimport { ChartContainer } from \"@mui/x-charts/ChartContainer\";\nimport { ScatterPlot } from \"@mui/x-charts/ScatterChart\";\nimport { ChartsXAxis } from \"@mui/x-charts/ChartsXAxis\";\nimport { ChartsYAxis } from \"@mui/x-charts/ChartsYAxis\";\nimport { useDrawingArea } from \"@mui/x-charts/hooks\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data: logistic map  x(n+1) = r · x(n) · (1 − x(n)) -------------------\n// Iterate deterministically from a fixed start, discard the transient, then\n// record long-term orbit points. 1000 r-steps × 120 records = 120 k points —\n// dense enough to meet the spec's 100 k+ target and fill the chaotic band.\nconst R_MIN = 2.5;\nconst R_MAX = 4.0;\nconst R_STEPS = 1000;   // parameter resolution along the x-axis\nconst TRANSIENT = 300;  // discarded initial iterations (settle onto attractor)\nconst RECORD = 120;     // states kept per r value (the steady-state orbit)\nconst X0 = 0.4;         // fixed seed (avoids the 0.5 trap at r=4)\n\nconst points: { x: number; y: number; id: number }[] = [];\nlet pid = 0;\nfor (let i = 0; i < R_STEPS; i++) {\n  const r = R_MIN + ((R_MAX - R_MIN) * i) / (R_STEPS - 1);\n  let x = X0;\n  for (let n = 0; n < TRANSIENT; n++) x = r * x * (1 - x);\n  for (let n = 0; n < RECORD; n++) {\n    x = r * x * (1 - x);\n    points.push({ x: r, y: x, id: pid++ });\n  }\n}\n\n// Key period-doubling bifurcations (analytic values).\n// Labels alternate left (anchor \"end\") / right (anchor \"start\") so the\n// clustered r=3.544 and r=3.5699 references don't crowd on the same side.\n// Two vertical levels spread each left/right pair apart vertically.\nconst MARKERS = [\n  { r: 3.0,    text: \"period-2\", anchor: \"end\",   level: 0 },\n  { r: 3.449,  text: \"period-4\", anchor: \"end\",   level: 1 },\n  { r: 3.544,  text: \"period-8\", anchor: \"start\", level: 0 },\n  { r: 3.5699, text: \"chaos\",    anchor: \"start\", level: 1 },\n];\nconst LABEL_Y_OFFSETS = [18, 54];   // two distinct heights (px from top of drawing area)\n\nconst TITLE_H = 60;\n\n// Overlay drawn in SVG space via the drawing-area hook. Linear axes map each\n// r value to an exact x pixel coordinate without guessing scale factors.\nfunction Bifurcations() {\n  const { left, top, width, height } = useDrawingArea();\n  const xOf = (r: number) => left + ((r - R_MIN) / (R_MAX - R_MIN)) * width;\n\n  return (\n    <g>\n      {MARKERS.map((m) => {\n        const x = xOf(m.r);\n        const dx = m.anchor === \"end\" ? -8 : 8;\n        const labelY = top + LABEL_Y_OFFSETS[m.level];\n        return (\n          <g key={m.r}>\n            <line\n              x1={x}\n              y1={top}\n              x2={x}\n              y2={top + height}\n              stroke={t.amber}\n              strokeWidth={1.5}\n              strokeDasharray=\"7 5\"\n              opacity={0.7}\n            />\n            <text\n              x={x + dx}\n              y={labelY}\n              fill={t.inkSoft}\n              textAnchor={m.anchor}\n              style={{ fontSize: 13, fontFamily: \"Inter, system-ui, sans-serif\", fontWeight: 600 }}\n            >\n              {m.text}\n            </text>\n            <text\n              x={x + dx}\n              y={labelY + 16}\n              fill={t.inkSoft}\n              textAnchor={m.anchor}\n              opacity={0.8}\n              style={{ fontSize: 11, fontFamily: \"Inter, system-ui, sans-serif\" }}\n            >\n              r ≈ {m.r}\n            </text>\n          </g>\n        );\n      })}\n    </g>\n  );\n}\n\nexport default function Chart() {\n  const W = window.ANYPLOT_SIZE.width;\n  const H = window.ANYPLOT_SIZE.height;\n\n  return (\n    <div\n      style={{\n        width: W,\n        height: H,\n        background: t.pageBg,\n        fontFamily: \"Inter, system-ui, sans-serif\",\n        display: \"flex\",\n        flexDirection: \"column\",\n      }}\n    >\n      <div\n        style={{\n          height: TITLE_H,\n          display: \"flex\",\n          alignItems: \"center\",\n          justifyContent: \"center\",\n        }}\n      >\n        <span style={{ fontSize: 22, fontWeight: 600, color: t.ink }}>\n          bifurcation-basic · javascript · muix · anyplot.ai\n        </span>\n      </div>\n      <ChartContainer\n        width={W}\n        height={H - TITLE_H}\n        skipAnimation\n        // Density via low-alpha brand green (Imprint palette position 1).\n        colors={[\"rgba(0, 158, 115, 0.55)\"]}\n        margin={{ top: 16, bottom: 70, left: 86, right: 28 }}\n        series={[\n          {\n            type: \"scatter\",\n            data: points,\n            markerSize: 1,\n            label: \"Steady-state orbit\",\n            disableHover: true,\n          },\n        ]}\n        xAxis={[\n          {\n            min: R_MIN,\n            max: R_MAX,\n            label: \"Growth rate  r\",\n            tickLabelStyle: { fontSize: 14 },\n            labelStyle: { fontSize: 16 },\n          },\n        ]}\n        yAxis={[\n          {\n            min: 0,\n            max: 1,\n            label: \"Steady-state population  x\",\n            tickNumber: 11,\n            tickLabelStyle: { fontSize: 14 },\n            labelStyle: { fontSize: 16 },\n          },\n        ]}\n        sx={{\n          \"& .MuiChartsLegend-root\": { display: \"none\" },\n          \"& .MuiChartsAxis-line\": { stroke: t.inkSoft },\n          \"& .MuiChartsAxis-tick\": { stroke: t.inkSoft },\n        }}\n      >\n        <ScatterPlot />\n        <ChartsXAxis />\n        <ChartsYAxis />\n        <Bifurcations />\n      </ChartContainer>\n    </div>\n  );\n}\n"}