def compile_controlled_phase(gate) -> QCircuit: if not isinstance(gate, PhaseGateImpl): return QCircuit.wrap_gate(gate) if len(gate.control) == 0: return QCircuit.wrap_gate(gate) count = len(gate.control) result = QCircuit() phase = gate.parameter if count == 1: result += H(target=gate.target) result += CNOT(gate.control, gate.target) result += H(target=gate.target) result += Phase(gate.parameter + numpy.pi, target=gate.target) elif count == 2: result += Rz(angle=phase / (2**2), target=gate.control[0]) result += Rz(angle=phase / (2**(1)), target=gate.control[1], control=gate.control[0]) result += Rz(angle=phase, target=gate.target, control=gate.control) elif count >= 3: result += Rz(angle=phase / (2**count), target=gate.control[0]) for i in range(1, count): result += Rz(angle=phase / (2**(count - i)), target=gate.control[i], control=gate.control[0:i]) result += Rz(angle=phase, target=gate.target, control=gate.control) return result
def compile_toffoli(gate) -> QCircuit: if gate.name.lower != 'x': return QCircuit.wrap_gate(gate) control = gate.control c1 = control[1] c0 = control[0] target = gate.target result = QCircuit() result += H(target) result += CNOT(c1, target) result += T(target).dagger() result += CNOT(c0, target) result += T(target) result += CNOT(c1, target) result += T(target).dagger() result += CNOT(c0, target) result += T(c1) result += T(target) result += CNOT(c0, c1) result += H(target) result += T(c0) result += T(c1).dagger() result += CNOT(c0, c1) return (result)
def change_basis(target, axis, daggered=False): """ helper function; returns circuit that performs change of basis. Parameters ---------- target: the qubit having its basis changed axis: The axis of rotation to shift into. daggered: bool: adjusts the sign of the gate if axis = 1, I.E, change of basis about Y axis. Returns ------- QCircuit that performs change of basis on target qubit onto desired axis """ if isinstance(axis, str): axis = RotationGateImpl.string_to_axis[axis.lower()] if axis == 0: return H(target=target) elif axis == 1 and daggered: return Rx(angle=-numpy.pi / 2, target=target) elif axis == 1: return Rx(angle=numpy.pi / 2, target=target) else: return QCircuit()
def test_basic_gates(): I = sympy.I cos = sympy.cos sin = sympy.sin exp = sympy.exp BS = QubitWaveFunction.from_int angle = sympy.pi gates = [ X(0), Y(0), Z(0), Rx(target=0, angle=angle), Ry(target=0, angle=angle), Rz(target=0, angle=angle), H(0) ] results = [ BS(1), I * BS(1), BS(0), cos(-angle / 2) * BS(0) + I * sin(-angle / 2) * BS(1), cos(-angle / 2) * BS(0) + I * sin(-angle / 2) * I * BS(1), exp(-I * angle / 2) * BS(0), 1 / sympy.sqrt(2) * (BS(0) + BS(1)) ] for i, g in enumerate(gates): wfn = simulate(g, backend="symbolic", variables={angle: sympy.pi}) assert (wfn == strip_sympy_zeros(results[i]))
def test_moments(): c = QCircuit() c += CNOT(target=0, control=(1, 2, 3)) c += H(target=[0, 1]) c += Rx(angle=numpy.pi, target=[0, 3]) c += Z(target=1) c += Phase(phi=numpy.pi, target=4) moms = c.moments assert len(moms) == 3 assert (moms[0].gates[1].parameter == assign_variable(numpy.pi)) assert (moms[0].gates[1].target == (4, ))
def change_basis(target, axis, daggered=False): if isinstance(axis, str): axis = RotationGateImpl.string_to_axis[axis.lower()] if axis == 0: return H(target=target) elif axis == 1 and daggered: return Rx(angle=-numpy.pi / 2, target=target) elif axis == 1: return Rx(angle=numpy.pi / 2, target=target) else: return QCircuit()
def test_circuit_from_moments(): c = QCircuit() c += CNOT(target=0, control=(1, 2, 3)) c += Phase(phi=numpy.pi, target=4) c += Rx(angle=Variable('a'), target=[0, 3]) c += H(target=[0, 1]) c += Rx(angle=Variable('a'), target=[2, 3]) ## table[1] should equal 1 at this point, len(moments should be 3) c += Z(target=1) c += Rx(angle=Variable('a'), target=[0, 3]) moms = c.moments c2 = QCircuit.from_moments(moms) assert c == c2
def compile_toffoli(gate) -> QCircuit: """ break down a toffoli gate into a sequence of CNOT and single qubit gates. Parameters ---------- gate: the gate. Returns ------- A QCircuit; the result of compilation. """ if gate.name.lower != 'x': return QCircuit.wrap_gate(gate) control = gate.control c1 = control[1] c0 = control[0] target = gate.target result = QCircuit() result += H(target) result += CNOT(c1, target) result += T(target).dagger() result += CNOT(c0, target) result += T(target) result += CNOT(c1, target) result += T(target).dagger() result += CNOT(c0, target) result += T(c1) result += T(target) result += CNOT(c0, c1) result += H(target) result += T(c0) result += T(c1).dagger() result += CNOT(c0, c1) return (result)
def test_canonical_moments(): c = QCircuit() c += CNOT(target=0, control=(1, 2, 3)) c += Rx(angle=Variable('a'), target=[0, 3]) c += H(target=[0, 1]) c += Rx(angle=Variable('a'), target=[2, 3]) c += Rx(angle=Variable('a'), target=[0, 3]) c += Z(target=1) c += Phase(phi=numpy.pi, target=4) moms = c.canonical_moments assert len(moms) == 6 assert (moms[0].gates[1].parameter == assign_variable(numpy.pi)) assert (moms[0].gates[1].target == (4, )) assert hasattr(moms[3].gates[0], 'axis') assert len(moms[0].qubits) == 5
def change_basis(target, axis=None, name=None, daggered=False): """ helper function; returns circuit that performs change of basis. Parameters ---------- target: the qubit having its basis changed axis: The axis of rotation to shift into. daggered: bool: adjusts the sign of the gate if axis = 1, I.E, change of basis about Y axis. Returns ------- QCircuit that performs change of basis on target qubit onto desired axis """ if axis is None and name is None: raise TequilaException('axis or name must be given.') if name: name = name.lower() if name in ['h', 'hadamard'] and daggered: return Ry(angle=numpy.pi / 4, target=target) elif name in ['h', 'hadamard']: return Ry(angle=-numpy.pi / 4, target=target) else: name_to_axis = {'rx': 0, 'ry': 1, 'rz': 2} axis = name_to_axis.get(name, name) if isinstance(axis, str): axis = RotationGateImpl.string_to_axis[axis.lower()] if axis == 0: return H(target=target) elif axis == 1 and daggered: return Rx(angle=-numpy.pi / 2, target=target) elif axis == 1: return Rx(angle=numpy.pi / 2, target=target) else: return QCircuit()