# Path: treecat/util.py
# COUNTERS = ProfilingSet(lambda: 0)
# 
# Path: treecat/util.py
# HISTOGRAMS = ProfilingSet(Counter)
# 
# Path: treecat/util.py
# SERIES = ProfilingSet(list)
# 
# Path: treecat/util.py
# TREECAT_JIT = int(os.environ.get('TREECAT_JIT', 1))
# TREECAT_THREADS = int(
#     os.environ.get('TREECAT_THREADS', multiprocessing.cpu_count()))
# PROFILING = int(os.environ.get('TREECAT_PROFILE', 0))
# LOG_LEVEL = int(os.environ.get('TREECAT_LOG_LEVEL', logging.CRITICAL))
# LOG_FILENAME = os.environ.get('TREECAT_LOG_FILE')
# LOG_FORMAT = '%(levelname).1s %(process)d %(name)s %(message)s'
#     N, M = probs.shape
#     V = ragged_index.shape[0] - 1
#     R = ragged_index[-1]
#     N, R = data.shape
#     V = len(ragged_index) - 1
# POOL = None
#         POOL = multiprocessing.Pool(TREECAT_THREADS)
# TIMERS = defaultdict(ProfileTimer)
# COUNTERS = ProfilingSet(lambda: 0)
# HISTOGRAMS = ProfilingSet(Counter)
# SERIES = ProfilingSet(list)
# def TODO(message=''):
# def no_jit(*args, **kwargs):
# def jit_random_seed(seed):
# def set_random_seed(seed):
# def np_printoptions(**kwargs):
# def sample_from_probs(probs):
# def sample_from_probs2(probs, out=None):
# def quantize_from_probs2(probs, resolution):
# def make_ragged_index(columns):
# def make_ragged_mask(ragged_index, mask):
# def count_observations(ragged_index, data):
# def guess_counts(ragged_index, data):
# def parallel_map(fun, args):
#     def __init__(self):
#     def __enter__(self):
#     def __exit__(self, type, value, traceback):
# def profile_timed(fun):
#     def profiled_fun(*args, **kwargs):
# def get_profiling_stats():
# def log_profiling_stats():
# class ProfilingSet(defaultdict):
# class ProfileTimer(object):
# 
# Path: treecat/util.py
# TREECAT_JIT = int(os.environ.get('TREECAT_JIT', 1))
# TREECAT_THREADS = int(
#     os.environ.get('TREECAT_THREADS', multiprocessing.cpu_count()))
# PROFILING = int(os.environ.get('TREECAT_PROFILE', 0))
# LOG_LEVEL = int(os.environ.get('TREECAT_LOG_LEVEL', logging.CRITICAL))
# LOG_FILENAME = os.environ.get('TREECAT_LOG_FILE')
# LOG_FORMAT = '%(levelname).1s %(process)d %(name)s %(message)s'
#     N, M = probs.shape
#     V = ragged_index.shape[0] - 1
#     R = ragged_index[-1]
#     N, R = data.shape
#     V = len(ragged_index) - 1
# POOL = None
#         POOL = multiprocessing.Pool(TREECAT_THREADS)
# TIMERS = defaultdict(ProfileTimer)
# COUNTERS = ProfilingSet(lambda: 0)
# HISTOGRAMS = ProfilingSet(Counter)
# SERIES = ProfilingSet(list)
# def TODO(message=''):
# def no_jit(*args, **kwargs):
# def jit_random_seed(seed):
# def set_random_seed(seed):
# def np_printoptions(**kwargs):
# def sample_from_probs(probs):
# def sample_from_probs2(probs, out=None):
# def quantize_from_probs2(probs, resolution):
# def make_ragged_index(columns):
# def make_ragged_mask(ragged_index, mask):
# def count_observations(ragged_index, data):
# def guess_counts(ragged_index, data):
# def parallel_map(fun, args):
#     def __init__(self):
#     def __enter__(self):
#     def __exit__(self, type, value, traceback):
# def profile_timed(fun):
#     def profiled_fun(*args, **kwargs):
# def get_profiling_stats():
# def log_profiling_stats():
# class ProfilingSet(defaultdict):
# class ProfileTimer(object):
# 
# Path: treecat/util.py
# @jit(nopython=True, cache=True)
# def sample_from_probs(probs):
#     """Sample from a vector of non-normalized probabilitites.
# 
#     Args:
#         probs: An [M]-shaped numpy array of non-normalized probabilities.
# 
#     Returns:
#         An integer in range(M).
#     """
#     cdf = probs.cumsum()
#     return (np.random.rand() * cdf[-1] < cdf).argmax()


