Library: RandomDraw - use dynamic quantiser

For sake of simplicity, since this whole exercise is a byproduct,
the mapping calculations are done in doubles. To get even distribution
of values and a good randomisation, it is thus necessary to break
down the size_t hash value in a first step (size_t can be 64bit
and random numbers would be subject to rounding errors otherwise)

The choice of this quantiser is tricky; it must be a power of two
to guarantee even distribution, and if chosen to close to the grid
of the result values, with lower probabilities we'd fail to cover
some of the possible result values.  If chosen to large, then
of course we'd run danger of producing correlated numbers on
consecutive picks.

Attempting to use 4 bits of headroom above the log-2 of the
required value range. For example, 10-step values would use
a quantiser of 128, which looks like a good compromise.
The following tests will show how good this choice holds up.
This commit is contained in:
Fischlurch 2023-11-21 19:50:22 +01:00
parent 418a5691ea
commit bdb2f12b80
3 changed files with 97 additions and 24 deletions

View file

@ -189,23 +189,23 @@ namespace lib {
val *= maxResult_ - org; // [0 .. m[
val += org+1; // [1 .. m]
val += CAP_EPSILON; // round down yet absorb dust
return Tar{val};
return Tar{floor (val)};
}
else// Origin is somewhere within value range
{// ==> wrap "negative" part above max
// to map 0.0 ⟼ org (≙neutral)
val *= maxResult_ - minResult_;
val += org+1; // max inclusive but <0 ⟼ org
if (val > maxResult_) // wrap the "negatives"
if (val >= maxResult_+1) // wrap the "negatives"
val -= maxResult_+1 - minResult_;
val += CAP_EPSILON;
return Tar{val};
return Tar{floor (val)};
}
}
static size_t constexpr QUANTISER = 1 << 8;
} //----headroom to accommodate low probabilities
static size_t constexpr QUANTISER = 1 << 4 + util::ilog2 (Tar::maxVal()-Tar::minVal());
static double constexpr CAP_EPSILON = 1/(2.0 * QUANTISER);
/** @internal draw from source of randomness */
double
asRand (size_t hash)

View file

