import os
import re
import sys
import platform
import subprocess

from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
from distutils.version import LooseVersion


class CMakeExtension(Extension):
    def __init__(self, name, sourcedir=''):
        Extension.__init__(self, name, sources=[])
        self.sourcedir = os.path.abspath(sourcedir)


class CMakeBuild(build_ext):
    def run(self):
        try:
            out = subprocess.check_output(['cmake', '--version'])
        except OSError:
            raise RuntimeError("CMake must be installed to build the following extensions: " +
                               ", ".join(e.name for e in self.extensions))

        if platform.system() == "Windows":
            cmake_version = LooseVersion(re.search(r'version\s*([\d.]+)', out.decode()).group(1))
            if cmake_version < '3.1.0':
                raise RuntimeError("CMake >= 3.1.0 is required on Windows")

        for ext in self.extensions:
            self.build_extension(ext)

    def build_extension(self, ext):
        extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
        cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir,
                      '-DPYTHON_EXECUTABLE=' + sys.executable]

        cfg = 'Debug' if self.debug else 'Release'
        build_args = ['--config', cfg]

        if platform.system() == "Windows":
            cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir)]
            if sys.maxsize > 2**32:
                cmake_args += ['-A', 'x64']
            build_args += ['--', '/m']
        else:
            cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
            build_args += ['--', '-j2']

        env = os.environ.copy()
        env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(env.get('CXXFLAGS', ''),
                                                              self.distribution.get_version())
        if not os.path.exists(self.build_temp):
            os.makedirs(self.build_temp)
        subprocess.check_call(['cmake', ext.sourcedir] + cmake_args, cwd=self.build_temp, env=env)
        subprocess.check_call(['cmake', '--build', '.'] + build_args, cwd=self.build_temp)

setup(
    name='netket',
    version='0.1',
    author='Giuseppe Carleo et al.',
    description='NetKet',
    url='http://github.com/netket/netket',
    author_email='netket@netket.org',
    license='Apache',
    ext_modules=[CMakeExtension('netket')],
    cmdclass=dict(build_ext=CMakeBuild),
    zip_safe=False,
)

setup.py
import os
import re
import sys
import platform
import subprocess

from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
from distutils.version import LooseVersion


class CMakeExtension(Extension):
    def __init__(self, name, sourcedir=''):
        Extension.__init__(self, name, sources=[])
        self.sourcedir = os.path.abspath(sourcedir)


class CMakeBuild(build_ext):
    def run(self):
        try:
            out = subprocess.check_output(['cmake', '--version'])
        except OSError:
            raise RuntimeError("CMake must be installed to build the following extensions: " +
                               ", ".join(e.name for e in self.extensions))

        if platform.system() == "Windows":
            cmake_version = LooseVersion(re.search(r'version\s*([\d.]+)', out.decode()).group(1))
            if cmake_version < '3.1.0':
                raise RuntimeError("CMake >= 3.1.0 is required on Windows")

        for ext in self.extensions:
            self.build_extension(ext)

    def build_extension(self, ext):
        extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
        cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir,
                      '-DPYTHON_EXECUTABLE=' + sys.executable]

        cfg = 'Debug' if self.debug else 'Release'
        build_args = ['--config', cfg]

        if platform.system() == "Windows":
            cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir)]
            if sys.maxsize > 2**32:
                cmake_args += ['-A', 'x64']
            build_args += ['--', '/m']
        else:
            cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
            build_args += ['--', '-j2']

        env = os.environ.copy()
        env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(env.get('CXXFLAGS', ''),
                                                              self.distribution.get_version())
        if not os.path.exists(self.build_temp):
            os.makedirs(self.build_temp)
        subprocess.check_call(['cmake', ext.sourcedir] + cmake_args, cwd=self.build_temp, env=env)
        subprocess.check_call(['cmake', '--build', '.'] + build_args, cwd=self.build_temp)

setup(
    name='netket',
    version='2.0',
    author='Giuseppe Carleo et al.',
    description='NetKet',
    url='http://github.com/netket/netket',
    author_email='netket@netket.org',
    license='Apache',
    ext_modules=[CMakeExtension('netket')],
    cmdclass=dict(build_ext=CMakeBuild),
    zip_safe=False,
)

setup.py
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3926b65d38..1568f22ec2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,9 +3,13 @@ cmake_minimum_required(VERSION 3.1)
 set(CMAKE_DISABLE_SOURCE_CHANGES ON)
 set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
 option(ENABLE_TESTS "Enable unit tests." OFF)
+option(NETKET_Sanitizer "Build test suite with Clang sanitizer" OFF)
 
 project(NetKet)
 
