QISKit (Quantum Information Software Kit) is a Python software development kit (SDK) that you can use to create your quantum programs, based in circuits over OpenQASM 2.0 Specs, compile and execute the SDK on several backends (via our upgraded 16 qubit chip, as well as online and local simulators). For the online backend QISKit, use our python API connector to the IBM Quantum Experience.

In this tutorial, learn how to use the QISKit SDK, from a developer’s point of view. We will show you how to install and start to use the SDK tools.

Install QISKit

The easiest way to install QISKit is to use the Anaconda Python distribution. Visit the Anaconda site for information on how to install Anaconda.

After you’ve installed Anaconda, install your QISKit from the git repository.

  • Clone the repo:
  • git clone https://github.com/IBM/qiskit-sdk-py.git
    cd qiskit-sdk-py-dev
    
  • Create the environment with the following dependencies: make env

Use the quantum examples

You can use the examples in an easy way with Jupyter or Python.
  • Add your API token to the file "Qconfig.py". Get the file from the IBM Quantum Experience account: cp tutorial/Qconfig.py.default Qconfig.py
  • Run the Jupyter notebook by using the command make run

Put QISKit to use

Step 1. Create a program

First, you need to import the QuantumProgram from QISKit

import sys
sys.path.append("../../") # solve the relative dependencies if you clone QISKit from the Git repo and use like a global.

from qiskit import QuantumProgram 
import Qconfig

The basic elements that you need to create your first program are the QuantumProgram, one circuit, one quantum register, and one classical register.

# Creating Programs

# create your first QuantumProgram object instance. Q_program = 
QuantumProgram() 

# Creating Registers

# create your first Quantum Register called "qr" with 2 Qbit qr = 
Q_program.create_quantum_registers("qr", 2)

# create your first Classical Register called "cr" with 2 bit cr = 
Q_program.create_classical_registers("cr", 2) 

# Creating Circuits

# create your first Quantum Circuit called "qc" related with your Quantum Regis ter "qr"

# and your Classical Register "cr"

qc = Q_program.create_circuit("qc", ["qr"], ["cr"]) 

Output:
   >> quantum_registers created: qr 2
   >> classical_registers created: cr 2

Another option for creating your QuantumProgram instance is to define a dictionary that includes all the components of your program.

Q_SPECS = {
    "name": "Program-tutorial",
    "circuits": [{
         "name": "Circuit",
         "quantum_registers": [{
             "name":"qr",
             "size": 4 
         }],
         "classical_registers": [{
              "name":"cr",
              "size": 4
         }]}],
}

One program must have a name and one circuit array. Any circuit must have a name, and it can have several quantum registers and several classical registers. Every register needs to have a name and the number of the elements (Qbits or bits).

After that, you can use this dictionary definition like the specs of one QuantumProgram object to initialize it.

Q_program = QuantumProgram(specs=Q_SPECS) 

Output
   >> quantum_registers created: qr 4
   >> classical_registers created: cr 4

You can get every component from you new_Q_program to use.

#get the components.

# get the circuit by Name
circuit = Q_program.get_circuit("Circuit")

# get the Quantum Register by Name
quantum_r = Q_program.get_quantum_registers("qr")

# get the Classical Register by Name
classical_r = Q_program.get_classical_registers('cr')

Step 2. Add gates to your circuit

After you create the circuit with its registers, you can add gates to manipulate the registers. The following listing shows you all the gates that you can use.

You can find extensive information about these gates and how use them in our Quantum Experience User Guide.

# H (Hadamard) gate to the Qbit 0 in the Quantum Register "qr" 
circuit.h(quantum_r[0]) 

# Pauli X gate to the Qbit 1 in the Quantum Register "qr"
circuit.x(quantum_r[1])

# Pauli Y gate to the Qbit 2 in the Quantum Register "qr"
circuit.y(quantum_r[2])

# Pauli Z gate to the Qbit 3 in the Quantum Register "qr"
circuit.z(quantum_r[3])

# Cnot (Controlled-NOT)gate from Qbit 0 to the Qbit 3
circuit.cx(quantum_r[0], quantum_r[3])

# add a barrier to your circuit
circuit.barrier()

# first physical gate: u1(lambda) to Qbit 0
circuit.u1(0.3, quantum_r[0])

# second physical gate: u2(phi,lambda) to Qbit 1
circuit.u2(0.3, 0.2, quantum_r[1])

# second physical gate: u3(theta,phi,lambda) to Qbit 2
circuit.u3(0.3, 0.2, 0.1, quantum_r[2])

