def smoothing_worker(method=None, N=100, seed=None, fk=None, fk_info=None,
                     add_func=None, log_gamma=None):
    """Generic worker for off-line smoothing algorithms.

    This worker may be used in conjunction with utils.multiplexer in order to 
    run in parallel (and eventually compare) off-line smoothing algorithms.
    
    Parameters
    ----------
    method: string
         ['FFBS_ON', 'FFBS_ON2', 'FFBS_QMC', 
           'two-filter_ON', 'two-filter_ON_prop', 'two-filter_ON2']
    N: int
        number of particles 
    seed: int
        random generator seed; if None, generator is not seeded
    fk: Feynman-Kac object
        The Feynman-Kac model for the forward filter
    fk_info: Feynman-Kac object (default=None)
        the Feynman-Kac model for the information filter; if None, 
        set to the same Feynman-Kac model as fk, with data in reverse
    add_func: function, with signature (t, x, xf) 
        additive function, at time t, for particles x=x_t and xf=x_{t+1}
    log_gamma: function
        log of function gamma (see book)

    Returns
    -------
    a dict with fields:
        est: a ndarray of length T
        cpu_time 
    """
    T = fk.T  
    if fk_info is None: 
        fk_info = fk.__class__(ssm=fk.ssm, data=fk.data[::-1])
    if seed:
        random.seed(seed)
    est = np.zeros(T - 1)
    if method=='FFBS_QMC':
        pf = particles.SQMC(fk=fk, N=N, store_history=True)
    else:
        pf = particles.SMC(fk=fk, N=N, store_history=True)
    tic = time.clock()
    pf.run()
    if method in ['FFBS_ON', 'FFBS_ON2', 'FFBS_QMC']:
        if method.startswith('FFBS_ON'): 
            z = pf.hist.backward_sampling(N, linear_cost=(method == 'FFBS_ON'))
        else:
            z = pf.hist.backward_sampling_qmc(N)
        for t in range(T - 1):
            est[t] = np.mean(add_func(t, z[t], z[t + 1]))
    elif method in ['two-filter_ON2', 'two-filter_ON', 'two-filter_ON_prop']:
        infopf = particles.SMC(fk=fk_info, N=N, store_history=True)
        infopf.run()
        for t in range(T - 1):
            psi = lambda x, xf: add_func(t, x, xf)
            if method == 'two-filter_ON2':
                est[t] = pf.hist.twofilter_smoothing(t, infopf, psi, log_gamma)
            else:
                ti = T - 2 - t  # t+1 for info filter
                if method == 'two-filter_ON_prop':
                    modif_fwd = stats.norm.logpdf(pf.hist.X[t],
                                          loc=np.mean(infopf.hist.X[ti + 1]),
                                          scale=np.std(infopf.hist.X[ti + 1]))
                    modif_info = stats.norm.logpdf(infopf.hist.X[ti],
                                           loc=np.mean(pf.hist.X[t + 1]),
                                           scale=np.std(pf.hist.X[t + 1]))
                else:
                    modif_fwd, modif_info = None, None
                est[t] = pf.hist.twofilter_smoothing(t, infopf, psi, log_gamma,
                                                     linear_cost=True,
                                                     modif_forward=modif_fwd,
                                                     modif_info=modif_info)
    else:
        print('no such method?')
    cpu_time = time.clock() - tic
    print(method + ' took %.2f s for N=%i' % (cpu_time, N))
    return {'est': est, 'cpu': cpu_time}
Generic worker for off-line smoothing algorithms.

    This worker may be used in conjunction with utils.multiplexer in order to 
    run in parallel (and eventually compare) off-line smoothing algorithms.
    
    Parameters
    ----------
    method: string
         ['FFBS_ON', 'FFBS_ON2', 'FFBS_QMC', 
           'two-filter_ON', 'two-filter_ON_prop', 'two-filter_ON2']
    N: int
        number of particles 
    seed: int
        random generator seed; if None, generator is not seeded
    fk: Feynman-Kac object
        The Feynman-Kac model for the forward filter
    fk_info: Feynman-Kac object (default=None)
        the Feynman-Kac model for the information filter; if None, 
        set to the same Feynman-Kac model as fk, with data in reverse
    add_func: function, with signature (t, x, xf) 
        additive function, at time t, for particles x=x_t and xf=x_{t+1}
    log_gamma: function
        log of function gamma (see book)

    Returns
    -------
    a dict with fields:
        est: a ndarray of length T
        cpu_time