Generated by Cython 0.29.21

Yellow lines hint at Python interaction.
Click on a line that starts with a "+" to see the C code that Cython generated for it.

Raw output: kernel_evaluations.c

+001: #!/usr/bin/env python 
  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 002: 
 003: # cython: language_level=3
 004: # cython: profile=True
 005: 
+006: __author__ = 'Florian Hase, Matteo Aldeghi'
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_author, __pyx_kp_u_Florian_Hase_Matteo_Aldeghi) < 0) __PYX_ERR(0, 6, __pyx_L1_error)
 007: 
 008: import  cython
 009: cimport cython
+010: import  numpy as np
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 10, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 10, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 011: cimport numpy as np
 012: from libc.math cimport exp, round
 013: 
 014: 
 015: # ==================
 016: # Distance functions
 017: # ==================
 018: @cython.cdivision(True)
+019: cdef double _gauss(double x, double loc, double sqrt_prec):
static double __pyx_f_7gryffin_16bayesian_network_18kernel_evaluations__gauss(double __pyx_v_x, double __pyx_v_loc, double __pyx_v_sqrt_prec) {
  double __pyx_v_argument;
  double __pyx_v_result;
  double __pyx_r;
  __Pyx_TraceDeclarations
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_gauss", 0);
  __Pyx_TraceCall("_gauss", __pyx_f[0], 19, 0, __PYX_ERR(0, 19, __pyx_L1_error));
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_WriteUnraisable("gryffin.bayesian_network.kernel_evaluations._gauss", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_TraceReturn(Py_None, 0);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 020:     cdef double argument, result
+021:     argument = 0.5 * (sqrt_prec * (x - loc))**2
  __pyx_v_argument = (0.5 * pow((__pyx_v_sqrt_prec * (__pyx_v_x - __pyx_v_loc)), 2.0));
+022:     if argument > 200.:
  __pyx_t_1 = ((__pyx_v_argument > 200.) != 0);
  if (__pyx_t_1) {
/* … */
    goto __pyx_L3;
  }
+023:         result = 0.
    __pyx_v_result = 0.;
 024:     else:
+025:         result = exp(-argument) * sqrt_prec * 0.3989422804014327  # the number is 1. / np.sqrt(2 * np.pi)
  /*else*/ {
    __pyx_v_result = ((exp((-__pyx_v_argument)) * __pyx_v_sqrt_prec) * 0.3989422804014327);
  }
  __pyx_L3:;
+026:     return result
  __pyx_r = __pyx_v_result;
  goto __pyx_L0;
 027: 
 028: 
 029: @cython.cdivision(True)
+030: cdef double _gauss_periodic(double x, double loc, double sqrt_prec, double var_range):
static double __pyx_f_7gryffin_16bayesian_network_18kernel_evaluations__gauss_periodic(double __pyx_v_x, double __pyx_v_loc, double __pyx_v_sqrt_prec, double __pyx_v_var_range) {
  double __pyx_v_argument;
  double __pyx_v_result;
  double __pyx_v_distance;
  double __pyx_r;
  __Pyx_TraceDeclarations
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_gauss_periodic", 0);
  __Pyx_TraceCall("_gauss_periodic", __pyx_f[0], 30, 0, __PYX_ERR(0, 30, __pyx_L1_error));
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_WriteUnraisable("gryffin.bayesian_network.kernel_evaluations._gauss_periodic", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_TraceReturn(Py_None, 0);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 031: 
 032:     cdef double argument, result, distance
 033: 
+034:     distance = abs(x - loc)
  __pyx_v_distance = fabs((__pyx_v_x - __pyx_v_loc));
+035:     if var_range - distance < distance:
  __pyx_t_1 = (((__pyx_v_var_range - __pyx_v_distance) < __pyx_v_distance) != 0);
  if (__pyx_t_1) {
/* … */
  }
+036:         distance = var_range - distance
    __pyx_v_distance = (__pyx_v_var_range - __pyx_v_distance);
 037: 
+038:     argument = 0.5 * (distance * sqrt_prec)**2
  __pyx_v_argument = (0.5 * pow((__pyx_v_distance * __pyx_v_sqrt_prec), 2.0));
+039:     if argument > 200.:
  __pyx_t_1 = ((__pyx_v_argument > 200.) != 0);
  if (__pyx_t_1) {
/* … */
    goto __pyx_L4;
  }
+040:         result = 0.
    __pyx_v_result = 0.;
 041:     else:
+042:         result = exp(-argument) * sqrt_prec * 0.3989422804014327  # the number is 1. / np.sqrt(2 * np.pi)
  /*else*/ {
    __pyx_v_result = ((exp((-__pyx_v_argument)) * __pyx_v_sqrt_prec) * 0.3989422804014327);
  }
  __pyx_L4:;
+043:     return result
  __pyx_r = __pyx_v_result;
  goto __pyx_L0;
 044: 
 045: 
 046: # ==========
 047: # Main Class
 048: # ==========
+049: cdef class KernelEvaluator:
struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator {
  PyObject_HEAD
  struct __pyx_vtabstruct_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *__pyx_vtab;
  int num_samples;
  int num_obs;
  int num_kernels;
  int num_cats;
  int num_continuous;
  double lower_prob_bound;
  double inv_vol;
  PyArrayObject *np_locs;
  PyArrayObject *np_sqrt_precs;
  PyArrayObject *np_cat_probs;
  PyArrayObject *np_kernel_types;
  PyArrayObject *np_kernel_sizes;
  PyArrayObject *np_kernel_ranges;
  PyArrayObject *np_objs;
  PyArrayObject *np_probs;
};
/* … */
struct __pyx_vtabstruct_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator {
  __Pyx_memviewslice (*_probs)(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *, __Pyx_memviewslice);
  PyObject *(*get_kernel_contrib)(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *, PyArrayObject *, int __pyx_skip_dispatch);
  PyObject *(*get_regression_surrogate)(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *, PyArrayObject *, int __pyx_skip_dispatch);
  PyObject *(*get_binary_kernel_densities)(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *, PyArrayObject *, int __pyx_skip_dispatch);
  PyObject *(*get_probability_of_infeasibility)(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *, PyArrayObject *, double, double, int __pyx_skip_dispatch);
  PyObject *(*get_probability_of_feasibility)(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *, PyArrayObject *, double, double, int __pyx_skip_dispatch);
};
static struct __pyx_vtabstruct_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *__pyx_vtabptr_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator;

 050: 
 051:     cdef int num_samples, num_obs, num_kernels, num_cats, num_continuous
 052:     cdef double lower_prob_bound, inv_vol
 053: 
 054:     cdef np.ndarray np_locs, np_sqrt_precs, np_cat_probs
 055:     cdef np.ndarray np_kernel_types, np_kernel_sizes, np_kernel_ranges
 056:     cdef np.ndarray np_objs
 057:     cdef np.ndarray np_probs
 058: 
+059:     var_dict = {}
  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 59, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem((PyObject *)__pyx_ptype_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator->tp_dict, __pyx_n_s_var_dict, __pyx_t_1) < 0) __PYX_ERR(0, 59, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  PyType_Modified(__pyx_ptype_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator);
 060: 
+061:     def __init__(self, locs, sqrt_precs, cat_probs, kernel_types, kernel_sizes, kernel_ranges,
/* Python wrapper */
static int __pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static int __pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_locs = 0;
  PyObject *__pyx_v_sqrt_precs = 0;
  PyObject *__pyx_v_cat_probs = 0;
  PyObject *__pyx_v_kernel_types = 0;
  PyObject *__pyx_v_kernel_sizes = 0;
  PyObject *__pyx_v_kernel_ranges = 0;
  PyObject *__pyx_v_lower_prob_bound = 0;
  PyObject *__pyx_v_objs = 0;
  PyObject *__pyx_v_inv_vol = 0;
  int __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_locs,&__pyx_n_s_sqrt_precs,&__pyx_n_s_cat_probs,&__pyx_n_s_kernel_types,&__pyx_n_s_kernel_sizes,&__pyx_n_s_kernel_ranges,&__pyx_n_s_lower_prob_bound,&__pyx_n_s_objs,&__pyx_n_s_inv_vol,0};
    PyObject* values[9] = {0,0,0,0,0,0,0,0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  9: values[8] = PyTuple_GET_ITEM(__pyx_args, 8);
        CYTHON_FALLTHROUGH;
        case  8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
        CYTHON_FALLTHROUGH;
        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
        CYTHON_FALLTHROUGH;
        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
        CYTHON_FALLTHROUGH;
        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
        CYTHON_FALLTHROUGH;
        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
        CYTHON_FALLTHROUGH;
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_locs)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_sqrt_precs)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("__init__", 1, 9, 9, 1); __PYX_ERR(0, 61, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_cat_probs)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("__init__", 1, 9, 9, 2); __PYX_ERR(0, 61, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  3:
        if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_kernel_types)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("__init__", 1, 9, 9, 3); __PYX_ERR(0, 61, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  4:
        if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_kernel_sizes)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("__init__", 1, 9, 9, 4); __PYX_ERR(0, 61, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  5:
        if (likely((values[5] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_kernel_ranges)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("__init__", 1, 9, 9, 5); __PYX_ERR(0, 61, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  6:
        if (likely((values[6] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lower_prob_bound)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("__init__", 1, 9, 9, 6); __PYX_ERR(0, 61, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  7:
        if (likely((values[7] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_objs)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("__init__", 1, 9, 9, 7); __PYX_ERR(0, 61, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  8:
        if (likely((values[8] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_inv_vol)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("__init__", 1, 9, 9, 8); __PYX_ERR(0, 61, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 61, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 9) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
      values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
      values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
      values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
      values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
      values[8] = PyTuple_GET_ITEM(__pyx_args, 8);
    }
    __pyx_v_locs = values[0];
    __pyx_v_sqrt_precs = values[1];
    __pyx_v_cat_probs = values[2];
    __pyx_v_kernel_types = values[3];
    __pyx_v_kernel_sizes = values[4];
    __pyx_v_kernel_ranges = values[5];
    __pyx_v_lower_prob_bound = values[6];
    __pyx_v_objs = values[7];
    __pyx_v_inv_vol = values[8];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("__init__", 1, 9, 9, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 61, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("gryffin.bayesian_network.kernel_evaluations.KernelEvaluator.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return -1;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator___init__(((struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *)__pyx_v_self), __pyx_v_locs, __pyx_v_sqrt_precs, __pyx_v_cat_probs, __pyx_v_kernel_types, __pyx_v_kernel_sizes, __pyx_v_kernel_ranges, __pyx_v_lower_prob_bound, __pyx_v_objs, __pyx_v_inv_vol);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static int __pyx_pf_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator___init__(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *__pyx_v_self, PyObject *__pyx_v_locs, PyObject *__pyx_v_sqrt_precs, PyObject *__pyx_v_cat_probs, PyObject *__pyx_v_kernel_types, PyObject *__pyx_v_kernel_sizes, PyObject *__pyx_v_kernel_ranges, PyObject *__pyx_v_lower_prob_bound, PyObject *__pyx_v_objs, PyObject *__pyx_v_inv_vol) {
  int __pyx_r;
  __Pyx_TraceDeclarations
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__init__", 0);
  __Pyx_TraceCall("__init__", __pyx_f[0], 61, 0, __PYX_ERR(0, 61, __pyx_L1_error));
/* … */
  /* function exit code */
  __pyx_r = 0;
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_AddTraceback("gryffin.bayesian_network.kernel_evaluations.KernelEvaluator.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = -1;
  __pyx_L0:;
  __Pyx_TraceReturn(Py_None, 0);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 062:                  lower_prob_bound, objs, inv_vol):
 063: 
+064:         self.np_locs          = locs
  if (!(likely(((__pyx_v_locs) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_locs, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 64, __pyx_L1_error)
  __pyx_t_1 = __pyx_v_locs;
  __Pyx_INCREF(__pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_1);
  __Pyx_GOTREF(__pyx_v_self->np_locs);
  __Pyx_DECREF(((PyObject *)__pyx_v_self->np_locs));
  __pyx_v_self->np_locs = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
+065:         self.np_sqrt_precs    = sqrt_precs
  if (!(likely(((__pyx_v_sqrt_precs) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_sqrt_precs, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 65, __pyx_L1_error)
  __pyx_t_1 = __pyx_v_sqrt_precs;
  __Pyx_INCREF(__pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_1);
  __Pyx_GOTREF(__pyx_v_self->np_sqrt_precs);
  __Pyx_DECREF(((PyObject *)__pyx_v_self->np_sqrt_precs));
  __pyx_v_self->np_sqrt_precs = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
+066:         self.np_cat_probs     = cat_probs
  if (!(likely(((__pyx_v_cat_probs) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_cat_probs, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 66, __pyx_L1_error)
  __pyx_t_1 = __pyx_v_cat_probs;
  __Pyx_INCREF(__pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_1);
  __Pyx_GOTREF(__pyx_v_self->np_cat_probs);
  __Pyx_DECREF(((PyObject *)__pyx_v_self->np_cat_probs));
  __pyx_v_self->np_cat_probs = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
+067:         self.np_kernel_types  = kernel_types
  if (!(likely(((__pyx_v_kernel_types) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_kernel_types, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 67, __pyx_L1_error)
  __pyx_t_1 = __pyx_v_kernel_types;
  __Pyx_INCREF(__pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_1);
  __Pyx_GOTREF(__pyx_v_self->np_kernel_types);
  __Pyx_DECREF(((PyObject *)__pyx_v_self->np_kernel_types));
  __pyx_v_self->np_kernel_types = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
+068:         self.np_kernel_sizes  = kernel_sizes
  if (!(likely(((__pyx_v_kernel_sizes) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_kernel_sizes, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 68, __pyx_L1_error)
  __pyx_t_1 = __pyx_v_kernel_sizes;
  __Pyx_INCREF(__pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_1);
  __Pyx_GOTREF(__pyx_v_self->np_kernel_sizes);
  __Pyx_DECREF(((PyObject *)__pyx_v_self->np_kernel_sizes));
  __pyx_v_self->np_kernel_sizes = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
+069:         self.np_kernel_ranges = kernel_ranges
  if (!(likely(((__pyx_v_kernel_ranges) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_kernel_ranges, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 69, __pyx_L1_error)
  __pyx_t_1 = __pyx_v_kernel_ranges;
  __Pyx_INCREF(__pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_1);
  __Pyx_GOTREF(__pyx_v_self->np_kernel_ranges);
  __Pyx_DECREF(((PyObject *)__pyx_v_self->np_kernel_ranges));
  __pyx_v_self->np_kernel_ranges = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
+070:         self.np_objs          = objs
  if (!(likely(((__pyx_v_objs) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_objs, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 70, __pyx_L1_error)
  __pyx_t_1 = __pyx_v_objs;
  __Pyx_INCREF(__pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_1);
  __Pyx_GOTREF(__pyx_v_self->np_objs);
  __Pyx_DECREF(((PyObject *)__pyx_v_self->np_objs));
  __pyx_v_self->np_objs = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
 071: 
+072:         self.num_samples      = locs.shape[0]
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_locs, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 72, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_t_1, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 72, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 72, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_self->num_samples = __pyx_t_3;
+073:         self.num_obs          = locs.shape[1]
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_locs, __pyx_n_s_shape); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 73, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_2, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 73, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 73, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_self->num_obs = __pyx_t_3;
+074:         self.num_kernels      = locs.shape[2]
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_locs, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 74, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_t_1, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 74, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 74, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_self->num_kernels = __pyx_t_3;
+075:         self.lower_prob_bound = lower_prob_bound
  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_v_lower_prob_bound); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 75, __pyx_L1_error)
  __pyx_v_self->lower_prob_bound = __pyx_t_4;
+076:         self.inv_vol          = inv_vol
  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_v_inv_vol); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 76, __pyx_L1_error)
  __pyx_v_self->inv_vol = __pyx_t_4;
 077: 
+078:         self.np_probs = np.zeros(self.num_obs, dtype = np.float64)
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 78, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_zeros); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 78, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_self->num_obs); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 78, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 78, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_GIVEREF(__pyx_t_2);
  PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_2);
  __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 78, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_np); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 78, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_float64); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 78, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_dtype, __pyx_t_7) < 0) __PYX_ERR(0, 78, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_5, __pyx_t_2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 78, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (!(likely(((__pyx_t_7) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_7, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 78, __pyx_L1_error)
  __Pyx_GIVEREF(__pyx_t_7);
  __Pyx_GOTREF(__pyx_v_self->np_probs);
  __Pyx_DECREF(((PyObject *)__pyx_v_self->np_probs));
  __pyx_v_self->np_probs = ((PyArrayObject *)__pyx_t_7);
  __pyx_t_7 = 0;
 079: 
 080:         # number of continuous variables (continuous kernels have id 0 or 1)
+081:         self.num_continuous = np.sum(kernel_types < 1.5)
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 81, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_sum); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 81, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = PyObject_RichCompare(__pyx_v_kernel_types, __pyx_float_1_5, Py_LT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 81, __pyx_L1_error)
  __pyx_t_1 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_5);
    if (likely(__pyx_t_1)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_5, function);
    }
  }
  __pyx_t_7 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_1, __pyx_t_2) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_2);
  __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 81, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_7); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 81, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __pyx_v_self->num_continuous = __pyx_t_3;
 082: 
 083:     @cython.boundscheck(False)
 084:     @cython.cdivision(True)
+085:     cdef double [:] _probs(self, double [:] sample):
static __Pyx_memviewslice __pyx_f_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator__probs(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *__pyx_v_self, __Pyx_memviewslice __pyx_v_sample) {
  int __pyx_v_sample_index;
  int __pyx_v_obs_index;
  int __pyx_v_feature_index;
  int __pyx_v_kernel_index;
  double __pyx_v_total_prob;
  double __pyx_v_prec_prod;
  double __pyx_v_exp_arg_sum;
  double __pyx_v_distance;
  __Pyx_memviewslice __pyx_v_locs = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v_sqrt_precs = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v_cat_probs = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v_kernel_types = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v_kernel_sizes = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v_kernel_ranges = { 0, 0, { 0 }, { 0 }, { 0 } };
  double __pyx_v_inv_sqrt_two_pi;
  __Pyx_memviewslice __pyx_v_probs = { 0, 0, { 0 }, { 0 }, { 0 } };
  double __pyx_v_obs_probs;
  __Pyx_memviewslice __pyx_r = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_TraceDeclarations
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_probs", 0);
  __Pyx_TraceCall("_probs", __pyx_f[0], 85, 0, __PYX_ERR(0, 85, __pyx_L1_error));
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __PYX_XDEC_MEMVIEW(&__pyx_t_1, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_2, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_3, 1);
  __pyx_r.data = NULL;
  __pyx_r.memview = NULL;
  __Pyx_AddTraceback("gryffin.bayesian_network.kernel_evaluations.KernelEvaluator._probs", __pyx_clineno, __pyx_lineno, __pyx_filename);
  goto __pyx_L2;
  __pyx_L0:;
  if (unlikely(!__pyx_r.memview)) {
    PyErr_SetString(PyExc_TypeError, "Memoryview return value is not initialized");
  }
  __pyx_L2:;
  __PYX_XDEC_MEMVIEW(&__pyx_v_locs, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_v_sqrt_precs, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_v_cat_probs, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_v_kernel_types, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_v_kernel_sizes, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_v_kernel_ranges, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_v_probs, 1);
  __Pyx_TraceReturn(Py_None, 0);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 086: 
 087:         cdef int    sample_index, obs_index, feature_index, kernel_index
 088:         cdef double total_prob, prec_prod, exp_arg_sum, distance
 089: 
+090:         cdef double [:, :, :] locs       = self.np_locs
  __pyx_t_1 = __Pyx_PyObject_to_MemoryviewSlice_dsdsds_double(((PyObject *)__pyx_v_self->np_locs), PyBUF_WRITABLE); if (unlikely(!__pyx_t_1.memview)) __PYX_ERR(0, 90, __pyx_L1_error)
  __pyx_v_locs = __pyx_t_1;
  __pyx_t_1.memview = NULL;
  __pyx_t_1.data = NULL;
+091:         cdef double [:, :, :] sqrt_precs = self.np_sqrt_precs
  __pyx_t_1 = __Pyx_PyObject_to_MemoryviewSlice_dsdsds_double(((PyObject *)__pyx_v_self->np_sqrt_precs), PyBUF_WRITABLE); if (unlikely(!__pyx_t_1.memview)) __PYX_ERR(0, 91, __pyx_L1_error)
  __pyx_v_sqrt_precs = __pyx_t_1;
  __pyx_t_1.memview = NULL;
  __pyx_t_1.data = NULL;
+092:         cdef double [:, :, :] cat_probs  = self.np_cat_probs
  __pyx_t_1 = __Pyx_PyObject_to_MemoryviewSlice_dsdsds_double(((PyObject *)__pyx_v_self->np_cat_probs), PyBUF_WRITABLE); if (unlikely(!__pyx_t_1.memview)) __PYX_ERR(0, 92, __pyx_L1_error)
  __pyx_v_cat_probs = __pyx_t_1;
  __pyx_t_1.memview = NULL;
  __pyx_t_1.data = NULL;
 093: 
+094:         cdef int [:] kernel_types = self.np_kernel_types
  __pyx_t_2 = __Pyx_PyObject_to_MemoryviewSlice_ds_int(((PyObject *)__pyx_v_self->np_kernel_types), PyBUF_WRITABLE); if (unlikely(!__pyx_t_2.memview)) __PYX_ERR(0, 94, __pyx_L1_error)
  __pyx_v_kernel_types = __pyx_t_2;
  __pyx_t_2.memview = NULL;
  __pyx_t_2.data = NULL;
+095:         cdef int [:] kernel_sizes = self.np_kernel_sizes
  __pyx_t_2 = __Pyx_PyObject_to_MemoryviewSlice_ds_int(((PyObject *)__pyx_v_self->np_kernel_sizes), PyBUF_WRITABLE); if (unlikely(!__pyx_t_2.memview)) __PYX_ERR(0, 95, __pyx_L1_error)
  __pyx_v_kernel_sizes = __pyx_t_2;
  __pyx_t_2.memview = NULL;
  __pyx_t_2.data = NULL;
+096:         cdef double [:] kernel_ranges = self.np_kernel_ranges
  __pyx_t_3 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(((PyObject *)__pyx_v_self->np_kernel_ranges), PyBUF_WRITABLE); if (unlikely(!__pyx_t_3.memview)) __PYX_ERR(0, 96, __pyx_L1_error)
  __pyx_v_kernel_ranges = __pyx_t_3;
  __pyx_t_3.memview = NULL;
  __pyx_t_3.data = NULL;
 097: 
+098:         cdef double inv_sqrt_two_pi = 0.3989422804014327
  __pyx_v_inv_sqrt_two_pi = 0.3989422804014327;
 099: 
+100:         cdef double [:] probs = self.np_probs
  __pyx_t_3 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(((PyObject *)__pyx_v_self->np_probs), PyBUF_WRITABLE); if (unlikely(!__pyx_t_3.memview)) __PYX_ERR(0, 100, __pyx_L1_error)
  __pyx_v_probs = __pyx_t_3;
  __pyx_t_3.memview = NULL;
  __pyx_t_3.data = NULL;
+101:         for obs_index in range(self.num_obs):
  __pyx_t_4 = __pyx_v_self->num_obs;
  __pyx_t_5 = __pyx_t_4;
  for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
    __pyx_v_obs_index = __pyx_t_6;
+102:             probs[obs_index] = 0.
    __pyx_t_7 = __pyx_v_obs_index;
    if (__pyx_t_7 < 0) __pyx_t_7 += __pyx_v_probs.shape[0];
    *((double *) ( /* dim=0 */ (__pyx_v_probs.data + __pyx_t_7 * __pyx_v_probs.strides[0]) )) = 0.;
  }
 103: 
 104:         cdef double cat_prob
 105:         cdef double obs_probs
 106: 
 107:         # for each kernel location
+108:         for obs_index in range(self.num_obs):
  __pyx_t_4 = __pyx_v_self->num_obs;
  __pyx_t_5 = __pyx_t_4;
  for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
    __pyx_v_obs_index = __pyx_t_6;
+109:             obs_probs = 0.
    __pyx_v_obs_probs = 0.;
 110: 
 111:             # for each BNN sample
+112:             for sample_index in range(self.num_samples):
    __pyx_t_8 = __pyx_v_self->num_samples;
    __pyx_t_9 = __pyx_t_8;
    for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) {
      __pyx_v_sample_index = __pyx_t_10;
+113:                 total_prob     = 1.
      __pyx_v_total_prob = 1.;
+114:                 prec_prod      = 1.
      __pyx_v_prec_prod = 1.;
+115:                 exp_arg_sum    = 0.
      __pyx_v_exp_arg_sum = 0.;
+116:                 feature_index, kernel_index = 0, 0
      __pyx_t_11 = 0;
      __pyx_t_12 = 0;
      __pyx_v_feature_index = __pyx_t_11;
      __pyx_v_kernel_index = __pyx_t_12;
 117: 
 118:                 # for each kernel/dimension
+119:                 while kernel_index < self.num_kernels:
      while (1) {
        __pyx_t_13 = ((__pyx_v_kernel_index < __pyx_v_self->num_kernels) != 0);
        if (!__pyx_t_13) break;
 120:                     # -----------------
 121:                     # continuous kernel
 122:                     # -----------------
+123:                     if kernel_types[kernel_index] == 0:
        __pyx_t_7 = __pyx_v_kernel_index;
        if (__pyx_t_7 < 0) __pyx_t_7 += __pyx_v_kernel_types.shape[0];
        __pyx_t_13 = (((*((int *) ( /* dim=0 */ (__pyx_v_kernel_types.data + __pyx_t_7 * __pyx_v_kernel_types.strides[0]) ))) == 0) != 0);
        if (__pyx_t_13) {
/* … */
          goto __pyx_L11;
        }
 124:                         # get product of inverse standard deviations
+125:                         prec_prod = prec_prod * sqrt_precs[sample_index, obs_index, kernel_index]
          __pyx_t_7 = __pyx_v_sample_index;
          __pyx_t_14 = __pyx_v_obs_index;
          __pyx_t_15 = __pyx_v_kernel_index;
          if (__pyx_t_7 < 0) __pyx_t_7 += __pyx_v_sqrt_precs.shape[0];
          if (__pyx_t_14 < 0) __pyx_t_14 += __pyx_v_sqrt_precs.shape[1];
          if (__pyx_t_15 < 0) __pyx_t_15 += __pyx_v_sqrt_precs.shape[2];
          __pyx_v_prec_prod = (__pyx_v_prec_prod * (*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_sqrt_precs.data + __pyx_t_7 * __pyx_v_sqrt_precs.strides[0]) ) + __pyx_t_14 * __pyx_v_sqrt_precs.strides[1]) ) + __pyx_t_15 * __pyx_v_sqrt_precs.strides[2]) ))));
 126:                         # get sum of the exponent argument
+127:                         exp_arg_sum = exp_arg_sum + (sqrt_precs[sample_index, obs_index, kernel_index] * (sample[feature_index] - locs[sample_index, obs_index, kernel_index]))**2
          __pyx_t_15 = __pyx_v_sample_index;
          __pyx_t_14 = __pyx_v_obs_index;
          __pyx_t_7 = __pyx_v_kernel_index;
          if (__pyx_t_15 < 0) __pyx_t_15 += __pyx_v_sqrt_precs.shape[0];
          if (__pyx_t_14 < 0) __pyx_t_14 += __pyx_v_sqrt_precs.shape[1];
          if (__pyx_t_7 < 0) __pyx_t_7 += __pyx_v_sqrt_precs.shape[2];
          __pyx_t_16 = __pyx_v_feature_index;
          if (__pyx_t_16 < 0) __pyx_t_16 += __pyx_v_sample.shape[0];
          __pyx_t_17 = __pyx_v_sample_index;
          __pyx_t_18 = __pyx_v_obs_index;
          __pyx_t_19 = __pyx_v_kernel_index;
          if (__pyx_t_17 < 0) __pyx_t_17 += __pyx_v_locs.shape[0];
          if (__pyx_t_18 < 0) __pyx_t_18 += __pyx_v_locs.shape[1];
          if (__pyx_t_19 < 0) __pyx_t_19 += __pyx_v_locs.shape[2];
          __pyx_v_exp_arg_sum = (__pyx_v_exp_arg_sum + pow(((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_sqrt_precs.data + __pyx_t_15 * __pyx_v_sqrt_precs.strides[0]) ) + __pyx_t_14 * __pyx_v_sqrt_precs.strides[1]) ) + __pyx_t_7 * __pyx_v_sqrt_precs.strides[2]) ))) * ((*((double *) ( /* dim=0 */ (__pyx_v_sample.data + __pyx_t_16 * __pyx_v_sample.strides[0]) ))) - (*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_locs.data + __pyx_t_17 * __pyx_v_locs.strides[0]) ) + __pyx_t_18 * __pyx_v_locs.strides[1]) ) + __pyx_t_19 * __pyx_v_locs.strides[2]) ))))), 2.0));
 128: 
 129:                     # --------------------------
 130:                     # continuous periodic kernel
 131:                     # --------------------------
+132:                     elif kernel_types[kernel_index] == 1:
        __pyx_t_19 = __pyx_v_kernel_index;
        if (__pyx_t_19 < 0) __pyx_t_19 += __pyx_v_kernel_types.shape[0];
        __pyx_t_13 = (((*((int *) ( /* dim=0 */ (__pyx_v_kernel_types.data + __pyx_t_19 * __pyx_v_kernel_types.strides[0]) ))) == 1) != 0);
        if (__pyx_t_13) {
/* … */
          goto __pyx_L11;
        }
 133:                         # get product of inverse standard deviations
+134:                         prec_prod = prec_prod * sqrt_precs[sample_index, obs_index, kernel_index]
          __pyx_t_19 = __pyx_v_sample_index;
          __pyx_t_18 = __pyx_v_obs_index;
          __pyx_t_17 = __pyx_v_kernel_index;
          if (__pyx_t_19 < 0) __pyx_t_19 += __pyx_v_sqrt_precs.shape[0];
          if (__pyx_t_18 < 0) __pyx_t_18 += __pyx_v_sqrt_precs.shape[1];
          if (__pyx_t_17 < 0) __pyx_t_17 += __pyx_v_sqrt_precs.shape[2];
          __pyx_v_prec_prod = (__pyx_v_prec_prod * (*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_sqrt_precs.data + __pyx_t_19 * __pyx_v_sqrt_precs.strides[0]) ) + __pyx_t_18 * __pyx_v_sqrt_precs.strides[1]) ) + __pyx_t_17 * __pyx_v_sqrt_precs.strides[2]) ))));
 135:                         # get distance between gaussian mean and sample location
