{
  "nbformat": 4,
  "nbformat_minor": 5,
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "name": "python",
      "version": "3.12.14"
    },
    "execution": {
      "method": "Python subprocess, exact code cell source",
      "deterministic_replay_passed": true
    },
    "runtime": {
      "packages": [],
      "local_assets": []
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "id": "question",
      "metadata": {},
      "source": [
        "# The payoff tables a monotonic QMIX mixer cannot represent\n",
        "Exact two-by-two tests separate additive values, nonlinear monotonic synergy, and a ranking reversal that no fixed utility order can express.\n",
        "\nExhaustive two-by-two payoff representation checks with an analytic mixer; no neural optimization.\n"
      ]
    },
    {
      "cell_type": "code",
      "id": "experiment",
      "metadata": {},
      "execution_count": 1,
      "source": [
        "\"\"\"The payoff tables a monotonic QMIX mixer cannot represent\n",
        "Deterministic, standard-library experiment. RESULTS contains the full data.\n",
        "\"\"\"\n",
        "from itertools import permutations, product\n",
        "\n",
        "tables = {\n",
        "    'additive': [[0, 2], [1, 3]],\n",
        "    'monotonic nonlinear': [[0, 1], [1, 4]],\n",
        "    'ranking reversal': [[0, 2], [2, 0]],\n",
        "}\n",
        "\n",
        "def monotonic_order_exists(table):\n",
        "    for rows in permutations(range(2)):\n",
        "        for cols in permutations(range(2)):\n",
        "            ordered = [[table[r][c] for c in cols] for r in rows]\n",
        "            row_ok = all(row[0] <= row[1] for row in ordered)\n",
        "            col_ok = all(ordered[0][c] <= ordered[1][c] for c in range(2))\n",
        "            if row_ok and col_ok:\n",
        "                return True\n",
        "    return False\n",
        "\n",
        "for name, table in tables.items():\n",
        "    difference = table[0][0] + table[1][1] - table[0][1] - table[1][0]\n",
        "    print(f'{name}: mixed difference={difference}, monotonic={monotonic_order_exists(table)}')\n",
        "\n",
        "def mixer(u, v):\n",
        "    return u + v + 2 * u * v\n",
        "\n",
        "for a, b in product(range(2), repeat=2):\n",
        "    assert mixer(a, b) == tables['monotonic nonlinear'][a][b]\n",
        "assert monotonic_order_exists(tables['additive'])\n",
        "assert not monotonic_order_exists(tables['ranking reversal'])\n",
        "print('constructed monotonic mixer greedy value:', mixer(1, 1))\n",
        "\n",
        "\n",
        "records=[]\n",
        "for name,table in tables.items():\n",
        "    orderings=[]\n",
        "    for rs in permutations(range(2)):\n",
        "        for cs in permutations(range(2)):\n",
        "            ordered=[[table[r][c] for c in cs] for r in rs]\n",
        "            violations=sum(row[0]>row[1] for row in ordered)+sum(ordered[0][c]>ordered[1][c] for c in range(2))\n",
        "            orderings.append(dict(rows=list(rs),columns=list(cs),violations=violations))\n",
        "    records.append(dict(name=name,table=table,mixed_difference=table[0][0]+table[1][1]-table[0][1]-table[1][0],monotonic=monotonic_order_exists(table),orderings=orderings))\n",
        "# Strictly increasing affine remapping preserves every ordering contradiction.\n",
        "transformed=[[3*x+7 for x in row] for row in tables['ranking reversal']]\n",
        "assert not monotonic_order_exists(transformed)\n",
        "RESULTS=dict(tables=records,affine_reversal_still_impossible=True,mixer_corners=[dict(u=u,v=v,value=mixer(u,v)) for u,v in product(range(2),repeat=2)])\n",
        "print('All 12 row/column orderings enumerated; affine-remapped reversal also rejected')\n"
      ],
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "additive: mixed difference=0, monotonic=True\n",
            "monotonic nonlinear: mixed difference=2, monotonic=True\n",
            "ranking reversal: mixed difference=-4, monotonic=False\n",
            "constructed monotonic mixer greedy value: 4\n",
            "All 12 row/column orderings enumerated; affine-remapped reversal also rejected\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from pathlib import Path\n",
        "import base64\n",
        "print('__NOTEBOOK_IMAGE__svg+xml:' + base64.b64encode(Path('figure.svg').read_bytes()).decode())\n"
      ]
    }
  ]
}