import logging
import numba
import numpy as np
from collections import defaultdict
from collections import deque
from scipy.sparse.csgraph import minimum_spanning_tree
from six.moves import range
from six.moves import zip
from treecat.util import COUNTERS
from treecat.util import HISTOGRAMS
from treecat.util import SERIES
from treecat.util import jit
from treecat.util import profile
from treecat.util import sample_from_probs
    COUNTERS.sample_tree_accept += accepted
    COUNTERS.sample_tree_propose += E
    SERIES.sample_tree_accepted.append(accepted)
    HISTOGRAMS.sample_tree_log2_choices.update(log2_choices)

    edges = sorted((grid[1, k], grid[2, k]) for k in e2k)
    assert len(edges) == E
    return edges


def triangular_to_square(grid, triangle):
    """Convert a packed triangular matrix to a square matrix.

    Args:
        grid: A 3 x K array as returned by make_complete_graph().
        triangle: A length-K array.

    Returns:
        A square symmetric V x V array with zero on the diagonal.
    """
    K = len(triangle)
    assert grid.shape == (3, K)
    V = int(round(0.5 + (0.25 + 2 * K)**0.5))
    assert K == V * (V - 1) // 2
    square = np.zeros([V, V], dtype=triangle.dtype)
    square[grid[1, :], grid[2, :]] = triangle
    square[grid[2, :], grid[1, :]] = triangle
    return square



