Функция outer
работает не так, как вы пытаетесь ее использовать. outer
принимает два числовых аргумента X
и Y
и аргумент функции FUN
, к которому применяются первые два аргумента. Смотри ?outer
. Так что это не значит, что вообще нет объекта O
. Скорее сообщение об ошибке в
Z <- outer(A, B, O, f)
#Error in get(as.character(FUN), mode = "function", envir = envir) :
# object 'O' of mode 'function' was not found
означает, что функция O
не была найдена. На самом деле такой функции нет.
Есть также некоторые проблемы с вашим определением f
. Во-первых, он ничего не возвращает. Сохраняет результат как F
, но никогда не возвращает его. Во-вторых, даже если он вернул F
, вывод не всегда будет соответствовать вашему ограничению. Когда ваше ограничение не выполняется, оно просто выводит значение O
. Наконец, сравнение A+B+O==1
является плохим тестом, поскольку оно может не оценить TRUE
, даже если вы ожидаете его из-за точности с плавающей запятой (попробуйте запустить 3 - 2.9 == 0.1
). Оценка на основе сетки ухудшает ситуацию. Возможно, вам следует вместо этого тестировать abs(A+B+O-1) < epsilon
, если вы настаиваете на трех аргументах для f
. То есть Я бы ожидал что-то вроде:
f <- function(A, B, O){
G <- 1.129675e-06
epsilon <- 1e-3
ifelse(abs(A+B+O-1) < epsilon,
G+186*log(A*A+2*A*O)+38*log(B*B+2*B*O)+13*log(2*A*B)+284*log(O*O),
NA)
}
Тогда вы можете сделать что-то вроде:
dat <- expand.grid(A = A, B = B, O = O) # All combinations of A, B, O
dat$Z <- f(dat$A, dat$B, dat$O) # Apply function
head(dat)
# A B O Z
#1 0.00010000 1e-04 1e-04 NA
#2 0.02050408 1e-04 1e-04 NA
#3 0.04090816 1e-04 1e-04 NA
#4 0.06131224 1e-04 1e-04 NA
#5 0.08171633 1e-04 1e-04 NA
#6 0.10212041 1e-04 1e-04 NA
Но я не вижу, как вы легко изобразите Z как функцию от A и B. Вам нужно было бы установить подмножество для удаления NA, и это кажется очень расточительным в вычислительном отношении. Также обратите внимание, что any(dat$A + dat$B + dat$O == 1)
возвращает FALSE
, поэтому ваш первоначальный тест ограничения действительно всегда завершается неудачей в этой сетке.
С учетом сказанного, почему вы не определяете O
с учетом A
и B
, используя свое ограничение внутри функции?
A <- seq(0.0001, .9999,length=50)
B <- A
f <- function(A, B){
G <- 1.129675e-06
O <- 1 - A - B
out <- G+186*log(A*A+2*A*O)+38*log(B*B+2*B*O)+13*log(2*A*B)+284*log(O*O)
return(out)
}
Z <- outer(A, B, f)
#Warning messages:
#1: In log(A * A + 2 * A * O) : NaNs produced
#2: In log(B * B + 2 * B * O) : NaNs produced
Z[is.infinite(Z)] <- NA
persp(A, B, Z, theta=60, phi=30, zlim = range(Z, na.rm = TRUE))
![enter image description here](https://i.stack.imgur.com/46LmI.png)
Это выглядит правильно? Вот как persp
и outer
предназначены для использования как минимум.
Конечно, вы можете изменить f
, чтобы избежать появления предупреждающих сообщений. Просто помните, что f
необходимо векторизовать.