Учебник. Изучение квантовой запутанности с помощью Q#
Этот учебник показывает, как написать программу на Q#, которая использует кубиты и измеряет их, а также демонстрирует явления суперпозиции и запутанности. Вы подготовите два кубита в определенном квантовом состоянии, узнаете, как работать с кубитами с Q# , чтобы изменить их состояние, и продемонстрировать эффекты суперпозиции и запутанности. Вы создаете Q# программу по частям, чтобы вводить состояния кубитов, операции и измерения.
Примечание
Microsoft Quantum Development Kit (классический QDK) больше не будет поддерживаться после 30 июня 2024 г. Если вы уже являетесь разработчиком QDK, мы рекомендуем перейти на новый пакет средств разработки Azure Quantum (Современный QDK), чтобы продолжить разработку квантовых решений. Дополнительные сведения см. в статье Перенос Q# кода в современный QDK.
Перед началом работы необходимо понять некоторые ключевые понятия.
- В классическом бите хранится одно двоичное значение (0 или 1), а кубит может находиться в состоянии суперпозиции двух квантовых значений (0 и 1). Каждое возможное квантовое состояние связано с амплитудой вероятности.
- Акт измерения кубита дает двоичный результат с определенной вероятностью и изменяет состояние кубита из суперпозиции.
- Несколько кубитов могут быть запутаны таким образом, что их нельзя описать независимо друг от друга. Это означает, что любые события с одним из кубитов в паре запутанных влияют и на другой кубит.
Из этого руководства вы узнаете, как выполнять следующие задачи:
- Q# Create операции для инициализации кубита в требуемом состоянии.
- создание суперпозиции для кубита;
- запутывание пары кубитов;
- Измерение кубита и наблюдение за результатами.
Совет
Если вы хотите ускорить путь квантовых вычислений, проверка код с помощью Azure Quantum, уникальной функции веб-сайта Azure Quantum. Здесь можно запускать встроенные Q# примеры или собственные Q# программы, создавать новый Q# код на основе запросов, открывать и запускать код в VS Code для Интернета одним щелчком мыши и задавать Copilot любые вопросы о квантовых вычислениях.
Предварительные требования
Чтобы запустить пример кода в Copilot для Azure Quantum, вам потребуется:
- Учетная запись электронной почты Майкрософт (MSA).
Дополнительные сведения о Copilot см. в статье Изучение Azure Quantum.
Инициализация кубита в известном состоянии
Первым делом мы определим операцию Q#, которая будет инициализировать кубит в известном состоянии. Это можно вызвать, чтобы задать для кубита классическое состояние, то есть при измерении он возвращает Zero
либо 100 % времени, либо возвращает One
100 % времени. Измерение кубита возвращает Q# тип Result
, который может иметь только значение Zero
или One
.
Откройте Copilot для Azure Quantum и скопируйте следующий код в окно редактора кода. Пока не нажимайте кнопку Выполнить ; вы запустите код далее в этом руководстве.
namespace Bell {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
}
Этот код добавляет две стандартные операции (M
и X
), которые преобразуют состояние кубита.
Операция SetQubitState
выполняет следующее.
- Принимает два параметра: тип
Result
с именемdesired
, который представляет требуемое состояние для кубита в (Zero
илиOne
), и типQubit
. - Выполняет операцию измерения
M
, которая получает состояние кубита (Zero
илиOne
) и сравнивает этот результат со значением, указанным вdesired
. - Если результат измерения не совпадает со значением для сравнения, то выполняется операция
X
, которая переворачивает состояние кубита. После этого действия вероятности полученияZero
иOne
при следующем измерении меняются местами. Таким образом,SetQubitState
всегда устанавливает целевой кубит в нужное состояние.
Написание тестовой операции для проверки состояния Bell
Теперь, чтобы продемонстрировать действие операции SetQubitState
, создайте другую операцию с именем TestBellState
. Эта операция выделит два кубита, вызовет SetQubitState
для первого кубита известное состояние, а затем измерит кубиты, чтобы увидеть результаты.
Скопируйте следующий код в окно редактора кода под операцией SetQubitState
.
operation TestBellState() : (Int, Int, Int, Int) {
mutable numOnesQ1 = 0;
mutable numOnesQ2 = 0;
let count = 1000;
let initial = One;
// allocate the qubits
use (q1, q2) = (Qubit(), Qubit());
for test in 1..count {
SetQubitState(initial, q1);
SetQubitState(Zero, q2);
// measure each qubit
let resultQ1 = M(q1);
let resultQ2 = M(q2);
// Count the number of 'Ones' returned:
if resultQ1 == One {
set numOnesQ1 += 1;
}
if resultQ2 == One {
set numOnesQ2 += 1;
}
}
// reset the qubits
SetQubitState(Zero, q1);
SetQubitState(Zero, q2);
// Display the times that |0> is returned, and times that |1> is returned
Message($"Q1 - Zeros: {count - numOnesQ1}");
Message($"Q1 - Ones: {numOnesQ1}");
Message($"Q2 - Zeros: {count - numOnesQ2}");
Message($"Q2 - Ones: {numOnesQ2}");
return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}
В коде count
переменным и initial
присваиваются значения 1000
и One
соответственно. Это действие инициализирует первый кубит в состоянии One
и измеряет каждый кубит 1000 раз.
Операция TestBellState
выполняет следующие действия.
- Задает переменные для счетчика и начального состояния кубита.
- Вызывает инструкцию
use
для инициализации двух кубитов. - Выполняет цикл
count
раз. В каждом из выполнений этого цикла выполняет следующее.- Вызывает метод
SetQubitState
, чтобы установить значениеinitial
для первого кубита. - Снова вызывает
SetQubitState
, чтобы установить состояниеZero
для второго кубита. - Использует операцию
M
для измерения каждого кубита. - Сохраняет количество измерений, в которых для каждого кубита возвращалось значение
One
.
- Вызывает метод
- После завершения цикла снова вызывает метод
SetQubitState
, чтобы сбросить кубиты до известного состояния (Zero
), чтобы другие пользователи смогли выделять кубиты в этом известном состоянии. Это поведение диктуется инструкциейuse
. - Наконец, функция используется
Message
для вывода результатов в выходные окна Copilot перед возвратом результатов.
Выполнение кода в Copilot для Azure Quantum
Прежде чем перейти к процедурам суперпозиции и запутанности, можно протестировать код до этого момента, чтобы увидеть инициализацию и измерение кубитов.
Чтобы запустить код как автономную программу, компилятор в Copilot должен знать, Q#с чего начать программу. Это делается в Q# файле путем добавления @EntryPoint()
непосредственно перед операцией, которую вы хотите выполнить первым. Например, в этом случае является операцией TestBellState
.
Примечание
@EntryPoint()
требуется только для автономных программ Q#. При запуске Q# программы в Записных книжках Jupyter Notebook или вызове Q# программы из файла узла Python это не требуется и при ее включении выдаст ошибку.
@EntryPoint()
Добавьте непосредственно перед TestBellState
операцией, и программа Q# до этого момента должна выглядеть следующим образом:
namespace Bell {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
@EntryPoint()
operation TestBellState() : (Int, Int, Int, Int) {
mutable numOnesQ1 = 0;
mutable numOnesQ2 = 0;
let count = 1000;
let initial = One;
// allocate the qubits
use (q1, q2) = (Qubit(), Qubit());
for test in 1..count {
SetQubitState(initial, q1);
SetQubitState(Zero, q2);
// measure each qubit
let resultQ1 = M(q1);
let resultQ2 = M(q2);
// Count the number of 'Ones' returned:
if resultQ1 == One {
set numOnesQ1 += 1;
}
if resultQ2 == One {
set numOnesQ2 += 1;
}
}
// reset the qubits
SetQubitState(Zero, q1);
SetQubitState(Zero, q2);
// Display the times that |0> is returned, and times that |1> is returned
Message($"Q1 - Zeros: {count - numOnesQ1}");
Message($"Q1 - Ones: {numOnesQ1}");
Message($"Q2 - Zeros: {count - numOnesQ2}");
Message($"Q2 - Ones: {numOnesQ2}");
return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}
}
Скопируйте и вставьте полный пример кода в окно Кода Copilot для Azure Quantum , задайте для слайда число снимков значение "1" и нажмите кнопку Выполнить. Результаты отображаются в гистограмме и в полях Результаты .
Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 1000
Q2 - Ones: 0
Так как вы еще не выполняли никаких операций с кубитами, они сохраняют начальные значения: первый кубит всегда возвращает One
, а второй — Zero
.
Если изменить значение initial
на Zero
и запустить программу снова, следует заметить, что первый кубит также возвращает каждый Zero
раз.
Q1 - Zeros: 1000
Q1 - Ones: 0
Q2 - Zeros: 1000
Q2 - Ones: 0
Состояние суперпозиции для кубита
В настоящее время кубиты в нашей программе находятся в классическом состоянии, то есть всегда имеют значение 1 или 0. Мы можем это утверждать, поскольку программа инициализирует кубиты в известном состоянии и вы пока не добавили никаких процессов для управления ими. Прежде чем запутать кубиты, вы поместите первый кубит в состояние суперпозиции, где измерение кубита вернет Zero
примерно 50 % времени и One
~ 50 % времени. Концептуально кубит можно рассматривать как имеющий одинаковую вероятность измерения или Zero
One
.
Чтобы помещать кубиты в состояние суперпозиции, Q# предоставляет операцию H
(операцию Адамара). X
Вспомните операцию из процедуры Инициализация кубита в известное состояние ранее, которая перевернула кубит от 0 до 1 (или наоборот); H
операция переворачивает кубит на полпути в состояние равных вероятностей Zero
или One
. При измерениях кубит в состоянии суперпозиции должен возвращать примерно равное количество результатов Zero
и One
.
Измените код в TestBellState
операции, сбросив начальное значение One
на и вставив строку для H
операции:
for test in 1..count {
use (q1, q2) = (Qubit(), Qubit());
for test in 1..count {
SetQubitState(initial, q1);
SetQubitState(Zero, q2);
H(q1); // Add the H operation after initialization and before measurement
// measure each qubit
let resultQ1 = M(q1);
let resultQ2 = M(q2);
...
Теперь при запуске программы можно увидеть результаты первого кубита в суперпозиции.
Q1 - Zeros: 523 // results will vary
Q1 - Ones: 477
Q2 - Zeros: 1000
Q2 - Ones: 0
При каждом запуске программы результаты для первого кубита будут немного разными, но всегда будет примерно 50 % значений One
и 50 % значений Zero
. При этом результаты для второго кубита всегда возвращают прежнее значение Zero
.
Q1 - Zeros: 510
Q1 - Ones: 490
Q2 - Zeros: 1000
Q2 - Ones: 0
Инициализация первого кубита в состоянии Zero
дает аналогичные результаты.
Q1 - Zeros: 504
Q1 - Ones: 496
Q2 - Zeros: 1000
Q2 - Ones: 0
Примечание
Переместив ползунок в Copilot для Azure Quantum и увеличив количество снимков, можно увидеть, как результаты суперпозиции немного изменяются по сравнению с распределением снимков.
Запутывание двух кубитов
Как упоминалось ранее, запутанные кубиты находятся в такой зависимости, что их невозможно описать независимо друг от друга. Любая операция, которая выполняется с одним из запутанных кубитов, определенным образом влияет на другой. Это позволяет вам выяснить состояние одного из этих кубитов без непосредственного измерения, зная результаты измерения состояние другого кубита. (В нашем примере используется всего два кубита, но вы можете запутать три кубита и даже больше.)
Для работы с состоянием запутанности Q# предоставляет операцию CNOT
, которая расшифровывается как Controlled-NOT (Контролируемое НЕ). В результате выполнения этой операции второй кубит инвертируется, только если первый кубит имеет значение One
.
Добавьте в программу операцию CNOT
, поместив ее сразу после операции H
. Теперь программа должна выглядеть так:
namespace Bell {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
@EntryPoint()
operation TestBellState() : (Int, Int, Int, Int) {
mutable numOnesQ1 = 0;
mutable numOnesQ2 = 0;
let count = 1000;
let initial = Zero;
// allocate the qubits
use (q1, q2) = (Qubit(), Qubit());
for test in 1..count {
SetQubitState(initial, q1);
SetQubitState(Zero, q2);
H(q1);
CNOT(q1, q2); // Add the CNOT operation after the H operation
// measure each qubit
let resultQ1 = M(q1);
let resultQ2 = M(q2);
// Count the number of 'Ones' returned:
if resultQ1 == One {
set numOnesQ1 += 1;
}
if resultQ2 == One {
set numOnesQ2 += 1;
}
}
// reset the qubits
SetQubitState(Zero, q1);
SetQubitState(Zero, q2);
// Display the times that |0> is returned, and times that |1> is returned
Message($"Q1 - Zeros: {count - numOnesQ1}");
Message($"Q1 - Ones: {numOnesQ1}");
Message($"Q2 - Zeros: {count - numOnesQ2}");
Message($"Q2 - Ones: {numOnesQ2}");
return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}
}
Теперь при запуске программы вы увидите примерно следующее:
Q1 - Zeros: 502 // results will vary
Q1 - Ones: 498
Q2 - Zeros: 502
Q2 - Ones: 498
Обратите внимание, что статистика для первого кубита не изменилась (по-прежнему существует вероятность около 50/50 после Zero
One
измерения), но результаты измерения для второго кубита всегда совпадают с измерением первого кубита, независимо от того, сколько раз вы запускаете программу. Операция CNOT
добавила запутанность кубитов, и теперь любые изменения одного из них влияют и на другой.
Предварительные требования
Чтобы разработать и запустить пример кода в локальной среде разработки, выполните следующие действия.
- Последняя версия Visual Studio Code или откройте VS Code в Интернете.
- Последняя версия расширения Пакета средств разработки Azure Quantum . Сведения об установке см. в разделе Установка современного QDK в VS Code.
Create новый Q# файл
- Откройте Visual Studio Code и выберите Файл > Новый текстовый файл, чтобы создать новый файл.
- Сохраните файл как
CreateBellStates.qs
. Этот файл будет содержать код для вашей Q# программы.
Инициализация кубита в известном состоянии
Первым делом мы определим операцию Q#, которая будет инициализировать кубит в известном состоянии. Вы можете вызвать эту операцию, чтобы установить кубит в классическое состояние, которое в 100 % случаев возвращает одно из значений Zero
или One
. Значения Zero
и One
имеют тип Q# и представляют единственные возможные результаты измерения кубита.
Откройте CreateBellStates.qs
и скопируйте следующий код:
namespace Bell {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
}
Этот код добавляет две стандартные операции (M
и X
), которые преобразуют состояние кубита.
Операция SetQubitState
выполняет следующее.
- Принимает два параметра: тип
Result
с именемdesired
, который представляет требуемое состояние для кубита (Zero
илиOne
), и типQubit
. - Выполняет операцию измерения
M
, которая получает состояние кубита (Zero
илиOne
) и сравнивает этот результат со значением, указанным вdesired
. - Если результат измерения не совпадает со значением для сравнения, то выполняется операция
X
, которая переворачивает состояние кубита. После этого действия вероятности полученияZero
иOne
при следующем измерении меняются местами. Таким образом,SetQubitState
всегда устанавливает целевой кубит в нужное состояние.
Написание тестовой операции для проверки состояния Bell
Теперь, чтобы продемонстрировать действие операции SetQubitState
, создайте другую операцию с именем TestBellState
. Эта операция выделит два кубита, вызовет SetQubitState
, чтобы задать для первого кубита известное состояние, а затем измерит кубиты, чтобы увидеть результаты.
Добавьте следующую операцию в файл CreateBellStates.qs
после операции SetQubitState
.
operation TestBellState() : (Int, Int, Int, Int) {
mutable numOnesQ1 = 0;
mutable numOnesQ2 = 0;
let count = 1000;
let initial = One;
// allocate the qubits
use (q1, q2) = (Qubit(), Qubit());
for test in 1..count {
SetQubitState(initial, q1);
SetQubitState(Zero, q2);
// measure each qubit
let resultQ1 = M(q1);
let resultQ2 = M(q2);
// Count the number of 'Ones' returned:
if resultQ1 == One {
set numOnesQ1 += 1;
}
if resultQ2 == One {
set numOnesQ2 += 1;
}
}
// reset the qubits
SetQubitState(Zero, q1);
SetQubitState(Zero, q2);
// Display the times that |0> is returned, and times that |1> is returned
Message($"Q1 - Zeros: {count - numOnesQ1}");
Message($"Q1 - Ones: {numOnesQ1}");
Message($"Q2 - Zeros: {count - numOnesQ2}");
Message($"Q2 - Ones: {numOnesQ2}");
return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}
В коде count
переменным и initial
присваиваются значения 1000
и One
соответственно. Это действие инициализирует первый кубит в состоянии One
и измеряет каждый кубит 1000 раз.
Операция TestBellState
выполняет следующие действия.
- Принимает два параметра, из которых
count
обозначает количество запусков измерения, аinitial
задает требуемое состояние для инициализации кубита. - Вызывает инструкцию
use
для инициализации двух кубитов. - Выполняет цикл
count
раз. В каждом из выполнений этого цикла выполняет следующее.- Вызывает метод
SetQubitState
, чтобы установить значениеinitial
для первого кубита. - Снова вызывает
SetQubitState
, чтобы установить состояниеZero
для второго кубита. - Использует операцию
M
для измерения каждого кубита. - Сохраняет количество измерений, в которых для каждого кубита возвращалось значение
One
.
- Вызывает метод
- После завершения цикла снова вызывает метод
SetQubitState
, чтобы сбросить кубиты до известного состояния (Zero
), чтобы другие пользователи смогли выделять кубиты в этом известном состоянии. Это поведение диктуется инструкциейuse
. - Наконец, использует функцию
Message
для вывода в консоль сообщения и возвращает полученные результаты.
Выполнение кода
Прежде чем переходить к процедурам для работы с суперпозицией и запутыванием, протестируйте весь описанный выше код, чтобы хорошо разобраться с инициализацией и измерениями кубитов.
Это делается в Q# файле путем добавления @EntryPoint()
непосредственно перед операцией, которую требуется выполнить. Например, в этом случае является операцией TestBellState
.
Примечание
@EntryPoint()
требуется только для автономных программ Q#. При запуске Q# программы в Записных книжках Jupyter Notebook или вызове Q# программы из хост-файла Python это не требуется и в случае включения в нее будет выдаваться ошибка.
Теперь файл
CreateBellStates.qs
должен выглядеть так:namespace Bell { open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Canon; operation SetQubitState(desired : Result, target : Qubit) : Unit { if desired != M(target) { X(target); } } @EntryPoint() operation TestBellState() : (Int, Int, Int, Int) { mutable numOnesQ1 = 0; mutable numOnesQ2 = 0; let count = 1000; let initial = One; // allocate the qubits use (q1, q2) = (Qubit(), Qubit()); for test in 1..count { SetQubitState(initial, q1); SetQubitState(Zero, q2); // measure each qubit let resultQ1 = M(q1); let resultQ2 = M(q2); // Count the number of 'Ones' returned: if resultQ1 == One { set numOnesQ1 += 1; } if resultQ2 == One { set numOnesQ2 += 1; } } // reset the qubits SetQubitState(Zero, q1); SetQubitState(Zero, q2); // Display the times that |0> is returned, and times that |1> is returned Message($"Q1 - Zeros: {count - numOnesQ1}"); Message($"Q1 - Ones: {numOnesQ1}"); Message($"Q2 - Zeros: {count - numOnesQ2}"); Message($"Q2 - Ones: {numOnesQ2}"); return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 ); } }
Перед запуском программы необходимо задать для целевого профиля значение Неограниченную. Выберите Вид —> палитра команд, найдите QIR, выберите Q#: Задайте целевой профиль Azure Quantum QIR, а затем выберите Q#: неограниченный.
Примечание
Если для целевого профиля не задано значение Неограниченная, при запуске программы появится сообщение об ошибке.
Чтобы запустить программу, выберите Запустить Q# файл в раскрывающемся списке значок воспроизведения в правом верхнем углу, щелкните Выполнить в списке команд ниже
@EntryPoint()
или нажмите клавиши CTRL+F5. Программа запускает операцию или функцию, помеченную атрибутом@EntryPoint()
в симуляторе по умолчанию.Выходные данные появятся в консоли отладки.
Q1 - Zeros: 0 Q1 - Ones: 1000 Q2 - Zeros: 1000 Q2 - Ones: 0
Так как вы еще не выполняли никаких операций с кубитами, они сохраняют начальные значения: первый кубит всегда возвращает
One
, а второй —Zero
.Если вы измените значение
initial
наZero
и снова запустите программу, следует заметить, что первый кубит также возвращаетсяZero
каждый раз.Q1 - Zeros: 1000 Q1 - Ones: 0 Q2 - Zeros: 1000 Q2 - Ones: 0
Совет
Помните, чтобы сохранить файл каждый раз, когда вы вносите изменения в код перед его повторным запуском.
Состояние суперпозиции для кубита
В настоящее время кубиты в нашей программе находятся в классическом состоянии, то есть всегда имеют значение 1 или 0. Мы можем это утверждать, поскольку программа инициализирует кубиты в известном состоянии и вы пока не добавили никаких процессов для управления ими. Прежде чем запутывать кубиты, вам нужно поместить первый кубит в состояние суперпозиции, в котором этот кубит будет возвращать значение Zero
в 50 % случаев и значение One
в остальных 50 % случаев. В теории можно рассматривать состояние кубита как промежуточное между Zero
и One
.
Чтобы помещать кубиты в состояние суперпозиции, Q# предоставляет операцию H
(операцию Адамара). Вспомните X
операцию из процедуры Инициализация кубита в известное состояние ранее, которая перевернула кубит с Zero
до One
(или наоборот); H
операция переворачивает кубит на полпути в состояние равных вероятностей Zero
или One
. При измерениях кубит в состоянии суперпозиции должен возвращать примерно равное количество результатов Zero
и One
.
Измените код в операции
TestBellState
, добавив в него операциюH
:for test in 1..count { use (q1, q2) = (Qubit(), Qubit()); for test in 1..count { SetQubitState(initial, q1); SetQubitState(Zero, q2); H(q1); // Add the H operation after initialization and before measurement // measure each qubit let resultQ1 = M(q1); let resultQ2 = M(q2); ...
Теперь при запуске программы вы можете наблюдать результаты применения суперпозиции к первому кубиту:
Q1 - Zeros: 523 // results will vary Q1 - Ones: 477 Q2 - Zeros: 1000 Q2 - Ones: 0
При каждом запуске программы результаты для первого кубита будут немного разными, но всегда будет примерно 50 % значений
One
и 50 % значенийZero
. При этом результаты для второго кубита всегда возвращают прежнее значениеZero
.Q1 - Zeros: 510 Q1 - Ones: 490 Q2 - Zeros: 1000 Q2 - Ones: 0
Инициализация первого кубита в состояние
Zero
дает аналогичные результаты.Q1 - Zeros: 504 Q1 - Ones: 496 Q2 - Zeros: 1000 Q2 - Ones: 0
Запутывание двух кубитов
Как упоминалось ранее, запутанные кубиты находятся в такой зависимости, что их невозможно описать независимо друг от друга. Любая операция, которая выполняется с одним из запутанных кубитов, определенным образом влияет на другой. Это позволяет вам выяснить состояние одного из этих кубитов без непосредственного измерения, зная результаты измерения состояние другого кубита. (В нашем примере используется всего два кубита, но вы можете запутать три кубита и даже больше.)
Для работы с состоянием запутанности Q# предоставляет операцию CNOT
, которая расшифровывается как Controlled-NOT (Контролируемое НЕ). В результате выполнения этой операции второй кубит инвертируется, только если первый кубит имеет значение One
.
Добавьте в программу операцию
CNOT
, поместив ее сразу после операцииH
. Теперь программа должна выглядеть так:namespace Bell { open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Canon; operation SetQubitState(desired : Result, target : Qubit) : Unit { if desired != M(target) { X(target); } } @EntryPoint() operation TestBellState() : (Int, Int, Int, Int) { mutable numOnesQ1 = 0; mutable numOnesQ2 = 0; let count = 1000; let initial = One; // allocate the qubits use (q1, q2) = (Qubit(), Qubit()); for test in 1..count { SetQubitState(initial, q1); SetQubitState(Zero, q2); H(q1); CNOT(q1, q2); // Add the CNOT operation after the H operation // measure each qubit let resultQ1 = M(q1); let resultQ2 = M(q2); // Count the number of 'Ones' returned: if resultQ1 == One { set numOnesQ1 += 1; } if resultQ2 == One { set numOnesQ2 += 1; } } // reset the qubits SetQubitState(Zero, q1); SetQubitState(Zero, q2); // Display the times that |0> is returned, and times that |1> is returned Message($"Q1 - Zeros: {count - numOnesQ1}"); Message($"Q1 - Ones: {numOnesQ1}"); Message($"Q2 - Zeros: {count - numOnesQ2}"); Message($"Q2 - Ones: {numOnesQ2}"); return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 ); } }
Q1 - Zeros: 502 Q1 - Ones: 498 // results will vary Q2 - Zeros: 502 Q2 - Ones: 498
Статистика значений для первого кубита не изменилась (соотношение Zero
и One
после измерения составляет 50 на 50), но при измерении второго кубита теперь всегда возвращается такое же состояние, как у первого кубита. Операция CNOT
добавила запутанность кубитов, и теперь любые изменения одного из них влияют и на другой.
Построение гистограммы частоты
Давайте визуализируем распределение результатов, полученных при выполнении квантовой программы несколько раз. Гистограмма частоты помогает визуализировать распределение вероятностей этих результатов.
Выберите Вид —> палитра команд или нажмите клавиши CTRL+SHIFT+P и введите "гистограмма", чтобы открыть Q#параметр : Запустить файл и показать гистограмму . Вы также можете щелкнуть гистограмму в списке команд ниже
@EntryPoint()
. Выберите этот параметр, чтобы открыть окно гистограммы Q# .Введите несколько снимков для выполнения программы, например 100 снимков, и нажмите клавишу ВВОД. Гистограмма отобразится в окне гистограммы Q# .
Каждая полоса в гистограмме соответствует возможному результату, а ее высота представляет количество наблюдаемых результатов. В этом случае существует 50 различных уникальных результатов. Обратите внимание, что для каждого результата результаты измерения для первого и второго кубитов всегда одинаковы.
Совет
Вы можете увеличить гистограмму с помощью колесика прокрутки мыши или жеста трекпада. При увеличении диаграммы можно сдвигать, нажимая клавишу ALT во время прокрутки.
Щелкните полосу, чтобы отобразить процент этого результата.
Щелкните значок параметров вверху слева, чтобы отобразить параметры. Вы можете отобразить первые 10 результатов, первые 25 результатов или все результаты. Вы также можете отсортировать результаты от высокого к низкому или от низкого к высокому.
Дальнейшие действия
Ознакомьтесь с другими учебниками по Q#:
- Квантовый генератор случайных чисел показывает, как написать Q# программу, которая создает случайные числа из кубитов в суперпозиции.
- Алгоритм поиска Гровера показывает, как написать Q# программу, которая использует алгоритм поиска Гровера.
- Квантовое преобразование Фурье исследует, как написать Q# программу, которая напрямую обращается к конкретным кубитам.
- Quantum Katas — это учебники в произвольном темпе и упражнения по программированию, направленные на одновременное обучение элементам квантовых вычислений и Q# программирования.
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по