Оптимизация внутри цикла for не может найти функцию - PullRequest
0 голосов
/ 18 октября 2018

У меня есть функция, KozakTaper, которая возвращает диаметр ствола дерева на заданной высоте (DHT).Не существует алгебраического способа изменить исходное уравнение конусности, чтобы вернуть DHT при заданном диаметре (4 дюйма, для моих целей) ... введите R!(с использованием 3.4.3 в Windows 10)

Мой подход состоял в том, чтобы использовать цикл for для итерации вероятных значений DHT (25-100% от общей высоты дерева, HT), а затем использовать оптимизацию для выбора одного из них.который возвращает диаметр, ближайший к 4 ". Жаль, что я получаю сообщение об ошибке Error in f(arg, ...) : could not find function "f".

Вот сокращенное определение KozakTaper вместе с моей лучшей попыткой на данный момент.

KozakTaper=function(Bark,SPP,DHT,DBH,HT,Planted){
  if(Bark=='ob' & SPP=='AB'){
    a0_tap=1.0693567631
    a1_tap=0.9975021951
    a2_tap=-0.01282775
    b1_tap=0.3921013594
    b2_tap=-1.054622304
    b3_tap=0.7758393514
    b4_tap=4.1034897617
    b5_tap=0.1185960455
    b6_tap=-1.080697381
    b7_tap=0}
  else if(Bark=='ob' & SPP=='RS'){
    a0_tap=0.8758
    a1_tap=0.992
    a2_tap=0.0633
    b1_tap=0.4128
    b2_tap=-0.6877
    b3_tap=0.4413
    b4_tap=1.1818
    b5_tap=0.1131
    b6_tap=-0.4356
    b7_tap=0.1042}
  else{
    a0_tap=1.1263776728
    a1_tap=0.9485083275
    a2_tap=0.0371321602
    b1_tap=0.7662525552
    b2_tap=-0.028147685
    b3_tap=0.2334044323
    b4_tap=4.8569609081
    b5_tap=0.0753180483
    b6_tap=-0.205052535
    b7_tap=0}
  p = 1.3/HT
  z = DHT/HT
  Xi = (1 - z^(1/3))/(1 - p^(1/3))
  Qi = 1 - z^(1/3)
  y = (a0_tap * (DBH^a1_tap) * (HT^a2_tap)) * Xi^(b1_tap * z^4 + b2_tap * (exp(-DBH/HT)) +
                                                    b3_tap * Xi^0.1 + b4_tap * (1/DBH) + b5_tap * HT^Qi + b6_tap * Xi + b7_tap*Planted)
  return(y=round(y,4))}


HT <- .3048*85 #converting from english to metric (sorry, it's forestry)

for (i in c((HT*.25):(HT+1))) {
  d <- KozakTaper(Bark='ob',SPP='RS',DHT=i,DBH=2.54*19,HT=.3048*85,Planted=0)
  frame <- na.omit(d)
  optimize(f=abs(10.16-d), interval=frame, lower=1, upper=90,
           maximum = FALSE,
           tol = .Machine$double.eps^0.25)
}

В конце концовЯ хотел бы, чтобы этот код перебрал csv и вернул i для лучшего d, что потребует некоторой перестановки, но я решил, что сначала я должен заставить его работать для одного дерева.
Когда я печатаю d, я получаю несколько значений, поэтомуон выполняет итерацию через i, но его удерживают с помощью функции оптимизации.Определение frame было моей последней тактикой, потому что d возвращает один NaN в конце, но это может быть не лучший вход для interval.Я пробовал interval=c((HT*.25):(HT+1)), определяя KozakTaper в цикле for и определяя f перед оптимизацией, но я получаю ту же ошибку.

-KB

Научный сотрудник по лесному хозяйству, Аппалачский горный клуб.MS, Университет штата Мэн

** Правка с помощью дополнительного вопроса: я сейчас пытаюсь запустить этот скрипт для каждой строки CSV, «Ввод».Строка содержит значения для KozakTaper, и я назвал их так:

Input=read.csv...
Input$Opt=0
o <- optimize(f = function(x) abs(10.16 - KozakTaper(Bark='ob',
                                                     SPP='Input$Species',
                                                     DHT=x,
                                                     DBH=(2.54*Input$DBH),
                                                     HT=(.3048*Input$Ht),
                                                     Planted=0)),
              lower=Input$Ht*.25, upper=Input$Ht+1,
              maximum = FALSE,  tol = .Machine$double.eps^0.25)
Input$Opt <- o$minimum
Input$Mht <- Input$Opt/.3048. # converting back to English 

Input $ Ht и Input $ DBH являются числовыми;Вход $ Вид является фактором.Однако я получаю ошибку invalid function value in 'optimize'.Я понимаю, определяю ли я «o» или просто запускаю «оптимизировать».Как ни странно, когда я не вызываю значения из строки, а вместо этого использую код из ответа, он говорит мне object 'HT' not found.У меня ужасное чувство, что это связано с какой-то очевидной / неосторожной ошибкой с моей стороны, но я не нахожу сообщения об этой ошибке с помощью optimize.Если вы заметили, что я сделал неправильно, ваше объяснение будет оценено!

1 Ответ

0 голосов
/ 18 октября 2018

Я не эксперт по оптимизации, но я вижу три проблемы: 1) ваш вызов KozakTaper не выполняет итерацию в диапазоне, указанном вами в цикле.2) KozakTaper возвращает одно число, а не вектор.3) Вы не дали оптимизировать функцию, но выражение.

То, что происходит, это то, что вы не даете optimize что-либо для повторения.

Все, что вам нужно, это:

optimize(f = function(x) abs(10.16 - KozakTaper(Bark='ob', 
                                    SPP='RS', 
                                    DHT=x, 
                                    DBH=2.54*19, 
                                    HT=.3048*85, 
                                    Planted=0)),
           lower=HT*.25, upper=HT+1,
           maximum = FALSE,  tol = .Machine$double.eps^0.25)

$minimum
[1] 22.67713 ##Hopefully this is the right answer

$objective
[1] 0

Оптимизация теперь заменитx от lower до higher, пытаясь минимизировать разницу

...