+136:                         distance = abs(sample[feature_index] - locs[sample_index, obs_index, kernel_index])
          __pyx_t_17 = __pyx_v_feature_index;
          if (__pyx_t_17 < 0) __pyx_t_17 += __pyx_v_sample.shape[0];
          __pyx_t_18 = __pyx_v_sample_index;
          __pyx_t_19 = __pyx_v_obs_index;
          __pyx_t_16 = __pyx_v_kernel_index;
          if (__pyx_t_18 < 0) __pyx_t_18 += __pyx_v_locs.shape[0];
          if (__pyx_t_19 < 0) __pyx_t_19 += __pyx_v_locs.shape[1];
          if (__pyx_t_16 < 0) __pyx_t_16 += __pyx_v_locs.shape[2];
          __pyx_v_distance = fabs(((*((double *) ( /* dim=0 */ (__pyx_v_sample.data + __pyx_t_17 * __pyx_v_sample.strides[0]) ))) - (*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_locs.data + __pyx_t_18 * __pyx_v_locs.strides[0]) ) + __pyx_t_19 * __pyx_v_locs.strides[1]) ) + __pyx_t_16 * __pyx_v_locs.strides[2]) )))));
 137:                         # consider closest distance across boundaries
+138:                         if kernel_ranges[kernel_index] - distance < distance:
          __pyx_t_16 = __pyx_v_kernel_index;
          if (__pyx_t_16 < 0) __pyx_t_16 += __pyx_v_kernel_ranges.shape[0];
          __pyx_t_13 = ((((*((double *) ( /* dim=0 */ (__pyx_v_kernel_ranges.data + __pyx_t_16 * __pyx_v_kernel_ranges.strides[0]) ))) - __pyx_v_distance) < __pyx_v_distance) != 0);
          if (__pyx_t_13) {
/* … */
          }