@ -55,7 +55,7 @@ namespace test{
// const Literal THE_END = "all dead and hero got the girl";
struct SymmetricFive
: function<Limited<int, 5,-5>(size_t)>
: function<Limited<int, 5,-5,0>(size_t)>
{
static size_t defaultSrc (size_t hash) { return hash; }
@ -136,9 +136,36 @@ namespace test{
{
auto draw = Draw().probability(0.5);
SHOW_EXPR (int(draw(0) ));
SHOW_EXPR (int(draw(63 )));
SHOW_EXPR (int(draw(64 )));
SHOW_EXPR (int(draw(70 )));
SHOW_EXPR (int(draw(72 )));
SHOW_EXPR (int(draw(82 )));
SHOW_EXPR (int(draw(83 )));
SHOW_EXPR (int(draw(84 )));
SHOW_EXPR (int(draw(85 )));
SHOW_EXPR (int(draw(86 )));
SHOW_EXPR (int(draw(87 )));
SHOW_EXPR (int(draw(88 )));
SHOW_EXPR (int(draw(89 )));
SHOW_EXPR (int(draw(90 )));
SHOW_EXPR (int(draw(91 )));
SHOW_EXPR (int(draw(92 )));
SHOW_EXPR (int(draw(93 )));
SHOW_EXPR (int(draw(94 )));
SHOW_EXPR (int(draw(95 )));
SHOW_EXPR (int(draw(96 )));
SHOW_EXPR (int(draw(97 )));
SHOW_EXPR (int(draw(102)));
SHOW_EXPR (int(draw(103)));
SHOW_EXPR (int(draw(108)));
SHOW_EXPR (int(draw(109)));
SHOW_EXPR (int(draw(121)));
SHOW_EXPR (int(draw(122)));
SHOW_EXPR (int(draw(127)));
SHOW_EXPR (int(draw(128)));
SHOW_EXPR (int(draw(141)));
SHOW_EXPR (int(draw(129)));
SHOW_EXPR (int(draw(192)));
SHOW_EXPR (int(draw(255)));
SHOW_EXPR (int(draw(256)));
// CHECK (draw(0) == 0);

View file

@ -96728,14 +96728,14 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700577987947" ID="ID_1072243558" MODIFIED="1700578044322" TEXT="Result-Mapping fertigstellen">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700578049835" ID="ID_1039524348" MODIFIED="1700578324330" TEXT="(optional) Minimal-Wert beachten">
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700577987947" ID="ID_1072243558" MODIFIED="1700591549880" TEXT="Result-Mapping fertigstellen">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1700578049835" ID="ID_1039524348" MODIFIED="1700591554997" TEXT="(optional) Minimal-Wert beachten">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700578067566" ID="ID_1673296895" MODIFIED="1700578327612" TEXT="(optional) neutralen Wert definieren">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700578338693" ID="ID_1746695653" MODIFIED="1700578488824" TEXT="Wunsch: neutralen Wert mitten im Wertebereich">
<node COLOR="#435e98" CREATED="1700578338693" ID="ID_1746695653" MODIFIED="1700591392565" TEXT="Wunsch: neutralen Wert mitten im Wertebereich">
<richcontent TYPE="NOTE"><html>
<head>
@ -96749,18 +96749,46 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</richcontent>
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700578688806" ID="ID_1002441906" MODIFIED="1700578701690" TEXT="brauche anderes Mapping-Layout">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700578703420" ID="ID_1936439930" MODIFIED="1700578736098" TEXT="erst mal als statischen-Zweig realisieren">
<node COLOR="#338800" CREATED="1700578688806" ID="ID_1002441906" MODIFIED="1700591389020" TEXT="brauche anderes Mapping-Layout">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1700578703420" ID="ID_1936439930" MODIFIED="1700591281596" TEXT="erst mal als Fallunterscheidung realisieren">
<icon BUILTIN="yes"/>
</node>
<node CREATED="1700578747462" ID="ID_1744331355" MODIFIED="1700578808542" TEXT="Idee: [0....0[1...max|min...-1]">
<node COLOR="#435e98" CREATED="1700578747462" ID="ID_1744331355" MODIFIED="1700591285475" TEXT="Idee: [0....0[1...max|min...-1]">
<icon BUILTIN="idea"/>
</node>
<node COLOR="#338800" CREATED="1700591296817" ID="ID_1493490706" MODIFIED="1700591311585" TEXT="mu&#xdf; mit floor() runden">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1700591321621" ID="ID_786179594" MODIFIED="1700591330740" TEXT="sonst Symmetrie-Probleme"/>
<node CREATED="1700591331493" ID="ID_851466258" MODIFIED="1700591378869">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
nat&#252;rliche Rundung <i>is towards zero</i>
</p>
</body>
</html>
</richcontent>
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...und das ist obendrein <i>implementation defined...</i>
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700579867534" ID="ID_1525251156" MODIFIED="1700579872321" TEXT="Quantisierung verbessern">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700579867534" ID="ID_1525251156" MODIFIED="1700591492624" TEXT="Quantisierung verbessern">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1700579884119" ID="ID_805978365" MODIFIED="1700579898358" TEXT="Probleme mit der Wahrscheinlichkeitsverteilung">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1700580065522" ID="ID_1293962654" MODIFIED="1700580090733" TEXT="f&#xfc;r Zuf&#xe4;lligkeit w&#xe4;re quant &#x2259; card ideal"/>
@ -96770,12 +96798,20 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node CREATED="1700580296744" ID="ID_1912245268" MODIFIED="1700580306635" TEXT="auch unebene Teil-Wertbereiche sind problematisch"/>
</node>
<node CREATED="1700579942375" ID="ID_1570826487" MODIFIED="1700579973751" TEXT="Quantiser auf 2-log der Kardinalit&#xe4;t aufbauen">
<node CREATED="1700580399003" ID="ID_1712768640" MODIFIED="1700580402212" TEXT="statische L&#xf6;sung">
<node COLOR="#338800" CREATED="1700579942375" ID="ID_1570826487" MODIFIED="1700591481064" TEXT="Quantiser auf 2-log der Kardinalit&#xe4;t aufbauen">
<icon BUILTIN="button_ok"/>
<node CREATED="1700580399003" ID="ID_1712768640" MODIFIED="1700591474474" TEXT="statische L&#xf6;sung">
<icon BUILTIN="forward"/>
<node CREATED="1700580403024" ID="ID_340644857" MODIFIED="1700580414388" TEXT="kann dann nur auf max(Template-Param) aufsetzen"/>
<node CREATED="1700580415496" ID="ID_241609475" MODIFIED="1700580425235" TEXT="mu&#xdf; mit zus&#xe4;tzlichem Headroom arbeiten"/>
<node CREATED="1700580415496" ID="ID_241609475" MODIFIED="1700591431909" TEXT="mu&#xdf; mit zus&#xe4;tzlichem Headroom arbeiten">
<linktarget COLOR="#a9b4c1" DESTINATION="ID_241609475" ENDARROW="Default" ENDINCLINATION="-131;9;" ID="Arrow_ID_404249054" SOURCE="ID_708309999" STARTARROW="None" STARTINCLINATION="77;5;"/>
</node>
<node CREATED="1700580428485" ID="ID_209321513" MODIFIED="1700580431707" TEXT="dynamische L&#xf6;sung">
<node COLOR="#338800" CREATED="1700591450189" ID="ID_1244482845" MODIFIED="1700591469597" TEXT="mein ilog2 kann constexpr sein">
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1700580428485" ID="ID_209321513" MODIFIED="1700591476960" TEXT="dynamische L&#xf6;sung">
<icon BUILTIN="hourglass"/>
<node CREATED="1700580432790" ID="ID_1779483070" MODIFIED="1700580440161" TEXT="w&#xe4;re ein zus&#xe4;tzliches Objektfeld"/>
<node CREATED="1700580440749" ID="ID_1688731462" MODIFIED="1700580454914" TEXT="m&#xfc;&#xdf;te von jedem Param-Setter mit bedient werden"/>
<node CREATED="1700580455526" ID="ID_1568213898" MODIFIED="1700580468829" TEXT="w&#xfc;rde den (schnellen) ilogb verwenden"/>
@ -96794,6 +96830,16 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node COLOR="#435e98" CREATED="1700591398164" ID="ID_708309999" MODIFIED="1700591436198" TEXT="Entscheidung: einfache statische L&#xf6;sung">
<arrowlink DESTINATION="ID_241609475" ENDARROW="Default" ENDINCLINATION="-131;9;" ID="Arrow_ID_404249054" STARTARROW="None" STARTINCLINATION="77;5;"/>
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1700591494047" ID="ID_367849222" MODIFIED="1700591500352" TEXT="Verteilung empirisch untersuchen">
<icon BUILTIN="flag-pink"/>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1700591521028" ID="ID_1363297386" MODIFIED="1700591544937" TEXT="DSL-Setter m&#xfc;ssen nun stets konsistente Gesamteinstellung erzeugen">
<icon BUILTIN="flag-pink"/>
</node>
<node COLOR="#338800" CREATED="1700578085130" ID="ID_1160195104" MODIFIED="1700578334393" TEXT="Konsistenz der Definitionen pr&#xfc;fen (statisch)">
<icon BUILTIN="button_ok"/>
@ -96811,8 +96857,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700491902622" ID="ID_523469259" MODIFIED="1700577965111" TEXT="soll auch den Proze&#xdf; der Spezialisierung demonstrieren">
<icon BUILTIN="pencil"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700491930155" ID="ID_1583745392" MODIFIED="1700577970844" TEXT="numerische Grenzen beleuchten">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700491930155" ID="ID_1583745392" MODIFIED="1700591561138" TEXT="numerische Grenzen beleuchten">
<icon BUILTIN="pencil"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700501979956" ID="ID_571312425" MODIFIED="1700577970844" TEXT="Wirkung des Builder-API dokumentieren">
<icon BUILTIN="flag-yellow"/>