{
  "nbformat": 4,
  "nbformat_minor": 5,
  "metadata": {
    "kernelspec": {
      "name": "aner",
      "display_name": "Aner",
      "language": "aner"
    },
    "language_info": {
      "name": "aner",
      "file_extension": ".aner"
    },
    "aner": {
      "execution_mode": "persistent-session",
      "runtime_mode": "development"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "# Precision policies and portable training\n\nAll runs use the same Float64 source and seeded tensors. Preserve retains Float64, using CPU when MPS cannot provide it. Adapt lowers precision only when required by the selected backend. Fast explicitly requests Float32. The Inspector shows actual tensor precision, device, and provider after each completed cell. Warnings identify any execution change.\n",
      "id": "precision-intro"
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "%aner dev"
      ],
      "execution_count": null,
      "outputs": [],
      "id": "precision-development"
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "import aner.nn\n",
        "import aner.dev\n",
        "\n",
        "fn exercise() -> Tensor {\n",
        "    print(nn.execution())\n",
        "    let input = nn.random(rows: 3, cols: 5, seed: 2026, scale: 0.25).place()\n",
        "    let target = nn.zeros(rows: 3, cols: 2).place()\n",
        "    var weights = nn.parameter(nn.random(rows: 5, cols: 2, seed: 42, scale: 0.1).place())\n",
        "    let first = nn.mse(nn.matmul(input, weights), target)\n",
        "    print(nn.item(first))\n",
        "    var step = 0\n",
        "    while step < 8 {\n",
        "        let loss = nn.mse(nn.matmul(input, weights), target)\n",
        "        nn.backward(loss)\n",
        "        weights = nn.sgd(weights, rate: 0.1)\n",
        "        step = step + 1\n",
        "    }\n",
        "    let final = nn.mse(nn.matmul(input, weights), target)\n",
        "    print(nn.item(final))\n",
        "    print(weights.dtype())\n",
        "    print(weights.device())\n",
        "    print(weights.backend())\n",
        "    dev.capture(label: \"trained precision weights\", value: weights)\n",
        "    return nn.detach(weights)\n",
        "}\n",
        "print(nn.devices())\n"
      ],
      "execution_count": null,
      "outputs": [],
      "id": "precision-setup"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "## CPU Float64 reference\n",
      "id": "precision-cpu-description"
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "nn.configure(device: \"cpu\", precision: \"Float64\", policy: \"preserve\")\n",
        "let cpu64_weights = exercise()\n"
      ],
      "execution_count": null,
      "outputs": [],
      "id": "precision-cpu"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "## Preserve high precision\n\nAn available CUDA backend uses native Float64. On an MPS Mac this profile selects CPU Float64 and explains the fallback.\n",
      "id": "precision-preserve-description"
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "nn.configure(device: \"auto\", precision: \"Float64\", policy: \"preserve\")\n",
        "let preserved_weights = exercise()\n"
      ],
      "execution_count": null,
      "outputs": [],
      "id": "precision-preserve"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "## Adapt for backend compatibility\n\nCUDA retains Float64. MPS uses Float32 with a warning.\n",
      "id": "precision-adapt-description"
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "nn.configure(device: \"auto\", precision: \"Float64\", policy: \"adapt\")\n",
        "let adapted_weights = exercise()\n"
      ],
      "execution_count": null,
      "outputs": [],
      "id": "precision-adapt"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "## Request Float32 for performance\n\nThis policy changes precision explicitly. Small workloads can still be faster on CPU.\n",
      "id": "precision-fast-description"
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "nn.configure(device: \"auto\", precision: \"Float64\", policy: \"fast\")\n",
        "let fast_weights = exercise()\n"
      ],
      "execution_count": null,
      "outputs": [],
      "id": "precision-fast"
    }
  ]
}