+139:                             distance = kernel_ranges[kernel_index] - distance
            __pyx_t_16 = __pyx_v_kernel_index;
            if (__pyx_t_16 < 0) __pyx_t_16 += __pyx_v_kernel_ranges.shape[0];
            __pyx_v_distance = ((*((double *) ( /* dim=0 */ (__pyx_v_kernel_ranges.data + __pyx_t_16 * __pyx_v_kernel_ranges.strides[0]) ))) - __pyx_v_distance);
 140:                         # get sum of the exponent argument
+141:                         exp_arg_sum = exp_arg_sum + (sqrt_precs[sample_index, obs_index, kernel_index] * distance)**2
          __pyx_t_16 = __pyx_v_sample_index;
          __pyx_t_19 = __pyx_v_obs_index;
          __pyx_t_18 = __pyx_v_kernel_index;
          if (__pyx_t_16 < 0) __pyx_t_16 += __pyx_v_sqrt_precs.shape[0];
          if (__pyx_t_19 < 0) __pyx_t_19 += __pyx_v_sqrt_precs.shape[1];
          if (__pyx_t_18 < 0) __pyx_t_18 += __pyx_v_sqrt_precs.shape[2];
          __pyx_v_exp_arg_sum = (__pyx_v_exp_arg_sum + pow(((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_sqrt_precs.data + __pyx_t_16 * __pyx_v_sqrt_precs.strides[0]) ) + __pyx_t_19 * __pyx_v_sqrt_precs.strides[1]) ) + __pyx_t_18 * __pyx_v_sqrt_precs.strides[2]) ))) * __pyx_v_distance), 2.0));
 142: 
 143:                     # ------------------
 144:                     # categorical kernel
 145:                     # ------------------
