Kosmologie und Quantenfluktuationen im Browser

Setzen wir uns ein rein praktisches Ziel - eine endlose Leinwand mit der FĂ€higkeit zu realisieren, sie mit der Maus zu bewegen und zu skalieren. Eine solche ZeichenflĂ€che kann beispielsweise als bewegliches Koordinatensystem in einem grafischen Editor dienen. Die Umsetzung unserer Idee ist nicht so kompliziert, aber der Prozess des Verstehens ist mit grundlegenden mathematischen und physikalischen Objekten verbunden, die wir bei unserer Entwicklung berĂŒcksichtigen werden.


Ergebnis

ErklÀrung des Problems


Auf unserer Leinwand möchten wir nur zwei Funktionen ausfĂŒhren: Bewegen der Maus und Bewegen der Maus sowie Zoomen beim Scrollen. Die Arena unserer Transformationen wird einen Browser auswĂ€hlen. Waffen mĂŒssen in diesem Fall nicht wĂ€hlen.



Zustandsmaschine


Das Verhalten solcher Systeme wird zweckmĂ€ĂŸigerweise durch ÜbergĂ€nge zwischen ihren ZustĂ€nden beschrieben, d.h. Zustandsmaschine  delta:S rightarrowSwo  delta- die Übergangsfunktion zwischen ZustĂ€nden, die viele ZustĂ€nde an sich anzeigt.


In unserem Fall sieht das Zustandsdiagramm folgendermaßen aus:





Bei der Implementierung der Übergangsfunktion ist es zweckmĂ€ĂŸig, das Ereignis abhĂ€ngig zu machen. Dies wird sich in Zukunft zeigen. Ebenso ist es bequem, eine Änderung des Zustands der Maschine abonnieren zu können.


type State = string | number; type Transition<States = State> = { to: States, where: (event: Event) => Array<boolean>, }; type Scheme<States = State> = { [key: States]: Array<Transition<States>> }; interface FSM<States = State> { constructor(state: States, scheme: Scheme<States>): void; // Returns true if the scheme had a transition, false otherwise get isActive(): boolean; // Dispatch event and try to do transition dispatch(event: Event): void; // subscribe on state change on(state: States, cb: (event: Event) => any): FSM<States>; // remove subscriber removeListener(state: States, cb: (event: Event) => any): void; }; 

Wir werden die Implementierung fĂŒr eine Weile verschieben und die geometrischen Transformationen aufgreifen, die unserer Aufgabe zugrunde liegen.


Geometrien


Wenn das Problem beim Verschieben der Leinwand so offensichtlich ist, dass wir uns nicht damit befassen, sollte das Dehnen genauer betrachtet werden. ZunĂ€chst benötigen wir, dass die Dehnung einen einzelnen Punkt stationĂ€r lĂ€sst - den Mauszeiger. Die ReversibilitĂ€tsbedingung muss ebenfalls erfĂŒllt sein, d.h. Die umgekehrte Reihenfolge der Benutzeraktionen sollte die Leinwand an ihre ursprĂŒngliche Position bringen. Welche Geometrie ist dafĂŒr geeignet? Wir werden eine Gruppe von Punkttransformationen der Ebene in sich selbst betrachten  mathbbR2 rightarrow mathbbR2, was im Allgemeinen durch die EinfĂŒhrung neuer Variablen ausgedrĂŒckt wird xâ€Č,yâ€Čdefiniert als Funktionen der alten:


xâ€Č= varphi(x,y)yâ€Č= psi(x,y)


In Übereinstimmung mit dem Prinzip der DualitĂ€t in der Mathematik können solche Transformationen als Änderung des Koordinatensystems sowie als Transformation des Raums selbst interpretiert werden, wobei letzteres festgelegt ist. Die zweite Interpretation ist fĂŒr unsere Zwecke zweckmĂ€ĂŸig.


Ein modernes VerstĂ€ndnis der Geometrie unterscheidet sich von einem VerstĂ€ndnis der Alten. Nach F. Klein untersucht die Geometrie Invarianten in Bezug auf bestimmte Transformationsgruppen. Also in einer Gruppe von Bewegungen DDie Invariante ist der Abstand zwischen zwei Punkten d((x1,y1),((x2,y2))= sqrt(x1−x2)2+(y1−y2)2. Es enthĂ€lt parallele Silbentrennung T(x,y)auf Vektor (x,y)Rotation R phirelativ zum Ursprung in einem Winkel  phiund Reflexionen Mlrelativ zu einer Linie l. Solche Bewegungen nennt man elementar. Die Zusammensetzung der beiden SĂ€tze gehört zu unserer Gruppe und ist manchmal elementar. So zum Beispiel zwei aufeinanderfolgende Spiegelreflexionen relativ zu geraden Linien lund nDrehen Sie sich in einem bestimmten Winkel um ein bestimmtes Zentrum (ĂŒberzeugen Sie sich selbst):

Ml circMn=T(−a,−b) circR alpha circT(a,b)


Sicher haben Sie schon vermutet, dass eine solche Gruppe von Bewegungen Dbildet euklidische Geometrie. Beim Strecken bleibt jedoch nicht der Abstand zwischen zwei Punkten erhalten, sondern deren Beziehung. Daher eine Gruppe von Bewegungen, obwohl es in unser Schema aufgenommen werden sollte, aber nur als Untergruppe.


Die Geometrie, die zu uns passt, basiert auf einer Dehnungsgruppe Pzu dem zusĂ€tzlich zu den obigen Bewegungen die Homothetik hinzugefĂŒgt wird Sknach Koeffizienten k.


Nun, der letzte. Das umgekehrte Element muss in der Gruppe vorhanden sein. Und deshalb gibt es eine neutrale e(oder Single) das Àndert nichts. Zum Beispiel

Sk circSk−1=e


bedeutet zuerst einstrecken kmal und dann in 1/k.

Jetzt können wir die Dehnung in gruppentheoretischer Sprache beschreiben, wobei der Mauszeiger fest bleibt:


(x,y) rightarrow(x,y)(T(−clientX,−clientY) circSk circT(clientX,clientY))


Anmerkung 1

Im allgemeinen Fall sind Umordnungen von Aktionen nicht kommutativ (Sie können zuerst Ihren Mantel und dann Ihr Hemd ausziehen, aber nicht umgekehrt).


 forall(x,y) in mathbbR2 neq0 RightarrowT(−x,−y) circSk circT(x,y)) neqSk circT(−x,−y) circT(x,y))



