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 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 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 test_conventions(): qubit = numpy.random.randint(0, 3) angle = Variable("angle") Rx1 = Rx(target=qubit, angle=angle) Rx2 = QCircuit.wrap_gate( RotationGateImpl(axis="X", target=qubit, angle=angle)) Rx3 = QCircuit.wrap_gate( RotationGateImpl(axis="x", target=qubit, angle=angle)) Rx4 = RotationGate(axis=0, target=qubit, angle=angle) Rx5 = RotationGate(axis="X", target=qubit, angle=angle) Rx6 = RotationGate(axis="x", target=qubit, angle=angle) Rx7 = RotationGate(axis=0, target=qubit, angle=angle) Rx7.axis = "X" ll = [Rx1, Rx2, Rx3, Rx4, Rx5, Rx6, Rx7] for l1 in ll: for l2 in ll: assert (l1 == l2) qubit = 2 for c in [None, 0, 3]: for angle in ["angle", 0, 1.234]: for axes in [[0, "x", "X"], [1, "y", "Y"], [2, "z", "Z"]]: ll = [ RotationGate(axis=i, target=qubit, control=c, angle=angle) for i in axes ] for l1 in ll: for l2 in ll: assert (l1 == l2) l1.axis = axes[numpy.random.randint(0, 2)] assert (l1 == l2)
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 compile_ry(gate: RotationGateImpl, controlled_rotation: bool = False) -> QCircuit: """ Compile Ry gates into Rx and Rz. Parameters ---------- gate: the gate. controlled_rotation: determines if the decomposition of the controlled-Ry gate will be performed in compile_controlled_rotation, if not, decomposition will be performed here Returns ------- QCircuit, the result of compilation. """ if gate.name.lower() == "ry": if not (gate.is_controlled() and controlled_rotation): return Rz(target=gate.target, control=None, angle=-numpy.pi / 2) \ + Rx(target=gate.target, control=gate.control, angle=gate.parameter) \ + Rz(target=gate.target, control=None, angle=numpy.pi / 2) return QCircuit.wrap_gate(gate)
def compile_power_base(gate): """ Base case of compile_power_gate: convert a 1-qubit parametrized power gate into rotation gates. Parameters ---------- gate: the gate. Returns ------- A QCircuit; the result of compilation. """ if not isinstance(gate, PowerGateImpl): return QCircuit.wrap_gate(gate) if gate.is_controlled(): return QCircuit.wrap_gate(gate) power = gate.power if gate.name.lower() in ['h', 'hadamard']: ### off by global phase of Exp[ pi power /2] theta = power * numpy.pi result = QCircuit() result += Ry(angle=-numpy.pi / 4, target=gate.target) result += Rz(angle=theta, target=gate.target) result += Ry(angle=numpy.pi / 4, target=gate.target) elif gate.name == 'X': ### off by global phase of Exp[ pi power /2] ''' if we wanted to do it formally we would use the following a=-numpy.pi/2 b=numpy.pi/2 theta = power*numpy.pi result = QCircuit() result+= Rz(angle=b,target=gate.target) result+= Ry(angle=theta,target=gate.target) result+= Rz(angle=a,target=gate.target) ''' result = Rx(angle=power * numpy.pi, target=gate.target) elif gate.name == 'Y': ### off by global phase of Exp[ pi power /2] theta = power * numpy.pi result = QCircuit() result += Ry(angle=theta, target=gate.target) elif gate.name == 'Z': ### off by global phase of Exp[ pi power /2] a = 0 b = power * numpy.pi theta = 0 result = QCircuit() result += Rz(angle=b, target=gate.target) else: raise TequilaException('passed a gate with name ' + gate.name + ', which cannot be handled!') return result
def test_consistency(): angle = numpy.pi / 2 cpairs = [(CNOT(target=0, control=1), X(target=0, control=1)), (Ry(target=0, angle=numpy.pi), Rz(target=0, angle=4 * numpy.pi) + X(target=0)), (Rz(target=0, angle=numpy.pi), Rz(target=0, angle=numpy.pi) + Z(target=0)), (Rz(target=0, angle=angle), Rz(target=0, angle=angle / 2) + Rz(target=0, angle=angle / 2)), (Rx(target=0, angle=angle), Rx(target=0, angle=angle / 2) + Rx(target=0, angle=angle / 2)), (Ry(target=0, angle=angle), Ry(target=0, angle=angle / 2) + Ry(target=0, angle=angle / 2))] for c in cpairs: print("circuit=", c[0], "\n", c[1]) wfn1 = simulate(c[0], backend="symbolic") wfn2 = simulate(c[1], backend="symbolic") assert (numpy.isclose(wfn1.inner(wfn2), 1.0))
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 and daggered: return Ry(angle=numpy.pi / 2, target=target) elif axis == 0: return Ry(angle=-numpy.pi / 2, 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_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 compile_power_base(gate): if not isinstance(gate, PowerGateImpl): return QCircuit.wrap_gate(gate) power = gate.parameter if gate.name in ['H', 'h', 'Hadamard', 'hadamard']: return compile_h_power(gate=gate) if gate.name == 'X': ### off by global phase of Exp[ pi power /2] ''' if we wanted to do it formally we would use the following a=-numpy.pi/2 b=numpy.pi/2 theta = power*numpy.pi result = QCircuit() result+= Rz(angle=b,target=gate.target) result+= Ry(angle=theta,target=gate.target) result+= Rz(angle=a,target=gate.target) ''' result = Rx(angle=power * numpy.pi, target=gate.target) elif gate.name == 'Y': ### off by global phase of Exp[ pi power /2] theta = power * numpy.pi result = QCircuit() result += Ry(angle=theta, target=gate.target) elif gate.name == 'Z': ### off by global phase of Exp[ pi power /2] a = 0 b = power * numpy.pi theta = 0 result = QCircuit() result += Rz(angle=b, target=gate.target) else: raise TequilaException('passed a gate with name ' + gate.name + ', which cannot be handled!') return result
def get_axbxc_decomp(gate): """ Break down single controlled parametrized power gates into CNOT and rotations. Parameters ---------- gate: the gate. Returns ------- QCircuit; the result of compilation. """ if not isinstance(gate, PowerGateImpl) or gate.name not in ['X', 'Y', 'Z']: return QCircuit.wrap_gate(gate) power = gate.parameter target = gate.target result = QCircuit() if gate.name == 'X': a = -numpy.pi / 2 b = numpy.pi / 2 theta = power * numpy.pi ''' result+=Phase(numpy.pi*power/2,gate.control) result+=Rz(-(a-b)/2,target) result+=CNOT(gate.control,target) #result+=Rz(-(a+b)/2,target) result+=Ry(-theta/2,target) result+=CNOT(gate.control,target) result+=Ry(theta/2,target) result+=Rz(a,target=target) ''' ''' result+=Rz((a-b)/2,target) result+=CNOT(gate.control,target) #result+=Rz(-(a+b)/2,target) result+=Ry(-theta/2,target) result+=CNOT(gate.control,target) result+=Ry(theta/2,target) result+=Rz(a,target) result += Phase(numpy.pi * power / 2, gate.control) ''' result += Rx(angle=theta, target=target, control=gate.control) result += Phase(numpy.pi * power / 2, gate.control) elif gate.name == 'Y': ### off by global phase of Exp[ pi power /2] theta = power * numpy.pi ''' result+=Phase(numpy.pi*power/2,gate.control) result+=CNOT(gate.control,target) result+=Ry(-theta/2,target) result+=CNOT(gate.control,target) result+=Ry(theta/2,target) ''' a = 0 b = 0 # result+=Rz((a-b)/2,target) result += CNOT(gate.control, target) # result+=Rz(-(a+b)/2,target) result += Ry(-theta / 2, target) result += CNOT(gate.control, target) result += Ry(theta / 2, target) # result+=Rz(a,target) result += Phase(numpy.pi * power / 2, gate.control) elif gate.name == 'Z': a = 0 b = power * numpy.pi theta = 0 result += Rz(b / 2, target) result += CNOT(gate.control, target) result += Rz(-b / 2, target) result += CNOT(gate.control, target) # result+=Rz(a,target) result += Phase(numpy.pi * power / 2, gate.control) ''' result+=Rz(b/2,target) result+=CNOT(gate.control,target) result+=Rz(-b/2,target) result+=CNOT(gate.control,target) ''' return result
Rz(target=0, control=ctrl, angle=phi) if ctrl is not None: c_u2 = X(target=ctrl) + c_u2 c_equiv = X(target=ctrl) + c_equiv wfn1 = simulate(c_u2, backend="symbolic") wfn2 = simulate(c_equiv, backend="symbolic") assert (numpy.isclose(wfn1.inner(wfn2), 1.0)) @pytest.mark.parametrize( "gate, theta, phi, lambd", [ (Rx(target=0, control=None, angle=numpy.pi / 5), numpy.pi / 5, -numpy.pi / 2, numpy.pi / 2), # Rx(angle) = u3(angle, -pi/2, pi/2) (Rx(target=0, control=1, angle=numpy.pi / 6), numpy.pi / 6, -numpy.pi / 2, numpy.pi / 2), (Rx(target=0, control=None, angle=numpy.pi / 7), numpy.pi / 7, -numpy.pi / 2, numpy.pi / 2), (Rx(target=0, control=1, angle=numpy.pi / 8), numpy.pi / 8, -numpy.pi / 2, numpy.pi / 2), (Ry(target=0, control=1, angle=numpy.pi / 4), numpy.pi / 4, 0, 0), # Ry(angle) = u3(angle, 0, 0) (Ry(target=0, control=1, angle=numpy.pi / 5), numpy.pi / 5, 0, 0), (Ry(target=0, control=1, angle=numpy.pi / 3), numpy.pi / 3, 0, 0), (Ry(target=0, control=1, angle=numpy.pi / 2), numpy.pi / 2, 0, 0), (Rz(target=0, control=None, angle=numpy.pi), 0, 0, numpy.pi), # Rz(angle) = U(0, 0, angle) (Rz(target=0, control=1, angle=numpy.pi / 6), 0, 0, numpy.pi / 6),
def get_axbxc_decomp(gate): if not isinstance(gate, PowerGateImpl) or gate.name not in ['X', 'Y', 'Z']: return QCircuit.wrap_gate(gate) power = gate.parameter target = gate.target result = QCircuit() if gate.name == 'X': a = -numpy.pi / 2 b = numpy.pi / 2 theta = power * numpy.pi ''' result+=Phase(numpy.pi*power/2,gate.control) result+=Rz(-(a-b)/2,target) result+=CNOT(gate.control,target) #result+=Rz(-(a+b)/2,target) result+=Ry(-theta/2,target) result+=CNOT(gate.control,target) result+=Ry(theta/2,target) result+=Rz(a,target=target) ''' ''' result+=Rz((a-b)/2,target) result+=CNOT(gate.control,target) #result+=Rz(-(a+b)/2,target) result+=Ry(-theta/2,target) result+=CNOT(gate.control,target) result+=Ry(theta/2,target) result+=Rz(a,target) result += Phase(numpy.pi * power / 2, gate.control) ''' result += Rx(angle=theta, target=target, control=gate.control) result += Phase(numpy.pi * power / 2, gate.control) elif gate.name == 'Y': ### off by global phase of Exp[ pi power /2] theta = power * numpy.pi ''' result+=Phase(numpy.pi*power/2,gate.control) result+=CNOT(gate.control,target) result+=Ry(-theta/2,target) result+=CNOT(gate.control,target) result+=Ry(theta/2,target) ''' a = 0 b = 0 # result+=Rz((a-b)/2,target) result += CNOT(gate.control, target) # result+=Rz(-(a+b)/2,target) result += Ry(-theta / 2, target) result += CNOT(gate.control, target) result += Ry(theta / 2, target) # result+=Rz(a,target) result += Phase(numpy.pi * power / 2, gate.control) elif gate.name == 'Z': a = 0 b = power * numpy.pi theta = 0 result += Rz(b / 2, target) result += CNOT(gate.control, target) result += Rz(-b / 2, target) result += CNOT(gate.control, target) # result+=Rz(a,target) result += Phase(numpy.pi * power / 2, gate.control) ''' result+=Rz(b/2,target) result+=CNOT(gate.control,target) result+=Rz(-b/2,target) result+=CNOT(gate.control,target) ''' return result