Published
Edited
Apr 30, 2021
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
color = {
const scale = d3.scaleSequential(["blue", "red"]).domain([1,2])
return d => scale(fitnessEvolution[showGeneration - 1][d.index]);
}
Insert cell
Insert cell
Insert cell
fitnessEvolution = {
const initial = initialFitness
const gen = [initial];
for (let i = 0; i < r-1; ++i) {
let pop = gen[gen.length - 1]

// Clone previous fitness
const nextFitness = pop.map(d => d)
// Pick a random birth node proportional to fitness
const nodeBirth = pickRandom(network.nodes, d => nextFitness[d.index])
// Pick a neighbouring node to replace
const neighbours = getNeighbours(nodeBirth)
const nodeDeath = pickRandom(neighbours, d => 1 / nextFitness[d.index])
nextFitness.birth = nodeBirth.index
nextFitness.death = nodeDeath.index
nextFitness.neighbours = neighbours
nextFitness.neighboursFitness = neighbours.map(d => nextFitness[d])
// Replace death node with birth node (replace the fitness)
nextFitness[nodeDeath.index] = nextFitness[nodeBirth.index]
gen.push(nextFitness)
}
return gen
}
Insert cell
initialFitness = network.nodes.map(node => {
if (node.index < initialNumberOfMutants) {
return relativeFitness
}
return 1
})
Insert cell
network = {
const network = graphLattice

const links = network.links//.map(d => Object.create(d));
const nodes = network.nodes//.map(d => Object.create(d));
const simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).id(d => d.index).strength(1).distance(20).iterations(10))
.force("charge", d3.forceManyBody().strength(-50))
.force("center", d3.forceCenter(width / 2, height / 2));

const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.attr("width", width)
.attr("height", height);

const link = svg.append("g")
.attr("stroke", "#999")
.attr("stroke-opacity", 0.6)
.selectAll("line")
.data(links)
.join("line")
.attr("stroke-width", d => Math.sqrt(d.value));

const node = svg.append("g")
.attr("stroke", "#fff")
.attr("stroke-width", 1.5)
.selectAll("circle")
.data(nodes)
.join("circle")
.attr("class", "node")
.attr("r", 5)
.attr("fill", "black")
.call(drag(simulation));

node.append("title")
.text(d => d.id);

simulation.on("tick", () => {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);

node
.attr("cx", d => d.x)
.attr("cy", d => d.y);
});

invalidation.then(() => simulation.stop());

return { nodes, links, svg, simulation }
}
Insert cell
graphLattice = {
const n = latticeSize;
const nodes = Array.from({length: n * n}, (_, i) => ({index: i, links: [], outLinks: [], inLinks: []}));
const links = [];
for (let y = 0; y < n; ++y) {
for (let x = 0; x < n; ++x) {
if (y > 0) {
const link = {source: (y - 1) * n + x, target: y * n + x}
links.push(link);
nodes[link.source].outLinks.push({...link})
nodes[link.target].inLinks.push({...link})
}
if (x > 0) {
const link = {source: y * n + (x - 1), target: y * n + x}
links.push(link);
nodes[link.source].outLinks.push({...link})
nodes[link.target].inLinks.push({...link})
}
}
}
return {nodes, links};
}
Insert cell
function getNeighbours(node) {
return [...node.outLinks.map(link => link.target), ...node.inLinks.map(link => link.source)]
.map(index => network.nodes[index])
}
Insert cell
getNeighbours(network.nodes[1])
Insert cell
network.nodes[0].outLinks
Insert cell
Insert cell
pickRandom([
['a', 1],
['b', 2],
['c', 3],
['d', 4]
], item => item[1])
Insert cell
function pickRandom(items, getWeight = () => 1) {
// Will contain the sum of all weights
let sum = 0;
// Will contain an array of each weight accumilating the sum of previous weights
const accumulatedWeights = [];

items.forEach((item, i) => {
const weight = getWeight(item, i)
sum += weight
accumulatedWeights.push(sum);
})

const rand = random() * sum;
const item = items[accumulatedWeights.filter(element => element <= rand).length];

return item;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more