DrĂŒcken Sie die Bewegung aus T(x,y)und Skund ihre Zusammensetzung als Funktionen eines Vektors im Code


 type Scalar = number; type Vec = [number, number]; type Action<A = Vec | Scalar> = (z: Vec) => (v: A) => Vec; // Translate const T: Action<Vec> = (z: Vec) => (d: Vec): Vec => [ z[0] + d[0], z[1] + d[1] ]; // Scale const S: Action<Scalar> = (z: Vec) => (k: Scalar): Vec => [ z[0] * k, z[1] * k ]; const compose = (z: Vec) => (...actions: Array<(z: Vec) => Vec>) => actions.reduce((z, g) => g(z), z); 

Schmerz 1

Es ist sehr seltsam, dass in JavaScript keine OperatorĂŒberladung auftritt. Es scheint, dass es bei einer derart weit verbreiteten Verwendung von Vektor- und Rastergrafiken viel bequemer ist, mit Vektoren oder komplexen Zahlen in einer "klassischen" Form zu arbeiten. Die Aktionskonzepte wĂŒrden arithmetische Operationen ersetzen. So zum Beispiel Rotation um einen Vektor aan der Ecke  phiwĂŒrde auf triviale Weise ausgedrĂŒckt werden:


T−a circR phi circTa LinkerrechterPfeilz rechterPfeil(z−a)ei phi+a


Leider folgt JS nicht der Entwicklung der wunderbaren pythagoreischen Idee „Die Welt ist eine Zahl“, im Gegensatz zu zumindest Python.



Beachten Sie, dass wir bisher mit einer Gruppe kontinuierlicher Transformationen gearbeitet haben. Der Computer arbeitet jedoch nicht mit kontinuierlichen Mengen. Daher verstehen wir nach Poincare eine kontinuierliche Gruppe als eine unendliche Gruppe diskreter Operationen. Nachdem wir die Geometrie herausgefunden haben, sollten wir uns der RelativitÀt der Bewegung zuwenden.


Kosmologie der Leinwand. Modulares Raster