+add_library(netket_test INTERFACE)
+target_link_libraries(netket_test INTERFACE netket_lib Catch2)
+
 set(NETKET_PYTHON_VERSION "" CACHE STRING "Python version to use for compiling modules")
 
 if(ENABLE_TESTS)
@@ -202,6 +206,21 @@ set_target_properties(netket  PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}"
                                          SUFFIX "${PYTHON_MODULE_EXTENSION}")
 add_dependencies(netket eigen_project pybind11_project)
 
+if(NETKET_Sanitizer)
+    message(STATUS "Building python library with Clang sanitizer")
+    if(NOT MSVC)
+        target_compile_options(netket
+            INTERFACE
+                -O2 -g -fno-omit-frame-pointer
+                -fsanitize=address -fsanitize=undefined
+        )
+        target_link_libraries(netket
+            INTERFACE
+                -fsanitize=address -fsanitize=undefined
+        )
+    endif()
+endif()
+
 #
 # Testing
 #
diff --git a/NetKet/Hilbert/bosons.hpp b/NetKet/Hilbert/bosons.hpp
index 48ff60bc53..70e6044122 100644
--- a/NetKet/Hilbert/bosons.hpp
+++ b/NetKet/Hilbert/bosons.hpp
@@ -131,10 +131,10 @@ class Boson : public AbstractHilbert {
     }
   }
 
