Like a flock of birds moving as one or ants building complex colonies, emergent behavior demonstrates how simple individual actions can create sophisticated collective intelligence. This principle mirrors 弘익인간—individual agents following simple rules create systems that benefit all through collective wisdom and coordination.
Emergence is the phenomenon where complex system-level behaviors arise from simple agent-level rules and local interactions. No single agent orchestrates the global pattern—it emerges spontaneously from the bottom up.
Key characteristics of emergent systems:
Swarm intelligence is collective behavior that emerges from large groups of simple agents following decentralized, self-organized principles.
Swarm intelligence draws inspiration from nature:
Craig Reynolds' Boids model demonstrates how three simple rules create realistic flocking behavior:
class BoidAgent {
constructor(id, x, y) {
this.id = id;
this.position = { x, y };
this.velocity = {
x: Math.random() * 2 - 1,
y: Math.random() * 2 - 1
};
this.acceleration = { x: 0, y: 0 };
this.maxSpeed = 4;
this.maxForce = 0.1;
this.perceptionRadius = 50;
}
flock(boids) {
const neighbors = this.getNeighbors(boids, this.perceptionRadius);
const separation = this.separate(neighbors);
const alignment = this.align(neighbors);
const cohesion = this.cohere(neighbors);
// Weight the forces
separation.x *= 1.5;
separation.y *= 1.5;
alignment.x *= 1.0;
alignment.y *= 1.0;
cohesion.x *= 1.0;
cohesion.y *= 1.0;
// Apply forces
this.acceleration.x += separation.x + alignment.x + cohesion.x;
this.acceleration.y += separation.y + alignment.y + cohesion.y;
}
// Rule 1: Separation - avoid crowding neighbors
separate(neighbors) {
const desiredSeparation = 25;
const steer = { x: 0, y: 0 };
let count = 0;
for (const other of neighbors) {
const d = this.distance(this.position, other.position);
if (d > 0 && d < desiredSeparation) {
const diff = {
x: this.position.x - other.position.x,
y: this.position.y - other.position.y
};
const normalized = this.normalize(diff);
normalized.x /= d; // Weight by distance
normalized.y /= d;
steer.x += normalized.x;
steer.y += normalized.y;
count++;
}
}
if (count > 0) {
steer.x /= count;
steer.y /= count;
}
return this.limitForce(steer);
}
// Rule 2: Alignment - steer towards average heading
align(neighbors) {
const avgVel = { x: 0, y: 0 };
let count = 0;
for (const other of neighbors) {
avgVel.x += other.velocity.x;
avgVel.y += other.velocity.y;
count++;
}
if (count > 0) {
avgVel.x /= count;
avgVel.y /= count;
// Desired velocity
const desired = this.setMagnitude(avgVel, this.maxSpeed);
// Steering = desired - current
const steer = {
x: desired.x - this.velocity.x,
y: desired.y - this.velocity.y
};
return this.limitForce(steer);
}
return { x: 0, y: 0 };
}
// Rule 3: Cohesion - steer towards average position
cohere(neighbors) {
const avgPos = { x: 0, y: 0 };
let count = 0;
for (const other of neighbors) {
avgPos.x += other.position.x;
avgPos.y += other.position.y;
count++;
}
if (count > 0) {
avgPos.x /= count;
avgPos.y /= count;
return this.seek(avgPos);
}
return { x: 0, y: 0 };
}
seek(target) {
const desired = {
x: target.x - this.position.x,
y: target.y - this.position.y
};
const normalized = this.setMagnitude(desired, this.maxSpeed);
const steer = {
x: normalized.x - this.velocity.x,
y: normalized.y - this.velocity.y
};
return this.limitForce(steer);
}
update() {
// Update velocity
this.velocity.x += this.acceleration.x;
this.velocity.y += this.acceleration.y;
// Limit speed
const speed = Math.sqrt(
this.velocity.x ** 2 + this.velocity.y ** 2
);
if (speed > this.maxSpeed) {
this.velocity.x = (this.velocity.x / speed) * this.maxSpeed;
this.velocity.y = (this.velocity.y / speed) * this.maxSpeed;
}
// Update position
this.position.x += this.velocity.x;
this.position.y += this.velocity.y;
// Reset acceleration
this.acceleration = { x: 0, y: 0 };
}
getNeighbors(boids, radius) {
return boids.filter(other =>
other.id !== this.id &&
this.distance(this.position, other.position) < radius
);
}
distance(p1, p2) {
return Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
}
normalize(vec) {
const mag = Math.sqrt(vec.x ** 2 + vec.y ** 2);
return mag > 0 ? { x: vec.x / mag, y: vec.y / mag } : { x: 0, y: 0 };
}
setMagnitude(vec, mag) {
const normalized = this.normalize(vec);
return { x: normalized.x * mag, y: normalized.y * mag };
}
limitForce(force) {
const mag = Math.sqrt(force.x ** 2 + force.y ** 2);
if (mag > this.maxForce) {
return {
x: (force.x / mag) * this.maxForce,
y: (force.y / mag) * this.maxForce
};
}
return force;
}
}
// 弘益人間: Simple rules creating harmonious collective movement
Ant Colony Optimization (ACO) uses principles of ant foraging behavior to solve optimization problems like finding shortest paths.
class AntColonyOptimizer {
constructor(graph, numAnts, iterations) {
this.graph = graph;
this.numAnts = numAnts;
this.iterations = iterations;
this.pheromones = new Map();
this.alpha = 1.0; // Pheromone importance
this.beta = 2.0; // Distance importance
this.evaporation = 0.5;
this.Q = 100; // Pheromone deposit factor
this.initializePheromones();
}
initializePheromones() {
for (const edge of this.graph.edges) {
this.pheromones.set(edge.id, 1.0);
}
}
solve(start, end) {
let bestPath = null;
let bestLength = Infinity;
for (let iter = 0; iter < this.iterations; iter++) {
const paths = [];
// Each ant constructs a solution
for (let a = 0; a < this.numAnts; a++) {
const path = this.constructAntPath(start, end);
if (path) {
paths.push(path);
if (path.length < bestLength) {
bestLength = path.length;
bestPath = path;
}
}
}
// Update pheromones
this.evaporatePheromones();
this.depositPheromones(paths);
}
return { path: bestPath, length: bestLength };
}
constructAntPath(start, end) {
const path = [start];
const visited = new Set([start]);
let current = start;
while (current !== end) {
const next = this.selectNextNode(current, visited);
if (!next) {
return null; // Dead end
}
path.push(next);
visited.add(next);
current = next;
// Prevent infinite loops
if (path.length > this.graph.nodes.length) {
return null;
}
}
return {
nodes: path,
length: this.calculatePathLength(path)
};
}
selectNextNode(current, visited) {
const neighbors = this.graph.getNeighbors(current);
const unvisited = neighbors.filter(n => !visited.has(n));
if (unvisited.length === 0) {
return null;
}
// Calculate probabilities using pheromone and distance
const probabilities = unvisited.map(node => {
const edge = this.graph.getEdge(current, node);
const pheromone = this.pheromones.get(edge.id);
const distance = edge.weight;
return {
node: node,
probability: Math.pow(pheromone, this.alpha) *
Math.pow(1 / distance, this.beta)
};
});
// Normalize probabilities
const sum = probabilities.reduce((s, p) => s + p.probability, 0);
probabilities.forEach(p => p.probability /= sum);
// Roulette wheel selection
const r = Math.random();
let cumulative = 0;
for (const p of probabilities) {
cumulative += p.probability;
if (r <= cumulative) {
return p.node;
}
}
return probabilities[probabilities.length - 1].node;
}
evaporatePheromones() {
for (const [edgeId, level] of this.pheromones) {
this.pheromones.set(edgeId, level * (1 - this.evaporation));
}
}
depositPheromones(paths) {
for (const path of paths) {
const deposit = this.Q / path.length;
for (let i = 0; i < path.nodes.length - 1; i++) {
const edge = this.graph.getEdge(path.nodes[i], path.nodes[i + 1]);
const current = this.pheromones.get(edge.id);
this.pheromones.set(edge.id, current + deposit);
}
}
}
calculatePathLength(path) {
let length = 0;
for (let i = 0; i < path.length - 1; i++) {
const edge = this.graph.getEdge(path[i], path[i + 1]);
length += edge.weight;
}
return length;
}
}
// 弘益人間: Collective optimization through stigmergy
PSO is inspired by social behavior of bird flocking and fish schooling to find optimal solutions in multi-dimensional search spaces.
class ParticleSwarmOptimizer {
constructor(objectiveFunction, dimensions, numParticles) {
this.objectiveFunction = objectiveFunction;
this.dimensions = dimensions;
this.numParticles = numParticles;
this.particles = [];
this.globalBestPosition = null;
this.globalBestValue = Infinity;
// PSO parameters
this.inertia = 0.7;
this.cognitiveWeight = 1.5;
this.socialWeight = 1.5;
this.initializeParticles();
}
initializeParticles() {
for (let i = 0; i < this.numParticles; i++) {
const position = this.randomPosition();
const velocity = this.randomVelocity();
const value = this.objectiveFunction(position);
this.particles.push({
id: i,
position: position,
velocity: velocity,
personalBestPosition: [...position],
personalBestValue: value
});
if (value < this.globalBestValue) {
this.globalBestValue = value;
this.globalBestPosition = [...position];
}
}
}
optimize(iterations) {
for (let iter = 0; iter < iterations; iter++) {
for (const particle of this.particles) {
this.updateParticle(particle);
}
}
return {
position: this.globalBestPosition,
value: this.globalBestValue
};
}
updateParticle(particle) {
// Update velocity
for (let d = 0; d < this.dimensions; d++) {
const r1 = Math.random();
const r2 = Math.random();
const cognitive = this.cognitiveWeight * r1 *
(particle.personalBestPosition[d] - particle.position[d]);
const social = this.socialWeight * r2 *
(this.globalBestPosition[d] - particle.position[d]);
particle.velocity[d] =
this.inertia * particle.velocity[d] +
cognitive +
social;
// Limit velocity
const maxVelocity = 1.0;
particle.velocity[d] = Math.max(-maxVelocity,
Math.min(maxVelocity, particle.velocity[d]));
}
// Update position
for (let d = 0; d < this.dimensions; d++) {
particle.position[d] += particle.velocity[d];
// Keep within bounds
particle.position[d] = Math.max(-10,
Math.min(10, particle.position[d]));
}
// Evaluate new position
const value = this.objectiveFunction(particle.position);
// Update personal best
if (value < particle.personalBestValue) {
particle.personalBestValue = value;
particle.personalBestPosition = [...particle.position];
}
// Update global best
if (value < this.globalBestValue) {
this.globalBestValue = value;
this.globalBestPosition = [...particle.position];
}
}
randomPosition() {
return Array(this.dimensions).fill(0).map(() =>
Math.random() * 20 - 10
);
}
randomVelocity() {
return Array(this.dimensions).fill(0).map(() =>
Math.random() * 2 - 1
);
}
}
// Example usage: minimize Rastrigin function
const rastrigin = (x) => {
const A = 10;
const n = x.length;
return A * n + x.reduce((sum, xi) =>
sum + (xi * xi - A * Math.cos(2 * Math.PI * xi)), 0
);
};
const pso = new ParticleSwarmOptimizer(rastrigin, 2, 30);
const result = pso.optimize(100);
// 弘益人間: Swarm intelligence finding optimal solutions
Cellular automata demonstrate how simple local rules create complex global patterns.
class CellularAutomaton {
constructor(width, height, rule) {
this.width = width;
this.height = height;
this.rule = rule;
this.grid = this.initializeGrid();
this.generation = 0;
}
initializeGrid() {
const grid = [];
for (let y = 0; y < this.height; y++) {
grid[y] = [];
for (let x = 0; x < this.width; x++) {
grid[y][x] = Math.random() > 0.5 ? 1 : 0;
}
}
return grid;
}
// Conway's Game of Life rules
gameOfLifeRule(x, y) {
const neighbors = this.countNeighbors(x, y);
const current = this.grid[y][x];
if (current === 1) {
// Live cell
return neighbors === 2 || neighbors === 3 ? 1 : 0;
} else {
// Dead cell
return neighbors === 3 ? 1 : 0;
}
}
countNeighbors(x, y) {
let count = 0;
for (let dy = -1; dy <= 1; dy++) {
for (let dx = -1; dx <= 1; dx++) {
if (dx === 0 && dy === 0) continue;
const nx = (x + dx + this.width) % this.width;
const ny = (y + dy + this.height) % this.height;
count += this.grid[ny][nx];
}
}
return count;
}
step() {
const newGrid = [];
for (let y = 0; y < this.height; y++) {
newGrid[y] = [];
for (let x = 0; x < this.width; x++) {
newGrid[y][x] = this.rule(x, y);
}
}
this.grid = newGrid;
this.generation++;
}
run(steps) {
for (let i = 0; i < steps; i++) {
this.step();
}
}
countLiveCells() {
return this.grid.reduce((sum, row) =>
sum + row.reduce((rowSum, cell) => rowSum + cell, 0), 0
);
}
}
// Create Game of Life simulation
const ca = new CellularAutomaton(50, 50,
(x, y) => ca.gameOfLifeRule(x, y)
);
ca.run(100);
console.log(`Live cells after 100 generations: ${ca.countLiveCells()}`);
// 弘益人間: Emergent patterns from simple local rules
Self-organizing systems exhibit several key principles:
Stigmergy is indirect coordination through environmental modification. Agents leave traces in the environment that influence future agent behaviors.
class StigmergySystem {
constructor() {
this.environment = new Map();
this.agents = [];
this.evaporationRate = 0.01;
}
depositPheromone(location, amount, type = 'trail') {
const key = `${location.x},${location.y}`;
const current = this.environment.get(key) || { trail: 0, marker: 0 };
current[type] += amount;
this.environment.set(key, current);
}
getPheromone(location, type = 'trail') {
const key = `${location.x},${location.y}`;
const cell = this.environment.get(key);
return cell ? cell[type] : 0;
}
evaporate() {
for (const [key, cell] of this.environment) {
cell.trail *= (1 - this.evaporationRate);
cell.marker *= (1 - this.evaporationRate);
if (cell.trail < 0.01 && cell.marker < 0.01) {
this.environment.delete(key);
} else {
this.environment.set(key, cell);
}
}
}
step() {
// Agents move and deposit pheromones
for (const agent of this.agents) {
agent.move(this);
this.depositPheromone(agent.position, 1.0);
}
// Evaporate pheromones
this.evaporate();
}
}
// 弘益人間: Coordination through environmental traces