Als Menschheit ist seit einem Jahrhundert die Expansion des Universums bekannt. Wenn wir entfernte Objekte - Galaxien und Quasare - beobachten, registrieren wir die Verschiebung des elektromagnetischen Spektrums zu lĂ€ngeren Wellen - die sogenannte kosmologische Rotverschiebung. Jede Messung verbindet den Beobachter, das Beobachtete und die Messmittel, in Bezug auf die wir unsere Messungen durchfĂŒhren. Ohne Messinstrumente ist es unmöglich, invariante Beziehungen in der Natur herzustellen, d. H. Die Geometrie des Universums zu bestimmen. Die Geometrie verliert jedoch ihre Bedeutung ohne Beobachtbarkeit. In unserer Aufgabe ist es also schön, Orientierungspunkte wie Galaxien zu haben, in Bezug auf deren Licht wir die RelativitĂ€t der Bewegung unserer Leinwand bestimmen können. Eine solche Struktur kann ein periodisches Gitter sein, das sich jedes Mal teilt, wenn der Raum zweimal erweitert wird.


Da das Gitter periodisch ist, ist es zweckmĂ€ĂŸig, eine modulare Algebra anzuwenden. Wir werden also als Gruppe agieren Pauch auf dem Torus T2=S1 malS1. Da der Monitorbildschirm keine durchgehende Ebene ist, sondern ein ganzzahliges Gitter  mathbbZ2(Wir vernachlĂ€ssigen jetzt, dass es endlich ist), dann die Aktion der Gruppe Pmuss auf einem ganzzahligen Torus berĂŒcksichtigt werden  mathbbZp2wo p- quadratische RippengrĂ¶ĂŸe p timesp::





Wenn wir also unseren Torus ein fĂŒr alle Mal in der NĂ€he des Ursprungs fixieren, werden wir alle weiteren Berechnungen daran durchfĂŒhren. Verbreiten Sie es dann mit Standardmethoden fĂŒr die Canvas-Bibliothek. So sieht eine Bewegung mit einem Pixel aus:





Offensichtlich ist die Standardoperation, das Modul x% p zu nehmen, fĂŒr uns nicht geeignet, da sie negative Werte des Arguments in negative Werte ĂŒbersetzt, aber es gibt keine auf dem ganzzahligen Torus. Schreiben Sie Ihre Funktion x modp::



 const mod = (x, p) => x >= 0 ? Math.round(x) % p : p + Math.round(x) % p; 

Nun zurĂŒck zur Endzustandsmaschine und


definiere es
Die FSM-Klasse wird bequem von EventEmitter geerbt, wodurch wir die Möglichkeit haben, sie zu abonnieren.
 class FSM<States> extends EventEmitter { static get TRANSITION() { return '__transition__'; } state: States; scheme: Scheme<States>; constructor(state: States, scheme: Scheme<States>) { super(); this.state = state; this.scheme = scheme; this.on(FSM.TRANSITION, event => this.emit(this.state, event)); } get isActive(): boolean { return typeof(this.scheme[this.state]) === 'object'; } dispatch(event: Event) { if (this.isActive) { const transition = this.scheme[this.state].find(({ where }) => where(event).every(domen => domen) ); if (transition) { this.state = transition.to; this.emit(FSM.TRANSITION, event); } } } } 


Definieren Sie als NĂ€chstes ein Übergangsschema, erstellen Sie eine ZeichenflĂ€che und


initialisiere alles.
 canvas = document.getElementById('canvas'); ctx = canvas.getContext('2d'); // Create a pattern, offscreen patternCanvas = document.createElement('canvas'); patternContext = patternCanvas.getContext('2d'); type States = | 'idle' | 'pressed' | 'dragging' | 'zooming'; const scheme: Scheme<States> = { 'idle': [ { to: 'pressed', where: event => [event.type === 'mousedown'] }, { to: 'zooming', where: event => [event.type === 'wheel'] }, ], 'pressed': [ { to: 'moving', where: event => [event.type === 'mousemove'] }, { to: 'idle', where: event => [event.type === 'mouseup'] }, ], 'moving': [ { to: 'moving', where: event => [event.type === 'mousemove'] }, { to: 'idle', where: event => [event.type === 'mouseup'] }, ], 'zooming': [ { to: 'zooming', where: event => [event.type === 'wheel'] }, { to: 'pressed', where: event => [event.type === 'mousedown'] }, { to: 'idle', where: event => [true] }, ], }; const fsm: FSM<States> = new FSM('idle', scheme); const dispatch = fsm.dispatch.bind(fsm); 


