def test_trotter_hamiltonian_operation_errors(): """Test errors in ``TrotterHamiltonian`` addition and subtraction.""" # test addition with different number of parts h1 = TFIM(nqubits=5, trotter=True) term = TFIM(nqubits=2, numpy=True) h2 = TrotterHamiltonian({ (0, 1): term, (2, 3): term }, { (1, 2): term, (3, 4): term }, {(4, 0): term}) with pytest.raises(ValueError): h = h1 + h2 # test subtraction with incompatible parts h2 = TrotterHamiltonian({ (0, 1): term, (2, 3): term }, { (1, 2): term, (3, 4): term }) with pytest.raises(ValueError): h = h1 - h2 # test matmul with bad type with pytest.raises(NotImplementedError): s = h1 @ "abc" # test matmul with bad shape with pytest.raises(ValueError): s = h1 @ np.zeros((2, 2))
def test_trotter_hamiltonian_make_compatible_repeating(nqubits): """Check ``make_compatible`` when first target is repeated in parts.""" h0target = X(nqubits) h0 = X(nqubits, trotter=True) term = TFIM(2, numpy=True) parts = [{(0, i): term} for i in range(1, nqubits)] parts.extend(({(i, 0): term} for i in range(1, nqubits))) h1 = TrotterHamiltonian(*parts) h0c = h1.make_compatible(h0) assert not h1.is_compatible(h0) assert h1.is_compatible(h0c) np.testing.assert_allclose(h0c.matrix, h0target.matrix)
def test_trotter_hamiltonian_make_compatible_redundant(): """Test ``make_compatible`` with redudant two-qubit terms.""" h0 = X(2, trotter=True) target_matrix = h0.dense.matrix.numpy() target_matrix = np.kron(target_matrix, np.eye(2, dtype=target_matrix.dtype)) parts = [{(0, 1, 2): TFIM(3, numpy=True)}] h1 = TrotterHamiltonian(*parts) h0c = h1.make_compatible(h0) assert not h1.is_compatible(h0) assert h1.is_compatible(h0c) np.testing.assert_allclose(h0c.matrix, target_matrix)
def test_trotter_hamiltonian_make_compatible_simple(): """Test ``make_compatible`` on a simple 3-qubit example.""" h0target = X(3) h0 = X(3, trotter=True) term1 = Y(1, numpy=True) term2 = TFIM(2, numpy=True) parts = [{(0, 1): term2, (1, 2): term2, (0, 2): term2, (2, ): term1}] h1 = TrotterHamiltonian(*parts) h0c = h1.make_compatible(h0) assert not h1.is_compatible(h0) assert h1.is_compatible(h0c) np.testing.assert_allclose(h0c.matrix, h0target.matrix)
def test_from_symbolic_application_hamiltonian(): """Check ``from_symbolic`` for a specific four-qubit Hamiltonian.""" import sympy z1, z2, z3, z4 = sympy.symbols("z1 z2 z3 z4") symmap = {z: (i, matrices.Z) for i, z in enumerate([z1, z2, z3, z4])} symham = (z1 * z2 - 0.5 * z1 * z3 + 2 * z2 * z3 + 0.35 * z2 + 0.25 * z3 * z4 + 0.5 * z3 + z4 - z1) # Check that Trotter dense matrix agrees will full Hamiltonian matrix fham = Hamiltonian.from_symbolic(symham, symmap) tham = TrotterHamiltonian.from_symbolic(symham, symmap) np.testing.assert_allclose(tham.dense.matrix, fham.matrix) # Check that no one-qubit terms exist in the Trotter Hamiltonian # (this means that merging was successful) first_targets = set() for part in tham.parts: for targets, term in part.items(): first_targets.add(targets[0]) assert len(targets) == 2 assert term.nqubits == 2 assert first_targets == set(range(4)) # Check making an ``X`` Hamiltonian compatible with ``tham`` 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_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 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 Hamiltonian types h2 = TFIM(nqubits=2, numpy=False) with pytest.raises(TypeError): ham = TrotterHamiltonian({(0, 1): h, (1, 2): h2})
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_trotter_hamiltonian_operation_errors(): """Test errors in ``TrotterHamiltonian`` addition and subtraction.""" # test addition with different number of parts h1 = TFIM(nqubits=5, trotter=True) term = TFIM(nqubits=2, numpy=True) h2 = TrotterHamiltonian({ (0, 1): term, (2, 3): term, (4, 0): term }, { (1, 2): term, (3, 4): term }) with pytest.raises(ValueError): h = h1 + h2 # test subtraction with incompatible parts h2 = TrotterHamiltonian({ (0, 1): term, (2, 3): term }, {(1, 2): term}, {(4, 0): term}) with pytest.raises(ValueError): h = h1 - h2 # test matmul with bad type with pytest.raises(NotImplementedError): s = h1 @ "abc" # test matmul with bad shape with pytest.raises(ValueError): s = h1 @ np.zeros((2, 2)) # test ``make_compatible`` with non-Trotter Hamiltonian with pytest.raises(TypeError): h2 = h1.make_compatible("test") # test ``make_compatible`` with interacting Hamiltonian with pytest.raises(NotImplementedError): h2 = h1.make_compatible(h2) # test ``make_compatible`` with insufficient two-qubit terms h3 = X(nqubits=7, trotter=True) with pytest.raises(ValueError): h3 = h1.make_compatible(h3)
def test_x_hamiltonian_from_symbols(nqubits, trotter): """Check creating sum(X) Hamiltonian using sympy.""" import sympy x_symbols = sympy.symbols(" ".join((f"X{i}" for i in range(nqubits)))) symham = -sum(x_symbols) symmap = {x: (i, matrices.X) for i, x in enumerate(x_symbols)} target_matrix = X(nqubits).matrix if trotter: trotter_ham = TrotterHamiltonian.from_symbolic(symham, symmap) final_matrix = trotter_ham.dense.matrix else: full_ham = Hamiltonian.from_symbolic(symham, symmap) final_matrix = full_ham.matrix np.testing.assert_allclose(final_matrix, target_matrix)
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_tfim_hamiltonian_from_symbols(nqubits, trotter): """Check creating TFIM Hamiltonian using sympy.""" import sympy h = 0.5 z_symbols = sympy.symbols(" ".join((f"Z{i}" for i in range(nqubits)))) x_symbols = sympy.symbols(" ".join((f"X{i}" for i in range(nqubits)))) symham = sum(z_symbols[i] * z_symbols[i + 1] for i in range(nqubits - 1)) symham += z_symbols[0] * z_symbols[-1] symham += h * sum(x_symbols) symmap = {z: (i, matrices.Z) for i, z in enumerate(z_symbols)} symmap.update({x: (i, matrices.X) for i, x in enumerate(x_symbols)}) target_matrix = TFIM(nqubits, h=h).matrix if trotter: trotter_ham = TrotterHamiltonian.from_symbolic(-symham, symmap) final_matrix = trotter_ham.dense.matrix else: full_ham = Hamiltonian.from_symbolic(-symham, symmap) final_matrix = full_ham.matrix np.testing.assert_allclose(final_matrix, target_matrix)
def test_three_qubit_term_hamiltonian_from_symbols(trotter): """Check creating Hamiltonian with three-qubit interaction using sympy.""" import sympy from qibo import matrices x_symbols = sympy.symbols(" ".join((f"X{i}" for i in range(4)))) y_symbols = sympy.symbols(" ".join((f"Y{i}" for i in range(4)))) z_symbols = sympy.symbols(" ".join((f"Z{i}" for i in range(4)))) symmap = {x: (i, matrices.X) for i, x in enumerate(x_symbols)} symmap.update({x: (i, matrices.Y) for i, x in enumerate(y_symbols)}) symmap.update({x: (i, matrices.Z) for i, x in enumerate(z_symbols)}) symham = x_symbols[0] * y_symbols[1] * z_symbols[2] symham += 0.5 * y_symbols[0] * z_symbols[1] * x_symbols[3] symham += z_symbols[0] * x_symbols[2] symham += -3 * x_symbols[1] * y_symbols[3] symham += y_symbols[2] symham += 1.5 * z_symbols[1] symham -= 2 target_matrix = np.kron(np.kron(matrices.X, matrices.Y), np.kron(matrices.Z, matrices.I)) target_matrix += 0.5 * np.kron(np.kron(matrices.Y, matrices.Z), np.kron(matrices.I, matrices.X)) target_matrix += np.kron(np.kron(matrices.Z, matrices.I), np.kron(matrices.X, matrices.I)) target_matrix += -3 * np.kron(np.kron(matrices.I, matrices.X), np.kron(matrices.I, matrices.Y)) target_matrix += np.kron(np.kron(matrices.I, matrices.I), np.kron(matrices.Y, matrices.I)) target_matrix += 1.5 * np.kron(np.kron(matrices.I, matrices.Z), np.kron(matrices.I, matrices.I)) target_matrix -= 2 * np.eye(2**4, dtype=target_matrix.dtype) if trotter: trotter_ham = TrotterHamiltonian.from_symbolic(symham, symmap) final_matrix = trotter_ham.dense.matrix else: full_ham = Hamiltonian.from_symbolic(symham, symmap) final_matrix = full_ham.matrix np.testing.assert_allclose(final_matrix, target_matrix)
def test_from_symbolic_with_power(trotter): """Check ``from_symbolic`` when the expression contains powers.""" import sympy z = sympy.symbols(" ".join((f"Z{i}" for i in range(3)))) symham = z[0]**2 - z[1]**2 + 3 * z[1] - 2 * z[0] * z[2] + +1 matrix = utils.random_numpy_hermitian(1) symmap = {x: (i, matrix) for i, x in enumerate(z)} if trotter: ham = TrotterHamiltonian.from_symbolic(symham, symmap) final_matrix = ham.dense.matrix else: ham = Hamiltonian.from_symbolic(symham, symmap) final_matrix = ham.matrix matrix2 = matrix.dot(matrix) eye = np.eye(2, dtype=matrix.dtype) target_matrix = np.kron(np.kron(matrix2, eye), eye) target_matrix -= np.kron(np.kron(eye, matrix2), eye) target_matrix += 3 * np.kron(np.kron(eye, matrix), eye) target_matrix -= 2 * np.kron(np.kron(matrix, eye), matrix) target_matrix += np.eye(8, dtype=matrix.dtype) np.testing.assert_allclose(final_matrix, target_matrix)