Skip to content

Commit

Permalink
Merge pull request #2 from BBN-Q/brj/concur-cleanup
Browse files Browse the repository at this point in the history
Use QRegisters instead of Qubits as toplevel inputs
  • Loading branch information
blakejohnson committed Apr 11, 2017
2 parents f038348 + 3f53a0c commit 66d23e7
Show file tree
Hide file tree
Showing 11 changed files with 146 additions and 159 deletions.
31 changes: 19 additions & 12 deletions src/python/pyqgl2/eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@
from pyqgl2.inline import TempVarManager
from pyqgl2.qgl2_check import QGL2check
from pyqgl2.qreg import is_qbit_create
from pyqgl2.qreg import QRegister
from pyqgl2.qreg import QRegister, QReference
from pyqgl2.quickcopy import quickcopy

from QGL import Qubit

def insert_keyword(kwargs, key, value):

if not isinstance(key, str):
Expand Down Expand Up @@ -922,23 +920,32 @@ def visit(self, orig_node):
qbit_preamble = list()
local_variables = self.eval_state.locals_stack[-1]
for k, v in local_variables.items():
if isinstance(v, Qubit):
# FIXME kludge assumption that label is sufficient description
stmnt = ast.parse("{0} = QRegister('{1}')".format(k, v.label))
if isinstance(v, QRegister):
# pass a QRegister straight thru as if it were simply
# delcared at the top of main
stmnt = ast.parse("{0} = {1}".format(k, v))
copy_all_loc(stmnt.body[0], node, recurse=True)
qbit_preamble.append(stmnt.body[0])
elif isinstance(v, QReference):
# make a new QRegister containing the referenced qubits
if isinstance(v.idx, slice):
qubit_args = ", ".join("'q{0}'".format(n) for n in v.ref.qubits[v.idx])
else:
qubit_args = "'q{0}'".format(v.ref.qubits[v.idx])
stmnt = ast.parse("{0} = QRegister({1})".format(k, qubit_args))
copy_all_loc(stmnt.body[0], node, recurse=True)
qbit_preamble.append(stmnt.body[0])
elif hasattr(v, '__iter__') and all(isinstance(x, Qubit) for x in v):
# a uniform list of Qubits
# FIXME same kludge as above
elif hasattr(v, '__iter__') and all(isinstance(x, QRegister) for x in v):
# a uniform list of QRegisters
tmp_namer = TempVarManager.create_temp_var_manager(
name_prefix='___preamble')
qstrs = ""
tmp_names = []
for elem in v:
tmp_name = tmp_namer.create_tmp_name(elem.label)
tmp_name = tmp_namer.create_tmp_name()
tmp_names.append(tmp_name)
qstrs += "{0} = QRegister('{1}')\n".format(tmp_name, elem.label)
qstrs += "{0} = ({1})".format(k, ", ".join(tmp_names))
qstrs += "{0} = {1}\n".format(tmp_name, elem)
qstrs += "{0} = ({1},)".format(k, ", ".join(tmp_names))
stmnt = ast.parse(qstrs)
for s in stmnt.body:
copy_all_loc(s, node, recurse=True)
Expand Down
2 changes: 1 addition & 1 deletion src/python/qgl2/basic_sequences/CRMin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright 2016 by Raytheon BBN Technologies Corp. All Rights Reserved.

from qgl2.qgl2 import qgl2decl, concur, qbit_list, QRegister
from qgl2.qgl2 import qgl2decl, qbit_list, QRegister
from qgl2.util import init
from qgl2.qgl1 import Id, flat_top_gaussian_edge, X, X90, echoCR
from qgl2.qgl1 import MEAS
Expand Down
32 changes: 12 additions & 20 deletions src/python/qgl2/basic_sequences/RabiMin.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,13 @@ def doRabiAmp(q:qbit, amps, phase):
MEAS(q)

@qgl2decl
def doRabiAmpPi(q1:qbit, q2:qbit, amps):
def doRabiAmpPi(qr:qbit, amps):
for l in amps:
init(q1)
init(q2)
X(q2)
Utheta(q1, amp=l, phase=0)
X(q2)
MEAS(q2)
init(qr)
X(qr[1])
Utheta(qr[0], amp=l, phase=0)
X(qr[1])
MEAS(qr[1])

@qgl2decl
def doSingleShot(q:qbit):
Expand All @@ -59,31 +58,24 @@ def doPulsedSpec(q:qbit, specOn):
MEAS(q)

@qgl2decl
def doRabiAmp_NQubits(qubits:qbit_list, amps, docals, calRepeats):
def doRabiAmp_NQubits(qr:qbit, amps, docals, calRepeats):
p = 0

for a in amps:
for q in qubits:
init(q)
for q in qubits:
Utheta(q, amp=a, phase=p)
Barrier("", qubits)
for q in qubits:
MEAS(q)
init(qr)
Utheta(qr, amp=a, phase=p)
MEAS(qr)

if docals:
create_cal_seqs(qubits, calRepeats)
create_cal_seqs(qr, calRepeats)

@qgl2decl
def doSwap(q:qbit, mq:qbit, delays):
qr = QRegister(q, mq)

