2015-05-21 5 views
15

Eine R-Funktion wird mir übergeben, die in einem Intervall der Real Line definiert ist und einen numerischen Wert zurückgibt. Gibt es eine Möglichkeit zu überprüfen, ob die Funktion konstant ist?Wie überprüft man, ob eine Funktion in R eine konstante Funktion ist?

Beispiel Funktionen:

f1<-function(x) {11} 
f2<-function(x) {x+2} 
f3<-function(x) {1+1} 
f4<-function(x) {return(3)} 

ich für einen Test suchen, die diesen f1, f3, f4 sind konstante Funktionen aber f2 sagen will, ist es nicht. Irgendwelche Ideen?

Edit:

Frank und Gregor (edit: und Michael Lawrence zweite Lösung) Lösungen unter allen Arbeiten für alle vier Testfälle gegeben oben (Marats und Michaels funktionieren nicht auf allen 4 Fällen). Es gibt also schon Lösungen. Aber zusätzliche Bonuspunkte, wenn Sie eine Lösung finden, die auch die richtige Antwort für die folgenden drei Testfunktionen gibt:

f5 <- function(x) ifelse(x == 5.46512616432116, 0, 1) 
f6 <- function(x) ifelse(x == 5.46512616432116, 0, 0) 
f7 <- function(x) {x - x} 
+4

Das Beste, was Sie tun können, ist eine Reihe von Werten versuchen. Viel Glück beim Abfangen meiner Funktion 'f3 = Funktion (x) ifelse (x == 5.46512616432116, 0, 1)'. – Gregor

+0

Nicht sicher, ob es programmatisch für beliebige Funktionen möglich ist. Aber wenn Sie den Zusammenhang erkennen können, wäre vielleicht jemand in der Lage, eine Lösung vorzuschlagen. –

+0

Ja genau Gregor, ich würde gerne solche Funktionen abfangen können. Deshalb habe ich gehofft, eine programmatische Lösung zu haben, die genau eine Reihe von Werten nicht testet. Weil R die Funktion kennt, ist die Information theoretisch dort ... –

Antwort

5

Diese Funktion testet, ob das Argument der f verwendet wird als Zahl:

is_using_argasnumber <- function(f) 
    grepl("non-numeric argument",try(f("Hello World!"),silent=TRUE)) 

Beispiele:

is_using_argasnumber(function(x)1+1)  # FALSE 
is_using_argasnumber(function(x)"guffaw") # FALSE 
is_using_argasnumber(function(x)sqrt(x+2)) # TRUE 

Wenn Sie, ob eine mathematische Funktion konstant testen müssen, werden Sie spezielle Werkzeuge benötigen, die verstehen und Formeln vereinfachen kann.


Allgemein.

  • Es macht keinen Sinn für Funktionen mit mehreren Argumenten.
  • Wenn eine andere Lokalisierung von R verwendet, ...
    • Ich würde vorschlagen, zu ersetzen oder zur Ergänzung der Regex, zum Beispiel mit "(non-numeric argument)|(argument non numérique)". Leider, soweit ich das beurteilen kann, verwendet R keine "Fehlercodes", die eine sprachinvariante Interpretation eines try Ergebnisses ermöglichen würden.
    • Eine Alternative vom OP vorgeschlagen würde einfach überprüft werden, ob gab es jeden Fehler, aber ich denke, dass zu viele Fehlalarme erzeugen würde, wenn die Funktionen eine Chance bugginess hatte erprobt:

.

is_breaking_withargascharacter <- function(f) 
    inherits(try(f("Hello World!"),silent=TRUE),'try-error') 
+0

Danke! Das ist gut, aber es funktioniert nur, wenn Ihre Systemsprache Englisch ist;) –

+0

Zum Beispiel bekomme ich: versuchen Sie (f2 ("Hallo Welt!")) Fehler in x + 2: Argument nicht nummerieren für den operating binaire –

+0

Es wäre besser, wenn die Lösung modifiziert wurde, um einfach einen Fehler zu finden. –

11

Versuchen functionBody:

> is.numeric(functionBody(f1)[[2]]) 
[1] TRUE 

> is.numeric(functionBody(f2)[[2]]) 
[1] FALSE 
+0

Danke !! Es ist nicht narrensicher, zum Beispiel f4 = Funktion (x) ifelse (x == 5.46512616432116, 0, 0) kommt als nicht konstant, obwohl es ist. Aber es ist nahe genug. –

+3

@bisounours_tronconneuse - denn das ist technisch ein Funktionsaufruf, und keine Konstante. Es hängt von einer anderen Variablen ab :) –

+0

