def test_limited_capability_engine_arithmetic(): default_eng = LimitedCapabilityEngine() eng = LimitedCapabilityEngine(allow_arithmetic=True) m = MainEngine(backend=DummyEngine(), engine_list=[eng]) q = m.allocate_qureg(5) inc = BasicMathGate(lambda x: x + 1) assert not default_eng.is_available(inc.generate_command(q)) assert eng.is_available(inc.generate_command(q))
def test_limited_capability_engine_classical_instructions(): default_eng = LimitedCapabilityEngine() eng = LimitedCapabilityEngine(allow_classical_instructions=False, allow_classes=[FlushGate]) m = MainEngine(backend=DummyEngine(), engine_list=[eng]) with pytest.raises(ValueError): _ = m.allocate_qubit() q = Qubit(m, 0) assert default_eng.is_available(Measure.generate_command(q)) assert not eng.is_available(Measure.generate_command(q))
def test_toffoli_size_of_modular_offset(): rec = DummyEngine(save_commands=True) eng = MainEngine(backend=rec, engine_list=[ AutoReplacerEx( DecompositionRuleSet(modules=[ pivot_flip_rules, offset_rules, addition_rules, swap2cnot, increment_rules, multi_not_rules, modular_addition_rules, comparison_rules, ])), LimitedCapabilityEngine(allow_toffoli=True), ]) controls = eng.allocate_qureg(15) target = eng.allocate_qureg(16) dirty = eng.allocate_qureg(2) modulus = 0xAEFD offset = 0x9E0A ModularOffsetGate(offset, modulus) & controls | target assert dirty is not None assert 5000 < len(rec.received_commands) < 15000
def simulate_sample_period(base, modulus): sim = Simulator() eng = MainEngine(backend=sim, engine_list=[ AutoReplacerEx( DecompositionRuleSet(modules=[decompositions])), LimitedCapabilityEngine( allow_arithmetic= not DECOMPOSE_INTO_TOFFOLIS_AND_GO_VERY_VERY_SLOW, allow_toffoli=True, allow_single_qubit_gates=True), ]) n = int(math.ceil(math.log(modulus, 2))) ancilla_qureg = eng.allocate_qureg(n) for q in ancilla_qureg[:-1]: if random.random() < 0.5: X | q before = ancilla_qureg.measure() result = shor_find_period(base=base, modulus=modulus, precision=n * 2, phase_qubit=eng.allocate_qubit(), work_qureg=eng.allocate_qureg(n), ancilla_qureg=ancilla_qureg) after = ancilla_qureg.measure() assert after == before return result
def test_toffoli_size_of_bimultiplication(): rec = DummyEngine(save_commands=True) eng = MainEngine(backend=rec, engine_list=[ AutoReplacerEx( DecompositionRuleSet(modules=[ swap2cnot, multi_not_rules, addition_rules, increment_rules, modular_addition_rules, modular_bimultiplication_rules, modular_scaled_addition_rules, pivot_flip_rules, offset_rules, modular_double_rules, rotate_bits_rules, reverse_bits_rules, modular_negate_rules, comparison_rules, ])), LimitedCapabilityEngine(allow_toffoli=True), ]) t1 = eng.allocate_qureg(5) t2 = eng.allocate_qureg(5) controls = eng.allocate_qureg(1) modulus = 29 factor = 17 ModularBimultiplicationGate(factor, modulus) & controls | (t1, t2) assert 5000 < len(rec.received_commands) < 10000
def test_toffoli_size_of_modular_negate(): rec = DummyEngine(save_commands=True) eng = MainEngine(backend=rec, engine_list=[ AutoReplacerEx( DecompositionRuleSet(modules=[ swap2cnot, multi_not_rules, addition_rules, increment_rules, pivot_flip_rules, offset_rules, comparison_rules, modular_negate_rules, ])), LimitedCapabilityEngine(allow_toffoli=True, ), ]) t = eng.allocate_qureg(5) controls = eng.allocate_qureg(1) workspace = eng.allocate_qureg(2) modulus = 29 ModularNegate(modulus) & controls | t assert 100 < len(rec.received_commands) < 200 assert workspace is not None
def main(): x = 2 modulus = 2 for reg_size in range(2, 20): reg_max_val = 1 << reg_size while True: modulus = random.randint(reg_max_val // 2 + 1, reg_max_val - 1) x = random.randint(2, modulus - 1) if modulus % 2 != 0 and fractions.gcd(x, modulus) == 1: break cnt = ResourceCounter() eng = MainEngine( backend=DummyEngine(), engine_list=[ AutoReplacerEx(DecompositionRuleSet(modules=[decompositions])), LimitedCapabilityEngine(allow_toffoli=True, allow_single_qubit_gates=True, allow_classes=[]), cnt, ]) v1 = eng.allocate_qureg(reg_size) v2 = eng.allocate_qureg(reg_size) c = eng.allocate_qubit() gate = ModularBimultiplicationGate(x, modulus) gate & c | (v1, v2) print() print() print("Register Size: {}".format(reg_size)) print("Gate count for controlled {}".format(gate)) print("\t{}".format(cnt).replace('\n', '\n\t'))
def test_toffoli_size_of_modular_addition(): rec = DummyEngine(save_commands=True) eng = MainEngine(backend=rec, engine_list=[ AutoReplacerEx( DecompositionRuleSet(modules=[ pivot_flip_rules, offset_rules, addition_rules, swap2cnot, increment_rules, multi_not_rules, modular_addition_rules, comparison_rules, ])), LimitedCapabilityEngine(allow_toffoli=True), ]) controls = eng.allocate_qureg(15) target1 = eng.allocate_qureg(16) target2 = eng.allocate_qureg(16) modulus = 0xAEFD ModularAdditionGate(modulus) & controls | (target1, target2) assert 10000 < len(rec.received_commands) < 15000
def test_limited_capability_engine_allow_toffoli(): default_eng = LimitedCapabilityEngine() eng = LimitedCapabilityEngine(allow_toffoli=True) m = MainEngine(backend=DummyEngine(), engine_list=[eng]) q = m.allocate_qureg(4) assert not default_eng.is_available(Z.generate_command(q)) assert not default_eng.is_available(X.generate_command(q)) assert not default_eng.is_available((X & q[1:2]).generate_command(q[0])) assert not default_eng.is_available((X & q[1:3]).generate_command(q[0])) assert not default_eng.is_available((X & q[1:4]).generate_command(q[0])) assert not eng.is_available(Z.generate_command(q)) assert eng.is_available(X.generate_command(q)) assert eng.is_available((X & q[1:2]).generate_command(q[0])) assert eng.is_available((X & q[1:3]).generate_command(q[0])) assert not eng.is_available((X & q[1:4]).generate_command(q[0]))
def test_limited_capability_engine_default(): eng = LimitedCapabilityEngine() m = MainEngine(backend=DummyEngine(), engine_list=[eng]) q = m.allocate_qureg(2) assert eng.is_available(Measure.generate_command(q)) assert not eng.is_available(H.generate_command(q)) assert not eng.is_available(Z.generate_command(q)) assert not eng.is_available(CNOT.generate_command(tuple(q)))
def test_limited_capability_engine_classes(): eng = LimitedCapabilityEngine(allow_classes=[H.__class__, X.__class__], ban_classes=[X.__class__, Y.__class__]) m = MainEngine(backend=DummyEngine(), engine_list=[eng]) q = m.allocate_qureg(5) assert eng.is_available(Measure.generate_command(q)) # Default. assert eng.is_available(H.generate_command(q)) # Allowed. assert not eng.is_available(X.generate_command(q)) # Ban overrides allow. assert not eng.is_available(Y.generate_command(q)) # Banned. assert not eng.is_available(Z.generate_command(q)) # Not mentioned.
def test_controlled_circuit(): check_phase_circuit( register_sizes=[5, 2], expected_turns=lambda (ns, nc), (s, c): s/2**ns/-4 if c + 1 == 1 << nc else 0, engine_list=[ AutoReplacerEx(DecompositionRuleSet(modules=[ phase_gradient_rules ])), LimitedCapabilityEngine( allow_single_qubit_gates_with_controls=True ) ], actions=lambda eng, regs: PhaseGradient**(-1/4) & regs[1] | regs[0])
def test_circuit_implements_phase_angle_specified_by_gate(): check_phase_circuit( register_sizes=[8], expected_turns=lambda lens, vals: PhaseGradient.phase_angle_in_turns_for(vals[0], lens[0]), engine_list=[ AutoReplacerEx(DecompositionRuleSet(modules=[ phase_gradient_rules ])), LimitedCapabilityEngine( allow_single_qubit_gates=True ) ], actions=lambda eng, regs: PhaseGradient | regs[0])
def test_toffoli_size_of_reverse(): rec = DummyEngine(save_commands=True) eng = MainEngine(backend=rec, engine_list=[ AutoReplacerEx(DecompositionRuleSet(modules=[ swap2cnot, multi_not_rules, reverse_bits_rules, ])), LimitedCapabilityEngine(allow_toffoli=True), ]) controls = eng.allocate_qureg(50) target = eng.allocate_qureg(100) ReverseBits & controls | target ReverseBits & controls | target[1:] assert 500 < len(rec.received_commands) < 5000
def test_toffoli_size_of_addition(): backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend, engine_list=[ AutoReplacerEx( DecompositionRuleSet(modules=[ addition_rules, increment_rules, multi_not_rules, swap2cnot, ])), LimitedCapabilityEngine(allow_toffoli=True), ]) src = eng.allocate_qureg(50) dst = eng.allocate_qureg(100) Add | (src, dst) assert 5000 < len(backend.received_commands) < 7000
def test_toffoli_size_of_increment(): backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend, engine_list=[ AutoReplacerEx( DecompositionRuleSet(modules=[ multi_not_rules, increment_rules, addition_rules, swap2cnot, ])), LimitedCapabilityEngine(allow_toffoli=True), ]) controls = eng.allocate_qureg(40) target = eng.allocate_qureg(35) _ = eng.allocate_qureg(2) Increment & controls | target assert 1000 < len(backend.received_commands) < 10000
def test_toffoli_size_of_negate(): backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend, engine_list=[ AutoReplacerEx( DecompositionRuleSet(modules=[ addition_rules, increment_rules, multi_not_rules, negate_rules, swap2cnot, ])), LimitedCapabilityEngine(allow_toffoli=True), ]) src = eng.allocate_qureg(100) workspace = eng.allocate_qubit() Negate | src assert 2000 < len(backend.received_commands) < 4000 assert workspace is not None
def test_toffoli_size_of_scaled_modular_addition(): rec = DummyEngine(save_commands=True) eng = MainEngine( backend=rec, engine_list=[ AutoReplacerEx( DecompositionRuleSet(modules=[ addition_rules, comparison_rules, increment_rules, multi_not_rules, offset_rules, scaled_addition_rules ])), LimitedCapabilityEngine(allow_toffoli=True), ]) controls = eng.allocate_qureg(15) target1 = eng.allocate_qureg(8) target2 = eng.allocate_qureg(8) factor = 0x9A ScaledAdditionGate(factor) & controls | (target1, target2) assert 1000 < len(rec.received_commands) < 2000
def test_toffoli_size_of_pivot_flip(): rec = DummyEngine(save_commands=True) eng = MainEngine(backend=rec, engine_list=[ AutoReplacerEx(DecompositionRuleSet(modules=[ pivot_flip_rules, addition_rules, swap2cnot, increment_rules, multi_not_rules, ])), LimitedCapabilityEngine(allow_toffoli=True), ]) controls = eng.allocate_qureg(15) target1 = eng.allocate_qureg(30) target2 = eng.allocate_qureg(40) dirty = eng.allocate_qureg(2) PivotFlip & controls | (target1, target2) assert dirty is not None assert 10000 < len(rec.received_commands) < 20000
def test_full_cnot_permutations_small(): for n in [1, 2, 3, 4, 7, 9]: control_mask = ((1 << (n - 1)) - 1) << 1 check_quantum_permutation_circuit( register_size=n, permutation_func=lambda ns, (i, ): i ^ (1 if control_mask & i == control_mask else 0), engine_list=[ AutoReplacerEx( DecompositionRuleSet(modules=[ bootstrap_ancilla_rules, phase_gradient_rules, increment_rules, multi_not_rules, addition_rules, swap2cnot, ])), LimitedCapabilityEngine(allow_toffoli=True, allow_single_qubit_gates=True), ], actions=lambda eng, regs: X & regs[0][1:] | regs[0][0])
def test_check_const_pivot_flip_permutations_small(): for n, nc in itertools.product([1, 2, 3], [0, 1]): for pivot in range((1 << n) + 1): dirty = 1 check_permutation_circuit( register_sizes=[n, nc, dirty], permutation=lambda _, (t, c, d): (pivot - t - 1 if c + 1 == 1 << nc and t < pivot else t, c, d), engine_list=[ AutoReplacerEx(DecompositionRuleSet(modules=[ pivot_flip_rules, ])), LimitedCapabilityEngine( allow_all=True, ban_classes=[ConstPivotFlipGate], ), ], actions=lambda eng, regs: ConstPivotFlipGate(pivot) & regs[1] | regs[0])
def test_toffoli_size_of_const_pivot_flip(): rec = DummyEngine(save_commands=True) eng = MainEngine(backend=rec, engine_list=[ AutoReplacerEx(DecompositionRuleSet(modules=[ pivot_flip_rules, addition_rules, offset_rules, swap2cnot, increment_rules, multi_not_rules, comparison_rules, ])), LimitedCapabilityEngine(allow_toffoli=True), ]) controls = eng.allocate_qureg(15) target = eng.allocate_qureg(32) dirty = eng.allocate_qureg(2) offset = 0x789ABCDEF ConstPivotFlipGate(offset) & controls | target assert dirty is not None assert 10000 < len(rec.received_commands) < 20000
def test_fuzz_const_pivot_flip_permutations_large(): for _ in range(10): n = random.randint(0, 50) nc = random.randint(0, 2) pivot = random.randint(0, 1 << n) dirty = 1 fuzz_permutation_circuit( register_sizes=[n, nc, dirty], permutation=lambda _, (t, c, d): (pivot - t - 1 if c + 1 == 1 << nc and t < pivot else t, c, d), engine_list=[ AutoReplacerEx(DecompositionRuleSet(modules=[ pivot_flip_rules, ])), LimitedCapabilityEngine( allow_all=True, ban_classes=[ConstPivotFlipGate], ), ], actions=lambda eng, regs: ConstPivotFlipGate(pivot) & regs[1] | regs[0])