Mit dbg debuggen


  • Mod

    Kontext!

    Du beschreibst gerade deine Symptome und Vermutungen wie für jemanden, der dein Programm in- und auswendig kennt. Hier versteht niemand, wovon du sprichst.



  • SeppJ schrieb:

    Kontext!

    Du beschreibst gerade deine Symptome und Vermutungen wie für jemanden, der dein Programm in- und auswendig kennt. Hier versteht niemand, wovon du sprichst.

    Ja, sorry - ich hatte schon lange nicht mehr gepostet, da wurde aus präziser Fragestellung seichtes Labern.

    Aber scheinbar hing es daran, dass die Zufallszahl zu klein war.

    Also ich habe eine Funktion get_uniform() , welche mit Hilfe der GSL Zufallszahlen in (0,1) erzeugt. Diese habe ich wie folgt modifiziert und jetzt klappt es.

    double random_number_generator::get_uniform()
    {
      double u = 0;
      do{ 
        u = gsl_rng_uniform(rng);
      } while( u < 0.001 || u > 0.999 );  
    
      return u;  
    }
    

    Mit Hilfe dieser Zufallszahlen möchte ich eine Gaussverteilung mit Hilfe der Box Muller Methode simulieren indem im Aufruf der Methode u und v mittels get_uniform() ausgewertet werden.

    double boxmuller(double mu, double sigma, double u, double v)
    {
      double rand_var = 0;
    
      do{ 
        rand_var = mu + sigma * sqrt(-log(u)) * cos(2*M_PI*v);
      } while ( rand_var < mu - 3 * sigma || rand_var > mu + 3 * sigma );
    
      return rand_var;
    
    }
    

    Und wenn ich die Informationen von gdb richtig deute, dann hing es daran, dass der Logarithmus in der boxmuller Methode nicht mit der kleinen (Zufalls- ) Zahl zurechtkam.

    Gruß,
    -- Klaus.


  • Mod

    Jain. Die Endlosschleife ist durchaus da, weil deine Funktion nicht mit kleinen Eingabewerten zurecht kommt (das hat übrigens nichts mit dem Logarithmus zu tun, der funktioniert tadellos). Der Grund ist jedoch, dass deine Box Muller Implementierung totaler Quatsch ist.

    Wann soll denn die Schleife jemals abbrechen? Warum ist überhaupt die Prüfung da? Wieso bekommt die Methode Zufallszahlen, anstatt einem Zufallsgenerator? Kurz: Schlechtes Design + fehlerhafte Implementierung.

    Ratschlag: Du möchtest ja anscheinend verhindern, dass deine Zufallszahlen zu groß werden. Dadurch verfälscht du aber die Gaussverteilung. Das ist sicher nicht gut für den Algorithmus, der die Zahlen benutzt. Ich rate aber einfach mal ganz frech, dass du gar keine Gaussverteilung brauchst, sondern bloß eine Verteilung mit den gleichen ersten beiden Momenten einer Gaussverteilung (-> zentraler Grenzwertsatz). Das heißt, du nimmst einfach eine entsprechend transformierte Gleichverteilung. Viel(!) performanter, viel einfacher zu implementieren, keine Designprobleme mehr, keine Probleme mehr mit Ausreißern.

    P.S.: Da du im C++-Forum mit dem Thread angefangen hast: C++ kennt bereits allerlei Zufallszahlengeneratoren und Verteilungen. Das heißt, selbst wenn eine Gleichverteilung überraschenderweise nicht passen sollte, dann brauchst du das alles nicht selber zu implementieren*. Die Standardbibliothek ist viel besser getestet und designt als das eine Einzelperson in vertretbarer Zeit schaffen könnte. Und auch in C würdest du wohl besser zu einer bewährten Numerikbibliothek greifen, z.B. GSL.

    *: Die transformierte Gleichverteilung implementierst du natürlich auch nicht selber, sondern nimmst die aus der Standardbibliothek.



  • SeppJ schrieb:

    Wann soll denn die Schleife jemals abbrechen? Warum ist überhaupt die Prüfung da? Wieso bekommt die Methode Zufallszahlen, anstatt einem Zufallsgenerator? Kurz: Schlechtes Design + fehlerhafte Implementierung.

    Meine Idee ist die Gaussverteilung zu simulieren. Da ich im Zuge der Monte Carlo (MC) Methode nur Zufallszahlen ui(0,1)u_i \in (0,1) zur Verfügung habe, führt mich die Inversionsmethode zur Box Muller Methode.
    Abstrakt gesehen ist das doch eine Funktion, welche mir für gegebenes μ\mu und σ\sigma und zwei gleichverteilten Zufallszahlen in (0,1) die Gaussverteilung simuliert.
    Was meinst du mit 'kriegt die Methode Zufallszahlen anstatt einen Zufallsgenerator' ?

    SeppJ schrieb:

    Ratschlag: Du möchtest ja anscheinend verhindern, dass deine Zufallszahlen zu groß werden. Dadurch verfälscht du aber die Gaussverteilung.

    Jain. Die Gaussverteilung ist von minus bis plus Unendlich ausgedehnt, allerdings 'reicht' das Intervall von (μ3σ,μ+3σ)(\mu - 3\sigma,\mu + 3\sigma), weil dann ca. 99% erfasst werden.
    Aus diesem Grund verwerfe ich Zufallsvariablen, die nicht in diesem Intervall liegen.

    SeppJ schrieb:

    P.S.: Da du im C++-Forum mit dem Thread angefangen hast: C++ kennt bereits allerlei Zufallszahlengeneratoren und Verteilungen. Das heißt, selbst wenn eine Gleichverteilung überraschenderweise nicht passen sollte, dann brauchst du das alles nicht selber zu implementieren*. Die Standardbibliothek ist viel besser getestet und designt als das eine Einzelperson in vertretbarer Zeit schaffen könnte. Und auch in C würdest du wohl besser zu einer bewährten Numerikbibliothek greifen, z.B. GSL.

    *: Die transformierte Gleichverteilung implementierst du natürlich auch nicht selber, sondern nimmst die aus der Standardbibliothek.

    Hä? 😕

    Ich verwende für die Erzeugung der Zufallszahlen schon die GSL. Ich habe die Klasse random_number_generator

    struct random_number_generator
    {
      random_number_generator();
      ~random_number_generator(){ gsl_rng_free(rng); }
      gsl_rng * rng;
      unsigned int get_uniform_int(unsigned int n); 
      double get_uniform(); 
    };
    

    Und dann eben für gleichverteilte Zufallszahlen in (0,1).

    double random_number_generator::get_uniform()
      5 {
      6   double u = 0;
      7   do{
      8     u = gsl_rng_uniform(rng);
      9   } while( u < 0.001 || u > 0.999 );
     10 
     11   return u;
     12 }
    

    Diese Methode hat natürlich die 'Abfrage' für oben diskutierte vermeintliche Verhalten des Logarithmus.


  • Mod

    Du machst dir die gewünschten Eigenschaften deiner Verteilungen kaputt, wenn du sie verfälscht.

    Leider gehst du nicht auf die von mir als interessant empfundenen Punkte ein. Ich weiß nicht, wie ich dir weiter helfen soll, außer dass
    1. es falsch ist.
    2. es unnötig ist, da du nachmachst, was längst hundertfach existiert.
    3. es unnötig ist, da du es wahrscheinlich gar nicht brauchst
    4. deine Vermutungen über die Fehlerursache (Logarithmus) ebenfalls falsch sind.

    Detaillierte Erklärungen habe ich oben schon gegeben.



  • Mh,

    also ich bin ja schon lange davon abgekommen das Rad neu zu erfinden und mehr anzuwenden was Leute mit viel mehr Expertise schon programmiert haben.

    Ich war überrascht zu sehen, dass z.B. die GSL eine eigene Funktion extra für die Gaussverteilung besitzt [1].

    Aber hey, dort steht z.B.

    This function uses the Box-Muller algorithm which requires two calls to the random number generator r.

    Also ich war zumindest auf dem richtigen Weg die Box Muller Methode zu verwenden! 🕶

    Dann werde ich versuchen diese Methode zu implementieren.

    Ist dies ein Beispiel dafür, dass du meintest ich solle mich mehr danach umschauen was schon vorhanden ist?

    Viele Grüße,
    -- Klaus.


  • Mod

    Ja, das meinte ich. Und wenn du dir die Methode genau anguckst, wirst du auch sehen, dass sie einen Zufallsgenerator als Argument hat, keine Zufallszahl.

    Was du dir noch unbedingt angucken solltest:
    - Zufallszahlen mit C++. Dann wirst du die fette Abhängigkeit GSL los, falls du sie nur der Zufallszahlen wegen benutzt:
    http://en.cppreference.com/w/cpp/numeric/random
    - Nochmal nachdenken, ob du wirklich gaussverteilte Zahlen brauchst. Du sprichst von Monte Carlo Verfahren, das klingt nach Simulation von physikalischen Vorgängen. Da ist es oft unangenehm, gaussverteilte Zufallszahlen zu haben, wegen der möglichen sehr großen Werte. Die Algorithmen, die ich so kenne, brauchen eigentlich nur passendes erstes und zweites Moment um (langfristig) zu funktionieren. Das kann man rechentechnisch viel günstiger haben und ohne die Ausreißer, die zu unangenehmen "Zuckungen" führen können.



  • SeppJ schrieb:

    Ja, das meinte ich. Und wenn du dir die Methode genau anguckst, wirst du auch sehen, dass sie einen Zufallsgenerator als Argument hat, keine Zufallszahl.

    Bei allem Respekt, aber der Unterschied ist doch bestenfalls die Art der Implementierung und nicht die Art wie es funktioniert. Immerhin steht dabei

    This function uses the Box-Muller algorithm which requires two calls to the random number generator r.

    Also du hast recht, dass ein Zufallsgenerator übergeben wird, aber intern werden von diesem zwei Zufallszahlen benötigt.

    Meine Variante sieht so aus:

    double boxmuller(double mu, double sigma, double u, double v)
    {
      return = mu + sigma * sqrt(-log(u)) * cos(2*M_PI*v);
    
    }
    

    Und was du meinst, würde in meinem Code z.B. so aussehen:

    double boxmuller(double mu, double sigma, random_number_generator & rng)
    {
      double u = rng.get_uniform();
      double v = rng.get_uniform();
    
      return = mu + sigma * sqrt(-log(u)) * cos(2*M_PI*v);
    }
    

    Natürlich lasse ich mich jetzt gerne überzeugen, warum es besser ist ganze Objekte zu übergeben (deine Variante), anstatt nur die Ausgaben deren (Klassen- ) Funktionen (meine Variante). 🙂

    SeppJ schrieb:

    - Nochmal nachdenken, ob du wirklich gaussverteilte Zahlen brauchst. Du sprichst von Monte Carlo Verfahren, das klingt nach Simulation von physikalischen Vorgängen. Da ist es oft unangenehm, gaussverteilte Zufallszahlen zu haben, wegen der möglichen sehr großen Werte. Die Algorithmen, die ich so kenne, brauchen eigentlich nur passendes erstes und zweites Moment um (langfristig) zu funktionieren. Das kann man rechentechnisch viel günstiger haben und ohne die Ausreißer, die zu unangenehmen "Zuckungen" führen können.

    Ich denke wir meinen dasselbe.
    Ich formuliere es mal so: Angenommen das Alter der Menschen wäre zwischen 0 und 100 Jahren gaussverteilt. Dann kann ich über die Box Muller Methode mittels zwei gleicherteilten Zufallszahlen in (0,1) das Alter als Zufallsvariable beschreiben, die gaussverteilt ist.
    Dummerweise kann das Ergebnis aber auch -3 oder 107 Jahre sein. Aus diesem Grund hatte ich die Schleife eingebaut

    double alter = 0;
    do{
      alter = <Box-Muller-Method>
    } while(alter < 0 || alter > 100);
    

    Wenn also das alter nicht in dem passenden Intervall liegt, wird eine neue Zufallsvariable erzeugt. Wenn ich das Intervall sehr groß wähle, relativ zur Standardabweichung, dann muss ich sehr selten wiederholen.
    Ich verstehe nur nicht, warum dies eine Endlosschleife sein soll! 😕

    Ich habe den Eindruck, dass du diese beschriebene Problematik genau damit beheben willst, dass du sagst Die Algorithmen, die ich so kenne, brauchen eigentlich nur passendes erstes und zweites Moment und führt mich z.B. zur Moment erzeugenden Funktion.

    Habe ich langsam verstanden was du meinst? 🙂

    Gruß,
    -- Klaus.


  • Mod

    Habe ich langsam verstanden was du meinst? 🙂

    Leider nein, daher
    Schluss mit den Hinweisen und Klartext:

    Klaus82 schrieb:

    SeppJ schrieb:

    Ja, das meinte ich. Und wenn du dir die Methode genau anguckst, wirst du auch sehen, dass sie einen Zufallsgenerator als Argument hat, keine Zufallszahl.

    Bei allem Respekt, aber der Unterschied ist doch bestenfalls die Art der Implementierung und nicht die Art wie es funktioniert. Immerhin steht dabei

    This function uses the Box-Muller algorithm which requires two calls to the random number generator r.

    Also du hast recht, dass ein Zufallsgenerator übergeben wird, aber intern werden von diesem zwei Zufallszahlen benötigt.

    Nö! Fällt dir denn nichts auf, wenn du das mit deinem eigenen Generator vergleichst? Der braucht nämlich viel mehr Zufallszahlen, wenn die Schleifenbedingung anschlägt. Bekommt er aber nicht. -> Endlosschleife.

    Wenn du dir den GSL Box-Muller anguckst, wirst du sehen, dass dieser auch nicht nur zwei Zufallszahlen braucht, sondern eine andere Variante des Box-Muller Verfahrens benutzt. Wusstest du nicht? Klar wusstest du das nicht, denn du musstest es nicht wissen und der Funktionskopf hat dieses völlig unnötige Details vor dir verborgen. Denn das braucht der Benutzer gar nicht zu wissen. Er sollte es nicht wissen. Denn jetzt können sie einfach die Implementierung ändern, der Funktionskopf sieht immer noch genau gleich aus, da völlig egal ist, wie viele Zufallszahlen intern verbraucht werden.

    Darum ist diese Variante vom Design her besser.

    SeppJ schrieb:

    - Nochmal nachdenken, ob du wirklich gaussverteilte Zahlen brauchst. Du sprichst von Monte Carlo Verfahren, das klingt nach Simulation von physikalischen Vorgängen. Da ist es oft unangenehm, gaussverteilte Zufallszahlen zu haben, wegen der möglichen sehr großen Werte. Die Algorithmen, die ich so kenne, brauchen eigentlich nur passendes erstes und zweites Moment um (langfristig) zu funktionieren. Das kann man rechentechnisch viel günstiger haben und ohne die Ausreißer, die zu unangenehmen "Zuckungen" führen können.

    Ich denke wir meinen dasselbe.

    Nein.

    Ich formuliere es mal so: Angenommen das Alter der Menschen wäre zwischen 0 und 100 Jahren gaussverteilt. Dann kann ich über die Box Muller Methode mittels zwei gleicherteilten Zufallszahlen in (0,1) das Alter als Zufallsvariable beschreiben, die gaussverteilt ist.

    Dann ist das Alter offensichtlich nicht gaussverteilt. Du samplest irgendeine andere Verteilung. Mit ganz anderen Eigenschaften. Mag sein, dass es für dich das richtige ist, ich weiß schließlich nicht, worum es geht. Ich kann dir nur sagen, mir kommt das verdächtig vor. Wenn du einen Betreuer oder ähnliches für deine Arbeit hast, würde ich dir dringend raten, diesen zu fragen, bevor du an Verteilungen rumspielst, die von einem Algorithmus vorausgesetzt werden.

    Ich habe den Eindruck, dass du diese beschriebene Problematik genau damit beheben willst, dass du sagst Die Algorithmen, die ich so kenne, brauchen eigentlich nur passendes erstes und zweites Moment und führt mich z.B. zur Moment erzeugenden Funktion.

    Ich fürchte, wir sind gar nicht auf einer Wellenlänge. Ich weiß nicht, was du überhaupt machst,du weißt nicht, wovon ich rede. Da brauchen wir bei diesem Nebenthema nicht weiter zu diskutieren. Aber es sollte bezüglich deiner Eingangsfrage nun klar sein, wieso die Endlosschleife auftritt und wieso das Design nicht so toll ist.



  • SeppJ schrieb:

    Nö! Fällt dir denn nichts auf, wenn du das mit deinem eigenen Generator vergleichst? Der braucht nämlich viel mehr Zufallszahlen, wenn die Schleifenbedingung anschlägt. Bekommt er aber nicht. -> Endlosschleife.

    Ja, eben habe ich es geschnallt. Stand echt auf dem Schlauch. Die while Bedingung bringt natürlich nichts, wenn die Zufallszahlen u und v übergeben werden, denn dann sind sie fix! D.h. die Zufallszahlen u und v müssen in jedem Durchlauf neu erzeugt werden!

    Über den Rest muss ich nachdenken. Ich verstehe noch nicht so recht die Kritik daran, dass ich Ergebnisse wegwerfe.
    Ich habe den Eindruck dir geht es darum, dass eine Methode, die aufgrund von gleichverteilten Zufallszahlen eine Verteilung simulieren soll nicht in die Verlegenheit kommen darf, dass ein Ergebnis verworfen wird. Denn sonst lässt die Methode Ergebnisse zu, die in der zu simulierenden Verteilung nicht vorkommen, ergo simuliert die Methode die Verteilung nicht eindeutig.

    Gruß,
    -- Klaus.


  • Mod

    Klaus82 schrieb:

    Über den Rest muss ich nachdenken. Ich verstehe noch nicht so recht die Kritik daran, dass ich Ergebnisse wegwerfe.
    Ich habe den Eindruck dir geht es darum, dass eine Methode, die aufgrund von gleichverteilten Zufallszahlen eine Verteilung simulieren soll nicht in die Verlegenheit kommen darf, dass ein Ergebnis verworfen wird. Denn sonst lässt die Methode Ergebnisse zu, die in der zu simulierenden Verteilung nicht vorkommen, ergo simuliert die Methode die Verteilung nicht eindeutig.

    Nein, das war nicht, was ich sagen wollte.

    Lassen wir das einfach ruhen. Ich kann dir hier nicht die Welt der Zufallszahlen erklären. Wenn du mit Momenten und Verteilungen usw. nichts anfangen kannst, dann wird es wohl auch (hoffentlich) nicht so wichtig sein für dich. Behalt im Hinterkopf, dass dir mal jemand gesagt hat, dass an der Methode etwas faul sein könnte. Wenn du dich besser auskennst, dann guckst du dir nochmal an, ob das wirklich in Ordnung ist.


Anmelden zum Antworten