Chain-Load: develop a design for a random-number-drawing DSL

This might seem totally overblown -- but already the development
of this prototype showed me time and again, that it is warranted.
Because it is damn hard to get the probabilities and the mappings
to fixed output values correct.

After in-depth analysis, I decided completely to abandon the
initially chosen approach with the Cap helper, where the user
just specifies an upper and lower bound. While this seems
compellingly simple at start, it directly lures into writing
hard-to-understand code tied to the implementation logic.

With the changed approach, most code should get along rather with

auto myRule = Draw().probabilty(0.6).maxVal(4);

...which is obviously a thousand times more legible than
any kind of tricky modulus expressions with shifted bounds.
This commit is contained in:
Fischlurch 2023-11-20 02:00:56 +01:00
parent 34f1b0da89
commit e127d0ad9a
2 changed files with 603 additions and 16 deletions

View file

@ -57,6 +57,18 @@
* limited to a very small value range. While numerically simple, this turns out to be rather
* error-prone, hence the desire to put a DSL in front. The challenge however arises from
* the additional requirement to support various usage patters, all with minimal specs.
*
* The following code lays out the ground structure, while treating Spec as a distinct
* type, which is then mixed into Draw. This logical separation basically was led me to the
* final solution: Draw both _is_ a function and _embodies_ the implementation of this function.
* This somewhat surprising layout is what enables use as a DSL builder, because it allows both
* to have the _builder use_ and the _converter use_ in the same class, even allowing to _define_
* a Draw by giving a function which _produces_ a (dynamically parametrised) Draw.
*
* In this prototype, all of the functor adaptation is also part of the Draw template; for the
* real implementation this will have to be supplied at usage site through a traits template,
* otherwise it would not be possible to integrate seamlessly with custom data sources (as
* happens in the intended use case, where actually a Node is the data source)
*/
typedef unsigned int uint;
@ -69,20 +81,24 @@ typedef unsigned int uint;
#include "lib/meta/function.hpp"
#include <functional>
#include <utility>
using lib::meta::_Fun;
using std::function;
using std::forward;
using std::move;
template<typename T, T max>
struct Limited
{
static constexpr T min() { return T(0); }
static constexpr T max() { return max; }
static constexpr T minVal() { return T(0); }
static constexpr T maxVal() { return max; }
T val;
template<typename X>
Limited (X raw)
: val(util::limited (X(min()), raw, X(max())))
: val(util::limited (X(minVal()), raw, X(maxVal())))
{ }
};
@ -90,22 +106,26 @@ template<typename T, T max>
struct Spec
{
using Lim = Limited<T,max>;
static constexpr double CAP_EPSILON = 0.001;
static constexpr double CAP_EPSILON = 0.0001;
double lower{0};
double upper{max};
double probability{0};
T maxResult{Lim::maxVal()};
Spec() = default;
explicit
Spec (double p) : probability{p}{ }
Lim
limited (double val)
{
if (val==lower)
if (probability == 0.0 or val == 0.0)
return Lim{0};
val -= lower;
val /= upper-lower;
val *= max;
val += CAP_EPSILON;
double q = (1.0 - probability);
val -= q;
val /= probability;
val *= maxResult;
val += 1 + CAP_EPSILON;
return Lim{val};
}
@ -122,13 +142,136 @@ struct Draw
Draw()
: Spc{}
, Fun{[](size_t){ return Spc{}.limited(0); }}
, Fun{[this](size_t hash){ return Spc::limited (asRand (hash)); }}
{ }
template<class FUN>
Draw(FUN fun)
: Fun{fun}
Draw(FUN&& fun)
: Spc{1.0}
, Fun{adaptOut(adaptIn(std::forward<FUN> (fun)))}
{ }
Draw&&
probability (double p)
{
Spc::probability = p;
return move (*this);
}
Draw&&
maxVal (uint m)
{
Spc::maxResult = m;
return move (*this);
}
template<class FUN>
Draw&&
mapping (FUN&& fun)
{
Fun(*this) = adaptOut(adaptIn(std::forward<FUN> (fun)));
return move (*this);
}
double
asRand (size_t hash)
{
return double(hash % 256)/256;
}
/**
* @internal helper to expose the signature `size_t(size_t)`
* by wrapping a given lambda or functor.
*/
template<class SIG, typename SEL=void>
struct Adaptor
{
static_assert (not sizeof(SIG), "Unable to adapt given functor.");
};
template<typename RES>
struct Adaptor<RES(size_t)>
{
template<typename FUN>
static decltype(auto)
build (FUN&& fun)
{
return std::forward<FUN>(fun);
}
};
template<typename RES>
struct Adaptor<RES(void)>
{
template<typename FUN>
static auto
build (FUN&& fun)
{
return [functor=std::forward<FUN>(fun)]
(size_t)
{
return functor();
};
}
};
template<class FUN>
decltype(auto)
adaptIn (FUN&& fun)
{
static_assert (lib::meta::_Fun<FUN>(), "Need something function-like.");
static_assert (lib::meta::_Fun<FUN>::ARITY <= 1, "Function with zero or one argument expected.");
using Sig = typename lib::meta::_Fun<FUN>::Sig;
return Adaptor<Sig>::build (forward<FUN> (fun));
}
template<class FUN>
decltype(auto)
adaptOut (FUN&& fun)
{
static_assert (lib::meta::_Fun<FUN>(), "Need something function-like.");
static_assert (lib::meta::_Fun<FUN>::ARITY ==1, "Function with exactly one argument required.");
using Res = typename lib::meta::_Fun<FUN>::Ret;
if constexpr (std::is_same_v<Res, Lim>)
return std::forward<FUN>(fun);
else
if constexpr (std::is_same_v<Res, size_t>)
return [functor=std::forward<FUN>(fun), this]
(size_t rawHash)
{
size_t hash = functor(rawHash);
double randomNum = asRand (hash);
return Spc::limited (randomNum);
};
else
if constexpr (std::is_same_v<Res, double>)
return [functor=std::forward<FUN>(fun), this]
(size_t rawHash)
{
double randomNum = functor(rawHash);
return Spc::limited (randomNum);
};
else
if constexpr (std::is_same_v<Res, Draw>)
return [functor=std::forward<FUN>(fun), this]
(size_t rawHash)
{
Draw parametricDraw = functor(rawHash);
return parametricDraw (rawHash);
};
else
static_assert (not sizeof(Res), "unable to adapt / handle result type");
NOTREACHED("Handle based on return type");
}
};
int
@ -140,10 +283,34 @@ main (int, char**)
D draw;
SHOW_EXPR(draw)
SHOW_EXPR(draw(5).val)
draw = D{[](size_t i){ return S{}.limited(i); }};
draw = D{[](size_t i){ return 0.75; }};
SHOW_EXPR(draw(5).val)
draw = D{}.probability(0.25).maxVal(5);
SHOW_EXPR(draw(256-65).val)
SHOW_EXPR(draw(256-64).val)
SHOW_EXPR(draw(256-64+ 1).val)
SHOW_EXPR(draw(256-64+10).val)
SHOW_EXPR(draw(256-64+11).val)
SHOW_EXPR(draw(256-64+12).val)
SHOW_EXPR(draw(256-64+13).val)
SHOW_EXPR(draw(256-64+23).val)
SHOW_EXPR(draw(256-64+24).val)
SHOW_EXPR(draw(256-64+25).val)
SHOW_EXPR(draw(256-64+26).val)
SHOW_EXPR(draw(256-64+36).val)
SHOW_EXPR(draw(256-64+37).val)
SHOW_EXPR(draw(256-64+38).val)
SHOW_EXPR(draw(256-64+39).val)
SHOW_EXPR(draw(256-64+49).val)
SHOW_EXPR(draw(256-64+50).val)
SHOW_EXPR(draw(256-64+51).val)
SHOW_EXPR(draw(256-64+52).val)
SHOW_EXPR(draw(256-64+62).val)
SHOW_EXPR(draw(256-64+63).val)
SHOW_EXPR(draw(256).val)
cout << "\n.gulp.\n";
return 0;
}

