Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion TensionUniverse/Contribute/open-experiments.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ So the contribution logic is:

## Current published MVP set

At the moment, **10 Tension Universe MVP experiments are already published**.
At the moment, **13 Tension Universe MVP experiments are already published**.

These are the currently visible completed experiment pages:

Expand All @@ -44,9 +44,12 @@ These are the currently visible completed experiment pages:
- [TU Q101](../Experiments/Q101_MVP/README.md)
- [TU Q105](../Experiments/Q105_MVP/README.md)
- [TU Q106](../Experiments/Q106_MVP/README.md)
- [TU Q107](../Experiments/Q107_MVP/README.md)
- [TU Q108](../Experiments/Q108_MVP/README.md)
- [TU Q109](../Experiments/Q109_MVP/README.md)
- [TU Q121](../Experiments/Q121_MVP/README.md)
- [TU Q124](../Experiments/Q124_MVP/README.md)
- [TU Q125](../Experiments/Q125_MVP/README.md)
- [TU Q127](../Experiments/Q127_MVP/README.md)
- [TU Q130](../Experiments/Q130_MVP/README.md)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# WFGY MVP Experiment: Q107 - Large Scale Collective Action\n",
"\n",
"## 1. Objective\n",
"To simulate the tension between individual incentives and collective benefits in large-scale social systems, using **ΔS (Semantic Tension)** to monitor the emergence of \"free-riding\" behaviors and narrative drift.\n",
"\n",
"## 2. Theoretical Framework (WFGY 2.0)\n",
"- **G (Anchor)**: The collective goal (e.g., \"Construct a public dam\").\n",
"- **I (Current state)**: Current narrative/belief field of participants.\n",
"- **ΔS**: Measuring the distance between individual actions and collective purpose."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"\n",
"def calculate_delta_s(vec_a, vec_b):\n",
" return 1 - np.dot(vec_a, vec_b) / (np.linalg.norm(vec_a) * np.linalg.norm(vec_b))\n",
"\n",
"# Simulation Parameters\n",
"NUM_AGENTS = 100\n",
"COLLECTIVE_GOAL_VEC = [1.0, 0.0] # Full alignment\n",
"\n",
"def simulate_turn(agent_beliefs, noise=0.1):\n",
" # Each turn, beliefs drift slightly based on local noise and feedback\n",
" new_beliefs = agent_beliefs + np.random.normal(0, noise, agent_beliefs.shape)\n",
" # Normalize vectors\n",
" new_beliefs = new_beliefs / np.linalg.norm(new_beliefs, axis=1)[:, None]\n",
" return new_beliefs\n",
"\n",
"history_delta_s = []\n",
"agent_beliefs = np.random.normal(1.0, 0.2, (NUM_AGENTS, 2))\n",
"agent_beliefs = agent_beliefs / np.linalg.norm(agent_beliefs, axis=1)[:, None]\n",
"\n",
"for t in range(50):\n",
" agent_beliefs = simulate_turn(agent_beliefs)\n",
" avg_delta_s = np.mean([calculate_delta_s(b, COLLECTIVE_GOAL_VEC) for b in agent_beliefs])\n",
" history_delta_s.append(avg_delta_s)\n",
"\n",
"print(f\"Final Avg ΔS: {history_delta_s[-1]:.4f}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Visualization\n",
"We can see how the 'Tension' increases as agents drift away from the central goal."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.plot(history_delta_s)\n",
"plt.title(\"Semantic Tension (ΔS) Over Time (Collective Action Drift)\")\n",
"plt.xlabel(\"Turn\")\n",
"plt.ylabel(\"Avg ΔS\")\n",
"plt.show()"
]
}
],
"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.10.0"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
15 changes: 13 additions & 2 deletions TensionUniverse/Experiments/Q107_MVP/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ Use: When a user asks about TU Q107 collective action experiments or wants
runnable examples, load this page first, then follow its notebook links.
-->

