{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": []
   },
   "source": [
    "# Transforming Continuous Values to Discrete Events\n",
    "\n",
    "The role of the trigger function in the conviction voting algorithm is to determine if a sufficient amount of conviction has accumulated in support of a particular proposal. In the 1hive use case for conviction, proposals map to precise quantities of resources $r$ requested from a communal resource pool $R$ (which is time varying $R_t$ but we will drop the subscript for ease of reading). Further more there is a supply of governance tokens $S$ which are being used as part of the goverance process.  In the implementation the quantity $S$ will be the effective supply which is the subset of the total Supply for the governance token in question. We assume a time varying supply $S_t$ and thereforewe can interpret $S_t$ as the effective supply without loss of generality. Furthermore we drop the subscript and refer to $S$ for ease of reading. The process of passing a proposal results in an allocation of $r$ funds as shown in the figure below.\n",
    "\n",
    "![](images/stockflow_cv_trigger.png)\n",
    "\n",
    "The trigger function is characterized by a set of parameters in addition to the current state of the system: $R$ and $S$. Those parameters are $\\alpha$, $\\beta$ and $\\rho$.\n",
    "\n",
    "$\\alpha \\in (0,1)$ is the conviction rate parameter defined in [Deriving Alpha](Deriving_Alpha.ipynb) and should be tuned according to a desired half life.\n",
    "\n",
    "$\\beta\\in (0,1)$ is the assymptotic limit for trigger function. It is impossible to discharge more $\\beta$ share of funds. \n",
    "\n",
    "$\\rho \\in (0, \\beta^2)$ is a the scale factor for trigger function. Note that we require $0<\\rho <\\beta^2$  \n",
    "\n",
    "The trigger function:\n",
    "\n",
    "$y^*(r) = y^*(r) = \\frac{\\rho S}{(1-\\alpha)\\left(\\beta^2 - \\frac{r}{R}\\right) }$\n",
    "\n",
    "The geometric properties of this function with respect to the parameter choices are shown here:\n",
    "\n",
    "![](images/trigger_geometry.png)\n",
    "\n",
    "Note that by requiring that: $0<\\rho <\\beta^2$ the following holds $0<\\frac{\\rho}{\\beta^2}<1$ and $0<\\beta - \\sqrt \\rho <\\beta <1$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "import warnings\n",
    "warnings.filterwarnings(\"ignore\")\n",
    "\n",
    "from cadCAD.configuration.utils import config_sim\n",
    "from model.parts.utils import *\n",
    "from model.parts.sys_params import * "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Pull params out of the existing files or use this notebook to ovewrite them with your own choices to see how the plots are affected."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'sentiment': 0.6, 'n': 30, 'm': 7, 'funds': 4867.21, 'supply': 22392.22}"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "initial_values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'beta': [0.2],\n",
       " 'rho': [0.0025],\n",
       " 'alpha': [0.7937005259840998],\n",
       " 'gamma': [0.001],\n",
       " 'sensitivity': [0.75],\n",
       " 'tmin': [1],\n",
       " 'min_supp': [1],\n",
       " 'base_completion_rate': [45],\n",
       " 'base_failure_rate': [180],\n",
       " 'base_engagement_rate': [0.3],\n",
       " 'lowest_affinity_to_support': [0.3]}"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "params"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "supply = initial_values['supply']\n",
    "funds = initial_values['funds']\n",
    "\n",
    "alpha = params['alpha'][0]\n",
    "beta = params['beta'][0]\n",
    "rho = params['rho'][0]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def trigger(requested, funds, supply, alpha, beta, rho):\n",
    "    '''\n",
    "    Function that determines threshold for proposals being accepted.\n",
    "    Refactored slightly from built in to be explicit for demo\n",
    "    '''\n",
    "    share = requested/funds\n",
    "    if share < beta:\n",
    "        threshold = rho*supply/(beta-share)**2  * 1/(1-alpha)\n",
    "        return threshold \n",
    "    else: \n",
    "        return np.inf"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Simple derivations:\n",
    "\n",
    "min_required_conviction = $y^*(0) = \\frac{\\rho S}{(1-\\alpha)\\beta^2}$\n",
    "\n",
    "max_achievable_conviction = $\\frac{S}{1-\\alpha}$\n",
    "\n",
    "min_required_conviction_as_a_share_of_max = $\\frac{\\rho S}{(1-\\alpha)\\beta^2} \\cdot \\frac{1-\\alpha}{S} = \\frac{\\rho}{\\beta^2}$\n",
    "\n",
    "To compute the max_achievable_request solve: \n",
    "\n",
    "$\\frac{S}{1-\\alpha} = \\frac{\\rho S}{(1-\\alpha)\\left(\\beta-\\frac{r}{R}\\right)^2}$\n",
    "\n",
    "max_achievable_request = $r = (\\beta -\\sqrt\\rho)F$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "min_required_conviction =6783.893932236272\n",
      "max_achievable_conviction =108542.30291578037\n",
      "\n",
      "min_achievable_conviction_as_a_share_of_max_achievable_conviction =0.06249999999999999\n",
      "\n",
      "max_achievable_request =730.0815000000001\n",
      "total_funds =4867.21\n",
      "\n",
      "max_achievable_request_as_a_share_of_funds =0.15000000000000002\n"
     ]
    }
   ],
   "source": [
    "min_required_conviction = trigger(0, funds, supply, alpha, beta, rho)\n",
    "print(\"min_required_conviction =\"+str(min_required_conviction))\n",
    "\n",
    "max_achievable_conviction = supply/(1-alpha)\n",
    "print(\"max_achievable_conviction =\"+str(max_achievable_conviction))\n",
    "print(\"\")\n",
    "print(\"min_achievable_conviction_as_a_share_of_max_achievable_conviction =\"+str(min_required_conviction/max_achievable_conviction))\n",
    "print(\"\")\n",
    "max_request = beta*funds\n",
    "max_achievable_request = (beta - np.sqrt(rho))*funds\n",
    "print(\"max_achievable_request =\"+str(max_achievable_request))\n",
    "print(\"total_funds =\"+str(funds))\n",
    "print(\"\")\n",
    "print(\"max_achievable_request_as_a_share_of_funds =\"+str(max_achievable_request/funds))\n",
    "\n",
    "granularity = 100 \n",
    "\n",
    "requests = np.arange(0,.9*max_request, max_request/granularity)\n",
    "requests_as_share_of_funds = requests/funds\n",
    "conviction_required = np.array([trigger(r, funds, supply, alpha, beta, rho) for r in requests])\n",
    "conviction_required_as_share_of_max = conviction_required/max_achievable_conviction\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First set of plots in \"Absolute Terms\" based on alpha, Supply and Funds as above"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'Conviction Required to Pass')"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 22852 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(requests, conviction_required)\n",
    "ax= plt.gca().axis()\n",
    "plt.vlines(max_request, 0, ax[3], 'r', '--')\n",
    "plt.vlines(max_achievable_request, 0, ax[3], 'g', '--')\n",
    "plt.hlines(max_achievable_conviction, 0, max_request, 'g', '--')\n",
    "plt.hlines(min_required_conviction, 0, max_request, 'k', '--')\n",
    "plt.title(\"Sample Trigger Function in Absolute Terms; Linear Scale\")\n",
    "plt.xlabel(\"Resources Requested\")\n",
    "plt.ylabel(\"Conviction Required to Pass\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.0, 119396.53320735841)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 30436 characters]\n",
      "text/plain": [
       "<Figure size 720x504 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(10, 7))\n",
    "plt.plot(requests, conviction_required)\n",
    "ax= plt.gca().axis()\n",
    "plt.vlines(max_request, 0, ax[3], 'r', '--')\n",
    "plt.vlines(max_achievable_request, 0, ax[3], 'g', '--')\n",
    "plt.hlines(max_achievable_conviction, 0, max_request, 'g', '--')\n",
    "plt.hlines(min_required_conviction, 0, max_request, 'k', '--')\n",
    "plt.title(\"Sample Trigger Function in Absolute Terms; Linear Scale\")\n",
    "plt.xlabel(\"Resources Requested\")\n",
    "plt.ylabel(\"Conviction Required to Pass\")\n",
    "plt.gca().set_ylim(0, max_achievable_conviction*(1.1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 21204 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(requests, conviction_required)\n",
    "ax= plt.gca().axis()\n",
    "plt.vlines(max_request, 0, ax[3], 'r', '--')\n",
    "plt.vlines(max_achievable_request, 0, ax[3], 'g', '--')\n",
    "plt.hlines(max_achievable_conviction, 0, max_request, 'g', '--')\n",
    "plt.hlines(min_required_conviction, 0, max_request, 'k', '--')\n",
    "plt.title(\"Sample Trigger Function in Absolute Terms; Log Scale\")\n",
    "plt.xlabel(\"Resources Requested\")\n",
    "plt.ylabel(\"Conviction Required to Pass\")\n",
    "plt.gca().set_yscale('log')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3391.946966118136, 217084.60583156074)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 28988 characters]\n",
      "text/plain": [
       "<Figure size 720x504 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(10, 7))\n",
    "plt.plot(requests, conviction_required)\n",
    "ax= plt.gca().axis()\n",
    "plt.vlines(max_request, 0, ax[3], 'r', '--')\n",
    "plt.vlines(max_achievable_request, 0, ax[3], 'g', '--')\n",
    "plt.hlines(max_achievable_conviction, 0, max_request, 'g', '--')\n",
    "plt.hlines(min_required_conviction, 0, max_request, 'k', '--')\n",
    "plt.title(\"Sample Trigger Function in Absolute Terms; Log Scale\")\n",
    "plt.xlabel(\"Resources Requested\")\n",
    "plt.ylabel(\"Conviction Required to Pass\")\n",
    "plt.gca().set_yscale('log')\n",
    "plt.gca().set_ylim(min_required_conviction/2, max_achievable_conviction*2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Second set of plots in \"Relative Terms\" which knock out the dependence on alpha and supply, as well as treating requests as share of total funds."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'Conviction Required to Pass as share of max achievable')"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 23852 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(requests_as_share_of_funds, conviction_required_as_share_of_max)\n",
    "ax= plt.gca().axis()\n",
    "plt.vlines(max_request/funds, 0, ax[3], 'r', '--')\n",
    "plt.vlines(max_achievable_request/funds, 0, ax[3], 'g', '--')\n",
    "plt.hlines(1, 0, max_request/funds, 'g', '--')\n",
    "plt.hlines(min_required_conviction/max_achievable_conviction, 0, max_request/funds, 'k', '--')\n",
    "plt.title(\"Sample Trigger Function in Relative Terms; Linear Scale\")\n",
    "plt.xlabel(\"Resources Requested as a share of Total Funds\")\n",
    "plt.ylabel(\"Conviction Required to Pass as share of max achievable\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.0, 1.1)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 32888 characters]\n",
      "text/plain": [
       "<Figure size 720x504 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(10, 7))\n",
    "plt.plot(requests_as_share_of_funds, conviction_required_as_share_of_max)\n",
    "ax= plt.gca().axis()\n",
    "plt.vlines(max_request/funds, 0, ax[3], 'r', '--')\n",
    "plt.vlines(max_achievable_request/funds, 0, ax[3], 'g', '--')\n",
    "plt.hlines(1, 0, max_request/funds, 'g', '--')\n",
    "plt.hlines(min_required_conviction/max_achievable_conviction, 0, max_request/funds, 'k', '--')\n",
    "plt.title(\"Sample Trigger Function in Relative Terms; Linear Scale\")\n",
    "plt.xlabel(\"Resources Requested as a share of Total Funds\")\n",
    "plt.ylabel(\"Conviction Required to Pass as share of max achievable\")\n",
    "plt.gca().set_ylim(0, 1.1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 25108 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(requests_as_share_of_funds, conviction_required_as_share_of_max)\n",
    "ax= plt.gca().axis()\n",
    "plt.vlines(max_request/funds, 0, ax[3], 'r', '--')\n",
    "plt.vlines(max_achievable_request/funds, 0, ax[3], 'g', '--')\n",
    "plt.hlines(1, 0, max_request/funds, 'g', '--')\n",
    "plt.hlines(min_required_conviction/max_achievable_conviction, 0, max_request/funds, 'k', '--')\n",
    "plt.title(\"Sample Trigger Function in Relative Terms; Log Scale\")\n",
    "plt.xlabel(\"Resources Requested as a share of Total Funds\")\n",
    "plt.ylabel(\"Conviction Required to Pass as share of max achievable\")\n",
    "plt.gca().set_yscale('log')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.031249999999999997, 2)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 32984 characters]\n",
      "text/plain": [
       "<Figure size 720x504 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(10, 7))\n",
    "plt.plot(requests_as_share_of_funds, conviction_required_as_share_of_max)\n",
    "ax= plt.gca().axis()\n",
    "plt.vlines(max_request/funds, 0, ax[3], 'r', '--')\n",
    "plt.vlines(max_achievable_request/funds, 0, ax[3], 'g', '--')\n",
    "plt.hlines(1, 0, max_request/funds, 'g', '--')\n",
    "plt.hlines(min_required_conviction/max_achievable_conviction, 0, max_request/funds, 'k', '--')\n",
    "plt.title(\"Sample Trigger Function in Relative Terms; Log Scale\")\n",
    "plt.xlabel(\"Resources Requested as a share of Total Funds\")\n",
    "plt.ylabel(\"Conviction Required to Pass as share of max achievable\")\n",
    "plt.gca().set_yscale('log')\n",
    "plt.gca().set_ylim(min_required_conviction/max_achievable_conviction/2,2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Third set of plots are heatmaps to show the simultaneous variation of multiple parameters with a focus on alpha and supply.\n",
    "\n",
    "Note: that i am using params stored in the supporting files, this won't have changed even if you have edited the plots above"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'beta': [0.2],\n",
       " 'rho': [0.0025],\n",
       " 'alpha': [0.7937005259840998],\n",
       " 'gamma': [0.001],\n",
       " 'sensitivity': [0.75],\n",
       " 'tmin': [1],\n",
       " 'min_supp': [1],\n",
       " 'base_completion_rate': [45],\n",
       " 'base_failure_rate': [180],\n",
       " 'base_engagement_rate': [0.3],\n",
       " 'lowest_affinity_to_support': [0.3]}"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "params"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "supply_sweep = trigger_sweep('effective_supply',trigger, params, supply)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "alpha_sweep = trigger_sweep('alpha',trigger, params, supply)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 54484 characters]\n",
      "text/plain": [
       "<Figure size 1440x1440 with 4 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "trigger_grid(supply_sweep, alpha_sweep)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "These plots demonstrate that the trigger functions the share of of max conviction required to pass a proposal remains constant under variations in both alpha and effective supply -- both of these variables scale the the conviction required to pass a proposal and the max conviction possible by the same amount."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
