diff --git a/src/lib/random.cpp b/src/lib/random.cpp index d44abed05..91efd7e78 100644 --- a/src/lib/random.cpp +++ b/src/lib/random.cpp @@ -84,8 +84,8 @@ namespace lib { void randomiseRandomness() { - entropyGen.randomise(entropyNucleus); - defaultGen.randomise(entropyNucleus); + entropyGen.reseed(entropyNucleus); + defaultGen.reseed(entropyNucleus); } } // namespace lib diff --git a/src/lib/random.hpp b/src/lib/random.hpp index 4cef79e84..2156ab0d5 100644 --- a/src/lib/random.hpp +++ b/src/lib/random.hpp @@ -80,7 +80,7 @@ namespace lib { double uni() { return uniformD_(generator_); } /** inject controlled randomisation */ - void randomise(SeedNucleus&); + void reseed (SeedNucleus&); }; /** @@ -121,9 +121,9 @@ namespace lib { template inline void - RandomSequencer::randomise (SeedNucleus& nucleus) + RandomSequencer::reseed (SeedNucleus& nucleus) { - generator_.discard (nucleus.getSeed() % 55555); + generator_.seed (nucleus.getSeed()); } diff --git a/tests/library/random-test.cpp b/tests/library/random-test.cpp index 4aef33168..260d687d7 100644 --- a/tests/library/random-test.cpp +++ b/tests/library/random-test.cpp @@ -90,11 +90,15 @@ namespace test { CHECK (r2 == src2.u64()); CHECK (r3 == src2.uni()); - src1.randomise(coreOfEvil); - CHECK (src1.i32() != src2.i32()); + src1.reseed (coreOfEvil); + CHECK (src1.u64() != src2.u64()); - src2.randomise(coreOfEvil); + src2.reseed (coreOfEvil); + CHECK (src1.u64() != src2.u64()); + (void) src2.u64(); + CHECK (src1.u64() == src2.u64()); CHECK (src1.i32() == src2.i32()); + CHECK (src1.uni() == src2.uni()); } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 2f7dc9abf..c94c4d4cd 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -14530,9 +14530,7 @@ - - - +

...denn das eigentliche Problem ist, @@ -14548,9 +14546,7 @@ - - - +

und zwar für die abstrahierte GUI-Location @@ -16587,9 +16583,7 @@ - - - +

Frage: wieviel Interaction Control @@ -19489,9 +19483,7 @@ - - - +

Analyse: welche beweglichen Teile gibt es überhaupt? @@ -25506,9 +25498,7 @@ - - - +

ich wollte mal ein viel generischeres Design schaffen, das sogar eine Art Grundgerüst für das Zusammenbauen des GUI sein könnte. In der vertieften Analyse wurde dann aber klar, daß dieses Design nicht so ohne Weiteres realisierbar ist. Daraufhin habe ich beschlossen, die Idee aufzugeben und stattdessen auf Einzelfälle zu spezialisieren. Und in einem weiteren Schritt habe ich dann die Themen "Grid" und "Canvas" voneinander getrennt @@ -33489,9 +33479,7 @@ - - - +

Wenn man einen neuen Gtk::StyleContext erzeugt, @@ -40004,9 +39992,7 @@ - - - +

ein cout in genau diesem Testcode gibt stets nur alternierend den Allocation-Wert für den Ruler-Canvas (konstant 5px) und dann den Main-Canvas (variiert mit Fensterhöhe) aus @@ -46632,9 +46618,7 @@ - - - +

mark "clearErr" @@ -47207,9 +47191,7 @@ - - - +

....so harmlos hat alles angefangen @@ -47738,9 +47720,7 @@ - - - +

since skipSrc performs both the `del` and the `skip` verb, it can not perform the match itself... @@ -47952,9 +47932,7 @@ - - - +

invoke mutateChild @@ -48183,9 +48161,7 @@ - - - +

