diff --git a/exercises/ex04_skeleton/build_alps.txt b/exercises/ex04_skeleton/build_alps.txt
new file mode 100644
index 0000000000000000000000000000000000000000..335b35da23515a052fd0de39c7e8f54c28ad3ab8
--- /dev/null
+++ b/exercises/ex04_skeleton/build_alps.txt
@@ -0,0 +1,21 @@
+# INSTRUCTIONS
+# ============
+#
+# 0. Make sure that lapack and blas are available
+#    (e.g. apt-get install liblapack-dev libblas-dev)
+# 1. Download http://alps.comp-phys.org/static/software/releases/alps-2.2.b1-r7195-src-with-boost.tar.gz
+#    (cf. http://alps.comp-phys.org/mediawiki/index.php/Download_and_install_ALPS_2)
+# 2. Unzip it (you do NOT need to build or install anything!)
+# 3. Set the following environment variable to the path of the unzipped directory:
+
+export ALPSDIR=.../alps-2.2.b1-r7195-src-with-boost
+
+# Now you can compile the skeleton by using:
+
+c++ -I${ALPSDIR}/boost -I${ALPSDIR}/alps/src -o skeleton skeleton.cpp -llapack -lblas
+
+# It will fail linking, because you have not yet implemented the Hamiltonian :-)
+#
+# Happy coding!
+#
+# If you run into problems that you can't solve, please contact your teaching assistant!
diff --git a/exercises/ex04_skeleton/skeleton.cpp b/exercises/ex04_skeleton/skeleton.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..324e86c4eab974ca3e2a868a5b21fa1562effeb7
--- /dev/null
+++ b/exercises/ex04_skeleton/skeleton.cpp
@@ -0,0 +1,59 @@
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <cassert>
+#include <boost/numeric/ublas/vector.hpp>
+#include <boost/random.hpp>
+#include <boost/tuple/tuple.hpp>
+
+class Hamiltonian
+{
+public:
+  typedef double Scalar;
+  typedef boost::numeric::ublas::vector<Scalar> Vector;
+
+  // Dimension of Vector Space
+  unsigned dimension() const;
+
+  // Calculate y = H x
+  void multiply(const Vector& x, Vector& y) const;
+
+  // ...
+};
+
+namespace ietl
+{
+	/* here we include a "mult" function in the ietl name space specifically designed for use with our Hamiltonian class objects.  */
+  inline void mult( const Hamiltonian& h, const Hamiltonian::Vector& x, Hamiltonian::Vector& y )
+  {
+    h.multiply( x, y );
+	/*To minimize your memory requirements you could implement this method "on the fly", i.e. in a way that never constructs the hamitonian matrix explicitly. */
+  }
+}
+
+// ietl::mult() needs to be declared before including these
+#include <ietl/interface/ublas.h>
+#include <ietl/lanczos.h>
+
+std::pair< std::vector<double>, std::vector<int> >
+diagonalize( const Hamiltonian& h, unsigned nvals=1, unsigned maxiter=1000)
+{
+  typedef ietl::vectorspace<Hamiltonian::Vector> Vectorspace;
+  typedef ietl::lanczos<Hamiltonian,Vectorspace> Lanczos;
+  typedef ietl::lanczos_iteration_nlowest<double> Iteration;
+  typedef boost::mt19937 Generator; 
+
+  Vectorspace vspace(h.dimension());
+  Lanczos solver(h,vspace);
+  Iteration iter(maxiter,nvals); /* maxiter limits the number of Lanczos iterations and nvals tells the solver the number of eigenvalues to calculate.*/
+  solver.calculate_eigenvalues(iter,Generator()); /* Generator() creates a pseudo-random number generator (Mersenne-Twister) used for starting the Lanczos algorithm. */
+
+  if( iter.iterations() == maxiter )
+    std::cerr << "Lanczos did not converge in " << iter.iterations() << " iterations." << std::endl;
+  else
+    std::cout << "  Lanczos converged after " << iter.iterations() << " iterations." << std::endl;
+
+  return std::make_pair(solver.eigenvalues(),solver.multiplicities());
+}
+
diff --git a/exercises/ex04_skeleton/skeleton.py b/exercises/ex04_skeleton/skeleton.py
new file mode 100644
index 0000000000000000000000000000000000000000..c477c33edd92f30ec7e2c204c440304d324b9991
--- /dev/null
+++ b/exercises/ex04_skeleton/skeleton.py
@@ -0,0 +1,21 @@
+import math as m, numpy as np
+
+from scipy.sparse.linalg as la
+# Documentation at http://docs.scipy.org/doc/scipy/reference/sparse.linalg.html
+
+d = # size of local basis
+L = # length of the chain
+
+
+def heisenberg(v):
+"""
+Given an input vector v, this function returns H*v.
+"""
+    pass
+
+def sparse_diag():
+	D = d**L
+	H = la.LinearOperator( (D,D), matvec=heisenberg, dtype='D')
+	(w,v) = la.eigsh(H, 10, which='SA')
+	return w
+
diff --git a/exercises/exercise4.pdf b/exercises/exercise4.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..9a3757a71b885eeac1d7cfd00043a6612eeda9c8
Binary files /dev/null and b/exercises/exercise4.pdf differ