Ein ernsteres Problem mit dieser Methode ist, dass die folgende Funktion als nicht konstant gegeben wird: f5 <-Funktion (x) {Rückkehr (3)} –

5

Diese Code-basierten Tests sind klug und macht Spaß zu sehen, aber so weit ich denke, die „versuchen, eine Reihe von Zahlen“ -Ansatz einen leistungsfähigeren Test sein kann, von der Art der Funktionen ab, die Sie möglicherweise erhalten und ob Ihnen die Typ-I- oder Typ-II-Fehler bei der Identifizierung wichtiger sind.

In Ihrer Frage, sagen Sie

which is defined on some interval of the Real Line

Lassen Sie uns also gehen wir davon aus, die Domäne von Interesse kennen. Probieren Sie einige Punkte in dieser Domain aus und testen Sie Ihre Funktion.

n = 1e5 
test = runif(n, min = 0, max = 5) 
results = f(test) # sapply(test, f) if f isn't vectorized 

# test for constancy 
all(results == results[1]) # or all(diff(results) == 0) or however else 

Jede Funktion, die wirklich eine konstante Funktion ist wird gut diesen Test bestehen, egal wie pathologisch --- dies nicht wahr sein, für alle anderen Methoden bisher vorgeschlagen. Es ist jedoch ganz einfach, den Test mit dem Beispiel zu täuschen ich in den Kommentaren nach links (oder irgendetwas dieser Art)

f3 = function(x) ifelse(x == 5.46512616432116, 0, 1) 
+1

I Bin mir immer noch nicht sicher, ob das OP nach dem Funktion-Eigenschaften- oder Mathe-Eigenschaften-Test gesucht hat, aber ich mag diese Lösung zu letzterem, zumindest in Form von "Wie kann ich testen, ob meine reellwertige Funktion aus einem kompakten ist Teilmenge der Reals ist konstant? " – Frank

+2

Und, wenn die Funktionen nicht irgendwie "zufällig" erzeugt werden, wäre es leicht, auch "spezielle" Werte zu überprüfen, 0 wenn es in der Domäne enthalten ist, vielleicht die Werte in 'pretty (mydomain)' überprüfend. – Gregor

3

Wenn Sie behaupten, dass die Funktion ihr „MathWorld“ Gegenstück ist die Antwort auf die Frage ist rekursiv unentscheidbar.

5

Diese Griffe Fällen wie explizite return, fehlende { und sogar leer { }:

evaluatesToConstant <- function(b) { 
    if (is(b, "{")) { 
     if (length(b) > 2L) 
      return(FALSE) 
     if (length(b) == 1L) 
      last <- NULL 
     else last <- b[[2L]] 
    } else { 
     last <- b 
    } 
    if (is.call(last) && last[[1L]] == quote(return)) { 
     last <- last[[2L]] 
    } 
    !is.language(last) 
} 
evaluatesToConstant(functionBody(fun)) 

Hier ist ein weiterer Ansatz, der ziemlich klug ist, aber es kann dazu verleitet werden. Es wird angenommen, dass jede primitive Funktion bei konstanten Argumenten den gleichen Wert zurückgibt. Es erlaubt auch Symbole, solange die Symbole innerhalb der Funktion definiert sind. Da jedoch auf Symbole verwiesen werden kann, bevor sie definiert oder aber in einem verschachtelten Bereich definiert werden, ist diese Heuristik nicht sicher. Wie auch immer, hier ist es:

evaluatesToConstant <- function(expr, allowDefinitions=FALSE) { 
    vars <- all.vars(expr) 
    calls <- setdiff(all.names(expr), vars) 
    funs <- mget(calls, parent.frame(), mode="function", inherits=TRUE) 
    defined <- if (allowDefinitions) 
        rapply(as.list(expr), 
          function(x) as.character(substitute(x)[[2L]]), "<-", 
          how="unlist") 
    length(setdiff(vars, defined)) == 0L && 
     all(vapply(funs, is.primitive, logical(1L))) 
} 

TRUE werden soll:

evaluatesToConstant(functionBody(function(x) { foo <- 1 + 1; foo }), TRUE) 
+0

Ich habe deine Funktion versucht, aber es schlägt für f2 in der Frage fehl. Es gibt wahr, während es falsch sein sollte ... > evaluatesToConstant (f2) [1] TRUE > f2 funktion (x) {x + 2} –

+0

sorry. mein Schlechter, mir war nicht klar, dass ich eventsToConstant (functionBody (fun)) tun sollte und nicht einfach evaluateToConstant. –

+0

Leider funktioniert es nicht auf f3 <- function (x) {1 + 1} –

Verwandte Themen