Created
January 25, 2019 16:03
-
-
Save WrathfulSpatula/6cbde1a428b0fa554f4af6f26e8b97a8 to your computer and use it in GitHub Desktop.
Demonstration of control bit ordering side effect in ProjectQ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pytest | |
import projectq | |
from projectq import MainEngine | |
from projectq.backends import Simulator | |
from projectq.cengines import (AutoReplacer, DecompositionRuleSet, DummyEngine, | |
InstructionFilter) | |
from projectq.meta import Compute, Control, Uncompute | |
from projectq.ops import (All, Measure, Ry, Rz, UniformlyControlledRy, | |
UniformlyControlledRz, X) | |
import projectq.setups.decompositions.uniformlycontrolledr2cnot as ucr2cnot | |
def slow_implementation(angles, control_qubits, target_qubit, eng, gate_class): | |
""" | |
Assumption is that control_qubits[0] is lowest order bit | |
We apply angles[0] to state |0> | |
""" | |
assert len(angles) == 2**len(control_qubits) | |
for index in range(2**len(control_qubits)): | |
with Compute(eng): | |
for bit_pos in range(len(control_qubits)): | |
if not (index >> bit_pos) & 1: | |
X | control_qubits[bit_pos] | |
with Control(eng, control_qubits): | |
gate_class(angles[index]) | target_qubit | |
Uncompute(eng) | |
def test_uniformly_controlled_ry(): | |
n = 2 | |
random_angles = [3.0, 0.8, 1.2, 0.7] | |
basis_state_index = 1 | |
basis_state = [0] * 2**(n+1) | |
basis_state[basis_state_index] = 1. | |
correct_dummy_eng = DummyEngine(save_commands=True) | |
correct_eng = MainEngine(backend=Simulator(), | |
engine_list=[correct_dummy_eng]) | |
test_dummy_eng = DummyEngine(save_commands=True) | |
test_eng = MainEngine(backend=Simulator(), | |
engine_list=[test_dummy_eng]) | |
correct_sim = correct_eng.backend | |
correct_qb = correct_eng.allocate_qubit() | |
correct_ctrl_qureg = correct_eng.allocate_qureg(n) | |
correct_eng.flush() | |
test_sim = test_eng.backend | |
test_qb = test_eng.allocate_qubit() | |
test_ctrl_qureg = test_eng.allocate_qureg(n) | |
test_eng.flush() | |
correct_sim.set_wavefunction(basis_state, correct_qb + correct_ctrl_qureg) | |
test_sim.set_wavefunction(basis_state, test_qb + test_ctrl_qureg) | |
# ****************** THIS IS THE CRUX OF THE WHOLE ISSUE: ************************* | |
# Because of the list reversal in this call, this test should fail, but it doesn't: | |
# ********************************************************************************* | |
slow_implementation(angles=random_angles, | |
control_qubits=list(reversed(test_ctrl_qureg)), | |
target_qubit=test_qb, | |
eng=test_eng, | |
gate_class=Ry) | |
slow_implementation(angles=random_angles, | |
control_qubits=correct_ctrl_qureg, | |
target_qubit=correct_qb, | |
eng=correct_eng, | |
gate_class=Ry) | |
test_eng.flush() | |
correct_eng.flush() | |
for fstate in range(2**(n+1)): | |
binary_state = format(fstate, '0' + str(n+1) + 'b') | |
test = test_sim.get_amplitude(binary_state, | |
test_qb + test_ctrl_qureg) | |
correct = correct_sim.get_amplitude(binary_state, correct_qb + | |
correct_ctrl_qureg) | |
print(test, "==", correct) | |
assert correct == pytest.approx(test, rel=1e-10, abs=1e-10) | |
All(Measure) | test_qb + test_ctrl_qureg | |
All(Measure) | correct_qb + correct_ctrl_qureg | |
test_eng.flush(deallocate_qubits=True) | |
correct_eng.flush(deallocate_qubits=True) | |
# Passes: | |
test_uniformly_controlled_ry() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment