Skip to content
This repository was archived by the owner on Oct 7, 2019. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 12 additions & 17 deletions referenceqvm/qam.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from referenceqvm.unitary_generator import value_get

from pyquil.quil import Program
from pyquil.quilbase import (Instr,
from pyquil.quilbase import (Gate,
Measurement,
UnaryClassicalInstruction,
BinaryClassicalInstruction)
Expand Down Expand Up @@ -72,9 +72,6 @@ def load_program(self, pyquil_program):
raise NotImplementedError("QAM needs to be subclassed in order to "
"load program")

# synthesize program into instruction list
synthesized_prog = pyquil_program.synthesize()

# create defgate dictionary
defined_gates = {}
for dg in pyquil_program.defined_gates:
Expand All @@ -83,10 +80,9 @@ def load_program(self, pyquil_program):

# if QVM_Unitary, check if all instructions are valid.
invalid = False
for index, action in enumerate(synthesized_prog):
if isinstance(action, Instr):
if (action.operator_name not in self.gate_set.keys()
and action.operator_name not in self.defgate_set.keys()):
for instr in pyquil_program:
if isinstance(instr, Gate):
if not (instr.name in self.gate_set.keys() or instr.name in self.defgate_set.keys()):
invalid = True
break
else:
Expand All @@ -98,7 +94,7 @@ def load_program(self, pyquil_program):
"supported")

# set internal program and counter to their appropriate values
self.program = synthesized_prog
self.program = pyquil_program
self.program_counter = 0

# setup quantum and classical memory
Expand All @@ -121,10 +117,10 @@ def identify_bits(self):
for index, inst in enumerate(self.program):
if isinstance(inst, Measurement):
# instruction is measurement, acts on qbits and cbits
if value_get(inst.arguments[0]) > q_max:
q_max = value_get(inst.arguments[0])
elif value_get(inst.arguments[1]) > c_max:
c_max = value_get(inst.arguments[1])
if value_get(inst.qubit) > q_max:
q_max = value_get(inst.qubit)
elif value_get(inst.classical_reg) > c_max:
c_max = value_get(inst.classical_reg)
elif isinstance(inst, UnaryClassicalInstruction):
# instruction acts on cbits
if value_get(inst.target) > c_max:
Expand All @@ -135,10 +131,9 @@ def identify_bits(self):
c_max = value_get(inst.left)
elif value_get(inst.right) > c_max:
c_max = value_get(inst.right)
elif isinstance(inst, Instr):
# instruction is Gate or DefGate, acts on qbits
if max(map(lambda x: value_get(x), inst.arguments)) > q_max:
q_max = max(map(lambda x: value_get(x), inst.arguments))
elif isinstance(inst, Gate):
if max(map(lambda x: value_get(x), inst.qubits)) > q_max:
q_max = max(map(lambda x: value_get(x), inst.qubits))
q_max += 1 # 0-indexed
c_max += 1 # 0-indexed
q_limit = 51
Expand Down
7 changes: 3 additions & 4 deletions referenceqvm/qvm_unitary.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,17 @@ def transition(self, instruction):
"""
Implements a transition on the unitary-qvm.

:param instruction: QuilAction gate to be implemented
:param Gate instruction: QuilAction gate to be implemented
"""
if instruction.operator_name in self.gate_set or \
instruction.operator_name in self.defgate_set:
if instruction.name in self.gate_set or instruction.name in self.defgate_set:
# get the unitary and evolve the state
unitary = tensor_gates(self.gate_set, self.defgate_set,
instruction, self.num_qubits)
self.umat = unitary.dot(self.umat)
self.program_counter += 1
else:
raise TypeError("Gate {} is not in the "
"gate set".format(instruction.operator_name))
"gate set".format(instruction.name))

def unitary(self, pyquil_program):
"""
Expand Down
11 changes: 5 additions & 6 deletions referenceqvm/qvm_wavefunction.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@
import scipy.sparse as sps

from pyquil.quil import Program
from pyquil.quilbase import (Instr,
Measurement,
from pyquil.quilbase import (Measurement,
UnaryClassicalInstruction,
BinaryClassicalInstruction,
ClassicalTrue,
Expand All @@ -59,7 +58,7 @@
JumpConditional,
JumpWhen,
JumpUnless,
Halt)
Halt, Gate)
from pyquil.wavefunction import Wavefunction
from referenceqvm.unitary_generator import lifted_gate, tensor_gates, value_get
from referenceqvm.gates import utility_gates
Expand Down Expand Up @@ -167,16 +166,16 @@ def _transition(self, instruction):
"""
if isinstance(instruction, Measurement):
# perform measurement and modify wf in-place
t_qbit = value_get(instruction.arguments[0])
t_cbit = value_get(instruction.arguments[1])
t_qbit = value_get(instruction.qubit)
t_cbit = value_get(instruction.classical_reg)
measured_val, unitary = self.measurement(t_qbit, psi=None)
self.wf = unitary.dot(self.wf)

# load measured value into classical bit destination
self.classical_memory[t_cbit] = measured_val
self.program_counter += 1

elif isinstance(instruction, Instr):
elif isinstance(instruction, Gate):
# apply Gate or DefGate
unitary = tensor_gates(self.gate_set, self.defgate_set, instruction, self.num_qubits)
self.wf = unitary.dot(self.wf)
Expand Down
14 changes: 7 additions & 7 deletions referenceqvm/tests/test_unitary_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,39 +176,39 @@ def test_single_qubit_gates():