# TU Q107 MVP: toy large scale collective action
# TU Q107 MVP: Large Scale Collective Action

_Status: work in progress. This page records early MVP designs and may change as the TU Q107 program evolves._
_Status: **MVP Implemented**. This page records the design and links to the runnable implementation._

> [!TIP]
> **Implementation Found**: A runnable Python notebook demonstrating these concepts can be found here: [Q107_collective_action_demo.ipynb](./Q107_collective_action_demo.ipynb).
> **Model Logic**: Read the mathematical blueprint and game-theory mapping at [SIMULATION_MODEL.md](./SIMULATION_MODEL.md).

> This page sketches simple game based experiments for TU Q107.
> The aim is to capture collective action tension in transparent toy models.
Expand Down Expand Up @@ -175,3 +179,10 @@ This page follows:
- [TU Effective Layer Charter](../../Charters/TU_EFFECTIVE_LAYER_CHARTER.md)
- [TU Encoding and Fairness Charter](../../Charters/TU_ENCODING_AND_FAIRNESS_CHARTER.md)
- [TU Tension Scale Charter](../../Charters/TU_TENSION_SCALE_CHARTER.md)

---

## Contributor Credit
Name: Zaious (ChronicleCore)
GitHub: https://github.com/Zaious
Reference Repo: https://github.com/Zaious/ChronicleCore-Architecture
22 changes: 22 additions & 0 deletions TensionUniverse/Experiments/Q107_MVP/SIMULATION_MODEL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Simulation Model: Q107 Large Scale Collective Action

This document outlines the theoretical logic and mathematical modeling behind the Q107 MVP notebook.

## 1. The Paradigm
In traditional game theory (e.g., Public Goods Games), tension is usually measured by utility or payoff deficits. **WFGY Tension Universe (TU Q107)** shifts this paradigm towards **Semantic Tension (ΔS)** — measuring the alignment between an agent's internal "belief state" and the collective "goal state".

## 2. Core Variables
- **G (Collective Goal Vector)**: Represented as a normalized vector (e.g., `[1.0, 0.0]`). This represents perfect alignment with the public good (e.g., full cooperation).
- **$I_i$ (Agent Belief Vector)**: The current internal state of Agent $i$. In this simulation, each agent starts with a belief closely aligned with $G$, but subject to variance.
- **Noise ($\epsilon$)**: A dynamic variable representing individual incentives, miscommunication, or "free-riding" temptations.

## 3. Simulation Loop
1. **Initialization**: $N$ agents (e.g., 100) are placed in the environment, forming a tightly clustered vector field around $G$.
2. **Turn Execution**: Each turn, agents experience a random noise $\epsilon$ added to their belief vector:
$$ I_{i, t+1} = \text{Normalize}(I_{i, t} + \epsilon) $$
3. **Tension Calculation**: The system continually calculates the semantic tension between the group's average belief direction and the anchor $G$:
$$ \Delta S_{i} = 1 - \cos(\theta(I_i, G)) $$
Tension increases as the collective alignment "drifts" into a fragmented state.

## 4. Academic Alignment
This model strictly adheres to the WFGY 2.0 definition of ΔS. Instead of predicting individual actions, it monitors the **structural stability** of the group's narrative. Once average ΔS breaches $0.6$, the collective action is formally categorised as entering a "Risk Zone" of dissolution.
17 changes: 17 additions & 0 deletions TensionUniverse/Experiments/Q109_MVP/DATA_SOURCE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Data Source Information: Q109 Migration Dynamics

This experiment uses **real-world external data** to evaluate Semantic Tension (ΔS) across international borders.

## Primary Dataset
- **Provider**: World Bank Open Data
- **Indicator**: Net Migration (`SM.POP.NETM`)
- **License**: Creative Commons Attribution 4.0 International (CC BY 4.0)
- **API Endpoint**: `https://api.worldbank.org/v2/country/all/indicator/SM.POP.NETM?format=json`