nur Zuweisung einiger Referenzen @@ -57147,6 +57123,293 @@ + + + + + + + + + + +

+ ...für den Zweck hier; wir brauchen durchaus mengenweise Zufallszahlen mit guten statistischen Eigenschaften, aber wir brauchen weder unglaublich lange Zyklenzahlen, noch bauchen wir einen extrem großen Konfigurationsraum +

+ +
+ + + + + + + + + + + + + + +

+ ...und mein Interface SeedNucleus ist nur darauf ausgelegt (auf den kleinsten gemeinsamen Nenner) +

+ +
+
+ + + + +

+ ...und zu allem Überfluß gibt es auch noch eine recht fragwürdige standard-Implementierung, std::seed_seq, welche die gegebenen Zahlen in einen Vector auf den Heap speichert. +

+ +
+
+ + + + +

+ meist wird Seeden aus einer einzigen Zahl unterstützt, aber viele Algorithmen brauchen eigentlich mehr initial state und hierfür ist mehr Seed-Input nützlich; wenn man also eine größere Entropiequelle hätte, könnte man eine bessere Diffusion erreichen +

+ +
+
+ + + + +

+ ...sofern man tatsächlich ein abstrahiertes Interface für das Seeding haben möchte (d.h. im usage-Kontext ist nicht explizit klar, was für eine Quelle tatsächlich verwendet wird) +

+ +
+
+
+ + + + + + +

+ std::seed_seq +

+
    +
  • + soll vor allem die Schwächen des Mersenne-Twister überbrücken, welcher einen sehr großen initial state benötigt, und für einige Eingabe-Sequenzen gefährlich degenerieren kann; diese Idee wurde dann verallgemeinert... +
  • +
  • + unabhängig davon wurde aber die zweite Variante erlaubt, nämlich den Random-Generator mit einer einzigen Zahl zu seeden... +
  • +
  • + Melissa O'Neil (sie spätere Autorin von PCG-Random) hat den Algorithmus für seed_seq dahingehend kritisiert, daß dieser eiene große Menge Entropie nicht optimal nutzt. Dem wurde von verschiedener Seite widersprochen; desweiteren ist fraglich, für welche Art Anwendungen diese Frage überhaupt relevant ist; denn auch nur mit einem einzigen Seed-Value erzeugt der Mersenne-Twiseter 2^32 verschiedene, extrem hochqualitative Sequenzen — es geht nur um die Frage, ob er auch 2^(624·32) verschiedene Sequenzen erzeugen könnte. +
  • +
  • + das Interface für <random> ist generisch: es gibt ein Konzept für Seed-seq, und ein Konzept Generator, und die beiden werden dann jeweils für den Einzelfall konkret kombiniert +
  • +
+

+ SeedNucleus +

+
    +
  • + ist auf die besondere Situation ausgerichtet, daß ein nicht näher bekannter Generator irgendwann zur Laufzeit eine nicht näher bekannte Seed-Quelle bekommen soll +
  • +
  • + es soll also zur Laufzeit aber damit auch dynamisch umgeschaltet werden zwischen einem festen Seed und deterministischem Verhalten und pseudo- oder echter Randomisierung +
  • +
  • + hier ist also die potentielle reproduzierbarkeit eine zentrale Hinsicht, wohingegen davon ausgegangen wird, daß durch interaktiven Gebrauch ohnehin eine unerschöpfliche Entropie-Quelle gegeben ist +
  • +
+ +
+
+ + + + +

+ ...und zwar würde es genügen, statt eines Seed-Value einen Iterator zurückzuliefern; dieses Proxy-Objekt müßte dann allerdings im Typ entsprechend fixiert sein (also z.B. ein uint32_t*). Dann bliebe allerdings auch noch die Frage offen, ob auch der im C++-Standard festgelegte Algorithmus implementiert werden muß, d.h. ob intern aus dem Aufruf des SeedNucleus wieder eine konforme Seed-seq erzeugt werden soll. Das wäre durchaus machbar (er ist genau spezifiziert und leicht zu implementieren) — würde aber wieder die gleichen Probleme aufwerfen, die auch für std::seed_seq gelten: +

