components -> site

This commit is contained in:
Michael Peters 2024-08-12 21:02:53 -07:00
parent 834d4443dc
commit 7a986b3296
21 changed files with 111 additions and 113 deletions

View File

@ -1,4 +1,4 @@
# AI in the Browser
## In this Repo:
- [Snake Lab](src/components/snake) - [Live](https://beefslab.com/webapps/snake-lab)
- [Snake Lab](src/site/snake) - [Live](https://beefslab.com/webapps/snake-lab)

View File

@ -1,6 +1,6 @@
import { createRoot } from 'react-dom/client';
import App from './components/app';
import App from './site/app';
import './index.scss';

View File

@ -94,9 +94,7 @@ const SnakePage: FC = () => {
<div>5,000 snakes per generation</div>
<div>Press Spacebar for Slow Motion</div>
<div>
<a href="https://git.beefslab.com/michael/webai/src/branch/master/src/components/snake">
View Repo
</a>
<a href="https://git.beefslab.com/michael/webai/src/branch/master/src/site/snake">View Repo</a>
</div>
</div>
</div>

View File

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View File

@ -1,93 +1,93 @@
import { alignGenome, compatibilityDistance } from '../components/snake/brain-neat';
import { alignGenome, compatibilityDistance } from '../site/snake/brain-neat';
import { assert, addTest } from './tests';
function testAlignGenome() {
// these genomes are taken from the NEAT paper's example
const genomeA = [
{ innovation: 1, src_id: 'A', dst_id: 'D', weight: 4, enabled: true },
{ innovation: 2, src_id: 'B', dst_id: 'D', weight: 0, enabled: false },
{ innovation: 3, src_id: 'C', dst_id: 'D', weight: 3, enabled: true },
{ innovation: 4, src_id: 'B', dst_id: 'E', weight: 9, enabled: true },
{ innovation: 5, src_id: 'E', dst_id: 'D', weight: 5, enabled: true },
// disjoint
{ innovation: 8, src_id: 'A', dst_id: 'E', weight: 7, enabled: true },
];
const genomeB = [
{ innovation: 1, src_id: 'A', dst_id: 'D', weight: 8, enabled: true },
{ innovation: 2, src_id: 'B', dst_id: 'D', weight: 1, enabled: false },
{ innovation: 3, src_id: 'C', dst_id: 'D', weight: 2, enabled: true },
{ innovation: 4, src_id: 'B', dst_id: 'E', weight: 9, enabled: true },
{ innovation: 5, src_id: 'E', dst_id: 'D', weight: 3, enabled: false },
// disjoint
{ innovation: 6, src_id: 'E', dst_id: 'F', weight: 5, enabled: true },
{ innovation: 7, src_id: 'F', dst_id: 'D', weight: 5, enabled: true },
// excess
{ innovation: 9, src_id: 'C', dst_id: 'E', weight: 5, enabled: true },
{ innovation: 10, src_id: 'A', dst_id: 'F', weight: 5, enabled: true },
];
// these genomes are taken from the NEAT paper's example
const genomeA = [
{ innovation: 1, src_id: 'A', dst_id: 'D', weight: 4, enabled: true },
{ innovation: 2, src_id: 'B', dst_id: 'D', weight: 0, enabled: false },
{ innovation: 3, src_id: 'C', dst_id: 'D', weight: 3, enabled: true },
{ innovation: 4, src_id: 'B', dst_id: 'E', weight: 9, enabled: true },
{ innovation: 5, src_id: 'E', dst_id: 'D', weight: 5, enabled: true },
// disjoint
{ innovation: 8, src_id: 'A', dst_id: 'E', weight: 7, enabled: true },
];
const genomeB = [
{ innovation: 1, src_id: 'A', dst_id: 'D', weight: 8, enabled: true },
{ innovation: 2, src_id: 'B', dst_id: 'D', weight: 1, enabled: false },
{ innovation: 3, src_id: 'C', dst_id: 'D', weight: 2, enabled: true },
{ innovation: 4, src_id: 'B', dst_id: 'E', weight: 9, enabled: true },
{ innovation: 5, src_id: 'E', dst_id: 'D', weight: 3, enabled: false },
// disjoint
{ innovation: 6, src_id: 'E', dst_id: 'F', weight: 5, enabled: true },
{ innovation: 7, src_id: 'F', dst_id: 'D', weight: 5, enabled: true },
// excess
{ innovation: 9, src_id: 'C', dst_id: 'E', weight: 5, enabled: true },
{ innovation: 10, src_id: 'A', dst_id: 'F', weight: 5, enabled: true },
];
const alignment = alignGenome(genomeA, genomeB);
const alignment = alignGenome(genomeA, genomeB);
assert(alignment.matching.length === 5);
assert(alignment.disjoint.length === 3);
assert(alignment.excess.length === 2);
assert(alignment.matching.length === 5);
assert(alignment.disjoint.length === 3);
assert(alignment.excess.length === 2);
const matchingPair = alignment.matching[1]!;
assert(matchingPair.a === genomeA[1]);
assert(matchingPair.b === genomeB[1]);
const matchingPair = alignment.matching[1]!;
assert(matchingPair.a === genomeA[1]);
assert(matchingPair.b === genomeB[1]);
const disjointPairA = alignment.disjoint[0]!;
assert(disjointPairA.a === null);
assert(disjointPairA.b === genomeB[5]);
const disjointPairA = alignment.disjoint[0]!;
assert(disjointPairA.a === null);
assert(disjointPairA.b === genomeB[5]);
const disjointPairB = alignment.disjoint[2]!;
assert(disjointPairB.a === genomeA[5]);
assert(disjointPairB.b === null);
const disjointPairB = alignment.disjoint[2]!;
assert(disjointPairB.a === genomeA[5]);
assert(disjointPairB.b === null);
const excessPair = alignment.excess[0]!;
assert(excessPair.a === null);
assert(excessPair.b === genomeB[7]);
const excessPair = alignment.excess[0]!;
assert(excessPair.a === null);
assert(excessPair.b === genomeB[7]);
}
addTest(testAlignGenome);
function testCompatibilityDistance() {
// these genomes are taken from the NEAT paper's example
const genomeA = [
{ innovation: 1, src_id: 'A', dst_id: 'D', weight: 4, enabled: true },
{ innovation: 2, src_id: 'B', dst_id: 'D', weight: 0, enabled: false },
{ innovation: 3, src_id: 'C', dst_id: 'D', weight: 3, enabled: true },
{ innovation: 4, src_id: 'B', dst_id: 'E', weight: 9, enabled: true },
{ innovation: 5, src_id: 'E', dst_id: 'D', weight: 5, enabled: true },
// disjoint
{ innovation: 8, src_id: 'A', dst_id: 'E', weight: 7, enabled: true },
];
const genomeB = [
{ innovation: 1, src_id: 'A', dst_id: 'D', weight: 8, enabled: true },
{ innovation: 2, src_id: 'B', dst_id: 'D', weight: 1, enabled: false },
{ innovation: 3, src_id: 'C', dst_id: 'D', weight: 2, enabled: true },
{ innovation: 4, src_id: 'B', dst_id: 'E', weight: 9, enabled: true },
{ innovation: 5, src_id: 'E', dst_id: 'D', weight: 3, enabled: false },
// disjoint
{ innovation: 6, src_id: 'E', dst_id: 'F', weight: 5, enabled: true },
{ innovation: 7, src_id: 'F', dst_id: 'D', weight: 5, enabled: true },
// excess
{ innovation: 9, src_id: 'C', dst_id: 'E', weight: 5, enabled: true },
{ innovation: 10, src_id: 'A', dst_id: 'F', weight: 5, enabled: true },
];
// these genomes are taken from the NEAT paper's example
const genomeA = [
{ innovation: 1, src_id: 'A', dst_id: 'D', weight: 4, enabled: true },
{ innovation: 2, src_id: 'B', dst_id: 'D', weight: 0, enabled: false },
{ innovation: 3, src_id: 'C', dst_id: 'D', weight: 3, enabled: true },
{ innovation: 4, src_id: 'B', dst_id: 'E', weight: 9, enabled: true },
{ innovation: 5, src_id: 'E', dst_id: 'D', weight: 5, enabled: true },
// disjoint
{ innovation: 8, src_id: 'A', dst_id: 'E', weight: 7, enabled: true },
];
const genomeB = [
{ innovation: 1, src_id: 'A', dst_id: 'D', weight: 8, enabled: true },
{ innovation: 2, src_id: 'B', dst_id: 'D', weight: 1, enabled: false },
{ innovation: 3, src_id: 'C', dst_id: 'D', weight: 2, enabled: true },
{ innovation: 4, src_id: 'B', dst_id: 'E', weight: 9, enabled: true },
{ innovation: 5, src_id: 'E', dst_id: 'D', weight: 3, enabled: false },
// disjoint
{ innovation: 6, src_id: 'E', dst_id: 'F', weight: 5, enabled: true },
{ innovation: 7, src_id: 'F', dst_id: 'D', weight: 5, enabled: true },
// excess
{ innovation: 9, src_id: 'C', dst_id: 'E', weight: 5, enabled: true },
{ innovation: 10, src_id: 'A', dst_id: 'F', weight: 5, enabled: true },
];
const alignment = alignGenome(genomeA, genomeB);
const alignment = alignGenome(genomeA, genomeB);
const dist1 = compatibilityDistance(alignment, { c1: 1, c2: 0, c3: 0 });
const dist2 = compatibilityDistance(alignment, { c1: 0, c2: 1, c3: 0 });
const dist3 = compatibilityDistance(alignment, { c1: 0, c2: 0, c3: 1 });
assert(dist1 === 2 / 10);
assert(dist2 === 3 / 10);
// |8 - 4| + |1 - 0| + |2 - 3| + |9 - 9| + |3 - 5|
// 4 + 1 + 1 + 0 + 2
// 8 / 5
assert(dist3 === 8 / 5);
const dist1 = compatibilityDistance(alignment, { c1: 1, c2: 0, c3: 0 });
const dist2 = compatibilityDistance(alignment, { c1: 0, c2: 1, c3: 0 });
const dist3 = compatibilityDistance(alignment, { c1: 0, c2: 0, c3: 1 });
assert(dist1 === 2 / 10);
assert(dist2 === 3 / 10);
// |8 - 4| + |1 - 0| + |2 - 3| + |9 - 9| + |3 - 5|
// 4 + 1 + 1 + 0 + 2
// 8 / 5
assert(dist3 === 8 / 5);
const distCombo = compatibilityDistance(alignment, { c1: 2, c2: 3, c3: 4 });
assert(distCombo === 2 * (2 / 10) + 3 * (3 / 10) + 4 * (8 / 5));
const distCombo = compatibilityDistance(alignment, { c1: 2, c2: 3, c3: 4 });
assert(distCombo === 2 * (2 / 10) + 3 * (3 / 10) + 4 * (8 / 5));
}
addTest(testCompatibilityDistance);

View File

@ -1,31 +1,31 @@
import IOSet from "../components/snake/ioset";
import { addTest, assert, assertArrayEqual } from "./tests";
import IOSet from '../site/snake/ioset';
import { addTest, assert, assertArrayEqual } from './tests';
function testOrderMaintained() {
const s = new IOSet();
s.add('A');
s.add('B');
s.add('C');
s.add('D');
s.add('E');
s.add('F');
assert(s.size === 6);
assertArrayEqual(Array.from(s), ['A', 'B', 'C', 'D', 'E', 'F']);
const s = new IOSet();
s.add('A');
s.add('B');
s.add('C');
s.add('D');
s.add('E');
s.add('F');
assert(s.size === 6);
assertArrayEqual(Array.from(s), ['A', 'B', 'C', 'D', 'E', 'F']);
}
addTest(testOrderMaintained);
function testOrderMaintainedWithDelete() {
const s = new IOSet();
s.add('A');
s.add('B');
s.add('C');
s.add('D');
s.add('E');
s.delete('D');
s.add('F');
s.delete('B');
s.add('G');
assert(s.size === 5);
assertArrayEqual(Array.from(s), ['A', 'C', 'E', 'F', 'G']);
const s = new IOSet();
s.add('A');
s.add('B');
s.add('C');
s.add('D');
s.add('E');
s.delete('D');
s.add('F');
s.delete('B');
s.add('G');
assert(s.size === 5);
assertArrayEqual(Array.from(s), ['A', 'C', 'E', 'F', 'G']);
}
addTest(testOrderMaintainedWithDelete);

View File

@ -1,4 +1,4 @@
import { Network, Edge, Node, RawEdge } from '../components/snake/network';
import { Network, Edge, Node, RawEdge } from '../site/snake/network';
import { addTest, assert, assertArrayEqual } from './tests';
function testEdgesToNodesBasic() {
@ -135,8 +135,8 @@ function testEdgesToNodesMaintainsData() {
addTest(testEdgesToNodesMaintainsData);
function testCopyNodesPreventsModify() {
type MyNode = Node<RawEdge & MyEdge>;
type MyEdge = Edge<MyNode>;
type MyNode = Node<RawEdge & MyEdge>;
type MyEdge = Edge<MyNode>;
const edges = [
{ src_id: 'A', dst_id: 'B' },
{ src_id: 'B', dst_id: 'C' },
@ -145,15 +145,15 @@ function testCopyNodesPreventsModify() {
const nodesCopy = Network.copyNodes(nodes);
assert(nodes.size === nodesCopy.size);
assert(nodes.size === nodesCopy.size);
// ensure that modifying a copied node does not modify the source node
const nodeA = nodes.get('A')!;
const nodeACopy = nodesCopy.get('A')!;
// ensure that modifying a copied node does not modify the source node
const nodeA = nodes.get('A')!;
const nodeACopy = nodesCopy.get('A')!;
nodeACopy.dsts.pop()
nodeACopy.dsts.pop();
assert(nodeA.dsts.size === 1);
assert(nodeACopy.dsts.size === 0);
assert(nodeA.dsts.size === 1);
assert(nodeACopy.dsts.size === 0);
}
addTest(testCopyNodesPreventsModify);