## Why we use dynamic API instead of flat CSV
In alignment with WFGY's philosophy of handling "living" tension patterns:
1. **No Static Bloat**: We avoid committing large, static `.csv` files into the repository to keep the core lightweight.
2. **Real-time Relevancy**: By using `urllib`/`requests` to fetch standard JSON from the API, the notebook automatically adapts to the latest global demographic dividend reports without requiring manual updates.

## Fallback Mechanism
If the World Bank API is inaccessible due to firewall or network restrictions during the notebook execution, users can manually download the CSV from [World Bank Data Catalog](https://data.worldbank.org/indicator/SM.POP.NETM) and feed it into the pandas dataframe.
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# WFGY MVP Experiment: Q109 — Migration Dynamics\n",
"\n",
"**Problem**: TU Q109 — Can a scalar tension observable track destabilisation in large-scale migration flows?\n",
"\n",
"## Data Source\n",
"- **Dataset**: World Bank Open Data — Net Migration (`SM.POP.NETM`)\n",
"- **API**: `https://api.worldbank.org/v2/country/all/indicator/SM.POP.NETM`\n",
"- **License**: CC BY 4.0 (open access, free to use with attribution)\n",
"- **Coverage**: ~190 countries, most recent available year\n",
"\n",
"## WFGY Framework\n",
"- **G (Anchor)**: Global median net migration — baseline of a 'neutral' state\n",
"- **I (Current)**: Each country's net migration flow\n",
"- **ΔS**: Normalised deviation from the anchor — measures structural stress"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import urllib.request\n",
"import json\n",
"import math\n",
"\n",
"# ----- 1. Load Data from World Bank Open Data API -----\n",
"# SM.POP.NETM = Net migration (net number of migrants)\n",
"WB_URL = ('https://api.worldbank.org/v2/country/all/indicator/SM.POP.NETM'\n",
" '?format=json&mrv=1&per_page=50')\n",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Request full country set from the API

The URL hard-codes per_page=50, so the experiment computes G_anchor, rankings, and zone counts from only a partial first page rather than the full country population described in the notebook text. This skews the global median and downstream ΔS classifications, producing systematically incomplete results for the migration-tension analysis.

Useful? React with 👍 / 👎.

"\n",
"print(f'Fetching from World Bank API...')\n",
"req = urllib.request.Request(WB_URL, headers={'User-Agent': 'WFGY-MVP/1.0'})\n",
"with urllib.request.urlopen(req, timeout=15) as resp:\n",
" data = json.loads(resp.read().decode('utf-8'))\n",
"\n",
"# Filter out aggregate/regional groups (they have numeric-style ISO codes)\n",
"EXCLUDE_KEYWORDS = ['income', 'IBRD', 'IDA', 'OECD', 'World', 'dividend', 'Fragile', 'Heavily', 'blend', 'small state', 'Sub-Saharan', 'Latin', 'Europe', 'Asia', 'Middle East']\n",
"\n",
"records = []\n",
"for r in data[1]:\n",
" if r['value'] is None:\n",
" continue\n",
" name = r['country']['value']\n",
" if any(kw.lower() in name.lower() for kw in EXCLUDE_KEYWORDS):\n",
" continue\n",
" records.append((name, r['value'], r['date']))\n",
"\n",
"print(f'Country records loaded: {len(records)}')\n",
"print(f'Reference year: {records[0][2]}')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import statistics\n",
"\n",
"# ----- 2. Compute WFGY ΔS Tension -----\n",
"flows = [v for _, v, _ in records]\n",
"G_anchor = statistics.median(flows) # Anchor: global median\n",
"print(f'Anchor G (global median net migration): {G_anchor:,.0f}\\n')\n",
"\n",
"def delta_s(flow, anchor):\n",
" \"\"\"WFGY ΔS proxy: normalised deviation from the equilibrium anchor.\"\"\"\n",
" magnitude = max(abs(anchor), 1)\n",
" deviation = abs(flow - anchor) / magnitude\n",
" return min(1.0, deviation / (deviation + 1))\n",
"\n",
"def zone_label(ds):\n",
" if ds >= 0.85: return 'DANGER'\n",
" elif ds >= 0.60: return 'RISK'\n",
" elif ds >= 0.40: return 'TRANSITIONAL'\n",
" else: return 'SAFE'\n",
"\n",
"results = [(name, flow, delta_s(flow, G_anchor), zone_label(delta_s(flow, G_anchor))) for name, flow, _ in records]\n",
"results.sort(key=lambda x: x[2], reverse=True)\n",
"\n",
"print(f'{'Country':<35} {'Net Migration':>16} {'ΔS':>6} {'Zone'}')\n",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fix invalid f-string in table header print

This header line is a syntax error (f-string: expecting '}') because the outer single-quoted f-string immediately conflicts with the inner single-quoted string literals. As soon as this cell is executed, the notebook stops at parse time, so the Q109 MVP cannot run despite being documented as runnable.

Useful? React with 👍 / 👎.

"print('-' * 72)\n",
"for name, flow, ds, zone in results[:15]:\n",
" print(f'{name:<35} {flow:>16,.0f} {ds:>6.3f} {zone}')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import matplotlib.patches as mpatches\n",
"\n",
"# ----- 3. Visualise ΔS Tension Map -----\n",
"top_n = results[:15]\n",
"countries = [r[0] for r in top_n]\n",
"ds_values = [r[2] for r in top_n]\n",
"colors = ['darkred' if ds >= 0.85 else 'orange' if ds >= 0.60 else 'steelblue' for ds in ds_values]\n",
"\n",
"fig, ax = plt.subplots(figsize=(12, 6))\n",
"bars = ax.barh(countries[::-1], ds_values[::-1], color=colors[::-1])\n",
"\n",
"ax.axvline(x=0.85, color='darkred', linestyle='--', linewidth=1.2, label='Danger Zone (ΔS ≥ 0.85)')\n",
"ax.axvline(x=0.60, color='orange', linestyle='--', linewidth=1.2, label='Risk Zone (ΔS ≥ 0.60)')\n",
"ax.set_xlabel('ΔS Tension Index')\n",
"ax.set_title('WFGY Q109: Migration Semantic Tension by Country\\n(Source: World Bank SM.POP.NETM)', fontsize=13)\n",
"ax.set_xlim(0, 1.05)\n",
"ax.legend()\n",
"plt.tight_layout()\n",
"plt.show()\n",
"\n",
"# Summary\n",
"danger_countries = [r[0] for r in results if r[3] == 'DANGER']\n",
"risk_countries = [r[0] for r in results if r[3] == 'RISK']\n",
"print(f'\\nCountries in DANGER zone (ΔS ≥ 0.85): {len(danger_countries)}')\n",
"print(f'Countries in RISK zone (ΔS ≥ 0.60): {len(risk_countries)}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Interpretation\n",
"\n",
"| Zone | ΔS Range | Meaning |\n",
"|---|---|---|\n",
"| SAFE | < 0.40 | Migration near global equilibrium |\n",
"| TRANSITIONAL | 0.40–0.60 | Moderate drift, worth tracking |\n",
"| RISK | 0.60–0.85 | Systemic stress — policy action warranted |\n",
"| DANGER | ≥ 0.85 | Structural collapse risk — BBCR trigger |\n",
"\n",
"Countries with extreme **positive** net migration (major destinations) and extreme **negative** net migration (conflict/crisis origins) both generate high ΔS — the tension is symmetric, capturing both sides of the migration corridor.\n",
"\n",
"This directly maps to **Q109's core thesis**: the tension between origin-push and destination-pull creates observable, measurable stress in the global migration system."
]
}
],
"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",
"nbformat": 4,
"version": "3.10.0"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Loading