def KetBra(ket: QubitWaveFunction, bra: QubitWaveFunction, hermitian: bool = False, threshold: float = 1.e-6, n_qubits=None): """ Notes ---------- Initialize the general KetBra operator .. math:: H = \\lvert ket \\rangle \\langle bra \\rvert e.g. wfn1 = tq.QubitWaveFunction.from_string("1.0*|00> + 1.0*|11>").normalize() wfn2 = tq.QubitWaveFunction.from_string("1.0*|00>") operator = tq.paulis.KetBra(ket=wfn1, bra=wfn1) initializes the transfer operator from the all-zero state to a Bell state Parameters ---------- ket: QubitWaveFunction: QubitWaveFunction which defines the ket element can also be given as string or array or integer bra: QubitWaveFunction: QubitWaveFunction which defines the bra element can also be given as string or array or integer hermitian: bool: (Default False) if True the hermitian version H + H^\dagger is returned threshold: float: (Default 1.e-6) elements smaller than the threshold will be ignored n_qubits: only needed if ket and/or bra are passed down as integers Returns ------- a tequila QubitHamiltonian (not necessarily hermitian) """ H = QubitHamiltonian.zero() ket = QubitWaveFunction(state=ket, n_qubits=n_qubits) bra = QubitWaveFunction(state=bra, n_qubits=n_qubits) for k1, v1 in bra.items(): for k2, v2 in ket.items(): c = v1.conjugate() * v2 if not numpy.isclose(c, 0.0, atol=threshold): H += c * decompose_transfer_operator(bra=k1, ket=k2) if hermitian: return H.split()[0] else: return H.simplify(threshold=threshold)
def apply_gate(cls, state: QubitWaveFunction, gate: QGate, qubits: dict, variables) -> QubitWaveFunction: result = QubitWaveFunction() n_qubits = len(qubits.keys()) for s, v in state.items(): s.nbits = n_qubits result += v * cls.apply_on_standard_basis(gate=gate, basisfunction=s, qubits=qubits, variables=variables) return result
def test_random_instances(target_space): # can happen that a tests fails, just start again ... if all tests fail: start to worry # it happens from time to time that UPS can not disentangle # it will throw the error/ # OpenVQEException: Could not disentangle the given state after 100 restarts qubits = len(target_space) coeffs = numpy.random.uniform(0, 1, qubits) wfn = QubitWaveFunction() for i, c in enumerate(coeffs): wfn += c * QubitWaveFunction.from_string("1.0|" + target_space[i] + ">") wfn = wfn.normalize() try: UPS = UnaryStatePrep(target_space=target_space) U = UPS(wfn=wfn) # now the coeffs are normalized bf2c = dict() for i, c in enumerate(coeffs): bf2c[target_space[i]] = coeffs[i] wfn2 = tequila.simulators.simulator_api.simulate(U, initial_state=0, variables=None) for k, v in wfn.items(): assert (numpy.isclose(wfn2[k], v)) except TequilaUnaryStateException: print("caught a tolerated excpetion")
def test_unary_states(target_space: list): UPS = UnaryStatePrep(target_space=target_space) qubits = len(target_space) coeff = 1.0 / numpy.sqrt( qubits ) # fails for the 3-Qubit Case because the wrong sign is picked in the solution coeffs = [coeff for i in range(qubits)] wfn = QubitWaveFunction() for i, c in enumerate(coeffs): wfn += c * QubitWaveFunction.from_string("1.0|" + target_space[i] + ">") U = UPS(wfn=wfn) wfn = BackendCircuitSymbolic(abstract_circuit=U, variables=None).simulate(variables=None) checksum = 0.0 for k, v in wfn.items(): assert (v.imag == 0.0) vv = numpy.float(v.real) cc = numpy.float(coeff.real) assert (numpy.isclose(vv, cc, atol=1.e-4)) checksum += vv assert (numpy.isclose(checksum, qubits * coeff, atol=1.e-4))
def Projector(wfn, threshold=0.0, n_qubits=None) -> QubitHamiltonian: """ Notes ---------- Initialize a projector given by .. math:: H = \\lvert \\Psi \\rangle \\langle \\Psi \\rvert Parameters ---------- wfn: QubitWaveFunction or int, or string, or array : The wavefunction onto which the projector projects Needs to be passed down as tequilas QubitWaveFunction type See the documentation on how to initialize a QubitWaveFunction from integer, string or array (can also be passed down diretly as one of those types) threshold: float: (Default value = 0.0) neglect small parts of the operator n_qubits: only needed when an integer is given as wavefunction Returns ------- """ wfn = QubitWaveFunction(state=wfn, n_qubits=n_qubits) H = QubitHamiltonian.zero() for k1, v1 in wfn.items(): for k2, v2 in wfn.items(): c = v1.conjugate() * v2 if not numpy.isclose(c, 0.0, atol=threshold): H += c * decompose_transfer_operator(bra=k1, ket=k2) assert (H.is_hermitian()) return H
def strip_sympy_zeros(wfn: QubitWaveFunction): result = QubitWaveFunction() for k, v in wfn.items(): if v != 0: result[k] = v return result