J o: Berechnung/Logik

Guten Morgen,

Ich stehe vor einem Problem und sehe sprichwörtlich den Wald vor lauter bäumen nicht mehr. Also ich bewege mich gedanklich in einer Schleife und komme auch durch Umformulierung des Problems und runter brechen auf die kleinsten Einheiten nicht mehr auf einen Lösungsansatz.

Gegeben sei ein Startvektor:

s=[1,2,3,4,5,6,7,8,9]

Auf diesen soll der zeilenvektor aus z.B dieser Matrix

0|0|0|0|0|0|0|-5b|b=b0e^f(dt,x) 2|1|0|3|0|0|0|-4|0 0|-2|-2.5|0|2|7|0|-1|0 -5|0|0|0|0|0|5|-2|0 -1|0|-1|0|0|0|0|5|0 0|0|0|0|0|0|-b*g(dt,x)|0|0

addiert werden um so auf einen Lösungsvektor zu kommen.

Bisher iteriere ich erst spaltenweise und dann zeilenweise über die Martrix und addiere auf den Startvektor.

Mein erstes Problem ist, dass falls der Startvektor, während der Iteration an einer Stelle kleiner Null wird, ändern sich die Werte in der Zeile der Matrix um das Verhältnis der Differenz zu Null und dem Eintrag in der Matrix, was noch nicht das Problem ist. Also zum Beispiel, wenn in der Iteration über den nullten Spaltenvektor, an Index 3 der Startvektor den Wert an Index 0, -2 annimmt, soll sich in der gleichen Zeile der Matrix an Index 6 die 5 zu einer 3 ändern.
Bei negativen Einträgen in einer Spalte, beeinflussen diese jede Zahl in der betreffenden Zeile, wenn die Summe erst in einer späteren Iteration kleiner Null wird. Also zum Beispiel der Spaltenvektor Index 2, wo der Startvektor 2 erst beim 5ten Iterationsschritt -0.5 wird, müssen sich alle Zahlen in Zeile 3 und 5 ändern, nur an diesem Punkt kann ich ja nicht mehr über die vorherigen Spalten- bzw. Zeilenvektoren Iterieren ( hier sollte sich die -2 an Index [1][2] zu -1 ändern also -2 * 0.5/1 ).

Hätte vielleicht jemand eine Idee wie ich eine Randbedingung formulieren könnte bzw generell vorgehen könnte?

Das Zweite, was aus dieser Randbedingung resultiert, ist die nicht Linearität, womit ich mich aber bisher noch nicht genau beschäftigt habe, da ich jetzt schon weiß, das die mathematische Formulierung nicht gerade trivial wird.