Anschließend sollten Sie die Rendering-Funktion festlegen, die erforderlichen Anfangswerte festlegen und die StatusĂ€nderung abonnieren. Betrachten Sie den interessantesten Teil des Codes:


  fsm.on('zooming', (event: WheelEvent) => { // next scale factor const nk = g >= 1 ? round(k + Math.sign(event.wheelDeltaY) * h * g / 1e2, 1e2) : round(k + Math.sign(event.wheelDeltaY) * h * g / 1e2, 1e12); // gain g = 2 ** Math.trunc(Math.log2(nk)); if (g < min || g > max) return; vec = compose(vec)( T([-event.clientX, -event.clientY]), S(nk / k), T([event.clientX, event.clientY]) ); size = base * nk; patternCanvas.width = Math.round(size / g); patternCanvas.height = Math.round(size / g); xyMod = [ mod(vec[0], patternCanvas.width), mod(vec[1], patternCanvas.height) ]; k = nk; main(); }); 

Erstens erweitern wir nicht um den Koeffizienten k, sondern um ein VerhĂ€ltnis nk / k. Dies liegt daran, dass der m-Schritt unserer Abbildung an einem festen Punkt liegt (a,b)ausgedrĂŒckt als


xm=(xm−1−a)km−1∗+aym=(ym−1−b)km−1∗+b


oder relativ zu den Anfangswerten x1,y1


xm=(x1−a) prodi=1m−1ki∗+aym=(y1−b) prodi=1m−1ki∗+b


Offensichtlich das Produkt  prodi=1m−1ki∗Es gibt eine nichtlineare Funktion des Iterationsschritts, die entweder sehr schnell gegen Null konvergiert oder mit kleinen anfĂ€nglichen Abweichungen ins Unendliche ablĂ€uft.


Wir fĂŒhren die Variable g ein, die ein Maß fĂŒr die Verdoppelung unserer Leinwand ist. Offensichtlich nimmt es in einem bestimmten Intervall einen konstanten Wert an. LinearitĂ€t erreichen ki∗Wir verwenden eine homogene Substitution


ki+1∗= fracki+1ki,k1=1


Dann werden alle Mitglieder der Arbeit außer dem ersten und dem letzten reduziert:


 prodi=1m−1ki∗= prodi=1m−1 frackiki−1= frack21 frack3k2... frackm−2km−3 frackm−1km−2=km−1


Ferner reduziert der Phasensprung g die Expansionsrate derart, dass sich die fraktale Struktur, die sich vor uns entfaltet, immer linear bewegt. Somit erhalten wir eine ungefÀhre Variation des Hubble-Potenzgesetzes der Expansion des Universums.


Es bleibt die Grenzen der Genauigkeit unseres Modells zu verstehen.


Quantenschwankungen. 2-adic Zahlenfeld


Das VerstĂ€ndnis des Messprozesses fĂŒhrte zum Konzept einer reellen Zahl. Heisenbergs Unsicherheitsprinzip weist auf seine Grenzen hin. Ein moderner Computer arbeitet nicht mit reellen Zahlen, sondern mit Maschinenwörtern, deren LĂ€nge von der KapazitĂ€t des Prozessors bestimmt wird. Maschinenwörter bilden ein Feld von 2-adischen Zahlen  mathbbQ2und werden als bezeichnet  mathbbF2nwo n- WortlĂ€nge. Der Messprozess wird in diesem Fall durch den Berechnungsprozess ersetzt und ist einer nicht-archimedischen Metrik zugeordnet:


 foralln in mathbbZ,z in mathbbF2n:n cdotz<2n


Somit hat unser Modell eine Berechnungsgrenze. Die EinschrĂ€nkungen sind im IEEE_754- Standard beschrieben. Ab einem bestimmten Zeitpunkt ĂŒberschreitet unsere BasisgrĂ¶ĂŸe die Genauigkeitsgrenze, und bei der Aufnahme des Moduls werden Fehler erzeugt, die pseudozufĂ€lligen Sequenzen Ă€hneln. Dies wird einfach durch Löschen der Zeile ĂŒberprĂŒft


 if (g < min || g > max) return; 

Die endgĂŒltige Grenze wird in unserem Fall nach der semi-empirischen Methode berechnet, da wir mit mehreren Parametern arbeiten.


Fazit


Auf den ersten Blick scheinbar weit entfernte Theorien sind also im Browser auf der Leinwand verbunden. Die Konzepte von Aktion, Messung und Berechnung sind eng miteinander verbunden. Das Problem der Kombination ist immer noch nicht gelöst.


Ergebnis

PS
Es war klar, dass der Quellcode klein sein wĂŒrde, also leitete ich die Entwicklung in der gewöhnlichen index.html. WĂ€hrend ich diesen Artikel schrieb, fĂŒgte ich die Eingabe hinzu, die ich auf dem TypeScript-Spielplatz getestet habe.

Source: https://habr.com/ru/post/de467959/


All Articles