2017-01-27 7 views
1

Как назначить переменную string или integer черепахе, используя вероятности переменных в группе/списке? Например, вероятность того, что одна конкретная переменная используется из конкретной группы/списка, равна 0,4. Функция случайным образом выбирает переменную, основанную на вероятности. Мне нужно использовать тот же метод впоследствии, чтобы выбрать переменную (строку) из списка в зависимости от вероятности. В питоне должно быть:Netlogo: Назначить переменную с использованием вероятностей

import random 
def random_value(probability_list, values): 
    r = random.random() 
    index = 0 
    while(r >= 0 and index < len(probability_list)): 
     r -= probability_list[index] 
     index += 1 
    value=values[index - 1] 
    value_index=index-1 
    return value,value_index 

Я попробовал его в NetLogo, как показано ниже (получить сообщение об ошибке, что индекс -1), но есть лучший способ?

globals [random_nr probabilities some_list index] 
to initialize-variables 
    set some_list[] 
    set probabilities[] 
end 
to random_pick 
    set random_nr random-float 1 
    set probabilities [0.1 0.2 0.4 0.3] 
    set some_list ["String1" "String2" "String3" "String4"] 
    set index 0 
    while [(random_nr >= 0) and (length probabilities < index)] [ 
    set random_nr random_nr - item index probabilities 
    set index index + 1 ] 
    set index index - 1 
end 
+0

Некоторые общие рекомендации: если вы оказываетесь в беспорядке с индексами и циклами, вы, вероятно, ошибаетесь; есть почти всегда лучший, более NetLogo-ish, путь. –

ответ

2

есть лучший способ?

Да, есть.

NetLogo 6.0 поставляется с комплектом rnd extension. (Вы можете также download the extension separately для более ранних версий NetLogo.)

Расширение rnd предлагает rnd:weighted-one-of-list примитив, который делает именно то, что вы пытаетесь сделать:

extensions [ rnd ] 

to-report pick 
    let probabilities [0.1 0.2 0.4 0.3] 
    let some_list ["String1" "String2" "String3" "String4"] 
    report first rnd:weighted-one-of-list (map list some_list probabilities) last 
end 

Позвольте мне распаковать последнее выражение немного :

  • роль (map list some_list probabilities) является «молнии» два списка вместе для того, чтобы получить список пар вида: [["String1" 0.1] ["String2" 0.2] ["String3" 0.4] ["String4" 0.3]].

  • Этот список пар передается как первый аргумент rnd:weighted-one-of-list. Мы передаем last в качестве второго аргумента rnd:weighted-one-of-list, чтобы сказать, что он должен использовать второй элемент каждой пары в качестве вероятности.

  • rnd:weighted-one-of-list затем выбирает одну из пар случайным образом и возвращает эту целую пару. Но поскольку нас интересует только первый элемент пары, мы используем first, чтобы извлечь его.

Чтобы понять, как работает этот код, он помогает понять, как работает Anonymous procedures. Обратите внимание, как мы используем краткий синтаксис для прохождения list до map и для прохождения last до rnd:weighted-one-of-list.

1

Не упускать из вида rnd расширения: https://github.com/NetLogo/Rnd-Extension Но можно сделать это по существу, как вы предлагаете. Я буду здесь, но лучше использовать явные аргументы.

to-report random-pick 
    let _r random-float 1 
    let _ps [0.1 0.2 0.4 0.3] 
    let _lst ["String1" "String2" "String3" "String4"] 
    let _i 0 
    while [_r >= item _i _ps] [ 
    set _r (_r - item _i _ps) 
    set _i (_i + 1) ] 
    report item _i _lst 
end