Квантовые Вычисления В Играх, Или Серьезно Сходим С Ума

Если ты живешь среди сумасшедших, тебе придется самому научиться быть сумасшедшим.

Вы когда-нибудь пробовали «научиться быть сумасшедшим»? Нетривиальная проблема.

Даже нормального метода не найдешь, потому что каждый сходит с ума по-своему.

Моя первая попытка: теория заговора.

Теория не предполагает практики, а значит, вам не придется усердно работать.

Опять же, в любом случае никто не пострадает. Как создавать теории заговора? Создать теорию заговора относительно легко.

Нам нужна идея, которая будет достаточно простой, чтобы ее могли принять 90% населения.

Оно должно быть спорным, чтобы 5% населения могли объяснить 90%, какие они идиоты.

Наконец, нам нужно какое-то исследование, которое эти 95% людей не понимают, но которое используется 90% как аргумент «люди умнее нас доказали…».

Квантовые вычисления — отличная область для таких исследований.

Вы можете набросать простую диаграмму, но слово «квант» придаст вес результатам.

Объектом исследования является игра, поскольку объект должен быть простым и знакомым подросткам.

Кто занимается квантовыми вычислениями и играми? Google. Итак, еретическая теория: через 5 лет Пейдж и Грин будут решать, кто будет руководить Google, и сделают это через игру.

В каждом из них есть группа исследователей.

Команда AlphaGo своими боевыми нейронными сетями привлекла соперников в Го.

Противники были вынуждены искать новые методы и, наконец, обнаружили инструмент тотального превосходства: квантовые вычисления.

Можно ли использовать квантовые вычисления для игр? Легко.

Покажем, например, что игру «Охотник на лис» можно «разгадать» за 6 ходов.

Для правдоподобия ограничимся 15 кубитами (онлайн-редактор причуд не эмулирует более пятнадцати); для простоты мы будем игнорировать ограничения архитектуры процессора и исправления ошибок.



Правила

Чрезвычайно просто.

В ряд расположены пять лунок (нумеруем их 0-1-2-3-4).

В одном из них сидит лиса.

Каждую ночь лиса перебирается в следующую нору слева или справа.

Каждое утро охотник может проверить одну лунку по своему выбору.

Задача охотника – поймать лису.

Задача лисы – выжить.

Теоретически лиса может вечно убегать от охотника.

На практике есть выигрышная стратегия: проверить лунки 1-2-3-1-2-3. Это единственная стратегия, которую я буду тестировать.



Построение схемы

Начнем с инициации кубитов 0-1-2-3-4 (5 дырок).

Вы можете редактировать здесь

Квантовые вычисления в играх, или серьезно сходим с ума

Фактически, после инициации мы имеем систему, в которой после измерения ровно один кубит будет единицей.

Вероятности «единицы» для каждого кубита различны, но в нашем случае это не критично.

Надо оставить место для обсуждения схемы (и заодно нашей теории).

В Q# мы получим такой код:

  
  
  
  
  
  
  
  
  
  
  
  
   

