mirror of https://github.com/intel/intel-qs.git
586 lines
20 KiB
Plaintext
586 lines
20 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"----\n",
|
|
"# Getting started with Intel Quantum Simulator\n",
|
|
"----\n",
|
|
"Tutorial on the basic use of Intel QS through its Python interface.\n",
|
|
"\n",
|
|
"**NOTE:**\n",
|
|
"Currently, the Python implementation only allows for single-core execution and does not take advantages of the MPI protocol.\n",
|
|
"However the user can familiarize with the same functionalities available in the distributed implementation (only C++ at the moment) and the transition should be relatively straighforward since all methods maintain name and effect."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Import Intel QS library\n",
|
|
"\n",
|
|
"Let's start by importing the Python library with the class and methods defined in the C++ implementation."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"metadata": {
|
|
"hideCode": false,
|
|
"hidePrompt": false,
|
|
"scrolled": true,
|
|
"slideshow": {
|
|
"slide_type": "-"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Import the Python library with the C++ class and methods of Intel Quantum Simulator.\n",
|
|
"# If the library is not contained in the same folder of this notebook, its path has to be added.\n",
|
|
"import sys\n",
|
|
"sys.path.insert(0, '../build/lib')\n",
|
|
"import intelqs_py as simulator\n",
|
|
"\n",
|
|
"# import numPy\n",
|
|
"import numpy as np\n",
|
|
"\n",
|
|
"# Import graphical library for plots.\n",
|
|
"import matplotlib.pyplot as plt"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Initialize the state of the quantum register\n",
|
|
"\n",
|
|
"IQS stores a full representation of the quantum state in the computational basis.\n",
|
|
"In practice, the quantum state of $N$ qubits is represented as a complex vector with $2^N$ components.\n",
|
|
"\n",
|
|
"Each component corresponds to the probability amplitude of a specific computational basis state:\n",
|
|
"$$\\psi(k) = \\langle k | \\psi \\rangle$$\n",
|
|
"with the index $k$ corresponding to the $N$-bit integer in decimal representation, and $k\\in\\{0,1,2,\\dots,2^N-1\\}$.\n",
|
|
"\n",
|
|
"----\n",
|
|
"\n",
|
|
"- First of all, one needs to allocate the memory to contain the state representation.\n",
|
|
"- Then the quantum register has to be initialized, either to a specific computational basis state (using the keyword \"base\") or to a random state (using the keyword \"rand\").\n",
|
|
"\n",
|
|
"----\n",
|
|
"\n",
|
|
"NOTE: the random number generator is able to generate three different kinds of random numbers:\n",
|
|
"- *local* --> different for each pool rank\n",
|
|
"- *state* --> common to all ranks of the same state\n",
|
|
"- *pool* --> common to all ranks of the pool"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Number of qubits.\n",
|
|
"num_qubits = 2;\n",
|
|
"# Index of the computational basis state corresponding to |00>.\n",
|
|
"index = 0;\n",
|
|
"\n",
|
|
"# Allocate memory for the quantum register's state and initialize it to |00>.\n",
|
|
"psi = simulator.QubitRegister(num_qubits, \"base\", index, 0);\n",
|
|
"\n",
|
|
"# To initialize the state to a random vector, one first need a random number generator.\n",
|
|
"# Create the random number generator, set its seed and then associate it to the IQS object 'psi'.\n",
|
|
"rng = simulator.RandomNumberGenerator();\n",
|
|
"rng_seed = 7777;\n",
|
|
"rng.SetSeedStreamPtrs( rng_seed );\n",
|
|
"psi.SetRngPtr(rng);\n",
|
|
"\n",
|
|
"# Initialize the state to a random state, this can be achieved with the codeword \"rand\" followed by 0\n",
|
|
"# if we desire to use *local* random numbers (this speed up the process of generating the random numbers).\n",
|
|
"psi.Initialize(\"rand\", 0);"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Display the quantum state\n",
|
|
"\n",
|
|
"It is important to be able to access and visualize the quantum state.\n",
|
|
"IQS allows to access the single components of the state or to print a comprehensive description.\n",
|
|
"\n",
|
|
"What index is associated to state $|1011\\rangle$?\n",
|
|
"In decimal representation one has:\n",
|
|
"$$1011 \\rightarrow 1\\times2^0 + 0\\times2^1 + 1\\times2^2 + 1\\times2^3 = 1+4+8 = 13$$\n",
|
|
"\n",
|
|
"**NOTE:** contrary to what is adopted in decimal notation, our binary representation must be read from left to right (from least significant to most significant bit)."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"psi(0) = <0|psi> = 0j\n",
|
|
"psi(1) = <1|psi> = (1+0j)\n",
|
|
"psi(2) = <2|psi> = 0j\n",
|
|
"psi(3) = <3|psi> = 0j\n",
|
|
"----\n",
|
|
"<<the output has been redirected to the terminal>>\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Initialize the state to |10>.\n",
|
|
"# The index of |10> in decimal representation is 1.\n",
|
|
"index = 1;\n",
|
|
"psi.Initialize(\"base\", index);\n",
|
|
"\n",
|
|
"# There are for amplitudes, corresponding to |00>, |10>, |01>, |11>.\n",
|
|
"for index in range(0,2**num_qubits):\n",
|
|
" amplitude = psi[index]\n",
|
|
" print(\"psi({}) = <{}|psi> = {}\".format(index,index,amplitude))\n",
|
|
"\n",
|
|
"# A complete description of the state is provided by the method Print().\n",
|
|
"print(\"----\")\n",
|
|
"label = \"Computational basis state |10>\"\n",
|
|
"psi.Print(label)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### One-qubit gates\n",
|
|
"\n",
|
|
"In the gate-model of quantum computation, one manipulates the quantum state by means of unitary transformations acting on one or two qubits. Let us apply a few of the standard one-qubit gates."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"metadata": {
|
|
"hidePrompt": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Currently, |psi>=|11>:\n",
|
|
" psi(0) = <0|psi> = 0j\n",
|
|
" psi(1) = <1|psi> = 0j\n",
|
|
" psi(2) = <2|psi> = 0j\n",
|
|
" psi(3) = <3|psi> = (1+0j)\n",
|
|
"----\n",
|
|
"Currently, |psi>=|-1>:\n",
|
|
" psi(0) = <0|psi> = 0j\n",
|
|
" psi(1) = <1|psi> = 0j\n",
|
|
" psi(2) = <2|psi> = (0.7071067811865475+0j)\n",
|
|
" psi(3) = <3|psi> = (-0.7071067811865475+0j)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# State was |10>. Let us re-prepare it:\n",
|
|
"psi = simulator.QubitRegister(2, \"base\", 1, 0);\n",
|
|
"# Flip the qubit 1 by applying the Pauli X gate: |10> ==> |11>\n",
|
|
"qubit = 1;\n",
|
|
"psi.ApplyPauliX(qubit);\n",
|
|
"\n",
|
|
"# Display all amplitudes.\n",
|
|
"print(\"Currently, |psi>=|11>:\");\n",
|
|
"for index in range(0,2**num_qubits):\n",
|
|
" print(\" psi({}) = <{}|psi> = {}\".format(index,index,psi[index]))\n",
|
|
"\n",
|
|
"print(\"----\")\n",
|
|
" \n",
|
|
"# Apply the Hadamard gate on qubit 0: |11> ==> |-1> ~ |01>-|11>\n",
|
|
"qubit = 0;\n",
|
|
"psi.ApplyHadamard(qubit);\n",
|
|
"\n",
|
|
"# Display all amplitudes.\n",
|
|
"print(\"Currently, |psi>=|-1>:\");\n",
|
|
"for index in range(0,2**num_qubits):\n",
|
|
" print(\" psi({}) = <{}|psi> = {}\".format(index,index,psi[index]))\n",
|
|
"\n",
|
|
"# Apply Pauli Z gate on qubit 1: |-1> ==> -|-1>\n",
|
|
"psi.ApplyPauliZ(1);\n",
|
|
"# Apply Pauli X gate on qubit 0: -|-1> ==> |-1>\n",
|
|
"psi.ApplyPauliX(0);"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Two-qubit gates\n",
|
|
"\n",
|
|
"To achieve universal quantum computation, it is enought to implement one-qubit gates and a single type of two-qubit gate.\n",
|
|
"The essential requirement is that such two-qubit gate is able to generate entanglement. Usually the controlled-not gate (CNOT in the following) is the operation of choice.\n",
|
|
"\n",
|
|
"IQS provides built-in methods to implement a much broader variety of two-qubit gates."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Currently, |psi>=-|-1>:\n",
|
|
" psi(0) = <0|psi> = 0j\n",
|
|
" psi(1) = <1|psi> = 0j\n",
|
|
" psi(2) = <2|psi> = (-0.7071067811865475+0j)\n",
|
|
" psi(3) = <3|psi> = (0.7071067811865475+0j)\n",
|
|
"----\n",
|
|
"Currently, |psi>=(|10>-|01>)/sqrt(2):\n",
|
|
" psi(0) = <0|psi> = 0j\n",
|
|
" psi(1) = <1|psi> = (0.7071067811865475+0j)\n",
|
|
" psi(2) = <2|psi> = (-0.7071067811865475+0j)\n",
|
|
" psi(3) = <3|psi> = 0j\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Currently, state is |-1>.\n",
|
|
"# Apply a CNOT(1,0): flip qubit 0 conditioned on the state of qubit 1.\n",
|
|
"# |-1> ==> -|-1>\n",
|
|
"control = 1;\n",
|
|
"target = 0;\n",
|
|
"psi.ApplyCPauliX(control, target);\n",
|
|
"\n",
|
|
"# Display all amplitudes.\n",
|
|
"print(\"Currently, |psi>=-|-1>:\");\n",
|
|
"for index in range(0,2**num_qubits):\n",
|
|
" print(\" psi({}) = <{}|psi> = {}\".format(index,index,psi[index]))\n",
|
|
"\n",
|
|
"print(\"----\")\n",
|
|
"\n",
|
|
"# The application of the previous CNOT did not create any entanglement.\n",
|
|
"# This is achieved by exchanging the role of control and target qubits.\n",
|
|
"# Apply a CNOT(0,1): flip qubit 1 conditioned on the state of qubit 0.\n",
|
|
"# -|-1> ~ -|01>+|11> ==> -|01>+|10>\n",
|
|
"control = 0;\n",
|
|
"target = 1;\n",
|
|
"psi.ApplyCPauliX(control, target);\n",
|
|
"\n",
|
|
"# Display all amplitudes.\n",
|
|
"print(\"Currently, |psi>=(|10>-|01>)/sqrt(2):\");\n",
|
|
"for index in range(0,2**num_qubits):\n",
|
|
" print(\" psi({}) = <{}|psi> = {}\".format(index,index,psi[index]))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Custom gates\n",
|
|
"\n",
|
|
"If IQS does not provide the gates needed in your circuit, it is possible to implement custom one-qubit gates and controlled gates."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Even before the application of G, state psi had normalization 0.9999999999999999\n",
|
|
"The application of G changed the norm of state psi: from 0.9999999999999999 to 1.0\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Define an arbitrary single qubit gate.\n",
|
|
"# The quantum gate G is given by a 2x2 unitary matrix, here using a bi-dimensional NumPy array.\n",
|
|
"G = np.zeros((2,2),dtype=np.complex_);\n",
|
|
"G[0,0] = 0.592056606032915 + 0.459533060553574j;\n",
|
|
"G[0,1] = -0.314948020757856 - 0.582328159830658j;\n",
|
|
"G[1,0] = 0.658235557641767 + 0.070882241549507j;\n",
|
|
"G[1,1] = 0.649564427121402 + 0.373855203932477j;\n",
|
|
"\n",
|
|
"# To verify that G is unitary, we will compute the norm of psi before and after the application of G.\n",
|
|
"initial_norm = psi.ComputeNorm();\n",
|
|
"if initial_norm != 1:\n",
|
|
" print(\"Even before the application of G, state psi had normalization {}\".format(initial_norm));\n",
|
|
"# Apply the custom gate G to qubit 0.\n",
|
|
"qubit = 0;\n",
|
|
"psi.Apply1QubitGate(qubit,G);\n",
|
|
"final_norm = psi.ComputeNorm();\n",
|
|
"if initial_norm != final_norm:\n",
|
|
" print(\"The application of G changed the norm of state psi: from {} to {}\".format(initial_norm,final_norm));\n",
|
|
"else:\n",
|
|
" print(\"Sanity check: norm was unchanged by G.\");"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"<<the output has been redirected to the terminal>>\n",
|
|
"\n",
|
|
"psi(0) = <0|psi> = (-0.22270188119916148-0.41176819069214193j)\n",
|
|
"psi(1) = <1|psi> = (0.4593114112350983+0.2643555498825341j)\n",
|
|
"psi(2) = <2|psi> = (0.018860567095173378-0.09793842271642633j)\n",
|
|
"psi(3) = <3|psi> = (-0.5361330884127283-0.45012626658938304j)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# It is also possible to apply the arbitrary gate specified by G conditioned on the state of another qubit.\n",
|
|
"# G is applied only when the control qubit is in |1>.\n",
|
|
"control = 1;\n",
|
|
"target = 0;\n",
|
|
"psi.ApplyControlled1QubitGate( control, target, G);\n",
|
|
"\n",
|
|
"# Notice that this output is directed to the terminal and not re-directed to the iPython notebook.\n",
|
|
"psi.Print(\"State of the quantum register after all gates.\")\n",
|
|
"print()\n",
|
|
"\n",
|
|
"# To display the amplitudes in the iPython notebook:\n",
|
|
"for index in range(0,2**num_qubits):\n",
|
|
" print(\"psi({}) = <{}|psi> = {}\".format(index,index,psi[index]))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Single-qubit measurements\n",
|
|
"\n",
|
|
"To extract information from the quantum register, one can obtain the probability of measuring a certain qubit in the computational basis and obtaining the outcome \"1\" (i.e. the state is in $|1\\rangle$).\n",
|
|
"\n",
|
|
"Once the probability is known, one can draw a random number to simulate the stochastic outcome of the measurement and collapse the wavefunction accordingly.\n",
|
|
"\n",
|
|
"**NOTE:**\n",
|
|
"Computing the probability of a certain outcome does not collapse automatically the wavefunction. This is helpful when the probabilities of multiple measurements have to be computed without re-executing the quantum simulation."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"metadata": {
|
|
"hidePrompt": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Probability that qubit 1 is in state |1> is 0.4999999999999997\n",
|
|
"\n",
|
|
"Simulated outcome is 0. Collapse the function accordingly.\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Compute the probability of qubit 1 being in state |1>.\n",
|
|
"measured_qubit = 1;\n",
|
|
"prob = psi.GetProbability( measured_qubit );\n",
|
|
"\n",
|
|
"print(\"Probability that qubit {} is in state |1> is {}\\n\".format(measured_qubit, prob));\n",
|
|
"\n",
|
|
"# Draw random number in [0,1)\n",
|
|
"r = np.random.rand()\n",
|
|
"if r < prob:\n",
|
|
" # Collapse the wavefunction according to qubit 1 being in |1>.\n",
|
|
" print(\"Simulated outcome is 1. Collapse the function accordingly.\")\n",
|
|
" psi.CollapseQubit(measured_qubit,True);\n",
|
|
"else:\n",
|
|
" # Collapse the wavefunction according to qubit 1 being in |0>\n",
|
|
" print(\"Simulated outcome is 0. Collapse the function accordingly.\")\n",
|
|
" psi.CollapseQubit(measured_qubit,False);\n",
|
|
"\n",
|
|
"# In both cases one needs to re-normalize the wavefunction:\n",
|
|
"psi.Normalize();"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Expectation value of products of Pauli matrices\n",
|
|
"\n",
|
|
"To extract information from the quantum register, one can obtain the expectation value of Pauli strings.\n",
|
|
"\n",
|
|
"For example, consider the Pauli string given by: $$X_0 \\otimes id_1 \\otimes Z_2 \\otimes Z_3$$\n",
|
|
"\n",
|
|
"Such observable is defined by:\n",
|
|
"- the position of the non-trivial Pauli matrices, in this case {0,2,3}\n",
|
|
"- the corresponding Pauli matrices ($X$=1, $Y$=2, $Z$=3).\n",
|
|
"\n",
|
|
"To facilitate the verification of the expectation value, we reinitialize the quantum state to $|+-01\\rangle$.\n",
|
|
"\n",
|
|
"We also consider the Pauli string $$X_0 \\otimes id_1 \\otimes Z_2 \\otimes Y_3$$."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"psi is in state |+-01>\n",
|
|
"\n",
|
|
"Expectation value <psi|X_0.id_1.Z_2.Z_3|psi> = -0.9999999999999996 <== it should be -1\n",
|
|
"\n",
|
|
"Expectation value <psi|X_0.id_1.Z_2.Y_3|psi> = 0.0 <== it should be 0\n",
|
|
"\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Prepare the state |+-01>\n",
|
|
"num_qubits = 4;\n",
|
|
"index = 0;\n",
|
|
"psi = simulator.QubitRegister(num_qubits, \"base\", index, 0);\n",
|
|
"psi.ApplyPauliX(1);\n",
|
|
"psi.ApplyPauliX(3);\n",
|
|
"psi.ApplyHadamard(0);\n",
|
|
"psi.ApplyHadamard(1);\n",
|
|
"print(\"psi is in state |+-01>\\n\");\n",
|
|
"\n",
|
|
"# The Pauli string given by: X_0 . id_1 . Z_2 . Z_3\n",
|
|
"# Such observable is defined by the position of the non-trivial Pauli matrices:\n",
|
|
"qubits_to_be_measured = [0,2,3]\n",
|
|
"\n",
|
|
"# And by the corresponding Pauli matrices (X=1, Y=2, Z=3)\n",
|
|
"observables = [1,3,3]\n",
|
|
"\n",
|
|
"# The expectation value <psi|X_0.id_1.Z_2.Z_3|psi> is obtained via:\n",
|
|
"average = psi.ExpectationValue(qubits_to_be_measured, observables, 1.);\n",
|
|
"print(\"Expectation value <psi|X_0.id_1.Z_2.Z_3|psi> = {} <== it should be -1\\n\".format(average));\n",
|
|
"\n",
|
|
"# The expectation value <psi|X_0.id_1.Z_2.Y_3|psi> is obtained via:\n",
|
|
"observables = [1,3,2]\n",
|
|
"average = psi.ExpectationValue(qubits_to_be_measured, observables, 1.);\n",
|
|
"print(\"Expectation value <psi|X_0.id_1.Z_2.Y_3|psi> = {} <== it should be 0\\n\".format(average));"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Examples of state preparation\n",
|
|
"\n",
|
|
"Let us prepare the state $|+-01\\rangle$. "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"metadata": {
|
|
"hidePrompt": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Verify that the state is now |0101>.\n",
|
|
"\n",
|
|
"Probability that qubit 0, if measured, is in state |1> = 0.0\n",
|
|
"Probability that qubit 1, if measured, is in state |1> = 1.0\n",
|
|
"Probability that qubit 2, if measured, is in state |1> = 0.0\n",
|
|
"Probability that qubit 3, if measured, is in state |1> = 1.0\n",
|
|
"\n",
|
|
"Now the state is |+-01>.\n",
|
|
"\n",
|
|
"Expectation value <psi|X_0.X_1.Z_2.Z_3|psi> = 0.9999999999999993 <== it should be +1\n",
|
|
"\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Method A:\n",
|
|
"# Prepare the state |0000>, flip qubits {1,3}, change basis to qubits {0,1}.\n",
|
|
"num_qubits = 4;\n",
|
|
"index = 0;\n",
|
|
"psi = simulator.QubitRegister(num_qubits, \"base\", index, 0);\n",
|
|
"psi.ApplyPauliX(1);\n",
|
|
"psi.ApplyPauliX(3);\n",
|
|
"psi.ApplyHadamard(0);\n",
|
|
"psi.ApplyHadamard(1);\n",
|
|
"\n",
|
|
"# Method B:\n",
|
|
"# Prepare the state |0000>, change basis to qubits {0,1}, flip qubit {3}, flip in X qubit {1}.\n",
|
|
"index = 0;\n",
|
|
"psi.Initialize(\"base\", index);\n",
|
|
"psi.ApplyHadamard(0);\n",
|
|
"psi.ApplyHadamard(1);\n",
|
|
"psi.ApplyPauliZ(1);\n",
|
|
"psi.ApplyPauliX(3);\n",
|
|
"\n",
|
|
"# Method C:\n",
|
|
"# Prepare the computational state |0101>, change basis to qubits {0,1}.\n",
|
|
"index = 2+8 ;\n",
|
|
"psi.Initialize(\"base\", index);\n",
|
|
"# Notice that GetProbability() does not change the state.\n",
|
|
"print(\"Verify that the state is now |0101>.\\n\")\n",
|
|
"for qubit in range(0,num_qubits):\n",
|
|
" prob = psi.GetProbability( qubit );\n",
|
|
" print(\"Probability that qubit {}, if measured, is in state |1> = {}\".format(qubit, prob));\n",
|
|
"psi.ApplyHadamard(0);\n",
|
|
"psi.ApplyHadamard(1);\n",
|
|
"print(\"\\nNow the state is |+-01>.\\n\")\n",
|
|
"\n",
|
|
"# The expectation value <psi|X_0.X_1.Z_2.Z_3|psi> is obtained via:\n",
|
|
"qubits_to_be_measured = [0,1,2,3]\n",
|
|
"observables = [1,1,3,3]\n",
|
|
"average = psi.ExpectationValue(qubits_to_be_measured, observables, 1.);\n",
|
|
"print(\"Expectation value <psi|X_0.X_1.Z_2.Z_3|psi> = {} <== it should be +1\\n\".format(average));"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"----\n",
|
|
"## END\n",
|
|
"----"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.8.5"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|