Programming Cirq

Cirq is a framework for writing quantum algorithms for noisy intermediate-scale quantum (NISQ) devices.

Cirq is a Python software library designed for writing, manipulating, and optimizing quantum circuits, particularly for noisy intermediate-scale quantum (NISQ) devices. It provides useful abstractions for handling the complexities of today's quantum computers, where hardware details are crucial for achieving state-of-the-art results.

Key features of Cirq include:
Circuit Representation: Quantum programs are represented by circuits, which consist of moments (slices of quantum gates) applied at the same time.

Simulators: Cirq includes built-in simulators for wave functions and density matrices, allowing users to simulate quantum circuits and perform transformations.

Variational Quantum Algorithms: Cirq supports the creation of variational quantum algorithms, enabling researchers to explore fault-tolerant quantum algorithms.

Open Source: Cirq is an open-source framework, making it accessible for both developers and researchers to contribute to quantum computing research.


What is NISQ?

NISQ devices, or Noisy Intermediate-Scale Quantum devices, are quantum computers that operate with a limited number of qubits (typically between 50 and 1,000) and are characterized by significant noise and errors.NISQ devices are those with O(100) qubits that can enact O(1000) gates.More details on Noisy intermediate-scale quantum computing - Wikipedia.

Installing Cirq on windows:

  pip install cirq

Test to verify sucessful installation:

#Test successful installation by printing out the Sycamore device.
import cirq_google
print(cirq_google.Sycamore)


Output of above program will be

                                                      (0, 5)───(0, 6)
                                                         │        │
                                                         │        │
                                    (1, 4)───(1, 5)───(1, 6)───(1, 7)
                                    │        │        │        │
                                    │        │        │        │
                           (2, 3)───(2, 4)───(2, 5)───(2, 6)───(2, 7)───(2, 8)
                           │        │        │        │        │        │
                           │        │        │        │        │        │
                  (3, 2)───(3, 3)───(3, 4)───(3, 5)───(3, 6)───(3, 7)───(3, 8)───(3, 9)
                  │        │        │        │        │        │        │        │
                  │        │        │        │        │        │        │        │
         (4, 1)───(4, 2)───(4, 3)───(4, 4)───(4, 5)───(4, 6)───(4, 7)───(4, 8)───(4, 9)
         │        │        │        │        │        │        │        │
         │        │        │        │        │        │        │        │
(5, 0)───(5, 1)───(5, 2)───(5, 3)───(5, 4)───(5, 5)───(5, 6)───(5, 7)───(5, 8)
         │        │        │        │        │        │        │
         │        │        │        │        │        │        │
         (6, 1)───(6, 2)───(6, 3)───(6, 4)───(6, 5)───(6, 6)───(6, 7)
                  │        │        │        │        │
                  │        │        │        │        │
                  (7, 2)───(7, 3)───(7, 4)───(7, 5)───(7, 6)
                           │        │        │
                           │        │        │
                           (8, 3)───(8, 4)───(8, 5)
                                    │
                                    │
                                    (9, 4)


What is Sycamore device?

The Sycamore device is a 53-qubit transmon superconducting quantum processor developed by Google's AI division. It was used to demonstrate quantum supremacy by completing a task in 200 seconds, which would take a classical supercomputer 10,000 years to finish. The device features a 2D grid structure with a tunable coupling architecture, allowing for efficient qubit connectivity and operation. Sycamore's development involved significant engineering challenges, including calibration and optimization of its quantum logic.

Simple Operation using Qubits:

q0=cirq.NamedQubit("q0")
q1=cirq.NamedQubit("q1")

The above operation will create 2 Qubits q0 & q1. Other ways to create Qubits are shown below:

# Line qubits
q3 = cirq.LineQubit(4)

# Create LineQubit(0), LineQubit(1), LineQubit(2)
q0, q1, q2 = cirq.LineQubit.range(3)

# Create 16 qubits from (0,0) to (7,7)
qubits16 = cirq.GridQubit.square(8)

# Grid Qubits can also be referenced individually
q01= cirq.GridQubit(0,1)

#print the values in qubits16
>>> qubits16
[cirq.GridQubit(0, 0), cirq.GridQubit(0, 1), cirq.GridQubit(0, 2), cirq.GridQubit(0, 3), cirq.GridQubit(0, 4), cirq.GridQubit(0, 5), cirq.GridQubit(0, 6), cirq.GridQubit(0, 7), cirq.GridQubit(1, 0), cirq.GridQubit(1, 1), cirq.GridQubit(1, 2), cirq.GridQubit(1, 3), cirq.GridQubit(1, 4), cirq.GridQubit(1, 5), cirq.GridQubit(1, 6), cirq.GridQubit(1, 7), cirq.GridQubit(2, 0), cirq.GridQubit(2, 1), cirq.GridQubit(2, 2), cirq.GridQubit(2, 3), cirq.GridQubit(2, 4), cirq.GridQubit(2, 5), cirq.GridQubit(2, 6), cirq.GridQubit(2, 7), cirq.GridQubit(3, 0), cirq.GridQubit(3, 1), cirq.GridQubit(3, 2), cirq.GridQubit(3, 3), cirq.GridQubit(3, 4), cirq.GridQubit(3, 5), cirq.GridQubit(3, 6), cirq.GridQubit(3, 7), cirq.GridQubit(4, 0), cirq.GridQubit(4, 1), cirq.GridQubit(4, 2), cirq.GridQubit(4, 3), cirq.GridQubit(4, 4), cirq.GridQubit(4, 5), cirq.GridQubit(4, 6), cirq.GridQubit(4, 7), cirq.GridQubit(5, 0), cirq.GridQubit(5, 1), cirq.GridQubit(5, 2), cirq.GridQubit(5, 3), cirq.GridQubit(5, 4), cirq.GridQubit(5, 5), cirq.GridQubit(5, 6), cirq.GridQubit(5, 7), cirq.GridQubit(6, 0), cirq.GridQubit(6, 1), cirq.GridQubit(6, 2), cirq.GridQubit(6, 3), cirq.GridQubit(6, 4), cirq.GridQubit(6, 5), cirq.GridQubit(6, 6), cirq.GridQubit(6, 7), cirq.GridQubit(7, 0), cirq.GridQubit(7, 1), cirq.GridQubit(7, 2), cirq.GridQubit(7, 3), cirq.GridQubit(7, 4), cirq.GridQubit(7, 5), cirq.GridQubit(7, 6), cirq.GridQubit(7, 7)]


