{ "cells": [ { "cell_type": "markdown", "id": "dd823b9a-b48f-41a0-8293-dd03ba377083", "metadata": {}, "source": [ "(interval_dependency)=\n", "# Interval dependency" ] }, { "cell_type": "code", "execution_count": 1, "id": "f7b4527c-e255-4f6e-8899-3f1678416ea3", "metadata": {}, "outputs": [], "source": [ "# remove this after finished\n", "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "code", "execution_count": 2, "id": "ea674bf5-d827-474d-874c-bec75cd388eb", "metadata": {}, "outputs": [], "source": [ "%load_ext rich\n", "from pyuncertainnumber import pba" ] }, { "cell_type": "markdown", "id": "9a981090-75d9-402a-afc1-aed6849c49cf", "metadata": {}, "source": [ "**Interval dependency** is a known caveat of [interval arithmetic](https://en.wikipedia.org/wiki/Interval_arithmetic). Despite the many appealing features of interval analysis, the presence of the dependency issue requires analysts to be cautious with their calculations since it may lead to unexpected inflation of uncertainty in the response. We will be demonstrating the *dependency issue* in this notebook." ] }, { "cell_type": "markdown", "id": "58739106-bde4-4730-ab96-b8ca1b005bdf", "metadata": { "jp-MarkdownHeadingCollapsed": true }, "source": [ "## Interval dependency\n", "\n", "It should be noted that $X^2$ is not the same as $X \\cdot X$ under interval arithmetic, though they are identical under ordinary arithmetic. We can have a quick check on the results of these two functions respectively" ] }, { "cell_type": "code", "execution_count": 3, "id": "96defea7-49a1-427e-8749-f940370f8e77", "metadata": {}, "outputs": [], "source": [ "X = pba.I(-1,1)" ] }, { "cell_type": "code", "execution_count": 4, "id": "b1f7269e-d625-4496-bdf3-17bdcd046a3c", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "\u001b[1m[\u001b[0m\u001b[1;36m0.0\u001b[0m,\u001b[1;36m1.0\u001b[0m\u001b[1m]\u001b[0m"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X**2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "85198d63-c681-49fa-8063-a22b17e20f24",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "
\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "\u001b[1m[\u001b[0m\u001b[1;36m-1.0\u001b[0m,\u001b[1;36m1.0\u001b[0m\u001b[1m]\u001b[0m"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X * X"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "83977273-f0ef-4004-9d64-8f9f8283dffc",
   "metadata": {},
   "source": [
    "```{note}\n",
    "Apparently $X \\cdot X$ leads to an overestimation, as explained in Moore et al. (2009) as \"Namely, if we assume x is an unknown number known to lie in the interval $X$, then, when we form the product $ x \\cdot x$, the $x$ in the second factor, although known only to lie in $X$ must be the same as the $x$ in the first factor, whereas, in the definition of the interval product $X \\cdot X$, it is assumed that the values in the first factor and the values in the second factor vary independently\"\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9213286c-ae5f-483f-ae04-42df460304c9",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true
   },
   "source": [
    "## Repeated variable problem\n",
    "\n",
    "Generally, analysts shall be very careful when the response function involves repeated variables, since interval arithmeic will likely to yield inflated results. Below shows another example function $x(1-x)$.\n",
    "\n",
    "\n",
    "
\n", " \n", "
\n", "\n", "Mathematically, under ordinary arithmetic, we can write in a few equivalent manners:\n", "\n", "```{math}\n", "\\begin{align}\n", "f(x) &= x(1-x) \\newline\n", "g(x) &= x - x^2 \\newline\n", "h(x) &= \\frac{1}{4} - (x - \\frac{1}{2})^2\n", "\\end{align}\n", "```\n", "\n", "However, as demonstrated below, the interval-valued extensions of these functions will give different results:\n", "" ] }, { "cell_type": "code", "execution_count": 6, "id": "15a7f0a6-fa86-4191-b8e9-cf76de9a4ca5", "metadata": {}, "outputs": [], "source": [ "X = pba.I(0,1)\n", "def f(x): return x * (1 - x)\n", "def g(x): return x - x**2\n", "def h(x): return 1/4 - (x - 1/2)**2" ] }, { "cell_type": "code", "execution_count": 7, "id": "5d3ad1f6-f5ad-4002-a6b6-76df58adb941", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "\u001b[1m[\u001b[0m\u001b[1;36m0.0\u001b[0m,\u001b[1;36m1.0\u001b[0m\u001b[1m]\u001b[0m"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "f(X)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "7885f7c3-8ac8-4e12-b715-02e51f23a870",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "
\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "\u001b[1m[\u001b[0m\u001b[1;36m-1.0\u001b[0m,\u001b[1;36m1.0\u001b[0m\u001b[1m]\u001b[0m"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "g(X)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "119aeca9-2b11-4063-90e1-58610b2b7584",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "
\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "\u001b[1m[\u001b[0m\u001b[1;36m0.0\u001b[0m,\u001b[1;36m0.25\u001b[0m\u001b[1m]\u001b[0m"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "h(X)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "35959780-bc1f-45e1-8de0-bd3e9548a6e0",
   "metadata": {},
   "source": [
    "It turns out that the united extension can be yielded from $h(x) = \\frac{1}{4} - (x - \\frac{1}{2})^2$. One can easily tell the correct result from the figure above."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6a19462f-1d86-4029-aad5-f881c38586ba",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true
   },
   "source": [
    "## Common strategies against repeated variable problem\n",
    "\n",
    "Commonly, one can try rewriting the considered function, if known, to remove the dependency as shown above, or to resort to other interval approaches, such as *subinterval* or *optimisation-based* approach."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e591d86-bfbc-42b6-9ff9-fc19f1948db7",
   "metadata": {},
   "source": [
    "```{tip}\n",
    "`pyuncertainnumber` provides a bespoke function [b2b](https://pyuncertainnumber.readthedocs.io/en/latest/autoapi/pyuncertainnumber/index.html#pyuncertainnumber.b2b) for a range of interval propagation strategies. \n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "a7516de0-c266-45ab-9b82-1c4915168331",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pyuncertainnumber as pun"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5500bd2d-e019-4730-9687-aded7066f0bf",
   "metadata": {},
   "outputs": [],
   "source": [
    "y_sub = pun.b2b(vars=X, \n",
    "        func=f,\n",
    "        interval_strategy=\"subinterval\",\n",
    "        subinterval_style=\"direct\",\n",
    "        n_sub=5000\n",
    "       )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "1921688a-162a-4d3c-8e30-d17b7beefbcd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "
\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "\u001b[1m[\u001b[0m\u001b[1;36m0.0\u001b[0m,\u001b[1;36m0.2501\u001b[0m\u001b[1m]\u001b[0m"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_sub"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "e3c9ca0b-c414-423e-925b-3ece9be7d1db",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%capture\n",
    "y_opt = pun.b2b(vars=X, \n",
    "        func=f,\n",
    "        interval_strategy=\"bo\",\n",
    "       )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "05fb5932-b8ae-41ae-a96c-3fbabbd01df1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "
\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "\u001b[1m[\u001b[0m\u001b[1;36m0.0\u001b[0m,\u001b[1;36m0.2499999760755748\u001b[0m\u001b[1m]\u001b[0m"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_opt"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9286d4d8-a4ca-4c49-b6e0-4ed7d4f4bd2b",
   "metadata": {},
   "source": [
    "```{note}\n",
    "As shown, for *subinterval* stategy it requires 5,000 subintervals to reasonably approximate the true result, while the *optimisation* strategy approximates well with less evaluations\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pyun_dev311",
   "language": "python",
   "name": "python3"
  },
  "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.11.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}