{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Events happen or do not happen. Things exist or do not. Probability is how we think about these."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Thie notebook is based on the original [here](https://gist.github.com/willkurt/6c209c14bf777470543393302d1b523c) (linked from [this excellent page](https://www.countbayesie.com/blog/2019/12/1/probability-and-statistics-in-90-minutes)).\n",
    "\n",
    "See [a related book by the author at Uni Freiburg](https://katalog.ub.uni-freiburg.de/opac/RDSIndex/Search?lookfor=Bayesian%20Statistics%20the%20Fun%20Way&source=homepage)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Probability as logic using Python's data model\n",
    "\n",
    "In this short notebook we'll show how probability really is just an extension of boolean logic. We'll make a class `P`, that uses Python's data model methods to implement a working example of probability as logic using `-`,`&` and `|`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class P:\n",
    "    \"\"\"\n",
    "    Example of Probability as logic using Python's data model\n",
    "    In this simple example these probabilites are assumed to \n",
    "    be conditionally independent.\n",
    "    \"\"\"\n",
    "    def __init__(self,prob):\n",
    "        assert prob >= 0, \"probabilities can't be negative!\" \n",
    "        assert prob <= 1, \"probabilities can't be greater than 1!\"\n",
    "        self.prob = prob\n",
    "        \n",
    "    def __repr__(self):\n",
    "        return \"P({})\".format(self.prob)\n",
    "\n",
    "    def __neg__(self):\n",
    "        return P(1-self.prob)\n",
    "    \n",
    "    def __and__(self,P2):\n",
    "        return P(self.prob * P2.prob)\n",
    "    \n",
    "    def __or__(self,P2):\n",
    "        return P(self.prob + P2.prob - (self & P2).prob)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "P(0.5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "P(0.5) & P(0.5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "True & True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "P(0.5) | P(0.5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can then use this to work out probabilities of various events happening using python!\n",
    "\n",
    "Suppose, for example, you know that there is a 0.3 probability of rain tomorrow and you'll get rained on if you forget your umbrella or your umbrella is broken. Then let's say you forget your umbrella with a probability 0.1 and you think your umbrella might be the broken, we'll give that a probability of 0.7. \n",
    "\n",
    "Now let's use logic to answer: What's the probability you will *not* get wet?\n",
    "\n",
    "Let's start with our facts:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rain = P(0.3)\n",
    "forget = P(0.1)\n",
    "broken = P(0.7)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The probability of being `wet` is:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "wet = rain & (forget | broken)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "wet"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "and logically the probability of being dry is:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "-wet"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With probability as logic, no matter how complicated our reasoning, we can now trivially code up a solution in Python!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusions\n",
    "\n",
    "* Probabilities are intuitive\n",
    "* Do not let mathematical notation of probabilities scare you\n",
    "* Working mathematically and computationally with probabilities can be very useful\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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": 4
}