Rekursionsproblem

Wie rufe ich R-Funktionen auf, wie selektiere ich Daten, ich weiß nicht genau ....

Moderatoren: EDi, jogo

Antworten
produnis
Beiträge: 3
Registriert: Di Mär 23, 2021 10:41 am

Rekursionsproblem

Beitrag von produnis »

Hallo liebes Forum.
Ich habe ein "Problem" mit Rekursionsgleichungen.

Ich habe eine Datenreihe von 0 bis 1700, mit denen ich das durchspielen möchte.

Code: Alles auswählen

x <- seq(0,1700, by=1)
rekursion <- function(x){
  if(x==1){
    return(0.002)
  } 
  else {
    
    return(
      rekursion(x-1) * (1 + (0.004/(1+( (x-2)*0.004 )) ) ) +0.002
    )
  }
  
}
Wenn ich die Funktion mit einer(!) Zahl aufrufe, erhalte ich das erwartete Ergebnis

Code: Alles auswählen

rekursion(3)
[1] 0.006023968


Wenn ich die Funktion mit einer hohen Zahl aufrufe, erhalte ich einen Fehler

Code: Alles auswählen

rekursion(800)
Fehler: C stack usage  7975172 is too close to the limit

Ich verstehe, dass der Fehler bedeutet, dass die Rekursion "zu tief" geht.

Da ich Linux benutze, beende ich RStudio und gebe ins Terminal ein:

Code: Alles auswählen

ulimit -s 16384
und starte RStudio neu.

Jetzt kann ich die Formel bis zur Zahl 1473 aufrufen

Code: Alles auswählen

> rekursion(1473)
[1] 6.654057
Danach kommt wieder der Fehler.

Also baue ich die Funktion etwas um, mit bekannten Ergebnissen, damit er nicht so tief runter muss

Code: Alles auswählen

rekursion <- function(x){
  if(x==1){
    return(0.002)
  } 
  if(x==1000){
    return(4.024376)
  }
  if(x==1400){
    return(6.229157)
  }
  else {
    
    return(
      rekursion(x-1) * (1 + (0.004/(1+( (x-2)*0.004 )) ) ) +0.002
    )
  }
  
}
Jetzt klappt es mit den Zahlen von 0 -1700, genau das, was ich brauche.

Jetzt mein "Problem":

Ich brauche einen neuen Vektor, welcher die Funktionsergebnisse für 0 bis 1700 enthält.

Rufe ich die Funktion mit meiner Datensequenz vom Anfang auf, bekomme ich wieder den Fehler:

Code: Alles auswählen

> x <- seq(0,1700, by=1)
> rekursion(x)
Fehler: C stack usage  15948500 is too close to the limit
Auch "while" funktioniert nicht und gibt die selbe Fehlermeldung aus...

Selbst bei kleinem Zahlenvektor raucht er ab

Code: Alles auswählen

> x <- c(0,1,2,3)
> rekursion(x)
Fehler: C stack usage  15948500 is too close to the limit
Wenn ich die Zahlen "einzeln" durchgebe, dann geht es. Der super dirty-ugly hack ist, mittels "cat" folgende Befehlsreihenfolge zu erzeugen:

Code: Alles auswählen

y <- 0.002
y <- c(y, mikrekursion( 2 ))
y <- c(y, mikrekursion( 3 ))
y <- c(y, mikrekursion( 4 ))
y <- c(y, mikrekursion( 5 ))
y <- c(y, mikrekursion( 6 ))
y <- c(y, mikrekursion( 7 ))
y <- c(y, mikrekursion( 8 ))
y <- c(y, mikrekursion( 9 ))

(...)

y <- c(y, mikrekursion( 1698 ))
y <- c(y, mikrekursion( 1699 ))
y <- c(y, mikrekursion( 1700 ))
und diese dann zu "sourcen".

Somit habe ich in y alles, was ich wollte.

Meine Frage ist, wie man das denn nun "richtig" macht?
Benutzeravatar
EDi
Beiträge: 1599
Registriert: Sa Okt 08, 2016 3:39 pm

Re: Rekursionsproblem

Beitrag von EDi »

Zunächst mal:

Code: Alles auswählen

> x <- seq(0,1700, by=1)
> rekursion(x)
Deine Funktion is nicht vektorisiert und wenn du ihr einen Vektor übergibts kommt folgende Warnung:

Code: Alles auswählen

Warning message:
In if (x == 1) { :
  the condition has length > 1 and only the first element will be used
Desweiteren ist x = 0 problematisch, wo soll da die funktion aussteigen? Geht ja immer weiter Richtung minus unendlich.

Ersteres kann man über vapply oder Vektorize lösen:

Code: Alles auswählen

x <- seq(1,10, by=1)
vapply(x, rekursion, FUN.VALUE = numeric(1))
vrekursion <- Vectorize(rekursion)
vrekursion(x)
für zweiteres muss man die Logik nochmal überdenken...
Bitte immer ein reproduzierbares Minimalbeispiel angeben. Meinungen gehören mir und geben nicht die meines Brötchengebers wieder.

Dieser Beitrag ist lizensiert unter einer CC BY 4.0 Lizenz
Bild.
Antworten