@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,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Random trees and random directed acyclic graphs.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { type U32 } from "@graphty/graph-format";
|
|
6
|
+
|
|
7
|
+
import { detLog } from "../random/log.js";
|
|
8
|
+
import { RandomStream, resolveSeed } from "../random/stream.js";
|
|
9
|
+
import { type SampleGraph } from "../types.js";
|
|
10
|
+
import { bernoulliSegment, binomialBuffer, checkInt, checkProbability, EdgeBuffer, toGraph } from "./util.js";
|
|
11
|
+
import { applyWeights, type WeightOptions } from "./weights.js";
|
|
12
|
+
|
|
13
|
+
/** Options of {@link randomTreeGraph}. */
|
|
14
|
+
export interface RandomTreeOptions extends WeightOptions {
|
|
15
|
+
/** The node count, >= 1. */
|
|
16
|
+
n: number;
|
|
17
|
+
/** The seed, an integer in [0, 2^53); default 0. */
|
|
18
|
+
seed?: number | undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A uniformly random labelled tree: a uniformly random Pruefer sequence (H. Pruefer, Archiv der
|
|
23
|
+
* Mathematik und Physik 27, 142-144, 1918) of n - 2 draws nextBelow(n) from stream (seed,
|
|
24
|
+
* "prufer", 0), decoded in O(n). Edge k joins the k-th removed leaf to its neighbour; the last
|
|
25
|
+
* edge is (leaf, n - 1).
|
|
26
|
+
* @param options - n and seed
|
|
27
|
+
* @returns the undirected tree
|
|
28
|
+
*/
|
|
29
|
+
export function randomTreeGraph(options: RandomTreeOptions): SampleGraph {
|
|
30
|
+
const { n } = options;
|
|
31
|
+
checkInt("n", n, 1);
|
|
32
|
+
const seed = resolveSeed(options.seed);
|
|
33
|
+
const out = new EdgeBuffer(n);
|
|
34
|
+
if (n === 1) {
|
|
35
|
+
return applyWeights(toGraph(1, out, false), options);
|
|
36
|
+
}
|
|
37
|
+
const stream = new RandomStream(seed, "prufer", 0);
|
|
38
|
+
const code = new Uint32Array(n - 2);
|
|
39
|
+
const degree = new Uint32Array(n).fill(1);
|
|
40
|
+
for (let i = 0; i < n - 2; i++) {
|
|
41
|
+
code[i] = stream.nextBelow(n);
|
|
42
|
+
degree[code[i]]++;
|
|
43
|
+
}
|
|
44
|
+
let ptr = 0;
|
|
45
|
+
while (degree[ptr] !== 1) {
|
|
46
|
+
ptr++;
|
|
47
|
+
}
|
|
48
|
+
let leaf = ptr;
|
|
49
|
+
for (let i = 0; i < n - 2; i++) {
|
|
50
|
+
const v = code[i];
|
|
51
|
+
out.push(leaf, v);
|
|
52
|
+
degree[v]--;
|
|
53
|
+
if (degree[v] === 1 && v < ptr) {
|
|
54
|
+
leaf = v;
|
|
55
|
+
} else {
|
|
56
|
+
ptr++;
|
|
57
|
+
while (degree[ptr] !== 1) {
|
|
58
|
+
ptr++;
|
|
59
|
+
}
|
|
60
|
+
leaf = ptr;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
out.push(leaf, n - 1);
|
|
64
|
+
return applyWeights(toGraph(n, out, false), options);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Options of {@link randomDagGraph}. */
|
|
68
|
+
export interface RandomDagOptions extends WeightOptions {
|
|
69
|
+
/** The width of every layer, top to bottom; layer i holds the next `layers[i]` node indices. */
|
|
70
|
+
layers: readonly number[];
|
|
71
|
+
/** The probability of each arc from a node to a node of the next layer. */
|
|
72
|
+
p: number;
|
|
73
|
+
/** The seed, an integer in [0, 2^53); default 0. */
|
|
74
|
+
seed?: number | undefined;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Rows [start, end) of the layered DAG: node u of layer i < L - 1 draws from stream (seed,
|
|
79
|
+
* "layered-dag", u) and holds the arcs to the chosen nodes of layer i + 1, ascending.
|
|
80
|
+
* @param starts - starts[i] = first node of layer i; starts[L] = n
|
|
81
|
+
* @param layerOf - the layer of every node
|
|
82
|
+
* @param p - the probability
|
|
83
|
+
* @param seed - the seed
|
|
84
|
+
* @param start - the first row
|
|
85
|
+
* @param end - one past the last row
|
|
86
|
+
* @param out - receives the arcs
|
|
87
|
+
*/
|
|
88
|
+
export function dagRows(
|
|
89
|
+
starts: readonly number[],
|
|
90
|
+
layerOf: U32,
|
|
91
|
+
p: number,
|
|
92
|
+
seed: number,
|
|
93
|
+
start: number,
|
|
94
|
+
end: number,
|
|
95
|
+
out: EdgeBuffer,
|
|
96
|
+
): void {
|
|
97
|
+
const logQ = detLog(1 - p);
|
|
98
|
+
const stream = new RandomStream(seed, "layered-dag", 0);
|
|
99
|
+
const last = starts.length - 2;
|
|
100
|
+
for (let u = start; u < end; u++) {
|
|
101
|
+
const layer = layerOf[u];
|
|
102
|
+
if (layer < last) {
|
|
103
|
+
stream.reset(u);
|
|
104
|
+
bernoulliSegment(stream, p, logQ, u, starts[layer + 1], starts[layer + 2], out);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* A random layered DAG: arcs only from layer i to layer i + 1, each independently with
|
|
111
|
+
* probability p, O(n + m). The standard input for layered (Sugiyama) drawing, topological sort
|
|
112
|
+
* and longest path. Arcs are listed by source node, targets ascending. Node column `layer` (u32).
|
|
113
|
+
* @param options - layers, p and seed
|
|
114
|
+
* @returns the directed graph
|
|
115
|
+
*/
|
|
116
|
+
export function randomDagGraph(options: RandomDagOptions): SampleGraph {
|
|
117
|
+
const { layers, p } = options;
|
|
118
|
+
checkInt("layers.length", layers.length, 1);
|
|
119
|
+
checkProbability("p", p);
|
|
120
|
+
const seed = resolveSeed(options.seed);
|
|
121
|
+
const starts = [0];
|
|
122
|
+
let pairs = 0;
|
|
123
|
+
for (let i = 0; i < layers.length; i++) {
|
|
124
|
+
checkInt(`layers[${i}]`, layers[i], 0);
|
|
125
|
+
starts.push(starts[i] + layers[i]);
|
|
126
|
+
if (i > 0) {
|
|
127
|
+
pairs += layers[i - 1] * layers[i];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const n = starts[layers.length];
|
|
131
|
+
checkInt("the total size", n, 0);
|
|
132
|
+
const layerOf = new Uint32Array(n);
|
|
133
|
+
for (let i = 0; i < layers.length; i++) {
|
|
134
|
+
layerOf.fill(i, starts[i], starts[i + 1]);
|
|
135
|
+
}
|
|
136
|
+
const out = binomialBuffer(pairs, p);
|
|
137
|
+
dagRows(starts, layerOf, p, seed, 0, n, out);
|
|
138
|
+
return applyWeights(toGraph(n, out, true, { layer: layerOf }), options);
|
|
139
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared plumbing of the generators: argument checks, the growable edge buffer and the Bernoulli
|
|
3
|
+
* row sampler every G(n, p)-style generator is built on.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { MAX_COUNT, type U32 } from "@graphty/graph-format";
|
|
7
|
+
|
|
8
|
+
import { type RandomStream } from "../random/stream.js";
|
|
9
|
+
import { type SampleGraph } from "../types.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Throw unless `value` is an integer in [min, max].
|
|
13
|
+
* @param name - the option name, for the message
|
|
14
|
+
* @param value - the value
|
|
15
|
+
* @param min - the smallest allowed value
|
|
16
|
+
* @param max - the largest allowed value
|
|
17
|
+
*/
|
|
18
|
+
export function checkInt(name: string, value: number, min: number, max: number = MAX_COUNT): void {
|
|
19
|
+
if (!Number.isInteger(value) || value < min || value > max) {
|
|
20
|
+
throw new RangeError(`${name} must be an integer in [${min}, ${max}], got ${String(value)}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Throw unless `value` is a probability in [0, 1].
|
|
26
|
+
* @param name - the option name, for the message
|
|
27
|
+
* @param value - the value
|
|
28
|
+
*/
|
|
29
|
+
export function checkProbability(name: string, value: number): void {
|
|
30
|
+
if (!(value >= 0 && value <= 1)) {
|
|
31
|
+
throw new RangeError(`${name} must be a probability in [0, 1], got ${String(value)}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Throw unless `count` edges fit a graph-format snapshot.
|
|
37
|
+
* @param count - the edge count
|
|
38
|
+
*/
|
|
39
|
+
export function checkEdgeCount(count: number): void {
|
|
40
|
+
if (count > MAX_COUNT) {
|
|
41
|
+
throw new RangeError(`the graph would have ${count} edges, above the limit of ${MAX_COUNT}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** A growable pair of Uint32Array edge endpoint arrays. */
|
|
46
|
+
export class EdgeBuffer {
|
|
47
|
+
src: U32;
|
|
48
|
+
dst: U32;
|
|
49
|
+
length = 0;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* An empty buffer.
|
|
53
|
+
* @param capacity - the initial capacity in edges
|
|
54
|
+
*/
|
|
55
|
+
constructor(capacity: number) {
|
|
56
|
+
const size = Math.max(16, Math.min(capacity, MAX_COUNT));
|
|
57
|
+
this.src = new Uint32Array(size);
|
|
58
|
+
this.dst = new Uint32Array(size);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Append one edge.
|
|
63
|
+
* @param u - the source index
|
|
64
|
+
* @param v - the target index
|
|
65
|
+
*/
|
|
66
|
+
push(u: number, v: number): void {
|
|
67
|
+
if (this.length === this.src.length) {
|
|
68
|
+
this.grow();
|
|
69
|
+
}
|
|
70
|
+
this.src[this.length] = u;
|
|
71
|
+
this.dst[this.length] = v;
|
|
72
|
+
this.length++;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* The edges pushed so far as exactly sized arrays (copies when the buffer has slack).
|
|
77
|
+
* @returns the endpoint arrays
|
|
78
|
+
*/
|
|
79
|
+
finish(): { src: U32; dst: U32 } {
|
|
80
|
+
if (this.length === this.src.length) {
|
|
81
|
+
return { src: this.src, dst: this.dst };
|
|
82
|
+
}
|
|
83
|
+
return { src: this.src.slice(0, this.length), dst: this.dst.slice(0, this.length) };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private grow(): void {
|
|
87
|
+
checkEdgeCount(this.length + 1);
|
|
88
|
+
const size = Math.min(this.src.length * 2, MAX_COUNT);
|
|
89
|
+
const src = new Uint32Array(size);
|
|
90
|
+
const dst = new Uint32Array(size);
|
|
91
|
+
src.set(this.src);
|
|
92
|
+
dst.set(this.dst);
|
|
93
|
+
this.src = src;
|
|
94
|
+
this.dst = dst;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* A buffer sized for a binomial number of edges: the mean plus six standard deviations, so it
|
|
100
|
+
* almost never grows.
|
|
101
|
+
* @param pairs - the number of candidate pairs
|
|
102
|
+
* @param p - the edge probability
|
|
103
|
+
* @returns the buffer
|
|
104
|
+
*/
|
|
105
|
+
export function binomialBuffer(pairs: number, p: number): EdgeBuffer {
|
|
106
|
+
const mean = pairs * p;
|
|
107
|
+
checkEdgeCount(mean);
|
|
108
|
+
return new EdgeBuffer(Math.ceil(mean + 6 * Math.sqrt(mean * (1 - p)) + 16));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Append (row, c) for every column c in [lo, hi) chosen independently with probability p, in
|
|
113
|
+
* ascending c, by geometric skipping (V. Batagelj and U. Brandes, "Efficient generation of large
|
|
114
|
+
* random networks", Phys. Rev. E 71, 036113, 2005): O(1 + selected) draws instead of hi - lo.
|
|
115
|
+
* p = 0 and p = 1 draw nothing.
|
|
116
|
+
* @param stream - the row's stream
|
|
117
|
+
* @param p - the probability
|
|
118
|
+
* @param logQ - detLog(1 - p)
|
|
119
|
+
* @param row - the row node, written as the source
|
|
120
|
+
* @param lo - the first candidate column
|
|
121
|
+
* @param hi - one past the last candidate column
|
|
122
|
+
* @param out - the buffer
|
|
123
|
+
*/
|
|
124
|
+
export function bernoulliSegment(
|
|
125
|
+
stream: RandomStream,
|
|
126
|
+
p: number,
|
|
127
|
+
logQ: number,
|
|
128
|
+
row: number,
|
|
129
|
+
lo: number,
|
|
130
|
+
hi: number,
|
|
131
|
+
out: EdgeBuffer,
|
|
132
|
+
): void {
|
|
133
|
+
if (p === 0 || lo >= hi) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (p === 1) {
|
|
137
|
+
for (let c = lo; c < hi; c++) {
|
|
138
|
+
out.push(row, c);
|
|
139
|
+
}
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
let c = lo + stream.nextSkip(logQ);
|
|
143
|
+
while (c < hi) {
|
|
144
|
+
out.push(row, c);
|
|
145
|
+
c += 1 + stream.nextSkip(logQ);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Assemble an undirected or directed SampleGraph from a buffer.
|
|
151
|
+
* @param nodeCount - the node count
|
|
152
|
+
* @param edges - the edges
|
|
153
|
+
* @param directed - whether the graph is directed
|
|
154
|
+
* @param nodeColumns - ground-truth columns, if any
|
|
155
|
+
* @returns the graph
|
|
156
|
+
*/
|
|
157
|
+
export function toGraph(
|
|
158
|
+
nodeCount: number,
|
|
159
|
+
edges: EdgeBuffer,
|
|
160
|
+
directed: boolean,
|
|
161
|
+
nodeColumns?: SampleGraph["nodeColumns"],
|
|
162
|
+
): SampleGraph {
|
|
163
|
+
const { src, dst } = edges.finish();
|
|
164
|
+
return nodeColumns === undefined
|
|
165
|
+
? { directed, nodeCount, src, dst }
|
|
166
|
+
: { directed, nodeCount, src, dst, nodeColumns };
|
|
167
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural variants for testing consumers: random multigraphs, a helper that adds self-loops,
|
|
3
|
+
* parallel and anti-parallel edges to any graph, and a pack of small (and a few huge) edge-case
|
|
4
|
+
* graphs that parsers, loaders and algorithms must survive.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { RandomStream, resolveSeed } from "../random/stream.js";
|
|
8
|
+
import { type SampleGraph } from "../types.js";
|
|
9
|
+
import { checkEdgeCount, checkInt } from "./util.js";
|
|
10
|
+
import { applyWeights, type WeightOptions } from "./weights.js";
|
|
11
|
+
|
|
12
|
+
/** Options of {@link randomMultigraph}. */
|
|
13
|
+
export interface RandomMultigraphOptions extends WeightOptions {
|
|
14
|
+
/** The node count, >= 1 (>= 2 without self-loops). */
|
|
15
|
+
n: number;
|
|
16
|
+
/** The edge count, >= 0. */
|
|
17
|
+
m: number;
|
|
18
|
+
/** Whether the edges are directed; default false. */
|
|
19
|
+
directed?: boolean | undefined;
|
|
20
|
+
/** Whether an edge may join a node to itself; default true. */
|
|
21
|
+
selfLoops?: boolean | undefined;
|
|
22
|
+
/** The seed, an integer in [0, 2^53); default 0. */
|
|
23
|
+
seed?: number | undefined;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A random multigraph: m edges, each an independent uniform ordered pair (u, v) -- drawn with
|
|
28
|
+
* replacement, so parallel edges and (when allowed) self-loops are kept. Undirected, this is the
|
|
29
|
+
* "each endpoint uniform" model: a given self-loop is half as likely as a given pair u != v. Edge e
|
|
30
|
+
* draws u = nextBelow(n) and then v = nextBelow(n), or v = nextBelow(n - 1) shifted past u when
|
|
31
|
+
* self-loops are off, from the stream (seed, "multigraph", 0); one sequential stream, since two
|
|
32
|
+
* draws per edge are cheaper than a per-edge stream derivation. O(m).
|
|
33
|
+
* @param options - n, m, directed, selfLoops and seed
|
|
34
|
+
* @returns the multigraph
|
|
35
|
+
*/
|
|
36
|
+
export function randomMultigraph(options: RandomMultigraphOptions): SampleGraph {
|
|
37
|
+
const { n, m } = options;
|
|
38
|
+
const loops = options.selfLoops ?? true;
|
|
39
|
+
checkInt("n", n, 1);
|
|
40
|
+
checkInt("m", m, 0);
|
|
41
|
+
if (!loops && n < 2) {
|
|
42
|
+
throw new RangeError(`selfLoops: false needs n >= 2, got ${n}`);
|
|
43
|
+
}
|
|
44
|
+
const stream = new RandomStream(resolveSeed(options.seed), "multigraph", 0);
|
|
45
|
+
const src = new Uint32Array(m);
|
|
46
|
+
const dst = new Uint32Array(m);
|
|
47
|
+
for (let e = 0; e < m; e++) {
|
|
48
|
+
const u = stream.nextBelow(n);
|
|
49
|
+
let v: number;
|
|
50
|
+
if (loops) {
|
|
51
|
+
v = stream.nextBelow(n);
|
|
52
|
+
} else {
|
|
53
|
+
v = stream.nextBelow(n - 1);
|
|
54
|
+
if (v >= u) {
|
|
55
|
+
v++;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
src[e] = u;
|
|
59
|
+
dst[e] = v;
|
|
60
|
+
}
|
|
61
|
+
return applyWeights({ directed: options.directed ?? false, nodeCount: n, src, dst }, options);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Options of {@link addPathologicalEdges}. */
|
|
65
|
+
export interface PathologicalEdgeOptions {
|
|
66
|
+
/** How many self-loops to add at uniform nodes; default 0. */
|
|
67
|
+
selfLoops?: number | undefined;
|
|
68
|
+
/** How many copies of uniform existing edges to add; default 0. */
|
|
69
|
+
parallelEdges?: number | undefined;
|
|
70
|
+
/** How many reversed copies of uniform existing arcs to add (directed graphs only); default 0. */
|
|
71
|
+
antiParallelEdges?: number | undefined;
|
|
72
|
+
/** The seed, an integer in [0, 2^53); default 0. */
|
|
73
|
+
seed?: number | undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* A copy of `graph` with pathological edges appended after its own, in this order: `selfLoops`
|
|
78
|
+
* self-loops (v, v) at v = nextBelow(nodeCount); `parallelEdges` copies of edge e =
|
|
79
|
+
* nextBelow(original edge count); `antiParallelEdges` reversed copies (dst[e], src[e]) of
|
|
80
|
+
* e = nextBelow(original edge count). Copies are only ever of the original edges. Draws come from
|
|
81
|
+
* the stream (seed, "pathological", 0) in that order. A weighted graph's copies keep the copied
|
|
82
|
+
* edge's weight and a self-loop gets weight 1. `ids` and `nodeColumns` are shared, not copied.
|
|
83
|
+
* O(m + added).
|
|
84
|
+
* @param graph - the graph
|
|
85
|
+
* @param options - the counts and the seed
|
|
86
|
+
* @returns the new graph
|
|
87
|
+
*/
|
|
88
|
+
export function addPathologicalEdges(graph: SampleGraph, options: PathologicalEdgeOptions): SampleGraph {
|
|
89
|
+
const loops = options.selfLoops ?? 0;
|
|
90
|
+
const parallel = options.parallelEdges ?? 0;
|
|
91
|
+
const anti = options.antiParallelEdges ?? 0;
|
|
92
|
+
checkInt("selfLoops", loops, 0);
|
|
93
|
+
checkInt("parallelEdges", parallel, 0);
|
|
94
|
+
checkInt("antiParallelEdges", anti, 0);
|
|
95
|
+
if (anti > 0 && !graph.directed) {
|
|
96
|
+
throw new RangeError("antiParallelEdges needs a directed graph");
|
|
97
|
+
}
|
|
98
|
+
const m = graph.src.length;
|
|
99
|
+
if (loops > 0 && graph.nodeCount === 0) {
|
|
100
|
+
throw new RangeError("selfLoops needs a graph with at least one node");
|
|
101
|
+
}
|
|
102
|
+
if (parallel + anti > 0 && m === 0) {
|
|
103
|
+
throw new RangeError("parallelEdges and antiParallelEdges need a graph with at least one edge");
|
|
104
|
+
}
|
|
105
|
+
const total = m + loops + parallel + anti;
|
|
106
|
+
checkEdgeCount(total);
|
|
107
|
+
const stream = new RandomStream(resolveSeed(options.seed), "pathological", 0);
|
|
108
|
+
const src = new Uint32Array(total);
|
|
109
|
+
const dst = new Uint32Array(total);
|
|
110
|
+
src.set(graph.src);
|
|
111
|
+
dst.set(graph.dst);
|
|
112
|
+
const weights = graph.weights === undefined ? undefined : new Float32Array(total);
|
|
113
|
+
weights?.set(graph.weights ?? []);
|
|
114
|
+
let e = m;
|
|
115
|
+
for (let i = 0; i < loops; i++, e++) {
|
|
116
|
+
const v = stream.nextBelow(graph.nodeCount);
|
|
117
|
+
src[e] = v;
|
|
118
|
+
dst[e] = v;
|
|
119
|
+
if (weights !== undefined) {
|
|
120
|
+
weights[e] = 1;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
for (let i = 0; i < parallel + anti; i++, e++) {
|
|
124
|
+
const f = stream.nextBelow(m);
|
|
125
|
+
const reversed = i >= parallel;
|
|
126
|
+
src[e] = reversed ? graph.dst[f] : graph.src[f];
|
|
127
|
+
dst[e] = reversed ? graph.src[f] : graph.dst[f];
|
|
128
|
+
if (weights !== undefined) {
|
|
129
|
+
weights[e] = weights[f];
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return { ...graph, src, dst, weights };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** The names of the {@link edgeCaseGraph} cases. */
|
|
136
|
+
export const EDGE_CASE_NAMES = [
|
|
137
|
+
"empty",
|
|
138
|
+
"single-node",
|
|
139
|
+
"single-self-loop",
|
|
140
|
+
"isolated-nodes",
|
|
141
|
+
"disconnected",
|
|
142
|
+
"pathological-undirected",
|
|
143
|
+
"pathological-directed",
|
|
144
|
+
"zero-weights",
|
|
145
|
+
"negative-weights",
|
|
146
|
+
"negative-cycle",
|
|
147
|
+
"duplicate-heavy",
|
|
148
|
+
"max-node-index",
|
|
149
|
+
"star-100k",
|
|
150
|
+
"path-100k",
|
|
151
|
+
] as const;
|
|
152
|
+
|
|
153
|
+
/** One of {@link EDGE_CASE_NAMES}. */
|
|
154
|
+
export type EdgeCaseName = (typeof EDGE_CASE_NAMES)[number];
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* A small graph from a flat edge list.
|
|
158
|
+
* @param directed - whether the edges are directed
|
|
159
|
+
* @param nodeCount - the node count
|
|
160
|
+
* @param edges - [u, v, u, v, ...], or [u, v, w, u, v, w, ...] when weighted
|
|
161
|
+
* @param weighted - whether every edge carries a weight
|
|
162
|
+
* @returns the graph
|
|
163
|
+
*/
|
|
164
|
+
function build(directed: boolean, nodeCount: number, edges: readonly number[], weighted = false): SampleGraph {
|
|
165
|
+
const stride = weighted ? 3 : 2;
|
|
166
|
+
const m = edges.length / stride;
|
|
167
|
+
const src = new Uint32Array(m);
|
|
168
|
+
const dst = new Uint32Array(m);
|
|
169
|
+
const weights = new Float32Array(weighted ? m : 0);
|
|
170
|
+
for (let e = 0; e < m; e++) {
|
|
171
|
+
src[e] = edges[e * stride];
|
|
172
|
+
dst[e] = edges[e * stride + 1];
|
|
173
|
+
weights[e] = weighted ? edges[e * stride + 2] : 0;
|
|
174
|
+
}
|
|
175
|
+
return weighted ? { directed, nodeCount, src, dst, weights } : { directed, nodeCount, src, dst };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* A graph whose edge e is end(e) for e < m.
|
|
180
|
+
* @param nodeCount - the node count
|
|
181
|
+
* @param m - the edge count
|
|
182
|
+
* @param end - maps e to [source, target]
|
|
183
|
+
* @returns the undirected graph
|
|
184
|
+
*/
|
|
185
|
+
function generated(nodeCount: number, m: number, end: (e: number) => [number, number]): SampleGraph {
|
|
186
|
+
const src = new Uint32Array(m);
|
|
187
|
+
const dst = new Uint32Array(m);
|
|
188
|
+
for (let e = 0; e < m; e++) {
|
|
189
|
+
[src[e], dst[e]] = end(e);
|
|
190
|
+
}
|
|
191
|
+
return { directed: false, nodeCount, src, dst };
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const CASES: Record<EdgeCaseName, () => SampleGraph> = {
|
|
195
|
+
empty: () => build(false, 0, []),
|
|
196
|
+
"single-node": () => build(false, 1, []),
|
|
197
|
+
"single-self-loop": () => build(false, 1, [0, 0]),
|
|
198
|
+
"isolated-nodes": () => build(false, 10, []),
|
|
199
|
+
// triangle 0-1-2, path 3-4-5, edge 6-7, isolated 8 and 9
|
|
200
|
+
disconnected: () => build(false, 10, [0, 1, 1, 2, 2, 0, 3, 4, 4, 5, 6, 7]),
|
|
201
|
+
// self-loop at 0; (1, 2) three times, once written (2, 1); weights 0, negative and fractional
|
|
202
|
+
"pathological-undirected": () =>
|
|
203
|
+
build(false, 4, [0, 0, 1, 1, 2, 0, 1, 2, -2, 2, 1, 0.5, 2, 3, 2.5, 3, 0, -1], true),
|
|
204
|
+
// self-loop at 0; parallel arcs 0 -> 1; the 2-cycle 1 <-> 2 (an anti-parallel pair, one arc
|
|
205
|
+
// of weight 0); the negative cycle 2 -> 3 -> 4 -> 2 of total weight -2, reachable from 0
|
|
206
|
+
"pathological-directed": () =>
|
|
207
|
+
build(true, 5, [0, 0, 1, 0, 1, 2, 0, 1, 3, 1, 2, 1, 2, 1, 0, 2, 3, -1, 3, 4, -2, 4, 2, 1, 1, 3, 0.5], true),
|
|
208
|
+
// a 4-cycle with the chord 0-2, every weight 0: ties everywhere for Dijkstra and MST
|
|
209
|
+
"zero-weights": () => build(false, 4, [0, 1, 0, 1, 2, 0, 2, 3, 0, 3, 0, 0, 0, 2, 0], true),
|
|
210
|
+
// a DAG with negative arcs and no negative cycle; distances from 0 are [0, 4, 1, 4, 3]
|
|
211
|
+
"negative-weights": () => build(true, 5, [0, 1, 4, 0, 2, 2, 1, 2, -3, 1, 3, 2, 2, 3, 3, 3, 4, -1, 2, 4, 5], true),
|
|
212
|
+
// 0 -> 1, then the cycle 1 -> 2 -> 3 -> 1 of total weight -1
|
|
213
|
+
"negative-cycle": () => build(true, 4, [0, 1, 1, 1, 2, -1, 2, 3, -1, 3, 1, 1], true),
|
|
214
|
+
// 1,000 copies of the edge (0, 1)
|
|
215
|
+
"duplicate-heavy": () => generated(2, 1000, () => [0, 1]),
|
|
216
|
+
// 2^20 nodes, edges only at the ends: sparse index handling and large-id output
|
|
217
|
+
"max-node-index": () => build(false, 2 ** 20, [0, 1, 2 ** 20 - 2, 2 ** 20 - 1, 0, 2 ** 20 - 1]),
|
|
218
|
+
// hub 0 with 100,000 leaves
|
|
219
|
+
"star-100k": () => generated(100_001, 100_000, (e) => [0, e + 1]),
|
|
220
|
+
// the path 0 - 1 - ... - 99,999
|
|
221
|
+
"path-100k": () => generated(100_000, 99_999, (e) => [e, e + 1]),
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* An edge-case graph for testing parsers, loaders and algorithms. Every case loads with
|
|
226
|
+
* graph-format's `fromEdgeArrays` default options, and each call returns fresh arrays.
|
|
227
|
+
*
|
|
228
|
+
* - `empty`: 0 nodes, 0 edges.
|
|
229
|
+
* - `single-node`: 1 node, no edges.
|
|
230
|
+
* - `single-self-loop`: 1 node with a self-loop.
|
|
231
|
+
* - `isolated-nodes`: 10 nodes, no edges.
|
|
232
|
+
* - `disconnected`: a triangle, a 3-node path, one edge and 2 isolated nodes (5 components).
|
|
233
|
+
* - `pathological-undirected`: a self-loop, a triple parallel edge (one written reversed), weights
|
|
234
|
+
* 0, negative and fractional.
|
|
235
|
+
* - `pathological-directed`: a self-loop, parallel arcs, an anti-parallel pair (a 2-cycle), a
|
|
236
|
+
* negative-weight cycle reachable from 0, zero and negative weights.
|
|
237
|
+
* - `zero-weights`: a 4-cycle plus a chord, all weights 0.
|
|
238
|
+
* - `negative-weights`: a DAG with negative weights and no negative cycle (Bellman-Ford, DAG
|
|
239
|
+
* shortest paths); distances from 0 are [0, 4, 1, 4, 3].
|
|
240
|
+
* - `negative-cycle`: a directed cycle of total weight -1 reachable from node 0.
|
|
241
|
+
* - `duplicate-heavy`: 1,000 copies of the edge (0, 1).
|
|
242
|
+
* - `max-node-index`: 2^20 nodes, 3 edges touching nodes 0, 1, 2^20 - 2 and 2^20 - 1.
|
|
243
|
+
* - `star-100k`: a hub with 100,000 leaves (degree extremes).
|
|
244
|
+
* - `path-100k`: a 100,000-node path (deep recursion, long diameters).
|
|
245
|
+
* @param name - the case
|
|
246
|
+
* @returns the graph
|
|
247
|
+
*/
|
|
248
|
+
export function edgeCaseGraph(name: EdgeCaseName): SampleGraph {
|
|
249
|
+
if (!(EDGE_CASE_NAMES as readonly string[]).includes(name)) {
|
|
250
|
+
throw new RangeError(`unknown edge case "${name}"; expected one of ${EDGE_CASE_NAMES.join(", ")}`);
|
|
251
|
+
}
|
|
252
|
+
return CASES[name]();
|
|
253
|
+
}
|