+146:                     elif kernel_types[kernel_index] == 2:
        __pyx_t_18 = __pyx_v_kernel_index;
        if (__pyx_t_18 < 0) __pyx_t_18 += __pyx_v_kernel_types.shape[0];
        __pyx_t_13 = (((*((int *) ( /* dim=0 */ (__pyx_v_kernel_types.data + __pyx_t_18 * __pyx_v_kernel_types.strides[0]) ))) == 2) != 0);
        if (__pyx_t_13) {
/* … */
        }
        __pyx_L11:;
 147:                         # total probability, if we have continuous variables only this stays at 1
+148:                         total_prob *= cat_probs[sample_index, obs_index, kernel_index + <int>round(sample[feature_index])]
          __pyx_t_18 = __pyx_v_feature_index;
          if (__pyx_t_18 < 0) __pyx_t_18 += __pyx_v_sample.shape[0];
          __pyx_t_19 = __pyx_v_sample_index;
          __pyx_t_16 = __pyx_v_obs_index;
          __pyx_t_17 = (__pyx_v_kernel_index + ((int)round((*((double *) ( /* dim=0 */ (__pyx_v_sample.data + __pyx_t_18 * __pyx_v_sample.strides[0]) ))))));
          if (__pyx_t_19 < 0) __pyx_t_19 += __pyx_v_cat_probs.shape[0];
          if (__pyx_t_16 < 0) __pyx_t_16 += __pyx_v_cat_probs.shape[1];
          if (__pyx_t_17 < 0) __pyx_t_17 += __pyx_v_cat_probs.shape[2];
          __pyx_v_total_prob = (__pyx_v_total_prob * (*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_cat_probs.data + __pyx_t_19 * __pyx_v_cat_probs.strides[0]) ) + __pyx_t_16 * __pyx_v_cat_probs.strides[1]) ) + __pyx_t_17 * __pyx_v_cat_probs.strides[2]) ))));
 149: 
 150:                     # increment indices
+151:                     kernel_index  += kernel_sizes[kernel_index]  # kernel size can be >1 for a certain param
        __pyx_t_18 = __pyx_v_kernel_index;
        if (__pyx_t_18 < 0) __pyx_t_18 += __pyx_v_kernel_sizes.shape[0];
        __pyx_v_kernel_index = (__pyx_v_kernel_index + (*((int *) ( /* dim=0 */ (__pyx_v_kernel_sizes.data + __pyx_t_18 * __pyx_v_kernel_sizes.strides[0]) ))));
+152:                     feature_index += 1
        __pyx_v_feature_index = (__pyx_v_feature_index + 1);
      }
 153: 
 154:                 # combine precision product with exponent argument, and categorical probability
+155:                 obs_probs += total_prob * prec_prod * exp(-0.5 * exp_arg_sum)
      __pyx_v_obs_probs = (__pyx_v_obs_probs + ((__pyx_v_total_prob * __pyx_v_prec_prod) * exp((-0.5 * __pyx_v_exp_arg_sum))));
 156: 
 157:                 # we assume 1000 BNN samples, so 100 is 10%
+158:                 if sample_index == 100:
      __pyx_t_13 = ((__pyx_v_sample_index == 0x64) != 0);
      if (__pyx_t_13) {
/* … */
        goto __pyx_L13;
      }
 159:                     # boosting criterion
+160:                     if 0.01 * obs_probs * inv_sqrt_two_pi**self.num_continuous < self.lower_prob_bound:
        __pyx_t_13 = ((((0.01 * __pyx_v_obs_probs) * pow(__pyx_v_inv_sqrt_two_pi, ((double)__pyx_v_self->num_continuous))) < __pyx_v_self->lower_prob_bound) != 0);
        if (__pyx_t_13) {
/* … */
        }
+161:                         probs[obs_index] = 0.01 * obs_probs
          __pyx_t_18 = __pyx_v_obs_index;
          if (__pyx_t_18 < 0) __pyx_t_18 += __pyx_v_probs.shape[0];
          *((double *) ( /* dim=0 */ (__pyx_v_probs.data + __pyx_t_18 * __pyx_v_probs.strides[0]) )) = (0.01 * __pyx_v_obs_probs);
+162:                         break
          goto __pyx_L8_break;
 163:                 else:
 164:                     # we take the average across the BNN samples
 165:                     # normalise the gaussian kernel probabilities
+166:                     probs[obs_index] = (obs_probs * inv_sqrt_two_pi**self.num_continuous) / self.num_samples
      /*else*/ {
        __pyx_t_18 = __pyx_v_obs_index;
        if (__pyx_t_18 < 0) __pyx_t_18 += __pyx_v_probs.shape[0];
        *((double *) ( /* dim=0 */ (__pyx_v_probs.data + __pyx_t_18 * __pyx_v_probs.strides[0]) )) = ((__pyx_v_obs_probs * pow(__pyx_v_inv_sqrt_two_pi, ((double)__pyx_v_self->num_continuous))) / ((double)__pyx_v_self->num_samples));
      }
      __pyx_L13:;
    }
    __pyx_L8_break:;
  }
+167:         return probs
  __PYX_INC_MEMVIEW(&__pyx_v_probs, 0);
  __pyx_r = __pyx_v_probs;
  goto __pyx_L0;
 168: 
+169:     cpdef get_kernel_contrib(self, np.ndarray sample):
static PyObject *__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_3get_kernel_contrib(PyObject *__pyx_v_self, PyObject *__pyx_v_sample); /*proto*/
static PyObject *__pyx_f_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_get_kernel_contrib(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *__pyx_v_self, PyArrayObject *__pyx_v_sample, int __pyx_skip_dispatch) {
  int __pyx_v_obs_index;
  double __pyx_v_temp_0;
  double __pyx_v_temp_1;
  double __pyx_v_inv_den;
  __Pyx_memviewslice __pyx_v_sample_memview = { 0, 0, { 0 }, { 0 }, { 0 } };
  PyObject *__pyx_v_probs_sample = NULL;
  double __pyx_v_num;
  double __pyx_v_den;
  __Pyx_memviewslice __pyx_v_objs = { 0, 0, { 0 }, { 0 }, { 0 } };
  PyObject *__pyx_r = NULL;
  __Pyx_TraceDeclarations
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_kernel_contrib", 0);
  __Pyx_TraceCall("get_kernel_contrib", __pyx_f[0], 169, 0, __PYX_ERR(0, 169, __pyx_L1_error));
  /* Check if called by wrapper */
  if (unlikely(__pyx_skip_dispatch)) ;
  /* Check if overridden in Python */
  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
    static PY_UINT64_T __pyx_tp_dict_version = __PYX_DICT_VERSION_INIT, __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT;
    if (unlikely(!__Pyx_object_dict_version_matches(((PyObject *)__pyx_v_self), __pyx_tp_dict_version, __pyx_obj_dict_version))) {
      PY_UINT64_T __pyx_type_dict_guard = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self));
      #endif
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_get_kernel_contrib); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 169, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_3get_kernel_contrib)) {
        __Pyx_XDECREF(__pyx_r);
        __Pyx_INCREF(__pyx_t_1);
        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
          if (likely(__pyx_t_4)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
            __Pyx_INCREF(__pyx_t_4);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_3, function);
          }
        }
        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, ((PyObject *)__pyx_v_sample)) : __Pyx_PyObject_CallOneArg(__pyx_t_3, ((PyObject *)__pyx_v_sample));
        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 169, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        __pyx_r = __pyx_t_2;
        __pyx_t_2 = 0;
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        goto __pyx_L0;
      }
      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
      __pyx_tp_dict_version = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self));
      __pyx_obj_dict_version = __Pyx_get_object_dict_version(((PyObject *)__pyx_v_self));
      if (unlikely(__pyx_type_dict_guard != __pyx_tp_dict_version)) {
        __pyx_tp_dict_version = __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT;
      }
      #endif
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
    }
    #endif
  }
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __PYX_XDEC_MEMVIEW(&__pyx_t_5, 1);
  __Pyx_AddTraceback("gryffin.bayesian_network.kernel_evaluations.KernelEvaluator.get_kernel_contrib", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __PYX_XDEC_MEMVIEW(&__pyx_v_sample_memview, 1);
  __Pyx_XDECREF(__pyx_v_probs_sample);
  __PYX_XDEC_MEMVIEW(&__pyx_v_objs, 1);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_TraceReturn(__pyx_r, 0);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_3get_kernel_contrib(PyObject *__pyx_v_self, PyObject *__pyx_v_sample); /*proto*/
static PyObject *__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_3get_kernel_contrib(PyObject *__pyx_v_self, PyObject *__pyx_v_sample) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_kernel_contrib (wrapper)", 0);
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sample), __pyx_ptype_5numpy_ndarray, 1, "sample", 0))) __PYX_ERR(0, 169, __pyx_L1_error)
  __pyx_r = __pyx_pf_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_2get_kernel_contrib(((struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *)__pyx_v_self), ((PyArrayObject *)__pyx_v_sample));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_2get_kernel_contrib(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *__pyx_v_self, PyArrayObject *__pyx_v_sample) {
  PyObject *__pyx_r = NULL;
  __Pyx_TraceDeclarations
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_kernel_contrib", 0);
  __Pyx_TraceCall("get_kernel_contrib (wrapper)", __pyx_f[0], 169, 0, __PYX_ERR(0, 169, __pyx_L1_error));
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __pyx_f_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_get_kernel_contrib(__pyx_v_self, __pyx_v_sample, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 169, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("gryffin.bayesian_network.kernel_evaluations.KernelEvaluator.get_kernel_contrib", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_TraceReturn(__pyx_r, 0);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 170: 
 171:         cdef int obs_index
 172:         cdef double temp_0, temp_1
 173:         cdef double inv_den
 174: 
+175:         cdef double [:] sample_memview = sample
  __pyx_t_5 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(((PyObject *)__pyx_v_sample), PyBUF_WRITABLE); if (unlikely(!__pyx_t_5.memview)) __PYX_ERR(0, 175, __pyx_L1_error)
  __pyx_v_sample_memview = __pyx_t_5;
  __pyx_t_5.memview = NULL;
  __pyx_t_5.data = NULL;
+176:         probs_sample = self._probs(sample_memview)
  __pyx_t_5 = ((struct __pyx_vtabstruct_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *)__pyx_v_self->__pyx_vtab)->_probs(__pyx_v_self, __pyx_v_sample_memview); if (unlikely(!__pyx_t_5.memview)) __PYX_ERR(0, 176, __pyx_L1_error)
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_t_5, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 176, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_5, 1);
  __pyx_t_5.memview = NULL;
  __pyx_t_5.data = NULL;
  __pyx_v_probs_sample = __pyx_t_1;
  __pyx_t_1 = 0;
 177: 
 178:         # construct numerator and denominator of acquisition
+179:         cdef double num = 0.
  __pyx_v_num = 0.;
+180:         cdef double den = 0.
  __pyx_v_den = 0.;
+181:         cdef double [:] objs = self.np_objs
  __pyx_t_5 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(((PyObject *)__pyx_v_self->np_objs), PyBUF_WRITABLE); if (unlikely(!__pyx_t_5.memview)) __PYX_ERR(0, 181, __pyx_L1_error)
  __pyx_v_objs = __pyx_t_5;
  __pyx_t_5.memview = NULL;
  __pyx_t_5.data = NULL;
 182: 
+183:         for obs_index in range(self.num_obs):
  __pyx_t_6 = __pyx_v_self->num_obs;
  __pyx_t_7 = __pyx_t_6;
  for (__pyx_t_8 = 0; __pyx_t_8 < __pyx_t_7; __pyx_t_8+=1) {
    __pyx_v_obs_index = __pyx_t_8;
+184:             temp_0 = objs[obs_index]
    __pyx_t_9 = __pyx_v_obs_index;
    __pyx_t_10 = -1;
    if (__pyx_t_9 < 0) {
      __pyx_t_9 += __pyx_v_objs.shape[0];
      if (unlikely(__pyx_t_9 < 0)) __pyx_t_10 = 0;
    } else if (unlikely(__pyx_t_9 >= __pyx_v_objs.shape[0])) __pyx_t_10 = 0;
    if (unlikely(__pyx_t_10 != -1)) {
      __Pyx_RaiseBufferIndexError(__pyx_t_10);
      __PYX_ERR(0, 184, __pyx_L1_error)
    }
    __pyx_v_temp_0 = (*((double *) ( /* dim=0 */ (__pyx_v_objs.data + __pyx_t_9 * __pyx_v_objs.strides[0]) )));
+185:             temp_1 = probs_sample[obs_index]
    __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_probs_sample, __pyx_v_obs_index, int, 1, __Pyx_PyInt_From_int, 0, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 185, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_11 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_11 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 185, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_temp_1 = __pyx_t_11;
+186:             num += temp_0 * temp_1
    __pyx_v_num = (__pyx_v_num + (__pyx_v_temp_0 * __pyx_v_temp_1));
+187:             den += temp_1
    __pyx_v_den = (__pyx_v_den + __pyx_v_temp_1);
  }
 188: 
+189:         inv_den = 1. / (self.inv_vol + den)
  __pyx_t_11 = (__pyx_v_self->inv_vol + __pyx_v_den);
  if (unlikely(__pyx_t_11 == 0)) {
    PyErr_SetString(PyExc_ZeroDivisionError, "float division");
    __PYX_ERR(0, 189, __pyx_L1_error)
  }
  __pyx_v_inv_den = (1. / __pyx_t_11);
 190: 
+191:         return num, inv_den, probs_sample
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_num); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 191, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_inv_den); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 191, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 191, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_GIVEREF(__pyx_t_1);
  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_2);
  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_2);
  __Pyx_INCREF(__pyx_v_probs_sample);
  __Pyx_GIVEREF(__pyx_v_probs_sample);
  PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_v_probs_sample);
  __pyx_t_1 = 0;
  __pyx_t_2 = 0;
  __pyx_r = __pyx_t_3;
  __pyx_t_3 = 0;
  goto __pyx_L0;
 192: 
