Пятница, 19.04.2024, 09:34
Мой персональный сайт Добрым людям smart & sober

Главная Регистрация Вход
Приветствую Вас, Гость · RSS
Калькулятор


Меню сайта
Календарь
«  Июнь 2012  »
ПнВтСрЧтПтСбВс
    123
45678910
11121314151617
18192021222324
252627282930


Форма входа


Архив записей
Мини-чат


Категории раздела


Наш опрос
В чем заключается ваш смысл жизни
Всего ответов: 154
 
Главная » 2012 » Июнь » 24 » Парадокс двух конвертов и стратегия Ковера (реализация на .NET)
03:41
Парадокс двух конвертов и стратегия Ковера (реализация на .NET)
Парадокс двух конвертов относится к так называемой теории принятия решений. Представим, что у нас имеются два одинаковых конверта, причем в одном денег (в рублях) в два раза больше, чем в другом. Играющему предлагается выбрать конверт и посмотреть на сумму внутри. После этого он может либо поменять конверт, либо оставить себе данную сумму денег. Существует ли способ при котором из серии множества пар конвертов можно получить максимально возможную сумму? (с учетом того, что сами конверты в каждой паре будут перемешаны в случайном порядке).



Изначально парадокс двух конвертов предстал в таком виде в 1980 году, хотя на самом деле никакого парадокса нет, все (как это часто бывает в подобных случаях) заключалось в формулировке задачи. Но меня привлекла статья на lenta.ru, а именно эти слова из нее:

В рамках исследования австралийские ученые создали стратегию, получившую название стратегии Кловера (в честь своего коллеги, который «подкинул им данную идею во время завтрака»). Ученые предлагают играющему сначала субъективно оценить количество денег, а затем на основе данной оценки вычислить вероятность обмена. При этом, чем денег кажется больше, тем меньше вероятность того, что надо выполнить обмен.


в других статьях по этой теме написано похожим образом:

Заключается она (стратегия) в следующем. Нужно менять или не менять конверты в каждом заходе случайным образом, но с вероятностью, которая зависит от суммы, увиденной в первом конверте. То есть чем меньше сумма в конверте А, тем с большей вероятностью следует сменить конверт и наоборот, несколько большая сумма в А говорит о том, что скорее следует оставить первый конверт себе.

Тогда, в 2003-м, Дерек посчитал идею своего коллеги бредом и отказался продумывать такую стратегию. И учёного можно понять: рассудите сами, увиденная сумма не говорит человеку ровным счётом ничего о намерении, условно, ведущего (который раскладывает деньги), ведь игрок не знает — в каком вообще диапазоне играет его оппонент. Может быть, от 10 центов до 100 долларов, а может, от 5 долларов до ста миллионов.


Другими словами, оказывается существует стратегия, при которой в серии из множества конвертов можно повысить свои шансы на выигрыш!

Я решил проверить эту теорию и написал программу на .NET'е. Смысла приводить код программы целиком нет, вот ссылка на github. Но хочется остановиться на некоторых моментах. В программе есть интерфейс Picker'а, т.е. механизма, который выбирает из двух конвертов один. Этот интерфейс выглядит вот так:

    public interface IPicker
    {
        int Pick(IRandomProvider randomProvider, EnvelopePair envelopePair);
    }
 


Также я реализовал два простых класса на базе этого интерфейса:

AlwaysFirstPicker — выбирает все время первый конверт
AlwaysSecondPicker — выбирает все время второй конверт

Сам конверт выглядит просто:

    public sealed class Envelope
    {
        public int Amount { get; set; }
    }
 


Пара конвертов, с которой мы собственно и имеем дело выглядит так:

    public sealed class EnvelopePair
    {
        public Envelope FirstEnvelope { get; set; }
        public Envelope SecondEnvelope { get; set; }
        //...
    }
 


В каждый конверт я положил 5 или 10 долларов. И, наконец, стратегия Ковера:

        public int Pick(IRandomProvider randomProvider, EnvelopePair envelopePair)
        {
            int randomValue = randomProvider.Next(110);
 
            /*
             * То есть чем меньше сумма в конверте А, тем с большей вероятностью следует сменить конверт и наоборот,
             * несколько большая сумма в А говорит о том, что скорее следует оставить первый конверт себе.
             */

 
            if (envelopePair.FirstEnvelope.Amount <= randomValue)
            {
                return envelopePair.SecondEnvelope.Amount;
            }
            else
            {
                return envelopePair.FirstEnvelope.Amount;
            }
        }
 


