Syntax

SpinQit supports three programming syntaxes: native SpinQit Python syntax, OpenQASM 2.0 syntax, and IBM Qiskit Python syntax.

SpinQit Python

SpinQit allows users to define arbitrary quantum circuits. The basic concepts in SpinQit Python syntax are as follows.

Circuit: In SpinQit, each quantum program is a Circuit instance.

Quantum register: A quantum register has a certain number of qubits, and must be allocated by a circuit using allocateQubits. A qubit is represented by the register name and its index.

Classical register: A classical register has a certain number of classical bits, and must be allocated by a circuit using allocateClbits. A classical bit is represented by the register name and its index. A classical bit stores a measurement result in the quantum program, which is used by subsequent conditional statements.

Quantum gates: SpinQit defines 22 logical quantum gates (I, H, X, Y, Z, Rx, Ry, Rz, P, T, Td, S, Sd, CX/CNOT, CY, CZ, U, CP, SWAP, CCX, Ph, CSWAP) and two special gates (MEASURE and BARRIER). Specifically, P is the phase-shift gate, while Ph is the global-phase gate.

There is a special gate named StateVector which directly initializes the qubits to a specific state, but this gate is only supported by the torch simulator backend.

Instruction: An instruction consists of a quantum gate, qubits, optional classical bits, and an optional rotation angle in radians. SpinQit uses << to add an instruction to a circuit, as shown in the example earlier.

Custom quantum gate: SpinQit provides a gate builder to define a custom quantum gate. The builder builds a gate based on sub-gates. Qubit indices and an optional parameter lambda are defined for each sub-gate. For example, a custom gate can be defined as follows:

param_lambda = lambda params: params[0]
builder = GateBuilder(2)
builder.append(H, [0])
builder.append(CX, [0, 1])
builder.append(Rx, [0], param_lambda)
builder.append(Rx, [0], pi)
g = builder.to_gate()
circ << (g, qreg, pi)

ControlledGate is a class that adds a control qubit to a base gate and creates a new controlled gate.

cswap = ControlledGate(SWAP)
circ << (cswap, (q[0], q[1], q[2]))

Parameter

Rotation gates and phase-shift gates take an angle in radians. This parameter can be a constant real number, or it can be a variable used in a variational quantum algorithm. A constant angle can be passed directly to a gate. To create trainable parameters, use Circuit.add_params() and pass the resulting parameters to the gates. Parameters can also be combined with constants or with other parameters in an expression, as shown below.

circuit = Circuit()
q=circuit.allocateQubits(qubit_num)
weight = circuit.add_params(shape=(2,)) 
noise = circuit.add_params(shape=(2,)) 

for i in range(qubit_num):
    circuit << (X, q[i])
    circuit << (H, q[i])
    circuit << (Ry, q[i], weight[0])
    circuit << (Rz, q[i], weight[1])
    circuit << (P, q[i], weight[0] + noise[0])
    circuit << (P, q[i], weight[1] + noise[1])

Conditions based on measurements: In SpinQit, Circuit has a measure method to measure some of the qubits and store the results in classical bits. This method inserts a special MEASURE gate into the circuit. After the measurement, a gate can be applied conditionally based on the values of classical bits. Such control flow is also known as cif. A condition in SpinQit is a tuple containing a list of classical bits, a comparator string ('==', '!=', '>', '>=', '<', or '<='), and an integer. The | operator is used to add a condition to an instruction. The usage is as follows:

circ = Circuit()
q = circ.allocateQubits(2)
c = circ.allocateClbits(2)
circ << (H, q[0])
circ << (X, q[1])
circ.measure(q[0], c[0])
circ << (H, q[1]) | (c, '==', 0)

The MEASURE gate cannot be used in a custom gate or with cif. Currently, this feature can only be executed by the basic classical simulator.

OpenQASM 2.0

SpinQit supports OpenQASM 2.0. The basic gates allowed in SpinQit include id, x, y, z, h, rx, ry, rz, t, tdg, s, sdg, p, cx, cy, cz, swap, ccx, u, U, CX, measure, and barrier. Other standard gates in OpenQASM can be called by including “qelib1.inc”, which is provided by SpinQit and is exactly the same as the library file in OpenQASM.

OPENQASM 2.0;
include "qelib1.inc";

gate bell a,b
{
h a;
cx a,b;
}

qreg q[2];
creg c[2];

h q[0];
cx q[0],q[1];
bell q[0],q[1];

IBM Qiskit

SpinQit also supports the IBM Qiskit Python interface. The version supported by SpinQit is qiskit-0.31.0 (qiskit-terra-0.18.3). We include the qiskit.circuit package and some related packages in SpinQit. Therefore, you can construct a Qiskit QuantumCircuit instance and run it with SpinQit, even without installing Qiskit. In particular, SpinQit supports the QFT, QPE, and Grover primitives in Qiskit (in spinqit.qiskit.circuit.library), so you can build quantum algorithms based on these primitives. Nevertheless, SpinQit does not include all Qiskit code. If you want to use the qiskit.algorithm package and run the circuit on SpinQit backends, you still need to install Qiskit.

from spinqit.qiskit.circuit import QuantumCircuit
from spinqit import get_compiler, get_basic_simulator, BasicSimulatorConfig
from math import pi

qc = QuantumCircuit(2)
qc.h(0)
qc.rx(pi, 1)
qc.cx(0, 1)

compiler = get_compiler('qiskit')
simulator = get_basic_simulator()
config = BasicSimulatorConfig()

exe = compiler.compile(qc, 0)
result = simulator.execute(exe, config)
print(result.states)
print(result.counts)