def qpdf_hamiltonian(nqubits, z_qubit=0): """Precomputes Hamiltonian. Args: nqubits (int): number of qubits. z_qubit (int): qubit where the Z measurement is applied, must be z_qubit < nqubits Returns: An Hamiltonian object. """ eye = matrices.I if z_qubit == 0: h = matrices.Z for _ in range(nqubits - 1): h = np.kron(eye, h) elif z_qubit == nqubits - 1: h = eye for _ in range(nqubits - 2): h = np.kron(eye, h) h = np.kron(matrices.Z, h) else: h = eye for _ in range(nqubits - 1): if _ + 1 == z_qubit: h = np.kron(matrices.Z, h) else: h = np.kron(eye, h) return Hamiltonian(nqubits, h)
def construct_terms(terms): """Helper method for `from_symbolic`. Constructs the term dictionary by using the same :class:`qibo.abstractions.hamiltonians.Hamiltonian` object for terms that have equal matrix representation. This is done for efficiency during the exponentiation of terms. Args: terms (dict): Dictionary that maps tuples of targets to the matrix that acts on these on targets. Returns: terms (dict): Dictionary that maps tuples of targets to the Hamiltonian term that acts on these on targets. """ from qibo.hamiltonians import Hamiltonian unique_matrices = [] hterms = {} for targets, matrix in terms.items(): flag = True for m, h in unique_matrices: if K.np.array_equal(matrix, m): ham = h flag = False break if flag: ham = Hamiltonian(len(targets), matrix, numpy=True) unique_matrices.append((matrix, ham)) hterms[targets] = ham return hterms
def test_trotter_hamiltonian_initialization_errors(): """Test errors in initialization of ``TrotterHamiltonian``.""" # Wrong type of terms with pytest.raises(TypeError): ham = TrotterHamiltonian({(0, 1): "abc"}) # Wrong type of parts with pytest.raises(TypeError): ham = TrotterHamiltonian([(0, 1)]) # Wrong number of target qubits with pytest.raises(ValueError): ham = TrotterHamiltonian({(0, 1): TFIM(nqubits=3, numpy=True)}) # Same targets multiple times h = TFIM(nqubits=2, numpy=True) with pytest.raises(ValueError): ham = TrotterHamiltonian({(0, 1): h}, {(0, 1): h}) # Different term matrix types h2 = Hamiltonian(2, np.eye(4, dtype=np.float32), numpy=True) with pytest.raises(TypeError): ham = TrotterHamiltonian({(0, 1): h, (1, 2): h2}) # ``from_twoqubit_term`` initialization with nqubits < 0 with pytest.raises(ValueError): ham = TrotterHamiltonian.from_twoqubit_term(-2, h) # ``from_twoqubit_term`` initialization with more than 2 targets h = TFIM(nqubits=3, numpy=True) with pytest.raises(ValueError): ham = TrotterHamiltonian.from_twoqubit_term(4, h)
def from_symbolic(cls, symbolic_hamiltonian, symbol_map, ground_state=None): """Creates a ``TrotterHamiltonian`` from a symbolic Hamiltonian. We refer to the :ref:`How to define custom Hamiltonians using symbols? <symbolicham-example>` example for more details. Args: symbolic_hamiltonian (sympy.Expr): The full Hamiltonian written with symbols. symbol_map (dict): Dictionary that maps each symbol that appears in the Hamiltonian to a pair of (target, matrix). ground_state (Callable): Optional callable with no arguments that returns the ground state of this ``TrotterHamiltonian``. See :class:`qibo.base.hamiltonians.TrotterHamiltonian` for more details. Returns: A :class:`qibo.base.hamiltonians.TrotterHamiltonian` object that implements the given symbolic Hamiltonian. """ from qibo.hamiltonians import Hamiltonian terms, constant = _SymbolicHamiltonian( symbolic_hamiltonian, symbol_map).trotter_terms() terms = {k: Hamiltonian(len(k), v, numpy=True) for k, v in terms.items()} return cls.from_dictionary(terms, ground_state=ground_state) + constant
def __init__(self, layers, domain, ansatz, function): self.function = function super().__init__(layers, domain, ansatz) self.target = self.function(self.domain) self.target = 2 * (self.target - np.min(self.target)) / ( np.max(self.target) - np.min(self.target)) - 1 self.H = Hamiltonian(1, matrices._Z) self.classical = globals()[f"classical_real_{self.ansatz}"]
def __init__(self, layers, domain, function, ansatz): self.function = function super().__init__(layers, domain, ansatz) self.target = np.array(list(self.function(self.domain))) self.target = 2 * (self.target - np.min(self.target)) / ( np.max(self.target) - np.min(self.target)) - 1 self.H = Hamiltonian(1, matrices._Z) self.classical = classical_real_Weighted_2D
def __init__(self, layers, domain, ansatz, real, imag): self.f_real = real self.f_imag = imag # self.function.name = lambda:self.real.name + '_' + self.imag.name super().__init__(layers, domain, ansatz) self.real = self.f_real(self.domain) self.real = 2 * (self.real - np.min(self.real)) / ( np.max(self.real) - np.min(self.real)) - 1 self.imag = self.f_imag(self.domain) self.imag = 2 * (self.imag - np.min(self.imag)) / ( np.max(self.imag) - np.min(self.imag)) - 1 self.target = self.real + 1j * self.imag self.target /= np.max(np.abs(self.target)) self.H = [Hamiltonian(1, matrices._X), Hamiltonian(1, matrices._Y)] self.classical = globals()[f"classical_complex_{self.ansatz}"]
def test_trotter_hamiltonian_make_compatible_onequbit_terms(): """Check ``make_compatible`` when the two-qubit Hamiltonian has one-qubit terms.""" term1 = Hamiltonian(1, matrices.Z, numpy=True) term2 = Hamiltonian(2, np.kron(matrices.Z, matrices.Z), numpy=True) terms = { (0, 1): term2, (0, 2): -0.5 * term2, (1, 2): 2 * term2, (1, ): 0.35 * term1, (2, 3): 0.25 * term2, (2, ): 0.5 * term1, (3, ): term1 } tham = TrotterHamiltonian.from_dictionary(terms) + 1.5 xham = X(nqubits=4, trotter=True) cxham = tham.make_compatible(xham) assert not tham.is_compatible(xham) assert tham.is_compatible(cxham) np.testing.assert_allclose(xham.dense.matrix, cxham.dense.matrix)
def test_trotter_hamiltonian_three_qubit_term(backend): """Test creating ``TrotterHamiltonian`` with three qubit term.""" import qibo from scipy.linalg import expm original_backend = qibo.get_backend() qibo.set_backend(backend) m1 = utils.random_numpy_hermitian(3) m2 = utils.random_numpy_hermitian(2) m3 = utils.random_numpy_hermitian(1) term1 = Hamiltonian(3, m1, numpy=True) term2 = Hamiltonian(2, m2, numpy=True) term3 = Hamiltonian(1, m3, numpy=True) parts = [{(0, 1, 2): term1}, {(2, 3): term2, (1, ): term3}] trotter_h = TrotterHamiltonian(*parts) # Test that the `TrotterHamiltonian` dense matrix is correct eye = np.eye(2, dtype=m1.dtype) mm1 = np.kron(m1, eye) mm2 = np.kron(np.kron(eye, eye), m2) mm3 = np.kron(np.kron(eye, m3), np.kron(eye, eye)) target_h = Hamiltonian(4, mm1 + mm2 + mm3) np.testing.assert_allclose(trotter_h.dense.matrix, target_h.matrix) dt = 1e-2 initial_state = utils.random_numpy_state(4) if backend == "custom": with pytest.raises(NotImplementedError): circuit = trotter_h.circuit(dt=dt) else: circuit = trotter_h.circuit(dt=dt) final_state = circuit(np.copy(initial_state)) u = [expm(-0.5j * dt * m) for m in [mm1, mm2, mm3]] target_state = u[2].dot(u[1].dot(u[0])).dot(initial_state) target_state = u[0].dot(u[1].dot(u[2])).dot(target_state) np.testing.assert_allclose(final_state, target_state) qibo.set_backend(original_backend)
def test_hamiltonian_initialization(): """Testing hamiltonian initialization errors.""" import tensorflow as tf dtype = K.dtypes('DTYPECPX') with pytest.raises(TypeError): H = Hamiltonian(2, "test") H1 = Hamiltonian(2, np.eye(4)) H1 = Hamiltonian(2, np.eye(4), numpy=True) H1 = Hamiltonian(2, tf.eye(4, dtype=dtype)) H1 = Hamiltonian(2, tf.eye(4, dtype=dtype), numpy=True) with pytest.raises(ValueError): H1 = Hamiltonian(-2, np.eye(4)) with pytest.raises(RuntimeError): H2 = Hamiltonian(np.eye(2), np.eye(4)) with pytest.raises(ValueError): H3 = Hamiltonian(4, np.eye(10))