Repository: rigetticomputing/pyquil
Pull request #260 (2018-01-11 02:04:33)

Feature/add function to offset program by n qubits and change CSWAP docstring

stevenheidel: Looks good, although you have to remove your commit from the other PR.
schuylerfried: Just merged the two PRs into one.. Is that chill?

Patch:
diff --git a/pyquil/gates.py b/pyquil/gates.py
index 224436f..6af1954 100644
--- a/pyquil/gates.py
+++ b/pyquil/gates.py
@@ -225,11 +225,11 @@ Produces a SWAP instruction. This gate swaps the state of two qubits.
 """
 CSWAP = _make_gate("CSWAP", 3)()
 """
-Produces a SWAP instruction. This gate swaps the state of two qubits.
+Produces a CSWAP instruction. This gate swaps the state of two qubits.
 
-:param q1: Qubit 1.
-:param q2: Qubit 2.
-:returns: A Gate object.
+:param control: The control qubit.
+:param target-1: The first target qubit.
+:param target-2: The second target qubit. The two target states are swapped if the control is in the excited state.
 """
 ISWAP = _make_gate("ISWAP", 2)()
 """
@@ -253,7 +253,8 @@ Produces a PSWAP instruction. This is a parameterized swap gate.
 
 WAIT = Wait()
 """
-This instruction tells the quantum computation to halt. Typically these is used while classical memory is being manipulated by a CPU in a hybrid classical/quantum algorithm.
+This instruction tells the quantum computation to halt. Typically these is used while classical memory is being
+manipulated by a CPU in a hybrid classical/quantum algorithm.
 
 :returns: A Wait object.
 """
diff --git a/pyquil/quil.py b/pyquil/quil.py
index 6d4be20..e50f7b0 100644
--- a/pyquil/quil.py
+++ b/pyquil/quil.py
@@ -561,3 +561,23 @@ def merge_programs(prog_list):
     :rtype: Program
     """
     return sum(prog_list, Program())
+
+
+def shift_quantum_gates(program, shift_offset):
+    """
+    Shifts a quantum gates in a quil program so that all qubit indices change by a certain offset
+    :param program: a pyquil Program
+    :param shift_offset: integer
+    :return: pyquil Program with shifted qubit indices
+    """
+    if not isinstance(shift_offset, int):
+        raise ValueError("shift_offset must be an integer")
+    if not isinstance(program, Program):
+        raise ValueError("Program must be a pyquil Program instance")
+    shifted_program = Program()
+    shifted_program.inst(program)
+    for instruct in shifted_program:
+        if isinstance(instruct, Gate):
+            for qubit in instruct.qubits:
+                qubit.index += shift_offset
+    return shifted_program


Test patch:
diff --git a/pyquil/tests/test_quil.py b/pyquil/tests/test_quil.py
index 6bd9d7a..b069084 100644
--- a/pyquil/tests/test_quil.py
+++ b/pyquil/tests/test_quil.py
@@ -24,7 +24,7 @@ from pyquil.gates import I, X, Y, Z, H, T, S, RX, RY, RZ, CNOT, CCNOT, PHASE, CP
     CPHASE10, CPHASE, SWAP, CSWAP, ISWAP, PSWAP, MEASURE, HALT, WAIT, NOP, RESET, \
     TRUE, FALSE, NOT, AND, OR, MOVE, EXCHANGE
 from pyquil.parameters import Parameter, cos, sin
-from pyquil.quil import Program, merge_programs
+from pyquil.quil import Program, merge_programs, shift_quantum_gates
 from pyquil.quilbase import DefGate, Gate, Addr, Qubit, JumpWhen
 
 
@@ -437,6 +437,11 @@ def test_prog_merge():
     assert merge_programs([prog_0, prog_1]).out() == (prog_0 + prog_1).out()
 
 
+def test_quantum_gate_shift():
+    prog = Program(X(0), CNOT(0, 4), MEASURE(5, [5]))
+    assert shift_quantum_gates(prog, 5) == Program(X(5), CNOT(5, 9), MEASURE(5, [5]))
+
+
 def test_get_qubits():
     pq = Program(X(0), CNOT(0, 4), MEASURE(5, [5]))
     assert pq.get_qubits() == {0, 4, 5}