Beiträge von Mars

    Eine weitere Methode wäre folgendes:

    - Schiebe deine Werte die du behalten möchtest (inplace) nach vorne und die die du loswerden möchtest nach hinten.

    - Benutze genau 1x Redim auf dein nun strukturiertes Array und schneide dir damit den Teil aus den du behalten möchtest.

    Code
    1. #include <Array.au3>
    2. Global $a[5][3] = [[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12],[13, 14, 15]]
    3. _ArrayDisplay($a)
    4. ReDim $a[3][2] ; Redim Schneidet jeweils den Inhalt jedes Index' von 0 bis End aus.
    5. _ArrayDisplay($a)

    Der Code dient nur als Beispiel für das was ReDim macht.


    M

    Ein Trick um das "ausufern" zu verhindern ist die Energieerhaltung.


    Zu Beginn berechnet man die Gesamtenergie (EPot + EKin) und nach jedem Frame (wenn alle Werte vorliegen) berechnet sie ebenfalls. Da es immer kleine Abweichungen gibt (man kann kein kontinuierliches system fehlerfrei diskret simulieren) wird die Gesamtenergie im System nicht erhalten sein. Jetzt passt man nach jedem Frame die Werte etwas an, sodass die Energie trotzdem erhalten bleibt. Das ist zwar eigentlich grober Unfug, hilft aber dabei das ein System nach einiger Zeit immernoch stabil (wenn auch falsch) läuft.


    kleiner Tip hier: (tooltip mit Energie (die kartesisch berechnet wurde... ist mir auch erst im nachhinein aufgefallen dass das doof ist :D))

    Die Zahlen darin sind eigentlich vollkommen wurscht :D


    Das Verfahren funktioniert so:

    - "Habe" eine Wahrscheinlichkeitstabelle für jedes Zeichen (wenn man nichts weiß ist das eine Gleichverteilung, oder in diesem Fall das Default Histogramm)

    - Baue einen Baum aus der Tabelle, Kodiere/Dekodiere ein Zeichen und erstelle damit die Tabelle neu. -> solange bis keine Zeichen übrig sind.


    Was du da reinschreibst ist also egal, alles was sich dadurch ändert ist die Kompressionsrate zu Beginn. Allerdings kann man keinen Text dekodieren, wenn eine andere Tabelle benutzt wurde als im Encoder, also könnte man dieses 256 float Gebilde als eine Art "viel zu langes Passwort" missbrauchen :D


    Max Mustermann, Musterbergheimer Landstraße 1 99, 12345 Musterbergheim am Musterberg.


    Edit: Falls jemand das Teil nochmal angesehen hat, ich habe den Min-Heap ergänzt, somit ist es jetzt ca. 30% schneller als vorher. Da es immernoch inplace in einem Array funktioniert kann man das 1:1 in jede beliebige Sprache genauso übernehmen und es müsste immer ziemlich effizient arbeiten. Außerdem habe ich TreeToLookup optimiert, sodass sie statt 3ms nur noch 2ms benötigt, leider immernoch rekursiv...


    lg

    M

    Ich bin ein wenig verwirrt, die BitShift Funktion in AutoIt tut genau das was man vermuten würde oder?


    Poste doch bitte ein Skriptbeispiel das dein Problem reproduzieren kann (z.B. BitShift(abc, x) = 123, sollte aber eigentlich 234 sein). Dann kann man auch was damit anfangen und eine Lösung finden


    M

    Hehehe,


    ich wollte die Sache erst "ADH = ADaptive Huffman" nennen, dann ist es aber "AHE = Adaptive Huffman Encoder" geworden. Wahrscheinlich wäre "AHC = Adaptive Huffman Code" noch besser. Namensfindung ist so kompliziert :(


    Den Baum aufspannen dauert (mit der jetzigen Methode) in AutoIt ca. 50ms. Schätze man kommt noch auf ca. 20-30ms wenn man ein wenig optimiert. Da ich alles so umgebaut habe, dass es inplace in einem Array stattfindet könnte man es 1 zu 1 in ASM übersetzen. Dann werden aus 20ms -> 20µs.


    //OT:

    Mit dem Internet stimmt wirklich etwas nicht. Ich wollte mir letztens einen Stream auf YT ansehen, der hat furchtbar gehackt ist andauernd stehengeblieben und konnte nur via F5 wieder für ein paar Sekunden am laufen gehalten werden. Dieses Totalversagen schiebe ich aber auf die Software. Meine Leitung hat einen Ping von ca. 25ms und kann ca. 5MB/s (wenn sie gute Laune hat), ich erwarte dass ein Stream damit flüssig läuft :thumbdown:

    Moin,


    (Gleich zu Beginn mal ein Wiki-Link, jeder der nicht weiß worum es geht sollte den ggf. erst durchgehen :))


    Einen Huffman Encoder kann vermutlich jeder basteln (ist ja nicht so schwer) wo ich aber häufig Probleme beobachtet habe ist der Part mit dem Abspeichern der Wahrscheinlichkeitstabelle. Es ist nämlich so, dass der Decoder im Regelfall den Huffman-Baum zum dekodieren benötigt.


    Beispiel:

    Wenn ich jetzt aber meinen Text: "Hallo Test 123" verwende gibt es ein großes Problem: Der Text besteht aus vielen verschiedenen Zeichen (es ist ja nicht "aaaaaaabbabaaaa" oder soetwas) die jeweils auch nicht allzuoft vorkommen (Leerzeichen x2 und "l" x2), egal in welcher optimierten Darstellung ich den Huffman-Baum abspeichere, er wird in jedem Fall mehr Speicher verbrauchen als mein eigentlicher Text. Wenn ich jetzt den kodierten Text + Baum benötige um wieder meinen ursprünglichen Text zu erhalten ist nichts gewonnen. Hier kommt der adaptive Teil zum tragen.


    Ein adaptiver Kodierer beginnt mit irgendeiner vorgegebenen Wahrscheinlichkeitsverteilung (z.B. eine Gleichverteilung, dann hat jedes Zeichen beim erstmaligen auftreten 8 Bit, da es 256 theoretisch mögliche Asc Zeichen gibt), generiert daraus den Huffman-Baum und kodiert damit nur das allererste Zeichen des Textes. Dann wird dieses Zeichen mit einem gewissen Faktor zur Wahrscheinlichkeitstabelle hinzugefügt, ein neuer Baum generiert und damit das 2te Zeichen kodiert. usw usw. Das bedeutet, dass der Decoder KEINEN Baum benötigt, da dieser implizit durch die kodierte Nachricht selbst mitgeliefert wird. Das hat eine ganze Reihe Vor- und Nachteile.


    Vorteile:

    - Funktioniert auch für kurze Texte deren Huffman-Baum alleine schon größer wäre als der Text selbst

    - Falls man eine Dämpfung festlegt (in meinem Skript nicht enthalten) ist es möglich dass der Kodierer lokal besser arbeitet als wenn für den vollen Text die gleiche Verteilung angenommen werden würde.

    - Da die Wahrscheinlichkeitsverteilung laufend angepasst wird kann man von einem beliebigen Startpunkt aus loslaufen. Eine Gleichverteilung, oder ein Histogramm aller Zeichen in meinem UDF-Ordner, oder der Buchstabenverteilung in irgendeiner Sprache. In diesem Fall müsste man dem kodierten Text z.B. 2 bit voranstellen damit der Decoder weiß welche Verteilung er als Startwert nehmen soll. Man könnte auch die nicht adaptive Version so verwenden und statt einem Baum nur eine Baumnummer in den kodierten Text schreiben. Das wäre aber bei weitem suboptimaler, da dieser Baum dann nicht angepasst werden würde und man nicht für jeden beliebigen Text einen gut passenden Baum im Decoder hinterlegen kann. Eine Hand voll Verteilungen reichen bei der adaptiven Version aber vollkommen aus um immer ein gutes Ergebnis zu erzielen.


    Nachteile:

    - Da nach JEDEM ZEICHEN alles neu aufgebaut werden muss ist diese Methode unglaublich langsam (eine Version mit Min-Heap bastele ich gerade bin aber noch nicht zufrieden).

    - Da die Wahrscheinlichkeitstabelle laufend angepasst wird ist sie zu keinem Zeitpunkt "wirklich" optimal. Verglichen mit einem "normalen" Huffman-Code ist die adaptive Version je nach situation unterlegen und erzeugt längeren Output als notwendig.

    - Der Textanfang wird zwangsweise suboptimal kodiert, da die Startverteilung (z.B. die Gleichverteilung) nicht immer gut auf die vorliegende Zeichenfolge passt.

    - Habe ich langsam schon erwähnt? (auf meinem PC aktuell ca. 20-25 Zeichen/Sekunde)


    Villeicht kann ja jemand das Skript gebrauchen, daher landet es hier :)


    Edit: 12.03.19:

    Jetzt funktioniert das ganze mit Min-Heap und ist ca. 30% schneller als vorher. Es hat viel Spaß gemacht das Teil im Rahmen der Geschwindigkeit von AutoIt zu optimieren. Wenn man die Methode aber tatsächlich auch benutzen will sollte man es in einer anderen Sprache tun... 30 Zeichen/Sek ist unzureichend, alleine diesen Post hier zu kodieren würde ne Stunde dauern :D



    lg

    M

    Vielen Dank für das Lob, ich mache immer viel zu viele Sachen gleichzeitig, weshalb einiges oft für Ewigkeiten auf der Strecke bleibt...

    Vermutlich werde ich eines schönen Tages die Vorschläge von BugFix umsetzen, das wäre ansich schon wichtig. Außerdem gibt es noch ein paar Bugs/Aufräumarbeiten...

    Für GDI+ "Objekte" kannst du den Datentyp ptr nutzen (denn nichts anderes sind die "hGFX" und "hBMP" und so weiter, alles nur Pointer auf ein Stückchen Speicher).


    lg

    M

    Interessant. Man wird jeden Tag ein kleines Stückchen schlauer :D

    Ich tendiere ja persönlich dazu inzwischen alles als HexString (UTF8) zu übertragen/speichern/sonstiges, denn 0-9A-F bekommt jedes Format einwandfrei hin (natürlich braucht man dann mehr Bandbreite/Speicher, weil man doppelt so viele Zeichen hat, aber es funktioniert wenigstens (meistens... manchmal denkt sich ein Programm auch, hey lass mal spontan irgendwelche Bytes rückwärts lesen, dann muss man kurz eine Schelle mit der Rückhand austeilen und dann gehts wieder)). Ansich finde ich es bescheuert, dass es überhaupt so viele Kompatibilitätsprobleme und den Bedarf an Umkodierern gibt... Ich will einfach die guten Alten ASC Zeiten wieder haben, da war Text noch eine Art "primitiver Datentyp" der durch seine Bits unmissverständlich eindeutig definiert war...


    Villeicht werde ich beim nächsten Mal wo ich auf soetwas stoße auch hier nachlesen wie das mit den verschieden kodierten Texten aussieht... mal schauen :D


    M

    Wird Round() in Kombination mit Funktionen verwendet, die je nach Datentyp unterschiedlich agieren (z.B. Hex(5) <> Hex(5.0)), kann es zu unerwarteten Ergebnissen führen, da Round() als Rückgabetyp immer ein Double liefert, sofern der optionale Parameter "decimalplaces" mit angegeben wird - wird dieser weggelassen, ist der Rückgabetyp immer Int32.

    Code
    1. ConsoleWrite('+ --------------------------------------------------------------------------------------------------------- ' & @CRLF)
    2. ConsoleWrite('+ Die Verwendung des optionalen Parameters "decimalplaces" führt zur Rückgabe unterschiedlicher Datentypen : ' & @CRLF)
    3. ConsoleWrite('! Datentyp ohne "decimalplaces" -> Round(5.5) = ' & VarGetType(Round(5.5)) & @CRLF)
    4. ConsoleWrite('! Datentyp mit "decimalplaces" -> Round(5.5, 0) = ' & VarGetType(Round(5.5, 0)) & @CRLF)
    5. ConsoleWrite('+ --------------------------------------------------------------------------------------------------------- ' & @CRLF)
    6. ConsoleWrite('+ Beispiel mit der Funktion Hex(), wo der Datentyp den Rückgabewert beeinflusst : ' & @CRLF)
    7. ConsoleWrite('! Hex mit Round(5.5) = ' & Hex((Round(5.5))) & @CRLF)
    8. ConsoleWrite('! Hex mit Round(5.5, 0) = ' & Hex((Round(5.5, 0))) & ' (Anm.: Hex-Repräsentation einer Gleitkommazahl)'& @CRLF)
    9. ConsoleWrite('+ --------------------------------------------------------------------------------------------------------- ' & @CRLF)

    Edit: Rechtschreibung und Formulierung und Code :D


    M

    Ceiling, Floor oder Int sind manchmal nicht die beste Wahl, vorallem wenn man Gleitkommarechnungen hat und "runden" möchte (und nicht ab- oder aufrunden).

    Der eigentlich interessante Teil ist das mit Int32 und Double als Returnwert der selben Funktion, je nachdem ob man mit- oder ohne Parameter auf 0 Kommastellen rundet, obwohl man eigentlich in beiden Fällen Int32 ODER Double erwarten würde (als jemand der auch andere Sprachen nutzt erwartet man in beiden Fällen Double)

    Wer gerne Round benutzt und häufiger ins Hexadezimalsystem vorstößt hat sich sicher schon über Hex(Int(Round($a, 0)), 2) geärgert (also dass man DREI Funktionen braucht um aus 125.5 ein 7E zu machen). Lustigerweise gibt Round($a, 0) ein Double, während Round($a) ein Int32 ausspuckt. Will man also Hex(Round($a)) hat man keine Probleme, solange man die Null weglässt (die ich intuitiv immer erstmal hinmache)

    Code
    1. Local $a = 125.5
    2. ConsoleWrite(VarGetType(Round($a)) & @CRLF)
    3. ConsoleWrite(VarGetType(Round($a, 0)) & @CRLF)
    4. ConsoleWrite(Hex(Round($a), 2) & @CRLF)
    5. ConsoleWrite(Hex(Round($a, 0), 2) & @CRLF)


    lg

    M

    Moin,


    Jeder Kennt die Matrixmultiplikation A * B = C, man kennt A und B und sucht C. Einfache Sache.


    Was passiert aber, wenn man A * B = C hat und B und C kennt und A sucht?


    Ich bin leider kein Meister der linearen Gleichungssysteme und habe jetzt einige Zeit probiert dazu eine anständige (analytische) Lösung zu programmieren, einige Erkenntnisse liste ich hier auf, vllt hilft das jemandem weiter. Ansich suche ich aber jemanden der zu viel Freizeit, oder bereits eine Lösung für dieses Problem parat hat.


    Wofür brauche ich das?

    Ich habe in der letzten Zeit versucht eine Art "Texterkennung" zu basteln die auch mit Pixelfehlern usw. klarkommt. Dabei sind die Inputpixel (Schwarz oder Weiß, 0 oder 1) jeweils eine Spalte in der Matrix B. Jede Zeile steht für die Erkennungspixel eines einzelnen Zeichens, (vereinfacht (als 3x3 Pixel "Bit"map) 010 010 010 = "I", 111 101 111 = "O", usw usw). In C stehen jetzt die zugeordneten Zeichen als Zeile, z.B. kommt soetwas heraus wie [0.123, 0.013, -1.5, 1], dann weiß man, dass die untersuchte Bitmap wahrscheinlich das Zeichen Nummer 4 ist (die Zuordnung welches Zeichen welche Nummer hat passiert woanders). Der Knackpunkt ist die Matrix A die quasi die "Gewichtung" der einzelnen Pixel für die einzelnen Zeichen beinhaltet. Vereinfacht: Ist der obere Linke Pixel = Schwarz, so ziehe ich vom Buchstaben O etwas ab da er unwahrscheinlich ist und Addiere bei W, T, P usw etwas dazu, weil diese Buchstaben wahrscheinlicher sind. Nachdem man also die Volle Multiplikation von A = Gewichtungsmatrix * B = "Bit"map durchgeführt hat weiß man welches Zeichen in der Bitmap steht. Vorteil bei der Geschichte ist folgendes: Selbst wenn ein paar Pixel falsch sind (weil z.B. die Kantensuche bei unterschiedlichen Farben für unterschiedliche Ergebnisse beim gleichen Buchstaben sorgt) haben die restlichen Pixel immernoch genug Informationen um den Buchstaben anständig zuzuordnen. Durch die Gewichtung ist diese Methode auch einem direkten Vergleich mit einer Testbitmap überlegen (außerdem müsste man dann alle theoretisch möglichen Zeichen 1x vergleichen und das mit der niedrigsten Abweichung ist dann das richtige, das ist zwar mathematisch einfacher, aber unnötig Rechenaufwändig und niemand will ein paar hundert Bitmaps haben).


    Problemstellung: A * B = C

    - A - Unbekannt <- Soll berechnet werden

    - B - Bekannt (Mögliche Werte sind 0, 1)

    - C - Bekannt (Mögliche Werte sind -1, 0, 1. Das -1 kommt vom OffsetVektor für ein komplett leeres B, da A * 0 = 0 ist, ein leeres B aber z.B. für ein Leerzeichen stehen kann, also muss C <> 0 sein)


    Erkenntnisse:

    - Die Lösung wäre Trivial, wenn A quadratisch wäre sodass man A invertieren kann. Da A aber beliebige Maße haben können muss ist das nicht möglich.

    - B[n][m] und C[k][m] bedeutet A[k][n] -> also ist A automatisch A[UBound(C, 1)][UBound(B, 1)]

    - Es gibt nicht immer eine Lösung (vorallem bei kleinen Matrizen die in meinem Anwendungsfall nicht vorkommen werden, genauso wie ein Inputvektor mit nur Nullen, oder ein Outputvektor mit nur Nullen, jede Matrix Zeile/Spalte hat immer mindestens einen von 0 verschiedenen Wert)

    - Es gibt, wenn es eine Lösung gibt (fast immer) unendlich viele Lösungen, da das Gleichungssystem (fast immer) überbestimmt ist, bzw. Werte voneinander abhängen (wenn man an beiden dreht bleibt das Ergebnis gleich). A enthält viel mehr Werte als es Gleichungen gibt. Für eine optimale Nutzung wäre natürlich eine Art "Durchschnittslösung" die best mögliche Lösung. Man kann also nicht einfach alle "überflüssigen" Werte aus A = 0 setzen und mit dem Rest das System lösen, das ruiniert die Fehlerkorrektur, weil es den Einfluss einzelner Pixel (einzelner Elemente aus B) auf das Ergebnis maximiert un der soll ja gerade minimiert werden.


    Beispielskript:

    Das Skript macht folgendes:

    1. Fülle A mit Zufallszahlen

    2. Suche ein Zufälliges Element aus A heraus, speichere dessen Wert und Addiere eine kleine Zufallszahl

    3. Berechne Abweichung(A * B, C)

    4. Schaue ob die Abweichung kleiner geworden ist:

    wenn ja -> Weiter zuSchritt 2.

    wenn nein -> Mache die Änderung des Elements rückgängig und dann weiter zu Schritt 2.

    5. Ist die Abweichung kleiner als irgendein Epsilon -> Höre auf

    6. Wird die Abweichung nie kleiner als ein Epsilon > 0, dann gibt es keine exakte Lösung. In dem Fall wird "eine" Approximation der Lösung generiert (die aber bei kleinen Matrizen meistens Müll ist, bei großen ist sie aber ziemlich gut).


    So das wars von mir. Wenn jemand Ideen, Skripte oder anderweitiges hat um A * B = C nach A aufzulösen, her damit!


    Edit: 12.2.19:

    Teile Des Systems sind unabhängig lösbar. Also es reicht eigentlich ein u * B = v zu lösen, wobei u,v = Vektoren sind.

    Dabei treten die Fälle auf:

    1. Es gibt mehr Gleichungen als Variablen -> Best Match gesucht (also ein u finden, sodass v möglichst gut quadratisch approximiert wird), hier gibt es ggf. ein Verfahren von Gauß (wie für alles in der Welt) in das ich mich noch einlesen muss.

    2. Es gibt gleich viele Gleichungen wie Variablen -> Trivial (Andys Gleichungssystemlöser freut sich)

    3. Es gibt mehr Variablen als Gleichungen -> "Durchschnittslösung" gesucht (für kleine Systeme habe ich hier eine Lösung, z.B. a + b = 1, die "Durchschnittslösung" ist hier a = b = 0.5. Da man hier immer Variablen paarweise gleichsetzt hat man aber eine Fakultät in der Anzahl Terme die man berechnen muss, für z.B. 20 variablen und 10 Gleichungen wären das 20!/10 = 2.4e17 Terme, was schon nicht mehr praktikabel ist...)



    lg

    M

    Wenn es nicht allzu genau sein muss und die Zahlen wirklich exorbitant groß werden (millionen von Stellen groß) kannst du sie auch in der Form a * 10^b speichern (wobei a und b jeweils float64 sind). Dann müsstest du dir die Rechenarten (Add, Sub, Mul, Div, usw) zwar selbst basteln, aber das ist ziemlich einfach. Dabei verliert man natürlich die Genauigkeit, wenn man z.B. 10^500 - 10^10 rechnet wird sich da nicht viel ändern. Addition und Subtraktion funktionieren bis zu einem Unterschied von ca. 10 Kommastellen, Multiplikation und Division funktionieren immer.

    Das geht hier auch nicht. Intern wird DllCallbackRegister genutzt um an Pointer für die Funktionen zu kommen die das Objekt dann verinnerlicht. Leider ist diese Funktion nicht ByRef Kompatibel und in der AutoIt-Hilfe/bzw. dem großen Internet steht auch kein Lösungsansatz.


    Man kann zwar via 'int*' eine Dllstruct ByRef verteilen (in dem Fall wird einfach der Pointer übergeben), AutoIt-Variablen scheinen aber AutoIt-Typisch eine Temporäre Struct zu bekommen deren Inhalt nach einer Neuzuweisung ignoriert wird.


    Villeicht übersehe ich auch irgendwas. Hier mein Beispielskript:

    (Man kann das Verhalten mit Structs nachbilden, da ist ByRef kein Problem, aber ich schätze mal das weißt du und das ist nicht was du suchst)

    Edit: Falls jemand DllStructCallbackRegister mit Byref hinbekommt kann ich das in die UDF einbauen.

    Außerdem habe ich einen Bug gefunden: Man MUSS Objektvariablen deklarieren (also mindestens eine) weil die UDF sonst abstürzt. Das schaue ich mir später nochmal an. Als Fix einfach Var('int abc') reinschreiben, dann geht alles.


    Edit2: Die UDF von ProgAndy & Friends baut auf einer mitgelieferten DLL auf und hat nichts mit dieser UDF hier zu tun (die ohne alles auskommt). Die Gundidee ist im Prinzip die selbe, nur die Methode wie man es in AutoIt wrappt ist unterschiedlich.


    M

    Was bedeutet in diesem Kontext "ByRef". Also was genau soll ByRef übergeben werden können? Wenn du ein Objekt selbst meinst (also eine Funktion die als Parameter byref ein Objekt bekommt) kann ich mal herumprobieren.

    Edit: Da der Kern der UDF genau der selbe ist wie vorher gebe ich aber davon aus dass das Vorhaben nicht klappt.

    Man muss auch in Objekten $a = ObjP(xyz) und dann $a.method aufrufen, weil Autoit scheinbar die referenz killt sobald der Wert von etwas zurückgegeben wurde ohne zu beachten dass er ggf. noch weiterverwendet wird. Das könnte man natürlich damit umgehen, dass man das Objekt zwar ByRef übergibt, aber eine referenz irgendwo seperat abspeichert. Das prüfe ich aber heute nicht mehr.

    Und direkt ein Doppelpost. Die UDF ist nun fertig. Habt Spaß damit.

    "fertig" bedeutet, dass ich davon ausgehe, dass die UDF im Kern ab jetzt Abwärtskompatibel bleibt. Skripte die heute Laufen sollten auch Morgen noch gehen.


    (Fehlermeldungen und Verbesserungsvorschläge sind gern gesehen)


    lg

    M

    Ohne nähere Informationen wie es zu dem Problem kommt wird dir niemand helfen können. Die Fehlermeldung besagt nur, dass "irgendwas" nicht stimmt (und das das Problem nicht nur eine einmalige Fehlfunktion war, sondern durch eine gewisse Situation hervorgerufen wird die unverändert bleibt). Bei mir stürzte der Helper ebenfalls ab wenn Skripte sich gegenseitig includen (siehe vorheriger Post von mir). Falls es das nicht ist musst du versuchen ein Minimalbeispiel bei dem der Fehler auftritt zu erstellen, das komplette ISN-Projekt in eine zip packen und hier posten.


    M