From c3619d27a6e64d2f13fc16d8959ad7ea70486eb8 Mon Sep 17 00:00:00 2001
From: Victor Chahuneau <vchahune@cs.cmu.edu>
Date: Thu, 14 Jun 2012 09:27:53 -0400
Subject: Detect boost location before building the python module

---
 python/setup.py      |   13 +-
 python/src/_cdec.cpp | 3128 ++++++++++++++++++++++++--------------------------
 python/src/_cdec.pyx |   30 +-
 3 files changed, 1543 insertions(+), 1628 deletions(-)

(limited to 'python')

diff --git a/python/setup.py b/python/setup.py
index 756de088..49a1ec8f 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -1,13 +1,22 @@
 from distutils.core import setup
 from distutils.extension import Extension
 from Cython.Distutils import build_ext
+import os
+
+INC = ['..', 'src/', '../decoder', '../utils']
+LIB = ['../decoder', '../utils', '../mteval', '../klm/lm', '../klm/util']
+
+BOOST_ROOT = os.getenv('BOOST_ROOT')
+if BOOST_ROOT:
+    INC.append(os.path.join(BOOST_ROOT, 'include/'))
+    LIB.append(os.path.join(BOOST_ROOT, 'lib/'))
 
 ext_modules = [
     Extension(name='_cdec',
         sources=['src/_cdec.pyx'],
         language='C++', 
-        include_dirs=['..', 'src/', '../decoder', '../utils'],
-        library_dirs=['../decoder', '../utils', '../mteval', '../klm/lm', '../klm/util'],
+        include_dirs=INC,
+        library_dirs=LIB,
         libraries=['boost_program_options-mt', 'z',
                    'cdec', 'utils', 'mteval', 'klm', 'klm_util'])
 ]
diff --git a/python/src/_cdec.cpp b/python/src/_cdec.cpp
index e1b0f20e..55470c89 100644
--- a/python/src/_cdec.cpp
+++ b/python/src/_cdec.cpp
@@ -1,11 +1,12 @@
-/* Generated by Cython 0.15.1 on Wed Jun  6 01:04:37 2012 */
+/* Generated by Cython 0.16 on Thu Jun 14 09:24:35 2012 */
 
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
 #ifndef Py_PYTHON_H
     #error Python headers needed to compile C extensions, please install development version of Python.
+#elif PY_VERSION_HEX < 0x02040000
+    #error Cython requires Python 2.4+.
 #else
-
 #include <stddef.h> /* For offsetof */
 #ifndef offsetof
 #define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
@@ -34,10 +35,22 @@
   #define PY_LONG_LONG LONG_LONG
 #endif
 
-#if PY_VERSION_HEX < 0x02040000
-  #define METH_COEXIST 0
-  #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type)
-  #define PyDict_Contains(d,o)   PySequence_Contains(d,o)
+#ifndef Py_HUGE_VAL
+  #define Py_HUGE_VAL HUGE_VAL
+#endif
+
+#ifdef PYPY_VERSION
+#define CYTHON_COMPILING_IN_PYPY 1
+#define CYTHON_COMPILING_IN_CPYTHON 0
+#else
+#define CYTHON_COMPILING_IN_PYPY 0
+#define CYTHON_COMPILING_IN_CPYTHON 1
+#endif
+
+#if CYTHON_COMPILING_IN_PYPY
+  #define __Pyx_PyCFunction_Call PyObject_Call
+#else
+  #define __Pyx_PyCFunction_Call PyCFunction_Call
 #endif
 
 #if PY_VERSION_HEX < 0x02050000
@@ -50,6 +63,9 @@
   #define PyNumber_Index(o)    PyNumber_Int(o)
   #define PyIndex_Check(o)     PyNumber_Check(o)
   #define PyErr_WarnEx(category, message, stacklevel) PyErr_Warn(category, message)
+  #define __PYX_BUILD_PY_SSIZE_T "i"
+#else
+  #define __PYX_BUILD_PY_SSIZE_T "n"
 #endif
 
 #if PY_VERSION_HEX < 0x02060000
@@ -83,13 +99,25 @@
   #define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES)
   #define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES)
   #define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES)
+  #define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_FORMAT | PyBUF_WRITABLE)
+  #define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_FORMAT | PyBUF_WRITABLE)
 
+  typedef int (*getbufferproc)(PyObject *, Py_buffer *, int);
+  typedef void (*releasebufferproc)(PyObject *, Py_buffer *);
 #endif
 
 #if PY_MAJOR_VERSION < 3
   #define __Pyx_BUILTIN_MODULE_NAME "__builtin__"
+  #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
+          PyCode_New(a, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
 #else
   #define __Pyx_BUILTIN_MODULE_NAME "builtins"
+  #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
+          PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
+#endif
+
+#if PY_MAJOR_VERSION < 3 && PY_MINOR_VERSION < 6
+  #define PyUnicode_FromString(s) PyUnicode_Decode(s, strlen(s), "UTF-8", "strict")
 #endif
 
 #if PY_MAJOR_VERSION >= 3
@@ -101,6 +129,17 @@
   #define Py_TPFLAGS_HAVE_NEWBUFFER 0
 #endif
 
+
+#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_GET_LENGTH)
+  #define CYTHON_PEP393_ENABLED 1
+  #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u)
+  #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i)
+#else
+  #define CYTHON_PEP393_ENABLED 0
+  #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u)
+  #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i]))
+#endif
+
 #if PY_MAJOR_VERSION >= 3
   #define PyBaseString_Type            PyUnicode_Type
   #define PyStringObject               PyUnicodeObject
@@ -168,15 +207,6 @@
   #define __Pyx_PyInt_AsHash_t   PyInt_AsSsize_t
 #endif
 
-
-#if PY_MAJOR_VERSION >= 3
-  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
-  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
-#else
-  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_Divide(x,y)
-  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceDivide(x,y)
-#endif
-
 #if (PY_MAJOR_VERSION < 3) || (PY_VERSION_HEX >= 0x03010300)
   #define __Pyx_PySequence_GetSlice(obj, a, b) PySequence_GetSlice(obj, a, b)
   #define __Pyx_PySequence_SetSlice(obj, a, b, value) PySequence_SetSlice(obj, a, b, value)
@@ -218,6 +248,14 @@
   #define __Pyx_DOCSTR(n)  (n)
 #endif
 
+#if PY_MAJOR_VERSION >= 3
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
+#else
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_Divide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceDivide(x,y)
+#endif
+
 #ifndef __PYX_EXTERN_C
   #ifdef __cplusplus
     #define __PYX_EXTERN_C extern "C"
@@ -285,7 +323,7 @@
 #   else
 #     define CYTHON_UNUSED
 #   endif
-# elif defined(__ICC) || defined(__INTEL_COMPILER)
+# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER))
 #   define CYTHON_UNUSED __attribute__ ((__unused__))
 # else
 #   define CYTHON_UNUSED
@@ -310,7 +348,7 @@ static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
 static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*);
 
 #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
-
+#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x))
 
 #ifdef __GNUC__
   /* Test for GCC > 2.95 */
@@ -340,15 +378,7 @@ static const char *__pyx_f[] = {
   "_cdec.pyx",
 };
 
-static PyObject *__Pyx_Generator_Next(PyObject *self);
-static PyObject *__Pyx_Generator_Send(PyObject *self, PyObject *value);
-static PyObject *__Pyx_Generator_Close(PyObject *self);
-static PyObject *__Pyx_Generator_Throw(PyObject *gen, PyObject *args, CYTHON_UNUSED PyObject *kwds);
-
-typedef PyObject *(*__pyx_generator_body_t)(PyObject *, PyObject *);
-
 /*--- Type declarations ---*/
-struct __pyx_Generator_object;
 struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree;
 struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample;
 struct __pyx_obj_5_cdec_Weights;
@@ -358,25 +388,7 @@ struct __pyx_obj_5_cdec_Lattice;
 struct __pyx_obj_5_cdec___pyx_scope_struct____iter__;
 struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest;
 
-/* "_cdec.pyx":33
- *         self.weights[0][fid] = value
- * 
- *     def __iter__(self):             # <<<<<<<<<<<<<<
- *         cdef unsigned fid
- *         for fid in range(1, self.weights.size()):
- */
-struct __pyx_Generator_object {
-  PyObject_HEAD
-  __pyx_generator_body_t body;
-  int is_running;
-  int resume_label;
-  PyObject *exc_type;
-  PyObject *exc_value;
-  PyObject *exc_traceback;
-};
-
-
-/* "_cdec.pyx":120
+/* "_cdec.pyx":105
  *         del derivations
  * 
  *     def kbest_tree(self, size):             # <<<<<<<<<<<<<<
@@ -384,11 +396,11 @@ struct __pyx_Generator_object {
  *         cdef kb.KBestDerivations[vector[WordID], kb.ETreeTraversal]* derivations = new kb.KBestDerivations[vector[WordID], kb.ETreeTraversal](self.hg[0], size)
  */
 struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree {
-  struct __pyx_Generator_object __pyx_base;
+  PyObject_HEAD
   KBest::KBestDerivations<std::vector<WordID>,ETreeTraversal>::Derivation *__pyx_v_derivation;
   KBest::KBestDerivations<std::vector<WordID>,ETreeTraversal> *__pyx_v_derivations;
   unsigned int __pyx_v_k;
-  PyObject *__pyx_v_self;
+  struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self;
   PyObject *__pyx_v_sentence;
   PyObject *__pyx_v_size;
   unsigned int __pyx_t_0;
@@ -396,7 +408,7 @@ struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree {
 };
 
 
-/* "_cdec.pyx":137
+/* "_cdec.pyx":122
  *         hypergraph.Intersect(lat.lattice[0], self.hg)
  * 
  *     def sample(self, unsigned n):             # <<<<<<<<<<<<<<
@@ -404,11 +416,11 @@ struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree {
  *         cdef vector[hypergraph.Hypothesis]* hypos = new vector[hypergraph.Hypothesis]()
  */
 struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample {
-  struct __pyx_Generator_object __pyx_base;
+  PyObject_HEAD
   std::vector<HypergraphSampler::Hypothesis> *__pyx_v_hypos;
   unsigned int __pyx_v_k;
   unsigned int __pyx_v_n;
-  PyObject *__pyx_v_self;
+  struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self;
   PyObject *__pyx_v_sentence;
   size_t __pyx_t_0;
   unsigned int __pyx_t_1;
@@ -442,7 +454,7 @@ struct __pyx_obj_5_cdec_Decoder {
 };
 
 
-/* "_cdec.pyx":86
+/* "_cdec.pyx":71
  *         return hg
  * 
  * cdef class Hypergraph:             # <<<<<<<<<<<<<<
@@ -456,7 +468,7 @@ struct __pyx_obj_5_cdec_Hypergraph {
 };
 
 
-/* "_cdec.pyx":154
+/* "_cdec.pyx":139
  *     # TODO: inside-outside pruning
  * 
  * cdef class Lattice:             # <<<<<<<<<<<<<<
@@ -477,15 +489,15 @@ struct __pyx_obj_5_cdec_Lattice {
  *         for fid in range(1, self.weights.size()):
  */
 struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ {
-  struct __pyx_Generator_object __pyx_base;
+  PyObject_HEAD
   unsigned int __pyx_v_fid;
-  PyObject *__pyx_v_self;
+  struct __pyx_obj_5_cdec_Weights *__pyx_v_self;
   size_t __pyx_t_0;
   unsigned int __pyx_t_1;
 };
 
 
-/* "_cdec.pyx":107
+/* "_cdec.pyx":92
  *         return tree.decode('utf8')
  * 
  *     def kbest(self, size):             # <<<<<<<<<<<<<<
@@ -493,22 +505,20 @@ struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ {
  *         cdef kb.KBestDerivations[vector[WordID], kb.ESentenceTraversal]* derivations = new kb.KBestDerivations[vector[WordID], kb.ESentenceTraversal](self.hg[0], size)
  */
 struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest {
-  struct __pyx_Generator_object __pyx_base;
+  PyObject_HEAD
   KBest::KBestDerivations<std::vector<WordID>,ESentenceTraversal>::Derivation *__pyx_v_derivation;
   KBest::KBestDerivations<std::vector<WordID>,ESentenceTraversal> *__pyx_v_derivations;
   unsigned int __pyx_v_k;
-  PyObject *__pyx_v_self;
+  struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self;
   PyObject *__pyx_v_size;
   PyObject *__pyx_v_tree;
   unsigned int __pyx_t_0;
   long __pyx_t_1;
 };
 
-
 #ifndef CYTHON_REFNANNY
   #define CYTHON_REFNANNY 0
 #endif
-
 #if CYTHON_REFNANNY
   typedef struct {
     void (*INCREF)(void*, PyObject*, int);
@@ -521,8 +531,21 @@ struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest {
   static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL;
   static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); /*proto*/
   #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL;
-  #define __Pyx_RefNannySetupContext(name)           __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
-  #define __Pyx_RefNannyFinishContext()           __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
+#ifdef WITH_THREAD
+  #define __Pyx_RefNannySetupContext(name, acquire_gil) \
+          if (acquire_gil) { \
+              PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \
+              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
+              PyGILState_Release(__pyx_gilstate_save); \
+          } else { \
+              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
+          }
+#else
+  #define __Pyx_RefNannySetupContext(name, acquire_gil) \
+          __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
+#endif
+  #define __Pyx_RefNannyFinishContext() \
+          __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
   #define __Pyx_INCREF(r)  __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
   #define __Pyx_DECREF(r)  __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
   #define __Pyx_GOTREF(r)  __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
@@ -533,7 +556,7 @@ struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest {
   #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0)
 #else
   #define __Pyx_RefNannyDeclarations
-  #define __Pyx_RefNannySetupContext(name)
+  #define __Pyx_RefNannySetupContext(name, acquire_gil)
   #define __Pyx_RefNannyFinishContext()
   #define __Pyx_INCREF(r) Py_INCREF(r)
   #define __Pyx_DECREF(r) Py_DECREF(r)
@@ -544,13 +567,16 @@ struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest {
   #define __Pyx_XGOTREF(r)
   #define __Pyx_XGIVEREF(r)
 #endif /* CYTHON_REFNANNY */
+#define __Pyx_CLEAR(r)    do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0)
+#define __Pyx_XCLEAR(r)   do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0)
 
 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
 
-static void __Pyx_RaiseDoubleKeywordsError(
-    const char* func_name, PyObject* kw_name); /*proto*/
+static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); /*proto*/
 
-static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],     PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,     const char* function_name); /*proto*/
+static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
+    PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
+    const char* function_name); /*proto*/
 
 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
     Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
@@ -569,13 +595,12 @@ static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected);
 
 static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected); /*proto*/
 
-static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
-
 static double __Pyx__PyObject_AsDouble(PyObject* obj); /* proto */
-
 #define __Pyx_PyObject_AsDouble(obj) \
-    ((likely(PyFloat_CheckExact(obj))) ? \
-     PyFloat_AS_DOUBLE(obj) : __Pyx__PyObject_AsDouble(obj))
+((likely(PyFloat_CheckExact(obj))) ? \
+ PyFloat_AS_DOUBLE(obj) : __Pyx__PyObject_AsDouble(obj))
+
+static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
 
 static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
 
@@ -587,8 +612,7 @@ static PyObject *__Pyx_FindPy2Metaclass(PyObject *bases); /*proto*/
 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name,
                                    PyObject *modname); /*proto*/
 
-#include "descrobject.h"
-static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/
+static PyObject* __Pyx_Globals(void); /*proto*/
 
 static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject *);
 
@@ -624,13 +648,47 @@ static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject *
 
 static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
 
+#define __Pyx_Generator_USED
+#include <structmember.h>
+typedef PyObject *(*__pyx_generator_body_t)(PyObject *, PyObject *);
+typedef struct {
+    PyObject_HEAD
+    __pyx_generator_body_t body;
+    PyObject *closure;
+    int is_running;
+    int resume_label;
+    PyObject *exc_type;
+    PyObject *exc_value;
+    PyObject *exc_traceback;
+    PyObject *gi_weakreflist;
+    PyObject *classobj;
+} __pyx_GeneratorObject;
+static __pyx_GeneratorObject *__Pyx_Generator_New(__pyx_generator_body_t body,
+                                                  PyObject *closure);
+static int __pyx_Generator_init(void);
+
 static int __Pyx_check_binary_version(void);
 
-static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno,
-                               int __pyx_lineno, const char *__pyx_filename); /*proto*/
+typedef struct {
+    int code_line;
+    PyCodeObject* code_object;
+} __Pyx_CodeObjectCacheEntry;
+struct __Pyx_CodeObjectCache {
+    int count;
+    int max_count;
+    __Pyx_CodeObjectCacheEntry* entries;
+};
+static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL};
+static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line);
+static PyCodeObject *__pyx_find_code_object(int code_line);
+static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object);
+
+static void __Pyx_AddTraceback(const char *funcname, int c_line,
+                               int py_line, const char *filename); /*proto*/
 
 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
 
+
 /* Module declarations from 'libcpp.string' */
 
 /* Module declarations from 'libcpp.vector' */
@@ -650,7 +708,6 @@ static PyTypeObject *__pyx_ptype_5_cdec_Weights = 0;
 static PyTypeObject *__pyx_ptype_5_cdec_Decoder = 0;
 static PyTypeObject *__pyx_ptype_5_cdec_Hypergraph = 0;
 static PyTypeObject *__pyx_ptype_5_cdec_Lattice = 0;
-static PyTypeObject *__pyx_ptype_5_cdec___pyx_Generator = 0;
 static PyTypeObject *__pyx_ptype_5_cdec___pyx_scope_struct____iter__ = 0;
 static PyTypeObject *__pyx_ptype_5_cdec___pyx_scope_struct_1_kbest = 0;
 static PyTypeObject *__pyx_ptype_5_cdec___pyx_scope_struct_2_kbest_tree = 0;
@@ -664,10 +721,31 @@ static PyObject *__pyx_builtin_KeyError;
 static PyObject *__pyx_builtin_range;
 static PyObject *__pyx_builtin_open;
 static PyObject *__pyx_builtin_eval;
