{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "mk43RirOWyAi",
        "outputId": "7e80338c-5912-4513-b5aa-df116abd79db"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "No matching cluster found for pattern: [1 0 1 0 1]\n",
            "\n",
            "Assigned clusters: [0, 0, 1, 2]\n"
          ]
        }
      ],
      "source": [
        "import numpy as np\n",
        "\n",
        "class ART1:\n",
        "    def __init__(self, input_size, num_clusters, vigilance=0.75):\n",
        "        self.input_size = input_size\n",
        "        self.num_clusters = num_clusters\n",
        "        self.vigilance = vigilance\n",
        "\n",
        "        # Initialize bottom-up (forward) and top-down (backward) weights\n",
        "        self.bu_weights = np.ones((num_clusters, input_size))  # Bottom-up weights\n",
        "        self.td_weights = np.ones((num_clusters, input_size))  # Top-down weights\n",
        "\n",
        "    def train(self, data):\n",
        "        clusters = []\n",
        "\n",
        "        for x in data:\n",
        "            x = np.array(x)\n",
        "            match_found = False\n",
        "\n",
        "            for j in range(self.num_clusters):\n",
        "                # Check if this cluster is eligible\n",
        "                top_down_match = np.minimum(x, self.td_weights[j])\n",
        "                similarity = np.sum(top_down_match) / np.sum(x)\n",
        "\n",
        "                if similarity >= self.vigilance:\n",
        "                    # Resonance occurs\n",
        "                    match_found = True\n",
        "\n",
        "                    # Update bottom-up and top-down weights\n",
        "                    self.bu_weights[j] = np.minimum(x, self.bu_weights[j])\n",
        "                    self.td_weights[j] = self.bu_weights[j].copy()\n",
        "                    clusters.append(j)\n",
        "                    break\n",
        "\n",
        "            if not match_found:\n",
        "                print(\"No matching cluster found for pattern:\", x)\n",
        "\n",
        "        return clusters\n",
        "\n",
        "# Sample binary input patterns\n",
        "patterns = [\n",
        "    [1, 1, 0, 0, 1],\n",
        "    [1, 1, 0, 0, 1],\n",
        "    [0, 0, 1, 1, 0],\n",
        "    [0, 0, 1, 1, 1],\n",
        "    [1, 0, 1, 0, 1],\n",
        "]\n",
        "\n",
        "# Create ART1 network\n",
        "art = ART1(input_size=5, num_clusters=3, vigilance=0.7)\n",
        "\n",
        "# Train the ART network\n",
        "assigned_clusters = art.train(patterns)\n",
        "\n",
        "# Output\n",
        "print(\"\\nAssigned clusters:\", assigned_clusters)\n"
      ]
    }
  ]
}