<commit_before>"""
Interface for parameterized objects. The Parameterized class represents a
parameterized object which can get/set its values and evaluate a log-prior over
those values. Note, however, that this does not define any error or probability
terms for the object. For this, see the Model class.
"""

from __future__ import division
from __future__ import absolute_import
from __future__ import print_function

import numpy as np
import copy
import tabulate
import warnings
import collections

from .priors import PRIORS
from .domains import REAL
from .domains import BOUNDS, TRANSFORMS

__all__ = ['Parameterized']


# CONSTANTS FOR ADJUSTING PARAMETER FORMATTING
PRECISION = 2


def _outbounds(bounds, theta):
    """
    Check whether a vector is inside the given bounds.
    """
    bounds = np.array(bounds, ndmin=2)
    return np.any(theta < bounds[:, 0]) or np.any(theta > bounds[:, 1])


def _deepcopy(obj, memo):
    """
    Method equivalent to `copy.deepcopy` except that it ignored the
    implementation of `obj.__deepcopy__`. This allows for an object to
    implement deepcopy, populate its memo dictionary, and then call this
    version of deepcopy.
    """
    ret = type(obj).__new__(type(obj))
    memo[id(obj)] = ret
    for key, val in obj.__dict__.items():
        setattr(ret, key, copy.deepcopy(val, memo))
    return ret


class Parameter(object):
    """
    Representation of a parameter vector.
    """
    def __init__(self, value, domain, prior=None, block=0):
        self.nparams = value.size
        self.value = value
        self.prior = prior
        self.block = block
        self.domain = domain
        self.transform = TRANSFORMS[domain]
        self.bounds = BOUNDS[domain]

        # note this will raise an error if we're out of bounds.
        self.set_params(self.value.ravel())

    def __repr__(self):
        if self.value.shape == ():
            return np.array2string(self.value.ravel(),
                                   precision=PRECISION,
                                   suppress_small=True)[1:-1].strip()
        else:
            return np.array2string(self.value,
                                   separator=',',
                                   precision=PRECISION,
                                   suppress_small=True)

    def __deepcopy__(self, memo):
        # this gets around a bug where copy.deepcopy(array) does not return an
        # array when called on a 0-dimensional object.
        memo[id(self.value)] = self.value.copy()
        return _deepcopy(self, memo)

    def get_params(self, transform=False):
        """<commit_msg>Make Parameter.nparams a property.<commit_after>"""
Interface for parameterized objects. The Parameterized class represents a
parameterized object which can get/set its values and evaluate a log-prior over
those values. Note, however, that this does not define any error or probability
terms for the object. For this, see the Model class.
"""

from __future__ import division
from __future__ import absolute_import
from __future__ import print_function

import numpy as np
import copy
import tabulate
import warnings
import collections

from .priors import PRIORS
from .domains import REAL
from .domains import BOUNDS, TRANSFORMS

__all__ = ['Parameterized']


# CONSTANTS FOR ADJUSTING PARAMETER FORMATTING
PRECISION = 2


def _outbounds(bounds, theta):
    """
    Check whether a vector is inside the given bounds.
    """
    bounds = np.array(bounds, ndmin=2)
    return np.any(theta < bounds[:, 0]) or np.any(theta > bounds[:, 1])


def _deepcopy(obj, memo):
    """
    Method equivalent to `copy.deepcopy` except that it ignored the
    implementation of `obj.__deepcopy__`. This allows for an object to
    implement deepcopy, populate its memo dictionary, and then call this
    version of deepcopy.
    """
    ret = type(obj).__new__(type(obj))
    memo[id(obj)] = ret
    for key, val in obj.__dict__.items():
        setattr(ret, key, copy.deepcopy(val, memo))
    return ret


class Parameter(object):
    """
    Representation of a parameter vector.
    """
    def __init__(self, value, domain, prior=None, block=0):
        self.value = value
        self.prior = prior
        self.block = block
        self.domain = domain
        self.transform = TRANSFORMS[domain]
        self.bounds = BOUNDS[domain]

        # note this will raise an error if we're out of bounds.
        self.set_params(self.value.ravel())

    def __repr__(self):
        if self.value.shape == ():
            return np.array2string(self.value.ravel(),
                                   precision=PRECISION,
                                   suppress_small=True)[1:-1].strip()
        else:
            return np.array2string(self.value,
                                   separator=',',
                                   precision=PRECISION,
                                   suppress_small=True)

    def __deepcopy__(self, memo):
        # this gets around a bug where copy.deepcopy(array) does not return an
        # array when called on a 0-dimensional object.
        memo[id(self.value)] = self.value.copy()
        return _deepcopy(self, memo)

    @property
    def nparams(self):
        return self.value.size

    def get_params(self, transform=False):
        """
{'fraction_non_alphanumeric': 0.08811320754716981, 'fraction_numerical': 0.0037735849056603774, 'mean_word_length': 2.4444444444444446, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3703713', 'n_tokens_mistral': 1496, 'n_tokens_neox': 1440, 'n_words': 496}