def test_tensor_gates_single_qubit():
prog = Program().inst([Hgate(0)])
test_unitary = tensor_gates(gate_matrix, {}, prog.actions[0][1], 1).toarray()
test_unitary = tensor_gates(gate_matrix, {}, prog.instructions[0], 1).toarray()
true_unitary = gate_matrix['H']
assert np.allclose(test_unitary, true_unitary)

prog = Program().inst([Hgate(0)])
test_unitary = tensor_gates(gate_matrix, {}, prog.actions[0][1], 5).toarray()
test_unitary = tensor_gates(gate_matrix, {}, prog.instructions[0], 5).toarray()
true_unitary = np.kron(np.eye(2**4), gate_matrix['H'])
assert np.allclose(test_unitary, true_unitary)

prog = Program().inst([RXgate(0.2)(3)])
test_unitary = tensor_gates(gate_matrix, {}, prog.actions[0][1], 5).toarray()
test_unitary = tensor_gates(gate_matrix, {}, prog.instructions[0], 5).toarray()
true_unitary = np.kron(np.eye(2**1), np.kron(gate_matrix['RX'](0.2), np.eye(2**3)))
assert np.allclose(test_unitary, true_unitary)

prog = Program().inst([RXgate(0.5)(4)])
test_unitary = tensor_gates(gate_matrix, {}, prog.actions[0][1], 5).toarray()
test_unitary = tensor_gates(gate_matrix, {}, prog.instructions[0], 5).toarray()
true_unitary = np.kron(np.eye(2**0), np.kron(gate_matrix['RX'](0.5), np.eye(2**4)))
assert np.allclose(test_unitary, true_unitary)


def test_tensor_gates_two_qubit():
prog = Program().inst([CNOTgate(0, 1)])
test_unitary = tensor_gates(gate_matrix, {}, prog.actions[0][1], 4).toarray()
test_unitary = tensor_gates(gate_matrix, {}, prog.instructions[0], 4).toarray()
true_unitary = apply_gate(gate_matrix['CNOT'], [0, 1], 4).toarray()
assert np.allclose(test_unitary, true_unitary)

prog = Program().inst([CNOTgate(1, 0)])
test_unitary = tensor_gates(gate_matrix, {}, prog.actions[0][1], 4).toarray()
test_unitary = tensor_gates(gate_matrix, {}, prog.instructions[0], 4).toarray()
true_unitary = apply_gate(gate_matrix['CNOT'], [1, 0], 4).toarray()
assert np.allclose(test_unitary, true_unitary)

prog = Program().inst([CNOTgate(1, 3)])
test_unitary = tensor_gates(gate_matrix, {}, prog.actions[0][1], 4).toarray()
test_unitary = tensor_gates(gate_matrix, {}, prog.instructions[0], 4).toarray()
true_unitary = apply_gate(gate_matrix['CNOT'], [1, 3], 4).toarray()
assert np.allclose(test_unitary, true_unitary)

Expand Down
23 changes: 11 additions & 12 deletions referenceqvm/unitary_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
"""
from collections import Sequence
from numbers import Integral
import warnings

import scipy.sparse as sps
from pyquil.quilbase import *
Expand Down Expand Up @@ -327,33 +326,33 @@ def tensor_gates(gate_set, defgate_set, pyquil_gate, num_qubits):

:param dict gate_set: gate dictionary (name, matrix) pairs
:param dict defgate_set: defined gate dictionary (name, matrix) pairs
:param Instr pyquil_gate: Instruction object for pyQuil gate
:param Gate pyquil_gate: Instruction object for pyQuil gate
:param int num_qubits: number of qubits in Hilbert space

:return: input gate lifted to full Hilbert space and applied
:rtype: np.array
"""
if pyquil_gate.operator_name in gate_set:
if pyquil_gate.name in gate_set:
# Input gate set. Assumed to be standard gate set.
dict_check = gate_set
elif pyquil_gate.operator_name in defgate_set:
elif pyquil_gate.name in defgate_set:
# defined_gates
dict_check = defgate_set
else:
raise ValueError("Instruction (presumed a Gate or DefGate) is not "
"found in standard gate set or defined "
"gate set of program!")

args = tuple(value_get(x) for x in pyquil_gate.arguments) \
if dict_check == gate_matrix else tuple(pyquil_gate.arguments)
args = tuple(value_get(x) for x in pyquil_gate.qubits) \
if dict_check == gate_matrix else tuple(pyquil_gate.qubits)

if pyquil_gate.parameters:
gate = apply_gate(dict_check[pyquil_gate.operator_name]
(*[value_get(p) for p in pyquil_gate.parameters]),
if pyquil_gate.params:
gate = apply_gate(dict_check[pyquil_gate.name]
(*[value_get(p) for p in pyquil_gate.params]),
args,
num_qubits)
else:
gate = apply_gate(dict_check[pyquil_gate.operator_name],
gate = apply_gate(dict_check[pyquil_gate.name],
args,
num_qubits)

Expand Down Expand Up @@ -412,8 +411,8 @@ def value_get(param_obj):
"""
if isinstance(param_obj, (float, int)):
return param_obj
elif isinstance(param_obj, AbstractQubit):
return param_obj.index()
elif isinstance(param_obj, Qubit):
return param_obj.index
elif isinstance(param_obj, Addr):
return param_obj.address
elif isinstance(param_obj, Slot):
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
numpy>=1.11.1
scipy>=0.18.1
pyquil==1.3.0
pyquil==1.4.2
funcsigs

# For testing
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
install_requires=[
"numpy >= 1.11.1",
"scipy >= 0.18.1",
"pyquil >= 1.1.1",
"pyquil >= 1.4.2",
"funcsigs"
],
setup_requires=['pytest-runner'],
Expand Down