// TODO - try visualising the 5-cells from a vertex on the layered 120-cell // and get an intuition for how they work with the dodecahedral structure // Another new approach - // pick a starting 5-cell // look at the neighbours on the 120-cell of all of its 5 vertices // try to find abother 5-cell with these neighbours // if there's only one, add that to the list and keep going // if there's more than one, are they disjoint with each other? import * as POLYTOPES from './polytopes.js'; // exploring more inscriptions of the 120-cell function choice(a) { const r = Math.floor(Math.random() * a.length); return a[r]; } export function nodes_links(links, nodeid) { return links.filter((l) => l.source === nodeid || l.target === nodeid); } export function linked(links, n1, n2) { const ls = nodes_links(nodes_links(links, n1), n2); if( ls.length ) { return ls[0] } else { return false; } } function fingerprint(ids) { const sids = [...ids]; sids.sort(); return sids.join(','); } export function dist(n1, n2) { return Math.sqrt((n1.x - n2.x) ** 2 + (n1.y - n2.y) ** 2 + (n1.z - n2.z) ** 2 + (n1.w - n2.w) ** 2); } export function make_120cell() { const nodes = POLYTOPES.make_120cell_vertices(); const links = POLYTOPES.auto_detect_edges(nodes, 4); return { nodes: nodes, links: links } } function round_dist(raw) { return Math.floor(raw * 100000) / 100000; } export function distance_groups(cell120) { // get list of other nodes by distance // sort them and dump them out const dists = {}; cell120.nodes.map((n) => { const draw = dist(cell120.nodes[0], n); const dtrunc = round_dist(draw); if( !(dtrunc in dists) ) { dists[dtrunc] = []; } dists[dtrunc].push(n); }); return dists; } function distance_group(cell120, n0, chord) { const nodes = [] cell120.nodes.map((n) => { const d = round_dist(dist(n0, n)); if( d == chord ) { nodes.push(n); } }); // filter and return those whose chord is also the same const equidistant = []; for( const n1 of nodes ) { for( const n2 of nodes ) { if( n2.id > n1.id ) { if( round_dist(dist(n1, n2)) == chord ) { equidistant.push([n1, n2]); } } } } return equidistant; } export function chord_survey() { const cell120 = POLYTOPES.cell120_inscribed(); const dgroups = distance_groups(cell120); const dists = Object.keys(dgroups); dists.sort(); for( const d of dists ) { const g0 = dgroups[d][0]; dgroups[d].map((g) => { console.log(`${g0.id}-${g.id}: ${round_dist(dist(g0, g))}`); }); } } function overlap(c1, c2) { for( const l in c1 ) { if( c1[l] === c2[l] ) { return true; } } return false; } export function gather_5cells(cell120) { const CHORD5 = round_dist(Math.sqrt(2.5)); const bins = []; const all = []; cell120.nodes.filter((n) => n.label === 1).map((n) => { const cells = [ ]; const g = distance_group(cell120, n, CHORD5); for( const pair of g ) { let seen = false; for( const cell of cells ) { const c = Object.values(cell); if( c.includes(pair[0].id) || c.includes(pair[1].id) ) { if( !c.includes(pair[0].id) ) { cell[pair[0].label] = pair[0].id; } if( !c.includes(pair[1].id) ) { cell[pair[1].label] = pair[1].id; } seen = true; break; } } if( !seen ) { const cell = {}; cell[1]= n.id; cell[pair[0].label] = pair[0].id; cell[pair[1].label] = pair[1].id; cells.push(cell); } } all.push(...cells); }); return all; } function audit_5cells(cells) { // this verifies that for each label (a 600-cell set), each of its // vertices is in exactly 7 5-cells. It checks out. ['1','2','3','4','5'].map((l) => { const sets = {}; for( const cell of cells ) { const lv = cell[l]; if( !(lv in sets) ) { sets[lv] = []; } sets[lv].push(cell); } for( const lv in sets ) { const ok = ( sets[lv].length === 7 ) ? 'ok' : 'miss'; console.log(`${l},${lv},${sets[lv].length},${ok}`); } }); } function try_120_5_cells_fails(cell120, cells, l) { // iterate over every vertex in the 600-cell defined by label l, // get all 7 5-cells including that vertex, and add them if they are // disjoint with what we already have // this always runs out of disjoint nodes early const vertices = cell120.nodes.filter((n) => n.label === l); const cellset = []; for( const v of vertices ) { console.log(`Vertex ${v.id}`); const vcells = cells.filter((c) => c[l] === v.id); const overlap_any = (cs, c) => { for( const seen of cs ) { if( overlap(seen, c) ) { console.log("overlap"); console.log(c); return true; } } return false; } const disjoint = vcells.filter((c) => ! overlap_any(cellset, c)); console.log(`Found ${disjoint.length} disjoint cells`); if( disjoint.length > 0 ) { cellset.push(choice(disjoint)); } } console.log(`Found total of ${cellset.length} disjoint cells`); //console.log(cellset); } function overlap_any(cs, c) { for( const seen of cs ) { if( overlap(seen, c) ) { return true; } } return false; } function explore_disjoint(cell120, all5, l) { const a = all5[0]; const overlaps = all5.filter((c) => overlap(c, a)); console.log(a); console.log(overlaps.length); console.log(overlaps); } // select a five-cell from a starting vertex v // find a neighbor of v vn on its 600 cell, find all of the 5-cells which include // vn. Then see if we can find any from that set which are similiar neighbours to // the other four vertices in the first 5-cell // the idea is that the 600-cells are a guide to finding the right subset of // 5-cells function neighbours600(cell120, vid) { const v = cell120.nodes.filter((node) => node.id === vid)[0]; const label = v.label; const links = cell120.links.filter((l) => { return l.label === v.label && (l.source === v.id || l.target == v.id ); }); const nodes = links.map((l) => { if( l.source === v.id ) { return l.target; } else { return l.source; } }); return nodes; } function cell120node(cell120, nid) { return cell120.nodes.filter((n) => n.id === nid)[0]; } function node_dist(cell120, aid, bid) { const a = cell120node(cell120, aid); const b = cell120node(cell120, bid); return dist(a, b); } function follow_600(cell120, all5) { const v = cell120.nodes[0]; console.log("Start vertex:"); console.log(v); const v5s = all5.filter((c5) => c5[v.label] === v.id); console.log(`Vertex ${v.id} belongs to these 5-cells:`); console.log(v5s); const n600s = neighbours600(cell120, v.id); const n600id = n600s[0]; const n600 = cell120node(cell120, n600id); console.log("One 600-cell neighbour:"); console.log(n600); const DIST600 = round_dist(node_dist(cell120, v.id, n600id)); const nv5s = all5.filter((c5) => c5[v.label] === n600id); console.log(`Vertex ${n600id} belongs to these 5-cells:`); console.log(nv5s); console.log("Distances for each pair of 5-cells from the two sets:"); for( const v5a of v5s ) { for( const v5b of nv5s ) { let match = true; const d = {}; for( const label in v5a ) { d[label] = round_dist(node_dist(cell120, v5a[label], v5b[label])); if( d[label] != DIST600 ) { match = false; } } if( match ) { console.log("--- pair ---"); console.log(v5a); console.log(v5b); } } } } const cell120 = POLYTOPES.cell120_inscribed(); const all5 = gather_5cells(cell120); follow_600(cell120, all5);