Как да програмирате квантов компютър - Част 2

Бойни кораби с квантови измервания

IBM Research https://www.flickr.com/photos/ibm_research_zurich/33072160062/

Тази статия има „Част 2“ в заглавието по уважителна причина. Имаше част 1, в която разгледахме основата на писане и изпълнение на квантови програми.

Предполагам, че сте прочели поне първата половина от това, преди да дойдете тук.

Повечето от действителните знания за кодирането, които са ви необходими за този урок, бяха разгледани миналия път. Тази статия ще се фокусира най-вече върху някои неща, които можем да направим с тези команди.

Как да гледаме кубитите

В програмите имаме променливи. В един момент ще трябва да ги разгледаме.

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

Това е така, защото не квантовите променливи имат определени стойности. Гледайки ги просто ни казва или други части на програмата каква е стойността. Нищо за самата променлива няма да се промени.

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

Когато ги гледаме, те трябва да се откажат от цялата тази странност. Те са принудени да приемат определена стойност и след това да ни кажат каква е тази стойност. Тъй като това не е само пасивен процес, той се нуждае от внимателно обмисляне. И има нужда от име. Ние го наричаме измерване.

В тази статия ще проучим някои от свойствата на измерването. Ще го използваме и като основа на механика за игри и ще видим как точно да го програмирате на квантов компютър. В крайна сметка ще имаме нова версия на Battleships.

Картографиране на света на кубит

Преди наистина да започнем да измерваме кубитите, трябва да се опитаме да разберем света им малко повече. Най-добрият начин за визуализация на кубит е използването на сфера. Всяко възможно състояние на кубит съответства на точка на повърхността на тази сфера.

Състоянията 0 и 1 са напълно различни, напълно разединени. Те са противоположностите един на друг. Следователно те ще живеят от противоположните страни на сферата. Обикновено избираме да сложим 0 на северния полюс и 1 на южния.

Нека изберем точка, която е на еднакво разстояние между двете, някъде по екватора. Тя може да бъде навсякъде, където искате. Ще го наречем +. Защо +? Защо не?

Състоянието + има и противоположно, различно от него като 0 е от 1. Това живее от противоположната страна, която също ще бъде точка по дължината на екватора. Ще наречем това състояние -.

С точки 0, 1, + и - вече дефинирани, още две точки просят нашето внимание. Това са тези, които са на еднакво разстояние между 0 и 1, а също и на еднакво разстояние между + и -. Ще ги наречем ↻ и ↺. Защо? Защото веднъж видях човек, който не написа Кода на Да Винчи да го прави, и ми хареса.

Сега начертахме света на кубита с шест точки. Това в никакъв случай не са единствените, които някога ще използваме. Те са просто ориентирите, по които ще се ориентираме.

Измерване на кубит

Всяко измерване е просто да поискаме от кубит да избираме между две противоположни точки на сферата.

Класическият пример е за любимата ни двойка от противоположни състояния: 0 и 1. Молим кубита да избере между двете. Ако вече беше в състояние 0, ще отиде за 0. Кубит в състояние 1 също ще даде резултат 1. За всяко друго състояние резултатът ще бъде случаен, като най-вероятният вариант е най-вероятният.

На екватора, това е шанс 50/50 или в двата случая. Така че, ако държавата ни беше + или -, и след това попитаме дали е 0 или 1, тя ще трябва да избере едно или друго с еднаква вероятност.

Измерването въз основа на 0 и 1 има няколко имена. Можем да го наречем измерване 0/1, по очевидни причини. Нарича се също Z измерване на базата, поради специалната връзка, която състоянията 0 и 1 имат с операция, наречена z. Повече за тази история друг път.

Следващият най-популярен вид измерване е този за + и -. Ще нарека това измерване +/-, но може да го видите и наречено X базисно измерване. Работи по същия начин както преди, но само за + и - вместо 0 и 1. Така че, ако започнете с кубит в състояние + и направите това измерване, ще получите резултата +. Но ако започнете с 0 и зададете същия въпрос, той ще избере произволно.

Имаме и измерване за странните неща със стрелка. Това се нарича Y базисно измерване. Никой не харесва Y базисни измервания.

Малко е просто малко, дори когато е квантов

Измерването на не квантовите обекти е пасивен процес. Той ви казва какво прави обектът, но не го променя по никакъв начин. Измерването на квантовите неща е много различно. Квантовите измервания не променят само нашите знания за променливите. Те сами променят променливите.

