Итак, проблема, с которой я столкнулся, заключается в следующем:
В студенческой столовой студенты приходят каждые 30 секунд группами по 1, 2, 3 или 4 человека. Вероятность для 4 групп составляет 50%, 20%, 5% и 25% соответственно.
Как я могу убедиться, что мой исходный блок может достичь такого рода инъекции?
Сделайте так, чтобы блок Source использовался "при вызовах метода 'inject()'":
Теперь создайте циклическое событие (каждые 30 секунд или сколько вам нужно). В нем создайте в источнике столько агентов, сколько прописано вашими вероятностями, примерно так:
if (randomTrue(0.5)) {
mySource.inject(1);
} else if (randomTrue(0.2)) {
mySource.inject(2);
} else...
Метод Бенджамина для случайного выбора количества инъекций даст вам неправильные вероятности для размеров вашей группы. Чтобы понять, почему это так, рассмотрим вероятность получения группы из 2 с помощью метода Бенджамина.
Чтобы получить группу из 2 с помощью метода Бенджамина, первое условие if: if (randomTrue(0.5)
должно быть ложным, а второе условие: else if (randomTrue(0.2)
также должно быть истинным. Это происходит с вероятностью 0,1, что дает примерно 10% групп размером 2, а не 20%.
Я проверил это на 100 000 образцов и с помощью метода Бенджамина получил следующие результаты:
Частота размеров групп не соответствует тому, что вы хотели! Чтобы правильно назначить размеры групп, используйте вместо этого следующий метод:
double u = uniform(0,1);
if (u < 0.5)
{
mySource.inject(1);
}
else if (u < 0.7)
{
mySource.inject(2);
}
else if (u < 0.75)
{
mySource.inject(3);
}
else
{
mySource.inject(4);
}
Я провел тот же тест со 100 000 образцов, используя этот метод, и получил следующие результаты:
Выглядит намного лучше. Надеюсь, это полезно :)
Да, это решение, которое дает желаемый результат. Если это помещается в циклическое событие, я также хочу указать на это self.restart(); надо поставить в конце :)
Более чистый способ сделать это — использовать пользовательские дистрибутивы, подобные этому:
и тогда вам нужна только одна строка кода:
mySource.inject(customDistribution());
Оглядываясь назад, я вижу, что решение хорошо работает только для двух случаев (только if и else), поскольку параметр p возвращает true, а 1 - p возвращает false.