+193:     cpdef get_regression_surrogate(self, np.ndarray sample):
static PyObject *__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_5get_regression_surrogate(PyObject *__pyx_v_self, PyObject *__pyx_v_sample); /*proto*/
static PyObject *__pyx_f_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_get_regression_surrogate(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *__pyx_v_self, PyArrayObject *__pyx_v_sample, int __pyx_skip_dispatch) {
  int __pyx_v_obs_index;
  double __pyx_v_temp_0;
  double __pyx_v_temp_1;
  double __pyx_v_y_pred;
  __Pyx_memviewslice __pyx_v_sample_memview = { 0, 0, { 0 }, { 0 }, { 0 } };
  PyObject *__pyx_v_probs_sample = NULL;
  double __pyx_v_num;
  double __pyx_v_den;
  __Pyx_memviewslice __pyx_v_objs = { 0, 0, { 0 }, { 0 }, { 0 } };
  PyObject *__pyx_r = NULL;
  __Pyx_TraceDeclarations
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_regression_surrogate", 0);
  __Pyx_TraceCall("get_regression_surrogate", __pyx_f[0], 193, 0, __PYX_ERR(0, 193, __pyx_L1_error));
  /* Check if called by wrapper */
  if (unlikely(__pyx_skip_dispatch)) ;
  /* Check if overridden in Python */
  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
    static PY_UINT64_T __pyx_tp_dict_version = __PYX_DICT_VERSION_INIT, __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT;
    if (unlikely(!__Pyx_object_dict_version_matches(((PyObject *)__pyx_v_self), __pyx_tp_dict_version, __pyx_obj_dict_version))) {
      PY_UINT64_T __pyx_type_dict_guard = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self));
      #endif
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_get_regression_surrogate); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 193, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_5get_regression_surrogate)) {
        __Pyx_XDECREF(__pyx_r);
        __Pyx_INCREF(__pyx_t_1);
        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
          if (likely(__pyx_t_4)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
            __Pyx_INCREF(__pyx_t_4);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_3, function);
          }
        }
        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, ((PyObject *)__pyx_v_sample)) : __Pyx_PyObject_CallOneArg(__pyx_t_3, ((PyObject *)__pyx_v_sample));
        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 193, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        __pyx_r = __pyx_t_2;
        __pyx_t_2 = 0;
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        goto __pyx_L0;
      }
      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
      __pyx_tp_dict_version = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self));
      __pyx_obj_dict_version = __Pyx_get_object_dict_version(((PyObject *)__pyx_v_self));
      if (unlikely(__pyx_type_dict_guard != __pyx_tp_dict_version)) {
        __pyx_tp_dict_version = __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT;
      }
      #endif
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
    }
    #endif
  }
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __PYX_XDEC_MEMVIEW(&__pyx_t_5, 1);
  __Pyx_AddTraceback("gryffin.bayesian_network.kernel_evaluations.KernelEvaluator.get_regression_surrogate", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __PYX_XDEC_MEMVIEW(&__pyx_v_sample_memview, 1);
  __Pyx_XDECREF(__pyx_v_probs_sample);
  __PYX_XDEC_MEMVIEW(&__pyx_v_objs, 1);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_TraceReturn(__pyx_r, 0);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_5get_regression_surrogate(PyObject *__pyx_v_self, PyObject *__pyx_v_sample); /*proto*/
static PyObject *__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_5get_regression_surrogate(PyObject *__pyx_v_self, PyObject *__pyx_v_sample) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_regression_surrogate (wrapper)", 0);
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sample), __pyx_ptype_5numpy_ndarray, 1, "sample", 0))) __PYX_ERR(0, 193, __pyx_L1_error)
  __pyx_r = __pyx_pf_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_4get_regression_surrogate(((struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *)__pyx_v_self), ((PyArrayObject *)__pyx_v_sample));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_4get_regression_surrogate(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *__pyx_v_self, PyArrayObject *__pyx_v_sample) {
  PyObject *__pyx_r = NULL;
  __Pyx_TraceDeclarations
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_regression_surrogate", 0);
  __Pyx_TraceCall("get_regression_surrogate (wrapper)", __pyx_f[0], 193, 0, __PYX_ERR(0, 193, __pyx_L1_error));
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __pyx_f_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_get_regression_surrogate(__pyx_v_self, __pyx_v_sample, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 193, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("gryffin.bayesian_network.kernel_evaluations.KernelEvaluator.get_regression_surrogate", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_TraceReturn(__pyx_r, 0);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 194: 
 195:         cdef int obs_index
 196:         cdef double temp_0, temp_1
 197:         cdef double inv_den
 198:         cdef double y_pred
+199:         cdef double [:] sample_memview = sample
  __pyx_t_5 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(((PyObject *)__pyx_v_sample), PyBUF_WRITABLE); if (unlikely(!__pyx_t_5.memview)) __PYX_ERR(0, 199, __pyx_L1_error)
  __pyx_v_sample_memview = __pyx_t_5;
  __pyx_t_5.memview = NULL;
  __pyx_t_5.data = NULL;
+200:         probs_sample = self._probs(sample_memview)
  __pyx_t_5 = ((struct __pyx_vtabstruct_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *)__pyx_v_self->__pyx_vtab)->_probs(__pyx_v_self, __pyx_v_sample_memview); if (unlikely(!__pyx_t_5.memview)) __PYX_ERR(0, 200, __pyx_L1_error)
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_t_5, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 200, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_5, 1);
  __pyx_t_5.memview = NULL;
  __pyx_t_5.data = NULL;
  __pyx_v_probs_sample = __pyx_t_1;
  __pyx_t_1 = 0;
 201: 
 202:         # construct numerator and denominator of acquisition
+203:         cdef double num = 0.
  __pyx_v_num = 0.;
+204:         cdef double den = 0.
  __pyx_v_den = 0.;
+205:         cdef double [:] objs = self.np_objs
  __pyx_t_5 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(((PyObject *)__pyx_v_self->np_objs), PyBUF_WRITABLE); if (unlikely(!__pyx_t_5.memview)) __PYX_ERR(0, 205, __pyx_L1_error)
  __pyx_v_objs = __pyx_t_5;
  __pyx_t_5.memview = NULL;
  __pyx_t_5.data = NULL;
 206: 
+207:         for obs_index in range(self.num_obs):
  __pyx_t_6 = __pyx_v_self->num_obs;
  __pyx_t_7 = __pyx_t_6;
  for (__pyx_t_8 = 0; __pyx_t_8 < __pyx_t_7; __pyx_t_8+=1) {
    __pyx_v_obs_index = __pyx_t_8;
+208:             temp_0 = objs[obs_index]
    __pyx_t_9 = __pyx_v_obs_index;
    __pyx_t_10 = -1;
    if (__pyx_t_9 < 0) {
      __pyx_t_9 += __pyx_v_objs.shape[0];
      if (unlikely(__pyx_t_9 < 0)) __pyx_t_10 = 0;
    } else if (unlikely(__pyx_t_9 >= __pyx_v_objs.shape[0])) __pyx_t_10 = 0;
    if (unlikely(__pyx_t_10 != -1)) {
      __Pyx_RaiseBufferIndexError(__pyx_t_10);
      __PYX_ERR(0, 208, __pyx_L1_error)
    }
    __pyx_v_temp_0 = (*((double *) ( /* dim=0 */ (__pyx_v_objs.data + __pyx_t_9 * __pyx_v_objs.strides[0]) )));
+209:             temp_1 = probs_sample[obs_index]
    __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_probs_sample, __pyx_v_obs_index, int, 1, __Pyx_PyInt_From_int, 0, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 209, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_11 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_11 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 209, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_temp_1 = __pyx_t_11;
+210:             num += temp_0 * temp_1
    __pyx_v_num = (__pyx_v_num + (__pyx_v_temp_0 * __pyx_v_temp_1));
+211:             den += temp_1
    __pyx_v_den = (__pyx_v_den + __pyx_v_temp_1);
  }
 212: 
+213:         y_pred = num / (den + 1e-8)  # avoid division by zero
  __pyx_t_11 = (__pyx_v_den + 1e-8);
  if (unlikely(__pyx_t_11 == 0)) {
    PyErr_SetString(PyExc_ZeroDivisionError, "float division");
    __PYX_ERR(0, 213, __pyx_L1_error)
  }
  __pyx_v_y_pred = (__pyx_v_num / __pyx_t_11);
+214:         return y_pred
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_y_pred); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 214, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;
 215: 
+216:     cpdef get_binary_kernel_densities(self, np.ndarray sample):
static PyObject *__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_7get_binary_kernel_densities(PyObject *__pyx_v_self, PyObject *__pyx_v_sample); /*proto*/
static PyObject *__pyx_f_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_get_binary_kernel_densities(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *__pyx_v_self, PyArrayObject *__pyx_v_sample, int __pyx_skip_dispatch) {
  int __pyx_v_obs_index;
  double __pyx_v_density_0;
  double __pyx_v_density_1;
  double __pyx_v_num_0;
  double __pyx_v_num_1;
  double __pyx_v_log_density_0;
  double __pyx_v_log_density_1;
  __Pyx_memviewslice __pyx_v_sample_memview = { 0, 0, { 0 }, { 0 }, { 0 } };
  PyObject *__pyx_v_probs_sample = NULL;
  PyObject *__pyx_v_obj = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_TraceDeclarations
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_binary_kernel_densities", 0);
  __Pyx_TraceCall("get_binary_kernel_densities", __pyx_f[0], 216, 0, __PYX_ERR(0, 216, __pyx_L1_error));
  /* Check if called by wrapper */
  if (unlikely(__pyx_skip_dispatch)) ;
  /* Check if overridden in Python */
  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
    static PY_UINT64_T __pyx_tp_dict_version = __PYX_DICT_VERSION_INIT, __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT;
    if (unlikely(!__Pyx_object_dict_version_matches(((PyObject *)__pyx_v_self), __pyx_tp_dict_version, __pyx_obj_dict_version))) {
      PY_UINT64_T __pyx_type_dict_guard = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self));
      #endif
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_get_binary_kernel_densities); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 216, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_7get_binary_kernel_densities)) {
        __Pyx_XDECREF(__pyx_r);
        __Pyx_INCREF(__pyx_t_1);
        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
          if (likely(__pyx_t_4)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
            __Pyx_INCREF(__pyx_t_4);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_3, function);
          }
        }
        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, ((PyObject *)__pyx_v_sample)) : __Pyx_PyObject_CallOneArg(__pyx_t_3, ((PyObject *)__pyx_v_sample));
        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 216, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        __pyx_r = __pyx_t_2;
        __pyx_t_2 = 0;
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        goto __pyx_L0;
      }
      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
      __pyx_tp_dict_version = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self));
      __pyx_obj_dict_version = __Pyx_get_object_dict_version(((PyObject *)__pyx_v_self));
      if (unlikely(__pyx_type_dict_guard != __pyx_tp_dict_version)) {
        __pyx_tp_dict_version = __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT;
      }
      #endif
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
    }
    #endif
  }
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __PYX_XDEC_MEMVIEW(&__pyx_t_5, 1);
  __Pyx_XDECREF(__pyx_t_11);
  __Pyx_AddTraceback("gryffin.bayesian_network.kernel_evaluations.KernelEvaluator.get_binary_kernel_densities", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __PYX_XDEC_MEMVIEW(&__pyx_v_sample_memview, 1);
  __Pyx_XDECREF(__pyx_v_probs_sample);
  __Pyx_XDECREF(__pyx_v_obj);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_TraceReturn(__pyx_r, 0);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_7get_binary_kernel_densities(PyObject *__pyx_v_self, PyObject *__pyx_v_sample); /*proto*/
static PyObject *__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_7get_binary_kernel_densities(PyObject *__pyx_v_self, PyObject *__pyx_v_sample) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_binary_kernel_densities (wrapper)", 0);
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sample), __pyx_ptype_5numpy_ndarray, 1, "sample", 0))) __PYX_ERR(0, 216, __pyx_L1_error)
  __pyx_r = __pyx_pf_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_6get_binary_kernel_densities(((struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *)__pyx_v_self), ((PyArrayObject *)__pyx_v_sample));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_6get_binary_kernel_densities(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *__pyx_v_self, PyArrayObject *__pyx_v_sample) {
  PyObject *__pyx_r = NULL;
  __Pyx_TraceDeclarations
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_binary_kernel_densities", 0);
  __Pyx_TraceCall("get_binary_kernel_densities (wrapper)", __pyx_f[0], 216, 0, __PYX_ERR(0, 216, __pyx_L1_error));
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __pyx_f_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_get_binary_kernel_densities(__pyx_v_self, __pyx_v_sample, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 216, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("gryffin.bayesian_network.kernel_evaluations.KernelEvaluator.get_binary_kernel_densities", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_TraceReturn(__pyx_r, 0);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 217: 
 218:         cdef int obs_index
+219:         cdef double density_0 = 0.  # density of feasible
  __pyx_v_density_0 = 0.;
+220:         cdef double density_1 = 0.  # density of infeasible
  __pyx_v_density_1 = 0.;
+221:         cdef double num_0 = 0.
  __pyx_v_num_0 = 0.;
+222:         cdef double num_1 = 0.
  __pyx_v_num_1 = 0.;
 223:         cdef double log_density_0
 224:         cdef double log_density_1
 225: 
+226:         cdef double [:] sample_memview = sample
  __pyx_t_5 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(((PyObject *)__pyx_v_sample), PyBUF_WRITABLE); if (unlikely(!__pyx_t_5.memview)) __PYX_ERR(0, 226, __pyx_L1_error)
  __pyx_v_sample_memview = __pyx_t_5;
  __pyx_t_5.memview = NULL;
  __pyx_t_5.data = NULL;
+227:         probs_sample = self._probs(sample_memview)
  __pyx_t_5 = ((struct __pyx_vtabstruct_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *)__pyx_v_self->__pyx_vtab)->_probs(__pyx_v_self, __pyx_v_sample_memview); if (unlikely(!__pyx_t_5.memview)) __PYX_ERR(0, 227, __pyx_L1_error)
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_t_5, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 227, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_5, 1);
  __pyx_t_5.memview = NULL;
  __pyx_t_5.data = NULL;
  __pyx_v_probs_sample = __pyx_t_1;
  __pyx_t_1 = 0;
 228: 
+229:         for obs_index, obj in enumerate(self.np_objs):
  __pyx_t_6 = 0;
  if (likely(PyList_CheckExact(((PyObject *)__pyx_v_self->np_objs))) || PyTuple_CheckExact(((PyObject *)__pyx_v_self->np_objs))) {
    __pyx_t_1 = ((PyObject *)__pyx_v_self->np_objs); __Pyx_INCREF(__pyx_t_1); __pyx_t_7 = 0;
    __pyx_t_8 = NULL;
  } else {
    __pyx_t_7 = -1; __pyx_t_1 = PyObject_GetIter(((PyObject *)__pyx_v_self->np_objs)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 229, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_8 = Py_TYPE(__pyx_t_1)->tp_iternext; if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 229, __pyx_L1_error)
  }
  for (;;) {
    if (likely(!__pyx_t_8)) {
      if (likely(PyList_CheckExact(__pyx_t_1))) {
        if (__pyx_t_7 >= PyList_GET_SIZE(__pyx_t_1)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_7); __Pyx_INCREF(__pyx_t_2); __pyx_t_7++; if (unlikely(0 < 0)) __PYX_ERR(0, 229, __pyx_L1_error)
        #else
        __pyx_t_2 = PySequence_ITEM(__pyx_t_1, __pyx_t_7); __pyx_t_7++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 229, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        #endif
      } else {
        if (__pyx_t_7 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_7); __Pyx_INCREF(__pyx_t_2); __pyx_t_7++; if (unlikely(0 < 0)) __PYX_ERR(0, 229, __pyx_L1_error)
        #else
        __pyx_t_2 = PySequence_ITEM(__pyx_t_1, __pyx_t_7); __pyx_t_7++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 229, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        #endif
      }
    } else {
      __pyx_t_2 = __pyx_t_8(__pyx_t_1);
      if (unlikely(!__pyx_t_2)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 229, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_2);
    }
    __Pyx_XDECREF_SET(__pyx_v_obj, __pyx_t_2);
    __pyx_t_2 = 0;
    __pyx_v_obs_index = __pyx_t_6;
    __pyx_t_6 = (__pyx_t_6 + 1);
/* … */
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+230:             if obj > 0.5:
    __pyx_t_2 = PyObject_RichCompare(__pyx_v_obj, __pyx_float_0_5, Py_GT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 230, __pyx_L1_error)
    __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 230, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (__pyx_t_9) {
/* … */
      goto __pyx_L5;
    }
+231:                 density_1 += probs_sample[obs_index]
      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_density_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 231, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_probs_sample, __pyx_v_obs_index, int, 1, __Pyx_PyInt_From_int, 0, 1, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 231, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 231, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __pyx_t_10 = __pyx_PyFloat_AsDouble(__pyx_t_4); if (unlikely((__pyx_t_10 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 231, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __pyx_v_density_1 = __pyx_t_10;
+232:                 num_1 += 1.
      __pyx_v_num_1 = (__pyx_v_num_1 + 1.);
 233:             else:
+234:                 density_0 += probs_sample[obs_index]
    /*else*/ {
      __pyx_t_4 = PyFloat_FromDouble(__pyx_v_density_0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 234, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_probs_sample, __pyx_v_obs_index, int, 1, __Pyx_PyInt_From_int, 0, 1, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 234, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 234, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __pyx_t_10 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_10 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 234, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_v_density_0 = __pyx_t_10;
+235:                 num_0 += 1.
      __pyx_v_num_0 = (__pyx_v_num_0 + 1.);
    }
    __pyx_L5:;
 236: 
 237:         # normalize wrt the number of kernels
+238:         log_density_0 = np.log(density_0) - np.log(num_0)
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 238, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_log); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 238, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_density_0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 238, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_4 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_4)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_4);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
    }
  }
  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_t_2) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2);
  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 238, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 238, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_log); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 238, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_num_0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 238, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_11 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_4);
    if (likely(__pyx_t_11)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_11);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_4, function);
    }
  }
  __pyx_t_3 = (__pyx_t_11) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_11, __pyx_t_2) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_2);
  __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 238, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_4 = PyNumber_Subtract(__pyx_t_1, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 238, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_10 = __pyx_PyFloat_AsDouble(__pyx_t_4); if (unlikely((__pyx_t_10 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 238, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_v_log_density_0 = __pyx_t_10;
+239:         log_density_1 = np.log(density_1) - np.log(num_1)
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 239, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_log); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 239, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = PyFloat_FromDouble(__pyx_v_density_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 239, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_2 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_1);
    if (likely(__pyx_t_2)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
      __Pyx_INCREF(__pyx_t_2);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_1, function);
    }
  }
  __pyx_t_4 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_3);
  __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 239, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 239, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_log); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 239, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = PyFloat_FromDouble(__pyx_v_num_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 239, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_11 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_2);
    if (likely(__pyx_t_11)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_11);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_2, function);
    }
  }
  __pyx_t_1 = (__pyx_t_11) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_11, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
  __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 239, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = PyNumber_Subtract(__pyx_t_4, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 239, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_10 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_10 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 239, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_log_density_1 = __pyx_t_10;
 240: 
+241:         return log_density_0, log_density_1
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_log_density_0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 241, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_log_density_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 241, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 241, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_GIVEREF(__pyx_t_2);
  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
  __Pyx_GIVEREF(__pyx_t_1);
  PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1);
  __pyx_t_2 = 0;
  __pyx_t_1 = 0;
  __pyx_r = __pyx_t_4;
  __pyx_t_4 = 0;
  goto __pyx_L0;
 242: 
