diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md
index d607381fde..02116881ad 100644
--- a/.github/CHANGELOG.md
+++ b/.github/CHANGELOG.md
@@ -9,6 +9,9 @@
 * Introduces requirements-dev.txt and improves dockerfile.
 [(#330)](https://github.com/PennyLaneAI/pennylane-lightning/pull/330)
 
+* Support `expval` for a Hamiltonian.
+[(#333)](https://github.com/PennyLaneAI/pennylane-lightning/pull/333)
+
 ### Documentation
 
 ### Bug fixes
diff --git a/pennylane_lightning/_serialize.py b/pennylane_lightning/_serialize.py
index 309484ad3d..e0e546192a 100644
--- a/pennylane_lightning/_serialize.py
+++ b/pennylane_lightning/_serialize.py
@@ -27,6 +27,7 @@
 from pennylane.grouping import is_pauli_word
 from pennylane.operation import Observable, Tensor
 from pennylane.tape import QuantumTape
+from pennylane.math import unwrap
 
 # Remove after the next release of PL
 # Add from pennylane import matrix
@@ -111,7 +112,7 @@ def _serialize_hamiltonian(ob, wires_map: dict, use_csingle: bool):
         rtype = np.float64
         hamiltonian_obs = HamiltonianC128
 
-    coeffs = np.array(ob.coeffs).astype(rtype)
+    coeffs = np.array(unwrap(ob.coeffs)).astype(rtype)
     terms = [_serialize_ob(t, wires_map, use_csingle) for t in ob.ops]
     return hamiltonian_obs(coeffs, terms)
 
diff --git a/pennylane_lightning/_version.py b/pennylane_lightning/_version.py
index 35bb0bee32..41ac2b39c3 100644
--- a/pennylane_lightning/_version.py
+++ b/pennylane_lightning/_version.py
@@ -16,4 +16,4 @@
    Version number (major.minor.patch[-label])
 """
 
-__version__ = "0.26.0-dev3"
+__version__ = "0.26.0-dev4"
diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py
index c865756569..ce6159a279 100644
--- a/pennylane_lightning/lightning_qubit.py
+++ b/pennylane_lightning/lightning_qubit.py
@@ -57,7 +57,7 @@
         best_alignment,
     )
 
-    from ._serialize import _serialize_observables, _serialize_ops
+    from ._serialize import _serialize_ob, _serialize_observables, _serialize_ops
 
     CPP_BINARY_AVAILABLE = True
 except ModuleNotFoundError:
@@ -621,8 +621,6 @@ def expval(self, observable, shot_range=None, bin_size=None):
         if isinstance(observable.name, List) or observable.name in [
             "Identity",
             "Projector",
-            "Hermitian",
-            "Hamiltonian",
         ]:
             return super().expval(observable, shot_range=shot_range, bin_size=bin_size)
 
@@ -648,6 +646,10 @@ def expval(self, observable, shot_range=None, bin_size=None):
                 )
             return super().expval(observable, shot_range=shot_range, bin_size=bin_size)
 
+        if observable.name in ["Hamiltonian", "Hermitian"]:
+            ob_serialized = _serialize_ob(observable, self.wire_map, use_csingle=self.use_csingle)
+            return M.expval(ob_serialized)
+
         # translate to wire labels used by device
         observable_wires = self.map_wires(observable.wires)
 
diff --git a/pennylane_lightning/src/algorithms/AlgUtil.hpp b/pennylane_lightning/src/algorithms/AlgUtil.hpp
index 8e1f50a064..4ea92712e6 100644
--- a/pennylane_lightning/src/algorithms/AlgUtil.hpp
+++ b/pennylane_lightning/src/algorithms/AlgUtil.hpp
@@ -66,7 +66,7 @@ inline void applyOperationAdj(StateVectorManagedCPU<T> &state,
  */
 template <typename T>
 inline void applyObservable(StateVectorManagedCPU<T> &state,
-                            Observable<T> &observable) {
+                            Simulators::Observable<T> &observable) {
     observable.applyInPlace(state);
 }
 
@@ -79,10 +79,11 @@ inline void applyObservable(StateVectorManagedCPU<T> &state,
  * @param observables Vector of observables to apply to each statevector.
  */
 template <typename T>
-inline void applyObservables(
-    std::vector<StateVectorManagedCPU<T>> &states,
-    const StateVectorManagedCPU<T> &reference_state,
-    const std::vector<std::shared_ptr<Observable<T>>> &observables) {
+inline void
+applyObservables(std::vector<StateVectorManagedCPU<T>> &states,
+                 const StateVectorManagedCPU<T> &reference_state,
+                 const std::vector<std::shared_ptr<Simulators::Observable<T>>>
+                     &observables) {
     std::exception_ptr ex = nullptr;
     size_t num_observables = observables.size();
 
diff --git a/pennylane_lightning/src/algorithms/CMakeLists.txt b/pennylane_lightning/src/algorithms/CMakeLists.txt
index 7b7bfca8d1..50e315a4fe 100644
--- a/pennylane_lightning/src/algorithms/CMakeLists.txt
+++ b/pennylane_lightning/src/algorithms/CMakeLists.txt
@@ -1,6 +1,6 @@
 project(lightning_algorithms LANGUAGES CXX)
 
-set(ALGORITHM_FILES AdjointDiff.cpp Observables.cpp JacobianTape.cpp StateVecAdjDiff.cpp CACHE INTERNAL "" FORCE)
+set(ALGORITHM_FILES AdjointDiff.cpp JacobianTape.cpp StateVecAdjDiff.cpp CACHE INTERNAL "" FORCE)
 add_library(lightning_algorithms STATIC ${ALGORITHM_FILES})
 
 target_link_libraries(lightning_algorithms PRIVATE lightning_compile_options
diff --git a/pennylane_lightning/src/algorithms/JacobianTape.hpp b/pennylane_lightning/src/algorithms/JacobianTape.hpp
index 1c94696a1b..848db63950 100644
--- a/pennylane_lightning/src/algorithms/JacobianTape.hpp
+++ b/pennylane_lightning/src/algorithms/JacobianTape.hpp
@@ -206,7 +206,7 @@ template <class T> class JacobianData {
      * @var observables
      * Observables for which to calculate Jacobian.
      */
-    const std::vector<std::shared_ptr<Observable<T>>> observables;
+    const std::vector<std::shared_ptr<Simulators::Observable<T>>> observables;
 
     /**
      * @var operations
@@ -238,7 +238,7 @@ template <class T> class JacobianData {
      * @endrst
      */
     JacobianData(size_t num_params, size_t num_elem, std::complex<T> *ps,
-                 std::vector<std::shared_ptr<Observable<T>>> obs,
+                 std::vector<std::shared_ptr<Simulators::Observable<T>>> obs,
                  OpsData<T> ops, std::vector<size_t> trainP)
         : num_parameters(num_params), num_elements(num_elem), psi(ps),
           observables(std::move(obs)), operations(std::move(ops)),
@@ -278,7 +278,7 @@ template <class T> class JacobianData {
      * @return List of observables
      */
     [[nodiscard]] auto getObservables() const
-        -> const std::vector<std::shared_ptr<Observable<T>>> & {
+        -> const std::vector<std::shared_ptr<Simulators::Observable<T>>> & {
         return observables;
     }
 
diff --git a/pennylane_lightning/src/bindings/Bindings.cpp b/pennylane_lightning/src/bindings/Bindings.cpp
index 9ec619c7b4..92caecefe9 100644
--- a/pennylane_lightning/src/bindings/Bindings.cpp
+++ b/pennylane_lightning/src/bindings/Bindings.cpp
@@ -18,6 +18,7 @@
 #include "Bindings.hpp"
 
 #include "GateUtil.hpp"
+#include "Measures.hpp"
 #include "StateVecAdjDiff.hpp"
 #include "StateVectorManagedCPU.hpp"
 
@@ -27,6 +28,7 @@
 namespace {
 using namespace Pennylane;
 using namespace Pennylane::Util;
+using namespace Pennylane::Simulators;
 using namespace Pennylane::Algorithms;
 using namespace Pennylane::Gates;
 
@@ -95,6 +97,13 @@ void lightning_class_bindings(py::module_ &m) {
                  const std::string &, const std::vector<size_t> &)>(
                  &Measures<PrecisionT>::expval),
              "Expected value of an operation by name.")
+        .def(
+            "expval",
+            [](Measures<PrecisionT> &M,
+               const std::shared_ptr<Observable<PrecisionT>> &ob) {
+                return M.expval(*ob);
+            },
+            "Expected value of an operation object.")
         .def(
             "expval",
             [](Measures<PrecisionT> &M, const np_arr_sparse_ind row_map,
@@ -413,7 +422,7 @@ PYBIND11_MODULE(lightning_qubit_ops, // NOLINT: No control over Pybind internals
     /* Add compile info */
     m.def("compile_info", &getCompileInfo, "Compiled binary information.");
 
-    /* Add compile info */
+    /* Add runtime info */
     m.def("runtime_info", &getRuntimeInfo, "Runtime information.");
 
     /* Add Kokkos and Kokkos Kernels info */
diff --git a/pennylane_lightning/src/simulator/CMakeLists.txt b/pennylane_lightning/src/simulator/CMakeLists.txt
index 50da06f71c..e1ea946e93 100644
--- a/pennylane_lightning/src/simulator/CMakeLists.txt
+++ b/pennylane_lightning/src/simulator/CMakeLists.txt
@@ -1,23 +1,13 @@
 project(lightning_simulator)
 
-set(SIMULATOR_FILES StateVectorRawCPU.cpp StateVectorManagedCPU.cpp Measures.cpp CACHE INTERNAL "" FORCE)
+set(SIMULATOR_FILES StateVectorRawCPU.cpp Observables.cpp StateVectorManagedCPU.cpp Measures.cpp CACHE INTERNAL "" FORCE)
 
 add_library(lightning_simulator STATIC ${SIMULATOR_FILES})
 
 if (UNIX AND (${CMAKE_SYSTEM_PROCESSOR} MATCHES "(AMD64)|(X64)|(x64)|(x86_64)"))
-    add_library(lightning_simulator_assign_kernels_x64 STATIC KernelMap_X64.cpp AssignKernelMap_AVX2.cpp AssignKernelMap_AVX512.cpp AssignKernelMap_Default.cpp)
-    target_link_libraries(lightning_simulator_assign_kernels_x64 PRIVATE lightning_compile_options
-                                                      lightning_external_libs
-                                                      lightning_gates
-                                                      lightning_utils)
-    target_link_libraries(lightning_simulator PRIVATE lightning_simulator_assign_kernels_x64)
+    target_sources(lightning_simulator PRIVATE KernelMap_X64.cpp AssignKernelMap_AVX2.cpp AssignKernelMap_AVX512.cpp AssignKernelMap_Default.cpp)
 else()
-    add_library(lightning_simulator_assign_kernels_default STATIC KernelMap_Default.cpp AssignKernelMap_Default.cpp)
-    target_link_libraries(lightning_simulator_assign_kernels_default PRIVATE lightning_compile_options
-                                                      lightning_external_libs
-                                                      lightning_gates
-                                                      lightning_utils)
-    target_link_libraries(lightning_simulator PRIVATE lightning_simulator_assign_kernels_default)
+    target_sources(lightning_simulator PRIVATE KernelMap_Default.cpp AssignKernelMap_Default.cpp)
 endif()
 
 target_include_directories(lightning_simulator PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/pennylane_lightning/src/simulator/Measures.cpp b/pennylane_lightning/src/simulator/Measures.cpp
index c817639950..513b898f51 100644
--- a/pennylane_lightning/src/simulator/Measures.cpp
+++ b/pennylane_lightning/src/simulator/Measures.cpp
@@ -15,6 +15,7 @@
 #include "Measures.hpp"
 
 // explicit instantiation
-template class Pennylane::Measures<float, Pennylane::StateVectorRawCPU<float>>;
-template class Pennylane::Measures<double,
-                                   Pennylane::StateVectorRawCPU<double>>;
+template class Pennylane::Simulators::Measures<
+    float, Pennylane::StateVectorRawCPU<float>>;
+template class Pennylane::Simulators::Measures<
+    double, Pennylane::StateVectorRawCPU<double>>;
diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp
index e0d2d53f0c..d053e4359a 100644
--- a/pennylane_lightning/src/simulator/Measures.hpp
+++ b/pennylane_lightning/src/simulator/Measures.hpp
@@ -30,10 +30,11 @@
 
 #include "Kokkos_Sparse.hpp"
 #include "LinearAlgebra.hpp"
+#include "Observables.hpp"
 #include "StateVectorManagedCPU.hpp"
 #include "StateVectorRawCPU.hpp"
 
-namespace Pennylane {
+namespace Pennylane::Simulators {
 
 /**
  * @brief Observable's Measurement Class.
@@ -217,6 +218,20 @@ class Measures {
         return expected_value_list;
     }
 
+    /**
+     * @brief Expectation value for a general Observable
+     *
+     * @param ob Observable
+     */
+    auto expval(const Observable<fp_t> &ob) -> fp_t {
+        StateVectorManagedCPU<fp_t> op_sv(original_statevector);
+        ob.applyInPlace(op_sv);
+        const auto inner_prod =
+            Util::innerProdC(original_statevector.getData(), op_sv.getData(),
+                             original_statevector.getLength());
+        return std::real(inner_prod);
+    }
+
     /**
      * @brief Variance of an observable.
      *
@@ -380,4 +395,4 @@ class Measures {
         return samples;
     }
 }; // class Measures
-} // namespace Pennylane
+} // namespace Pennylane::Simulators
diff --git a/pennylane_lightning/src/algorithms/Observables.cpp b/pennylane_lightning/src/simulator/Observables.cpp
similarity index 57%
rename from pennylane_lightning/src/algorithms/Observables.cpp
rename to pennylane_lightning/src/simulator/Observables.cpp
index d784910db0..8b200a2651 100644
--- a/pennylane_lightning/src/algorithms/Observables.cpp
+++ b/pennylane_lightning/src/simulator/Observables.cpp
@@ -14,14 +14,14 @@
 
 #include "Observables.hpp"
 
-template class Pennylane::Algorithms::NamedObs<float>;
-template class Pennylane::Algorithms::NamedObs<double>;
+template class Pennylane::Simulators::NamedObs<float>;
+template class Pennylane::Simulators::NamedObs<double>;
 
-template class Pennylane::Algorithms::HermitianObs<float>;
-template class Pennylane::Algorithms::HermitianObs<double>;
+template class Pennylane::Simulators::HermitianObs<float>;
+template class Pennylane::Simulators::HermitianObs<double>;
 
-template class Pennylane::Algorithms::TensorProdObs<float>;
-template class Pennylane::Algorithms::TensorProdObs<double>;
+template class Pennylane::Simulators::TensorProdObs<float>;
+template class Pennylane::Simulators::TensorProdObs<double>;
 
-template class Pennylane::Algorithms::Hamiltonian<float>;
-template class Pennylane::Algorithms::Hamiltonian<double>;
+template class Pennylane::Simulators::Hamiltonian<float>;
+template class Pennylane::Simulators::Hamiltonian<double>;
diff --git a/pennylane_lightning/src/algorithms/Observables.hpp b/pennylane_lightning/src/simulator/Observables.hpp
similarity index 99%
rename from pennylane_lightning/src/algorithms/Observables.hpp
rename to pennylane_lightning/src/simulator/Observables.hpp
index bf2e765272..f803276e96 100644
--- a/pennylane_lightning/src/algorithms/Observables.hpp
+++ b/pennylane_lightning/src/simulator/Observables.hpp
@@ -21,7 +21,7 @@
 #include <memory>
 #include <unordered_set>
 
-namespace Pennylane::Algorithms {
+namespace Pennylane::Simulators {
 
 /**
  * @brief A base class for all observable classes.
@@ -442,4 +442,4 @@ template <typename T> class Hamiltonian final : public Observable<T> {
     }
 };
 
-} // namespace Pennylane::Algorithms
+} // namespace Pennylane::Simulators
diff --git a/pennylane_lightning/src/tests/Test_AdjDiff.cpp b/pennylane_lightning/src/tests/Test_AdjDiff.cpp
index a131433ab0..78ffdc5045 100644
--- a/pennylane_lightning/src/tests/Test_AdjDiff.cpp
+++ b/pennylane_lightning/src/tests/Test_AdjDiff.cpp
@@ -23,6 +23,7 @@
 
 using namespace Pennylane;
 using namespace Pennylane::Algorithms;
+using namespace Pennylane::Simulators;
 
 TEST_CASE("Algorithms::adjointJacobian Op=RX, Obs=Z", "[Algorithms]") {
     const std::vector<double> param{-M_PI / 7, M_PI / 5, 2 * M_PI / 3};
@@ -540,7 +541,7 @@ TEST_CASE(
     "Algorithms::adjointJacobian with exceedingly complicated Hamiltonian",
     "[Algorithms]") {
     using namespace std::literals;
-    using Pennylane::Algorithms::detail::HamiltonianApplyInPlace;
+    using Pennylane::Simulators::detail::HamiltonianApplyInPlace;
 
     std::vector<double> param{-M_PI / 7, M_PI / 5, 2 * M_PI / 3};
     std::vector<size_t> t_params{0, 2};
diff --git a/pennylane_lightning/src/tests/Test_AlgUtil.cpp b/pennylane_lightning/src/tests/Test_AlgUtil.cpp
index 3698ada7ec..51a1853e6b 100644
--- a/pennylane_lightning/src/tests/Test_AlgUtil.cpp
+++ b/pennylane_lightning/src/tests/Test_AlgUtil.cpp
@@ -5,6 +5,7 @@
 
 using namespace Pennylane;
 using namespace Pennylane::Algorithms;
+using namespace Pennylane::Simulators;
 
 class TestException : public std::exception {};
 
diff --git a/pennylane_lightning/src/tests/Test_Measures.cpp b/pennylane_lightning/src/tests/Test_Measures.cpp
index 311cc714c4..ff6760f7bf 100644
--- a/pennylane_lightning/src/tests/Test_Measures.cpp
+++ b/pennylane_lightning/src/tests/Test_Measures.cpp
@@ -16,6 +16,7 @@
 
 using namespace Pennylane;
 using namespace Pennylane::Util;
+using namespace Pennylane::Simulators;
 
 using std::complex;
 using std::size_t;
diff --git a/pennylane_lightning/src/tests/Test_Measures_Sparse.cpp b/pennylane_lightning/src/tests/Test_Measures_Sparse.cpp
index 32a2aca8b9..0e361ffde3 100644
--- a/pennylane_lightning/src/tests/Test_Measures_Sparse.cpp
+++ b/pennylane_lightning/src/tests/Test_Measures_Sparse.cpp
@@ -17,6 +17,7 @@
 
 using namespace Pennylane;
 using namespace Pennylane::Util;
+using namespace Pennylane::Simulators;
 
 namespace {
 using std::complex;
diff --git a/pennylane_lightning/src/tests/Test_Observables.cpp b/pennylane_lightning/src/tests/Test_Observables.cpp
index fb37dba954..c1b62275a9 100644
--- a/pennylane_lightning/src/tests/Test_Observables.cpp
+++ b/pennylane_lightning/src/tests/Test_Observables.cpp
@@ -4,7 +4,7 @@
 #include <catch2/catch.hpp>
 
 using namespace Pennylane;
-using namespace Pennylane::Algorithms;
+using namespace Pennylane::Simulators;
 using Pennylane::Util::LightningException;
 
 // NOLINTNEXTLINE(readability-function-cognitive-complexity)
diff --git a/pennylane_lightning/src/tests/Test_StateVecAdjDiff.cpp b/pennylane_lightning/src/tests/Test_StateVecAdjDiff.cpp
index 092e0e380b..8b26641cda 100644
--- a/pennylane_lightning/src/tests/Test_StateVecAdjDiff.cpp
+++ b/pennylane_lightning/src/tests/Test_StateVecAdjDiff.cpp
@@ -15,6 +15,7 @@
 using namespace Pennylane;
 using namespace Pennylane::Util;
 using namespace Pennylane::Algorithms;
+using namespace Pennylane::Simulators;
 
 /**
  * @brief
diff --git a/tests/test_measures.py b/tests/test_measures.py
index 8df8864b40..4c83c24b4c 100644
--- a/tests/test_measures.py
+++ b/tests/test_measures.py
@@ -227,6 +227,41 @@ def circuit():
 
         assert np.allclose(circuit(), cases[1], atol=tol, rtol=0)
 
+    @pytest.mark.parametrize(
+        "obs, coeffs, res",
+        [
+            ([qml.PauliX(0) @ qml.PauliZ(1)], [1.0], 0.0),
+            ([qml.PauliZ(0) @ qml.PauliZ(1)], [1.0], math.cos(0.4) * math.cos(-0.2)),
+            (
+                [
+                    qml.PauliX(0) @ qml.PauliZ(1),
+                    qml.Hermitian(
+                        [
+                            [1.0, 0.0, 0.0, 0.0],
+                            [0.0, 3.0, 0.0, 0.0],
+                            [0.0, 0.0, -1.0, 1.0],
+                            [0.0, 0.0, 1.0, -2.0],
+                        ],
+                        wires=[0, 1],
+                    ),
+                ],
+                [0.3, 1.0],
+                0.9319728930156066,
+            ),
+        ],
+    )
+    def test_expval_hamiltonian(self, obs, coeffs, res, tol, dev):
+        """Test expval with Hamiltonian"""
+        ham = qml.Hamiltonian(coeffs, obs)
+
+        @qml.qnode(dev)
+        def circuit():
+            qml.RX(0.4, wires=[0])
+            qml.RY(-0.2, wires=[1])
+            return qml.expval(ham)
+
+        assert np.allclose(circuit(), res, atol=tol, rtol=0)
+
     def test_value(self, dev, tol):
         """Test that the expval interface works"""
 
@@ -428,6 +463,55 @@ def circuit2():
 
         assert np.allclose(circuit1(), circuit2(), atol=tol)
 
+    @pytest.mark.parametrize(
+        "wires1, wires2",
+        [
+            ([2, 3, 0], [2, 3, 0]),
+            ([0, 1], [0, 1]),
+            ([0, 2, 3], [2, 0, 3]),
+            (["a", "c", "d"], [2, 3, 0]),
+            ([-1, -2, -3], ["q1", "ancilla", 2]),
+            (["a", "c"], [3, 0]),
+            ([-1, -2], ["ancilla", 2]),
+        ],
+    )
+    @pytest.mark.parametrize("C", [np.complex64, np.complex128])
+    def test_wires_expval_hermitian(self, wires1, wires2, C, tol):
+        """Test that the expectation of a circuit is independent from the wire labels used."""
+        dev1 = qml.device("lightning.qubit", wires=wires1, c_dtype=C)
+        dev1._state = dev1._asarray(dev1._state, C)
+
+        dev2 = qml.device("lightning.qubit", wires=wires2)
+        dev2._state = dev2._asarray(dev2._state, C)
+        ob_mat = [
+            [1.0, 2.0, 0.0, 1.0],
+            [2.0, -1.0, 0.0, 0.0],
+            [0.0, 0.0, 2.0, 0.0],
+            [1.0, 0.0, 0.0, -1.0],
+        ]
+
+        n_wires = len(wires1)
+        ob1 = qml.Hermitian(ob_mat, wires=[wires1[0 % n_wires], wires1[1 % n_wires]])
+        ob2 = qml.Hermitian(ob_mat, wires=[wires2[0 % n_wires], wires2[1 % n_wires]])
+
+        @qml.qnode(dev1)
+        def circuit1():
+            qml.RX(0.5, wires=wires1[0 % n_wires])
+            qml.RY(2.0, wires=wires1[1 % n_wires])
+            if n_wires > 1:
+                qml.CNOT(wires=[wires1[0], wires1[1]])
+            return [qml.expval(ob1)]
+
+        @qml.qnode(dev2)
+        def circuit2():
+            qml.RX(0.5, wires=wires2[0 % n_wires])
+            qml.RY(2.0, wires=wires2[1 % n_wires])
+            if n_wires > 1:
+                qml.CNOT(wires=[wires2[0], wires2[1]])
+            return [qml.expval(ob2)]
+
+        assert np.allclose(circuit1(), circuit2(), atol=tol)
+
 
 class TestSample:
     """Tests that samples are properly calculated."""