plr 0.1.1

Performs greedy or optimal error-bounded piecewise linear regression (PLR)
Documentation
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from matplotlib import pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 186,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.PathCollection at 0x7fd05c97da50>"
      ]
     },
     "execution_count": 186,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = np.linspace(0, 7, 1000)\n",
    "y = np.sin(x)\n",
    "data = list(zip(x, y))\n",
    "plt.scatter(x, y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 187,
   "metadata": {},
   "outputs": [],
   "source": [
    "def slope(p1, p2):\n",
    "    x1, y1 = p1\n",
    "    x2, y2 = p2\n",
    "    return (y2 - y1) / (x2 - x1)\n",
    "\n",
    "# a x + b = y\n",
    "# ax + b - y = 0\n",
    "# ax - y = -b\n",
    "\n",
    "def line(p1, p2):\n",
    "    a = slope(p1, p2)\n",
    "    b = -a * p1[0] + p1[1]\n",
    "    return (a,b)\n",
    "\n",
    "def intersection(l1, l2):\n",
    "    a, c = l1\n",
    "    b, d = l2\n",
    "    \n",
    "    return ((d - c) / (a - b)), ((a*d - b*c)/(a - b))\n",
    "\n",
    "def above(pt, line):\n",
    "    return pt[1] > line[0] * pt[0] + line[1]\n",
    "\n",
    "def below(pt, line):\n",
    "        return pt[1] < line[0] * pt[0] + line[1]\n",
    "\n",
    "def upper_bound(pt, gamma):\n",
    "    return (pt[0], pt[1] + gamma)\n",
    "\n",
    "def lower_bound(pt, gamma):\n",
    "    return (pt[0], pt[1] - gamma)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 189,
   "metadata": {},
   "outputs": [],
   "source": [
    "class GreedyPLR:\n",
    "    def __init__(self, gamma):\n",
    "        self.__state = \"need2\"\n",
    "        self.__gamma = gamma\n",
    "        \n",
    "    def process(self, pt):\n",
    "        self.__last_pt = pt\n",
    "        if self.__state == \"need2\":\n",
    "            self.__s0 = pt\n",
    "            self.__state = \"need1\"\n",
    "        elif self.__state == \"need1\":\n",
    "            self.__s1 = pt\n",
    "            self.__setup()\n",
    "            self.__state = \"ready\"\n",
    "        elif self.__state == \"ready\":\n",
    "            return self.__process(pt)\n",
    "        else:\n",
    "            assert False\n",
    "    \n",
    "    def __setup(self):\n",
    "        self.__rho_lower = line(upper_bound(self.__s0, self.__gamma),\n",
    "                                lower_bound(self.__s1, self.__gamma))\n",
    "        self.__rho_upper = line(lower_bound(self.__s0, self.__gamma),\n",
    "                                upper_bound(self.__s1, self.__gamma))\n",
    "        \n",
    "        self.__sint = intersection(self.__rho_lower, self.__rho_upper)\n",
    "        \n",
    "    def __current_segment(self):\n",
    "        segment_start = self.__s0[0]\n",
    "        segment_stop = self.__last_pt[0]\n",
    "        avg_slope = (self.__rho_lower[0] + self.__rho_upper[0]) / 2\n",
    "        intercept = -avg_slope * self.__sint[0] + self.__sint[1]\n",
    "        return (segment_start, segment_stop, avg_slope, intercept)\n",
    "        \n",
    "    def __process(self, pt):\n",
    "        if not (above(pt, self.__rho_lower) and below(pt, self.__rho_upper)):\n",
    "            # we have to start a new segment.\n",
    "            prev_segment = self.__current_segment()\n",
    "            \n",
    "            self.__s0 = pt\n",
    "            self.__state = \"need1\"\n",
    "            \n",
    "            # return the previous segment\n",
    "            return prev_segment\n",
    "        \n",
    "        # we can tweak our extreme slopes to account for this point.\n",
    "        # if this point's upper bound is below the current rho_upper,\n",
    "        # we have to change rho_upper.\n",
    "\n",
    "        s_upper = upper_bound(pt, self.__gamma)\n",
    "        s_lower = lower_bound(pt, self.__gamma)\n",
    "        if below(s_upper, self.__rho_upper):\n",
    "            self.__rho_upper = line(self.__sint, s_upper)\n",
    "        \n",
    "        # if this point's lower bound is above the current rho_lower,\n",
    "        # we have to change rho_lower\n",
    "        if above(s_lower, self.__rho_lower):\n",
    "            self.__rho_lower = line(self.__sint, s_lower)\n",
    "            \n",
    "        return None\n",
    "    \n",
    "    def finish(self):\n",
    "        if self.__state == \"need2\":\n",
    "            self.__state = \"finished\"\n",
    "            return None\n",
    "        elif self.__state == \"need1\":\n",
    "            self.__state = \"finished\"\n",
    "            return (self.__s0[0], self.__s0[0] + 1, 0, self.__s0[1])\n",
    "        elif self.__state == \"ready\":\n",
    "            self.__state = \"finished\"\n",
    "            return self.__current_segment()\n",
    "        else:\n",
    "            assert False\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 190,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "77"
      ]
     },
     "execution_count": 190,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "plr = GreedyPLR(0.0005)\n",
    "lines = []\n",
    "for pt in data:\n",
    "    l = plr.process(pt)\n",
    "    if l:\n",
    "        lines.append(l)\n",
    "    \n",
    "last = plr.finish()\n",
    "if last:\n",
    "    lines.append(last)\n",
    "    \n",
    "len(lines)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 191,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.scatter(x, y)\n",
    "for l in lines:\n",
    "    xl = np.linspace(l[0], l[1], 100)\n",
    "    yl = l[2] * xl + l[3]\n",
    "    plt.scatter(xl, yl)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 198,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(1, 1), (3, 3), (4, 3)]"
      ]
     },
     "execution_count": 198,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def update_hull(hull, upper=True):\n",
    "    # update an upper or lower convex hull using the triangle update rule\n",
    "    # assume the hull is sorted by x coordinate already.\n",
    "    \n",
    "    # take the last three points of the hull. If the middle point is\n",
    "    # above the line connecting the other two points, remove it. If not,\n",
    "    # repeat. When updating the lower hull, check if below the line.\n",
    "    reversed_hull = list(reversed(hull))\n",
    "    kept_points = []\n",
    "    while True:\n",
    "        if len(reversed_hull) < 3:\n",
    "            break\n",
    "            \n",
    "        pt1, pt2, pt3, *_ = reversed_hull\n",
    "                \n",
    "        l = line(pt1, pt3)\n",
    "        if upper and above(pt2, l):\n",
    "            del reversed_hull[1]\n",
    "            continue\n",
    "            \n",
    "        if not upper and below(pt2, l):\n",
    "            del reversed_hull[1]\n",
    "            continue\n",
    "            \n",
    "        # otherwise, pt1 gets to stay!\n",
    "        kept_points.insert(0, reversed_hull.pop(0))\n",
    "        \n",
    "        \n",
    "    while reversed_hull:\n",
    "        kept_points.insert(0, reversed_hull.pop(0))\n",
    "\n",
    "    return kept_points\n",
    "\n",
    "current_hull = [(1, 1), (2, 1), (3, 3), (4, 3)]\n",
    "current_hull = update_hull(current_hull, upper=False)\n",
    "current_hull"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 211,
   "metadata": {},
   "outputs": [],
   "source": [
    "def argmax(l):\n",
    "    return max(enumerate(l), key=lambda x: x[1])[0]\n",
    "\n",
    "def argmin(l):\n",
    "    return min(enumerate(l), key=lambda x: x[1])[0]\n",
    "        \n",
    "\n",
    "class OptimalPLR:\n",
    "    def __init__(self, gamma):\n",
    "        self.__state = \"need2\"\n",
    "        self.__gamma = gamma\n",
    "        \n",
    "    def process(self, pt):\n",
    "        self.__last_pt = pt\n",
    "        if self.__state == \"need2\":\n",
    "            self.__s0 = pt\n",
    "            self.__state = \"need1\"\n",
    "        elif self.__state == \"need1\":\n",
    "            self.__s1 = pt\n",
    "            self.__setup()\n",
    "            self.__state = \"ready\"\n",
    "        elif self.__state == \"ready\":\n",
    "            return self.__process(pt)\n",
    "        else:\n",
    "            assert False\n",
    "    \n",
    "    def __setup(self):\n",
    "        self.__rho_lower = line(upper_bound(self.__s0, self.__gamma),\n",
    "                                lower_bound(self.__s1, self.__gamma))\n",
    "        self.__rho_upper = line(lower_bound(self.__s0, self.__gamma),\n",
    "                                upper_bound(self.__s1, self.__gamma))\n",
    "        \n",
    "        self.__upper_hull = [upper_bound(self.__s0, self.__gamma),\n",
    "                             upper_bound(self.__s1, self.__gamma)]\n",
    "        self.__lower_hull = [lower_bound(self.__s0, self.__gamma),\n",
    "                             lower_bound(self.__s1, self.__gamma)]\n",
    "    def __current_segment(self):\n",
    "        sint = intersection(self.__rho_lower, self.__rho_upper)\n",
    "        segment_start = self.__s0[0]\n",
    "        segment_stop = self.__last_pt[0]\n",
    "        avg_slope = (self.__rho_lower[0] + self.__rho_upper[0]) / 2\n",
    "        intercept = -avg_slope * sint[0] + sint[1]\n",
    "        return (segment_start, segment_stop, avg_slope, intercept)\n",
    "        \n",
    "    def __process(self, pt):\n",
    "        if not (above(pt, self.__rho_lower) and below(pt, self.__rho_upper)):\n",
    "            # we have to start a new segment.\n",
    "            prev_segment = self.__current_segment()\n",
    "            \n",
    "            self.__s0 = pt\n",
    "            self.__state = \"need1\"\n",
    "            \n",
    "            # return the previous segment\n",
    "            return prev_segment\n",
    "        \n",
    "        # we can tweak our extreme slopes to account for this point.\n",
    "        # if this point's upper bound is below the current rho_upper,\n",
    "        # we have to change rho_upper.\n",
    "\n",
    "        s_upper = upper_bound(pt, self.__gamma)\n",
    "        s_lower = lower_bound(pt, self.__gamma)\n",
    "        if below(s_upper, self.__rho_upper):\n",
    "            # find the point in the lower hull that would minimize\n",
    "            # the slope between that point and s_upper. \n",
    "            resulting_slopes = [line(x, s_upper)[0] for x in self.__lower_hull]\n",
    "            idx = argmin(resulting_slopes)\n",
    "            self.__rho_upper = line(self.__lower_hull[idx], s_upper)\n",
    "            \n",
    "            # remove everything from the hull prior to that point, add new point\n",
    "            self.__lower_hull = self.__lower_hull[idx:]\n",
    "            self.__lower_hull.append(s_lower)\n",
    "            self.__lower_hull = update_hull(self.__lower_hull, upper=False)\n",
    "\n",
    "        \n",
    "        # if this point's lower bound is above the current rho_lower,\n",
    "        # we have to change rho_lower\n",
    "        if above(s_lower, self.__rho_lower):\n",
    "            # find the point in the upper hull that would maximize\n",
    "            # the slope between the point and s_lower\n",
    "            resulting_slopes = [line(x, s_lower)[0] for x in self.__upper_hull]\n",
    "            idx = argmax(resulting_slopes)\n",
    "            self.__rho_lower = line(self.__upper_hull[idx], s_lower)\n",
    "            \n",
    "            # remove everything from the hull prior to that point, add new point\n",
    "            self.__upper_hull = self.__upper_hull[idx:]\n",
    "            self.__upper_hull.append(s_upper)\n",
    "            self.__upper_hull = update_hull(self.__upper_hull)\n",
    "        \n",
    "        return None\n",
    "    \n",
    "    def finish(self):\n",
    "        if self.__state == \"need2\":\n",
    "            self.__state = \"finished\"\n",
    "            return None\n",
    "        elif self.__state == \"need1\":\n",
    "            self.__state = \"finished\"\n",
    "            return (self.__s0[0], self.__s0[0] + 1, 0, self.__s0[1])\n",
    "        elif self.__state == \"ready\":\n",
    "            self.__state = \"finished\"\n",
    "            return self.__current_segment()\n",
    "        else:\n",
    "            assert False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 228,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 228,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "plr = OptimalPLR(0.05)\n",
    "lines = []\n",
    "for pt in data:\n",
    "    l = plr.process(pt)\n",
    "    if l:\n",
    "        lines.append(l)\n",
    "    \n",
    "last = plr.finish()\n",
    "if last:\n",
    "    lines.append(last)\n",
    "len(lines)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 230,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "22"
      ]
     },
     "execution_count": 230,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "plr = OptimalPLR(0.005)\n",
    "lines2 = []\n",
    "for pt in data:\n",
    "    l = plr.process(pt)\n",
    "    if l:\n",
    "        lines2.append(l)\n",
    "    \n",
    "last = plr.finish()\n",
    "if last:\n",
    "    lines2.append(last)\n",
    "len(lines2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 243,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1440x360 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(20,5))\n",
    "\n",
    "\n",
    "plt.subplot(1, 3, 1)\n",
    "plt.scatter(x, y)\n",
    "plt.title(\"Original data (n=1000)\", size=20)\n",
    "plt.tick_params(axis='x', labelrotation=0, labelsize=16)\n",
    "plt.tick_params(axis='y', labelsize=16)\n",
    "\n",
    "plt.subplot(1, 3, 2)\n",
    "for l in lines:\n",
    "    xl = np.linspace(l[0], l[1], 100)\n",
    "    yl = l[2] * xl + l[3]\n",
    "    plt.scatter(xl, yl)\n",
    "plt.title(\"Optimal PLR, δ = 0.05 (7 segments)\", size=20)\n",
    "plt.tick_params(axis='x', labelrotation=0, labelsize=16)\n",
    "plt.tick_params(axis='y', labelsize=16)\n",
    "    \n",
    "plt.subplot(1, 3, 3)\n",
    "for l in lines2:\n",
    "    xl = np.linspace(l[0], l[1], 100)\n",
    "    yl = l[2] * xl + l[3]\n",
    "    plt.scatter(xl, yl)\n",
    "plt.title(\"Optimal PLR, δ = 0.005 (22 segments)\", size=20)\n",
    "plt.tick_params(axis='x', labelrotation=0, labelsize=16)\n",
    "plt.tick_params(axis='y', labelsize=16)\n",
    "plt.savefig(\"plot.png\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 208,
   "metadata": {},
   "outputs": [],
   "source": [
    "from_rust = [\n",
    "(0, 0.224, 0.9925214438051018, 0.00014488723457774244),\n",
    "(0.224, 0.371, 0.9564359979470114, 0.00811544111468232),\n",
    "(0.371, 0.49000000000000005, 0.9098257927831952, 0.025184110625250444),\n",
    "(0.49000000000000005, 0.602, 0.8560902362553744, 0.051374096095132604),\n",
    "(0.602, 0.7000000000000001, 0.7973679477778012, 0.08644199332413038),\n",
    "(0.7000000000000001, 0.798, 0.7345403303455742, 0.13026493807044426),\n",
    "(0.798, 0.889, 0.6672938613391461, 0.18364968490552003),\n",
    "(0.889, 0.9800000000000001, 0.5968809282166496, 0.2460461759022603),\n",
    "(0.9800000000000001, 1.064, 0.52453963029918, 0.3166206305259157),\n",
    "(1.064, 1.1480000000000001, 0.4512773049507166, 0.3943392750949695),\n",
    "(1.1480000000000001, 1.232, 0.37483263881525447, 0.48185046990923225),\n",
    "(1.232, 1.316, 0.2957447083682151, 0.5790264497986415),\n",
    "(1.316, 1.4000000000000001, 0.21456509612801, 0.6855881183987156),\n",
    "(1.4000000000000001, 1.4769999999999999, 0.13535613338353905, 0.7961030925848586),\n",
    "(1.4769999999999999, 1.554, 0.05875237893886226, 0.9089827857523513),\n",
    "(1.554, 1.631, -0.018199546284158596, 1.0282975942267096),\n",
    "(1.631, 1.708, -0.09504361970083763, 1.153358954523449),\n",
    "(1.708, 1.792, -0.17476140876329194, 1.2893415834624926),\n",
    "(1.792, 1.8760000000000001, -0.25674332111792314, 1.4359537229597428),\n",
    "(1.8760000000000001, 1.9600000000000002, -0.3369097215772785, 1.5860507383639242),\n",
    "(1.9600000000000002, 2.044, -0.41470028452663665, 1.7382295287324734),\n",
    "(2.044, 2.128, -0.4895664424253739, 1.890971731375827),\n",
    "(2.128, 2.219, -0.5638422878887794, 2.0488442399382443),\n",
    "(2.219, 2.31, -0.6365330755574079, 2.20984715465532),\n",
    "(2.31, 2.408, -0.7064150208952986, 2.371076767650351),\n",
    "(2.408, 2.506, -0.7722395133713664, 2.529290458375451),\n",
    "(2.506, 2.6109999999999998, -0.832566340878024, 2.680265889786253),\n",
    "(2.6109999999999998, 2.73, -0.8890772083181679, 2.827667324426729),\n",
    "(2.73, 2.863, -0.9393402024298271, 2.9646838555034947),\n",
    "(2.863, 3.045, -0.980719181256966, 3.0830673326267295),\n",
    "(3.045, 3.346, -1.0587004536456222, 3.3386367109432715),\n",
    "(3.346, 3.5, -1.0194089527822754, 3.2163564540974594),\n",
    "(3.5, 3.6260000000000003, -0.969537899233178, 3.0490937912774494),\n",
    "(3.6260000000000003, 3.745, -0.9112648557380234, 2.8443939825940068),\n",
    "(3.745, 3.8500000000000005, -0.8470640051072593, 2.6097982889007594),\n",
    "(3.8500000000000005, 3.9549999999999996, -0.7778436510635867, 2.3488828625107105),\n",
    "(3.9549999999999996, 4.053, -0.7035404258383973, 2.0602635640493663),\n",
    "(4.053, 4.151, -0.6255241060600776, 1.7491566288953644),\n",
    "(4.151, 4.242, -0.5452012677617251, 1.420545750946877),\n",
    "(4.242, 4.333, -0.4637127145158647, 1.0795392357639941),\n",
    "(4.333, 4.424, -0.3788934556974868, 0.7166593459207461),\n",
    "(4.424, 4.515000000000001, -0.29144539501621314, 0.3344128066449319),\n",
    "(4.515000000000001, 4.606, -0.20211904114644377, -0.06428224649977465),\n",
    "(4.606, 4.69, -0.1151167858286416, -0.4606319398756733),\n",
    "(4.69, 4.774, -0.031174188126666322, -0.8500583320514762),\n",
    "(4.774, 4.858, 0.05256849223960554, -1.2455724883595696),\n",
    "(4.858, 4.949, 0.13893433546476147, -1.6606130712268432),\n",
    "(4.949, 5.04, 0.2271286146332705, -2.092412737173717),\n",
    "(5.04, 5.131, 0.3129166735955567, -2.520077948156951),\n",
    "(5.131, 5.2219999999999995, 0.3956086070533476, -2.939622030057251),\n",
    "(5.2219999999999995, 5.313, 0.4745201155249519, -3.346901263923985),\n",
    "(5.313, 5.4110000000000005, 0.5517095003597423, -3.751884706679768),\n",
    "(5.4110000000000005, 5.509, 0.6260229407482628, -4.148680392368301),\n",
    "(5.509, 5.614000000000001, 0.6958450294401022, -4.527636690886439),\n",
    "(5.614000000000001, 5.726, 0.761797755685506, -4.891664002832056),\n",
    "(5.726, 5.845, 0.8211801307009096, -5.224864212667721),\n",
    "(5.845, 5.984999999999999, 0.873255945628706, -5.52102481985113),\n",
    "(5.984999999999999, 6.167, 0.9148761058720644, -5.758745208484667),\n",
    "(6.167, 6.503, 0.9929896535897769, -6.239043539927865),\n",
    "(6.503, 6.6499999999999995, 0.9576396162376866, -6.009263861693788),\n",
    "(6.6499999999999995, 6.769, 0.9115503947797831, -5.702988862860086),\n",
    "(6.769, 6.881, 0.8582426830616655, -5.342287319093105),\n",
    "(6.881, 6.986, 0.7977272612145305, -4.926080687706908),\n",
    "(6.986, 6.993, 0.7607573751780505, -4.6682830946896905)\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 209,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.scatter(x, y)\n",
    "for l in from_rust:\n",
    "    xl = np.linspace(l[0], l[1], 100)\n",
    "    yl = l[2] * xl + l[3]\n",
    "    plt.scatter(xl, yl)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "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.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}