Operations on the Qubits:

1) Pauli Operators:

   Cirq provides the Pauli operators X, Y and Z as cirq.X, cirq.Y and cirq.Z respectively. Together with the identity operator cirq.I, these three operators form a complete basis for the set of all unitary transformations on a single qubit. That is, any quantum circuit on a single qubit can be represented by a linear combination (weighted sum) of the X,Y,Z and I operators applied to that qubit.

  Observables are, in general, some sort of measurable property of a circuit. At its very simplest, this could be whether a qubit measures to be |0> or |1> in the standard computational basis.

Notable gates in Cirq:

In Cirq, the main gates are :

cirq.MeasurementGate-This is a measurement in the computational basis. This gate can be applied to a variable number of qubits.

cirq.X / cirq.Y / cirq.Z :The Pauli gates X, Y, and Z which rotate the state by one half-turn around the X,Y or Z axis respectively

cirq.CZ :The controlled-Z gate. A two qubit gate that phases the |11⟩ state

cirq.CNOT: The controlled-X gate. This gate swaps the |11⟩ and |10⟩ states

cirq.SWAP: The swap gate swaps the |01⟩ and |10⟩ states

The CZ,CNOT and SWAP are two qubit gates that act on 2 qubits, whilst the X,Y,Z gates are single qubit

Hadamard Gate:

In order to create superposition state of a qubit, apply the Hadamard gate which creates an equal superposition of the states 0 and 1, or on measurement the state has a 50% chance of collapsing into state 0 and a 50% chance of collapsing into state 1. Then  apply a CNOT gate to entangle qubits q0 and q1.

Create a quantum circuit in Cirq as follows that will achieve quantum entanglement and measure the output

circuit=cirq.Circuit(cirq.H(q0), cirq.CNOT(q0,q1), cirq.measure(q0,q1))

#Print the Circuit
print(circuit)

0: ───H───@───M───
                        │         │
1: ───────X───M───

@ is the controlled qubit and the X is the target qubit

Run the Circuit on the Cirq Simulator

#Create the simulator object.
simulator=Cirq.Simulator()

#get the result by calling the run() function.
result=simulator.run(circuit,repetitions=20)
print(result)


In short it is a 3 step operatons

Step 1 : Define and Initialize the Qubits

Step 2: Perform operations on the Qubits

Step 3: Run the Circuit on the Circuit simulator and measure the output

Alternate Approach:

Step 1: Instantiate an empty circuit using the syntax cirq.Circuit()
Step 2: Append the gates using the append function

# Generate the Bell State:
# sqrt(2) * ( |00> + |11> )
bell_circuit = cirq.Circuit()
a, b = cirq.LineQubit.range(2)
bell_circuit.append(cirq.H(a))
bell_circuit.append(cirq.CNOT(a,b))

# Initialize Simulator
s=cirq.Simulator()

print('Simulate the circuit:')
results=s.simulate(bell_circuit)
print(results)


# add a measurement at the end for sampling purpose
bell_circuit.append(cirq.measure(a, b, key='result'))

print('Sample the circuit:')
samples=s.run(bell_circuit, repetitions=1000)


Unitary Matrices

Most quantum operations have a unique unitary matrix representation. We can access the matrix by applying cirq.unitary() which returns the unitary matrix that represents the object.

>>> print(cirq.unitary(cirq.X)) #Unitary of the X gate
[[0.+0.j 1.+0.j]
 [1.+0.j 0.+0.j]]
>>>
>>> a, b = cirq.LineQubit.range(2) #Unitary of SWAP operator on two qubits
>>> print(cirq.unitary(cirq.SWAP(a, b)))
[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 1.+0.j 0.+0.j]
 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 1.+0.j]]
>>>
>>> print(cirq.unitary(cirq.Circuit(cirq.X(a), cirq.SWAP(a, b)))) #unitary of a random circuit we created by applying X and SWAP gate
[[0.+0.j 0.+0.j 1.+0.j 0.+0.j]
 [1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 1.+0.j]
 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]]

Moment:

In Cirq, a Moment is a fundamental unit of a quantum circuit, representing a collection of operations that operate on different sets of qubits.Each Moment can contain multiple operations, such as gates, and is structured to execute these operations during a specific time slice.

The Circuit object in Cirq is an ordered series of Moment objects, allowing for efficient construction and manipulation of quantum circuits.

In other words, a moment is a collection of operations that all act during a time interval.
 
[circuit]  [Operations] [qubit]