{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "results-intro",
      "metadata": {
      },
      "source": "# Native results: C, D and E\n\nRead the completed saved trial table and compute medians, ranges and serial speedups with native Aner. This notebook runs no 100-million-draw workload. Run from the project root with **Shared variables**, in cell order. Outputs ship empty. [Measurement boundaries and interpretation](../docs/methodology.md).\n"
    },
    {
      "cell_type": "markdown",
      "id": "results-read-note",
      "metadata": {
      },
      "source": "## Read and validate the 36 trials\n\nThe selected-field CSV has columns `case,trial,order,elapsed_ns,draws,workers`. Require 12 unique trials for each of C/D/E, equal positive draw counts, admitted worker counts 1/4/8 and balanced order positions. The CSV is a projection of the raw trace: retain the trace and its full equality-validation records.\n\nEach case's 12 integer nanosecond durations are sorted. The median is the average of zero-based positions **5 and 6**, converted to seconds.\n"
    },
    {
      "cell_type": "code",
      "id": "results-read",
      "metadata": {
      },
      "execution_count": null,
      "outputs": [

      ],
      "source": "// Run from the project root after results/native-trials.csv is complete.\n// The six-column CSV preserves selected raw trial fields; retain original traces.\n// SVG export requires a fresh path. Notebook uses the same analysis without saving.\nimport aner.data\nimport aner.plot\n\nlet native_input = \"results/native-trials.csv\"\nlet native_export_svg = false\n\nfn native_require(condition: Bool, message: String) -> Unit {\n    if !condition {\n        print(\"FAILED: native trial analysis: \" + message)\n        let failure: Result<Bool, String> = Result.err(\"Native trial analysis: \" + message)\n        print(failure.unwrap())\n    }\n}\n\nfn native_case_index(label: String) -> Int64 {\n    if label == \"C\" { return 0 }\n    if label == \"D\" { return 1 }\n    if label == \"E\" { return 2 }\n    return -1\n}\n\nvar native_schema = data.schema()\nnative_schema = data.column(native_schema, \"case\", \"String\", false)\nnative_schema = data.column(native_schema, \"trial\", \"Int64\", false)\nnative_schema = data.column(native_schema, \"order\", \"Int64\", false)\nnative_schema = data.column(native_schema, \"elapsed_ns\", \"Int64\", false)\nnative_schema = data.column(native_schema, \"draws\", \"Int64\", false)\nnative_schema = data.column(native_schema, \"workers\", \"Int64\", false)\nlet native_trials = data.collect(data.scan_csv(native_input, native_schema, missing: \"\"),\n    max_rows: 256, max_bytes: 1_048_576, batch_rows: 64)\nnative_require(data.rows(native_trials) == 36, \"expected 36 rows: 12 each for C, D and E\")\n\nlet native_names = List(\"C\", \"D\", \"E\")\nlet native_worker_counts = List(1, 4, 8)\nlet native_seen = Array<Bool>(36, false)\nlet native_times = Array<Int64>(36, 0)\nlet native_positions = Array<Int64>(9, 0)\nlet native_draws = data.integer(native_trials, 0, \"draws\")\nnative_require(native_draws > 0, \"draw count must be positive\")\nfor row in Range(data.rows(native_trials)) {\n    let arm = native_case_index(data.text(native_trials, row, \"case\"))\n    let trial = data.integer(native_trials, row, \"trial\")\n    let position = data.integer(native_trials, row, \"order\")\n    let elapsed = data.integer(native_trials, row, \"elapsed_ns\")\n    native_require(arm >= 0, \"unexpected case label\")\n    native_require(trial >= 1 && trial <= 12, \"trial must be 1 through 12\")\n    native_require(position >= 1 && position <= 3, \"order must be 1 through 3\")\n    native_require(elapsed > 0, \"elapsed nanoseconds must be positive\")\n    native_require(data.integer(native_trials, row, \"draws\") == native_draws,\n        \"all trials must have the same draw count\")\n    native_require(data.integer(native_trials, row, \"workers\") == cast<Int64>(native_worker_counts.get(arm)),\n        \"expected C=1, D=4, E=8 admitted workers\")\n    let slot = arm * 12 + trial - 1\n    native_require(!native_seen[slot], \"duplicate case/trial identity\")\n    native_seen[slot] = true\n    native_times[slot] = elapsed\n    native_positions[arm * 3 + position - 1] += 1\n}\nfor slot in Range(36) { native_require(native_seen[slot], \"missing case/trial identity\") }\nfor position in Range(9) { native_require(native_positions[position] == 4, \"order positions must be balanced\") }\n\nlet native_medians = Array<Float64>(3, 0.0)\nlet native_minima = Array<Float64>(3, 0.0)\nlet native_maxima = Array<Float64>(3, 0.0)\nfor arm in Range(3) {\n    let sorted = Array<Int64>(12, 0)\n    for trial in Range(12) { sorted[trial] = native_times[arm * 12 + trial] }\n    sorted.sort()\n    native_minima[arm] = Float64(sorted[0]) / 1_000_000_000.0\n    native_maxima[arm] = Float64(sorted[11]) / 1_000_000_000.0\n    // For 12 observations, average sorted zero-based positions 5 and 6.\n    native_medians[arm] = (Float64(sorted[5]) + Float64(sorted[6])) / 2_000_000_000.0\n}\n\n"
    },
    {
      "cell_type": "markdown",
      "id": "results-plot-note",
      "metadata": {
      },
      "source": "## Compute the summary and show the chart\n\nBars show the median repeat-call wall time; the printed record also includes min/max and speedup against C. Lower is faster. Cluster calls include their actual connection/admission and teardown; warmups and post-call validation are excluded. Twelve fixed-seed repetitions are timing replications, not independent RNG datasets.\n\nThis notebook displays the computed chart without overwriting files. The standalone [analyzer](../analysis/summarize_native.aner) exports the same figure to a fresh `media/native-timing.svg`; use a new export path or disable export before rerunning it when that file already exists.\n"
    },
    {
      "cell_type": "code",
      "id": "results-summary-chart",
      "metadata": {
      },
      "execution_count": null,
      "outputs": [

      ],
      "source": "var native_json_cases = \"[\"\nfor arm in Range(3) {\n    if arm > 0 { native_json_cases = native_json_cases + \",\" }\n    let name = cast<String>(native_names.get(arm))\n    let speedup = native_medians[0] / native_medians[arm]\n    print(\"Case \" + name + \": median=\" + String(native_medians[arm])\n        + \" s; min=\" + String(native_minima[arm]) + \"; max=\" + String(native_maxima[arm])\n        + \"; serial speedup=\" + String(speedup))\n    native_json_cases = native_json_cases + \"{\\\"case\\\":\\\"\" + name\n        + \"\\\",\\\"workers\\\":\" + String(cast<Int64>(native_worker_counts.get(arm)))\n        + \",\\\"n\\\":12,\\\"median_seconds\\\":\" + String(native_medians[arm])\n        + \",\\\"min_seconds\\\":\" + String(native_minima[arm])\n        + \",\\\"max_seconds\\\":\" + String(native_maxima[arm])\n        + \",\\\"speedup_vs_C\\\":\" + String(speedup) + \"}\"\n}\nnative_json_cases = native_json_cases + \"]\"\nprint(\"TNC_NATIVE_SUMMARY_V1 {\\\"schema\\\":\\\"traceable-number-choices/native-analysis/1\\\",\"\n    + \"\\\"source\\\":\\\"results/native-trials.csv\\\",\\\"timing_scope\\\":\\\"parallel-repeat-call\\\",\"\n    + \"\\\"draws\\\":\" + String(native_draws) + \",\\\"cases\\\":\" + native_json_cases\n    + \",\\\"cluster_elapsed_reduction_vs_parallel\\\":\" + String(1.0 - native_medians[2] / native_medians[1])\n    + \",\\\"cluster_throughput_gain_vs_parallel\\\":\" + String(native_medians[1] / native_medians[2] - 1.0) + \"}\")\n\nlet native_timing_chart = plot.bar(List(\"C: Serial 1\", \"D: Local 4\", \"E: Nodes 4+4\"), native_medians)\n    .title(\"Same native draws, different execution policies\")\n    .labels(\"Execution policy (admitted workers)\", \"Median repeat-call wall time (seconds)\")\n    .caption(String(native_draws) + \" fixed-seed draws; 12 balanced trials per policy. Lower is faster. Cluster setup included; warmup and validation excluded.\")\n    .theme(plot.theme(\"light\"))\n    .size(width: 1_120, height: 620)\nif native_export_svg { native_timing_chart.save(\"media/native-timing.svg\") }\nnative_timing_chart.show()\n"
    }
  ],
  "metadata": {
    "kernelspec": {
      "name": "aner",
      "display_name": "Aner",
      "language": "aner"
    },
    "language_info": {
      "name": "aner",
      "file_extension": ".aner",
      "mimetype": "text/x-aner"
    },
    "aner": {
      "execution_mode": "persistent-session",
      "runtime_mode": "production",
      "source_file": "../analysis/summarize_native.aner",
      "status": "live-source-only"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