# Path: treecat/util.py
# COUNTERS = ProfilingSet(lambda: 0)
# 
# Path: treecat/util.py
# HISTOGRAMS = ProfilingSet(Counter)
# 
# Path: treecat/util.py
# SERIES = ProfilingSet(list)
# 
# Path: treecat/util.py
# TREECAT_JIT = int(os.environ.get('TREECAT_JIT', 1))
# TREECAT_THREADS = int(
#     os.environ.get('TREECAT_THREADS', multiprocessing.cpu_count()))
# PROFILING = int(os.environ.get('TREECAT_PROFILE', 0))
# LOG_LEVEL = int(os.environ.get('TREECAT_LOG_LEVEL', logging.CRITICAL))
# LOG_FILENAME = os.environ.get('TREECAT_LOG_FILE')
# LOG_FORMAT = '%(levelname).1s %(process)d %(name)s %(message)s'
#     N, M = probs.shape
#     V = ragged_index.shape[0] - 1
#     R = ragged_index[-1]
#     N, R = data.shape
#     V = len(ragged_index) - 1
# POOL = None
#         POOL = multiprocessing.Pool(TREECAT_THREADS)
# TIMERS = defaultdict(ProfileTimer)
# COUNTERS = ProfilingSet(lambda: 0)
# HISTOGRAMS = ProfilingSet(Counter)
# SERIES = ProfilingSet(list)
# def TODO(message=''):
# def no_jit(*args, **kwargs):
# def jit_random_seed(seed):
# def set_random_seed(seed):
# def np_printoptions(**kwargs):
# def sample_from_probs(probs):
# def sample_from_probs2(probs, out=None):
# def quantize_from_probs2(probs, resolution):
# def make_ragged_index(columns):
# def make_ragged_mask(ragged_index, mask):
# def count_observations(ragged_index, data):
# def guess_counts(ragged_index, data):
# def parallel_map(fun, args):
#     def __init__(self):
#     def __enter__(self):
#     def __exit__(self, type, value, traceback):
# def profile_timed(fun):
#     def profiled_fun(*args, **kwargs):
# def get_profiling_stats():
# def log_profiling_stats():
# class ProfilingSet(defaultdict):
# class ProfileTimer(object):
# 
# Path: treecat/util.py
# TREECAT_JIT = int(os.environ.get('TREECAT_JIT', 1))
# TREECAT_THREADS = int(
#     os.environ.get('TREECAT_THREADS', multiprocessing.cpu_count()))
# PROFILING = int(os.environ.get('TREECAT_PROFILE', 0))
# LOG_LEVEL = int(os.environ.get('TREECAT_LOG_LEVEL', logging.CRITICAL))
# LOG_FILENAME = os.environ.get('TREECAT_LOG_FILE')
# LOG_FORMAT = '%(levelname).1s %(process)d %(name)s %(message)s'
#     N, M = probs.shape
#     V = ragged_index.shape[0] - 1
#     R = ragged_index[-1]
#     N, R = data.shape
#     V = len(ragged_index) - 1
# POOL = None
#         POOL = multiprocessing.Pool(TREECAT_THREADS)
# TIMERS = defaultdict(ProfileTimer)
# COUNTERS = ProfilingSet(lambda: 0)
# HISTOGRAMS = ProfilingSet(Counter)
# SERIES = ProfilingSet(list)
# def TODO(message=''):
# def no_jit(*args, **kwargs):
# def jit_random_seed(seed):
# def set_random_seed(seed):
# def np_printoptions(**kwargs):
# def sample_from_probs(probs):
# def sample_from_probs2(probs, out=None):
# def quantize_from_probs2(probs, resolution):
# def make_ragged_index(columns):
# def make_ragged_mask(ragged_index, mask):
# def count_observations(ragged_index, data):
# def guess_counts(ragged_index, data):
# def parallel_map(fun, args):
#     def __init__(self):
#     def __enter__(self):
#     def __exit__(self, type, value, traceback):
# def profile_timed(fun):
#     def profiled_fun(*args, **kwargs):
# def get_profiling_stats():
# def log_profiling_stats():
# class ProfilingSet(defaultdict):
# class ProfileTimer(object):
# 
# Path: treecat/util.py
# @jit(nopython=True, cache=True)
# def sample_from_probs(probs):
#     """Sample from a vector of non-normalized probabilitites.
# 
#     Args:
#         probs: An [M]-shaped numpy array of non-normalized probabilities.
# 
#     Returns:
#         An integer in range(M).
#     """
#     cdf = probs.cumsum()
#     return (np.random.rand() * cdf[-1] < cdf).argmax()


# Path: treecat/structure.py
import logging
import numba
import numpy as np
from collections import defaultdict
from collections import deque
from scipy.sparse.csgraph import minimum_spanning_tree
from six.moves import range
from six.moves import zip
from treecat.util import COUNTERS
from treecat.util import HISTOGRAMS
from treecat.util import SERIES
from treecat.util import jit
from treecat.util import profile
from treecat.util import sample_from_probs

    COUNTERS.sample_tree_accept += accepted
    COUNTERS.sample_tree_propose += E
    SERIES.sample_tree_accepted.append(accepted)
    HISTOGRAMS.sample_tree_log2_choices.update(log2_choices)

    edges = sorted((grid[1, k], grid[2, k]) for k in e2k)
    assert len(edges) == E
    return edges


def triangular_to_square(grid, triangle):
    """Convert a packed triangular matrix to a square matrix.

    Args:
        grid: A 3 x K array as returned by make_complete_graph().
        triangle: A length-K array.

    Returns:
        A square symmetric V x V array with zero on the diagonal.
    """
    K = len(triangle)
    assert grid.shape == (3, K)
    V = int(round(0.5 + (0.25 + 2 * K)**0.5))
    assert K == V * (V - 1) // 2
    square = np.zeros([V, V], dtype=triangle.dtype)
    square[grid[1, :], grid[2, :]] = triangle
    square[grid[2, :], grid[1, :]] = triangle
    return square



@profile