После экспериментов оказалось, что этот способ действительно работает. Вывод программы при использовании стратегии AlwaysFirst:

Your balance is: 7503495

Вывод программы при использовании стратегии AlwaysSecond:

Your balance is: 7504335

Т.е. в среднем при использовании этих стратегий мы получили вполне ожидаемый средний выигрыш в 7,5 долларов. Вывод программы при использовании стратегии Ковера:

Your balance is: 8886740 (!!!)

Как говорится, почувствуйте разницу! 8,8 доллара из 10! Забавно, что изменяя строку в стратегии Ковера результат меняется не сильно:

            int randomValue = randomProvider.Next(120);


т.е. таким образом мы выполняем вот это требование:

ведь игрок не знает — в каком вообще диапазоне играет его оппонент

Читатели могут самостоятельно стать «учеными, которые провели около 20 тысяч компьютерных симуляций», скачать программу и попробовать её в действии. Может быть найдется человек, который сможет усовершенствовать результат и показать в комментариях свой Picker.

P.S. lenta.ru почему-то назвали ученого Кловером, хотя на самом деле он Ковер.

UPD: минусаторы и «знатоки» теории вероятности в порыве своей ярости наставили минусов к комментам, конечно не разобравшись в вопросе. Утверждали, что якобы программа использует знания о диапазоне денег в конверте. Специально для них изменил пару строк в стратегии Ковера таким образом, чтобы программа не знала заранее о диапазоне. Результат, понятное дело, не изменился. Минусаторы расстроились.
+15
21 июня 2012 в 03:02
60
Gangsta 57,0

комментарии (73)

+13
qwerty787788 #
Смысла писать программу, по-моему, не было, т. к. такие же результаты вы могли получить, воспользовавшись основами теории вероятности. Главная же проблема в другом. Ваша программа (выбора решения) очень сильно опирается на то, что весь промежуток денег лежит от 1 доллара до 10, если ей давать 50 и 100 долларов, то ее результат будет ровно 75 (плюс-минус погрешность).
Если же мы хотим написать программу, которая работает «для любых входных данных», то необходимо выбрать монотонную функцию (вероятность оставить конверт при наличии в нем X долларов), которая в 0 принимает значение 0, а на бесконечности 1. Очевидно, что для любой функции мы сможем выбрать два довольно далеко располагающихся друг от друга числа, для которые вероятность будет примерно одинаковой. Т. е. мы можем предоставить входные данные, на которых алгоритм не будет давать никакого результата.
–2
Gangsta #
изменил на 50:

7755685

ровно 75 тут не пахнет) Явно прослеживается увеличение) Впрочем, вы это сами могли сделать, если бы следовали инструкциям. В диапазоне от 1 до 30 результат 7931495.

Если поменяете на 100, результат будет все равно больше, но никак не «ровно 75». Интуиция вам подсказывает обратное? Проверьте.
+3
Fury #
Вы вообще поняли, что вам сказал qwerty787788?

У вас программа использует знание о том, в каком диапазоне находятся суммы, лежащие в конверте.
От того, что вы увеличили randomProvider.Next(1, 20) до 50, вы не перестали использовать это знание :)

Попробуйте всё-таки сделать так, как вам предложили сделать — не трогать randomProvider.Next, а в EnvelopePair заменить 5 и 10 на 50 и 100, и посмотрите на результат.
–2
Gangsta #
ну а вы, скажем, знаете какое максимальное количество денег можно поместить в конверт? это тоже знание. речь идет не о сферическом коне в вакууме, а о реальных жизненных ситуациях, где мы имеем какие-либо знания.
+2
Fury #
ну а вы, скажем, знаете какое максимальное количество денег можно поместить в конверт? это тоже знание. речь идет не о сферическом коне в вакууме, а о реальных жизненных ситуациях, где мы имеем какие-либо знания.


Ок, согласен, что можно с потолка взять некую оценку сверху. Давайте, например, возьмём 1000000000.
Я не С# разработчик, так что у меня не установлен .Net, но вот не поленился найти онлайн-редактор javascript и набросать аналог вашего приложения, с учётом моей оценки суммы сверху. При этом в конверты всё так же кладётся 5 или 10.

var sum = 0;
for(var i=0; i<10000; i++) {
 var envelopA;
Просмотров: 611 | Добавил: Bliss | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Copyright MyCorp © 2024