@graphty/graph-samples 0.0.1 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/NOTICE +123 -0
- package/README.md +190 -1
- package/dist/chunks/build-DdCe60t3.js +47 -0
- package/dist/chunks/build-DdCe60t3.js.map +1 -0
- package/dist/chunks/meta-B6toBzaa.js +19 -0
- package/dist/chunks/meta-B6toBzaa.js.map +1 -0
- package/dist/chunks/meta-BM_YIhlA.js +28 -0
- package/dist/chunks/meta-BM_YIhlA.js.map +1 -0
- package/dist/chunks/meta-BMmtUpPx.js +30 -0
- package/dist/chunks/meta-BMmtUpPx.js.map +1 -0
- package/dist/chunks/meta-BXC7oi86.js +22 -0
- package/dist/chunks/meta-BXC7oi86.js.map +1 -0
- package/dist/chunks/meta-BaFPvhc1.js +19 -0
- package/dist/chunks/meta-BaFPvhc1.js.map +1 -0
- package/dist/chunks/meta-C58v1Oy0.js +28 -0
- package/dist/chunks/meta-C58v1Oy0.js.map +1 -0
- package/dist/chunks/meta-CQRXyexG.js +23 -0
- package/dist/chunks/meta-CQRXyexG.js.map +1 -0
- package/dist/chunks/meta-DrgM1eS0.js +23 -0
- package/dist/chunks/meta-DrgM1eS0.js.map +1 -0
- package/dist/chunks/meta-IhoaDXAV.js +19 -0
- package/dist/chunks/meta-IhoaDXAV.js.map +1 -0
- package/dist/chunks/meta-MQPbBUUB.js +29 -0
- package/dist/chunks/meta-MQPbBUUB.js.map +1 -0
- package/dist/chunks/meta-Qp4HNYAZ.js +24 -0
- package/dist/chunks/meta-Qp4HNYAZ.js.map +1 -0
- package/dist/chunks/meta-mns0uFIW.js +19 -0
- package/dist/chunks/meta-mns0uFIW.js.map +1 -0
- package/dist/datasets/celegans-neural.d.ts +1 -0
- package/dist/datasets/celegans-neural.js +7359 -0
- package/dist/datasets/celegans-neural.js.map +1 -0
- package/dist/datasets/contiguous-usa.d.ts +1 -0
- package/dist/datasets/contiguous-usa.js +501 -0
- package/dist/datasets/contiguous-usa.js.map +1 -0
- package/dist/datasets/davis-southern-women.d.ts +1 -0
- package/dist/datasets/davis-southern-women.js +235 -0
- package/dist/datasets/davis-southern-women.js.map +1 -0
- package/dist/datasets/dolphins.d.ts +1 -0
- package/dist/datasets/dolphins.js +406 -0
- package/dist/datasets/dolphins.js.map +1 -0
- package/dist/datasets/florentine-families.d.ts +1 -0
- package/dist/datasets/florentine-families.js +75 -0
- package/dist/datasets/florentine-families.js.map +1 -0
- package/dist/datasets/football.d.ts +1 -0
- package/dist/datasets/football.js +1508 -0
- package/dist/datasets/football.js.map +1 -0
- package/dist/datasets/karate.d.ts +1 -0
- package/dist/datasets/karate.js +295 -0
- package/dist/datasets/karate.js.map +1 -0
- package/dist/datasets/knuth-miles.d.ts +1 -0
- package/dist/datasets/knuth-miles.js +24933 -0
- package/dist/datasets/knuth-miles.js.map +1 -0
- package/dist/datasets/les-miserables.d.ts +1 -0
- package/dist/datasets/les-miserables.js +860 -0
- package/dist/datasets/les-miserables.js.map +1 -0
- package/dist/datasets/openflights.d.ts +1 -0
- package/dist/datasets/openflights.js +130277 -0
- package/dist/datasets/openflights.js.map +1 -0
- package/dist/datasets/political-blogs.d.ts +1 -0
- package/dist/datasets/political-blogs.js +42551 -0
- package/dist/datasets/political-blogs.js.map +1 -0
- package/dist/datasets/political-books.d.ts +1 -0
- package/dist/datasets/political-books.js +1124 -0
- package/dist/datasets/political-books.js.map +1 -0
- package/dist/generators.d.ts +1 -0
- package/dist/generators.js +4496 -0
- package/dist/generators.js.map +1 -0
- package/dist/graph-samples.d.ts +1 -0
- package/dist/graph-samples.js +142 -0
- package/dist/graph-samples.js.map +1 -0
- package/dist/src/datasets/build.d.ts +89 -0
- package/dist/src/datasets/build.d.ts.map +1 -0
- package/dist/src/datasets/build.js +53 -0
- package/dist/src/datasets/build.js.map +1 -0
- package/dist/src/datasets/catalog.d.ts +8 -0
- package/dist/src/datasets/catalog.d.ts.map +1 -0
- package/dist/src/datasets/catalog.js +34 -0
- package/dist/src/datasets/catalog.js.map +1 -0
- package/dist/src/datasets/celegans-neural/data.d.ts +3 -0
- package/dist/src/datasets/celegans-neural/data.d.ts.map +1 -0
- package/dist/src/datasets/celegans-neural/data.js +573 -0
- package/dist/src/datasets/celegans-neural/data.js.map +1 -0
- package/dist/src/datasets/celegans-neural/index.d.ts +11 -0
- package/dist/src/datasets/celegans-neural/index.d.ts.map +1 -0
- package/dist/src/datasets/celegans-neural/index.js +14 -0
- package/dist/src/datasets/celegans-neural/index.js.map +1 -0
- package/dist/src/datasets/celegans-neural/meta.d.ts +4 -0
- package/dist/src/datasets/celegans-neural/meta.d.ts.map +1 -0
- package/dist/src/datasets/celegans-neural/meta.js +21 -0
- package/dist/src/datasets/celegans-neural/meta.js.map +1 -0
- package/dist/src/datasets/contiguous-usa/data.d.ts +3 -0
- package/dist/src/datasets/contiguous-usa/data.d.ts.map +1 -0
- package/dist/src/datasets/contiguous-usa/data.js +162 -0
- package/dist/src/datasets/contiguous-usa/data.js.map +1 -0
- package/dist/src/datasets/contiguous-usa/index.d.ts +11 -0
- package/dist/src/datasets/contiguous-usa/index.d.ts.map +1 -0
- package/dist/src/datasets/contiguous-usa/index.js +14 -0
- package/dist/src/datasets/contiguous-usa/index.js.map +1 -0
- package/dist/src/datasets/contiguous-usa/meta.d.ts +4 -0
- package/dist/src/datasets/contiguous-usa/meta.d.ts.map +1 -0
- package/dist/src/datasets/contiguous-usa/meta.js +27 -0
- package/dist/src/datasets/contiguous-usa/meta.js.map +1 -0
- package/dist/src/datasets/davis-southern-women/data.d.ts +3 -0
- package/dist/src/datasets/davis-southern-women/data.d.ts.map +1 -0
- package/dist/src/datasets/davis-southern-women/data.js +57 -0
- package/dist/src/datasets/davis-southern-women/data.js.map +1 -0
- package/dist/src/datasets/davis-southern-women/index.d.ts +11 -0
- package/dist/src/datasets/davis-southern-women/index.d.ts.map +1 -0
- package/dist/src/datasets/davis-southern-women/index.js +14 -0
- package/dist/src/datasets/davis-southern-women/index.js.map +1 -0
- package/dist/src/datasets/davis-southern-women/meta.d.ts +4 -0
- package/dist/src/datasets/davis-southern-women/meta.d.ts.map +1 -0
- package/dist/src/datasets/davis-southern-women/meta.js +17 -0
- package/dist/src/datasets/davis-southern-women/meta.js.map +1 -0
- package/dist/src/datasets/dolphins/data.d.ts +3 -0
- package/dist/src/datasets/dolphins/data.d.ts.map +1 -0
- package/dist/src/datasets/dolphins/data.js +93 -0
- package/dist/src/datasets/dolphins/data.js.map +1 -0
- package/dist/src/datasets/dolphins/index.d.ts +11 -0
- package/dist/src/datasets/dolphins/index.d.ts.map +1 -0
- package/dist/src/datasets/dolphins/index.js +14 -0
- package/dist/src/datasets/dolphins/index.js.map +1 -0
- package/dist/src/datasets/dolphins/meta.d.ts +4 -0
- package/dist/src/datasets/dolphins/meta.d.ts.map +1 -0
- package/dist/src/datasets/dolphins/meta.js +17 -0
- package/dist/src/datasets/dolphins/meta.js.map +1 -0
- package/dist/src/datasets/florentine-families/data.d.ts +3 -0
- package/dist/src/datasets/florentine-families/data.d.ts.map +1 -0
- package/dist/src/datasets/florentine-families/data.js +31 -0
- package/dist/src/datasets/florentine-families/data.js.map +1 -0
- package/dist/src/datasets/florentine-families/index.d.ts +11 -0
- package/dist/src/datasets/florentine-families/index.d.ts.map +1 -0
- package/dist/src/datasets/florentine-families/index.js +14 -0
- package/dist/src/datasets/florentine-families/index.js.map +1 -0
- package/dist/src/datasets/florentine-families/meta.d.ts +4 -0
- package/dist/src/datasets/florentine-families/meta.d.ts.map +1 -0
- package/dist/src/datasets/florentine-families/meta.js +17 -0
- package/dist/src/datasets/florentine-families/meta.js.map +1 -0
- package/dist/src/datasets/football/data.d.ts +3 -0
- package/dist/src/datasets/football/data.d.ts.map +1 -0
- package/dist/src/datasets/football/data.js +210 -0
- package/dist/src/datasets/football/data.js.map +1 -0
- package/dist/src/datasets/football/index.d.ts +11 -0
- package/dist/src/datasets/football/index.d.ts.map +1 -0
- package/dist/src/datasets/football/index.js +14 -0
- package/dist/src/datasets/football/index.js.map +1 -0
- package/dist/src/datasets/football/meta.d.ts +4 -0
- package/dist/src/datasets/football/meta.d.ts.map +1 -0
- package/dist/src/datasets/football/meta.js +17 -0
- package/dist/src/datasets/football/meta.js.map +1 -0
- package/dist/src/datasets/hosted.d.ts +7 -0
- package/dist/src/datasets/hosted.d.ts.map +1 -0
- package/dist/src/datasets/hosted.js +80 -0
- package/dist/src/datasets/hosted.js.map +1 -0
- package/dist/src/datasets/karate/data.d.ts +3 -0
- package/dist/src/datasets/karate/data.d.ts.map +1 -0
- package/dist/src/datasets/karate/data.js +30 -0
- package/dist/src/datasets/karate/data.js.map +1 -0
- package/dist/src/datasets/karate/index.d.ts +11 -0
- package/dist/src/datasets/karate/index.d.ts.map +1 -0
- package/dist/src/datasets/karate/index.js +14 -0
- package/dist/src/datasets/karate/index.js.map +1 -0
- package/dist/src/datasets/karate/meta.d.ts +4 -0
- package/dist/src/datasets/karate/meta.d.ts.map +1 -0
- package/dist/src/datasets/karate/meta.js +22 -0
- package/dist/src/datasets/karate/meta.js.map +1 -0
- package/dist/src/datasets/knuth-miles/data.d.ts +3 -0
- package/dist/src/datasets/knuth-miles/data.d.ts.map +1 -0
- package/dist/src/datasets/knuth-miles/data.js +1203 -0
- package/dist/src/datasets/knuth-miles/data.js.map +1 -0
- package/dist/src/datasets/knuth-miles/index.d.ts +11 -0
- package/dist/src/datasets/knuth-miles/index.d.ts.map +1 -0
- package/dist/src/datasets/knuth-miles/index.js +14 -0
- package/dist/src/datasets/knuth-miles/index.js.map +1 -0
- package/dist/src/datasets/knuth-miles/meta.d.ts +4 -0
- package/dist/src/datasets/knuth-miles/meta.d.ts.map +1 -0
- package/dist/src/datasets/knuth-miles/meta.js +26 -0
- package/dist/src/datasets/knuth-miles/meta.js.map +1 -0
- package/dist/src/datasets/les-miserables/data.d.ts +3 -0
- package/dist/src/datasets/les-miserables/data.d.ts.map +1 -0
- package/dist/src/datasets/les-miserables/data.js +117 -0
- package/dist/src/datasets/les-miserables/data.js.map +1 -0
- package/dist/src/datasets/les-miserables/index.d.ts +11 -0
- package/dist/src/datasets/les-miserables/index.d.ts.map +1 -0
- package/dist/src/datasets/les-miserables/index.js +14 -0
- package/dist/src/datasets/les-miserables/index.js.map +1 -0
- package/dist/src/datasets/les-miserables/meta.d.ts +4 -0
- package/dist/src/datasets/les-miserables/meta.d.ts.map +1 -0
- package/dist/src/datasets/les-miserables/meta.js +21 -0
- package/dist/src/datasets/les-miserables/meta.js.map +1 -0
- package/dist/src/datasets/openflights/data.d.ts +3 -0
- package/dist/src/datasets/openflights/data.d.ts.map +1 -0
- package/dist/src/datasets/openflights/data.js +15457 -0
- package/dist/src/datasets/openflights/data.js.map +1 -0
- package/dist/src/datasets/openflights/index.d.ts +11 -0
- package/dist/src/datasets/openflights/index.d.ts.map +1 -0
- package/dist/src/datasets/openflights/index.js +14 -0
- package/dist/src/datasets/openflights/index.js.map +1 -0
- package/dist/src/datasets/openflights/meta.d.ts +4 -0
- package/dist/src/datasets/openflights/meta.d.ts.map +1 -0
- package/dist/src/datasets/openflights/meta.js +28 -0
- package/dist/src/datasets/openflights/meta.js.map +1 -0
- package/dist/src/datasets/political-blogs/data.d.ts +3 -0
- package/dist/src/datasets/political-blogs/data.d.ts.map +1 -0
- package/dist/src/datasets/political-blogs/data.js +4857 -0
- package/dist/src/datasets/political-blogs/data.js.map +1 -0
- package/dist/src/datasets/political-blogs/index.d.ts +11 -0
- package/dist/src/datasets/political-blogs/index.d.ts.map +1 -0
- package/dist/src/datasets/political-blogs/index.js +14 -0
- package/dist/src/datasets/political-blogs/index.js.map +1 -0
- package/dist/src/datasets/political-blogs/meta.d.ts +4 -0
- package/dist/src/datasets/political-blogs/meta.d.ts.map +1 -0
- package/dist/src/datasets/political-blogs/meta.js +26 -0
- package/dist/src/datasets/political-blogs/meta.js.map +1 -0
- package/dist/src/datasets/political-books/data.d.ts +3 -0
- package/dist/src/datasets/political-books/data.d.ts.map +1 -0
- package/dist/src/datasets/political-books/data.js +165 -0
- package/dist/src/datasets/political-books/data.js.map +1 -0
- package/dist/src/datasets/political-books/index.d.ts +11 -0
- package/dist/src/datasets/political-books/index.d.ts.map +1 -0
- package/dist/src/datasets/political-books/index.js +14 -0
- package/dist/src/datasets/political-books/index.js.map +1 -0
- package/dist/src/datasets/political-books/meta.d.ts +4 -0
- package/dist/src/datasets/political-books/meta.d.ts.map +1 -0
- package/dist/src/datasets/political-books/meta.js +20 -0
- package/dist/src/datasets/political-books/meta.js.map +1 -0
- package/dist/src/datasets/remote.d.ts +27 -0
- package/dist/src/datasets/remote.d.ts.map +1 -0
- package/dist/src/datasets/remote.js +30 -0
- package/dist/src/datasets/remote.js.map +1 -0
- package/dist/src/element.d.ts +20 -0
- package/dist/src/element.d.ts.map +1 -0
- package/dist/src/element.js +27 -0
- package/dist/src/element.js.map +1 -0
- package/dist/src/generators/bipartite.d.ts +51 -0
- package/dist/src/generators/bipartite.d.ts.map +1 -0
- package/dist/src/generators/bipartite.js +99 -0
- package/dist/src/generators/bipartite.js.map +1 -0
- package/dist/src/generators/block-model.d.ts +75 -0
- package/dist/src/generators/block-model.d.ts.map +1 -0
- package/dist/src/generators/block-model.js +116 -0
- package/dist/src/generators/block-model.js.map +1 -0
- package/dist/src/generators/classic.d.ts +208 -0
- package/dist/src/generators/classic.d.ts.map +1 -0
- package/dist/src/generators/classic.js +437 -0
- package/dist/src/generators/classic.js.map +1 -0
- package/dist/src/generators/degree-sequence.d.ts +273 -0
- package/dist/src/generators/degree-sequence.d.ts.map +1 -0
- package/dist/src/generators/degree-sequence.js +646 -0
- package/dist/src/generators/degree-sequence.js.map +1 -0
- package/dist/src/generators/directed.d.ts +141 -0
- package/dist/src/generators/directed.d.ts.map +1 -0
- package/dist/src/generators/directed.js +329 -0
- package/dist/src/generators/directed.js.map +1 -0
- package/dist/src/generators/erdos-renyi.d.ts +58 -0
- package/dist/src/generators/erdos-renyi.d.ts.map +1 -0
- package/dist/src/generators/erdos-renyi.js +154 -0
- package/dist/src/generators/erdos-renyi.js.map +1 -0
- package/dist/src/generators/flow.d.ts +153 -0
- package/dist/src/generators/flow.d.ts.map +1 -0
- package/dist/src/generators/flow.js +346 -0
- package/dist/src/generators/flow.js.map +1 -0
- package/dist/src/generators/geometric.d.ts +133 -0
- package/dist/src/generators/geometric.d.ts.map +1 -0
- package/dist/src/generators/geometric.js +495 -0
- package/dist/src/generators/geometric.js.map +1 -0
- package/dist/src/generators/growth.d.ts +187 -0
- package/dist/src/generators/growth.d.ts.map +1 -0
- package/dist/src/generators/growth.js +445 -0
- package/dist/src/generators/growth.js.map +1 -0
- package/dist/src/generators/hyperbolic.d.ts +84 -0
- package/dist/src/generators/hyperbolic.d.ts.map +1 -0
- package/dist/src/generators/hyperbolic.js +153 -0
- package/dist/src/generators/hyperbolic.js.map +1 -0
- package/dist/src/generators/index.d.ts +25 -0
- package/dist/src/generators/index.d.ts.map +1 -0
- package/dist/src/generators/index.js +24 -0
- package/dist/src/generators/index.js.map +1 -0
- package/dist/src/generators/lattices.d.ts +87 -0
- package/dist/src/generators/lattices.d.ts.map +1 -0
- package/dist/src/generators/lattices.js +237 -0
- package/dist/src/generators/lattices.js.map +1 -0
- package/dist/src/generators/lfr.d.ts +55 -0
- package/dist/src/generators/lfr.d.ts.map +1 -0
- package/dist/src/generators/lfr.js +178 -0
- package/dist/src/generators/lfr.js.map +1 -0
- package/dist/src/generators/named.d.ts +23 -0
- package/dist/src/generators/named.d.ts.map +1 -0
- package/dist/src/generators/named.js +191 -0
- package/dist/src/generators/named.js.map +1 -0
- package/dist/src/generators/preferential-attachment.d.ts +66 -0
- package/dist/src/generators/preferential-attachment.d.ts.map +1 -0
- package/dist/src/generators/preferential-attachment.js +157 -0
- package/dist/src/generators/preferential-attachment.js.map +1 -0
- package/dist/src/generators/trees-and-dags.d.ts +53 -0
- package/dist/src/generators/trees-and-dags.d.ts.map +1 -0
- package/dist/src/generators/trees-and-dags.js +108 -0
- package/dist/src/generators/trees-and-dags.js.map +1 -0
- package/dist/src/generators/util.d.ts +84 -0
- package/dist/src/generators/util.d.ts.map +1 -0
- package/dist/src/generators/util.js +138 -0
- package/dist/src/generators/util.js.map +1 -0
- package/dist/src/generators/variants.d.ts +85 -0
- package/dist/src/generators/variants.d.ts.map +1 -0
- package/dist/src/generators/variants.js +215 -0
- package/dist/src/generators/variants.js.map +1 -0
- package/dist/src/generators/weights.d.ts +65 -0
- package/dist/src/generators/weights.d.ts.map +1 -0
- package/dist/src/generators/weights.js +135 -0
- package/dist/src/generators/weights.js.map +1 -0
- package/dist/src/index.d.ts +12 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +10 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/random/exp.d.ts +23 -0
- package/dist/src/random/exp.d.ts.map +1 -0
- package/dist/src/random/exp.js +101 -0
- package/dist/src/random/exp.js.map +1 -0
- package/dist/src/random/log.d.ts +19 -0
- package/dist/src/random/log.d.ts.map +1 -0
- package/dist/src/random/log.js +83 -0
- package/dist/src/random/log.js.map +1 -0
- package/dist/src/random/stream.d.ts +93 -0
- package/dist/src/random/stream.d.ts.map +1 -0
- package/dist/src/random/stream.js +154 -0
- package/dist/src/random/stream.js.map +1 -0
- package/dist/src/random/threefry.d.ts +19 -0
- package/dist/src/random/threefry.d.ts.map +1 -0
- package/dist/src/random/threefry.js +43 -0
- package/dist/src/random/threefry.js.map +1 -0
- package/dist/src/random/trig.d.ts +16 -0
- package/dist/src/random/trig.d.ts.map +1 -0
- package/dist/src/random/trig.js +78 -0
- package/dist/src/random/trig.js.map +1 -0
- package/dist/src/types.d.ts +28 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/package.json +102 -5
- package/src/datasets/build.ts +140 -0
- package/src/datasets/catalog.ts +35 -0
- package/src/datasets/celegans-neural/data.ts +575 -0
- package/src/datasets/celegans-neural/index.ts +17 -0
- package/src/datasets/celegans-neural/meta.ts +25 -0
- package/src/datasets/contiguous-usa/data.ts +164 -0
- package/src/datasets/contiguous-usa/index.ts +17 -0
- package/src/datasets/contiguous-usa/meta.ts +31 -0
- package/src/datasets/davis-southern-women/data.ts +59 -0
- package/src/datasets/davis-southern-women/index.ts +17 -0
- package/src/datasets/davis-southern-women/meta.ts +20 -0
- package/src/datasets/dolphins/data.ts +95 -0
- package/src/datasets/dolphins/index.ts +17 -0
- package/src/datasets/dolphins/meta.ts +21 -0
- package/src/datasets/florentine-families/data.ts +33 -0
- package/src/datasets/florentine-families/index.ts +17 -0
- package/src/datasets/florentine-families/meta.ts +20 -0
- package/src/datasets/football/data.ts +212 -0
- package/src/datasets/football/index.ts +17 -0
- package/src/datasets/football/meta.ts +20 -0
- package/src/datasets/hosted.ts +90 -0
- package/src/datasets/karate/data.ts +32 -0
- package/src/datasets/karate/index.ts +17 -0
- package/src/datasets/karate/meta.ts +25 -0
- package/src/datasets/knuth-miles/data.ts +1205 -0
- package/src/datasets/knuth-miles/index.ts +17 -0
- package/src/datasets/knuth-miles/meta.ts +29 -0
- package/src/datasets/les-miserables/data.ts +119 -0
- package/src/datasets/les-miserables/index.ts +17 -0
- package/src/datasets/les-miserables/meta.ts +24 -0
- package/src/datasets/openflights/data.ts +15459 -0
- package/src/datasets/openflights/index.ts +17 -0
- package/src/datasets/openflights/meta.ts +31 -0
- package/src/datasets/political-blogs/data.ts +4859 -0
- package/src/datasets/political-blogs/index.ts +17 -0
- package/src/datasets/political-blogs/meta.ts +30 -0
- package/src/datasets/political-books/data.ts +167 -0
- package/src/datasets/political-books/index.ts +17 -0
- package/src/datasets/political-books/meta.ts +23 -0
- package/src/datasets/remote.ts +42 -0
- package/src/element.ts +41 -0
- package/src/generators/bipartite.ts +127 -0
- package/src/generators/block-model.ts +160 -0
- package/src/generators/classic.ts +461 -0
- package/src/generators/degree-sequence.ts +807 -0
- package/src/generators/directed.ts +418 -0
- package/src/generators/erdos-renyi.ts +188 -0
- package/src/generators/flow.ts +443 -0
- package/src/generators/geometric.ts +591 -0
- package/src/generators/growth.ts +532 -0
- package/src/generators/hyperbolic.ts +193 -0
- package/src/generators/index.ts +133 -0
- package/src/generators/lattices.ts +290 -0
- package/src/generators/lfr.ts +227 -0
- package/src/generators/named.ts +198 -0
- package/src/generators/preferential-attachment.ts +188 -0
- package/src/generators/trees-and-dags.ts +139 -0
- package/src/generators/util.ts +167 -0
- package/src/generators/variants.ts +253 -0
- package/src/generators/weights.ts +177 -0
- package/src/index.ts +12 -0
- package/src/random/exp.ts +104 -0
- package/src/random/log.ts +86 -0
- package/src/random/stream.ts +169 -0
- package/src/random/threefry.ts +45 -0
- package/src/random/trig.ts +83 -0
- package/src/types.ts +28 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge weights for any graph: the `weights` option every generator takes, and `withWeights` for a
|
|
3
|
+
* graph that already exists (a dataset, a hand-built graph).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { type TypedArrayData } from "@graphty/graph-format";
|
|
7
|
+
|
|
8
|
+
import { detLog } from "../random/log.js";
|
|
9
|
+
import { RandomStream, resolveSeed } from "../random/stream.js";
|
|
10
|
+
import { type SampleGraph } from "../types.js";
|
|
11
|
+
|
|
12
|
+
/** How to combine the two endpoint values of a node column into an edge weight. */
|
|
13
|
+
export type ColumnCombine = "source" | "target" | "sum" | "mean" | "product" | "min" | "max" | "difference";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A weight distribution. Random kinds draw one value per edge, in edge order, from stream
|
|
17
|
+
* (seed, "weights", 0).
|
|
18
|
+
*
|
|
19
|
+
* - `uniform`: a real in [min, max) (default [0, 1)).
|
|
20
|
+
* - `integer`: an integer in [min, max], both ends included -- capacities, Dijkstra demos.
|
|
21
|
+
* - `exponential`: -mean ln(1 - u), mean default 1.
|
|
22
|
+
* - `euclidean`: the distance between the endpoints' `x`, `y` (and `z`, when present) node columns;
|
|
23
|
+
* for the generators that emit positions.
|
|
24
|
+
* - `column`: from a numeric node column: the source's value, the target's, their sum, mean,
|
|
25
|
+
* product, min, max, or the absolute difference.
|
|
26
|
+
*/
|
|
27
|
+
export type WeightSpec =
|
|
28
|
+
| { readonly kind: "uniform"; readonly min?: number | undefined; readonly max?: number | undefined }
|
|
29
|
+
| { readonly kind: "integer"; readonly min: number; readonly max: number }
|
|
30
|
+
| { readonly kind: "exponential"; readonly mean?: number | undefined }
|
|
31
|
+
| { readonly kind: "euclidean" }
|
|
32
|
+
| { readonly kind: "column"; readonly column: string; readonly combine?: ColumnCombine | undefined };
|
|
33
|
+
|
|
34
|
+
/** The options every generator accepts on top of its own. */
|
|
35
|
+
export interface WeightOptions {
|
|
36
|
+
/** Give every edge a weight from this distribution; absent means unweighted. */
|
|
37
|
+
weights?: WeightSpec | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* The seed of the weight draws, an integer in [0, 2^53); default 0. Random generators share it
|
|
40
|
+
* with their structure (the weights use their own stream domain, so adding weights never changes
|
|
41
|
+
* the edges).
|
|
42
|
+
*/
|
|
43
|
+
seed?: number | undefined;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* A numeric node column of the graph, or a RangeError naming it.
|
|
48
|
+
* @param graph - the graph
|
|
49
|
+
* @param name - the column name
|
|
50
|
+
* @returns the column's values
|
|
51
|
+
*/
|
|
52
|
+
function numericColumn(graph: SampleGraph, name: string): TypedArrayData {
|
|
53
|
+
const column = graph.nodeColumns?.[name];
|
|
54
|
+
if (column === undefined || !ArrayBuffer.isView(column)) {
|
|
55
|
+
throw new RangeError(`weights: the graph has no numeric node column "${name}"`);
|
|
56
|
+
}
|
|
57
|
+
return column;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The weight of every edge under `spec`.
|
|
62
|
+
* @param graph - the graph
|
|
63
|
+
* @param spec - the distribution
|
|
64
|
+
* @param seed - the seed (already resolved)
|
|
65
|
+
* @returns one weight per edge
|
|
66
|
+
*/
|
|
67
|
+
function drawWeights(graph: SampleGraph, spec: WeightSpec, seed: number): Float32Array<ArrayBuffer> {
|
|
68
|
+
const m = graph.src.length;
|
|
69
|
+
const out = new Float32Array(m);
|
|
70
|
+
const { src, dst } = graph;
|
|
71
|
+
const stream = new RandomStream(seed, "weights", 0);
|
|
72
|
+
switch (spec.kind) {
|
|
73
|
+
case "uniform": {
|
|
74
|
+
const min = spec.min ?? 0;
|
|
75
|
+
const max = spec.max ?? 1;
|
|
76
|
+
if (!(Number.isFinite(min) && Number.isFinite(max) && min <= max)) {
|
|
77
|
+
throw new RangeError(`weights: uniform needs finite min <= max, got ${min} and ${max}`);
|
|
78
|
+
}
|
|
79
|
+
for (let e = 0; e < m; e++) {
|
|
80
|
+
out[e] = min + (max - min) * stream.nextFloat();
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
case "integer": {
|
|
85
|
+
const { min, max } = spec;
|
|
86
|
+
if (!(Number.isSafeInteger(min) && Number.isSafeInteger(max) && min <= max)) {
|
|
87
|
+
throw new RangeError(`weights: integer needs integers min <= max, got ${min} and ${max}`);
|
|
88
|
+
}
|
|
89
|
+
for (let e = 0; e < m; e++) {
|
|
90
|
+
out[e] = min + stream.nextBelow(max - min + 1);
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
case "exponential": {
|
|
95
|
+
const mean = spec.mean ?? 1;
|
|
96
|
+
if (!(mean > 0 && Number.isFinite(mean))) {
|
|
97
|
+
throw new RangeError(`weights: exponential needs a positive mean, got ${mean}`);
|
|
98
|
+
}
|
|
99
|
+
for (let e = 0; e < m; e++) {
|
|
100
|
+
out[e] = -mean * detLog(1 - stream.nextFloat());
|
|
101
|
+
}
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
case "euclidean": {
|
|
105
|
+
const x = numericColumn(graph, "x");
|
|
106
|
+
const y = numericColumn(graph, "y");
|
|
107
|
+
const z = graph.nodeColumns?.z === undefined ? null : numericColumn(graph, "z");
|
|
108
|
+
for (let e = 0; e < m; e++) {
|
|
109
|
+
const dx = x[src[e]] - x[dst[e]];
|
|
110
|
+
const dy = y[src[e]] - y[dst[e]];
|
|
111
|
+
const dz = z === null ? 0 : z[src[e]] - z[dst[e]];
|
|
112
|
+
out[e] = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
113
|
+
}
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
default: {
|
|
117
|
+
const values = numericColumn(graph, spec.column);
|
|
118
|
+
const combine = spec.combine ?? "sum";
|
|
119
|
+
for (let e = 0; e < m; e++) {
|
|
120
|
+
const a = values[src[e]];
|
|
121
|
+
const b = values[dst[e]];
|
|
122
|
+
out[e] = combineValues(combine, a, b);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return out;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Combine two endpoint values.
|
|
131
|
+
* @param combine - the rule
|
|
132
|
+
* @param a - the source value
|
|
133
|
+
* @param b - the target value
|
|
134
|
+
* @returns the weight
|
|
135
|
+
*/
|
|
136
|
+
function combineValues(combine: ColumnCombine, a: number, b: number): number {
|
|
137
|
+
switch (combine) {
|
|
138
|
+
case "source":
|
|
139
|
+
return a;
|
|
140
|
+
case "target":
|
|
141
|
+
return b;
|
|
142
|
+
case "sum":
|
|
143
|
+
return a + b;
|
|
144
|
+
case "mean":
|
|
145
|
+
return (a + b) / 2;
|
|
146
|
+
case "product":
|
|
147
|
+
return a * b;
|
|
148
|
+
case "min":
|
|
149
|
+
return Math.min(a, b);
|
|
150
|
+
case "max":
|
|
151
|
+
return Math.max(a, b);
|
|
152
|
+
default:
|
|
153
|
+
return Math.abs(a - b);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* A copy of `graph` (sharing its arrays) with edge weights drawn from `spec`. Any graph works: a
|
|
159
|
+
* generator's output, a dataset, a hand-built SampleGraph. Existing weights are replaced.
|
|
160
|
+
* @param graph - the graph
|
|
161
|
+
* @param spec - the distribution
|
|
162
|
+
* @param seed - the seed of the draws, default 0
|
|
163
|
+
* @returns the weighted graph
|
|
164
|
+
*/
|
|
165
|
+
export function withWeights(graph: SampleGraph, spec: WeightSpec, seed?: number): SampleGraph {
|
|
166
|
+
return { ...graph, weights: drawWeights(graph, spec, resolveSeed(seed)) };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Apply the common `weights` option, if set: the last step of every generator.
|
|
171
|
+
* @param graph - the generated graph
|
|
172
|
+
* @param options - the generator's options
|
|
173
|
+
* @returns the graph, weighted when asked
|
|
174
|
+
*/
|
|
175
|
+
export function applyWeights(graph: SampleGraph, options: WeightOptions): SampleGraph {
|
|
176
|
+
return options.weights === undefined ? graph : withWeights(graph, options.weights, options.seed);
|
|
177
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@graphty/graph-samples`: the shared types, the dataset catalogue, the loader for hosted
|
|
3
|
+
* datasets and the conversion to graphty-element records. The generators live in
|
|
4
|
+
* `@graphty/graph-samples/generators` and each bundled dataset in
|
|
5
|
+
* `@graphty/graph-samples/datasets/<name>`, so an application bundles only what it imports.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export { type DatasetMeta } from "./datasets/build.js";
|
|
9
|
+
export { DATASETS } from "./datasets/catalog.js";
|
|
10
|
+
export { DEFAULT_DATASET_BASE_URL, fetchDataset, type FetchDatasetOptions } from "./datasets/remote.js";
|
|
11
|
+
export { type ElementData, toElementData } from "./element.js";
|
|
12
|
+
export { type SampleGraph } from "./types.js";
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An exponential and the power functions built on it, returning the same bits on every JavaScript
|
|
3
|
+
* engine: a port of fdlibm's `__ieee754_exp` (e_exp.c, Sun Microsystems 1993), for the same reason
|
|
4
|
+
* and with the same technique as `detLog` in log.ts -- the exponent is read and written through a
|
|
5
|
+
* little-endian DataView and everything else is IEEE-754 double addition, subtraction,
|
|
6
|
+
* multiplication and division, which ECMAScript requires to be correctly rounded. Error below 1 ulp.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { detLog } from "./log.js";
|
|
10
|
+
|
|
11
|
+
const O_THRESHOLD = 7.09782712893383973096e2;
|
|
12
|
+
const U_THRESHOLD = -7.45133219101941108420e2;
|
|
13
|
+
const LN2_HI = 6.93147180369123816490e-1;
|
|
14
|
+
const LN2_LO = 1.90821492927058770002e-10;
|
|
15
|
+
const INV_LN2 = 1.44269504088896338700;
|
|
16
|
+
const TWOM1000 = 9.33263618503218878990e-302;
|
|
17
|
+
const P1 = 1.66666666666666019037e-1;
|
|
18
|
+
const P2 = -2.77777777770155933842e-3;
|
|
19
|
+
const P3 = 6.61375632143793436117e-5;
|
|
20
|
+
const P4 = -1.65339022054652515390e-6;
|
|
21
|
+
const P5 = 4.13813679705723846039e-8;
|
|
22
|
+
|
|
23
|
+
const view = new DataView(new ArrayBuffer(8));
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* `y * 2^k` for a y in [0.5, 2) and k >= -1021, by adding k to the exponent field.
|
|
27
|
+
* @param y - the mantissa part
|
|
28
|
+
* @param k - the power of two
|
|
29
|
+
* @returns the scaled value
|
|
30
|
+
*/
|
|
31
|
+
function scale(y: number, k: number): number {
|
|
32
|
+
view.setFloat64(0, y, true);
|
|
33
|
+
view.setInt32(4, view.getInt32(4, true) + (k << 20), true);
|
|
34
|
+
return view.getFloat64(0, true);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* e^x, bit-identical across engines.
|
|
39
|
+
* @param x - the argument
|
|
40
|
+
* @returns e^x; +Infinity above about 709.78, 0 below about -745.13, NaN for NaN
|
|
41
|
+
*/
|
|
42
|
+
export function detExp(x: number): number {
|
|
43
|
+
view.setFloat64(0, x, true);
|
|
44
|
+
const high = view.getInt32(4, true);
|
|
45
|
+
const negative = high < 0 ? 1 : 0;
|
|
46
|
+
const hx = high & 0x7fffffff;
|
|
47
|
+
if (hx >= 0x40862e42) {
|
|
48
|
+
if (hx >= 0x7ff00000) {
|
|
49
|
+
// NaN stays NaN, +Infinity stays, -Infinity gives 0
|
|
50
|
+
return negative === 0 || Number.isNaN(x) ? x + x : 0;
|
|
51
|
+
}
|
|
52
|
+
if (x > O_THRESHOLD) {
|
|
53
|
+
return Infinity;
|
|
54
|
+
}
|
|
55
|
+
if (x < U_THRESHOLD) {
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
let hi = 0;
|
|
60
|
+
let lo = 0;
|
|
61
|
+
let k = 0;
|
|
62
|
+
let r = x;
|
|
63
|
+
if (hx > 0x3fd62e42) {
|
|
64
|
+
// |x| > 0.5 ln 2: reduce to r = x - k ln 2
|
|
65
|
+
if (hx < 0x3ff0a2b2) {
|
|
66
|
+
hi = negative === 0 ? x - LN2_HI : x + LN2_HI;
|
|
67
|
+
lo = negative === 0 ? LN2_LO : -LN2_LO;
|
|
68
|
+
k = 1 - negative - negative;
|
|
69
|
+
} else {
|
|
70
|
+
k = Math.trunc(INV_LN2 * x + (negative === 0 ? 0.5 : -0.5));
|
|
71
|
+
hi = x - k * LN2_HI;
|
|
72
|
+
lo = k * LN2_LO;
|
|
73
|
+
}
|
|
74
|
+
r = hi - lo;
|
|
75
|
+
} else if (hx < 0x3e300000) {
|
|
76
|
+
// |x| < 2^-28
|
|
77
|
+
return 1 + x;
|
|
78
|
+
}
|
|
79
|
+
const t = r * r;
|
|
80
|
+
const c = r - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
|
|
81
|
+
if (k === 0) {
|
|
82
|
+
return 1 - ((r * c) / (c - 2.0) - r);
|
|
83
|
+
}
|
|
84
|
+
const y = 1 - (lo - (r * c) / (2.0 - c) - hi);
|
|
85
|
+
return k >= -1021 ? scale(y, k) : scale(y, k + 1000) * TWOM1000;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* x^y as `detExp(y * detLog(x))` for x > 0: deterministic, not correctly rounded (the relative
|
|
90
|
+
* error grows with |y ln x|, about 1e-13 for the magnitudes the generators use). 0^y is 0 for
|
|
91
|
+
* y > 0.
|
|
92
|
+
* @param x - the base, >= 0
|
|
93
|
+
* @param y - the exponent
|
|
94
|
+
* @returns x^y
|
|
95
|
+
*/
|
|
96
|
+
export function detPow(x: number, y: number): number {
|
|
97
|
+
if (x === 0) {
|
|
98
|
+
if (y === 0) {
|
|
99
|
+
return 1;
|
|
100
|
+
}
|
|
101
|
+
return y > 0 ? 0 : Infinity;
|
|
102
|
+
}
|
|
103
|
+
return detExp(y * detLog(x));
|
|
104
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A natural logarithm that returns the same bits on every JavaScript engine.
|
|
3
|
+
*
|
|
4
|
+
* ECMAScript leaves `Math.log` "implementation-approximated", so two engines may differ in the
|
|
5
|
+
* last bit, and a geometric skip `floor(log(u) / log(1 - p))` that lands on an integer boundary
|
|
6
|
+
* would then pick a different edge. This is a port of fdlibm's `__ieee754_log` (e_log.c, Sun
|
|
7
|
+
* Microsystems 1993, the code V8 and SpiderMonkey themselves use): it reads the exponent and
|
|
8
|
+
* mantissa through a little-endian DataView and otherwise uses only IEEE-754 double addition,
|
|
9
|
+
* subtraction, multiplication and division, which ECMAScript requires to be correctly rounded
|
|
10
|
+
* (and forbids from being fused). So the result is a pure function of the input bits.
|
|
11
|
+
* Error below 1 ulp.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const LN2_HI = 6.9314718036912381649e-1; // 3fe62e42 fee00000
|
|
15
|
+
const LN2_LO = 1.90821492927058770002e-10; // 3dea39ef 35793c76
|
|
16
|
+
const TWO54 = 1.8014398509481984e16; // 43500000 00000000
|
|
17
|
+
const LG1 = 6.66666666666673513e-1; // 3FE55555 55555593
|
|
18
|
+
const LG2 = 3.999999999940941908e-1; // 3FD99999 9997FA04
|
|
19
|
+
const LG3 = 2.857142874366239149e-1; // 3FD24924 94229359
|
|
20
|
+
const LG4 = 2.222219843214978396e-1; // 3FCC71C5 1D8E78AF
|
|
21
|
+
const LG5 = 1.818357216161805012e-1; // 3FC74664 96CB03DE
|
|
22
|
+
const LG6 = 1.531383769920937332e-1; // 3FC39A09 D078C69F
|
|
23
|
+
const LG7 = 1.479819860511658591e-1; // 3FC2F112 DF3E5244
|
|
24
|
+
|
|
25
|
+
const view = new DataView(new ArrayBuffer(8));
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The natural logarithm of `x`, bit-identical across engines.
|
|
29
|
+
* @param input - the argument
|
|
30
|
+
* @returns ln(input); -Infinity for 0, NaN for negative input or NaN
|
|
31
|
+
*/
|
|
32
|
+
export function detLog(input: number): number {
|
|
33
|
+
let x = input;
|
|
34
|
+
view.setFloat64(0, x, true);
|
|
35
|
+
let hx = view.getInt32(4, true);
|
|
36
|
+
const lx = view.getUint32(0, true);
|
|
37
|
+
|
|
38
|
+
let k = 0;
|
|
39
|
+
if (hx < 0x00100000) {
|
|
40
|
+
if (((hx & 0x7fffffff) | lx) === 0) {
|
|
41
|
+
return -Infinity;
|
|
42
|
+
}
|
|
43
|
+
if (hx < 0) {
|
|
44
|
+
return NaN;
|
|
45
|
+
}
|
|
46
|
+
// subnormal: scale up
|
|
47
|
+
k -= 54;
|
|
48
|
+
x *= TWO54;
|
|
49
|
+
view.setFloat64(0, x, true);
|
|
50
|
+
hx = view.getInt32(4, true);
|
|
51
|
+
}
|
|
52
|
+
if (hx >= 0x7ff00000) {
|
|
53
|
+
return x + x;
|
|
54
|
+
}
|
|
55
|
+
k += (hx >> 20) - 1023;
|
|
56
|
+
hx &= 0x000fffff;
|
|
57
|
+
const i0 = (hx + 0x95f64) & 0x100000;
|
|
58
|
+
// normalize x or x/2
|
|
59
|
+
view.setInt32(4, hx | (i0 ^ 0x3ff00000), true);
|
|
60
|
+
x = view.getFloat64(0, true);
|
|
61
|
+
k += i0 >> 20;
|
|
62
|
+
const f = x - 1.0;
|
|
63
|
+
if ((0x000fffff & (2 + hx)) < 3) {
|
|
64
|
+
// |f| < 2**-20
|
|
65
|
+
if (f === 0) {
|
|
66
|
+
return k === 0 ? 0 : k * LN2_HI + k * LN2_LO;
|
|
67
|
+
}
|
|
68
|
+
const r = f * f * (0.5 - 0.3333333333333333 * f);
|
|
69
|
+
return k === 0 ? f - r : k * LN2_HI - (r - k * LN2_LO - f);
|
|
70
|
+
}
|
|
71
|
+
const s = f / (2.0 + f);
|
|
72
|
+
const dk = k;
|
|
73
|
+
const z = s * s;
|
|
74
|
+
let i = hx - 0x6147a;
|
|
75
|
+
const w = z * z;
|
|
76
|
+
const j = 0x6b851 - hx;
|
|
77
|
+
const t1 = w * (LG2 + w * (LG4 + w * LG6));
|
|
78
|
+
const t2 = z * (LG1 + w * (LG3 + w * (LG5 + w * LG7)));
|
|
79
|
+
i |= j;
|
|
80
|
+
const R = t2 + t1;
|
|
81
|
+
if (i > 0) {
|
|
82
|
+
const hfsq = 0.5 * f * f;
|
|
83
|
+
return k === 0 ? f - (hfsq - s * (hfsq + R)) : dk * LN2_HI - (hfsq - (s * (hfsq + R) + dk * LN2_LO) - f);
|
|
84
|
+
}
|
|
85
|
+
return k === 0 ? f - s * (f - R) : dk * LN2_HI - (s * (f - R) - dk * LN2_LO - f);
|
|
86
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one random number source of @graphty/graph-samples, and its determinism contract.
|
|
3
|
+
*
|
|
4
|
+
* A stream is named by `(seed, domain, block)`:
|
|
5
|
+
*
|
|
6
|
+
* - `seed` is the caller's seed, any safe integer in [0, 2^53).
|
|
7
|
+
* - `domain` is a fixed ASCII name per generator and purpose ("gnp", "sbm", ...). It is hashed
|
|
8
|
+
* with 32-bit FNV-1a to `domainId`.
|
|
9
|
+
* - `block` is a unit of work the ALGORITHM defines (a row of the adjacency matrix, a node), an
|
|
10
|
+
* integer in [0, 2^32). It never depends on how many workers or chunks run the generator.
|
|
11
|
+
*
|
|
12
|
+
* The stream's key is `Threefry2x32-20(key = (seed mod 2^32, floor(seed / 2^32)),
|
|
13
|
+
* counter = (domainId, block))`, and its words are `Threefry2x32-20(key = streamKey,
|
|
14
|
+
* counter = (i mod 2^32, floor(i / 2^32)))` for i = 0, 1, 2, ..., two words per counter, word 0
|
|
15
|
+
* first. Every draw below is defined in terms of those words with integer-exact arithmetic, so the
|
|
16
|
+
* same `(seed, domain, block)` yields the same values on every engine, platform and version.
|
|
17
|
+
* `test/random/stream.test.ts` freezes it with golden values: changing anything here changes every
|
|
18
|
+
* seeded graph, which is a breaking change of the package.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { detLog } from "./log.js";
|
|
22
|
+
import { threefry2x32 } from "./threefry.js";
|
|
23
|
+
|
|
24
|
+
const TWO_32 = 4294967296;
|
|
25
|
+
const TWO_53 = 9007199254740992;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 32-bit FNV-1a over the UTF-16 code units of `name` (the names are ASCII, so this is the bytes).
|
|
29
|
+
* @param name - the domain name
|
|
30
|
+
* @returns the unsigned 32-bit hash
|
|
31
|
+
*/
|
|
32
|
+
export function domainId(name: string): number {
|
|
33
|
+
let h = 0x811c9dc5;
|
|
34
|
+
for (let i = 0; i < name.length; i++) {
|
|
35
|
+
h ^= name.charCodeAt(i);
|
|
36
|
+
h = Math.imul(h, 0x01000193);
|
|
37
|
+
}
|
|
38
|
+
return h >>> 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The seed every random generator uses when the caller gives none: 0. A fixed default, never the
|
|
43
|
+
* clock, so an unseeded call is as reproducible as a seeded one. Frozen with the rest of the
|
|
44
|
+
* contract: changing it changes every unseeded graph.
|
|
45
|
+
*/
|
|
46
|
+
export const DEFAULT_SEED = 0;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The caller's seed, or {@link DEFAULT_SEED} when it is undefined; throws on an invalid seed.
|
|
50
|
+
* @param seed - the seed option
|
|
51
|
+
* @returns the seed to use
|
|
52
|
+
*/
|
|
53
|
+
export function resolveSeed(seed: number | undefined): number {
|
|
54
|
+
const resolved = seed ?? DEFAULT_SEED;
|
|
55
|
+
checkSeed(resolved);
|
|
56
|
+
return resolved;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Throw unless `seed` is a safe non-negative integer.
|
|
61
|
+
* @param seed - the seed
|
|
62
|
+
*/
|
|
63
|
+
export function checkSeed(seed: number): void {
|
|
64
|
+
if (!Number.isSafeInteger(seed) || seed < 0) {
|
|
65
|
+
throw new RangeError(`seed must be an integer in [0, 2^53), got ${String(seed)}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** A deterministic stream of random words keyed by (seed, domain, block). */
|
|
70
|
+
export class RandomStream {
|
|
71
|
+
private readonly seedLo: number;
|
|
72
|
+
private readonly seedHi: number;
|
|
73
|
+
private readonly domain: number;
|
|
74
|
+
private readonly key = new Uint32Array(2);
|
|
75
|
+
private readonly out = new Uint32Array(2);
|
|
76
|
+
private counter = 0;
|
|
77
|
+
private spare = -1;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The stream of one block.
|
|
81
|
+
* @param seed - the caller's seed, an integer in [0, 2^53)
|
|
82
|
+
* @param domain - the generator's fixed domain name
|
|
83
|
+
* @param block - the first block, an integer in [0, 2^32)
|
|
84
|
+
*/
|
|
85
|
+
constructor(seed: number, domain: string, block: number) {
|
|
86
|
+
checkSeed(seed);
|
|
87
|
+
this.seedLo = seed >>> 0;
|
|
88
|
+
this.seedHi = Math.floor(seed / TWO_32);
|
|
89
|
+
this.domain = domainId(domain);
|
|
90
|
+
this.reset(block);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Restart the stream at the first word of another block of the same seed and domain.
|
|
95
|
+
* @param block - the block, an integer in [0, 2^32)
|
|
96
|
+
*/
|
|
97
|
+
reset(block: number): void {
|
|
98
|
+
threefry2x32(this.seedLo, this.seedHi, this.domain, block >>> 0, this.key);
|
|
99
|
+
this.counter = 0;
|
|
100
|
+
this.spare = -1;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The next word.
|
|
105
|
+
* @returns an unsigned 32-bit integer
|
|
106
|
+
*/
|
|
107
|
+
nextU32(): number {
|
|
108
|
+
if (this.spare >= 0) {
|
|
109
|
+
const word = this.spare;
|
|
110
|
+
this.spare = -1;
|
|
111
|
+
return word;
|
|
112
|
+
}
|
|
113
|
+
const c = this.counter++;
|
|
114
|
+
threefry2x32(this.key[0], this.key[1], c >>> 0, Math.floor(c / TWO_32), this.out);
|
|
115
|
+
this.spare = this.out[1];
|
|
116
|
+
return this.out[0];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* A uniform double in [0, 1) with 53 random bits: (a >>> 5) * 2^26 + (b >>> 6), over 2^53,
|
|
121
|
+
* for the next two words a and b. Exact: every step is an integer below 2^53.
|
|
122
|
+
* @returns the double
|
|
123
|
+
*/
|
|
124
|
+
nextFloat(): number {
|
|
125
|
+
const a = this.nextU32() >>> 5;
|
|
126
|
+
const b = this.nextU32() >>> 6;
|
|
127
|
+
return (a * 67108864 + b) / TWO_53;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* A uniform integer in [0, n) by masked rejection: draw a word, keep its low
|
|
132
|
+
* ceil(log2 n) bits, retry while the result is >= n. Exact and unbiased; fewer than two
|
|
133
|
+
* words per call on average. For n above 2^32 the high bits come from one extra word drawn
|
|
134
|
+
* first.
|
|
135
|
+
* @param n - the bound, an integer in [1, 2^53]
|
|
136
|
+
* @returns the integer
|
|
137
|
+
*/
|
|
138
|
+
nextBelow(n: number): number {
|
|
139
|
+
if (n <= TWO_32) {
|
|
140
|
+
const mask = n === 1 ? 0 : 0xffffffff >>> Math.clz32(n - 1);
|
|
141
|
+
for (;;) {
|
|
142
|
+
const x = (this.nextU32() & mask) >>> 0;
|
|
143
|
+
if (x < n) {
|
|
144
|
+
return x;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const hiBound = Math.ceil(n / TWO_32);
|
|
149
|
+
const hiMask = 0xffffffff >>> Math.clz32(hiBound - 1);
|
|
150
|
+
for (;;) {
|
|
151
|
+
const hi = (this.nextU32() & hiMask) >>> 0;
|
|
152
|
+
const x = hi * TWO_32 + this.nextU32();
|
|
153
|
+
if (x < n) {
|
|
154
|
+
return x;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* The number of failures before the next success of a Bernoulli(p) sequence, given
|
|
161
|
+
* `logQ = detLog(1 - p)` for 0 < p < 1: floor(detLog(1 - u) / logQ) for u = nextFloat().
|
|
162
|
+
* The caller handles p = 0 and p = 1 without drawing.
|
|
163
|
+
* @param logQ - detLog(1 - p), negative and finite
|
|
164
|
+
* @returns a non-negative integer (possibly above 2^53 for tiny p)
|
|
165
|
+
*/
|
|
166
|
+
nextSkip(logQ: number): number {
|
|
167
|
+
return Math.floor(detLog(1 - this.nextFloat()) / logQ);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Threefry-2x32 with 20 rounds: the counter-based block function of J. K. Salmon, M. A. Moraes,
|
|
3
|
+
* R. O. Dror and D. E. Shaw, "Parallel random numbers: as easy as 1, 2, 3", SC11 (2011),
|
|
4
|
+
* doi:10.1145/2063384.2063405, as specified by the Random123 library and used by JAX.
|
|
5
|
+
*
|
|
6
|
+
* It maps a 64-bit key and a 64-bit counter to 64 random bits using only 32-bit addition,
|
|
7
|
+
* rotation and xor, so JavaScript computes it exactly on every engine: no floating point, no
|
|
8
|
+
* 64-bit multiply, no BigInt. It passes BigCrush with 13 rounds; 20 is Random123's default.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Rotation constants R_32x2 of Threefry-2x32 (Random123 threefry.h). */
|
|
12
|
+
const ROTATIONS = [13, 15, 26, 6, 17, 29, 16, 24] as const;
|
|
13
|
+
|
|
14
|
+
/** The Skein key-schedule parity constant for 32-bit words. */
|
|
15
|
+
const KS_PARITY = 0x1bd11bda;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Encrypt one 64-bit counter under one 64-bit key.
|
|
19
|
+
* @param k0 - key word 0 (unsigned 32-bit)
|
|
20
|
+
* @param k1 - key word 1 (unsigned 32-bit)
|
|
21
|
+
* @param c0 - counter word 0 (unsigned 32-bit)
|
|
22
|
+
* @param c1 - counter word 1 (unsigned 32-bit)
|
|
23
|
+
* @param out - receives the two output words
|
|
24
|
+
*/
|
|
25
|
+
export function threefry2x32(k0: number, k1: number, c0: number, c1: number, out: Uint32Array): void {
|
|
26
|
+
const ks0 = k0 >>> 0;
|
|
27
|
+
const ks1 = k1 >>> 0;
|
|
28
|
+
const ks2 = (KS_PARITY ^ ks0 ^ ks1) >>> 0;
|
|
29
|
+
const ks = [ks0, ks1, ks2];
|
|
30
|
+
let x0 = (c0 + ks0) | 0;
|
|
31
|
+
let x1 = (c1 + ks1) | 0;
|
|
32
|
+
for (let round = 0; round < 20; round++) {
|
|
33
|
+
x0 = (x0 + x1) | 0;
|
|
34
|
+
const r = ROTATIONS[round & 7];
|
|
35
|
+
x1 = (x1 << r) | (x1 >>> (32 - r));
|
|
36
|
+
x1 ^= x0;
|
|
37
|
+
if ((round & 3) === 3) {
|
|
38
|
+
const s = (round + 1) >>> 2;
|
|
39
|
+
x0 = (x0 + ks[s % 3]) | 0;
|
|
40
|
+
x1 = (x1 + ks[(s + 1) % 3] + s) | 0;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
out[0] = x0;
|
|
44
|
+
out[1] = x1;
|
|
45
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The cosine and sine of a uniformly drawn angle, the same bits on every engine.
|
|
3
|
+
*
|
|
4
|
+
* The angle is given as a turn fraction u in [0, 1) (angle 2 pi u), so the argument reduction is
|
|
5
|
+
* exact: 8u splits into an octant k and a fraction f without rounding, and only f * pi / 4 rounds
|
|
6
|
+
* once. On [0, pi / 4] the polynomials are fdlibm's `__kernel_sin` and `__kernel_cos` (FreeBSD
|
|
7
|
+
* k_sin.c and k_cos.c, Sun Microsystems 1993) with a zero tail, evaluated with the four basic
|
|
8
|
+
* operations only. Error a few ulp; bit-identical everywhere.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const PIO4 = 7.85398163397448278999e-1;
|
|
12
|
+
|
|
13
|
+
const S1 = -1.66666666666666324348e-1;
|
|
14
|
+
const S2 = 8.33333333332248946124e-3;
|
|
15
|
+
const S3 = -1.98412698298579493134e-4;
|
|
16
|
+
const S4 = 2.75573137070700676789e-6;
|
|
17
|
+
const S5 = -2.50507602534068634195e-8;
|
|
18
|
+
const S6 = 1.58969099521155010221e-10;
|
|
19
|
+
|
|
20
|
+
const C1 = 4.16666666666666019037e-2;
|
|
21
|
+
const C2 = -1.38888888888741095749e-3;
|
|
22
|
+
const C3 = 2.48015872894767294178e-5;
|
|
23
|
+
const C4 = -2.75573143513906633035e-7;
|
|
24
|
+
const C5 = 2.08757232129817482790e-9;
|
|
25
|
+
const C6 = -1.13596475577881948265e-11;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* sin(x) for |x| <= pi / 4.
|
|
29
|
+
* @param x - the argument
|
|
30
|
+
* @returns the sine
|
|
31
|
+
*/
|
|
32
|
+
function kernelSin(x: number): number {
|
|
33
|
+
const z = x * x;
|
|
34
|
+
const r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6)));
|
|
35
|
+
return x + z * x * (S1 + z * r);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* cos(x) for |x| <= pi / 4.
|
|
40
|
+
* @param x - the argument
|
|
41
|
+
* @returns the cosine
|
|
42
|
+
*/
|
|
43
|
+
function kernelCos(x: number): number {
|
|
44
|
+
const z = x * x;
|
|
45
|
+
const w = z * z;
|
|
46
|
+
const r = z * (C1 + z * (C2 + z * C3)) + w * w * (C4 + z * (C5 + z * C6));
|
|
47
|
+
const hz = 0.5 * z;
|
|
48
|
+
const v = 1.0 - hz;
|
|
49
|
+
return v + (1.0 - v - hz + z * r);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* cos(2 pi u) and sin(2 pi u).
|
|
54
|
+
* @param u - the turn fraction, in [0, 1)
|
|
55
|
+
* @param out - receives [cos, sin]
|
|
56
|
+
*/
|
|
57
|
+
export function detCosSinTurn(u: number, out: Float64Array): void {
|
|
58
|
+
const t = u * 8;
|
|
59
|
+
const octant = Math.floor(t);
|
|
60
|
+
const x = (t - octant) * PIO4;
|
|
61
|
+
// the octant's angle is (octant >> 1) quarter turns plus x (even octant) or pi/2 - (pi/4 - x)
|
|
62
|
+
const odd = (octant & 1) === 1;
|
|
63
|
+
const z = odd ? PIO4 - x : x;
|
|
64
|
+
const c = odd ? kernelSin(z) : kernelCos(z);
|
|
65
|
+
const s = odd ? kernelCos(z) : kernelSin(z);
|
|
66
|
+
switch ((octant >> 1) & 3) {
|
|
67
|
+
case 0:
|
|
68
|
+
out[0] = c;
|
|
69
|
+
out[1] = s;
|
|
70
|
+
break;
|
|
71
|
+
case 1:
|
|
72
|
+
out[0] = -s;
|
|
73
|
+
out[1] = c;
|
|
74
|
+
break;
|
|
75
|
+
case 2:
|
|
76
|
+
out[0] = -c;
|
|
77
|
+
out[1] = -s;
|
|
78
|
+
break;
|
|
79
|
+
default:
|
|
80
|
+
out[0] = s;
|
|
81
|
+
out[1] = -c;
|
|
82
|
+
}
|
|
83
|
+
}
|