{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from math import e\n",
    "from numpy.typing import NDArray as array\n",
    "from numpy import float64 as float"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "def sigmoid(z):\n",
    "    return 1 / (1 + e ** (-z))\n",
    "\n",
    "\n",
    "def ht(weights, x):\n",
    "    return g(weights.T @ x)\n",
    "\n",
    "\n",
    "def g(x):\n",
    "    return sigmoid(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.9999546021312976\n",
      "4.539786870243442e-05\n",
      "9.357622968839314e-14\n",
      "4.539786870243442e-05\n"
     ]
    }
   ],
   "source": [
    "# and gate?\n",
    "weights_and = np.array([-30, 20, 20])\n",
    "\n",
    "print(ht(weights_and, np.array([1, 1, 1])))\n",
    "print(ht(weights_and, np.array([1, 0, 1])))\n",
    "print(ht(weights_and, np.array([1, 0, 0])))\n",
    "print(ht(weights_and, np.array([1, 1, 0])))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9.357622968839314e-14\n",
      "4.539786870243442e-05\n",
      "0.9999546021312976\n",
      "4.539786870243442e-05\n"
     ]
    }
   ],
   "source": [
    "# not x and not y gate?\n",
    "weights = np.array([10, -20, -20])\n",
    "\n",
    "print(ht(weights, np.array([1, 1, 1])))\n",
    "print(ht(weights, np.array([1, 0, 1])))\n",
    "print(ht(weights, np.array([1, 0, 0])))\n",
    "print(ht(weights, np.array([1, 1, 0])))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.9999999999999065\n",
      "0.9999546021312976\n",
      "4.539786870243442e-05\n",
      "0.9999546021312976\n"
     ]
    }
   ],
   "source": [
    "# or gate?\n",
    "weights = np.array([-10, 20, 20])\n",
    "print(ht(weights, np.array([1, 1, 1])))\n",
    "print(ht(weights, np.array([1, 0, 1])))\n",
    "print(ht(weights, np.array([1, 0, 0])))\n",
    "print(ht(weights, np.array([1, 1, 0])))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [],
   "source": [
    "# make it more generic\n",
    "def layer(a: array, w: array, debug=False) -> array:\n",
    "    a_with_one: array = np.concatenate(([1], a))\n",
    "    z = w @ a_with_one\n",
    "    a_next = sigmoid(z)\n",
    "\n",
    "    return a_next"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.9999999999999656\n",
      "0.999983298578152\n",
      "0.0001233945759862318\n",
      "0.999983298578152\n"
     ]
    }
   ],
   "source": [
    "# or gate but cooler\n",
    "weights = np.array([1, -10, 20, 20])\n",
    "print(layer(np.array([1, 1, 1]), weights))\n",
    "print(layer(np.array([1, 0, 1]), weights))\n",
    "print(layer(np.array([1, 0, 0]), weights))\n",
    "print(layer(np.array([1, 1, 0]), weights))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.9999545869652744\n",
      "4.5622486386054965e-05\n",
      "4.5622486386054965e-05\n",
      "0.9999545869652744\n"
     ]
    }
   ],
   "source": [
    "# xnor gate, needs 3 layers\n",
    "weights = [\n",
    "    np.array(\n",
    "        [\n",
    "            [1, -30, 20, 20],\n",
    "            [1, 10, -20, -20],\n",
    "        ]\n",
    "    ),\n",
    "    np.array([-10, 20, 20]),\n",
    "]\n",
    "\n",
    "def l2(x: array, w1: array, w2: array) -> array:\n",
    "    z = layer(x, w1)\n",
    "    z2 = layer(z, w2)\n",
    "    return z2\n",
    "\n",
    "print(l2(np.array([1,0,0]), weights[0], weights[1]))\n",
    "print(l2(np.array([1,1,0]), weights[0], weights[1]))\n",
    "print(l2(np.array([1,0,1]), weights[0], weights[1]))\n",
    "print(l2(np.array([1,1,1]), weights[0], weights[1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "ki",
   "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.13.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