+
    +
  • + der Algorithmus muß die Länge der gelieferten Seed-Seq und die Länge der Quell-Sequenz kennen ⟹ beide Infos könnte man aus Pointer-Arrithmetik gewinnen (und das bereitzustellende C++ Interface für die Seed-seq läßt auch gar keinen anderen Ausweg zu) +
  • +
  • + alle Unsicherheiten und Einwände bezüglich der Qualität der Seed-seq. bleiben bestehen (das wäre aber immer noch besser als nur ein einziger Seed-Wert) +
  • +
  • + es bleibt offen, ob dieses Schema auch für andere (modernere) PRNG-Algorithmen vorteilhaft ist +
  • +
+ + +
+
+ + + + +

+ damit wird klar: das aktuelle SeedNucleus-Interface is zunächst gut genug (KISS) +

+ + +
+ +
+
+
+ + + + + + + +

+ der SeedNucleus soll ja eben grade opaque sein, also möchte ich da keine zusätzliche Operation zum State-Speichern hinzunehmen; und für die std::seed_seq ergibt sich das Problem, daß die Länge nicht bekannt ist; man bekäme also u.U eine unbeschränkt lange Sequenz von Zahlen als Seed-Zustand +

+ +
+
+ + + + +
    +
  • + ein SeedNucleus, der einen quell-Nucleus einpackt und den/die ausgelesenen Wert(e) dokumentiert +
  • +
  • + und natürlich dann als Gegenstück ein Seed-Nucleus der einen festen Wert ausliefert (trivial), oder ggfs. sogar eine Weiche, die entweder die Quelle verwendet, oder einen gegeben Override +
  • +
+ +
+
+
+ + + + + + + + + + + + +

+ eigentlich hatte ich das nur als Vorsichtsmaßnahme eingefürt, da wir noch kein Framework für Zufallszahlen in Tests hatten; die Tests liefen seither stets mit einem festen Seed los, aber es sollte eben eine »Hintertür« geben, mit der man in bestimmte Tests echte Zufälligkeit injizieren klnnte +

+ +
+
+ + + + + +

+ ...das wäre nur notwendig, wenn mal eine ganze Familie von Generatoren (z.B. in parallelen Tests) zum Einsatz kommt, und zudem der unterliegende PRNG eine schlechte Diffusion hat. Normalerweise aber erzeugen wir solche Generatoren (gemäß diesem Plan) nun stets aus dem Seed eines Vater-Generators, und wir verwenden qualitativ hochwertige PRNGs, und das sollte eigentlich zur Dekorrelation genügen +

+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ...und zwar weil das einfach umständlich ist, die Aufrufe sind länger, man muß es durchreichen und ggfs ist dann doch noch irgendwo bei den sonstigen Utilities ein versteckter Aufruf des default-Generators. Es gibt auch nur selten einen Mehrwert, verschiedene Generatoren zu verwenden; das wäre nur notwendig wenn ein komplexer Prozeß durchgeführt wird, der in Teilen nicht völlig ablaufstabil ist, z.B. weil in mehreren Threads unabhängig voneinander Zufallszahlen gezogen werden. +

+ +
+
+ + + + + + + + + + + + + + + + + + + +

+ der Test-Autor ist selber dafür verantwortlich,
die Zufallszahlen-Generierung zu verstehen... +

+ +
+
+
+
+ + + + + + + +

+ etwa analog zu dem Framework, welches mein Kollege Oleg Galimov bei der Baaderbank mitgebracht hat (es ist OpenSource, in Java geschrieben) +

+ +
+
+
+
+
+
@@ -91576,6 +91839,24 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + +

+ läuft darauf hinaus, +

+

+ nun den Umbau anzugehen +