# S Phase gate to Qbit 0
circuit.s(quantum_r[0])

# T Phase gate to Qbit 1
circuit.t(quantum_r[1])

# identity gate to Qbit 1
circuit.iden(quantum_r[1])

# Classical if, from Qbit2 gate Z to classical bit 1
circuit.z(quantum_r[2]).c_if(classical_r, 1)

# measure gate from the Qbit 0 to Classical bit 0
circuit.measure(quantum_r[0], classical_r[0]) 

Step 3. Extract QASM

You can obtain a QASM representation of your code.

Input:

# QASM from a program

QASM_source = Q_program.get_qasm("Circuit")

print(QASM_source)

Output:

OPENQASM 2.0;
include "qelib1.inc";
qreg qr[4];
creg cr[4];
h qr[0];
x qr[1];
y qr[2];
z qr[3];
cx qr[0],qr[3];
barrier qr[0],qr[1],qr[2],qr[3];
u1(0.300000000000000) qr[0];
u2(0.300000000000000,0.200000000000000) qr[1];
u3(0.300000000000000,0.200000000000000,0.100000000000000) qr[2];
u1(1.570796326794897) qr[0];
u1(0.785398163397448) qr[1];
id qr[1];
if(cr==1) z qr[2];
measure qr[0] -> cr[0];

Notice that both codes don't have the same notation. The second one returns a conversion from every H, X, Y, Z gate the the u1, u2 and u3 represents.

Step 4. Compile and run or execute

Input

device = 'simulator' #Backed where execute your program, in this case in the on line simulator 
circuits = ['Circuit] #Group of circuits to exec 

Q_program.set_api(Qconfig.APItoken, Qconfig.config["url"]) 
#set the APIToken and API url 

Output: True

Input:

Q_program.compile(circuits, device) # Compile your program

result = Q_program.run(wait=2, timeout=240) # Run your 
program in the device and check the execution result 
every 2 seconds 

print(result)

print(Q_program.get_qasms(circuits)) (circuits))

Output


