def test_gate_filter(): # BasicGate with no get_inverse used for testing: with pytest.raises(NotInvertible): TestGate.get_inverse() # Loading of decomposition rules: def decompose_test1(cmd): qb = cmd.qubits X | qb def recognize_test(cmd): return True register_decomposition(TestGate.__class__, decompose_test1, recognize_test) def decompose_test2(cmd): qb = cmd.qubits H | qb register_decomposition(TestGate.__class__, decompose_test2, recognize_test) assert len(decompositions[TestGate.__class__.__name__]) == 2 # Filter which doesn't allow TestGate def test_gate_filter_func(self, cmd): if cmd.gate == TestGate: return False return True return _replacer.InstructionFilter(test_gate_filter_func)
def test_auto_replacer_use_inverse_decomposition(): # Check that if there is no decomposition for the gate, that # AutoReplacer runs the decomposition for the inverse gate in reverse # Create test gate and inverse class NoMagicGate(BasicGate): pass class MagicGate(BasicGate): def get_inverse(self): return NoMagicGate() def decompose_no_magic_gate(cmd): qb = cmd.qubits Rx(0.6) | qb H | qb def recognize_no_magic_gate(cmd): return True register_decomposition(NoMagicGate, decompose_no_magic_gate, recognize_no_magic_gate) def magic_filter(self, cmd): if cmd.gate == MagicGate(): return False return True backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend, engine_list=[ _replacer.AutoReplacer(), _replacer.InstructionFilter(magic_filter) ]) assert len(backend.received_commands) == 0 qb = eng.allocate_qubit() MagicGate() | qb eng.flush() for cmd in backend.received_commands: print(cmd) assert len(backend.received_commands) == 4 assert backend.received_commands[1].gate == H assert backend.received_commands[2].gate == Rx(-0.6)
from ._gates import (AddConstant, SubConstant, AddConstantModN, SubConstantModN, MultiplyByConstantModN) from ._constantmath import (add_constant, add_constant_modN, mul_by_constant_modN) def _replace_addconstant(cmd): eng = cmd.engine c = cmd.gate.a quint = cmd.qubits[0] with Control(eng, cmd.control_qubits): add_constant(eng, c, quint) register_decomposition(AddConstant, _replace_addconstant) def _replace_addconstmodN(cmd): eng = cmd.engine c = cmd.gate.a N = cmd.gate.N quint = cmd.qubits[0] with Control(eng, cmd.control_qubits): add_constant_modN(eng, c, N, quint) register_decomposition(AddConstantModN, _replace_addconstmodN)
# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Registers a decomposition to achieve a Swap gate. Decomposes a Swap gate using 3 CNOT gates, where the one in the middle features as many control qubits as the Swap gate has control qubits. """ from projectq.cengines import register_decomposition from projectq.meta import Compute, Uncompute, Control, get_control_count from projectq.ops import Swap, CNOT def _decompose_swap(cmd): """ Decompose (controlled) swap gates. """ ctrl = cmd.control_qubits eng = cmd.engine with Compute(eng): CNOT | (cmd.qubits[0], cmd.qubits[1]) with Control(eng, ctrl): CNOT | (cmd.qubits[1], cmd.qubits[0]) Uncompute(eng) register_decomposition(Swap.__class__, _decompose_swap)
# See the License for the specific language governing permissions and # limitations under the License. """ Registers a decomposition for the controlled global phase gate. Turns the controlled global phase gate into a (controlled) phase-shift gate. Each time this rule is applied, one control can be shaved off. """ from projectq.cengines import register_decomposition from projectq.meta import Control, get_control_count from projectq.ops import Ph, R def _decompose_Ph(cmd): """ Decompose the controlled phase gate (C^nPh(phase)). """ ctrl = cmd.control_qubits gate = cmd.gate eng = cmd.engine with Control(eng, ctrl[1:]): R(gate._angle) | ctrl[0] def _recognize_Ph(cmd): """ Recognize the controlled phase gate. """ return get_control_count(cmd) >= 1 register_decomposition(Ph, _decompose_Ph, _recognize_Ph)
# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Registers a decomposition rule for the phase-shift gate. Decomposes the (controlled) phase-shift gate using z-rotation and a global phase gate. """ from projectq.cengines import register_decomposition from projectq.meta import Control from projectq.ops import Ph, Rz, R def _decompose_R(cmd): """ Decompose the (controlled) phase-shift gate, denoted by R(phase). """ ctrl = cmd.control_qubits eng = cmd.engine gate = cmd.gate with Control(eng, ctrl): Ph(.5 * gate._angle) | cmd.qubits Rz(gate._angle) | cmd.qubits register_decomposition(R, _decompose_R)
ctrl = cmd.control_qubits eng = cmd.engine target = cmd.qubits[0] c1 = ctrl[0] c2 = ctrl[1] H | target CNOT | (c1, target) T | c1 Tdag | target CNOT | (c2, target) CNOT | (c2, c1) Tdag | c1 T | target CNOT | (c2, c1) CNOT | (c1, target) Tdag | target CNOT | (c2, target) T | target T | c2 H | target def _recognize_toffoli(cmd): """ Recognize the Toffoli gate. """ return get_control_count(cmd) == 2 register_decomposition(NOT.__class__, _decompose_toffoli, _recognize_toffoli)
# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Registers a decomposition for the Entangle gate. Applies a Hadamard gate to the first qubit and then, conditioned on this first qubit, CNOT gates to all others. """ from projectq.cengines import register_decomposition from projectq.meta import Control, get_control_count from projectq.ops import X, H, Entangle, All def _decompose_entangle(cmd): """ Decompose the entangle gate. """ qr = cmd.qubits[0] eng = cmd.engine with Control(eng, cmd.control_qubits): H | qr[0] with Control(eng, qr[0]): All(X) | qr[1:] register_decomposition(Entangle.__class__, _decompose_entangle)
# limitations under the License. """ Registers a decomposition rule for the quantum Fourier transform. Decomposes the QFT gate into Hadamard and controlled phase-shift gates (R). Warning: The final Swaps are not included, as those are simply a re-indexing of quantum registers. """ import math from projectq.cengines import register_decomposition from projectq.ops import H, R, QFT from projectq.meta import Control def _decompose_QFT(cmd): qb = cmd.qubits[0] eng = cmd.engine with Control(eng, cmd.control_qubits): for i in range(len(qb)): H | qb[-1 - i] for j in range(len(qb) - 1 - i): with Control(eng, qb[-1 - (j + i + 1)]): R(math.pi / (1 << (1 + j))) | qb[-1 - i] register_decomposition(QFT.__class__, _decompose_QFT)
# # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Registers a decomposition rule for global phases. Deletes global phase gates (which can be ignored). """ from projectq.cengines import register_decomposition from projectq.meta import get_control_count from projectq.ops import Ph def _decompose_PhNoCtrl(cmd): """ Throw out global phases (no controls). """ pass def _recognize_PhNoCtrl(cmd): """ Recognize global phases (no controls). """ return get_control_count(cmd) == 0 register_decomposition(Ph, _decompose_PhNoCtrl, _recognize_PhNoCtrl)
""" Registers a decomposition for controlled z-rotation gates. It uses 2 z-rotations and 2 C^n NOT gates to achieve this gate. """ from projectq.cengines import register_decomposition from projectq.meta import get_control_count from projectq.ops import NOT, Rz, C def _decompose_CRz(cmd): """ Decompose the controlled Rz gate (into CNOT and Rz). """ qubit = cmd.qubits[0] ctrl = cmd.control_qubits gate = cmd.gate n = get_control_count(cmd) Rz(0.5 * gate._angle) | qubit C(NOT, n) | (ctrl, qubit) Rz(-0.5 * gate._angle) | qubit C(NOT, n) | (ctrl, qubit) def _recognize_CRz(cmd): """ Recognize the controlled Rz gate. """ return get_control_count(cmd) >= 1 register_decomposition(Rz, _decompose_CRz, _recognize_CRz)