diff --git a/tests/vault/gear/test-chain-load-test.cpp b/tests/vault/gear/test-chain-load-test.cpp index ad8f07939..e44cb8c8a 100644 --- a/tests/vault/gear/test-chain-load-test.cpp +++ b/tests/vault/gear/test-chain-load-test.cpp @@ -231,6 +231,7 @@ namespace test { + /** @test demonstrate shaping of generated topology * - the expansion rule injects forking nodes * - after some expansion, width limitation is enforced @@ -302,6 +303,7 @@ namespace test { + /** @test demonstrate impact of reduction on graph topology * - after one fixed initial expansion, reduction causes * all chains to be joined eventually @@ -331,7 +333,6 @@ namespace test { CHECK (stat.indicators[STAT_NODE].cL == "0.37890625"_expect); // Nodes are concentrated towards the beginning - // expansion and reduction can counterbalance each other graph.expansionRule(graph.rule().probability(0.2).maxVal(3).shuffle(555)) .reductionRule(graph.rule().probability(0.2).maxVal(3).shuffle(555)) @@ -350,7 +351,6 @@ namespace test { CHECK (stat.indicators[STAT_JOIN].cL == "0.66666667"_expect); // while joins need forks as prerequisite - // expansion bursts can be balanced with a heightened reduction intensity graph.expansionRule(graph.rule().probability(0.3).maxVal(4).shuffle(555)) .reductionRule(graph.rule().probability(0.9).maxVal(2).shuffle(555)) @@ -373,6 +373,7 @@ namespace test { + /** @test demonstrate shaping of generated topology by seeding new chains * - the seed rule allows to start new chains in the middle of the graph * - combined with with reduction, the emerging structure resembles @@ -405,7 +406,6 @@ namespace test { CHECK (stat.indicators[STAT_JOIN].cL == "0.92857143"_expect); // while joining only happens at the end when connecting to exit - // combining random seed nodes with reduction leads to a processing pattern // with side-chaines successively joined into a single common result graph.seedingRule(graph.rule().probability(0.2).maxVal(3).shuffle()) @@ -430,6 +430,7 @@ namespace test { + /** @test TODO demonstrate shaping of generated topology * - TODO the prune rule terminates chains randomly * - this can lead to fragmentation in several sub-graphs @@ -438,7 +439,165 @@ namespace test { void verify_PruneChains() { + ChainLoad32 graph; + // terminate chains randomly + graph.pruningRule(graph.rule().probability(0.2)) + .buildToplolgy() +// .printTopologyDOT() +// .printTopologyStatistics() + ; + + CHECK (graph.getHash() == 0xC4AE6EB741C22FCE); + + auto stat = graph.computeGraphStatistics(); + CHECK (stat.levels == 32); // only a single line of connections... + CHECK (stat.segments == 8); // albeit severed into 8 segments + CHECK (stat.indicators[STAT_NODE].pS == 4); // with always 4 Nodes per segment + CHECK (stat.indicators[STAT_NODE].pL == 1); // and only ever a single node per level + CHECK (stat.indicators[STAT_SEED].cnt == 8); // consequently we get 8 »Seed« nodes + CHECK (stat.indicators[STAT_EXIT].cnt == 8); // 8 »Exit« nodes + CHECK (stat.indicators[STAT_LINK].cnt == 16); // and 16 interconnecting links + + + // combined with expansion, several tree-shaped segments emerge + graph.pruningRule(graph.rule().probability(0.2)) + .expansionRule(graph.rule().probability(0.6)) + .setSeed(10101) + .buildToplolgy() +// .printTopologyDOT() +// .printTopologyStatistics() + ; + + CHECK (graph.getHash() == 0xC515DB464FF76818); + + stat = graph.computeGraphStatistics(); + CHECK (stat.levels == 15); // + CHECK (stat.segments == 5); // this time the graph is segregated into 5 parts + CHECK (stat.indicators[STAT_NODE].pS == 6.4); // with 4 Nodes per segment + CHECK (stat.indicators[STAT_FORK].sL == 0.0); // where »Fork« is always placed at the beginning of each segment + CHECK (stat.indicators[STAT_LINK].sL == 0.5); // carry-on »Link« nodes in the very middle of the segment + CHECK (stat.indicators[STAT_EXIT].sL == 1.0); // and several »Exit« at the end + CHECK (stat.indicators[STAT_EXIT].pS == 2.6); // averaging 2.6 exits per segment (4·3 + 1)/5 + CHECK (stat.indicators[STAT_SEED].cnt == 5); // so overall we get 8 »Seed« nodes + CHECK (stat.indicators[STAT_FORK].cnt == 5); // 5 »Fork« nodes + CHECK (stat.indicators[STAT_EXIT].cnt == 13); // 13 »Exit« nodes + CHECK (stat.indicators[STAT_LINK].cnt == 14); // and 14 interconnecting links + CHECK (stat.indicators[STAT_NODE].pL == "2.1333333"_expect); // leading to ∅ ~2 Nodes per level + + + // however, by chance, with more randomised pruning points... + graph.pruningRule(graph.rule().probability(0.2).shuffle(5)) + .expansionRule(graph.rule().probability(0.6)) + .setSeed(10101) + .buildToplolgy() +// .printTopologyDOT() +// .printTopologyStatistics() + ; + + CHECK (graph.getHash() == 0xEF172CC4B0DE2334); + + stat = graph.computeGraphStatistics(); + CHECK (stat.segments == 1); // ...the graph can evade severing altogether + CHECK (stat.indicators[STAT_FORK].cnt == 2); // with overall 2 »Fork« + CHECK (stat.indicators[STAT_EXIT].cnt == 9); // and 9 »Exit« nodes + CHECK (stat.indicators[STAT_EXIT].pL == "1.2857143"_expect); // ∅ 1.3 exits per level + CHECK (stat.indicators[STAT_NODE].pL == "4.5714286"_expect); // ∅ 4.6 nodes per level + + + graph.expansionRule(graph.rule()); // reset + + + // combined with a special seeding rule, + // which injects /another seed/ in the next level after each seed, + // an equilibrium of chain seeding and termination can be achieved... + graph.seedingRule(graph.rule_atStart(1)) + .pruningRule(graph.rule().probability(0.2)) + .setSeed(10101) + .buildToplolgy() +// .printTopologyDOT() +// .printTopologyStatistics() + ; + + CHECK (graph.getHash() == 0xD0A27C9B81058637); + + // NOTE: this example produced 10 disjoint graph parts, + // which however start and end interleaved + stat = graph.computeGraphStatistics(); + CHECK (stat.levels == 13); // Generation carries on for 13 levels + CHECK (stat.segments == 1); // NOTE: the detection of segments FAILS here (due to interleaved starts) + CHECK (stat.indicators[STAT_SEED].cnt == 11); // 11 »Seed« nodes + CHECK (stat.indicators[STAT_EXIT].cnt == 10); // 10 »Exit« nodes + CHECK (stat.indicators[STAT_LINK].cnt == 10); // 10 interconnecting links + CHECK (stat.indicators[STAT_JOIN].cnt == 1); // and one additional »Join« + CHECK (stat.indicators[STAT_JOIN].cL == "0.91666667"_expect); // ....appended at graph completion + CHECK (stat.indicators[STAT_NODE].pL == "2.4615385"_expect); // overall ∅ 2½ nodes per level + CHECK (stat.indicators[STAT_NODE].cL == "0.48697917"_expect); // with generally levelled distribution + CHECK (stat.indicators[STAT_SEED].cL == "0.41666667"_expect); // also for the seeds + CHECK (stat.indicators[STAT_EXIT].cL == "0.55"_expect); // and the exits + + + // The next example is »interesting« insofar it shows self-similarity + // The generation is entirely repetitive and locally predictable, + // producing an ongoing sequence of small graph segments, + // partially overlapping with interwoven starts. + graph.seedingRule(graph.rule().fixedVal(1)) + .pruningRule(graph.rule().probability(0.5)) + .reductionRule(graph.rule().probability(0.8).maxVal(4)) + .setSeed(10101) + .buildToplolgy() +// .printTopologyDOT() +// .printTopologyStatistics() + ; + CHECK (graph.getHash() == 0x1D56DF2FB0D4AF97); + + stat = graph.computeGraphStatistics(); + CHECK (stat.levels == 9); // Generation carries on for 13 levels + CHECK (stat.indicators[STAT_JOIN].pL == 1); // with one »Join« event per level on average + CHECK (stat.indicators[STAT_SEED].cnt == 21); // seeds are injected with /fixed rate/, meaning that + CHECK (stat.indicators[STAT_SEED].pL == "2.3333333"_expect); // there is one additional seed for every node in previous level + + + TestChainLoad<256> gra_2; + // The next example is »interesting« insofar it shows self-similarity + // The generation is entirely repetitive and locally predictable, + // producing an ongoing sequence of small graph segments, + // partially overlapping with interwoven starts. +// gra_2.seedingRule(gra_2.rule_atLink(1)) +// .pruningRule(gra_2.rule().probability(0.4)) +// .reductionRule(gra_2.rule().probability(0.6).maxVal(5).minVal(2)) +// .setSeed(23) +// .buildToplolgy() +// .printTopologyDOT() +// .printTopologyStatistics() +// ; + + // this one goes into a stable repetition loop +// gra_2.seedingRule(gra_2.rule_atLink(1)) +// .pruningRule(gra_2.rule().probability(0.5)) +// .reductionRule(gra_2.rule().probability(0.6).maxVal(5).minVal(2)) +// .setSeed(23) +// .buildToplolgy() +// .printTopologyDOT() +// .printTopologyStatistics() +// ; + + // this one comes close to a relistic stable processing pattern + // just the individual graph is still to complicated + // and it the load increases over time + gra_2.seedingRule(gra_2.rule().probability(0.5).maxVal(2)) +// .pruningRule(gra_2.rule().probability(0.55)) + .reductionRule(gra_2.rule().probability(0.5).maxVal(5)) + .pruningRule(gra_2.rule_atJoin(1)) + .setSeed(42) + .buildToplolgy() + .printTopologyDOT() + .printTopologyStatistics() + ; +//SHOW_EXPR(graph.getHash()) + + stat = gra_2.computeGraphStatistics(); +// CHECK (stat.levels == 9); // Generation carries on for 13 levels } //SHOW_EXPR(graph.getHash()) //SHOW_EXPR(stat.indicators[STAT_NODE].pL) diff --git a/tests/vault/gear/test-chain-load.hpp b/tests/vault/gear/test-chain-load.hpp index c044a23ee..e870c96f6 100644 --- a/tests/vault/gear/test-chain-load.hpp +++ b/tests/vault/gear/test-chain-load.hpp @@ -359,6 +359,38 @@ namespace test { }); } + static Rule + rule_atJoin (uint v) + { + return Rule().mapping([v](Node* n) + { + return isJoin(n) ? Rule().fixedVal(v) + : Rule(); + }); + } + + static Rule + rule_atLink (uint v) + { + return Rule().mapping([v](Node* n) + { // NOTE: when applying these rules, + // successors are not yet wired... + return not (isJoin(n) or isStart(n)) + ? Rule().fixedVal(v) + : Rule(); + }); + } + + static Rule + rule_atJoin_else (double p1, double p2, uint v=1) + { + return Rule().mapping([p1,p2,v](Node* n) + { + return isJoin(n) ? Rule().probability(p1).maxVal(v) + : Rule().probability(p2).maxVal(v); + }); + } + /** diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 80c11788a..3dd90fab2 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -96296,15 +96296,49 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - -