# Path: pyglm/utils/parallel_util.py
# def parallel_compute_ll(dview,
#                         v,
#                         N):
#     """ Compute the log prob in parallel
#     """
#     ll_tot = 0
#     # Decorate with @interactive to ensure that the function runs
#     # in the __main__ namespace that contains 'popn'
#     @interactive
#     def _compute_glm_ll(n, vs):
#         print "Computing log lkhd for GLM %d" % n
#         syms = popn.get_variables()
#         nvars = popn.extract_vars(vs, n)
#         lp = seval(popn.glm.ll,
#                    syms,
#                    nvars)
#         return lp
# 
#     ll_glms = dview.map_async(_compute_glm_ll,
#                               range(N),
#                               [v]*N)
# 
#     ll_tot += sum(ll_glms.get())
#     return ll_tot
# 
# def parallel_compute_log_p(dview,
#                            master,
#                            v,
#                            N):
#     """ Compute the log prob in parallel
#     """
# 
#     # Compute the log probabaility of global variables
#     # (e.g. the network) on the first node
#     lp_tot = 0
# 
#     @interactive
#     def _compute_network_lp(vs):
#         print "Computing log prob for network"
#         syms = popn.get_variables()
#         nvars = popn.extract_vars(vs,0)
#         lp = seval(popn.network.log_p,
#                    syms,
#                    nvars)
#         #lp = popn.network.log_p.eval(dict(zip(_flatten(tmpsyms),
#                                      #        _flatten(tmpnvars))),
#                                      #on_unused_input='ignore')
#         return lp
# 
#     lp_tot += master.apply_sync(_compute_network_lp, v)
# 
#     # Decorate with @interactive to ensure that the function runs
#     # in the __main__ namespace that contains 'popn'
#     @interactive
#     def _compute_glm_lp(n, vs):
#         print "Computing lp for GLM %d" % n
#         syms = popn.get_variables()
#         nvars = popn.extract_vars(vs, n)
#         lp = seval(popn.glm.log_p,
#                    syms,
#                    nvars)
#         return lp
# 
#     lp_glms = dview.map_async(_compute_glm_lp,
#                               range(N),
#                               [v]*N)
#     # print lp_glms.get()
#     # lp_glms.display_outputs()
# 
#     lp_tot += sum(lp_glms.get())
#     return lp_tot
# 
# def parallel_compute_log_prior(dview,
#                                master,
#                                v,
#                                N):
#     """ Compute the log prob in parallel
#     """
# 
#     # Compute the log probabaility of global variables
#     # (e.g. the network) on the first node
#     lp_tot = 0
# 
#     @interactive
#     def _compute_network_lp(vs):
#         print "Computing log prob for network"
#         syms = popn.get_variables()
#         nvars = popn.extract_vars(vs,0)
#         lp = seval(popn.network.log_p,
#                    syms,
#                    nvars)
#         #lp = popn.network.log_p.eval(dict(zip(_flatten(tmpsyms),
#                                      #        _flatten(tmpnvars))),
#                                      #on_unused_input='ignore')
#         return lp
# 
#     lp_tot += master.apply_sync(_compute_network_lp, v)
# 
#     # Decorate with @interactive to ensure that the function runs
#     # in the __main__ namespace that contains 'popn'
#     @interactive
#     def _compute_glm_lp(n, vs):
#         print "Computing log prior for GLM %d" % n
#         syms = popn.get_variables()
#         nvars = popn.extract_vars(vs, n)
#         lp = seval(popn.glm.log_prior,
#                    syms,
#                    nvars)
#         return lp
# 
#     lp_glms = dview.map_async(_compute_glm_lp,
#                               range(N),
#                               [v]*N)
#     # print lp_glms.get()
#     # lp_glms.display_outputs()
# 
#     lp_tot += sum(lp_glms.get())
#     return lp_tot


import copy
import numpy as np
    import os
    import cPickle
    import time
from IPython.parallel.util import interactive
from pyglm.utils.parallel_util import parallel_compute_ll, \
                                parallel_compute_log_p, \
                                parallel_compute_log_prior
    @interactive
    def _parallel_update(i, x, n):
        return parallel_updates[i].update(x, n)
        
    @interactive
    def _serial_update(i, x):
        return serial_updates[i].update(x)

    ## DEBUG Profile the Gibbs sampling loop
    # import cProfile, pstats, StringIO
    # pr = cProfile.Profile()
    # pr.enable()
    ## END DEBUG

    # Alternate fitting the network and fitting the GLMs
    lp_smpls = np.zeros(N_samples+1)
    lp_smpls[0] = parallel_compute_log_p(dview, master, x0, N)

    ll_smpls = np.zeros(N_samples+1)
    ll_smpls[0] = parallel_compute_ll(dview, x0, N)

    lprior = parallel_compute_log_prior(dview, master, x0, N)

    x_smpls = [x0]
    x = copy.deepcopy(x0)

    start_time = time.time()
    for smpl in np.arange(N_samples):
        # Print the current log likelihood
        ll = parallel_compute_ll(dview, x, N)

# Path: pyglm/utils/parallel_util.py
# def parallel_compute_ll(dview,
#                         v,
#                         N):
#     """ Compute the log prob in parallel
#     """
#     ll_tot = 0
#     # Decorate with @interactive to ensure that the function runs
#     # in the __main__ namespace that contains 'popn'
#     @interactive
#     def _compute_glm_ll(n, vs):
#         print "Computing log lkhd for GLM %d" % n
#         syms = popn.get_variables()
#         nvars = popn.extract_vars(vs, n)
#         lp = seval(popn.glm.ll,
#                    syms,
#                    nvars)
#         return lp
# 
#     ll_glms = dview.map_async(_compute_glm_ll,
#                               range(N),
#                               [v]*N)
# 
#     ll_tot += sum(ll_glms.get())
#     return ll_tot
# 
# def parallel_compute_log_p(dview,
#                            master,
#                            v,
#                            N):
#     """ Compute the log prob in parallel
#     """
# 
#     # Compute the log probabaility of global variables
#     # (e.g. the network) on the first node
#     lp_tot = 0
# 
#     @interactive
#     def _compute_network_lp(vs):
#         print "Computing log prob for network"
#         syms = popn.get_variables()
#         nvars = popn.extract_vars(vs,0)
#         lp = seval(popn.network.log_p,
#                    syms,
#                    nvars)
#         #lp = popn.network.log_p.eval(dict(zip(_flatten(tmpsyms),
#                                      #        _flatten(tmpnvars))),
#                                      #on_unused_input='ignore')
#         return lp
# 
#     lp_tot += master.apply_sync(_compute_network_lp, v)
# 
#     # Decorate with @interactive to ensure that the function runs
#     # in the __main__ namespace that contains 'popn'
#     @interactive
#     def _compute_glm_lp(n, vs):
#         print "Computing lp for GLM %d" % n
#         syms = popn.get_variables()
#         nvars = popn.extract_vars(vs, n)
#         lp = seval(popn.glm.log_p,
#                    syms,
#                    nvars)
#         return lp
# 
#     lp_glms = dview.map_async(_compute_glm_lp,
#                               range(N),
#                               [v]*N)
#     # print lp_glms.get()
#     # lp_glms.display_outputs()
# 
#     lp_tot += sum(lp_glms.get())
#     return lp_tot
# 
# def parallel_compute_log_prior(dview,
#                                master,
#                                v,
#                                N):
#     """ Compute the log prob in parallel
#     """
# 
#     # Compute the log probabaility of global variables
#     # (e.g. the network) on the first node
#     lp_tot = 0
# 
#     @interactive
#     def _compute_network_lp(vs):
#         print "Computing log prob for network"
#         syms = popn.get_variables()
#         nvars = popn.extract_vars(vs,0)
#         lp = seval(popn.network.log_p,
#                    syms,
#                    nvars)
#         #lp = popn.network.log_p.eval(dict(zip(_flatten(tmpsyms),
#                                      #        _flatten(tmpnvars))),
#                                      #on_unused_input='ignore')
#         return lp
# 
#     lp_tot += master.apply_sync(_compute_network_lp, v)
# 
#     # Decorate with @interactive to ensure that the function runs
#     # in the __main__ namespace that contains 'popn'
#     @interactive
#     def _compute_glm_lp(n, vs):
#         print "Computing log prior for GLM %d" % n
#         syms = popn.get_variables()
#         nvars = popn.extract_vars(vs, n)
#         lp = seval(popn.glm.log_prior,
#                    syms,
#                    nvars)
#         return lp
# 
#     lp_glms = dview.map_async(_compute_glm_lp,
#                               range(N),
#                               [v]*N)
#     # print lp_glms.get()
#     # lp_glms.display_outputs()
# 
#     lp_tot += sum(lp_glms.get())
#     return lp_tot


# Path: pyglm/inference/parallel_gibbs.py
import copy
import numpy as np
    import os
    import cPickle
    import time
from IPython.parallel.util import interactive
from pyglm.utils.parallel_util import parallel_compute_ll, \
                                parallel_compute_log_p, \
                                parallel_compute_log_prior

    @interactive
    def _parallel_update(i, x, n):
        return parallel_updates[i].update(x, n)
        
    @interactive
    def _serial_update(i, x):
        return serial_updates[i].update(x)

    ## DEBUG Profile the Gibbs sampling loop
    # import cProfile, pstats, StringIO
    # pr = cProfile.Profile()
    # pr.enable()
    ## END DEBUG

    # Alternate fitting the network and fitting the GLMs
    lp_smpls = np.zeros(N_samples+1)
    lp_smpls[0] = parallel_compute_log_p(dview, master, x0, N)

    ll_smpls = np.zeros(N_samples+1)
    ll_smpls[0] = parallel_compute_ll(dview, x0, N)

    lprior = parallel_compute_log_prior(dview, master, x0, N)

    x_smpls = [x0]
    x = copy.deepcopy(x0)

    start_time = time.time()
    for smpl in np.arange(N_samples):
        # Print the current log likelihood
        ll = parallel_compute_ll(dview, x, N)

        lp = parallel_compute_log_p(dview,