-  bool CheckConstraint(const Eigen::VectorXd &v) const {
+  bool CheckConstraint(Eigen::Ref<const Eigen::VectorXd> v) const {
     int tot = 0;
     for (int i = 0; i < v.size(); i++) {
-      tot += int(v(i));
+      tot += std::round(v(i));
     }
 
     return tot == nbosons_;
@@ -150,6 +150,7 @@ class Boson : public AbstractHilbert {
       v(sf) = newconf[i];
       i++;
       assert(v(sf) <= nmax_);
+      assert(v(sf) >= 0);
     }
 
     if (constraintN_) {
diff --git a/NetKet/Machine/jastrow.hpp b/NetKet/Machine/jastrow.hpp
index 31f1cc8db7..f6fd66e380 100644
--- a/NetKet/Machine/jastrow.hpp
+++ b/NetKet/Machine/jastrow.hpp
@@ -62,7 +62,13 @@ class Jastrow : public AbstractMachine<T> {
   }
 
   void Init() {
+    if (nv_ < 2) {
+      throw InvalidInputError(
+          "Cannot construct Jastrow states with less than two visible units");
+    }
+
     W_.resize(nv_, nv_);
+    W_.setZero();
 
     npar_ = (nv_ * (nv_ - 1)) / 2;
 
@@ -104,10 +110,10 @@ class Jastrow : public AbstractMachine<T> {
     int k = 0;
 
     for (int i = 0; i < nv_; i++) {
+      W_(i, i) = T(0.);
       for (int j = i + 1; j < nv_; j++) {
         W_(i, j) = pars(k);
         W_(j, i) = W_(i, j);  // create the lower triangle
-        W_(i, i) = T(0);
         k++;
       }
     }
diff --git a/NetKet/Machine/jastrow_symm.hpp b/NetKet/Machine/jastrow_symm.hpp
index 7e07f6a2c3..11baa33d84 100644
--- a/NetKet/Machine/jastrow_symm.hpp
+++ b/NetKet/Machine/jastrow_symm.hpp
@@ -75,6 +75,11 @@ class JastrowSymm : public AbstractMachine<T> {
   }
 
   void Init(std::shared_ptr<const AbstractGraph> graph) {
+    if (nv_ < 2) {
+      throw InvalidInputError(
+          "Cannot construct Jastrow states with less than two visible units");
+    }
+
     permtable_ = graph->SymmetryTable();
     permsize_ = permtable_.size();
 
@@ -83,6 +88,7 @@ class JastrowSymm : public AbstractMachine<T> {
     }
 
     W_.resize(nv_, nv_);
+    W_.setZero();
     thetas_.resize(nv_);
     thetasnew_.resize(nv_);
 
diff --git a/Test/Machine/test_machine.py b/Test/Machine/test_machine.py
index 1c844d2aa9..20d4ca2a10 100644
--- a/Test/Machine/test_machine.py
+++ b/Test/Machine/test_machine.py
@@ -99,7 +99,6 @@ def test_log_derivative():
         print("Machine test: %s" % name)
 
         npar = machine.n_par()
-        randpars = 0.1 * (np.random.randn(npar) + 1.0j * np.random.randn(npar))
 
         # random visibile state
         hi = machine.get_hilbert()
@@ -109,15 +108,18 @@ def test_log_derivative():
 
         for i in range(100):
             hi.random_vals(v, rg)
-            grad = (nd.Gradient(log_val_f, step=1.0e-8))
 
+            randpars = 0.1 * (np.random.randn(npar) +
+                              1.0j * np.random.randn(npar))
             machine.set_parameters(randpars)
             der_log = machine.der_log(v)
 
             if("Jastrow" in name):
                 assert(np.max(np.imag(der_log)) == approx(0.))
 
+            grad = (nd.Gradient(log_val_f, step=1.0e-8))
             num_der_log = grad(randpars, machine, v)
+
             assert(np.max(np.real(der_log - num_der_log))
                    == approx(0., rel=1e-4, abs=1e-4))
             # The imaginary part is a bit more tricky, there might be an arbitrary phase shift
diff --git a/Test/Operator/test_operator.py b/Test/Operator/test_operator.py
index a243f5da92..f88477255f 100644
--- a/Test/Operator/test_operator.py
+++ b/Test/Operator/test_operator.py
@@ -6,19 +6,19 @@
 operators = {}
 
 # Ising 1D
-g_1 = nk.graph.Hypercube(length=20, ndim=1, pbc=True)
-hi = nk.hilbert.Spin(s=0.5, graph=g_1)
-operators["Ising 1D"] = [nk.operator.Ising(h=1.321, hilbert=hi), hi]
+g = nk.graph.Hypercube(length=20, ndim=1, pbc=True)
+hi = nk.hilbert.Spin(s=0.5, graph=g)
+operators["Ising 1D"] = nk.operator.Ising(h=1.321, hilbert=hi)
 
 # Heisenberg 1D
-g_2 = nk.graph.Hypercube(length=20, ndim=1, pbc=True)
-hi = nk.hilbert.Spin(s=0.5, total_sz=0, graph=g_1)
-operators["Heisenberg 1D"] = [nk.operator.Heisenberg(hilbert=hi), hi]
+g = nk.graph.Hypercube(length=20, ndim=1, pbc=True)
+hi = nk.hilbert.Spin(s=0.5, total_sz=0, graph=g)
+operators["Heisenberg 1D"] = nk.operator.Heisenberg(hilbert=hi)
 
 # Bose Hubbard
-g_3 = nk.graph.Hypercube(length=10, ndim=2, pbc=True)
-hi = nk.hilbert.Boson(n_max=3, n_bosons=23, graph=g_3)
-operators["Bose Hubbard"] = [nk.operator.BoseHubbard(U=4.0, hilbert=hi), hi]
+g = nk.graph.Hypercube(length=3, ndim=2, pbc=True)
+hi = nk.hilbert.Boson(n_max=3, n_bosons=6, graph=g)
+operators["Bose Hubbard"] = nk.operator.BoseHubbard(U=4.0, hilbert=hi)
 
 # Graph Hamiltonian
 # TODO (jamesETsmith)
@@ -30,23 +30,26 @@
 #sy = np.array([[0,1j],[-1j,0]])
 #
 # operators["Custom"] =
+rg = nk.utils.RandomEngine(seed=1234)
 
 
 def test_produce_elements_in_hilbert():
     for name, ha in operators.items():
-        hi = ha[1]
+        hi = ha.get_hilbert()
         print(name, hi)
         assert (len(hi.local_states()) == hi.local_size())
 
         rstate = np.zeros(hi.size())
-        rg = nk.utils.RandomEngine(seed=1234)
+
         local_states = hi.local_states()
 
         for i in range(1000):
             hi.random_vals(rstate, rg)
-            conns = ha[0].get_conn(rstate)
+            conns = ha.get_conn(rstate)
 
             for connector, newconf in zip(conns[1], conns[2]):
-                hi.update_conf(rstate, connector, newconf)
-                for rs in rstate:
+                rstatet = np.array(rstate)
+                hi.update_conf(rstatet, connector, newconf)
+
+                for rs in rstatet:
                     assert(rs in local_states)
diff --git a/setup.py b/setup.py
index c036e75fd2..094a2d65fc 100644
--- a/setup.py
+++ b/setup.py
@@ -58,7 +58,7 @@ def build_extension(self, ext):
 
 setup(
     name='netket',
-    version='0.1',
+    version='2.0',
     author='Giuseppe Carleo et al.',
     description='NetKet',
     url='http://github.com/netket/netket',

Python bindings for Jastrow machines randomly failing
I realized in #91 that once in a while the python tests for the `Jastrow` machines fail. This issue seems related to some memory problem, but I still don't understand if it is on the c++ side or python 