Да предположим, че имате кубит в състояние + и след това го попитайте дали е 0 или 1. Когато ви дава случаен резултат, не е просто да ви изтрие. Не ви казва някакви глупости, защото сте задали грешен въпрос. След като ви даде резултат, той ще се придържа към него. Стойността му ще се промени, за да отрази отговора. Ако ви каже 0, то ще бъде 0 завинаги (или докато отново не се забъркате с него). Ще забрави, че някога е било +.

Това означава, че един кубит винаги може да бъде сигурен в резултата си само с едно измерване. Ако определено знае дали е 0 или 1, е напълно несигурно дали е + или - и също така е напълно несигурно дали е ↻ или ↺. Кубитът има само ограничена доза сигурност, ограничена от принципа на несигурността на Хайзенберг.

Това означава, че ние получаваме информация само от кубит. След като извлечем един бинарен резултат, всичко, което кубитът е знаел преди измерването, е забравено. Спомня си само резултата, който ни даде. И така, въпреки безкрайния брой възможни състояния на кубит, можем винаги да извлечем само един бит информация. Ето защо ние мислим за това като квантова версия на бит, а не като квантов поплавък или квантов 3 вектор и т.н.

Механикът на играта

Ще направим вариант на бойни кораби, в който ще има два типа атака: бомби и торпеда. Ще бъде необходима само една успешна атака, за да потъне кораб, но получаването на успешна атака не винаги е толкова лесно. Някои кораби имат толкова голяма защита срещу самолети, че нито една бомба никога няма да се приближи до тях. Други са страхотни в отблъскването на торпеда.

За да реализираме това на нормален компютър, бихме могли да определим две булеви променливи за всеки кораб. Единият ще ни каже дали корабът е имунизиран срещу бомби, а другият за торпеда. След това те могат да бъдат проверени по време на атаки, за да се види дали корабът потъва или не.

Ако това беше прилагането, което използваме, теоретично би било възможно корабът да е имунизиран и срещу двата типа атаки. Това би бил лош дизайн на играта, тъй като прави невъзможно един играч да спечели. Доброто прилагане би трябвало да предотврати неразрушими кораби.

Един от начините да се избегне създаването на такива кораби е с няколко прости реда код. Това всъщност не е наш стил. Вместо това ще го оправим с квантовата механика!

По-конкретно, ние ще се опитаме да изтръгнем тези два була в един кубит. Тъй като те не са напълно подходящи, ще получим интересно квантово поведение. Това ще добави интересен геймплей към играта, както и ще попречи на всеки кораб да бъде неразрушим.

Ще осъществим това, като свържем бомбена атака с измерване 0/1. Ако получим резултат 1, казваме, че корабът е потънал. За 0 правим извод, че корабът е имунизиран срещу бомбени атаки. За торпеда вместо това правим +/- измерване, като - предполагаме унищожаване и + предполагаме имунитет.

Този метод прави невъзможно корабът да бъде категорично имунизиран срещу двата типа атака. Ако разберем, че вражески кораб е имунизиран срещу бомби (т.е. състоянието му е 0), ние знаем, че трябва да бъде напълно несигурен за торпеда (резултатът от измерване +/-). Тъй като бомбената атака със сигурност ще се провали, следователно следва да атакуваме с торпеда.

Тогава може да се окаже, че торпедната атака се проваля (състоянието става + след измерването +/-). Корабът ще реши, че определено е имунизиран срещу тях и всяка следваща атака с торпеда ще се провали. Но цялата надежда не се губи. Ставайки сигурен за торпедите, той стана несигурен за бомбите. Атакирането с тях следващо (извършване на измерване 0/1) може да доведе до победа.

Ако бомбената атака не успее, се връщаме към торпеди и т.н. Най-добрата тактика е да продължавате да превключвате между двете, докато корабът най-накрая потъне.

Ще започнем корабите да не са сигурни в имунитета си към двете атаки. Това може да стане чрез инициализиране на кубита в едно от базовите състояния на Y. Да продължим за ↻. Това всъщност е състояние, което срещнахме в част 1, а именно u3 (0.5 * pi, 0,0) 0, така че вече знаем как да го направим.

Справяне с краткотрайни кубити

Внедряването на играта на квантов процесор няма да е толкова лесно, колкото може би се надяваме. Ще разгледаме всички проблеми, които ще ни пречат, и ще видим как да ги заобиколим.

Да предположим, че кораб бъде нападнат от бомба и оцелява. След това в следващия кръг се удря от торпедо.

Ако играта се стартира на нормален компютър и се симулира с помощта на нормални битове, реализирането на това би било съвсем просто. Корабът ще бъде инициализиран, когато играта започне, и след това изчакайте в паметта, докато играчът реши какво да прави с нея. След като играчът изпрати бомба, ще бъдат приложени съответните операции, за да се види дали е унищожена. Ако оцелее, чака отново до следващата атака.

