Учебник. Изучение квантовой запутанности с помощью Q#
В этом руководстве вы будете писать Q# программу, управляющую и измеряющую кубиты, и демонстрирующую эффекты суперпозиции и запутанности. Вы подготовили два кубита в определенном квантовом состоянии, научились работать с кубитами с помощью Q#, чтобы изменить их состояние, и продемонстрировали эффекты суперпозиции и запутанности. Вы создаете программу Q# по частям, чтобы представить состояния кубитов, операции и измерения.
Ниже приведены некоторые основные понятия, которые необходимо понять перед началом работы:
- В классическом бите хранится одно двоичное значение (0 или 1), а кубит может находиться в состоянии суперпозиции двух квантовых значений (0 и 1). Каждое возможное квантовое состояние связано с амплитудой вероятности.
- Действие измерения кубита создает двоичный результат с определенной вероятностью и изменяет состояние кубита вне суперпозиции.
- Несколько кубитов могут быть запутаны таким образом, что их нельзя описать независимо друг от друга. Это означает, что все, что происходит с одним из кубитов в паре запутанных, также происходит и с другим кубитом.
Из этого руководства вы узнаете, как выполнять следующие задачи:
- Создайте Q# операции для инициализации кубита в требуемое состояние.
- поместить кубит в суперпозицию.
- Спутайте пару кубитов.
- Измерение кубита и наблюдение за результатами.
Совет
Если вы хотите ускорить путешествие квантовых вычислений, ознакомьтесь с кодом с помощью 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 и скопируйте следующий код в окно редактора кода. Еще не выбирайте запуск; позже вы запустите код в ходе руководства.
import Microsoft.Quantum.Intrinsic.*;
import 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
всегда устанавливает целевой кубит в нужное состояние.
Написать тестовую операцию для проверки состояния Белла
Далее, чтобы продемонстрировать результат операции SetQubitState
, создайте другую операцию с именем Main
. Эта операция выделяет два кубита, вызов SetQubitState
для задания первого кубита известному состоянию, а затем измеряет кубиты, чтобы увидеть результаты.
Скопируйте следующий код в окно редактора кода под операцией SetQubitState
.
operation Main() : (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 {
numOnesQ1 += 1;
}
if resultQ2 == One {
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 раз.
Операция Main
:
- Задает переменные для счетчика и начального состояния кубита.
- Вызывает инструкцию
use
для инициализации двух кубитов. - Выполняет цикл в течение
count
итераций. Для каждого цикла он- Вызывает
SetQubitState
, чтобы задать указанное значениеinitial
для первого кубита. - Снова вызывает
SetQubitState
, чтобы установить для второго кубита состояниеZero
. - Использует операцию
M
для измерения каждого кубита. - Сохраняет количество измерений для каждого кубита, возвращающего значение
One
.
- Вызывает
- После завершения цикла снова вызывается метод
SetQubitState
, чтобы сбросить кубиты до известного состояния (Zero
) и разрешить другим пользователям выделить кубиты в известном состоянии. Сброс требуется операторомuse
. - Наконец, используется функция
Message
для вывода результатов в окна вывода Copilot, прежде чем вернуть результаты.
Запустите код в Copilot для Azure Quantum
Перед переходом к процедурам по суперпозиции и запутыванию можно проверить код до этой точки, чтобы увидеть инициализацию кубитов и их измерение.
Чтобы запустить код как автономную программу, Q# компилятор в Copilot должен знать , где начать программу. Так как пространство имен не указано, компилятор распознает точку входа по умолчанию как Main
операцию. Дополнительные сведения см. в разделе "Проекты" и неявные пространства имен.
К этому моменту ваша программа Q# должна выглядеть следующим образом:
import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
operation Main() : (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 {
numOnesQ1 += 1;
}
if resultQ2 == One {
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
Совет
Нажмите Ctrl-Z или выберите Изменить > Отменить и сохраните файл всякий раз, когда вы вводите тестовое изменение в код перед его повторным запуском.
Поместите кубит в состояние суперпозиции
В настоящее время кубиты в программе находятся в классическом состоянии, то есть они либо 1 или 0. Это известно, потому что программа инициализирует кубиты в известном состоянии, и вы не добавили процессы для управления ими. Прежде чем запутать кубиты, вы помещаете первый кубит в состояние суперпозиции, где при измерении кубита результат равен Zero
примерно в 50% случаев и One
примерно в 50% случаев. Концептуально кубит можно представить как имеющий равную вероятность измерения либо Zero
, либо One
.
Чтобы помещать кубиты в состояние суперпозиции, Q# предоставляет операцию H
(операцию Адамара).
X
Вспомните операцию из процедуры инициализации кубита в известное состояние ранее, которая перевернула кубит с 0 на 1 (или наоборот); операция H
переворачивает кубит на полпути, приводя его в состояние с равной вероятностью Zero
и One
. При измерении кубита в суперпозиции он должен возвращать примерно равное количество результатов Zero
и One
.
Измените код в операции Main
, установив начальное значение в 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 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
. Теперь программа должна выглядеть так:
import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
operation Main() : (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 {
numOnesQ1 += 1;
}
if resultQ2 == One {
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.
Создайте новый файл Q#
- Откройте Visual Studio Code и выберите "Создать > текстовый файл ", чтобы создать новый файл.
- Сохраните файл как
CreateBellStates.qs
. Этот файл будет содержать Q# код для программы.
Инициализация кубита в известном состоянии
Первым делом мы определим операцию Q#, которая инициализирует кубит в известном состоянии. Эту операцию можно вызвать, чтобы задать кубит классическому состоянию, что означает, что она возвращает Zero
100% времени или возвращает One
100% времени. Значения Zero
и One
имеют тип Q# и представляют единственные возможные результаты измерения кубита.
Откройте CreateBellStates.qs
и скопируйте следующий код:
import Microsoft.Quantum.Intrinsic.*;
import 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
всегда устанавливает целевой кубит в нужное состояние.
Написать тестовую операцию для проверки состояния Белла
Далее, чтобы продемонстрировать результат операции SetQubitState
, создайте другую операцию с именем Main
. Эта операция выделяет два кубита, вызов SetQubitState
для задания первого кубита известному состоянию, а затем измеряет кубиты, чтобы увидеть результаты.
Добавьте следующую операцию в файл CreateBellStates.qs
после операции SetQubitState
.
operation Main() : (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 {
numOnesQ1 += 1;
}
if resultQ2 == One {
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 раз.
Операция Main
:
- Принимает два параметра:
count
— количество запусков измерения,initial
— требуемое состояние для инициализации кубита. - Вызывает инструкцию
use
для инициализации двух кубитов. - Выполняет цикл на протяжении
count
итераций. Для каждого цикла он- Вызывает
SetQubitState
, чтобы задать указанное значениеinitial
для первого кубита. - Снова вызывает
SetQubitState
, чтобы установить для второго кубита состояниеZero
. - Использует операцию
M
для измерения каждого кубита. - Сохраняет количество измерений для каждого кубита, возвращающего значение
One
.
- Вызывает
- После завершения цикла снова вызывается метод
SetQubitState
, чтобы сбросить кубиты до известного состояния (Zero
) и разрешить другим пользователям выделить кубиты в известном состоянии. Сброс кубита требуется инструкциейuse
. - Наконец, функция
Message
используется для вывода сообщения в консоль перед возвратом результатов.
Выполнение кода
Прежде чем переходить к процедурам для работы с суперпозицией и запутанностью, протестируйте код на данном этапе, чтобы увидеть инициализацию и измерение кубитов.
Чтобы запустить код как автономную программу, Q# компилятор должен знать , где запустить программу. Так как пространство имен не указано, компилятор распознает точку входа по умолчанию как Main
операцию. Дополнительные сведения см. в разделе "Проекты" и неявные пространства имен.
Файл
CreateBellStates.qs
до этого момента должен выглядеть следующим образом:import Microsoft.Quantum.Intrinsic.*; import Microsoft.Quantum.Canon.*; operation SetQubitState(desired : Result, target : Qubit) : Unit { if desired != M(target) { X(target); } } operation Main() : (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 { numOnesQ1 += 1; } if resultQ2 == One { 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 ); }
Перед запуском программы убедитесь, что целевой профиль имеет значение "Неограниченный". Выберите
Палитра команд<с0 />, найдите QIR, выберите <с2 />: Установите целевой профиль QIR Azure Quantum , и выберите .: неограниченный Примечание.
Если целевой профиль не задан как Неограниченный, при запуске программы возникает ошибка.
Чтобы запустить программу, выберите Запустить Q# Файл в раскрывающемся списке значка воспроизведения в правом верхнем углу, выберите Запустить из списка команд перед
Main
операцией, или нажмите клавиши Ctrl+F5. Программа выполняетMain
операцию на симуляторе по умолчанию.Выходные данные отображаются в консоли отладки.
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
Совет
Нажмите Ctrl+Z или Редактировать > Отменить и сохраните файл каждый раз, когда вы вносите тестовое изменение в код перед повторным запуском.
Поместить кубит в состояние суперпозиции
В настоящее время кубиты в нашей программе находятся в классическом состоянии, то есть всегда имеют значение 1 или 0. Это известно, потому что программа инициализирует кубиты в известном состоянии, и вы не добавили процессы для управления ими. Прежде чем запутать кубиты, вы помещаете первый кубит в состояние суперпозиции, в котором измерение кубита дает результат Zero
в 50% случаев и One
в 50% случаев. В теории можно рассматривать состояние кубита как промежуточное между Zero
и One
.
Чтобы помещать кубиты в состояние суперпозиции, Q# предоставляет операцию H
(операцию Адамара).
X
Вспомните операцию из процедуры инициализации кубита в известное состояние ранее, которая перевернула кубит из состояния Zero
в состояние One
(или наоборот); H
операция переворачивает кубит на полпути в состояние с равной вероятностью быть в Zero
или One
. При измерении кубита в состоянии суперпозиции он должен возвращать примерно равное количество результатов Zero
и One
.
Измените код в операции
Main
, добавив в него операцию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
, которая расшифровывается как Контролируемое-НЕ. В результате выполнения этой операции инвертируется второй кубит, если первый кубит имеет значение One
.
Добавьте в программу операцию
CNOT
, поместив ее сразу после операцииH
. Теперь программа должна выглядеть так:import Microsoft.Quantum.Intrinsic.*; import Microsoft.Quantum.Canon.*; operation SetQubitState(desired : Result, target : Qubit) : Unit { if desired != M(target) { X(target); } } operation Main() : (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 { numOnesQ1 += 1; } if resultQ2 == One { 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 Result: "(502, 498, 502, 498)"
Статистика первого кубита не изменилась (после измерения вероятность Zero
или One
составляет 50 на 50), но результаты измерения второго кубита всегда совпадают с измерением первого кубита. Операция CNOT
запутала два кубита, так что все, что происходит с одним из них, происходит с другим.
График гистограммы частоты
Давайте визуализируем распределение результатов, полученных при выполнении квантовой программы несколько раз. Гистограмма частоты помогает визуализировать распределение вероятностей этих результатов.
Выберите Вид —> Палитра команд или нажмите Ctrl+Shift+P, и введите «гистограмма», чтобы открыть Q#: Запустить файл и отобразить гистограмму. Вы также можете выбрать гистограмму из списка команд, описанных выше
Main
. Выберите этот параметр, чтобы открыть Q# окно гистограммы.Введите количество раз для выполнения программы, например, 100 итераций, и нажмите клавишу ВВОД. Гистограмма отображается в Q# окне гистограммы.
Каждая полоса в гистограмме соответствует возможному результату, и его высота представляет количество наблюдаемых результатов. В этом случае существует 50 различных уникальных результатов. Обратите внимание, что для каждого результата результаты измерения для первого и второго кубита всегда одинаковы.
Совет
Вы можете увеличить гистограмму с помощью колесика прокрутки мыши или жеста трекпада. При увеличении масштаба диаграмму можно сдвигать, нажав клавиши ALT во время прокрутки.
Выберите столбец, чтобы отобразить процент этого результата.
Щелкните значок параметров вверху слева, чтобы отобразить параметры. Вы можете отобразить первые 10 результатов, 25 лучших результатов или все результаты. Вы также можете отсортировать результаты от высокого до низкого или от низкого до высокого.
Связанный контент
Ознакомьтесь с другими учебниками по Q#:
- Алгоритм поиска Гровера показывает, как написать Q# программу, использующую алгоритм поиска Гровера.
- Quantum Fourier Transform изучает, как писать программу, которая напрямую Q# обращается к определенным кубитам.
- Quantum Katas — это самостоятельные учебные материалы и упражнения по программированию, направленные на обучение основам квантовых вычислений и Q# программирования одновременно.