diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a4dc7a59a..d5348c43a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,10 +60,7 @@ While `dev` contains the most complete set of install dependencies, a number of pip install -e ".[dev]" ~~~ -The `dev` extra includes QMCPy's PyPI-hosted MPMC dependencies. MPMC additionally -requires a platform-specific `pyg_lib` wheel that is not available from PyPI. -After installing `dev`, let the QMCPy installer select the wheel page matching -the installed PyTorch build: +The `dev` extra includes QMCPy's PyPI-hosted MPMC dependencies. MPMC additionally requires a platform-specific `pyg_lib` wheel that is not available from PyPI. After installing `dev`, let the QMCPy installer select the wheel page matching the installed PyTorch build: ~~~bash qmcpy-install-mpmc diff --git a/demos/true_measure_domain_inclusion.ipynb b/demos/true_measure_domain_inclusion.ipynb new file mode 100644 index 000000000..00c8f6367 --- /dev/null +++ b/demos/true_measure_domain_inclusion.ipynb @@ -0,0 +1,956 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a4c44dd5", + "metadata": {}, + "source": [ + "# Chaining `TrueMeasure` Transformations with Compatible Domains\n", + "\n", + "## 1. Problem and proposed rule\n", + "\n", + "Consider consecutive transformations\n", + "\n", + "$$\n", + "T_{j-1}:D_{j-1}\\rightarrow R_{j-1},\n", + "\\qquad\n", + "T_j:D_j\\rightarrow R_j.\n", + "$$\n", + "\n", + "QMCPy previously treated the shared boundary as compatible only when\n", + "\n", + "$$\n", + "R_{j-1}=D_j.\n", + "$$\n", + "\n", + "The output of $T_{j-1}$ becomes input to $T_j$, so exact equality is unnecessary. For domain compatibility, every output only needs to lie inside the domain accepted by the next transformation:\n", + "\n", + "$$\n", + "R_{j-1}\\subseteq D_j.\n", + "$$\n", + "\n", + "One example captures the difference:\n", + "\n", + "$$\n", + "[0.25,0.75]\\neq[0,1],\n", + "\\qquad\n", + "[0.25,0.75]\\subseteq[0,1].\n", + "$$\n", + "\n", + "For one-dimensional bounds\n", + "\n", + "$$\n", + "R=[r_L,r_U],\n", + "\\qquad\n", + "D=[d_L,d_U],\n", + "$$\n", + "\n", + "compatibility means\n", + "\n", + "$$\n", + "d_L\\leq r_L\n", + "\\qquad\\text{and}\\qquad\n", + "r_U\\leq d_U.\n", + "$$\n", + "\n", + "The same inequalities are checked coordinate-wise for multidimensional axis-aligned boxes. The implemented scope covers intervals and boxes with finite or unbounded numerical bounds, while preserving NumPy broadcasting between common `(1,2)` bounds and coordinate-specific `(d,2)` bounds.\n", + "\n", + "> QMCPy currently stores numerical lower/upper support envelopes, including `-np.inf` and `np.inf`; explicit open/closed endpoints, disconnected supports, and arbitrary nonrectangular supports are not represented by this change." + ] + }, + { + "cell_type": "markdown", + "id": "d94f50a6", + "metadata": {}, + "source": [ + "## 2. What changed in QMCPy?\n", + "\n", + "The old chained-`TrueMeasure` check was\n", + "\n", + "```python\n", + "if (self.domain != self.transform.range).any():\n", + " self.sub_compatibility_error = True\n", + "```\n", + "\n", + "It is now\n", + "\n", + "```python\n", + "if not self._range_in_domain(self.transform.range, self.domain):\n", + " self.sub_compatibility_error = True\n", + "```\n", + "\n", + "After broadcasting the bound arrays, the essential helper logic is\n", + "\n", + "```python\n", + "domain[:, 0] <= transform_range[:, 0]\n", + "transform_range[:, 1] <= domain[:, 1]\n", + "```\n", + "\n", + "Both inequalities must hold in every coordinate. Equality still works because it is a special case of containment, and broadcasting preserves the existing `(1,2)` versus `(d,2)` convention." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "8d512296", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-24T19:24:44.410561Z", + "iopub.status.busy": "2026-08-24T19:24:44.409591Z", + "iopub.status.idle": "2026-08-24T19:24:46.645979Z", + "shell.execute_reply": "2026-08-24T19:24:46.644328Z" + } + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import pandas as pd\n", + "from matplotlib.patches import Rectangle\n", + "from scipy.stats import logistic, norm\n", + "\n", + "from qmcpy import (\n", + " AbstractTrueMeasure,\n", + " CubQMCSobolG,\n", + " CustomFun,\n", + " DigitalNetB2,\n", + " Kumaraswamy,\n", + " Uniform,\n", + ")\n", + "from qmcpy.util import ParameterError\n", + "\n", + "\n", + "def previous_compatibility_check(transform_range, domain):\n", + " # Reproduce the previous broadcasted exact-equality rule.\n", + " return not (np.asarray(domain) != np.asarray(transform_range)).any()\n" + ] + }, + { + "cell_type": "markdown", + "id": "85f8195a", + "metadata": {}, + "source": [ + "## 3. Behavior before and after\n", + "\n", + "A compact comparison shows the intended behavioral boundary. The following cells then exercise three real QMCPy chains rather than testing only the helper." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "ed148c64", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-24T19:24:46.650630Z", + "iopub.status.busy": "2026-08-24T19:24:46.649593Z", + "iopub.status.idle": "2026-08-24T19:24:46.680364Z", + "shell.execute_reply": "2026-08-24T19:24:46.679106Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
CaseOld equality ruleNew containment rule
0Exact equalityTrueTrue
1Strict inclusionFalseTrue
2Infinite containing domainFalseTrue
3Lower-bound violationFalseFalse
4Multidimensional inclusionFalseTrue
\n", + "
" + ], + "text/plain": [ + " Case Old equality rule New containment rule\n", + "0 Exact equality True True\n", + "1 Strict inclusion False True\n", + "2 Infinite containing domain False True\n", + "3 Lower-bound violation False False\n", + "4 Multidimensional inclusion False True" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "comparison_cases = [\n", + " (\"Exact equality\", [[0, 1]], [[0, 1]]),\n", + " (\"Strict inclusion\", [[0.25, 0.75]], [[0, 1]]),\n", + " (\"Infinite containing domain\", [[-5, 5]], [[-np.inf, np.inf]]),\n", + " (\"Lower-bound violation\", [[-0.1, 0.75]], [[0, 1]]),\n", + " (\n", + " \"Multidimensional inclusion\",\n", + " [[0.1, 0.8], [0.2, 0.9]],\n", + " [[0, 1]],\n", + " ),\n", + "]\n", + "\n", + "comparison = pd.DataFrame(\n", + " [\n", + " {\n", + " \"Case\": name,\n", + " \"Old equality rule\": previous_compatibility_check(bounds, domain),\n", + " \"New containment rule\": AbstractTrueMeasure._range_in_domain(\n", + " bounds, domain\n", + " ),\n", + " }\n", + " for name, bounds, domain in comparison_cases\n", + " ]\n", + ")\n", + "comparison" + ] + }, + { + "cell_type": "markdown", + "id": "5fad26b1", + "metadata": {}, + "source": [ + "### A. Strict 1D inclusion\n", + "\n", + "An inner `Uniform` produces values in $[0.25,0.75]$, while the outer `Kumaraswamy` accepts inputs in $[0,1]$." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "e3f1220f", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-24T19:24:46.686289Z", + "iopub.status.busy": "2026-08-24T19:24:46.685485Z", + "iopub.status.idle": "2026-08-24T19:24:46.720415Z", + "shell.execute_reply": "2026-08-24T19:24:46.715058Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Inner range: [[0.25 0.75]]\n", + "Outer domain: [[0 1]]\n", + "Range contained in domain: True\n", + "Compatibility error: False\n", + "Sample shape: (8, 1)\n", + "All samples finite: True\n" + ] + } + ], + "source": [ + "inner = Uniform(\n", + " DigitalNetB2(1, seed=7),\n", + " lower_bound=0.25,\n", + " upper_bound=0.75,\n", + ")\n", + "outer = Kumaraswamy(inner)\n", + "samples_1d = outer.gen_samples(8)\n", + "\n", + "print(\"Inner range:\", inner.range)\n", + "print(\"Outer domain:\", outer.domain)\n", + "print(\n", + " \"Range contained in domain:\",\n", + " AbstractTrueMeasure._range_in_domain(inner.range, outer.domain),\n", + ")\n", + "print(\"Compatibility error:\", outer.sub_compatibility_error)\n", + "print(\"Sample shape:\", samples_1d.shape)\n", + "print(\"All samples finite:\", np.isfinite(samples_1d).all())" + ] + }, + { + "cell_type": "markdown", + "id": "a27ca7cd", + "metadata": {}, + "source": [ + "### B. Multidimensional/broadcast inclusion\n", + "\n", + "Here a `(2,2)` inner range is checked against the outer measure's common `(1,2)` unit-domain interval." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "3b524d4a", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-24T19:24:46.724795Z", + "iopub.status.busy": "2026-08-24T19:24:46.724399Z", + "iopub.status.idle": "2026-08-24T19:24:46.737550Z", + "shell.execute_reply": "2026-08-24T19:24:46.734862Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Inner range: [[0.1 0.8]\n", + " [0.2 0.9]]\n", + "Outer domain: [[0 1]]\n", + "Range contained in domain: True\n", + "Compatibility error: False\n", + "Sample shape: (8, 2)\n", + "All samples finite: True\n" + ] + } + ], + "source": [ + "inner_2d = Uniform(\n", + " DigitalNetB2(2, seed=7),\n", + " lower_bound=[0.1, 0.2],\n", + " upper_bound=[0.8, 0.9],\n", + ")\n", + "outer_2d = Kumaraswamy(inner_2d)\n", + "samples_2d = outer_2d.gen_samples(8)\n", + "\n", + "print(\"Inner range:\", inner_2d.range)\n", + "print(\"Outer domain:\", outer_2d.domain)\n", + "print(\n", + " \"Range contained in domain:\",\n", + " AbstractTrueMeasure._range_in_domain(inner_2d.range, outer_2d.domain),\n", + ")\n", + "print(\"Compatibility error:\", outer_2d.sub_compatibility_error)\n", + "print(\"Sample shape:\", samples_2d.shape)\n", + "print(\"All samples finite:\", np.isfinite(samples_2d).all())" + ] + }, + { + "cell_type": "markdown", + "id": "6c017194", + "metadata": {}, + "source": [ + "### C. Actual incompatibility\n", + "\n", + "The range\n", + "\n", + "$$\n", + "[-0.1,0.75]\\nsubseteq[0,1]\n", + "$$\n", + "\n", + "extends below the next domain and must remain rejected." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "fd51b128", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-24T19:24:46.743432Z", + "iopub.status.busy": "2026-08-24T19:24:46.742993Z", + "iopub.status.idle": "2026-08-24T19:24:46.752101Z", + "shell.execute_reply": "2026-08-24T19:24:46.750435Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Range contained in domain: False\n", + "Compatibility error: True\n", + "Sampling result: ParameterError - The sub-transform range must be contained within the transform domain.\n" + ] + } + ], + "source": [ + "invalid_inner = Uniform(\n", + " DigitalNetB2(1, seed=7),\n", + " lower_bound=-0.1,\n", + " upper_bound=0.75,\n", + ")\n", + "invalid_outer = Kumaraswamy(invalid_inner)\n", + "\n", + "print(\n", + " \"Range contained in domain:\",\n", + " AbstractTrueMeasure._range_in_domain(\n", + " invalid_inner.range, invalid_outer.domain\n", + " ),\n", + ")\n", + "print(\"Compatibility error:\", invalid_outer.sub_compatibility_error)\n", + "\n", + "try:\n", + " invalid_outer.gen_samples(8)\n", + "except ParameterError as error:\n", + " print(\"Sampling result:\", type(error).__name__, \"-\", error)" + ] + }, + { + "cell_type": "markdown", + "id": "d4d209de", + "metadata": {}, + "source": [ + "The change accepts strict containment without accepting genuinely out-of-domain transformations.\n", + "\n", + "### D. One compatibility visual\n", + "\n", + "For axis-aligned boxes, compatibility is checked coordinate by coordinate. The dashed box is fully contained; the dotted box violates the second-coordinate upper bound." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "490d7fe0", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-24T19:24:46.754962Z", + "iopub.status.busy": "2026-08-24T19:24:46.754730Z", + "iopub.status.idle": "2026-08-24T19:24:46.996190Z", + "shell.execute_reply": "2026-08-24T19:24:46.995224Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "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bl999dVqfR6qWob4WTN79mw0b95cXTy4T58++Pnnn4+5/bvvvov27dur7Tt37ozPPvusxmIlIqLwtH//ftx6661o2bIloqKi0KRJEwwaNAgrVqyo0uc57bTTcPvtt1f4cbNmzcK8efOqNBYyj6DX8C1cuBDjx4/HnDlzVLI3c+ZMDBw4EFu2bPF7iRW5Vt+VV16J6dOn44ILLsDbb7+NIUOGYO3atejUqRPM6vDhw8EOwRTk0koFBQXIy8vjpZVYroZm1mPV4XDA5XKpvzab7ZjbymXQKkuDpp7DW0ZBBpbuWOqzX6fDCYfNdzt/duzYoRKxxMREdf6R843sf9myZRg9ejQ2btxY6VjLugRcyfiPJzY2Vv2t6OMqSt4/ibG8ZFt5TERE0FOOsGbRKvKuVQNJ8k488UQ899xzalkOcvnVJL+iJk6cWGr7oUOHIjc3F5988oln3UknnYRu3bqppPF4srOz1Qc2KysLCQkJMKJDhw6pZFe+5OUC0vv27avQh4vKxjKtHixXlml5NWvWTH1X165dG3muPDyz6xmf+29rehtibUcTlzf3vomVGSsrVbgNoxri0daP+qzLdmZj3JZxqGWrhSOuI2rdrHazkBBx/HPBuHHjsHXrVrz33nuIiYnxuS8nJwfx8fGeWsAnnngCv/zyi7pmb9++fTFhwgSkpqaq+1966SWsWrUK11xzjSoHOSf169cP9913H+Li4lRz6aeffuqz/w8//BD16tXDtGnT8OuvvyItLU0tX3rppaoCRCePPXLkCJ588km1fPPNN6NNmzaIjIxU+5CE65JLLsFNN93kE7vUDK5evVolih06dMAdd9yBtm3beraRWsN33nlH/QAZMGAAkpKS8MMPP6gKF2G329Vju3btqv4vr+/0009XrW/3338/NmzYgC+//FKd26WC58cff1TncXkuSZ5lnzpp7ZP4pKylNS85OVntwztmqfiRJHvz5s0q8Zb7L7roIqxbt07lAkIS8LvuugvffPONKtezzz4bTz/9tDrujELKc/v27WjRooVqsfQmOYqUc1XmKkFNt4uKirBmzRpMmjTJs04+IPLmy8Hkj6yXA8ab1AiW1WehsLBQ3XTy4RKSQBk1iZK45ATqfaOqwTKtHixXlmlFjhWdU3NiS94Wn/tlne7SepfiwroXVqpwrcfosaQne+UlJ10594waNapUsif0ZE8qLO68805V0/biiy+qWq3HH38c9957r1rW7dmzRyVFM2bMUAmXnANff/11lcRIcrhr1y60atVKJWxCkh45L0hFgCRIUmnx+++/qwRQEpizzjqrzNilcuTqq6/Ga6+9phKvKVOmqMRMKluEVKxI87QkfbVq1cLixYtVHO+//756HqnBfPnll3H33Xerx33++eeqZa5hw4Z+n8/73Cr7luRXmsDlNezevRvnnnsuHnnkEfWcb7zxhmoSl8StadOmnn089dRTmDp1qioXSbCl3P/3v/+hXbt26hwujznvvPMwf/587Ny5UyWo3s8t/RjPOOMM3HDDDaqM8/PzVSyXX355lTe/B0IvJ3/5SHXkJxHBbqaUD4T8UvEmy3IA+CO/nvxtL+v9kQ+HHOAlya+L4zUnBDPrl5o9+WKsU6eOWmfU5DTUsExZrqHCrMeqvCb57pXaJrvFXup+qSGyR9g9/69Kx3u+suitLK1btz5mTJIUbtu2TdXQ1a9fX62T5EZq1aSbktRGSaWGJIayXmqehHRPkpo72bckRlIjJ0mjnAe8jR071qcmbNOmTVi5cqVKfoTsW44bPUb5v9TUSQInJImUWjOpaDnllFNUjdgff/yh9iHPKaRW7Ouvv1YJqdQgLliwQHWbkv8LqTGU2kupSNGfR/8rr0u/6TWOZ555pidmqbGSfvc6OTdLZY3UPo4ZM8azXpLCW265xROPdPWSGOW5JcmT1yW1o1IrJv35JcmW5Fh/7meffVbV9EkZ615++WVVZpJbeNdeBpMer3TbkFyoZI5S1UzfoC6/ELxrBOXXgVQrywdN/7AZjbz58gWj/xJmk27VYZlWD5Yry7S8JLGQk5vT6YTDWbqvmTQNOrTq6YNW2eeTWPW/x+ofJ82QUgEhzbf6dlJzJTWAcp/UUMkJXhI5KQd9m5SUFNVMqy+X1Ydv0aJF+Pjjj1UFhyRccr8kL/p28hh5rPd+JMnz3o/EJpUtsk6SPTnf9O/f3+d5ZN9SyyjbSJPjxRdf7LMPSVwlQfVeJ/+XhFO/Cemupf9fSHOzJIHS1CvnNSlPqX2Tmj/v7bp06eKzLMmzdHWSdX/99Ze6X++vKPTaSv25pSZTElapoSxp+/btKkk0Aj1eeS0lm3T1Y840CZ9URcsvvQMHDvisl2X911FJsr4i20u1sdxKMnJTqZSLvCa907YcCEaNNdSwTFmuocKsx6okBunp6aovXz7yAd8WXXQ6oROSo5Or5bll0EZlnk8qCeQ9kERImjXLIv3FJJEruY2c52Qfsl4SQkkAvbeR/nNSS6avk6ZVqQn13kaaUaXmSpqIJcGRfUhzpcxqoW8niaMkEN77keTSez+SBElNm6yTfnVyvzTbliTb6OdoPXadxCZN2/o6STTleaXW1vvcKs/vfexKbZ08l/QxlNpS2YfUHMox4b2dlKH3svzfu6uTvs77fv2v3CSxlGbf//u//yv1uhr813pmBCXj9nefaRI+eVN79uyp2tSlylg/cGTZu+ram3SAlfu9h6zLASTrzUI+OPKBkgNcqnWlJtIoB2ioY5myXEOFWY9VSWKlT5zq6I/StWU5rhxEuCp2aoqNiEV0hG8NiXeSJyN21b6dOaXuj7BHHLfpWJI06SsuzYjSX6xk65D0GZMESWq+pLZKauAkSRJSiyb3S62UPI8kUN7NrkLvXqSvk0oKef+9t/npp5/U4A4Z0OhdW+W9L73GyLtJ13u55DZSAyexSuIlzZ3+yMAKaQK+/vrrPeskydSfV6+N1JuTj+W7775TcwXKAAshiZmMfq4IqSV96623VPKtV+ZIE7O3Hj16qD6I8po4MthATbrS3DpixAj06tULvXv3Vm318iV33XXXqfuHDx+ORo0aqb54+kgpqX6WTp3nn3++6l8gVcsy8omIiELbkA+P/viviHv73Isr2xePVvV24QcXIqMwo0rmiz355JPVeUoGFEgCJ81uUuHwwgsv4M8//1QDDqWPmgySkHOZ3C/95+ScJee48pJERRI8SYaklkxq7qT/mgxy+OKLL9SozjfffFMlOvL/ypJ4pbJEKlyk5lCah/fu3av6IEpSJjHLOVeSNPm/vH7pQyd9B2UgRkXJa5BBIVL7JsnhAw88UOGpd6666io1ollG7cpADGl61kcl6wmn9AeUPnsyglkGm0j5bd26VeULr7zyimH775t+4mWZZkXerAcffFB1sly/fj2WLl3qGZghb6a09evkF44MBZcET6qTZQSPdPo08xx8REQUXJLgyHyvMt2IDBKQc46MjpUWJ0n49IRDBiDIwAsZVSoJlTxOmmMrQkbqSlLSsWNH1doj50EZlCB96eScKU260udPH4xRWRKv9KeTWKWSRRK+K664Qo181c/B8nySmEniJC1ycp+Mmq0MaYKWspHzuCR9UmsqtXEVIVOUSD9GyRUkZ5DkT/IHofeDkxHEUpsofUVlOhZJwm+//XZVC+vdNzDcBH0evpoWCvPwmb1JJ5hYpizXUGHWY7Wsucc6v148erMqa/j+t+B/x6zhM9Ol1YKhIk261UVqHSVhlfO6v2lzjKognObhIyIiIqoIadqWmlPp7vXbb7/hnnvuUXPshVKyFwxM+IiIKOikpq2yZNBGWT4c8qFn0Ia/2qikqKRKPy8Fhww0kWZc+Sujbi+77DI8+qjvVVWoNCZ8REQUdNXVrOo95YoRmh8pcNKfUG5UMeHbe5GIiIgoTDDhIyIiIjI5JnxEREREJseEj4iIiMjkmPARERERmRwTPiIiIiKTY8JHRERB48rJQd6aNeqmFRWVut+dl+e5X26uzEy/+8lbu9azjWPvXr/bFGzejPw1a333l5ODUCfz0cll3uSqLHJ1hopcs1eu+Rts8+bNq1DcVDmch4+IiIKm8K+/sPPqa9T/23z7DSJq1/a5v2j3bs/9ovGcFxB/2mml9rNz+AjA6VT/r33rWNQZM6bUNvsfmoKC337zWdds/luI7dmzXLHu3r0bkydPVtd7P3z4sJr0d8iQIWoS4NTU1HK+YmDHjh3qclrr1q1T14MN1NNPP62uOS/Xl5VLh4YauV7veeedF+wwTI8JHxERGYK7oADOw4dLJX1VLfakk2D97zJctnImSP/88w/69u2Ltm3b4p133lEJ26ZNm3DXXXfh888/x48//oiUlOBck3fbtm3o2bMn2rRpg1Akl0Sr6suiuVwuNbm2TLJNR7EkiIjIEP4dPQZFO3dW/xNZLGg04yk0eeF5RLVuXa6HjBkzBpGRkfjyyy/Rv39/NG3aFOeeey6WL1+OPXv24L777vPavQUffPCBz+OlyVKaLoUki6J79+5q29P81Fh6e+GFF9CqVSv1/O3atcObb77p0yz7/vvvq+vLyr6uvfZav/s4ePAgBg0apBIref758+eX2mbXrl248MILUatWLSQkJKjr0x44cMBz/0MPPaRqJOfOnatev2w3evRolVw9/vjjqF+/PurWrVvqMmczZsxA586dVZNzkyZN1GOOHDlSZpOu/jzyOuX1Sa3lFVdcgZxjNL/r+/joo4/QsWNHREVFqdfzyy+/qObu2rVrq/3Ie7d27Vqfx0q5vfLKK7jooosQGxurEmfZjzdZlvXR0dE4/fTT8frrr6vHZXp1Mfj2229x6qmnqjKW13nbbbchNzcXRsGEj4iIDNO8W1Jkkyaq2VW/xZbRBNrsjdc92yRddJHfbeo/NBlN3ngDtceMhrsCJ+L09HR88cUXKlEpWRMlSc7VV1+NhQsXqku3lcfPP/+s/kqyKE2xixcvLnPbJUuWYNy4cbjzzjuxceNG3Hzzzbjuuuvw1VdfqfsloTnnnHNUcib7mjVrlt/9SCIoTdLyuPfeew/PP/+8SgJ1csk5Sfbkta5evRrLli1TtZrS3FqyNlFqNKVZW2o6JfmTRPLff/9Vj/u///s/3H///fjpp588j5FatmeeeUbViEqitHLlyuNeGk2eR5LmTz75RN1k34899tgxH5OXl6eeX5I3eS5JPiVJHDFihErGpBZWkjZpPi6ZPE6ZMkWV4e+//67ul/dUykJs374dl156qWq+/+2339R74J3g6/HK+3DJJZeofcjxIM85duxYGIYWZrKysuQTqf4andvt1nJyctRfYpkaGY9Vlml55efna3/88Yf6KxyHDmkZ773nuclydR6nTqezwt+pP/74ozpvLFmyxO/9M2bMUPcfOHBALfvbNjExUXvttdfU/7dv3662Wbdu3XGfu1+/ftrIkSN91l122WXaeeed51m+8MILtREjRpS5jy1btqjn+/nnnz3r/vzzT7Xu6aefVstffvmlZrPZtF27dnm22bRpk8/jJk+erMXGxmrZ2dmebQYOHKg1b95clauuXbt22vTp08uM591339VSU1M9y1IuUj46f89z1113aX369Clzn7IPiXX9+vXasbhcLi0+Pl77+OOPPevkcffff79n+ciRI2rd559/rpbvuecerVOnTj77ue+++9Q2GRkZavmGG27QbrrpJp9tvvnmG81qtXqO9eN9FrxlZmZWea7CGj4iIgoa6a+XdMklnlt1998LRHlr8Crjm2++UU2k+k1vcv3zzz9x8skn+2wry7LeH3mc935kv7JtRESE6uena9++vU8zqmwjzZBy00nTqGzj/VzSxBofH+9ZrlevHjp06ODTV07WedceSk3mmWeeiUaNGqnHDhs2DGlpaapGriwln0cGyHjv0x9p8u7SpYvPOmmSHjlypKrZkyZdaaqW5mRp7vXm/Thpepbt9OfbsmULTjzxRJ/te/fu7bMs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GTx4MOLi4vDoo4+q9Y899hjq1auH+Ph43HDDDSgoKPB5XMkmXalNu+2223D33XcjJSUF9evXV83A3mbMmKGSV3keqbGU13nkyBF136pVq3DdddchKytLxSQ3/fGFhYWYMGECGjVqpB7bp08ftf2x3H777Zg4cSJOOumkCpY+EZkNEz4iMpz09HQsXbpU1eRJclOS3uTpdrtVsifbr169GsuWLcM///yDoUOHerZdsmQJxo0bhzvvvBMbN27EzTffrJKqr776ymefklhddNFF2LBhA66//nosWrRIrZs2bRp+/fVXNGjQAM8///xxY3/99ddVzD/99BMef/xxTJ06VcWls1qteOaZZ7Bp0ya17cqVK1WCKPr164eZM2eqxHXfvn3qJkmeGDt2LH744QcsWLAAv//+Oy677DJVc/f3338HUNJEFDY0IiKD+emnnzT5elq8ePExt/vyyy81m82m7dq1y7Nu06ZN6rE///yzWu7Xr582cuRIn8dddtll2nnnnedZlu1vv/12n2369u2rjR492mddnz59tK5du3qWR4wYoV144YWe5f79+2unnHKKz2NOPPFE7Z577inzNbz77rtaamqqZ/m1117TEhMTfbbZuXOnep179uzxWX/mmWdqkyZN0o7nq6++Uq8xIyPjuNsSkTmxho+IDOdoDnZ8f/75p2oWlZuuY8eOqgZQ7tO3kb6A3mRZv1/Xq1evUvuWZlNvffv2PW5MXbp08VmWmsGDBw96lpcvX44zzzxTNc1KU/GwYcOQlpam+tuVRWodXS6XataWpmv9JrWa27ZtO25MREQctEFEhtOmTRvVf606B2aU5K/puDJKDvaQ1yFNz/pAlAsuuACjRo1S/QSln9+3336r+gcWFRUhNjbW7z6lj5/NZsOaNWvUX2+S+BERHQ9r+IjIcCQRGjhwIGbPno3c3NxS9+vTi3To0AG7d+9WN90ff/yh7peaPn2b7777zufxsqzfXxZ5nPTD8+Y9WKQyJGGT5O+pp55SAymkxm7v3r0+28jAEqnN89a9e3e1TmoKW7du7XOTgSFERMfDhI+IDEmSPUlyevfujffff18NTpBmVhnwoDetDhgwQI14vfrqq7F27Vo1onf48OHo37+/p4n2rrvuUnPbyShc2YeMkl28eLFnMERZZKDH3Llz8dprr+Gvv/7C5MmT1UCLQEiCJlO+PPvss2pwiYwWnjNnjs82zZs3VzV6Mtfg4cOHVVOvJIbyGuW1Sezbt29Xr3X69On49NNPjzmP4fr167F161ZP07AsyyAXIgozwe5ESERUlr1792pjxozRmjVrpkVGRmqNGjXSBg8erAYheA9okHVxcXFafHy8GpCxf/9+n/08//zzWsuWLTW73a61bdtWe+ONN3zul6/CJUuWlHr+Rx99VKtdu7ZWq1YtNUDj7rvvPu6gjXHjxvnsQ+6X7XQzZszQGjRooMXExGgDBw5UsZQcUHHLLbeogRyyfvLkyWpdUVGR9uCDD2rNmzdXr0P2cdFFF2m///57meUnj5V9lLzJwBAiCi8W+SfYSScRERERVR826RIRERGZHBM+IiIiIpNjwkdERERkckz4iIiIiEyOCR8RERGRyTHhIyIiIjI5JnxEREREJseEj4iIiMjkmPARERERmRwTPiIiIiKTY8JHREREZHJM+IiIiIhgbv8Pz4xfblLu/N4AAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(figsize=(6.5, 6.5))\n", + "\n", + "outer_box = Rectangle(\n", + " (0, 0), 1, 1, fill=False, linewidth=3, color=\"black\", label=\"Domain $[0,1]^2$\"\n", + ")\n", + "valid_box = Rectangle(\n", + " (0.1, 0.2),\n", + " 0.7,\n", + " 0.7,\n", + " fill=False,\n", + " linewidth=3,\n", + " linestyle=\"--\",\n", + " color=\"tab:green\",\n", + " label=\"Contained range\",\n", + ")\n", + "invalid_box = Rectangle(\n", + " (0.1, 0.2),\n", + " 0.7,\n", + " 0.9,\n", + " fill=False,\n", + " linewidth=2.5,\n", + " linestyle=\":\",\n", + " color=\"tab:red\",\n", + " label=\"Out-of-domain range\",\n", + ")\n", + "\n", + "for box in (outer_box, valid_box, invalid_box):\n", + " ax.add_patch(box)\n", + "\n", + "ax.set(\n", + " xlim=(-0.1, 1.2),\n", + " ylim=(-0.1, 1.2),\n", + " xlabel=\"Coordinate 1\",\n", + " ylabel=\"Coordinate 2\",\n", + " title=\"Coordinate-wise range-in-domain compatibility\",\n", + ")\n", + "ax.set_aspect(\"equal\")\n", + "ax.legend(loc=\"lower right\")\n", + "ax.grid(alpha=0.15)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "9e3e56de", + "metadata": {}, + "source": [ + "### E. Integration with a compatible chained measure\n", + "\n", + "Here the inner sampler and chained outer target both represent $\\mathcal{U}[0.25,0.75]$, while the inner range is strictly contained in the outer unit domain. Because the mean $\\mathbb{E}[X]=0.5$ is symmetry-driven, the second moment provides a stronger end-to-end check using QMCPy's standard integration API." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "5a1ad5ba", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-24T19:24:47.000674Z", + "iopub.status.busy": "2026-08-24T19:24:47.000331Z", + "iopub.status.idle": "2026-08-24T19:24:47.014019Z", + "shell.execute_reply": "2026-08-24T19:24:47.012979Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Chained-measure integration estimate: 0.500000000\n", + "Exact Uniform mean: 0.500000000\n", + "Absolute error: 5.551e-17\n", + "Within requested tolerance: True\n", + "Chained-measure second-moment estimate: 0.270833333335\n", + "Exact second moment: 0.270833333333\n", + "Absolute error: 1.847e-12\n", + "Within requested tolerance: True\n" + ] + } + ], + "source": [ + "integration_inner = Uniform(\n", + " DigitalNetB2(1, seed=7),\n", + " lower_bound=0.25,\n", + " upper_bound=0.75,\n", + ")\n", + "integration_outer = Uniform(\n", + " integration_inner,\n", + " lower_bound=0.25,\n", + " upper_bound=0.75,\n", + ")\n", + "integrand = CustomFun(integration_outer, g=lambda x: x[..., 0])\n", + "\n", + "integration_tolerance = 1e-6\n", + "solution, data = CubQMCSobolG(\n", + " integrand,\n", + " abs_tol=integration_tolerance,\n", + ").integrate()\n", + "solution = float(np.asarray(solution))\n", + "exact_value = 0.5\n", + "absolute_error = abs(solution - exact_value)\n", + "\n", + "print(\"Chained-measure integration estimate:\", f\"{solution:.9f}\")\n", + "print(\"Exact Uniform mean:\", f\"{exact_value:.9f}\")\n", + "print(\"Absolute error:\", f\"{absolute_error:.3e}\")\n", + "print(\"Within requested tolerance:\", absolute_error <= integration_tolerance)\n", + "\n", + "second_moment_integrand = CustomFun(\n", + " integration_outer,\n", + " g=lambda x: x[..., 0] ** 2,\n", + ")\n", + "second_moment_solution, second_moment_data = CubQMCSobolG(\n", + " second_moment_integrand,\n", + " abs_tol=integration_tolerance,\n", + ").integrate()\n", + "second_moment_solution = float(np.asarray(second_moment_solution))\n", + "a, b = 0.25, 0.75\n", + "exact_second_moment = (a**2 + a * b + b**2) / 3\n", + "second_moment_error = abs(second_moment_solution - exact_second_moment)\n", + "\n", + "print(\n", + " \"Chained-measure second-moment estimate:\",\n", + " f\"{second_moment_solution:.12f}\",\n", + ")\n", + "print(\"Exact second moment:\", f\"{exact_second_moment:.12f}\")\n", + "print(\"Absolute error:\", f\"{second_moment_error:.3e}\")\n", + "print(\n", + " \"Within requested tolerance:\",\n", + " second_moment_error <= integration_tolerance,\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "02c17b09", + "metadata": {}, + "source": [ + "## 4. What this change solves\n", + "\n", + "The current PR solves only\n", + "\n", + "$$\n", + "R_{j-1}=D_j\n", + "\\quad\\longrightarrow\\quad\n", + "R_{j-1}\\subseteq D_j.\n", + "$$\n", + "\n", + "This determines whether the output support of one existing `TrueMeasure` transformation can feed the domain of the next. It does **not** by itself implement arbitrary measure transport, Gaussian-to-Logistic importance sampling, forward CDF maps, or general transport/Jacobian abstractions." + ] + }, + { + "cell_type": "markdown", + "id": "d560ec14", + "metadata": {}, + "source": [ + "## 5. QMC, Transport, and Importance Sampling\n", + "\n", + "### 5.1 QMC and the role of Uniform\n", + "\n", + "Sobol/DigitalNet points live in the unit cube, so direct QMC sampling begins with Uniform coordinates. Gaussian and Logistic samples are obtained separately from that reference space:\n", + "\n", + "$$\n", + "U\\xrightarrow{F_G^{-1}}X_G,\n", + "\\qquad\n", + "U\\xrightarrow{F_L^{-1}}X_L.\n", + "$$\n", + "\n", + "Uniform is the reference space from which QMC points originate. We therefore need to distinguish the direction of a mathematical transport from the direction in which the QMC algorithm is actually evaluated." + ] + }, + { + "cell_type": "markdown", + "id": "a76d04ee", + "metadata": {}, + "source": [ + "### 5.2 Why the deterministic Logistic detour cancels\n", + "\n", + "Let $F_G$ and $F_L$ be the Gaussian and Logistic CDFs. A deterministic Gaussian-to-Logistic transport is\n", + "\n", + "$$\n", + "T_{G\\to L}(x)=F_L^{-1}(F_G(x)).\n", + "$$\n", + "\n", + "If that Logistic value is immediately mapped to Uniform, then\n", + "\n", + "$$\n", + "F_L(T_{G\\to L}(x))\n", + "=F_L(F_L^{-1}(F_G(x)))\n", + "=F_G(x).\n", + "$$\n", + "\n", + "Equivalently,\n", + "\n", + "$$\n", + "F_L\\circ F_L^{-1}\\circ F_G=F_G,\n", + "\\qquad\n", + "\\boxed{G\\rightarrow L\\rightarrow U\\equiv G\\rightarrow U}.\n", + "$$\n", + "\n", + "If Logistic is inserted only as a deterministic transport and is immediately mapped back to Uniform, it adds no new transformation: the Logistic inverse CDF and CDF cancel." + ] + }, + { + "cell_type": "markdown", + "id": "4c444800", + "metadata": {}, + "source": [ + "### 5.3 Logistic as an importance-sampling proposal\n", + "\n", + "Logistic becomes useful here when it is introduced as an alternative sampling measure rather than as an intermediate deterministic transport. Let $p_G$ be the Gaussian target density and $p_L$ the Logistic proposal density:\n", + "\n", + "$$\n", + "I=\\int_{\\mathbb R}g(x)p_G(x)\\,dx\n", + "=\\int_{\\mathbb R}g(x)\\frac{p_G(x)}{p_L(x)}p_L(x)\\,dx.\n", + "$$\n", + "\n", + "This is a **change of measure through a likelihood ratio**, not a Gaussian-CDF-to-Logistic-inverse-CDF point transport. With $x=F_L^{-1}(u)$ and $du=p_L(x)\\,dx$,\n", + "\n", + "$$\n", + "\\boxed{\n", + "I=\\int_0^1\n", + "g(F_L^{-1}(u))\n", + "\\frac{p_G(F_L^{-1}(u))}{p_L(F_L^{-1}(u))}\n", + "\\,du\n", + "}.\n", + "$$\n", + "\n", + "The runtime QMC path is therefore\n", + "\n", + "$$\n", + "\\boxed{\n", + "U_{\\mathrm{Sobol}}\n", + "\\xrightarrow{F_L^{-1}}\n", + "X_L\n", + "\\xrightarrow{\\times\\,p_G(X_L)/p_L(X_L)}\n", + "\\text{weighted integrand}\n", + "}.\n", + "$$\n", + "\n", + "There is no Gaussian-to-Uniform transformation in this runtime path; Sobol points already supply Uniform inputs. Logistic matters because it changes the sampling measure and hence the function presented to those points.\n", + "\n", + "Direct Gaussian QMC uses\n", + "\n", + "$$\n", + "h_G(v)=g(F_G^{-1}(v)),\n", + "\\qquad\n", + "I=\\int_0^1h_G(v)\\,dv,\n", + "$$\n", + "\n", + "whereas Logistic importance-sampling QMC uses\n", + "\n", + "$$\n", + "h_L(u)=g(F_L^{-1}(u))\n", + "\\frac{p_G(F_L^{-1}(u))}{p_L(F_L^{-1}(u))},\n", + "\\qquad\n", + "I=\\int_0^1h_L(u)\\,du.\n", + "$$\n", + "\n", + "Thus\n", + "\n", + "$$\n", + "\\int_0^1h_G(v)\\,dv=\\int_0^1h_L(u)\\,du,\n", + "\\qquad\n", + "h_G\\neq h_L\\ \\text{in general}.\n", + "$$\n", + "\n", + "Both formulations estimate the same Gaussian integral but present different functions to the Sobol points. A proposal can therefore improve or worsen QMC behavior; Logistic is not universally better." + ] + }, + { + "cell_type": "markdown", + "id": "6b1acc04", + "metadata": {}, + "source": [ + "### 5.4 Connection: the likelihood ratio is a transport Jacobian\n", + "\n", + "Define the Logistic- and Gaussian-based Uniform coordinates\n", + "\n", + "$$\n", + "u=F_L(x),\n", + "\\qquad\n", + "v=F_G(x).\n", + "$$\n", + "\n", + "Since $x=F_L^{-1}(u)$, the map between them is\n", + "\n", + "$$\n", + "T(u)=F_G(F_L^{-1}(u)).\n", + "$$\n", + "\n", + "Differentiating gives\n", + "\n", + "$$\n", + "\\frac{dT}{du}=p_G(x)\\frac{dx}{du}.\n", + "$$\n", + "\n", + "Because $du/dx=p_L(x)$,\n", + "\n", + "$$\n", + "\\frac{dx}{du}=\\frac{1}{p_L(x)},\n", + "$$\n", + "\n", + "and therefore\n", + "\n", + "$$\n", + "\\boxed{\n", + "T'(u)=\n", + "\\frac{p_G(F_L^{-1}(u))}{p_L(F_L^{-1}(u))}\n", + "}.\n", + "$$\n", + "\n", + "The Gaussian/Logistic importance-sampling likelihood ratio is exactly the Jacobian of the map between their two Uniform parameterizations in one dimension. Deterministic transport and importance sampling are distinct constructions, but this Jacobian explains their mathematical connection.\n", + "\n", + "The numerical check below stays away from $0$ and $1$, compares a stable finite-difference derivative with the density ratio, and then uses one deterministic DigitalNet point set for a compact same-target integral check." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "f6da6902", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-24T19:24:47.018298Z", + "iopub.status.busy": "2026-08-24T19:24:47.017888Z", + "iopub.status.idle": "2026-08-24T19:24:47.195600Z", + "shell.execute_reply": "2026-08-24T19:24:47.194506Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Maximum interior absolute error: 8.440e-05\n", + "Mean interior absolute error: 1.535e-05\n", + "All verification values finite: True\n" + ] + }, + { + "data": { + "image/png": "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J8vr7w8NGzZM5rB9+EYny+jvY8eOYcGCBbh48WIS1ZKM2d8iIDtw4ADatWsnA7O7d++iT58+8kO32GCELKu/27ZtK+9XoUIFkVGAyMhI9OrVCz/99FMS1ZqSSnyxWkBAAEJCQuQcAkPiCDmRAf31119yot/GjRvlBCKyLIGBgfj222/lRF4PDw9jV4eSgEajkd+GzJ07F8WLF0erVq3w888/Y/bs2Wx/CyQm+YlvQGbOnInz589jw4YN2L59O0aPHm3sqpGF4Qi5nsQfXRsbG/j4+MQ6Lsqenp5x3kcc1+f2ZN79rTVhwgQZkO/btw+FChUycE3JGP197949PHz4UM7kjxmwCba2trh16xayZ8/OzrGg97dYWcXOzk7eTytv3rxydE2kRNjb2xu83pR0/f3LL7/ID93dunWTZbFKWlBQEHr06CE/iImUF7IMnvHEai4uLgYfHRf4StKT+GUrRkX2798f6w+wKIu8wriI4zFvL+zduzfe25N597fw999/yxGUXbt2oUSJEklUW0rq/hZLmV65ckWmq2gvjRo1QtWqVeV1sUQaWdb7u3z58jJNRfvBS7h9+7YM1BmMW15/izlAHwbd2g9j0XMFyVKUNXasliRTRy1w2SSxDNLixYvl0jg9evSQyya9ePFC/vzbb79Vfvzxx1jLHtra2ioTJkyQy+CNHDmSyx5acH//9ddfclmtdevWKc+fP9ddAgMDjfgsyFD9/SGusmLZ/e3t7S1XTerXr59y69YtZdu2bUqaNGmUP/74w4jPggzV3+LvtejvlStXymXx9uzZo2TPnl2unkamLTAwUC4/LC4i3J00aZK8/ujRI/lz0c+ivz9c9nDo0KEyVhPLF3PZQzMg1qfMlCmTDLzEMkr//fef7meVK1eWf5RjWrNmjZIrVy55e7Gszvbt241Qa0qK/s6cObN88394Eb/YyTLf3zExILf8/j5x4oRculYEdmIJxD///FMufUmW198RERHKb7/9JoNwR0dHxcvLS+nTp4/i7+9vpNpTQh08eDDOv8Xa/hX/i/7+8D5FihSRrw3x3l60aJGSVFTin6QZiyciIiIiog8xh5yIiIiIyIgYkBMRERERGREDciIiIiIiI2JATkRERERkRAzIiYiIiIiMiAE5EREREZERMSAnIiIiIjIiBuREREREREbEgJyIiIiIyIgYkBMRERER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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "u = np.linspace(0.01, 0.99, 500)\n", + "x_logistic = logistic.ppf(u)\n", + "transport = norm.cdf(x_logistic)\n", + "numerical_derivative = np.gradient(transport, u, edge_order=2)\n", + "density_ratio = norm.pdf(x_logistic) / logistic.pdf(x_logistic)\n", + "\n", + "interior = slice(2, -2)\n", + "absolute_error = np.abs(numerical_derivative - density_ratio)\n", + "\n", + "print(\n", + " \"Maximum interior absolute error:\",\n", + " f\"{absolute_error[interior].max():.3e}\",\n", + ")\n", + "print(\n", + " \"Mean interior absolute error:\",\n", + " f\"{absolute_error[interior].mean():.3e}\",\n", + ")\n", + "print(\n", + " \"All verification values finite:\",\n", + " np.isfinite(numerical_derivative).all()\n", + " and np.isfinite(density_ratio).all(),\n", + ")\n", + "\n", + "fig, ax = plt.subplots(figsize=(7.5, 4.8))\n", + "ax.plot(u, numerical_derivative, linewidth=2.5, label=r\"Numerical $T'(u)$\")\n", + "ax.plot(\n", + " u,\n", + " density_ratio,\n", + " linestyle=\"--\",\n", + " linewidth=2,\n", + " label=r\"$p_G(F_L^{-1}(u))/p_L(F_L^{-1}(u))$\",\n", + ")\n", + "ax.set(\n", + " xlabel=\"Logistic-based Uniform coordinate $u$\",\n", + " ylabel=\"Derivative / density ratio\",\n", + " title=\"Likelihood ratio as a transport Jacobian\",\n", + ")\n", + "ax.grid(alpha=0.25)\n", + "ax.legend()\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "b6cd52e8", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-24T19:24:47.198770Z", + "iopub.status.busy": "2026-08-24T19:24:47.198263Z", + "iopub.status.idle": "2026-08-24T19:24:47.216129Z", + "shell.execute_reply": "2026-08-24T19:24:47.214482Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Target E[X^2]: 1.0\n", + "Direct Gaussian-QMC estimate: 0.999295953\n", + "Logistic IS-QMC estimate: 1.000000026\n", + "All integral-check values finite: True\n" + ] + } + ], + "source": [ + "qmc_u = DigitalNetB2(1, seed=7).gen_samples(2**12).reshape(-1)\n", + "\n", + "gaussian_samples = norm.ppf(qmc_u)\n", + "direct_gaussian_qmc = np.mean(gaussian_samples**2)\n", + "\n", + "logistic_samples = logistic.ppf(qmc_u)\n", + "logistic_weights = norm.pdf(logistic_samples) / logistic.pdf(logistic_samples)\n", + "logistic_is_qmc = np.mean(logistic_samples**2 * logistic_weights)\n", + "\n", + "print(\"Target E[X^2]:\", 1.0)\n", + "print(\"Direct Gaussian-QMC estimate:\", f\"{direct_gaussian_qmc:.9f}\")\n", + "print(\"Logistic IS-QMC estimate:\", f\"{logistic_is_qmc:.9f}\")\n", + "print(\n", + " \"All integral-check values finite:\",\n", + " np.isfinite(gaussian_samples).all()\n", + " and np.isfinite(logistic_samples).all()\n", + " and np.isfinite(logistic_weights).all(),\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "2938bb1c", + "metadata": {}, + "source": [ + "## 6. Takeaways and next step\n", + "\n", + "1. **Current PR:** chained `TrueMeasure` domain compatibility changes from exact equality to containment:\n", + "\n", + " $$\n", + " R_{j-1}=D_j\n", + " \\quad\\longrightarrow\\quad\n", + " R_{j-1}\\subseteq D_j.\n", + " $$\n", + "\n", + "2. **Safety remains:** strict containment is accepted, while ranges that actually leave the next domain remain rejected.\n", + "\n", + "3. **QMC direction:** Sobol points already begin in Uniform space; direct Gaussian and Logistic sampling are $U\\rightarrow X_G$ and $U\\rightarrow X_L$.\n", + "\n", + "4. **Pure deterministic detour:** Gaussian $\\rightarrow$ Logistic $\\rightarrow$ Uniform collapses to Gaussian $\\rightarrow$ Uniform, so inserting Logistic only as a CDF/inverse-CDF transport adds nothing by itself.\n", + "\n", + "5. **Importance sampling is the meaningful alternative:** Logistic changes the sampling measure through $p_G/p_L$, and in one dimension that likelihood ratio is the Jacobian\n", + "\n", + " $$\n", + " \\frac{d}{du}F_G(F_L^{-1}(u)).\n", + " $$\n", + "\n", + "**Next question.** The current domain-inclusion PR should remain scoped as implemented. A separate follow-up can examine how QMCPy's existing importance-sampling machinery represents this Gaussian/Logistic relationship and whether any additional transport/Jacobian semantics are actually needed." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "qmcpy kernel", + "language": "python", + "name": "qmcpy" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/api/discrete_distributions.md b/docs/api/discrete_distributions.md index daa782cb6..49b60fbb4 100644 --- a/docs/api/discrete_distributions.md +++ b/docs/api/discrete_distributions.md @@ -70,10 +70,7 @@ python -m pip install "qmcpy[mpmc]" qmcpy-install-mpmc ``` -The second command selects the `pyg_lib` wheel page matching the installed -PyTorch and accelerator builds. For GPU support or platform-specific wheels, -see the [PyTorch installation guide](https://pytorch.org/get-started/locally/) -and the [PyTorch Geometric installation guide](https://pytorch-geometric.readthedocs.io/en/latest/install/installation.html). +The second command selects the `pyg_lib` wheel page matching the installed PyTorch and accelerator builds. For GPU support or platform-specific wheels, see the [PyTorch installation guide](https://pytorch.org/get-started/locally/) and the [PyTorch Geometric installation guide](https://pytorch-geometric.readthedocs.io/en/latest/install/installation.html). ::: qmcpy.discrete_distribution.mpmc.mpmc.MPMC diff --git a/docs/mpmc-compatibility.md b/docs/mpmc-compatibility.md index 92d6f1526..4e9bbf424 100644 --- a/docs/mpmc-compatibility.md +++ b/docs/mpmc-compatibility.md @@ -36,17 +36,14 @@ This gives one place to enforce modern MPMC compatibility without forcing the en ## Local Developer Commands -Install the usual test and MPMC extras first, then add the platform-specific -PyG runtime with QMCPy's installed helper command: +Install the usual test and MPMC extras first, then add the platform-specific PyG runtime with QMCPy's installed helper command: ```bash python -m pip install -e ".[test,test_torch,test_gpytorch,test_botorch,mpmc]" qmcpy-install-mpmc ``` -The `mpmc` extra contains dependencies available from PyPI. The helper handles -`pyg_lib` separately because its wheel page depends on the installed PyTorch -version and accelerator build, which standard project metadata cannot select. +The `mpmc` extra contains dependencies available from PyPI. The helper handles `pyg_lib` separately because its wheel page depends on the installed PyTorch version and accelerator build, which standard project metadata cannot select. Then run the MPMC-specific checks: diff --git a/mkdocs.yml b/mkdocs.yml index 792731c47..35edf3f00 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -75,6 +75,7 @@ nav: - Importance Sampling with True Measures: - Statistics for True Measures: demos/statistics_for_TrueMeasure.ipynb - Some True Measures: demos/some_true_measures.ipynb + - TrueMeasure Domain Inclusion: demos/true_measure_domain_inclusion.ipynb - SciPyWrapper dependence and Custom distributions: demos/scipywrapper_dependence_custom/scipywrapper_demo.ipynb - ProductMeasure: demos/product_measure.ipynb - Acceptance-Rejection Sampling: demos/acceptance_rejection.ipynb diff --git a/qmcpy/true_measure/abstract_true_measure.py b/qmcpy/true_measure/abstract_true_measure.py index b7611b1f3..929da50bc 100644 --- a/qmcpy/true_measure/abstract_true_measure.py +++ b/qmcpy/true_measure/abstract_true_measure.py @@ -30,6 +30,52 @@ def _read_only_array(value): array.setflags(write=False) return array + @staticmethod + def _range_in_domain(transform_range, domain): + """Return whether a transform range is contained within a domain.""" + try: + transform_range = np.asarray(transform_range) + domain = np.asarray(domain) + except (TypeError, ValueError): + return False + + if ( + transform_range.ndim != 2 + or domain.ndim != 2 + or transform_range.shape[1] != 2 + or domain.shape[1] != 2 + or transform_range.shape[0] == 0 + or domain.shape[0] == 0 + ): + return False + + if not ( + np.issubdtype(transform_range.dtype, np.number) + and np.issubdtype(domain.dtype, np.number) + and np.isrealobj(transform_range) + and np.isrealobj(domain) + and transform_range.dtype != np.bool_ + and domain.dtype != np.bool_ + ): + return False + + if np.isnan(transform_range).any() or np.isnan(domain).any(): + return False + + if np.any(transform_range[:, 0] > transform_range[:, 1]) or np.any( + domain[:, 0] > domain[:, 1] + ): + return False + + try: + transform_range, domain = np.broadcast_arrays(transform_range, domain) + except ValueError: + return False + + lower_bounds_valid = np.all(domain[:, 0] <= transform_range[:, 0]) + upper_bounds_valid = np.all(transform_range[:, 1] <= domain[:, 1]) + return bool(lower_bounds_valid and upper_bounds_valid) + def _set_moments(self, mean, variance, standard_deviation, covariance): self._mean = self._read_only_array(mean) self._variance = self._read_only_array(variance) @@ -100,11 +146,11 @@ def _parse_sampler(self, sampler): sampler.d ) # take the dimension from the sub-sampler (composed transform) self.discrete_distrib = self.transform.discrete_distrib - if (self.domain != self.transform.range).any(): + if not self._range_in_domain(self.transform.range, self.domain): self.sub_compatibility_error = True if self.transform.sub_compatibility_error: raise ParameterError( - "The sub-transform domain must match the sub-sub-transform range." + "The sub-sub-transform range must be contained within the sub-transform domain." ) else: raise ParameterError( @@ -147,7 +193,7 @@ def _jacobian_transform_r(self, x, return_weights): jac = None if self.sub_compatibility_error: raise ParameterError( - "The transform domain must match the sub-transform range." + "The sub-transform range must be contained within the transform domain." ) if self.transform == self: # is \Psi_0 if return_weights: diff --git a/test/booktests/tb_true_measure_domain_inclusion.py b/test/booktests/tb_true_measure_domain_inclusion.py new file mode 100644 index 000000000..b34abcb60 --- /dev/null +++ b/test/booktests/tb_true_measure_domain_inclusion.py @@ -0,0 +1,18 @@ +import unittest +from testbook import testbook +from __init__ import TB_TIMEOUT, BaseNotebookTest + + +class NotebookTests(BaseNotebookTest): + + @testbook( + "../../demos/true_measure_domain_inclusion.ipynb", + execute=True, + timeout=TB_TIMEOUT, + ) + def test_true_measure_domain_inclusion_notebook(self, tb): + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/test/test_true_measures.py b/test/test_true_measures.py index ae58d9604..3099128e8 100644 --- a/test/test_true_measures.py +++ b/test/test_true_measures.py @@ -1,4 +1,5 @@ from qmcpy import ( + AbstractTrueMeasure, BernoulliCont, BrownianMotion, DigitalNetB2, @@ -10,6 +11,7 @@ Lattice, Lebesgue, MaternGP, + SciPyWrapper, Uniform, ZeroInflatedExpUniform, ) @@ -20,7 +22,6 @@ import unittest import warnings from qmcpy.true_measure.uniform_triangle import UniformTriangle, _UniformTriangleAdapter -from qmcpy import SciPyWrapper def dense_covariance(covariance): @@ -42,6 +43,138 @@ def assert_sample_mean_and_covariance(measure): class TestTrueMeasure(unittest.TestCase): """General tests for TrueMeasures""" + def test_range_in_domain(self): + cases = [ + ("exact equality", [[0, 1]], [[0, 1]], True), + ("strict finite inclusion", [[0.25, 0.75]], [[0, 1]], True), + ("infinite domain", [[-5, 5]], [[-np.inf, np.inf]], True), + ("positive half-line", [[1, 3]], [[0, np.inf]], True), + ("lower-bound failure", [[-0.1, 0.75]], [[0, 1]], False), + ("upper-bound failure", [[0.25, 1.1]], [[0, 1]], False), + ( + "multidimensional box", + [[0.1, 0.8], [0.2, 0.9]], + [[0, 1], [0, 1]], + True, + ), + ( + "failure in one coordinate", + [[0.1, 0.8], [0.2, 1.1]], + [[0, 1], [0, 1]], + False, + ), + ( + "broadcast domain", + [[0.1, 0.8], [0.2, 0.9]], + [[0, 1]], + True, + ), + ( + "non-broadcastable rows", + [[0.1, 0.8], [0.2, 0.9]], + [[0, 1], [0, 1], [0, 1]], + False, + ), + ] + + for name, transform_range, domain, expected in cases: + with self.subTest(name=name): + self.assertIs( + AbstractTrueMeasure._range_in_domain(transform_range, domain), + expected, + ) + + def test_range_in_domain_rejects_invalid_bounds(self): + invalid_cases = [ + ("one-dimensional range", [0, 1], [[0, 1]]), + ("three-column range", [[0, 0.5, 1]], [[0, 1]]), + ("ragged range", [[0, 1], [0, 0.5, 1]], [[0, 1]]), + ("one-dimensional domain", [[0, 1]], [0, 1]), + ("three-column domain", [[0, 1]], [[0, 0.5, 1]]), + ( + "reversed transform range", + np.array([[0.8, 0.2]]), + np.array([[0.0, 1.0]]), + ), + ("reversed domain", [[0, 1]], [[0.8, 0.2]]), + ( + "reversed multidimensional transform range", + [[0.1, 0.8], [0.9, 0.2]], + [[0, 1], [0, 1]], + ), + ( + "reversed multidimensional domain", + [[0.1, 0.8], [0.2, 0.9]], + [[0, 1], [0.9, 0.2]], + ), + ("empty transform range", np.empty((0, 2)), [[0, 1]]), + ("empty domain", [[0, 1]], np.empty((0, 2))), + ( + "string bounds", + np.array([["a", "z"]]), + np.array([["a", "z"]]), + ), + ( + "object bounds", + np.array([[0, 1]], dtype=object), + np.array([[0, 1]], dtype=object), + ), + ("complex bounds", [[0 + 0j, 1 + 0j]], [[0 + 0j, 1 + 0j]]), + ("boolean bounds", [[False, True]], [[False, True]]), + ("NaN transform range", [[np.nan, 1]], [[0, 1]]), + ("NaN domain", [[0, 1]], [[np.nan, 1]]), + ] + + for name, transform_range, domain in invalid_cases: + with self.subTest(name=name): + self.assertIs( + AbstractTrueMeasure._range_in_domain(transform_range, domain), + False, + ) + + def test_strict_range_in_domain_chain(self): + inner = Uniform( + DigitalNetB2(1, seed=7), lower_bound=0.25, upper_bound=0.75 + ) + outer = Kumaraswamy(inner) + + self.assertFalse(outer.sub_compatibility_error) + samples = outer.gen_samples(8) + self.assertEqual(samples.shape, (8, 1)) + self.assertTrue(np.isfinite(samples).all()) + + def test_multidimensional_range_in_domain_chain_broadcasts(self): + inner = Uniform( + DigitalNetB2(2, seed=7), + lower_bound=[0.1, 0.2], + upper_bound=[0.8, 0.9], + ) + outer = Kumaraswamy(inner) + + self.assertFalse(outer.sub_compatibility_error) + samples = outer.gen_samples(8) + self.assertEqual(samples.shape, (8, 2)) + self.assertTrue(np.isfinite(samples).all()) + + def test_out_of_domain_chain_preserves_deferred_errors(self): + inner = Uniform( + DigitalNetB2(1, seed=7), lower_bound=-0.1, upper_bound=0.75 + ) + incompatible = Kumaraswamy(inner) + + self.assertTrue(incompatible.sub_compatibility_error) + with self.assertRaisesRegex( + ParameterError, + "The sub-transform range must be contained within the transform domain.", + ): + incompatible.gen_samples(8) + + with self.assertRaisesRegex( + ParameterError, + "The sub-sub-transform range must be contained within the sub-transform domain.", + ): + Kumaraswamy(incompatible) + def test_abstract_methods(self): d = 2 tms = [