Skip to content

Commit

Permalink
Merge pull request #23 from chriseclectic/fix-quantumprogram
Browse files Browse the repository at this point in the history
Combine results, apply controlled gates and measure to whole registers
  • Loading branch information
awcross1 authored Aug 8, 2017
2 parents e778cad + d9673d0 commit 59dee63
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 43 deletions.
17 changes: 12 additions & 5 deletions qiskit/_quantumcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def add(self, *regs):
self.regs[register.name] = register
else:
raise QISKitError("register name \"%s\" already exists"
% register.name)
% register.name)

def _check_qreg(self, register):
"""Raise exception if r is not in this circuit or not qreg."""
Expand Down Expand Up @@ -174,10 +174,17 @@ def qasm(self):

def measure(self, qubit, cbit):
"""Measure quantum bit into classical bit (tuples)."""
self._check_qubit(qubit)
self._check_creg(cbit[0])
cbit[0].check_range(cbit[1])
return self._attach(Measure(qubit, cbit, self))
if isinstance(qubit, QuantumRegister) and \
isinstance(cbit, ClassicalRegister) and len(qubit) == len(cbit):
instructions = InstructionSet()
for i in range(qubit.size):
instructions.add(self.measure((qubit, i), (cbit, i)))
return instructions
else:
self._check_qubit(qubit)
self._check_creg(cbit[0])
cbit[0].check_range(cbit[1])
return self._attach(Measure(qubit, cbit, self))

def reset(self, quantum_register):
"""Reset q."""
Expand Down
34 changes: 34 additions & 0 deletions qiskit/_quantumprogram.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import os
import string
import re
import copy