{'qasm': 'OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg qr[4];\ncreg cr[4];\nu1(3
.141592653589793) qr[3];\nu3(3.141592653589793,1.5707963267948966,1.5707963267
948966) qr[2];\nu3(3.141592653589793,0.0,3.141592653589793) qr[1];\nu2(0.0,3.1
41592653589793) qr[0];\ncx qr[0],qr[3];\nbarrier qr[0],qr[1],qr[2],qr[3];\nu1(
0.3) qr[0];\nu1(1.570796326794897) qr[0];\nu2(0.3,0.2) qr[1];\nu1(0.7853981633
97448) qr[1];\nid qr[1];\nu3(0.3,0.2,0.1) qr[2];\nif(cr==1) u1(3.1415926535897
93) qr[2];\nmeasure qr[0] -> cr[0];\n'}
status = RUNNING (2 seconds)
status = RUNNING (4 seconds)
status = RUNNING (6 seconds)
{'qasms': [{'qasm': '\ninclude "qelib1.inc";\nqreg qr[4];\ncreg cr[4];\nu1(3.1
41592653589793) qr[3];\nu3(3.141592653589793,1.5707963267948966,1.570796326794
8966) qr[2];\nu3(3.141592653589793,0.0,3.141592653589793) qr[1];\nu2(0.0,3.141
592653589793) qr[0];\ncx qr[0],qr[3];\nbarrier qr[0],qr[1],qr[2],qr[3];\nu1(0.
3) qr[0];\nu1(1.570796326794897) qr[0];\nu2(0.3,0.2) qr[1];\nu1(0.785398163397
448) qr[1];\nid qr[1];\nu3(0.3,0.2,0.1) qr[2];\nif(cr==1) u1(3.141592653589793
) qr[2];\nmeasure qr[0] -> cr[0];\n', 'status': 'DONE', 'executionId': '62c466
7cf29a35ad009e8754baa85c80', 'result': {'date': '2017-05-14T08:45:36.552Z', 'd
ata': {'time': 0.2707841396331787, 'counts': {'0000': 516, '0001': 508}}}}], '
shots': 1024, 'backend': {'name': 'simulator'}, 'status': 'COMPLETED', 'maxCre
dits': 3, 'usedCredits': 0, 'creationDate': '2017-05-14T08:45:35.262Z', 'delet
ed': False, 'id': '451903c7de63febb2614adbdeeaeb485', 'userId': '933a590a13327
c52eb5310484d6bcf54'}

When you run a program, the result can be:

possible program output

The run() command waits until timeout or when it receives the "COMPLETED" or some error message.

You can use the execute() command to make the compile and run command happen in a unique step.

Input

result = Q_program.execute(circuits, device, wait=2, timeout=240) 

print(Q_program.get_qasms(circuits))

Output:


{'qasm': 'OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg qr[4];\ncreg cr[4];\nu1(3
.141592653589793) qr[3];\nu3(3.141592653589793,1.5707963267948966,1.5707963267
948966) qr[2];\nu3(3.141592653589793,0.0,3.141592653589793) qr[1];\nu2(0.0,3.1
41592653589793) qr[0];\ncx qr[0],qr[3];\nbarrier qr[0],qr[1],qr[2],qr[3];\nu1(
0.3) qr[0];\nu1(1.570796326794897) qr[0];\nu2(0.3,0.2) qr[1];\nu1(0.7853981633
97448) qr[1];\nid qr[1];\nu3(0.3,0.2,0.1) qr[2];\nif(cr==1) u1(3.1415926535897
93) qr[2];\nmeasure qr[0] -> cr[0];\n'}
status = RUNNING (2 seconds)
status = RUNNING (4 seconds)
status = RUNNING (6 seconds)

Compile parameters

The quantum compile parameters are: Q_program.compile(circuits, device="simulator", shots=1024, max_credits=3, basis_gates=None, coupling_map=None)

  • circuits: Array of circuit to compile
  • device: Backend
    ["ibmqx_qasm_simulator", #Online simulator
    "ibmqx2", #Online RealChip, 5Qbits
    "ibmqx3:, #Online RealChip, 16Qbits
    "local_unitary_simulator", #Local unitary Simulator
    "local_qasm_simulator"] # Local Simulator
  • shots: Number of shots, only for real chips
  • max_credits: Maximum number of the credits to spend in the executions. If the executions are more expensive, the job is aborted, only the real chips
  • basis_gates: are the base gates. By default, they are: u1,u2,u3,cx,id
  • coupling_map: Object that represent the physical/topological Layout in a chip.

Run parameters

The run parameters are: Q_program.run(wait=5, timeout=60)
  • wait: Time to wait to check if the execution is COMPLETED.
  • timeout: Timeout of the execution.

Execute parameters

The execute command has the combined parameters of Compile and Run:

Q_program.execute(circuits, device, shots=1024, max_credits=3, basis_gates=None, wait=5, timeout=60, basis_gates=None, coupling_map=None,)

Step 5. Execute in a real chip

Input:


device = 'qx5qv2' #Backed where execute your program, in this case in the Real Quantum Chip online
circuits = [circuit] #Group of circuits to exec
shots = 1024m        #Number of shots to run the program (experiment), Maximum 8192 shots.
max_credits=3s.      #Maximum number of the credits to spend in the executions

result = Q_program.execute(circuits, device, shots, max_credits=3, wait+10, timeout=240)

print(Q_program.get_qasms(circuits))

Output:

{'qasm': 'OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg qr[4];\ncreg cr[4];\nu1(3
.141592653589793) qr[3];\nu3(3.141592653589793,1.5707963267948966,1.5707963267
948966) qr[2];\nu3(3.141592653589793,0.0,3.141592653589793) qr[1];\nu2(0.0,3.1
41592653589793) qr[0];\ncx qr[0],qr[3];\nbarrier qr[0],qr[1],qr[2],qr[3];\nu1(
0.3) qr[0];\nu1(1.570796326794897) qr[0];\nu2(0.3,0.2) qr[1];\nu1(0.7853981633
97448) qr[1];\nid qr[1];\nu3(0.3,0.2,0.1) qr[2];\nif(cr==1) u1(3.1415926535897
93) qr[2];\nmeasure qr[0] -> cr[0];\n'}

Result

You can access the result using get_counts:

Input: Q_program.get_counts("Circuit")
Output: {'0000': 516, '0001': 508}

Or you can use the function tool get_data(n) to obtain it directly:

Input: Q_program.get_data(result,0)
Output: {'counts': {'00000': 532, '00001': 492}, 'time': 14.103801012039185}

Conclusion

Want more information about the IBM Quantum Experience? We have other tutorials that introduce you to more complex concepts directly related to the upgraded service. For more information about how to use the Quantum Experience, consult the tutorials on IBM Bluemix or check out the community.

5 Comments on "A developer’s guide to using the Quantum QISKit SDK"

  1. […] InfoQ reported, IBM provides a Python-based quantum development SDK called QISKit that can be used to run experiments on the IBM Q processors. IBM’s new 16 qubit […]

Join The Discussion

Your email address will not be published. Required fields are marked *