diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..623062f8eae2fc82e9c013daf6e389e7492f5725
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,162 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+#   For a library or package, you might want to ignore these files since the code is
+#   intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+#   However, in case of collaboration, if having platform-specific dependencies or dependencies
+#   having no cross-platform support, pipenv may install dependencies that don't work, or not
+#   install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+#   Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+#   This is especially recommended for binary packages to ensure reproducibility, and is more
+#   commonly ignored for libraries.
+#   https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+#   Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+#   pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+#   in version control.
+#   https://pdm.fming.dev/latest/usage/project/#working-with-version-control
+.pdm.toml
+.pdm-python
+.pdm-build/
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+*.pyc
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+#  JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+#  and can be added to the global gitignore or merged into this file.  For a more nuclear
+#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
+#.idea/
\ No newline at end of file
diff --git a/Copy_of_social_network_abm.ipynb b/Copy_of_social_network_abm.ipynb
index dbff98eba4a9377fca71c777c0a0d3bca5abcd1b..0afa2d8f39d92872f73494e1deb3865d3c62b585 100644
--- a/Copy_of_social_network_abm.ipynb
+++ b/Copy_of_social_network_abm.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": null,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -21,7 +21,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 2,
+   "execution_count": null,
    "metadata": {
     "colab": {
      "base_uri": "https://localhost:8080/"
@@ -29,19 +29,14 @@
     "id": "NELTz5Ax_wh-",
     "outputId": "0180289a-ccae-4bf2-c783-41bf71291b80"
    },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Mesa version: 3.0.3\n"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
     "import mesa\n",
+    "print(f\"Mesa version: {mesa.__version__}\")\n",
+    "\n",
     "\n",
-    "print(f\"Mesa version: {mesa.__version__}\")"
+    "import random\n",
+    "random.random()"
    ]
   },
   {
@@ -53,7 +48,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 3,
+   "execution_count": null,
    "metadata": {
     "id": "JkBtDB_tdrIO"
    },
@@ -64,7 +59,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": null,
    "metadata": {
     "colab": {
      "base_uri": "https://localhost:8080/",
@@ -107,25 +102,7 @@
     "id": "60nsPHQ8_wh_",
     "outputId": "e5083585-0810-4c08-9d3d-5755dfb71718"
    },
-   "outputs": [
-    {
-     "data": {
-      "application/vnd.jupyter.widget-view+json": {
-       "model_id": "1144bcabdd8b4bd6aa2d4ca9a538febe",
-       "version_major": 2,
-       "version_minor": 0
-      },
-      "text/html": [
-       "Cannot show widget. You probably want to rerun the code cell above (<i>Click in the code cell, and press Shift+Enter <kbd>⇧</kbd>+<kbd>↩</kbd></i>)."
-      ],
-      "text/plain": [
-       "Cannot show ipywidgets in text"
-      ]
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    }
-   ],
+   "outputs": [],
    "source": [
     "from models.grid import GridModel\n",
     "\n",
@@ -201,27 +178,9 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": null,
    "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "application/vnd.jupyter.widget-view+json": {
-       "model_id": "97d3fb4ea5e04e38832820fe16d90ac5",
-       "version_major": 2,
-       "version_minor": 0
-      },
-      "text/html": [
-       "Cannot show widget. You probably want to rerun the code cell above (<i>Click in the code cell, and press Shift+Enter <kbd>⇧</kbd>+<kbd>↩</kbd></i>)."
-      ],
-      "text/plain": [
-       "Cannot show ipywidgets in text"
-      ]
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    }
-   ],
+   "outputs": [],
    "source": [
     "from mesa.visualization import SolaraViz, make_space_component\n",
     "from models.network import NetworkModel\n",
@@ -229,10 +188,17 @@
     "def agent_portrayal(agent):\n",
     "    return {\n",
     "        \"color\": agent.model.narrative_info[agent.opinion]['color'],\n",
-    "        \"marker\": \"s\",\n",
-    "        \"size\": 5,\n",
+    "        \"size\": 12,\n",
     "    }\n",
     "\n",
+    "algorithm_values = {\n",
+    "    \"type\": \"SliderFloat\",\n",
+    "    'initial': 0,\n",
+    "    'min': 0,\n",
+    "    'max': 0.1,\n",
+    "    'step': 0.001\n",
+    "}\n",
+    "\n",
     "model_params = {\n",
     "    \"initial_prob_a\":{\n",
     "        \"type\": \"SliderFloat\",\n",
@@ -252,11 +218,11 @@
     "    },\n",
     "    \"n\": {\n",
     "        \"type\": \"SliderInt\",\n",
-    "        \"value\": 900,\n",
+    "        \"value\": 100,\n",
     "        \"label\": \"n\",\n",
-    "        \"min\": 10,\n",
-    "        \"max\": 5000,\n",
-    "        \"step\": 100,\n",
+    "        \"min\": 1,\n",
+    "        \"max\": 1000,\n",
+    "        \"step\": 10,\n",
     "    },\n",
     "    \"k\": {\n",
     "        \"type\": \"SliderInt\",\n",
@@ -266,17 +232,29 @@
     "        \"max\": 50,\n",
     "        \"step\": 1,\n",
     "    },\n",
-    "    \"p\": {\n",
-    "        \"type\": \"SliderInt\",\n",
-    "        \"value\": 3,\n",
-    "        \"label\": \"p\",\n",
-    "        \"min\": 1,\n",
-    "        \"max\": 10,\n",
-    "        \"step\": 1,\n",
+    "    \"same_connect_prob\": {\n",
+    "        \"label\": \"same_connect_prob\",\n",
+    "        \"type\": \"SliderFloat\",\n",
+    "        **algorithm_values\n",
+    "    },\n",
+    "    \"opp_connect_prob\": {\n",
+    "        \"label\": \"opp_connect_prob\",\n",
+    "        \"type\": \"SliderFloat\",\n",
+    "        **algorithm_values\n",
+    "    },\n",
+    "    \"same_disconnect_prob\": {\n",
+    "        \"label\": \"same_disconnect_prob\",\n",
+    "        \"type\": \"SliderFloat\",\n",
+    "        **algorithm_values\n",
+    "    },\n",
+    "    \"opp_disconnect_prob\": {\n",
+    "        \"label\": \"opp_disconnect_prob\",\n",
+    "        \"type\": \"SliderFloat\",\n",
+    "        **algorithm_values\n",
     "    },\n",
     "}\n",
     "\n",
-    "model = NetworkModel()\n",
+    "model = NetworkModel(n=300)\n",
     "SpaceGraph = make_space_component(agent_portrayal)\n",
     "\n",
     "page = SolaraViz(\n",
@@ -288,133 +266,6 @@
     "\n",
     "page"
    ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 6,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "# import math\n",
-    "\n",
-    "# import solara\n",
-    "\n",
-    "# from mesa.examples.basic.virus_on_network.model import (\n",
-    "#     State,\n",
-    "#     VirusOnNetwork,\n",
-    "#     number_infected,\n",
-    "# )\n",
-    "# from mesa.visualization import (\n",
-    "#     Slider,\n",
-    "#     SolaraViz,\n",
-    "#     make_plot_component,\n",
-    "#     make_space_component,\n",
-    "# )\n",
-    "\n",
-    "\n",
-    "# def agent_portrayal(agent):\n",
-    "#     node_color_dict = {\n",
-    "#         State.INFECTED: \"tab:red\",\n",
-    "#         State.SUSCEPTIBLE: \"tab:green\",\n",
-    "#         State.RESISTANT: \"tab:gray\",\n",
-    "#     }\n",
-    "#     return {\"color\": node_color_dict[agent.state], \"size\": 10}\n",
-    "\n",
-    "\n",
-    "# def get_resistant_susceptible_ratio(model):\n",
-    "#     ratio = model.resistant_susceptible_ratio()\n",
-    "#     ratio_text = r\"$\\infty$\" if ratio is math.inf else f\"{ratio:.2f}\"\n",
-    "#     infected_text = str(number_infected(model))\n",
-    "\n",
-    "#     return solara.Markdown(\n",
-    "#         f\"Resistant/Susceptible Ratio: {ratio_text}<br>Infected Remaining: {infected_text}\"\n",
-    "#     )\n",
-    "\n",
-    "\n",
-    "# model_params = {\n",
-    "#     \"seed\": {\n",
-    "#         \"type\": \"InputText\",\n",
-    "#         \"value\": 42,\n",
-    "#         \"label\": \"Random Seed\",\n",
-    "#     },\n",
-    "#     \"num_nodes\": Slider(\n",
-    "#         label=\"Number of agents\",\n",
-    "#         value=10,\n",
-    "#         min=10,\n",
-    "#         max=100,\n",
-    "#         step=1,\n",
-    "#     ),\n",
-    "#     \"avg_node_degree\": Slider(\n",
-    "#         label=\"Avg Node Degree\",\n",
-    "#         value=3,\n",
-    "#         min=3,\n",
-    "#         max=8,\n",
-    "#         step=1,\n",
-    "#     ),\n",
-    "#     \"initial_outbreak_size\": Slider(\n",
-    "#         label=\"Initial Outbreak Size\",\n",
-    "#         value=1,\n",
-    "#         min=1,\n",
-    "#         max=10,\n",
-    "#         step=1,\n",
-    "#     ),\n",
-    "#     \"virus_spread_chance\": Slider(\n",
-    "#         label=\"Virus Spread Chance\",\n",
-    "#         value=0.4,\n",
-    "#         min=0.0,\n",
-    "#         max=1.0,\n",
-    "#         step=0.1,\n",
-    "#     ),\n",
-    "#     \"virus_check_frequency\": Slider(\n",
-    "#         label=\"Virus Check Frequency\",\n",
-    "#         value=0.4,\n",
-    "#         min=0.0,\n",
-    "#         max=1.0,\n",
-    "#         step=0.1,\n",
-    "#     ),\n",
-    "#     \"recovery_chance\": Slider(\n",
-    "#         label=\"Recovery Chance\",\n",
-    "#         value=0.3,\n",
-    "#         min=0.0,\n",
-    "#         max=1.0,\n",
-    "#         step=0.1,\n",
-    "#     ),\n",
-    "#     \"gain_resistance_chance\": Slider(\n",
-    "#         label=\"Gain Resistance Chance\",\n",
-    "#         value=0.5,\n",
-    "#         min=0.0,\n",
-    "#         max=1.0,\n",
-    "#         step=0.1,\n",
-    "#     ),\n",
-    "# }\n",
-    "\n",
-    "\n",
-    "# def post_process_lineplot(ax):\n",
-    "#     ax.set_ylim(ymin=0)\n",
-    "#     ax.set_ylabel(\"# people\")\n",
-    "#     ax.legend(bbox_to_anchor=(1.05, 1.0), loc=\"upper left\")\n",
-    "\n",
-    "\n",
-    "# SpacePlot = make_space_component(agent_portrayal)\n",
-    "# StatePlot = make_plot_component(\n",
-    "#     {\"Infected\": \"tab:red\", \"Susceptible\": \"tab:green\", \"Resistant\": \"tab:gray\"},\n",
-    "#     post_process=post_process_lineplot,\n",
-    "# )\n",
-    "\n",
-    "# model1 = VirusOnNetwork()\n",
-    "\n",
-    "# page = SolaraViz(\n",
-    "#     model1,\n",
-    "#     components=[\n",
-    "#         SpacePlot,\n",
-    "#         StatePlot,\n",
-    "#         get_resistant_susceptible_ratio,\n",
-    "#     ],\n",
-    "#     model_params=model_params,\n",
-    "#     name=\"Virus Model\",\n",
-    "# )\n",
-    "# page  # noqa"
-   ]
   }
  ],
  "metadata": {
@@ -422,7 +273,7 @@
    "provenance": []
   },
   "kernelspec": {
-   "display_name": "base",
+   "display_name": ".venv",
    "language": "python",
    "name": "python3"
   },
