<commit_before>"""
This module provides a general "estimate" function and EstimationObj class for
pylogit's logit-type models.
"""
import sys
import time
import numpy as np
from scipy.optimize import minimize

import choice_calcs as cc
from choice_calcs import create_matrix_block_indices
from choice_tools import ensure_ridge_is_scalar_or_none


class EstimationObj(object):
    """
    Generic class for storing pointers to data and methods needed in the
    estimation process. Defines the basic Estimation Object and the various
    methods and attributes that such an object should have. Will be subclassed
    in order to serve the needs of the various types of estimated models.

    Parameters
    ----------
    model_obj : a pylogit.base_multinomial_cm_v2.MNDC_Model instance.
        Should contain the following attributes:

          - alt_IDs
          - choices
          - design
          - intercept_ref_position
          - shape_ref_position
          - utility_transform
    mapping_res : dict.
        Should contain the scipy sparse matrices that map the rows of the long
        format dataframe to various other objects such as the available
        alternatives, the unique observations, etc. The keys that it must have
        are `['rows_to_obs', 'rows_to_alts', 'chosen_row_to_obs']`
    ridge : int, float, long, or None.
            Determines whether or not ridge regression is performed. If a
            scalar is passed, then that scalar determines the ridge penalty for
            the optimization. The scalar should be greater than or equal to
            zero..
    zero_vector : 1D ndarray.
        Determines what is viewed as a "null" set of parameters. It is
        explicitly passed because some parameters (e.g. parameters that must be
        greater than zero) have their null values at values other than zero.
    split_params : callable.
        Should take a vector of parameters, `mapping_res['rows_to_alts']`, and
        model_obj.design as arguments. Should return a tuple containing
        separate arrays for the model's shape, outside intercept, and index
        coefficients. For each of these arrays, if this model does not contain
        the particular type of parameter, the callable should place a `None` in
        its place in the tuple.
    constrained_pos : list or None, optional.
        Denotes the positions of the array of estimated parameters that are
        not to change from their initial values. If a list is passed, the
        elements are to be integers where no such integer is greater than
        `init_values.size.` Default == None.
    """
    def __init__(self,
                 model_obj,
                 mapping_dict,
                 ridge,
                 zero_vector,
                 split_params,
                 constrained_pos=None):
        # Store pointers to needed objects
        self.alt_id_vector = model_obj.alt_IDs
        self.choice_vector = model_obj.choices
        self.design = model_obj.design
        self.intercept_ref_pos = model_obj.intercept_ref_position
        self.shape_ref_pos = model_obj.shape_ref_position

        # Explicitly store pointers to the mapping matrices
        self.rows_to_obs = mapping_dict["rows_to_obs"]
        self.rows_to_alts = mapping_dict["rows_to_alts"]
        self.chosen_row_to_obs = mapping_dict["chosen_row_to_obs"]
        self.rows_to_nests = mapping_dict["rows_to_nests"]
        self.rows_to_mixers = mapping_dict["rows_to_mixers"]

        # Perform necessary checking of ridge parameter here!
        ensure_ridge_is_scalar_or_none(ridge)

        # Store the ridge parameter<commit_msg>Added an observation_id vector as an attribute for EstimationObj. Also made it so that we check for contiguity in rows with the same obs_id when we initialize the EstimationObj.<commit_after>"""
This module provides a general "estimate" function and EstimationObj class for
pylogit's logit-type models.
"""
import sys
import time
import numpy as np
from scipy.optimize import minimize

import choice_calcs as cc
from choice_calcs import create_matrix_block_indices
from choice_tools import ensure_ridge_is_scalar_or_none


class EstimationObj(object):
    """
    Generic class for storing pointers to data and methods needed in the
    estimation process. Defines the basic Estimation Object and the various
    methods and attributes that such an object should have. Will be subclassed
    in order to serve the needs of the various types of estimated models.

    Parameters
    ----------
    model_obj : a pylogit.base_multinomial_cm_v2.MNDC_Model instance.
        Should contain the following attributes:

          - alt_IDs
          - choices
          - design
          - intercept_ref_position
          - shape_ref_position
          - utility_transform
    mapping_res : dict.
        Should contain the scipy sparse matrices that map the rows of the long
        format dataframe to various other objects such as the available
        alternatives, the unique observations, etc. The keys that it must have
        are `['rows_to_obs', 'rows_to_alts', 'chosen_row_to_obs']`
    ridge : int, float, long, or None.
            Determines whether or not ridge regression is performed. If a
            scalar is passed, then that scalar determines the ridge penalty for
            the optimization. The scalar should be greater than or equal to
            zero..
    zero_vector : 1D ndarray.
        Determines what is viewed as a "null" set of parameters. It is
        explicitly passed because some parameters (e.g. parameters that must be
        greater than zero) have their null values at values other than zero.
    split_params : callable.
        Should take a vector of parameters, `mapping_res['rows_to_alts']`, and
        model_obj.design as arguments. Should return a tuple containing
        separate arrays for the model's shape, outside intercept, and index
        coefficients. For each of these arrays, if this model does not contain
        the particular type of parameter, the callable should place a `None` in
        its place in the tuple.
    constrained_pos : list or None, optional.
        Denotes the positions of the array of estimated parameters that are
        not to change from their initial values. If a list is passed, the
        elements are to be integers where no such integer is greater than
        `init_values.size.` Default == None.
    """
    def __init__(self,
                 model_obj,
                 mapping_dict,
                 ridge,
                 zero_vector,
                 split_params,
                 constrained_pos=None):
        # Store pointers to needed objects
        self.alt_id_vector = model_obj.alt_IDs
        self.choice_vector = model_obj.choices
        self.obs_id_vector = model_obj.data[model_obj.obs_id_col].values
        self.design = model_obj.design
        self.intercept_ref_pos = model_obj.intercept_ref_position
        self.shape_ref_pos = model_obj.shape_ref_position

        # Explicitly store pointers to the mapping matrices
        self.rows_to_obs = mapping_dict["rows_to_obs"]
        self.rows_to_alts = mapping_dict["rows_to_alts"]
        self.chosen_row_to_obs = mapping_dict["chosen_row_to_obs"]
        self.rows_to_nests = mapping_dict["rows_to_nests"]
        self.rows_to_mixers = mapping_dict["rows_to_mixers"]

        # Perform necessary checking of ridge parameter here!
        ensure_ridge_is_scalar_or_none(ridge)
        # Ensure the dataset has contiguity in rows with the same obs_id
        ensure_contiguity_in_observation_rows(self.obs_id_vector)

        # Store the ridge parameter
{'fraction_non_alphanumeric': 0.04855506378547253, 'fraction_numerical': 0.000520697734964853, 'mean_word_length': 2.6760765550239234, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '881337', 'n_tokens_mistral': 2022, 'n_tokens_neox': 1974, 'n_words': 787}