+ + +
+ +
+
@@ -91620,10 +91901,43 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + + + + +

+ ...im Hinblick auf Reproduzierbarkeit sollte die Voraussetzung geschaffen werden, einen Testfall au einem einzigen Seed zu speisen (auch wenn das weitere Framework für derart reproduzierbare Testfälle noch nicht gegeben ist) +

+ +
+ +
+ + + + +

+ der Header sollte optional sein (und hinter den Daten liegen), aber die Gegenwart eines Headers sollte explizit erkennbar sein +

+ + +
+
+ + + + +

+ bisher haben wir nur nach einem Standard generierte Serien von Zufallsdaten, das heißt, wir könnten eine Speicher-Korruption erkennen, oder eben daß diese Daten geändert wurden; was aber fehlt die die Möglichkeit, nach einer solchen Änderung den neuen Stand wieder durch eine Prüfsumme zu qualifizieren (wodurch man ein erwartetes Ergebnis feststellen könnte) +

+ +
+
@@ -137843,6 +138157,107 @@ std::cout << tmpl.render({"what", "World"}) << s + + + + +

+   +

+ +
+ + + + + + + + + + + + + + + + + + + + + +

+ »Simple C++« Dimitrij Mijoski  2021-11

+

+ + +
+
+ + + + + +

+ Letztlich werde ich aus der Diskussion zu diesem Aspekt nicht klug. Zumindest aber sind nicht alle möglichen Ergebniszahlen sofort zu Beginn gleich wahrscheinlich; es wird auch immer wieder ein Zusammenhang impliziert mit dem Umfang des internal state, der beim Mersenne-Twister extrem groß ist (624 int). Festzuhalten bleibt, daß ein PRNG eine gweisse predictability haben kann, und das heißt, man sollte sich niemals auf das Auftreten / nicht-auftreten bestimmter Zahlen verlassen. Die Eigenschaften zeigen sich erst im statistischen Durchschnitt. Will man eine echte Zufallszahl, muß man eine echte Zufallszahl nehmen +

+ + +
+
+ + + + +

+ ...das heißt, nur wenn man tatsächlich mit 624 ints seeded, erreicht man alle möglichen Sequenzen. Wobei aber bereits zwei ints (2^64) für die meisten praktischen Probleme mehr als genug sein sollte; problematisch wird das nur bei Simulationen und Lösungssuche durch Monte-Carlo. +

+ + +
+
+ + + + +

+ ...darauf wird nirgends hingeweisen, und es gibt ein Interface, um einen Allokator einzuführen. Kritisiert wird auch generell das Interface für std::seed_seq — die Stichhaltigkeit dieser Kritik kann ich nicht beurteilen (anders als daß es nicht „einfach“ ist) +

+ + +
+ +
+ + + + +

+ Es läuft darauf hinaus, den Mersenne-Twister in Form von std::mt19937 als »default« zu verwenden. Und der ist langsam, braucht viel Speicher und ist kompliziert zu seeden. Außerdem sind die gebotenen Distributions-Funktionen allesamt nicht portabel (sondern implementation-defined). Leider werden dann in der Diskussion (Reddit, Stackoverflow) diverse Favoriten genannt, für die es dann stets auch wieder (ohne tiefere Expertise schwer nachprüfbare) Einwände gibt. Die einzige Alternative, gegen die niemand wirklich etwas einzuwenden hatte (außer daß es angeblich modernere / schnellere / coolere Alternativen gäbe) ist der allseits bekannte Jenkins jsf32 +

+ + +
+
+
+
+ + + + + + + + + + + @@ -137874,6 +138289,9 @@ std::cout << tmpl.render({"what", "World"}) << s + + + @@ -140278,8 +140696,20 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo - - + + + + +

+ Dokumentation zu
+ Themenbereichen +

+ +
+ + + + @@ -142814,7 +143244,109 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo - + + + + + + + + + + + + + +

+ Wenn eine Codebasis als Sammlung von Quellen veröffentlicht wird, muß  der Lizenzhinweis prominent sichtbar direkt beim Zugang zur Quelle gegeben sein. Die Veröffentlichung ist rechtlich bindend. Wenn die Veröffentlichung in Form eines Quellbaumes erfolgt, dann muß das Lizenz-Statement direkt in der Wurzel liegen. Es deckt damit automatisch alle anderen Resourcen in dieser Distribution mit ab, auch wenn in diesen Ressourcen nichts weiter steht. Darin liegt aber eine latente Gefahr: wenn eine Resource ohne direkt angehefteten Lizenz-Marker in ein anderes Projekt kopiert wird, fällt sie unter dessen allgemeine Lizenzbestimmung. Fehlt jedwede allgemeine Lizenzbestimmung, dann tritt das jeweilige Copyright-Gesetz des Landes in Kraft, und das bedeutet praktisch überall auf der Welt: der Original-Autor hat die exclusiven Veröffentlichungsrechte. Auf rechtlicher Ebene gilt stets, was sich feststellen und belegen läßt, nicht was jemand beabsichtigt hat oder haben könnte. +

+ +
+
+ + + + +

+ ...und zwar für den Fall, daß jemand eine in-sich geschlossene Quelldatei aus dem Projekt heraus kopiert; alle Hinweise direkt in der Datei erhöhen die Wahrscheinlichkeit, daß die Lizenzinformation nicht verlorengeht. Hinweise über Haftungsausschluß und wo man die Lizenz bekommt sind nur eine Empfehlung und haben keine rechtliche Wirkung. Diese ensteht durch die Veröffentlichung, und dazu genügt ein Statement im Root des Quellbaumes. Diese Einschätzung geht sogar aus den Hinweisen im Appendix der GPL selber hervor. Auch auf den Seiten der FSF wird zwar stark nahegelegt, den kopletten Präambel-Text einzufügen, aber es handelt sich daber ohne jeden Zweifel nur um eine Empfehlung +

+ + +
+
+ + + + +

+ Wenn dieser Claim in jeder Quelldatei eigens gepflegt wird, erhöht das die Sicherheit der Verbindung von Copyright und Lizensierung. Allerdings auch nur, wenn dieser Claim korrekt ist. Es genügt, den Zeitpunkt der allerersten signifikanten Schöpfung und Veröffentlichung aufzuführen, denn alle weiteren Beiträge sind dann bereits durch die GPL gedeckt. Empfohlen wird, spätere signifikante Beiträge gesondert mit Jahreszahl aufzuführen. Jahresbereiche sind nur sinnvoll, wenn in jedem der eingeschlossenen Jahre tatsächlich etwas beigetragen wurde. +

+ + +
+
+ + + + +

+ Notwendig wäre das nicht, aber hilfreich, wenn die Datei herausgelöst wird. Es genügt ein Hinweis auf die exakte Form der Lizenz. Man kenn "this Program" durch den expliziten Namen ersetzen. Man kann dazu noch auf die COPYING-Datei verweisen. Alle weiteren Infos, z.B. ein Haftungsausschluß sind nur empfohlen und ändern nicht die rechtliche Wirkung der Lizenz, unter der veröffentlicht wurde +

+ + +
+
+
+ + + + +

+ /* +

+

+   INDEX-ITER.hpp  -  iterator with indexed random-access to referred container +

+

+ +

+

+   Copyright (C) +

+

+     2024,            Hermann Vosseler <Ichthyostega@web.de> +

+

+ +

+

+   **Lumiera** is free software; you can redistribute it and/or modify it +

+

+   under the terms of the GNU General Public License as published by the +

+

+   Free Software Foundation; either version 2 of the License, or (at your +

+

+   option) any later version. See the file COPYING for further details. +

+

+ +

+

+ */ +

+ + +
+ +
+
+
+
+
+