Това няма да работи за нас. Кубитите не могат да седят наоколо и чакат човешки времеви диапазон. Няколко секунди са повече от достатъчно време, за да се сринат и изгорят, поне при съвременните технологии.

Алтернативата е да се стартира нов квантов процес всеки път, когато се извърши атака. Първото задание ще бъде инициализирано със състояние ↻, така че резултатите ще бъдат случайни както за измерване 0/1 (бомба атака), така и за +/- измерване (торпедна атака). След това резултатът от измерването се записва и съхранява в паметта на нормалния компютър. Когато се случи следващата атака, се създава друга работа, за да се види какво се случва. Той ще бъде инициализиран с резултата от последното измерване и така продължава.

Извършване на +/- измерване

Досега написах цял набор от думи, но нито един ред код. Нека започнем с припомняне как 0/1 измерване се реализира в QASM код.

измерете q [0] -> c [0];

Ролята на c [0] тук е важна за преразглеждане. Това е изходът на процеса на измерване. Това е нормалният бит, върху който се съхранява резултатът от измерването. За измерване 0/1 резултатът е 0 или 1.

Всичко това е доста ясно за измерване на 0/1. Но това са +/- измервания, които разглеждаме сега. Как да извлечем информацията от един от тях?

Все още ще искаме да съхраним резултата в нормален бит c [0]. Тъй като това е нормален бит, той не знае за странните състояния + и -. Той знае само нормални двоични. Следователно решаваме да отчитаме резултата + като c [0] = 0 и - като c [0] = 1. Фактът, че те ще изглеждат същите като резултатите от измерване 0/1, няма да е проблем. Както във всяка компютърна програма, ние трябва да знаем какво сме програмирали и затова трябва да знаем как да интерпретираме резултатите.

Сега знаем как да извлечем резултатите от измерване +/-. Но все още не сме разбрали как всъщност да го направим. Това е така, защото трябва да бъдем подъл в това отношение. Трябва да хакнем процеса, който прави измервания 0/1 и вместо това да го накараме да направи +/-.

Ключът към нашия хак е операция, наречена Hadamard. Прилагането на това на кубит q [0] в QASM код изглежда така.

HQ [0];

Командата, която използваме в Python за добавяне на този ред към QASM файл, наречен gridScript е

gridScript.h (Q [0])

Ефектът на Hadamard е да смени Z базисните състояния с X базисни такива и обратно. Това е въртене на сферата, което премества завоите в състояние на кубит 0 в + и + до 0. По същия начин 1 се завърта към - и обратно.

Това означава, че историята, която можем да разкажем за кубит по отношение на 0 и 1 преди Хадамард, трябва да разкажем с + и - след него. И всяка история на + и - става една от 0 и 1.

Точно от това имаме нужда. Това означава, че +/- измерване на кубит q [0] може да се извърши чрез следния QASM код.

HQ [0]; измерете q [0] -> c [0]; HQ [0];

За да разберем защо това работи, нека да разгледаме няколко примера. Кубитът q [0] ще започне току-що деклариран във всеки и така ще бъде в началната си стойност 0.

Пример нула:

измерете q [0] -> c [0];

Кубитът започва в състояние 0. Пита се дали е 0 или 1 и казва c [0] отговора. Резултатът винаги ще бъде c [0] = 0.

Пример първи:

XQ [0];
измерете q [0] -> c [0];

Кубитът започва в състояние 0 и след това се завърта на 1. След това се пита дали е 0 или 1. Той винаги отговаря на 1.

Пример +:

HQ [0];
измерете q [0] -> c [0];

Кубитът започва в състояние 0 и веднага се завърта към +. След това се пита дали състоянието му е 0 или 1. Тя произволно избира едно или друго и състоянието му се актуализира с отговора.

Сега направихме няколко тривиални примера, нека направим нещо по-сложно.

Пример ++:

HQ [0];
HQ [0]; измерете q [0] -> c [0]; HQ [0];

Кубитът започва в състояние 0 и след това се завърта към +. След това има два еквивалентни начина, по които можем да продължим историята.

Едно е да се каже, че трите крайни линии заедно правят +/- измерване. Те питат кубита дали е + или -. За + те връщат резултата c [0] = 0, а за - връщат c [0] = 1. Тъй като в този пример кубитът преминава в измерването със състояние +, той винаги се измерва като +. Следователно той излиза от измерването, все още в това състояние.

За другата история разглеждаме ефектите на линиите един по един. Вторият Хадамар отменя ефекта на първия и така върти кубита обратно в състояние 0. След това се пита дали състоянието му е 0 или 1 и така винаги отговаря на 0. По-нататък Хадамар го завърта отново на +.