+243:     cpdef get_probability_of_infeasibility(self, np.ndarray sample, double log_prior_0, double log_prior_1):
static PyObject *__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_9get_probability_of_infeasibility(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyObject *__pyx_f_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_get_probability_of_infeasibility(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *__pyx_v_self, PyArrayObject *__pyx_v_sample, double __pyx_v_log_prior_0, double __pyx_v_log_prior_1, int __pyx_skip_dispatch) {
  double __pyx_v_prob_infeas;
  double __pyx_v_log_density_0;
  double __pyx_v_log_density_1;
  double __pyx_v_posterior_0;
  double __pyx_v_posterior_1;
  PyObject *__pyx_r = NULL;
  __Pyx_TraceDeclarations
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_probability_of_infeasibility", 0);
  __Pyx_TraceCall("get_probability_of_infeasibility", __pyx_f[0], 243, 0, __PYX_ERR(0, 243, __pyx_L1_error));
  /* Check if called by wrapper */
  if (unlikely(__pyx_skip_dispatch)) ;
  /* Check if overridden in Python */
  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
    static PY_UINT64_T __pyx_tp_dict_version = __PYX_DICT_VERSION_INIT, __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT;
    if (unlikely(!__Pyx_object_dict_version_matches(((PyObject *)__pyx_v_self), __pyx_tp_dict_version, __pyx_obj_dict_version))) {
      PY_UINT64_T __pyx_type_dict_guard = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self));
      #endif
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_get_probability_of_infeasibility); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 243, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_9get_probability_of_infeasibility)) {
        __Pyx_XDECREF(__pyx_r);
        __pyx_t_3 = PyFloat_FromDouble(__pyx_v_log_prior_0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 243, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __pyx_t_4 = PyFloat_FromDouble(__pyx_v_log_prior_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 243, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        __Pyx_INCREF(__pyx_t_1);
        __pyx_t_5 = __pyx_t_1; __pyx_t_6 = NULL;
        __pyx_t_7 = 0;
        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
          __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
          if (likely(__pyx_t_6)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
            __Pyx_INCREF(__pyx_t_6);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_5, function);
            __pyx_t_7 = 1;
          }
        }
        #if CYTHON_FAST_PYCALL
        if (PyFunction_Check(__pyx_t_5)) {
          PyObject *__pyx_temp[4] = {__pyx_t_6, ((PyObject *)__pyx_v_sample), __pyx_t_3, __pyx_t_4};
          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 243, __pyx_L1_error)
          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
          __Pyx_GOTREF(__pyx_t_2);
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        } else
        #endif
        #if CYTHON_FAST_PYCCALL
        if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
          PyObject *__pyx_temp[4] = {__pyx_t_6, ((PyObject *)__pyx_v_sample), __pyx_t_3, __pyx_t_4};
          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 243, __pyx_L1_error)
          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
          __Pyx_GOTREF(__pyx_t_2);
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        } else
        #endif
        {
          __pyx_t_8 = PyTuple_New(3+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 243, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_8);
          if (__pyx_t_6) {
            __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
          }
          __Pyx_INCREF(((PyObject *)__pyx_v_sample));
          __Pyx_GIVEREF(((PyObject *)__pyx_v_sample));
          PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, ((PyObject *)__pyx_v_sample));
          __Pyx_GIVEREF(__pyx_t_3);
          PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_t_3);
          __Pyx_GIVEREF(__pyx_t_4);
          PyTuple_SET_ITEM(__pyx_t_8, 2+__pyx_t_7, __pyx_t_4);
          __pyx_t_3 = 0;
          __pyx_t_4 = 0;
          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 243, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_2);
          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
        }
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        __pyx_r = __pyx_t_2;
        __pyx_t_2 = 0;
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        goto __pyx_L0;
      }
      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
      __pyx_tp_dict_version = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self));
      __pyx_obj_dict_version = __Pyx_get_object_dict_version(((PyObject *)__pyx_v_self));
      if (unlikely(__pyx_type_dict_guard != __pyx_tp_dict_version)) {
        __pyx_tp_dict_version = __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT;
      }
      #endif
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
    }
    #endif
  }
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_AddTraceback("gryffin.bayesian_network.kernel_evaluations.KernelEvaluator.get_probability_of_infeasibility", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_TraceReturn(__pyx_r, 0);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_9get_probability_of_infeasibility(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyObject *__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_9get_probability_of_infeasibility(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyArrayObject *__pyx_v_sample = 0;
  double __pyx_v_log_prior_0;
  double __pyx_v_log_prior_1;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_probability_of_infeasibility (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_sample,&__pyx_n_s_log_prior_0,&__pyx_n_s_log_prior_1,0};
    PyObject* values[3] = {0,0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_sample)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_log_prior_0)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("get_probability_of_infeasibility", 1, 3, 3, 1); __PYX_ERR(0, 243, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_log_prior_1)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("get_probability_of_infeasibility", 1, 3, 3, 2); __PYX_ERR(0, 243, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "get_probability_of_infeasibility") < 0)) __PYX_ERR(0, 243, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
    }
    __pyx_v_sample = ((PyArrayObject *)values[0]);
    __pyx_v_log_prior_0 = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_log_prior_0 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 243, __pyx_L3_error)
    __pyx_v_log_prior_1 = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_log_prior_1 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 243, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("get_probability_of_infeasibility", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 243, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("gryffin.bayesian_network.kernel_evaluations.KernelEvaluator.get_probability_of_infeasibility", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sample), __pyx_ptype_5numpy_ndarray, 1, "sample", 0))) __PYX_ERR(0, 243, __pyx_L1_error)
  __pyx_r = __pyx_pf_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_8get_probability_of_infeasibility(((struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *)__pyx_v_self), __pyx_v_sample, __pyx_v_log_prior_0, __pyx_v_log_prior_1);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_8get_probability_of_infeasibility(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *__pyx_v_self, PyArrayObject *__pyx_v_sample, double __pyx_v_log_prior_0, double __pyx_v_log_prior_1) {
  PyObject *__pyx_r = NULL;
  __Pyx_TraceDeclarations
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_probability_of_infeasibility", 0);
  __Pyx_TraceCall("get_probability_of_infeasibility (wrapper)", __pyx_f[0], 243, 0, __PYX_ERR(0, 243, __pyx_L1_error));
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __pyx_f_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_get_probability_of_infeasibility(__pyx_v_self, __pyx_v_sample, __pyx_v_log_prior_0, __pyx_v_log_prior_1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 243, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("gryffin.bayesian_network.kernel_evaluations.KernelEvaluator.get_probability_of_infeasibility", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_TraceReturn(__pyx_r, 0);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 244: 
 245:         # 0 = feasible, 1 = infeasible
 246:         cdef double prob_infeas
 247:         cdef double log_density_0
 248:         cdef double log_density_1
 249:         cdef double posterior_0
 250:         cdef double posterior_1
 251: 
 252:         # get log probabilities
+253:         log_density_0, log_density_1 = self.get_binary_kernel_densities(sample)
  __pyx_t_1 = ((struct __pyx_vtabstruct_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *)__pyx_v_self->__pyx_vtab)->get_binary_kernel_densities(__pyx_v_self, __pyx_v_sample, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 253, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
    PyObject* sequence = __pyx_t_1;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 253, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); 
      __pyx_t_5 = PyTuple_GET_ITEM(sequence, 1); 
    } else {
      __pyx_t_2 = PyList_GET_ITEM(sequence, 0); 
      __pyx_t_5 = PyList_GET_ITEM(sequence, 1); 
    }
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_5);
    #else
    __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 253, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_5 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 253, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    #endif
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_8 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 253, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_9 = Py_TYPE(__pyx_t_8)->tp_iternext;
    index = 0; __pyx_t_2 = __pyx_t_9(__pyx_t_8); if (unlikely(!__pyx_t_2)) goto __pyx_L3_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_2);
    index = 1; __pyx_t_5 = __pyx_t_9(__pyx_t_8); if (unlikely(!__pyx_t_5)) goto __pyx_L3_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_5);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_8), 2) < 0) __PYX_ERR(0, 253, __pyx_L1_error)
    __pyx_t_9 = NULL;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    goto __pyx_L4_unpacking_done;
    __pyx_L3_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __pyx_t_9 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 253, __pyx_L1_error)
    __pyx_L4_unpacking_done:;
  }
  __pyx_t_10 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_10 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 253, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_11 = __pyx_PyFloat_AsDouble(__pyx_t_5); if (unlikely((__pyx_t_11 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 253, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_v_log_density_0 = __pyx_t_10;
  __pyx_v_log_density_1 = __pyx_t_11;
 254: 
 255:         # compute unnormalized posteriors
+256:         posterior_0 = exp(log_density_0 + log_prior_0)
  __pyx_v_posterior_0 = exp((__pyx_v_log_density_0 + __pyx_v_log_prior_0));
+257:         posterior_1 = exp(log_density_1 + log_prior_1)
  __pyx_v_posterior_1 = exp((__pyx_v_log_density_1 + __pyx_v_log_prior_1));
 258: 
 259:         # guard against zero division. This may happen if both densities are zero
+260:         if np.log(posterior_0 + posterior_1) < - 230:  # i.e. less then 1e-100
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_np); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 260, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_log); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 260, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_t_5 = PyFloat_FromDouble((__pyx_v_posterior_0 + __pyx_v_posterior_1)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 260, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_8 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_2);
    if (likely(__pyx_t_8)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_8);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_2, function);
    }
  }
  __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_8, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_5);
  __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 260, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = PyObject_RichCompare(__pyx_t_1, __pyx_int_neg_230, Py_LT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 260, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_12 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_12 < 0)) __PYX_ERR(0, 260, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (__pyx_t_12) {
/* … */
  }
+261:             return exp(log_prior_1) / (exp(log_prior_0) + exp(log_prior_1))  # return prior prob
    __Pyx_XDECREF(__pyx_r);
    __pyx_t_11 = exp(__pyx_v_log_prior_1);
    __pyx_t_10 = (exp(__pyx_v_log_prior_0) + exp(__pyx_v_log_prior_1));
    if (unlikely(__pyx_t_10 == 0)) {
      PyErr_SetString(PyExc_ZeroDivisionError, "float division");
      __PYX_ERR(0, 261, __pyx_L1_error)
    }
    __pyx_t_2 = PyFloat_FromDouble((__pyx_t_11 / __pyx_t_10)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 261, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_r = __pyx_t_2;
    __pyx_t_2 = 0;
    goto __pyx_L0;
 262: 
 263:         # get normalized posterior for prob of infeasible
+264:         prob_infeas = posterior_1 / (posterior_0 + posterior_1)
  __pyx_t_10 = (__pyx_v_posterior_0 + __pyx_v_posterior_1);
  if (unlikely(__pyx_t_10 == 0)) {
    PyErr_SetString(PyExc_ZeroDivisionError, "float division");
    __PYX_ERR(0, 264, __pyx_L1_error)
  }
  __pyx_v_prob_infeas = (__pyx_v_posterior_1 / __pyx_t_10);
 265: 
+266:         return prob_infeas
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_prob_infeas); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 266, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_r = __pyx_t_2;
  __pyx_t_2 = 0;
  goto __pyx_L0;
 267: 
+268:     cpdef get_probability_of_feasibility(self, np.ndarray sample, double log_prior_0, double log_prior_1):
static PyObject *__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_11get_probability_of_feasibility(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyObject *__pyx_f_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_get_probability_of_feasibility(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *__pyx_v_self, PyArrayObject *__pyx_v_sample, double __pyx_v_log_prior_0, double __pyx_v_log_prior_1, int __pyx_skip_dispatch) {
  double __pyx_v_prob_feas;
  double __pyx_v_log_density_0;
  double __pyx_v_log_density_1;
  double __pyx_v_posterior_0;
  double __pyx_v_posterior_1;
  PyObject *__pyx_r = NULL;
  __Pyx_TraceDeclarations
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_probability_of_feasibility", 0);
  __Pyx_TraceCall("get_probability_of_feasibility", __pyx_f[0], 268, 0, __PYX_ERR(0, 268, __pyx_L1_error));
  /* Check if called by wrapper */
  if (unlikely(__pyx_skip_dispatch)) ;
  /* Check if overridden in Python */
  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
    static PY_UINT64_T __pyx_tp_dict_version = __PYX_DICT_VERSION_INIT, __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT;
    if (unlikely(!__Pyx_object_dict_version_matches(((PyObject *)__pyx_v_self), __pyx_tp_dict_version, __pyx_obj_dict_version))) {
      PY_UINT64_T __pyx_type_dict_guard = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self));
      #endif
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_get_probability_of_feasibility); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 268, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_11get_probability_of_feasibility)) {
        __Pyx_XDECREF(__pyx_r);
        __pyx_t_3 = PyFloat_FromDouble(__pyx_v_log_prior_0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 268, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __pyx_t_4 = PyFloat_FromDouble(__pyx_v_log_prior_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 268, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        __Pyx_INCREF(__pyx_t_1);
        __pyx_t_5 = __pyx_t_1; __pyx_t_6 = NULL;
        __pyx_t_7 = 0;
        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
          __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
          if (likely(__pyx_t_6)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
            __Pyx_INCREF(__pyx_t_6);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_5, function);
            __pyx_t_7 = 1;
          }
        }
        #if CYTHON_FAST_PYCALL
        if (PyFunction_Check(__pyx_t_5)) {
          PyObject *__pyx_temp[4] = {__pyx_t_6, ((PyObject *)__pyx_v_sample), __pyx_t_3, __pyx_t_4};
          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 268, __pyx_L1_error)
          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
          __Pyx_GOTREF(__pyx_t_2);
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        } else
        #endif
        #if CYTHON_FAST_PYCCALL
        if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
          PyObject *__pyx_temp[4] = {__pyx_t_6, ((PyObject *)__pyx_v_sample), __pyx_t_3, __pyx_t_4};
          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 268, __pyx_L1_error)
          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
          __Pyx_GOTREF(__pyx_t_2);
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        } else
        #endif
        {
          __pyx_t_8 = PyTuple_New(3+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 268, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_8);
          if (__pyx_t_6) {
            __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
          }
          __Pyx_INCREF(((PyObject *)__pyx_v_sample));
          __Pyx_GIVEREF(((PyObject *)__pyx_v_sample));
          PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, ((PyObject *)__pyx_v_sample));
          __Pyx_GIVEREF(__pyx_t_3);
          PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_t_3);
          __Pyx_GIVEREF(__pyx_t_4);
          PyTuple_SET_ITEM(__pyx_t_8, 2+__pyx_t_7, __pyx_t_4);
          __pyx_t_3 = 0;
          __pyx_t_4 = 0;
          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 268, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_2);
          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
        }
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        __pyx_r = __pyx_t_2;
        __pyx_t_2 = 0;
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        goto __pyx_L0;
      }
      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
      __pyx_tp_dict_version = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self));
      __pyx_obj_dict_version = __Pyx_get_object_dict_version(((PyObject *)__pyx_v_self));
      if (unlikely(__pyx_type_dict_guard != __pyx_tp_dict_version)) {
        __pyx_tp_dict_version = __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT;
      }
      #endif
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
    }
    #endif
  }
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_AddTraceback("gryffin.bayesian_network.kernel_evaluations.KernelEvaluator.get_probability_of_feasibility", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_TraceReturn(__pyx_r, 0);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_11get_probability_of_feasibility(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyObject *__pyx_pw_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_11get_probability_of_feasibility(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyArrayObject *__pyx_v_sample = 0;
  double __pyx_v_log_prior_0;
  double __pyx_v_log_prior_1;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_probability_of_feasibility (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_sample,&__pyx_n_s_log_prior_0,&__pyx_n_s_log_prior_1,0};
    PyObject* values[3] = {0,0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_sample)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_log_prior_0)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("get_probability_of_feasibility", 1, 3, 3, 1); __PYX_ERR(0, 268, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_log_prior_1)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("get_probability_of_feasibility", 1, 3, 3, 2); __PYX_ERR(0, 268, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "get_probability_of_feasibility") < 0)) __PYX_ERR(0, 268, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
    }
    __pyx_v_sample = ((PyArrayObject *)values[0]);
    __pyx_v_log_prior_0 = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_log_prior_0 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 268, __pyx_L3_error)
    __pyx_v_log_prior_1 = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_log_prior_1 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 268, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("get_probability_of_feasibility", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 268, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("gryffin.bayesian_network.kernel_evaluations.KernelEvaluator.get_probability_of_feasibility", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sample), __pyx_ptype_5numpy_ndarray, 1, "sample", 0))) __PYX_ERR(0, 268, __pyx_L1_error)
  __pyx_r = __pyx_pf_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_10get_probability_of_feasibility(((struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *)__pyx_v_self), __pyx_v_sample, __pyx_v_log_prior_0, __pyx_v_log_prior_1);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_10get_probability_of_feasibility(struct __pyx_obj_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *__pyx_v_self, PyArrayObject *__pyx_v_sample, double __pyx_v_log_prior_0, double __pyx_v_log_prior_1) {
  PyObject *__pyx_r = NULL;
  __Pyx_TraceDeclarations
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_probability_of_feasibility", 0);
  __Pyx_TraceCall("get_probability_of_feasibility (wrapper)", __pyx_f[0], 268, 0, __PYX_ERR(0, 268, __pyx_L1_error));
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __pyx_f_7gryffin_16bayesian_network_18kernel_evaluations_15KernelEvaluator_get_probability_of_feasibility(__pyx_v_self, __pyx_v_sample, __pyx_v_log_prior_0, __pyx_v_log_prior_1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 268, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("gryffin.bayesian_network.kernel_evaluations.KernelEvaluator.get_probability_of_feasibility", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_TraceReturn(__pyx_r, 0);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 269: 
 270:         # 0 = feasible, 1 = infeasible
 271:         cdef double prob_feas
 272:         cdef double log_density_0
 273:         cdef double log_density_1
 274:         cdef double posterior_0
 275:         cdef double posterior_1
 276: 
 277:         # get log probabilities
+278:         log_density_0, log_density_1 = self.get_binary_kernel_densities(sample)
  __pyx_t_1 = ((struct __pyx_vtabstruct_7gryffin_16bayesian_network_18kernel_evaluations_KernelEvaluator *)__pyx_v_self->__pyx_vtab)->get_binary_kernel_densities(__pyx_v_self, __pyx_v_sample, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 278, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
    PyObject* sequence = __pyx_t_1;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 278, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); 
      __pyx_t_5 = PyTuple_GET_ITEM(sequence, 1); 
    } else {
      __pyx_t_2 = PyList_GET_ITEM(sequence, 0); 
      __pyx_t_5 = PyList_GET_ITEM(sequence, 1); 
    }
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_5);
    #else
    __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 278, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_5 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 278, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    #endif
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_8 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 278, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_9 = Py_TYPE(__pyx_t_8)->tp_iternext;
    index = 0; __pyx_t_2 = __pyx_t_9(__pyx_t_8); if (unlikely(!__pyx_t_2)) goto __pyx_L3_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_2);
    index = 1; __pyx_t_5 = __pyx_t_9(__pyx_t_8); if (unlikely(!__pyx_t_5)) goto __pyx_L3_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_5);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_8), 2) < 0) __PYX_ERR(0, 278, __pyx_L1_error)
    __pyx_t_9 = NULL;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    goto __pyx_L4_unpacking_done;
    __pyx_L3_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __pyx_t_9 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 278, __pyx_L1_error)
    __pyx_L4_unpacking_done:;
  }
  __pyx_t_10 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_10 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 278, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_11 = __pyx_PyFloat_AsDouble(__pyx_t_5); if (unlikely((__pyx_t_11 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 278, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_v_log_density_0 = __pyx_t_10;
  __pyx_v_log_density_1 = __pyx_t_11;
 279: 
 280:         # compute unnormalized posteriors
+281:         posterior_0 = exp(log_density_0 + log_prior_0)
  __pyx_v_posterior_0 = exp((__pyx_v_log_density_0 + __pyx_v_log_prior_0));
+282:         posterior_1 = exp(log_density_1 + log_prior_1)
  __pyx_v_posterior_1 = exp((__pyx_v_log_density_1 + __pyx_v_log_prior_1));
 283: 
 284:         # guard against zero division. This may happen if both densities are zero
+285:         if np.log(posterior_0 + posterior_1) < - 230:  # i.e. less then 1e-100
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_np); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 285, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_log); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 285, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_t_5 = PyFloat_FromDouble((__pyx_v_posterior_0 + __pyx_v_posterior_1)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 285, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_8 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_2);
    if (likely(__pyx_t_8)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_8);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_2, function);
    }
  }
  __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_8, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_5);
  __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 285, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = PyObject_RichCompare(__pyx_t_1, __pyx_int_neg_230, Py_LT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 285, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_12 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_12 < 0)) __PYX_ERR(0, 285, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (__pyx_t_12) {
/* … */
  }
+286:             return exp(log_prior_1) / (exp(log_prior_0) + exp(log_prior_1))  # return prior prob
    __Pyx_XDECREF(__pyx_r);
    __pyx_t_11 = exp(__pyx_v_log_prior_1);
    __pyx_t_10 = (exp(__pyx_v_log_prior_0) + exp(__pyx_v_log_prior_1));
    if (unlikely(__pyx_t_10 == 0)) {
      PyErr_SetString(PyExc_ZeroDivisionError, "float division");
      __PYX_ERR(0, 286, __pyx_L1_error)
    }
    __pyx_t_2 = PyFloat_FromDouble((__pyx_t_11 / __pyx_t_10)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 286, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_r = __pyx_t_2;
    __pyx_t_2 = 0;
    goto __pyx_L0;
 287: 
 288:         # get normalized posterior for prob of infeasible
+289:         prob_feas = posterior_0 / (posterior_0 + posterior_1)
  __pyx_t_10 = (__pyx_v_posterior_0 + __pyx_v_posterior_1);
  if (unlikely(__pyx_t_10 == 0)) {
    PyErr_SetString(PyExc_ZeroDivisionError, "float division");
    __PYX_ERR(0, 289, __pyx_L1_error)
  }
  __pyx_v_prob_feas = (__pyx_v_posterior_0 / __pyx_t_10);
 290: 
+291:         return prob_feas
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_prob_feas); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 291, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_r = __pyx_t_2;
  __pyx_t_2 = 0;
  goto __pyx_L0;