def test_initialization(): H = paulis.I() for i in range(10): H += paulis.pauli(qubit=numpy.random.randint(0,5,3), type=numpy.random.choice(["X", "Y", "Z"],1)) for H1 in [H, paulis.I(), paulis.Zero(), paulis.X(0), paulis.Y(1), 1.234*paulis.Z(2)]: string = str(H1) ofstring = str(H1.to_openfermion()) H2 = QubitHamiltonian.from_string(string=string) assert H1 == H2 H3 = QubitHamiltonian.from_string(string=ofstring, openfermion_format=True) assert H1 == H3
def test_amp_damp(simulator, p): qubit = 0 H = (0.5) * (paulis.I(0) - paulis.Z(0)) U = gates.X(target=qubit) O = ExpectationValue(U=U, H=H) NM = AmplitudeDamp(p, 1) E = simulate(O, backend=simulator, samples=1, noise=NM)
def QubitExcitation(angle: typing.Union[numbers.Real, Variable, typing.Hashable], target: typing.List, control=None, assume_real: bool = False): """ A Qubit Excitation, as described under "qubit perspective" in https://doi.org/10.1039/D0SC06627C For the Fermionic operators under corresponding Qubit encodings: Use the chemistry interface Parameters ---------- angle: the angle of the excitation unitary target: even number of qubit indices interpreted as [0,1,2,3....] = [(0,1), (2,3), ...] i.e. as qubit excitations from 0 to 1, 2 to 3, etc control: possible control qubits assume_real: assume the wavefunction on which this acts is always real (cheaper gradients: see https://doi.org/10.1039/D0SC06627C) Returns ------- QubitExcitation gate wrapped into a tequila circuit """ try: assert len(target) % 2 == 0 except: raise Exception("QubitExcitation: Needs an even number of targets") generator = paulis.I() p0a = paulis.I() p0b = paulis.I() for i in range(len(target) // 2): generator *= paulis.Sp(target[2 * i]) * paulis.Sm(target[2 * i + 1]) p0a *= paulis.Qp(target[2 * i]) * paulis.Qm(target[2 * i + 1]) p0b *= paulis.Qm(target[2 * i]) * paulis.Qp(target[2 * i + 1]) generator = (1.0j * (generator - generator.dagger())).simplify() p0 = paulis.I() - p0a - p0b return QCircuit.wrap_gate( impl.QubitExcitationImpl(angle=angle, generator=generator, p0=p0, assume_real=assume_real))
def __init__(self, phase, target: list, control: list = None): assert (phase is not None) super().__init__(eigenvalues_magnitude=0.5, name='Phase', parameter=phase, target=target, control=control) self.generator = paulis.Z(target) - paulis.I(target)
def test_rz_phase_flip_1(simulator, p, angle): U = gates.X(target=0) + gates.H(1) + gates.CRz(control=0, target=1, angle=Variable('a')) + gates.H(1) H = paulis.Z(1) * paulis.I(0) O = ExpectationValue(U, H) NM = PhaseFlip(p, 2) E = simulate(O, backend=simulator, variables={'a': angle}, samples=1000, noise=NM) print(E) assert (numpy.isclose(E, ((1.0 - 2 * p) ** 2) * numpy.cos(angle), atol=1.e-1))
def __init__(self, angle, target=None, generator=None, p0=None, assume_real=True, control=None, compile_options=None): angle = assign_variable(angle) if generator is None: assert target is not None assert p0 is None generator = paulis.I() p0a = paulis.I() p0b = paulis.I() for i in range(len(target) // 2): generator *= paulis.Sp(target[2 * i]) * paulis.Sm( target[2 * i + 1]) p0a *= paulis.Qp(target[2 * i]) * paulis.Qm(target[2 * i + 1]) p0b *= paulis.Qm(target[2 * i]) * paulis.Qp(target[2 * i + 1]) generator = (1.0j * (generator - generator.dagger())).simplify() p0 = paulis.I() - p0a - p0b else: assert generator is not None assert p0 is not None super().__init__(name="QubitExcitation", parameter=angle, target=self.extract_targets(generator), control=control) self.generator = generator if control is not None: # augment p0 for control qubits # Qp = 1/2(1+Z) = |0><0| p0 = p0 * paulis.Qp(control) self.p0 = p0 self.assume_real = assume_real if compile_options is None: self.compile_options = "optimize" else: self.compile_options = compile_options
def test_rx_bit_flip_1(simulator, p, angle): U = gates.X(target=0) + gates.CRx(control=0, target=1, angle="a") H = paulis.Z(1) * paulis.I(0) NM = BitFlip(p, 2) O = ExpectationValue(U=U, H=H) E = simulate(O, backend=simulator, samples=1000, variables={'a': angle}, noise=NM) print(E) print(p + numpy.cos(angle) - p * numpy.cos(angle)) assert (numpy.isclose(E, p + numpy.cos(angle) - p * numpy.cos(angle), atol=1.e-1))
def test_rz_phase_flip_1(simulator, p, angle): U = gates.X(target=0) + gates.H(1) + gates.CRz( control=0, target=1, angle=Variable('a')) + gates.H(1) H = paulis.Z(1) * paulis.I(0) O = ExpectationValue(U, H) NM = PhaseFlip(p, 2) E = simulate(O, backend=simulator, variables={'a': angle}, samples=1, noise=NM) print(E)
def test_special_operators(): # sigma+ sigma- as well as Q+ and Q- assert (paulis.Sp(0) * paulis.Sp(0) == QubitHamiltonian.zero()) assert (paulis.Sm(0) * paulis.Sm(0) == QubitHamiltonian.zero()) assert (paulis.Qp(0) * paulis.Qp(0) == paulis.Qp(0)) assert (paulis.Qm(0) * paulis.Qm(0) == paulis.Qm(0)) assert (paulis.Qp(0) * paulis.Qm(0) == QubitHamiltonian.zero()) assert (paulis.Qm(0) * paulis.Qp(0) == QubitHamiltonian.zero()) assert (paulis.Sp(0) * paulis.Sm(0) == paulis.Qp(0)) assert (paulis.Sm(0) * paulis.Sp(0) == paulis.Qm(0)) assert (paulis.Sp(0) + paulis.Sm(0) == paulis.X(0)) assert (paulis.Qp(0) + paulis.Qm(0) == paulis.I(0))
def test_rx_bit_flip_1(simulator, p, angle): qubit = 1 U = gates.X(target=0) + gates.CRx(control=0, target=1, angle=Variable('a')) H = paulis.Z(1) * paulis.I(0) NM = BitFlip(p, 2) O = ExpectationValue(U=U, H=H) E = simulate(O, backend=simulator, samples=1, variables={'a': angle}, noise=NM) print(E) print(p + numpy.cos(angle) - p * numpy.cos(angle))
def test_binarypauli_conversion(): ''' Testing PauliString's built-in binary form conversion ''' H, n_qubits, binary_sol, coeff_sol = prepare_test_hamiltonian() word1 = H.paulistrings[0].binary(n_qubits) word2 = H.paulistrings[1].binary(n_qubits) word3 = H.paulistrings[2].binary(n_qubits) word4 = paulis.I().paulistrings[0].binary(n_qubits) assert (word1.coeff == coeff_sol[0]) assert (all(word1.binary == binary_sol[0, :])) assert (word2.coeff == coeff_sol[1]) assert (all(word2.binary == binary_sol[1, :])) assert (word3.coeff == coeff_sol[2]) assert (all(word3.binary == binary_sol[2, :])) assert (all(word4.binary == np.zeros(2 * n_qubits)))
def test_convenience(): i = numpy.random.randint(0, 10, 1)[0] assert paulis.X(i) + paulis.I(i) == paulis.X(i) + 1.0 assert paulis.Qp(i) == 0.5 * (1.0 + paulis.Z(i)) assert paulis.Qm(i) == 0.5 * (1.0 - paulis.Z(i)) assert paulis.Sp(i) == 0.5 * (paulis.X(i) + 1.j * paulis.Y(i)) assert paulis.Sm(i) == 0.5 * (paulis.X(i) - 1.j * paulis.Y(i)) i = numpy.random.randint(0, 10, 1)[0] assert paulis.Qp(i) == (0.5 + 0.5 * paulis.Z(i)) assert paulis.Qm(i) == (0.5 - 0.5 * paulis.Z(i)) assert paulis.Sp(i) == (0.5 * paulis.X(i) + 0.5j * paulis.Y(i)) assert paulis.Sm(i) == (0.5 * paulis.X(i) - 0.5j * paulis.Y(i)) assert -1.0 * paulis.Y(i) == -paulis.Y(i) test = paulis.Z(i) test *= -1.0 assert test == -paulis.Z(i) test = paulis.Z(i) test += 1.0 assert test == paulis.Z(i) + 1.0 test = paulis.X(i) test += paulis.Y(i + 1) assert test == paulis.X(i) + paulis.Y(i + 1) test = paulis.X(i) test -= paulis.Y(i) test += 3.0 test = -test assert test == -1.0 * (paulis.X(i) - paulis.Y(i) + 3.0) test = paulis.X([0, 1, 2, 3]) assert test == QubitHamiltonian.from_string("X(0)X(1)X(2)X(3)", False) test = paulis.Y([0, 1, 2, 3]) assert test == QubitHamiltonian.from_string("Y(0)Y(1)Y(2)Y(3)", False) test = paulis.Z([0, 1, 2, 3]) assert test == QubitHamiltonian.from_string("Z(0)Z(1)Z(2)Z(3)", False)
def H(target: typing.Union[list, int], control: typing.Union[list, int] = None, power=None, angle=None, *args, **kwargs) -> QCircuit: """ Notes ---------- Hadamard gate Parameters ---------- target int or list of int control int or list of int power numeric type (fixed exponent) or hashable type (parametrized exponent) angle similar to power, but will be interpreted as .. math:: U(\\text{angle})=e^{-i\\frac{angle}{2} generator} the default is angle=pi .. math:: U(\\pi) = H If angle and power are given both, tequila will combine them Returns ------- QCircuit object """ coef = 1 / np.sqrt(2) generator = lambda q: coef * (paulis.Z(q) + paulis.X(q)) - paulis.I(q) return _initialize_power_gate(name="H", power=power, angle=angle, target=target, control=control, generator=generator, *args, **kwargs)
def SWAP(first: int, second: int, control: typing.Union[int, list] = None, power: float = None, *args, **kwargs) -> QCircuit: """ Notes ---------- SWAP gate, order of targets does not matter Parameters ---------- first: int target qubit second: int target qubit control int or list of ints power numeric type (fixed exponent) or hashable type (parametrized exponent) Returns ------- QCircuit """ target = [first, second] generator = 0.5 * (paulis.X(target) + paulis.Y(target) + paulis.Z(target) - paulis.I(target)) if power is None or power in [1, 1.0]: return QGate(name="SWAP", target=target, control=control, generator=generator) else: return GeneralizedRotation(angle=power * np.pi, control=control, generator=generator, eigenvalues_magnitude=0.25)
def Y(target: typing.Union[list, int], control: typing.Union[list, int] = None, power=None, angle=None, *args, **kwargs) -> QCircuit: """ Notes ---------- Pauli Y Gate Parameters ---------- target: int or list of int control int or list of int power numeric type (fixed exponent) or hashable type (parametrized exponent) angle similar to power, but will be interpreted as .. math:: U(\\text{angle})=e^{-i\\frac{angle}{2} (1-Y)} the default is angle=pi .. math:: U(\\pi) = Y If angle and power are given both, tequila will combine them Returns ------- QCircuit object """ generator = lambda q: paulis.Y(q) - paulis.I(q) return _initialize_power_gate(name="Y", power=power, angle=angle, target=target, control=control, generator=generator)