Quantum Programming Tutorial 1: Bell State
“The Bell state, \(| x_1 x_2 > = \frac{1}{\sqrt{2}} | 00 > + \frac{1}{\sqrt{2}} | 11 >\) , is of particular interest: if we pick any of the two qubits to measure, we would obtain outcome j0i or j1i with equal probability; and the other qubit is guaranteed to be measured in the same state as the first. This “correlation” between the two qubits are called quantum entanglement. However, this is not to be confused with two correlated random bits each with equal probability of being observed |0> or |1> . Proof of the distinction is omitted for the sake of brevity; we refer the interested reader to the studies on “local hidden variables” theory, Bell’s inequality, and the CHSH game. In essence, the measurement of one qubit intrinsically alters and determines the state of the other. Perhaps even more surprising is that these two qubits can be physically far apart as long as they were previous entangled as a Bell state. To form such a relationship between the two qubits, they must interact with each other, either directly through a two- qubit gate as shown above, or indirectly through a photon or a third qubit (Ding (2020),Chong (2020), University of Chicago, book,Quantum Computer Systems: Research for Noisy Intermediate-Scale Quantum Computers Synthesis Lectures on Computer Architecture)”.
The simplest example for quantum computation is to generate a Bell state from the controlled-not gate to or Cnot with a previous superposition of the qubit and control with the Hadamard gate.
Qiskit Program
The qiskit code to perform the previously mentioned state of bell is described.
import qiskit
from qiskit.quantum_info import Statevector # the state vector of the required qubits is generated
from qiskit.visualization import plot_state_qsphere # plot the qubits in a qsphere
sv = Statevector.from_label('00') # show the input state 00
plot_state_qsphere(sv.data) #plot the previous state
mycircuit = qiskit.QuantumCircuit(2,2)# generate the circuit's bell state
mycircuit.h(0)
mycircuit.cx(0,1)
mycircuit.draw('mpl')
new_sv = sv.evolve(mycircuit) # show the output vector state
print(new_sv)
plot_state_qsphere(new_sv.data) # show the plot of the output qubits
Statevector([0.70710678+0.j, 0. +0.j, 0. +0.j,
0.70710678+0.j],
dims=(2, 2))
counts = new_sv.sample_counts(shots=1000) # simulate with 1000 iterations
from qiskit.visualization import plot_histogram
plot_histogram(counts) # plot the output istogram
Qiskit Real Quantum Computing
Generate the same circuit on a real quantum computing that use 15 qubits.
qiskit.IBMQ.load_account() # load the token
provider = qiskit.IBMQ.get_provider('ibm-q') # select the provider
backend = provider.get_backend('ibmq_16_melbourne') # select the name of the quatum computer to use
print("real device:",backend.name())
real device: ibmq_16_melbourne
mycircuit.measure([0,1],[0,1]) # we apply the measurement
job = qiskit.execute( mycircuit, backend)
result = job.result()
counts =result.get_counts(mycircuit) # obtain he output values
print("counts: ", counts ) # show the result
counts: {'01': 47, '00': 502, '11': 442, '10': 33}
qiskit.visualization.plot_histogram(counts) # plot the histogram
Cirq Program
The cirq code to perform the previously mentioned state of bell is described.
import cirq # call the library
q0 = cirq.GridQubit(0, 0) # call the qubit (0,0)
q1 = cirq.GridQubit(0, 1) # call the qubit (0,1)
circuit = cirq.Circuit() # call the method circuit
circuit.append(cirq.H(q0)) # adder in the circuit the Hadamard gate in q0
circuit.append(cirq.CX(q0,q1)) # adder in the circuit the CX or Cnot gate between q0 and q1
circuit.append(cirq.measure(q0, key='m0')) # adder the measure in q0
circuit.append(cirq.measure(q1, key='m1')) # adder the measure in q1
print("Circuit:")
print(circuit) # print the circuit at this moment
# Simulate the circuit.
shots = 100 # number of shots in the simulation
simulator = cirq.Simulator() # call the Simulator method
result = simulator.run(circuit, repetitions=shots) # run the circuit in shots time (100 times)
print("Results:")
print(result) # show the results
Circuit:
(0, 0): ───H───@───M('m0')───
│
(0, 1): ───────X───M('m1')───
Results:
m0=0001000110111001000100001000101111100110101111010100101000011000000101101011101111010110001111001011
m1=0001000110111001000100001000101111100110101111010100101000011000000101101011101111010110001111001011
counts = cirq.plot_state_histogram(result) # cal the method to generate a plot
print("Probabiity =", counts/shots) # print the probabilities of every qubit_state
Probabiity = [0.51 0. 0. 0.49]
QDK Program
The QDK (using Q#) code to perform the previously mentioned state of bell is described.
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if (desired != M(target)) { // change the target qubit with the desired value
X(target);
}
}
@EntryPoint()
operation TestBellState(count : Int, initial : Result) : (Int, Int) { // generate the Bell State
mutable numOnes = 0; // vriable to count
using (qubit = Qubit()) { // call a qubit
for (test in 1..count) { // for from 1 to 1000
SetQubitState(initial, qubit); // call the function with (Zero/One,qubit)
H(qubit); // superposition of the value
let res = M(qubit); // measurement the value of the quit
// Count the number of ones we saw:
if (res == One) {
set numOnes += 1;
}
}
SetQubitState(Zero, qubit);
}
// Return number of times we saw a |0> and number of times we saw a |1>
return (count - numOnes, numOnes);
}
/snippet:(1,94): warning QS6003: The namespace is already open.
/snippet:(2,10): warning QS6003: The namespace is already open.
- SetQubitState
- TestBellState
operation BellState(): Unit{
let (nZero,nOne) = TestBellState(1000,Zero); // call the function with 1000 iterations and flag to detect Zero state
Message($"Probablity of obtain the state |00> :{nZero} ");// print results
Message($"Probablity of obtain the state |11> :{nOne} ");
}
- BellState
%simulate BellState
Probablity of obtain the state |00> :510
Probablity of obtain the state |11> :490
()
Silq Program
The silq code to perform the previously mentioned state of bell is described.
Introduction to Silq
For this first example we must take into account the following properties of the silq language:
B type variables are Boolean variables.
x := false:B; // variable boolean x with the value in False
// x, means variable name
// :=, means assignment
// false, means value in false;
// :B, indicates the type of false value
Apply pre-defined functions
x := H(x); // the Hadamard gate is applied to the boolean variable x and assigned to the same variable x
// x, means variable name
Generate a function
def classicalExample(x:𝔹,f:𝔹->𝔹){ // generate a examle function that has a boolean variable x
//and function f that Boolean mapping to another Boolean
return f(x); // return the function f
}
To know more about the documentation check the following link : https://silq.ethz.ch/documentation
Generate cnot function
To generate the denied controlled gate it is necessary to indicate two boolean variables: x,y where x represents the control qubit and if it is true it denies the variable y.
// B means the boolean type
// const mens constant value in this case in the boolean variable x
def cnot(const x:B,y:B):B{ //generate the function Cnot gate
if x{ // if x is true apply the sentence inside the {}
y := X(y); // apply X gate in the boolean variable x
}
return y; // return the only
}
Define main function
We initialize the boolean variables x,y in false or zero state, to the variable x we apply the Hadamard gate, followed by the cnot function where x is the control qubit over the qubit y. Finally, we measure and return the values of the qubits (obtaining their classic values from the two qubits used in the program).
def main(){ // main function
x := false:B; // A boolean (B type) variable x is initialized in false or zero state (|0>)
y := false:B; // A boolean (B type) variable x is initialized in false or zero state (|0>)
x := H(x); // Applying Hadamard to the boolean variable x
y := cnot(x,y); // It called the function cnot(x,y)
return measure(x,y); // return the measure by the x and y variables or qubits.
}
Expected outputs
(1,1)
or
(0,0)
The previous silq code is in the file called bell_state.sql
Strawberry Fields
The strawberry fields code to perform the previously mentioned state of bell is described.
import strawberryfields as sf
from strawberryfields import ops
# create a quantum program with 3 qubits
prog = sf.Program(2)
# describe the circuit
with prog.context as q:
ops.Rgate(1.57) | q[0] # call the Sgate
ops.CXgate() | (q[0], q[1]) # call the BSGate
ops.MeasureFock() | q # perform the measurement on all qubits of the variable q
prog.print()
eng = sf.Engine("fock", backend_options={"cutoff_dim": 5}) # generate the simulation
result = eng.run(prog)
print(result.state)
state = result.state
state.trace()
state.dm().shape # density matrix
result.samples #print the output states
Rgate(1.57) | (q[0])
CXgate(1) | (q[0], q[1])
MeasureFock | (q[0], q[1])
<FockState: num_modes=2, cutoff=5, pure=True, hbar=2>
array([[0, 0]])