-static char __pyx_k_1[] = "#";
-static char __pyx_k_3[] = "=";
+static int __pyx_pf_5_cdec_7Weights___cinit__(struct __pyx_obj_5_cdec_Weights *__pyx_v_self, struct __pyx_obj_5_cdec_Decoder *__pyx_v_decoder); /* proto */
+static PyObject *__pyx_pf_5_cdec_7Weights_2__getitem__(struct __pyx_obj_5_cdec_Weights *__pyx_v_self, char *__pyx_v_fname); /* proto */
+static int __pyx_pf_5_cdec_7Weights_4__setitem__(struct __pyx_obj_5_cdec_Weights *__pyx_v_self, char *__pyx_v_fname, float __pyx_v_value); /* proto */
+static PyObject *__pyx_pf_5_cdec_7Weights_6__iter__(struct __pyx_obj_5_cdec_Weights *__pyx_v_self); /* proto */
+static int __pyx_pf_5_cdec_7Decoder___cinit__(struct __pyx_obj_5_cdec_Decoder *__pyx_v_self, char *__pyx_v_config); /* proto */
+static void __pyx_pf_5_cdec_7Decoder_2__dealloc__(CYTHON_UNUSED struct __pyx_obj_5_cdec_Decoder *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_5_cdec_7Decoder_4read_weights(struct __pyx_obj_5_cdec_Decoder *__pyx_v_self, PyObject *__pyx_v_cfg); /* proto */
+static PyObject *__pyx_pf_5_cdec_7Decoder_6translate(struct __pyx_obj_5_cdec_Decoder *__pyx_v_self, PyObject *__pyx_v_sentence, PyObject *__pyx_v_grammar); /* proto */
+static PyObject *__pyx_pf_5_cdec_7Decoder_7weights___get__(struct __pyx_obj_5_cdec_Decoder *__pyx_v_self); /* proto */
+static int __pyx_pf_5_cdec_7Decoder_7weights_2__set__(struct __pyx_obj_5_cdec_Decoder *__pyx_v_self, PyObject *__pyx_v_value); /* proto */
+static int __pyx_pf_5_cdec_7Decoder_7weights_4__del__(struct __pyx_obj_5_cdec_Decoder *__pyx_v_self); /* proto */
+static void __pyx_pf_5_cdec_10Hypergraph___dealloc__(struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_5_cdec_10Hypergraph_2viterbi(struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_5_cdec_10Hypergraph_4viterbi_tree(struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_5_cdec_10Hypergraph_6kbest(struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self, PyObject *__pyx_v_size); /* proto */
+static PyObject *__pyx_pf_5_cdec_10Hypergraph_9kbest_tree(struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self, PyObject *__pyx_v_size); /* proto */
+static PyObject *__pyx_pf_5_cdec_10Hypergraph_12intersect(struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self, struct __pyx_obj_5_cdec_Lattice *__pyx_v_lat); /* proto */
+static PyObject *__pyx_pf_5_cdec_10Hypergraph_14sample(struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self, unsigned int __pyx_v_n); /* proto */
+static int __pyx_pf_5_cdec_7Lattice___init__(struct __pyx_obj_5_cdec_Lattice *__pyx_v_self, PyObject *__pyx_v_plf_tuple); /* proto */
+static PyObject *__pyx_pf_5_cdec_7Lattice_2__str__(struct __pyx_obj_5_cdec_Lattice *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_5_cdec_7Lattice_4__iter__(struct __pyx_obj_5_cdec_Lattice *__pyx_v_self); /* proto */
+static void __pyx_pf_5_cdec_7Lattice_6__dealloc__(CYTHON_UNUSED struct __pyx_obj_5_cdec_Lattice *__pyx_v_self); /* proto */
 static char __pyx_k__eval[] = "eval";
 static char __pyx_k__open[] = "open";
+static char __pyx_k__self[] = "self";
 static char __pyx_k__utf8[] = "utf8";
 static char __pyx_k___cdec[] = "_cdec";
 static char __pyx_k__range[] = "range";
@@ -686,11 +764,7 @@ static char __pyx_k__sentence[] = "sentence";
 static char __pyx_k__Exception[] = "Exception";
 static char __pyx_k____enter__[] = "__enter__";
 static char __pyx_k__plf_tuple[] = "plf_tuple";
-static char __pyx_k__fromconfig[] = "fromconfig";
-static char __pyx_k__startswith[] = "startswith";
 static char __pyx_k__ParseFailed[] = "ParseFailed";
-static PyObject *__pyx_kp_s_1;
-static PyObject *__pyx_kp_s_3;
 static PyObject *__pyx_n_s__Exception;
 static PyObject *__pyx_n_s__KeyError;
 static PyObject *__pyx_n_s__ParseFailed;
@@ -704,63 +778,50 @@ static PyObject *__pyx_n_s__decode;
 static PyObject *__pyx_n_s__decoder;
 static PyObject *__pyx_n_s__encode;
 static PyObject *__pyx_n_s__eval;
-static PyObject *__pyx_n_s__fromconfig;
 static PyObject *__pyx_n_s__grammar;
 static PyObject *__pyx_n_s__open;
 static PyObject *__pyx_n_s__plf_tuple;
 static PyObject *__pyx_n_s__range;
+static PyObject *__pyx_n_s__self;
 static PyObject *__pyx_n_s__sentence;
 static PyObject *__pyx_n_s__split;
-static PyObject *__pyx_n_s__startswith;
 static PyObject *__pyx_n_s__strip;
 static PyObject *__pyx_n_s__utf8;
+static PyObject *__pyx_k_tuple_1;
 static PyObject *__pyx_k_tuple_2;
+static PyObject *__pyx_k_tuple_3;
 static PyObject *__pyx_k_tuple_4;
 static PyObject *__pyx_k_tuple_5;
 static PyObject *__pyx_k_tuple_6;
 static PyObject *__pyx_k_tuple_7;
-static PyObject *__pyx_k_tuple_8;
-static PyObject *__pyx_k_tuple_9;
-static PyObject *__pyx_k_tuple_10;
-static PyObject *__pyx_k_tuple_11;
-static PyObject *__pyx_k_tuple_12;
-
-/* "_cdec.pyx":18
- *     cdef vector[weight_t]* weights
- * 
- *     def __cinit__(self, Decoder decoder):             # <<<<<<<<<<<<<<
- *         self.weights = &decoder.dec.CurrentWeightVector()
- * 
- */
 
-static int __pyx_pf_5_cdec_7Weights___cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static int __pyx_pf_5_cdec_7Weights___cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+/* Python wrapper */
+static int __pyx_pw_5_cdec_7Weights_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_5_cdec_7Weights_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_5_cdec_Decoder *__pyx_v_decoder = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__decoder,0};
   int __pyx_r;
   __Pyx_RefNannyDeclarations
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__decoder,0};
-  __Pyx_RefNannySetupContext("__cinit__");
+  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
   {
     PyObject* values[1] = {0};
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
-      switch (PyTuple_GET_SIZE(__pyx_args)) {
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
         case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
         case  0: break;
         default: goto __pyx_L5_argtuple_error;
       }
       kw_args = PyDict_Size(__pyx_kwds);
-      switch (PyTuple_GET_SIZE(__pyx_args)) {
+      switch (pos_args) {
         case  0:
         values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__decoder);
         if (likely(values[0])) kw_args--;
         else goto __pyx_L5_argtuple_error;
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "__cinit__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 1) {
       goto __pyx_L5_argtuple_error;
@@ -778,6 +839,27 @@ static int __pyx_pf_5_cdec_7Weights___cinit__(PyObject *__pyx_v_self, PyObject *
   return -1;
   __pyx_L4_argument_unpacking_done:;
   if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_decoder), __pyx_ptype_5_cdec_Decoder, 1, "decoder", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5_cdec_7Weights___cinit__(((struct __pyx_obj_5_cdec_Weights *)__pyx_v_self), __pyx_v_decoder);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "_cdec.pyx":18
+ *     cdef vector[weight_t]* weights
+ * 
+ *     def __cinit__(self, Decoder decoder):             # <<<<<<<<<<<<<<
+ *         self.weights = &decoder.dec.CurrentWeightVector()
+ * 
+ */
+
+static int __pyx_pf_5_cdec_7Weights___cinit__(struct __pyx_obj_5_cdec_Weights *__pyx_v_self, struct __pyx_obj_5_cdec_Decoder *__pyx_v_decoder) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__cinit__", 0);
 
   /* "_cdec.pyx":19
  * 
@@ -786,14 +868,30 @@ static int __pyx_pf_5_cdec_7Weights___cinit__(PyObject *__pyx_v_self, PyObject *
  * 
  *     def __getitem__(self, char* fname):
  */
-  ((struct __pyx_obj_5_cdec_Weights *)__pyx_v_self)->weights = (&__pyx_v_decoder->dec->CurrentWeightVector());
+  __pyx_v_self->weights = (&__pyx_v_decoder->dec->CurrentWeightVector());
 
   __pyx_r = 0;
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_AddTraceback("_cdec.Weights.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = -1;
-  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_5_cdec_7Weights_3__getitem__(PyObject *__pyx_v_self, PyObject *__pyx_arg_fname); /*proto*/
+static PyObject *__pyx_pw_5_cdec_7Weights_3__getitem__(PyObject *__pyx_v_self, PyObject *__pyx_arg_fname) {
+  char *__pyx_v_fname;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__getitem__ (wrapper)", 0);
+  assert(__pyx_arg_fname); {
+    __pyx_v_fname = PyBytes_AsString(__pyx_arg_fname); if (unlikely((!__pyx_v_fname) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("_cdec.Weights.__getitem__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_5_cdec_7Weights_2__getitem__(((struct __pyx_obj_5_cdec_Weights *)__pyx_v_self), ((char *)__pyx_v_fname));
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
@@ -806,9 +904,7 @@ static int __pyx_pf_5_cdec_7Weights___cinit__(PyObject *__pyx_v_self, PyObject *
  *         if fid <= self.weights.size():
  */
 
-static PyObject *__pyx_pf_5_cdec_7Weights_1__getitem__(PyObject *__pyx_v_self, PyObject *__pyx_arg_fname); /*proto*/
-static PyObject *__pyx_pf_5_cdec_7Weights_1__getitem__(PyObject *__pyx_v_self, PyObject *__pyx_arg_fname) {
-  char *__pyx_v_fname;
+static PyObject *__pyx_pf_5_cdec_7Weights_2__getitem__(struct __pyx_obj_5_cdec_Weights *__pyx_v_self, char *__pyx_v_fname) {
   unsigned int __pyx_v_fid;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
@@ -818,16 +914,7 @@ static PyObject *__pyx_pf_5_cdec_7Weights_1__getitem__(PyObject *__pyx_v_self, P
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__getitem__");
-  assert(__pyx_arg_fname); {
-    __pyx_v_fname = PyBytes_AsString(__pyx_arg_fname); if (unlikely((!__pyx_v_fname) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_cdec.Weights.__getitem__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
+  __Pyx_RefNannySetupContext("__getitem__", 0);
 
   /* "_cdec.pyx":22
  * 
@@ -845,7 +932,7 @@ static PyObject *__pyx_pf_5_cdec_7Weights_1__getitem__(PyObject *__pyx_v_self, P
  *             return self.weights[0][fid]
  *         raise KeyError(fname)
  */
-  __pyx_t_1 = (__pyx_v_fid <= ((struct __pyx_obj_5_cdec_Weights *)__pyx_v_self)->weights->size());
+  __pyx_t_1 = (__pyx_v_fid <= __pyx_v_self->weights->size());
   if (__pyx_t_1) {
 
     /* "_cdec.pyx":24
@@ -856,14 +943,14 @@ static PyObject *__pyx_pf_5_cdec_7Weights_1__getitem__(PyObject *__pyx_v_self, P
  * 
  */
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_2 = PyFloat_FromDouble(((((struct __pyx_obj_5_cdec_Weights *)__pyx_v_self)->weights[0])[__pyx_v_fid])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyFloat_FromDouble(((__pyx_v_self->weights[0])[__pyx_v_fid])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __pyx_r = __pyx_t_2;
     __pyx_t_2 = 0;
     goto __pyx_L0;
-    goto __pyx_L5;
+    goto __pyx_L3;
   }
-  __pyx_L5:;
+  __pyx_L3:;
 
   /* "_cdec.pyx":25
  *         if fid <= self.weights.size():
@@ -875,7 +962,7 @@ static PyObject *__pyx_pf_5_cdec_7Weights_1__getitem__(PyObject *__pyx_v_self, P
   __pyx_t_2 = PyBytes_FromString(__pyx_v_fname); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_2));
   __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  __Pyx_GOTREF(__pyx_t_3);
   PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_t_2));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_2));
   __pyx_t_2 = 0;
@@ -899,31 +986,19 @@ static PyObject *__pyx_pf_5_cdec_7Weights_1__getitem__(PyObject *__pyx_v_self, P
   return __pyx_r;
 }
 
-/* "_cdec.pyx":27
- *         raise KeyError(fname)
- * 
- *     def __setitem__(self, char* fname, float value):             # <<<<<<<<<<<<<<
- *         cdef unsigned fid = FDConvert(<char *>fname)
- *         if self.weights.size() <= fid:
- */
-
-static int __pyx_pf_5_cdec_7Weights_2__setitem__(PyObject *__pyx_v_self, PyObject *__pyx_arg_fname, PyObject *__pyx_arg_value); /*proto*/
-static int __pyx_pf_5_cdec_7Weights_2__setitem__(PyObject *__pyx_v_self, PyObject *__pyx_arg_fname, PyObject *__pyx_arg_value) {
+/* Python wrapper */
+static int __pyx_pw_5_cdec_7Weights_5__setitem__(PyObject *__pyx_v_self, PyObject *__pyx_arg_fname, PyObject *__pyx_arg_value); /*proto*/
+static int __pyx_pw_5_cdec_7Weights_5__setitem__(PyObject *__pyx_v_self, PyObject *__pyx_arg_fname, PyObject *__pyx_arg_value) {
   char *__pyx_v_fname;
   float __pyx_v_value;
-  unsigned int __pyx_v_fid;
   int __pyx_r;
   __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__setitem__");
+  __Pyx_RefNannySetupContext("__setitem__ (wrapper)", 0);
   assert(__pyx_arg_fname); {
     __pyx_v_fname = PyBytes_AsString(__pyx_arg_fname); if (unlikely((!__pyx_v_fname) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   assert(__pyx_arg_value); {
-    __pyx_v_value = __pyx_PyFloat_AsDouble(__pyx_arg_value); if (unlikely((__pyx_v_value == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_value = __pyx_PyFloat_AsFloat(__pyx_arg_value); if (unlikely((__pyx_v_value == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -931,6 +1006,25 @@ static int __pyx_pf_5_cdec_7Weights_2__setitem__(PyObject *__pyx_v_self, PyObjec
   __Pyx_RefNannyFinishContext();
   return -1;
   __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_5_cdec_7Weights_4__setitem__(((struct __pyx_obj_5_cdec_Weights *)__pyx_v_self), ((char *)__pyx_v_fname), ((float)__pyx_v_value));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "_cdec.pyx":27
+ *         raise KeyError(fname)
+ * 
+ *     def __setitem__(self, char* fname, float value):             # <<<<<<<<<<<<<<
+ *         cdef unsigned fid = FDConvert(<char *>fname)
+ *         if self.weights.size() <= fid:
+ */
+
+static int __pyx_pf_5_cdec_7Weights_4__setitem__(struct __pyx_obj_5_cdec_Weights *__pyx_v_self, char *__pyx_v_fname, float __pyx_v_value) {
+  unsigned int __pyx_v_fid;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  __Pyx_RefNannySetupContext("__setitem__", 0);
 
   /* "_cdec.pyx":28
  * 
@@ -948,7 +1042,7 @@ static int __pyx_pf_5_cdec_7Weights_2__setitem__(PyObject *__pyx_v_self, PyObjec
  *             self.weights.resize(fid + 1)
  *         self.weights[0][fid] = value
  */
-  __pyx_t_1 = (((struct __pyx_obj_5_cdec_Weights *)__pyx_v_self)->weights->size() <= __pyx_v_fid);
+  __pyx_t_1 = (__pyx_v_self->weights->size() <= __pyx_v_fid);
   if (__pyx_t_1) {
 
     /* "_cdec.pyx":30
@@ -958,10 +1052,10 @@ static int __pyx_pf_5_cdec_7Weights_2__setitem__(PyObject *__pyx_v_self, PyObjec
  *         self.weights[0][fid] = value
  * 
  */
-    ((struct __pyx_obj_5_cdec_Weights *)__pyx_v_self)->weights->resize((__pyx_v_fid + 1));
-    goto __pyx_L5;
+    __pyx_v_self->weights->resize((__pyx_v_fid + 1));
+    goto __pyx_L3;
   }
-  __pyx_L5:;
+  __pyx_L3:;
 
   /* "_cdec.pyx":31
  *         if self.weights.size() <= fid:
@@ -970,13 +1064,24 @@ static int __pyx_pf_5_cdec_7Weights_2__setitem__(PyObject *__pyx_v_self, PyObjec
  * 
  *     def __iter__(self):
  */
-  ((((struct __pyx_obj_5_cdec_Weights *)__pyx_v_self)->weights[0])[__pyx_v_fid]) = __pyx_v_value;
+  ((__pyx_v_self->weights[0])[__pyx_v_fid]) = __pyx_v_value;
 
   __pyx_r = 0;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
-static PyObject *__pyx_gb_5_cdec_7Weights_4generator(struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ *__pyx_cur_scope, PyObject *__pyx_sent_value); /* proto */
+static PyObject *__pyx_gb_5_cdec_7Weights_8generator(__pyx_GeneratorObject *__pyx_generator, PyObject *__pyx_sent_value); /* proto */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_5_cdec_7Weights_7__iter__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_5_cdec_7Weights_7__iter__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__iter__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_5_cdec_7Weights_6__iter__(((struct __pyx_obj_5_cdec_Weights *)__pyx_v_self));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
 /* "_cdec.pyx":33
  *         self.weights[0][fid] = value
@@ -986,36 +1091,45 @@ static PyObject *__pyx_gb_5_cdec_7Weights_4generator(struct __pyx_obj_5_cdec___p
  *         for fid in range(1, self.weights.size()):
  */
 
-static PyObject *__pyx_pf_5_cdec_7Weights_3__iter__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pf_5_cdec_7Weights_3__iter__(PyObject *__pyx_v_self) {
+static PyObject *__pyx_pf_5_cdec_7Weights_6__iter__(struct __pyx_obj_5_cdec_Weights *__pyx_v_self) {
   struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ *__pyx_cur_scope;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__iter__");
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__iter__", 0);
   __pyx_cur_scope = (struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ *)__pyx_ptype_5_cdec___pyx_scope_struct____iter__->tp_new(__pyx_ptype_5_cdec___pyx_scope_struct____iter__, __pyx_empty_tuple, NULL);
   if (unlikely(!__pyx_cur_scope)) {
     __Pyx_RefNannyFinishContext();
     return NULL;
   }
   __Pyx_GOTREF(__pyx_cur_scope);
-  __Pyx_INCREF(__pyx_v_self);
   __pyx_cur_scope->__pyx_v_self = __pyx_v_self;
+  __Pyx_INCREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
   __Pyx_GIVEREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
-  __pyx_cur_scope->__pyx_base.resume_label = 0;
-  __pyx_cur_scope->__pyx_base.body = (__pyx_generator_body_t) __pyx_gb_5_cdec_7Weights_4generator;
-  __Pyx_GIVEREF(__pyx_cur_scope);
-  __Pyx_RefNannyFinishContext();
-  return (PyObject *) __pyx_cur_scope;
+  {
+    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_5_cdec_7Weights_8generator, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_cur_scope);
+    __Pyx_RefNannyFinishContext();
+    return (PyObject *) gen;
+  }
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("_cdec.Weights.__iter__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_DECREF(((PyObject *)__pyx_cur_scope));
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_gb_5_cdec_7Weights_4generator(struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ *__pyx_cur_scope, PyObject *__pyx_sent_value) /* generator body */
+static PyObject *__pyx_gb_5_cdec_7Weights_8generator(__pyx_GeneratorObject *__pyx_generator, PyObject *__pyx_sent_value) /* generator body */
 {
+  struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ *__pyx_cur_scope = ((struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ *)__pyx_generator->closure);
   PyObject *__pyx_r = NULL;
   size_t __pyx_t_1;
   unsigned int __pyx_t_2;
@@ -1023,8 +1137,8 @@ static PyObject *__pyx_gb_5_cdec_7Weights_4generator(struct __pyx_obj_5_cdec___p
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("None");
-  switch (__pyx_cur_scope->__pyx_base.resume_label) {
+  __Pyx_RefNannySetupContext("None", 0);
+  switch (__pyx_generator->resume_label) {
     case 0: goto __pyx_L3_first_run;
     case 1: goto __pyx_L6_resume_from_yield;
     default: /* CPython raises the right error here */
@@ -1041,7 +1155,7 @@ static PyObject *__pyx_gb_5_cdec_7Weights_4generator(struct __pyx_obj_5_cdec___p
  *             yield FDConvert(fid).c_str(), self.weights[0][fid]
  * 
  */
-  __pyx_t_1 = ((struct __pyx_obj_5_cdec_Weights *)__pyx_cur_scope->__pyx_v_self)->weights->size();
+  __pyx_t_1 = __pyx_cur_scope->__pyx_v_self->weights->size();
   for (__pyx_t_2 = 1; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {
     __pyx_cur_scope->__pyx_v_fid = __pyx_t_2;
 
@@ -1054,10 +1168,10 @@ static PyObject *__pyx_gb_5_cdec_7Weights_4generator(struct __pyx_obj_5_cdec___p
  */
     __pyx_t_3 = PyBytes_FromString(FD::Convert(__pyx_cur_scope->__pyx_v_fid).c_str()); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_3));
-    __pyx_t_4 = PyFloat_FromDouble(((((struct __pyx_obj_5_cdec_Weights *)__pyx_cur_scope->__pyx_v_self)->weights[0])[__pyx_cur_scope->__pyx_v_fid])); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyFloat_FromDouble(((__pyx_cur_scope->__pyx_v_self->weights[0])[__pyx_cur_scope->__pyx_v_fid])); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+    __Pyx_GOTREF(__pyx_t_5);
     PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_t_3));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_3));
     PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_4);
@@ -1071,14 +1185,14 @@ static PyObject *__pyx_gb_5_cdec_7Weights_4generator(struct __pyx_obj_5_cdec___p
     __Pyx_XGIVEREF(__pyx_r);
     __Pyx_RefNannyFinishContext();
     /* return from generator, yielding value */
-    __pyx_cur_scope->__pyx_base.resume_label = 1;
+    __pyx_generator->resume_label = 1;
     return __pyx_r;
     __pyx_L6_resume_from_yield:;
     __pyx_t_1 = __pyx_cur_scope->__pyx_t_0;
     __pyx_t_2 = __pyx_cur_scope->__pyx_t_1;
     if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  PyErr_SetNone(PyExc_StopIteration); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  PyErr_SetNone(PyExc_StopIteration);
   goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_3);
@@ -1087,50 +1201,38 @@ static PyObject *__pyx_gb_5_cdec_7Weights_4generator(struct __pyx_obj_5_cdec___p
   __Pyx_AddTraceback("__iter__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_cur_scope->__pyx_base.resume_label = -1;
+  __pyx_generator->resume_label = -1;
   __Pyx_RefNannyFinishContext();
   return NULL;
 }
 
-/* "_cdec.pyx":42
- *     cdef public Weights weights
- * 
- *     def __cinit__(self, char* config):             # <<<<<<<<<<<<<<
- *         decoder.register_feature_functions()
- *         cdef istringstream* config_stream = new istringstream(config) # ConfigStream(kwargs)
- */
-
-static int __pyx_pf_5_cdec_7Decoder___cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static int __pyx_pf_5_cdec_7Decoder___cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+/* Python wrapper */
+static int __pyx_pw_5_cdec_7Decoder_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_5_cdec_7Decoder_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   char *__pyx_v_config;
-  std::istringstream *__pyx_v_config_stream;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__config,0};
   int __pyx_r;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__config,0};
-  __Pyx_RefNannySetupContext("__cinit__");
+  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
   {
     PyObject* values[1] = {0};
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
-      switch (PyTuple_GET_SIZE(__pyx_args)) {
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
         case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
         case  0: break;
         default: goto __pyx_L5_argtuple_error;
       }
       kw_args = PyDict_Size(__pyx_kwds);
-      switch (PyTuple_GET_SIZE(__pyx_args)) {
+      switch (pos_args) {
         case  0:
         values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__config);
         if (likely(values[0])) kw_args--;
         else goto __pyx_L5_argtuple_error;
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "__cinit__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 1) {
       goto __pyx_L5_argtuple_error;
@@ -1147,62 +1249,85 @@ static int __pyx_pf_5_cdec_7Decoder___cinit__(PyObject *__pyx_v_self, PyObject *
   __Pyx_RefNannyFinishContext();
   return -1;
   __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_5_cdec_7Decoder___cinit__(((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self), __pyx_v_config);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "_cdec.pyx":42
+ *     cdef public Weights weights
+ * 
+ *     def __cinit__(self, char* config):             # <<<<<<<<<<<<<<
+ *         decoder.register_feature_functions()
+ *         cdef istringstream* config_stream = new istringstream(config)
+ */
+
+static int __pyx_pf_5_cdec_7Decoder___cinit__(struct __pyx_obj_5_cdec_Decoder *__pyx_v_self, char *__pyx_v_config) {
+  std::istringstream *__pyx_v_config_stream;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__cinit__", 0);
 
   /* "_cdec.pyx":43
  * 
  *     def __cinit__(self, char* config):
  *         decoder.register_feature_functions()             # <<<<<<<<<<<<<<
- *         cdef istringstream* config_stream = new istringstream(config) # ConfigStream(kwargs)
- *         #cdef ReadFile* config_file = new ReadFile(string(config))
+ *         cdef istringstream* config_stream = new istringstream(config)
+ *         self.dec = new decoder.Decoder(config_stream)
  */
   register_feature_functions();
 
   /* "_cdec.pyx":44
  *     def __cinit__(self, char* config):
  *         decoder.register_feature_functions()
- *         cdef istringstream* config_stream = new istringstream(config) # ConfigStream(kwargs)             # <<<<<<<<<<<<<<
- *         #cdef ReadFile* config_file = new ReadFile(string(config))
- *         #cdef istream* config_stream = config_file.stream()
+ *         cdef istringstream* config_stream = new istringstream(config)             # <<<<<<<<<<<<<<
+ *         self.dec = new decoder.Decoder(config_stream)
+ *         del config_stream
  */
   __pyx_v_config_stream = new std::istringstream(__pyx_v_config);
 
-  /* "_cdec.pyx":47
- *         #cdef ReadFile* config_file = new ReadFile(string(config))
- *         #cdef istream* config_stream = config_file.stream()
+  /* "_cdec.pyx":45
+ *         decoder.register_feature_functions()
+ *         cdef istringstream* config_stream = new istringstream(config)
  *         self.dec = new decoder.Decoder(config_stream)             # <<<<<<<<<<<<<<
  *         del config_stream
- *         #del config_file
+ *         self.weights = Weights(self)
  */
-  ((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->dec = new Decoder(__pyx_v_config_stream);
+  __pyx_v_self->dec = new Decoder(__pyx_v_config_stream);
 
-  /* "_cdec.pyx":48
- *         #cdef istream* config_stream = config_file.stream()
+  /* "_cdec.pyx":46
+ *         cdef istringstream* config_stream = new istringstream(config)
  *         self.dec = new decoder.Decoder(config_stream)
  *         del config_stream             # <<<<<<<<<<<<<<
- *         #del config_file
  *         self.weights = Weights(self)
+ * 
  */
   delete __pyx_v_config_stream;
 
-  /* "_cdec.pyx":50
+  /* "_cdec.pyx":47
+ *         self.dec = new decoder.Decoder(config_stream)
  *         del config_stream
- *         #del config_file
  *         self.weights = Weights(self)             # <<<<<<<<<<<<<<
  * 
  *     def __dealloc__(self):
  */
-  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  __Pyx_INCREF(__pyx_v_self);
-  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self);
-  __Pyx_GIVEREF(__pyx_v_self);
-  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_5_cdec_Weights)), ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(((PyObject *)__pyx_v_self));
+  PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_self));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_self));
+  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_5_cdec_Weights)), ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
   __Pyx_GIVEREF(__pyx_t_2);
-  __Pyx_GOTREF(((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->weights);
-  __Pyx_DECREF(((PyObject *)((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->weights));
-  ((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->weights = ((struct __pyx_obj_5_cdec_Weights *)__pyx_t_2);
+  __Pyx_GOTREF(__pyx_v_self->weights);
+  __Pyx_DECREF(((PyObject *)__pyx_v_self->weights));
+  __pyx_v_self->weights = ((struct __pyx_obj_5_cdec_Weights *)__pyx_t_2);
   __pyx_t_2 = 0;
 
   __pyx_r = 0;
@@ -1217,7 +1342,16 @@ static int __pyx_pf_5_cdec_7Decoder___cinit__(PyObject *__pyx_v_self, PyObject *
   return __pyx_r;
 }
 
-/* "_cdec.pyx":52
+/* Python wrapper */
+static void __pyx_pw_5_cdec_7Decoder_3__dealloc__(PyObject *__pyx_v_self); /*proto*/
+static void __pyx_pw_5_cdec_7Decoder_3__dealloc__(PyObject *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
+  __pyx_pf_5_cdec_7Decoder_2__dealloc__(((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self));
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "_cdec.pyx":49
  *         self.weights = Weights(self)
  * 
  *     def __dealloc__(self):             # <<<<<<<<<<<<<<
@@ -1225,37 +1359,45 @@ static int __pyx_pf_5_cdec_7Decoder___cinit__(PyObject *__pyx_v_self, PyObject *
  * 
  */
 
-static void __pyx_pf_5_cdec_7Decoder_1__dealloc__(PyObject *__pyx_v_self); /*proto*/
-static void __pyx_pf_5_cdec_7Decoder_1__dealloc__(PyObject *__pyx_v_self) {
+static void __pyx_pf_5_cdec_7Decoder_2__dealloc__(CYTHON_UNUSED struct __pyx_obj_5_cdec_Decoder *__pyx_v_self) {
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__dealloc__");
+  __Pyx_RefNannySetupContext("__dealloc__", 0);
 
-  /* "_cdec.pyx":53
+  /* "_cdec.pyx":50
  * 
  *     def __dealloc__(self):
  *         del self.dec             # <<<<<<<<<<<<<<
  * 
- *     @classmethod
+ *     def read_weights(self, cfg):
  */
-  delete ((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->dec;
+  delete __pyx_v_self->dec;
 
   __Pyx_RefNannyFinishContext();
 }
 
-/* "_cdec.pyx":56
+/* Python wrapper */
+static PyObject *__pyx_pw_5_cdec_7Decoder_5read_weights(PyObject *__pyx_v_self, PyObject *__pyx_v_cfg); /*proto*/
+static PyObject *__pyx_pw_5_cdec_7Decoder_5read_weights(PyObject *__pyx_v_self, PyObject *__pyx_v_cfg) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("read_weights (wrapper)", 0);
+  __pyx_r = __pyx_pf_5_cdec_7Decoder_4read_weights(((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self), ((PyObject *)__pyx_v_cfg));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "_cdec.pyx":52
+ *         del self.dec
  * 
- *     @classmethod
- *     def fromconfig(cls, ini):             # <<<<<<<<<<<<<<
- *         cdef dict config = {}
- *         with open(ini) as fp:
+ *     def read_weights(self, cfg):             # <<<<<<<<<<<<<<
+ *         with open(cfg) as fp:
+ *             for line in fp:
  */
 
-static PyObject *__pyx_pf_5_cdec_7Decoder_2fromconfig(PyObject *__pyx_v_cls, PyObject *__pyx_v_ini); /*proto*/
-static PyObject *__pyx_pf_5_cdec_7Decoder_2fromconfig(PyObject *__pyx_v_cls, PyObject *__pyx_v_ini) {
-  PyObject *__pyx_v_config = 0;
+static PyObject *__pyx_pf_5_cdec_7Decoder_4read_weights(struct __pyx_obj_5_cdec_Decoder *__pyx_v_self, PyObject *__pyx_v_cfg) {
   PyObject *__pyx_v_fp = NULL;
   PyObject *__pyx_v_line = NULL;
-  PyObject *__pyx_v_param = NULL;
+  PyObject *__pyx_v_fname = NULL;
   PyObject *__pyx_v_value = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
@@ -1265,396 +1407,22 @@ static PyObject *__pyx_pf_5_cdec_7Decoder_2fromconfig(PyObject *__pyx_v_cls, PyO
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
-  Py_ssize_t __pyx_t_7;
-  PyObject *(*__pyx_t_8)(PyObject *);
-  PyObject *__pyx_t_9 = NULL;
-  int __pyx_t_10;
-  int __pyx_t_11;
-  int __pyx_t_12;
-  PyObject *__pyx_t_13 = NULL;
-  PyObject *__pyx_t_14 = NULL;
-  PyObject *(*__pyx_t_15)(PyObject *);
-  PyObject *__pyx_t_16 = NULL;
+  PyObject *__pyx_t_7 = NULL;
+  Py_ssize_t __pyx_t_8;
+  PyObject *(*__pyx_t_9)(PyObject *);
+  PyObject *__pyx_t_10 = NULL;
+  PyObject *__pyx_t_11 = NULL;
+  PyObject *(*__pyx_t_12)(PyObject *);
+  double __pyx_t_13;
+  int __pyx_t_14;
+  PyObject *__pyx_t_15 = NULL;
+  int __pyx_t_16;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("fromconfig");
+  __Pyx_RefNannySetupContext("read_weights", 0);
 
-  /* "_cdec.pyx":57
- *     @classmethod
- *     def fromconfig(cls, ini):
- *         cdef dict config = {}             # <<<<<<<<<<<<<<
- *         with open(ini) as fp:
- *             for line in fp:
- */
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  __pyx_v_config = __pyx_t_1;
-  __pyx_t_1 = 0;
-
-  /* "_cdec.pyx":58
- *     def fromconfig(cls, ini):
- *         cdef dict config = {}
- *         with open(ini) as fp:             # <<<<<<<<<<<<<<
- *             for line in fp:
- *                 line = line.strip()
- */
-  /*with:*/ {
-    __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-    __Pyx_INCREF(__pyx_v_ini);
-    PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_ini);
-    __Pyx_GIVEREF(__pyx_v_ini);
-    __pyx_t_2 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
-    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____enter__); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L5_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L5_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    /*try:*/ {
-      {
-        __Pyx_ExceptionSave(&__pyx_t_4, &__pyx_t_5, &__pyx_t_6);
-        __Pyx_XGOTREF(__pyx_t_4);
-        __Pyx_XGOTREF(__pyx_t_5);
-        __Pyx_XGOTREF(__pyx_t_6);
-        /*try:*/ {
-          __pyx_v_fp = __pyx_t_2;
-          __pyx_t_2 = 0;
-
-          /* "_cdec.pyx":59
- *         cdef dict config = {}
- *         with open(ini) as fp:
- *             for line in fp:             # <<<<<<<<<<<<<<
- *                 line = line.strip()
- *                 if not line or line.startswith('#'): continue
- */
-          if (PyList_CheckExact(__pyx_v_fp) || PyTuple_CheckExact(__pyx_v_fp)) {
-            __pyx_t_2 = __pyx_v_fp; __Pyx_INCREF(__pyx_t_2); __pyx_t_7 = 0;
-            __pyx_t_8 = NULL;
-          } else {
-            __pyx_t_7 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_fp); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __Pyx_GOTREF(__pyx_t_2);
-            __pyx_t_8 = Py_TYPE(__pyx_t_2)->tp_iternext;
-          }
-          for (;;) {
-            if (PyList_CheckExact(__pyx_t_2)) {
-              if (__pyx_t_7 >= PyList_GET_SIZE(__pyx_t_2)) break;
-              __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_7); __Pyx_INCREF(__pyx_t_1); __pyx_t_7++;
-            } else if (PyTuple_CheckExact(__pyx_t_2)) {
-              if (__pyx_t_7 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
-              __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_7); __Pyx_INCREF(__pyx_t_1); __pyx_t_7++;
-            } else {
-              __pyx_t_1 = __pyx_t_8(__pyx_t_2);
-              if (unlikely(!__pyx_t_1)) {
-                if (PyErr_Occurred()) {
-                  if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-                  else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-                }
-                break;
-              }
-              __Pyx_GOTREF(__pyx_t_1);
-            }
-            __Pyx_XDECREF(__pyx_v_line);
-            __pyx_v_line = __pyx_t_1;
-            __pyx_t_1 = 0;
-
-            /* "_cdec.pyx":60
- *         with open(ini) as fp:
- *             for line in fp:
- *                 line = line.strip()             # <<<<<<<<<<<<<<
- *                 if not line or line.startswith('#'): continue
- *                 param, value = line.split('=')
- */
-            __pyx_t_1 = PyObject_GetAttr(__pyx_v_line, __pyx_n_s__strip); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __Pyx_GOTREF(__pyx_t_1);
-            __pyx_t_9 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __Pyx_GOTREF(__pyx_t_9);
-            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-            __Pyx_DECREF(__pyx_v_line);
-            __pyx_v_line = __pyx_t_9;
-            __pyx_t_9 = 0;
-
-            /* "_cdec.pyx":61
- *             for line in fp:
- *                 line = line.strip()
- *                 if not line or line.startswith('#'): continue             # <<<<<<<<<<<<<<
- *                 param, value = line.split('=')
- *                 config[param.strip()] = value.strip()
- */
-            __pyx_t_10 = __Pyx_PyObject_IsTrue(__pyx_v_line); if (unlikely(__pyx_t_10 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __pyx_t_11 = (!__pyx_t_10);
-            if (!__pyx_t_11) {
-              __pyx_t_9 = PyObject_GetAttr(__pyx_v_line, __pyx_n_s__startswith); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-              __Pyx_GOTREF(__pyx_t_9);
-              __pyx_t_1 = PyObject_Call(__pyx_t_9, ((PyObject *)__pyx_k_tuple_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-              __Pyx_GOTREF(__pyx_t_1);
-              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-              __pyx_t_10 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_10 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-              __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-              __pyx_t_12 = __pyx_t_10;
-            } else {
-              __pyx_t_12 = __pyx_t_11;
-            }
-            if (__pyx_t_12) {
-              goto __pyx_L17_continue;
-              goto __pyx_L19;
-            }
-            __pyx_L19:;
-
-            /* "_cdec.pyx":62
- *                 line = line.strip()
- *                 if not line or line.startswith('#'): continue
- *                 param, value = line.split('=')             # <<<<<<<<<<<<<<
- *                 config[param.strip()] = value.strip()
- *         return cls(**config)
- */
-            __pyx_t_1 = PyObject_GetAttr(__pyx_v_line, __pyx_n_s__split); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __Pyx_GOTREF(__pyx_t_1);
-            __pyx_t_9 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_4), NULL); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __Pyx_GOTREF(__pyx_t_9);
-            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-            if ((likely(PyTuple_CheckExact(__pyx_t_9))) || (PyList_CheckExact(__pyx_t_9))) {
-              PyObject* sequence = __pyx_t_9;
-              if (likely(PyTuple_CheckExact(sequence))) {
-                if (unlikely(PyTuple_GET_SIZE(sequence) != 2)) {
-                  if (PyTuple_GET_SIZE(sequence) > 2) __Pyx_RaiseTooManyValuesError(2);
-                  else __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(sequence));
-                  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-                }
-                __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); 
-                __pyx_t_13 = PyTuple_GET_ITEM(sequence, 1); 
-              } else {
-                if (unlikely(PyList_GET_SIZE(sequence) != 2)) {
-                  if (PyList_GET_SIZE(sequence) > 2) __Pyx_RaiseTooManyValuesError(2);
-                  else __Pyx_RaiseNeedMoreValuesError(PyList_GET_SIZE(sequence));
-                  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-                }
-                __pyx_t_1 = PyList_GET_ITEM(sequence, 0); 
-                __pyx_t_13 = PyList_GET_ITEM(sequence, 1); 
-              }
-              __Pyx_INCREF(__pyx_t_1);
-              __Pyx_INCREF(__pyx_t_13);
-              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-            } else {
-              Py_ssize_t index = -1;
-              __pyx_t_14 = PyObject_GetIter(__pyx_t_9); if (unlikely(!__pyx_t_14)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-              __Pyx_GOTREF(__pyx_t_14);
-              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-              __pyx_t_15 = Py_TYPE(__pyx_t_14)->tp_iternext;
-              index = 0; __pyx_t_1 = __pyx_t_15(__pyx_t_14); if (unlikely(!__pyx_t_1)) goto __pyx_L20_unpacking_failed;
-              __Pyx_GOTREF(__pyx_t_1);
-              index = 1; __pyx_t_13 = __pyx_t_15(__pyx_t_14); if (unlikely(!__pyx_t_13)) goto __pyx_L20_unpacking_failed;
-              __Pyx_GOTREF(__pyx_t_13);
-              if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_14), 2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-              __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
-              goto __pyx_L21_unpacking_done;
-              __pyx_L20_unpacking_failed:;
-              __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
-              if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration)) PyErr_Clear();
-              if (!PyErr_Occurred()) __Pyx_RaiseNeedMoreValuesError(index);
-              {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-              __pyx_L21_unpacking_done:;
-            }
-            __Pyx_XDECREF(__pyx_v_param);
-            __pyx_v_param = __pyx_t_1;
-            __pyx_t_1 = 0;
-            __Pyx_XDECREF(__pyx_v_value);
-            __pyx_v_value = __pyx_t_13;
-            __pyx_t_13 = 0;
-
-            /* "_cdec.pyx":63
- *                 if not line or line.startswith('#'): continue
- *                 param, value = line.split('=')
- *                 config[param.strip()] = value.strip()             # <<<<<<<<<<<<<<
- *         return cls(**config)
- * 
- */
-            __pyx_t_9 = PyObject_GetAttr(__pyx_v_value, __pyx_n_s__strip); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __Pyx_GOTREF(__pyx_t_9);
-            __pyx_t_13 = PyObject_Call(__pyx_t_9, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __Pyx_GOTREF(__pyx_t_13);
-            __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-            __pyx_t_9 = PyObject_GetAttr(__pyx_v_param, __pyx_n_s__strip); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __Pyx_GOTREF(__pyx_t_9);
-            __pyx_t_1 = PyObject_Call(__pyx_t_9, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __Pyx_GOTREF(__pyx_t_1);
-            __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-            if (PyDict_SetItem(((PyObject *)__pyx_v_config), __pyx_t_1, __pyx_t_13) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-            __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-            __pyx_L17_continue:;
-          }
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-        }
-        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        goto __pyx_L16_try_end;
-        __pyx_L9_error:;
-        __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
-        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
-        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-        __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
-        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
-
-        /* "_cdec.pyx":58
- *     def fromconfig(cls, ini):
- *         cdef dict config = {}
- *         with open(ini) as fp:             # <<<<<<<<<<<<<<
- *             for line in fp:
- *                 line = line.strip()
- */
-        /*except:*/ {
-          __Pyx_AddTraceback("_cdec.Decoder.fromconfig", __pyx_clineno, __pyx_lineno, __pyx_filename);
-          if (__Pyx_GetException(&__pyx_t_2, &__pyx_t_13, &__pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L11_except_error;}
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_GOTREF(__pyx_t_13);
-          __Pyx_GOTREF(__pyx_t_1);
-          __pyx_t_9 = PyTuple_New(3); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L11_except_error;}
-          __Pyx_GOTREF(((PyObject *)__pyx_t_9));
-          __Pyx_INCREF(__pyx_t_2);
-          PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_2);
-          __Pyx_GIVEREF(__pyx_t_2);
-          __Pyx_INCREF(__pyx_t_13);
-          PyTuple_SET_ITEM(__pyx_t_9, 1, __pyx_t_13);
-          __Pyx_GIVEREF(__pyx_t_13);
-          __Pyx_INCREF(__pyx_t_1);
-          PyTuple_SET_ITEM(__pyx_t_9, 2, __pyx_t_1);
-          __Pyx_GIVEREF(__pyx_t_1);
-          __pyx_t_16 = PyObject_Call(__pyx_t_3, __pyx_t_9, NULL);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-          if (unlikely(!__pyx_t_16)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L11_except_error;}
-          __Pyx_GOTREF(__pyx_t_16);
-          __pyx_t_12 = __Pyx_PyObject_IsTrue(__pyx_t_16);
-          __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
-          if (unlikely(__pyx_t_12 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L11_except_error;}
-          __pyx_t_11 = (!__pyx_t_12);
-          if (__pyx_t_11) {
-            __Pyx_GIVEREF(__pyx_t_2);
-            __Pyx_GIVEREF(__pyx_t_13);
-            __Pyx_GIVEREF(__pyx_t_1);
-            __Pyx_ErrRestore(__pyx_t_2, __pyx_t_13, __pyx_t_1);
-            __pyx_t_2 = 0; __pyx_t_13 = 0; __pyx_t_1 = 0; 
-            {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L11_except_error;}
-            goto __pyx_L24;
-          }
-          __pyx_L24:;
-          __Pyx_DECREF(((PyObject *)__pyx_t_9)); __pyx_t_9 = 0;
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-          __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-          goto __pyx_L10_exception_handled;
-        }
-        __pyx_L11_except_error:;
-        __Pyx_XGIVEREF(__pyx_t_4);
-        __Pyx_XGIVEREF(__pyx_t_5);
-        __Pyx_XGIVEREF(__pyx_t_6);
-        __Pyx_ExceptionReset(__pyx_t_4, __pyx_t_5, __pyx_t_6);
-        goto __pyx_L1_error;
-        __pyx_L10_exception_handled:;
-        __Pyx_XGIVEREF(__pyx_t_4);
-        __Pyx_XGIVEREF(__pyx_t_5);
-        __Pyx_XGIVEREF(__pyx_t_6);
-        __Pyx_ExceptionReset(__pyx_t_4, __pyx_t_5, __pyx_t_6);
-        __pyx_L16_try_end:;
-      }
-    }
-    /*finally:*/ {
-      if (__pyx_t_3) {
-        __pyx_t_6 = PyObject_Call(__pyx_t_3, __pyx_k_tuple_5, NULL);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __Pyx_GOTREF(__pyx_t_6);
-        __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_6);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      }
-    }
-    goto __pyx_L25;
-    __pyx_L5_error:;
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    goto __pyx_L1_error;
-    __pyx_L25:;
-  }
-
-  /* "_cdec.pyx":64
- *                 param, value = line.split('=')
- *                 config[param.strip()] = value.strip()
- *         return cls(**config)             # <<<<<<<<<<<<<<
- * 
- *     def read_weights(self, cfg):
- */
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyEval_CallObjectWithKeywords(__pyx_v_cls, ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_v_config)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_9);
-  __Pyx_XDECREF(__pyx_t_13);
-  __Pyx_XDECREF(__pyx_t_14);
-  __Pyx_AddTraceback("_cdec.Decoder.fromconfig", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_config);
-  __Pyx_XDECREF(__pyx_v_fp);
-  __Pyx_XDECREF(__pyx_v_line);
-  __Pyx_XDECREF(__pyx_v_param);
-  __Pyx_XDECREF(__pyx_v_value);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "_cdec.pyx":66
- *         return cls(**config)
- * 
- *     def read_weights(self, cfg):             # <<<<<<<<<<<<<<
- *         with open(cfg) as fp:
- *             for line in fp:
- */
-
-static PyObject *__pyx_pf_5_cdec_7Decoder_3read_weights(PyObject *__pyx_v_self, PyObject *__pyx_v_cfg); /*proto*/
-static PyObject *__pyx_pf_5_cdec_7Decoder_3read_weights(PyObject *__pyx_v_self, PyObject *__pyx_v_cfg) {
-  PyObject *__pyx_v_fp = NULL;
-  PyObject *__pyx_v_line = NULL;
-  PyObject *__pyx_v_fname = NULL;
-  PyObject *__pyx_v_value = NULL;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
-  Py_ssize_t __pyx_t_7;
-  PyObject *(*__pyx_t_8)(PyObject *);
-  PyObject *__pyx_t_9 = NULL;
-  PyObject *__pyx_t_10 = NULL;
-  PyObject *__pyx_t_11 = NULL;
-  PyObject *(*__pyx_t_12)(PyObject *);
-  double __pyx_t_13;
-  int __pyx_t_14;
-  PyObject *__pyx_t_15 = NULL;
-  int __pyx_t_16;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("read_weights");
-
-  /* "_cdec.pyx":67
+  /* "_cdec.pyx":53
  * 
  *     def read_weights(self, cfg):
  *         with open(cfg) as fp:             # <<<<<<<<<<<<<<
@@ -1662,33 +1430,34 @@ static PyObject *__pyx_pf_5_cdec_7Decoder_3read_weights(PyObject *__pyx_v_self,
  *                 fname, value = line.split()
  */
   /*with:*/ {
-    __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+    __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
     __Pyx_INCREF(__pyx_v_cfg);
     PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_cfg);
     __Pyx_GIVEREF(__pyx_v_cfg);
-    __pyx_t_2 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
-    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____enter__); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L5_error;}
+    __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____enter__); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L5_error;}
-    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     /*try:*/ {
       {
-        __Pyx_ExceptionSave(&__pyx_t_4, &__pyx_t_5, &__pyx_t_6);
-        __Pyx_XGOTREF(__pyx_t_4);
+        __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7);
         __Pyx_XGOTREF(__pyx_t_5);
         __Pyx_XGOTREF(__pyx_t_6);
+        __Pyx_XGOTREF(__pyx_t_7);
         /*try:*/ {
-          __pyx_v_fp = __pyx_t_2;
-          __pyx_t_2 = 0;
+          __Pyx_INCREF(__pyx_t_4);
+          __pyx_v_fp = __pyx_t_4;
+          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-          /* "_cdec.pyx":68
+          /* "_cdec.pyx":54
  *     def read_weights(self, cfg):
  *         with open(cfg) as fp:
  *             for line in fp:             # <<<<<<<<<<<<<<
@@ -1696,129 +1465,129 @@ static PyObject *__pyx_pf_5_cdec_7Decoder_3read_weights(PyObject *__pyx_v_self,
  *                 self.weights[fname.strip()] = float(value)
  */
           if (PyList_CheckExact(__pyx_v_fp) || PyTuple_CheckExact(__pyx_v_fp)) {
-            __pyx_t_2 = __pyx_v_fp; __Pyx_INCREF(__pyx_t_2); __pyx_t_7 = 0;
-            __pyx_t_8 = NULL;
+            __pyx_t_4 = __pyx_v_fp; __Pyx_INCREF(__pyx_t_4); __pyx_t_8 = 0;
+            __pyx_t_9 = NULL;
           } else {
-            __pyx_t_7 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_fp); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __Pyx_GOTREF(__pyx_t_2);
-            __pyx_t_8 = Py_TYPE(__pyx_t_2)->tp_iternext;
+            __pyx_t_8 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_v_fp); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_4);
+            __pyx_t_9 = Py_TYPE(__pyx_t_4)->tp_iternext;
           }
           for (;;) {
-            if (PyList_CheckExact(__pyx_t_2)) {
-              if (__pyx_t_7 >= PyList_GET_SIZE(__pyx_t_2)) break;
-              __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_7); __Pyx_INCREF(__pyx_t_1); __pyx_t_7++;
-            } else if (PyTuple_CheckExact(__pyx_t_2)) {
-              if (__pyx_t_7 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
-              __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_7); __Pyx_INCREF(__pyx_t_1); __pyx_t_7++;
+            if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_4)) {
+              if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_4)) break;
+              __pyx_t_2 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++;
+            } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_4)) {
+              if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
+              __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++;
             } else {
-              __pyx_t_1 = __pyx_t_8(__pyx_t_2);
-              if (unlikely(!__pyx_t_1)) {
+              __pyx_t_2 = __pyx_t_9(__pyx_t_4);
+              if (unlikely(!__pyx_t_2)) {
                 if (PyErr_Occurred()) {
                   if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-                  else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
+                  else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
                 break;
               }
-              __Pyx_GOTREF(__pyx_t_1);
+              __Pyx_GOTREF(__pyx_t_2);
             }
             __Pyx_XDECREF(__pyx_v_line);
-            __pyx_v_line = __pyx_t_1;
-            __pyx_t_1 = 0;
+            __pyx_v_line = __pyx_t_2;
+            __pyx_t_2 = 0;
 
-            /* "_cdec.pyx":69
+            /* "_cdec.pyx":55
  *         with open(cfg) as fp:
  *             for line in fp:
  *                 fname, value = line.split()             # <<<<<<<<<<<<<<
  *                 self.weights[fname.strip()] = float(value)
  * 
  */
-            __pyx_t_1 = PyObject_GetAttr(__pyx_v_line, __pyx_n_s__split); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
+            __pyx_t_2 = PyObject_GetAttr(__pyx_v_line, __pyx_n_s__split); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
+            __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_1);
-            __pyx_t_9 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __Pyx_GOTREF(__pyx_t_9);
-            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-            if ((likely(PyTuple_CheckExact(__pyx_t_9))) || (PyList_CheckExact(__pyx_t_9))) {
-              PyObject* sequence = __pyx_t_9;
+            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+            if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
+              PyObject* sequence = __pyx_t_1;
               if (likely(PyTuple_CheckExact(sequence))) {
                 if (unlikely(PyTuple_GET_SIZE(sequence) != 2)) {
                   if (PyTuple_GET_SIZE(sequence) > 2) __Pyx_RaiseTooManyValuesError(2);
                   else __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(sequence));
-                  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
+                  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
-                __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); 
+                __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); 
                 __pyx_t_10 = PyTuple_GET_ITEM(sequence, 1); 
               } else {
                 if (unlikely(PyList_GET_SIZE(sequence) != 2)) {
                   if (PyList_GET_SIZE(sequence) > 2) __Pyx_RaiseTooManyValuesError(2);
                   else __Pyx_RaiseNeedMoreValuesError(PyList_GET_SIZE(sequence));
-                  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
+                  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
-                __pyx_t_1 = PyList_GET_ITEM(sequence, 0); 
+                __pyx_t_2 = PyList_GET_ITEM(sequence, 0); 
                 __pyx_t_10 = PyList_GET_ITEM(sequence, 1); 
               }
-              __Pyx_INCREF(__pyx_t_1);
+              __Pyx_INCREF(__pyx_t_2);
               __Pyx_INCREF(__pyx_t_10);
-              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
+              __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
             } else {
               Py_ssize_t index = -1;
-              __pyx_t_11 = PyObject_GetIter(__pyx_t_9); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
+              __pyx_t_11 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_11);
-              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
+              __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
               __pyx_t_12 = Py_TYPE(__pyx_t_11)->tp_iternext;
-              index = 0; __pyx_t_1 = __pyx_t_12(__pyx_t_11); if (unlikely(!__pyx_t_1)) goto __pyx_L19_unpacking_failed;
-              __Pyx_GOTREF(__pyx_t_1);
-              index = 1; __pyx_t_10 = __pyx_t_12(__pyx_t_11); if (unlikely(!__pyx_t_10)) goto __pyx_L19_unpacking_failed;
+              index = 0; __pyx_t_2 = __pyx_t_12(__pyx_t_11); if (unlikely(!__pyx_t_2)) goto __pyx_L18_unpacking_failed;
+              __Pyx_GOTREF(__pyx_t_2);
+              index = 1; __pyx_t_10 = __pyx_t_12(__pyx_t_11); if (unlikely(!__pyx_t_10)) goto __pyx_L18_unpacking_failed;
               __Pyx_GOTREF(__pyx_t_10);
-              if (__Pyx_IternextUnpackEndCheck(__pyx_t_12(__pyx_t_11), 2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
+              if (__Pyx_IternextUnpackEndCheck(__pyx_t_12(__pyx_t_11), 2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
-              goto __pyx_L20_unpacking_done;
-              __pyx_L19_unpacking_failed:;
+              goto __pyx_L19_unpacking_done;
+              __pyx_L18_unpacking_failed:;
               __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
               if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration)) PyErr_Clear();
               if (!PyErr_Occurred()) __Pyx_RaiseNeedMoreValuesError(index);
-              {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-              __pyx_L20_unpacking_done:;
+              {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_L19_unpacking_done:;
             }
             __Pyx_XDECREF(__pyx_v_fname);
-            __pyx_v_fname = __pyx_t_1;
-            __pyx_t_1 = 0;
+            __pyx_v_fname = __pyx_t_2;
+            __pyx_t_2 = 0;
             __Pyx_XDECREF(__pyx_v_value);
             __pyx_v_value = __pyx_t_10;
             __pyx_t_10 = 0;
 
-            /* "_cdec.pyx":70
+            /* "_cdec.pyx":56
  *             for line in fp:
  *                 fname, value = line.split()
  *                 self.weights[fname.strip()] = float(value)             # <<<<<<<<<<<<<<
  * 
  *     # TODO: list, lattice translation
  */
-            __pyx_t_13 = __Pyx_PyObject_AsDouble(__pyx_v_value); if (unlikely(__pyx_t_13 == ((double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __pyx_t_9 = PyFloat_FromDouble(__pyx_t_13); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __Pyx_GOTREF(__pyx_t_9);
-            __pyx_t_10 = PyObject_GetAttr(__pyx_v_fname, __pyx_n_s__strip); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
-            __Pyx_GOTREF(__pyx_t_10);
-            __pyx_t_1 = PyObject_Call(__pyx_t_10, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
+            __pyx_t_13 = __Pyx_PyObject_AsDouble(__pyx_v_value); if (unlikely(__pyx_t_13 == ((double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_1 = PyFloat_FromDouble(__pyx_t_13); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_1);
+            __pyx_t_10 = PyObject_GetAttr(__pyx_v_fname, __pyx_n_s__strip); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_10);
+            __pyx_t_2 = PyObject_Call(__pyx_t_10, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
             __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-            if (PyObject_SetItem(((PyObject *)((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->weights), __pyx_t_1, __pyx_t_9) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L9_error;}
+            if (PyObject_SetItem(((PyObject *)__pyx_v_self->weights), __pyx_t_2, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
             __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-            __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
           }
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
         }
-        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
         __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        goto __pyx_L16_try_end;
-        __pyx_L9_error:;
+        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+        goto __pyx_L14_try_end;
+        __pyx_L7_error:;
         __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
         __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
-        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
         __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-        /* "_cdec.pyx":67
+        /* "_cdec.pyx":53
  * 
  *     def read_weights(self, cfg):
  *         with open(cfg) as fp:             # <<<<<<<<<<<<<<
@@ -1827,75 +1596,75 @@ static PyObject *__pyx_pf_5_cdec_7Decoder_3read_weights(PyObject *__pyx_v_self,
  */
         /*except:*/ {
           __Pyx_AddTraceback("_cdec.Decoder.read_weights", __pyx_clineno, __pyx_lineno, __pyx_filename);
-          if (__Pyx_GetException(&__pyx_t_2, &__pyx_t_9, &__pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L11_except_error;}
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_GOTREF(__pyx_t_9);
+          if (__Pyx_GetException(&__pyx_t_4, &__pyx_t_1, &__pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          __Pyx_GOTREF(__pyx_t_4);
           __Pyx_GOTREF(__pyx_t_1);
-          __pyx_t_10 = PyTuple_New(3); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L11_except_error;}
-          __Pyx_GOTREF(((PyObject *)__pyx_t_10));
-          __Pyx_INCREF(__pyx_t_2);
-          PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_2);
-          __Pyx_GIVEREF(__pyx_t_2);
-          __Pyx_INCREF(__pyx_t_9);
-          PyTuple_SET_ITEM(__pyx_t_10, 1, __pyx_t_9);
-          __Pyx_GIVEREF(__pyx_t_9);
+          __Pyx_GOTREF(__pyx_t_2);
+          __pyx_t_10 = PyTuple_New(3); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          __Pyx_GOTREF(__pyx_t_10);
+          __Pyx_INCREF(__pyx_t_4);
+          PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_4);
+          __Pyx_GIVEREF(__pyx_t_4);
           __Pyx_INCREF(__pyx_t_1);
-          PyTuple_SET_ITEM(__pyx_t_10, 2, __pyx_t_1);
+          PyTuple_SET_ITEM(__pyx_t_10, 1, __pyx_t_1);
           __Pyx_GIVEREF(__pyx_t_1);
+          __Pyx_INCREF(__pyx_t_2);
+          PyTuple_SET_ITEM(__pyx_t_10, 2, __pyx_t_2);
+          __Pyx_GIVEREF(__pyx_t_2);
           __pyx_t_15 = PyObject_Call(__pyx_t_3, __pyx_t_10, NULL);
           __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-          if (unlikely(!__pyx_t_15)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L11_except_error;}
+          if (unlikely(!__pyx_t_15)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_15);
           __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_15);
           __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
-          if (unlikely(__pyx_t_14 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L11_except_error;}
+          if (unlikely(__pyx_t_14 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __pyx_t_16 = (!__pyx_t_14);
           if (__pyx_t_16) {
-            __Pyx_GIVEREF(__pyx_t_2);
-            __Pyx_GIVEREF(__pyx_t_9);
+            __Pyx_GIVEREF(__pyx_t_4);
             __Pyx_GIVEREF(__pyx_t_1);
-            __Pyx_ErrRestore(__pyx_t_2, __pyx_t_9, __pyx_t_1);
-            __pyx_t_2 = 0; __pyx_t_9 = 0; __pyx_t_1 = 0; 
-            {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L11_except_error;}
-            goto __pyx_L23;
+            __Pyx_GIVEREF(__pyx_t_2);
+            __Pyx_ErrRestore(__pyx_t_4, __pyx_t_1, __pyx_t_2);
+            __pyx_t_4 = 0; __pyx_t_1 = 0; __pyx_t_2 = 0; 
+            {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+            goto __pyx_L22;
           }
-          __pyx_L23:;
+          __pyx_L22:;
           __Pyx_DECREF(((PyObject *)__pyx_t_10)); __pyx_t_10 = 0;
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
+          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-          goto __pyx_L10_exception_handled;
+          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          goto __pyx_L8_exception_handled;
         }
-        __pyx_L11_except_error:;
-        __Pyx_XGIVEREF(__pyx_t_4);
+        __pyx_L9_except_error:;
         __Pyx_XGIVEREF(__pyx_t_5);
         __Pyx_XGIVEREF(__pyx_t_6);
-        __Pyx_ExceptionReset(__pyx_t_4, __pyx_t_5, __pyx_t_6);
+        __Pyx_XGIVEREF(__pyx_t_7);
+        __Pyx_ExceptionReset(__pyx_t_5, __pyx_t_6, __pyx_t_7);
         goto __pyx_L1_error;
-        __pyx_L10_exception_handled:;
-        __Pyx_XGIVEREF(__pyx_t_4);
+        __pyx_L8_exception_handled:;
         __Pyx_XGIVEREF(__pyx_t_5);
         __Pyx_XGIVEREF(__pyx_t_6);
-        __Pyx_ExceptionReset(__pyx_t_4, __pyx_t_5, __pyx_t_6);
-        __pyx_L16_try_end:;
+        __Pyx_XGIVEREF(__pyx_t_7);
+        __Pyx_ExceptionReset(__pyx_t_5, __pyx_t_6, __pyx_t_7);
+        __pyx_L14_try_end:;
       }
     }
     /*finally:*/ {
       if (__pyx_t_3) {
-        __pyx_t_6 = PyObject_Call(__pyx_t_3, __pyx_k_tuple_6, NULL);
+        __pyx_t_7 = PyObject_Call(__pyx_t_3, __pyx_k_tuple_1, NULL);
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __Pyx_GOTREF(__pyx_t_6);
-        __pyx_t_16 = __Pyx_PyObject_IsTrue(__pyx_t_6);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        if (unlikely(__pyx_t_16 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(__pyx_t_7);
+        __pyx_t_16 = __Pyx_PyObject_IsTrue(__pyx_t_7);
+        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+        if (unlikely(__pyx_t_16 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
     }
-    goto __pyx_L24;
-    __pyx_L5_error:;
+    goto __pyx_L23;
+    __pyx_L3_error:;
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     goto __pyx_L1_error;
-    __pyx_L24:;
+    __pyx_L23:;
   }
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
@@ -1903,7 +1672,7 @@ static PyObject *__pyx_pf_5_cdec_7Decoder_3read_weights(PyObject *__pyx_v_self,
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_9);
+  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_10);
   __Pyx_XDECREF(__pyx_t_11);
   __Pyx_AddTraceback("_cdec.Decoder.read_weights", __pyx_clineno, __pyx_lineno, __pyx_filename);
@@ -1918,45 +1687,37 @@ static PyObject *__pyx_pf_5_cdec_7Decoder_3read_weights(PyObject *__pyx_v_self,
   return __pyx_r;
 }
 
-/* "_cdec.pyx":73
+/* Python wrapper */
+static PyObject *__pyx_pw_5_cdec_7Decoder_7translate(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_5_cdec_7Decoder_7translate(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_sentence = 0;
+  PyObject *__pyx_v_grammar = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__sentence,&__pyx_n_s__grammar,0};
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("translate (wrapper)", 0);
+  {
+    PyObject* values[2] = {0,0};
+
+    /* "_cdec.pyx":59
  * 
  *     # TODO: list, lattice translation
  *     def translate(self, unicode sentence, grammar=None):             # <<<<<<<<<<<<<<
  *         if grammar:
  *             self.dec.SetSentenceGrammarFromString(string(<char *> grammar))
  */
-
-static PyObject *__pyx_pf_5_cdec_7Decoder_4translate(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyObject *__pyx_pf_5_cdec_7Decoder_4translate(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_sentence = 0;
-  PyObject *__pyx_v_grammar = 0;
-  PyObject *__pyx_v_sgml = NULL;
-  BasicObserver __pyx_v_observer;
-  struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_hg = 0;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
-  char *__pyx_t_2;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__sentence,&__pyx_n_s__grammar,0};
-  __Pyx_RefNannySetupContext("translate");
-  {
-    PyObject* values[2] = {0,0};
     values[1] = ((PyObject *)Py_None);
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
-      switch (PyTuple_GET_SIZE(__pyx_args)) {
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
         case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
         case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
         case  0: break;
         default: goto __pyx_L5_argtuple_error;
       }
       kw_args = PyDict_Size(__pyx_kwds);
-      switch (PyTuple_GET_SIZE(__pyx_args)) {
+      switch (pos_args) {
         case  0:
         values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__sentence);
         if (likely(values[0])) kw_args--;
@@ -1968,7 +1729,7 @@ static PyObject *__pyx_pf_5_cdec_7Decoder_4translate(PyObject *__pyx_v_self, PyO
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "translate") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "translate") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -1983,80 +1744,103 @@ static PyObject *__pyx_pf_5_cdec_7Decoder_4translate(PyObject *__pyx_v_self, PyO
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("translate", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("translate", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("_cdec.Decoder.translate", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sentence), (&PyUnicode_Type), 1, "sentence", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sentence), (&PyUnicode_Type), 1, "sentence", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5_cdec_7Decoder_6translate(((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self), __pyx_v_sentence, __pyx_v_grammar);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-  /* "_cdec.pyx":74
+static PyObject *__pyx_pf_5_cdec_7Decoder_6translate(struct __pyx_obj_5_cdec_Decoder *__pyx_v_self, PyObject *__pyx_v_sentence, PyObject *__pyx_v_grammar) {
+  PyObject *__pyx_v_inp = NULL;
+  BasicObserver __pyx_v_observer;
+  struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_hg = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  char *__pyx_t_2;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("translate", 0);
+
+  /* "_cdec.pyx":60
  *     # TODO: list, lattice translation
  *     def translate(self, unicode sentence, grammar=None):
  *         if grammar:             # <<<<<<<<<<<<<<
  *             self.dec.SetSentenceGrammarFromString(string(<char *> grammar))
- *         #sgml = '<seg grammar="%s">%s</seg>' % (grammar, sentence.encode('utf8'))
+ *         inp = sentence.strip().encode('utf8')
  */
-  __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_grammar); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_grammar); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__pyx_t_1) {
 
-    /* "_cdec.pyx":75
+    /* "_cdec.pyx":61
  *     def translate(self, unicode sentence, grammar=None):
  *         if grammar:
  *             self.dec.SetSentenceGrammarFromString(string(<char *> grammar))             # <<<<<<<<<<<<<<
- *         #sgml = '<seg grammar="%s">%s</seg>' % (grammar, sentence.encode('utf8'))
- *         sgml = sentence.strip().encode('utf8')
+ *         inp = sentence.strip().encode('utf8')
+ *         cdef decoder.BasicObserver observer = decoder.BasicObserver()
  */
-    __pyx_t_2 = PyBytes_AsString(__pyx_v_grammar); if (unlikely((!__pyx_t_2) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    ((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->dec->SetSentenceGrammarFromString(std::string(((char *)__pyx_t_2)));
-    goto __pyx_L6;
+    __pyx_t_2 = PyBytes_AsString(__pyx_v_grammar); if (unlikely((!__pyx_t_2) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_v_self->dec->SetSentenceGrammarFromString(std::string(((char *)__pyx_t_2)));
+    goto __pyx_L3;
   }
-  __pyx_L6:;
+  __pyx_L3:;
 
-  /* "_cdec.pyx":77
+  /* "_cdec.pyx":62
+ *         if grammar:
  *             self.dec.SetSentenceGrammarFromString(string(<char *> grammar))
- *         #sgml = '<seg grammar="%s">%s</seg>' % (grammar, sentence.encode('utf8'))
- *         sgml = sentence.strip().encode('utf8')             # <<<<<<<<<<<<<<
+ *         inp = sentence.strip().encode('utf8')             # <<<<<<<<<<<<<<
  *         cdef decoder.BasicObserver observer = decoder.BasicObserver()
- *         self.dec.Decode(string(<char *>sgml), &observer)
+ *         self.dec.Decode(string(<char *>inp), &observer)
  */
-  __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_sentence), __pyx_n_s__strip); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_sentence), __pyx_n_s__strip); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__encode); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__encode); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_k_tuple_7), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_k_tuple_2), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_v_sgml = __pyx_t_4;
+  __pyx_v_inp = __pyx_t_4;
   __pyx_t_4 = 0;
 
-  /* "_cdec.pyx":78
- *         #sgml = '<seg grammar="%s">%s</seg>' % (grammar, sentence.encode('utf8'))
- *         sgml = sentence.strip().encode('utf8')
+  /* "_cdec.pyx":63
+ *             self.dec.SetSentenceGrammarFromString(string(<char *> grammar))
+ *         inp = sentence.strip().encode('utf8')
  *         cdef decoder.BasicObserver observer = decoder.BasicObserver()             # <<<<<<<<<<<<<<
- *         self.dec.Decode(string(<char *>sgml), &observer)
+ *         self.dec.Decode(string(<char *>inp), &observer)
  *         if observer.hypergraph == NULL:
  */
   __pyx_v_observer = BasicObserver();
 
-  /* "_cdec.pyx":79
- *         sgml = sentence.strip().encode('utf8')
+  /* "_cdec.pyx":64
+ *         inp = sentence.strip().encode('utf8')
  *         cdef decoder.BasicObserver observer = decoder.BasicObserver()
- *         self.dec.Decode(string(<char *>sgml), &observer)             # <<<<<<<<<<<<<<
+ *         self.dec.Decode(string(<char *>inp), &observer)             # <<<<<<<<<<<<<<
  *         if observer.hypergraph == NULL:
  *             raise ParseFailed()
  */
-  __pyx_t_2 = PyBytes_AsString(__pyx_v_sgml); if (unlikely((!__pyx_t_2) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  ((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->dec->Decode(std::string(((char *)__pyx_t_2)), (&__pyx_v_observer));
+  __pyx_t_2 = PyBytes_AsString(__pyx_v_inp); if (unlikely((!__pyx_t_2) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_self->dec->Decode(std::string(((char *)__pyx_t_2)), (&__pyx_v_observer));
 
-  /* "_cdec.pyx":80
+  /* "_cdec.pyx":65
  *         cdef decoder.BasicObserver observer = decoder.BasicObserver()
- *         self.dec.Decode(string(<char *>sgml), &observer)
+ *         self.dec.Decode(string(<char *>inp), &observer)
  *         if observer.hypergraph == NULL:             # <<<<<<<<<<<<<<
  *             raise ParseFailed()
  *         cdef Hypergraph hg = Hypergraph()
@@ -2064,38 +1848,38 @@ static PyObject *__pyx_pf_5_cdec_7Decoder_4translate(PyObject *__pyx_v_self, PyO
   __pyx_t_1 = (__pyx_v_observer.hypergraph == NULL);
   if (__pyx_t_1) {
 
-    /* "_cdec.pyx":81
- *         self.dec.Decode(string(<char *>sgml), &observer)
+    /* "_cdec.pyx":66
+ *         self.dec.Decode(string(<char *>inp), &observer)
  *         if observer.hypergraph == NULL:
  *             raise ParseFailed()             # <<<<<<<<<<<<<<
  *         cdef Hypergraph hg = Hypergraph()
  *         hg.hg = new hypergraph.Hypergraph(observer.hypergraph[0])
  */
-    __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__ParseFailed); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 81; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__ParseFailed); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 81; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_Raise(__pyx_t_3, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 81; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L7;
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L4;
   }
-  __pyx_L7:;
+  __pyx_L4:;
 
-  /* "_cdec.pyx":82
+  /* "_cdec.pyx":67
  *         if observer.hypergraph == NULL:
  *             raise ParseFailed()
  *         cdef Hypergraph hg = Hypergraph()             # <<<<<<<<<<<<<<
  *         hg.hg = new hypergraph.Hypergraph(observer.hypergraph[0])
  *         return hg
  */
-  __pyx_t_3 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_5_cdec_Hypergraph)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_5_cdec_Hypergraph)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_v_hg = ((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_t_3);
   __pyx_t_3 = 0;
 
-  /* "_cdec.pyx":83
+  /* "_cdec.pyx":68
  *             raise ParseFailed()
  *         cdef Hypergraph hg = Hypergraph()
  *         hg.hg = new hypergraph.Hypergraph(observer.hypergraph[0])             # <<<<<<<<<<<<<<
@@ -2104,7 +1888,7 @@ static PyObject *__pyx_pf_5_cdec_7Decoder_4translate(PyObject *__pyx_v_self, PyO
  */
   __pyx_v_hg->hg = new Hypergraph((__pyx_v_observer.hypergraph[0]));
 
-  /* "_cdec.pyx":84
+  /* "_cdec.pyx":69
  *         cdef Hypergraph hg = Hypergraph()
  *         hg.hg = new hypergraph.Hypergraph(observer.hypergraph[0])
  *         return hg             # <<<<<<<<<<<<<<
@@ -2124,13 +1908,24 @@ static PyObject *__pyx_pf_5_cdec_7Decoder_4translate(PyObject *__pyx_v_self, PyO
   __Pyx_AddTraceback("_cdec.Decoder.translate", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_sgml);
+  __Pyx_XDECREF(__pyx_v_inp);
   __Pyx_XDECREF((PyObject *)__pyx_v_hg);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
+/* Python wrapper */
+static PyObject *__pyx_pw_5_cdec_7Decoder_7weights_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_5_cdec_7Decoder_7weights_1__get__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_5_cdec_7Decoder_7weights___get__(((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
 /* "_cdec.pyx":40
  * cdef class Decoder:
  *     cdef decoder.Decoder* dec
@@ -2139,14 +1934,13 @@ static PyObject *__pyx_pf_5_cdec_7Decoder_4translate(PyObject *__pyx_v_self, PyO
  *     def __cinit__(self, char* config):
  */
 
-static PyObject *__pyx_pf_5_cdec_7Decoder_7weights___get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pf_5_cdec_7Decoder_7weights___get__(PyObject *__pyx_v_self) {
+static PyObject *__pyx_pf_5_cdec_7Decoder_7weights___get__(struct __pyx_obj_5_cdec_Decoder *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__");
+  __Pyx_RefNannySetupContext("__get__", 0);
   __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(((PyObject *)((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->weights));
-  __pyx_r = ((PyObject *)((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->weights);
+  __Pyx_INCREF(((PyObject *)__pyx_v_self->weights));
+  __pyx_r = ((PyObject *)__pyx_v_self->weights);
   goto __pyx_L0;
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
@@ -2156,20 +1950,30 @@ static PyObject *__pyx_pf_5_cdec_7Decoder_7weights___get__(PyObject *__pyx_v_sel
   return __pyx_r;
 }
 
-static int __pyx_pf_5_cdec_7Decoder_7weights_1__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pf_5_cdec_7Decoder_7weights_1__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
+/* Python wrapper */
+static int __pyx_pw_5_cdec_7Decoder_7weights_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
+static int __pyx_pw_5_cdec_7Decoder_7weights_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_5_cdec_7Decoder_7weights_2__set__(((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_5_cdec_7Decoder_7weights_2__set__(struct __pyx_obj_5_cdec_Decoder *__pyx_v_self, PyObject *__pyx_v_value) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__set__");
+  __Pyx_RefNannySetupContext("__set__", 0);
   if (!(likely(((__pyx_v_value) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_value, __pyx_ptype_5_cdec_Weights))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_INCREF(__pyx_v_value);
   __Pyx_GIVEREF(__pyx_v_value);
-  __Pyx_GOTREF(((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->weights);
-  __Pyx_DECREF(((PyObject *)((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->weights));
-  ((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->weights = ((struct __pyx_obj_5_cdec_Weights *)__pyx_v_value);
+  __Pyx_GOTREF(__pyx_v_self->weights);
+  __Pyx_DECREF(((PyObject *)__pyx_v_self->weights));
+  __pyx_v_self->weights = ((struct __pyx_obj_5_cdec_Weights *)__pyx_v_value);
 
   __pyx_r = 0;
   goto __pyx_L0;
@@ -2181,23 +1985,42 @@ static int __pyx_pf_5_cdec_7Decoder_7weights_1__set__(PyObject *__pyx_v_self, Py
   return __pyx_r;
 }
 
-static int __pyx_pf_5_cdec_7Decoder_7weights_2__del__(PyObject *__pyx_v_self); /*proto*/
-static int __pyx_pf_5_cdec_7Decoder_7weights_2__del__(PyObject *__pyx_v_self) {
+/* Python wrapper */
+static int __pyx_pw_5_cdec_7Decoder_7weights_5__del__(PyObject *__pyx_v_self); /*proto*/
+static int __pyx_pw_5_cdec_7Decoder_7weights_5__del__(PyObject *__pyx_v_self) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__");
+  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_5_cdec_7Decoder_7weights_4__del__(((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_5_cdec_7Decoder_7weights_4__del__(struct __pyx_obj_5_cdec_Decoder *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__del__", 0);
   __Pyx_INCREF(Py_None);
   __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->weights);
-  __Pyx_DECREF(((PyObject *)((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->weights));
-  ((struct __pyx_obj_5_cdec_Decoder *)__pyx_v_self)->weights = ((struct __pyx_obj_5_cdec_Weights *)Py_None);
+  __Pyx_GOTREF(__pyx_v_self->weights);
+  __Pyx_DECREF(((PyObject *)__pyx_v_self->weights));
+  __pyx_v_self->weights = ((struct __pyx_obj_5_cdec_Weights *)Py_None);
 
   __pyx_r = 0;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "_cdec.pyx":90
+/* Python wrapper */
+static void __pyx_pw_5_cdec_10Hypergraph_1__dealloc__(PyObject *__pyx_v_self); /*proto*/
+static void __pyx_pw_5_cdec_10Hypergraph_1__dealloc__(PyObject *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
+  __pyx_pf_5_cdec_10Hypergraph___dealloc__(((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self));
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "_cdec.pyx":75
  *     cdef MT19937* rng
  * 
  *     def __dealloc__(self):             # <<<<<<<<<<<<<<
@@ -2205,47 +2028,57 @@ static int __pyx_pf_5_cdec_7Decoder_7weights_2__del__(PyObject *__pyx_v_self) {
  *         if self.rng != NULL:
  */
 
-static void __pyx_pf_5_cdec_10Hypergraph___dealloc__(PyObject *__pyx_v_self); /*proto*/
-static void __pyx_pf_5_cdec_10Hypergraph___dealloc__(PyObject *__pyx_v_self) {
+static void __pyx_pf_5_cdec_10Hypergraph___dealloc__(struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self) {
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
-  __Pyx_RefNannySetupContext("__dealloc__");
+  __Pyx_RefNannySetupContext("__dealloc__", 0);
 
-  /* "_cdec.pyx":91
+  /* "_cdec.pyx":76
  * 
  *     def __dealloc__(self):
  *         del self.hg             # <<<<<<<<<<<<<<
  *         if self.rng != NULL:
  *             del self.rng
  */
-  delete ((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self)->hg;
+  delete __pyx_v_self->hg;
 
-  /* "_cdec.pyx":92
+  /* "_cdec.pyx":77
  *     def __dealloc__(self):
  *         del self.hg
  *         if self.rng != NULL:             # <<<<<<<<<<<<<<
  *             del self.rng
  * 
  */
-  __pyx_t_1 = (((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self)->rng != NULL);
+  __pyx_t_1 = (__pyx_v_self->rng != NULL);
   if (__pyx_t_1) {
 
-    /* "_cdec.pyx":93
+    /* "_cdec.pyx":78
  *         del self.hg
  *         if self.rng != NULL:
  *             del self.rng             # <<<<<<<<<<<<<<
  * 
  *     def viterbi(self):
  */
-    delete ((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self)->rng;
-    goto __pyx_L5;
+    delete __pyx_v_self->rng;
+    goto __pyx_L3;
   }
-  __pyx_L5:;
+  __pyx_L3:;
 
   __Pyx_RefNannyFinishContext();
 }
 
-/* "_cdec.pyx":95
+/* Python wrapper */
+static PyObject *__pyx_pw_5_cdec_10Hypergraph_3viterbi(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_5_cdec_10Hypergraph_3viterbi(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("viterbi (wrapper)", 0);
+  __pyx_r = __pyx_pf_5_cdec_10Hypergraph_2viterbi(((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "_cdec.pyx":80
  *             del self.rng
  * 
  *     def viterbi(self):             # <<<<<<<<<<<<<<
@@ -2253,8 +2086,7 @@ static void __pyx_pf_5_cdec_10Hypergraph___dealloc__(PyObject *__pyx_v_self) {
  *         cdef vector[WordID] trans
  */
 
-static PyObject *__pyx_pf_5_cdec_10Hypergraph_1viterbi(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pf_5_cdec_10Hypergraph_1viterbi(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+static PyObject *__pyx_pf_5_cdec_10Hypergraph_2viterbi(struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self) {
   std::vector<WordID> __pyx_v_trans;
   PyObject *__pyx_v_sentence = 0;
   PyObject *__pyx_r = NULL;
@@ -2264,9 +2096,9 @@ static PyObject *__pyx_pf_5_cdec_10Hypergraph_1viterbi(PyObject *__pyx_v_self, C
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("viterbi");
+  __Pyx_RefNannySetupContext("viterbi", 0);
 
-  /* "_cdec.pyx":96
+  /* "_cdec.pyx":81
  * 
  *     def viterbi(self):
  *         assert (self.hg != NULL)             # <<<<<<<<<<<<<<
@@ -2274,35 +2106,35 @@ static PyObject *__pyx_pf_5_cdec_10Hypergraph_1viterbi(PyObject *__pyx_v_self, C
  *         hypergraph.ViterbiESentence(self.hg[0], &trans)
  */
   #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!(((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self)->hg != NULL))) {
+  if (unlikely(!(__pyx_v_self->hg != NULL))) {
     PyErr_SetNone(PyExc_AssertionError);
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 96; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 81; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   #endif
 
-  /* "_cdec.pyx":98
+  /* "_cdec.pyx":83
  *         assert (self.hg != NULL)
  *         cdef vector[WordID] trans
  *         hypergraph.ViterbiESentence(self.hg[0], &trans)             # <<<<<<<<<<<<<<
  *         cdef str sentence = GetString(trans).c_str()
  *         return sentence.decode('utf8')
  */
-  ViterbiESentence((((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self)->hg[0]), (&__pyx_v_trans));
+  ViterbiESentence((__pyx_v_self->hg[0]), (&__pyx_v_trans));
 
-  /* "_cdec.pyx":99
+  /* "_cdec.pyx":84
  *         cdef vector[WordID] trans
  *         hypergraph.ViterbiESentence(self.hg[0], &trans)
  *         cdef str sentence = GetString(trans).c_str()             # <<<<<<<<<<<<<<
  *         return sentence.decode('utf8')
  * 
  */
-  __pyx_t_1 = PyBytes_FromString(TD::GetString(__pyx_v_trans).c_str()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyBytes_FromString(TD::GetString(__pyx_v_trans).c_str()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  if (!(likely(PyString_CheckExact(((PyObject *)__pyx_t_1)))||(PyErr_Format(PyExc_TypeError, "Expected str, got %.200s", Py_TYPE(((PyObject *)__pyx_t_1))->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (!(likely(PyString_CheckExact(((PyObject *)__pyx_t_1)))||(PyErr_Format(PyExc_TypeError, "Expected str, got %.200s", Py_TYPE(((PyObject *)__pyx_t_1))->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_sentence = ((PyObject*)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "_cdec.pyx":100
+  /* "_cdec.pyx":85
  *         hypergraph.ViterbiESentence(self.hg[0], &trans)
  *         cdef str sentence = GetString(trans).c_str()
  *         return sentence.decode('utf8')             # <<<<<<<<<<<<<<
@@ -2310,9 +2142,9 @@ static PyObject *__pyx_pf_5_cdec_10Hypergraph_1viterbi(PyObject *__pyx_v_self, C
  *     def viterbi_tree(self):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_sentence), __pyx_n_s__decode); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_sentence), __pyx_n_s__decode); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_8), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __pyx_r = __pyx_t_2;
@@ -2333,7 +2165,18 @@ static PyObject *__pyx_pf_5_cdec_10Hypergraph_1viterbi(PyObject *__pyx_v_self, C
   return __pyx_r;
 }
 
-/* "_cdec.pyx":102
+/* Python wrapper */
+static PyObject *__pyx_pw_5_cdec_10Hypergraph_5viterbi_tree(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_5_cdec_10Hypergraph_5viterbi_tree(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("viterbi_tree (wrapper)", 0);
+  __pyx_r = __pyx_pf_5_cdec_10Hypergraph_4viterbi_tree(((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "_cdec.pyx":87
  *         return sentence.decode('utf8')
  * 
  *     def viterbi_tree(self):             # <<<<<<<<<<<<<<
@@ -2341,8 +2184,7 @@ static PyObject *__pyx_pf_5_cdec_10Hypergraph_1viterbi(PyObject *__pyx_v_self, C
  *         cdef str tree = hypergraph.ViterbiETree(self.hg[0]).c_str()
  */
 
-static PyObject *__pyx_pf_5_cdec_10Hypergraph_2viterbi_tree(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pf_5_cdec_10Hypergraph_2viterbi_tree(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+static PyObject *__pyx_pf_5_cdec_10Hypergraph_4viterbi_tree(struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self) {
   PyObject *__pyx_v_tree = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
@@ -2351,9 +2193,9 @@ static PyObject *__pyx_pf_5_cdec_10Hypergraph_2viterbi_tree(PyObject *__pyx_v_se
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("viterbi_tree");
+  __Pyx_RefNannySetupContext("viterbi_tree", 0);
 
-  /* "_cdec.pyx":103
+  /* "_cdec.pyx":88
  * 
  *     def viterbi_tree(self):
  *         assert (self.hg != NULL)             # <<<<<<<<<<<<<<
@@ -2361,26 +2203,26 @@ static PyObject *__pyx_pf_5_cdec_10Hypergraph_2viterbi_tree(PyObject *__pyx_v_se
  *         return tree.decode('utf8')
  */
   #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!(((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self)->hg != NULL))) {
+  if (unlikely(!(__pyx_v_self->hg != NULL))) {
     PyErr_SetNone(PyExc_AssertionError);
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   #endif
 
-  /* "_cdec.pyx":104
+  /* "_cdec.pyx":89
  *     def viterbi_tree(self):
  *         assert (self.hg != NULL)
  *         cdef str tree = hypergraph.ViterbiETree(self.hg[0]).c_str()             # <<<<<<<<<<<<<<
  *         return tree.decode('utf8')
  * 
  */
-  __pyx_t_1 = PyBytes_FromString(ViterbiETree((((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self)->hg[0])).c_str()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyBytes_FromString(ViterbiETree((__pyx_v_self->hg[0])).c_str()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  if (!(likely(PyString_CheckExact(((PyObject *)__pyx_t_1)))||(PyErr_Format(PyExc_TypeError, "Expected str, got %.200s", Py_TYPE(((PyObject *)__pyx_t_1))->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (!(likely(PyString_CheckExact(((PyObject *)__pyx_t_1)))||(PyErr_Format(PyExc_TypeError, "Expected str, got %.200s", Py_TYPE(((PyObject *)__pyx_t_1))->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_tree = ((PyObject*)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "_cdec.pyx":105
+  /* "_cdec.pyx":90
  *         assert (self.hg != NULL)
  *         cdef str tree = hypergraph.ViterbiETree(self.hg[0]).c_str()
  *         return tree.decode('utf8')             # <<<<<<<<<<<<<<
@@ -2388,9 +2230,9 @@ static PyObject *__pyx_pf_5_cdec_10Hypergraph_2viterbi_tree(PyObject *__pyx_v_se
  *     def kbest(self, size):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_tree), __pyx_n_s__decode); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_tree), __pyx_n_s__decode); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_9), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_4), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __pyx_r = __pyx_t_2;
@@ -2410,9 +2252,20 @@ static PyObject *__pyx_pf_5_cdec_10Hypergraph_2viterbi_tree(PyObject *__pyx_v_se
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
-static PyObject *__pyx_gb_5_cdec_10Hypergraph_4generator1(struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest *__pyx_cur_scope, PyObject *__pyx_sent_value); /* proto */
+static PyObject *__pyx_gb_5_cdec_10Hypergraph_8generator1(__pyx_GeneratorObject *__pyx_generator, PyObject *__pyx_sent_value); /* proto */
 
-/* "_cdec.pyx":107
+/* Python wrapper */
+static PyObject *__pyx_pw_5_cdec_10Hypergraph_7kbest(PyObject *__pyx_v_self, PyObject *__pyx_v_size); /*proto*/
+static PyObject *__pyx_pw_5_cdec_10Hypergraph_7kbest(PyObject *__pyx_v_self, PyObject *__pyx_v_size) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("kbest (wrapper)", 0);
+  __pyx_r = __pyx_pf_5_cdec_10Hypergraph_6kbest(((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self), ((PyObject *)__pyx_v_size));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "_cdec.pyx":92
  *         return tree.decode('utf8')
  * 
  *     def kbest(self, size):             # <<<<<<<<<<<<<<
@@ -2420,39 +2273,48 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_4generator1(struct __pyx_obj_5_cde
  *         cdef kb.KBestDerivations[vector[WordID], kb.ESentenceTraversal]* derivations = new kb.KBestDerivations[vector[WordID], kb.ESentenceTraversal](self.hg[0], size)
  */
 
-static PyObject *__pyx_pf_5_cdec_10Hypergraph_3kbest(PyObject *__pyx_v_self, PyObject *__pyx_v_size); /*proto*/
-static PyObject *__pyx_pf_5_cdec_10Hypergraph_3kbest(PyObject *__pyx_v_self, PyObject *__pyx_v_size) {
+static PyObject *__pyx_pf_5_cdec_10Hypergraph_6kbest(struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self, PyObject *__pyx_v_size) {
   struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest *__pyx_cur_scope;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("kbest");
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("kbest", 0);
   __pyx_cur_scope = (struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest *)__pyx_ptype_5_cdec___pyx_scope_struct_1_kbest->tp_new(__pyx_ptype_5_cdec___pyx_scope_struct_1_kbest, __pyx_empty_tuple, NULL);
   if (unlikely(!__pyx_cur_scope)) {
     __Pyx_RefNannyFinishContext();
     return NULL;
   }
   __Pyx_GOTREF(__pyx_cur_scope);
-  __Pyx_INCREF(__pyx_v_self);
   __pyx_cur_scope->__pyx_v_self = __pyx_v_self;
-  __Pyx_INCREF(__pyx_v_size);
-  __pyx_cur_scope->__pyx_v_size = __pyx_v_size;
+  __Pyx_INCREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
   __Pyx_GIVEREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
+  __pyx_cur_scope->__pyx_v_size = __pyx_v_size;
+  __Pyx_INCREF(__pyx_cur_scope->__pyx_v_size);
   __Pyx_GIVEREF(__pyx_cur_scope->__pyx_v_size);
-  __pyx_cur_scope->__pyx_base.resume_label = 0;
-  __pyx_cur_scope->__pyx_base.body = (__pyx_generator_body_t) __pyx_gb_5_cdec_10Hypergraph_4generator1;
-  __Pyx_GIVEREF(__pyx_cur_scope);
-  __Pyx_RefNannyFinishContext();
-  return (PyObject *) __pyx_cur_scope;
+  {
+    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_5_cdec_10Hypergraph_8generator1, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_cur_scope);
+    __Pyx_RefNannyFinishContext();
+    return (PyObject *) gen;
+  }
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("_cdec.Hypergraph.kbest", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_DECREF(((PyObject *)__pyx_cur_scope));
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_gb_5_cdec_10Hypergraph_4generator1(struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest *__pyx_cur_scope, PyObject *__pyx_sent_value) /* generator body */
+static PyObject *__pyx_gb_5_cdec_10Hypergraph_8generator1(__pyx_GeneratorObject *__pyx_generator, PyObject *__pyx_sent_value) /* generator body */
 {
+  struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest *__pyx_cur_scope = ((struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest *)__pyx_generator->closure);
   PyObject *__pyx_r = NULL;
   unsigned int __pyx_t_1;
   long __pyx_t_2;
@@ -2460,8 +2322,8 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_4generator1(struct __pyx_obj_5_cde
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("None");
-  switch (__pyx_cur_scope->__pyx_base.resume_label) {
+  __Pyx_RefNannySetupContext("None", 0);
+  switch (__pyx_generator->resume_label) {
     case 0: goto __pyx_L3_first_run;
     case 1: goto __pyx_L7_resume_from_yield;
     default: /* CPython raises the right error here */
@@ -2469,9 +2331,9 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_4generator1(struct __pyx_obj_5_cde
     return NULL;
   }
   __pyx_L3_first_run:;
-  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "_cdec.pyx":108
+  /* "_cdec.pyx":93
  * 
  *     def kbest(self, size):
  *         assert (self.hg != NULL)             # <<<<<<<<<<<<<<
@@ -2479,43 +2341,43 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_4generator1(struct __pyx_obj_5_cde
  *         cdef kb.KBestDerivations[vector[WordID], kb.ESentenceTraversal].Derivation* derivation
  */
   #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!(((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_cur_scope->__pyx_v_self)->hg != NULL))) {
+  if (unlikely(!(__pyx_cur_scope->__pyx_v_self->hg != NULL))) {
     PyErr_SetNone(PyExc_AssertionError);
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   #endif
 
-  /* "_cdec.pyx":109
+  /* "_cdec.pyx":94
  *     def kbest(self, size):
  *         assert (self.hg != NULL)
  *         cdef kb.KBestDerivations[vector[WordID], kb.ESentenceTraversal]* derivations = new kb.KBestDerivations[vector[WordID], kb.ESentenceTraversal](self.hg[0], size)             # <<<<<<<<<<<<<<
  *         cdef kb.KBestDerivations[vector[WordID], kb.ESentenceTraversal].Derivation* derivation
  *         cdef str tree
  */
-  __pyx_t_1 = __Pyx_PyInt_AsUnsignedInt(__pyx_cur_scope->__pyx_v_size); if (unlikely((__pyx_t_1 == (unsigned int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_cur_scope->__pyx_v_derivations = new KBest::KBestDerivations<std::vector<WordID>,ESentenceTraversal>((((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_cur_scope->__pyx_v_self)->hg[0]), __pyx_t_1);
+  __pyx_t_1 = __Pyx_PyInt_AsUnsignedInt(__pyx_cur_scope->__pyx_v_size); if (unlikely((__pyx_t_1 == (unsigned int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_cur_scope->__pyx_v_derivations = new KBest::KBestDerivations<std::vector<WordID>,ESentenceTraversal>((__pyx_cur_scope->__pyx_v_self->hg[0]), __pyx_t_1);
 
-  /* "_cdec.pyx":113
+  /* "_cdec.pyx":98
  *         cdef str tree
  *         cdef unsigned k
  *         for k in range(size):             # <<<<<<<<<<<<<<
  *             derivation = derivations.LazyKthBest(self.hg.nodes_.size() - 1, k)
  *             if not derivation: break
  */
-  __pyx_t_2 = __Pyx_PyInt_AsLong(__pyx_cur_scope->__pyx_v_size); if (unlikely((__pyx_t_2 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyInt_AsLong(__pyx_cur_scope->__pyx_v_size); if (unlikely((__pyx_t_2 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   for (__pyx_t_1 = 0; __pyx_t_1 < __pyx_t_2; __pyx_t_1+=1) {
     __pyx_cur_scope->__pyx_v_k = __pyx_t_1;
 
-    /* "_cdec.pyx":114
+    /* "_cdec.pyx":99
  *         cdef unsigned k
  *         for k in range(size):
  *             derivation = derivations.LazyKthBest(self.hg.nodes_.size() - 1, k)             # <<<<<<<<<<<<<<
  *             if not derivation: break
  *             tree = GetString(derivation._yield).c_str()
  */
-    __pyx_cur_scope->__pyx_v_derivation = __pyx_cur_scope->__pyx_v_derivations->LazyKthBest((((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_cur_scope->__pyx_v_self)->hg->nodes_.size() - 1), __pyx_cur_scope->__pyx_v_k);
+    __pyx_cur_scope->__pyx_v_derivation = __pyx_cur_scope->__pyx_v_derivations->LazyKthBest((__pyx_cur_scope->__pyx_v_self->hg->nodes_.size() - 1), __pyx_cur_scope->__pyx_v_k);
 
-    /* "_cdec.pyx":115
+    /* "_cdec.pyx":100
  *         for k in range(size):
  *             derivation = derivations.LazyKthBest(self.hg.nodes_.size() - 1, k)
  *             if not derivation: break             # <<<<<<<<<<<<<<
@@ -2529,32 +2391,32 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_4generator1(struct __pyx_obj_5_cde
     }
     __pyx_L6:;
 
-    /* "_cdec.pyx":116
+    /* "_cdec.pyx":101
  *             derivation = derivations.LazyKthBest(self.hg.nodes_.size() - 1, k)
  *             if not derivation: break
  *             tree = GetString(derivation._yield).c_str()             # <<<<<<<<<<<<<<
  *             yield tree.decode('utf8')
  *         del derivations
  */
-    __pyx_t_4 = PyBytes_FromString(TD::GetString(__pyx_cur_scope->__pyx_v_derivation->yield).c_str()); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyBytes_FromString(TD::GetString(__pyx_cur_scope->__pyx_v_derivation->yield).c_str()); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_4));
-    if (!(likely(PyString_CheckExact(((PyObject *)__pyx_t_4)))||(PyErr_Format(PyExc_TypeError, "Expected str, got %.200s", Py_TYPE(((PyObject *)__pyx_t_4))->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(PyString_CheckExact(((PyObject *)__pyx_t_4)))||(PyErr_Format(PyExc_TypeError, "Expected str, got %.200s", Py_TYPE(((PyObject *)__pyx_t_4))->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XGOTREF(((PyObject *)__pyx_cur_scope->__pyx_v_tree));
     __Pyx_XDECREF(((PyObject *)__pyx_cur_scope->__pyx_v_tree));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_4));
     __pyx_cur_scope->__pyx_v_tree = ((PyObject*)__pyx_t_4);
     __pyx_t_4 = 0;
 
-    /* "_cdec.pyx":117
+    /* "_cdec.pyx":102
  *             if not derivation: break
  *             tree = GetString(derivation._yield).c_str()
  *             yield tree.decode('utf8')             # <<<<<<<<<<<<<<
  *         del derivations
  * 
  */
-    __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_cur_scope->__pyx_v_tree), __pyx_n_s__decode); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 117; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_cur_scope->__pyx_v_tree), __pyx_n_s__decode); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_10), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 117; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_5), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __pyx_r = __pyx_t_5;
@@ -2564,16 +2426,16 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_4generator1(struct __pyx_obj_5_cde
     __Pyx_XGIVEREF(__pyx_r);
     __Pyx_RefNannyFinishContext();
     /* return from generator, yielding value */
-    __pyx_cur_scope->__pyx_base.resume_label = 1;
+    __pyx_generator->resume_label = 1;
     return __pyx_r;
     __pyx_L7_resume_from_yield:;
     __pyx_t_1 = __pyx_cur_scope->__pyx_t_0;
     __pyx_t_2 = __pyx_cur_scope->__pyx_t_1;
-    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 117; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_L5_break:;
 
-  /* "_cdec.pyx":118
+  /* "_cdec.pyx":103
  *             tree = GetString(derivation._yield).c_str()
  *             yield tree.decode('utf8')
  *         del derivations             # <<<<<<<<<<<<<<
@@ -2581,7 +2443,7 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_4generator1(struct __pyx_obj_5_cde
  *     def kbest_tree(self, size):
  */
   delete __pyx_cur_scope->__pyx_v_derivations;
-  PyErr_SetNone(PyExc_StopIteration); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  PyErr_SetNone(PyExc_StopIteration);
   goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_4);
@@ -2589,13 +2451,24 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_4generator1(struct __pyx_obj_5_cde
   __Pyx_AddTraceback("kbest", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_cur_scope->__pyx_base.resume_label = -1;
+  __pyx_generator->resume_label = -1;
   __Pyx_RefNannyFinishContext();
   return NULL;
 }
-static PyObject *__pyx_gb_5_cdec_10Hypergraph_6generator2(struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree *__pyx_cur_scope, PyObject *__pyx_sent_value); /* proto */
+static PyObject *__pyx_gb_5_cdec_10Hypergraph_11generator2(__pyx_GeneratorObject *__pyx_generator, PyObject *__pyx_sent_value); /* proto */
 
-/* "_cdec.pyx":120
+/* Python wrapper */
+static PyObject *__pyx_pw_5_cdec_10Hypergraph_10kbest_tree(PyObject *__pyx_v_self, PyObject *__pyx_v_size); /*proto*/
+static PyObject *__pyx_pw_5_cdec_10Hypergraph_10kbest_tree(PyObject *__pyx_v_self, PyObject *__pyx_v_size) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("kbest_tree (wrapper)", 0);
+  __pyx_r = __pyx_pf_5_cdec_10Hypergraph_9kbest_tree(((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self), ((PyObject *)__pyx_v_size));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "_cdec.pyx":105
  *         del derivations
  * 
  *     def kbest_tree(self, size):             # <<<<<<<<<<<<<<
@@ -2603,39 +2476,48 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_6generator2(struct __pyx_obj_5_cde
  *         cdef kb.KBestDerivations[vector[WordID], kb.ETreeTraversal]* derivations = new kb.KBestDerivations[vector[WordID], kb.ETreeTraversal](self.hg[0], size)
  */
 
-static PyObject *__pyx_pf_5_cdec_10Hypergraph_5kbest_tree(PyObject *__pyx_v_self, PyObject *__pyx_v_size); /*proto*/
-static PyObject *__pyx_pf_5_cdec_10Hypergraph_5kbest_tree(PyObject *__pyx_v_self, PyObject *__pyx_v_size) {
+static PyObject *__pyx_pf_5_cdec_10Hypergraph_9kbest_tree(struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self, PyObject *__pyx_v_size) {
   struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree *__pyx_cur_scope;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("kbest_tree");
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("kbest_tree", 0);
   __pyx_cur_scope = (struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree *)__pyx_ptype_5_cdec___pyx_scope_struct_2_kbest_tree->tp_new(__pyx_ptype_5_cdec___pyx_scope_struct_2_kbest_tree, __pyx_empty_tuple, NULL);
   if (unlikely(!__pyx_cur_scope)) {
     __Pyx_RefNannyFinishContext();
     return NULL;
   }
   __Pyx_GOTREF(__pyx_cur_scope);
-  __Pyx_INCREF(__pyx_v_self);
   __pyx_cur_scope->__pyx_v_self = __pyx_v_self;
-  __Pyx_INCREF(__pyx_v_size);
-  __pyx_cur_scope->__pyx_v_size = __pyx_v_size;
+  __Pyx_INCREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
   __Pyx_GIVEREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
+  __pyx_cur_scope->__pyx_v_size = __pyx_v_size;
+  __Pyx_INCREF(__pyx_cur_scope->__pyx_v_size);
   __Pyx_GIVEREF(__pyx_cur_scope->__pyx_v_size);
-  __pyx_cur_scope->__pyx_base.resume_label = 0;
-  __pyx_cur_scope->__pyx_base.body = (__pyx_generator_body_t) __pyx_gb_5_cdec_10Hypergraph_6generator2;
-  __Pyx_GIVEREF(__pyx_cur_scope);
-  __Pyx_RefNannyFinishContext();
-  return (PyObject *) __pyx_cur_scope;
+  {
+    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_5_cdec_10Hypergraph_11generator2, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_cur_scope);
+    __Pyx_RefNannyFinishContext();
+    return (PyObject *) gen;
+  }
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("_cdec.Hypergraph.kbest_tree", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_DECREF(((PyObject *)__pyx_cur_scope));
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_gb_5_cdec_10Hypergraph_6generator2(struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree *__pyx_cur_scope, PyObject *__pyx_sent_value) /* generator body */
+static PyObject *__pyx_gb_5_cdec_10Hypergraph_11generator2(__pyx_GeneratorObject *__pyx_generator, PyObject *__pyx_sent_value) /* generator body */
 {
+  struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree *__pyx_cur_scope = ((struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree *)__pyx_generator->closure);
   PyObject *__pyx_r = NULL;
   unsigned int __pyx_t_1;
   long __pyx_t_2;
@@ -2643,8 +2525,8 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_6generator2(struct __pyx_obj_5_cde
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("None");
-  switch (__pyx_cur_scope->__pyx_base.resume_label) {
+  __Pyx_RefNannySetupContext("None", 0);
+  switch (__pyx_generator->resume_label) {
     case 0: goto __pyx_L3_first_run;
     case 1: goto __pyx_L7_resume_from_yield;
     default: /* CPython raises the right error here */
@@ -2652,9 +2534,9 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_6generator2(struct __pyx_obj_5_cde
     return NULL;
   }
   __pyx_L3_first_run:;
-  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "_cdec.pyx":121
+  /* "_cdec.pyx":106
  * 
  *     def kbest_tree(self, size):
  *         assert (self.hg != NULL)             # <<<<<<<<<<<<<<
@@ -2662,43 +2544,43 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_6generator2(struct __pyx_obj_5_cde
  *         cdef kb.KBestDerivations[vector[WordID], kb.ETreeTraversal].Derivation* derivation
  */
   #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!(((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_cur_scope->__pyx_v_self)->hg != NULL))) {
+  if (unlikely(!(__pyx_cur_scope->__pyx_v_self->hg != NULL))) {
     PyErr_SetNone(PyExc_AssertionError);
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 121; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   #endif
 
-  /* "_cdec.pyx":122
+  /* "_cdec.pyx":107
  *     def kbest_tree(self, size):
  *         assert (self.hg != NULL)
  *         cdef kb.KBestDerivations[vector[WordID], kb.ETreeTraversal]* derivations = new kb.KBestDerivations[vector[WordID], kb.ETreeTraversal](self.hg[0], size)             # <<<<<<<<<<<<<<
  *         cdef kb.KBestDerivations[vector[WordID], kb.ETreeTraversal].Derivation* derivation
  *         cdef str sentence
  */
-  __pyx_t_1 = __Pyx_PyInt_AsUnsignedInt(__pyx_cur_scope->__pyx_v_size); if (unlikely((__pyx_t_1 == (unsigned int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_cur_scope->__pyx_v_derivations = new KBest::KBestDerivations<std::vector<WordID>,ETreeTraversal>((((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_cur_scope->__pyx_v_self)->hg[0]), __pyx_t_1);
+  __pyx_t_1 = __Pyx_PyInt_AsUnsignedInt(__pyx_cur_scope->__pyx_v_size); if (unlikely((__pyx_t_1 == (unsigned int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_cur_scope->__pyx_v_derivations = new KBest::KBestDerivations<std::vector<WordID>,ETreeTraversal>((__pyx_cur_scope->__pyx_v_self->hg[0]), __pyx_t_1);
 
-  /* "_cdec.pyx":126
+  /* "_cdec.pyx":111
  *         cdef str sentence
  *         cdef unsigned k
  *         for k in range(size):             # <<<<<<<<<<<<<<
  *             derivation = derivations.LazyKthBest(self.hg.nodes_.size() - 1, k)
  *             if not derivation: break
  */
-  __pyx_t_2 = __Pyx_PyInt_AsLong(__pyx_cur_scope->__pyx_v_size); if (unlikely((__pyx_t_2 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyInt_AsLong(__pyx_cur_scope->__pyx_v_size); if (unlikely((__pyx_t_2 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   for (__pyx_t_1 = 0; __pyx_t_1 < __pyx_t_2; __pyx_t_1+=1) {
     __pyx_cur_scope->__pyx_v_k = __pyx_t_1;
 
-    /* "_cdec.pyx":127
+    /* "_cdec.pyx":112
  *         cdef unsigned k
  *         for k in range(size):
  *             derivation = derivations.LazyKthBest(self.hg.nodes_.size() - 1, k)             # <<<<<<<<<<<<<<
  *             if not derivation: break
  *             sentence = GetString(derivation._yield).c_str()
  */
-    __pyx_cur_scope->__pyx_v_derivation = __pyx_cur_scope->__pyx_v_derivations->LazyKthBest((((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_cur_scope->__pyx_v_self)->hg->nodes_.size() - 1), __pyx_cur_scope->__pyx_v_k);
+    __pyx_cur_scope->__pyx_v_derivation = __pyx_cur_scope->__pyx_v_derivations->LazyKthBest((__pyx_cur_scope->__pyx_v_self->hg->nodes_.size() - 1), __pyx_cur_scope->__pyx_v_k);
 
-    /* "_cdec.pyx":128
+    /* "_cdec.pyx":113
  *         for k in range(size):
  *             derivation = derivations.LazyKthBest(self.hg.nodes_.size() - 1, k)
  *             if not derivation: break             # <<<<<<<<<<<<<<
@@ -2712,32 +2594,32 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_6generator2(struct __pyx_obj_5_cde
     }
     __pyx_L6:;
 
-    /* "_cdec.pyx":129
+    /* "_cdec.pyx":114
  *             derivation = derivations.LazyKthBest(self.hg.nodes_.size() - 1, k)
  *             if not derivation: break
  *             sentence = GetString(derivation._yield).c_str()             # <<<<<<<<<<<<<<
  *             yield sentence.decode('utf8')
  *         del derivations
  */
-    __pyx_t_4 = PyBytes_FromString(TD::GetString(__pyx_cur_scope->__pyx_v_derivation->yield).c_str()); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyBytes_FromString(TD::GetString(__pyx_cur_scope->__pyx_v_derivation->yield).c_str()); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_4));
-    if (!(likely(PyString_CheckExact(((PyObject *)__pyx_t_4)))||(PyErr_Format(PyExc_TypeError, "Expected str, got %.200s", Py_TYPE(((PyObject *)__pyx_t_4))->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(PyString_CheckExact(((PyObject *)__pyx_t_4)))||(PyErr_Format(PyExc_TypeError, "Expected str, got %.200s", Py_TYPE(((PyObject *)__pyx_t_4))->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XGOTREF(((PyObject *)__pyx_cur_scope->__pyx_v_sentence));
     __Pyx_XDECREF(((PyObject *)__pyx_cur_scope->__pyx_v_sentence));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_4));
     __pyx_cur_scope->__pyx_v_sentence = ((PyObject*)__pyx_t_4);
     __pyx_t_4 = 0;
 
-    /* "_cdec.pyx":130
+    /* "_cdec.pyx":115
  *             if not derivation: break
  *             sentence = GetString(derivation._yield).c_str()
  *             yield sentence.decode('utf8')             # <<<<<<<<<<<<<<
  *         del derivations
  * 
  */
-    __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_cur_scope->__pyx_v_sentence), __pyx_n_s__decode); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_cur_scope->__pyx_v_sentence), __pyx_n_s__decode); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_11), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_6), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __pyx_r = __pyx_t_5;
@@ -2747,16 +2629,16 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_6generator2(struct __pyx_obj_5_cde
     __Pyx_XGIVEREF(__pyx_r);
     __Pyx_RefNannyFinishContext();
     /* return from generator, yielding value */
-    __pyx_cur_scope->__pyx_base.resume_label = 1;
+    __pyx_generator->resume_label = 1;
     return __pyx_r;
     __pyx_L7_resume_from_yield:;
     __pyx_t_1 = __pyx_cur_scope->__pyx_t_0;
     __pyx_t_2 = __pyx_cur_scope->__pyx_t_1;
-    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_L5_break:;
 
-  /* "_cdec.pyx":131
+  /* "_cdec.pyx":116
  *             sentence = GetString(derivation._yield).c_str()
  *             yield sentence.decode('utf8')
  *         del derivations             # <<<<<<<<<<<<<<
@@ -2764,7 +2646,7 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_6generator2(struct __pyx_obj_5_cde
  *     def intersect(self, Lattice lat):
  */
   delete __pyx_cur_scope->__pyx_v_derivations;
-  PyErr_SetNone(PyExc_StopIteration); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  PyErr_SetNone(PyExc_StopIteration);
   goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_4);
@@ -2772,12 +2654,28 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_6generator2(struct __pyx_obj_5_cde
   __Pyx_AddTraceback("kbest_tree", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_cur_scope->__pyx_base.resume_label = -1;
+  __pyx_generator->resume_label = -1;
   __Pyx_RefNannyFinishContext();
   return NULL;
 }
 
-/* "_cdec.pyx":133
+/* Python wrapper */
+static PyObject *__pyx_pw_5_cdec_10Hypergraph_13intersect(PyObject *__pyx_v_self, PyObject *__pyx_v_lat); /*proto*/
+static PyObject *__pyx_pw_5_cdec_10Hypergraph_13intersect(PyObject *__pyx_v_self, PyObject *__pyx_v_lat) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("intersect (wrapper)", 0);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lat), __pyx_ptype_5_cdec_Lattice, 1, "lat", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 118; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5_cdec_10Hypergraph_12intersect(((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self), ((struct __pyx_obj_5_cdec_Lattice *)__pyx_v_lat));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "_cdec.pyx":118
  *         del derivations
  * 
  *     def intersect(self, Lattice lat):             # <<<<<<<<<<<<<<
@@ -2785,17 +2683,15 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_6generator2(struct __pyx_obj_5_cde
  *         hypergraph.Intersect(lat.lattice[0], self.hg)
  */
 
-static PyObject *__pyx_pf_5_cdec_10Hypergraph_7intersect(PyObject *__pyx_v_self, PyObject *__pyx_v_lat); /*proto*/
-static PyObject *__pyx_pf_5_cdec_10Hypergraph_7intersect(PyObject *__pyx_v_self, PyObject *__pyx_v_lat) {
+static PyObject *__pyx_pf_5_cdec_10Hypergraph_12intersect(struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self, struct __pyx_obj_5_cdec_Lattice *__pyx_v_lat) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("intersect");
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lat), __pyx_ptype_5_cdec_Lattice, 1, "lat", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 133; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_RefNannySetupContext("intersect", 0);
 
-  /* "_cdec.pyx":134
+  /* "_cdec.pyx":119
  * 
  *     def intersect(self, Lattice lat):
  *         assert (self.hg != NULL)             # <<<<<<<<<<<<<<
@@ -2803,20 +2699,20 @@ static PyObject *__pyx_pf_5_cdec_10Hypergraph_7intersect(PyObject *__pyx_v_self,
  * 
  */
   #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!(((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self)->hg != NULL))) {
+  if (unlikely(!(__pyx_v_self->hg != NULL))) {
     PyErr_SetNone(PyExc_AssertionError);
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   #endif
 
-  /* "_cdec.pyx":135
+  /* "_cdec.pyx":120
  *     def intersect(self, Lattice lat):
  *         assert (self.hg != NULL)
  *         hypergraph.Intersect(lat.lattice[0], self.hg)             # <<<<<<<<<<<<<<
  * 
  *     def sample(self, unsigned n):
  */
-  HG::Intersect((((struct __pyx_obj_5_cdec_Lattice *)__pyx_v_lat)->lattice[0]), ((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self)->hg);
+  HG::Intersect((__pyx_v_lat->lattice[0]), __pyx_v_self->hg);
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
@@ -2828,9 +2724,30 @@ static PyObject *__pyx_pf_5_cdec_10Hypergraph_7intersect(PyObject *__pyx_v_self,
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
-static PyObject *__pyx_gb_5_cdec_10Hypergraph_9generator3(struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample *__pyx_cur_scope, PyObject *__pyx_sent_value); /* proto */
+static PyObject *__pyx_gb_5_cdec_10Hypergraph_16generator3(__pyx_GeneratorObject *__pyx_generator, PyObject *__pyx_sent_value); /* proto */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_5_cdec_10Hypergraph_15sample(PyObject *__pyx_v_self, PyObject *__pyx_arg_n); /*proto*/
+static PyObject *__pyx_pw_5_cdec_10Hypergraph_15sample(PyObject *__pyx_v_self, PyObject *__pyx_arg_n) {
+  unsigned int __pyx_v_n;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("sample (wrapper)", 0);
+  assert(__pyx_arg_n); {
+    __pyx_v_n = __Pyx_PyInt_AsUnsignedInt(__pyx_arg_n); if (unlikely((__pyx_v_n == (unsigned int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("_cdec.Hypergraph.sample", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_5_cdec_10Hypergraph_14sample(((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_v_self), ((unsigned int)__pyx_v_n));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-/* "_cdec.pyx":137
+/* "_cdec.pyx":122
  *         hypergraph.Intersect(lat.lattice[0], self.hg)
  * 
  *     def sample(self, unsigned n):             # <<<<<<<<<<<<<<
@@ -2838,50 +2755,46 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_9generator3(struct __pyx_obj_5_cde
  *         cdef vector[hypergraph.Hypothesis]* hypos = new vector[hypergraph.Hypothesis]()
  */
 
-static PyObject *__pyx_pf_5_cdec_10Hypergraph_8sample(PyObject *__pyx_v_self, PyObject *__pyx_arg_n); /*proto*/
-static PyObject *__pyx_pf_5_cdec_10Hypergraph_8sample(PyObject *__pyx_v_self, PyObject *__pyx_arg_n) {
+static PyObject *__pyx_pf_5_cdec_10Hypergraph_14sample(struct __pyx_obj_5_cdec_Hypergraph *__pyx_v_self, unsigned int __pyx_v_n) {
   struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample *__pyx_cur_scope;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("sample");
+  __Pyx_RefNannySetupContext("sample", 0);
   __pyx_cur_scope = (struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample *)__pyx_ptype_5_cdec___pyx_scope_struct_3_sample->tp_new(__pyx_ptype_5_cdec___pyx_scope_struct_3_sample, __pyx_empty_tuple, NULL);
   if (unlikely(!__pyx_cur_scope)) {
     __Pyx_RefNannyFinishContext();
     return NULL;
   }
   __Pyx_GOTREF(__pyx_cur_scope);
-  __Pyx_INCREF(__pyx_v_self);
   __pyx_cur_scope->__pyx_v_self = __pyx_v_self;
-  assert(__pyx_arg_n); {
-    __pyx_cur_scope->__pyx_v_n = __Pyx_PyInt_AsUnsignedInt(__pyx_arg_n); if (unlikely((__pyx_cur_scope->__pyx_v_n == (unsigned int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 137; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_cdec.Hypergraph.sample", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_XDECREF((PyObject *)__pyx_cur_scope->__pyx_v_self); __pyx_cur_scope->__pyx_v_self = 0;
-  __Pyx_DECREF(((PyObject *)__pyx_cur_scope));
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
+  __Pyx_INCREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
   __Pyx_GIVEREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
-  __pyx_cur_scope->__pyx_base.resume_label = 0;
-  __pyx_cur_scope->__pyx_base.body = (__pyx_generator_body_t) __pyx_gb_5_cdec_10Hypergraph_9generator3;
-  __Pyx_GIVEREF(__pyx_cur_scope);
-  __Pyx_RefNannyFinishContext();
-  return (PyObject *) __pyx_cur_scope;
+  __pyx_cur_scope->__pyx_v_n = __pyx_v_n;
+  {
+    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_5_cdec_10Hypergraph_16generator3, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_cur_scope);
+    __Pyx_RefNannyFinishContext();
+    return (PyObject *) gen;
+  }
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("_cdec.Hypergraph.sample", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_DECREF(((PyObject *)__pyx_cur_scope));
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_gb_5_cdec_10Hypergraph_9generator3(struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample *__pyx_cur_scope, PyObject *__pyx_sent_value) /* generator body */
+static PyObject *__pyx_gb_5_cdec_10Hypergraph_16generator3(__pyx_GeneratorObject *__pyx_generator, PyObject *__pyx_sent_value) /* generator body */
 {
+  struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample *__pyx_cur_scope = ((struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample *)__pyx_generator->closure);
   PyObject *__pyx_r = NULL;
   int __pyx_t_1;
   size_t __pyx_t_2;
@@ -2889,8 +2802,8 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_9generator3(struct __pyx_obj_5_cde
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("None");
-  switch (__pyx_cur_scope->__pyx_base.resume_label) {
+  __Pyx_RefNannySetupContext("None", 0);
+  switch (__pyx_generator->resume_label) {
     case 0: goto __pyx_L3_first_run;
     case 1: goto __pyx_L7_resume_from_yield;
     default: /* CPython raises the right error here */
@@ -2898,9 +2811,9 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_9generator3(struct __pyx_obj_5_cde
     return NULL;
   }
   __pyx_L3_first_run:;
-  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 137; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "_cdec.pyx":138
+  /* "_cdec.pyx":123
  * 
  *     def sample(self, unsigned n):
  *         assert (self.hg != NULL)             # <<<<<<<<<<<<<<
@@ -2908,13 +2821,13 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_9generator3(struct __pyx_obj_5_cde
  *         if self.rng == NULL:
  */
   #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!(((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_cur_scope->__pyx_v_self)->hg != NULL))) {
+  if (unlikely(!(__pyx_cur_scope->__pyx_v_self->hg != NULL))) {
     PyErr_SetNone(PyExc_AssertionError);
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 138; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   #endif
 
-  /* "_cdec.pyx":139
+  /* "_cdec.pyx":124
  *     def sample(self, unsigned n):
  *         assert (self.hg != NULL)
  *         cdef vector[hypergraph.Hypothesis]* hypos = new vector[hypergraph.Hypothesis]()             # <<<<<<<<<<<<<<
@@ -2923,38 +2836,38 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_9generator3(struct __pyx_obj_5_cde
  */
   __pyx_cur_scope->__pyx_v_hypos = new std::vector<HypergraphSampler::Hypothesis>();
 
-  /* "_cdec.pyx":140
+  /* "_cdec.pyx":125
  *         assert (self.hg != NULL)
  *         cdef vector[hypergraph.Hypothesis]* hypos = new vector[hypergraph.Hypothesis]()
  *         if self.rng == NULL:             # <<<<<<<<<<<<<<
  *             self.rng = new MT19937()
  *         hypergraph.sample_hypotheses(self.hg[0], n, self.rng, hypos)
  */
-  __pyx_t_1 = (((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_cur_scope->__pyx_v_self)->rng == NULL);
+  __pyx_t_1 = (__pyx_cur_scope->__pyx_v_self->rng == NULL);
   if (__pyx_t_1) {
 
-    /* "_cdec.pyx":141
+    /* "_cdec.pyx":126
  *         cdef vector[hypergraph.Hypothesis]* hypos = new vector[hypergraph.Hypothesis]()
  *         if self.rng == NULL:
  *             self.rng = new MT19937()             # <<<<<<<<<<<<<<
  *         hypergraph.sample_hypotheses(self.hg[0], n, self.rng, hypos)
  *         cdef str sentence
  */
-    ((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_cur_scope->__pyx_v_self)->rng = new MT19937();
+    __pyx_cur_scope->__pyx_v_self->rng = new MT19937();
     goto __pyx_L4;
   }
   __pyx_L4:;
 
-  /* "_cdec.pyx":142
+  /* "_cdec.pyx":127
  *         if self.rng == NULL:
  *             self.rng = new MT19937()
  *         hypergraph.sample_hypotheses(self.hg[0], n, self.rng, hypos)             # <<<<<<<<<<<<<<
  *         cdef str sentence
  *         cdef unsigned k
  */
-  HypergraphSampler::sample_hypotheses((((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_cur_scope->__pyx_v_self)->hg[0]), __pyx_cur_scope->__pyx_v_n, ((struct __pyx_obj_5_cdec_Hypergraph *)__pyx_cur_scope->__pyx_v_self)->rng, __pyx_cur_scope->__pyx_v_hypos);
+  HypergraphSampler::sample_hypotheses((__pyx_cur_scope->__pyx_v_self->hg[0]), __pyx_cur_scope->__pyx_v_n, __pyx_cur_scope->__pyx_v_self->rng, __pyx_cur_scope->__pyx_v_hypos);
 
-  /* "_cdec.pyx":145
+  /* "_cdec.pyx":130
  *         cdef str sentence
  *         cdef unsigned k
  *         for k in range(hypos.size()):             # <<<<<<<<<<<<<<
@@ -2965,32 +2878,32 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_9generator3(struct __pyx_obj_5_cde
   for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
     __pyx_cur_scope->__pyx_v_k = __pyx_t_3;
 
-    /* "_cdec.pyx":146
+    /* "_cdec.pyx":131
  *         cdef unsigned k
  *         for k in range(hypos.size()):
  *             sentence = GetString(hypos[0][k].words).c_str()             # <<<<<<<<<<<<<<
  *             yield sentence.decode('utf8')
  *         del hypos
  */
-    __pyx_t_4 = PyBytes_FromString(TD::GetString(((__pyx_cur_scope->__pyx_v_hypos[0])[__pyx_cur_scope->__pyx_v_k]).words).c_str()); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyBytes_FromString(TD::GetString(((__pyx_cur_scope->__pyx_v_hypos[0])[__pyx_cur_scope->__pyx_v_k]).words).c_str()); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 131; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_4));
-    if (!(likely(PyString_CheckExact(((PyObject *)__pyx_t_4)))||(PyErr_Format(PyExc_TypeError, "Expected str, got %.200s", Py_TYPE(((PyObject *)__pyx_t_4))->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(PyString_CheckExact(((PyObject *)__pyx_t_4)))||(PyErr_Format(PyExc_TypeError, "Expected str, got %.200s", Py_TYPE(((PyObject *)__pyx_t_4))->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 131; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XGOTREF(((PyObject *)__pyx_cur_scope->__pyx_v_sentence));
     __Pyx_XDECREF(((PyObject *)__pyx_cur_scope->__pyx_v_sentence));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_4));
     __pyx_cur_scope->__pyx_v_sentence = ((PyObject*)__pyx_t_4);
     __pyx_t_4 = 0;
 
-    /* "_cdec.pyx":147
+    /* "_cdec.pyx":132
  *         for k in range(hypos.size()):
  *             sentence = GetString(hypos[0][k].words).c_str()
  *             yield sentence.decode('utf8')             # <<<<<<<<<<<<<<
  *         del hypos
  * 
  */
-    __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_cur_scope->__pyx_v_sentence), __pyx_n_s__decode); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_cur_scope->__pyx_v_sentence), __pyx_n_s__decode); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_12), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_7), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __pyx_r = __pyx_t_5;
@@ -3000,15 +2913,15 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_9generator3(struct __pyx_obj_5_cde
     __Pyx_XGIVEREF(__pyx_r);
     __Pyx_RefNannyFinishContext();
     /* return from generator, yielding value */
-    __pyx_cur_scope->__pyx_base.resume_label = 1;
+    __pyx_generator->resume_label = 1;
     return __pyx_r;
     __pyx_L7_resume_from_yield:;
     __pyx_t_2 = __pyx_cur_scope->__pyx_t_0;
     __pyx_t_3 = __pyx_cur_scope->__pyx_t_1;
-    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
 
-  /* "_cdec.pyx":148
+  /* "_cdec.pyx":133
  *             sentence = GetString(hypos[0][k].words).c_str()
  *             yield sentence.decode('utf8')
  *         del hypos             # <<<<<<<<<<<<<<
@@ -3016,7 +2929,7 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_9generator3(struct __pyx_obj_5_cde
  *     # TODO: get feature expectations, get partition function ("inside" score)
  */
   delete __pyx_cur_scope->__pyx_v_hypos;
-  PyErr_SetNone(PyExc_StopIteration); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 137; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  PyErr_SetNone(PyExc_StopIteration);
   goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_4);
@@ -3024,51 +2937,38 @@ static PyObject *__pyx_gb_5_cdec_10Hypergraph_9generator3(struct __pyx_obj_5_cde
   __Pyx_AddTraceback("sample", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_cur_scope->__pyx_base.resume_label = -1;
+  __pyx_generator->resume_label = -1;
   __Pyx_RefNannyFinishContext();
   return NULL;
 }
 
-/* "_cdec.pyx":157
- *     cdef lattice.Lattice* lattice
- * 
- *     def __init__(self, tuple plf_tuple):             # <<<<<<<<<<<<<<
- *         self.lattice = new lattice.Lattice()
- *         cdef bytes plf = str(plf_tuple)
- */
-
-static int __pyx_pf_5_cdec_7Lattice___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static int __pyx_pf_5_cdec_7Lattice___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+/* Python wrapper */
+static int __pyx_pw_5_cdec_7Lattice_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_5_cdec_7Lattice_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_plf_tuple = 0;
-  PyObject *__pyx_v_plf = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__plf_tuple,0};
   int __pyx_r;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  char *__pyx_t_3;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__plf_tuple,0};
-  __Pyx_RefNannySetupContext("__init__");
+  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
   {
     PyObject* values[1] = {0};
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
-      switch (PyTuple_GET_SIZE(__pyx_args)) {
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
         case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
         case  0: break;
         default: goto __pyx_L5_argtuple_error;
       }
       kw_args = PyDict_Size(__pyx_kwds);
-      switch (PyTuple_GET_SIZE(__pyx_args)) {
+      switch (pos_args) {
         case  0:
         values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__plf_tuple);
         if (likely(values[0])) kw_args--;
         else goto __pyx_L5_argtuple_error;
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "__init__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 1) {
       goto __pyx_L5_argtuple_error;
@@ -3079,51 +2979,79 @@ static int __pyx_pf_5_cdec_7Lattice___init__(PyObject *__pyx_v_self, PyObject *_
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("_cdec.Lattice.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return -1;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_plf_tuple), (&PyTuple_Type), 1, "plf_tuple", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_plf_tuple), (&PyTuple_Type), 1, "plf_tuple", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5_cdec_7Lattice___init__(((struct __pyx_obj_5_cdec_Lattice *)__pyx_v_self), __pyx_v_plf_tuple);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "_cdec.pyx":142
+ *     cdef lattice.Lattice* lattice
+ * 
+ *     def __init__(self, tuple plf_tuple):             # <<<<<<<<<<<<<<
+ *         self.lattice = new lattice.Lattice()
+ *         cdef bytes plf = str(plf_tuple)
+ */
+
+static int __pyx_pf_5_cdec_7Lattice___init__(struct __pyx_obj_5_cdec_Lattice *__pyx_v_self, PyObject *__pyx_v_plf_tuple) {
+  PyObject *__pyx_v_plf = 0;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  char *__pyx_t_3;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__init__", 0);
 
-  /* "_cdec.pyx":158
+  /* "_cdec.pyx":143
  * 
  *     def __init__(self, tuple plf_tuple):
  *         self.lattice = new lattice.Lattice()             # <<<<<<<<<<<<<<
  *         cdef bytes plf = str(plf_tuple)
  *         hypergraph.PLFtoLattice(string(<char *>plf), self.lattice)
  */
-  ((struct __pyx_obj_5_cdec_Lattice *)__pyx_v_self)->lattice = new Lattice();
+  __pyx_v_self->lattice = new Lattice();
 
-  /* "_cdec.pyx":159
+  /* "_cdec.pyx":144
  *     def __init__(self, tuple plf_tuple):
  *         self.lattice = new lattice.Lattice()
  *         cdef bytes plf = str(plf_tuple)             # <<<<<<<<<<<<<<
  *         hypergraph.PLFtoLattice(string(<char *>plf), self.lattice)
  * 
  */
-  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 159; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
   __Pyx_INCREF(((PyObject *)__pyx_v_plf_tuple));
   PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_plf_tuple));
   __Pyx_GIVEREF(((PyObject *)__pyx_v_plf_tuple));
-  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)(&PyString_Type))), ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 159; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)(&PyString_Type))), ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
-  if (!(likely(PyBytes_CheckExact(__pyx_t_2))||((__pyx_t_2) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected bytes, got %.200s", Py_TYPE(__pyx_t_2)->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 159; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (!(likely(PyBytes_CheckExact(__pyx_t_2))||((__pyx_t_2) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected bytes, got %.200s", Py_TYPE(__pyx_t_2)->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_plf = ((PyObject*)__pyx_t_2);
   __pyx_t_2 = 0;
 
-  /* "_cdec.pyx":160
+  /* "_cdec.pyx":145
  *         self.lattice = new lattice.Lattice()
  *         cdef bytes plf = str(plf_tuple)
  *         hypergraph.PLFtoLattice(string(<char *>plf), self.lattice)             # <<<<<<<<<<<<<<
  * 
  *     def __str__(self):
  */
-  __pyx_t_3 = PyBytes_AsString(((PyObject *)__pyx_v_plf)); if (unlikely((!__pyx_t_3) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  HypergraphIO::PLFtoLattice(std::string(((char *)__pyx_t_3)), ((struct __pyx_obj_5_cdec_Lattice *)__pyx_v_self)->lattice);
+  __pyx_t_3 = PyBytes_AsString(((PyObject *)__pyx_v_plf)); if (unlikely((!__pyx_t_3) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  HypergraphIO::PLFtoLattice(std::string(((char *)__pyx_t_3)), __pyx_v_self->lattice);
 
   __pyx_r = 0;
   goto __pyx_L0;
@@ -3138,7 +3066,18 @@ static int __pyx_pf_5_cdec_7Lattice___init__(PyObject *__pyx_v_self, PyObject *_
   return __pyx_r;
 }
 
-/* "_cdec.pyx":162
+/* Python wrapper */
+static PyObject *__pyx_pw_5_cdec_7Lattice_3__str__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_5_cdec_7Lattice_3__str__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__str__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_5_cdec_7Lattice_2__str__(((struct __pyx_obj_5_cdec_Lattice *)__pyx_v_self));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "_cdec.pyx":147
  *         hypergraph.PLFtoLattice(string(<char *>plf), self.lattice)
  * 
  *     def __str__(self):             # <<<<<<<<<<<<<<
@@ -3146,17 +3085,16 @@ static int __pyx_pf_5_cdec_7Lattice___init__(PyObject *__pyx_v_self, PyObject *_
  * 
  */
 
-static PyObject *__pyx_pf_5_cdec_7Lattice_1__str__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pf_5_cdec_7Lattice_1__str__(PyObject *__pyx_v_self) {
+static PyObject *__pyx_pf_5_cdec_7Lattice_2__str__(struct __pyx_obj_5_cdec_Lattice *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__str__");
+  __Pyx_RefNannySetupContext("__str__", 0);
 
-  /* "_cdec.pyx":163
+  /* "_cdec.pyx":148
  * 
  *     def __str__(self):
  *         return hypergraph.AsPLF(self.lattice[0]).c_str()             # <<<<<<<<<<<<<<
@@ -3164,7 +3102,7 @@ static PyObject *__pyx_pf_5_cdec_7Lattice_1__str__(PyObject *__pyx_v_self) {
  *     def __iter__(self):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyBytes_FromString(HypergraphIO::AsPLF((((struct __pyx_obj_5_cdec_Lattice *)__pyx_v_self)->lattice[0]), NULL).c_str()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 163; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyBytes_FromString(HypergraphIO::AsPLF((__pyx_v_self->lattice[0]), NULL).c_str()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_r = ((PyObject *)__pyx_t_1);
   __pyx_t_1 = 0;
@@ -3182,7 +3120,18 @@ static PyObject *__pyx_pf_5_cdec_7Lattice_1__str__(PyObject *__pyx_v_self) {
   return __pyx_r;
 }
 
-/* "_cdec.pyx":165
+/* Python wrapper */
+static PyObject *__pyx_pw_5_cdec_7Lattice_5__iter__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_5_cdec_7Lattice_5__iter__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__iter__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_5_cdec_7Lattice_4__iter__(((struct __pyx_obj_5_cdec_Lattice *)__pyx_v_self));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "_cdec.pyx":150
  *         return hypergraph.AsPLF(self.lattice[0]).c_str()
  * 
  *     def __iter__(self):             # <<<<<<<<<<<<<<
@@ -3190,18 +3139,19 @@ static PyObject *__pyx_pf_5_cdec_7Lattice_1__str__(PyObject *__pyx_v_self) {
  * 
  */
 
-static PyObject *__pyx_pf_5_cdec_7Lattice_2__iter__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pf_5_cdec_7Lattice_2__iter__(PyObject *__pyx_v_self) {
+static PyObject *__pyx_pf_5_cdec_7Lattice_4__iter__(struct __pyx_obj_5_cdec_Lattice *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__iter__");
+  __Pyx_RefNannySetupContext("__iter__", 0);
 
-  /* "_cdec.pyx":166
+  /* "_cdec.pyx":151
  * 
  *     def __iter__(self):
  *         return iter(eval(str(self)))             # <<<<<<<<<<<<<<
@@ -3209,27 +3159,40 @@ static PyObject *__pyx_pf_5_cdec_7Lattice_2__iter__(PyObject *__pyx_v_self) {
  *     def __dealloc__(self):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  __Pyx_INCREF(__pyx_v_self);
-  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self);
-  __Pyx_GIVEREF(__pyx_v_self);
-  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)(&PyString_Type))), ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(((PyObject *)__pyx_v_self));
+  PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_self));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_self));
+  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)(&PyString_Type))), ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
-  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2);
+  __pyx_t_1 = __Pyx_Globals(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  if (((PyObject *)__pyx_v_self)) {
+    if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__self), ((PyObject *)__pyx_v_self)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
   __Pyx_GIVEREF(__pyx_t_2);
+  PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_t_1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
+  PyTuple_SET_ITEM(__pyx_t_4, 2, ((PyObject *)__pyx_t_3));
+  __Pyx_GIVEREF(((PyObject *)__pyx_t_3));
   __pyx_t_2 = 0;
-  __pyx_t_2 = PyObject_Call(__pyx_builtin_eval, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
+  __pyx_t_3 = 0;
+  __pyx_t_3 = PyObject_Call(__pyx_builtin_eval, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __pyx_t_4 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_r = __pyx_t_4;
+  __pyx_t_4 = 0;
   goto __pyx_L0;
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
@@ -3237,6 +3200,8 @@ static PyObject *__pyx_pf_5_cdec_7Lattice_2__iter__(PyObject *__pyx_v_self) {
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_AddTraceback("_cdec.Lattice.__iter__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -3245,7 +3210,16 @@ static PyObject *__pyx_pf_5_cdec_7Lattice_2__iter__(PyObject *__pyx_v_self) {
   return __pyx_r;
 }
 
-/* "_cdec.pyx":168
+/* Python wrapper */
+static void __pyx_pw_5_cdec_7Lattice_7__dealloc__(PyObject *__pyx_v_self); /*proto*/
+static void __pyx_pw_5_cdec_7Lattice_7__dealloc__(PyObject *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
+  __pyx_pf_5_cdec_7Lattice_6__dealloc__(((struct __pyx_obj_5_cdec_Lattice *)__pyx_v_self));
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "_cdec.pyx":153
  *         return iter(eval(str(self)))
  * 
  *     def __dealloc__(self):             # <<<<<<<<<<<<<<
@@ -3253,19 +3227,18 @@ static PyObject *__pyx_pf_5_cdec_7Lattice_2__iter__(PyObject *__pyx_v_self) {
  * 
  */
 
-static void __pyx_pf_5_cdec_7Lattice_3__dealloc__(PyObject *__pyx_v_self); /*proto*/
-static void __pyx_pf_5_cdec_7Lattice_3__dealloc__(PyObject *__pyx_v_self) {
+static void __pyx_pf_5_cdec_7Lattice_6__dealloc__(CYTHON_UNUSED struct __pyx_obj_5_cdec_Lattice *__pyx_v_self) {
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__dealloc__");
+  __Pyx_RefNannySetupContext("__dealloc__", 0);
 
-  /* "_cdec.pyx":169
+  /* "_cdec.pyx":154
  * 
  *     def __dealloc__(self):
  *         del self.lattice             # <<<<<<<<<<<<<<
  * 
  * # TODO: wrap SparseVector
  */
-  delete ((struct __pyx_obj_5_cdec_Lattice *)__pyx_v_self)->lattice;
+  delete __pyx_v_self->lattice;
 
   __Pyx_RefNannyFinishContext();
 }
@@ -3273,7 +3246,7 @@ static void __pyx_pf_5_cdec_7Lattice_3__dealloc__(PyObject *__pyx_v_self) {
 static PyObject *__pyx_tp_new_5_cdec_Weights(PyTypeObject *t, PyObject *a, PyObject *k) {
   PyObject *o = (*t->tp_alloc)(t, 0);
   if (!o) return 0;
-  if (__pyx_pf_5_cdec_7Weights___cinit__(o, a, k) < 0) {
+  if (__pyx_pw_5_cdec_7Weights_1__cinit__(o, a, k) < 0) {
     Py_DECREF(o); o = 0;
   }
   return o;
@@ -3292,7 +3265,7 @@ static PyObject *__pyx_sq_item_5_cdec_Weights(PyObject *o, Py_ssize_t i) {
 
 static int __pyx_mp_ass_subscript_5_cdec_Weights(PyObject *o, PyObject *i, PyObject *v) {
   if (v) {
-    return __pyx_pf_5_cdec_7Weights_2__setitem__(o, i, v);
+    return __pyx_pw_5_cdec_7Weights_5__setitem__(o, i, v);
   }
   else {
     PyErr_Format(PyExc_NotImplementedError,
@@ -3378,7 +3351,7 @@ static PySequenceMethods __pyx_tp_as_sequence_Weights = {
 
 static PyMappingMethods __pyx_tp_as_mapping_Weights = {
   0, /*mp_length*/
-  __pyx_pf_5_cdec_7Weights_1__getitem__, /*mp_subscript*/
+  __pyx_pw_5_cdec_7Weights_3__getitem__, /*mp_subscript*/
   __pyx_mp_ass_subscript_5_cdec_Weights, /*mp_ass_subscript*/
 };
 
@@ -3433,7 +3406,7 @@ static PyTypeObject __pyx_type_5_cdec_Weights = {
   0, /*tp_clear*/
   0, /*tp_richcompare*/
   0, /*tp_weaklistoffset*/
-  __pyx_pf_5_cdec_7Weights_3__iter__, /*tp_iter*/
+  __pyx_pw_5_cdec_7Weights_7__iter__, /*tp_iter*/
   0, /*tp_iternext*/
   __pyx_methods_5_cdec_Weights, /*tp_methods*/
   0, /*tp_members*/
@@ -3465,7 +3438,7 @@ static PyObject *__pyx_tp_new_5_cdec_Decoder(PyTypeObject *t, PyObject *a, PyObj
   if (!o) return 0;
   p = ((struct __pyx_obj_5_cdec_Decoder *)o);
   p->weights = ((struct __pyx_obj_5_cdec_Weights *)Py_None); Py_INCREF(Py_None);
-  if (__pyx_pf_5_cdec_7Decoder___cinit__(o, a, k) < 0) {
+  if (__pyx_pw_5_cdec_7Decoder_1__cinit__(o, a, k) < 0) {
     Py_DECREF(o); o = 0;
   }
   return o;
@@ -3477,7 +3450,7 @@ static void __pyx_tp_dealloc_5_cdec_Decoder(PyObject *o) {
     PyObject *etype, *eval, *etb;
     PyErr_Fetch(&etype, &eval, &etb);
     ++Py_REFCNT(o);
-    __pyx_pf_5_cdec_7Decoder_1__dealloc__(o);
+    __pyx_pw_5_cdec_7Decoder_3__dealloc__(o);
     if (PyErr_Occurred()) PyErr_WriteUnraisable(o);
     --Py_REFCNT(o);
     PyErr_Restore(etype, eval, etb);
@@ -3505,22 +3478,21 @@ static int __pyx_tp_clear_5_cdec_Decoder(PyObject *o) {
 }
 
 static PyObject *__pyx_getprop_5_cdec_7Decoder_weights(PyObject *o, void *x) {
-  return __pyx_pf_5_cdec_7Decoder_7weights___get__(o);
+  return __pyx_pw_5_cdec_7Decoder_7weights_1__get__(o);
 }
 
 static int __pyx_setprop_5_cdec_7Decoder_weights(PyObject *o, PyObject *v, void *x) {
   if (v) {
-    return __pyx_pf_5_cdec_7Decoder_7weights_1__set__(o, v);
+    return __pyx_pw_5_cdec_7Decoder_7weights_3__set__(o, v);
   }
   else {
-    return __pyx_pf_5_cdec_7Decoder_7weights_2__del__(o);
+    return __pyx_pw_5_cdec_7Decoder_7weights_5__del__(o);
   }
 }
 
 static PyMethodDef __pyx_methods_5_cdec_Decoder[] = {
-  {__Pyx_NAMESTR("fromconfig"), (PyCFunction)__pyx_pf_5_cdec_7Decoder_2fromconfig, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("read_weights"), (PyCFunction)__pyx_pf_5_cdec_7Decoder_3read_weights, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("translate"), (PyCFunction)__pyx_pf_5_cdec_7Decoder_4translate, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("read_weights"), (PyCFunction)__pyx_pw_5_cdec_7Decoder_5read_weights, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("translate"), (PyCFunction)__pyx_pw_5_cdec_7Decoder_7translate, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)},
   {0, 0, 0, 0}
 };
 
@@ -3694,7 +3666,7 @@ static void __pyx_tp_dealloc_5_cdec_Hypergraph(PyObject *o) {
     PyObject *etype, *eval, *etb;
     PyErr_Fetch(&etype, &eval, &etb);
     ++Py_REFCNT(o);
-    __pyx_pf_5_cdec_10Hypergraph___dealloc__(o);
+    __pyx_pw_5_cdec_10Hypergraph_1__dealloc__(o);
     if (PyErr_Occurred()) PyErr_WriteUnraisable(o);
     --Py_REFCNT(o);
     PyErr_Restore(etype, eval, etb);
@@ -3703,12 +3675,12 @@ static void __pyx_tp_dealloc_5_cdec_Hypergraph(PyObject *o) {
 }
 
 static PyMethodDef __pyx_methods_5_cdec_Hypergraph[] = {
-  {__Pyx_NAMESTR("viterbi"), (PyCFunction)__pyx_pf_5_cdec_10Hypergraph_1viterbi, METH_NOARGS, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("viterbi_tree"), (PyCFunction)__pyx_pf_5_cdec_10Hypergraph_2viterbi_tree, METH_NOARGS, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("kbest"), (PyCFunction)__pyx_pf_5_cdec_10Hypergraph_3kbest, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("kbest_tree"), (PyCFunction)__pyx_pf_5_cdec_10Hypergraph_5kbest_tree, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("intersect"), (PyCFunction)__pyx_pf_5_cdec_10Hypergraph_7intersect, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("sample"), (PyCFunction)__pyx_pf_5_cdec_10Hypergraph_8sample, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("viterbi"), (PyCFunction)__pyx_pw_5_cdec_10Hypergraph_3viterbi, METH_NOARGS, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("viterbi_tree"), (PyCFunction)__pyx_pw_5_cdec_10Hypergraph_5viterbi_tree, METH_NOARGS, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("kbest"), (PyCFunction)__pyx_pw_5_cdec_10Hypergraph_7kbest, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("kbest_tree"), (PyCFunction)__pyx_pw_5_cdec_10Hypergraph_10kbest_tree, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("intersect"), (PyCFunction)__pyx_pw_5_cdec_10Hypergraph_13intersect, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("sample"), (PyCFunction)__pyx_pw_5_cdec_10Hypergraph_15sample, METH_O, __Pyx_DOCSTR(0)},
   {0, 0, 0, 0}
 };
 
@@ -3877,7 +3849,7 @@ static void __pyx_tp_dealloc_5_cdec_Lattice(PyObject *o) {
     PyObject *etype, *eval, *etb;
     PyErr_Fetch(&etype, &eval, &etb);
     ++Py_REFCNT(o);
-    __pyx_pf_5_cdec_7Lattice_3__dealloc__(o);
+    __pyx_pw_5_cdec_7Lattice_7__dealloc__(o);
     if (PyErr_Occurred()) PyErr_WriteUnraisable(o);
     --Py_REFCNT(o);
     PyErr_Restore(etype, eval, etb);
@@ -3989,220 +3961,10 @@ static PyBufferProcs __pyx_tp_as_buffer_Lattice = {
 
 static PyTypeObject __pyx_type_5_cdec_Lattice = {
   PyVarObject_HEAD_INIT(0, 0)
-  __Pyx_NAMESTR("_cdec.Lattice"), /*tp_name*/
-  sizeof(struct __pyx_obj_5_cdec_Lattice), /*tp_basicsize*/
-  0, /*tp_itemsize*/
-  __pyx_tp_dealloc_5_cdec_Lattice, /*tp_dealloc*/
-  0, /*tp_print*/
-  0, /*tp_getattr*/
-  0, /*tp_setattr*/
-  #if PY_MAJOR_VERSION < 3
-  0, /*tp_compare*/
-  #else
-  0, /*reserved*/
-  #endif
-  0, /*tp_repr*/
-  &__pyx_tp_as_number_Lattice, /*tp_as_number*/
-  &__pyx_tp_as_sequence_Lattice, /*tp_as_sequence*/
-  &__pyx_tp_as_mapping_Lattice, /*tp_as_mapping*/
-  0, /*tp_hash*/
-  0, /*tp_call*/
-  __pyx_pf_5_cdec_7Lattice_1__str__, /*tp_str*/
-  0, /*tp_getattro*/
-  0, /*tp_setattro*/
-  &__pyx_tp_as_buffer_Lattice, /*tp_as_buffer*/
-  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/
-  0, /*tp_doc*/
-  0, /*tp_traverse*/
-  0, /*tp_clear*/
-  0, /*tp_richcompare*/
-  0, /*tp_weaklistoffset*/
-  __pyx_pf_5_cdec_7Lattice_2__iter__, /*tp_iter*/
-  0, /*tp_iternext*/
-  __pyx_methods_5_cdec_Lattice, /*tp_methods*/
-  0, /*tp_members*/
-  0, /*tp_getset*/
-  0, /*tp_base*/
-  0, /*tp_dict*/
-  0, /*tp_descr_get*/
-  0, /*tp_descr_set*/
-  0, /*tp_dictoffset*/
-  __pyx_pf_5_cdec_7Lattice___init__, /*tp_init*/
-  0, /*tp_alloc*/
-  __pyx_tp_new_5_cdec_Lattice, /*tp_new*/
-  0, /*tp_free*/
-  0, /*tp_is_gc*/
-  0, /*tp_bases*/
-  0, /*tp_mro*/
-  0, /*tp_cache*/
-  0, /*tp_subclasses*/
-  0, /*tp_weaklist*/
-  0, /*tp_del*/
-  #if PY_VERSION_HEX >= 0x02060000
-  0, /*tp_version_tag*/
-  #endif
-};
-
-static PyObject *__pyx_tp_new_5_cdec___pyx_Generator(PyTypeObject *t, PyObject *a, PyObject *k) {
-  struct __pyx_Generator_object *p;
-  PyObject *o = (*t->tp_alloc)(t, 0);
-  if (!o) return 0;
-  p = ((struct __pyx_Generator_object *)o);
-  p->exc_type = 0;
-  p->exc_value = 0;
-  p->exc_traceback = 0;
-  return o;
-}
-
-static void __pyx_tp_dealloc_5_cdec___pyx_Generator(PyObject *o) {
-  struct __pyx_Generator_object *p = (struct __pyx_Generator_object *)o;
-  Py_XDECREF(p->exc_type);
-  Py_XDECREF(p->exc_value);
-  Py_XDECREF(p->exc_traceback);
-  (*Py_TYPE(o)->tp_free)(o);
-}
-
-static int __pyx_tp_traverse_5_cdec___pyx_Generator(PyObject *o, visitproc v, void *a) {
-  int e;
-  struct __pyx_Generator_object *p = (struct __pyx_Generator_object *)o;
-  if (p->exc_type) {
-    e = (*v)(p->exc_type, a); if (e) return e;
-  }
-  if (p->exc_value) {
-    e = (*v)(p->exc_value, a); if (e) return e;
-  }
-  if (p->exc_traceback) {
-    e = (*v)(p->exc_traceback, a); if (e) return e;
-  }
-  return 0;
-}
-
-static int __pyx_tp_clear_5_cdec___pyx_Generator(PyObject *o) {
-  struct __pyx_Generator_object *p = (struct __pyx_Generator_object *)o;
-  PyObject* tmp;
-  tmp = ((PyObject*)p->exc_type);
-  p->exc_type = Py_None; Py_INCREF(Py_None);
-  Py_XDECREF(tmp);
-  tmp = ((PyObject*)p->exc_value);
-  p->exc_value = Py_None; Py_INCREF(Py_None);
-  Py_XDECREF(tmp);
-  tmp = ((PyObject*)p->exc_traceback);
-  p->exc_traceback = Py_None; Py_INCREF(Py_None);
-  Py_XDECREF(tmp);
-  return 0;
-}
-
-static PyMethodDef __pyx_methods_5_cdec___pyx_Generator[] = {
-  {__Pyx_NAMESTR("send"), (PyCFunction)__Pyx_Generator_Send, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("close"), (PyCFunction)__Pyx_Generator_Close, METH_NOARGS, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("throw"), (PyCFunction)__Pyx_Generator_Throw, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)},
-  {0, 0, 0, 0}
-};
-
-static PyNumberMethods __pyx_tp_as_number___pyx_Generator = {
-  0, /*nb_add*/
-  0, /*nb_subtract*/
-  0, /*nb_multiply*/
-  #if PY_MAJOR_VERSION < 3
-  0, /*nb_divide*/
-  #endif
-  0, /*nb_remainder*/
-  0, /*nb_divmod*/
-  0, /*nb_power*/
-  0, /*nb_negative*/
-  0, /*nb_positive*/
-  0, /*nb_absolute*/
-  0, /*nb_nonzero*/
-  0, /*nb_invert*/
-  0, /*nb_lshift*/
-  0, /*nb_rshift*/
-  0, /*nb_and*/
-  0, /*nb_xor*/
-  0, /*nb_or*/
-  #if PY_MAJOR_VERSION < 3
-  0, /*nb_coerce*/
-  #endif
-  0, /*nb_int*/
-  #if PY_MAJOR_VERSION < 3
-  0, /*nb_long*/
-  #else
-  0, /*reserved*/
-  #endif
-  0, /*nb_float*/
-  #if PY_MAJOR_VERSION < 3
-  0, /*nb_oct*/
-  #endif
-  #if PY_MAJOR_VERSION < 3
-  0, /*nb_hex*/
-  #endif
-  0, /*nb_inplace_add*/
-  0, /*nb_inplace_subtract*/
-  0, /*nb_inplace_multiply*/
-  #if PY_MAJOR_VERSION < 3
-  0, /*nb_inplace_divide*/
-  #endif
-  0, /*nb_inplace_remainder*/
-  0, /*nb_inplace_power*/
-  0, /*nb_inplace_lshift*/
-  0, /*nb_inplace_rshift*/
-  0, /*nb_inplace_and*/
-  0, /*nb_inplace_xor*/
-  0, /*nb_inplace_or*/
-  0, /*nb_floor_divide*/
-  0, /*nb_true_divide*/
-  0, /*nb_inplace_floor_divide*/
-  0, /*nb_inplace_true_divide*/
-  #if PY_VERSION_HEX >= 0x02050000
-  0, /*nb_index*/
-  #endif
-};
-
-static PySequenceMethods __pyx_tp_as_sequence___pyx_Generator = {
-  0, /*sq_length*/
-  0, /*sq_concat*/
-  0, /*sq_repeat*/
-  0, /*sq_item*/
-  0, /*sq_slice*/
-  0, /*sq_ass_item*/
-  0, /*sq_ass_slice*/
-  0, /*sq_contains*/
-  0, /*sq_inplace_concat*/
-  0, /*sq_inplace_repeat*/
-};
-
-static PyMappingMethods __pyx_tp_as_mapping___pyx_Generator = {
-  0, /*mp_length*/
-  0, /*mp_subscript*/
-  0, /*mp_ass_subscript*/
-};
-
-static PyBufferProcs __pyx_tp_as_buffer___pyx_Generator = {
-  #if PY_MAJOR_VERSION < 3
-  0, /*bf_getreadbuffer*/
-  #endif
-  #if PY_MAJOR_VERSION < 3
-  0, /*bf_getwritebuffer*/
-  #endif
-  #if PY_MAJOR_VERSION < 3
-  0, /*bf_getsegcount*/
-  #endif
-  #if PY_MAJOR_VERSION < 3
-  0, /*bf_getcharbuffer*/
-  #endif
-  #if PY_VERSION_HEX >= 0x02060000
-  0, /*bf_getbuffer*/
-  #endif
-  #if PY_VERSION_HEX >= 0x02060000
-  0, /*bf_releasebuffer*/
-  #endif
-};
-
-static PyTypeObject __pyx_Generator_type = {
-  PyVarObject_HEAD_INIT(0, 0)
-  __Pyx_NAMESTR("_cdec.__pyx_Generator"), /*tp_name*/
-  sizeof(struct __pyx_Generator_object), /*tp_basicsize*/
+  __Pyx_NAMESTR("_cdec.Lattice"), /*tp_name*/
+  sizeof(struct __pyx_obj_5_cdec_Lattice), /*tp_basicsize*/
   0, /*tp_itemsize*/
-  __pyx_tp_dealloc_5_cdec___pyx_Generator, /*tp_dealloc*/
+  __pyx_tp_dealloc_5_cdec_Lattice, /*tp_dealloc*/
   0, /*tp_print*/
   0, /*tp_getattr*/
   0, /*tp_setattr*/
@@ -4212,24 +3974,24 @@ static PyTypeObject __pyx_Generator_type = {
   0, /*reserved*/
   #endif
   0, /*tp_repr*/
-  &__pyx_tp_as_number___pyx_Generator, /*tp_as_number*/
-  &__pyx_tp_as_sequence___pyx_Generator, /*tp_as_sequence*/
-  &__pyx_tp_as_mapping___pyx_Generator, /*tp_as_mapping*/
+  &__pyx_tp_as_number_Lattice, /*tp_as_number*/
+  &__pyx_tp_as_sequence_Lattice, /*tp_as_sequence*/
+  &__pyx_tp_as_mapping_Lattice, /*tp_as_mapping*/
   0, /*tp_hash*/
   0, /*tp_call*/
-  0, /*tp_str*/
+  __pyx_pw_5_cdec_7Lattice_3__str__, /*tp_str*/
   0, /*tp_getattro*/
   0, /*tp_setattro*/
-  &__pyx_tp_as_buffer___pyx_Generator, /*tp_as_buffer*/
-  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+  &__pyx_tp_as_buffer_Lattice, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/
   0, /*tp_doc*/
-  __pyx_tp_traverse_5_cdec___pyx_Generator, /*tp_traverse*/
-  __pyx_tp_clear_5_cdec___pyx_Generator, /*tp_clear*/
+  0, /*tp_traverse*/
+  0, /*tp_clear*/
   0, /*tp_richcompare*/
   0, /*tp_weaklistoffset*/
-  PyObject_SelfIter, /*tp_iter*/
-  __Pyx_Generator_Next, /*tp_iternext*/
-  __pyx_methods_5_cdec___pyx_Generator, /*tp_methods*/
+  __pyx_pw_5_cdec_7Lattice_5__iter__, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_5_cdec_Lattice, /*tp_methods*/
   0, /*tp_members*/
   0, /*tp_getset*/
   0, /*tp_base*/
@@ -4237,9 +3999,9 @@ static PyTypeObject __pyx_Generator_type = {
   0, /*tp_descr_get*/
   0, /*tp_descr_set*/
   0, /*tp_dictoffset*/
-  0, /*tp_init*/
+  __pyx_pw_5_cdec_7Lattice_1__init__, /*tp_init*/
   0, /*tp_alloc*/
-  __pyx_tp_new_5_cdec___pyx_Generator, /*tp_new*/
+  __pyx_tp_new_5_cdec_Lattice, /*tp_new*/
   0, /*tp_free*/
   0, /*tp_is_gc*/
   0, /*tp_bases*/
@@ -4255,7 +4017,7 @@ static PyTypeObject __pyx_Generator_type = {
 
 static PyObject *__pyx_tp_new_5_cdec___pyx_scope_struct____iter__(PyTypeObject *t, PyObject *a, PyObject *k) {
   struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ *p;
-  PyObject *o = __pyx_tp_new_5_cdec___pyx_Generator(t, a, k);
+  PyObject *o = (*t->tp_alloc)(t, 0);
   if (!o) return 0;
   p = ((struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ *)o);
   p->__pyx_v_self = 0;
@@ -4265,13 +4027,12 @@ static PyObject *__pyx_tp_new_5_cdec___pyx_scope_struct____iter__(PyTypeObject *
 static void __pyx_tp_dealloc_5_cdec___pyx_scope_struct____iter__(PyObject *o) {
   struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ *p = (struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ *)o;
   Py_XDECREF(((PyObject *)p->__pyx_v_self));
-  __pyx_tp_dealloc_5_cdec___pyx_Generator(o);
+  (*Py_TYPE(o)->tp_free)(o);
 }
 
 static int __pyx_tp_traverse_5_cdec___pyx_scope_struct____iter__(PyObject *o, visitproc v, void *a) {
   int e;
   struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ *p = (struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ *)o;
-  e = __pyx_tp_traverse_5_cdec___pyx_Generator(o, v, a); if (e) return e;
   if (p->__pyx_v_self) {
     e = (*v)(((PyObject*)p->__pyx_v_self), a); if (e) return e;
   }
@@ -4281,9 +4042,8 @@ static int __pyx_tp_traverse_5_cdec___pyx_scope_struct____iter__(PyObject *o, vi
 static int __pyx_tp_clear_5_cdec___pyx_scope_struct____iter__(PyObject *o) {
   struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ *p = (struct __pyx_obj_5_cdec___pyx_scope_struct____iter__ *)o;
   PyObject* tmp;
-  __pyx_tp_clear_5_cdec___pyx_Generator(o);
   tmp = ((PyObject*)p->__pyx_v_self);
-  p->__pyx_v_self = Py_None; Py_INCREF(Py_None);
+  p->__pyx_v_self = ((struct __pyx_obj_5_cdec_Weights *)Py_None); Py_INCREF(Py_None);
   Py_XDECREF(tmp);
   return 0;
 }
@@ -4448,7 +4208,7 @@ static PyTypeObject __pyx_type_5_cdec___pyx_scope_struct____iter__ = {
 
 static PyObject *__pyx_tp_new_5_cdec___pyx_scope_struct_1_kbest(PyTypeObject *t, PyObject *a, PyObject *k) {
   struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest *p;
-  PyObject *o = __pyx_tp_new_5_cdec___pyx_Generator(t, a, k);
+  PyObject *o = (*t->tp_alloc)(t, 0);
   if (!o) return 0;
   p = ((struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest *)o);
   p->__pyx_v_self = 0;
@@ -4462,13 +4222,12 @@ static void __pyx_tp_dealloc_5_cdec___pyx_scope_struct_1_kbest(PyObject *o) {
   Py_XDECREF(((PyObject *)p->__pyx_v_self));
   Py_XDECREF(p->__pyx_v_size);
   Py_XDECREF(((PyObject *)p->__pyx_v_tree));
-  __pyx_tp_dealloc_5_cdec___pyx_Generator(o);
+  (*Py_TYPE(o)->tp_free)(o);
 }
 
 static int __pyx_tp_traverse_5_cdec___pyx_scope_struct_1_kbest(PyObject *o, visitproc v, void *a) {
   int e;
   struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest *p = (struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest *)o;
-  e = __pyx_tp_traverse_5_cdec___pyx_Generator(o, v, a); if (e) return e;
   if (p->__pyx_v_self) {
     e = (*v)(((PyObject*)p->__pyx_v_self), a); if (e) return e;
   }
@@ -4484,9 +4243,8 @@ static int __pyx_tp_traverse_5_cdec___pyx_scope_struct_1_kbest(PyObject *o, visi
 static int __pyx_tp_clear_5_cdec___pyx_scope_struct_1_kbest(PyObject *o) {
   struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest *p = (struct __pyx_obj_5_cdec___pyx_scope_struct_1_kbest *)o;
   PyObject* tmp;
-  __pyx_tp_clear_5_cdec___pyx_Generator(o);
   tmp = ((PyObject*)p->__pyx_v_self);
-  p->__pyx_v_self = Py_None; Py_INCREF(Py_None);
+  p->__pyx_v_self = ((struct __pyx_obj_5_cdec_Hypergraph *)Py_None); Py_INCREF(Py_None);
   Py_XDECREF(tmp);
   tmp = ((PyObject*)p->__pyx_v_size);
   p->__pyx_v_size = Py_None; Py_INCREF(Py_None);
@@ -4657,7 +4415,7 @@ static PyTypeObject __pyx_type_5_cdec___pyx_scope_struct_1_kbest = {
 
 static PyObject *__pyx_tp_new_5_cdec___pyx_scope_struct_2_kbest_tree(PyTypeObject *t, PyObject *a, PyObject *k) {
   struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree *p;
-  PyObject *o = __pyx_tp_new_5_cdec___pyx_Generator(t, a, k);
+  PyObject *o = (*t->tp_alloc)(t, 0);
   if (!o) return 0;
   p = ((struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree *)o);
   p->__pyx_v_self = 0;
@@ -4671,13 +4429,12 @@ static void __pyx_tp_dealloc_5_cdec___pyx_scope_struct_2_kbest_tree(PyObject *o)
   Py_XDECREF(((PyObject *)p->__pyx_v_self));
   Py_XDECREF(((PyObject *)p->__pyx_v_sentence));
   Py_XDECREF(p->__pyx_v_size);
-  __pyx_tp_dealloc_5_cdec___pyx_Generator(o);
+  (*Py_TYPE(o)->tp_free)(o);
 }
 
 static int __pyx_tp_traverse_5_cdec___pyx_scope_struct_2_kbest_tree(PyObject *o, visitproc v, void *a) {
   int e;
   struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree *p = (struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree *)o;
-  e = __pyx_tp_traverse_5_cdec___pyx_Generator(o, v, a); if (e) return e;
   if (p->__pyx_v_self) {
     e = (*v)(((PyObject*)p->__pyx_v_self), a); if (e) return e;
   }
@@ -4693,9 +4450,8 @@ static int __pyx_tp_traverse_5_cdec___pyx_scope_struct_2_kbest_tree(PyObject *o,
 static int __pyx_tp_clear_5_cdec___pyx_scope_struct_2_kbest_tree(PyObject *o) {
   struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree *p = (struct __pyx_obj_5_cdec___pyx_scope_struct_2_kbest_tree *)o;
   PyObject* tmp;
-  __pyx_tp_clear_5_cdec___pyx_Generator(o);
   tmp = ((PyObject*)p->__pyx_v_self);
-  p->__pyx_v_self = Py_None; Py_INCREF(Py_None);
+  p->__pyx_v_self = ((struct __pyx_obj_5_cdec_Hypergraph *)Py_None); Py_INCREF(Py_None);
   Py_XDECREF(tmp);
   tmp = ((PyObject*)p->__pyx_v_sentence);
   p->__pyx_v_sentence = ((PyObject*)Py_None); Py_INCREF(Py_None);
@@ -4866,7 +4622,7 @@ static PyTypeObject __pyx_type_5_cdec___pyx_scope_struct_2_kbest_tree = {
 
 static PyObject *__pyx_tp_new_5_cdec___pyx_scope_struct_3_sample(PyTypeObject *t, PyObject *a, PyObject *k) {
   struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample *p;
-  PyObject *o = __pyx_tp_new_5_cdec___pyx_Generator(t, a, k);
+  PyObject *o = (*t->tp_alloc)(t, 0);
   if (!o) return 0;
   p = ((struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample *)o);
   p->__pyx_v_self = 0;
@@ -4878,13 +4634,12 @@ static void __pyx_tp_dealloc_5_cdec___pyx_scope_struct_3_sample(PyObject *o) {
   struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample *p = (struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample *)o;
   Py_XDECREF(((PyObject *)p->__pyx_v_self));
   Py_XDECREF(((PyObject *)p->__pyx_v_sentence));
-  __pyx_tp_dealloc_5_cdec___pyx_Generator(o);
+  (*Py_TYPE(o)->tp_free)(o);
 }
 
 static int __pyx_tp_traverse_5_cdec___pyx_scope_struct_3_sample(PyObject *o, visitproc v, void *a) {
   int e;
   struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample *p = (struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample *)o;
-  e = __pyx_tp_traverse_5_cdec___pyx_Generator(o, v, a); if (e) return e;
   if (p->__pyx_v_self) {
     e = (*v)(((PyObject*)p->__pyx_v_self), a); if (e) return e;
   }
@@ -4897,9 +4652,8 @@ static int __pyx_tp_traverse_5_cdec___pyx_scope_struct_3_sample(PyObject *o, vis
 static int __pyx_tp_clear_5_cdec___pyx_scope_struct_3_sample(PyObject *o) {
   struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample *p = (struct __pyx_obj_5_cdec___pyx_scope_struct_3_sample *)o;
   PyObject* tmp;
-  __pyx_tp_clear_5_cdec___pyx_Generator(o);
   tmp = ((PyObject*)p->__pyx_v_self);
-  p->__pyx_v_self = Py_None; Py_INCREF(Py_None);
+  p->__pyx_v_self = ((struct __pyx_obj_5_cdec_Hypergraph *)Py_None); Py_INCREF(Py_None);
   Py_XDECREF(tmp);
   tmp = ((PyObject*)p->__pyx_v_sentence);
   p->__pyx_v_sentence = ((PyObject*)Py_None); Py_INCREF(Py_None);
@@ -5084,8 +4838,6 @@ static struct PyModuleDef __pyx_moduledef = {
 #endif
 
 static __Pyx_StringTabEntry __pyx_string_tab[] = {
-  {&__pyx_kp_s_1, __pyx_k_1, sizeof(__pyx_k_1), 0, 0, 1, 0},
-  {&__pyx_kp_s_3, __pyx_k_3, sizeof(__pyx_k_3), 0, 0, 1, 0},
   {&__pyx_n_s__Exception, __pyx_k__Exception, sizeof(__pyx_k__Exception), 0, 0, 1, 1},
   {&__pyx_n_s__KeyError, __pyx_k__KeyError, sizeof(__pyx_k__KeyError), 0, 0, 1, 1},
   {&__pyx_n_s__ParseFailed, __pyx_k__ParseFailed, sizeof(__pyx_k__ParseFailed), 0, 0, 1, 1},
@@ -5099,14 +4851,13 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__decoder, __pyx_k__decoder, sizeof(__pyx_k__decoder), 0, 0, 1, 1},
   {&__pyx_n_s__encode, __pyx_k__encode, sizeof(__pyx_k__encode), 0, 0, 1, 1},
   {&__pyx_n_s__eval, __pyx_k__eval, sizeof(__pyx_k__eval), 0, 0, 1, 1},
-  {&__pyx_n_s__fromconfig, __pyx_k__fromconfig, sizeof(__pyx_k__fromconfig), 0, 0, 1, 1},
   {&__pyx_n_s__grammar, __pyx_k__grammar, sizeof(__pyx_k__grammar), 0, 0, 1, 1},
   {&__pyx_n_s__open, __pyx_k__open, sizeof(__pyx_k__open), 0, 0, 1, 1},
   {&__pyx_n_s__plf_tuple, __pyx_k__plf_tuple, sizeof(__pyx_k__plf_tuple), 0, 0, 1, 1},
   {&__pyx_n_s__range, __pyx_k__range, sizeof(__pyx_k__range), 0, 0, 1, 1},
+  {&__pyx_n_s__self, __pyx_k__self, sizeof(__pyx_k__self), 0, 0, 1, 1},
   {&__pyx_n_s__sentence, __pyx_k__sentence, sizeof(__pyx_k__sentence), 0, 0, 1, 1},
   {&__pyx_n_s__split, __pyx_k__split, sizeof(__pyx_k__split), 0, 0, 1, 1},
-  {&__pyx_n_s__startswith, __pyx_k__startswith, sizeof(__pyx_k__startswith), 0, 0, 1, 1},
   {&__pyx_n_s__strip, __pyx_k__strip, sizeof(__pyx_k__strip), 0, 0, 1, 1},
   {&__pyx_n_s__utf8, __pyx_k__utf8, sizeof(__pyx_k__utf8), 0, 0, 1, 1},
   {0, 0, 0, 0, 0, 0, 0}
@@ -5115,8 +4866,8 @@ static int __Pyx_InitCachedBuiltins(void) {
   __pyx_builtin_Exception = __Pyx_GetName(__pyx_b, __pyx_n_s__Exception); if (!__pyx_builtin_Exception) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_builtin_KeyError = __Pyx_GetName(__pyx_b, __pyx_n_s__KeyError); if (!__pyx_builtin_KeyError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_builtin_range = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_builtin_open = __Pyx_GetName(__pyx_b, __pyx_n_s__open); if (!__pyx_builtin_open) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_builtin_eval = __Pyx_GetName(__pyx_b, __pyx_n_s__eval); if (!__pyx_builtin_eval) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_open = __Pyx_GetName(__pyx_b, __pyx_n_s__open); if (!__pyx_builtin_open) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_eval = __Pyx_GetName(__pyx_b, __pyx_n_s__eval); if (!__pyx_builtin_eval) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   return 0;
   __pyx_L1_error:;
   return -1;
@@ -5124,159 +4875,111 @@ static int __Pyx_InitCachedBuiltins(void) {
 
 static int __Pyx_InitCachedConstants(void) {
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants");
-
-  /* "_cdec.pyx":61
- *             for line in fp:
- *                 line = line.strip()
- *                 if not line or line.startswith('#'): continue             # <<<<<<<<<<<<<<
- *                 param, value = line.split('=')
- *                 config[param.strip()] = value.strip()
- */
-  __pyx_k_tuple_2 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_2));
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_1));
-  PyTuple_SET_ITEM(__pyx_k_tuple_2, 0, ((PyObject *)__pyx_kp_s_1));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_1));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_2));
-
-  /* "_cdec.pyx":62
- *                 line = line.strip()
- *                 if not line or line.startswith('#'): continue
- *                 param, value = line.split('=')             # <<<<<<<<<<<<<<
- *                 config[param.strip()] = value.strip()
- *         return cls(**config)
- */
-  __pyx_k_tuple_4 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_4));
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_3));
-  PyTuple_SET_ITEM(__pyx_k_tuple_4, 0, ((PyObject *)__pyx_kp_s_3));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_3));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_4));
+  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0);
 
-  /* "_cdec.pyx":58
- *     def fromconfig(cls, ini):
- *         cdef dict config = {}
- *         with open(ini) as fp:             # <<<<<<<<<<<<<<
- *             for line in fp:
- *                 line = line.strip()
- */
-  __pyx_k_tuple_5 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_5));
-  __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_5, 0, Py_None);
-  __Pyx_GIVEREF(Py_None);
-  __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_5, 1, Py_None);
-  __Pyx_GIVEREF(Py_None);
-  __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_5, 2, Py_None);
-  __Pyx_GIVEREF(Py_None);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_5));
-
-  /* "_cdec.pyx":67
+  /* "_cdec.pyx":53
  * 
  *     def read_weights(self, cfg):
  *         with open(cfg) as fp:             # <<<<<<<<<<<<<<
  *             for line in fp:
  *                 fname, value = line.split()
  */
-  __pyx_k_tuple_6 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_6));
+  __pyx_k_tuple_1 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_1);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_6, 0, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_1, 0, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_6, 1, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_1, 1, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_6, 2, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_1, 2, Py_None);
   __Pyx_GIVEREF(Py_None);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_6));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_1));
 
-  /* "_cdec.pyx":77
+  /* "_cdec.pyx":62
+ *         if grammar:
  *             self.dec.SetSentenceGrammarFromString(string(<char *> grammar))
- *         #sgml = '<seg grammar="%s">%s</seg>' % (grammar, sentence.encode('utf8'))
- *         sgml = sentence.strip().encode('utf8')             # <<<<<<<<<<<<<<
+ *         inp = sentence.strip().encode('utf8')             # <<<<<<<<<<<<<<
  *         cdef decoder.BasicObserver observer = decoder.BasicObserver()
- *         self.dec.Decode(string(<char *>sgml), &observer)
+ *         self.dec.Decode(string(<char *>inp), &observer)
  */
-  __pyx_k_tuple_7 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_7));
+  __pyx_k_tuple_2 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_2);
   __Pyx_INCREF(((PyObject *)__pyx_n_s__utf8));
-  PyTuple_SET_ITEM(__pyx_k_tuple_7, 0, ((PyObject *)__pyx_n_s__utf8));
+  PyTuple_SET_ITEM(__pyx_k_tuple_2, 0, ((PyObject *)__pyx_n_s__utf8));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__utf8));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_7));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_2));
 
-  /* "_cdec.pyx":100
+  /* "_cdec.pyx":85
  *         hypergraph.ViterbiESentence(self.hg[0], &trans)
  *         cdef str sentence = GetString(trans).c_str()
  *         return sentence.decode('utf8')             # <<<<<<<<<<<<<<
  * 
  *     def viterbi_tree(self):
  */
-  __pyx_k_tuple_8 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_8));
+  __pyx_k_tuple_3 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_3);
   __Pyx_INCREF(((PyObject *)__pyx_n_s__utf8));
-  PyTuple_SET_ITEM(__pyx_k_tuple_8, 0, ((PyObject *)__pyx_n_s__utf8));
+  PyTuple_SET_ITEM(__pyx_k_tuple_3, 0, ((PyObject *)__pyx_n_s__utf8));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__utf8));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_8));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_3));
 
-  /* "_cdec.pyx":105
+  /* "_cdec.pyx":90
  *         assert (self.hg != NULL)
  *         cdef str tree = hypergraph.ViterbiETree(self.hg[0]).c_str()
  *         return tree.decode('utf8')             # <<<<<<<<<<<<<<
  * 
  *     def kbest(self, size):
  */
-  __pyx_k_tuple_9 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_9));
+  __pyx_k_tuple_4 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_4);
   __Pyx_INCREF(((PyObject *)__pyx_n_s__utf8));
-  PyTuple_SET_ITEM(__pyx_k_tuple_9, 0, ((PyObject *)__pyx_n_s__utf8));
+  PyTuple_SET_ITEM(__pyx_k_tuple_4, 0, ((PyObject *)__pyx_n_s__utf8));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__utf8));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_9));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_4));
 
-  /* "_cdec.pyx":117
+  /* "_cdec.pyx":102
  *             if not derivation: break
  *             tree = GetString(derivation._yield).c_str()
  *             yield tree.decode('utf8')             # <<<<<<<<<<<<<<
  *         del derivations
  * 
  */
-  __pyx_k_tuple_10 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 117; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_10));
+  __pyx_k_tuple_5 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_5);
   __Pyx_INCREF(((PyObject *)__pyx_n_s__utf8));
-  PyTuple_SET_ITEM(__pyx_k_tuple_10, 0, ((PyObject *)__pyx_n_s__utf8));
+  PyTuple_SET_ITEM(__pyx_k_tuple_5, 0, ((PyObject *)__pyx_n_s__utf8));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__utf8));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_10));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_5));
 
-  /* "_cdec.pyx":130
+  /* "_cdec.pyx":115
  *             if not derivation: break
  *             sentence = GetString(derivation._yield).c_str()
  *             yield sentence.decode('utf8')             # <<<<<<<<<<<<<<
  *         del derivations
  * 
  */
-  __pyx_k_tuple_11 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_11));
+  __pyx_k_tuple_6 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_6);
   __Pyx_INCREF(((PyObject *)__pyx_n_s__utf8));
-  PyTuple_SET_ITEM(__pyx_k_tuple_11, 0, ((PyObject *)__pyx_n_s__utf8));
+  PyTuple_SET_ITEM(__pyx_k_tuple_6, 0, ((PyObject *)__pyx_n_s__utf8));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__utf8));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_11));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_6));
 
-  /* "_cdec.pyx":147
+  /* "_cdec.pyx":132
  *         for k in range(hypos.size()):
  *             sentence = GetString(hypos[0][k].words).c_str()
  *             yield sentence.decode('utf8')             # <<<<<<<<<<<<<<
  *         del hypos
  * 
  */
-  __pyx_k_tuple_12 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_12));
+  __pyx_k_tuple_7 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_7);
   __Pyx_INCREF(((PyObject *)__pyx_n_s__utf8));
-  PyTuple_SET_ITEM(__pyx_k_tuple_12, 0, ((PyObject *)__pyx_n_s__utf8));
+  PyTuple_SET_ITEM(__pyx_k_tuple_7, 0, ((PyObject *)__pyx_n_s__utf8));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__utf8));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_12));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_7));
   __Pyx_RefNannyFinishContext();
   return 0;
   __pyx_L1_error:;
@@ -5312,12 +5015,18 @@ PyMODINIT_FUNC PyInit__cdec(void)
           Py_FatalError("failed to import 'refnanny' module");
   }
   #endif
-  __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit__cdec(void)");
+  __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit__cdec(void)", 0);
   if ( __Pyx_check_binary_version() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  #ifdef __pyx_binding_PyCFunctionType_USED
-  if (__pyx_binding_PyCFunctionType_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #ifdef __Pyx_CyFunction_USED
+  if (__Pyx_CyFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #endif
+  #ifdef __Pyx_FusedFunction_USED
+  if (__pyx_FusedFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #endif
+  #ifdef __Pyx_Generator_USED
+  if (__pyx_Generator_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   #endif
   /*--- Library function declarations ---*/
   /*--- Threads initialization code ---*/
@@ -5358,25 +5067,19 @@ PyMODINIT_FUNC PyInit__cdec(void)
   if (PyType_Ready(&__pyx_type_5_cdec_Decoder) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__Pyx_SetAttrString(__pyx_m, "Decoder", (PyObject *)&__pyx_type_5_cdec_Decoder) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_5_cdec_Decoder = &__pyx_type_5_cdec_Decoder;
-  if (PyType_Ready(&__pyx_type_5_cdec_Hypergraph) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "Hypergraph", (PyObject *)&__pyx_type_5_cdec_Hypergraph) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_5_cdec_Hypergraph) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "Hypergraph", (PyObject *)&__pyx_type_5_cdec_Hypergraph) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_5_cdec_Hypergraph = &__pyx_type_5_cdec_Hypergraph;
-  if (PyType_Ready(&__pyx_type_5_cdec_Lattice) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 154; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "Lattice", (PyObject *)&__pyx_type_5_cdec_Lattice) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 154; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_5_cdec_Lattice) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "Lattice", (PyObject *)&__pyx_type_5_cdec_Lattice) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_5_cdec_Lattice = &__pyx_type_5_cdec_Lattice;
-  if (PyType_Ready(&__pyx_Generator_type) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5_cdec___pyx_Generator = &__pyx_Generator_type;
-  __pyx_type_5_cdec___pyx_scope_struct____iter__.tp_base = __pyx_ptype_5_cdec___pyx_Generator;
   if (PyType_Ready(&__pyx_type_5_cdec___pyx_scope_struct____iter__) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_5_cdec___pyx_scope_struct____iter__ = &__pyx_type_5_cdec___pyx_scope_struct____iter__;
-  __pyx_type_5_cdec___pyx_scope_struct_1_kbest.tp_base = __pyx_ptype_5_cdec___pyx_Generator;
-  if (PyType_Ready(&__pyx_type_5_cdec___pyx_scope_struct_1_kbest) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_5_cdec___pyx_scope_struct_1_kbest) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_5_cdec___pyx_scope_struct_1_kbest = &__pyx_type_5_cdec___pyx_scope_struct_1_kbest;
-  __pyx_type_5_cdec___pyx_scope_struct_2_kbest_tree.tp_base = __pyx_ptype_5_cdec___pyx_Generator;
-  if (PyType_Ready(&__pyx_type_5_cdec___pyx_scope_struct_2_kbest_tree) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_5_cdec___pyx_scope_struct_2_kbest_tree) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_5_cdec___pyx_scope_struct_2_kbest_tree = &__pyx_type_5_cdec___pyx_scope_struct_2_kbest_tree;
-  __pyx_type_5_cdec___pyx_scope_struct_3_sample.tp_base = __pyx_ptype_5_cdec___pyx_Generator;
-  if (PyType_Ready(&__pyx_type_5_cdec___pyx_scope_struct_3_sample) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 137; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_5_cdec___pyx_scope_struct_3_sample) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_5_cdec___pyx_scope_struct_3_sample = &__pyx_type_5_cdec___pyx_scope_struct_3_sample;
   /*--- Type import code ---*/
   /*--- Variable import code ---*/
@@ -5402,7 +5105,7 @@ PyMODINIT_FUNC PyInit__cdec(void)
   __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  __Pyx_GOTREF(__pyx_t_2);
   __Pyx_INCREF(__pyx_builtin_Exception);
   PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_builtin_Exception);
   __Pyx_GIVEREF(__pyx_builtin_Exception);
@@ -5413,31 +5116,15 @@ PyMODINIT_FUNC PyInit__cdec(void)
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
 
-  /* "_cdec.pyx":56
- * 
- *     @classmethod
- *     def fromconfig(cls, ini):             # <<<<<<<<<<<<<<
- *         cdef dict config = {}
- *         with open(ini) as fp:
- */
-  __pyx_t_1 = __Pyx_GetName((PyObject *)__pyx_ptype_5_cdec_Decoder, __pyx_n_s__fromconfig); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_3 = __Pyx_Method_ClassMethod(__pyx_t_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (PyDict_SetItem((PyObject *)__pyx_ptype_5_cdec_Decoder->tp_dict, __pyx_n_s__fromconfig, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  PyType_Modified(__pyx_ptype_5_cdec_Decoder);
-
   /* "_cdec.pyx":1
  * from libcpp.string cimport string             # <<<<<<<<<<<<<<
  * from libcpp.vector cimport vector
  * from cython.operator cimport dereference as deref
  */
-  __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s____test__, ((PyObject *)__pyx_t_3)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s____test__, ((PyObject *)__pyx_t_1)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
   goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
@@ -5459,7 +5146,6 @@ PyMODINIT_FUNC PyInit__cdec(void)
 }
 
 /* Runtime support code */
-
 #if CYTHON_REFNANNY
 static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) {
     PyObject *m = NULL, *p = NULL;
@@ -5516,7 +5202,6 @@ static int __Pyx_ParseOptionalKeywords(
     Py_ssize_t pos = 0;
     PyObject*** name;
     PyObject*** first_kw_arg = argnames + num_pos_args;
-
     while (PyDict_Next(kwds, &pos, &key, &value)) {
         name = first_kw_arg;
         while (*name && (**name != key)) name++;
@@ -5526,7 +5211,7 @@ static int __Pyx_ParseOptionalKeywords(
             #if PY_MAJOR_VERSION < 3
             if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
             #else
-            if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
+            if (unlikely(!PyUnicode_Check(key))) {
             #endif
                 goto invalid_keyword_type;
             } else {
@@ -5542,7 +5227,6 @@ static int __Pyx_ParseOptionalKeywords(
                 if (*name) {
                     values[name-argnames] = value;
                 } else {
-                    /* unexpected keyword found */
                     for (name=argnames; name != first_kw_arg; name++) {
                         if (**name == key) goto arg_passed_twice;
                         #if PY_MAJOR_VERSION >= 3
@@ -5592,7 +5276,6 @@ static void __Pyx_RaiseArgtupleInvalid(
 {
     Py_ssize_t num_expected;
     const char *more_or_less;
-
     if (num_found < num_min) {
         num_expected = num_min;
         more_or_less = "at least";
@@ -5630,9 +5313,9 @@ static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed
 }
 
 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
+#if CYTHON_COMPILING_IN_CPYTHON
     PyObject *tmp_type, *tmp_value, *tmp_tb;
     PyThreadState *tstate = PyThreadState_GET();
-
     tmp_type = tstate->curexc_type;
     tmp_value = tstate->curexc_value;
     tmp_tb = tstate->curexc_traceback;
@@ -5642,27 +5325,30 @@ static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyOb
     Py_XDECREF(tmp_type);
     Py_XDECREF(tmp_value);
     Py_XDECREF(tmp_tb);
+#else
+    PyErr_Restore(type, value, tb);
+#endif
 }
-
 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
+#if CYTHON_COMPILING_IN_CPYTHON
     PyThreadState *tstate = PyThreadState_GET();
     *type = tstate->curexc_type;
     *value = tstate->curexc_value;
     *tb = tstate->curexc_traceback;
-
     tstate->curexc_type = 0;
     tstate->curexc_value = 0;
     tstate->curexc_traceback = 0;
+#else
+    PyErr_Fetch(type, value, tb);
+#endif
 }
 
-
 #if PY_MAJOR_VERSION < 3
-static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
-    /* cause is unused */
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
+                        CYTHON_UNUSED PyObject *cause) {
     Py_XINCREF(type);
     Py_XINCREF(value);
     Py_XINCREF(tb);
-    /* First, check the traceback argument, replacing None with NULL. */
     if (tb == Py_None) {
         Py_DECREF(tb);
         tb = 0;
@@ -5672,7 +5358,6 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
             "raise: arg 3 must be a traceback or None");
         goto raise_error;
     }
-    /* Next, replace a missing value with None */
     if (value == NULL) {
         value = Py_None;
         Py_INCREF(value);
@@ -5683,13 +5368,11 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
     if (!PyType_Check(type))
     #endif
     {
-        /* Raising an instance.  The value should be a dummy. */
         if (value != Py_None) {
             PyErr_SetString(PyExc_TypeError,
                 "instance exception may not have a separate value");
             goto raise_error;
         }
-        /* Normalize to raise <class>, <instance> */
         Py_DECREF(value);
         value = type;
         #if PY_VERSION_HEX < 0x02050000
@@ -5713,7 +5396,6 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
             }
         #endif
     }
-
     __Pyx_ErrRestore(type, value, tb);
     return;
 raise_error:
@@ -5722,9 +5404,7 @@ raise_error:
     Py_XDECREF(tb);
     return;
 }
-
 #else /* Python 3+ */
-
 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
     if (tb == Py_None) {
         tb = 0;
@@ -5735,7 +5415,6 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
     }
     if (value == Py_None)
         value = 0;
-
     if (PyExceptionInstance_Check(type)) {
         if (value) {
             PyErr_SetString(PyExc_TypeError,
@@ -5749,7 +5428,6 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
             "raise: exception class must be a subclass of BaseException");
         goto bad;
     }
-
     if (cause) {
         PyObject *fixed_cause;
         if (PyExceptionClass_Check(cause)) {
@@ -5772,9 +5450,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
         }
         PyException_SetCause(value, fixed_cause);
     }
-
     PyErr_SetObject(type, value);
-
     if (tb) {
         PyThreadState *tstate = PyThreadState_GET();
         PyObject* tmp_tb = tstate->curexc_traceback;
@@ -5784,7 +5460,6 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
             Py_XDECREF(tmp_tb);
         }
     }
-
 bad:
     return;
 }
@@ -5817,6 +5492,33 @@ static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected) {
     return 0;
 }
 
+static double __Pyx__PyObject_AsDouble(PyObject* obj) {
+    PyObject* float_value;
+    if (Py_TYPE(obj)->tp_as_number && Py_TYPE(obj)->tp_as_number->nb_float) {
+        return PyFloat_AsDouble(obj);
+    } else if (PyUnicode_CheckExact(obj) || PyBytes_CheckExact(obj)) {
+#if PY_MAJOR_VERSION >= 3
+        float_value = PyFloat_FromString(obj);
+#else
+        float_value = PyFloat_FromString(obj, 0);
+#endif
+    } else {
+        PyObject* args = PyTuple_New(1);
+        if (unlikely(!args)) goto bad;
+        PyTuple_SET_ITEM(args, 0, obj);
+        float_value = PyObject_Call((PyObject*)&PyFloat_Type, args, 0);
+        PyTuple_SET_ITEM(args, 0, 0);
+        Py_DECREF(args);
+    }
+    if (likely(float_value)) {
+        double value = PyFloat_AS_DOUBLE(float_value);
+        Py_DECREF(float_value);
+        return value;
+    }
+bad:
+    return (double)-1;
+}
+
 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
     PyObject *local_type, *local_value, *local_tb;
     PyObject *tmp_type, *tmp_value, *tmp_tb;
@@ -5862,34 +5564,6 @@ bad:
     return -1;
 }
 
-
-static double __Pyx__PyObject_AsDouble(PyObject* obj) {
-    PyObject* float_value;
-    if (Py_TYPE(obj)->tp_as_number && Py_TYPE(obj)->tp_as_number->nb_float) {
-        return PyFloat_AsDouble(obj);
-    } else if (PyUnicode_CheckExact(obj) || PyBytes_CheckExact(obj)) {
-#if PY_MAJOR_VERSION >= 3
-        float_value = PyFloat_FromString(obj);
-#else
-        float_value = PyFloat_FromString(obj, 0);
-#endif
-    } else {
-        PyObject* args = PyTuple_New(1);
-        if (unlikely(!args)) goto bad;
-        PyTuple_SET_ITEM(args, 0, obj);
-        float_value = PyObject_Call((PyObject*)&PyFloat_Type, args, 0);
-        PyTuple_SET_ITEM(args, 0, 0);
-        Py_DECREF(args);
-    }
-    if (likely(float_value)) {
-        double value = PyFloat_AS_DOUBLE(float_value);
-        Py_DECREF(float_value);
-        return value;
-    }
-bad:
-    return (double)-1;
-}
-
 static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
     if (unlikely(!type)) {
         PyErr_Format(PyExc_SystemError, "Missing type object");
@@ -5911,7 +5585,6 @@ static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value,
     Py_XINCREF(*value);
     Py_XINCREF(*tb);
 }
-
 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
     PyObject *tmp_type, *tmp_value, *tmp_tb;
     PyThreadState *tstate = PyThreadState_GET();
@@ -5956,10 +5629,8 @@ static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *na
                                    PyObject *modname) {
     PyObject *result;
     PyObject *metaclass;
-
     if (PyDict_SetItemString(dict, "__module__", modname) < 0)
         return NULL;
-
     /* Python2 __metaclass__ */
     metaclass = PyDict_GetItemString(dict, "__metaclass__");
     if (metaclass) {
@@ -5972,38 +5643,41 @@ static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *na
     return result;
 }
 
-static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
-    /* It appears that PyMethodDescr_Type is not anywhere exposed in the Python/C API */
-    static PyTypeObject *methoddescr_type = NULL;
-    if (methoddescr_type == NULL) {
-       PyObject *meth = __Pyx_GetAttrString((PyObject*)&PyList_Type, "append");
-       if (!meth) return NULL;
-       methoddescr_type = Py_TYPE(meth);
-       Py_DECREF(meth);
-    }
-    if (PyObject_TypeCheck(method, methoddescr_type)) { /* cdef classes */
-        PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
-        #if PY_VERSION_HEX < 0x03020000
-        PyTypeObject *d_type = descr->d_type;
-        #else
-        PyTypeObject *d_type = descr->d_common.d_type;
-        #endif
-        return PyDescr_NewClassMethod(d_type, descr->d_method);
-    }
-    else if (PyMethod_Check(method)) { /* python classes */
-        return PyClassMethod_New(PyMethod_GET_FUNCTION(method));
-    }
-    else if (PyCFunction_Check(method)) {
-        return PyClassMethod_New(method);
+static PyObject* __Pyx_Globals() {
+    Py_ssize_t i;
+    /*PyObject *d;*/
+    PyObject *names = NULL;
+    PyObject *globals = PyObject_GetAttrString(__pyx_m, "__dict__");
+    if (!globals) {
+        PyErr_SetString(PyExc_TypeError,
+            "current module must have __dict__ attribute");
+        goto bad;
     }
-#ifdef __pyx_binding_PyCFunctionType_USED
-    else if (PyObject_TypeCheck(method, __pyx_binding_PyCFunctionType)) { /* binded CFunction */
-        return PyClassMethod_New(method);
+    names = PyObject_Dir(__pyx_m);
+    if (!names)
+        goto bad;
+    for (i = 0; i < PyList_GET_SIZE(names); i++) {
+        PyObject* name = PyList_GET_ITEM(names, i);
+        if (!PyDict_Contains(globals, name)) {
+            PyObject* value = PyObject_GetAttr(__pyx_m, PyList_GET_ITEM(names, i));
+            if (!value)
+                goto bad;
+            if (PyDict_SetItem(globals, name, value) < 0) {
+                Py_DECREF(value);
+                goto bad;
+            }
+        }
     }
-#endif
-    PyErr_Format(PyExc_TypeError,
-                 "Class-level classmethod() can only be called on "
-                 "a method_descriptor or instance method.");
+    Py_DECREF(names);
+    return globals;
+    /*
+    d = PyDictProxy_New(globals);
+    Py_DECREF(globals);
+    return d;
+    */
+bad:
+    Py_XDECREF(names);
+    Py_XDECREF(globals);
     return NULL;
 }
 
@@ -6410,86 +6084,79 @@ static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject*
 static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb) {
     PyObject *tmp_type, *tmp_value, *tmp_tb;
     PyThreadState *tstate = PyThreadState_GET();
-
     tmp_type = tstate->exc_type;
     tmp_value = tstate->exc_value;
     tmp_tb = tstate->exc_traceback;
-
     tstate->exc_type = *type;
     tstate->exc_value = *value;
     tstate->exc_traceback = *tb;
-
     *type = tmp_type;
     *value = tmp_value;
     *tb = tmp_tb;
 }
 
-static CYTHON_INLINE void __Pyx_Generator_ExceptionClear(struct __pyx_Generator_object *self)
+static PyObject *__Pyx_Generator_Next(PyObject *self);
+static PyObject *__Pyx_Generator_Send(PyObject *self, PyObject *value);
+static PyObject *__Pyx_Generator_Close(PyObject *self);
+static PyObject *__Pyx_Generator_Throw(PyObject *gen, PyObject *args);
+static CYTHON_INLINE
+void __Pyx_Generator_ExceptionClear(__pyx_GeneratorObject *self)
 {
-    Py_XDECREF(self->exc_type);
-    Py_XDECREF(self->exc_value);
-    Py_XDECREF(self->exc_traceback);
-
+    PyObject *exc_type = self->exc_type;
+    PyObject *exc_value = self->exc_value;
+    PyObject *exc_traceback = self->exc_traceback;
     self->exc_type = NULL;
     self->exc_value = NULL;
     self->exc_traceback = NULL;
+    Py_XDECREF(exc_type);
+    Py_XDECREF(exc_value);
+    Py_XDECREF(exc_traceback);
 }
-
-static CYTHON_INLINE PyObject *__Pyx_Generator_SendEx(struct __pyx_Generator_object *self, PyObject *value)
+static CYTHON_INLINE
+PyObject *__Pyx_Generator_SendEx(__pyx_GeneratorObject *self, PyObject *value)
 {
     PyObject *retval;
-
-    if (self->is_running) {
+    if (unlikely(self->is_running)) {
         PyErr_SetString(PyExc_ValueError,
                         "generator already executing");
         return NULL;
     }
-
-    if (self->resume_label == 0) {
-        if (value && value != Py_None) {
+    if (unlikely(self->resume_label == 0)) {
+        if (unlikely(value && value != Py_None)) {
             PyErr_SetString(PyExc_TypeError,
                             "can't send non-None value to a "
                             "just-started generator");
             return NULL;
         }
     }
-
-    if (self->resume_label == -1) {
+    if (unlikely(self->resume_label == -1)) {
         PyErr_SetNone(PyExc_StopIteration);
         return NULL;
     }
-
-
     if (value)
         __Pyx_ExceptionSwap(&self->exc_type, &self->exc_value, &self->exc_traceback);
     else
         __Pyx_Generator_ExceptionClear(self);
-
     self->is_running = 1;
     retval = self->body((PyObject *) self, value);
     self->is_running = 0;
-
     if (retval)
         __Pyx_ExceptionSwap(&self->exc_type, &self->exc_value, &self->exc_traceback);
     else
         __Pyx_Generator_ExceptionClear(self);
-
     return retval;
 }
-
 static PyObject *__Pyx_Generator_Next(PyObject *self)
 {
-    return __Pyx_Generator_SendEx((struct __pyx_Generator_object *) self, Py_None);
+    return __Pyx_Generator_SendEx((__pyx_GeneratorObject *) self, Py_None);
 }
-
 static PyObject *__Pyx_Generator_Send(PyObject *self, PyObject *value)
 {
-    return __Pyx_Generator_SendEx((struct __pyx_Generator_object *) self, value);
+    return __Pyx_Generator_SendEx((__pyx_GeneratorObject *) self, value);
 }
-
 static PyObject *__Pyx_Generator_Close(PyObject *self)
 {
-    struct __pyx_Generator_object *generator = (struct __pyx_Generator_object *) self;
+    __pyx_GeneratorObject *generator = (__pyx_GeneratorObject *) self;
     PyObject *retval;
 #if PY_VERSION_HEX < 0x02050000
     PyErr_SetNone(PyExc_StopIteration);
@@ -6516,19 +6183,190 @@ static PyObject *__Pyx_Generator_Close(PyObject *self)
     }
     return NULL;
 }
-
-static PyObject *__Pyx_Generator_Throw(PyObject *self, PyObject *args, CYTHON_UNUSED PyObject *kwds)
+static PyObject *__Pyx_Generator_Throw(PyObject *self, PyObject *args)
 {
-    struct __pyx_Generator_object *generator = (struct __pyx_Generator_object *) self;
+    __pyx_GeneratorObject *generator = (__pyx_GeneratorObject *) self;
     PyObject *typ;
     PyObject *tb = NULL;
     PyObject *val = NULL;
-
     if (!PyArg_UnpackTuple(args, (char *)"throw", 1, 3, &typ, &val, &tb))
         return NULL;
     __Pyx_Raise(typ, val, tb, NULL);
     return __Pyx_Generator_SendEx(generator, NULL);
 }
+static int
+__Pyx_Generator_traverse(PyObject *self, visitproc visit, void *arg)
+{
+    __pyx_GeneratorObject *gen = (__pyx_GeneratorObject *) self;
+    Py_VISIT(gen->closure);
+    Py_VISIT(gen->classobj);
+    Py_VISIT(gen->exc_type);
+    Py_VISIT(gen->exc_value);
+    Py_VISIT(gen->exc_traceback);
+    return 0;
+}
+static void
+__Pyx_Generator_dealloc(PyObject *self)
+{
+    __pyx_GeneratorObject *gen = (__pyx_GeneratorObject *) self;
+    PyObject_GC_UnTrack(gen);
+    if (gen->gi_weakreflist != NULL)
+        PyObject_ClearWeakRefs(self);
+    PyObject_GC_Track(self);
+    if (gen->resume_label > 0) {
+        Py_TYPE(gen)->tp_del(self);
+        if (self->ob_refcnt > 0)
+            return;                     /* resurrected.  :( */
+    }
+    PyObject_GC_UnTrack(self);
+    Py_CLEAR(gen->closure);
+    Py_CLEAR(gen->classobj);
+    Py_CLEAR(gen->exc_type);
+    Py_CLEAR(gen->exc_value);
+    Py_CLEAR(gen->exc_traceback);
+    PyObject_GC_Del(gen);
+}
+static void
+__Pyx_Generator_del(PyObject *self)
+{
+    PyObject *res;
+    PyObject *error_type, *error_value, *error_traceback;
+    __pyx_GeneratorObject *gen = (__pyx_GeneratorObject *) self;
+    if (gen->resume_label <= 0)
+        return ;
+    assert(self->ob_refcnt == 0);
+    self->ob_refcnt = 1;
+    __Pyx_ErrFetch(&error_type, &error_value, &error_traceback);
+    res = __Pyx_Generator_Close(self);
+    if (res == NULL)
+        PyErr_WriteUnraisable(self);
+    else
+        Py_DECREF(res);
+    __Pyx_ErrRestore(error_type, error_value, error_traceback);
+    /* Undo the temporary resurrection; can't use DECREF here, it would
+     * cause a recursive call.
+     */
+    assert(self->ob_refcnt > 0);
+    if (--self->ob_refcnt == 0)
+        return; /* this is the normal path out */
+    /* close() resurrected it!  Make it look like the original Py_DECREF
+     * never happened.
+     */
+    {
+        Py_ssize_t refcnt = self->ob_refcnt;
+        _Py_NewReference(self);
+        self->ob_refcnt = refcnt;
+    }
+    assert(PyType_IS_GC(self->ob_type) &&
+           _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
+    /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
+     * we need to undo that. */
+    _Py_DEC_REFTOTAL;
+    /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
+     * chain, so no more to do there.
+     * If COUNT_ALLOCS, the original decref bumped tp_frees, and
+     * _Py_NewReference bumped tp_allocs:  both of those need to be
+     * undone.
+     */
+#ifdef COUNT_ALLOCS
+    --self->ob_type->tp_frees;
+    --self->ob_type->tp_allocs;
+#endif
+}
+static PyMemberDef __pyx_Generator_memberlist[] = {
+    {(char *) "gi_running",
+     T_INT,
+     offsetof(__pyx_GeneratorObject, is_running),
+     READONLY,
+     NULL},
+    {0, 0, 0, 0, 0}
+};
+static PyMethodDef __pyx_Generator_methods[] = {
+    {__Pyx_NAMESTR("send"), (PyCFunction) __Pyx_Generator_Send, METH_O, 0},
+    {__Pyx_NAMESTR("throw"), (PyCFunction) __Pyx_Generator_Throw, METH_VARARGS, 0},
+    {__Pyx_NAMESTR("close"), (PyCFunction) __Pyx_Generator_Close, METH_NOARGS, 0},
+    {0, 0, 0, 0}
+};
+static PyTypeObject __pyx_GeneratorType = {
+    PyVarObject_HEAD_INIT(0, 0)
+    __Pyx_NAMESTR("generator"),         /*tp_name*/
+    sizeof(__pyx_GeneratorObject),      /*tp_basicsize*/
+    0,                                  /*tp_itemsize*/
+    (destructor) __Pyx_Generator_dealloc,/*tp_dealloc*/
+    0,                                  /*tp_print*/
+    0,                                  /*tp_getattr*/
+    0,                                  /*tp_setattr*/
+#if PY_MAJOR_VERSION < 3
+    0,                                  /*tp_compare*/
+#else
+    0,                                  /*reserved*/
+#endif
+    0,                                   /*tp_repr*/
+    0,                                  /*tp_as_number*/
+    0,                                  /*tp_as_sequence*/
+    0,                                  /*tp_as_mapping*/
+    0,                                  /*tp_hash*/
+    0,                                  /*tp_call*/
+    0,                                  /*tp_str*/
+    PyObject_GenericGetAttr,            /*tp_getattro*/
+    0,                                  /*tp_setattro*/
+    0,                                  /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags*/
+    0,                                  /*tp_doc*/
+    (traverseproc) __Pyx_Generator_traverse,   /*tp_traverse*/
+    0,                                  /*tp_clear*/
+    0,                                  /*tp_richcompare*/
+    offsetof(__pyx_GeneratorObject, gi_weakreflist), /* tp_weaklistoffse */
+    PyObject_SelfIter,                  /*tp_iter*/
+    (iternextfunc) __Pyx_Generator_Next, /*tp_iternext*/
+    __pyx_Generator_methods,            /*tp_methods*/
+    __pyx_Generator_memberlist,         /*tp_members*/
+    0,                                  /*tp_getset*/
+    0,                                  /*tp_base*/
+    0,                                  /*tp_dict*/
+    0,                                  /*tp_descr_get*/
+    0,                                  /*tp_descr_set*/
+    0,                                  /*tp_dictoffset*/
+    0,                                  /*tp_init*/
+    0,                                  /*tp_alloc*/
+    0,                                  /*tp_new*/
+    0,                                  /*tp_free*/
+    0,                                  /*tp_is_gc*/
+    0,                                  /*tp_bases*/
+    0,                                  /*tp_mro*/
+    0,                                  /*tp_cache*/
+    0,                                  /*tp_subclasses*/
+    0,                                  /*tp_weaklist*/
+    __Pyx_Generator_del,                /*tp_del*/
+#if PY_VERSION_HEX >= 0x02060000
+    0,                                  /*tp_version_tag*/
+#endif
+};
+static
+__pyx_GeneratorObject *__Pyx_Generator_New(__pyx_generator_body_t body,
+                                           PyObject *closure)
+{
+    __pyx_GeneratorObject *gen =
+        PyObject_GC_New(__pyx_GeneratorObject, &__pyx_GeneratorType);
+    if (gen == NULL)
+        return NULL;
+    gen->body = body;
+    gen->closure = closure;
+    Py_XINCREF(closure);
+    gen->is_running = 0;
+    gen->resume_label = 0;
+    gen->classobj = NULL;
+    gen->exc_type = NULL;
+    gen->exc_value = NULL;
+    gen->exc_traceback = NULL;
+    gen->gi_weakreflist = NULL;
+    PyObject_GC_Track(gen);
+    return gen;
+}
+static int __pyx_Generator_init(void)
+{
+    return PyType_Ready(&__pyx_GeneratorType);
+}
 
 static int __Pyx_check_binary_version(void) {
     char ctversion[4], rtversion[4];
@@ -6549,29 +6387,105 @@ static int __Pyx_check_binary_version(void) {
     return 0;
 }
 
+static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) {
+    int start = 0, mid = 0, end = count - 1;
+    if (end >= 0 && code_line > entries[end].code_line) {
+        return count;
+    }
+    while (start < end) {
+        mid = (start + end) / 2;
+        if (code_line < entries[mid].code_line) {
+            end = mid;
+        } else if (code_line > entries[mid].code_line) {
+             start = mid + 1;
+        } else {
+            return mid;
+        }
+    }
+    if (code_line <= entries[mid].code_line) {
+        return mid;
+    } else {
+        return mid + 1;
+    }
+}
+static PyCodeObject *__pyx_find_code_object(int code_line) {
+    PyCodeObject* code_object;
+    int pos;
+    if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) {
+        return NULL;
+    }
+    pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
+    if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) {
+        return NULL;
+    }
+    code_object = __pyx_code_cache.entries[pos].code_object;
+    Py_INCREF(code_object);
+    return code_object;
+}
+static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) {
+    int pos, i;
+    __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries;
+    if (unlikely(!code_line)) {
+        return;
+    }
+    if (unlikely(!entries)) {
+        entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry));
+        if (likely(entries)) {
+            __pyx_code_cache.entries = entries;
+            __pyx_code_cache.max_count = 64;
+            __pyx_code_cache.count = 1;
+            entries[0].code_line = code_line;
+            entries[0].code_object = code_object;
+            Py_INCREF(code_object);
+        }
+        return;
+    }
+    pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
+    if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) {
+        PyCodeObject* tmp = entries[pos].code_object;
+        entries[pos].code_object = code_object;
+        Py_DECREF(tmp);
+        return;
+    }
+    if (__pyx_code_cache.count == __pyx_code_cache.max_count) {
+        int new_max = __pyx_code_cache.max_count + 64;
+        entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc(
+            __pyx_code_cache.entries, new_max*sizeof(__Pyx_CodeObjectCacheEntry));
+        if (unlikely(!entries)) {
+            return;
+        }
+        __pyx_code_cache.entries = entries;
+        __pyx_code_cache.max_count = new_max;
+    }
+    for (i=__pyx_code_cache.count; i>pos; i--) {
+        entries[i] = entries[i-1];
+    }
+    entries[pos].code_line = code_line;
+    entries[pos].code_object = code_object;
+    __pyx_code_cache.count++;
+    Py_INCREF(code_object);
+}
+
 #include "compile.h"
 #include "frameobject.h"
 #include "traceback.h"
-
-static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno,
-                               int __pyx_lineno, const char *__pyx_filename) {
+static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
+            const char *funcname, int c_line,
+            int py_line, const char *filename) {
+    PyCodeObject *py_code = 0;
     PyObject *py_srcfile = 0;
     PyObject *py_funcname = 0;
-    PyObject *py_globals = 0;
-    PyCodeObject *py_code = 0;
-    PyFrameObject *py_frame = 0;
-
     #if PY_MAJOR_VERSION < 3
-    py_srcfile = PyString_FromString(__pyx_filename);
+    py_srcfile = PyString_FromString(filename);
     #else
-    py_srcfile = PyUnicode_FromString(__pyx_filename);
+    py_srcfile = PyUnicode_FromString(filename);
     #endif
     if (!py_srcfile) goto bad;
-    if (__pyx_clineno) {
+    if (c_line) {
         #if PY_MAJOR_VERSION < 3
-        py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno);
+        py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
         #else
-        py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno);
+        py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
         #endif
     }
     else {
@@ -6582,28 +6496,45 @@ static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno,
         #endif
     }
     if (!py_funcname) goto bad;
-    py_globals = PyModule_GetDict(__pyx_m);
-    if (!py_globals) goto bad;
-    py_code = PyCode_New(
+    py_code = __Pyx_PyCode_New(
         0,            /*int argcount,*/
-        #if PY_MAJOR_VERSION >= 3
         0,            /*int kwonlyargcount,*/
-        #endif
         0,            /*int nlocals,*/
         0,            /*int stacksize,*/
         0,            /*int flags,*/
         __pyx_empty_bytes, /*PyObject *code,*/
-        __pyx_empty_tuple,  /*PyObject *consts,*/
-        __pyx_empty_tuple,  /*PyObject *names,*/
-        __pyx_empty_tuple,  /*PyObject *varnames,*/
-        __pyx_empty_tuple,  /*PyObject *freevars,*/
-        __pyx_empty_tuple,  /*PyObject *cellvars,*/
+        __pyx_empty_tuple, /*PyObject *consts,*/
+        __pyx_empty_tuple, /*PyObject *names,*/
+        __pyx_empty_tuple, /*PyObject *varnames,*/
+        __pyx_empty_tuple, /*PyObject *freevars,*/
+        __pyx_empty_tuple, /*PyObject *cellvars,*/
         py_srcfile,   /*PyObject *filename,*/
         py_funcname,  /*PyObject *name,*/
-        __pyx_lineno,   /*int firstlineno,*/
+        py_line,      /*int firstlineno,*/
         __pyx_empty_bytes  /*PyObject *lnotab*/
     );
-    if (!py_code) goto bad;
+    Py_DECREF(py_srcfile);
+    Py_DECREF(py_funcname);
+    return py_code;
+bad:
+    Py_XDECREF(py_srcfile);
+    Py_XDECREF(py_funcname);
+    return NULL;
+}
+static void __Pyx_AddTraceback(const char *funcname, int c_line,
+                               int py_line, const char *filename) {
+    PyCodeObject *py_code = 0;
+    PyObject *py_globals = 0;
+    PyFrameObject *py_frame = 0;
+    py_code = __pyx_find_code_object(c_line ? c_line : py_line);
+    if (!py_code) {
+        py_code = __Pyx_CreateCodeObjectForTraceback(
+            funcname, c_line, py_line, filename);
+        if (!py_code) goto bad;
+        __pyx_insert_code_object(c_line ? c_line : py_line, py_code);
+    }
+    py_globals = PyModule_GetDict(__pyx_m);
+    if (!py_globals) goto bad;
     py_frame = PyFrame_New(
         PyThreadState_GET(), /*PyThreadState *tstate,*/
         py_code,             /*PyCodeObject *code,*/
@@ -6611,11 +6542,9 @@ static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno,
         0                    /*PyObject *locals*/
     );
     if (!py_frame) goto bad;
-    py_frame->f_lineno = __pyx_lineno;
+    py_frame->f_lineno = py_line;
     PyTraceBack_Here(py_frame);
 bad:
-    Py_XDECREF(py_srcfile);
-    Py_XDECREF(py_funcname);
     Py_XDECREF(py_code);
     Py_XDECREF(py_frame);
 }
@@ -6650,6 +6579,7 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
     return 0;
 }
 
+
 /* Type Conversion Functions */
 
 static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
diff --git a/python/src/_cdec.pyx b/python/src/_cdec.pyx
index 45320c46..664724dd 100644
--- a/python/src/_cdec.pyx
+++ b/python/src/_cdec.pyx
@@ -41,28 +41,14 @@ cdef class Decoder:
 
     def __cinit__(self, char* config):
         decoder.register_feature_functions()
-        cdef istringstream* config_stream = new istringstream(config) # ConfigStream(kwargs)
-        #cdef ReadFile* config_file = new ReadFile(string(config))
-        #cdef istream* config_stream = config_file.stream()
+        cdef istringstream* config_stream = new istringstream(config)
         self.dec = new decoder.Decoder(config_stream)
         del config_stream
-        #del config_file
         self.weights = Weights(self)
 
     def __dealloc__(self):
         del self.dec
 
-    @classmethod
-    def fromconfig(cls, ini):
-        cdef dict config = {}
-        with open(ini) as fp:
-            for line in fp:
-                line = line.strip()
-                if not line or line.startswith('#'): continue
-                param, value = line.split('=')
-                config[param.strip()] = value.strip()
-        return cls(**config)
-
     def read_weights(self, cfg):
         with open(cfg) as fp:
             for line in fp:
@@ -73,10 +59,9 @@ cdef class Decoder:
     def translate(self, unicode sentence, grammar=None):
         if grammar:
             self.dec.SetSentenceGrammarFromString(string(<char *> grammar))
-        #sgml = '<seg grammar="%s">%s</seg>' % (grammar, sentence.encode('utf8'))
-        sgml = sentence.strip().encode('utf8')
+        inp = sentence.strip().encode('utf8')
         cdef decoder.BasicObserver observer = decoder.BasicObserver()
-        self.dec.Decode(string(<char *>sgml), &observer)
+        self.dec.Decode(string(<char *>inp), &observer)
         if observer.hypergraph == NULL:
             raise ParseFailed()
         cdef Hypergraph hg = Hypergraph()
@@ -169,12 +154,3 @@ cdef class Lattice:
         del self.lattice
 
 # TODO: wrap SparseVector
-
-"""
-def params_str(params):
-    return '\n'.join('%s=%s' % (param, value) for param, value in params.iteritems())
-
-cdef istringstream* ConfigStream(dict params):
-    ini = params_str(params)
-    return new istringstream(<char *> ini)
-"""
-- 
cgit v1.2.3