The Retention Illusion
About This Sketch
A neural pathway visualization comparing passive exposure (reading, highlighting) to active retrieval (testing, spaced practice). Watch as exposure pathways fade rapidly while retrieval pathways strengthen through spaced reinforcement—a visual representation of the science of learning.
Algorithm
This sketch visualizes the forgetting curve and retention strength of two different learning strategies: passive exposure vs. active retrieval practice.
Each horizontal pathway represents a neural connection formed during learning. The pathways are color-coded by strategy:
- Orange pathways represent exposure-based learning (reading, highlighting, passive review)
- Brown pathways represent retrieval-based learning (testing, spaced repetition)
Exposure pathways start bright and strong but decay rapidly over time, mimicking how we quickly forget passively consumed information.
Retrieval pathways start dimmer but receive periodic reinforcement (marked with "R") at spaced intervals, simulating retrieval practice. Each retrieval event strengthens the pathway, building more durable retention.
Over time, you can observe that retrieval pathways maintain higher average strength while exposure pathways fade away—visualizing the research on effective learning strategies.
Pseudocode
SETUP:
Initialize empty pathway array
Set canvas to 400x300
FOR EACH PATHWAY:
Randomly assign strategy (exposure or retrieval)
IF exposure:
Start with high strength (255)
Set fast decay rate (2.5 per frame)
No reinforcement events
IF retrieval:
Start with medium strength (100)
Set slow decay rate (0.3 per frame)
Schedule spaced reinforcement at: 60, 150, 300, 500 frames
EACH FRAME:
Clear background with theme colors
FOR EACH PATHWAY:
Increment age
IF retrieval pathway AND at reinforcement time:
Boost strength by 80
Mark reinforcement event
Decay strength by decay rate
Draw neurons as circles
Draw connections with opacity based on strength
Display strength percentage
IF pathway strength too low:
Remove from array
Generate new pathway every 80 frames
Display statistics: count and average strength per strategy
Show legend explaining visual encoding
Source Code
let sketch = function(p) {
// Neural pathway simulation showing retention strength
let pathways = [];
let maxPathways = 20;
let time = 0;
class Pathway {
constructor(id) {
this.id = id;
this.x = p.random(50, 350);
this.y = 80 + (id % 4) * 50;
// Two learning strategies
this.strategy = p.random() > 0.5 ? 'exposure' : 'retrieval';
// Exposure: bright initially, rapid decay
// Retrieval: dim initially, slow decay with reinforcement
if (this.strategy === 'exposure') {
this.strength = 255;
this.decayRate = 2.5; // Fast decay
this.color = 'accent2'; // Orange
this.reinforcements = [];
} else {
this.strength = 100;
this.decayRate = 0.3; // Slow decay
this.color = 'accent1'; // Warm brown
// Spaced retrieval events
this.reinforcements = [60, 150, 300, 500];
this.nextReinforcement = 0;
}
this.age = 0;
this.neurons = [];
this.connections = [];
// Create neuron chain (simplified pathway)
let numNeurons = 5;
for (let i = 0; i < numNeurons; i++) {
this.neurons.push({
x: this.x + i * 20,
y: this.y + p.random(-3, 3),
size: 6
});
}
// Create connections between neurons
for (let i = 0; i < numNeurons - 1; i++) {
this.connections.push({
from: i,
to: i + 1,
strength: this.strength
});
}
}
update() {
this.age++;
// Check for retrieval reinforcement
if (this.strategy === 'retrieval') {
if (this.nextReinforcement < this.reinforcements.length) {
if (this.age >= this.reinforcements[this.nextReinforcement]) {
// Retrieval event - strengthen pathway
this.strength = p.min(255, this.strength + 80);
this.nextReinforcement++;
}
}
}
// Decay over time
this.strength = p.max(0, this.strength - this.decayRate);
// Update connection strengths
for (let conn of this.connections) {
conn.strength = this.strength;
}
return this.age < 600; // Pathway exists for 600 frames
}
display(colors) {
let pathwayColor = this.strategy === 'exposure' ? colors.accent2 : colors.accent1;
// Draw connections between neurons
for (let conn of this.connections) {
let fromNeuron = this.neurons[conn.from];
let toNeuron = this.neurons[conn.to];
let opacity = p.map(conn.strength, 0, 255, 0, 200);
let weight = p.map(conn.strength, 0, 255, 0.5, 3);
p.stroke(...pathwayColor, opacity);
p.strokeWeight(weight);
p.line(fromNeuron.x, fromNeuron.y, toNeuron.x, toNeuron.y);
}
// Draw neurons
for (let neuron of this.neurons) {
let opacity = p.map(this.strength, 0, 255, 30, 180);
p.fill(...pathwayColor, opacity);
p.noStroke();
p.circle(neuron.x, neuron.y, neuron.size);
}
// Draw retrieval markers
if (this.strategy === 'retrieval') {
for (let i = 0; i < this.reinforcements.length; i++) {
if (this.age >= this.reinforcements[i]) {
let markerY = this.y + 15;
let markerX = this.x + i * 25;
p.fill(...colors.accent1, 150);
p.noStroke();
p.circle(markerX, markerY, 4);
// Little "R" for retrieval
p.fill(...colors.accent3, 120);
p.textSize(6);
p.textAlign(p.CENTER, p.CENTER);
p.text('R', markerX, markerY);
}
}
}
// Strength indicator
let strengthPercent = p.floor((this.strength / 255) * 100);
if (strengthPercent > 5) {
p.fill(...colors.accent3, 100);
p.noStroke();
p.textSize(7);
p.textAlign(p.LEFT);
p.text(`${strengthPercent}%`, this.x + 105, this.y);
}
}
}
p.setup = function() {
p.createCanvas(400, 300);
};
p.draw = function() {
const colors = getThemeColors();
p.background(...colors.bg);
time++;
// Title
p.fill(...colors.accent3);
p.noStroke();
p.textAlign(p.CENTER);
p.textSize(12);
p.text('The Retention Illusion', 200, 20);
// Subtitle
p.textSize(7);
p.fill(...colors.accent3, 180);
p.text('Exposure fades fast. Retrieval builds strength.', 200, 32);
// Generate new pathways periodically
if (time % 80 === 0 && pathways.length < maxPathways) {
pathways.push(new Pathway(pathways.length));
}
// Update and display pathways
for (let i = pathways.length - 1; i >= 0; i--) {
if (!pathways[i].update()) {
pathways.splice(i, 1);
} else {
pathways[i].display(colors);
}
}
// Count surviving pathways by strategy
let exposureCount = 0;
let retrievalCount = 0;
let exposureAvgStrength = 0;
let retrievalAvgStrength = 0;
for (let pathway of pathways) {
if (pathway.strategy === 'exposure') {
exposureCount++;
exposureAvgStrength += pathway.strength;
} else {
retrievalCount++;
retrievalAvgStrength += pathway.strength;
}
}
if (exposureCount > 0) exposureAvgStrength /= exposureCount;
if (retrievalCount > 0) retrievalAvgStrength /= retrievalCount;
// Legend
p.textAlign(p.LEFT);
p.textSize(8);
// Exposure learning
let exposureY = 250;
p.stroke(...colors.accent2, 200);
p.strokeWeight(3);
p.line(15, exposureY, 35, exposureY);
p.noStroke();
p.fill(...colors.accent3);
p.text(`Exposure (${exposureCount})`, 40, exposureY + 3);
p.textSize(6);
p.fill(...colors.accent3, 150);
p.text('Bright initially, rapid decay', 40, exposureY + 11);
if (exposureCount > 0) {
p.text(`Avg strength: ${p.floor(exposureAvgStrength)}%`, 40, exposureY + 19);
}
// Retrieval learning
let retrievalY = 275;
p.stroke(...colors.accent1, 200);
p.strokeWeight(3);
p.line(15, retrievalY, 35, retrievalY);
p.noStroke();
p.fill(...colors.accent3);
p.textSize(8);
p.text(`Retrieval (${retrievalCount})`, 40, retrievalY + 3);
p.textSize(6);
p.fill(...colors.accent3, 150);
p.text('Spaced practice (R), builds strength', 40, retrievalY + 11);
if (retrievalCount > 0) {
p.text(`Avg strength: ${p.floor(retrievalAvgStrength)}%`, 40, retrievalY + 19);
}
// Dynamic insight
if (time > 400) {
p.fill(...colors.accent1, 200);
p.textAlign(p.CENTER);
p.textSize(7);
p.text('Retrieval pathways survive and strengthen', 200, 50);
}
};
};