View file

@ -96122,13 +96122,433 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700264961367" ID="ID_788328130" MODIFIED="1700331818142" TEXT="Einstieg: ein Funktor-Adaptor (wie neulich f&#xfc;r microbenchmark)">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1700265008950" ID="ID_751701905" MODIFIED="1700265018898" TEXT="der Funktor liefert am Ende ein Draw"/>
<node CREATED="1700265019715" ID="ID_624547616" MODIFIED="1700265047770" TEXT="aber auf Wunsch kann man auch ein Draw in die Hand bekommen"/>
<node COLOR="#5b280f" CREATED="1700265019715" ID="ID_624547616" MODIFIED="1700345650023" TEXT="aber auf Wunsch kann man auch ein Draw in die Hand bekommen">
<linktarget COLOR="#ad253c" DESTINATION="ID_624547616" ENDARROW="Default" ENDINCLINATION="679;28;" ID="Arrow_ID_124457360" SOURCE="ID_790826770" STARTARROW="None" STARTINCLINATION="-215;-7;"/>
<icon BUILTIN="button_cancel"/>
</node>
<node CREATED="1700331717687" ID="ID_503595857" MODIFIED="1700331791642" TEXT="&#x27f9; Draw mu&#xdf; eine Doppel-Natur haben: es ist sowohl das Cap, alsauch ein Funktor">
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700331799351" ID="ID_619819862" MODIFIED="1700331808784" TEXT="Baumuster untersuchen (try.cpp)...">
<icon BUILTIN="pencil"/>
<node CREATED="1700342161236" ID="ID_1281138479" MODIFIED="1700342171869" TEXT="1.Enwurf: Funktions-Komposition">
<node CREATED="1700342178718" ID="ID_1331338727" MODIFIED="1700342198924" TEXT="die Cap-Funktionalit&#xe4;t als eigener Funktor"/>
<node CREATED="1700342199523" ID="ID_1963684995" MODIFIED="1700342217408" TEXT="vorgeschaltet dann die Erzeugung des Zufallswertes"/>
<node CREATED="1700342243501" ID="ID_1390319632" MODIFIED="1700342253999" TEXT="damit w&#xe4;ren wir aber einerm reinen Funktor-Builder"/>
<node CREATED="1700342254915" ID="ID_834526555" MODIFIED="1700342262877" TEXT="w&#xfc;rde gehen, war aber nicht das was mir vorschwebte"/>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1700342264818" ID="ID_330199412" MODIFIED="1700342273106" TEXT="was will ich denn &#xfc;berhaupt?">
<font NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="help"/>
<node CREATED="1700342274840" ID="ID_1272510180" MODIFIED="1700342289356" TEXT="wahrscheinlich alles und nix Bestimmtes...">
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="smiley-angry"/>
</node>
<node CREATED="1700342294128" ID="ID_537212981" MODIFIED="1700342303208" TEXT="F&#xe4;lle">
<node CREATED="1700342304484" ID="ID_1886340875" MODIFIED="1700342308511" TEXT="Fix und Null"/>
<node CREATED="1700342309883" ID="ID_1696099413" MODIFIED="1700342328894" TEXT="parametrisierbarer Baukasten">
<node CREATED="1700342331280" ID="ID_1439525551" MODIFIED="1700342337658" TEXT="x% Wahrscheinlichkeit"/>
<node CREATED="1700342338270" ID="ID_1408546997" MODIFIED="1700342345570" TEXT="Werbereich von...bis"/>
<node CREATED="1700342346989" ID="ID_630827273" MODIFIED="1700342351304" TEXT="und Variationen"/>
</node>
<node CREATED="1700342356676" ID="ID_176542907" MODIFIED="1700342397416" TEXT="Eingangswerte">
<node CREATED="1700342399687" ID="ID_1347906808" MODIFIED="1700342422577" TEXT="einfach nur den Hash &#x27fc; Zufallszahl"/>
<node CREATED="1700342423591" ID="ID_844665669" MODIFIED="1700342438660" TEXT="noch einfacher: Node&amp; und anwenden"/>
<node CREATED="1700342447000" ID="ID_1636759044" MODIFIED="1700342462080" TEXT="das Verhalten &#xfc;ber Neben-Parameter steuern"/>
<node CREATED="1700342492226" ID="ID_208563751" MODIFIED="1700342502708" TEXT="daf&#xfc;r einen 2.Parameter (H&#xf6;he)"/>
<node CREATED="1700342503270" ID="ID_548215053" MODIFIED="1700342537704" TEXT="Hintert&#xfc;r: Node (Connectivity nutzen)"/>
</node>
</node>
<node CREATED="1700342637639" ID="ID_260749595" MODIFIED="1700342644798" TEXT="zwei verschiedene Richtungen">
<node CREATED="1700342652133" ID="ID_78523329" MODIFIED="1700342662640" TEXT="nur einen Draw parametrisieren"/>
<node CREATED="1700342681993" ID="ID_668990384" MODIFIED="1700342693987" TEXT="direkt in die Wertermittlung eingreifen"/>
</node>
<node CREATED="1700344550213" ID="ID_1861811705" MODIFIED="1700344559095" TEXT="im Grunde widersprechen sich beide Richtungen">
<node CREATED="1700344560444" ID="ID_1461905222" MODIFIED="1700344875948">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
will sagen: es ist nicht hilftreich,
</p>
<p>
das&#160;kombinieren zu wollen...
</p>
</body>
</html>
</richcontent>
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
....aber irgendwie scheint mir genau <i>das </i>vorzuschweben...
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1700344878022" ID="ID_522918254" MODIFIED="1700344952685" TEXT="leider hat Beides seine Berechtigung">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...zumindest der M&#246;glichkeit nach
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1700344955499" ID="ID_39017715" MODIFIED="1700345043525" TEXT="Gefahr: den Rahmen hier sprengen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
hab das Gef&#252;hl da&#223; ich schon wieder mal viel zu weit ausgreife, f&#252;r ein St&#252;ck Infrastruktur, das einem einzigen Zweck dient (noch dazu lediglich f&#252;r Tests) und dann wahrscheinlich nur noch rumliegt und zuf&#228;llig vorbeikommende Leser verwirrt
</p>
</body>
</html>
</richcontent>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1700345060957" ID="ID_1137289762" MODIFIED="1700346709861" TEXT="die DSL soll die Verwirrung f&#xfc;r die Leser reduzieren">
<arrowlink COLOR="#7b3855" DESTINATION="ID_80420737" ENDARROW="Default" ENDINCLINATION="5;-52;" ID="Arrow_ID_505910155" STARTARROW="None" STARTINCLINATION="-132;7;"/>
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
<node CREATED="1700345164765" ID="ID_21014183" MODIFIED="1700345183315" TEXT="das w&#xfc;rde f&#xfc;r ausdrucksstarke Builder-Terme sprechen"/>
<node CREATED="1700345191716" ID="ID_604174615" MODIFIED="1700345282458" TEXT="selbst die direkte Verwendung von Cap ist vermutlich bereits verwirrend"/>
<node CREATED="1700345502707" ID="ID_1858490263" MODIFIED="1700345574935" TEXT="...und auch mit den Node-Internals sollte ich vorsichtig sein">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
<i>mir </i>sind die <i>im Moment </i>ganz klar, dagegen beim Leser kann man nur so etwas wie eine generelle Idee von einem DAG voraussetzen
</p>
</body>
</html>
</richcontent>
</node>
<node COLOR="#5b280f" CREATED="1700345585658" ID="ID_790826770" MODIFIED="1700345657721" TEXT="&#x27f9; die Idee, den Builder per Parameter reinzugeben, gebe ich hiermit auf">
<arrowlink COLOR="#ad253c" DESTINATION="ID_624547616" ENDARROW="Default" ENDINCLINATION="679;28;" ID="Arrow_ID_124457360" STARTARROW="None" STARTINCLINATION="-215;-7;"/>
<icon BUILTIN="yes"/>
</node>
</node>
<node CREATED="1700345704906" ID="ID_1841557041" MODIFIED="1700345722687">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
aber <i>Kaskadieren </i>der Auswertung bleibt eine M&#246;glichkeit
</p>
</body>
</html>
</richcontent>
<node CREATED="1700345732596" ID="ID_671293266" MODIFIED="1700345753720" TEXT="auch alle F&#xe4;lle mit unvollst&#xe4;ndigen Ketten und Adaption fallen darunter"/>
<node CREATED="1700345861423" ID="ID_1043929335" MODIFIED="1700345882162" TEXT="Anpassen der Parametrisierung auf Einzelfall-Basis ebenfalls"/>
</node>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1700346594064" ID="ID_80420737" MODIFIED="1700346703430">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
konsequenterweise sollte die ganze Freiheit
</p>
<p>
und Offenheit f&#252;r beliebige Rechenregeln
</p>
<p>
nun komplett aufgegeben werden
</p>
</body>
</html>
</richcontent>
<linktarget COLOR="#7b3855" DESTINATION="ID_80420737" ENDARROW="Default" ENDINCLINATION="5;-52;" ID="Arrow_ID_505910155" SOURCE="ID_1137289762" STARTARROW="None" STARTINCLINATION="-132;7;"/>
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
<node CREATED="1700346721182" ID="ID_960938727" MODIFIED="1700346854239" TEXT="anfangs schwebte mir eine Experimentier-L&#xf6;sung vor"/>
<node CREATED="1700346758569" ID="ID_1639593656" MODIFIED="1700346771531" TEXT="aber im ersten Gebrauch merke ich, da&#xdf; diese zu m&#xfc;hsam ist"/>
<node CREATED="1700346773757" ID="ID_920832027" MODIFIED="1700346820305">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
und gem&#228;&#223; <b>YAGNI</b>&#160;werde ich nur <font color="#c42b2b">10% der M&#246;glichkeiten</font>&#160; wirklich brauchen
</p>
</body>
</html>
</richcontent>
</node>
</node>
</node>
<node CREATED="1700345892467" ID="ID_920427348" MODIFIED="1700345909861" TEXT="2.Entwurf: Funktor-Builder + auto-Adaption">
<node CREATED="1700345916752" ID="ID_267595647" MODIFIED="1700345920980" TEXT="Grunds&#xe4;tzlich">
<node CREATED="1700345943261" ID="ID_388408150" MODIFIED="1700345956998" TEXT="Draw und Spec (Bereichseinteilung) werden verschmolzen"/>
<node CREATED="1700345922921" ID="ID_1268721778" MODIFIED="1700345942500" TEXT="Ergebnis ist immer ein Draw (und damit eine Spec)"/>
<node CREATED="1700345962170" ID="ID_403316998" MODIFIED="1700345997738" TEXT="die Anpassung auf den aktuellen Wertebereich passiert erst im Aufrufkontext">
<node CREATED="1700346005353" ID="ID_189359340" MODIFIED="1700346017255" TEXT="und zwar &#xfc;ber eine impliziter Konversionsfunktion"/>
<node CREATED="1700346017781" ID="ID_993364774" MODIFIED="1700346038252" TEXT="damit kann ich den Typ-Parameter (max) aus Draw heraushalten"/>
<node CREATED="1700346113092" ID="ID_967212835" MODIFIED="1700346145242" TEXT="&#x27f9; sollte damit explizit alles auf double 0..1 umstellen"/>
<node CREATED="1700346196557" ID="ID_692975538" MODIFIED="1700346266485" TEXT="aber einen Builder maxVal(uint) kann man trotzdem bieten">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...der m&#252;&#223;te dann aber absolut gelten, und Teil der Spec werden. Ja warum nicht
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node CREATED="1700346890510" ID="ID_910775175" MODIFIED="1700346908192" TEXT="gespeichert werden (entsprechend Spec) nun aber die intentionalen Parameter"/>
<node CREATED="1700346912731" ID="ID_1211946237" MODIFIED="1700346939323" TEXT="die Zufalls-Erzeugung wird zum komplett fixierten internen Detail"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700347027726" ID="ID_1401418986" MODIFIED="1700347064092" TEXT="Draw wird zu einer externen Hilfsklasse und unabh&#xe4;ngig von TestChainLog">
<icon BUILTIN="yes"/>
</node>
</node>
<node CREATED="1700346948591" ID="ID_1467611806" MODIFIED="1700346954769" TEXT="Nutz-Varianten">
<node CREATED="1700346959359" ID="ID_1645518847" MODIFIED="1700346976614" TEXT="default-Initialisiert &#x2261; deaktiviert"/>
<node CREATED="1700347086640" ID="ID_1826929764" MODIFIED="1700347098373" TEXT="Draw()&#x27f6;Builder">
<node CREATED="1700347103249" ID="ID_296844288" MODIFIED="1700347118842" TEXT="probability(d)"/>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1700347329202" ID="ID_211528936" MODIFIED="1700347374197" TEXT="drawRange(d,d) &#x27f6; Alternative zu probability(d)">
<icon BUILTIN="hourglass"/>
<node CREATED="1700347376236" ID="ID_557693039" MODIFIED="1700347406591" TEXT="Festlegung wo aus [0..1[ gezogen wird"/>
<node CREATED="1700347408438" ID="ID_813288863" MODIFIED="1700347508095" TEXT="damit kann man mehrere Regeln koordiniert zusammenarbeiten lassen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...da sich alle auf den gleichen Hash beziehen, und daher auch korreliert ziehen werden
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node CREATED="1700347540795" ID="ID_1467236280" MODIFIED="1700347578153" TEXT="shuffle(i) &#x27f6; zus&#xe4;tzliche Randomisierung"/>
<node CREATED="1700347175727" ID="ID_598523987" MODIFIED="1700347227164" TEXT="mayVal(u) &#x27f6; fester H&#xf6;chstwert(incl)"/>
<node CREATED="1700347230896" ID="ID_474385396" MODIFIED="1700347245097" TEXT="maxVal(d) &#x27f6; relative Angabe zum Limited-Range"/>
<node CREATED="1700347601126" ID="ID_182532316" MODIFIED="1700347655506" TEXT="valRange(u,u) &#x27f6; Ergebnis liegt zwischen Grenzen (incl)"/>
</node>
<node CREATED="1700348584016" ID="ID_1964046335" MODIFIED="1700348587715" TEXT="Adaptierung">
<node CREATED="1700348594938" ID="ID_1324160554" MODIFIED="1700348600842" TEXT="Funktion als Argument"/>
<node CREATED="1700348629770" ID="ID_1768016710" MODIFIED="1700348638309" TEXT="Res (Ergebniswert)">
<node CREATED="1700348639648" ID="ID_848159984" MODIFIED="1700348681510" TEXT="Draw : das resultierende Draw wird ausgewertet"/>
<node CREATED="1700348687146" ID="ID_983092134" MODIFIED="1700348726478" TEXT="size_t : Zufalls-Generierung mit diesem Hash"/>
<node CREATED="1700348745921" ID="ID_399739426" MODIFIED="1700348761884" TEXT="double : wird modulo 1.0 als Zufallszahl genommen"/>
</node>
<node CREATED="1700348801743" ID="ID_431735724" MODIFIED="1700348803862" TEXT="Argumente">
<node CREATED="1700348805681" ID="ID_1826620691" MODIFIED="1700348909909" TEXT="size_t : wird aus der Zufalls-Quelle(Hash) versorgt"/>
<node CREATED="1700348877400" ID="ID_800573442" MODIFIED="1700348940451" TEXT="size_t, double : Zufalls-Quelle, relative Zeitpos (0...1...)"/>
<node CREATED="1700348957981" ID="ID_362451989" MODIFIED="1700348973999" TEXT="Node&amp; : Direktzugriff"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1700349122079" ID="ID_419191002" MODIFIED="1700349127420" TEXT="Problem mit der Adaptierung">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1700349130966" ID="ID_831772652" MODIFIED="1700349160702" TEXT="verhindert Herausl&#xf6;sen als Library-Klasse (und ist komplex)"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1700359719367" ID="ID_1254612041" MODIFIED="1700359739837" TEXT="damit verbundenes Problem: was ist die Signatur der Draw-Funktion?">
<icon BUILTIN="help"/>
</node>
<node CREATED="1700358795138" ID="ID_1657442729" MODIFIED="1700358800541" TEXT="Analyse der F&#xe4;lle">
<node CREATED="1700358808651" ID="ID_1831518834" MODIFIED="1700358840560" TEXT="RES:Draw">
<node CREATED="1700358871480" ID="ID_67347765" MODIFIED="1700358938939" TEXT="invoke this one instead of the host-Draw"/>
<node CREATED="1700358920993" ID="ID_1393200431" MODIFIED="1700358941509" TEXT="warning: other fields on host-Draw ignored">
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
<node CREATED="1700358946654" ID="ID_1303202325" MODIFIED="1700358951961" TEXT="RES:size_t">
<node CREATED="1700359106793" ID="ID_1838154416" MODIFIED="1700359130043" TEXT="drive the random-generation from there"/>
<node CREATED="1700359139666" ID="ID_1136647874" MODIFIED="1700359163797" TEXT="feed the result(random-number) into value-Mapping"/>
</node>
<node CREATED="1700359133177" ID="ID_975096506" MODIFIED="1700359136289" TEXT="RES:double">
<node CREATED="1700359178515" ID="ID_1731430992" MODIFIED="1700359195241" TEXT="feed this directly into value-Mapping"/>
</node>
<node CREATED="1700359198907" ID="ID_497062117" MODIFIED="1700359205384" TEXT="ARG:size_t">
<node CREATED="1700359238759" ID="ID_532741018" MODIFIED="1700359266969" TEXT="invoke Adapter Node&amp; &#x27fc; size_t"/>
<node CREATED="1700359267757" ID="ID_382070125" MODIFIED="1700359278659" TEXT="feed result into given function"/>
</node>
<node CREATED="1700359289671" ID="ID_1629349126" MODIFIED="1700359296666" TEXT="ARG:size_t,double">
<node CREATED="1700359238759" ID="ID_775508120" MODIFIED="1700359266969" TEXT="invoke Adapter Node&amp; &#x27fc; size_t"/>
<node CREATED="1700359238759" ID="ID_1643202887" MODIFIED="1700359325976" TEXT="invoke Adapter Node&amp; &#x27fc; time-pos(=double)"/>
<node CREATED="1700359329661" ID="ID_1273277245" MODIFIED="1700359341798" TEXT="feed these into the given function"/>
</node>
<node CREATED="1700359347345" ID="ID_819042732" MODIFIED="1700359353472" TEXT="ARG:Node&amp;">
<node CREATED="1700359365230" ID="ID_421033716" MODIFIED="1700359373977" TEXT="directly invoke the given function"/>
</node>
</node>
<node CREATED="1700359509971" ID="ID_1483199036" MODIFIED="1700359524565" TEXT="ben&#xf6;tigt wird: ein Function-chain-builder"/>
<node CREATED="1700359612504" ID="ID_988711396" MODIFIED="1700359623743" TEXT="Design-Stufe-1: dediziert">
<node CREATED="1700359625649" ID="ID_364635181" MODIFIED="1700359630119" TEXT="Adapter">
<node CREATED="1700361162606" ID="ID_1345527183" MODIFIED="1700361176208" TEXT="adaptOut(&#x3bb;)">
<node CREATED="1700359640066" ID="ID_918713248" MODIFIED="1700359766325" TEXT="&#x3bb;-RES:Draw">
<node CREATED="1700359783118" ID="ID_1603023899" MODIFIED="1700360709335" TEXT="&#x3bb;&#x2081; = adaptIn(&#x3bb;)"/>
<node CREATED="1700359915157" ID="ID_187166759" MODIFIED="1700360702864" TEXT="&#x3bb;&#x2082; = getHash&lt;Node&amp;&gt;"/>
<node CREATED="1700359964462" ID="ID_1947237493" MODIFIED="1700360219245" TEXT="&#x3bb;&apos; = [&amp;](Node&amp; n) { Draw=&#x3bb;&#x2081;(n); return Draw(&#x3bb;&#x2082;(n)); }"/>
</node>
<node CREATED="1700360242595" ID="ID_1250110463" MODIFIED="1700360256210" TEXT="&#x3bb;-RES:size_t">
<node CREATED="1700360317479" ID="ID_398185887" MODIFIED="1700360719118" TEXT="&#x3bb;&#x2081; = adaptIn(&#x3bb;)"/>
<node CREATED="1700360320159" ID="ID_1150072758" MODIFIED="1700360489678" TEXT="&#x3bb;&apos; = valMap &#x2218; rand &#x2218; &#x3bb;&#x2081;"/>
</node>
<node CREATED="1700360242595" ID="ID_1221101753" MODIFIED="1700360539181" TEXT="&#x3bb;-RES:double">
<node CREATED="1700360317479" ID="ID_976526249" MODIFIED="1700360723405" TEXT="&#x3bb;&#x2081; = adaptIn(&#x3bb;)"/>
<node CREATED="1700360320159" ID="ID_750329067" MODIFIED="1700360549067" TEXT="&#x3bb;&apos; = valMap &#x2218; &#x3bb;&#x2081;"/>
</node>
</node>
<node CREATED="1700360728877" ID="ID_102147233" MODIFIED="1700360730373" TEXT="adaptIn(&#x3bb;)">
<node CREATED="1700360577645" ID="ID_1755081012" MODIFIED="1700360583480" TEXT="&#x3bb;-ARG:size_t">
<node CREATED="1700359915157" ID="ID_376940900" MODIFIED="1700360702864" TEXT="&#x3bb;&#x2082; = getHash&lt;Node&amp;&gt;"/>
<node CREATED="1700360788960" ID="ID_810511927" MODIFIED="1700360816464" TEXT="&#x3bb;&apos; = &#x3bb; &#x2218; &#x3bb;&#x2082;"/>
</node>
<node CREATED="1700360863774" ID="ID_1744430958" MODIFIED="1700360869681" TEXT="&#x3bb;-ARG:size_t,double">
<node CREATED="1700360896684" ID="ID_288650615" MODIFIED="1700360897733" TEXT="&#x3bb;&#x2082; = getHash&lt;Node&amp;&gt;"/>
<node CREATED="1700360900474" ID="ID_421368401" MODIFIED="1700360934536" TEXT="&#x3bb;&#x2083; = getTimePos&lt;Node&amp;&gt;"/>
<node CREATED="1700360962265" ID="ID_1511929029" MODIFIED="1700360988442" TEXT="&#x3bb;&apos; = &#x3bb; (&#x3bb;&#x2082;(n), &#x3bb;&#x2083;(n))"/>
</node>
<node CREATED="1700361010315" ID="ID_180811750" MODIFIED="1700361032876" TEXT="&#x3bb;-ARG:Node&amp; &#x2261; id"/>
</node>
</node>
<node CREATED="1700361130035" ID="ID_1688775055" MODIFIED="1700361138008" TEXT="Struktur wird erkennbar....">
<icon BUILTIN="idea"/>
<node CREATED="1700361187795" ID="ID_620483169" MODIFIED="1700361189310" TEXT="adaptOut(&#x3bb;)">
<node CREATED="1700361190298" ID="ID_1980457426" MODIFIED="1700361194806" TEXT="wird stets ben&#xf6;tigt"/>
<node CREATED="1700361202553" ID="ID_1117913470" MODIFIED="1700361326820" TEXT="liefert stets einen Funktor mit RES:Spec"/>
</node>
<node CREATED="1700361383585" ID="ID_1767430341" MODIFIED="1700361384580" TEXT="adaptIn(&#x3bb;)">
<node CREATED="1700361385576" ID="ID_176675363" MODIFIED="1700361390875" TEXT="ist optional / flexibel"/>
<node CREATED="1700361391736" ID="ID_1064796631" MODIFIED="1700361486767" TEXT="wird in jedem Zweig von adaptOut(&#x3bb;) ben&#xf6;tigt"/>
</node>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1700361501097" ID="ID_401015563" MODIFIED="1700361518463" TEXT="noch unklar: was ist der Ergebnis-Typ?">
<icon BUILTIN="help"/>
<node CREATED="1700361526878" ID="ID_981729861" MODIFIED="1700361562965" TEXT="damit implizierte Frage: ist Draw sinnvollerweise std::function ?"/>
<node CREATED="1700361585230" ID="ID_1897786487" MODIFIED="1700361617245" TEXT="wenn ja: dann w&#xe4;re der Ergebnistyp Draw&amp;">
<node CREATED="1700361662236" ID="ID_430183904" MODIFIED="1700361674294" TEXT="m&#xfc;&#xdf;te auf sich selber referenzieren"/>
<node CREATED="1700361695735" ID="ID_1277775461" MODIFIED="1700361713576" TEXT="sonst w&#xfc;rde ja der Builder-Ansatz nicht mehr funktionieren"/>
<node CREATED="1700361734947" ID="ID_1547996439" MODIFIED="1700361766613" TEXT="damit ist dann aber &#x3bb;-RES:Draw unm&#xf6;glich">
<icon BUILTIN="stop-sign"/>
<node CREATED="1700361779036" ID="ID_35323612" MODIFIED="1700361782723" TEXT="dangling reference"/>
</node>
</node>
<node CREATED="1700361800384" ID="ID_1496434440" MODIFIED="1700361807492" TEXT="alternativ: Ergebnistyp Spec">
<node CREATED="1700361809672" ID="ID_797207468" MODIFIED="1700361818203" TEXT="dann m&#xfc;&#xdf;ten wir den jedes Mal konstruieren"/>
</node>
<node CREATED="1700361859497" ID="ID_1388286109" MODIFIED="1700361872195" TEXT="oder : Ergebnistyp Limited">
<node CREATED="1700361873265" ID="ID_971481403" MODIFIED="1700361878704" TEXT="nicht mehr per Konversions-Operator"/>
<node CREATED="1700361879302" ID="ID_947380994" MODIFIED="1700361904631" TEXT="man m&#xfc;&#xdf;te dann jeweils einen Ausgangs-Adapter installieren"/>
</node>
<node CREATED="1700361955468" ID="ID_171432809" MODIFIED="1700361964999" TEXT="oder : Draw ist keine Fuktion">
<node CREATED="1700361966107" ID="ID_440284003" MODIFIED="1700361977187" TEXT="der operator() hat einen Seiteneffekt"/>
<node CREATED="1700361977817" ID="ID_527836444" MODIFIED="1700361991395" TEXT="anschlie&#xdf;end hold man sich das Ergebnis per Konversions-Operator"/>
</node>
</node>
</node>
<node CREATED="1700365769348" ID="ID_556380585" MODIFIED="1700365775516" TEXT="Design-stufe-2: generisch">
<node CREATED="1700365860944" ID="ID_1336006745" MODIFIED="1700365909109" TEXT="es handelt sich dann insgesamt um eine Funktion: Q &#x27fc; Limited&lt;T, T max&gt;">
<node CREATED="1700365917573" ID="ID_1497905227" MODIFIED="1700365934014" TEXT="es sollte eine einzige Funktion sein aus Gr&#xfc;nden der Klarheit"/>
<node CREATED="1700365936094" ID="ID_1933404992" MODIFIED="1700365960831" TEXT="der Zieltyp Limited ist essentieller Bestandteil des Rechenschmas"/>
<node CREATED="1700365983480" ID="ID_1777594236" MODIFIED="1700366003647" TEXT="aber der Ziel-Basistyp T ist weitgehend frei (er mu&#xdf; &quot;numerisch&quot; sein)"/>
</node>
<node CREATED="1700395292886" ID="ID_1011783962" MODIFIED="1700395297765" TEXT="Konfiguration der Adapter">
<node CREATED="1700395325464" ID="ID_175362456" MODIFIED="1700395357689" TEXT="eingangsseitige Adapter m&#xfc;ssen im Nutzkontext konfiguriert werden">
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1700395964241" ID="ID_92451979" MODIFIED="1700396026386" TEXT="adaptIn(&#x3bb;) wird zuerst ben&#xf6;tigt &#x27f6; liefert ein &#x3bb;(Q)"/>
<node CREATED="1700396597111" ID="ID_405049807" MODIFIED="1700396605160" TEXT="Form des Adapters">
<node CREATED="1700396608085" ID="ID_1182305946" MODIFIED="1700396703981" TEXT="mu&#xdf; konkrete Signatur des Funktors feststellen"/>
<node CREATED="1700396714119" ID="ID_1154980053" MODIFIED="1700396737880" TEXT="verwendet partielle Template-Spezialisierung auf Basis der Signatur"/>
<node CREATED="1700396891353" ID="ID_1391747733" MODIFIED="1700396901301" TEXT="&#x27f9; Doppel-H&#xfc;lle">
<node CREATED="1700396903770" ID="ID_422430772" MODIFIED="1700397010293" TEXT="&#xe4;u&#xdf;ere Klasse um Scope f&#xfc;r partielle Spezialisierungen zu schaffen"/>
<node CREATED="1700397011683" ID="ID_644908811" MODIFIED="1700397044983" TEXT="darin eine Familie von Templates mit konkreten partiellen oder totalen Spezialisierungen"/>
</node>
<node CREATED="1700397048917" ID="ID_157848143" MODIFIED="1700397051145" TEXT="Varianten">
<node CREATED="1700397052416" ID="ID_857588012" MODIFIED="1700397068674" TEXT="&#xe4;u&#xdf;ere Klasse ist selbst Template">
<node CREATED="1700397069906" ID="ID_604183530" MODIFIED="1700397078349" TEXT="Parameter ist der zu adaptierende Funktor"/>
<node CREATED="1700397079295" ID="ID_1463110151" MODIFIED="1700397173506" TEXT="es wird dann instantiiert per ctor mit konkreter Funktor-Instanz (C++17)">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...diese Variante ist erst mit C++17 m&#246;glich, da nun der Template-Parameter inferiert werden kann
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1700397181252" ID="ID_623260560" MODIFIED="1700397224117" TEXT="es enth&#xe4;lt eine std::function mit fester Signatur als Member"/>
<node CREATED="1700397224870" ID="ID_1797839843" MODIFIED="1700397240608" TEXT="Ergebnis wird per automatischer Konversion abgeholt"/>
<node CREATED="1700397244662" ID="ID_122524878" MODIFIED="1700397254575" TEXT="nur m&#xf6;glich wenn...">
<node CREATED="1700397255722" ID="ID_1600526198" MODIFIED="1700397266309" TEXT="std::function akzeptabel ist"/>
<node CREATED="1700397267484" ID="ID_960639723" MODIFIED="1700397276548" TEXT="die Signatur komplett festliegt"/>
<node CREATED="1700397345738" ID="ID_1619656561" MODIFIED="1700399318338" TEXT="&#xe4;u&#xdf;ere Klasse dient nur als H&#xfc;lle">
<linktarget COLOR="#a9b4c1" DESTINATION="ID_1619656561" ENDARROW="Default" ENDINCLINATION="-154;13;" ID="Arrow_ID_252746284" SOURCE="ID_144021391" STARTARROW="None" STARTINCLINATION="95;-44;"/>
<node CREATED="1700397369684" ID="ID_87447722" MODIFIED="1700397387365" TEXT="enth&#xe4;lt eine statische Adapter-Funktion(Template)"/>
<node CREATED="1700397389017" ID="ID_791189999" MODIFIED="1700397409263" TEXT="diese ermittelt in ihrem Block-Scope die Funktor-Signatur"/>
<node CREATED="1700397410087" ID="ID_1849610690" MODIFIED="1700397488657" TEXT="und instantiiert dann den eigentlichen Adapter"/>
<node CREATED="1700397490005" ID="ID_285297036" MODIFIED="1700397512206" TEXT="wobei auch in diesem eine statische Funktion mit auto-Returntyp aufgerufen wird"/>
</node>
</node>
</node>
<node CREATED="1700397559764" ID="ID_582172020" MODIFIED="1700397574430" TEXT="es wird nur eine Adapter-Funktion(Template) &#xfc;bergeben">
<node CREATED="1700397578050" ID="ID_1702442322" MODIFIED="1700397599766" TEXT="diese verwendet Adapter-Templates im umgebenden class/namespace"/>
<node CREATED="1700398333857" ID="ID_574373381" MODIFIED="1700398364328" TEXT="Vorteil: kompakt und flexibel (kann in den umgebenden Kontext binden)"/>
<node CREATED="1700398366364" ID="ID_323294914" MODIFIED="1700398388757" TEXT="Nachteil: &#xdc;bergabe eines Funktions-Template ist schwierig">
<node CREATED="1700398403823" ID="ID_166562351" MODIFIED="1700398419413" TEXT="umgebendes Konfigurations/Trait-Template"/>
<node CREATED="1700398464409" ID="ID_569449309" MODIFIED="1700398474624" TEXT="Builder-Funktion(Template) auf einem Kollaborationspartner"/>
</node>
</node>
</node>
<node CREATED="1700398617512" ID="ID_985893923" MODIFIED="1700398646776" TEXT="&#x27f9; &#xdc;bergabe von Templates ist hier die praktische H&#xfc;rde">
<node CREATED="1700398774795" ID="ID_288481211" MODIFIED="1700398782662" TEXT="templtate-template-Paramter">
<node CREATED="1700398796693" ID="ID_648918481" MODIFIED="1700398835455" TEXT="sind schwer lesbar Definitions-Ort"/>
<node CREATED="1700398846233" ID="ID_269736776" MODIFIED="1700398871441" TEXT="erfordern Festlegung der Template-Parameter"/>
<node CREATED="1700398802991" ID="ID_119546823" MODIFIED="1700398876633" TEXT="Problem ist stets die Dokumentation f&#xfc;r den Nutzer"/>
</node>
<node CREATED="1700398893875" ID="ID_568728168" MODIFIED="1700399292920" TEXT="Konfigurationsklasse / Trait-Template">
<arrowlink DESTINATION="ID_144021391" ENDARROW="Default" ENDINCLINATION="151;-46;" ID="Arrow_ID_1749412477" STARTARROW="None" STARTINCLINATION="-189;14;"/>
<node CREATED="1700398907786" ID="ID_255722018" MODIFIED="1700398916895" TEXT="darauf l&#xe4;uft es praktisch immer hinaus"/>
<node CREATED="1700399009524" ID="ID_1222684688" MODIFIED="1700399023461" TEXT="entweder durch Zugriff im umgebenden Namespace"/>
<node CREATED="1700399024310" ID="ID_1466090440" MODIFIED="1700399100563" TEXT="oder als einfacher Template-Parameter"/>
<node CREATED="1700399101511" ID="ID_1070113470" MODIFIED="1700399123640" TEXT="oder Instanz durch Aufruf eines extension-Point (ADL)"/>
</node>
</node>
</node>
<node CREATED="1700399151659" ID="ID_144021391" MODIFIED="1700399318338" TEXT="Hier erscheint ein Config-Typ sinnvoll">
<arrowlink COLOR="#a9b4c1" DESTINATION="ID_1619656561" ENDARROW="Default" ENDINCLINATION="-154;13;" ID="Arrow_ID_252746284" STARTARROW="None" STARTINCLINATION="95;-44;"/>
<linktarget COLOR="#a9b4c1" DESTINATION="ID_144021391" ENDARROW="Default" ENDINCLINATION="151;-46;" ID="Arrow_ID_1749412477" SOURCE="ID_568728168" STARTARROW="None" STARTINCLINATION="-189;14;"/>
<node CREATED="1700399198368" ID="ID_1781925975" MODIFIED="1700399205813" TEXT="&#xfc;bergeben als Template Paramter"/>
<node CREATED="1700399206449" ID="ID_1309572183" MODIFIED="1700399222443" TEXT="aber mit einem Default &#x27f9; dient als copy-n-paste-Vorlage"/>
<node CREATED="1700399243756" ID="ID_510267956" MODIFIED="1700399258246" TEXT="das Konverter-Funktions-Temlate kann darin direkt enthalten sein"/>
</node>
</node>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1700444194601" ID="ID_1576940362" MODIFIED="1700444225488" TEXT="Funktionalit&#xe4;t deiziert ohne Quell-Typ prototypisch implementieren">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
</node>