def doSwap(qr:qbit, delays):
for d in delays:
init(qr)
X(qr)
Id(qr[1], length=d)
Barrier("", (qr,))
MEAS(qr)


create_cal_seqs(qr, 2)
96 changes: 3 additions & 93 deletions src/python/qgl2/qgl2.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,102 +4,15 @@
Definitions that must be loaded into each QGL2 module.
In order to be recognized by the compiler, you should include
the following snipped at the start of each module that uses
the following snippet at the start of each module that uses
QGL2 constructs:
from qgl2.qgl2 import concur, qgl2decl, qgl2main
from qgl2.qgl2 import classical, pulse, qbit, qbit_list, sequence, control, GATHER_SEQUENCES
from qgl2.qgl1 import *
from qgl2.qgl2 import qgl2decl, qgl2main, QRegister
from qgl2.qgl2 import classical, pulse, qbit, qbit_list, sequence, control
"""

from functools import wraps

class SimpleWithObject(object):
"""
Base class that defines a degenerate __enter__ and __exit__
method, so that instances of this class or its subclasses
can be used as "with" objects.
(somewhat unexpectedly, the base object class does not
include any __exit__ method at all, although it *does*
include an __enter__ method)
"""

def __init__(self, *args, **kwargs):
"""
Provided in case a superclass calls it, but does nothing
"""
pass

def __enter__(self):
return True

def __exit__(self, extype, value, traceback):
"""
A degenerate __exit__ that passes all exceptions through
"""

return False


class Concur(SimpleWithObject):
"""
A degenerate class used to create "concurrent" statements via
the "with" statement. For example, for the following pseudocode,
the qgl2 processor will attempt to execute stmnt1 and stmnt2
concurrently:
with Concur():
stmnt1
stmnt2
The purpose of the "concur()" is to mark these statements as
things to execute concurrently.
The "with Concur()" currently has no effect if executed outside
of a qgl2 context. If the statements don't have any side
effects, executing them concurrently or sequentially should
have the same effect. (it's tempting to have it be an error,
however, because even though it should behave correctly, it
means that the programmer is confused)
I've included a quasi-degenerate __init__() because we've tossed
around some ideas for how we could use pseudo-parameters to provide
additional info to the preprocessor, but this behavior hasn't been
defined yet.
"""

def __init__(self, *args, **kwargs):
pass


class Seq(SimpleWithObject):
"""
Similar to Concur, but used to create "sequences" of statements
via the "with" statement. For example, for the following pseudocode,
the qgl2 processor will attempt to execute stmnt1 and stmnt2 in
sequence, while concurrently attempting to execute stmnt3 and stmnt4
in sequence:
with Concur():
with Seq():
stmnt1
stmnt2
with Seq():
stmnt3
stmnt4
The "with Seq()" currently has no effect if executed outside
of a qgl2 context.
This bit of syntax may go away, once we can infer things
more cleanly, but I'm keeping it for prototyping purposes.
"""

def __init__(self, *args, **kwargs):
pass


def qgl2main(function):
@wraps(function)
def wrapper(*f_args, **f_kwargs):
Expand Down Expand Up @@ -185,6 +98,3 @@ def QRegister(*args):
pulse = True
sequence = True
control = True

concur = Concur()
seq = Seq()
2 changes: 1 addition & 1 deletion test/code/AllXY_alt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# QGL2 test versions of AllXY

from qgl2.qgl2 import qgl2decl, qbit, concur, QRegister
from qgl2.qgl2 import qgl2decl, qbit, QRegister
from qgl2.util import init
from qgl2.qgl1 import MEAS

Expand Down
7 changes: 3 additions & 4 deletions test/code/qft.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from qgl2.qgl2 import qgl2decl, qgl2main, qbit, qbit_list
from qgl2.qgl2 import qgl2decl, qgl2main, qbit, qbit_list, QRegister
from qgl2.qgl1 import Id, X90, Y90, X, Y, Ztheta, MEAS, CNOT

from math import pi
Expand All @@ -17,10 +17,9 @@ def CZ_k(c:qbit, t:qbit, k):
CNOT(c, t)

@qgl2decl
def qft(qs:qbit_list):
def qft(qs:qbit):
for i in range(len(qs)):
hadamard(qs[i])
for j in range(i+1, len(qs)):
CZ_k(qs[i], qs[j], j-i)
for q in qs:
MEAS(q)
MEAS(qs)
2 changes: 1 addition & 1 deletion test/code/reset.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from qgl2.qgl2 import concur, qgl2decl, qgl2main
from qgl2.qgl2 import qgl2decl, qgl2main
from qgl2.qgl2 import classical, pulse, qbit, qbit_list, QRegister
from qgl2.qgl1 import Id, X90, Y90, X, Y, Z, MEAS

Expand Down
2 changes: 1 addition & 1 deletion test/code/scope.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from qgl2.qgl2 import concur, qgl2decl
from qgl2.qgl2 import qgl2decl
from qgl2.qgl2 import qbit, qbit_list, QRegister
from qgl2.qgl1 import Xtheta, Ytheta

Expand Down
Loading

0 comments on commit 66d23e7

Please sign in to comment.