operation TestStrategy () : (Result) { let res = Zero; using(qubits=Qubit[16]) { // 0.4 - holes // 5 - current movement direction. Zero means "go down", One means "go up" // 6 - Game status. 1 means "fox is free, go further" // 7,8,9,10, 11 - movements history InitFoxHoles(qubits); ResetAll(qubits); // ALWAYS clean after yourself } return Zero; } // Inits fox holes, with almost equal probabilities operation InitFoxHoles(register: Qubit[]) : Unit { body { ResetAll(register); // Step 1 H(register[0]); H(register[2]); // Step 2 (Controlled (X))([register[0],register[2]], register[3]); // Step 3 X(register[0]); X(register[2]); (Controlled (X))([register[0],register[2]], register[3]); X(register[0]); X(register[2]); // Step 4 CNOT(register[3], register[0]); CNOT(register[3], register[2]); // Step 5 (Controlled (H))([register[3]], register[4]); // Step 6 CNOT(register[4], register[3]); } }

TestStrategy проверит нашу стратегию 1-2-3-1-2-3, InitFoxHoles() отвечает только за создание лисьих нор.

Проверим инициацию.

Давайте скопируем TestStrategy, запустим инициацию, измерим первые 5 кубитов и вернем их значения.



operation TestInit(): (Result, Result, Result, Result, Result) { body { mutable res0 = Zero; mutable res1 = Zero; mutable res2 = Zero; mutable res3 = Zero; mutable res4 = Zero; using(qubits=Qubit[16]) { // 0.4 - holes // 5 - current movement direction. Zero means "go down", One means "go up" // 6 - Game status. 1 means "fox is free, go further" // 7,8,9,10, 11 - movements history InitFoxHoles(qubits); set res0 = M(qubits[0]); set res1 = M(qubits[1]); set res2 = M(qubits[2]); set res3 = M(qubits[3]); set res4 = M(qubits[4]); ResetAll(qubits); // ALWAYS clean after yourself } return (res0, res1, res2, res3, res4); } }

Мы проведем тест тысячу раз (несколько прогонов характерны для квантовых алгоритмов, а кое-где они даже необходимы).

Код вызова под спойлером, результаты на скриншоте ниже.

Давайте быстро проверим инициацию

static void TestInitiation() { using (var sim = new QuantumSimulator()) { var initedQubitsValues = Enumerable.Range(0, 5) .

ToDictionary(qubitIndex => qubitIndex, oneMesaured => 0); for (int i = 0; i < 1000; i++) { (Result, Result, Result, Result, Result) result = TestInit.Run(sim).

Result; if (result.Item1 == Result.One) { initedQubitsValues[0]++; } if (result.Item2 == Result.One) { initedQubitsValues[1]++; } if (result.Item3 == Result.One) { initedQubitsValues[2]++; } if (result.Item4 == Result.One) { initedQubitsValues[3]++; } if (result.Item5 == Result.One) { initedQubitsValues[4]++; } } Console.WriteLine($"Qubit-0 initiations: {initedQubitsValues[0]}"); Console.WriteLine($"Qubit-1 initiations: {initedQubitsValues[1]}"); Console.WriteLine($"Qubit-2 initiations: {initedQubitsValues[2]}"); Console.WriteLine($"Qubit-3 initiations: {initedQubitsValues[3]}"); Console.WriteLine($"Qubit-4 initiations: {initedQubitsValues[4]}"); } }



Квантовые вычисления в играх, или серьезно сходим с ума

Что-то пошло не так.

Ожидалось почти равномерное распределение.

Причина проста: на шаге 3 я инвертировал третий кубит вместо первого: (Controlled (X))([register[0],register[2]], Register[3]); старый плохой копипаст. Исправляем код и запускаем тест: Исправлено инициирование

// Inits fox holes, with almost equal probabilities operation InitFoxHoles(register: Qubit[]) : Unit { body { ResetAll(register); // Step 1 H(register[0]); H(register[2]); // Step 2 (Controlled (X))([register[0],register[2]], register[3]); // Step 3 X(register[0]); X(register[2]); (Controlled (X))([register[0],register[2]], register[1]); X(register[0]); X(register[2]); // Step 4 CNOT(register[3], register[0]); CNOT(register[3], register[2]); // Step 5 (Controlled (H))([register[3]], register[4]); // Step 6 CNOT(register[4], register[3]); } } }



Квантовые вычисления в играх, или серьезно сходим с ума

Уже лучше.

Код можно найти в репе, версия Зафиксировать 1 .



Куда бежать лисе?

Выделим пятый кубит (нумерация начинается сверху) для текущего направления движения лисы.

Договоримся, что ноль означает движение вниз, единица – движение вверх.

Очевидно, что если лиса уже находится в нулевой норе, она должна двигаться вниз.

Если лиса находится в четвертой норе, она движется вверх.

В остальных случаях лисица может двигаться как вниз, так и вверх.

Используя эти простые правила, вы можете установить «кубит текущего направления» на 0, 1 или суперпозицию нуля и единицы.

Смотрим код в репозитории, Коммит 2 .



Квантовые вычисления в играх, или серьезно сходим с ума

Схема в редакторе.

Код и тест

// Select next Fox movement direction, updating qubit 5 // 1 means go up (4 -> 3, 3 -> 2, .

1 -> 0) // 0 means go down (0 -> 1, 1 -> 2, .

3 -> 4) operation SetupMovementDirection(qubits: Qubit[]) : Unit { body { // Step 1 CNOT(qubits[4], qubits[5]); // Step 2 (Controlled (H))([qubits[3]], qubits[5]); // Step 3 (Controlled (H))([qubits[2]], qubits[5]); // Step 4 (Controlled (H))([qubits[1]], qubits[5]); } } operation TestMovementDirectionSetup(): (Result, Result, Result, Result, Result, Result) { body { mutable res0 = Zero; mutable res1 = Zero; mutable res2 = Zero; mutable res3 = Zero; mutable res4 = Zero; mutable res5 = Zero; using(qubits=Qubit[16]) { InitFoxHoles(qubits); SetupMovementDirection(qubits); set res0 = M(qubits[0]); set res1 = M(qubits[1]); set res2 = M(qubits[2]); set res3 = M(qubits[3]); set res4 = M(qubits[4]); set res5 = M(qubits[5]); ResetAll(qubits); // ALWAYS clean after yourself } return (res0, res1, res2, res3, res4, res5); } }



static void TestMovementDirectionSetup() { using (var sim = new QuantumSimulator()) { List<string> results = new List<string>(); string initedCubit = null; string moveDirection = null; for (int i = 0; i < 1000; i++) { (Result, Result, Result, Result, Result, Result) result = Quantum.FoxHunter.TestMovementDirectionSetup.Run(sim).

Result; if (result.Item1 == Result.One) { initedCubit = "0"; } if (result.Item2 == Result.One) { initedCubit = "1"; } if (result.Item3 == Result.One) { initedCubit = "2"; } if (result.Item4 == Result.One) { initedCubit = "3"; } if (result.Item5 == Result.One) { initedCubit = "4"; } if (result.Item6 == Result.One) { moveDirection = "1"; } else { moveDirection = "0"; } results.Add($"{initedCubit}{moveDirection}"); } foreach(var group in results .

GroupBy(result => result) .

OrderBy(group => group.Key)) { Console.WriteLine($"{group.Key} was measured {group.Count()} times"); } Console.WriteLine($"\r\nTotal measures: {results.Count()}"); } }



Квантовые вычисления в играх, или серьезно сходим с ума



Движение

Реализовано посредством управляемого SWAP. Если управляющий кубит один, мы меняем местами вниз.

Если управляющий кубит обнулён, мы меняем местами.



Квантовые вычисления в играх, или серьезно сходим с ума

Схема в редакторе .

оператор Q#

// Makes a movement based on the 5'th qubit value // 1 means go up (4 -> 3, 3 -> 2, .

1 -> 0) // 0 means go down (0 -> 1, 1 -> 2, .

3 -> 4) operation MakeMovement(qubits: Qubit[]) : Unit { body { // Code movement Up // Step 1 mutable qubitsToSwap = [qubits[0], qubits[1]]; (Controlled(SwapReverseRegister))([qubits[5]],qubitsToSwap); // Step 2 set qubitsToSwap = [qubits[1], qubits[2]]; (Controlled(SwapReverseRegister))([qubits[5]],qubitsToSwap); // Step 3 set qubitsToSwap = [qubits[2], qubits[3]]; (Controlled(SwapReverseRegister))([qubits[5]],qubitsToSwap); // Step 4 set qubitsToSwap = [qubits[3], qubits[4]]; (Controlled(SwapReverseRegister))([qubits[5]],qubitsToSwap); // COde movement down X(qubits[5]); // Invert direction qubit for the ZeroControlled operations // Step 5 set qubitsToSwap = [qubits[3], qubits[4]]; (Controlled(SwapReverseRegister))([qubits[5]],qubitsToSwap); // Step 6 set qubitsToSwap = [qubits[2], qubits[3]]; (Controlled(SwapReverseRegister))([qubits[5]],qubitsToSwap); // Step 7 set qubitsToSwap = [qubits[1], qubits[2]]; (Controlled(SwapReverseRegister))([qubits[5]],qubitsToSwap); // Step 8 set qubitsToSwap = [qubits[0], qubits[1]]; (Controlled(SwapReverseRegister))([qubits[5]],qubitsToSwap); X(qubits[5]); // Back-invert for the direction qubit } }

Вопрос#: оператор для тестов

operation TestFirstMovement(): (Result, Result, Result, Result, Result, Result) { body { mutable res0 = Zero; mutable res1 = Zero; mutable res2 = Zero; mutable res3 = Zero; mutable res4 = Zero; mutable res5 = Zero; using(qubits=Qubit[16]) { InitFoxHoles(qubits); SetupMovementDirection(qubits); MakeMovement(qubits); set res0 = M(qubits[0]); set res1 = M(qubits[1]); set res2 = M(qubits[2]); set res3 = M(qubits[3]); set res4 = M(qubits[4]); set res5 = M(qubits[5]); ResetAll(qubits); // ALWAYS clean after yourself } return (res0, res1, res2, res3, res4, res5); } }

код С#

static void TestFirstMove() { using (var sim = new QuantumSimulator()) { List<string> results = new List<string>(); string initedCubit = null; string moveDirection = null; for (int i = 0; i < 1000; i++) { (Result, Result, Result, Result, Result, Result) result = Quantum.FoxHunter.TestFirstMovement.Run(sim).

Result; if (result.Item1 == Result.One) { initedCubit = "0"; } if (result.Item2 == Result.One) { initedCubit = "1"; } if (result.Item3 == Result.One) { initedCubit = "2"; } if (result.Item4 == Result.One) { initedCubit = "3"; } if (result.Item5 == Result.One) { initedCubit = "4"; } if (result.Item6 == Result.One) { moveDirection = "1"; } else { moveDirection = "0"; } results.Add($"{initedCubit}{moveDirection}"); } // Holes measurements foreach (var group in results .

GroupBy(result => result[0]) .

OrderBy(group => group.Key)) { Console.WriteLine($"{group.Key} hole was measured {group.Count()} times"); } // Directions measuremetns foreach (var group in results .

GroupBy(result => result[1]) .

OrderBy(group => group.Key)) { Console.WriteLine($"{group.Key} direction was measured {group.Count()} times"); } Console.WriteLine($"\r\nTotal measures: {results.Count()}"); } }

Код можно посмотреть в Коммит 3 .



Делаем 6 ходов

Наконец, мы выделяем шестой кубит для статуса игры (лиса свободна/лиса не свободна).

Один соответствует свободной лисе.

Дальнейшие ходы мы будем делать только с одним статусным кубитом.

Кубиты 7,8,9,10,11 будут хранить историю ходов.

После каждого хода мы будем сопоставлять один из них с кубитом текущего направления (это позволит нам хранить историю ходов и сбрасывать кубит текущего направления перед каждым ходом).



Квантовые вычисления в играх, или серьезно сходим с ума

Схема прилагается .

Q# оператор

/// Make 6 movements. Every movement is controlled by the 6'th qubit. /// After the every qubit we check if the fox has been captured and invert the 6'th qubit /// Reminder: 6'th qubit equal to One means "Fox is free, go further" operation MakeSixMovements(qubits: Qubit[]) : Unit { body { // Move 1 (Controlled(SetupMovementDirection))([qubits[6]],(qubits)); (Controlled(MakeMovement))([qubits[6]],(qubits)); CNOT(qubits[1], qubits[6]); // Reverse Fox State if it's shot // Move 2 SwapReverseRegister([qubits[5], qubits[7]]); // Move the first move direction to the qubit 7, qubit 5 is Zero again (Controlled(SetupMovementDirection))([qubits[6]],(qubits)); (Controlled(MakeMovement))([qubits[6]],(qubits)); CNOT(qubits[2], qubits[6]); // Move 3 SwapReverseRegister([qubits[5], qubits[8]]); (Controlled(SetupMovementDirection))([qubits[6]],(qubits)); (Controlled(MakeMovement))([qubits[6]],(qubits)); CNOT(qubits[3], qubits[6]); // Move 4 SwapReverseRegister([qubits[5], qubits[9]]); (Controlled(SetupMovementDirection))([qubits[6]],(qubits)); (Controlled(MakeMovement))([qubits[6]],(qubits)); CNOT(qubits[1], qubits[6]); // Move 5 SwapReverseRegister([qubits[5], qubits[10]]); (Controlled(SetupMovementDirection))([qubits[6]],(qubits)); (Controlled(MakeMovement))([qubits[6]],(qubits)); CNOT(qubits[2], qubits[6]); // Move 6 SwapReverseRegister([qubits[5], qubits[11]]); (Controlled(SetupMovementDirection))([qubits[6]],(qubits)); (Controlled(MakeMovement))([qubits[6]],(qubits)); CNOT(qubits[3], qubits[6]); } }

Q#: оператор для тестов

operation TestSixMovements(): (Result) { body { mutable res = Zero; using(qubits=Qubit[16]) { ResetAll(qubits); InitFoxHoles(qubits); X(qubits[6]); // At the beginning of the game our fox is alive MakeSixMovements(qubits); set res = M(qubits[6]); ResetAll(qubits); // ALWAYS clean after yourself } return (res); } }

С#: тестирование

static void TestMovements() { using (var sim = new QuantumSimulator()) { int zerosCount = 0; for (int i = 0; i < 1000; i++) { Result result = Quantum.FoxHunter.TestSixMovements.Run(sim).

Result; if(result == Result.Zero) { zerosCount++; } } Console.WriteLine($"\r\nTotal zeroes: {zerosCount}"); } }

Давайте посмотрим Коммит 4 .



Последние штрихи

У нас ошибка в схеме.

Поскольку мы тестируем стратегию 1-2-3-1-2-3, то каждую лунку мы тестируем дважды.

Соответственно, поймав лису на первом ходу, мы пройдем статусный кубит дважды (на первом ходу и четвертом).

Чтобы избежать такой ситуации, мы используем кубит 12 для фиксации статуса после ходов 4-5-6. Кроме того, мы добавим определение победы: если хотя бы один из статусных кубитов обращается в ноль, мы победили.



Квантовые вычисления в играх, или серьезно сходим с ума

Итоговая схема .

Q#: исправить движения оператора 6

operation MakeSixMovements(qubits: Qubit[]) : Unit { body { // Move 1 (Controlled(SetupMovementDirection))([qubits[6]],(qubits)); (Controlled(MakeMovement))([qubits[6]],(qubits)); CNOT(qubits[1], qubits[6]); // Reverse Fox State if it's shot // Move 2 SwapReverseRegister([qubits[5], qubits[7]]); // Move the first move direction to the qubit 7, qubit 5 is Zero again (Controlled(SetupMovementDirection))([qubits[6]],(qubits)); (Controlled(MakeMovement))([qubits[6]],(qubits)); CNOT(qubits[2], qubits[6]); // Move 3 SwapReverseRegister([qubits[5], qubits[8]]); (Controlled(SetupMovementDirection))([qubits[6]],(qubits)); (Controlled(MakeMovement))([qubits[6]],(qubits)); CNOT(qubits[3], qubits[6]); // Move 4 SwapReverseRegister([qubits[5], qubits[9]]); (Controlled(SetupMovementDirection))([qubits[6], qubits[12]],(qubits)); (Controlled(MakeMovement))([qubits[6], qubits[12

Теги: #Квантовые технологии #Разработка игр #Логические игры #.

NET #будущее близко #Q #безумие #far Cry 3 #квантовые схемы

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.