Chain-Load: handle node seed and recalculation

- with the new pruning option, start-Nodes can now be anywhere
- introduce predicates to detect start-Nodes and exit-Nodes
- ensure each new seed node gets the global seed on graph construction
- provide functionality to re-propagate a seed and clear hashes
- provide functionality to recalculate the hashes over the graph
This commit is contained in:
Fischlurch 2023-11-26 22:28:12 +01:00
parent 1ff9225086
commit 619a5173b0
4 changed files with 124 additions and 9 deletions

View file

@ -1647,6 +1647,13 @@ namespace lib {
return IterExplorer::reduce ([](const reference val){ return val; });
}
/** simplified _terminal builder_ to count number of elements from this sequence. */
size_t
count()
{
return IterExplorer::reduce ([](auto){ return size_t(1); });
}
/** simplified _terminal builder_ to check if any result yields `true` (short-circuit) */
bool
has_any()

View file

@ -64,6 +64,7 @@ namespace test {
verify_Node();
verify_Topology();
control_Topology();
reseed_recalculate();
witch_gate();
}
@ -215,21 +216,51 @@ namespace test {
/** @test flexible control of generated topology
* @todo WIP 11/23 🔁 define implement
* @todo WIP 11/23 🔁 define 🔁 implement
*/
void
control_Topology()
{
auto graph = TestChainLoad<32>{};
graph.expansionRule(graph.rule().probability(0.25).maxVal(4).shuffle())
.pruningRule(graph.rule().probability(0.2).shuffle())
graph.expansionRule(graph.rule().probability(0.8).maxVal(1))
.pruningRule(graph.rule().probability(0.6))
.buildToplolgy()
.printTopologyDOT();
}
/** @test set and propagate seed values and recalculate all node hashes
* @todo WIP 11/23 🔁 define implement
*/
void
reseed_recalculate()
{
auto graph = TestChainLoad<32>{};
graph.expansionRule(graph.rule().probability(0.8).maxVal(1))
.pruningRule(graph.rule().probability(0.6))
.buildToplolgy();
using Node = TestChainLoad<32>::Node;
auto isStartNode = [](Node& n){ return isStart(n); };
auto isExitNode = [](Node& n){ return isExit(n); };
CHECK (8 == graph.allNodes().filter(isStartNode).count());
CHECK (15 == graph.allNodes().filter(isExitNode).count());
CHECK (graph.getHash() == 14172386810742845390u);
graph.setSeed(55).clearNodeHashes();
CHECK (graph.getSeed() == 55);
CHECK (graph.getHash() == 0);
graph.recalculate();
CHECK (graph.getHash() == 6093128458724583708u);
}
/** @test TODO diagnostic blah
* @todo WIP 11/23 🔁 define implement
*/

View file

@ -237,6 +237,12 @@ namespace test {
hash_combine (hash, entry->hash);
return hash;
}
friend bool isStart (Node const& n) { return isnil (n.pred); };
friend bool isStart (Node const* n) { return n and isnil (n->pred); };
friend bool isExit (Node const& n) { return isnil (n.succ); };
friend bool isExit (Node const* n) { return n and isnil (n->succ); };
};
@ -336,10 +342,12 @@ namespace test {
auto moreNext = [&]{ return next->size() < maxFan; };
auto moreNodes = [&]{ return node < &nodes_->back(); };
auto spaceLeft = [&]{ return moreNext() and moreNodes(); };
auto addNode = [&]{
auto addNode = [&](size_t seed =0)
{
Node* n = *next->add (node++);
n->clear();
n->level = level;
n->hash = seed;
return n;
};
auto apply = [&](Rule& rule, Node* n)
@ -364,8 +372,7 @@ namespace test {
size_t toExpand = apply (expansionRule,o);
while (0 < toSeed and spaceLeft())
{ // start a new chain from seed
Node* n = addNode();
n->hash = this->getSeed();
addNode(this->getSeed());
--toSeed;
}
while (0 < toExpand and spaceLeft())
@ -391,8 +398,8 @@ namespace test {
}
}
ENSURE (not isnil(next) or spaceLeft());
if (isnil(next))
addNode(); // ensure parent
if (isnil(next)) // ensure graph continues
addNode(this->getSeed());
ENSURE (not next->empty());
++level;
}
@ -411,6 +418,47 @@ namespace test {
}
/**
* Set the overall seed value.
* @note does not propagate seed to consecutive start nodes
*/
TestChainLoad&&
setSeed (size_t seed = rand())
{
nodes_->front().hash = seed;
return move(*this);
}
/**
* Recalculate all node hashes and propagate seed value.
*/
TestChainLoad&&
recalculate()
{
size_t seed = this->getSeed();
for (Node& n : allNodes())
{
n.hash = isStart(n)? seed : 0;
n.calculate();
}
return move(*this);
}
/**
* Clear node hashes and propagate seed value.
*/
TestChainLoad&&
clearNodeHashes()
{
size_t seed = this->getSeed();
for (Node& n : allNodes())
n.hash = isStart(n)? seed : 0;
return move(*this);
}
/* ===== Operators ===== */

View file

@ -98722,6 +98722,12 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="idea"/>
</node>
<node CREATED="1701013395009" ID="ID_532861011" MODIFIED="1701013411163" TEXT="&#x27f9; Corrolar: die erste Start-Node entsteht dann von selbst"/>
<node COLOR="#338800" CREATED="1701029194543" ID="ID_428563573" MODIFIED="1701029206980" TEXT="Seed aus erster Seed-Node entnehmen">
<icon BUILTIN="button_ok"/>
<node CREATED="1701029211699" ID="ID_1504750686" MODIFIED="1701029216727" TEXT="Programmiertrick.."/>
<node CREATED="1701029217650" ID="ID_820767620" MODIFIED="1701029224237" TEXT="wenn es die erste Node ist..."/>
<node CREATED="1701029224849" ID="ID_178091052" MODIFIED="1701029238572" TEXT="dann verstecken wir den aktuellen Seed im Aufrufparameter"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1699805890752" ID="ID_604823204" MODIFIED="1699827731274" TEXT="Limitierungen einhalten">
@ -99438,9 +99444,32 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<linktarget COLOR="#42b360" DESTINATION="ID_1175949615" ENDARROW="Default" ENDINCLINATION="334;0;" ID="Arrow_ID_357935660" SOURCE="ID_479859970" STARTARROW="None" STARTINCLINATION="-103;5;"/>
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700105549294" ID="ID_1778641158" MODIFIED="1700105554766" TEXT="Neuberechnung">
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700105549294" ID="ID_1778641158" MODIFIED="1701033551086" TEXT="Neuberechnung">
<icon BUILTIN="pencil"/>
<node COLOR="#435e98" CREATED="1701033351833" ID="ID_133315306" MODIFIED="1701033556660" TEXT="clearNodeHashes()">
<node CREATED="1701033364791" ID="ID_442706492" MODIFIED="1701033368037" TEXT="besucht alle Nodes"/>
<node CREATED="1701033368583" ID="ID_244375144" MODIFIED="1701033384649" TEXT="&#xfc;bertr&#xe4;gt den seed-Hash in die &#xbb;startNodes&#xab;"/>
<node CREATED="1701033387653" ID="ID_1025656772" MODIFIED="1701033395879" TEXT="alle anderen Hashes werden auf 0 gesetzt"/>
</node>
<node COLOR="#435e98" CREATED="1701033359408" ID="ID_1025063671" MODIFIED="1701033556660" STYLE="fork" TEXT="recalculate()">
<node CREATED="1701033439613" ID="ID_1016987047" MODIFIED="1701033554697" TEXT="gleiches Schema"/>
<node CREATED="1701033450252" ID="ID_1730538159" MODIFIED="1701033554697" TEXT="st&#xf6;&#xdf;t aber zudem die Berechnung der Nodes an"/>
<node COLOR="#435e98" CREATED="1701033564378" ID="ID_1444681023" MODIFIED="1701033638235" TEXT="Warum L&#xf6;schen der Hashes?">
<node CREATED="1701033583314" ID="ID_571057687" MODIFIED="1701033594728" TEXT="weil die Hash-Berechnung nicht idempotent ist"/>
<node CREATED="1701033595585" ID="ID_1443626199" MODIFIED="1701033611274" TEXT="das liegt an der Aufrufstruktur von boost::hash"/>
<node CREATED="1701033623128" ID="ID_1915341389" MODIFIED="1701033635439" TEXT="durch das L&#xf6;schen wird ein sehr naheliegender Fehler vermieden"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1701033495195" ID="ID_193483520" MODIFIED="1701033506285" TEXT="Ergebnisse im Test verifizieren">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1701033509532" ID="ID_1793560814" MODIFIED="1701033521653" TEXT="Filter-Pr&#xe4;gdikate: isStart und isExit">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1701033523034" ID="ID_1580648658" MODIFIED="1701033543744" TEXT="irgendwie geschickt auf die Nodes zugreifen und pr&#xfc;fen">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700105555476" ID="ID_587761135" MODIFIED="1700105558876" TEXT="Scheduling">
<icon BUILTIN="flag-yellow"/>
</node>