@@ -436,7 +287,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.12.4"
+   "version": "3.11.1"
   },
   "widgets": {
    "application/vnd.jupyter.widget-state+json": {
diff --git a/models/__pycache__/__init__.cpython-311.pyc b/models/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 7e1cd863e65a84ef4e129f7cdd8806f4f60ec039..0000000000000000000000000000000000000000
Binary files a/models/__pycache__/__init__.cpython-311.pyc and /dev/null differ
diff --git a/models/__pycache__/base.cpython-311.pyc b/models/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index 3e641e3f4cdbc8ec6fb0961b288948ef045b5492..0000000000000000000000000000000000000000
Binary files a/models/__pycache__/base.cpython-311.pyc and /dev/null differ
diff --git a/models/__pycache__/grid.cpython-311.pyc b/models/__pycache__/grid.cpython-311.pyc
deleted file mode 100644
index 4e7c8f8286b5ecff89829f272f87ca4c5ec3215b..0000000000000000000000000000000000000000
Binary files a/models/__pycache__/grid.cpython-311.pyc and /dev/null differ
diff --git a/models/__pycache__/network.cpython-311.pyc b/models/__pycache__/network.cpython-311.pyc
deleted file mode 100644
index b8f0fbe20585e75cf6c2f41dee60ccc6556d51da..0000000000000000000000000000000000000000
Binary files a/models/__pycache__/network.cpython-311.pyc and /dev/null differ
diff --git a/models/base.py b/models/base.py
index a16b76ba63c46cce118008f2e35125a50c18665e..661b9f7926c0005254833e9efe649d727124c018 100644
--- a/models/base.py
+++ b/models/base.py
@@ -7,7 +7,7 @@ class Narrative(Enum):
     A = 0
     B = 1
     C = 2
-
+    
 class BaseUser(mesa.Agent):
     """ A node in the social network. """
 
diff --git a/models/network.py b/models/network.py
index 17d84735aea3380618438a5946d06f4f32d5bd90..65fa5146dd1993aa4ad5189822cd666a548510ca 100644
--- a/models/network.py
+++ b/models/network.py
@@ -1,4 +1,5 @@
-from models.base import BaseUser, BaseModel
+import random
+from models.base import BaseUser, BaseModel, Narrative
 import mesa
 import numpy as np
 import networkx as nx
@@ -13,7 +14,7 @@ class NetworkUser(BaseUser):
 
     def _get_neighbors(self):
         return self.model.space.get_neighbors(self.unique_id)
-
+    
 class NetworkModel(BaseModel):
     """ A model of a social network. """
 
@@ -23,7 +24,12 @@ class NetworkModel(BaseModel):
         initial_prob_b = 0.4,
         n = 900,
         k = 8, 
-        p = 3
+        p = 3,
+        range = 'inf',
+        same_connect_prob = 0,
+        opp_connect_prob = 0,
+        same_disconnect_prob = 0,
+        opp_disconnect_prob = 0,
         ):
         """ Initialize the model. """
         payoff_matrix = np.array([[1, 0, 1], [0, 2, -4], [0, 0, 0]])    #from paper to calculate fitness
@@ -32,6 +38,11 @@ class NetworkModel(BaseModel):
         space = mesa.space.NetworkGrid(small_world)
 
         super().__init__(space, payoff_matrix, beta, initial_prob_a, initial_prob_b)
+        
+        self.same_connect_prob = same_connect_prob
+        self.opp_connect_prob = opp_connect_prob
+        self.same_disconnect_prob = same_disconnect_prob
+        self.opp_disconnect_prob = opp_disconnect_prob
 
     def _init_agents(self):
 
@@ -40,11 +51,49 @@ class NetworkModel(BaseModel):
             self.schedule.add(new_agent)
             self.space.place_agent(new_agent, node)
 
-        for agent in self.space.get_all_cell_contents():
+        for agent in self.agents:
             agent.calculate_fitness()
 
     def step(self):
         """ Run one step of the model. """
 
-        # do we want to explore with more activation strategies?
-        self.schedule.step() # this updates all the nodes, in random order
\ No newline at end of file
+        super().step()
+        self._reshuffle_network()
+
+    def _reshuffle_network(self):
+        agents_a = set(self.agents.select(lambda a: a.opinion == Narrative.A))
+        agents_b = set(self.agents.select(lambda a: a.opinion == Narrative.B))
+
+        for agent in self.agents:
+            neighbors = set(agent.neighbors)
+            same_group = agents_a if agent.opinion == Narrative.A else agents_b
+            opp_group = agents_b if agent.opinion == Narrative.A else agents_a
+
+            # Connect similar
+            if random.random() < self.same_connect_prob: 
+                candidates = list(same_group - neighbors)
+                if len(candidates): 
+                    same_partner = random.choice(candidates)
+                    self.space.G.add_edge(agent.unique_id, same_partner.unique_id)
+
+            # Connect opposite
+            if random.random() < self.opp_connect_prob: 
+                candidates = list(opp_group - neighbors)
+                if len(candidates): 
+                    opp_partner = random.choice(candidates)
+                    self.space.G.add_edge(agent.unique_id, opp_partner.unique_id)
+
+            # Disconnect similar
+            if random.random() < self.same_disconnect_prob: 
+                candidates = list(same_group.intersection(neighbors))
+                if len(candidates): 
+                    same_partner = random.choice(candidates)
+                    self.space.G.remove_edge(agent.unique_id, same_partner.unique_id)
+
+            # Disconnect opposite
+            if random.random() < self.opp_disconnect_prob: 
+                candidates = list(opp_group.intersection(neighbors))
+                if len(candidates): 
+                    opp_partner = random.choice(candidates)
+                    self.space.G.remove_edge(agent.unique_id, opp_partner.unique_id)
+            
\ No newline at end of file