Gruß
Jo

  1. Hallo Jo,

    Gegeben sei ein Startvektor:

    Auf diesen soll der zeilenvektor aus z.B dieser Matrix

    addiert werden um so auf einen Lösungsvektor zu kommen.

    auf welchen der sechs Zeilenvektoren? Wo kommen die Werte für die Variablen (b, b0, ...) her?

    Bisher iteriere ich erst spaltenweise und dann zeilenweise über die Martrix und addiere auf den Startvektor.

    Warum iterierst du?

    Kannst du mal eine Musterrechnung mit einem 3er Vektor und einer 3x2 Matrix zeigen?

    Gruß
    Jürgen

    1. Hey,

      Gegeben sei ein Startvektor:

      Auf diesen soll der zeilenvektor aus z.B dieser Matrix

      addiert werden um so auf einen Lösungsvektor zu kommen.

      auf welchen der sechs Zeilenvektoren? Wo kommen die Werte für die Variablen (b, b0, ...) her?

      Tut mir Leid, dass ist mir nicht aufgefallen, alle Zeilenvektoren sollen zum Startvektor addiert werden.

      Bisher iteriere ich erst spaltenweise und dann zeilenweise über die Martrix und addiere auf den Startvektor.

      Warum iterierst du?

      Weil ich das für eine 24x14 Matrix nicht einzeln formulieren/rechnen möchte.

      Kannst du mal eine Musterrechnung mit einem 3er Vektor und einer 3x2 Matrix zeigen?

      Mit oder ohne eintreten der Randbedingung?

      Gruß
      Jo

    2. Hey,

      Kannst du mal eine Musterrechnung mit einem 3er Vektor und einer 3x2 Matrix zeigen?

      Fall 1 ohne eintreten der Randbedingung, (trivialer Fall):

      var s = [5,9,3];
      var M = [[1,-2,0],[0,2,-4],[-1,-1,0]]; //Spaltenvektoren in einem Array
      
      // Rechnungenschritte:
      
      s[0] = 5 + 1 -2 + 0; // s[0] + M[0][i]
      s[1] = 9 + 0 + 2 - 4; // s[1] + M[1][i]
      s[2] = 3 - 1 - 1 + 0; // s[2] + M[2][i]
      
      // Ergebnis
      s = [4,7,1];
      

      Fall 2 mit eintreten der Randbedingung, (trivialer Fall):

      var s = [1,9,3];
      var M = [[1,-4,0],[0,2,-4],[-1,-1,0]]; //Spaltenvektoren in einem Array
      
      // Rechnungenschritte:
      
      s[0] = 1 + 1 -4 + 0; // < 0 Randbedingung
      
      // M neu aus 2tem Zeilenvektor * 0.5:
      M = [[1,-2,0],[0,1,-4],[-1,-0.5,0]];
      
      s[0] = 1 + 1 -2 + 0;
      s[1] = 9 + 0 + 1 - 4;
      s[2] = 3 - 1 - 0.5 + 0;
      
      // Ergebnis
      s = [0,7,1.5];
      

      Fall 3 mit eintreten der Randbedingung in mehreren Iterationsschritten, (Kopfrauchen):

      var s = [1,9,3];
      var M = [[1,-4,-2],[0,2,-4],[-1,-1,0]]; //Spaltenvektoren in einem Array
      
      // Iterationsschritt 1:
      
      s[0] = 1 + 1;
      
      // Iterationsschritt 2:
      
      s[0] = 2 - 4;  // < 0 Randbedingung
      
      // M neu aus 2tem Zeilenvektor * 0.5:
      Mneu = [[1,-2,-2],[0,1,-4],[-1,-0.5,0]];
      
      // Iterationsschritt 3:
      
      s[0] = 0 - 2;  // < 0 Randbedingung
      
      // Zurück zu Iterationsschritt 2 ??
      
      // M neu: M[1] und M[2] mal 1/3
      // Gleichmäßiges verkleinerungs Verhältnis zwischen den Zeilenvektoren, folgt aus dem Mittelwert der Subtrahenden ( 4+2 = 6, 6/2 = 3 ), oder? Ich bin mir gerade selbst nicht sicher.
      Mneu = [[1,-1.33,-0.66],[0,0.33,-1.33],[-1,-0.33,0]];
      
      s[0] = 1 + 1 - 1.33 - 0.66;
      s[1] = 9 + 0 + 0.33 - 1.33;
      s[2] = 3 - 1 - 0.33 + 0;
      
      // Ergebnis
      s = [0,8,1.66];
      

      Und wenn dieser Fall nun irgendwo auftritt, müsste ich in beiden Iterationen Schritte zurück gehen.

      Gruß
      Jo

      1. Hallo Jo,

        also erst einmal habe ich das Gefühl, du verwendest den Begriff Iteration sowohl für Schleifendurchläufe, als auch für wiederholte Berechnungen.

        Und dann habe ich noch nicht verstanden, was bei welcher Randbedingung gemacht werden soll. Du berechnest den ersten Summanden und wenn dieser negativ ist, halbierst du die zweite Spalte, und dann?

        Gruß
        Jürgen

        1. Hey,

          also erst einmal habe ich das Gefühl, du verwendest den Begriff Iteration sowohl für Schleifendurchläufe, als auch für wiederholte Berechnungen.

          Ähm, ja? Ein Schleifendurchlauf entspricht einer Berechnung.

          Und dann habe ich noch nicht verstanden, was bei welcher Randbedingung gemacht werden soll. Du berechnest den ersten Summanden und wenn dieser negativ ist, halbierst du die zweite Spalte, und dann?

          Es gibt nur eine Randbedingung, das der Startvektor[i] nicht kleiner 0 werden darf, dann muss die entsprechende Zeile mit einer Zahl dividiert werden, sodass der Startvektor 0 wird.

          Gruß
          Jo

          1. Hallo Jo,

            Du formulierst deine Randbedingung simpler als sie ist. Du hast ja vorgerechnet, dass du bei zweimaligem unterschreiten der 0 zwei Zeilenvektoren in balancierter Form anpasst. Muss auch sein, sonst würdest du nach der ersten Anpassung alle weiteren Zeilen auf 0 setzen müssen, die zur Unterschreitung führen.

            Aber warum passt du jedes mal Einzeln an? Aus welchem Grund bleibt Zeile 1 unverändert, wenn Zeile 2 zum Unterlauf führt? Die Frage mag blöd sein, ich kenne den Hintergrund deiner Rechnung nicht. Worauf ich hinaus will, ist: kannst du nicht erstmal den Spaltenvektor aufsummieren, dann prüfen ob die Addition zum Element des Eingangsvektors negativ würde, und dann bei Bedarf die ganze Matrix skalieren?

            Was du dann machst wenn es in der zweiten Spalte zum Unterlauf kommt, hängt von deiner Gesamtlogik ab. Eventuell bestimmst du Spalte für Spalte den erforderlichen Skalierungsfaktor, OHNE DEN EINGANGSVEKTOR ZU ÄNDERN, und skalierst mit dem höchsten.

            Keine Ahnung ob das für dich passt...

            Rolf

            --
            sumpsi - posui - clusi
            1. Hey,

              Du formulierst deine Randbedingung simpler als sie ist. Du hast ja vorgerechnet, dass du bei zweimaligem unterschreiten der 0 zwei Zeilenvektoren in balancierter Form anpasst. Muss auch sein, sonst würdest du nach der ersten Anpassung alle weiteren Zeilen auf 0 setzen müssen, die zur Unterschreitung führen.

              Richtig, dass ist der erste Punkt wo ich hänge.

              Aber warum passt du jedes mal Einzeln an? Aus welchem Grund bleibt Zeile 1 unverändert, wenn Zeile 2 zum Unterlauf führt? Die Frage mag blöd sein, ich kenne den Hintergrund deiner Rechnung nicht. Worauf ich hinaus will, ist: kannst du nicht erstmal den Spaltenvektor aufsummieren, dann prüfen ob die Addition zum Element des Eingangsvektors negativ würde, und dann bei Bedarf die ganze Matrix skalieren?

              Gibt keine blöden Fragen! Ich finde aber auch kein passendes Beispiel um den Hintergrund zu verdeutlichen. Aber nur Zeilenvektoren die einen Negative Wert besitzen sollen skaliert werden.

              Was du dann machst wenn es in der zweiten Spalte zum Unterlauf kommt, hängt von deiner Gesamtlogik ab. Eventuell bestimmst du Spalte für Spalte den erforderlichen Skalierungsfaktor, OHNE DEN EINGANGSVEKTOR ZU ÄNDERN, und skalierst mit dem höchsten.

              Absolut richtig, dass hatte ich jedenfalls vor. Ich bin nur noch nicht dahintergekommen wie ich das am geschicktesten umsetze, vor allem weil die Abhängigkeiten mich immer wieder durcheinander bringen.

              Gruß
              Jo

          2. Hallo Jo,

            Es gibt nur eine Randbedingung, das der Startvektor[i] nicht kleiner 0 werden darf, dann muss die entsprechende Zeile mit einer Zahl dividiert werden, sodass der Startvektor 0 wird.

            ok. dann must du doch nur den Summenvektor berechnen, prüfen, bei Bedarf die Matrix ändern, neu rechnen, prüfen ... bis alle Summanden positiv sind.

            Ich würde die beiden geschachteteln for-Schleifen in eine while-Schleife legen. In der inneren for-Schleife wird gerechnet, geprüft und für jedes Element im Summenvektor ein Flag nichtok[i]=summe[i]<0; gesetzt. Für jedes gesetzte Flag wird korrigiert und die while-Schleife wird fortgesetzt. Erst wenn alle Flags nicht gesetzt sind, ist die Rechnung fertig.

            Gruß
            Jürgen

            1. Hallo Jo,

              Es gibt nur eine Randbedingung, das der Startvektor[i] nicht kleiner 0 werden darf, dann muss die entsprechende Zeile mit einer Zahl dividiert werden, sodass der Startvektor 0 wird.

              ok. dann must du doch nur den Summenvektor berechnen, prüfen, bei Bedarf die Matrix ändern, neu rechnen, prüfen ... bis alle Summanden positiv sind.

              Die Vorzeichen bleiben alle erhalten.

              Ich würde die beiden geschachteteln for-Schleifen in eine while-Schleife legen. In der inneren for-Schleife wird gerechnet, geprüft und für jedes Element im Summenvektor ein Flag nichtok[i]=summe[i]<0; gesetzt. Für jedes gesetzte Flag wird korrigiert und die while-Schleife wird fortgesetzt. Erst wenn alle Flags nicht gesetzt sind, ist die Rechnung fertig.

              Klingt als hättest du einen gedanklichen roten Faden, dem ich leider gerade nicht ganz folgen kann.

              Gruß
              Jo

              1. Hallo Jo,

                Die Vorzeichen bleiben alle erhalten.

                ich dachte, die Rechnung kann auch negative Summen ergeben, und dann soll korrigiert werden durch Multiplikation der entsprechenden Matrixelemente mit einer Zahl < 1, z.B. 0.5.

                Gruß
                Jürgen

                1. Hallo Jo,

                  Die Vorzeichen bleiben alle erhalten.

                  ich dachte, die Rechnung kann auch negative Summen ergeben, und dann soll korrigiert werden durch Multiplikation der entsprechenden Matrixelemente mit einer Zahl < 1, z.B. 0.5.

                  Ja, die Vorzeichen in der Matrix bleiben alle erhalten, wenn man mit Zahlen 0 < x <= 1 multipliziert. Das hat ja nichts mit dem Ergebnis der Summe zutun welche ja gerade auch nicht Negativ werden darf. Oder verstehe ich dich gerade falsch?

                  Gruß
                  Jo

                  1. Hallo Jo,

                    Ja, die Vorzeichen in der Matrix bleiben alle erhalten, wenn man mit Zahlen 0 < x <= 1 multipliziert. Das hat ja nichts mit dem Ergebnis der Summe zutun welche ja gerade auch nicht Negativ werden darf. Oder verstehe ich dich gerade falsch?

                    OK, dann mal eine Idee in Pseudocode, wie das gehen könnte.

                    Gegeben: Ein Startvektor s mit Elementen s[i] und eine Matrix M[i][j]

                    for(i) {   // über Spalten von M bzw Elemente von s
                      do {
                        sum = s[i]
                        for(j) // über Zeilen von M
                          sum += M[i][j]
                        nichtok = sum<0   // prüfen, ob negativ
                        if(nichtok)       // korrigieren
                          for(j) // über Zeilen von M
                            M[i][j] *= 0.5   // oder mit anderem Faktor verkleinern
                      } while(nichtok)
                    }
                    

                    Dabei bin ich davon ausgegangen, dass sich die einzelnen Summen unabhängig von einander berechnen lassen.

                    Gruß
                    Jürgen

                    1. Hey,

                      OK, dann mal eine Idee in Pseudocode, wie das gehen könnte.

                      Gegeben: Ein Startvektor s mit Elementen s[i] und eine Matrix M[i][j]

                      Ich spiele mal etwas:

                      for(i) {   										// über Spalten von M bzw Elemente von s
                        while(!nichtok) {
                         	sum = s[i]
                         	for(j){ 									// über Zeilen von M
                            sum += M[i][j]
                      			nichtok = sum<0   			// prüfen, ob Summe negativ
                          	if(!nichtok)       			// korrigieren
                      				if(M[i][j]<0)					// prüfen ob Wert negativ
                            		for(i){ 						// über Spalten von M
                      						f = l = 0
                      						for(j){
                      							if(M[i][j]<0)
                      								f += M[i][j]
                      								l++
                      						}
                              		M[i][j] *= l/f  	// Zeile im Verhältnis verkleinern  	
                      					}
                      			}
                      		}
                        }
                      }
                      

                      Moment... ich bin schon wieder raus.

                      Nochmal ganz langsam Schritt für Schritt Formulieren.

                      1. Die Summe der Spalte und dem Vektorelement soll positiv sein.
                      2. Nur Zeilen in der Matrix die Negative Werte enthalten sollen skaliert werden, falls die Summe kleiner 0 wird, sodass die Summe 0 ergibt.
                      3. Falls 2 Werte in der Spalte negativ sind sollen diese abhängig von einander skaliert werden, ebenfalls wenn die Summe kleiner 0 wird, sodass die Summe 0 ergibt

                      Soll heißen, ich versuche mich morgen weiter. Danke erstmal für die Axt, hoffe ich finde morgen die Kettensäge.

                      Gruß
                      Jo

                      1. Hallo Jo,

                        5 Schleifen ineinander, grusel...

                        Bevor du Pseudocode raushaust, sollte man vielleicht noch etwas konzeptionell denken. Was ist denn in dem Fall, dass beim Summieren ein negativer Zwischenwert auftritt, die Endsumme der Spalte aber positiv ist? Musst Du dann auch skalieren?

                        Also z.B. s[0] = 2, M[0] = [ 1, -4, 2 ]. Es gibt nach Addition von -4 die Zwischensumme -1, aber am Ende bist Du auf 1.

                        Rolf

                        --
                        sumpsi - posui - clusi
                        1. Hallo Jo,

                          5 Schleifen ineinander, grusel...

                          Bevor du Pseudocode raushaust, sollte man vielleicht noch etwas konzeptionell denken. Was ist denn in dem Fall, dass beim Summieren ein negativer Zwischenwert auftritt, die Endsumme der Spalte aber positiv ist? Musst Du dann auch skalieren?

                          Also z.B. s[0] = 2, M[0] = [ 1, -4, 2 ]. Es gibt nach Addition von -4 die Zwischensumme -1, aber am Ende bist Du auf 1.

                          Interessanter Gedanke, nein, gibt sogar eine Spalte wo das passieren könnte. Danke für den Hinweis.

                          Ich bin gerade dran deine noch nicht überarbeitete Antwort in Code zu fassen, damit wird das auch berücksichtigt weil du ja vorgeschlagen hast die Spaltenwerte welche positiv und negativ sind getrennt zu betrachten.

                          Gruß
                          Jo

                          1. Hallo Jo,

                            ja, die erste Version hab ich erstmal überschrieben, weil sie von der Antwort auf meine dann gestellte Frage abhing... Ich packe sie also wieder aus:

                            Du gehst also erstmal die erste Spalte durch. Wenn die Summierung zum Unterlauf führt, willst du die Zeilenvektoren herunter skalieren, die in der betrachteten Spalte negative Werte haben. Das ist, denke ich, am einfachsten, wenn du zunächst positive und negative Werte für die ganze Spalte getrennt addierst und danach schaust, ob du skalieren musst. Wenn ja, berechne den Faktor und skaliere die betroffenen Zeilen.

                            Dann machst du das gleiche mit Spalte 2. Problem ist, dass hier andere Zeilen die negativen Werte enthalten können, d.h. wenn du jetzt skalierst, machst du dir ggf. die Summe für Spalte 1 negativ. Das ignoriere erstmal. Gehe einfach alle Spalten durch.

                            Nach dem ersten Durchgang hast du keine sichere Lösung, bist ihr aber näher gekommen. Darum wiederholst du nun den Prozess, bis du nicht mehr skalieren musstest.

                            D.h. die nichtOk schleife muss die äußerste sein, und du solltest Funktionen verwenden, um die Lesbarkeit zu verbessern.

                            while (skaliereMatrix(e, M));
                            

                            skaliereMatrix gibt true zurück wenn skaliert wurde.

                            function skaliereMatrix(Vector s, Matrix M) : bool {
                              bool skaliert = false
                              for (i) { /* alle Indexe von s bzw. M-Spalten */
                                f = berechneFaktor(s[i], M[i]);
                                if (f < 1) {
                                  skaliert = true;
                                  skaliereNegativeZeilen(i, f, M);
                                }
                              }
                              return skaliert;
                            }
                            

                            berechneFaktor macht die getrennte Addition und gibt stumpf 1 zurück, wenn nichts zu skalieren ist. Ansonsten den Skalierungsfaktor, der zwischen 0 und 1 liegen muss.

                            skaliereNegativeZeilen habe ich noch um einen Parameter i erweitert, weil diese Funktion ja wissen muss, in welcher Spalte sie nach negativen Werten schauen muss.

                            Das und skaliereNegativeZeilen zu implementieren schaffst Du bestimmt selbst, und die eigentlich Addition der Spaltenvektoren auf s kommt zum Schluss.

                            Rolf

                            --
                            sumpsi - posui - clusi
                            1. Hallo Rolf,

                              ja, die erste Version hab ich erstmal überschrieben, weil sie von der Antwort auf meine dann gestellte Frage abhing... Ich packe sie also wieder aus:

                              Du gehst also erstmal die erste Spalte durch. Wenn die Summierung zum Unterlauf führt, willst du die Zeilenvektoren herunter skalieren, die in der betrachteten Spalte negative Werte haben. Das ist, denke ich, am einfachsten, wenn du zunächst positive und negative Werte für die ganze Spalte getrennt addierst und danach schaust, ob du skalieren musst. Wenn ja, berechne den Faktor und skaliere die betroffenen Zeilen.

                              Genau, ist schon fertig.

                              Dann machst du das gleiche mit Spalte 2. Problem ist, dass hier andere Zeilen die negativen Werte enthalten können, d.h. wenn du jetzt skalierst, machst du dir ggf. die Summe für Spalte 1 negativ. Das ignoriere erstmal. Gehe einfach alle Spalten durch.

                              Muss ich ja gar nicht, da die while Schleife, wenn skaliert wurde nochmal durchläuft, um zu schauen ob alles passt.

                              skaliereNegativeZeilen habe ich noch um einen Parameter i erweitert, weil diese Funktion ja wissen muss, in welcher Spalte sie nach negativen Werten schauen muss.

                              Ist bei mir schon ein Object, da schon der im Verhältnis stehende skalierungsfaktor berechnet wird und die Zeilen auf der dieser angewendet werden soll.

                              Das und skaliereNegativeZeilen zu implementieren schaffst Du bestimmt selbst, und die eigentlich Addition der Spaltenvektoren auf s kommt zum Schluss.

                              Auch schon fertig.

                              Hier schon mal das Zwischenergebnis. Jetzt noch die Exponentielle abhängigkeit und ich bin Fertig.

                              Gruß
                              Jo