И двете истории са съгласни относно наблюдаваните ефекти. Те са съгласни, че изходът c [0] винаги ще бъде 0 и те са съгласни, че състоянието на кубита в края ще бъде +. Те просто не са съгласни как се е случило. И двете интерпретации са еднакво валидни.

Ако искате някой жаргон да разгледа нещата в Уикипедия, това са примери за снимки на Шрьодингер и Хайзенберг на квантовата механика.

Пример +1:

XQ [0];
HQ [0]; измерете q [0] -> c [0]; HQ [0];

Ето още един пример, за който имаме две еквивалентни истории. Можем да кажем, че q [0] започва като 0 и след това се завърта на 1. Това след това се завърта t0 - преди да премине през измерване 0/1. Той случайно решава едно или друго, дава изхода c [0] = 0 или c [0] = 1 и съответно актуализира състоянието си. Ако реши 0, крайният Хадамар го завърти на +. В противен случай ще се получи като -.

Като алтернатива можем да кажем, че след завъртането си към 1, кубитът преминава през +/- измерване. Той избира на случаен принцип между тези две опции, като дава изход c [0] = 0 за + и c [0] = 0 за -. Състоянието се актуализира съответно, завършвайки или в състояние + или -.

Отново тези две истории са еднакво валидни и са съгласни за всички наблюдавани ефекти. Ако искаме да мислим за трите реда

HQ [0]; измерете q [0] -> c [0]; HQ [0];

като +/- измерване, ние сме свободни да го направим. Ако искаме да мислим за това като за Адамар, последвано от измерване 0/1, последвано от Хадамар, това също е добре.

Има едно важно нещо, което трябва да се отбележи, преди да продължим. В момента API на IBM не ни позволява да правим нищо на кубит, след като сме го измерили. Това не е общо правило за квантовите компютри. Обикновено бихме очаквали да успеем да запазим измерването и манипулирането на кубитите толкова дълго, колкото бихме искали. Но не можем да го направим в момента.

Това не ни създава проблеми. Тъй като кубитите не могат да седят наоколо, докато играчите правят избор, ние вече трябва напълно да пресъздадем състоянието след всеки кръг на измерване. Вторият Хадамар ефективно ще се появи в следващата работа, действайки върху превъплътената версия на държавата.

Всички други възможни измервания могат да бъдат постигнати чрез подобни хакове. Просто е необходимо предварително да направим някои операции, за да нагласим алтернативното си измерване и след това (ако API позволява) направете обратните операции веднага след това.

Справяне с грешки

Настоящата квантова технология не е перфектна. Кубитите не винаги правят това, което трябва. Ако вашият кубит е 0 и направите измерване 0/1, резултатът винаги трябва да е 0. Винаги. Но при сегашните квантови устройства има вероятност да е 1. Може би е, защото х операция се промъква, докато ние не търсихме. Може да е така, защото измерването ни лъже. Събития като тези са рядкост, но се случват.

Има два начина да се справим с грешките. Едно е да ги игнорираме. Можем да ги запишем в разказа на играта. По морето има големи бури. Те понякога водят кораб да бъде унищожен от атака, дори и да е имунизиран. Или да оцелееш при атака, която би трябвало да я унищожи.

Вторият начин за справяне с грешките е да се опитате да премахнете техните ефекти. Ако бяха налични много кубити, бихме могли да направим това с квантова корекция на грешки. За съжаление, това е още няколко години.

Вместо това ще направим малко статистика. За това се нуждаем от вероятности, които получаваме, като стартираме всяка работа многократно и виждаме колко често се появява всеки възможен резултат.

В безшумния случай всички вероятности биха били 0%, 100% или 50%. Резултатът е или невъзможен (като получаване на 1, ако състоянието е 0), определен (като получаване на +, ако състоянието е +), или напълно случаен (като получаване на 0, когато състоянието е +).

Шумът ще ги обърка малко. Когато правим измерване на 0/1 на 0, може да открием, че резултатът 0 се проявява само в 98% от времето, като 2% са вместо 1. За да коригираме това, ще направим нещо доста произволно. Ние ще решим, че нищо с по-малка от 5% вероятност никога не би трябвало да се случи. Всичко с повече от 95% вероятност би трябвало да е сигурно.

Поставяме всичко заедно

Тази статия обхваща широките удари на игровия механик за тази версия на Battleships и как да я приложим с квантов компютър. Вместо да мине през всички дебелозърнести подробности тук, ще го оставя за коментарите в действителния изходен код.

Ако има нещо, което смятате, че има нужда от повече обяснение, не се колебайте да ме уведомите.