# use the external IBMQuantumExperience Library
from IBMQuantumExperience.IBMQuantumExperience import IBMQuantumExperience
Expand Down Expand Up @@ -1182,6 +1183,39 @@ def __str__(self):
"""
return self.__result['status']

def __iadd__(self, other):
"""Append a Result object to current Result object.
Arg:
other (Result): a Result object to append.
Returns:
The current object with appended results.
"""
if self.__qobj['config'] == other.__qobj['config']:
if isinstance(self.__qobj['id'], str):
self.__qobj['id'] = [self.__qobj['id']]
self.__qobj['id'].append(other.__qobj['id'])
self.__qobj['circuits'] += other.__qobj['circuits']
self.__result['result'] += other.__result['result']
return self
else:
raise QISKitError('Result objects have different configs and cannot be combined.')

def __add__(self, other):
"""Combine Result objects.
Note that the qobj id of the returned result will be the same as the
first result.
Arg:
other (Result): a Result object to combine.
Returns:
A new Result object consisting of combined objects.
"""
ret = copy.deepcopy(self)
ret += other
return ret

def get_error(self):
if self.__result['status'] == 'ERROR':
return self.__result['result'][0]
Expand Down
19 changes: 14 additions & 5 deletions qiskit/extensions/standard/ch.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
from qiskit import Gate
from qiskit import CompositeGate
from qiskit.extensions.standard import header

from qiskit._quantumregister import QuantumRegister
from qiskit._instructionset import InstructionSet

class CHGate(Gate):
"""controlled-H gate."""
Expand All @@ -49,10 +50,18 @@ def reapply(self, circ):

def ch(self, ctl, tgt):
"""Apply CH from ctl to tgt."""
self._check_qubit(ctl)
self._check_qubit(tgt)
self._check_dups([ctl, tgt])
return self._attach(CHGate(ctl, tgt, self))
if isinstance(ctl, QuantumRegister) and \
isinstance(tgt, QuantumRegister) and len(ctl) == len(tgt):
# apply cx to qubits between two registers
instructions = InstructionSet()
for i in range(ctl.size):
instructions.add(self.ch((ctl, i), (tgt, i)))
return instructions
else:
self._check_qubit(ctl)
self._check_qubit(tgt)
self._check_dups([ctl, tgt])
return self._attach(CHGate(ctl, tgt, self))


QuantumCircuit.ch = ch
Expand Down
19 changes: 14 additions & 5 deletions qiskit/extensions/standard/crz.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
from qiskit import Gate
from qiskit import CompositeGate
from qiskit.extensions.standard import header

from qiskit._quantumregister import QuantumRegister
from qiskit._instructionset import InstructionSet

class CrzGate(Gate):
"""controlled-rz gate."""
Expand Down Expand Up @@ -51,10 +52,18 @@ def reapply(self, circ):

def crz(self, theta, ctl, tgt):
"""Apply crz from ctl to tgt with angle theta."""
self._check_qubit(ctl)
self._check_qubit(tgt)
self._check_dups([ctl, tgt])
return self._attach(CrzGate(theta, ctl, tgt, self))
if isinstance(ctl, QuantumRegister) and \
isinstance(tgt, QuantumRegister) and len(ctl) == len(tgt):
# apply cx to qubits between two registers
instructions = InstructionSet()
for i in range(ctl.size):
instructions.add(self.crz(theta, (ctl, i), (tgt, i)))
return instructions
else:
self._check_qubit(ctl)
self._check_qubit(tgt)
self._check_dups([ctl, tgt])
return self._attach(CrzGate(theta, ctl, tgt, self))


QuantumCircuit.crz = crz
Expand Down
18 changes: 14 additions & 4 deletions qiskit/extensions/standard/cu1.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
from qiskit import Gate
from qiskit import CompositeGate
from qiskit.extensions.standard import header
from qiskit._quantumregister import QuantumRegister
from qiskit._instructionset import InstructionSet


class Cu1Gate(Gate):
Expand Down Expand Up @@ -51,10 +53,18 @@ def reapply(self, circ):

def cu1(self, theta, ctl, tgt):
"""Apply cu1 from ctl to tgt with angle theta."""
self._check_qubit(ctl)
self._check_qubit(tgt)
self._check_dups([ctl, tgt])
return self._attach(Cu1Gate(theta, ctl, tgt, self))
if isinstance(ctl, QuantumRegister) and \
isinstance(tgt, QuantumRegister) and len(ctl) == len(tgt):
# apply cx to qubits between two registers
instructions = InstructionSet()
for i in range(ctl.size):
instructions.add(self.cu1(theta, (ctl, i), (tgt, i)))
return instructions
else:
self._check_qubit(ctl)
self._check_qubit(tgt)
self._check_dups([ctl, tgt])
return self._attach(Cu1Gate(theta, ctl, tgt, self))


QuantumCircuit.cu1 = cu1
Expand Down
18 changes: 14 additions & 4 deletions qiskit/extensions/standard/cu3.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
from qiskit import Gate
from qiskit import CompositeGate
from qiskit.extensions.standard import header
from qiskit._quantumregister import QuantumRegister
from qiskit._instructionset import InstructionSet


class Cu3Gate(Gate):
Expand Down Expand Up @@ -57,10 +59,18 @@ def reapply(self, circ):

def cu3(self, theta, phi, lam, ctl, tgt):
"""Apply cu3 from ctl to tgt with angle theta, phi, lam."""
self._check_qubit(ctl)
self._check_qubit(tgt)
self._check_dups([ctl, tgt])
return self._attach(Cu3Gate(theta, phi, lam, ctl, tgt, self))
if isinstance(ctl, QuantumRegister) and \
isinstance(tgt, QuantumRegister) and len(ctl) == len(tgt):
# apply cx to qubits between two registers
instructions = InstructionSet()
for i in range(ctl.size):
instructions.add(self.cu3(theta, phi, lam, (ctl, i), (tgt, i)))
return instructions
else:
self._check_qubit(ctl)
self._check_qubit(tgt)
self._check_dups([ctl, tgt])
return self._attach(Cu3Gate(theta, phi, lam, ctl, tgt, self))


QuantumCircuit.cu3 = cu3
Expand Down
18 changes: 14 additions & 4 deletions qiskit/extensions/standard/cx.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
from qiskit import Gate
from qiskit import CompositeGate
from qiskit.extensions.standard import header
from qiskit._quantumregister import QuantumRegister
from qiskit._instructionset import InstructionSet


class CnotGate(Gate):
Expand Down Expand Up @@ -49,10 +51,18 @@ def reapply(self, circ):

def cx(self, ctl, tgt):
"""Apply CNOT from ctl to tgt."""
self._check_qubit(ctl)
self._check_qubit(tgt)
self._check_dups([ctl, tgt])
return self._attach(CnotGate(ctl, tgt, self))
if isinstance(ctl, QuantumRegister) and \
isinstance(tgt, QuantumRegister) and len(ctl) == len(tgt):
# apply cx to qubits between two registers
instructions = InstructionSet()
for i in range(ctl.size):
instructions.add(self.cx((ctl, i), (tgt, i)))
return instructions
else:
self._check_qubit(ctl)
self._check_qubit(tgt)
self._check_dups([ctl, tgt])
return self._attach(CnotGate(ctl, tgt, self))


QuantumCircuit.cx = cx
Expand Down
19 changes: 14 additions & 5 deletions qiskit/extensions/standard/cy.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
from qiskit import Gate
from qiskit import CompositeGate
from qiskit.extensions.standard import header

from qiskit._quantumregister import QuantumRegister
from qiskit._instructionset import InstructionSet

class CyGate(Gate):
"""controlled-Y gate."""
Expand All @@ -49,10 +50,18 @@ def reapply(self, circ):

def cy(self, ctl, tgt):
"""Apply CY to circuit."""
self._check_qubit(ctl)
self._check_qubit(tgt)
self._check_dups([ctl, tgt])
return self._attach(CyGate(ctl, tgt, self))
if isinstance(ctl, QuantumRegister) and \
isinstance(tgt, QuantumRegister) and len(ctl) == len(tgt):
# apply cx to qubits between two registers
instructions = InstructionSet()
for i in range(ctl.size):
instructions.add(self.cy((ctl, i), (tgt, i)))
return instructions
else:
self._check_qubit(ctl)
self._check_qubit(tgt)
self._check_dups([ctl, tgt])
return self._attach(CyGate(ctl, tgt, self))


QuantumCircuit.cy = cy
Expand Down
19 changes: 14 additions & 5 deletions qiskit/extensions/standard/cz.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
from qiskit import Gate
from qiskit import CompositeGate
from qiskit.extensions.standard import header

from qiskit._quantumregister import QuantumRegister
from qiskit._instructionset import InstructionSet

class CzGate(Gate):
"""controlled-Z gate."""
Expand All @@ -48,10 +49,18 @@ def reapply(self, circ):

def cz(self, ctl, tgt):
"""Apply CZ to circuit."""
self._check_qubit(ctl)
self._check_qubit(tgt)
self._check_dups([ctl, tgt])
return self._attach(CzGate(ctl, tgt, self))
if isinstance(ctl, QuantumRegister) and \
isinstance(tgt, QuantumRegister) and len(ctl) == len(tgt):
# apply cx to qubits between two registers
instructions = InstructionSet()
for i in range(ctl.size):
instructions.add(self.cz((ctl, i), (tgt, i)))
return instructions
else:
self._check_qubit(ctl)
self._check_qubit(tgt)
self._check_dups([ctl, tgt])
return self._attach(CzGate(ctl, tgt, self))


QuantumCircuit.cz = cz
Expand Down
31 changes: 25 additions & 6 deletions test/python/test_quantumprogram.py
Original file line number Diff line number Diff line change
Expand Up @@ -802,12 +802,8 @@ def test_run_program(self):
qc2.cx(qr[0], qr[1])
qc2.cx(qr[0], qr[2])
qc3.h(qr)
qc2.measure(qr[0], cr[0])
qc3.measure(qr[0], cr[0])
qc2.measure(qr[1], cr[1])
qc3.measure(qr[1], cr[1])
qc2.measure(qr[2], cr[2])
qc3.measure(qr[2], cr[2])
qc2.measure(qr, cr)
qc3.measure(qr, cr)
circuits = ['qc2', 'qc3']
shots = 1024 # the number of shots in the experiment.
backend = 'local_qasm_simulator'
Expand All @@ -821,6 +817,29 @@ def test_run_program(self):
'100': 117, '000': 129, '101': 126,
'010': 145, '011': 125})

def test_combine_results(self):
"""Test run.
If all correct should the data.
"""
QP_program = QuantumProgram()
qr = QP_program.create_quantum_register("qr", 1)
cr = QP_program.create_classical_register("cr", 1)
qc1 = QP_program.create_circuit("qc1", [qr], [cr])
qc2 = QP_program.create_circuit("qc2", [qr], [cr])
qc1.measure(qr[0], cr[0])
qc2.x(qr[0])
qc2.measure(qr[0], cr[0])
shots = 1024 # the number of shots in the experiment.
backend = 'local_qasm_simulator'
res1 = QP_program.execute(['qc1'], backend=backend, shots=shots)
res2 = QP_program.execute(['qc2'], backend=backend, shots=shots)
counts1 = res1.get_counts('qc1')
counts2 = res2.get_counts('qc2')
res1 += res2 # combine results
counts12 = [res1.get_counts('qc1'), res1.get_counts('qc2')]
self.assertEqual(counts12, [counts1, counts2])

def test_local_qasm_simulator(self):
"""Test execute.
Expand Down

0 comments on commit 59dee63

Please sign in to comment.